[Pcsclite-cvs-commit] r2989 - in /branches/Solaris: ./ buildenv/ buildenv/pkgbld/ buildenv/pkgbld/pkgconfig/ buildenv/solaris/ src/ src/PCSC/ src/modules/

klissner-guest at users.alioth.debian.org klissner-guest at users.alioth.debian.org
Thu Jun 12 10:28:09 UTC 2008


Author: klissner-guest
Date: Thu Jun 12 10:28:09 2008
New Revision: 2989

URL: http://svn.debian.org/wsvn/pcsclite/?sc=1&rev=2989
Log: (empty)

Added:
    branches/Solaris/BUGS.txt
    branches/Solaris/README.build
    branches/Solaris/SECURITY_SCALABILITY_ENHANCEMENTS.pdf   (with props)
    branches/Solaris/buildenv/
    branches/Solaris/buildenv/Makefile
    branches/Solaris/buildenv/env   (with props)
    branches/Solaris/buildenv/pkgbld/
    branches/Solaris/buildenv/pkgbld/Makefile
    branches/Solaris/buildenv/pkgbld/copyright   (with props)
    branches/Solaris/buildenv/pkgbld/depend   (with props)
    branches/Solaris/buildenv/pkgbld/pkgconfig/
    branches/Solaris/buildenv/pkgbld/pkgconfig/libusb.pc
    branches/Solaris/buildenv/pkgbld/pkginfo   (with props)
    branches/Solaris/buildenv/pkgbld/pkgmk.log
    branches/Solaris/buildenv/pkgbld/postinstall   (with props)
    branches/Solaris/buildenv/pkgbld/preinstall   (with props)
    branches/Solaris/buildenv/pkgbld/preremove   (with props)
    branches/Solaris/buildenv/pkgbld/prototype
    branches/Solaris/buildenv/setup   (with props)
    branches/Solaris/buildenv/solaris/
    branches/Solaris/buildenv/solaris/Makefile
    branches/Solaris/buildenv/solaris/pcscd-Local
    branches/Solaris/buildenv/solaris/pcscd-Local.conf   (with props)
    branches/Solaris/buildenv/solaris/pcscd-svc   (with props)
    branches/Solaris/buildenv/solaris/pcscd.conf   (with props)
    branches/Solaris/buildenv/solaris/pcscd.xml   (with props)
    branches/Solaris/config.h.in
    branches/Solaris/configure.ac
    branches/Solaris/ltmain.sh
    branches/Solaris/src/PCSC/clientcred.h   (with props)
    branches/Solaris/src/PCSC/ifd-auth.h
    branches/Solaris/src/PCSC/pcscd-auth.h
    branches/Solaris/src/PCSC/pcscd-validate.h
    branches/Solaris/src/auth.c   (with props)
    branches/Solaris/src/auth.h   (with props)
    branches/Solaris/src/cfgfuncs.c
    branches/Solaris/src/configfile.c   (with props)
    branches/Solaris/src/daemon_utils.c
    branches/Solaris/src/daemon_utils.h
    branches/Solaris/src/instance.c
    branches/Solaris/src/instance.h
    branches/Solaris/src/launcher.c
    branches/Solaris/src/launcher.h   (with props)
    branches/Solaris/src/modules/
    branches/Solaris/src/modules/Makefile.am   (with props)
    branches/Solaris/src/modules/Makefile.in
    branches/Solaris/src/modules/ifdAuth_generic.c   (with props)
    branches/Solaris/src/modules/pcscdAuth_generic.c   (with props)
    branches/Solaris/src/modules/pcscd_validate.conf
    branches/Solaris/src/modules/validate_generic.c
    branches/Solaris/src/pcsc_config.h
    branches/Solaris/src/pcscdaemon.h   (with props)
    branches/Solaris/src/util.h   (with props)
    branches/Solaris/src/validate.c   (with props)
    branches/Solaris/src/validate.h   (with props)
    branches/Solaris/src/winscard_client.h   (with props)
Removed:
    branches/Solaris/configure.in
    branches/Solaris/src/README_INTERNALS.txt
Modified:
    branches/Solaris/INSTALL
    branches/Solaris/src/Makefile.am
    branches/Solaris/src/PCSC/ifdhandler.h
    branches/Solaris/src/PCSC/pcsclite.h.in
    branches/Solaris/src/PCSC/reader.h.in
    branches/Solaris/src/configfile.l
    branches/Solaris/src/debug.c
    branches/Solaris/src/debug.h
    branches/Solaris/src/debuglog.c
    branches/Solaris/src/dyn_unix.c
    branches/Solaris/src/error.c
    branches/Solaris/src/eventhandler.c
    branches/Solaris/src/eventhandler.h
    branches/Solaris/src/hotplug_libusb.c
    branches/Solaris/src/hotplug_linux.c
    branches/Solaris/src/hotplug_macosx.c
    branches/Solaris/src/ifdwrapper.c
    branches/Solaris/src/pcscdaemon.c
    branches/Solaris/src/powermgt_macosx.c
    branches/Solaris/src/prothandler.c
    branches/Solaris/src/readerfactory.c
    branches/Solaris/src/readerfactory.h
    branches/Solaris/src/sys_generic.h
    branches/Solaris/src/sys_unix.c
    branches/Solaris/src/thread_generic.h
    branches/Solaris/src/thread_unix.c
    branches/Solaris/src/winscard.c
    branches/Solaris/src/winscard_clnt.c
    branches/Solaris/src/winscard_msg.c
    branches/Solaris/src/winscard_msg.h
    branches/Solaris/src/winscard_msg_srv.c
    branches/Solaris/src/winscard_scf.c
    branches/Solaris/src/winscard_svc.c
    branches/Solaris/src/winscard_svc.h

Added: branches/Solaris/BUGS.txt
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/BUGS.txt?rev=2989&op=file
==============================================================================
--- branches/Solaris/BUGS.txt (added)
+++ branches/Solaris/BUGS.txt Thu Jun 12 10:28:09 2008
@@ -1,0 +1,5 @@
+There are some known bugs in this version.  Most are minor or corner cases or clean-up.  Some issues with 3rd party stacks have shown up, and some issues running as an RDP client of Microsoft Windows that are being worked on.
+
+There is currently an issue with USB enumeration delays affecting some 3rd party applications that are not sufficiently hotplug-aware or 'hotplug robust', and some sort of architectural workaround for that will probably need to be created.  For example if an application performs the first SCardEstablishContext() that results in a new instance being started, and the application very quickly calls SCardListReaders(), the application may miss some of the readers as the USB bus may not have had time to fully enumerate.
+
+USB enumeration delays currently impact session mobility on Sun Ray thin client network when the CCID handler is being used, and also can affect applications when pcscd instances are restarted after self-termination timeout after the default idle period has elapsed.

Modified: branches/Solaris/INSTALL
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/INSTALL?rev=2989&op=diff
==============================================================================
--- branches/Solaris/INSTALL (original)
+++ branches/Solaris/INSTALL Thu Jun 12 10:28:09 2008
@@ -1,38 +1,54 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
 Basic Installation
 ==================
 
-   These are generic installation instructions.
+Briefly, the shell commands `./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.
 
    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, a file
-`config.cache' that saves the results of its tests to speed up
-reconfiguring, and a file `config.log' containing compiler output
-(useful mainly for debugging `configure').
+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 at some point `config.cache'
-contains results you don't want to keep, you may remove or edit it.
-
-   The file `configure.in' is used to create `configure' by a program
-called `autoconf'.  You only need `configure.in' if you want to change
-it or regenerate `configure' using a newer version of `autoconf'.
+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.  If you're
-     using `csh' on an old version of System V, you might need to type
-     `sh ./configure' instead to prevent `csh' from trying to execute
-     `configure' itself.
-
-     Running `configure' takes awhile.  While running, it prints some
-     messages telling which features it is checking for.
+     `./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.
 
@@ -54,49 +70,49 @@
 Compilers and Options
 =====================
 
-   Some systems require unusual options for compilation or linking that
-the `configure' script does not know about.  You can give `configure'
-initial values for variables by setting them in the environment.  Using
-a Bourne-compatible shell, you can do that on the command line like
-this:
-     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
-
-Or on systems that have the `env' program, you can do it like this:
-     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+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
+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 must use a version of `make' that
-supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+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 `..'.
 
-   If you have to use a `make' that does not supports the `VPATH'
-variable, you have 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.
+   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.
 
 Installation Names
 ==================
 
-   By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc.  You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
+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'.
 
    You can specify separate installation prefixes for
 architecture-specific files and architecture-independent files.  If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
+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=PATH' to specify different values for particular
+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.
 
@@ -107,7 +123,7 @@
 Optional Features
 =================
 
-   Some packages pay attention to `--enable-FEATURE' options to
+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
@@ -122,47 +138,85 @@
 Specifying the System Type
 ==========================
 
-   There may be some features `configure' can not figure out
-automatically, but needs to determine by the type of host the package
-will run on.  Usually `configure' can figure that out, but if it prints
-a message saying it can not guess the host type, give it the
-`--host=TYPE' option.  TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name with three fields:
+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
 
-See the file `config.sub' for the possible values of each field.  If
+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 host type.
-
-   If you are building compiler tools for cross-compiling, you can also
-use the `--target=TYPE' option to select the type of system they will
-produce code for and the `--build=TYPE' option to select the type of
-system on which you are compiling the package.
+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'.
+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.
 
-Operation Controls
+Defining Variables
 ==================
 
-   `configure' recognizes the following options to control how it
-operates.
+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 bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /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 the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
 
 `--cache-file=FILE'
-     Use and save the results of the tests in FILE instead of
-     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
-     debugging `configure'.
-
-`--help'
-     Print a summary of the options to `configure', and exit.
+     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'
@@ -175,8 +229,6 @@
      Look for the package's source code in directory DIR.  Usually
      `configure' can determine that directory automatically.
 
-`--version'
-     Print the version of Autoconf used to generate the `configure'
-     script, and exit.
-
-`configure' also accepts some other, not widely useful, options.
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+

Added: branches/Solaris/README.build
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/README.build?rev=2989&op=file
==============================================================================
--- branches/Solaris/README.build (added)
+++ branches/Solaris/README.build Thu Jun 12 10:28:09 2008
@@ -1,0 +1,84 @@
+This is Solaris-specific version of PC/SC-Lite that has been re-architected
+with security and scalability enhancements to support larger installs
+beyond just single user machines -- for example thin client networks.
+
+Some of the changes were necessitated by the requirement that PC/SC-Lite
+run under the security constraints of Solaris Trusted Extensions and
+Solaris Zones.
+
+For more information about the re-design, please see the file
+SECURITY_SCALABILITY_ENHANCEMENTS.pdf in this branch.
+
+PREPARING THE SOLARIS 10 BUILD MACHINE:
+--------------------------------------
+
+This workspace is setup to build the package "SolarisPCSC" on a 
+Solaris 10 system.   The hope is that this code will ultimately be
+merged back into the trunk, but there is some work involved in doing
+that as is explained in SECURITY_SCALABILITY_ENHANCEMENTS.pdf.
+
+To build with the pre-set configuration provided in this workspace
+in the buildenv folder, the following need to be present on the build
+machine:
+
+	Sun Studio 11 (gcc works if buildenv tweaked)
+	Solaris 10 Companion Software (from sun.com).
+
+The following utilities supporting autoconf and automake should
+be present on the system.  If acceptable versions of these
+utilities are found in /opt/sfw (from the Solaris Companion Software),
+you will need to modify the path in the buildenv directory to find them,
+because the minimum working versions were not when this build
+environment was originally created.
+
+So you may need to require these or later version from the Internet.
+Note: Later versions of the following may work but haven't been tested.
+Currently the buildenv tries to use the ones it finds in /usr/local:
+
+
+	automake 1.10	(http://www.gnu.org/software/automake/)
+	aclocal 1.10    (part of automake distribution)
+	autoconf 2.6.0  (http://www.gnu.org/software/autoconf/)
+	libtool 1.5.22  (http://www.gnu.org/software/libtool/)
+	m4 1.4.4 	(http://www.gnu.org/software/m4/)
+	pkgconfig 0.19  (http://pkg-config.freedesktop.org/wiki)
+
+
+BUILDING WORKSPACE WITH PRE-BUILT CONFIGURATION:
+-----------------------------------------------
+
+1. Move or copy the 'buildenv' directory to some place outside of the 
+   this download bundle. 
+
+2. Copy the distribution (in its current layout) into a folder named pcsclite
+   under the buildenv folder you relocated, such that the top level files
+   including the top level Makefile and autoconf configuration files
+   are inside the pcsclite folder (ie. not in another folder underneath
+   pcsclite).
+
+3. $ cd buildenv/pcsclite
+
+4. Issue the following commands to set up the autoconf environment:
+
+   $ aclocal
+   $ autoconf
+   $ automake --add-missing
+   $ autoreconf
+
+   There may be some weird warnings, but unless they look particularly
+   fatal they're probably OK.  You'll know for sure if it fails when you try
+   to run make config next.  (Note: Any suggestions on how to clean
+   this up to make the autoconf stuff work w/o errors are welcome).
+
+5. Issue the following commands:
+
+   $ cd ..
+   $ make config
+   $ make all
+
+If all goes well buildenv/dist/<platform>/SolarisPCSC should be created.
+To build on the alternate Solaris infrastructure (for example if you 
+built the SPARC packages and want to build i386 packages in the same
+workspace), you can log into a properly provisioned Solaris machine,
+cd into buildenv, run make clean, make config, make all, which will
+build the new package without destroying the one for the other 

Added: branches/Solaris/SECURITY_SCALABILITY_ENHANCEMENTS.pdf
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/SECURITY_SCALABILITY_ENHANCEMENTS.pdf?rev=2989&op=file
==============================================================================
Binary file - no diff available.

Propchange: branches/Solaris/SECURITY_SCALABILITY_ENHANCEMENTS.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: branches/Solaris/buildenv/Makefile
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/Makefile?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/Makefile (added)
+++ branches/Solaris/buildenv/Makefile Thu Jun 12 10:28:09 2008
@@ -1,0 +1,71 @@
+BASH = /bin/bash
+
+RM	= /usr/bin/rm
+CHMOD   = /bin/chmod
+CURDIR:sh =pwd
+LIB 	= ./proto/usr/lib
+LIB64	= ./proto/usr/lib/64
+SCLIB 	= $(LIB)/smartcard
+INC 	= $./proto/usr/include/smartcard
+SCINC	= $(INC)/PCSC
+DATE:sh= date +"%a_%m-%d-%Y_%H:%M" | sed 's/ /_/g'
+BLD   	= _$(DATE)
+PLATFORM:sh =uname -p
+
+default:
+	@echo ""
+	@echo " Valid make targets: "
+	@echo ""
+	@echo "   config   - Configure PC/SC-Lite workspace for building" 
+	@echo "   all      - Build everything, and make packages"
+	@echo "   clean    - Remove built files from source directories" 
+	@echo "   clobber  - Remove proto and architecture-specific packages"
+	@echo ""
+
+all:	pcsclite solaris install pkg
+
+pcsclite: FRC
+	. env; cd pcsclite; make
+
+solaris:	FRC
+	cd solaris; make
+
+pkg: FRC
+	cd pkgbld; make
+
+config: FRC
+	cd pcsclite; $(RM) -f config.log config.status
+	PRODUCT_BLD=$(BLD); . env; ./setup $(CURDIR)/proto
+
+install:	FRC
+	. env $(BLD); cd pcsclite/src; make install
+
+clean:	FRC
+	cd pcsclite; make clean
+	cd pcsclite; $(CHMOD) -R 777 m4 doc etc win32 stamp-h1
+	cd pkgbld; make clean
+
+DISTFILES  = $(INC)/debug.h 
+DISTFILES += $(SCINC)/clientcred.h 
+DISTFILES += $(SCINC)/ifdhandler.h
+DISTFILES += $(SCINC)/reader.h 
+DISTFILES += $(SCINC)/wintypes.h 
+DISTFILES += $(SCINC)/debuglog.h
+DISTFILES += $(SCINC)/pcscd-validate.h 
+DISTFILES += $(SCINC)/pcscd-auth.h
+DISTFILES += $(SCLIB)/pcscd 
+DISTFILES += $(SCLIB)/installifd 
+DISTFILES += $(SCLIB)/formaticc
+DISTFILES += $(SCINC)/pcsclite.h 
+DISTFILES += $(SCINC)/winscard.h
+DISTFILES += $(LIB)/libpcsclite.* 
+DISTFILES += $(LIB)/pkgconfig
+
+clobber:
+	$(RM) -rf proto $(DISTFILES)
+	$(RM) -rf dist/$(PLATFORM)
+
+.PRECIOUS:
+	config 
+
+FRC:

Added: branches/Solaris/buildenv/env
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/env?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/env (added)
+++ branches/Solaris/buildenv/env Thu Jun 12 10:28:09 2008
@@ -1,0 +1,34 @@
+#!/sbin/sh
+#
+# Setup environment for building PCSClite on Solaris
+#
+# Prerequisites:
+#
+#   Solaris 10 Companion software (/opt/sfw)
+#   SUNWspro version 11+ compilers (/opt/SUNWspro)
+#
+
+unset LD_LIBRARY_PATH
+
+PATH=/bin
+PATH=${PATH}:/usr/bin
+PATH=${PATH}:/usr/sfw/bin
+PATH=${PATH}:/usr/ccs/bin
+PATH=${PATH}:/opt/sfw/bin
+
+CFLAGS="-g -I/usr/include -DBUILD=\\\"$PRODUCT_BLD\\\""
+LDFLAGS="-L/usr/sfw/lib -R/usr/sfw/lib"
+PKG_CONFIG_PATH=`pwd`/pkgbld/pkgconfig
+CC="/opt/Studio11/SunOS.`uname -p`/SUNWspro/bin/cc"
+CXX="/opt/Studio11/SunOS.`uname -p`/SUNWspro/bin/CC"
+LIBUSB_CFLAGS="-I/usr/sfw/include"
+LIBUSB_LIBS="-L/usr/sfw/lib -R/usr/sfw/lib -lusb"
+
+export PATH
+export CFLAGS
+export LDFLAGS
+export PKG_CONFIG_PATH
+export CC
+export CXX
+export LIBUSB_CFLAGS
+export LIBUSB_LIBS

Propchange: branches/Solaris/buildenv/env
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/pkgbld/Makefile
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/pkgbld/Makefile?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/pkgbld/Makefile (added)
+++ branches/Solaris/buildenv/pkgbld/Makefile Thu Jun 12 10:28:09 2008
@@ -1,0 +1,34 @@
+DATE:sh= date +"%a_%m-%d-%Y_%H:%M" | sed 's/ /_/g'
+
+#PODUCT_NAME  = PC/SC-Lite for Solaris
+#PRODUCT_LABEL = pcsclite
+PRODUCT_REL   = 100
+PRODUCT_BLD   = DEVBLD_$(DATE)
+
+thedate:sh =/bin/date '+%m-%d-%y--%H:%M'
+CMD=basename $(DOT)
+ARCH:sh=uname -p
+OS:sh = uname -s
+OSVER:sh = uname -r
+PSTAMPDATE:sh = date +"20%y%m%d%H%M%S"
+PLATFORM:sh =uname -p
+DIST=../dist/$(PLATFORM)
+PROTO=../proto
+all:
+	[ -d $(DIST) ] || mkdir -p $(DIST)
+	chmod 755 $(DIST)
+	pkgmk \
+	  -o \
+	  -a $(ARCH) \
+	  -d $(DIST) \
+	  -r $(PROTO) \
+	  -p $(OS)_$(OSVER)_$(PSTAMPDATE) \
+	  -v $(PRODUCT_REL)_$(PRODUCT_BLD) \
+	1>pkgmk.log 2>&1
+
+clobber:
+	rm -rf ../dist/SolarisPCSC
+
+config:
+
+clean:

Added: branches/Solaris/buildenv/pkgbld/copyright
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/pkgbld/copyright?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/pkgbld/copyright (added)
+++ branches/Solaris/buildenv/pkgbld/copyright Thu Jun 12 10:28:09 2008
@@ -1,0 +1,2 @@
+Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+Use is subject to license terms.

Propchange: branches/Solaris/buildenv/pkgbld/copyright
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/pkgbld/depend
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/pkgbld/depend?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/pkgbld/depend (added)
+++ branches/Solaris/buildenv/pkgbld/depend Thu Jun 12 10:28:09 2008
@@ -1,0 +1,17 @@
+#
+# ident "@(#)depend.src 1.1 04/01/19 SMI"
+#
+# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+#
+# P     prerequisite  for installation
+# I     incompatible package
+# R     reverse dependency, package depends on me
+
+I SUNWsrcbp
+I SUNWocfd
+I SUNWocfh
+I SUNWocfr
+I SUNWpcsclite
+I SUNWpcsclite-devel
+I SUNWjcom
+

Propchange: branches/Solaris/buildenv/pkgbld/depend
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/pkgbld/pkgconfig/libusb.pc
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/pkgbld/pkgconfig/libusb.pc?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/pkgbld/pkgconfig/libusb.pc (added)
+++ branches/Solaris/buildenv/pkgbld/pkgconfig/libusb.pc Thu Jun 12 10:28:09 2008
@@ -1,0 +1,11 @@
+prefix=/usr/sfw
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: libusb
+Description: USB API
+Version: 0.1.8
+Libs: -L${libdir} -lusb
+Cflags: -I${includedir} 
+

Added: branches/Solaris/buildenv/pkgbld/pkginfo
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/pkgbld/pkginfo?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/pkgbld/pkginfo (added)
+++ branches/Solaris/buildenv/pkgbld/pkginfo Thu Jun 12 10:28:09 2008
@@ -1,0 +1,18 @@
+PKG=SolarisPCSC
+NAME=pcsclite for Solaris 
+DESC=Makes pcsclite opensource software available on Solaris 
+VERSION=0.0
+BASEDIR=/
+CLASSES=none
+CATEGORY=system
+MAXINST=1000
+HOTLINE=Please contact your local service provider
+EMAIL=
+SUNW_PKG_THISZONE=true
+SUNW_PKG_INSTALL_ZONENAME=global
+SUNW_PKG_ALLZONES=false
+VENDOR=Sun Microsystems, Inc.
+SUNW_PRODNAME=pcsclite (unbundled) 
+SUNW_PRODVERS=1.3.2
+SUNW_PKGVERS=1.0
+SUNW_PKGTYPE=opt

Propchange: branches/Solaris/buildenv/pkgbld/pkginfo
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/pkgbld/pkgmk.log
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/pkgbld/pkgmk.log?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/pkgbld/pkgmk.log (added)
+++ branches/Solaris/buildenv/pkgbld/pkgmk.log Thu Jun 12 10:28:09 2008
@@ -1,0 +1,40 @@
+## Building pkgmap from package prototype file.
+## Processing pkginfo file.
+WARNING: missing directory entry for <usr/lib/64>
+WARNING: missing directory entry for <usr/lib/pkgconfig>
+## Attempting to volumize 41 entries in pkgmap.
+part  1 -- 3010 blocks, 35 entries
+## Packaging one part.
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/pkgmap
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/pkginfo
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/install/depend
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/etc/smartcard/pcscd-Local.conf
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/etc/smartcard/pcscd.conf
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/lib/svc/method/pcscd-svc
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/install/postinstall
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/install/preinstall
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/install/preremove
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/clientcred.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/debug.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/debuglog.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/ifd-auth.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/ifdhandler.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/pcscd-auth.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/pcscd-validate.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/pcsclite.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/reader.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/winscard.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/include/smartcard/wintypes.h
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/lib/64/libpcsclite.so.1
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/lib/libpcsclite.so.1
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/lib/pkgconfig/libpcsclite.pc
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/lib/smartcard/ifdAuth.so.1
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/lib/smartcard/pcscd
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/lib/smartcard/pcscd-Local
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/lib/smartcard/pcscdAuth-Local.so.1
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/lib/smartcard/pcscdValidate.so.1
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/usr/lib/smartcard/pcscd_validate.conf
+/local/home/paul/new/buildenv/dist/sparc/SolarisPCSC/reloc/var/svc/manifest/application/security/pcscd.xml
+## Validating control scripts.
+WARNING: script <preinstall> may seek access to the transitional package database at line <273>. This is safest in the postinstall or postremove script.
+## Packaging complete.

Added: branches/Solaris/buildenv/pkgbld/postinstall
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/pkgbld/postinstall?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/pkgbld/postinstall (added)
+++ branches/Solaris/buildenv/pkgbld/postinstall Thu Jun 12 10:28:09 2008
@@ -1,0 +1,9 @@
+#!/bin/sh
+
+cd /var/svc/manifest/application/security
+svccfg -v import pcscd.xml
+svcadm -v enable pcscd
+
+ps -ef | grep /usr/lib/smartcard/pcscd | grep -v grep
+
+exit 0

Propchange: branches/Solaris/buildenv/pkgbld/postinstall
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/pkgbld/preinstall
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/pkgbld/preinstall?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/pkgbld/preinstall (added)
+++ branches/Solaris/buildenv/pkgbld/preinstall Thu Jun 12 10:28:09 2008
@@ -1,0 +1,273 @@
+#!/bin/sh
+
+
+echo ""
+echo "****************************************************"
+echo "*  REQUIRED LICENSE AGREEMENT                      *"
+echo "****************************************************"
+echo ""
+echo "Pre-Release "
+echo "Software Evaluation Agreement"
+echo ""
+echo "SUN MICROSYSTEMS, INC. (\"SUN\") IS WILLING TO LICENSE THE JAVA USB "
+echo "API FOR SUN RAY CLIENTS 1.0 PRE-RELEASE SOFTWARE TO LICENSEE ONLY "
+echo "UPON THE CONDITION THAT LICENSEE ACCEPTS ALL OF THE TERMS CONTAINED "
+echo "IN THIS LICENSE AGREEMENT (\"AGREEMENT\"). PLEASE READ THE TERMS AND "
+echo "CONDITIONS OF THIS AGREEMENT CAREFULLY. BY DOWNLOADING OR "
+echo "INSTALLING THIS SOFTWARE, LICENSEE ACCEPTS THE TERMS AND CONDITIONS "
+echo "OF THIS LICENSE AGREEMENT. INDICATE ACCEPTANCE BY SELECTING THE "
+echo "\"ACCEPT\" BUTTON AT THE BOTTOM OF THIS AGREEMENT. IF LICENSEE IS NOT "
+echo "WILLING TO BE BOUND BY ALL THE TERMS, SELECT THE \"DECLINE\" BUTTON "
+echo "AT THE BOTTOM OF THE AGREEMENT AND THE DOWNLOAD OR INSTALL PROCESS "
+echo "WILL NOT CONTINUE. "
+echo ""
+echo "1.0 DEFINITIONS "
+echo ""
+echo "\"Licensed Software\" means the Java USB API for Sun Ray Clients 1.0 "
+echo "pre-release software in binary and/or source code forms, any other "
+echo "machine readable materials (including, but not limited to, "
+echo "libraries, source files, header files, and data files) and any user "
+echo "manuals, programming guides and other documentation provided to "
+echo "Licensee by Sun under this Agreement. "
+printf "\nPress RETURN to continue: "
+#read yn </dev/tty
+echo ""
+echo "2.0 LIMITED LICENSE "
+echo ""
+echo "2.1 Source Code. Sun grants to Licensee, a non-exclusive, "
+echo "non-transferable, royalty-free and limited license to view the "
+echo "source code portions of the Licensed Software internally for the "
+echo "purposes of evaluation only."
+echo ""
+echo "2.2 Binary Code. Sun grants to Licensee, a non-exclusive, "
+echo "non-transferable, royalty-free and limited license to use the "
+echo "binary code portions of the Licensed Software internally for the "
+echo "purposes of evaluation only."
+echo ""
+echo "2.3 No licenses are granted to Licensee for any other purposes, "
+echo "Licensee may not sell, rent, loan or otherwise encumber or transfer "
+echo "Licensed Software in whole or in part, to any third party."
+echo ""
+echo "3.0 LICENSE RESTRICTIONS "
+echo ""
+echo "3.1 Licensee may not duplicate Licensed Software other than for a "
+echo "single copy of Licensed Software for archival purposes only. "
+echo "Licensee agrees to reproduce any copyright and other proprietary "
+printf "\nPress RETURN to continue: "
+#read yn </dev/tty
+echo "right notices on any such copy. "
+echo ""
+echo "3.2 Except as otherwise provided by law, Licensee may not modify or "
+echo "create derivative works of the Licensed Software, or reverse "
+echo "engineer, disassemble or decompile binary portions of the Licensed "
+echo "Software, or otherwise attempt to derive the source code from such "
+echo "portions. "
+echo ""
+echo "3.3 No right, title, or interest in or to Licensed Software, any "
+echo "trademarks, service marks, or trade names of Sun or Sun's licensors "
+echo "is granted under this Agreement. "
+echo ""
+echo "3.4 Licensee shall have no right to use the Licensed Software for "
+echo "productive or commercial use."
+echo ""
+echo "4.0 NO SUPPORT "
+echo ""
+echo "Sun is under no obligation to support Licensed Software or to "
+echo "provide Licensee with updates or error corrections (collectively "
+echo "\"Software Updates\"). If Sun, at its sole option, supplies Software "
+echo "Updates to Licensee, the Software Updates will be considered part "
+echo "of Licensed Software, and subject to the terms of this Agreement. "
+printf "\nPress RETURN to continue: "
+#read yn </dev/tty
+echo ""
+echo "5.0 LICENSEE DUTIES "
+echo ""
+echo "Licensee agrees to evaluate and test the Software for use in "
+echo "Licensee's software environment and provide feedback to Sun in a "
+echo "manner reasonably requested by Sun. Any and all test results, error "
+echo "data, reports or other information, feedback or materials made or "
+echo "provided by Licensee relating to Software (collectively, "
+echo "\"Feedback\") are the exclusive property of Sun and Licensee hereby "
+echo "assigns all Feedback to Sun at no cost to Sun. Sun may use such "
+echo "Feedback in any manner and for any purpose, without limitation, "
+echo "liability or obligation to Licensee. "
+echo ""
+echo "6.0 TERM AND TERMINATION OF AGREEMENT "
+echo ""
+echo "6.1 This Agreement will commence on the date on which Licensee "
+echo "receives Licensed Software (the \"Effective Date\") and will expire "
+echo "ninety (90)days from the Effective Date, unless terminated earlier "
+echo "as provided herein. "
+echo ""
+echo "6.2 Either party may terminate this Agreement upon ten (10) days' "
+echo "written notice to the other party. However, Sun may terminate this "
+printf "\nPress RETURN to continue: "
+#read yn </dev/tty
+echo "Agreement immediately should any Licensed Software become, or in "
+echo "Sun's opinion be likely to become, the subject of a claim of "
+echo "infringement of a patent, trade secret or copyright. "
+echo ""
+echo "6.3 Sun may terminate this Agreement immediately should Licensee "
+echo "materially breach any of its provisions or take any action in "
+echo "derogation of Sun's rights to the Confidential Information licensed "
+echo "to Licensee. "
+echo ""
+echo "6.4 Upon termination or expiration of this Agreement, Licensee will "
+echo "immediately cease use of and destroy Licensed Software, any copies "
+echo "thereof and provide to Sun a written statement certifying that "
+echo "Licensee has complied with the foregoing obligations. "
+echo ""
+echo "6.5 Rights and obligations under this Agreement which by their "
+echo "nature should survive, will remain in effect after termination or "
+echo "expiration hereof."
+echo ""
+echo "7.0 CONFIDENTIAL INFORMATION "
+echo ""
+echo "7.1 For purposes of this Agreement, \"Confidential Information\" "
+echo "means: (i) business and technical information and any source code "
+printf "\nPress RETURN to continue: "
+#read yn </dev/tty
+echo "or binary code, which Sun discloses to Licensee related to Licensed "
+echo "Software; (ii) Licensee's feedback based on Licensed Software; and "
+echo "(iii) the terms, conditions, and existence of this Agreement. "
+echo "Licensee may not disclose or use Confidential Information, except "
+echo "for the purposes specified in this Agreement. Licensee will protect "
+echo "the Confidential Information with the same degree of care, but not "
+echo "less than a reasonable degree of care, as Licensee uses to protect "
+echo "its own Confidential Information. Licensee's obligations regarding "
+echo "Confidential Information will expire no less than five (5) years "
+echo "from the date of receipt of the Confidential Information, except "
+echo "for Sun source code which will be protected in perpetuity. Licensee "
+echo "agrees that Licensed Software contains Sun trade secrets. "
+echo ""
+echo "7.2 Notwithstanding any provisions contained in this Agreement "
+echo "concerning nondisclosure and non-use of the Confidential "
+echo "Information, the nondisclosure obligations of Section 7.1 will not "
+echo "apply to any portion of Confidential Information that Licensee can "
+echo "demonstrate in writing is: (i) now, or hereafter through no act or "
+echo "failure to act on the part of Licensee becomes, generally known to "
+echo "the general public; (ii) known to Licensee at the time of receiving "
+echo "the Confidential Information without an obligation of "
+echo "confidentiality; (iii) hereafter rightfully furnished to Licensee "
+printf "\nPress RETURN to continue: "
+#read yn </dev/tty
+echo "by a third party without restriction on disclosure; or (iv) "
+echo "independently developed by Licensee without any use of the "
+echo "Confidential Information. "
+echo ""
+echo "7.3 Licensee must restrict access to Confidential Information to "
+echo "its employees or contractors with a need for this access to perform "
+echo "their employment or contractual obligations and who have agreed in "
+echo "writing to be bound by a confidentiality obligation, which "
+echo "incorporates the protections and restrictions substantially as set "
+echo "forth in this Agreement."
+echo ""
+echo "8.0 DISCLAIMER OF WARRANTY "
+echo ""
+echo "8.1 Licensee acknowledges that Licensed Software may contain errors "
+echo "and is not designed, licensed, or intended for use in the design, "
+echo "construction, operation or maintenance of any nuclear facility "
+echo "(\"High Risk Activities\"). Sun disclaims any express or implied "
+echo "warranty of fitness for such uses. Licensee represents and warrants "
+echo "to Sun that it will not use, distribute or license the Licensed "
+echo "Software for High Risk Activities. "
+echo ""
+echo "8.2 LICENSED SOFTWARE IS PROVIDED \"AS IS\". ALL EXPRESS OR IMPLIED "
+printf "\nPress RETURN to continue: "
+#read yn </dev/tty
+echo "CONDITIONS, REPRESENTATIONS, AND WARRANTIES, INCLUDING ANY IMPLIED "
+echo "WARRANTY OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A "
+echo "PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO "
+echo "THE EXTENT THAT SUCH DISCLAIMERS ARE HELD TO BE LEGALLY INVALID."
+echo ""
+echo "9.0 LIMITATION OF LIABILITY "
+echo ""
+echo "9.1 Licensee acknowledges that the Licensed Software may be "
+echo "experimental and that the Licensed Software may have defects or "
+echo "deficiencies, which cannot or will not be corrected by Sun. "
+echo "Licensee will hold Sun harmless from any claims based on Licensee's "
+echo "use of the Licensed Software for any purposes other than those of "
+echo "internal evaluation, and from any claims that later versions or "
+echo "releases of any Licensed Software furnished to Licensee are "
+echo "incompatible with the Licensed Software provided to Licensee under "
+echo "this Agreement. "
+echo ""
+echo "9.2 To the extent not prohibited by law, in no event will Sun be "
+echo "liable for any indirect, punitive, special, incidental or "
+echo "consequential damage in connection with or arising out of this "
+echo "Agreement (including loss of business, revenue, profits, use, data "
+echo "or other economic advantage), however it arises, whether for breach "
+printf "\nPress RETURN to continue: "
+#read yn </dev/tty
+echo "or in tort, even if Sun has been previously advised of the "
+echo "possibility of such damage."
+echo ""
+echo "10.0 U.S. GOVERNMENT RESTRICTED RIGHTS "
+echo ""
+echo "If this Software is being acquired by or on behalf of the U.S. "
+echo "Government or by a U.S. Government prime contractor or "
+echo "subcontractor (at any tier), then the Government's rights in the "
+echo "Software and accompanying documentation shall be only as set forth "
+echo "in this license; this is in accordance with 48 C.F.R. 227.7202-4 "
+echo "(for Department of Defense (DOD) acquisitions) and with 48 C.F.R. "
+echo "2.101 and 12.212 (for non-DOD acquisitions). "
+echo ""
+echo "11.0 GENERAL TERMS "
+echo ""
+echo "11.1 Any action relating to or arising out of this Agreement will "
+echo "be governed by California law and controlling U.S. federal law. The "
+echo "U.N. Convention for the International Sale of Goods and the choice "
+echo "of law rules of any jurisdiction will not apply. "
+echo ""
+echo "11.2 Licensed Software and technical data delivered under this "
+echo "Agreement are subject to U.S. export control laws and may be "
+printf "\nPress RETURN to continue: "
+#read yn </dev/tty
+echo "subject to export or import regulations in other countries. "
+echo "Licensee agrees to comply strictly with all such laws and "
+echo "regulations and acknowledges that it has the responsibility to "
+echo "obtain such licenses to export, re-export or import as may be "
+echo "required after delivery to Licensee. "
+echo ""
+echo "11.3 It is understood and agreed that, notwithstanding any other "
+echo "provision of this Agreement, Licensee's breach of the provisions of "
+echo "Section 7 of this Agreement will cause Sun irreparable damage for "
+echo "which recovery of money damages would be inadequate, and that Sun "
+echo "will therefore be entitled to seek timely injunctive relief to "
+echo "protect Sun's rights under this Agreement in addition to any and "
+echo "all remedies available at law. "
+echo ""
+echo "11.4 Neither party may assign or otherwise transfer any of its "
+echo "rights or obligations under this Agreement, without the prior "
+echo "written consent of the other party, except that Sun may assign this "
+echo "Agreement to an affiliated company. "
+echo ""
+echo "11.5 This Agreement is the parties' entire agreement relating to "
+echo "its subject matter. It supersedes all prior or contemporaneous oral "
+echo "or written communications, proposals, conditions, representations "
+printf "\nPress RETURN to continue: "
+#read yn </dev/tty
+echo "and warranties and prevails over any conflicting or additional "
+echo "terms of any quote, order, acknowledgment, or other communication "
+echo "between the parties relating to its subject matter, including any "
+echo "Binary Code Licenses, Supplemental Terms, or other licenses "
+echo "contained within Licensed Software. No modification to this "
+echo "Agreement will be binding, unless in writing and signed by an "
+echo "authorized representative of each party. "
+echo ""
+echo "(Form ID#011801) "
+echo ""
+echo ""
+
+echo "Remove previous pcscd service (if any)"
+svcadm disable pcscd
+svccfg delete -f pcscd
+
+echo "Cleaning up previous server run files"
+rm -f /var/run/pcscd/pcscd.pid
+rm -f /var/run/pcscd/fifo/*
+rm -f /var/run/pcscd/pid/*
+
+[ -L /usr/lib/libpcsclite.so ] && rm -f /usr/lib/libpcsclite.so
+
+removef -f $PKGINST || exit 2

Propchange: branches/Solaris/buildenv/pkgbld/preinstall
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/pkgbld/preremove
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/pkgbld/preremove?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/pkgbld/preremove (added)
+++ branches/Solaris/buildenv/pkgbld/preremove Thu Jun 12 10:28:09 2008
@@ -1,0 +1,14 @@
+#!/bin/bash
+#
+echo "*****************************************"
+echo "Stopping and Removing pcscd service"
+svcadm disable pcscd
+svccfg delete -f pcscd
+
+echo "Stopping pcscd instances"
+pkill -9 -f /usr/lib/smartcard/pcscd
+
+echo "Removing instance fifo files"
+rm -f /var/run/pcscd/fifo/*
+rm -f /var/run/pcscd/run/*
+echo "*****************************************"

Propchange: branches/Solaris/buildenv/pkgbld/preremove
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/pkgbld/prototype
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/pkgbld/prototype?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/pkgbld/prototype (added)
+++ branches/Solaris/buildenv/pkgbld/prototype Thu Jun 12 10:28:09 2008
@@ -1,0 +1,58 @@
+i pkginfo
+i depend
+i preinstall
+i postinstall
+i preremove
+
+d none lib ??? root bin
+d none lib/svc ??? root bin
+d none lib/svc/method ??? root bin
+
+d none var ??? root bin
+d none var/svc ??? root bin
+d none var/svc/manifest ??? root bin
+d none var/svc/manifest/application ??? root bin
+d none var/svc/manifest/application/security ??? root bin
+
+d none etc ??? root bin
+d none etc/smartcard 755 root bin
+
+d none usr ??? root bin
+d none usr/lib ??? root bin
+d none usr/lib/smartcard 755 root bin
+
+d none usr/include ??? root bin
+d none usr/include/smartcard 755 root bin
+
+f none var/svc/manifest/application/security/pcscd.xml=smf/pcscd.xml 0444 root sys
+f none lib/svc/method/pcscd-svc=smf/pcscd-svc 0555 root bin
+
+f none usr/lib/smartcard/pcscd=usr/lib/smartcard/pcscd 0555 root bin
+f none usr/lib/smartcard/pcscd-Local=usr/lib/smartcard/pcscd-Local 0555 root bin
+f none usr/lib/smartcard/ifdAuth.so.1=usr/lib/libIfdAuth.so.0.0.0 0555 root bin
+f none usr/lib/smartcard/pcscdAuth-Local.so.1=usr/lib/libPcscdAuth.so.0.0.0 0555 root bin
+f none usr/lib/smartcard/pcscdValidate.so.1=usr/lib/libValidate.so.0.0.0 0555 root bin
+
+f none usr/lib/pkgconfig/libpcsclite.pc=usr/lib/pkgconfig/libpcsclite.pc 0555 root bin
+
+f none usr/lib/64/libpcsclite.so.1=usr/lib/libpcsclite64.so.1.0.0 0555 root bin
+f none usr/lib/libpcsclite.so.1=usr/lib/libpcsclite.so.1.0.0 0555 root bin
+
+s none usr/lib/64/libpcsclite.so=libpcsclite.so.1 0755 root bin
+s none usr/lib/libpcsclite.so=libpcsclite.so.1 0755 root bin
+
+f none etc/smartcard/pcscd.conf=etc/smartcard/pcscd.conf 0644 root bin
+f none etc/smartcard/pcscd-Local.conf=etc/smartcard/pcscd-Local.conf 0644 root bin
+f none usr/lib/smartcard/pcscd_validate.conf=usr/share/doc/smartcard/pcscd_validate.conf 0644 root bin
+f none usr/include/smartcard/clientcred.h=usr/include/smartcard/PCSC/clientcred.h 0644 root bin
+f none usr/include/smartcard/debuglog.h=usr/include/smartcard/PCSC/debuglog.h 0644 root bin
+f none usr/include/smartcard/debug.h=usr/include/smartcard/debug.h 0644 root bin
+f none usr/include/smartcard/ifdhandler.h=usr/include/smartcard/PCSC/ifdhandler.h 0644 root bin
+f none usr/include/smartcard/pcsclite.h=usr/include/smartcard/PCSC/pcsclite.h 0644 root bin
+f none usr/include/smartcard/reader.h=usr/include/smartcard/PCSC/reader.h 0644 root bin
+f none usr/include/smartcard/winscard.h=usr/include/smartcard/PCSC/winscard.h 0644 root bin
+f none usr/include/smartcard/wintypes.h=usr/include/smartcard/PCSC/wintypes.h 0644 root bin
+f none usr/include/smartcard/pcscd-validate.h=usr/include/smartcard/PCSC/pcscd-validate.h 0644 root bin
+f none usr/include/smartcard/pcscd-auth.h=usr/include/smartcard/PCSC/pcscd-auth.h 0644 root bin
+f none usr/include/smartcard/ifd-auth.h=usr/include/smartcard/PCSC/ifd-auth.h 0644 root bin
+

Added: branches/Solaris/buildenv/setup
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/setup?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/setup (added)
+++ branches/Solaris/buildenv/setup Thu Jun 12 10:28:09 2008
@@ -1,0 +1,44 @@
+#!/sbin/sh
+#
+# Set's up PC/SC lite workspace (configures it for OS)
+#
+# Prerequisites:
+#   Solaris 10 Companion software (/opt/sfw)
+#   SUNWspro version 11+ compilers (/opt/SUNWspro)
+#
+#
+# Configure for building PCSClite on Solaris
+#
+# Prerequisites:
+#
+#   Solaris 10 Companion Software (/opt/sfw)
+#   SUNWspro Version 11+ Compilers (/opt/SUNWspro)
+#
+
+PROTO_ROOT=$1
+chmod 777 $PROTO_ROOT/..
+cd pcsclite
+echo "Executing configure $PWD/configure"
+./configure \
+	--prefix=$PROTO_ROOT \
+	--exec-prefix=$PROTO_ROOT \
+	--enable-portsvc=5999 \
+	--enable-confdir=/etc/smartcard \
+	--enable-xtag=/usr/dt/config/Xservers \
+	--enable-rtlibdir=/usr/lib/smartcard \
+	--enable-runpid=/var/run/pcscd/pcscd.pid \
+	--enable-ipcdir=/var/run \
+	--enable-libusb=/usr/sfw/lib \
+	--enable-usbdropdir=/usr/lib/smartcard \
+	--libdir=$PROTO_ROOT/usr/lib \
+	--bindir=$PROTO_ROOT/usr/lib/smartcard \
+	--sysconfdir=$PROTO_ROOT/etc/smartcard \
+	--sbindir=$PROTO_ROOT/usr/lib/smartcard \
+	--includedir=$PROTO_ROOT/usr/include/smartcard \
+	--datadir=$PROTO_ROOT/usr/share/doc/smartcard \
+	--localedir=$iPROTO_ROOT/usr/share/locale \
+	--infodir=$PROTO_ROOT/usr/share/doc/smartcard \
+	--docdir=$PROTO_ROOT/usr/share/doc/smartcard \
+	--pdfdir=$PROTO_ROOT/usr/share/doc/smartcard \
+	--mandir=$PROTO_ROOT/usr/man \
+

Propchange: branches/Solaris/buildenv/setup
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/solaris/Makefile
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/solaris/Makefile?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/solaris/Makefile (added)
+++ branches/Solaris/buildenv/solaris/Makefile Thu Jun 12 10:28:09 2008
@@ -1,0 +1,36 @@
+
+RM		= /usr/bin/rm
+MKDIR		= /usr/bin/mkdir
+
+SMF		= ../proto/smf
+ETC		= ../proto/etc/smartcard
+LIB             = ../proto/usr/lib/smartcard
+
+DISTDIRS	= $(SMF) $(ETC) $(LIB)
+SMF_FILES	= pcscd.xml pcscd-svc
+ETC_FILES	= pcscd.conf pcscd-Local.conf
+LIB_FILES       = pcscd-Local
+
+all:	install
+	
+install:	$(DISTDIRS)
+	cp $(SMF_FILES) $(SMF)
+	cp $(ETC_FILES) $(ETC)
+	cp $(LIB_FILES) $(LIB)
+
+$(DISTDIRS):	FRC
+	[ -d $@ ] || $(MKDIR) -p $@ 
+
+clean:
+	$(RM) -f $(SMF)/pcscd.xml
+	$(RM) -f $(SMF)/pcscd-svc
+	$(RM) -f $(ETC)/pcscd.conf
+	$(RM) -f $(ETC)/pcscd-Local.conf
+
+config:
+
+clobber:
+
+pkg:
+
+FRC:

Added: branches/Solaris/buildenv/solaris/pcscd-Local
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/solaris/pcscd-Local?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/solaris/pcscd-Local (added)
+++ branches/Solaris/buildenv/solaris/pcscd-Local Thu Jun 12 10:28:09 2008
@@ -1,0 +1,34 @@
+#!/bin/sh
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+while getopts x:P:p:b:m: opt; do
+     case $opt in
+	   m)   mode=$OPTARG;;
+           x)   DISPLAY=$OPTARG;;
+           b)   BASEDIR=$OPTARG;;
+	   P)   CONFIG=$OPTARG;;
+	   p)   INSTPID=$OPTARG;;
+          \?)   logger -t pcscd-Local -p user.err \
+                   "Bad argument passed to launch script"
+                exit 1;;
+     esac
+done
+shift `expr $OPTIND - 1`
+
+if [ -z "$DISPLAY" ]; then
+        logger -t pcscd-Local -p user.err \
+            "Missing DISPLAY (-x parameter ) in launch script"
+        exit 1
+fi
+if [ -z "$BASEDIR" ]; then
+        logger -t pcscd-Local -p user.err \
+            "Missing BASEDIR (-b parameter) in launch script"
+        exit 1
+fi
+
+chmod -R 700 $BASEDIR
+
+exit 0

Added: branches/Solaris/buildenv/solaris/pcscd-Local.conf
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/solaris/pcscd-Local.conf?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/solaris/pcscd-Local.conf (added)
+++ branches/Solaris/buildenv/solaris/pcscd-Local.conf Thu Jun 12 10:28:09 2008
@@ -1,0 +1,21 @@
+## Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+# Note: reader-Local.conf is referenced via "READER_CONFIG_FILE",
+#       not provided by default. reader-Local.conf is to be created
+#       by the administor as necessary to extend the list of supported readers.
+#       See documentation for details.
+#
+LAUNCH_MODE = INSTANCE
+TRANSPORT = SOCKET_INETV4
+BASE_DIR = /var/run/pcscd/$DISPLAY
+IFD_PLUGIN_PATH = /usr/lib/smartcard
+READER_CONFIG_FILE = /etc/smartcard/reader-Local.conf
+USE_AUTHENTICATION = TRUE
+USE_MAPPED_MEMORY = FALSE
+INSTANCE_TIMEOUT = 600
+#LOG_FILE = /tmp/dbg
+#LOG_LEVEL = DEBUG
+#LOG_TYPE = STDERR
+#APDU_DEBUG=TRUE
+#$IFDH_SCBUS_DEBUG = 2

Propchange: branches/Solaris/buildenv/solaris/pcscd-Local.conf
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/solaris/pcscd-svc
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/solaris/pcscd-svc?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/solaris/pcscd-svc (added)
+++ branches/Solaris/buildenv/solaris/pcscd-svc Thu Jun 12 10:28:09 2008
@@ -1,0 +1,49 @@
+#!/sbin/sh
+
+. /lib/svc/share/smf_include.sh
+
+PIDFILE=/var/run/pcscd/pcscd.pid
+PCSCD=/usr/lib/smartcard/pcscd
+
+case "$1" in
+start)
+	if [ -f "$PIDFILE" ]; then
+		rm -f $PIDFILE
+	fi
+	if [ -f "$PCSCD" ]; then 
+		$PCSCD -L
+		exit $SMF_EXIT_OK
+	else
+		exit $SMF_ERR_FATAL
+	fi
+	;;
+stop)
+	pkill -f "$PCSCD -L"
+	pkill -f "$PCSCD -I"
+	pkill -f "utaction -x $PCSCD"
+	exit $SMF_EXIT_OK
+	;;
+restart)
+	pkill -f "$PCSCD -L"
+	if [ -f "$PIDFILE" ]; then
+		rm -f $PIDFILE
+	fi
+	if [ -f "$PCSCD" ]; then 
+		$PCSCD -L
+		exit $SMF_EXIT_OK
+	else
+		exit $SMF_ERR_FATAL
+	fi
+	;;
+debug)  
+	rm -f ${PIDFILE}
+        $PCSCD -f -d debug -L
+	;;
+
+*)
+	echo "Usage: $0 {start|stop}"
+	exit $SMF_ERR_FATAL
+	;;
+esac
+
+exec $cmd

Propchange: branches/Solaris/buildenv/solaris/pcscd-svc
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/solaris/pcscd.conf
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/solaris/pcscd.conf?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/solaris/pcscd.conf (added)
+++ branches/Solaris/buildenv/solaris/pcscd.conf Thu Jun 12 10:28:09 2008
@@ -1,0 +1,5 @@
+BASE_DIR = /var/run/pcscd
+TRANSPORT = SOCKET_INETV4
+USE_MAPPED_MEMORY = FALSE
+USE_AUTHENTICATION = TRUE
+FIFO_PING_TIMEOUT = 20

Propchange: branches/Solaris/buildenv/solaris/pcscd.conf
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/buildenv/solaris/pcscd.xml
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/buildenv/solaris/pcscd.xml?rev=2989&op=file
==============================================================================
--- branches/Solaris/buildenv/solaris/pcscd.xml (added)
+++ branches/Solaris/buildenv/solaris/pcscd.xml Thu Jun 12 10:28:09 2008
@@ -1,0 +1,37 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+	Copyright 2007 Sun Microsystems, Inc. All Rights Reserved
+	
+	Service that manages PCSClite pcscd instance-launcher
+
+-->
+
+<service_bundle type='manifest' name='PCSClite:pcscd'>
+
+    <service
+	name='application/security/pcscd' type='service' version='1'>
+
+	<create_default_instance enabled='true' />
+
+        <dependency name='multi-user'
+            grouping='require_all'
+            restart_on='error'
+            type='service'>
+                <service_fmri value='svc:/milestone/multi-user:default'/>
+        </dependency>
+
+	<exec_method
+		type='method'
+		name='start'
+		exec='/lib/svc/method/pcscd-svc start'
+		timeout_seconds='0'/>
+
+	<exec_method
+		type='method'
+		name='stop'
+		exec='/lib/svc/method/pcscd-svc stop'
+		timeout_seconds='0'/>
+    </service>
+
+</service_bundle>

Propchange: branches/Solaris/buildenv/solaris/pcscd.xml
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/config.h.in
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/config.h.in?rev=2989&op=file
==============================================================================
--- branches/Solaris/config.h.in (added)
+++ branches/Solaris/config.h.in Thu Jun 12 10:28:09 2008
@@ -1,0 +1,377 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* display ATR parsing debug messages. */
+#undef ATR_DEBUG
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+#undef CLOSEDIR_VOID
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the `atexit' function. */
+#undef HAVE_ATEXIT
+
+/* Define to 1 if your system has a working `chown' function. */
+#undef HAVE_CHOWN
+
+/* Define to 1 if you have the `daemon' function. */
+#undef HAVE_DAEMON
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#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 <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `flock' function. */
+#undef HAVE_FLOCK
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* 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 `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#undef HAVE_INET_NTOA
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
+/* Libusb is available */
+#undef HAVE_LIBUSB
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mkdir' function. */
+#undef HAVE_MKDIR
+
+/* Define to 1 if you have the `mkfifo' function. */
+#undef HAVE_MKFIFO
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the `munmap' function. */
+#undef HAVE_MUNMAP
+
+/* 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
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define if you have POSIX threads libraries and header files. */
+#undef HAVE_PTHREAD
+
+/* Define to 1 if you have the `putenv' function. */
+#undef HAVE_PUTENV
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+   and to 0 otherwise. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if you have the `rmdir' function. */
+#undef HAVE_RMDIR
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the <smartcard/scf.h> header file. */
+#undef HAVE_SMARTCARD_SCF_H
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* 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 `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* 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 you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* 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/file.h> header file. */
+#undef HAVE_SYS_FILE_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/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_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/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_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/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/tsol/label.h> header file. */
+#undef HAVE_SYS_TSOL_LABEL_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 <usb.h> header file. */
+#undef HAVE_USB_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_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 `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if you have the <zone.h> header file. */
+#undef HAVE_ZONE_H
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* 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 version of this package. */
+#undef PACKAGE_VERSION
+
+/* directory containing USB drivers */
+#undef PCSCLITE_HP_DROPDIR
+
+/* Port client library contacts pcscd on to obtain info */
+#undef PCSCLITE_PORTSVC_PORTNO
+
+/* PC/SC target architecture */
+#undef PCSC_ARCH
+
+/* Define to the necessary symbol if this constant uses a non-standard name on
+   your system. */
+#undef PTHREAD_CREATE_JOINABLE
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to the type of arg 1 for `select'. */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg 5 for `select'. */
+#undef SELECT_TYPE_ARG5
+
+/* 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 (default /var/run) */
+#undef USE_IPCDIR
+
+/* file containing pcscd pid */
+#undef USE_RUN_PID
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#undef YYTEXT_POINTER
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+   #define below would cause a syntax error. */
+#undef _UINT32_T
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
+   #define below would cause a syntax error. */
+#undef _UINT8_T
+
+/* 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 the type of a signed integer type of width exactly 16 bits if
+   such a type exists and the standard includes do not define it. */
+#undef int16_t
+
+/* Define to the type of a signed integer type of width exactly 32 bits if
+   such a type exists and the standard includes do not define it. */
+#undef int32_t
+
+/* Define to the type of a signed integer type of width exactly 8 bits if such
+   a type exists and the standard includes do not define it. */
+#undef int8_t
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
+
+/* 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
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+   such a type exists and the standard includes do not define it. */
+#undef uint16_t
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+   such a type exists and the standard includes do not define it. */
+#undef uint32_t
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+   such a type exists and the standard includes do not define it. */
+#undef uint8_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
+
+/* path to Xservers file */
+#undef xservers_file

Added: branches/Solaris/configure.ac
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/configure.ac?rev=2989&op=file
==============================================================================
--- branches/Solaris/configure.ac (added)
+++ branches/Solaris/configure.ac Thu Jun 12 10:28:09 2008
@@ -1,0 +1,405 @@
+# -*- mode: m4; -*-
+# Process this file with autoconf to produce a configure script
+
+m4_pattern_allow([AC_MSG_ERROR])
+m4_pattern_allow([AS_AC_EXPAND])
+m4_pattern_allow([AC_DEFINE])
+m4_pattern_allow([AC_MSG_WARN])
+m4_pattern_allow([AC_VERBOSE])
+m4_pattern_allow([AC_PROGRAM_CHECK])
+m4_pattern_allow([_PKG_SHORT_ERRORS_SUPPORTED])
+
+AC_PREREQ(2.60)
+
+AC_INIT([pcsclite with Solaris security and scalability enhancements],[1.1])
+AC_CONFIG_SRCDIR([src/pcscdaemon.c])
+AM_INIT_AUTOMAKE(1.10)
+AC_CONFIG_HEADERS([config.h])
+
+AC_CONFIG_MACRO_DIR([m4])
+
+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
+AC_PROG_GCC_TRADITIONAL
+AC_PROG_RANLIB
+AC_PATH_PROG(TEST_MINUS_S_SH, bash)
+AC_PATH_PROG(TEST_MINUS_S_SH, ksh)
+AC_PATH_PROG(TEST_MINUS_S_SH, sh)
+
+# Special check for pthread support
+ACX_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)
+
+# Add libtool support
+AM_PROG_LIBTOOL
+# 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_HEADER_DIRENT
+AC_CHECK_HEADERS([dirent.h dl.h dlfcn.h errno.h fcntl.h getopt.h malloc.h stdlib.h string.h strings.h sys/filio.h sys/time.h syslog.h unistd.h smartcard/scf.h zone.h sys/tsol/label.h libgen.h arpa/inet.h netdb.h netinet/in.h  sys/file.h sys/ioctl.h sys/socket.h])
+
+# Checks for typedefs, structures, and compiler characteristics
+AC_C_CONST
+AC_TYPE_UID_T
+AC_TYPE_SIZE_T
+AC_TYPE_INT16_T
+AC_TYPE_INT32_T
+AC_TYPE_INT8_T
+AC_TYPE_PID_T
+AC_TYPE_SIGNAL
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT8_T
+AC_HEADER_TIME
+
+# Checks for library functions
+AC_FUNC_ERROR_AT_LINE
+AC_FUNC_STAT
+AC_FUNC_VPRINTF
+AC_FUNC_CHOWN
+AC_FUNC_CLOSEDIR_VOID
+AC_FUNC_FORK
+AC_FUNC_MALLOC
+AC_FUNC_MMAP
+AC_FUNC_REALLOC
+#AC_FUNC_SELECT
+AC_FUNC_SELECT_ARGTYPES
+
+AC_CHECK_FUNCS(daemon flock getopt_long nanosleep strerror vsnprintf atexit gethostbyname getpagesize gettimeofday inet_ntoa memset mkdir mkfifo munmap putenv rmdir select socket strchr strdup strrchr strstr strtol strtoul)
+
+# strlcpy, strlcat from OpenBSD
+AC_CHECK_FUNCS(strlcpy strlcat)
+
+# 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([char foo;],
+	[	AC_VERBOSE([yes])
+		SYMBOL_VISIBILITY="-fvisibility=hidden" ],
+	AC_VERBOSE([no]))
+CFLAGS="$saved_CFLAGS"
+AC_SUBST(SYMBOL_VISIBILITY)
+
+AC_SUBST(LIBDL)
+AC_CHECK_LIB(dl, dlopen, [LIBDL="$LIBDL -ldl" ac_cv_func_dlopen_ldl=yes], ac_cv_func_dlopen_ldl=no)
+
+# Use 'uname' output as an architecture define
+uname=`uname`
+case "$uname" in
+Darwin)
+	uname=MacOS
+	;;
+SunOS)
+	uname=Solaris
+	;;
+esac
+AC_DEFINE_UNQUOTED(PCSC_ARCH, "$uname", [PC/SC target architecture])
+
+# See if socket() is found from libsocket
+AC_CHECK_LIB(socket, socket, [LIBS="$LIBS -lsocket"])
+
+# See if gethostbyname is found from libnsl.so
+AC_CHECK_LIB(nsl, gethostbyname, [LIBS="$LIBS -lnsl"])
+
+# --enable-xtag                                       
+AC_ARG_ENABLE(xtag,
+                AS_HELP_STRING([--enable-xtag=<Xservers PATH>],
+		[specifies path to system's Xservers file.  Needed only if configuring for portsvc, ie. launcher mode]), 
+                [xtag="${enableval}"],[xtag=false])           
+AC_VERBOSE([enable xtag: $xtag])             
+                                                         
+AC_DEFINE_UNQUOTED(xservers_file, 
+		   "$xtag", [path to Xservers file])
+
+
+# --enable-portsvc
+AC_ARG_ENABLE(portsvc,
+		AS_HELP_STRING([--enable-portsvc=PORT],[specifies port \
+                        client library can contact pcscd on if a server \
+			instance is running in 'port server' mode. \
+			(default=port server mode not available)]),
+		[portsvc="${enableval}"],[portsvc=false])
+AC_VERBOSE([enable portsvc                : $portsvc])
+
+AC_DEFINE_UNQUOTED(PCSCLITE_PORTSVC_PORTNO, 
+		$enableval, 
+		[Port client library contacts pcscd on to obtain info])
+
+
+# --enable-libusb
+AC_ARG_ENABLE(libusb,
+	AS_HELP_STRING([--disable-libusb,do not use libusb]),
+	[ use_libusb="${enableval}" ], [ use_libusb="${use_libusb-yes}" ] )
+
+# check if libusb is used
+if test "x$use_libusb" != xno ; then
+	PKG_CHECK_MODULES([LIBUSB], [libusb], [],
+		[
+			AC_VERBOSE([no])
+			AC_PROGRAM_CHECK([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(usb.h, [],
+		[ AC_MSG_ERROR([usb.h not found, use ./configure LIBUSB_CFLAGS=...]) ])
+
+	LIBS="$LIBS $COREFOUNDATION $IOKIT"
+
+	AC_MSG_CHECKING([for usb_init])
+	AC_TRY_LINK_FUNC(usb_init, [ AC_VERBOSE([yes]) ],
+		[ AC_MSG_ERROR([libusb not found, use ./configure LIBUSB_LIBS=...]) ])
+
+	AC_MSG_CHECKING([for usb_get_string_simple])
+	AC_TRY_LINK_FUNC(usb_get_string_simple, [ AC_VERBOSE([yes]) ],
+		[ AC_MSG_ERROR([your libusb is too old. install version 0.1.7 or above]) ])
+
+	# 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])
+fi
+AC_VERBOSE([enable libusb support         : $use_libusb])
+
+# --enable-usbdropdir=DIR
+AC_ARG_ENABLE(usbdropdir,
+  AS_HELP_STRING(--enable-usbdropdir=DIR,directory containing USB
+				  drivers (default /usr/local/pcsc/drivers)),
+[usbdropdir="${enableval}"], [usbdropdir=false])
+if test x${usbdropdir} = xfalse ; then
+	if test "x$prefix" != xNONE; then
+		usbdropdir="$prefix/pcsc/drivers"
+	else
+		usbdropdir="$ac_default_prefix/pcsc/drivers"
+	fi
+fi
+AC_VERBOSE([enable USB drop directory     : $usbdropdir])
+AC_DEFINE_UNQUOTED(PCSCLITE_HP_DROPDIR, "$usbdropdir", [directory containing USB drivers])
+
+# --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])
+
+AC_VERBOSE([enable ATR parsing messages   : $debugatr])
+
+if test x${debugatr} = xtrue ; then
+  AC_DEFINE(ATR_DEBUG, 1, [display ATR parsing debug messages.])
+fi
+
+# --enable-scf
+AC_ARG_ENABLE(scf,
+  AS_HELP_STRING(--enable-scf,use SCF for reader support),
+[ case "${enableval}" in
+  yes)	scf=true ;;
+  no)	scf=false ;;
+  *) AC_MSG_ERROR([bad value ${enableval} for --enable-scf]) ;;
+esac], [scf=false])
+
+AC_SUBST(LIBSMARTCARD)
+if test x$scf = xtrue -a x$ac_cv_header_smartcard_scf_h = xyes; then
+  AC_CHECK_LIB(smartcard, SCF_strerror, [LIBSMARTCARD="$LIBSMARTCARD -lsmartcard" scf=true], scf=false)
+else
+  scf=false
+fi
+AC_VERBOSE([enable SCF reader support     : $scf])
+AM_CONDITIONAL(HAVE_SCF, test x$scf = xtrue)
+
+# --enable-rtlib=DIR
+AC_ARG_ENABLE(rtlibdir,
+	AS_HELP_STRING(--enable-rtlib=DIR, daemon-specific runtime path for library path, (default /usr/lib/smartcard)), 
+	[rtlibdir="${enableval}"], [rtlibdir=false])
+
+if test x${rtlibdir} != xfalse ; then
+	AC_VERBOSE([enable rtlibdir               : $rtlibdir])
+else
+	rtlibdir="/usr/lib/smartcard"
+	AC_VERBOSE([enable rtlibdir               : /usr/lib/smartcard (default)])
+fi
+
+# --enable-confdir=DIR
+AC_ARG_ENABLE(confdir,
+	AS_HELP_STRING(--enable-confdir=DIR,directory containing pcsc.conf
+			(default /etc)),
+	[confdir="${enableval}"], [confdir=false])
+
+if test x${confdir} != xfalse ; then
+	AC_VERBOSE([enable confdir                : $confdir])
+else
+	confdir="/etc"
+	AC_VERBOSE([enable confdir                : /etc (default)])
+fi
+
+# --enable-runpid=FILE
+AC_ARG_ENABLE(runpid,
+  AS_HELP_STRING(--enable-runpid=FILE,file containing pcscd pid),
+[runpid="${enableval}"], [runpid=false])
+
+AC_VERBOSE([enable runpid                 : $runpid])
+
+# HAVE_RUNPID is for pcscd.8
+if test x${runpid} != xfalse ; then
+	AC_DEFINE_UNQUOTED(USE_RUN_PID, "$runpid", [file containing pcscd pid])
+	AC_SUBST(HAVE_RUNPID,'')
+else
+	AC_SUBST(HAVE_RUNPID,'.\" ')
+fi
+
+# --enable-ipcdir=DIR
+AC_ARG_ENABLE(ipcdir,
+  AS_HELP_STRING(--enable-ipcdir=DIR,directory containing IPC files
+				  (default /var/run)),
+[ipcdir="${enableval}"], [ipcdir=false])
+
+if test x${ipcdir} != xfalse ; then
+	AC_VERBOSE([enable ipcdir                 : $ipcdir])
+
+	AC_DEFINE_UNQUOTED(USE_IPCDIR, "$ipcdir", [directory containing IPC files (default /var/run)])
+else
+	AC_VERBOSE([enable ipcdir                 : /var/run (default)])
+fi
+
+CPPFLAGS="-I\${top_srcdir}/src $CPPFLAGS"
+
+# HOST_TO_CCID
+if test "x$ac_cv_c_bigendian" = "xyes"; then
+	AC_SUBST(host_to_ccid_16, ['((((x) >> 8) & 0xFF) + ((x & 0xFF) << 8))'])
+	AC_SUBST(host_to_ccid_32, ['((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + ((x & 0xFF00) << 8) + (((x) & 0xFF) << 24))'])
+	AC_VERBOSE([plateform endianess           : big endian])
+else
+	AC_SUBST(host_to_ccid_16, ['(x)'])
+	AC_SUBST(host_to_ccid_32, ['(x)'])
+	AC_VERBOSE([plateform endianess           : little endian])
+fi
+
+# Setup dist stuff
+AC_SUBST(usbdropdir)
+AC_SUBST(confdir)
+AC_SUBST(rtlibdir)
+AC_SUBST(xtag)
+AC_SUBST(libdir)
+AC_SUBST(runpid)
+AC_SUBST(host_to_ccid_16)
+AC_SUBST(host_to_ccid_32)
+AS_AC_EXPAND(confdir_exp,$confdir) 
+AS_AC_EXPAND(rtlibdir_exp,$rtlibdir)
+AS_AC_EXPAND(libdir_exp,$libdir)
+AS_AC_EXPAND(xservers_file_exp,$xtag)
+AS_AC_EXPAND(sysconfdir_exp,$sysconfdir) 
+AS_AC_EXPAND(sbindir_exp,$sbindir)
+AS_AC_EXPAND(localstatedir_exp,$localstatedir)
+
+# Write Makefiles
+AC_CONFIG_FILES([
+Makefile
+m4/Makefile
+doc/Makefile
+doc/doxygen.conf
+doc/pcscd.8
+doc/reader.conf.5
+doc/example/Makefile
+etc/Makefile
+etc/pcscd.init
+etc/reader.conf
+etc/update-reader.conf
+src/Makefile
+src/PCSC/pcsclite.h
+src/PCSC/reader.h
+src/utils/Makefile
+src/modules/Makefile
+src/libpcsclite.pc
+win32/Makefile
+])
+AC_OUTPUT
+

Added: branches/Solaris/ltmain.sh
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/ltmain.sh?rev=2989&op=file
==============================================================================
--- branches/Solaris/ltmain.sh (added)
+++ branches/Solaris/ltmain.sh Thu Jun 12 10:28:09 2008
@@ -1,0 +1,6863 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord at gnu.ai.mit.edu>, 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 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# 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.
+
+basename="s,^.*/,,g"
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+progname=`echo "$progpath" | $SED $basename`
+modename="$progname"
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.5.22
+TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes.
+if test -n "${ZSH_VERSION+set}" ; then
+  setopt NO_GLOB_SUBST
+fi
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell, and then maybe $echo will work.
+  exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit $EXIT_SUCCESS
+fi
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  SP2NL='tr \040 \012'
+  NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  SP2NL='tr \100 \n'
+  NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+  save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+  save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS=" 	$lt_nl"
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+  $echo "$modename: not configured to build any kind of library" 1>&2
+  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+  exit $EXIT_FAILURE
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+duplicate_deps=no
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+	# Failing that, at least try and use $RANDOM to avoid a race
+	my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+	save_mktempdir_umask=`umask`
+	umask 0077
+	$mkdir "$my_tmpdir"
+	umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || {
+        $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
+	exit $EXIT_FAILURE
+      }
+    fi
+
+    $echo "X$my_tmpdir" | $Xsed
+}
+
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+      $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+      win32_nmres=`eval $NM -f posix -A $1 | \
+	$SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $echo $win32_libid_type
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+	case $arg in
+	  *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  arg="\"$arg\""
+	  ;;
+	esac
+	CC_quoted="$CC_quoted $arg"
+      done
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+	for z in $available_tags; do
+	  if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+	    # Evaluate the configuration.
+	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+	    CC_quoted=
+	    for arg in $CC; do
+	    # Double-quote args containing other shell metacharacters.
+	    case $arg in
+	      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	      arg="\"$arg\""
+	      ;;
+	    esac
+	    CC_quoted="$CC_quoted $arg"
+	  done
+	    case "$@ " in
+	      " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
+	      # The compiler in the base compile command matches
+	      # the one in the tagged configuration.
+	      # Assume this is the tagged configuration we want.
+	      tagname=$z
+	      break
+	      ;;
+	    esac
+	  fi
+	done
+	# If $tagname still isn't set, then no tagged configuration
+	# was found and let the user know that the "--tag" command
+	# line option must be used.
+	if test -z "$tagname"; then
+	  $echo "$modename: unable to infer tagged configuration"
+	  $echo "$modename: specify a tag with \`--tag'" 1>&2
+	  exit $EXIT_FAILURE
+#        else
+#          $echo "$modename: using $tagname tagged configuration"
+	fi
+	;;
+      esac
+    fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+
+    $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+    $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+      exit $EXIT_FAILURE
+    fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+    my_status=""
+
+    $show "${rm}r $my_gentop"
+    $run ${rm}r "$my_gentop"
+    $show "$mkdir $my_gentop"
+    $run $mkdir "$my_gentop"
+    my_status=$?
+    if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+      exit $my_status
+    fi
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+	[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+	*) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+      my_xdir="$my_gentop/$my_xlib"
+
+      $show "${rm}r $my_xdir"
+      $run ${rm}r "$my_xdir"
+      $show "$mkdir $my_xdir"
+      $run $mkdir "$my_xdir"
+      exit_status=$?
+      if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
+	exit $exit_status
+      fi
+      case $host in
+      *-darwin*)
+	$show "Extracting $my_xabs"
+	# Do not bother doing anything if just a dry run
+	if test -z "$run"; then
+	  darwin_orig_dir=`pwd`
+	  cd $my_xdir || exit $?
+	  darwin_archive=$my_xabs
+	  darwin_curdir=`pwd`
+	  darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+	  darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+	  if test -n "$darwin_arches"; then 
+	    darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+	    darwin_arch=
+	    $show "$darwin_base_archive has multiple architectures $darwin_arches"
+	    for darwin_arch in  $darwin_arches ; do
+	      mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+	      cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+	      func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+	      cd "$darwin_curdir"
+	      $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+	    done # $darwin_arches
+      ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+	    darwin_file=
+	    darwin_files=
+	    for darwin_file in $darwin_filelist; do
+	      darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+	      lipo -create -output "$darwin_file" $darwin_files
+	    done # $darwin_filelist
+	    ${rm}r unfat-$$
+	    cd "$darwin_orig_dir"
+	  else
+	    cd "$darwin_orig_dir"
+ 	    func_extract_an_archive "$my_xdir" "$my_xabs"
+	  fi # $darwin_arches
+	fi # $run
+	;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+        ;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+    func_extract_archives_result="$my_oldobjs"
+}
+# End of Shell function definitions
+#####################################
+
+# Darwin sucks
+eval std_shrext=\"$shrext_cmds\"
+
+disable_libs=no
+
+# Parse our command line options once, thoroughly.
+while test "$#" -gt 0
+do
+  arg="$1"
+  shift
+
+  case $arg in
+  -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$prev"; then
+    case $prev in
+    execute_dlfiles)
+      execute_dlfiles="$execute_dlfiles $arg"
+      ;;
+    tag)
+      tagname="$arg"
+      preserve_args="${preserve_args}=$arg"
+
+      # Check whether tagname contains only valid characters
+      case $tagname in
+      *[!-_A-Za-z0-9,/]*)
+	$echo "$progname: invalid tag name: $tagname" 1>&2
+	exit $EXIT_FAILURE
+	;;
+      esac
+
+      case $tagname in
+      CC)
+	# Don't test for the "default" C tag, as we know, it's there, but
+	# not specially marked.
+	;;
+      *)
+	if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
+	  taglist="$taglist $tagname"
+	  # Evaluate the configuration.
+	  eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
+	else
+	  $echo "$progname: ignoring unknown tag $tagname" 1>&2
+	fi
+	;;
+      esac
+      ;;
+    *)
+      eval "$prev=\$arg"
+      ;;
+    esac
+
+    prev=
+    prevopt=
+    continue
+  fi
+
+  # Have we seen a non-optional argument yet?
+  case $arg in
+  --help)
+    show_help=yes
+    ;;
+
+  --version)
+    $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+    $echo
+    $echo "Copyright (C) 2005  Free Software Foundation, Inc."
+    $echo "This is free software; see the source for copying conditions.  There is NO"
+    $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+    exit $?
+    ;;
+
+  --config)
+    ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
+    done
+    exit $?
+    ;;
+
+  --debug)
+    $echo "$progname: enabling shell trace mode"
+    set -x
+    preserve_args="$preserve_args $arg"
+    ;;
+
+  --dry-run | -n)
+    run=:
+    ;;
+
+  --features)
+    $echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      $echo "enable shared libraries"
+    else
+      $echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      $echo "enable static libraries"
+    else
+      $echo "disable static libraries"
+    fi
+    exit $?
+    ;;
+
+  --finish) mode="finish" ;;
+
+  --mode) prevopt="--mode" prev=mode ;;
+  --mode=*) mode="$optarg" ;;
+
+  --preserve-dup-deps) duplicate_deps="yes" ;;
+
+  --quiet | --silent)
+    show=:
+    preserve_args="$preserve_args $arg"
+    ;;
+
+  --tag)
+    prevopt="--tag"
+    prev=tag
+    preserve_args="$preserve_args --tag"
+    ;;
+  --tag=*)
+    set tag "$optarg" ${1+"$@"}
+    shift
+    prev=tag
+    preserve_args="$preserve_args --tag"
+    ;;
+
+  -dlopen)
+    prevopt="-dlopen"
+    prev=execute_dlfiles
+    ;;
+
+  -*)
+    $echo "$modename: unrecognized option \`$arg'" 1>&2
+    $echo "$help" 1>&2
+    exit $EXIT_FAILURE
+    ;;
+
+  *)
+    nonopt="$arg"
+    break
+    ;;
+  esac
+done
+
+if test -n "$prevopt"; then
+  $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+  $echo "$help" 1>&2
+  exit $EXIT_FAILURE
+fi
+
+case $disable_libs in
+no) 
+  ;;
+shared)
+  build_libtool_libs=no
+  build_old_libs=yes
+  ;;
+static)
+  build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+  ;;
+esac
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+  # Infer the operation mode.
+  if test -z "$mode"; then
+    $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+    $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
+    case $nonopt in
+    *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
+      mode=link
+      for arg
+      do
+	case $arg in
+	-c)
+	   mode=compile
+	   break
+	   ;;
+	esac
+      done
+      ;;
+    *db | *dbx | *strace | *truss)
+      mode=execute
+      ;;
+    *install*|cp|mv)
+      mode=install
+      ;;
+    *rm)
+      mode=uninstall
+      ;;
+    *)
+      # If we have no mode, but dlfiles were specified, then do execute mode.
+      test -n "$execute_dlfiles" && mode=execute
+
+      # Just use the default operation mode.
+      if test -z "$mode"; then
+	if test -n "$nonopt"; then
+	  $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+	else
+	  $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+	fi
+      fi
+      ;;
+    esac
+  fi
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+    $echo "$help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$modename --help --mode=$mode' for more information."
+
+  # These modes are in order of execution frequency so that they run quickly.
+  case $mode in
+  # libtool compile mode
+  compile)
+    modename="$modename: compile"
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+	# do not "continue".  Instead, add this to base_compile
+	lastarg="$arg"
+	arg_mode=normal
+	;;
+
+      target )
+	libobj="$arg"
+	arg_mode=normal
+	continue
+	;;
+
+      normal )
+	# Accept any command-line options.
+	case $arg in
+	-o)
+	  if test -n "$libobj" ; then
+	    $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+	  arg_mode=target
+	  continue
+	  ;;
+
+	-static | -prefer-pic | -prefer-non-pic)
+	  later="$later $arg"
+	  continue
+	  ;;
+
+	-no-suppress)
+	  suppress_opt=no
+	  continue
+	  ;;
+
+	-Xcompiler)
+	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
+	  continue      #  The current "srcfile" will either be retained or
+	  ;;            #  replaced later.  I would guess that would be a bug.
+
+	-Wc,*)
+	  args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+	  lastarg=
+	  save_ifs="$IFS"; IFS=','
+ 	  for arg in $args; do
+	    IFS="$save_ifs"
+
+	    # Double-quote args containing other shell metacharacters.
+	    # Many Bourne shells cannot handle close brackets correctly
+	    # in scan sets, so we specify it separately.
+	    case $arg in
+	      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	      arg="\"$arg\""
+	      ;;
+	    esac
+	    lastarg="$lastarg $arg"
+	  done
+	  IFS="$save_ifs"
+	  lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+	  # Add the arguments to base_compile.
+	  base_compile="$base_compile $lastarg"
+	  continue
+	  ;;
+
+	* )
+	  # Accept the current argument as the source file.
+	  # The previous "srcfile" becomes the current argument.
+	  #
+	  lastarg="$srcfile"
+	  srcfile="$arg"
+	  ;;
+	esac  #  case $arg
+	;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+      case $lastarg in
+      # Double-quote args containing other shell metacharacters.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, and some SunOS ksh mistreat backslash-escaping
+      # in scan sets (worked around with variable expansion),
+      # and furthermore cannot handle '|' '&' '(' ')' in scan sets 
+      # at all, so we specify them separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	lastarg="\"$lastarg\""
+	;;
+      esac
+
+      base_compile="$base_compile $lastarg"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      $echo "$modename: you must specify an argument for -Xcompile"
+      exit $EXIT_FAILURE
+      ;;
+    target)
+      $echo "$modename: you must specify a target with \`-o'" 1>&2
+      exit $EXIT_FAILURE
+      ;;
+    *)
+      # Get the name of the library object.
+      [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    xform='[cCFSifmso]'
+    case $libobj in
+    *.ada) xform=ada ;;
+    *.adb) xform=adb ;;
+    *.ads) xform=ads ;;
+    *.asm) xform=asm ;;
+    *.c++) xform=c++ ;;
+    *.cc) xform=cc ;;
+    *.ii) xform=ii ;;
+    *.class) xform=class ;;
+    *.cpp) xform=cpp ;;
+    *.cxx) xform=cxx ;;
+    *.f90) xform=f90 ;;
+    *.for) xform=for ;;
+    *.java) xform=java ;;
+    esac
+
+    libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+    case $libobj in
+    *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+    *)
+      $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+      exit $EXIT_FAILURE
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -static)
+	build_old_libs=yes
+	continue
+	;;
+
+      -prefer-pic)
+	pic_mode=yes
+	continue
+	;;
+
+      -prefer-non-pic)
+	pic_mode=no
+	continue
+	;;
+      esac
+    done
+
+    qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+    case $qlibobj in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	qlibobj="\"$qlibobj\"" ;;
+    esac
+    test "X$libobj" != "X$qlibobj" \
+	&& $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' 	&()|`$[]' \
+	&& $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
+    objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+    xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+    if test "X$xdir" = "X$obj"; then
+      xdir=
+    else
+      xdir=$xdir/
+    fi
+    lobj=${xdir}$objdir/$objname
+
+    if test -z "$base_compile"; then
+      $echo "$modename: you must specify a compilation command" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    $run $rm $removelist
+    trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+      removelist="$removelist $output_obj $lockfile"
+      trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $run ln "$progpath" "$lockfile" 2>/dev/null; do
+	$show "Waiting for $lockfile to be removed"
+	sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+	$echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$run $rm $removelist
+	exit $EXIT_FAILURE
+      fi
+      $echo "$srcfile" > "$lockfile"
+    fi
+
+    if test -n "$fix_srcfile_path"; then
+      eval srcfile=\"$fix_srcfile_path\"
+    fi
+    qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+    case $qsrcfile in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+      qsrcfile="\"$qsrcfile\"" ;;
+    esac
+
+    $run $rm "$libobj" "${libobj}T"
+
+    # Create a libtool object file (analogous to a ".la" file),
+    # but don't create it if we're doing a dry run.
+    test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+	command="$base_compile $qsrcfile $pic_flag"
+      else
+	# Don't build PIC code
+	command="$base_compile $qsrcfile"
+      fi
+
+      if test ! -d "${xdir}$objdir"; then
+	$show "$mkdir ${xdir}$objdir"
+	$run $mkdir ${xdir}$objdir
+	exit_status=$?
+	if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
+	  exit $exit_status
+	fi
+      fi
+
+      if test -z "$output_obj"; then
+	# Place PIC objects in $objdir
+	command="$command -o $lobj"
+      fi
+
+      $run $rm "$lobj" "$output_obj"
+
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+	test -n "$output_obj" && $run $rm $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$run $rm $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+	$show "$mv $output_obj $lobj"
+	if $run $mv $output_obj $lobj; then :
+	else
+	  error=$?
+	  $run $rm $removelist
+	  exit $error
+	fi
+      fi
+
+      # Append the name of the PIC object to the libtool object file.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+        suppress_output=' >/dev/null 2>&1'
+      fi
+    else
+      # No PIC object so indicate it doesn't exist in the libtool
+      # object file.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+	# Don't build PIC code
+	command="$base_compile $qsrcfile"
+      else
+	command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+	command="$command -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      $run $rm "$obj" "$output_obj"
+      $show "$command"
+      if $run eval "$command"; then :
+      else
+	$run $rm $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      if test "$need_locks" = warn &&
+	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+	$echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+	$run $rm $removelist
+	exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+	$show "$mv $output_obj $obj"
+	if $run $mv $output_obj $obj; then :
+	else
+	  error=$?
+	  $run $rm $removelist
+	  exit $error
+	fi
+      fi
+
+      # Append the name of the non-PIC object the libtool object file.
+      # Only append if the libtool object file exists.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+    else
+      # Append the name of the non-PIC object the libtool object file.
+      # Only append if the libtool object file exists.
+      test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+    fi
+
+    $run $mv "${libobj}T" "${libobj}"
+
+    # Unlock the critical section if it was locked
+    if test "$need_locks" != no; then
+      $run $rm "$lockfile"
+    fi
+
+    exit $EXIT_SUCCESS
+    ;;
+
+  # libtool link mode
+  link | relink)
+    modename="$modename: link"
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args="$nonopt"
+    base_compile="$nonopt $@"
+    compile_command="$nonopt"
+    finalize_command="$nonopt"
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+
+    avoid_version=no
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    notinst_path= # paths that contain not-installed libtool libraries
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -all-static | -static)
+	if test "X$arg" = "X-all-static"; then
+	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+	    $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+	  fi
+	  if test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=yes
+	else
+	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
+	    dlopen_self=$dlopen_self_static
+	  fi
+	  prefer_static_libs=built
+	fi
+	build_libtool_libs=no
+	build_old_libs=yes
+	break
+	;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+	;;
+      *) qarg=$arg ;;
+      esac
+      libtool_args="$libtool_args $qarg"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+	case $prev in
+	output)
+	  compile_command="$compile_command @OUTPUT@"
+	  finalize_command="$finalize_command @OUTPUT@"
+	  ;;
+	esac
+
+	case $prev in
+	dlfiles|dlprefiles)
+	  if test "$preload" = no; then
+	    # Add the symbol object into the linking commands.
+	    compile_command="$compile_command @SYMFILE@"
+	    finalize_command="$finalize_command @SYMFILE@"
+	    preload=yes
+	  fi
+	  case $arg in
+	  *.la | *.lo) ;;  # We handle these cases below.
+	  force)
+	    if test "$dlself" = no; then
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  self)
+	    if test "$prev" = dlprefiles; then
+	      dlself=yes
+	    elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+	      dlself=yes
+	    else
+	      dlself=needless
+	      export_dynamic=yes
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  *)
+	    if test "$prev" = dlfiles; then
+	      dlfiles="$dlfiles $arg"
+	    else
+	      dlprefiles="$dlprefiles $arg"
+	    fi
+	    prev=
+	    continue
+	    ;;
+	  esac
+	  ;;
+	expsyms)
+	  export_symbols="$arg"
+	  if test ! -f "$arg"; then
+	    $echo "$modename: symbol file \`$arg' does not exist"
+	    exit $EXIT_FAILURE
+	  fi
+	  prev=
+	  continue
+	  ;;
+	expsyms_regex)
+	  export_symbols_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	inst_prefix)
+	  inst_prefix_dir="$arg"
+	  prev=
+	  continue
+	  ;;
+	precious_regex)
+	  precious_files_regex="$arg"
+	  prev=
+	  continue
+	  ;;
+	release)
+	  release="-$arg"
+	  prev=
+	  continue
+	  ;;
+	objectlist)
+	  if test -f "$arg"; then
+	    save_arg=$arg
+	    moreargs=
+	    for fil in `cat $save_arg`
+	    do
+#	      moreargs="$moreargs $fil"
+	      arg=$fil
+	      # A libtool-controlled object.
+
+	      # Check to see that this really is a libtool object.
+	      if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+		pic_object=
+		non_pic_object=
+
+		# Read the .lo file
+		# If there is no directory component, then add one.
+		case $arg in
+		*/* | *\\*) . $arg ;;
+		*) . ./$arg ;;
+		esac
+
+		if test -z "$pic_object" || \
+		   test -z "$non_pic_object" ||
+		   test "$pic_object" = none && \
+		   test "$non_pic_object" = none; then
+		  $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+		  exit $EXIT_FAILURE
+		fi
+
+		# Extract subdirectory from the argument.
+		xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+		if test "X$xdir" = "X$arg"; then
+		  xdir=
+		else
+		  xdir="$xdir/"
+		fi
+
+		if test "$pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  pic_object="$xdir$pic_object"
+
+		  if test "$prev" = dlfiles; then
+		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		      dlfiles="$dlfiles $pic_object"
+		      prev=
+		      continue
+		    else
+		      # If libtool objects are unsupported, then we need to preload.
+		      prev=dlprefiles
+		    fi
+		  fi
+
+		  # CHECK ME:  I think I busted this.  -Ossama
+		  if test "$prev" = dlprefiles; then
+		    # Preload the old-style object.
+		    dlprefiles="$dlprefiles $pic_object"
+		    prev=
+		  fi
+
+		  # A PIC object.
+		  libobjs="$libobjs $pic_object"
+		  arg="$pic_object"
+		fi
+
+		# Non-PIC object.
+		if test "$non_pic_object" != none; then
+		  # Prepend the subdirectory the object is found in.
+		  non_pic_object="$xdir$non_pic_object"
+
+		  # A standard non-PIC object
+		  non_pic_objects="$non_pic_objects $non_pic_object"
+		  if test -z "$pic_object" || test "$pic_object" = none ; then
+		    arg="$non_pic_object"
+		  fi
+		else
+		  # If the PIC object exists, use it instead.
+		  # $xdir was prepended to $pic_object above.
+		  non_pic_object="$pic_object"
+		  non_pic_objects="$non_pic_objects $non_pic_object"
+		fi
+	      else
+		# Only an error if not doing a dry-run.
+		if test -z "$run"; then
+		  $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+		  exit $EXIT_FAILURE
+		else
+		  # Dry-run case.
+
+		  # Extract subdirectory from the argument.
+		  xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+		  if test "X$xdir" = "X$arg"; then
+		    xdir=
+		  else
+		    xdir="$xdir/"
+		  fi
+
+		  pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+		  non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+		  libobjs="$libobjs $pic_object"
+		  non_pic_objects="$non_pic_objects $non_pic_object"
+		fi
+	      fi
+	    done
+	  else
+	    $echo "$modename: link input file \`$save_arg' does not exist"
+	    exit $EXIT_FAILURE
+	  fi
+	  arg=$save_arg
+	  prev=
+	  continue
+	  ;;
+	rpath | xrpath)
+	  # We need an absolute path.
+	  case $arg in
+	  [\\/]* | [A-Za-z]:[\\/]*) ;;
+	  *)
+	    $echo "$modename: only absolute run-paths are allowed" 1>&2
+	    exit $EXIT_FAILURE
+	    ;;
+	  esac
+	  if test "$prev" = rpath; then
+	    case "$rpath " in
+	    *" $arg "*) ;;
+	    *) rpath="$rpath $arg" ;;
+	    esac
+	  else
+	    case "$xrpath " in
+	    *" $arg "*) ;;
+	    *) xrpath="$xrpath $arg" ;;
+	    esac
+	  fi
+	  prev=
+	  continue
+	  ;;
+	xcompiler)
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  compile_command="$compile_command $qarg"
+	  finalize_command="$finalize_command $qarg"
+	  continue
+	  ;;
+	xlinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $wl$qarg"
+	  prev=
+	  compile_command="$compile_command $wl$qarg"
+	  finalize_command="$finalize_command $wl$qarg"
+	  continue
+	  ;;
+	xcclinker)
+	  linker_flags="$linker_flags $qarg"
+	  compiler_flags="$compiler_flags $qarg"
+	  prev=
+	  compile_command="$compile_command $qarg"
+	  finalize_command="$finalize_command $qarg"
+	  continue
+	  ;;
+	shrext)
+  	  shrext_cmds="$arg"
+	  prev=
+	  continue
+	  ;;
+	darwin_framework|darwin_framework_skip)
+	  test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
+	  compile_command="$compile_command $arg"
+	  finalize_command="$finalize_command $arg"
+	  prev=
+	  continue
+	  ;;
+	*)
+	  eval "$prev=\"\$arg\""
+	  prev=
+	  continue
+	  ;;
+	esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+	if test -n "$link_static_flag"; then
+	  compile_command="$compile_command $link_static_flag"
+	  finalize_command="$finalize_command $link_static_flag"
+	fi
+	continue
+	;;
+
+      -allow-undefined)
+	# FIXME: remove this flag sometime in the future.
+	$echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+	continue
+	;;
+
+      -avoid-version)
+	avoid_version=yes
+	continue
+	;;
+
+      -dlopen)
+	prev=dlfiles
+	continue
+	;;
+
+      -dlpreopen)
+	prev=dlprefiles
+	continue
+	;;
+
+      -export-dynamic)
+	export_dynamic=yes
+	continue
+	;;
+
+      -export-symbols | -export-symbols-regex)
+	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	  $echo "$modename: more than one -exported-symbols argument is not allowed"
+	  exit $EXIT_FAILURE
+	fi
+	if test "X$arg" = "X-export-symbols"; then
+	  prev=expsyms
+	else
+	  prev=expsyms_regex
+	fi
+	continue
+	;;
+
+      -framework|-arch|-isysroot)
+	case " $CC " in
+	  *" ${arg} ${1} "* | *" ${arg}	${1} "*) 
+		prev=darwin_framework_skip ;;
+	  *) compiler_flags="$compiler_flags $arg"
+	     prev=darwin_framework ;;
+	esac
+	compile_command="$compile_command $arg"
+	finalize_command="$finalize_command $arg"
+	continue
+	;;
+
+      -inst-prefix-dir)
+	prev=inst_prefix
+	continue
+	;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+	case $with_gcc/$host in
+	no/*-*-irix* | /*-*-irix*)
+	  compile_command="$compile_command $arg"
+	  finalize_command="$finalize_command $arg"
+	  ;;
+	esac
+	continue
+	;;
+
+      -L*)
+	dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  absdir=`cd "$dir" && pwd`
+	  if test -z "$absdir"; then
+	    $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+	    absdir="$dir"
+	    notinst_path="$notinst_path $dir"
+	  fi
+	  dir="$absdir"
+	  ;;
+	esac
+	case "$deplibs " in
+	*" -L$dir "*) ;;
+	*)
+	  deplibs="$deplibs -L$dir"
+	  lib_search_path="$lib_search_path $dir"
+	  ;;
+	esac
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+	  testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$dir:"*) ;;
+	  *) dllsearchpath="$dllsearchpath:$dir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  esac
+	  ;;
+	esac
+	continue
+	;;
+
+      -l*)
+	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
+	    # These systems don't actually have a C or math library (as such)
+	    continue
+	    ;;
+	  *-*-os2*)
+	    # These systems don't actually have a C library (as such)
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C and math libraries are in the System framework
+	    deplibs="$deplibs -framework System"
+	    continue
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    test "X$arg" = "X-lc" && continue
+	    ;;
+	  esac
+	elif test "X$arg" = "X-lc_r"; then
+	 case $host in
+	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	   # Do not include libc_r directly, use -pthread flag.
+	   continue
+	   ;;
+	 esac
+	fi
+	deplibs="$deplibs $arg"
+	continue
+	;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      -model)
+	compile_command="$compile_command $arg"
+	compiler_flags="$compiler_flags $arg"
+	finalize_command="$finalize_command $arg"
+	prev=xcompiler
+	continue
+	;;
+
+     -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+	compiler_flags="$compiler_flags $arg"
+	compile_command="$compile_command $arg"
+	finalize_command="$finalize_command $arg"
+	continue
+	;;
+
+      -module)
+	module=yes
+	continue
+	;;
+
+      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+      # -r[0-9][0-9]* specifies the processor on the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+      # +DA*, +DD* enable 64-bit mode on the HP compiler
+      # -q* pass through compiler args for the IBM compiler
+      # -m* pass through architecture-specific compiler args for GCC
+      # -m*, -t[45]*, -txscale* pass through architecture-specific
+      # compiler args for GCC
+      # -pg pass through profiling flag for GCC
+      # @file GCC response files
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \
+      -t[45]*|-txscale*|@*)
+
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+	case $arg in
+	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  arg="\"$arg\""
+	  ;;
+	esac
+        compile_command="$compile_command $arg"
+        finalize_command="$finalize_command $arg"
+        compiler_flags="$compiler_flags $arg"
+        continue
+        ;;
+
+      -shrext)
+	prev=shrext
+	continue
+	;;
+
+      -no-fast-install)
+	fast_install=no
+	continue
+	;;
+
+      -no-install)
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+	  # The PATH hackery in wrapper scripts is required on Windows
+	  # in order for the loader to find any dlls it needs.
+	  $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+	  $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+	  fast_install=no
+	  ;;
+	*) no_install=yes ;;
+	esac
+	continue
+	;;
+
+      -no-undefined)
+	allow_undefined=no
+	continue
+	;;
+
+      -objectlist)
+	prev=objectlist
+	continue
+	;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+	prev=precious_regex
+	continue
+	;;
+
+      -release)
+	prev=release
+	continue
+	;;
+
+      -rpath)
+	prev=rpath
+	continue
+	;;
+
+      -R)
+	prev=xrpath
+	continue
+	;;
+
+      -R*)
+	dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+	# We need an absolute path.
+	case $dir in
+	[\\/]* | [A-Za-z]:[\\/]*) ;;
+	*)
+	  $echo "$modename: only absolute run-paths are allowed" 1>&2
+	  exit $EXIT_FAILURE
+	  ;;
+	esac
+	case "$xrpath " in
+	*" $dir "*) ;;
+	*) xrpath="$xrpath $dir" ;;
+	esac
+	continue
+	;;
+
+      -static)
+	# The effects of -static are defined in a previous loop.
+	# We used to do the same as -all-static on platforms that
+	# didn't have a PIC flag, but the assumption that the effects
+	# would be equivalent was wrong.  It would break on at least
+	# Digital Unix and AIX.
+	continue
+	;;
+
+      -thread-safe)
+	thread_safe=yes
+	continue
+	;;
+
+      -version-info)
+	prev=vinfo
+	continue
+	;;
+      -version-number)
+	prev=vinfo
+	vinfo_number=yes
+	continue
+	;;
+
+      -Wc,*)
+	args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+	  case $flag in
+	    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	    flag="\"$flag\""
+	    ;;
+	  esac
+	  arg="$arg $wl$flag"
+	  compiler_flags="$compiler_flags $flag"
+	done
+	IFS="$save_ifs"
+	arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+	;;
+
+      -Wl,*)
+	args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+	arg=
+	save_ifs="$IFS"; IFS=','
+	for flag in $args; do
+	  IFS="$save_ifs"
+	  case $flag in
+	    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	    flag="\"$flag\""
+	    ;;
+	  esac
+	  arg="$arg $wl$flag"
+	  compiler_flags="$compiler_flags $wl$flag"
+	  linker_flags="$linker_flags $flag"
+	done
+	IFS="$save_ifs"
+	arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+	;;
+
+      -Xcompiler)
+	prev=xcompiler
+	continue
+	;;
+
+      -Xlinker)
+	prev=xlinker
+	continue
+	;;
+
+      -XCClinker)
+	prev=xcclinker
+	continue
+	;;
+
+      # Some other compiler flag.
+      -* | +*)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+	case $arg in
+	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  arg="\"$arg\""
+	  ;;
+	esac
+	;;
+
+      *.$objext)
+	# A standard object.
+	objs="$objs $arg"
+	;;
+
+      *.lo)
+	# A libtool-controlled object.
+
+	# Check to see that this really is a libtool object.
+	if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	  pic_object=
+	  non_pic_object=
+
+	  # Read the .lo file
+	  # If there is no directory component, then add one.
+	  case $arg in
+	  */* | *\\*) . $arg ;;
+	  *) . ./$arg ;;
+	  esac
+
+	  if test -z "$pic_object" || \
+	     test -z "$non_pic_object" ||
+	     test "$pic_object" = none && \
+	     test "$non_pic_object" = none; then
+	    $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+
+	  # Extract subdirectory from the argument.
+	  xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+	  if test "X$xdir" = "X$arg"; then
+	    xdir=
+ 	  else
+	    xdir="$xdir/"
+	  fi
+
+	  if test "$pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    pic_object="$xdir$pic_object"
+
+	    if test "$prev" = dlfiles; then
+	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+		dlfiles="$dlfiles $pic_object"
+		prev=
+		continue
+	      else
+		# If libtool objects are unsupported, then we need to preload.
+		prev=dlprefiles
+	      fi
+	    fi
+
+	    # CHECK ME:  I think I busted this.  -Ossama
+	    if test "$prev" = dlprefiles; then
+	      # Preload the old-style object.
+	      dlprefiles="$dlprefiles $pic_object"
+	      prev=
+	    fi
+
+	    # A PIC object.
+	    libobjs="$libobjs $pic_object"
+	    arg="$pic_object"
+	  fi
+
+	  # Non-PIC object.
+	  if test "$non_pic_object" != none; then
+	    # Prepend the subdirectory the object is found in.
+	    non_pic_object="$xdir$non_pic_object"
+
+	    # A standard non-PIC object
+	    non_pic_objects="$non_pic_objects $non_pic_object"
+	    if test -z "$pic_object" || test "$pic_object" = none ; then
+	      arg="$non_pic_object"
+	    fi
+	  else
+	    # If the PIC object exists, use it instead.
+	    # $xdir was prepended to $pic_object above.
+	    non_pic_object="$pic_object"
+	    non_pic_objects="$non_pic_objects $non_pic_object"
+	  fi
+	else
+	  # Only an error if not doing a dry-run.
+	  if test -z "$run"; then
+	    $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+	    exit $EXIT_FAILURE
+	  else
+	    # Dry-run case.
+
+	    # Extract subdirectory from the argument.
+	    xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+	    if test "X$xdir" = "X$arg"; then
+	      xdir=
+	    else
+	      xdir="$xdir/"
+	    fi
+
+	    pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+	    non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+	    libobjs="$libobjs $pic_object"
+	    non_pic_objects="$non_pic_objects $non_pic_object"
+	  fi
+	fi
+	;;
+
+      *.$libext)
+	# An archive.
+	deplibs="$deplibs $arg"
+	old_deplibs="$old_deplibs $arg"
+	continue
+	;;
+
+      *.la)
+	# A libtool-controlled library.
+
+	if test "$prev" = dlfiles; then
+	  # This library was specified with -dlopen.
+	  dlfiles="$dlfiles $arg"
+	  prev=
+	elif test "$prev" = dlprefiles; then
+	  # The library was specified with -dlpreopen.
+	  dlprefiles="$dlprefiles $arg"
+	  prev=
+	else
+	  deplibs="$deplibs $arg"
+	fi
+	continue
+	;;
+
+      # Some other compiler argument.
+      *)
+	# Unknown arguments in both finalize_command and compile_command need
+	# to be aesthetically quoted because they are evaled later.
+	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+	case $arg in
+	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	  arg="\"$arg\""
+	  ;;
+	esac
+	;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+	compile_command="$compile_command $arg"
+	finalize_command="$finalize_command $arg"
+      fi
+    done # argument parsing loop
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      compile_command="$compile_command $arg"
+      finalize_command="$finalize_command $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+    if test "X$output_objdir" = "X$output"; then
+      output_objdir="$objdir"
+    else
+      output_objdir="$output_objdir/$objdir"
+    fi
+    # Create the object directory.
+    if test ! -d "$output_objdir"; then
+      $show "$mkdir $output_objdir"
+      $run $mkdir $output_objdir
+      exit_status=$?
+      if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
+	exit $exit_status
+      fi
+    fi
+
+    # Determine the type of output
+    case $output in
+    "")
+      $echo "$modename: you must specify an output file" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    case $host in
+    *cygwin* | *mingw* | *pw32*)
+      # don't eliminate duplications in $postdeps and $predeps
+      duplicate_compiler_generated_deps=yes
+      ;;
+    *)
+      duplicate_compiler_generated_deps=$duplicate_deps
+      ;;
+    esac
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if test "X$duplicate_deps" = "Xyes" ; then
+	case "$libs " in
+	*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	esac
+      fi
+      libs="$libs $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+	for pre_post_dep in $predeps $postdeps; do
+	  case "$pre_post_deps " in
+	  *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+	  esac
+	  pre_post_deps="$pre_post_deps $pre_post_dep"
+	done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    case $linkmode in
+    lib)
+	passes="conv link"
+	for file in $dlfiles $dlprefiles; do
+	  case $file in
+	  *.la) ;;
+	  *)
+	    $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+	    exit $EXIT_FAILURE
+	    ;;
+	  esac
+	done
+	;;
+    prog)
+	compile_deplibs=
+	finalize_deplibs=
+	alldeplibs=no
+	newdlfiles=
+	newdlprefiles=
+	passes="conv scan dlopen dlpreopen link"
+	;;
+    *)  passes="conv"
+	;;
+    esac
+    for pass in $passes; do
+      if test "$linkmode,$pass" = "lib,link" ||
+	 test "$linkmode,$pass" = "prog,scan"; then
+	libs="$deplibs"
+	deplibs=
+      fi
+      if test "$linkmode" = prog; then
+	case $pass in
+	dlopen) libs="$dlfiles" ;;
+	dlpreopen) libs="$dlprefiles" ;;
+	link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+	esac
+      fi
+      if test "$pass" = dlopen; then
+	# Collect dlpreopened libraries
+	save_deplibs="$deplibs"
+	deplibs=
+      fi
+      for deplib in $libs; do
+	lib=
+	found=no
+	case $deplib in
+	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+	  if test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$deplib $compile_deplibs"
+	    finalize_deplibs="$deplib $finalize_deplibs"
+	  else
+	    compiler_flags="$compiler_flags $deplib"
+	  fi
+	  continue
+	  ;;
+	-l*)
+	  if test "$linkmode" != lib && test "$linkmode" != prog; then
+	    $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+	    continue
+	  fi
+	  name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+	  for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+	    for search_ext in .la $std_shrext .so .a; do
+	      # Search the libtool library
+	      lib="$searchdir/lib${name}${search_ext}"
+	      if test -f "$lib"; then
+		if test "$search_ext" = ".la"; then
+		  found=yes
+		else
+		  found=no
+		fi
+		break 2
+	      fi
+	    done
+	  done
+	  if test "$found" != yes; then
+	    # deplib doesn't seem to be a libtool library
+	    if test "$linkmode,$pass" = "prog,link"; then
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      deplibs="$deplib $deplibs"
+	      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    continue
+	  else # deplib is a libtool library
+	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+	    # We need to do some special things here, and not later.
+	    if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	      case " $predeps $postdeps " in
+	      *" $deplib "*)
+		if (${SED} -e '2q' $lib |
+                    grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+		  library_names=
+		  old_library=
+		  case $lib in
+		  */* | *\\*) . $lib ;;
+		  *) . ./$lib ;;
+		  esac
+		  for l in $old_library $library_names; do
+		    ll="$l"
+		  done
+		  if test "X$ll" = "X$old_library" ; then # only static version available
+		    found=no
+		    ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+		    test "X$ladir" = "X$lib" && ladir="."
+		    lib=$ladir/$old_library
+		    if test "$linkmode,$pass" = "prog,link"; then
+		      compile_deplibs="$deplib $compile_deplibs"
+		      finalize_deplibs="$deplib $finalize_deplibs"
+		    else
+		      deplibs="$deplib $deplibs"
+		      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+		    fi
+		    continue
+		  fi
+		fi
+	        ;;
+	      *) ;;
+	      esac
+	    fi
+	  fi
+	  ;; # -l
+	-L*)
+	  case $linkmode in
+	  lib)
+	    deplibs="$deplib $deplibs"
+	    test "$pass" = conv && continue
+	    newdependency_libs="$deplib $newdependency_libs"
+	    newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+	    ;;
+	  prog)
+	    if test "$pass" = conv; then
+	      deplibs="$deplib $deplibs"
+	      continue
+	    fi
+	    if test "$pass" = scan; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+	    ;;
+	  *)
+	    $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
+	    ;;
+	  esac # linkmode
+	  continue
+	  ;; # -L
+	-R*)
+	  if test "$pass" = link; then
+	    dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+	    # Make sure the xrpath contains only unique directories.
+	    case "$xrpath " in
+	    *" $dir "*) ;;
+	    *) xrpath="$xrpath $dir" ;;
+	    esac
+	  fi
+	  deplibs="$deplib $deplibs"
+	  continue
+	  ;;
+	*.la) lib="$deplib" ;;
+	*.$libext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	    continue
+	  fi
+	  case $linkmode in
+	  lib)
+	    valid_a_lib=no
+	    case $deplibs_check_method in
+	      match_pattern*)
+		set dummy $deplibs_check_method
+	        match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+		if eval $echo \"$deplib\" 2>/dev/null \
+		    | $SED 10q \
+		    | $EGREP "$match_pattern_regex" > /dev/null; then
+		  valid_a_lib=yes
+		fi
+		;;
+	      pass_all)
+		valid_a_lib=yes
+		;;
+            esac
+	    if test "$valid_a_lib" != yes; then
+	      $echo
+	      $echo "*** Warning: Trying to link with static lib archive $deplib."
+	      $echo "*** I have the capability to make that library automatically link in when"
+	      $echo "*** you link to this library.  But I can only do this if you have a"
+	      $echo "*** shared version of the library, which you do not appear to have"
+	      $echo "*** because the file extensions .$libext of this argument makes me believe"
+	      $echo "*** that it is just a static archive that I should not used here."
+	    else
+	      $echo
+	      $echo "*** Warning: Linking the shared library $output against the"
+	      $echo "*** static library $deplib is not portable!"
+	      deplibs="$deplib $deplibs"
+	    fi
+	    continue
+	    ;;
+	  prog)
+	    if test "$pass" != link; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    fi
+	    continue
+	    ;;
+	  esac # linkmode
+	  ;; # *.$libext
+	*.lo | *.$objext)
+	  if test "$pass" = conv; then
+	    deplibs="$deplib $deplibs"
+	  elif test "$linkmode" = prog; then
+	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+	      # If there is no dlopen support or we're linking statically,
+	      # we need to preload.
+	      newdlprefiles="$newdlprefiles $deplib"
+	      compile_deplibs="$deplib $compile_deplibs"
+	      finalize_deplibs="$deplib $finalize_deplibs"
+	    else
+	      newdlfiles="$newdlfiles $deplib"
+	    fi
+	  fi
+	  continue
+	  ;;
+	%DEPLIBS%)
+	  alldeplibs=yes
+	  continue
+	  ;;
+	esac # case $deplib
+	if test "$found" = yes || test -f "$lib"; then :
+	else
+	  $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
+	  exit $EXIT_FAILURE
+	fi
+
+	# Check to see that this really is a libtool archive.
+	if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+	else
+	  $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+	  exit $EXIT_FAILURE
+	fi
+
+	ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+	test "X$ladir" = "X$lib" && ladir="."
+
+	dlname=
+	dlopen=
+	dlpreopen=
+	libdir=
+	library_names=
+	old_library=
+	# If the library was installed with an old release of libtool,
+	# it will not redefine variables installed, or shouldnotlink
+	installed=yes
+	shouldnotlink=no
+	avoidtemprpath=
+
+
+	# Read the .la file
+	case $lib in
+	*/* | *\\*) . $lib ;;
+	*) . ./$lib ;;
+	esac
+
+	if test "$linkmode,$pass" = "lib,link" ||
+	   test "$linkmode,$pass" = "prog,scan" ||
+	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+	  test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+	  test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+	fi
+
+	if test "$pass" = conv; then
+	  # Only check for convenience libraries
+	  deplibs="$lib $deplibs"
+	  if test -z "$libdir"; then
+	    if test -z "$old_library"; then
+	      $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+	      exit $EXIT_FAILURE
+	    fi
+	    # It is a libtool convenience library, so add in its objects.
+	    convenience="$convenience $ladir/$objdir/$old_library"
+	    old_convenience="$old_convenience $ladir/$objdir/$old_library"
+	    tmp_libs=
+	    for deplib in $dependency_libs; do
+	      deplibs="$deplib $deplibs"
+              if test "X$duplicate_deps" = "Xyes" ; then
+	        case "$tmp_libs " in
+	        *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	        esac
+              fi
+	      tmp_libs="$tmp_libs $deplib"
+	    done
+	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
+	    $echo "$modename: \`$lib' is not a convenience library" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+	  continue
+	fi # $pass = conv
+
+
+	# Get the name of the library we link against.
+	linklib=
+	for l in $old_library $library_names; do
+	  linklib="$l"
+	done
+	if test -z "$linklib"; then
+	  $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+	  exit $EXIT_FAILURE
+	fi
+
+	# This library was specified with -dlopen.
+	if test "$pass" = dlopen; then
+	  if test -z "$libdir"; then
+	    $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+	  if test -z "$dlname" ||
+	     test "$dlopen_support" != yes ||
+	     test "$build_libtool_libs" = no; then
+	    # If there is no dlname, no dlopen support or we're linking
+	    # statically, we need to preload.  We also need to preload any
+	    # dependent libraries so libltdl's deplib preloader doesn't
+	    # bomb out in the load deplibs phase.
+	    dlprefiles="$dlprefiles $lib $dependency_libs"
+	  else
+	    newdlfiles="$newdlfiles $lib"
+	  fi
+	  continue
+	fi # $pass = dlopen
+
+	# We need an absolute path.
+	case $ladir in
+	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+	*)
+	  abs_ladir=`cd "$ladir" && pwd`
+	  if test -z "$abs_ladir"; then
+	    $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+	    $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+	    abs_ladir="$ladir"
+	  fi
+	  ;;
+	esac
+	laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+	# Find the relevant object directory and library name.
+	if test "X$installed" = Xyes; then
+	  if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    $echo "$modename: warning: library \`$lib' was moved." 1>&2
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    libdir="$abs_ladir"
+	  else
+	    dir="$libdir"
+	    absdir="$libdir"
+	  fi
+	  test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+	else
+	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+	    dir="$ladir"
+	    absdir="$abs_ladir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  else
+	    dir="$ladir/$objdir"
+	    absdir="$abs_ladir/$objdir"
+	    # Remove this search path later
+	    notinst_path="$notinst_path $abs_ladir"
+	  fi
+	fi # $installed = yes
+	name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+	# This library was specified with -dlpreopen.
+	if test "$pass" = dlpreopen; then
+	  if test -z "$libdir"; then
+	    $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+	  # Prefer using a static library (so that no silly _DYNAMIC symbols
+	  # are required to link).
+	  if test -n "$old_library"; then
+	    newdlprefiles="$newdlprefiles $dir/$old_library"
+	  # Otherwise, use the dlname, so that lt_dlopen finds it.
+	  elif test -n "$dlname"; then
+	    newdlprefiles="$newdlprefiles $dir/$dlname"
+	  else
+	    newdlprefiles="$newdlprefiles $dir/$linklib"
+	  fi
+	fi # $pass = dlpreopen
+
+	if test -z "$libdir"; then
+	  # Link the convenience library
+	  if test "$linkmode" = lib; then
+	    deplibs="$dir/$old_library $deplibs"
+	  elif test "$linkmode,$pass" = "prog,link"; then
+	    compile_deplibs="$dir/$old_library $compile_deplibs"
+	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
+	  else
+	    deplibs="$lib $deplibs" # used for prog,scan pass
+	  fi
+	  continue
+	fi
+
+
+	if test "$linkmode" = prog && test "$pass" != link; then
+	  newlib_search_path="$newlib_search_path $ladir"
+	  deplibs="$lib $deplibs"
+
+	  linkalldeplibs=no
+	  if test "$link_all_deplibs" != no || test -z "$library_names" ||
+	     test "$build_libtool_libs" = no; then
+	    linkalldeplibs=yes
+	  fi
+
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    case $deplib in
+	    -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+	    esac
+	    # Need to link against all dependency_libs?
+	    if test "$linkalldeplibs" = yes; then
+	      deplibs="$deplib $deplibs"
+	    else
+	      # Need to hardcode shared library paths
+	      # or/and link against static libraries
+	      newdependency_libs="$deplib $newdependency_libs"
+	    fi
+	    if test "X$duplicate_deps" = "Xyes" ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done # for deplib
+	  continue
+	fi # $linkmode = prog...
+
+	if test "$linkmode,$pass" = "prog,link"; then
+	  if test -n "$library_names" &&
+	     { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+	    # We need to hardcode the library path
+	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+	      # Make sure the rpath contains only unique directories.
+	      case "$temp_rpath " in
+	      *" $dir "*) ;;
+	      *" $absdir "*) ;;
+	      *) temp_rpath="$temp_rpath $absdir" ;;
+	      esac
+	    fi
+
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi # $linkmode,$pass = prog,link...
+
+	  if test "$alldeplibs" = yes &&
+	     { test "$deplibs_check_method" = pass_all ||
+	       { test "$build_libtool_libs" = yes &&
+		 test -n "$library_names"; }; }; then
+	    # We only need to search for static libraries
+	    continue
+	  fi
+	fi
+
+	link_static=no # Whether the deplib will be linked statically
+	use_static_libs=$prefer_static_libs
+	if test "$use_static_libs" = built && test "$installed" = yes ; then
+	  use_static_libs=no
+	fi
+	if test -n "$library_names" &&
+	   { test "$use_static_libs" = no || test -z "$old_library"; }; then
+	  if test "$installed" = no; then
+	    notinst_deplibs="$notinst_deplibs $lib"
+	    need_relink=yes
+	  fi
+	  # This is a shared library
+
+	  # Warn about portability, can't link against -module's on
+	  # some systems (darwin)
+	  if test "$shouldnotlink" = yes && test "$pass" = link ; then
+	    $echo
+	    if test "$linkmode" = prog; then
+	      $echo "*** Warning: Linking the executable $output against the loadable module"
+	    else
+	      $echo "*** Warning: Linking the shared library $output against the loadable module"
+	    fi
+	    $echo "*** $linklib is not portable!"
+	  fi
+	  if test "$linkmode" = lib &&
+	     test "$hardcode_into_libs" = yes; then
+	    # Hardcode the library path.
+	    # Skip directories that are in the system default run-time
+	    # search path.
+	    case " $sys_lib_dlsearch_path " in
+	    *" $absdir "*) ;;
+	    *)
+	      case "$compile_rpath " in
+	      *" $absdir "*) ;;
+	      *) compile_rpath="$compile_rpath $absdir"
+	      esac
+	      ;;
+	    esac
+	    case " $sys_lib_dlsearch_path " in
+	    *" $libdir "*) ;;
+	    *)
+	      case "$finalize_rpath " in
+	      *" $libdir "*) ;;
+	      *) finalize_rpath="$finalize_rpath $libdir"
+	      esac
+	      ;;
+	    esac
+	  fi
+
+	  if test -n "$old_archive_from_expsyms_cmds"; then
+	    # figure out the soname
+	    set dummy $library_names
+	    realname="$2"
+	    shift; shift
+	    libname=`eval \\$echo \"$libname_spec\"`
+	    # use dlname if we got it. it's perfectly good, no?
+	    if test -n "$dlname"; then
+	      soname="$dlname"
+	    elif test -n "$soname_spec"; then
+	      # bleh windows
+	      case $host in
+	      *cygwin* | mingw*)
+		major=`expr $current - $age`
+		versuffix="-$major"
+		;;
+	      esac
+	      eval soname=\"$soname_spec\"
+	    else
+	      soname="$realname"
+	    fi
+
+	    # Make a new name for the extract_expsyms_cmds to use
+	    soroot="$soname"
+	    soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+	    newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+	    # If the library has no export list, then create one now
+	    if test -f "$output_objdir/$soname-def"; then :
+	    else
+	      $show "extracting exported symbol list from \`$soname'"
+	      save_ifs="$IFS"; IFS='~'
+	      cmds=$extract_expsyms_cmds
+	      for cmd in $cmds; do
+		IFS="$save_ifs"
+		eval cmd=\"$cmd\"
+		$show "$cmd"
+		$run eval "$cmd" || exit $?
+	      done
+	      IFS="$save_ifs"
+	    fi
+
+	    # Create $newlib
+	    if test -f "$output_objdir/$newlib"; then :; else
+	      $show "generating import library for \`$soname'"
+	      save_ifs="$IFS"; IFS='~'
+	      cmds=$old_archive_from_expsyms_cmds
+	      for cmd in $cmds; do
+		IFS="$save_ifs"
+		eval cmd=\"$cmd\"
+		$show "$cmd"
+		$run eval "$cmd" || exit $?
+	      done
+	      IFS="$save_ifs"
+	    fi
+	    # make sure the library variables are pointing to the new library
+	    dir=$output_objdir
+	    linklib=$newlib
+	  fi # test -n "$old_archive_from_expsyms_cmds"
+
+	  if test "$linkmode" = prog || test "$mode" != relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    lib_linked=yes
+	    case $hardcode_action in
+	    immediate | unsupported)
+	      if test "$hardcode_direct" = no; then
+		add="$dir/$linklib"
+		case $host in
+		  *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+		  *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+		  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+		    *-*-unixware7*) add_dir="-L$dir" ;;
+		  *-*-darwin* )
+		    # if the lib is a module then we can not link against
+		    # it, someone is ignoring the new warnings I added
+		    if /usr/bin/file -L $add 2> /dev/null |
+                      $EGREP ": [^:]* bundle" >/dev/null ; then
+		      $echo "** Warning, lib $linklib is a module, not a shared library"
+		      if test -z "$old_library" ; then
+		        $echo
+		        $echo "** And there doesn't seem to be a static archive available"
+		        $echo "** The link will probably fail, sorry"
+		      else
+		        add="$dir/$old_library"
+		      fi
+		    fi
+		esac
+	      elif test "$hardcode_minus_L" = no; then
+		case $host in
+		*-*-sunos*) add_shlibpath="$dir" ;;
+		esac
+		add_dir="-L$dir"
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = no; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    relink)
+	      if test "$hardcode_direct" = yes; then
+		add="$dir/$linklib"
+	      elif test "$hardcode_minus_L" = yes; then
+		add_dir="-L$dir"
+		# Try looking first in the location we're being installed to.
+		if test -n "$inst_prefix_dir"; then
+		  case $libdir in
+		    [\\/]*)
+		      add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		      ;;
+		  esac
+		fi
+		add="-l$name"
+	      elif test "$hardcode_shlibpath_var" = yes; then
+		add_shlibpath="$dir"
+		add="-l$name"
+	      else
+		lib_linked=no
+	      fi
+	      ;;
+	    *) lib_linked=no ;;
+	    esac
+
+	    if test "$lib_linked" != yes; then
+	      $echo "$modename: configuration error: unsupported hardcode properties"
+	      exit $EXIT_FAILURE
+	    fi
+
+	    if test -n "$add_shlibpath"; then
+	      case :$compile_shlibpath: in
+	      *":$add_shlibpath:"*) ;;
+	      *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+	      esac
+	    fi
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	      if test "$hardcode_direct" != yes && \
+		 test "$hardcode_minus_L" != yes && \
+		 test "$hardcode_shlibpath_var" = yes; then
+		case :$finalize_shlibpath: in
+		*":$libdir:"*) ;;
+		*) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+		esac
+	      fi
+	    fi
+	  fi
+
+	  if test "$linkmode" = prog || test "$mode" = relink; then
+	    add_shlibpath=
+	    add_dir=
+	    add=
+	    # Finalize command for both is simple: just hardcode it.
+	    if test "$hardcode_direct" = yes; then
+	      add="$libdir/$linklib"
+	    elif test "$hardcode_minus_L" = yes; then
+	      add_dir="-L$libdir"
+	      add="-l$name"
+	    elif test "$hardcode_shlibpath_var" = yes; then
+	      case :$finalize_shlibpath: in
+	      *":$libdir:"*) ;;
+	      *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+	      esac
+	      add="-l$name"
+	    elif test "$hardcode_automatic" = yes; then
+	      if test -n "$inst_prefix_dir" &&
+		 test -f "$inst_prefix_dir$libdir/$linklib" ; then
+	        add="$inst_prefix_dir$libdir/$linklib"
+	      else
+	        add="$libdir/$linklib"
+	      fi
+	    else
+	      # We cannot seem to hardcode it, guess we'll fake it.
+	      add_dir="-L$libdir"
+	      # Try looking first in the location we're being installed to.
+	      if test -n "$inst_prefix_dir"; then
+		case $libdir in
+		  [\\/]*)
+		    add_dir="$add_dir -L$inst_prefix_dir$libdir"
+		    ;;
+		esac
+	      fi
+	      add="-l$name"
+	    fi
+
+	    if test "$linkmode" = prog; then
+	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+	    else
+	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
+	      test -n "$add" && deplibs="$add $deplibs"
+	    fi
+	  fi
+	elif test "$linkmode" = prog; then
+	  # Here we assume that one of hardcode_direct or hardcode_minus_L
+	  # is not unsupported.  This is valid on all known static and
+	  # shared platforms.
+	  if test "$hardcode_direct" != unsupported; then
+	    test -n "$old_library" && linklib="$old_library"
+	    compile_deplibs="$dir/$linklib $compile_deplibs"
+	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
+	  else
+	    compile_deplibs="-l$name -L$dir $compile_deplibs"
+	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+	  fi
+	elif test "$build_libtool_libs" = yes; then
+	  # Not a shared library
+	  if test "$deplibs_check_method" != pass_all; then
+	    # We're trying link a shared library against a static one
+	    # but the system doesn't support it.
+
+	    # Just print a warning and add the library to dependency_libs so
+	    # that the program can be linked against the static library.
+	    $echo
+	    $echo "*** Warning: This system can not link to static lib archive $lib."
+	    $echo "*** I have the capability to make that library automatically link in when"
+	    $echo "*** you link to this library.  But I can only do this if you have a"
+	    $echo "*** shared version of the library, which you do not appear to have."
+	    if test "$module" = yes; then
+	      $echo "*** But as you try to build a module library, libtool will still create "
+	      $echo "*** a static module, that should work as long as the dlopening application"
+	      $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+	      if test -z "$global_symbol_pipe"; then
+		$echo
+		$echo "*** However, this would only work if libtool was able to extract symbol"
+		$echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+		$echo "*** not find such a program.  So, this module is probably useless."
+		$echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	      fi
+	      if test "$build_old_libs" = no; then
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  else
+	    deplibs="$dir/$old_library $deplibs"
+	    link_static=yes
+	  fi
+	fi # link shared/static library?
+
+	if test "$linkmode" = lib; then
+	  if test -n "$dependency_libs" &&
+	     { test "$hardcode_into_libs" != yes ||
+	       test "$build_old_libs" = yes ||
+	       test "$link_static" = yes; }; then
+	    # Extract -R from dependency_libs
+	    temp_deplibs=
+	    for libdir in $dependency_libs; do
+	      case $libdir in
+	      -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+		   case " $xrpath " in
+		   *" $temp_xrpath "*) ;;
+		   *) xrpath="$xrpath $temp_xrpath";;
+		   esac;;
+	      *) temp_deplibs="$temp_deplibs $libdir";;
+	      esac
+	    done
+	    dependency_libs="$temp_deplibs"
+	  fi
+
+	  newlib_search_path="$newlib_search_path $absdir"
+	  # Link against this library
+	  test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+	  # ... and its dependency_libs
+	  tmp_libs=
+	  for deplib in $dependency_libs; do
+	    newdependency_libs="$deplib $newdependency_libs"
+	    if test "X$duplicate_deps" = "Xyes" ; then
+	      case "$tmp_libs " in
+	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+	      esac
+	    fi
+	    tmp_libs="$tmp_libs $deplib"
+	  done
+
+	  if test "$link_all_deplibs" != no; then
+	    # Add the search paths of all dependency libraries
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      -L*) path="$deplib" ;;
+	      *.la)
+		dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+		test "X$dir" = "X$deplib" && dir="."
+		# We need an absolute path.
+		case $dir in
+		[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+		*)
+		  absdir=`cd "$dir" && pwd`
+		  if test -z "$absdir"; then
+		    $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+		    absdir="$dir"
+		  fi
+		  ;;
+		esac
+		if grep "^installed=no" $deplib > /dev/null; then
+		  path="$absdir/$objdir"
+		else
+		  eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		  if test -z "$libdir"; then
+		    $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+		    exit $EXIT_FAILURE
+		  fi
+		  if test "$absdir" != "$libdir"; then
+		    $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+		  fi
+		  path="$absdir"
+		fi
+		depdepl=
+		case $host in
+		*-*-darwin*)
+		  # we do not want to link against static libs,
+		  # but need to link against shared
+		  eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+		  if test -n "$deplibrary_names" ; then
+		    for tmp in $deplibrary_names ; do
+		      depdepl=$tmp
+		    done
+		    if test -f "$path/$depdepl" ; then
+		      depdepl="$path/$depdepl"
+		    fi
+		    # do not add paths which are already there
+		    case " $newlib_search_path " in
+		    *" $path "*) ;;
+		    *) newlib_search_path="$newlib_search_path $path";;
+		    esac
+		  fi
+		  path=""
+		  ;;
+		*)
+		  path="-L$path"
+		  ;;
+		esac
+		;;
+	      -l*)
+		case $host in
+		*-*-darwin*)
+		  # Again, we only want to link against shared libraries
+		  eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+		  for tmp in $newlib_search_path ; do
+		    if test -f "$tmp/lib$tmp_libs.dylib" ; then
+		      eval depdepl="$tmp/lib$tmp_libs.dylib"
+		      break
+		    fi
+		  done
+		  path=""
+		  ;;
+		*) continue ;;
+		esac
+		;;
+	      *) continue ;;
+	      esac
+	      case " $deplibs " in
+	      *" $path "*) ;;
+	      *) deplibs="$path $deplibs" ;;
+	      esac
+	      case " $deplibs " in
+	      *" $depdepl "*) ;;
+	      *) deplibs="$depdepl $deplibs" ;;
+	      esac
+	    done
+	  fi # link_all_deplibs != no
+	fi # linkmode = lib
+      done # for deplib in $libs
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+	# Link the dlpreopened libraries before other libraries
+	for deplib in $save_deplibs; do
+	  deplibs="$deplib $deplibs"
+	done
+      fi
+      if test "$pass" != dlopen; then
+	if test "$pass" != conv; then
+	  # Make sure lib_search_path contains only unique directories.
+	  lib_search_path=
+	  for dir in $newlib_search_path; do
+	    case "$lib_search_path " in
+	    *" $dir "*) ;;
+	    *) lib_search_path="$lib_search_path $dir" ;;
+	    esac
+	  done
+	  newlib_search_path=
+	fi
+
+	if test "$linkmode,$pass" != "prog,link"; then
+	  vars="deplibs"
+	else
+	  vars="compile_deplibs finalize_deplibs"
+	fi
+	for var in $vars dependency_libs; do
+	  # Add libraries to $var in reverse order
+	  eval tmp_libs=\"\$$var\"
+	  new_libs=
+	  for deplib in $tmp_libs; do
+	    # FIXME: Pedantically, this is the right thing to do, so
+	    #        that some nasty dependency loop isn't accidentally
+	    #        broken:
+	    #new_libs="$deplib $new_libs"
+	    # Pragmatically, this seems to cause very few problems in
+	    # practice:
+	    case $deplib in
+	    -L*) new_libs="$deplib $new_libs" ;;
+	    -R*) ;;
+	    *)
+	      # And here is the reason: when a library appears more
+	      # than once as an explicit dependence of a library, or
+	      # is implicitly linked in more than once by the
+	      # compiler, it is considered special, and multiple
+	      # occurrences thereof are not removed.  Compare this
+	      # with having the same library being listed as a
+	      # dependency of multiple other libraries: in this case,
+	      # we know (pedantically, we assume) the library does not
+	      # need to be listed more than once, so we keep only the
+	      # last copy.  This is not always right, but it is rare
+	      # enough that we require users that really mean to play
+	      # such unportable linking tricks to link the library
+	      # using -Wl,-lname, so that libtool does not consider it
+	      # for duplicate removal.
+	      case " $specialdeplibs " in
+	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
+	      *)
+		case " $new_libs " in
+		*" $deplib "*) ;;
+		*) new_libs="$deplib $new_libs" ;;
+		esac
+		;;
+	      esac
+	      ;;
+	    esac
+	  done
+	  tmp_libs=
+	  for deplib in $new_libs; do
+	    case $deplib in
+	    -L*)
+	      case " $tmp_libs " in
+	      *" $deplib "*) ;;
+	      *) tmp_libs="$tmp_libs $deplib" ;;
+	      esac
+	      ;;
+	    *) tmp_libs="$tmp_libs $deplib" ;;
+	    esac
+	  done
+	  eval $var=\"$tmp_libs\"
+	done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+	case " $predeps $postdeps $compiler_lib_search_path " in
+	*" $i "*)
+	  i=""
+	  ;;
+	esac
+	if test -n "$i" ; then
+	  tmp_libs="$tmp_libs $i"
+	fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$deplibs"; then
+	$echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	$echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+	$echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+	$echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+	$echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$release"; then
+	$echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+      fi
+
+      if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+	$echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+      fi
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs="$objs$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+	name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+	eval shared_ext=\"$shrext_cmds\"
+	eval libname=\"$libname_spec\"
+	;;
+      *)
+	if test "$module" = no; then
+	  $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+	  $echo "$help" 1>&2
+	  exit $EXIT_FAILURE
+	fi
+	if test "$need_lib_prefix" != no; then
+	  # Add the "lib" prefix for modules if required
+	  name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+	  eval shared_ext=\"$shrext_cmds\"
+	  eval libname=\"$libname_spec\"
+	else
+	  libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+	fi
+	;;
+      esac
+
+      if test -n "$objs"; then
+	if test "$deplibs_check_method" != pass_all; then
+	  $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+	  exit $EXIT_FAILURE
+	else
+	  $echo
+	  $echo "*** Warning: Linking the shared library $output against the non-libtool"
+	  $echo "*** objects $objs is not portable!"
+	  libobjs="$libobjs $objs"
+	fi
+      fi
+
+      if test "$dlself" != no; then
+	$echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+      fi
+
+      set dummy $rpath
+      if test "$#" -gt 2; then
+	$echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+      fi
+      install_libdir="$2"
+
+      oldlibs=
+      if test -z "$rpath"; then
+	if test "$build_libtool_libs" = yes; then
+	  # Building a libtool convenience library.
+	  # Some compilers have problems with a `.al' extension so
+	  # convenience libraries should have the same extension an
+	  # archive normally would.
+	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
+	  build_libtool_libs=convenience
+	  build_old_libs=yes
+	fi
+
+	if test -n "$vinfo"; then
+	  $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
+	fi
+
+	if test -n "$release"; then
+	  $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+	fi
+      else
+
+	# Parse the version information argument.
+	save_ifs="$IFS"; IFS=':'
+	set dummy $vinfo 0 0 0
+	IFS="$save_ifs"
+
+	if test -n "$8"; then
+	  $echo "$modename: too many parameters to \`-version-info'" 1>&2
+	  $echo "$help" 1>&2
+	  exit $EXIT_FAILURE
+	fi
+
+	# convert absolute version numbers to libtool ages
+	# this retains compatibility with .la files and attempts
+	# to make the code below a bit more comprehensible
+
+	case $vinfo_number in
+	yes)
+	  number_major="$2"
+	  number_minor="$3"
+	  number_revision="$4"
+	  #
+	  # There are really only two kinds -- those that
+	  # use the current revision as the major version
+	  # and those that subtract age and use age as
+	  # a minor version.  But, then there is irix
+	  # which has an extra 1 added just for fun
+	  #
+	  case $version_type in
+	  darwin|linux|osf|windows)
+	    current=`expr $number_major + $number_minor`
+	    age="$number_minor"
+	    revision="$number_revision"
+	    ;;
+	  freebsd-aout|freebsd-elf|sunos)
+	    current="$number_major"
+	    revision="$number_minor"
+	    age="0"
+	    ;;
+	  irix|nonstopux)
+	    current=`expr $number_major + $number_minor - 1`
+	    age="$number_minor"
+	    revision="$number_minor"
+	    ;;
+	  esac
+	  ;;
+	no)
+	  current="$2"
+	  revision="$3"
+	  age="$4"
+	  ;;
+	esac
+
+	# Check that each of the things are valid numbers.
+	case $current in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
+	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+	  exit $EXIT_FAILURE
+	  ;;
+	esac
+
+	case $revision in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
+	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+	  exit $EXIT_FAILURE
+	  ;;
+	esac
+
+	case $age in
+	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+	*)
+	  $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
+	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+	  exit $EXIT_FAILURE
+	  ;;
+	esac
+
+	if test "$age" -gt "$current"; then
+	  $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+	  exit $EXIT_FAILURE
+	fi
+
+	# Calculate the version variables.
+	major=
+	versuffix=
+	verstring=
+	case $version_type in
+	none) ;;
+
+	darwin)
+	  # Like Linux, but with the current version available in
+	  # verstring for coding it into the library header
+	  major=.`expr $current - $age`
+	  versuffix="$major.$age.$revision"
+	  # Darwin ld doesn't like 0 for these options...
+	  minor_current=`expr $current + 1`
+	  verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+	  ;;
+
+	freebsd-aout)
+	  major=".$current"
+	  versuffix=".$current.$revision";
+	  ;;
+
+	freebsd-elf)
+	  major=".$current"
+	  versuffix=".$current";
+	  ;;
+
+	irix | nonstopux)
+	  major=`expr $current - $age + 1`
+
+	  case $version_type in
+	    nonstopux) verstring_prefix=nonstopux ;;
+	    *)         verstring_prefix=sgi ;;
+	  esac
+	  verstring="$verstring_prefix$major.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$revision
+	  while test "$loop" -ne 0; do
+	    iface=`expr $revision - $loop`
+	    loop=`expr $loop - 1`
+	    verstring="$verstring_prefix$major.$iface:$verstring"
+	  done
+
+	  # Before this point, $major must not contain `.'.
+	  major=.$major
+	  versuffix="$major.$revision"
+	  ;;
+
+	linux)
+	  major=.`expr $current - $age`
+	  versuffix="$major.$age.$revision"
+	  ;;
+
+	osf)
+	  major=.`expr $current - $age`
+	  versuffix=".$current.$age.$revision"
+	  verstring="$current.$age.$revision"
+
+	  # Add in all the interfaces that we are compatible with.
+	  loop=$age
+	  while test "$loop" -ne 0; do
+	    iface=`expr $current - $loop`
+	    loop=`expr $loop - 1`
+	    verstring="$verstring:${iface}.0"
+	  done
+
+	  # Make executables depend on our current version.
+	  verstring="$verstring:${current}.0"
+	  ;;
+
+	sunos)
+	  major=".$current"
+	  versuffix=".$current.$revision"
+	  ;;
+
+	windows)
+	  # Use '-' rather than '.', since we only want one
+	  # extension on DOS 8.3 filesystems.
+	  major=`expr $current - $age`
+	  versuffix="-$major"
+	  ;;
+
+	*)
+	  $echo "$modename: unknown library version type \`$version_type'" 1>&2
+	  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
+	  exit $EXIT_FAILURE
+	  ;;
+	esac
+
+	# Clear the version info if we defaulted, and they specified a release.
+	if test -z "$vinfo" && test -n "$release"; then
+	  major=
+	  case $version_type in
+	  darwin)
+	    # we can't check for "0.0" in archive_cmds due to quoting
+	    # problems, so we reset it completely
+	    verstring=
+	    ;;
+	  *)
+	    verstring="0.0"
+	    ;;
+	  esac
+	  if test "$need_version" = no; then
+	    versuffix=
+	  else
+	    versuffix=".0.0"
+	  fi
+	fi
+
+	# Remove version info from name if versioning should be avoided
+	if test "$avoid_version" = yes && test "$need_version" = no; then
+	  major=
+	  versuffix=
+	  verstring=""
+	fi
+
+	# Check to see if the archive will have undefined symbols.
+	if test "$allow_undefined" = yes; then
+	  if test "$allow_undefined_flag" = unsupported; then
+	    $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+	    build_libtool_libs=no
+	    build_old_libs=yes
+	  fi
+	else
+	  # Don't allow undefined symbols.
+	  allow_undefined_flag="$no_undefined_flag"
+	fi
+      fi
+
+      if test "$mode" != relink; then
+	# Remove our outputs, but don't remove object files since they
+	# may have been created when compiling PIC objects.
+	removelist=
+	tempremovelist=`$echo "$output_objdir/*"`
+	for p in $tempremovelist; do
+	  case $p in
+	    *.$objext)
+	       ;;
+	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+	       if test "X$precious_files_regex" != "X"; then
+	         if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+	         then
+		   continue
+		 fi
+	       fi
+	       removelist="$removelist $p"
+	       ;;
+	    *) ;;
+	  esac
+	done
+	if test -n "$removelist"; then
+	  $show "${rm}r $removelist"
+	  $run ${rm}r $removelist
+	fi
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+	oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+	# Transform .lo files to .o files.
+	oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      for path in $notinst_path; do
+	lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
+	deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
+	dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
+      done
+
+      if test -n "$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	temp_xrpath=
+	for libdir in $xrpath; do
+	  temp_xrpath="$temp_xrpath -R$libdir"
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+	if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+	  dependency_libs="$temp_xrpath $dependency_libs"
+	fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+	case " $dlprefiles $dlfiles " in
+	*" $lib "*) ;;
+	*) dlfiles="$dlfiles $lib" ;;
+	esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+	case "$dlprefiles " in
+	*" $lib "*) ;;
+	*) dlprefiles="$dlprefiles $lib" ;;
+	esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+	if test -n "$rpath"; then
+	  case $host in
+	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+	    # these systems don't actually have a c library (as such)!
+	    ;;
+	  *-*-rhapsody* | *-*-darwin1.[012])
+	    # Rhapsody C library is in the System framework
+	    deplibs="$deplibs -framework System"
+	    ;;
+	  *-*-netbsd*)
+	    # Don't link with libc until the a.out ld.so is fixed.
+	    ;;
+	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+	    # Do not include libc due to us having libc/libc_r.
+	    ;;
+	  *-*-sco3.2v5* | *-*-sco5v6*)
+	    # Causes problems with __ctype
+	    ;;
+	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+	    # Compiler inserts libc in the correct place for threads to work
+	    ;;
+ 	  *)
+	    # Add libc to deplibs on all other systems if necessary.
+	    if test "$build_libtool_need_lc" = "yes"; then
+	      deplibs="$deplibs -lc"
+	    fi
+	    ;;
+	  esac
+	fi
+
+	# Transform deplibs into only deplibs that can be linked in shared.
+	name_save=$name
+	libname_save=$libname
+	release_save=$release
+	versuffix_save=$versuffix
+	major_save=$major
+	# I'm not sure if I'm treating the release correctly.  I think
+	# release should show up in the -l (ie -lgmp5) so we don't want to
+	# add it in twice.  Is that correct?
+	release=""
+	versuffix=""
+	major=""
+	newdeplibs=
+	droppeddeps=no
+	case $deplibs_check_method in
+	pass_all)
+	  # Don't check for shared/static.  Everything works.
+	  # This might be a little naive.  We might want to check
+	  # whether the library exists or not.  But this is on
+	  # osf3 & osf4 and I'm not really sure... Just
+	  # implementing what was already the behavior.
+	  newdeplibs=$deplibs
+	  ;;
+	test_compile)
+	  # This code stresses the "libraries are programs" paradigm to its
+	  # limits. Maybe even breaks it.  We compile a program, linking it
+	  # against the deplibs as a proxy for the library.  Then we can check
+	  # whether they linked in statically or dynamically with ldd.
+	  $rm conftest.c
+	  cat > conftest.c <<EOF
+	  int main() { return 0; }
+EOF
+	  $rm conftest
+	  $LTCC $LTCFLAGS -o conftest conftest.c $deplibs
+	  if test "$?" -eq 0 ; then
+	    ldd_output=`ldd conftest`
+	    for i in $deplibs; do
+	      name=`expr $i : '-l\(.*\)'`
+	      # If $name is empty we are operating on a -L argument.
+              if test "$name" != "" && test "$name" -ne "0"; then
+		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		  case " $predeps $postdeps " in
+		  *" $i "*)
+		    newdeplibs="$newdeplibs $i"
+		    i=""
+		    ;;
+		  esac
+	        fi
+		if test -n "$i" ; then
+		  libname=`eval \\$echo \"$libname_spec\"`
+		  deplib_matches=`eval \\$echo \"$library_names_spec\"`
+		  set dummy $deplib_matches
+		  deplib_match=$2
+		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		    newdeplibs="$newdeplibs $i"
+		  else
+		    droppeddeps=yes
+		    $echo
+		    $echo "*** Warning: dynamic linker does not accept needed library $i."
+		    $echo "*** I have the capability to make that library automatically link in when"
+		    $echo "*** you link to this library.  But I can only do this if you have a"
+		    $echo "*** shared version of the library, which I believe you do not have"
+		    $echo "*** because a test_compile did reveal that the linker did not use it for"
+		    $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+		  fi
+		fi
+	      else
+		newdeplibs="$newdeplibs $i"
+	      fi
+	    done
+	  else
+	    # Error occurred in the first compile.  Let's try to salvage
+	    # the situation: Compile a separate program for each library.
+	    for i in $deplibs; do
+	      name=`expr $i : '-l\(.*\)'`
+	      # If $name is empty we are operating on a -L argument.
+              if test "$name" != "" && test "$name" != "0"; then
+		$rm conftest
+		$LTCC $LTCFLAGS -o conftest conftest.c $i
+		# Did it work?
+		if test "$?" -eq 0 ; then
+		  ldd_output=`ldd conftest`
+		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		    case " $predeps $postdeps " in
+		    *" $i "*)
+		      newdeplibs="$newdeplibs $i"
+		      i=""
+		      ;;
+		    esac
+		  fi
+		  if test -n "$i" ; then
+		    libname=`eval \\$echo \"$libname_spec\"`
+		    deplib_matches=`eval \\$echo \"$library_names_spec\"`
+		    set dummy $deplib_matches
+		    deplib_match=$2
+		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+		      newdeplibs="$newdeplibs $i"
+		    else
+		      droppeddeps=yes
+		      $echo
+		      $echo "*** Warning: dynamic linker does not accept needed library $i."
+		      $echo "*** I have the capability to make that library automatically link in when"
+		      $echo "*** you link to this library.  But I can only do this if you have a"
+		      $echo "*** shared version of the library, which you do not appear to have"
+		      $echo "*** because a test_compile did reveal that the linker did not use this one"
+		      $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+		    fi
+		  fi
+		else
+		  droppeddeps=yes
+		  $echo
+		  $echo "*** Warning!  Library $i is needed by this library but I was not able to"
+		  $echo "***  make it link in!  You will probably need to install it or some"
+		  $echo "*** library that it depends on before this library will be fully"
+		  $echo "*** functional.  Installing it before continuing would be even better."
+		fi
+	      else
+		newdeplibs="$newdeplibs $i"
+	      fi
+	    done
+	  fi
+	  ;;
+	file_magic*)
+	  set dummy $deplibs_check_method
+	  file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    name=`expr $a_deplib : '-l\(.*\)'`
+	    # If $name is empty we are operating on a -L argument.
+            if test "$name" != "" && test  "$name" != "0"; then
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval \\$echo \"$libname_spec\"`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		      # Follow soft links.
+		      if ls -lLd "$potent_lib" 2>/dev/null \
+			 | grep " -> " >/dev/null; then
+			continue
+		      fi
+		      # The statement above tries to avoid entering an
+		      # endless loop below, in case of cyclic links.
+		      # We might still enter an endless loop, since a link
+		      # loop can be closed while we follow links,
+		      # but so what?
+		      potlib="$potent_lib"
+		      while test -h "$potlib" 2>/dev/null; do
+			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+			case $potliblink in
+			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+			*) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+			esac
+		      done
+		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+			 | ${SED} 10q \
+			 | $EGREP "$file_magic_regex" > /dev/null; then
+			newdeplibs="$newdeplibs $a_deplib"
+			a_deplib=""
+			break 2
+		      fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		$echo
+		$echo "*** Warning: linker path does not have real file for library $a_deplib."
+		$echo "*** I have the capability to make that library automatically link in when"
+		$echo "*** you link to this library.  But I can only do this if you have a"
+		$echo "*** shared version of the library, which you do not appear to have"
+		$echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $echo "*** with $libname but no candidates were found. (...for file magic test)"
+		else
+		  $echo "*** with $libname and none of the candidates passed a file format test"
+		  $echo "*** using a file magic. Last file checked: $potlib"
+		fi
+	      fi
+	    else
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	    fi
+	  done # Gone through all deplibs.
+	  ;;
+	match_pattern*)
+	  set dummy $deplibs_check_method
+	  match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+	  for a_deplib in $deplibs; do
+	    name=`expr $a_deplib : '-l\(.*\)'`
+	    # If $name is empty we are operating on a -L argument.
+	    if test -n "$name" && test "$name" != "0"; then
+	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+		case " $predeps $postdeps " in
+		*" $a_deplib "*)
+		  newdeplibs="$newdeplibs $a_deplib"
+		  a_deplib=""
+		  ;;
+		esac
+	      fi
+	      if test -n "$a_deplib" ; then
+		libname=`eval \\$echo \"$libname_spec\"`
+		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+		  for potent_lib in $potential_libs; do
+		    potlib="$potent_lib" # see symlink-check above in file_magic test
+		    if eval $echo \"$potent_lib\" 2>/dev/null \
+		        | ${SED} 10q \
+		        | $EGREP "$match_pattern_regex" > /dev/null; then
+		      newdeplibs="$newdeplibs $a_deplib"
+		      a_deplib=""
+		      break 2
+		    fi
+		  done
+		done
+	      fi
+	      if test -n "$a_deplib" ; then
+		droppeddeps=yes
+		$echo
+		$echo "*** Warning: linker path does not have real file for library $a_deplib."
+		$echo "*** I have the capability to make that library automatically link in when"
+		$echo "*** you link to this library.  But I can only do this if you have a"
+		$echo "*** shared version of the library, which you do not appear to have"
+		$echo "*** because I did check the linker path looking for a file starting"
+		if test -z "$potlib" ; then
+		  $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+		else
+		  $echo "*** with $libname and none of the candidates passed a file format test"
+		  $echo "*** using a regex pattern. Last file checked: $potlib"
+		fi
+	      fi
+	    else
+	      # Add a -L argument.
+	      newdeplibs="$newdeplibs $a_deplib"
+	    fi
+	  done # Gone through all deplibs.
+	  ;;
+	none | unknown | *)
+	  newdeplibs=""
+	  tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+	    -e 's/ -[LR][^ ]*//g'`
+	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+	    for i in $predeps $postdeps ; do
+	      # can't use Xsed below, because $i might contain '/'
+	      tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+	    done
+	  fi
+	  if $echo "X $tmp_deplibs" | $Xsed -e 's/[ 	]//g' \
+	    | grep . >/dev/null; then
+	    $echo
+	    if test "X$deplibs_check_method" = "Xnone"; then
+	      $echo "*** Warning: inter-library dependencies are not supported in this platform."
+	    else
+	      $echo "*** Warning: inter-library dependencies are not known to be supported."
+	    fi
+	    $echo "*** All declared inter-library dependencies are being dropped."
+	    droppeddeps=yes
+	  fi
+	  ;;
+	esac
+	versuffix=$versuffix_save
+	major=$major_save
+	release=$release_save
+	libname=$libname_save
+	name=$name_save
+
+	case $host in
+	*-*-rhapsody* | *-*-darwin1.[012])
+	  # On Rhapsody replace the C library is the System framework
+	  newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+	  ;;
+	esac
+
+	if test "$droppeddeps" = yes; then
+	  if test "$module" = yes; then
+	    $echo
+	    $echo "*** Warning: libtool could not satisfy all declared inter-library"
+	    $echo "*** dependencies of module $libname.  Therefore, libtool will create"
+	    $echo "*** a static module, that should work as long as the dlopening"
+	    $echo "*** application is linked with the -dlopen flag."
+	    if test -z "$global_symbol_pipe"; then
+	      $echo
+	      $echo "*** However, this would only work if libtool was able to extract symbol"
+	      $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+	      $echo "*** not find such a program.  So, this module is probably useless."
+	      $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+	    fi
+	    if test "$build_old_libs" = no; then
+	      oldlibs="$output_objdir/$libname.$libext"
+	      build_libtool_libs=module
+	      build_old_libs=yes
+	    else
+	      build_libtool_libs=no
+	    fi
+	  else
+	    $echo "*** The inter-library dependencies that have been dropped here will be"
+	    $echo "*** automatically added whenever a program is linked with this library"
+	    $echo "*** or is declared to -dlopen it."
+
+	    if test "$allow_undefined" = no; then
+	      $echo
+	      $echo "*** Since this library must not contain undefined symbols,"
+	      $echo "*** because either the platform does not support them or"
+	      $echo "*** it was explicitly requested with -no-undefined,"
+	      $echo "*** libtool will only create a static version of it."
+	      if test "$build_old_libs" = no; then
+		oldlibs="$output_objdir/$libname.$libext"
+		build_libtool_libs=module
+		build_old_libs=yes
+	      else
+		build_libtool_libs=no
+	      fi
+	    fi
+	  fi
+	fi
+	# Done checking deplibs!
+	deplibs=$newdeplibs
+      fi
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs="$new_libs -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs="$new_libs $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs="$new_libs $deplib" ;;
+	esac
+      done
+      deplibs="$new_libs"
+
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+	if test "$hardcode_into_libs" = yes; then
+	  # Hardcode the library paths
+	  hardcode_libdirs=
+	  dep_rpath=
+	  rpath="$finalize_rpath"
+	  test "$mode" != relink && rpath="$compile_rpath$rpath"
+	  for libdir in $rpath; do
+	    if test -n "$hardcode_libdir_flag_spec"; then
+	      if test -n "$hardcode_libdir_separator"; then
+		if test -z "$hardcode_libdirs"; then
+		  hardcode_libdirs="$libdir"
+		else
+		  # Just accumulate the unique libdirs.
+		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		    ;;
+		  *)
+		    hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		    ;;
+		  esac
+		fi
+	      else
+		eval flag=\"$hardcode_libdir_flag_spec\"
+		dep_rpath="$dep_rpath $flag"
+	      fi
+	    elif test -n "$runpath_var"; then
+	      case "$perm_rpath " in
+	      *" $libdir "*) ;;
+	      *) perm_rpath="$perm_rpath $libdir" ;;
+	      esac
+	    fi
+	  done
+	  # Substitute the hardcoded libdirs into the rpath.
+	  if test -n "$hardcode_libdir_separator" &&
+	     test -n "$hardcode_libdirs"; then
+	    libdir="$hardcode_libdirs"
+	    if test -n "$hardcode_libdir_flag_spec_ld"; then
+	      eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+	    else
+	      eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+	    fi
+	  fi
+	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
+	    # We should set the runpath_var.
+	    rpath=
+	    for dir in $perm_rpath; do
+	      rpath="$rpath$dir:"
+	    done
+	    eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+	  fi
+	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+	fi
+
+	shlibpath="$finalize_shlibpath"
+	test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+	if test -n "$shlibpath"; then
+	  eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+	fi
+
+	# Get the real and link names of the library.
+	eval shared_ext=\"$shrext_cmds\"
+	eval library_names=\"$library_names_spec\"
+	set dummy $library_names
+	realname="$2"
+	shift; shift
+
+	if test -n "$soname_spec"; then
+	  eval soname=\"$soname_spec\"
+	else
+	  soname="$realname"
+	fi
+	if test -z "$dlname"; then
+	  dlname=$soname
+	fi
+
+	lib="$output_objdir/$realname"
+	linknames=
+	for link
+	do
+	  linknames="$linknames $link"
+	done
+
+	# Use standard objects if they are pic
+	test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+	# Prepare the list of exported symbols
+	if test -z "$export_symbols"; then
+	  if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+	    $show "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $run $rm $export_symbols
+	    cmds=$export_symbols_cmds
+	    save_ifs="$IFS"; IFS='~'
+	    for cmd in $cmds; do
+	      IFS="$save_ifs"
+	      eval cmd=\"$cmd\"
+	      if len=`expr "X$cmd" : ".*"` &&
+	       test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	        $show "$cmd"
+	        $run eval "$cmd" || exit $?
+	        skipped_export=false
+	      else
+	        # The command line is too long to execute in one step.
+	        $show "using reloadable object file for export list..."
+	        skipped_export=:
+		# Break out early, otherwise skipped_export may be
+		# set to false by a later but shorter cmd.
+		break
+	      fi
+	    done
+	    IFS="$save_ifs"
+	    if test -n "$export_symbols_regex"; then
+	      $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+	      $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+	      $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+	      $run eval '$mv "${export_symbols}T" "$export_symbols"'
+	    fi
+	  fi
+	fi
+
+	if test -n "$export_symbols" && test -n "$include_expsyms"; then
+	  $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+	fi
+
+	tmp_deplibs=
+	for test_deplib in $deplibs; do
+		case " $convenience " in
+		*" $test_deplib "*) ;;
+		*)
+			tmp_deplibs="$tmp_deplibs $test_deplib"
+			;;
+		esac
+	done
+	deplibs="$tmp_deplibs"
+
+	if test -n "$convenience"; then
+	  if test -n "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	  else
+	    gentop="$output_objdir/${outputname}x"
+	    generated="$generated $gentop"
+
+	    func_extract_archives $gentop $convenience
+	    libobjs="$libobjs $func_extract_archives_result"
+	  fi
+	fi
+	
+	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+	  eval flag=\"$thread_safe_flag_spec\"
+	  linker_flags="$linker_flags $flag"
+	fi
+
+	# Make a backup of the uninstalled library when relinking
+	if test "$mode" = relink; then
+	  $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+	fi
+
+	# Do each of the archive commands.
+	if test "$module" = yes && test -n "$module_cmds" ; then
+	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	    eval test_cmds=\"$module_expsym_cmds\"
+	    cmds=$module_expsym_cmds
+	  else
+	    eval test_cmds=\"$module_cmds\"
+	    cmds=$module_cmds
+	  fi
+	else
+	if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	  eval test_cmds=\"$archive_expsym_cmds\"
+	  cmds=$archive_expsym_cmds
+	else
+	  eval test_cmds=\"$archive_cmds\"
+	  cmds=$archive_cmds
+	  fi
+	fi
+
+	if test "X$skipped_export" != "X:" &&
+	   len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+	   test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  :
+	else
+	  # The command line is too long to link in one step, link piecewise.
+	  $echo "creating reloadable object files..."
+
+	  # Save the value of $output and $libobjs because we want to
+	  # use them later.  If we have whole_archive_flag_spec, we
+	  # want to use save_libobjs as it was before
+	  # whole_archive_flag_spec was expanded, because we can't
+	  # assume the linker understands whole_archive_flag_spec.
+	  # This may have to be revisited, in case too many
+	  # convenience libraries get linked in and end up exceeding
+	  # the spec.
+	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+	    save_libobjs=$libobjs
+	  fi
+	  save_output=$output
+	  output_la=`$echo "X$output" | $Xsed -e "$basename"`
+
+	  # Clear the reloadable object creation command queue and
+	  # initialize k to one.
+	  test_cmds=
+	  concat_cmds=
+	  objlist=
+	  delfiles=
+	  last_robj=
+	  k=1
+	  output=$output_objdir/$output_la-${k}.$objext
+	  # Loop over the list of objects to be linked.
+	  for obj in $save_libobjs
+	  do
+	    eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+	    if test "X$objlist" = X ||
+	       { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+		 test "$len" -le "$max_cmd_len"; }; then
+	      objlist="$objlist $obj"
+	    else
+	      # The command $test_cmds is almost too long, add a
+	      # command to the queue.
+	      if test "$k" -eq 1 ; then
+		# The first file doesn't have a previous command to add.
+		eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+	      else
+		# All subsequent reloadable object files will link in
+		# the last one created.
+		eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+	      fi
+	      last_robj=$output_objdir/$output_la-${k}.$objext
+	      k=`expr $k + 1`
+	      output=$output_objdir/$output_la-${k}.$objext
+	      objlist=$obj
+	      len=1
+	    fi
+	  done
+	  # Handle the remaining objects by creating one last
+	  # reloadable object file.  All subsequent reloadable object
+	  # files will link in the last one created.
+	  test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	  eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+	  if ${skipped_export-false}; then
+	    $show "generating symbol list for \`$libname.la'"
+	    export_symbols="$output_objdir/$libname.exp"
+	    $run $rm $export_symbols
+	    libobjs=$output
+	    # Append the command to create the export file.
+	    eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+          fi
+
+	  # Set up a command to remove the reloadable object files
+	  # after they are used.
+	  i=0
+	  while test "$i" -lt "$k"
+	  do
+	    i=`expr $i + 1`
+	    delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
+	  done
+
+	  $echo "creating a temporary reloadable object file: $output"
+
+	  # Loop through the commands generated above and execute them.
+	  save_ifs="$IFS"; IFS='~'
+	  for cmd in $concat_cmds; do
+	    IFS="$save_ifs"
+	    $show "$cmd"
+	    $run eval "$cmd" || exit $?
+	  done
+	  IFS="$save_ifs"
+
+	  libobjs=$output
+	  # Restore the value of output.
+	  output=$save_output
+
+	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+	  fi
+	  # Expand the library linking commands again to reset the
+	  # value of $libobjs for piecewise linking.
+
+	  # Do each of the archive commands.
+	  if test "$module" = yes && test -n "$module_cmds" ; then
+	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+	      cmds=$module_expsym_cmds
+	    else
+	      cmds=$module_cmds
+	    fi
+	  else
+	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+	    cmds=$archive_expsym_cmds
+	  else
+	    cmds=$archive_cmds
+	    fi
+	  fi
+
+	  # Append the command to remove the reloadable object files
+	  # to the just-reset $cmds.
+	  eval cmds=\"\$cmds~\$rm $delfiles\"
+	fi
+	save_ifs="$IFS"; IFS='~'
+	for cmd in $cmds; do
+	  IFS="$save_ifs"
+	  eval cmd=\"$cmd\"
+	  $show "$cmd"
+	  $run eval "$cmd" || {
+	    lt_exit=$?
+
+	    # Restore the uninstalled library and exit
+	    if test "$mode" = relink; then
+	      $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+	    fi
+
+	    exit $lt_exit
+	  }
+	done
+	IFS="$save_ifs"
+
+	# Restore the uninstalled library and exit
+	if test "$mode" = relink; then
+	  $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+
+	  if test -n "$convenience"; then
+	    if test -z "$whole_archive_flag_spec"; then
+	      $show "${rm}r $gentop"
+	      $run ${rm}r "$gentop"
+	    fi
+	  fi
+
+	  exit $EXIT_SUCCESS
+	fi
+
+	# Create links to the real library.
+	for linkname in $linknames; do
+	  if test "$realname" != "$linkname"; then
+	    $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+	    $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+	  fi
+	done
+
+	# If -module or -export-dynamic was specified, set the dlname.
+	if test "$module" = yes || test "$export_dynamic" = yes; then
+	  # On all known operating systems, these are identical.
+	  dlname="$soname"
+	fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$deplibs"; then
+	$echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+      fi
+
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	$echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$rpath"; then
+	$echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$xrpath"; then
+	$echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$vinfo"; then
+	$echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+      fi
+
+      if test -n "$release"; then
+	$echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+      fi
+
+      case $output in
+      *.lo)
+	if test -n "$objs$old_deplibs"; then
+	  $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+	  exit $EXIT_FAILURE
+	fi
+	libobj="$output"
+	obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+	;;
+      *)
+	libobj=
+	obj="$output"
+	;;
+      esac
+
+      # Delete the old objects.
+      $run $rm $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec
+      wl=
+
+      if test -n "$convenience"; then
+	if test -n "$whole_archive_flag_spec"; then
+	  eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+	else
+	  gentop="$output_objdir/${obj}x"
+	  generated="$generated $gentop"
+
+	  func_extract_archives $gentop $convenience
+	  reload_conv_objs="$reload_objs $func_extract_archives_result"
+	fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      cmds=$reload_cmds
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+	IFS="$save_ifs"
+	eval cmd=\"$cmd\"
+	$show "$cmd"
+	$run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+	if test -n "$gentop"; then
+	  $show "${rm}r $gentop"
+	  $run ${rm}r $gentop
+	fi
+
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+	if test -n "$gentop"; then
+	  $show "${rm}r $gentop"
+	  $run ${rm}r $gentop
+	fi
+
+	# Create an invalid libtool object if no PIC, so that we don't
+	# accidentally link it into a program.
+	# $show "echo timestamp > $libobj"
+	# $run eval "echo timestamp > $libobj" || exit $?
+	exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+	# Only do commands if we really have different PIC objects.
+	reload_objs="$libobjs $reload_conv_objs"
+	output="$libobj"
+	cmds=$reload_cmds
+	save_ifs="$IFS"; IFS='~'
+	for cmd in $cmds; do
+	  IFS="$save_ifs"
+	  eval cmd=\"$cmd\"
+	  $show "$cmd"
+	  $run eval "$cmd" || exit $?
+	done
+	IFS="$save_ifs"
+      fi
+
+      if test -n "$gentop"; then
+	$show "${rm}r $gentop"
+	$run ${rm}r $gentop
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+	*cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+      esac
+      if test -n "$vinfo"; then
+	$echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+      fi
+
+      if test -n "$release"; then
+	$echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+      fi
+
+      if test "$preload" = yes; then
+	if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+	   test "$dlopen_self_static" = unknown; then
+	  $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+	fi
+      fi
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+	# On Rhapsody replace the C library is the System framework
+	compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+	finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+	;;
+      esac
+
+      case $host in
+      *darwin*)
+        # Don't allow lazy linking, it breaks C++ global constructors
+        if test "$tagname" = CXX ; then
+        compile_command="$compile_command ${wl}-bind_at_load"
+        finalize_command="$finalize_command ${wl}-bind_at_load"
+        fi
+        ;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+	case " $new_libs " in
+	*" -L$path/$objdir "*) ;;
+	*)
+	  case " $compile_deplibs " in
+	  *" -L$path/$objdir "*)
+	    new_libs="$new_libs -L$path/$objdir" ;;
+	  esac
+	  ;;
+	esac
+      done
+      for deplib in $compile_deplibs; do
+	case $deplib in
+	-L*)
+	  case " $new_libs " in
+	  *" $deplib "*) ;;
+	  *) new_libs="$new_libs $deplib" ;;
+	  esac
+	  ;;
+	*) new_libs="$new_libs $deplib" ;;
+	esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      compile_command="$compile_command $compile_deplibs"
+      finalize_command="$finalize_command $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+	# If the user specified any rpath flags, then add them.
+	for libdir in $rpath $xrpath; do
+	  # This is the magic to use -rpath.
+	  case "$finalize_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_rpath="$finalize_rpath $libdir" ;;
+	  esac
+	done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) perm_rpath="$perm_rpath $libdir" ;;
+	  esac
+	fi
+	case $host in
+	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+	  testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
+	  case :$dllsearchpath: in
+	  *":$libdir:"*) ;;
+	  *) dllsearchpath="$dllsearchpath:$libdir";;
+	  esac
+	  case :$dllsearchpath: in
+	  *":$testbindir:"*) ;;
+	  *) dllsearchpath="$dllsearchpath:$testbindir";;
+	  esac
+	  ;;
+	esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+	if test -n "$hardcode_libdir_flag_spec"; then
+	  if test -n "$hardcode_libdir_separator"; then
+	    if test -z "$hardcode_libdirs"; then
+	      hardcode_libdirs="$libdir"
+	    else
+	      # Just accumulate the unique libdirs.
+	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+		;;
+	      *)
+		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+		;;
+	      esac
+	    fi
+	  else
+	    eval flag=\"$hardcode_libdir_flag_spec\"
+	    rpath="$rpath $flag"
+	  fi
+	elif test -n "$runpath_var"; then
+	  case "$finalize_perm_rpath " in
+	  *" $libdir "*) ;;
+	  *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+	  esac
+	fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+	 test -n "$hardcode_libdirs"; then
+	libdir="$hardcode_libdirs"
+	eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+	# Transform all the library objects into standard objects.
+	compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+      fi
+
+      dlsyms=
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+	if test -n "$NM" && test -n "$global_symbol_pipe"; then
+	  dlsyms="${outputname}S.c"
+	else
+	  $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+	fi
+      fi
+
+      if test -n "$dlsyms"; then
+	case $dlsyms in
+	"") ;;
+	*.c)
+	  # Discover the nlist of each of the dlfiles.
+	  nlist="$output_objdir/${outputname}.nm"
+
+	  $show "$rm $nlist ${nlist}S ${nlist}T"
+	  $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+	  # Parse the name list into a source file.
+	  $show "creating $output_objdir/$dlsyms"
+
+	  test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+	  if test "$dlself" = yes; then
+	    $show "generating symbol list for \`$output'"
+
+	    test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+	    # Add our own program objects to the symbol list.
+	    progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+	    for arg in $progfiles; do
+	      $show "extracting global C symbols from \`$arg'"
+	      $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+	    done
+
+	    if test -n "$exclude_expsyms"; then
+	      $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+	      $run eval '$mv "$nlist"T "$nlist"'
+	    fi
+
+	    if test -n "$export_symbols_regex"; then
+	      $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+	      $run eval '$mv "$nlist"T "$nlist"'
+	    fi
+
+	    # Prepare the list of exported symbols
+	    if test -z "$export_symbols"; then
+	      export_symbols="$output_objdir/$outputname.exp"
+	      $run $rm $export_symbols
+	      $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+              case $host in
+              *cygwin* | *mingw* )
+	        $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+		$run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+                ;;
+              esac
+	    else
+	      $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+	      $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+	      $run eval 'mv "$nlist"T "$nlist"'
+              case $host in
+              *cygwin* | *mingw* )
+	        $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+		$run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+                ;;
+              esac
+	    fi
+	  fi
+
+	  for arg in $dlprefiles; do
+	    $show "extracting global C symbols from \`$arg'"
+	    name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+	    $run eval '$echo ": $name " >> "$nlist"'
+	    $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+	  done
+
+	  if test -z "$run"; then
+	    # Make sure we have at least an empty file.
+	    test -f "$nlist" || : > "$nlist"
+
+	    if test -n "$exclude_expsyms"; then
+	      $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+	      $mv "$nlist"T "$nlist"
+	    fi
+
+	    # Try sorting and uniquifying the output.
+	    if grep -v "^: " < "$nlist" |
+		if sort -k 3 </dev/null >/dev/null 2>&1; then
+		  sort -k 3
+		else
+		  sort +2
+		fi |
+		uniq > "$nlist"S; then
+	      :
+	    else
+	      grep -v "^: " < "$nlist" > "$nlist"S
+	    fi
+
+	    if test -f "$nlist"S; then
+	      eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+	    else
+	      $echo '/* NONE */' >> "$output_objdir/$dlsyms"
+	    fi
+
+	    $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+"
+
+	    case $host in
+	    *cygwin* | *mingw* )
+	  $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+   runtime relocations are performed -- see ld's documentation
+   on pseudo-relocs */
+struct {
+"
+	      ;;
+	    * )
+	  $echo >> "$output_objdir/$dlsyms" "\
+const struct {
+"
+	      ;;
+	    esac
+
+
+	  $echo >> "$output_objdir/$dlsyms" "\
+  const char *name;
+  lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+	    $echo >> "$output_objdir/$dlsyms" "\
+  {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+	  fi
+
+	  pic_flag_for_symtable=
+	  case $host in
+	  # compiling the symbol table file with pic_flag works around
+	  # a FreeBSD bug that causes programs to crash when -lm is
+	  # linked before any other PIC object.  But we must not use
+	  # pic_flag when linking with -static.  The problem exists in
+	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+	  *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+	    case "$compile_command " in
+	    *" -static "*) ;;
+	    *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
+	    esac;;
+	  *-*-hpux*)
+	    case "$compile_command " in
+	    *" -static "*) ;;
+	    *) pic_flag_for_symtable=" $pic_flag";;
+	    esac
+	  esac
+
+	  # Now compile the dynamic symbol file.
+	  $show "(cd $output_objdir && $LTCC  $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+	  $run eval '(cd $output_objdir && $LTCC  $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+	  # Clean up the generated files.
+	  $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+	  $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+	  # Transform the symbol file into the correct name.
+          case $host in
+          *cygwin* | *mingw* )
+            if test -f "$output_objdir/${outputname}.def" ; then
+              compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
+              finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
+            else
+              compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+              finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+             fi
+            ;;
+          * )
+            compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+            finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+            ;;
+          esac
+	  ;;
+	*)
+	  $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+	  exit $EXIT_FAILURE
+	  ;;
+	esac
+      else
+	# We keep going just in case the user didn't refer to
+	# lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+	# really was required.
+
+	# Nullify the symbol file.
+	compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+	finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+      fi
+
+      if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+	# Replace the output file specification.
+	compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+	link_command="$compile_command$compile_rpath"
+
+	# We have no uninstalled library dependencies, so finalize right now.
+	$show "$link_command"
+	$run eval "$link_command"
+	exit_status=$?
+
+	# Delete the generated files.
+	if test -n "$dlsyms"; then
+	  $show "$rm $output_objdir/${outputname}S.${objext}"
+	  $run $rm "$output_objdir/${outputname}S.${objext}"
+	fi
+
+	exit $exit_status
+      fi
+
+      if test -n "$shlibpath_var"; then
+	# We should set the shlibpath_var
+	rpath=
+	for dir in $temp_rpath; do
+	  case $dir in
+	  [\\/]* | [A-Za-z]:[\\/]*)
+	    # Absolute path.
+	    rpath="$rpath$dir:"
+	    ;;
+	  *)
+	    # Relative path: add a thisdir entry.
+	    rpath="$rpath\$thisdir/$dir:"
+	    ;;
+	  esac
+	done
+	temp_rpath="$rpath"
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+	if test -n "$perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+	if test -n "$finalize_perm_rpath"; then
+	  # We should set the runpath_var.
+	  rpath=
+	  for dir in $finalize_perm_rpath; do
+	    rpath="$rpath$dir:"
+	  done
+	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+	fi
+      fi
+
+      if test "$no_install" = yes; then
+	# We don't need to create a wrapper script.
+	link_command="$compile_var$compile_command$compile_rpath"
+	# Replace the output file specification.
+	link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+	# Delete the old output file.
+	$run $rm $output
+	# Link the executable and exit
+	$show "$link_command"
+	$run eval "$link_command" || exit $?
+	exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+	# Fast installation is not supported
+	link_command="$compile_var$compile_command$compile_rpath"
+	relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+	$echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+	$echo "$modename: \`$output' will be relinked during installation" 1>&2
+      else
+	if test "$fast_install" != no; then
+	  link_command="$finalize_var$compile_command$finalize_rpath"
+	  if test "$fast_install" = yes; then
+	    relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+	  else
+	    # fast_install is set to needless
+	    relink_command=
+	  fi
+	else
+	  link_command="$compile_var$compile_command$compile_rpath"
+	  relink_command="$finalize_var$finalize_command$finalize_rpath"
+	fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      $show "$link_command"
+      $run eval "$link_command" || exit $?
+
+      # Now create the wrapper script.
+      $show "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+	# Preserve any variables that may affect compiler behavior
+	for var in $variables_saved_for_relink; do
+	  if eval test -z \"\${$var+set}\"; then
+	    relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+	  elif eval var_value=\$$var; test -z "$var_value"; then
+	    relink_command="$var=; export $var; $relink_command"
+	  else
+	    var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+	    relink_command="$var=\"$var_value\"; export $var; $relink_command"
+	  fi
+	done
+	relink_command="(cd `pwd`; $relink_command)"
+	relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Quote $echo for shipping.
+      if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
+	case $progpath in
+	[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+	*) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+	esac
+	qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+      else
+	qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if our run command is non-null.
+      if test -z "$run"; then
+	# win32 will think the script is a binary if it has
+	# a .exe suffix, so we strip it off here.
+	case $output in
+	  *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
+	esac
+	# test for cygwin because mv fails w/o .exe extensions
+	case $host in
+	  *cygwin*)
+	    exeext=.exe
+	    outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
+	  *) exeext= ;;
+	esac
+	case $host in
+	  *cygwin* | *mingw* )
+            output_name=`basename $output`
+            output_path=`dirname $output`
+            cwrappersource="$output_path/$objdir/lt-$output_name.c"
+            cwrapper="$output_path/$output_name.exe"
+            $rm $cwrappersource $cwrapper
+            trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+	    cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "/bin/sh $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+	    cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+        (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+/* -DDEBUG is fairly common in CFLAGS.  */
+#undef DEBUG
+#if defined DEBUGWRAPPER
+# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
+#else
+# define DEBUG(format, ...)
+#endif
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+const char * base_name (const char *name);
+char * find_executable(const char *wrapper);
+int    check_executable(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  DEBUG("(main) argv[0]      : %s\n",argv[0]);
+  DEBUG("(main) program_name : %s\n",program_name);
+  newargz = XMALLOC(char *, argc+2);
+EOF
+
+            cat >> $cwrappersource <<EOF
+  newargz[0] = (char *) xstrdup("$SHELL");
+EOF
+
+            cat >> $cwrappersource <<"EOF"
+  newargz[1] = find_executable(argv[0]);
+  if (newargz[1] == NULL)
+    lt_fatal("Couldn't find %s", argv[0]);
+  DEBUG("(main) found exe at : %s\n",newargz[1]);
+  /* we know the script has the same name, without the .exe */
+  /* so make sure newargz[1] doesn't end in .exe */
+  strendzap(newargz[1],".exe");
+  for (i = 1; i < argc; i++)
+    newargz[i+1] = xstrdup(argv[i]);
+  newargz[argc+1] = NULL;
+
+  for (i=0; i<argc+1; i++)
+  {
+    DEBUG("(main) newargz[%d]   : %s\n",i,newargz[i]);
+    ;
+  }
+
+EOF
+
+            case $host_os in
+              mingw*)
+                cat >> $cwrappersource <<EOF
+  execv("$SHELL",(char const **)newargz);
+EOF
+              ;;
+              *)
+                cat >> $cwrappersource <<EOF
+  execv("$SHELL",newargz);
+EOF
+              ;;
+            esac
+
+            cat >> $cwrappersource <<"EOF"
+  return 127;
+}
+
+void *
+xmalloc (size_t num)
+{
+  void * p = (void *) malloc (num);
+  if (!p)
+    lt_fatal ("Memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char)name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable(const char * path)
+{
+  struct stat st;
+
+  DEBUG("(check_executable)  : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0) &&
+      (
+        /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
+#if defined (S_IXOTH)
+       ((st.st_mode & S_IXOTH) == S_IXOTH) ||
+#endif
+#if defined (S_IXGRP)
+       ((st.st_mode & S_IXGRP) == S_IXGRP) ||
+#endif
+       ((st.st_mode & S_IXUSR) == S_IXUSR))
+      )
+    return 1;
+  else
+    return 0;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise */
+char *
+find_executable (const char* wrapper)
+{
+  int has_slash = 0;
+  const char* p;
+  const char* p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char* concat_name;
+
+  DEBUG("(find_executable)  : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
+  {
+    concat_name = xstrdup (wrapper);
+    if (check_executable(concat_name))
+      return concat_name;
+    XFREE(concat_name);
+  }
+  else
+  {
+#endif
+    if (IS_DIR_SEPARATOR (wrapper[0]))
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable(concat_name))
+        return concat_name;
+      XFREE(concat_name);
+    }
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+    {
+      has_slash = 1;
+      break;
+    }
+  if (!has_slash)
+  {
+    /* no slashes; search PATH */
+    const char* path = getenv ("PATH");
+    if (path != NULL)
+    {
+      for (p = path; *p; p = p_next)
+      {
+        const char* q;
+        size_t p_len;
+        for (q = p; *q; q++)
+          if (IS_PATH_SEPARATOR(*q))
+            break;
+        p_len = q - p;
+        p_next = (*q == '\0' ? q : q + 1);
+        if (p_len == 0)
+        {
+          /* empty path: current directory */
+          if (getcwd (tmp, LT_PATHMAX) == NULL)
+            lt_fatal ("getcwd failed");
+          tmp_len = strlen(tmp);
+          concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+          memcpy (concat_name, tmp, tmp_len);
+          concat_name[tmp_len] = '/';
+          strcpy (concat_name + tmp_len + 1, wrapper);
+        }
+        else
+        {
+          concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
+          memcpy (concat_name, p, p_len);
+          concat_name[p_len] = '/';
+          strcpy (concat_name + p_len + 1, wrapper);
+        }
+        if (check_executable(concat_name))
+          return concat_name;
+        XFREE(concat_name);
+      }
+    }
+    /* not found in PATH; assume curdir */
+  }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal ("getcwd failed");
+  tmp_len = strlen(tmp);
+  concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable(concat_name))
+    return concat_name;
+  XFREE(concat_name);
+  return NULL;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert(str != NULL);
+  assert(pat != NULL);
+
+  len = strlen(str);
+  patlen = strlen(pat);
+
+  if (patlen <= len)
+  {
+    str += len - patlen;
+    if (strcmp(str, pat) == 0)
+      *str = '\0';
+  }
+  return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+          const char * message, va_list ap)
+{
+  fprintf (stderr, "%s: %s: ", program_name, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  va_end (ap);
+}
+EOF
+          # we should really use a build-platform specific compiler
+          # here, but OTOH, the wrappers (shell script and this C one)
+          # are only useful if you want to execute the "real" binary.
+          # Since the "real" binary is built for $host, then this
+          # wrapper might as well be built for $host, too.
+          $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+          ;;
+        esac
+        $rm $output
+        trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+
+	$echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variable:
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$echo are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    echo=\"$qecho\"
+    file=\"\$0\"
+    # Make sure echo works.
+    if test \"X\$1\" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+      # Yippee, \$echo works!
+      :
+    else
+      # Restart under the correct shell, and then maybe \$echo will work.
+      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+    fi
+  fi\
+"
+	$echo >> $output "\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+  done
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+	if test "$fast_install" = yes; then
+	  $echo >> $output "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" || \\
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $mkdir \"\$progdir\"
+    else
+      $rm \"\$progdir/\$file\"
+    fi"
+
+	  $echo >> $output "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+	$echo \"\$relink_command_output\" >&2
+	$rm \"\$progdir/\$file\"
+	exit $EXIT_FAILURE
+      fi
+    fi
+
+    $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $rm \"\$progdir/\$program\";
+      $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $rm \"\$progdir/\$file\"
+  fi"
+	else
+	  $echo >> $output "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+	fi
+
+	$echo >> $output "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+	# Export our shlibpath_var if we have one.
+	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+	  $echo >> $output "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+	fi
+
+	# fixup the dll searchpath if we need to.
+	if test -n "$dllsearchpath"; then
+	  $echo >> $output "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+	fi
+
+	$echo >> $output "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+	case $host in
+	# Backslashes separate directories on plain windows
+	*-*-mingw | *-*-os2*)
+	  $echo >> $output "\
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+	  ;;
+
+	*)
+	  $echo >> $output "\
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+	  ;;
+	esac
+	$echo >> $output "\
+      \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+      exit $EXIT_FAILURE
+    fi
+  else
+    # The program doesn't exist.
+    \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$echo \"This script is just a wrapper for \$program.\" 1>&2
+    $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit $EXIT_FAILURE
+  fi
+fi\
+"
+	chmod +x $output
+      fi
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+	oldobjs="$libobjs_save"
+	addlibs="$convenience"
+	build_libtool_libs=no
+      else
+	if test "$build_libtool_libs" = module; then
+	  oldobjs="$libobjs_save"
+	  build_libtool_libs=no
+	else
+	  oldobjs="$old_deplibs $non_pic_objects"
+	fi
+	addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+	gentop="$output_objdir/${outputname}x"
+	generated="$generated $gentop"
+
+	func_extract_archives $gentop $addlibs
+	oldobjs="$oldobjs $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+       cmds=$old_archive_from_new_cmds
+      else
+	# POSIX demands no paths to be encoded in archives.  We have
+	# to avoid creating archives with duplicate basenames if we
+	# might have to extract them afterwards, e.g., when creating a
+	# static archive out of a convenience library, or when linking
+	# the entirety of a libtool archive into another (currently
+	# not supported by libtool).
+	if (for obj in $oldobjs
+	    do
+	      $echo "X$obj" | $Xsed -e 's%^.*/%%'
+	    done | sort | sort -uc >/dev/null 2>&1); then
+	  :
+	else
+	  $echo "copying selected object files to avoid basename conflicts..."
+
+	  if test -z "$gentop"; then
+	    gentop="$output_objdir/${outputname}x"
+	    generated="$generated $gentop"
+
+	    $show "${rm}r $gentop"
+	    $run ${rm}r "$gentop"
+	    $show "$mkdir $gentop"
+	    $run $mkdir "$gentop"
+	    exit_status=$?
+	    if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
+	      exit $exit_status
+	    fi
+	  fi
+
+	  save_oldobjs=$oldobjs
+	  oldobjs=
+	  counter=1
+	  for obj in $save_oldobjs
+	  do
+	    objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+	    case " $oldobjs " in
+	    " ") oldobjs=$obj ;;
+	    *[\ /]"$objbase "*)
+	      while :; do
+		# Make sure we don't pick an alternate name that also
+		# overlaps.
+		newobj=lt$counter-$objbase
+		counter=`expr $counter + 1`
+		case " $oldobjs " in
+		*[\ /]"$newobj "*) ;;
+		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
+		esac
+	      done
+	      $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+	      $run ln "$obj" "$gentop/$newobj" ||
+	      $run cp "$obj" "$gentop/$newobj"
+	      oldobjs="$oldobjs $gentop/$newobj"
+	      ;;
+	    *) oldobjs="$oldobjs $obj" ;;
+	    esac
+	  done
+	fi
+
+	eval cmds=\"$old_archive_cmds\"
+
+	if len=`expr "X$cmds" : ".*"` &&
+	     test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+	  cmds=$old_archive_cmds
+	else
+	  # the command line is too long to link in one step, link in parts
+	  $echo "using piecewise archive linking..."
+	  save_RANLIB=$RANLIB
+	  RANLIB=:
+	  objlist=
+	  concat_cmds=
+	  save_oldobjs=$oldobjs
+
+	  # Is there a better way of finding the last object in the list?
+	  for obj in $save_oldobjs
+	  do
+	    last_oldobj=$obj
+	  done
+	  for obj in $save_oldobjs
+	  do
+	    oldobjs="$objlist $obj"
+	    objlist="$objlist $obj"
+	    eval test_cmds=\"$old_archive_cmds\"
+	    if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
+	       test "$len" -le "$max_cmd_len"; then
+	      :
+	    else
+	      # the above command should be used before it gets too long
+	      oldobjs=$objlist
+	      if test "$obj" = "$last_oldobj" ; then
+	        RANLIB=$save_RANLIB
+	      fi
+	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+	      eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+	      objlist=
+	    fi
+	  done
+	  RANLIB=$save_RANLIB
+	  oldobjs=$objlist
+	  if test "X$oldobjs" = "X" ; then
+	    eval cmds=\"\$concat_cmds\"
+	  else
+	    eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+	  fi
+	fi
+      fi
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+        eval cmd=\"$cmd\"
+	IFS="$save_ifs"
+	$show "$cmd"
+	$run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$generated"; then
+      $show "${rm}r$generated"
+      $run ${rm}r$generated
+    fi
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      $show "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+	if eval test -z \"\${$var+set}\"; then
+	  relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+	elif eval var_value=\$$var; test -z "$var_value"; then
+	  relink_command="$var=; export $var; $relink_command"
+	else
+	  var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+	  relink_command="$var=\"$var_value\"; export $var; $relink_command"
+	fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+	relink_command=
+      fi
+
+
+      # Only create the output if not a dry run.
+      if test -z "$run"; then
+	for installed in no yes; do
+	  if test "$installed" = yes; then
+	    if test -z "$install_libdir"; then
+	      break
+	    fi
+	    output="$output_objdir/$outputname"i
+	    # Replace all uninstalled libtool libraries with the installed ones
+	    newdependency_libs=
+	    for deplib in $dependency_libs; do
+	      case $deplib in
+	      *.la)
+		name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+		if test -z "$libdir"; then
+		  $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+		  exit $EXIT_FAILURE
+		fi
+		newdependency_libs="$newdependency_libs $libdir/$name"
+		;;
+	      *) newdependency_libs="$newdependency_libs $deplib" ;;
+	      esac
+	    done
+	    dependency_libs="$newdependency_libs"
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+	      eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+	      if test -z "$libdir"; then
+		$echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+		exit $EXIT_FAILURE
+	      fi
+	      newdlfiles="$newdlfiles $libdir/$name"
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+	      eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+	      if test -z "$libdir"; then
+		$echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+		exit $EXIT_FAILURE
+	      fi
+	      newdlprefiles="$newdlprefiles $libdir/$name"
+	    done
+	    dlprefiles="$newdlprefiles"
+	  else
+	    newdlfiles=
+	    for lib in $dlfiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlfiles="$newdlfiles $abs"
+	    done
+	    dlfiles="$newdlfiles"
+	    newdlprefiles=
+	    for lib in $dlprefiles; do
+	      case $lib in
+		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+		*) abs=`pwd`"/$lib" ;;
+	      esac
+	      newdlprefiles="$newdlprefiles $abs"
+	    done
+	    dlprefiles="$newdlprefiles"
+	  fi
+	  $rm $output
+	  # place dlname in correct position for cygwin
+	  tdlname=$dlname
+	  case $host,$output,$installed,$module,$dlname in
+	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+	  esac
+	  $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+	  if test "$installed" = no && test "$need_relink" = yes; then
+	    $echo >> $output "\
+relink_command=\"$relink_command\""
+	  fi
+	done
+      fi
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+      $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+    ;;
+
+  # libtool install mode
+  install)
+    modename="$modename: install"
+
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       $echo "X$nonopt" | grep shtool > /dev/null; then
+      # Aesthetically quote it.
+      arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	arg="\"$arg\""
+	;;
+      esac
+      install_prog="$arg "
+      arg="$1"
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+    case $arg in
+    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+      arg="\"$arg\""
+      ;;
+    esac
+    install_prog="$install_prog$arg"
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    for arg
+    do
+      if test -n "$dest"; then
+	files="$files $dest"
+	dest=$arg
+	continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f) 
+      	case " $install_prog " in
+	*[\\\ /]cp\ *) ;;
+	*) prev=$arg ;;
+	esac
+	;;
+      -g | -m | -o) prev=$arg ;;
+      -s)
+	stripme=" -s"
+	continue
+	;;
+      -*)
+	;;
+      *)
+	# If the previous option needed an argument, then skip it.
+	if test -n "$prev"; then
+	  prev=
+	else
+	  dest=$arg
+	  continue
+	fi
+	;;
+      esac
+
+      # Aesthetically quote the argument.
+      arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+      case $arg in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
+	arg="\"$arg\""
+	;;
+      esac
+      install_prog="$install_prog $arg"
+    done
+
+    if test -z "$install_prog"; then
+      $echo "$modename: you must specify an install program" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    if test -n "$prev"; then
+      $echo "$modename: the \`$prev' option requires an argument" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+	$echo "$modename: no file or destination specified" 1>&2
+      else
+	$echo "$modename: you must specify a destination" 1>&2
+      fi
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    # Strip any trailing slash from the destination.
+    dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+      test "X$destdir" = "X$dest" && destdir=.
+      destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files
+      if test "$#" -gt 2; then
+	$echo "$modename: \`$dest' is not a directory" 1>&2
+	$echo "$help" 1>&2
+	exit $EXIT_FAILURE
+      fi
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+	case $file in
+	*.lo) ;;
+	*)
+	  $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+	  $echo "$help" 1>&2
+	  exit $EXIT_FAILURE
+	  ;;
+	esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+	# Do the static libraries later.
+	staticlibs="$staticlibs $file"
+	;;
+
+      *.la)
+	# Check to see that this really is a libtool archive.
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+	else
+	  $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+	  $echo "$help" 1>&2
+	  exit $EXIT_FAILURE
+	fi
+
+	library_names=
+	old_library=
+	relink_command=
+	# If there is no directory component, then add one.
+	case $file in
+	*/* | *\\*) . $file ;;
+	*) . ./$file ;;
+	esac
+
+	# Add the libdir to current_libdirs if it is the destination.
+	if test "X$destdir" = "X$libdir"; then
+	  case "$current_libdirs " in
+	  *" $libdir "*) ;;
+	  *) current_libdirs="$current_libdirs $libdir" ;;
+	  esac
+	else
+	  # Note the libdir as a future libdir.
+	  case "$future_libdirs " in
+	  *" $libdir "*) ;;
+	  *) future_libdirs="$future_libdirs $libdir" ;;
+	  esac
+	fi
+
+	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+	test "X$dir" = "X$file/" && dir=
+	dir="$dir$objdir"
+
+	if test -n "$relink_command"; then
+	  # Determine the prefix the user has applied to our future dir.
+	  inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+	  # Don't allow the user to place us outside of our expected
+	  # location b/c this prevents finding dependent libraries that
+	  # are installed to the same prefix.
+	  # At present, this check doesn't affect windows .dll's that
+	  # are installed into $libdir/../bin (currently, that works fine)
+	  # but it's something to keep an eye on.
+	  if test "$inst_prefix_dir" = "$destdir"; then
+	    $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+
+	  if test -n "$inst_prefix_dir"; then
+	    # Stick the inst_prefix_dir data into the link command.
+	    relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+	  else
+	    relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+	  fi
+
+	  $echo "$modename: warning: relinking \`$file'" 1>&2
+	  $show "$relink_command"
+	  if $run eval "$relink_command"; then :
+	  else
+	    $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+	fi
+
+	# See the names of the shared library.
+	set dummy $library_names
+	if test -n "$2"; then
+	  realname="$2"
+	  shift
+	  shift
+
+	  srcname="$realname"
+	  test -n "$relink_command" && srcname="$realname"T
+
+	  # Install the shared library and build the symlinks.
+	  $show "$install_prog $dir/$srcname $destdir/$realname"
+	  $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+	  if test -n "$stripme" && test -n "$striplib"; then
+	    $show "$striplib $destdir/$realname"
+	    $run eval "$striplib $destdir/$realname" || exit $?
+	  fi
+
+	  if test "$#" -gt 0; then
+	    # Delete the old symlinks, and create new ones.
+	    # Try `ln -sf' first, because the `ln' binary might depend on
+	    # the symlink we replace!  Solaris /bin/ln does not understand -f,
+	    # so we also need to try rm && ln -s.
+	    for linkname
+	    do
+	      if test "$linkname" != "$realname"; then
+                $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+                $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+	      fi
+	    done
+	  fi
+
+	  # Do each command in the postinstall commands.
+	  lib="$destdir/$realname"
+	  cmds=$postinstall_cmds
+	  save_ifs="$IFS"; IFS='~'
+	  for cmd in $cmds; do
+	    IFS="$save_ifs"
+	    eval cmd=\"$cmd\"
+	    $show "$cmd"
+	    $run eval "$cmd" || {
+	      lt_exit=$?
+
+	      # Restore the uninstalled library and exit
+	      if test "$mode" = relink; then
+		$run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+	      fi
+
+	      exit $lt_exit
+	    }
+	  done
+	  IFS="$save_ifs"
+	fi
+
+	# Install the pseudo-library for information purposes.
+	name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+	instname="$dir/$name"i
+	$show "$install_prog $instname $destdir/$name"
+	$run eval "$install_prog $instname $destdir/$name" || exit $?
+
+	# Maybe install the static library, too.
+	test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+	;;
+
+      *.lo)
+	# Install (i.e. copy) a libtool object.
+
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+	  destfile="$destdir/$destfile"
+	fi
+
+	# Deduce the name of the destination old-style object file.
+	case $destfile in
+	*.lo)
+	  staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+	  ;;
+	*.$objext)
+	  staticdest="$destfile"
+	  destfile=
+	  ;;
+	*)
+	  $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+	  $echo "$help" 1>&2
+	  exit $EXIT_FAILURE
+	  ;;
+	esac
+
+	# Install the libtool object if requested.
+	if test -n "$destfile"; then
+	  $show "$install_prog $file $destfile"
+	  $run eval "$install_prog $file $destfile" || exit $?
+	fi
+
+	# Install the old object if enabled.
+	if test "$build_old_libs" = yes; then
+	  # Deduce the name of the old-style object file.
+	  staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+	  $show "$install_prog $staticobj $staticdest"
+	  $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+	fi
+	exit $EXIT_SUCCESS
+	;;
+
+      *)
+	# Figure out destination file name, if it wasn't already specified.
+	if test -n "$destname"; then
+	  destfile="$destdir/$destname"
+	else
+	  destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+	  destfile="$destdir/$destfile"
+	fi
+
+	# If the file is missing, and there is a .exe on the end, strip it
+	# because it is most likely a libtool script we actually want to
+	# install
+	stripped_ext=""
+	case $file in
+	  *.exe)
+	    if test ! -f "$file"; then
+	      file=`$echo $file|${SED} 's,.exe$,,'`
+	      stripped_ext=".exe"
+	    fi
+	    ;;
+	esac
+
+	# Do a test to see if this is really a libtool program.
+	case $host in
+	*cygwin*|*mingw*)
+	    wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+	    ;;
+	*)
+	    wrapper=$file
+	    ;;
+	esac
+	if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+	  notinst_deplibs=
+	  relink_command=
+
+	  # Note that it is not necessary on cygwin/mingw to append a dot to
+	  # foo even if both foo and FILE.exe exist: automatic-append-.exe
+	  # behavior happens only for exec(3), not for open(2)!  Also, sourcing
+	  # `FILE.' does not work on cygwin managed mounts.
+	  #
+	  # If there is no directory component, then add one.
+	  case $wrapper in
+	  */* | *\\*) . ${wrapper} ;;
+	  *) . ./${wrapper} ;;
+	  esac
+
+	  # Check the variables that should have been set.
+	  if test -z "$notinst_deplibs"; then
+	    $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+	    exit $EXIT_FAILURE
+	  fi
+
+	  finalize=yes
+	  for lib in $notinst_deplibs; do
+	    # Check to see that each library is installed.
+	    libdir=
+	    if test -f "$lib"; then
+	      # If there is no directory component, then add one.
+	      case $lib in
+	      */* | *\\*) . $lib ;;
+	      *) . ./$lib ;;
+	      esac
+	    fi
+	    libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+	    if test -n "$libdir" && test ! -f "$libfile"; then
+	      $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+	      finalize=no
+	    fi
+	  done
+
+	  relink_command=
+	  # Note that it is not necessary on cygwin/mingw to append a dot to
+	  # foo even if both foo and FILE.exe exist: automatic-append-.exe
+	  # behavior happens only for exec(3), not for open(2)!  Also, sourcing
+	  # `FILE.' does not work on cygwin managed mounts.
+	  #
+	  # If there is no directory component, then add one.
+	  case $wrapper in
+	  */* | *\\*) . ${wrapper} ;;
+	  *) . ./${wrapper} ;;
+	  esac
+
+	  outputname=
+	  if test "$fast_install" = no && test -n "$relink_command"; then
+	    if test "$finalize" = yes && test -z "$run"; then
+	      tmpdir=`func_mktempdir`
+	      file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
+	      outputname="$tmpdir/$file"
+	      # Replace the output file specification.
+	      relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+	      $show "$relink_command"
+	      if $run eval "$relink_command"; then :
+	      else
+		$echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+		${rm}r "$tmpdir"
+		continue
+	      fi
+	      file="$outputname"
+	    else
+	      $echo "$modename: warning: cannot relink \`$file'" 1>&2
+	    fi
+	  else
+	    # Install the binary that we compiled earlier.
+	    file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+	  fi
+	fi
+
+	# remove .exe since cygwin /usr/bin/install will append another
+	# one anyway 
+	case $install_prog,$host in
+	*/usr/bin/install*,*cygwin*)
+	  case $file:$destfile in
+	  *.exe:*.exe)
+	    # this is ok
+	    ;;
+	  *.exe:*)
+	    destfile=$destfile.exe
+	    ;;
+	  *:*.exe)
+	    destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
+	    ;;
+	  esac
+	  ;;
+	esac
+	$show "$install_prog$stripme $file $destfile"
+	$run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+	test -n "$outputname" && ${rm}r "$tmpdir"
+	;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      $show "$install_prog $file $oldlib"
+      $run eval "$install_prog \$file \$oldlib" || exit $?
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+	$show "$old_striplib $oldlib"
+	$run eval "$old_striplib $oldlib" || exit $?
+      fi
+
+      # Do each command in the postinstall commands.
+      cmds=$old_postinstall_cmds
+      save_ifs="$IFS"; IFS='~'
+      for cmd in $cmds; do
+	IFS="$save_ifs"
+	eval cmd=\"$cmd\"
+	$show "$cmd"
+	$run eval "$cmd" || exit $?
+      done
+      IFS="$save_ifs"
+    done
+
+    if test -n "$future_libdirs"; then
+      $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+    fi
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      test -n "$run" && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+    ;;
+
+  # libtool finish mode
+  finish)
+    modename="$modename: finish"
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+	libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+	if test -n "$finish_cmds"; then
+	  # Do each command in the finish commands.
+	  cmds=$finish_cmds
+	  save_ifs="$IFS"; IFS='~'
+	  for cmd in $cmds; do
+	    IFS="$save_ifs"
+	    eval cmd=\"$cmd\"
+	    $show "$cmd"
+	    $run eval "$cmd" || admincmds="$admincmds
+       $cmd"
+	  done
+	  IFS="$save_ifs"
+	fi
+	if test -n "$finish_eval"; then
+	  # Do the single finish_eval.
+	  eval cmds=\"$finish_eval\"
+	  $run eval "$cmds" || admincmds="$admincmds
+       $cmds"
+	fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    test "$show" = : && exit $EXIT_SUCCESS
+
+    $echo "X----------------------------------------------------------------------" | $Xsed
+    $echo "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      $echo "   $libdir"
+    done
+    $echo
+    $echo "If you ever happen to want to link against installed libraries"
+    $echo "in a given directory, LIBDIR, you must either use libtool, and"
+    $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    $echo "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      $echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      $echo "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      $echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+      $echo "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval flag=\"$hardcode_libdir_flag_spec\"
+
+      $echo "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      $echo "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      $echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    $echo
+    $echo "See any operating system documentation about shared libraries for"
+    $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+    $echo "X----------------------------------------------------------------------" | $Xsed
+    exit $EXIT_SUCCESS
+    ;;
+
+  # libtool execute mode
+  execute)
+    modename="$modename: execute"
+
+    # The first argument is the command name.
+    cmd="$nonopt"
+    if test -z "$cmd"; then
+      $echo "$modename: you must specify a COMMAND" 1>&2
+      $echo "$help"
+      exit $EXIT_FAILURE
+    fi
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      if test ! -f "$file"; then
+	$echo "$modename: \`$file' is not a file" 1>&2
+	$echo "$help" 1>&2
+	exit $EXIT_FAILURE
+      fi
+
+      dir=
+      case $file in
+      *.la)
+	# Check to see that this really is a libtool archive.
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+	else
+	  $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+	  $echo "$help" 1>&2
+	  exit $EXIT_FAILURE
+	fi
+
+	# Read the libtool library.
+	dlname=
+	library_names=
+
+	# If there is no directory component, then add one.
+	case $file in
+	*/* | *\\*) . $file ;;
+	*) . ./$file ;;
+	esac
+
+	# Skip this library if it cannot be dlopened.
+	if test -z "$dlname"; then
+	  # Warn if it was a shared library.
+	  test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+	  continue
+	fi
+
+	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+	test "X$dir" = "X$file" && dir=.
+
+	if test -f "$dir/$objdir/$dlname"; then
+	  dir="$dir/$objdir"
+	else
+	  $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+	  exit $EXIT_FAILURE
+	fi
+	;;
+
+      *.lo)
+	# Just add the directory containing the .lo file.
+	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+	test "X$dir" = "X$file" && dir=.
+	;;
+
+      *)
+	$echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+	continue
+	;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+	eval "$shlibpath_var=\"\$dir\""
+      else
+	eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -*) ;;
+      *)
+	# Do a test to see if this is really a libtool program.
+	if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	  # If there is no directory component, then add one.
+	  case $file in
+	  */* | *\\*) . $file ;;
+	  *) . ./$file ;;
+	  esac
+
+	  # Transform arg to wrapped name.
+	  file="$progdir/$program"
+	fi
+	;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+      args="$args \"$file\""
+    done
+
+    if test -z "$run"; then
+      if test -n "$shlibpath_var"; then
+	# Export the shlibpath_var.
+	eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      if test "${save_LC_ALL+set}" = set; then
+	LC_ALL="$save_LC_ALL"; export LC_ALL
+      fi
+      if test "${save_LANG+set}" = set; then
+	LANG="$save_LANG"; export LANG
+      fi
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+	eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+	$echo "export $shlibpath_var"
+      fi
+      $echo "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+    ;;
+
+  # libtool clean and uninstall mode
+  clean | uninstall)
+    modename="$modename: $mode"
+    rm="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) rm="$rm $arg"; rmforce=yes ;;
+      -*) rm="$rm $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    if test -z "$rm"; then
+      $echo "$modename: you must specify an RM program" 1>&2
+      $echo "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    rmdirs=
+
+    origobjdir="$objdir"
+    for file in $files; do
+      dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+      if test "X$dir" = "X$file"; then
+	dir=.
+	objdir="$origobjdir"
+      else
+	objdir="$dir/$origobjdir"
+      fi
+      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+      test "$mode" = uninstall && objdir="$dir"
+
+      # Remember objdir for removal later, being careful to avoid duplicates
+      if test "$mode" = clean; then
+	case " $rmdirs " in
+	  *" $objdir "*) ;;
+	  *) rmdirs="$rmdirs $objdir" ;;
+	esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if (test -L "$file") >/dev/null 2>&1 \
+	|| (test -h "$file") >/dev/null 2>&1 \
+	|| test -f "$file"; then
+	:
+      elif test -d "$file"; then
+	exit_status=1
+	continue
+      elif test "$rmforce" = yes; then
+	continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+	# Possibly a libtool archive, so verify it.
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	  . $dir/$name
+
+	  # Delete the libtool libraries and symlinks.
+	  for n in $library_names; do
+	    rmfiles="$rmfiles $objdir/$n"
+	  done
+	  test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+	  case "$mode" in
+	  clean)
+	    case "  $library_names " in
+	    # "  " in the beginning catches empty $dlname
+	    *" $dlname "*) ;;
+	    *) rmfiles="$rmfiles $objdir/$dlname" ;;
+	    esac
+	     test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+	    ;;
+	  uninstall)
+	    if test -n "$library_names"; then
+	      # Do each command in the postuninstall commands.
+	      cmds=$postuninstall_cmds
+	      save_ifs="$IFS"; IFS='~'
+	      for cmd in $cmds; do
+		IFS="$save_ifs"
+		eval cmd=\"$cmd\"
+		$show "$cmd"
+		$run eval "$cmd"
+		if test "$?" -ne 0 && test "$rmforce" != yes; then
+		  exit_status=1
+		fi
+	      done
+	      IFS="$save_ifs"
+	    fi
+
+	    if test -n "$old_library"; then
+	      # Do each command in the old_postuninstall commands.
+	      cmds=$old_postuninstall_cmds
+	      save_ifs="$IFS"; IFS='~'
+	      for cmd in $cmds; do
+		IFS="$save_ifs"
+		eval cmd=\"$cmd\"
+		$show "$cmd"
+		$run eval "$cmd"
+		if test "$?" -ne 0 && test "$rmforce" != yes; then
+		  exit_status=1
+		fi
+	      done
+	      IFS="$save_ifs"
+	    fi
+	    # FIXME: should reinstall the best remaining shared library.
+	    ;;
+	  esac
+	fi
+	;;
+
+      *.lo)
+	# Possibly a libtool object, so verify it.
+	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+	  # Read the .lo file
+	  . $dir/$name
+
+	  # Add PIC object to the list of files to remove.
+	  if test -n "$pic_object" \
+	     && test "$pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$pic_object"
+	  fi
+
+	  # Add non-PIC object to the list of files to remove.
+	  if test -n "$non_pic_object" \
+	     && test "$non_pic_object" != none; then
+	    rmfiles="$rmfiles $dir/$non_pic_object"
+	  fi
+	fi
+	;;
+
+      *)
+	if test "$mode" = clean ; then
+	  noexename=$name
+	  case $file in
+	  *.exe)
+	    file=`$echo $file|${SED} 's,.exe$,,'`
+	    noexename=`$echo $name|${SED} 's,.exe$,,'`
+	    # $file with .exe has already been added to rmfiles,
+	    # add $file without .exe
+	    rmfiles="$rmfiles $file"
+	    ;;
+	  esac
+	  # Do a test to see if this is a libtool program.
+	  if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+	    relink_command=
+	    . $dir/$noexename
+
+	    # note $name still contains .exe if it was in $file originally
+	    # as does the version of $file that was added into $rmfiles
+	    rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+	    if test "$fast_install" = yes && test -n "$relink_command"; then
+	      rmfiles="$rmfiles $objdir/lt-$name"
+	    fi
+	    if test "X$noexename" != "X$name" ; then
+	      rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+	    fi
+	  fi
+	fi
+	;;
+      esac
+      $show "$rm $rmfiles"
+      $run $rm $rmfiles || exit_status=1
+    done
+    objdir="$origobjdir"
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+	$show "rmdir $dir"
+	$run rmdir $dir >/dev/null 2>&1
+      fi
+    done
+
+    exit $exit_status
+    ;;
+
+  "")
+    $echo "$modename: you must specify a MODE" 1>&2
+    $echo "$generic_help" 1>&2
+    exit $EXIT_FAILURE
+    ;;
+  esac
+
+  if test -z "$exec_cmd"; then
+    $echo "$modename: invalid operation mode \`$mode'" 1>&2
+    $echo "$generic_help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+  eval exec $exec_cmd
+  exit $EXIT_FAILURE
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+    --config          show all configuration variables
+    --debug           enable verbose shell tracing
+-n, --dry-run         display commands without modifying any files
+    --features        display basic configuration information and exit
+    --finish          same as \`--mode=finish'
+    --help            display this help message and exit
+    --mode=MODE       use operation mode MODE [default=inferred from MODE-ARGS]
+    --quiet           same as \`--silent'
+    --silent          don't print informational messages
+    --tag=TAG         use configuration variables from tag TAG
+    --version         print version information
+
+MODE must be one of the following:
+
+      clean           remove files from the build directory
+      compile         compile a source file into a libtool object
+      execute         automatically set library path, then run a program
+      finish          complete the installation of libtool libraries
+      install         install libraries or executables
+      link            create a library or an executable
+      uninstall       remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE.  Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool at gnu.org>."
+  exit $EXIT_SUCCESS
+  ;;
+
+clean)
+  $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+compile)
+  $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -prefer-pic       try to building PIC objects only
+  -prefer-non-pic   try to building non-PIC objects only
+  -static           always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+  ;;
+
+execute)
+  $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+  ;;
+
+finish)
+  $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+  ;;
+
+install)
+  $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+  ;;
+
+link)
+  $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+		    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+		    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -static           do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+		    specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+  ;;
+
+uninstall)
+  $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+  ;;
+
+*)
+  $echo "$modename: invalid operation mode \`$mode'" 1>&2
+  $echo "$help" 1>&2
+  exit $EXIT_FAILURE
+  ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit $?
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+disable_libs=shared
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+disable_libs=static
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:

Modified: branches/Solaris/src/Makefile.am
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/Makefile.am?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/Makefile.am (original)
+++ branches/Solaris/src/Makefile.am Thu Jun 12 10:28:09 2008
@@ -1,10 +1,10 @@
 # Process this file with automake to create Makefile.in.
 
-SUBDIRS = . utils
+SUBDIRS = . utils modules
 AM_CPPFLAGS = -I$(top_srcdir)/src/PCSC -I$(top_builddir)/src/PCSC \
 	$(SYMBOL_VISIBILITY)
 
-lib_LTLIBRARIES = libpcsclite.la
+lib_LTLIBRARIES = libpcsclite.la libpcsclite64.la
 
 if !HAVE_SCF
 sbin_PROGRAMS = pcscd
@@ -17,9 +17,32 @@
 PCSC_CLIENT_SRC  = winscard_clnt.c
 endif
 
+
+libpcsclite64_la_SOURCES = \
+	debug.c \
+	debug.h \
+	pcsc_config.h \
+	cfgfuncs.c \
+	dyn_hpux.c \
+	dyn_macosx.c \
+	dyn_unix.c \
+	error.c \
+	$(PCSC_CLIENT_SRC) \
+	strlcat.c \
+	strlcpy.c \
+	sys_unix.c \
+	thread_unix.c \
+	winscard_msg.c
+libpcsclite64_la_LDFLAGS = -64 -version-info 1:0:0
+libpcsclite64_la_CFLAGS = $(CFLAGS) -xarch=generic64 $(PTHREAD_CFLAGS) -DLIBPCSCLITE
+libpcsclite64_la_LIBADD = $(COREFOUNDATION) $(LIBSMARTCARD) $(LIBDL) \
+	$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
+
 libpcsclite_la_SOURCES = \
 	debug.c \
 	debug.h \
+	pcsc_config.h \
+	cfgfuncs.c \
 	dyn_hpux.c \
 	dyn_macosx.c \
 	dyn_unix.c \
@@ -38,9 +61,15 @@
 pcscd_SOURCES = \
 	atrhandler.c \
 	atrhandler.h \
+	auth.c \
+	auth.h \
 	configfile.h \
 	configfile.l \
+	pcsc_config.h \
+	cfgfuncs.c \
 	debuglog.c \
+	daemon_utils.c \
+	daemon_utils.h \
 	dyn_generic.h \
 	dyn_hpux.c \
 	dyn_macosx.c \
@@ -54,15 +83,28 @@
 	hotplug_macosx.c \
 	ifdwrapper.c \
 	ifdwrapper.h \
+	instance.c \
+	instance.h \
+	launcher.h \
+	launcher.c \
 	misc.h \
 	parser.h \
 	pcscdaemon.c \
+	pcscdaemon.h \
+	debug.h \
+	validate.c \
+	validate.h \
+	util.h \
 	PCSC/debuglog.h \
 	PCSC/ifdhandler.h \
 	PCSC/pcsclite.h \
 	PCSC/pcsclite.h.in \
 	PCSC/winscard.h \
 	PCSC/wintypes.h \
+	PCSC/clientcred.h \
+	PCSC/pcscd-auth.h \
+	PCSC/ifd-auth.h \
+	PCSC/pcscd-validate.h \
 	powermgt_generic.c \
 	powermgt_generic.h \
 	powermgt_macosx.c \
@@ -95,10 +137,15 @@
 testpcsc_LDADD = libpcsclite.la
 
 nobase_include_HEADERS = \
+	debug.h \
+	PCSC/clientcred.h \
 	PCSC/debuglog.h \
 	PCSC/ifdhandler.h \
 	PCSC/winscard.h \
-	PCSC/wintypes.h
+	PCSC/wintypes.h \
+	PCSC/pcscd-auth.h \
+	PCSC/ifd-auth.h \
+	PCSC/pcscd-validate.h
 
 nodistheaderdir = $(includedir)/PCSC
 nodistheader_DATA = PCSC/reader.h PCSC/pcsclite.h

Added: branches/Solaris/src/PCSC/clientcred.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/PCSC/clientcred.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/PCSC/clientcred.h (added)
+++ branches/Solaris/src/PCSC/clientcred.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,58 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 1999-2006
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  David Markowitz <david.markowitz at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * //// PUT RIGHT MACRO EXPANSION KEYWORDS IN HERE ////
+ */
+
+/**
+ * @file
+ * @brief This is for passing client credentials.
+ */
+
+#ifndef _client_cred_h_
+#define _client_cred_h_
+
+#include <ucred.h>
+#include <netdb.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define	IOCTL_CLIENT_CRED	SCARD_CTL_CODE(0x340001)
+
+typedef struct pcsc_client_cred {
+	uid_t		euid;		/* Solaris, Linux, FreeBSD, MacOS */
+	uid_t		egid;		/* Solaris, Linux, FreeBSD, MacOS */
+	pid_t		pid;		/* Solaris, Linux */
+	uint_t		dpyNbr;		/* X11 */
+	uint_t		screenNbr;	/* X11 */
+	in_addr_t	clientXhostIP;	/* Avail from $DISPLAY */
+	in_addr_t	clientIP;	/* Avail from accept() */
+	struct {
+		uid_t		ruid;	/* Real user id */
+		uid_t		rgid;	/* Real group id */
+#if 0
+#ifdef _SYS_TSOL_LABEL_H
+		m_label_t	*zone_label; /* Zone label */
+#endif
+#ifdef _ZONE_H
+		zoneid_t	zone_id; /* Zone Id */
+#endif
+#endif
+	} solaris;
+} PCSCLITE_CRED_T;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Propchange: branches/Solaris/src/PCSC/clientcred.h
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/src/PCSC/ifd-auth.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/PCSC/ifd-auth.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/PCSC/ifd-auth.h (added)
+++ branches/Solaris/src/PCSC/ifd-auth.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,99 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 1999-2005
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *
+ */
+
+/**
+ * @file
+ * @brief This keeps a list of defines shared between the driver and the application
+ */
+
+#ifndef __ifd_auth_h__
+#define __ifd_auth_h__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif //__cplusplus
+
+#ifndef __kvp_definition__
+#define __kvp_definition__
+
+#define MAX_KEY_LEN 64
+
+typedef struct kvp_list {
+	struct kvp_list *next;
+	char *key;
+	char *val;
+} kvp_t;
+
+#endif //__kvp_definition__
+
+/*
+ * Plugin entry points (plugin developer must implement these):
+ *
+ *  initIfdAuth() 
+ *
+ *      This function is called by the pcscd daemon with a list of keys as
+ *      the argument so the plugin can do self-setup.  The key list is valid
+ *      only in the scope of this function, so if the values need to be 
+ *      accessed afterwards a local copy or representation must be made.
+ *
+ *      NOTE: This function can be called more than once. Code accordingly!
+ *
+ *      Return values: 
+ *		SUCCESS  = 1
+ *		FAIL	 = 0
+ *
+ *  isAuthorizedForIfd()
+ *
+ *      This function determes whether the client is authorized to access
+ *      the specific ifd handler.  The display #, as well as the credentials of 
+ *      the client are passed in the cred structure.
+ *
+ *      The resource argument is the AUTHSERVICE argument defined in the
+ *      reader configuration file that associated the reader with the 
+ *      ifd handler whose access is being authenticated here.
+ * 
+ *      Return values:
+ *              SUCCESS = 1
+ *              FAIL    = 0
+ */
+int init(kvp_t *kvps);
+int isAuthorized(PCSCLITE_CRED_T *cred, 
+	const char *ifdHandlerName, const void *resource);
+
+
+
+/* Convenience functions:
+ *
+ *  findValueForKey()
+ * 
+ *       Optionally called by plugin to lookup specified key in a case
+ *       insensitive way.  The list of key-value pairs must be passed thru
+ *       the kvps argument.  The function returns the corresponding value
+ *       if the key is located, otherwise it returns NULL.
+ *
+ *  isKeyValueTrue()
+ *  
+ *       Optionally called by plugin to lookup a key and determine
+ *       if its corresponding value is one of the following strings:
+ *       "TRUE", "true", "YES", "yes", "ON", "on", or "1".
+ *
+ *       The function returns status 1 (boolean TRUE) if the key is defined 
+ *       and the key's value is set to one of the aforemrentioned strings,
+ *       otherwise the function returns 0 (boolean FALSE).
+ */
+char *findValueForKey(const kvp_t *kvps, const char *key);
+int isKeyValueTrue(const kvp_t *kvps, const char *key);
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif //__cplusplus
+
+#endif //__ifd_auth_h___

Modified: branches/Solaris/src/PCSC/ifdhandler.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/PCSC/ifdhandler.h?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/PCSC/ifdhandler.h (original)
+++ branches/Solaris/src/PCSC/ifdhandler.h Thu Jun 12 10:28:09 2008
@@ -140,6 +140,7 @@
 #define IFD_NOT_SUPPORTED		614
 #define IFD_ICC_PRESENT			615
 #define IFD_ICC_NOT_PRESENT		616
+#define IFD_NO_SUCH_DEVICE		617
 
 	/*
 	 * If you want to compile a V2.0 IFDHandler, define IFDHANDLERv2 before you

Added: branches/Solaris/src/PCSC/pcscd-auth.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/PCSC/pcscd-auth.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/PCSC/pcscd-auth.h (added)
+++ branches/Solaris/src/PCSC/pcscd-auth.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,113 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 1999-2005
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *
+ */
+
+/**
+ * @file
+ * @brief This keeps a list of defines shared between the driver and the application
+ */
+
+#ifndef __pcscd_auth_h__
+#define __pcscd_auth_h__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifndef __kvp_definition__
+#define __kvp_definition__
+
+#define MAX_KEY_LEN 64
+
+typedef struct kvp_list {
+	struct kvp_list *next;
+	char *key;
+	char *val;
+} kvp_t;
+
+#endif //__kvp_definition__
+
+/*
+ * Plugin entry points (plugin developer must implement these):
+ *
+ *  init(kvp_t *kvps) 
+ *
+ *      This function is called by the pcscd daemon with a list of keys as
+ *      the argument so the plugin can do self-setup.  The key list is valid
+ *      only in the scope of this function, so if the values need to be 
+ *      accessed afterwards a local copy or representation must be made.
+ *
+ *      NOTE: This function can be called more than once. Code accordingly!
+ *
+ *      Function arguments:
+ *      	kvps		keys value pairs passed from pcscd to plugin
+ *
+ *      Return values: 
+ *		SUCCESS  = 1
+ *		FAIL	 = 0
+ *
+ *  isAuthorized(PCSCLITE_CRED_T *cred, const void *resource)
+ *
+ *      This function determes whether the client is authorized to access
+ *      the pcscd daemon.  The display #, as well as the credentials of the
+ *      client are passed in the cred structure.
+ *
+ *      The resource argument is a determined by the plugin that validated
+ *      the display prior to this authentication plugin being called, and 
+ *      can be NULL.
+ *
+ *      Function arguments:
+ * 		cred		client cred struct from pcscd to plugin
+ *		resource	display resource from pcscd to plugin
+ *
+ *      Return values:
+ *              SUCCESS = 1
+ *              FAIL    = 0
+ */
+int init(kvp_t *kvps);
+int isAuthorized(PCSCLITE_CRED_T *cred, const void *resource);
+
+
+/* Convenience functions:
+ *
+ *  findValueForKey(const kvp_t *kvps, const char *key)
+ * 
+ *       Optionally called by plugin to lookup specified key in a case
+ *       insensitive way.  The list of key-value pairs must be passed thru
+ *       the kvps argument.  The function returns the corresponding value
+ *       if the key is located, otherwise it returns NULL.
+ *
+ *      Function arguments:
+ *		kvps		key value pairs from plugin to pcscd
+ *		key		key to find, plugin to pcscd
+ *
+ *  isKeyValueTrue(const kvp_t *kvps, const char *key)
+ *  
+ *       Optionally called by plugin to lookup a key and determine
+ *       if its corresponding value is one of the following strings:
+ *       "TRUE", "true", "YES", "yes", "ON", "on", or "1".
+ *
+ *      Function arguments:
+ *		kvps		key value pairs from plugin to pcscd
+ *		key		key to evaluation, plugin to pcscd
+ *
+ *       The function returns status 1 (boolean TRUE) if the key is defined 
+ *       and the key's value is set to one of the aforemrentioned strings,
+ *       otherwise the function returns 0 (boolean FALSE).
+ */
+
+char *findValueForKey(const kvp_t *kvps, const char *key);
+int isKeyValueTrue(const kvp_t *kvps, const char *key);
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif //__cplusplus
+
+#endif //__pcscd_auth_h___

Added: branches/Solaris/src/PCSC/pcscd-validate.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/PCSC/pcscd-validate.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/PCSC/pcscd-validate.h (added)
+++ branches/Solaris/src/PCSC/pcscd-validate.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,119 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 1999-2005
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ */
+
+/**
+ * @file
+ * @brief This keeps a list of defines shared between the driver and the application
+ */
+
+#ifndef __pcscd_validate_h__
+#define __pcscd_validate_h__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef int (*initValidate_t)(int, char **);
+typedef char *(*getDisplayTag_t)(int, char **);
+typedef void *(*getDisplayResource_t)(int, void **);
+typedef int (*getDisplayStatus_t)(int dpyNbr, unsigned int *flags);
+
+/*
+ * 
+ * Plugin entry points (plugin developer must implement these)
+ *
+ *   initValidation(int argc, char **argv, int *errnop):
+ *
+ *      This function is called by the pcscd daemon with argc, argv, in the
+ *      same manner that main() is called by UNIX-like OSes, and may be parsed
+ *      using getopt().  This function's job is to do whatever setup is 
+ *      necessary in order to use the validation functions also defined
+ *      plugin.
+ *
+ *      NOTE: This function can be called more than once. Code accordingly!
+ *
+ *      Function Arguments:
+ *
+ *              argc           Argument count
+ *              argv           Argument vector
+ *              errno          Pointer to errno (so plugin uses correct one)
+ *
+ *      Return values: 
+ *		SUCCESS  = 1
+ *		FAIL	 = 0
+ *
+ *   getDisplayTag(int dpyNbr, char **facilityTag):
+ *
+ *      This function returns the platform-specific name of the facility that
+ *      the display belongs to. For example, it could be the 'tag' value that
+ *      is defined for the dispaly in the Xservers file.
+ *
+ *      Function arguments:
+ *             dpyNbr          Passed from pcscd to plugin
+ *             **facilityTag   Ptr to bufptr passed to plugin to return tag into
+ * 		  	       The caller must free the buffer;
+ *
+ *      Return values:
+ *             Same value returned to *facilityTag;
+ * 
+ *
+ *   getDisplayResource(int dpyNbr, void **resource):
+ *
+ *      This function returns the platform-specific resource associated with
+ *      the display.  For example, it could be the whole entry that defines
+ *      the display in the Xservers file, or something else.   It is up to
+ *      the platform to decide.  This resource argument will be passed to
+ *      the authentication plugin during daemon access authentication.
+ *
+ *      Function arguments:
+ *      	dpyNbr         Passed from pcscd to plugin
+ *      	resource       Ptr to bufptr passed to plugin to return res into
+ *			       The caller must free the buffer.
+ *
+ *      Return values:
+ *		Same value returned to *resource
+ * 
+ * 
+ *    getDisplayStatus(int dpyNbr, unsigned int *flags):
+ *
+ *       This function returns whether or not a display is recognized
+ *       and valid, and returns flags providing extra information 
+ *       about the display pcscd will use to make decisions about
+ *       controlling access.
+ *
+ *       Function arguments:
+ *              dpyNbr        Passed from pcscd to plugin
+ *      	flags         Flags returned from plugin to pcscd:
+ *   
+ *       Return values:
+ *               DISPLAY_IS_VALID
+ *		 DISPLAY_NOT_VALID
+ *
+ *       
+ */
+#define DISPLAY_NOT_VALID	-1
+#define DISPLAY_IS_VALID	0
+
+/* 
+ * Bitmask values for getDisplayStatus flags argument.
+ */
+#define DISPLAY_HAS_NEW_PROVIDER 1	/* New session / owner for display */
+
+int initValidate(int argc, char **argv);
+char *getDisplayTag(int dpyNbr, char **facilityTag);
+void *getDisplayResource(int dpyNbr, void **resource);
+int getDisplayStatus(int dpyNbr, unsigned int *flags);
+
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif
+
+#endif

Modified: branches/Solaris/src/PCSC/pcsclite.h.in
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/PCSC/pcsclite.h.in?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/PCSC/pcsclite.h.in (original)
+++ branches/Solaris/src/PCSC/pcsclite.h.in Thu Jun 12 10:28:09 2008
@@ -102,6 +102,7 @@
 #define SCARD_E_CARD_UNSUPPORTED	0x8010001C
 #define SCARD_E_NO_SERVICE		0x8010001D
 #define SCARD_E_SERVICE_STOPPED		0x8010001E
+#define SCARD_E_NO_PERMISSION		0x80100020
 
 #define SCARD_SCOPE_USER		0x0000	/**< Scope in user space */
 #define SCARD_SCOPE_TERMINAL		0x0001	/**< Scope in terminal */
@@ -161,6 +162,8 @@
 #define BLOCK_STATUS_BLOCKING		0x00FA	/**< Function is blocking */
 
 #define PCSCLITE_CONFIG_DIR		"@confdir_exp@"
+#define XSERVERS_FILE			"@xservers_file_exp@"
+#define PCSCLITE_LIB_DIR		"@rtlibdir_exp@"
 
 #ifndef USE_IPCDIR
 #define PCSCLITE_IPC_DIR		"/var/run"
@@ -209,6 +212,7 @@
 #define PCSCLITE_TRANSACTION_TIMEOUT	40	/**< Transaction timeout */
 #define MAX_READERNAME			52
 #define MAX_LIBNAME			100
+#define MAX_AUTHSVCNAME			255	
 #define MAX_DEVICENAME		255
 
 #ifndef SCARD_ATR_LENGTH

Modified: branches/Solaris/src/PCSC/reader.h.in
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/PCSC/reader.h.in?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/PCSC/reader.h.in (original)
+++ branches/Solaris/src/PCSC/reader.h.in Thu Jun 12 10:28:09 2008
@@ -119,7 +119,7 @@
 
 /* Set structure elements aligment on bytes
  * http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */
-#ifdef __APPLE__
+#if defined(__APPLE__) || defined(sun)
 #pragma pack(1)
 #else
 #pragma pack(push, 1)
@@ -197,7 +197,7 @@
 } PIN_MODIFY_STRUCTURE;
 
 /* restore default structure elements alignment */
-#ifdef __APPLE__
+#if defined(__APPLE__) || defined(sun)
 #pragma pack()
 #else
 #pragma pack(pop)

Added: branches/Solaris/src/auth.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/auth.c?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/auth.c (added)
+++ branches/Solaris/src/auth.c Thu Jun 12 10:28:09 2008
@@ -1,0 +1,600 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2000-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * <NEED TO FIX KEYWORDS>
+ */
+
+/**
+ * @file
+ * @brief This handles thread function abstraction.
+ */
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ucred.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <thread.h>
+#include <synch.h>
+#include <debuglog.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "clientcred.h"
+#include "pcsc_config.h"
+#include "pcsclite.h"
+#include "auth.h"
+#if 0
+#include "pcscd-auth.h"
+#include "ifd-auth.h"
+#endif
+#include "util.h"
+
+#define AUTHORIZED 		1
+#define SUCCESS			0
+#define PLUGIN_NOT_FOUND 	-1
+#define PLUGIN_NOT_VALID	-2
+#define NOT_AUTHORIZED 		-3
+#define RELOAD_ABORTED		-4
+#define PATH_MAX 		256
+#define LINEMAX			256
+#define KVMAXLEN		256
+#define IFD_PLUGIN		0
+#define DAEMON_PLUGIN		1
+
+#define NONULL(s) s ? s : "<null>"
+
+#define MAX_KEY_LEN 64
+
+typedef struct kvp_list {
+	struct kvp_list *next;
+	char *key;
+	char *val;
+} kvp_t;
+
+typedef struct authPlugin {
+	struct authPlugin *nx;
+	struct authPlugin *pv;
+	void *handle;
+	char *path;
+	char *cfgFilePath;
+	char *tag;
+	char *resource;
+	int refcnt;
+	mutex_t refcnt_lock;
+	mutex_t unload_lock;
+	kvp_t *kvps;
+	time_t ctime;
+	time_t cfg_ctime;
+	int (*initFunc)();
+	int (*authFunc)();
+} plugin_t;
+
+static void freeKvp(kvp_t *);
+static void freeKvps(kvp_t *);
+static int loadPlugin(plugin_t **, const char *, char *, const char *, int);
+static int reloadPlugin(plugin_t **, int);
+static time_t getFileCtime(char *);
+static plugin_t *acquirePluginAccess(const char *, int);
+static plugin_t *releasePluginAccess(const char *, int);
+static int loadCfgFile(const char *, const char *, kvp_t **);
+static int invokeAuthPlugin(const char *, PCSCLITE_CRED_T *,
+    const char *, const void *, int);
+static plugin_t *findPluginByTag(const char *, int);
+
+static plugin_t plist, ilist;
+static time_t conf_ctime;
+
+#define NONULL(n) n ? n : "<null>"
+
+/**
+ * @brief Get client credentials from socket.
+ *
+ * Returns 0 if successful and populates euid & egid params
+ * Otherwise returns -1, and stores -1 in euid and egid params
+ *
+ * *** CURRENTLY SOLARIS ONLY... need to know how to check
+ * how feature works or OS and return in platform indep. way.
+ */
+int
+AUTHGetClientCreds(int fd, PCSCLITE_CRED_T *cred)
+{
+	ucred_t *ucred = NULL;
+	struct sockaddr_in s;
+	int rv, len;
+	/* For security purposed, assume it will fail */
+	cred->euid = -1;
+	cred->egid = -1;
+	cred->pid  = -1;
+	cred->solaris.ruid = -1;
+	cred->solaris.rgid = -1;
+
+	/* Calculate size of INETV4 type sockaddr struct */
+	memset(&s, 0, sizeof (s));
+	s.sin_family = AF_INET;
+	len = sizeof(s);
+
+	/* Attempt to get client IP address */
+	if ((rv = getpeername(fd, (struct sockaddr *)&s, &len)) != -1)
+		cred->clientIP = (in_addr_t)s.sin_addr.s_addr;
+
+	/* Attempt to get client credentials */
+	if ((rv = getpeerucred(fd, &ucred)) < 0)
+		return -1;
+
+	cred->euid = ucred_geteuid(ucred);
+	cred->egid = ucred_getegid(ucred);
+	cred->pid  = ucred_getpid(ucred);
+	cred->solaris.ruid = ucred_getruid(ucred);
+	cred->solaris.rgid = ucred_getrgid(ucred);
+
+	ucred_free(ucred);
+	return 0;
+}
+
+
+int
+AUTHCheckDaemon(const char *facilityTag, PCSCLITE_CRED_T *cred,
+			const char *resource)
+{
+	plugin_t *pp;
+
+	if (plist.nx == NULL)
+		LIST_INIT(&plist);
+
+	pp = acquirePluginAccess(facilityTag, DAEMON_PLUGIN);
+	/* Invoke the facility-specific module */
+	switch(invokeAuthPlugin(facilityTag, cred, "", resource, DAEMON_PLUGIN)) {
+	case AUTHORIZED:
+		if (pp)
+			releasePluginAccess(facilityTag, DAEMON_PLUGIN);
+		return 0;
+	case NOT_AUTHORIZED:
+		if (pp)
+			releasePluginAccess(facilityTag, DAEMON_PLUGIN);
+		return -1;
+	case PLUGIN_NOT_VALID:
+	case PLUGIN_NOT_FOUND:
+		/* Try again using the generic module */
+		switch(invokeAuthPlugin(NULL, cred, "", resource, DAEMON_PLUGIN)) {
+		case AUTHORIZED:
+			if (pp)
+				releasePluginAccess(facilityTag, DAEMON_PLUGIN);
+			return 0;
+		case NOT_AUTHORIZED:
+		case PLUGIN_NOT_VALID:
+		case PLUGIN_NOT_FOUND:
+			if (pp)
+				releasePluginAccess(facilityTag, DAEMON_PLUGIN);
+			return -1;
+		}
+	}
+	if (pp)
+		releasePluginAccess(facilityTag, DAEMON_PLUGIN);
+	return 0;
+}
+
+int
+AUTHCheckIfd(const char *facilityTag, PCSCLITE_CRED_T *cred,
+		 const char *ifdHandlerName, const char *resource)
+{
+	plugin_t *pp;
+
+	if (ilist.nx == NULL)
+		LIST_INIT(&ilist);
+
+	pp = acquirePluginAccess(facilityTag, IFD_PLUGIN);
+	/* Invoke the facility-specific module */
+	switch(invokeAuthPlugin(facilityTag, cred,
+	    ifdHandlerName, resource, IFD_PLUGIN)) {
+	case AUTHORIZED:
+		if (pp)
+			releasePluginAccess(facilityTag, IFD_PLUGIN);
+		return 0;
+	case NOT_AUTHORIZED:
+		if (pp)
+			releasePluginAccess(facilityTag, IFD_PLUGIN);
+		return -1;
+	case PLUGIN_NOT_VALID:
+	case PLUGIN_NOT_FOUND:
+		/* Try again using the generic module */
+		switch(invokeAuthPlugin(NULL, cred,
+		   ifdHandlerName, resource, IFD_PLUGIN)) {
+		case AUTHORIZED:
+			if (pp)
+				releasePluginAccess(facilityTag, IFD_PLUGIN);
+			return 0;
+		case NOT_AUTHORIZED:
+		case PLUGIN_NOT_VALID:
+		case PLUGIN_NOT_FOUND:
+			if (pp)
+				releasePluginAccess(facilityTag, IFD_PLUGIN);
+			return -1;
+		}
+	}
+	if (pp)
+		releasePluginAccess(facilityTag, IFD_PLUGIN);
+	return 0;
+}
+
+static int
+invokeAuthPlugin(const char *facilityTag, PCSCLITE_CRED_T *cred,
+	 const char *ifdHandlerName, const void *resource, int type)
+{
+	char cfgFilePath[PATH_MAX], *tag;
+	void *pluginHandle = NULL;
+	int rv;
+	plugin_t *pp, *listhead;
+
+	/*
+	 * See if we've already loaded the plugin
+	 */
+	listhead = (type == DAEMON_PLUGIN) ? &plist : &ilist;
+	LIST_FOREACH(pp, listhead) {
+		if (strcmp(pp->tag, facilityTag) == 0) {
+			pluginHandle = pp->handle;
+			break;
+		}
+	}
+	/*
+	 * If plugin isn't loaded, or the plugin or configuration file changed
+	 * on disk load (or refresh) the plugin.
+	 */
+	 if (pluginHandle == NULL) {
+		pp = NULL;
+		if (loadPlugin(&pp, facilityTag, cfgFilePath, resource, type) ==
+		    PLUGIN_NOT_VALID)
+			return 0;
+		LIST_INSERT_LAST(pp, listhead);
+	} else if (getFileCtime(pp->path) != pp->ctime ||
+		   getFileCtime(pp->cfgFilePath) != pp->cfg_ctime) {
+
+		if ((rv = reloadPlugin(&pp, type)) == PLUGIN_NOT_VALID)
+			return 0;
+		LIST_INSERT_LAST(pp, listhead);
+	}
+	/*
+	 * Call plugin authorization check function
+	 */
+	switch(type) {
+	case DAEMON_PLUGIN:
+		rv = pp->authFunc(cred, resource);
+		break;
+	case IFD_PLUGIN:
+		rv = pp->authFunc(cred, ifdHandlerName, resource);
+		break;
+	}
+	return rv;
+}
+
+static int
+loadPlugin(plugin_t **plugin, const char *facilityTag,
+    char *cfgFilePath, const char *resource, int type)
+{
+	char pluginPath[PATH_MAX];
+	plugin_t *pp;
+
+
+	if (*plugin != NULL) {
+		pp = *plugin;
+	} else {
+		if ((pp = malloc(sizeof (plugin_t))) == NULL) {
+			Log1(PCSC_LOG_CRITICAL, "Out of Memory");
+			return PLUGIN_NOT_VALID;
+		}
+		if (facilityTag == NULL) {
+			sprintf(pluginPath,  "%s/%sAuth.so.1",
+			    PCSCLITE_LIB_DIR, type == DAEMON_PLUGIN ? "pcscd" : "ifd");
+			sprintf(cfgFilePath, "%s/%sAuth.conf",
+			    PCSCLITE_LIB_DIR, type == DAEMON_PLUGIN ? "pcscd" : "ifd");
+		} else {
+			sprintf(pluginPath,  "%s/%sAuth-%s.so.1",
+			    PCSCLITE_LIB_DIR, type == DAEMON_PLUGIN ? "pcscd" : "ifd",
+			    facilityTag);
+			sprintf(cfgFilePath, "%s/%sAuth-%s.conf",
+			    PCSCLITE_LIB_DIR, type == DAEMON_PLUGIN ? "pcscd" : "ifd",
+			    facilityTag);
+		}
+		bzero(pp, sizeof (plugin_t));
+		pp->path = strdup(pluginPath);
+		pp->tag = strdup(facilityTag);
+		pp->cfgFilePath = strdup(cfgFilePath);
+		pp->resource = strdup(resource);
+	}
+
+	pp->ctime = getFileCtime(pluginPath);
+	pp->cfg_ctime = getFileCtime(cfgFilePath);
+	if (pp->kvps != NULL) {
+		freeKvps(pp->kvps);
+		pp->kvps = NULL;
+	}
+
+	if ((pp->handle = dlopen(pp->path,
+	    RTLD_GLOBAL | RTLD_PARENT | RTLD_LAZY)) == NULL) {
+		Log3(PCSC_LOG_CRITICAL,
+			"Err opening Auth plugin: %s:\n%s\n\n",
+			NONULL(pluginPath), dlerror());
+		free(pp);
+		return PLUGIN_NOT_FOUND;
+	}
+	if ((pp->initFunc = (int(*)())dlsym(pp->handle,  "init")) == NULL) {
+		Log3(PCSC_LOG_CRITICAL,
+		    "Err finding symbol 'init' in %s:\n%s\n\n",
+		    NONULL(pluginPath), dlerror());
+		dlclose(pp->handle);
+		free(pp);
+		return PLUGIN_NOT_VALID;
+	}
+	if ((pp->authFunc = (int(*)())dlsym(pp->handle, "isAuthorized")) == NULL) {
+		Log3(PCSC_LOG_CRITICAL,
+		    "Err finding symbol 'isAuthorized' in %s:\n%s\n\n",
+		     NONULL(pluginPath), dlerror());
+		dlclose(pp->handle);
+		free(pp);
+		return PLUGIN_NOT_VALID;
+	}
+	(void) loadCfgFile(cfgFilePath, resource, &pp->kvps);
+
+	/* Initialize the plugin */
+	if (pp->initFunc(pp->kvps) < 0) {
+		Log2(PCSC_LOG_CRITICAL,
+		    "Error initializing plugin: %s\n",
+		    NONULL(pluginPath));
+		freeKvps(pp->kvps);
+		dlclose(pp->handle);
+		free(pp);
+		return PLUGIN_NOT_VALID;
+	}
+
+	*plugin = pp;
+	return SUCCESS;
+}
+static int
+reloadPlugin(plugin_t **pp, int type)
+{
+	int rv;
+
+	/*
+	 * If the plugin is being unloaded by another thread
+	 * just return so we don't deadlock via the refcnt test
+	 */
+	if (mutex_trylock(&(*pp)->unload_lock) == EBUSY)
+		return PLUGIN_NOT_VALID;
+
+	/*
+	 * Wait for plugin accesses already in progess to complete
+	 */
+	for(;;) {
+		mutex_lock(&(*pp)->refcnt_lock);
+		if ((*pp)->refcnt == 1) {
+			// We unload when refcnt is 1 because that's us
+			mutex_unlock(&(*pp)->refcnt_lock);
+			break;
+		}
+		mutex_unlock(&(*pp)->refcnt_lock);
+		usleep(50000);
+	}
+	/*
+	 * Now have exclusive access to plugin.  Unload it.
+	 */
+	dlclose((*pp)->handle);
+	rv = loadPlugin(pp, NULL, NULL, NULL, NULL);
+	mutex_unlock(&(*pp)->unload_lock);
+	return rv;
+
+}
+
+/*
+ * Load and parse configuration file into global array.
+ * If an error occurs, displays brief definitive message
+ * which includes filename and line number and aborts
+ * the daemon.
+ */
+static int
+loadCfgFile(const char *path, const char *resource, kvp_t **kvps)
+{
+	FILE *fp = NULL;
+	char *cp, line[LINEMAX], temp[LINEMAX];
+	char key[KVMAXLEN], val[KVMAXLEN];
+	int i, j, rv, lineNbr;
+	kvp_t *new_kvp, *kvpp;
+	kvp_t *kvp_list = NULL;
+
+	if ((fp = fopen(path, "r")) == NULL)
+		return SUCCESS; // this conf file is optional
+
+	for (lineNbr = 1; fgets(temp, 256, fp) != NULL; ++lineNbr) {
+
+		memset(key,  0, sizeof (key));
+		memset(val,  0, sizeof (val));
+		memset(line, 0, sizeof(line));
+
+		if ((cp = strchr(temp, '\n')) != NULL)
+		    *cp = '\0';
+
+		if (strncmp(temp, "#", 1) == 0)  /* Discard comments */
+		       continue;
+
+		if ((cp = strchr(temp, '#')) != NULL) {
+		}
+		/* Get rid of whitespace and quote marks */
+		for (j = 0, i = 0; i < strlen(temp); i++)
+			if (temp[i] != ' ' && temp[i] != '\t' && temp[i] != '"')
+				line[j++] = temp[i];
+
+		/* Discard empty lines or lines with only whitespace */
+		if (j == 0)
+			continue;
+
+		/* Find '=' delimiter, error out if missing */
+		if ((cp = strchr(line, '=')) == NULL) {
+			Log3(PCSC_LOG_CRITICAL,
+			     "Missing delimiter in cfg file %s line %d\n",
+			     path, lineNbr);
+			fclose(fp);
+			return PLUGIN_NOT_VALID;
+
+		} else
+			*cp = '\0';  /* Divide line into two strings */
+
+		/* Extract val */
+		if (cp >= line + strlen(line))
+			strcpy(val, cp + 1);
+
+		/* Extract key */
+		strcpy(key, line);
+
+		new_kvp = malloc(sizeof (struct kvp_list));
+		new_kvp->next = NULL;
+		new_kvp->key = strdup(key);
+		new_kvp->val = strdup(val);
+		if (kvp_list == NULL)
+			kvp_list = new_kvp;
+		else {
+			for (kvpp = kvp_list; kvpp->next != NULL; kvpp = kvpp->next);
+			kvpp->next = new_kvp;
+		}
+	}
+	fclose(fp);
+	*kvps = kvp_list;
+	return SUCCESS;
+}
+
+static plugin_t *
+acquirePluginAccess(const char *tag, int type) {
+	plugin_t *pp, *listhead, *plugin = NULL;
+
+	if ((plugin = findPluginByTag(tag, type)) == NULL)
+		return NULL;
+	/*
+	 * Acquire/immedidate release intentional in order to deny access to
+	 * the plugin while reloadPlugin() is active. If, due to bad timing,
+	 * this brief acquisition causes the mutex_trylock() to abort
+	 * reloadPlugin(), statistics ensure the plugin will get reloaded
+	 * at a subsequent access, as the cached plugin file timestamp will
+	 * remain out of sync with the one in the filesystem.
+	 */
+	mutex_lock(&plugin->unload_lock);
+	mutex_unlock(&plugin->unload_lock);
+	mutex_lock(&plugin->refcnt_lock);
+	++plugin->refcnt;
+	mutex_unlock(&plugin->refcnt_lock);
+	return plugin;
+}
+
+static plugin_t *
+releasePluginAccess(const char *tag, int type) {
+	plugin_t *pp, *listhead, *plugin = NULL;
+
+	if ((plugin = findPluginByTag(tag, type)) == NULL)
+		return NULL;
+
+	mutex_lock(&plugin->refcnt_lock);
+	--plugin->refcnt;
+	mutex_unlock(&plugin->refcnt_lock);
+	return plugin;
+}
+
+
+static plugin_t *
+findPluginByTag(const char *tag, int type) {
+	plugin_t *pp, *listhead;
+
+	switch (type) {
+	case IFD_PLUGIN:
+		listhead = &ilist;
+		break;
+	case DAEMON_PLUGIN:
+		listhead = &plist;
+		break;
+	}
+
+	LIST_FOREACH(pp, listhead)
+		if (strcmp(pp->tag, tag) == 0)
+			return pp;
+
+	return NULL;
+}
+
+static void
+freeKvps(kvp_t *kvpp) {
+	kvp_t *saveptr;
+	while (kvpp != NULL) {
+		if (kvpp->key != NULL)
+			free(kvpp->key);
+		if (kvpp->val != NULL)
+			free(kvpp->val);
+		saveptr = kvpp;
+		kvpp = kvpp->next;
+		free(saveptr);
+	}
+}
+
+static void
+freeKvp(kvp_t *kvpp)
+{
+	if (kvpp == NULL)
+		return;
+	if (kvpp->key != NULL)
+		free(kvpp->key);
+	if (kvpp->val != NULL)
+		free(kvpp->val);
+	free(kvpp);
+}
+
+static time_t
+getFileCtime(char *path)
+{
+	struct stat statbuf;
+	if (stat(path, &statbuf) < 0)
+		return 0;
+	return statbuf.st_ctime;
+}
+
+
+char *
+findValueForKey(const kvp_t *kvps, const char *key)
+{
+	kvp_t *kvp;
+	int len;
+
+	if (kvps == NULL || key == NULL)
+		return NULL;
+	len = strlen(key);
+	if (len < 1 || len > MAX_KEY_LEN)
+		return NULL;
+	for(kvp = (kvp_t *)kvps; kvp != NULL; kvp = kvp->next) {
+		if (strncasecmp(key, kvp->key, len) == 0)
+			return kvp->val;
+	}
+	return NULL;
+}
+
+int
+isKeyValueTrue(const kvp_t *kvps, const char *key)
+{
+	char *val = findValueForKey(kvps, key);
+
+	if (val == NULL)
+		return 0;
+	if (strcasecmp(val, "TRUE") == 0)
+		return 1;
+	if (strcasecmp(val, "1") == 0)
+		return 1;
+	if (strcasecmp(val, "YES") == 0)
+		return 1;
+	if (strcasecmp(val, "ON") == 0)
+		return 1;
+	return 0;
+}

Propchange: branches/Solaris/src/auth.c
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/src/auth.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/auth.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/auth.h (added)
+++ branches/Solaris/src/auth.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,39 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2000-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * <NEED TO FIX KEYWORDS>
+ */
+
+
+#ifndef	__auth_h__
+#define	__auth_h__
+
+#include "clientcred.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int AUTHGetClientCreds(int, PCSCLITE_CRED_T *);
+
+int AUTHCheckDaemon(const char *facilityTag, PCSCLITE_CRED_T *cred,
+    const char *resource);
+
+int AUTHCheckIfd(const char *facilityTag, PCSCLITE_CRED_T *cred,
+    const char *ifdHandlerName, const char *resource);
+
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif
+
+#endif

Propchange: branches/Solaris/src/auth.h
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/src/cfgfuncs.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/cfgfuncs.c?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/cfgfuncs.c (added)
+++ branches/Solaris/src/cfgfuncs.c Thu Jun 12 10:28:09 2008
@@ -1,0 +1,933 @@
+ /*
+  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+  * Use is subject to license terms.
+  *
+  *  Paul Klissner <paul.klissner at sun.com>
+  *  Michael Bender <michael.bender at sun.com>
+  */
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "debuglog.h"
+#include "pcsclite.h"
+#include "pcsc_config.h"
+#include "sys_generic.h"
+#include "pcsclite.h"
+#include "config.h"
+
+
+#define LINEMAX         256
+#define KVMAXLEN        128
+
+#ifndef NONULL
+#define NONULL(a) (a) ? (a) : "<null>"
+#endif
+
+#define USE_SYSTEM_MKDIR
+
+void dbg(const char *, ...);
+void cfgitem(FILE *, char *, void *);
+
+int  validateInt(const char *, struct kvpValidation *);
+int  validateString(const char *, struct kvpValidation *);
+int  processKvp(const char *, const char *, int, int, char *);
+static char *retrofitPath(char *, char *, char *);
+
+
+/*
+ * Specifies the consumer of this configuration module
+ */
+void
+CFGSetConfigConsumer(int consumer) {
+	pcscCfg.consumer = consumer;
+}
+
+
+
+/*
+ * Load and parse configuration file into global array.
+ * If an error occurs, displays brief definitive message
+ * which includes filename and line number and aborts
+ * the daemon.
+ */
+int
+CFGLoadConfigFile(const char *cfgFile)
+{
+	FILE *fp = NULL;
+	char *cp, line[LINEMAX], temp[LINEMAX];
+	char key[KVMAXLEN], val[KVMAXLEN];
+	int i, j, rv, lineNbr;
+
+	if ((fp = fopen(cfgFile, "r")) == NULL)
+		return CFG_FILE_NOT_FOUND;
+
+	for (lineNbr = 1; fgets(temp, 256, fp) != NULL; ++lineNbr) {
+
+		memset(key,  0, sizeof (key));
+		memset(val,  0, sizeof (val));
+		memset(line, 0, sizeof(line));
+
+		if ((cp = strchr(temp, '\n')) != NULL)
+		    *cp = '\0';
+
+		if (strncmp(temp, "#", 1) == 0)  /* Discard comments */
+		       continue;
+
+		if ((cp = strchr(temp, '#')) != NULL) {
+		}
+		/* Get rid of whitespace and quote marks */
+		for (j = 0, i = 0; i < strlen(temp); i++)
+			if (temp[i] != ' ' && temp[i] != '\t' && temp[i] != '"')
+				line[j++] = temp[i];
+
+		/* Discard empty lines or lines with only whitespace */
+		if (j == 0)
+			continue;
+
+		/* Find '=' delimiter, error out if missing */
+		if ((cp = strchr(line, '=')) == NULL) {
+			Log3(PCSC_LOG_CRITICAL,
+			     "Missing delimiter in cfg file %s line %d\n",
+			     cfgFile, lineNbr);
+			fclose(fp);
+			return CFG_MISSING_DELIMITER;
+
+		} else
+			*cp = '\0';  /* Divide line into two strings */
+
+		/* Extract val */
+		if (cp >= line + strlen(line))
+			strcpy(val, cp + 1);
+
+		/* Extract key */
+		strcpy(key, line);
+
+
+		/* Parse value into it's respective variable */
+		rv = CFGProcessKvp(key, val, USER);
+		if (rv != CFG_SUCCESS) {
+			Log3(PCSC_LOG_CRITICAL,
+			     "Error in cfg file %s line %d\n",
+			     cfgFile, lineNbr);
+			fclose(fp);
+			return rv;
+		}
+	}
+	fclose(fp);
+	return CFG_SUCCESS;
+}
+
+
+/*
+ * Set command line option in the form of a KVP
+ */
+
+int
+CFGSetArg(const int opt, const char *key, const char *val,
+	  const int provider) {
+
+	if (CFGProcessKvp(key, val, ENGINE) != CFG_SUCCESS)
+		Log4(PCSC_LOG_CRITICAL,
+		     "Error setting cmdline arg: -%c, %s = %s",
+		     opt, NONULL(key), NONULL(val));
+
+       return CFG_SUCCESS;
+
+}
+
+/*
+ * Set a default value.  If error, log message and
+ * exit daemon.
+ */
+void
+CFGDefault(const char *key, const char *val)
+{
+	if (CFGProcessKvp(key, val, ENGINE) != CFG_SUCCESS)
+		 Log3(PCSC_LOG_CRITICAL,  "Error setting default: %s = %s",
+		      NONULL(key), NONULL(val));
+}
+
+/*
+ * Validate key / value pair according to the grammar rules
+ * parsing tables, storing literal or represented value in
+ * specified  target storage location.
+ */
+int
+CFGProcessKvp(const char *key, const char *val, const int provider)
+{
+	int i, j, rv;
+	static char env[LINEMAX];
+
+	if (key == NULL)
+		return (CFG_NULL_POINTER);
+	if (val == NULL)
+		return (CFG_NULL_POINTER);
+
+	/*
+	 * Allow environment variables to be set from conf file.
+	 * Keywords that begin with '$' are assumed to be
+	 * environment variables to be set for the process
+	 * that is loading the configuration file
+	 *
+	 * Example:
+	 *     $VAR = VAL
+	 * Sets the environment variable VAR to equal "VAL".
+	 */
+	 if (*key == '$') {
+		setenv(key + 1, val, 0);
+		return CFG_SUCCESS;
+	 }
+	 for (i = 0; i < sizeof (kvps) / sizeof (struct kvp); i++) {
+		if (strcasecmp(kvps[i].key, key) == 0) {
+		      /*
+		       * Client and server can share the same config
+		       * file ... this allows the client to ignore server parameters
+		       */
+		       if (pcscCfg.consumer == CLIENT &&
+			  (kvps[i].consumer != CLIENT &&
+			   kvps[i].consumer != MUTUAL)) {
+			      return CFG_SUCCESS;
+		       }
+
+		      /*
+		       * Ensure internal variables cannot be configured
+		       * from the command line or config file.
+		       */
+		      if (kvps[i].visibility == INTERN  && provider == USER)
+			      return CFG_DISALLOWED_PARAM;
+
+		      switch(kvps[i].type) {
+			/*
+			 * Find grammar constant named in value,
+			 * substitute in constant's equivalent integer
+			 * for storage in target location.
+			 */
+			 case _CONSTANT: {
+			      int *result = kvps[i].result;
+			      for (j = 0; !kvps[i].validation[j].eolFlag; j++) {
+				  if (strcasecmp(kvps[i].validation[j].key, val) == 0) {
+					*result = kvps[i].validation[j].constVal;
+					return CFG_SUCCESS;
+				  }
+			      }
+			      return CFG_UNRECOGNIZED_CONSTANT;
+			 }
+			 /*
+			  * Pass value through all range checks specified
+			  * in the grammar, storing validated value in
+			  * specified target location.
+			  */
+			 case _NUMERIC: {
+			       int v = atoi(val);
+			       int *result = kvps[i].result;
+			       rv = validateInt(val, kvps[i].validation);
+			       if (rv != CFG_SUCCESS)
+				       return rv;
+			       *result = (int)v;
+			       return CFG_SUCCESS;
+			 }
+			 /*
+			  * Validate the value as T/F, TRUE/FALSE, Y/N or
+			  * YES/NO and set the result to 1 or 0, accordingly
+			  */
+			 case _BOOLEAN: {
+				 int *result = kvps[i].result;
+				 if (strcmp(val, "T") == 0 ||
+				     strcmp(val, "TRUE") == 0 ||
+				     strcmp(val, "Y") == 0 ||
+				     strcmp(val, "YES") == 0) {
+					 *result = 1;
+					 return CFG_SUCCESS;
+				 }
+				 if (strcmp(val, "F") == 0 ||
+				     strcmp(val, "FALSE") == 0 ||
+				     strcmp(val, "N") == 0 ||
+				     strcmp(val, "NO") == 0) {
+					 *result = 0;
+					 return CFG_SUCCESS;
+				 }
+				 return CFG_UNRECOGNIZED_CONSTANT;
+			 }
+			 /*
+			  *
+			  * Duplicate the string, perform optional validation
+			  * processing on it and store pointer to new string
+			  * in specified result area.
+			  */
+			 case _STRING: {
+			      char **result = kvps[i].result;
+			      rv = validateString(
+				      (const char *)val, kvps[i].validation);
+			      if (rv != CFG_SUCCESS)
+				      return rv;
+			      *result = strdup(val);
+			      return CFG_SUCCESS;
+			 }
+		      default:
+			      return CFG_TABLE_ERROR;
+		      }
+		}
+	}
+	return CFG_UNRECOGNIZED_KEY;
+}
+
+
+/*
+ * Given an X Display string value in standard $DISPLAY format
+ * parse it's components into global configuration array.
+ *
+ * Return values:
+ *      SUCCESS
+ *      BAD_DISPLAY_VALUE
+ */
+int
+CFGParseXdisplay(char *display, int *dpyNbr, int *screenNbr, in_addr_t *xHostIp)
+{
+	int i, len, ipFlag = 0;
+	struct hostent *pHostEnt;
+	struct in_addr sia;
+	char token[MAXHOSTNAMELEN + 1];
+
+	*dpyNbr = -1;
+	*screenNbr = -1;
+	*xHostIp = -1;
+
+	if (display != NULL)  {
+		char *pDot = strrchr(display, '.');
+		char *pColon = strchr(display, ':');
+
+		if (pColon == NULL) {
+			return CFG_SYNTAX_ERROR;
+		} else {
+			/*
+			 * Extract Display and, if present sub-display numbers
+			 */
+			if (pDot != NULL && pDot > pColon) {
+				len = pDot - pColon - 1;
+				strncpy(token, pColon + 1, len);
+				token[len] = '\0';
+
+				for (i = 0; i < strlen(token); i++)
+					if (!isdigit(token[i]))
+						return CFG_BAD_DISPLAY_VALUE;
+
+				for (i = 0; i < strlen(pDot + 1); i++)
+					if (!isdigit(*(pDot + i + 1)))
+						return CFG_BAD_DISPLAY_VALUE;
+
+				*dpyNbr = atoi(token);
+				*screenNbr = atoi(pDot + 1);
+			} else {
+				for (i = 0; i < strlen(pColon + 1); i++)
+					if (!isdigit(*(pColon + i + 1)))
+					    return -1;
+				*dpyNbr = atoi(pColon + 1);
+				*screenNbr = 0;
+			}
+
+			if (*dpyNbr < 0 || *dpyNbr > 65535)
+				return CFG_BAD_DISPLAY_VALUE;
+
+			if (*screenNbr < 0 || *screenNbr > 65535)
+				return CFG_BAD_DISPLAY_VALUE;
+			/*
+			 * Extract and validate hostname, if any, if none
+			 * specified use "localhost"
+			 */
+			if ((len = pColon - display) == 0) {
+				strcpy(token, "localhost");
+			} else {
+				strncpy(token, display, len);
+				token[len] = '\0';
+			}
+			/*
+			 * Try to resolve the IP address
+			 *
+			 */
+			if ((sia.s_addr = inet_addr(token)) == (in_addr_t) -1) {
+				if ((pHostEnt = gethostbyname(token)) != NULL) {
+				       in_addr_t **iap =
+					   (in_addr_t **) pHostEnt->h_addr_list;
+				       sia = * (struct in_addr *) *iap;
+				       ipFlag = 1;
+				}
+			} else {
+				ipFlag = 1;
+			}
+			if (!ipFlag)
+				return CFG_BAD_DISPLAY_VALUE;
+			*xHostIp = sia.s_addr;
+		}
+		return CFG_SUCCESS;
+	}
+	return CFG_UNDEFINED_DISPLAY;
+}
+
+
+/*
+ * Wraps retrofitPath
+ */
+char *
+CFGRetrofitPath(char *inpath, char *relpath)
+{
+	return retrofitPath(pcscCfg.baseDir, inpath, relpath);
+}
+
+/*
+ * Conditionally substitutes another path to the base file indicated by
+ * inpath such that it becomes relative to basePath, using the following
+ * decision rules:
+ *
+ *   If basePath == NULL, return inpath unchanged
+ *   if inpath starts with "/" return inpath unchanged
+ *   If relpath == NULL, return <baspath>/<inpath>
+ *   If relpath != NULL, return path = <basepath>/<relpath>/<basename inpath>
+ *
+ * (Leading and trailing '/' characters on basedir and relpath are optional
+ *  and ignored)
+ *
+ * Side effects:
+ *      Caller must free() returned string.
+ */
+
+static char *
+retrofitPath(char *basePath, char *inpath, char *relpath)
+{
+	char *cp, *base, *rel, *tmp;
+	char newpath[LINEMAX];
+
+	if (basePath == NULL || inpath[0] == '/')
+		return inpath;
+
+	if (inpath == NULL || strlen(inpath) < 1 ||
+	    strlen(basePath) < 1 || *basePath != '/') {
+		return NULL;
+	}
+
+	/* Remove leading and trailing '/' characters */
+	base = strdup(basePath + strspn(basePath, "/"));
+
+	if (relpath == NULL) {
+		tmp = SYS_Dirname(inpath);
+		rel  = strdup(tmp + strspn(tmp, "/"));
+		free(tmp);
+	} else
+		rel  = strdup(relpath + strspn(relpath, "/"));
+
+	while ((cp = strrchr(base, '/')) == base + strlen(base) - 1)
+		*cp = '\0';
+
+	while ((cp = strrchr(rel, '/')) == rel + strlen(rel) - 1)
+		*cp = '\0';
+
+	/* Construct path from prepared components */
+	strcpy(newpath, "/");
+	strcat(newpath, base);
+	strcat(newpath, "/");
+	if (rel != NULL && *rel != '.' && *rel != '/') {
+		strcat(newpath, rel);
+		strcat(newpath, "/");
+	}
+	strcat(newpath, SYS_Basename(inpath));
+
+	free(base);
+	free(rel);
+	return (strdup(newpath));
+}
+
+int
+CFGDoesFileExist(char *path)
+{
+       struct stat statbuf;
+       if (SYS_Stat(path, &statbuf) < 0)
+	       return 0;
+       return 1;
+       }
+/*
+ * Create any missing directories in the *absolute* path specified.
+ * If the path is fully populated with existing
+ * directories, or null pointer or empty string is passed
+ * this function is effectively a NOP.
+ */
+int
+CFGEnsurePathExists(char *path)
+{
+#ifdef USE_SYSTEM_MKDIR
+	char buf[256];
+	sprintf(buf, "mkdir -p %s", path);
+	system(buf);
+#else
+	int mode = S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO;
+	char newpath[LINEMAX], *elem = 0, *wrk = 0;
+	struct stat statbuf;
+
+	if (path == NULL || strlen(path) == 0)
+		return CFG_SUCCESS;
+
+	bzero(newpath, LINEMAX);
+
+	wrk = strdup(path);
+
+	if ((elem = strtok(wrk, "/")) == NULL) {
+		free(wrk);
+		return;
+	}
+
+	do {
+		strcat(newpath, "/");
+		strcat(newpath, elem);
+		if (SYS_Stat(newpath, &statbuf) < 0) {
+			switch(errno) {
+			case ENOENT:
+				if (SYS_Mkdir(newpath, mode) < 0) {
+					free(wrk);
+					return CFG_DIR_CREATION_ERROR;
+				}
+				break;
+			default:
+				free(wrk);
+				return CFG_DIR_CREATION_ERROR;
+			}
+		}
+		elem = strtok(NULL, "/");
+	} while (elem != NULL);
+
+	free(wrk);
+#endif
+	return CFG_SUCCESS;
+}
+
+/*
+ * Remove path
+ */
+int
+CFGRmPath(char *path) {
+	if (path != NULL)
+		if (SYS_Unlink(path) != 0)
+			return CFG_CANNOT_REMOVE_PATH;
+	return CFG_SUCCESS;
+}
+
+
+/*
+ * Do dynamic substring replacement.
+ */
+char *
+CFGSubstitute(char *src, char *tag, char *repl) {
+	char buf[256];
+	char *cp;
+	bzero(buf, sizeof (buf));
+	strcpy(buf, src);
+	if (repl == NULL || (cp = strstr(buf, tag)) == NULL)
+		return (src);
+	*cp = '\0';
+	strcat(buf, repl);
+	cp = strstr(src, tag) + strlen(tag);
+	strcat(buf, cp);
+	return (strdup(buf));
+}
+/*
+ * Passed the address of a wildcarded configuration target variable,
+ * and value to replace wildcard with, update variable's wildcarded
+ * portion of contents with replacement value
+ */
+int
+CFGresolveWildcard(void *kvpTargAddr, void *v) {
+	int i, j;
+	char wrk[LINEMAX];
+	bzero(wrk, LINEMAX);
+	for (i = 0; i < sizeof (kvps) / sizeof (struct kvp); i++) {
+	    struct kvpValidation *validation;
+	    struct kvpValidation *validationList = kvps[i].validation;
+	    if (kvps[i].result == kvpTargAddr) {
+		    for (j = 0; !validationList[j].eolFlag; j++) {
+			 validation = &validationList[j];
+			 if (validation->process == PARSE_WILD) {
+				 switch(validation->option) {
+				 case _NUMERIC: {
+				      int  *result = (int *)kvpTargAddr;
+				      switch((int)validation->datum1) {
+				      case WILD_INCREMENT:
+					      *result += (int)v;
+					      break;
+				      case WILD_DECREMENT:
+					      *result -= (int)v;
+					      break;
+				      }
+				      return CFG_SUCCESS;
+				    }
+				 case _STRING: {
+				      char **result = (char **)kvpTargAddr;
+				      int offset  = (int)validation->datum1;
+				      int wildlen = (int)validation->datum2;
+				      char *sfxcp= *result + offset + wildlen;
+				      strncpy(wrk, *result, offset);
+				      strcat(wrk, (char *)v);
+				      strcat(wrk, sfxcp);
+				      *result = strdup(wrk);
+				      return CFG_SUCCESS;
+				    }
+				 }
+			 }
+		    }
+		    return CFG_TABLE_ERROR;
+	    }
+	}
+	return CFG_TABLE_ERROR;
+}
+
+/*
+ * Apply further validation checking/processing to the value
+ * based on validation options in parsing definition tables.
+ */
+int
+validateInt(const char *val, struct kvpValidation *validationList) {
+	struct kvpValidation *validation;
+	int j;
+	for (j = 0; !validationList[j].eolFlag; j++) {
+		validation = &validationList[j];
+		switch(validation->process) {
+		/*
+		 * Pre-process wildcard by locating token, and if present
+		 * require that a + or - be located to indicate if the
+		 * value substuted for the token is ultimately added
+		 * or subtracted from the original int.
+		 * It is not an error if the specified token isn't found in
+		 * the R.H.S. of the KVP (passed in as val), since the
+		 * validation list only indicates wildcarding is an option.
+		 */
+		case PARSE_WILD: {
+			char *tok = (char *)validation->arg2;
+			int *flg = (int *)validation->arg3;
+			if (strstr(val, tok) == NULL) /* allowed, not req'd */
+				return CFG_SUCCESS;
+			if (strchr(val, '+') != 0)
+				validation->datum1 = (void *)WILD_INCREMENT;
+			else if (strchr(val, '-') != 0)
+				validation->datum1 = (void *)WILD_DECREMENT;
+			else
+				return CFG_BAD_WILDCARD_OFFSET;
+			*flg = TRUE;
+			break;
+		  }
+		 case PARSE_RANGE: {
+			int v  = atoi(val);
+			int lo = atoi((char *)validation->arg1);
+			int hi = atoi((char *)validation->arg2);
+			if (v >= lo && v <= hi)
+				break;
+			return CFG_VALUE_OUT_OF_RANGE;
+		  }
+		 default:
+			return CFG_TABLE_ERROR;
+		 }
+	}
+	return CFG_SUCCESS;
+}
+
+/*
+ * Apply further validation checking/processing to the value
+ * based on validation options in parsing definition tables.
+ */
+int
+validateString(const char *val, struct kvpValidation *validationList)
+{
+	struct kvpValidation *validation;
+	struct stat statBuf;
+	int j;
+
+	for (j = 0; !validationList[j].eolFlag; j++) {
+
+		validation = &validationList[j];
+
+		switch(validation->process) {
+		/*
+		 * Pre-process wildcard by locating token, such as %X in
+		 * string argument, and save addr and loc of token for later
+		 * when token substitution occurs. It is not an error if the
+		 * specified token isn't found in the R.H.S. of the KVP
+		 * (passed in as val), since the validation list only indicates
+		 * wildcarding is an option.
+		 */
+		case PARSE_WILD: {
+			char *cp, *tok = (char *)validation->arg2;
+			int *flg = (int *)validation->arg3;
+			if ((cp = strstr(val, tok)) == NULL) /* Allowed not req'd */
+				return CFG_SUCCESS;
+			validation->datum1 = (void *)(cp - val); /* Stash offset */
+			validation->datum2 = (void *)strlen(tok); /* and length  */
+			*flg = TRUE;
+			return CFG_SUCCESS;
+		   }
+		case PARSE_PATH:
+			  switch(validation->option) {
+			  case PATH_OPTIONAL:
+				  break;
+
+			  case PATH_REQUIRED:
+				  return SYS_Stat((char *)val, &statBuf) < 0 ?
+				       CFG_INVALID_PATH : CFG_SUCCESS;
+
+			  case DIR_PATH_REQUIRED:
+				  return (SYS_Stat((char *)val, &statBuf) < 0 ||
+				      !(statBuf.st_mode & S_IFDIR)) ?
+				       CFG_INVALID_DIR_PATH : CFG_SUCCESS;
+
+			  case FILE_PATH_REQUIRED:
+				  return (SYS_Stat((char *)val, &statBuf) < 0 ||
+				      (statBuf.st_mode & S_IFDIR)) ?
+				       CFG_INVALID_FILE_PATH : CFG_SUCCESS;
+
+			  }
+			  break;
+		}
+	}
+	return CFG_SUCCESS;
+}
+
+void
+CFGperror(int errCode, char *msg) {
+	static char buf[256];
+	sprintf(buf, "%s: %s", msg, CFGErrText(errCode));
+	Log2(PCSC_LOG_ERROR, "%s", buf);
+}
+/*
+ * Check errCode. If no err is detected, do nothing,
+ * otherwise, log error along with file name and line #
+ */
+char *
+CFGErrText(int errCode)
+{
+	switch(errCode) {
+	case CFG_SUCCESS:
+		return "SUCCESS";
+
+	case CFG_SYNTAX_ERROR:
+		return "SYNTAX ERROR";
+
+	case CFG_UNRECOGNIZED_CONSTANT:
+		return "UNRECOCNIZED CONSTANT";
+
+	case CFG_TABLE_ERROR:
+		return "BAD INTERNAL CFG TABLES ";
+
+	case CFG_INTERNAL_ERROR:
+		return "INTERNAL ERROR";
+
+	case CFG_VALUE_OUT_OF_RANGE:
+		return "VALUE OUT OF RANGE";
+
+	case CFG_UNRECOGNIZED_KEY:
+		return "UNRECOGNIZED KEY";
+
+	case CFG_UNTERMINATED_QUOTE:
+		return "UNTERMINATED QUOTE";
+
+	case CFG_MISSING_DELIMITER:
+		return "MISSING DELIMITER";
+
+	case CFG_NON_INTEGER:
+		return "NON-INTEGER";
+
+	case CFG_OUT_OF_MEMORY:
+		return "OUT OF MEMORY";
+
+	case CFG_INVALID_PATH:
+		return "NON-EXISTANT/INACCESSIBLE PATH";
+
+	case CFG_INVALID_DIR_PATH:
+		return "NON-EXISTANT/INACCESSIBLE PATH, OR NOT DIRECTORY";
+
+	case CFG_INVALID_FILE_PATH:
+		return "NON-EXISTANT/INACCESSIBLE PATH, OR IS DIRECTORY";
+
+	case CFG_FILE_NOT_FOUND:
+		return "CANNOT OPEN FILE";
+
+	case CFG_FILE_CREATION_ERROR:
+		return "CANNOT CREATE FILE";
+
+	case CFG_DIR_CREATION_ERROR:
+		return "CANNOT CREATE DIR";
+
+	case CFG_CANNOT_REMOVE_PATH:
+		return "CANNOT REMOVE PATH";
+
+	case CFG_BAD_DISPLAY_VALUE:
+		return "ILLEGAL X DISPLAY VALUE";
+
+	case CFG_UNDEFINED_DISPLAY:
+		return "X DISPLAY UNDEFINED";
+
+	case CFG_NULL_POINTER:
+		return "NULL POINTER";
+
+	case CFG_ILLEGAL_OPTION:
+		return "ILLEGAL OPTION OR OPTION COMBINATION";
+
+	case CFG_UNDEFINED_PORT:
+		return "PORT NUMBER UNDEFINED";
+
+	case CFG_BAD_WILDCARD_OFFSET:
+		return "BAD NUMERIC WILDCARD OFFSET (+ or - req'd)";
+
+	case CFG_DISALLOWED_PARAM:
+		return "DISALLOWED PARAMEMTER";
+	}
+	return "UNKNOWN ERROR";
+}
+
+/*
+ * Do formatted dump of the global configuration struct
+ * and it's elements.
+ */
+void
+CFGdumpCfg(FILE *fp) {
+	cfgitem(fp, "launchMode............ ", &pcscCfg.launchMode);
+	cfgitem(fp, "logLevel ............. ", &pcscCfg.logLevel);
+	cfgitem(fp, "logType .............. ", &pcscCfg.logType);
+	cfgitem(fp, "logFile .............. ", &pcscCfg.logFile);
+	cfgitem(fp, "baseDir .............. ", &pcscCfg.baseDir);
+	cfgitem(fp, "instanceScript........ ", &pcscCfg.instanceScript);
+	cfgitem(fp, "ifdPluginDir ......... ", &pcscCfg.ifdPluginDir);
+	cfgitem(fp, "pcscdPIDFile ......... ", &pcscCfg.pcscdPIDFile);
+	cfgitem(fp, "pcscConfigFile........ ", &pcscCfg.pcscConfigFile);
+	cfgitem(fp, "readerConfigFile...... ", &pcscCfg.readerConfigFile);
+	cfgitem(fp, "netBindFile .......... ", &pcscCfg.netBindFile);
+	cfgitem(fp, "pcscdMemMappedFile.... ", &pcscCfg.pcscdMemMappedFile);
+	cfgitem(fp, "argv0 ................ ", &pcscCfg.argv0);
+	cfgitem(fp, "transportType ........ ", &pcscCfg.transportType);
+	cfgitem(fp, "portNbr .............. ", &pcscCfg.portNbr);
+	cfgitem(fp, "dpyNbr ............... ", &pcscCfg.dpyNbr);
+	cfgitem(fp, "screenNbr ............ ", &pcscCfg.screenNbr);
+	cfgitem(fp, "xHostIp .............. ", &pcscCfg.xHostIp);
+	cfgitem(fp, "useMappedMemory....... ", &pcscCfg.useMappedMemory);
+	cfgitem(fp, "runInForeground ...... ", &pcscCfg.runInForeground);
+	cfgitem(fp, "apduDebug ............ ", &pcscCfg.apduDebug);
+	cfgitem(fp, "verbose .............. ", &pcscCfg.verbose);
+	cfgitem(fp, "portNbrWild .......... ", &pcscCfg.portNbrWild);
+	cfgitem(fp, "baseDirWild .......... ", &pcscCfg.baseDirWild);
+	cfgitem(fp, "useAuthentication..... ", &pcscCfg.useAuthentication);
+	cfgitem(fp, "instanceTimeout ...... ", &pcscCfg.instanceTimeout);
+	cfgitem(fp, "statusPollRate ....... ", &pcscCfg.statusPollRate);
+	cfgitem(fp, "fifoPingTimeout ...... ", &pcscCfg.fifoPingTimeout);
+	cfgitem(fp, "relaunchThreshold .... ", &pcscCfg.relaunchThreshold);
+	cfgitem(fp, "relaunchInterval ..... ", &pcscCfg.relaunchInterval);
+}
+
+/*
+ * Given the address of a variable in the global configuration
+ * array, represent it's value optimally according to the type of parameter
+ */
+void
+cfgitem(FILE *fp, char *desc, void *v) {
+	static char buf[256];
+	int i, j;
+
+	bzero(buf, sizeof (buf));
+
+	if (desc == NULL || v == NULL) {
+		if (fp == NULL)
+			Log1(PCSC_LOG_DEBUG, "");
+		else
+			fprintf(fp, "\n");
+		return;
+	}
+
+	for (i = 0; i < sizeof (kvps) / sizeof (struct kvp); i++) {
+		struct kvpValidation *validated = kvps[i].validation;
+		if (kvps[i].result == v) {
+			if (pcscCfg.consumer == CLIENT) {
+				if (kvps[i].consumer != CLIENT &&
+				    kvps[i].consumer != MUTUAL)
+					return;
+			}
+			switch(kvps[i].type) {
+			case _CONSTANT:
+				for (j = 0; !validated[j].eolFlag; j++)
+					if (validated[j].constVal == *(int *)v)
+					     sprintf(buf, "%s%s",
+						  desc, validated[j].key);
+				break;
+			case _BOOLEAN:
+				sprintf(buf, "%s%s",
+				     desc, *(int *)v ? "TRUE" : "FALSE");
+				break;
+			case _NUMERIC:
+				sprintf(buf, "%s%d", desc, *(int *)v);
+				break;
+			case _STRING:
+				sprintf(buf, "%s%s", desc, NONULL(*(char **)v));
+				break;
+			case _IPADDR:
+				sprintf(buf, "%s%s",
+				    desc, inet_ntoa(*(struct in_addr *)v));
+				break;
+			default:
+				sprintf(buf, "BAD TYPE: %s", desc);
+				break;
+			}
+			if (fp == NULL)
+				Log2(PCSC_LOG_DEBUG, "%s", buf);
+			else
+				fprintf(fp, "%s\n", buf);
+			return;
+		}
+	}
+}
+
+
+/*
+ * Given the address of a variable in the global configuration
+ * array, represent it's value optimally according to the type of parameter
+ */
+char *
+CFGListConstants(void *v)
+{
+	static char buf[LINEMAX];
+
+	int i, j;
+
+	if (v == NULL)
+		return "";
+
+	bzero(buf, sizeof (buf));
+
+	for (i = 0; i < sizeof (kvps) / sizeof (struct kvp); i++) {
+		struct kvpValidation *validated = kvps[i].validation;
+		if (kvps[i].result == v) {
+			switch(kvps[i].type) {
+			case _CONSTANT:
+				for (j = 0; !validated[j].eolFlag; j++) {
+					if (j > 0)
+						strcat(buf, ",");
+					strcat(buf, validated[j].key);
+				}
+				break;
+			case _BOOLEAN:
+				strcat(buf, "TRUE,FALSE");
+				break;
+			}
+
+		}
+	}
+	return strdup(buf);
+}
+
+

Added: branches/Solaris/src/configfile.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/configfile.c?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/configfile.c (added)
+++ branches/Solaris/src/configfile.c Thu Jun 12 10:28:09 2008
@@ -1,0 +1,1799 @@
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ * 	if ( condition_holds )
+ *		yyless( 5 );
+ *	else
+ *		do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		*yy_cp = yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+	};
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yytext_ptr = yy_bp; \
+	yyleng = (int) (yy_cp - yy_bp); \
+	yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 7
+#define YY_END_OF_BUFFER 8
+static yyconst short int yy_accept[17] =
+    {   0,
+        0,    0,    8,    6,    4,    2,    6,    1,    6,    5,
+        0,    3,    1,    0,    5,    0
+    } ;
+
+static yyconst int yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    5,    1,    1,    1,    6,    1,
+        1,    1,    1,    1,    7,    7,    7,    8,    8,    8,
+        8,    8,    8,    8,    8,    8,    8,    7,    1,    1,
+        1,    1,    1,    7,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        9,    9,    9,    9,    9,    9,    9,    9,    9,    9,
+        1,    7,    1,    1,    7,    1,   10,   10,   10,   10,
+
+       10,   10,   10,   10,   10,   10,   10,   10,   10,   10,
+       10,   10,   10,   10,   10,   10,   10,   10,   10,   10,
+       10,   10,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst int yy_meta[11] =
+    {   0,
+        1,    1,    2,    1,    1,    1,    1,    1,    1,    1
+    } ;
+
+static yyconst short int yy_base[20] =
+    {   0,
+        0,    0,   15,   31,   31,   31,    8,    0,   10,   10,
+       18,   31,    0,   20,    0,   31,   26,   13,   28
+    } ;
+
+static yyconst short int yy_def[20] =
+    {   0,
+       16,    1,   16,   16,   16,   16,   17,   18,   19,   16,
+       17,   16,   18,   19,   10,    0,   16,   16,   16
+    } ;
+
+static yyconst short int yy_nxt[42] =
+    {   0,
+        4,    5,    6,    7,    8,    9,   10,   10,   10,   10,
+       12,   12,   12,   13,   16,   12,   15,   15,   15,   15,
+       12,   12,   12,   16,   16,   12,   11,   11,   14,   14,
+        3,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16
+    } ;
+
+static yyconst short int yy_chk[42] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        7,    7,    9,   18,    3,    9,   10,   10,   10,   10,
+       11,   11,   14,    0,    0,   14,   17,   17,   19,   19,
+       16,   16,   16,   16,   16,   16,   16,   16,   16,   16,
+       16
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "configfile.l"
+#define INITIAL 0
+/*
+ * Reads lexical config files and updates database.
+ *
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 1999-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *
+ * $Id: configfile.l 2114 2006-07-31 13:28:50Z rousseau $
+ */
+#line 15 "configfile.l"
+#include "wintypes.h"
+#include "readerfactory.h"
+#include "configfile.h"
+
+
+int evaluatetoken(char *pcToken);
+
+static int iLinenumber;
+static char *pcPrevious;
+static char *pcCurrent;
+static char *pcFriendlyname;
+static char *pcDevicename;                
+static char *pcAuthSvcName;
+static char *pcLibpath;
+static char *pcChannelid;
+static int badError;
+static SerialReader *reader_list;
+static int reader_list_size;
+
+void tok_error(char *pcToken_error);
+
+#define YY_NO_UNPUT 1
+#line 412 "configfile.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( yy_current_buffer->yy_is_interactive ) \
+		{ \
+		int c = '*', n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+		  && ferror( yyin ) ) \
+		YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+YY_DECL
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+
+#line 41 "configfile.l"
+
+
+#line 566 "configfile.c"
+
+	if ( yy_init )
+		{
+		yy_init = 0;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yy_start )
+			yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! yy_current_buffer )
+			yy_current_buffer =
+				yy_create_buffer( yyin, YY_BUF_SIZE );
+
+		yy_load_buffer_state();
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yy_start;
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				yy_last_accepting_state = yy_current_state;
+				yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 17 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 31 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = yy_last_accepting_cpos;
+			yy_current_state = yy_last_accepting_state;
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+
+do_action:	/* This label is used only to access EOF actions. */
+
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yy_hold_char;
+			yy_cp = yy_last_accepting_cpos;
+			yy_current_state = yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 43 "configfile.l"
+{}
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 44 "configfile.l"
+{ iLinenumber++; }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 45 "configfile.l"
+{ evaluatetoken( yytext); } 
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 46 "configfile.l"
+{}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 47 "configfile.l"
+{ evaluatetoken( yytext ); } 
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 48 "configfile.l"
+{ tok_error( yytext ); }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 49 "configfile.l"
+ECHO;
+	YY_BREAK
+#line 684 "configfile.c"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between yy_current_buffer and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yy_n_chars = yy_current_buffer->yy_n_chars;
+			yy_current_buffer->yy_input_file = yyin;
+			yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state();
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yy_c_buf_p;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer() )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yy_did_buffer_switch_on_eof = 0;
+
+				if ( yywrap() )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yy_c_buf_p =
+					yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yy_c_buf_p =
+				&yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+	} /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+	{
+	register char *dest = yy_current_buffer->yy_ch_buf;
+	register char *source = yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( yy_current_buffer->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+	else
+		{
+		int num_to_read =
+			yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+			YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = yy_current_buffer;
+
+			int yy_c_buf_p_offset =
+				(int) (yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yy_flex_realloc( (void *) b->yy_ch_buf,
+							 b->yy_buf_size + 2 );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = yy_current_buffer->yy_buf_size -
+						number_to_move - 1;
+#endif
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+			yy_n_chars, num_to_read );
+
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	if ( yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart( yyin );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			yy_current_buffer->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	yy_n_chars += number_to_move;
+	yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+	return ret_val;
+	}
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+
+	yy_current_state = yy_start;
+
+	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yy_last_accepting_state = yy_current_state;
+			yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 17 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+	}
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+	{
+	register int yy_is_jam;
+	register char *yy_cp = yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yy_last_accepting_state = yy_current_state;
+		yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 17 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 16);
+
+	return yy_is_jam ? 0 : yy_current_state;
+	}
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+	{
+	register char *yy_cp = yy_c_buf_p;
+
+	/* undo effects of setting up yytext */
+	*yy_cp = yy_hold_char;
+
+	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = yy_n_chars + 2;
+		register char *dest = &yy_current_buffer->yy_ch_buf[
+					yy_current_buffer->yy_buf_size + 2];
+		register char *source =
+				&yy_current_buffer->yy_ch_buf[number_to_move];
+
+		while ( source > yy_current_buffer->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		yy_current_buffer->yy_n_chars =
+			yy_n_chars = yy_current_buffer->yy_buf_size;
+
+		if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+
+	yytext_ptr = yy_bp;
+	yy_hold_char = *yy_cp;
+	yy_c_buf_p = yy_cp;
+	}
+#endif	/* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+	{
+	int c;
+
+	*yy_c_buf_p = yy_hold_char;
+
+	if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			/* This was really a NUL. */
+			*yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yy_c_buf_p - yytext_ptr;
+			++yy_c_buf_p;
+
+			switch ( yy_get_next_buffer() )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart( yyin );
+
+					/* fall through */
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap() )
+						return EOF;
+
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yy_c_buf_p = yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yy_c_buf_p;	/* cast for 8-bit char's */
+	*yy_c_buf_p = '\0';	/* preserve yytext */
+	yy_hold_char = *++yy_c_buf_p;
+
+
+	return c;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+	{
+	if ( ! yy_current_buffer )
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+	yy_init_buffer( yy_current_buffer, input_file );
+	yy_load_buffer_state();
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+	{
+	if ( yy_current_buffer == new_buffer )
+		return;
+
+	if ( yy_current_buffer )
+		{
+		/* Flush out information for old buffer. */
+		*yy_c_buf_p = yy_hold_char;
+		yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	yy_current_buffer = new_buffer;
+	yy_load_buffer_state();
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yy_did_buffer_switch_on_eof = 1;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+	{
+	yy_n_chars = yy_current_buffer->yy_n_chars;
+	yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+	yyin = yy_current_buffer->yy_input_file;
+	yy_hold_char = *yy_c_buf_p;
+	}
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer( b, file );
+
+	return b;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+	{
+	if ( ! b )
+		return;
+
+	if ( b == yy_current_buffer )
+		yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yy_flex_free( (void *) b->yy_ch_buf );
+
+	yy_flex_free( (void *) b );
+	}
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+	{
+	yy_flush_buffer( b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+	b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+	b->yy_is_interactive = 0;
+#else
+	b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+	{
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == yy_current_buffer )
+		yy_load_buffer_state();
+	}
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer( b );
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+	{
+	int len;
+	for ( len = 0; yy_str[len]; ++len )
+		;
+
+	return yy_scan_bytes( yy_str, len );
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+	{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = len + 2;
+	buf = (char *) yy_flex_alloc( n );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < len; ++i )
+		buf[i] = bytes[i];
+
+	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer( buf, n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+	{
+	if ( yy_start_stack_ptr >= yy_start_stack_depth )
+		{
+		yy_size_t new_size;
+
+		yy_start_stack_depth += YY_START_STACK_INCR;
+		new_size = yy_start_stack_depth * sizeof( int );
+
+		if ( ! yy_start_stack )
+			yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+		else
+			yy_start_stack = (int *) yy_flex_realloc(
+					(void *) yy_start_stack, new_size );
+
+		if ( ! yy_start_stack )
+			YY_FATAL_ERROR(
+			"out of memory expanding start-condition stack" );
+		}
+
+	yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+	BEGIN(new_state);
+	}
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+	{
+	if ( --yy_start_stack_ptr < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(yy_start_stack[yy_start_stack_ptr]);
+	}
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+	{
+	return yy_start_stack[yy_start_stack_ptr - 1];
+	}
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+	{
+	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+	}
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		yytext[yyleng] = yy_hold_char; \
+		yy_c_buf_p = yytext + n; \
+		yy_hold_char = *yy_c_buf_p; \
+		*yy_c_buf_p = '\0'; \
+		yyleng = n; \
+		} \
+	while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+	{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+	}
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+	{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+	}
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+	{
+	return (void *) malloc( size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+	{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+	{
+	free( ptr );
+	}
+
+#if YY_MAIN
+int main()
+	{
+	yylex();
+	return 0;
+	}
+#endif
+#line 49 "configfile.l"
+
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "misc.h"
+#include "pcsclite.h"
+#include "debuglog.h"
+#include "config.h"
+#include "sys_generic.h"
+#include "readerfactory.h"
+
+int evaluatetoken(char *pcToken)
+{
+
+	DWORD dwChannelId = 0;
+	int p = 0;
+	int n = 0;
+
+	if (pcPrevious == NULL)
+	{							/* This is the key */
+		pcPrevious = strdup(pcToken);
+	}
+	else
+	{
+		pcCurrent = pcToken;
+		if (strcmp(pcPrevious, "FRIENDLYNAME") == 0)
+		{
+			if (pcFriendlyname == NULL)
+			{
+				pcFriendlyname = malloc(strlen(pcCurrent) - 1);
+				for (n = 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, ':'))
+					&& (SYS_Stat(pcDevicename, &fStatBuf) != 0))
+				{
+					Log3(PCSC_LOG_CRITICAL, "Error with device %s: %s",
+						pcDevicename, strerror(errno));
+					Log1(PCSC_LOG_CRITICAL, "You should use 'DEVICENAME /dev/null' if your driver does not use this field");
+					badError = 1;
+				}
+			}
+			else
+			{
+				tok_error(pcPrevious);
+				return 1;
+			}
+		}
+		else if (strcmp(pcPrevious, "AUTHSERVICE") == 0)
+		{
+			if (pcAuthSvcName == NULL)
+			{
+                                if (strlen(pcCurrent) > 255) {
+                                        Log2(PCSC_LOG_CRITICAL, 
+                                             "ERROR: AUTH Service Name > 255 chars: %s\n", 
+                                                pcCurrent);
+				        badError = 1;
+                                }
+                                pcAuthSvcName = malloc(strlen(pcCurrent) - 1);
+				for (n = 0; n < strlen(pcCurrent); n++)
+				{
+					if (pcCurrent[n] != '"')
+					{			/* Strip off the quotes */
+						pcAuthSvcName[p++] = pcCurrent[n];
+					}
+				}
+				pcAuthSvcName[p++] = '\0';
+			}
+			else
+			{
+				tok_error(pcPrevious);
+				return 1;
+			}
+		}
+		else if (strcmp(pcPrevious, "LIBPATH") == 0)
+		{
+			if (pcLibpath == NULL)
+			{
+				struct stat fStatBuf;
+
+				pcLibpath = strdup(pcCurrent);
+				if (strcmp(SYS_Dirname(pcLibpath), ".") != 0 &&
+                                     SYS_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);
+			return 1;
+		}
+
+		free(pcPrevious);
+		pcPrevious = NULL;
+	}
+
+	if (pcFriendlyname != NULL && pcDevicename != NULL &&
+		pcLibpath != NULL &&  pcAuthSvcName != NULL && badError != 1)
+	{
+		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;
+
+		dwChannelId = 0;
+		if (pcChannelid != NULL)
+			dwChannelId = strtoul(pcChannelid, 0, 16);
+		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].pcAuthSvcName = strdup(pcAuthSvcName);
+		reader_list[reader_list_size-2].dwChannelId = dwChannelId;
+
+		pcFriendlyname = NULL;
+		pcDevicename = NULL;
+		pcLibpath = NULL;
+		pcChannelid = NULL;
+                pcAuthSvcName = NULL;
+	}
+
+	return 0;
+}
+
+void tok_error(char *token_error)
+{
+	Log2(PCSC_LOG_ERROR, "tok_error: invalid value in reader.conf: %s",
+		token_error);
+	badError = 1;
+}
+
+int DBGetReaderList(char *readerconf, SerialReader **caller_reader_list)
+{
+	FILE *configFile = NULL;
+
+	*caller_reader_list = NULL;	/* no list by default */
+
+	configFile = fopen(readerconf, "r");
+
+	if (configFile == NULL)
+		return 1;
+
+	yyin = configFile;
+
+	/* (re)start with a clean state */
+	iLinenumber = 1;
+	reader_list = NULL;
+	reader_list_size = 0;
+	pcFriendlyname = NULL;
+	pcDevicename = NULL;
+	pcLibpath = NULL;
+        pcAuthSvcName = NULL;
+	pcChannelid = NULL;
+	pcPrevious = NULL;
+	pcCurrent = NULL;
+	badError = 0;
+
+	do
+	{
+		yylex();
+	}
+	while (!feof(configFile));
+
+	fclose(configFile);
+
+	*caller_reader_list = reader_list;
+
+	if (badError == 1)
+		return -1;
+	else
+		return 0;
+}								/* End of configfile.c */
+

Propchange: branches/Solaris/src/configfile.c
------------------------------------------------------------------------------
    svn:executable = *

Modified: branches/Solaris/src/configfile.l
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/configfile.l?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/configfile.l (original)
+++ branches/Solaris/src/configfile.l Thu Jun 12 10:28:09 2008
@@ -16,6 +16,7 @@
 #include "readerfactory.h"
 #include "configfile.h"
 
+
 int evaluatetoken(char *pcToken);
 
 static int iLinenumber;
@@ -23,6 +24,7 @@
 static char *pcCurrent;
 static char *pcFriendlyname;
 static char *pcDevicename;                
+static char *pcAuthSvcName;
 static char *pcLibpath;
 static char *pcChannelid;
 static int badError;
@@ -113,6 +115,32 @@
 				return 1;
 			}
 		}
+		else if (strcmp(pcPrevious, "AUTHSERVICE") == 0)
+		{
+			if (pcAuthSvcName == NULL)
+			{
+                                if (strlen(pcCurrent) > 255) {
+                                        Log2(PCSC_LOG_CRITICAL, 
+                                             "ERROR: AUTH Service Name > 255 chars: %s\n", 
+                                                pcCurrent);
+				        badError = 1;
+                                }
+                                pcAuthSvcName = malloc(strlen(pcCurrent) - 1);
+				for (n = 0; n < strlen(pcCurrent); n++)
+				{
+					if (pcCurrent[n] != '"')
+					{			/* Strip off the quotes */
+						pcAuthSvcName[p++] = pcCurrent[n];
+					}
+				}
+				pcAuthSvcName[p++] = '\0';
+			}
+			else
+			{
+				tok_error(pcPrevious);
+				return 1;
+			}
+		}
 		else if (strcmp(pcPrevious, "LIBPATH") == 0)
 		{
 			if (pcLibpath == NULL)
@@ -120,7 +148,8 @@
 				struct stat fStatBuf;
 
 				pcLibpath = strdup(pcCurrent);
-				if (SYS_Stat(pcLibpath, &fStatBuf) != 0)
+				if (strcmp(SYS_Dirname(pcLibpath), ".") != 0 &&
+                                     SYS_Stat(pcLibpath, &fStatBuf) != 0)
 				{
 					Log3(PCSC_LOG_CRITICAL, "Error with library %s: %s",
 						pcLibpath, strerror(errno));
@@ -161,7 +190,7 @@
 	}
 
 	if (pcFriendlyname != NULL && pcDevicename != NULL &&
-		pcLibpath != NULL && pcChannelid != NULL && badError != 1)
+		pcLibpath != NULL &&  pcAuthSvcName != NULL && badError != 1)
 	{
 		if (0 == reader_list_size)
 		{
@@ -179,16 +208,20 @@
 		/* end marker */
 		reader_list[reader_list_size-1].pcFriendlyname = NULL;
 
-		dwChannelId = strtoul(pcChannelid, 0, 16);
+		dwChannelId = 0;
+		if (pcChannelid != NULL)
+			dwChannelId = strtoul(pcChannelid, 0, 16);
 		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].pcAuthSvcName = strdup(pcAuthSvcName);
 		reader_list[reader_list_size-2].dwChannelId = dwChannelId;
 
 		pcFriendlyname = NULL;
 		pcDevicename = NULL;
 		pcLibpath = NULL;
 		pcChannelid = NULL;
+                pcAuthSvcName = NULL;
 	}
 
 	return 0;
@@ -221,6 +254,7 @@
 	pcFriendlyname = NULL;
 	pcDevicename = NULL;
 	pcLibpath = NULL;
+        pcAuthSvcName = NULL;
 	pcChannelid = NULL;
 	pcPrevious = NULL;
 	pcCurrent = NULL;

Added: branches/Solaris/src/daemon_utils.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/daemon_utils.c?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/daemon_utils.c (added)
+++ branches/Solaris/src/daemon_utils.c Thu Jun 12 10:28:09 2008
@@ -1,0 +1,602 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ */
+
+#include "config.h"
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stropts.h>
+#include <syslog.h>
+#include <ucred.h>
+#include <unistd.h>
+#include <wait.h>
+#include <syslog.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/conf.h>
+#include <sys/filio.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <libgen.h>
+#include <thread.h>
+#include <syslog.h>
+#include <sys/time.h>
+
+#include "pcsc_config.h"
+#include "validate.h"
+#include "daemon_utils.h"
+#include "launcher.h"
+#include "instance.h"
+#include "pcsclite.h"
+#include "debuglog.h"
+#include <sys/socket.h>
+
+#define LINEMAX	256
+#define NONULL(a) (a) ? (a) : "<null>"
+
+int instanceTotalFdsReceived = 0;
+static int isPrefixed(char *, char *);
+
+int
+GetPidFromFile(int dpyNbr)
+{
+	char pidPath[256], pidbuf[10];
+	FILE *pidFile;
+	int pid;
+	sprintf(pidPath, "%s/pid/%d", pcscCfg.baseDir, dpyNbr);
+	if ((pidFile = fopen(pidPath, "r")) == NULL) {
+// This needs to be silent
+//		Log3(PCSC_LOG_DEBUG,
+//			"GetPidFromFile:  Error opening %s: %s",
+//			pidPath, strerror(errno));
+
+		return 0;
+	}
+	setvbuf(pidFile, pidbuf, _IONBF, sizeof (pidbuf));
+	fgets(pidbuf, sizeof (pidbuf), pidFile);
+	fclose(pidFile);
+	return atoi(pidbuf);
+}
+void
+DeletePidFile(int dpyNbr)
+{
+	char pidPath[256];
+	sprintf(pidPath, "%s/pid/%d", pcscCfg.baseDir, dpyNbr);
+	unlink(pidPath);
+}
+
+
+int
+StopInstance(int dpyNbr, int pid)
+{
+#define RETRY_MAX 20
+	char fifoPath[256], cmd[256], *cfg, *inst;
+	int instanceOutFifo, fpid, r = 0, cnt = 0;
+	int instanceTerminated = 0;
+	struct sigaction action;
+
+	/*
+	 * If pid is 0 we look up the pid for the specified
+	 * display's instance in the pid directory and
+	 */
+	if (pid == 0) {
+		sprintf(fifoPath,"%s/fifo/%d.i",
+		    pcscCfg.baseDir, dpyNbr);
+
+		if ((fpid = GetPidFromFile(dpyNbr)) != 0) {
+			Log3(PCSC_LOG_DEBUG, "Terminating instance :%d, pid=%d",
+				dpyNbr, fpid);
+
+			if ((instanceOutFifo = open(fifoPath, O_RDWR)) >= 0)
+				 SendCmd(instanceOutFifo, INSTANCE_DIED_TOKEN);
+			 /*
+			  * Be *sure* it's gone
+			  */
+			while (kill(fpid, SIGKILL) == 0 && ++cnt < 100) {
+				instanceTerminated = 1;
+				usleep(250000);
+			}
+
+			DeletePidFile(dpyNbr);
+		} else {
+			Log2(PCSC_LOG_INFO, "Can't stop instance :%d "
+			    "(Couldn't find PID file)", dpyNbr);
+			return;
+
+		}
+	} else {
+		char buf[LINEMAX], dpy[10];
+		FILE *fp;
+
+		/*
+		 * On the very slim chance that the pid's have cycled
+		 * and been re-used, make sure we're terminating a pcscd
+		 * process targetted for the originally named display.
+		 * This makes the chance of terminating the wrong program
+		 * impossible, and the chances of terminating the wrong
+		 * pcscd instance astronomically slim.
+		 *
+		 * Some day this should be improved to make it impossible
+		 * to ever fail under any circumstances.
+		 */
+		sprintf(cmd, "pargs -l %d", pid);
+		if ((fp = popen(cmd , "r")) == NULL ||
+		     fgets(buf, LINEMAX, fp) == NULL)
+				return -1;
+		pclose(fp);
+
+		sprintf(dpy, ":%d", dpyNbr);
+		if (strncmp(buf, pcscCfg.argv0, strlen(pcscCfg.argv0)) != 0 ||
+		    strstr(buf, dpy) == NULL) {
+			fprintf(stderr, "Error: Process args don't match.\n");
+			pid = 0;
+		} else {
+			Log3(PCSC_LOG_DEBUG,
+				"Terminating instance :%d, pid=%d", dpyNbr, pid);
+			while (kill(pid, SIGKILL) == 0 && ++cnt < 100) {
+				instanceTerminated = 1;
+				usleep(250000);
+			}
+
+			DeletePidFile(dpyNbr);
+		}
+	}
+
+	/*
+	 * Do per platform specific instance clean up if a process was terminated.
+	 */
+		 if (VALfindInstanceFiles(dpyNbr, &cfg, &inst) == 0) {
+			bzero(cmd, sizeof(cmd));
+			sprintf(cmd, "%s -m STOP -x :%d -P %s -b %s -p %d",
+				inst, dpyNbr, cfg, pcscCfg.baseDir, pid);
+			if (system(cmd) < 0)
+				Log3(PCSC_LOG_CRITICAL,
+				    "system(\"%s\") failed: %s", cmd, strerror(errno));
+
+			free(cfg);
+
+			free(inst);
+		}
+	return pid;
+}
+
+/*
+ * Receive file descriptor from parent process
+ * If we can an fd, we cancel self-termination timer.
+ */
+int
+ReceiveClientFd(int inFifo, int outFifo, int *receivedFd, int timeout) {
+	char rcvbuf[LINEMAX];
+	struct strrecvfd fdDescr;
+	int rv, len;
+
+	Log1(PCSC_LOG_DEBUG, "ReceiveClientFd()....");
+	bzero(rcvbuf, sizeof (rcvbuf));
+	/*
+	 * Receive fd from fifo
+	 */
+	if ((rv = ioctl(inFifo, I_RECVFD, &fdDescr)) < 0) {
+		if (pcscCfg.pcscdExiting)
+			return TERMINATED;
+		if (errno == EBADMSG) {
+		       Log3(PCSC_LOG_DEBUG,
+			   "ReceiveClientFd(i:%d, o:%d): Non-FD msg from fifo",
+			   inFifo, outFifo);
+		       /*
+			* Receive non-FD message
+			*/
+		       len = sizeof (rcvbuf);
+		       rv = DoFifoReceive(inFifo, rcvbuf, len,
+			    pcscCfg.fifoPingTimeout);
+		       if (rv < 0)
+			       return rv;
+
+		       return (DoFifoCmd(outFifo, rcvbuf));
+		}
+	}
+	if (pcscCfg.pcscdExiting)
+		return TERMINATED;
+
+	Log3(PCSC_LOG_DEBUG,
+	    "RECV# %d: Received fd=%d", ++instanceTotalFdsReceived, fdDescr.fd);
+
+	/*
+	 * Cancel self-termination timer before we ACK
+	 */
+	LockContextLookup();
+	CancelInstanceTimer();
+
+	/*
+	 * unlocked after context thread created
+	 */
+	if (SendCmd(outFifo, FIFO_FD_ACK) < 0) {
+		Log4(PCSC_LOG_CRITICAL,
+			"ReceiveClientFd(i:%d, o:%d) "
+			"Err writing ACK to fifo: %s",
+			inFifo, outFifo, strerror(errno));
+		return -1;
+
+	}
+	*receivedFd = fdDescr.fd;
+	return SUCCESS;
+}
+
+/**
+ * @brief Send ping message to out-fifo, expect in-fifo response
+ *
+ * The two fifo mechanism is a speed (performance) optimization.
+ * It allows us to avoid the problem wherein if we used a single
+ * fifo and send a 'ping' message, if we read back from the fifo
+ * too soon (before receiver gets it), we'll REMOVE the message
+ * from the fifo before the other side can read it.
+ * To avoid that we'd have to wait a min. amount of time,
+ * which means that we introduce an unnecessary delay
+ * if the other side happens to be really fast with the response.
+ */
+int
+PingFifo(int outFifo, int inFifo, int timeout) {
+	char rcvbuf[LINEMAX];
+	int len, pid;
+
+	if (SendCmd(outFifo, FIFO_PING_CMD) < 0) {
+		Log3(PCSC_LOG_ERROR, "<%4.4x> PingFifo(outfd=%d) Err sending",
+		    thr_self(), outFifo);
+		return ERROR;
+	}
+	len = sizeof (rcvbuf);
+	switch(DoFifoReceive(inFifo, rcvbuf, len, timeout)) {
+	case ERROR:
+		Log3(PCSC_LOG_ERROR,
+		    "<%4.4x> PingFifo(outfd=%d): Err receiving",
+		    thr_self(), outFifo);
+		return ERROR;
+	case TIMEOUT:
+		Log3(PCSC_LOG_ERROR, "<%4.4x> PingFifo(outfd=%d) ACK timed out",
+		    thr_self(), outFifo);
+		return TIMEOUT;
+	}
+
+	if (strcmp(rcvbuf, INSTANCE_DIED_TOKEN) == 0)
+		return INSTANCE_DIED;
+
+	if (!isPrefixed(rcvbuf, "PID="))
+		return ERROR;
+
+	pid = atoi(rcvbuf + 4);
+
+	Log4(PCSC_LOG_DEBUG, "<%4.4x> PingFifo((outfd=%d): OK pid=%d",
+		    thr_self(), outFifo, pid);
+
+	return pid;
+}
+
+
+/*
+ * @brief Handle 'non-FD' message
+ *
+ * Handles case where instance was waiting for an FD to be
+ * sent to the fifo, but instead got a message.  The message
+ * was read, and handed to this function to process it.
+ */
+int
+DoFifoCmd(int outFifo, char *cmd) {
+	char sndbuf[LINEMAX];
+	/*
+	 * If it's a ping message, respond with PID
+	 */
+	if (isPrefixed(cmd, FIFO_PING_CMD)) {
+		Log4(PCSC_LOG_DEBUG,
+		    "<%4.4x> DoFifoCmd(o:%d) Got PING. Replying with PID=%d",
+		    thr_self(), outFifo, getpid());
+
+		sprintf(sndbuf, "PID=%d", (int)getpid());
+
+		if (SendMsg(outFifo, sndbuf) < 0) {
+			Log4(PCSC_LOG_ERROR,
+			    "<%4.4x> DoFifoCmd(fd=%d):SendMsg(): %s",
+			    thr_self(), outFifo, strerror(errno));
+			return ERROR;
+		}
+		return INTERRUPTED;
+
+	} else if (isPrefixed(cmd, FIFO_EXIT_CMD)) {
+		kill(getpid(), SIGTERM);
+		return TERMINATED;
+	}
+	Log4(PCSC_LOG_ERROR,
+		"<%4.4x> DoFifoCmd(fd=%d): Bad fifo msg: \"%s\"",
+		thr_self(), outFifo, cmd);
+	return ERROR;
+}
+
+/**
+ * @brief Open an existing fifo and set fd characteristics.
+ */
+int
+OpenFifo(char *fifoName, int ndelay)
+{
+	int fd;
+
+	if ((fd = open(fifoName, O_RDWR)) < 0) {
+		Log4(PCSC_LOG_ERROR, "<%4.4x> OpenFifo(%s):\n%s",
+		    thr_self(), NONULL(fifoName), strerror(errno));
+		return ERROR;
+	}
+	{
+		char logbuf[LINEMAX];
+		sprintf(logbuf, "<%4.4x> %s -> fd=%d",
+		    thr_self(), NONULL(fifoName), fd);
+		Log2(PCSC_LOG_DEBUG, "%s", logbuf);
+	}
+	if (ndelay) {
+		if (fcntl(fd, F_SETFL, O_NDELAY) < 0) {
+			Log4(PCSC_LOG_DEBUG,
+			    "<%4.4x> OpenFifo(%s):fcntl(O_NDELAY): %s",
+			    thr_self(), fifoName, strerror(errno));
+			return ERROR;
+		}
+	}
+
+	if (fcntl(fd, F_SETFL, FD_CLOEXEC) < 0) {
+		Log4(PCSC_LOG_DEBUG,
+		    "<%4.4x> OpenFifo(%s):fcntl(FD_CLOEXEC): %s",
+		    thr_self(), fifoName, strerror(errno));
+		return ERROR;
+	}
+	return fd;
+}
+
+/*
+ * Receive response respons from fifo which is returned to
+ * caller.  If timeout, an error is returned.
+ */
+int
+DoFifoReceive(int inFifo, void *rcvbuf, int rcvlen, int timesecs)
+{
+	fd_set read_fd;
+	struct timeval tv;
+	tv.tv_sec = timesecs;
+	tv.tv_usec = 0;
+	char logbuf[LINEMAX];
+	int rv;
+
+	FD_ZERO(&read_fd);
+	FD_SET(inFifo, &read_fd);
+
+	if (pcscCfg.verbose)
+		Log3(PCSC_LOG_DEBUG, "<%4.4x> DoFifoReceive(infd=%d):select()",
+		    thr_self(), inFifo);
+
+	if ((rv = select(inFifo + 1, &read_fd, NULL, NULL, &tv)) < 0) {
+		while (rv < 0 && (errno == EINTR || errno == EAGAIN)) {
+			usleep(50000);
+			rv = select(inFifo + 1, &read_fd, NULL, NULL, &tv);
+		}
+		if (rv < 0) {
+			Log4(PCSC_LOG_ERROR,
+			    "<%4.4x> DoFifoReceive():select(infd=%d): %s",
+			    thr_self(), inFifo, strerror(errno));
+			return ERROR;      // Error
+		}
+	} else if (rv == 0) {
+		Log4(PCSC_LOG_ERROR,
+		    "<%4.4x> DoFifoReceive():select(infd=%d) Timeout (%d secs)",
+		    thr_self(), inFifo, timesecs);
+		return TIMEOUT;
+	}
+
+	if (FD_ISSET(inFifo, &read_fd)) {
+		if (read(inFifo, rcvbuf, rcvlen) < 0) {
+			while (rv < 0 && (errno == EINTR || errno == EAGAIN)) {
+				usleep(50000);
+				rv = select(inFifo + 1, &read_fd, NULL, NULL, &tv);
+			}
+			if (rv < 0) {
+				Log4(PCSC_LOG_ERROR,
+					"<%4.4x> DoFifoReceive():read(infd=%d) failed: %s",
+					thr_self(), inFifo, strerror(errno));
+				return ERROR;      // Error
+			}
+		}
+	}
+
+	if (pcscCfg.verbose) {
+		sprintf(logbuf, "<%4.4x> DoFifoReceive(infd=%d): ...Read %d bytes",
+		    thr_self(), inFifo, rv);
+
+		Log2(PCSC_LOG_DEBUG, "%s", logbuf);
+	}
+	return SUCCESS;
+}
+
+
+/*
+ * @brief  Send client's file descriptor over fifo
+ *
+ * Send's client's FD over pipe and expect response.
+ */
+int
+SendClientFd(int outFifo, int inFifo, int fdToSend, int timeout) {
+	char rcvbuf[LINEMAX];
+	int rv;
+
+	if (pcscCfg.verbose)
+		Log4(PCSC_LOG_DEBUG,
+			"SendClientFd(outfd=%d, infd:%d sendfd:%d)",
+			outFifo, inFifo, fdToSend);
+
+	if (ioctl(outFifo, I_SENDFD, fdToSend) < 0) {
+		Log4(PCSC_LOG_CRITICAL,
+		    "<%4.4x> SendClientFd(fd=%d) ioctl(I_SENDFD): %s",
+		    thr_self(), outFifo, strerror(errno));
+		return ERROR;
+	}
+	bzero(rcvbuf,sizeof (rcvbuf));
+	rv = DoFifoReceive(inFifo, rcvbuf, sizeof (rcvbuf), timeout);
+	switch(rv){
+	case ERROR:
+		Log4(PCSC_LOG_CRITICAL,
+		   "<%4.4x> SendClientFd(outfd=%d, send:fd=%d) ACK error",
+		   thr_self(), outFifo, fdToSend);
+		return ERROR;
+	case TIMEOUT:
+		Log4(PCSC_LOG_CRITICAL,
+		    "<%4.4x> SendClientFd(outfd=%d, send:fd=%d) ACK timeout",
+		    thr_self(), outFifo, fdToSend);
+		return TIMEOUT;
+	default:
+		break;
+	}
+	if (strcmp(rcvbuf, INSTANCE_DIED_TOKEN) == 0)
+		return INSTANCE_DIED;
+
+	if (!isPrefixed(rcvbuf, FIFO_FD_ACK)) {
+		Log4(PCSC_LOG_CRITICAL,
+		    "<%4.4x> SendClientFd(outfd=%d, sendfd=%d): Bad ACK msg:",
+		    thr_self(), outFifo, fdToSend);
+		Log3(PCSC_LOG_CRITICAL,
+		    "<%4.4x>   Expected ACK as \"%s\"",
+		    thr_self(), FIFO_FD_ACK);
+		Log3(PCSC_LOG_CRITICAL,
+		    "<%4.4x>   Received: \"%s\"",
+		    thr_self(), rcvbuf);
+		return ERROR;
+	}
+	return SUCCESS;
+}
+
+/*
+ * Send Message to fd
+ */
+int
+SendMsg(int fd, char *s)
+{
+	int rv =  write(fd, s, strlen(s) + 1);
+	while (rv < 0 && (errno == EINTR || errno == EAGAIN)) {
+		usleep(50000);
+		rv =  write(fd, s, strlen(s) + 1);
+	}
+	if (rv < 0) {
+		Log4(PCSC_LOG_ERROR,
+		    "<%4.4x> SendMsg(): Err during write(fd=%d): %s",
+		    thr_self(), fd, strerror(errno));
+		return ERROR;
+	}
+	return SUCCESS;
+}
+
+/*
+ * Send Command to fd
+ */
+int
+SendCmd(int fd, char *s)
+{
+	int rv =  write(fd, s, strlen(s) + 1);
+	while (rv < 0 && (errno == EINTR || errno == EAGAIN)) {
+		usleep(50000);
+		rv =  write(fd, s, strlen(s) + 1);
+	}
+	if (rv < 0) {
+		Log4(PCSC_LOG_ERROR,
+		    "<%4.4x> SendCmd(): Err during write(fd=%d): %s",
+		    thr_self(), fd, strerror(errno));
+		return ERROR;
+	}
+	return SUCCESS;
+}
+
+void
+catch_SIGHUP(int signo)
+{
+	FILE *fp;
+	char buf[256];
+
+	Log1(PCSC_LOG_DEBUG, "Caught SIGHUP\n");
+
+	sprintf(buf, "/tmp/pcscd_%d", (int)getpid());
+	if ((fp = fopen(buf, "w+")) == NULL) {
+		Log2(PCSC_LOG_CRITICAL,
+		    "Couldn't open file /tmp/pcscd_%d",
+		     (int)getpid());
+	}
+	CFGdumpCfg(fp);
+	fclose(fp);
+}
+
+void
+catch_SIGCHLD(int signo)
+{
+	int stat, pid;
+	pid = wait(&stat);
+	Log2(PCSC_LOG_DEBUG, "\nCaught SIGCHLD for pid %d\n", pid);
+
+}
+
+void
+SetupSignalHandlers(void (*fp)(int), int trapKbdSignals) {
+
+	struct sigaction action;
+	action.sa_handler = fp;
+	action.sa_flags = 0;
+
+	sigemptyset(&action.sa_mask);
+	if (sigaction(SIGTERM, &action, NULL) < 0) {
+		Log2(PCSC_LOG_CRITICAL,
+		     "Sigaction failed: %s", strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	if (trapKbdSignals &&
+	    sigaction(SIGQUIT, &action, NULL) < 0 ||
+	    sigaction(SIGINT,  &action, NULL) < 0) {
+		Log2(PCSC_LOG_CRITICAL,
+		     "Sigaction failed: %s", strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	action.sa_handler = catch_SIGHUP;
+	sigemptyset(&action.sa_mask);
+	action.sa_flags = 0;
+	if (sigaction(SIGHUP, &action, NULL) < 0) {
+		Log2(PCSC_LOG_CRITICAL, "Sigaction failed: %s",
+		     strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	/*
+	 * Disable zombie creation and SIGCHLD (both) - helps performance
+	 * prevents zombies, and prevent difficult EINTR issues.
+	 */
+	action.sa_handler = NULL;
+	sigemptyset(&action.sa_mask);
+	action.sa_flags = SA_NOCLDWAIT | SA_NOCLDSTOP;
+	if (sigaction(SIGCHLD, &action, NULL) < 0) {
+		Log2(PCSC_LOG_CRITICAL, "Sigaction failed: %s",  strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+}
+
+/*
+ * Returns true if buf is begins with string s
+ */
+static int
+isPrefixed(char *buf, char *s) {
+	return (strncmp(buf, s, strlen(s)) == 0);
+}

Added: branches/Solaris/src/daemon_utils.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/daemon_utils.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/daemon_utils.h (added)
+++ branches/Solaris/src/daemon_utils.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,63 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2000-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * <NEED TO FIX KEYWORDS>
+ */
+
+
+#ifndef	__daemon_utils_h__
+#define	__daemon_utils_h__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define FIFONAME_MAX_BUFSIZE    256        // Max name length for launcher fifos
+
+/*
+ * Protocol used over fifos
+ */
+#define FIFO_FD_ACK     "FD OK"
+#define FIFO_PING_CMD   "PING"
+#define FIFO_EXIT_CMD   "EXIT"
+#define INSTANCE_DIED_TOKEN   "DIED"
+
+#define PID_ASCII_SIZE 11
+
+int  SendClientFd(int, int, int, int);
+int  ReceiveClientFd(int, int,  int *, int);
+void SetupSignalHandlers(void (*fp)(int), int);
+int  DoFifoReceive(int, void *,int, int);
+void DeletePidFile(int);
+int  GetPidFromFile(int);
+int  DoFifoCmd(int, char *);
+int  OpenFifo(char *, int);
+int  PingFifo(int, int, int);
+int  SendMsg(int, char *);
+int  SendCmd(int, char *);
+int  StopInstance(int, int);
+/*
+ * Status codes
+ */
+#define SUCCESS         0
+#define ERROR          -1
+#define TIMEOUT        -2
+#define INTERRUPTED    -3
+#define SEVERE         -4
+#define TERMINATED     -5
+#define INSTANCE_DIED  -6
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif
+
+#endif

Modified: branches/Solaris/src/debug.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/debug.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/debug.c (original)
+++ branches/Solaris/src/debug.c Thu Jun 12 10:28:09 2008
@@ -13,20 +13,25 @@
  * @file
  * @brief This handles debugging for libpcsclite.
  */
- 
+
 #include "config.h"
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
 #include <stdarg.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
-
+#include <stdio.h>
+#include <sys/time.h>
 #include "debug.h"
 #include "strlcpycat.h"
 
+
 #define DEBUG_BUF_SIZE 2048
 
 /* default level is a bit verbose to be backward compatible */
-static char LogLevel = PCSC_LOG_ERROR;
+static int LogLevel = PCSC_LOG_CRITICAL;
 
 static signed char LogDoColor = 0;	/* no color by default */
 
@@ -73,8 +78,13 @@
 void log_msg(const int priority, const char *fmt, ...)
 {
 	char DebugBuffer[DEBUG_BUF_SIZE];
+	char printBuf[DEBUG_BUF_SIZE];
+
 	va_list argptr;
 	static int is_initialized = 0;
+	time_t clock = time(0);
+	struct tm *curtime = localtime(&clock);
+	unsigned long ms;
 
 	if (!is_initialized)
 	{
@@ -84,6 +94,7 @@
 
 	if (priority < LogLevel) /* log priority lower than threshold? */
 		return;
+
 
 	va_start(argptr, fmt);
 #ifndef WIN32
@@ -97,8 +108,19 @@
 #endif
 	va_end(argptr);
 
+	ms  = (unsigned long)
+		((gethrtime() / (unsigned long long)100000) % 10000);
+
+	sprintf(printBuf, "%2d:%2.2d:%2.2d.%4.4d ",
+		curtime->tm_hour, curtime->tm_min, curtime->tm_sec, ms);
+	strlcat(printBuf, DebugBuffer, DEBUG_BUF_SIZE);
+
 #ifndef WIN32
 	{
+#ifdef HAVE_SYSLOG_H
+		if (priority == PCSC_LOG_CRITICAL)
+			syslog(LOG_ERR, "%s", DebugBuffer);
+#endif
 		if (LogDoColor)
 		{
 			const char *color_pfx = "", *color_sfx = "\33[0m";
@@ -122,13 +144,13 @@
 					color_sfx = "";
 					break;
 			}
-			fprintf(stderr, "%s%s%s\n", color_pfx, DebugBuffer, color_sfx);
+			fprintf(stderr, "%s%s%s\n", color_pfx, printBuf, color_sfx);
 		}
 		else
-			fprintf(stderr, "%s\n", DebugBuffer);
-	}
-#else
-	fprintf(stderr, "%s\n", DebugBuffer);
+			fprintf(stderr, "%s\n", printBuf);
+	}
+#else
+	fprintf(stderr, "%s\n", printBuf);
 #endif
 } /* log_msg */
 
@@ -139,13 +161,16 @@
 	int i;
 	char *c;
 	char *debug_buf_end;
+	time_t clock = time(0);
+	struct tm *curtime = localtime(&clock);
 
 	if (priority < LogLevel) /* log priority lower than threshold? */
 		return;
 
 	debug_buf_end = DebugBuffer + DEBUG_BUF_SIZE - 5;
 
-	strlcpy(DebugBuffer, msg, sizeof(DebugBuffer));
+	sprintf(DebugBuffer, "%d:%d ", curtime->tm_hour, curtime->tm_min);
+	strlcat(DebugBuffer, msg, sizeof(DebugBuffer));
 	c = DebugBuffer + strlen(DebugBuffer);
 
 	for (i = 0; (i < len) && (c < debug_buf_end); ++i)
@@ -157,3 +182,69 @@
 	fprintf(stderr, "%s\n", DebugBuffer);
 } /* log_xxd */
 
+/*** PKK REMOVE ***/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <thread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define MAXBUF  ( 256 * 256 )
+
+/*
+ * Display stack traceback of specified thread (0 = current thread)
+ * on stdout.
+ */
+void
+traceback(int thr)
+{
+	int pfds[2], tid;
+
+	pipe(pfds);
+	tid = (thr == 0) ? thr_self() : thr;
+
+	if (fork() == 0) {
+		char buf[MAXBUF], cmp[20], line[256], *cp, *lb, *lp;
+		int triggered = 0, bufsize = 0, n;
+		printf("------------- Thread# %d "
+		       "Traceback --------------\n", tid);
+		if ((n = read(pfds[0], buf + bufsize, MAXBUF)) >= 0)
+			bufsize += n;
+		lb = buf + bufsize;
+		for(cp = buf; cp < lb;) {
+			bzero(lp = line, sizeof (line));
+			while (*cp++ != '\n' && cp < lb)
+				*lp++ = *cp;
+			*--lp = '\0';
+			if (!triggered) {
+			    sprintf(cmp, "thread# %d", tid);
+			    if (strstr(line, cmp) == NULL)
+				continue;
+			    triggered = 1;
+			    continue;
+			}
+			if (triggered && *line == '-') {
+				printf("------------------------"
+				       "------------------------\n");
+				return;
+			}
+			puts(line);
+		}
+		printf("------------------------"
+		       "------------------------\n");
+		exit(0);
+	} else {
+		char cmd[15];
+		int out = dup(1);
+		sprintf(cmd, "/bin/pstack %d", getpid());
+		dup2(pfds[1], 1);
+		system(cmd);
+		dup2(out, 1);
+	}
+}
+

Modified: branches/Solaris/src/debug.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/debug.h?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/debug.h (original)
+++ branches/Solaris/src/debug.h Thu Jun 12 10:28:09 2008
@@ -1,78 +1,92 @@
 /*
- * MUSCLE SmartCard Development ( http://www.linuxnet.com )
- *
- * Copyright (C) 1999-2004
- *  David Corcoran <corcoran at linuxnet.com>
- * Copyright (C) 1999-2005
- *  Ludovic Rousseau <ludovic.rousseau at free.fr>
- *
- * $Id: debuglog.h 1835 2006-01-25 10:42:23Z rousseau $
+    debug.h: log (or not) messages using syslog
+    Copyright (C) 2003-2005   Ludovic Rousseau
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+*/
+
+/*
+ * $Id: debug.h 1702 2005-11-07 15:41:47Z rousseau $
  */
 
-/**
- * @file
- * @brief This handles debugging.
+/*
+ * DEBUG_CRITICAL("text");
+ * 	log "text" if (LogLevel & DEBUG_LEVEL_CRITICAL) is TRUE
  *
- * @note log message is sent to syslog or stderr depending on --foreground
- * command line argument
+ * DEBUG_CRITICAL2("text: %d", 1234);
+ *  log "text: 1234" if (DEBUG_LEVEL_CRITICAL & DEBUG_LEVEL_CRITICAL) is TRUE
+ * the format string can be anything printf() can understand
+ * 
+ * same thing for DEBUG_INFO, DEBUG_COMM and DEBUG_PERIODIC
  *
- * @test
- * @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
+ * DEBUG_XXD(msg, buffer, size);
+ *  log a dump of buffer if (LogLevel & DEBUG_LEVEL_COMM) is TRUE
+ *
  */
-
-#ifndef __debug_h__
-#define __debug_h__
-
-#ifdef PCSC
-/* use syslog, etc. if we are included from a file for pcscd */
-#include "debuglog.h"
-#else
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-enum {
-	PCSC_LOG_DEBUG = 0,
-	PCSC_LOG_INFO,
-	PCSC_LOG_ERROR,
-	PCSC_LOG_CRITICAL
-};
-
-#include <stdio.h>
+ 
+#ifndef _GCDEBUG_H_
+#define  _GCDEBUG_H_
 
 /* You can't do #ifndef __FUNCTION__ */
 #if !defined(__GNUC__) && !defined(__IBMC__)
 #define __FUNCTION__ ""
 #endif
 
-#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 LogXxd(priority, msg, buffer, size) log_xxd(priority, msg, buffer, size)
+extern int LogLevel;
 
-void log_msg(const int priority, const char *fmt, ...);
-void log_xxd(const int priority, const char *msg,
-	const unsigned char *buffer, const int size);
+#define DEBUG_LEVEL_CRITICAL 1
+#define DEBUG_LEVEL_INFO     2
+#define DEBUG_LEVEL_COMM     4
+#define DEBUG_LEVEL_PERIODIC 8
 
-#ifdef __cplusplus
-}
-#endif
+#include <debuglog.h>	/* from pcsc-lite */
+
+/* DEBUG_CRITICAL */
+#define DEBUG_CRITICAL(fmt) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log1(PCSC_LOG_CRITICAL, fmt)
+
+#define DEBUG_CRITICAL2(fmt, data) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log2(PCSC_LOG_CRITICAL, fmt, data)
+
+#define DEBUG_CRITICAL3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log3(PCSC_LOG_CRITICAL, fmt, data1, data2)
+
+#define DEBUG_CRITICAL4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_CRITICAL) Log4(PCSC_LOG_CRITICAL, fmt, data1, data2, data3)
+
+/* DEBUG_INFO */
+#define DEBUG_INFO(fmt) if (LogLevel & DEBUG_LEVEL_INFO) Log1(PCSC_LOG_INFO, fmt)
+
+#define DEBUG_INFO2(fmt, data) if (LogLevel & DEBUG_LEVEL_INFO) Log2(PCSC_LOG_INFO, fmt, data)
+
+#define DEBUG_INFO3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_INFO) Log3(PCSC_LOG_INFO, fmt, data1, data2)
+
+#define DEBUG_INFO4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_INFO) Log4(PCSC_LOG_INFO, fmt, data1, data2, data3)
+
+/* DEBUG_PERIODIC */
+#define DEBUG_PERIODIC(fmt) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log1(PCSC_LOG_DEBUG, fmt)
+
+#define DEBUG_PERIODIC2(fmt, data) if (LogLevel & DEBUG_LEVEL_PERIODIC) Log2(PCSC_LOG_DEBUG, fmt, data)
+
+/* DEBUG_COMM */
+#define DEBUG_COMM(fmt) if (LogLevel & DEBUG_LEVEL_COMM) Log1(PCSC_LOG_DEBUG, fmt)
+
+#define DEBUG_COMM2(fmt, data) if (LogLevel & DEBUG_LEVEL_COMM) Log2(PCSC_LOG_DEBUG, fmt, data)
+
+#define DEBUG_COMM3(fmt, data1, data2) if (LogLevel & DEBUG_LEVEL_COMM) Log3(PCSC_LOG_DEBUG, fmt, data1, data2)
+
+#define DEBUG_COMM4(fmt, data1, data2, data3) if (LogLevel & DEBUG_LEVEL_COMM) Log4(PCSC_LOG_DEBUG, fmt, data1, data2, data3)
+
+/* DEBUG_XXD */
+#define DEBUG_XXD(msg, buffer, size) if (LogLevel & DEBUG_LEVEL_COMM) log_xxd(PCSC_LOG_DEBUG, msg, buffer, size)
 
 #endif
 
-#endif							/* __debug_h__ */
-

Modified: branches/Solaris/src/debuglog.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/debuglog.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/debuglog.c (original)
+++ branches/Solaris/src/debuglog.c Thu Jun 12 10:28:09 2008
@@ -13,7 +13,7 @@
  * @file
  * @brief This handles debugging for pcscd.
  */
- 
+
 #include "config.h"
 #ifdef HAVE_SYSLOG_H
 #include <syslog.h>
@@ -22,19 +22,22 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <strings.h>
 #include <stdarg.h>
 #include <assert.h>
 #include <sys/types.h>
+#include <fcntl.h>
 
 #include "pcsclite.h"
 #include "misc.h"
 #include "debuglog.h"
 #include "sys_generic.h"
+#include <sys/time.h>
 #include "strlcpycat.h"
 
-/** 
+/**
  * Max string size when dumping a 256 bytes longs APDU
- * Should be bigger than 256*3+30 
+ * Should be bigger than 256*3+30
  */
 #define DEBUG_BUF_SIZE 2048
 
@@ -43,37 +46,70 @@
 static char LogCategory = DEBUG_CATEGORY_NOTHING;
 
 /* default level is a bit verbose to be backward compatible */
-static char LogLevel = PCSC_LOG_INFO;
+static int LogLevel = PCSC_LOG_INFO;
 
 static signed char LogDoColor = 0;	/* no color by default */
 
 void log_msg(const int priority, const char *fmt, ...)
 {
-	char DebugBuffer[DEBUG_BUF_SIZE];
+	char *wrkbuf, *printbuf;
 	va_list argptr;
+	static int init_flag;
+	time_t clock = time(0);
+	struct tm *curtime = 0;
+	unsigned long ms;
+
 
 	if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
 		|| (priority < LogLevel) /* log priority lower than threshold? */
 		|| (DEBUGLOG_NO_DEBUG == LogMsgType))
 		return;
 
+	curtime = localtime(&clock);
+	printbuf = malloc(DEBUG_BUF_SIZE);
+	if (printbuf == NULL) {
+		syslog(LOG_ERR, "Out of Memory");
+		return;
+	}
+
+	bzero(printbuf, DEBUG_BUF_SIZE);
+	wrkbuf = malloc(DEBUG_BUF_SIZE);
+	if (wrkbuf == NULL) {
+		syslog(LOG_ERR, "Out of Memory");
+		free(printbuf);
+		return;
+	}
+	bzero(wrkbuf, DEBUG_BUF_SIZE);
+
 	va_start(argptr, fmt);
 #ifndef WIN32
-	vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
+	vsnprintf(wrkbuf, DEBUG_BUF_SIZE, fmt, argptr);
 #else
 #if HAVE_VSNPRINTF
-	vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
+	vsnprintf(wrkbuf, DEBUG_BUF_SIZE, fmt, argptr);
 #else
-	vsprintf(DebugBuffer, fmt, argptr);
+	vsprintf(wrkbuf, fmt, argptr);
 #endif
 #endif
 	va_end(argptr);
 
-#ifndef WIN32
-	if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
-		syslog(LOG_INFO, "%s", DebugBuffer);
-	else
-	{
+	ms  = (unsigned long)
+		((gethrtime() / (unsigned long long)100000) % 10000);
+
+	sprintf(printbuf, "%2d:%2.2d:%2.2d.%4.4d ",
+		curtime->tm_hour, curtime->tm_min, curtime->tm_sec, ms);
+
+	strlcat(printbuf, wrkbuf, DEBUG_BUF_SIZE);
+
+#ifndef WIN32
+	if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType) {
+#if HAVE_SYSLOG_H
+		syslog(LOG_INFO, "%s", wrkbuf);
+#endif
+	} else {
+		if (priority == PCSC_LOG_CRITICAL)
+			syslog(LOG_ERR, "%s", wrkbuf);
+
 		if (LogDoColor)
 		{
 			const char *color_pfx = "", *color_sfx = "\33[0m";
@@ -97,33 +133,50 @@
 					color_sfx = "";
 					break;
 			}
-			fprintf(stderr, "%s%s%s\n", color_pfx, DebugBuffer, color_sfx);
+			fprintf(stderr, "%s%s%s\n", color_pfx, wrkbuf, color_sfx);
 		}
-		else
-			fprintf(stderr, "%s\n", DebugBuffer);
+		else {
+			write(2, printbuf, strlen(printbuf));
+			write(2, "\n", 1);
+		}
 	}
 #else
-	fprintf(stderr, "%s\n", DebugBuffer);
-#endif
+		write(2, printbuf, strlen(printbuf));
+		write(2, "\n", 1);
+#endif
+	free(printbuf);
+	free(wrkbuf);
 } /* log_msg */
 
+int init_flag = 0;
 void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
 	const int len)
 {
-	char DebugBuffer[DEBUG_BUF_SIZE];
+	static char wrkbuf[DEBUG_BUF_SIZE];
 	int i;
 	char *c;
 	char *debug_buf_end;
+	time_t clock = time(0);
+	struct tm *curtime = localtime(&clock);
+
+	/*
+	 * Set stderr to non-blocking
+	 */
+	if (init_flag) {
+		init_flag = 1;
+		fcntl(2, F_SETFL, O_NDELAY);
+	}
 
 	if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
 		|| (priority < LogLevel) /* log priority lower than threshold? */
 		|| (DEBUGLOG_NO_DEBUG == LogMsgType))
 		return;
 
-	debug_buf_end = DebugBuffer + DEBUG_BUF_SIZE - 5;
-
-	strlcpy(DebugBuffer, msg, sizeof(DebugBuffer));
-	c = DebugBuffer + strlen(DebugBuffer);
+	debug_buf_end = wrkbuf + DEBUG_BUF_SIZE - 5;
+
+	sprintf(wrkbuf, "%d:%d ", curtime->tm_hour, curtime->tm_min);
+	strlcat(wrkbuf, msg, sizeof(wrkbuf));
+	c = wrkbuf + strlen(wrkbuf);
 
 	for (i = 0; (i < len) && (c < debug_buf_end); ++i)
 	{
@@ -137,10 +190,12 @@
 
 #ifndef WIN32
 	if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
-		syslog(LOG_INFO, "%s", DebugBuffer);
-	else
-#endif
-		fprintf(stderr, "%s\n", DebugBuffer);
+		syslog(LOG_INFO, "%s", wrkbuf);
+	else {
+#endif
+		write(2, wrkbuf, strlen(wrkbuf));
+		write(2, "\n", 1);
+	}
 } /* log_xxd */
 
 #ifdef PCSCD
@@ -195,20 +250,22 @@
 
 void DebugLogSetLevel(const int level)
 {
-	LogLevel = level;
-	switch (level)
-	{
+	if (LogLevel == level)
+		return;
+
+	switch (level)	{
 		case PCSC_LOG_CRITICAL:
+			break;
+
 		case PCSC_LOG_ERROR:
-			/* do not log anything */
 			break;
 
 		case PCSC_LOG_INFO:
-			Log1(PCSC_LOG_INFO, "debug level=notice");
+			Log1(PCSC_LOG_INFO, "debug level notice");
 			break;
 
 		case PCSC_LOG_DEBUG:
-			Log1(PCSC_LOG_DEBUG, "debug level=debug");
+			Log1(PCSC_LOG_DEBUG, "debug level debug");
 			break;
 
 		default:
@@ -216,6 +273,7 @@
 			Log2(PCSC_LOG_CRITICAL, "unknown level (%d), using level=notice",
 				level);
 	}
+	LogLevel = level;
 }
 
 INTERNAL int DebugLogSetCategory(const int dbginfo)
@@ -261,7 +319,7 @@
 #ifdef PCSCD
 void debug_msg(const char *fmt, ...)
 {
-	char DebugBuffer[DEBUG_BUF_SIZE];
+	char wrkbuf[DEBUG_BUF_SIZE];
 	va_list argptr;
 
 	if ((LogSuppress != DEBUGLOG_LOG_ENTRIES)
@@ -270,22 +328,22 @@
 
 	va_start(argptr, fmt);
 #ifndef WIN32
-	vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
+	vsnprintf(wrkbuf, DEBUG_BUF_SIZE, fmt, argptr);
 #else
 #if HAVE_VSNPRINTF
-	vsnprintf(DebugBuffer, DEBUG_BUF_SIZE, fmt, argptr);
+	vsnprintf(wrkbuf, DEBUG_BUF_SIZE, fmt, argptr);
 #else
-	vsprintf(DebugBuffer, fmt, argptr);
+	vsprintf(wrkbuf, fmt, argptr);
 #endif
 #endif
 	va_end(argptr);
 
 #ifndef WIN32
 	if (DEBUGLOG_SYSLOG_DEBUG == LogMsgType)
-		syslog(LOG_INFO, "%s", DebugBuffer);
+		syslog(LOG_INFO, "%s", wrkbuf);
 	else
 #endif
-		fprintf(stderr, "%s\n", DebugBuffer);
+		fprintf(stderr, "%s\n", wrkbuf);
 } /* debug_msg */
 
 void debug_xxd(const char *msg, const unsigned char *buffer, const int len)
@@ -294,3 +352,67 @@
 } /* debug_xxd */
 #endif
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <thread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define MAXBUF  ( 256 * 256 )
+
+/*
+ * Display stack traceback of specified thread (0 = current thread)
+ * on stdout.
+ */
+void
+traceback(int thr)
+{
+	int pfds[2], tid;
+
+	pipe(pfds);
+	tid = (thr == 0) ? thr_self() : thr;
+
+	if (fork() == 0) {
+		char buf[MAXBUF], cmp[20], line[256], *cp, *lb, *lp;
+		int triggered = 0, bufsize = 0, n;
+		printf("------------- Thread# %d "
+		       "Traceback --------------\n", tid);
+		if ((n = read(pfds[0], buf + bufsize, MAXBUF)) >= 0)
+			bufsize += n;
+		lb = buf + bufsize;
+		for(cp = buf; cp < lb;) {
+			bzero(lp = line, sizeof (line));
+			while (*cp++ != '\n' && cp < lb)
+				*lp++ = *cp;
+			*--lp = '\0';
+			if (!triggered) {
+			    sprintf(cmp, "thread# %d", tid);
+			    if (strstr(line, cmp) == NULL)
+				continue;
+			    triggered = 1;
+			    continue;
+			}
+			if (triggered && *line == '-') {
+				printf("------------------------"
+				       "------------------------\n");
+				return;
+			}
+			puts(line);
+		}
+		printf("------------------------"
+		       "------------------------\n");
+		exit(0);
+	} else {
+		char cmd[15];
+		int out = dup(1);
+		sprintf(cmd, "/bin/pstack %d", getpid());
+		dup2(pfds[1], 1);
+		system(cmd);
+		dup2(out, 1);
+	}
+}
+

Modified: branches/Solaris/src/dyn_unix.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/dyn_unix.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/dyn_unix.c (original)
+++ branches/Solaris/src/dyn_unix.c Thu Jun 12 10:28:09 2008
@@ -43,10 +43,8 @@
 INTERNAL int DYN_CloseLibrary(void **pvLHandle)
 {
 	int ret;
-
 	ret = dlclose(*pvLHandle);
 	*pvLHandle = NULL;
-
 	if (ret)
 	{
 		Log2(PCSC_LOG_CRITICAL, "%s", dlerror());

Modified: branches/Solaris/src/error.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/error.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/error.c (original)
+++ branches/Solaris/src/error.c Thu Jun 12 10:28:09 2008
@@ -159,6 +159,9 @@
 	case SCARD_E_SERVICE_STOPPED:
 		strlcpy(strError, "Service was stopped.", sizeof(strError));
 		break;
+	case SCARD_E_NO_PERMISSION:
+		strlcpy(strError, "Permission denied.", sizeof(strError));
+		break;
 	default:
 		snprintf(strError, sizeof(strError)-1, "Unkown error: 0x%08lX",
 			pcscError);

Modified: branches/Solaris/src/eventhandler.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/eventhandler.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/eventhandler.c (original)
+++ branches/Solaris/src/eventhandler.c Thu Jun 12 10:28:09 2008
@@ -24,7 +24,8 @@
 #include <stdlib.h>
 
 #include "misc.h"
-#include "pcsclite.h"
+#include "pcsclite.h"    
+#include "pcsc_config.h"
 #include "ifdhandler.h"
 #include "debuglog.h"
 #include "thread_generic.h"
@@ -36,66 +37,112 @@
 #include "prothandler.h"
 #include "strlcpycat.h"
 
+
 static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
 
 void EHStatusHandlerThread(PREADER_CONTEXT);
+
+
+
+LONG EHfetchReaderState(unsigned int index, PREADER_STATE data)
+{
+	/*
+	 * These are client side request errors and should NEVER
+	 * be returned during normal operation.
+	 */
+        if (index < 0 || index > PCSCLITE_MAX_READERS_CONTEXTS -1 || 
+	    data==NULL)
+                return -1;
+ 
+        memcpy(data, readerStates[index], sizeof (READER_STATE));
+        return 0;
+}
+
 
 LONG EHInitializeEventStructures(void)
 {
 	int fd, i, pageSize;
 
-	fd = 0;
-	i = 0;
-	pageSize = 0;
-
-	SYS_RemoveFile(PCSCLITE_PUBSHM_FILE);
-
-	fd = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDWR | O_CREAT, 00644);
-	if (fd < 0)
-	{
-		Log3(PCSC_LOG_CRITICAL, "Cannot create public shared file %s: %s",
-			PCSCLITE_PUBSHM_FILE, strerror(errno));
-		exit(1);
-	}
-
-	SYS_Chmod(PCSCLITE_PUBSHM_FILE,
-		S_IRGRP | S_IREAD | S_IWRITE | S_IROTH);
-
-	pageSize = SYS_GetPageSize();
-
-	/*
-	 * Jump to end of file space and allocate zero's 
-	 */
-	SYS_SeekFile(fd, pageSize * PCSCLITE_MAX_READERS_CONTEXTS);
-	SYS_WriteFile(fd, "", 1);
-
-	/*
-	 * Allocate each reader structure 
-	 */
-	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
-	{
-		readerStates[i] = (PREADER_STATE)
-			SYS_MemoryMap(sizeof(READER_STATE), fd, (i * pageSize));
-		if (readerStates[i] == MAP_FAILED)
-		{
-			Log3(PCSC_LOG_CRITICAL, "Cannot memory map public shared file %s: %s",
-				PCSCLITE_PUBSHM_FILE, strerror(errno));
-			exit(1);
-		}
-
-		/*
-		 * Zero out each value in the struct 
-		 */
-		memset((readerStates[i])->readerName, 0, MAX_READERNAME);
-		memset((readerStates[i])->cardAtr, 0, MAX_ATR_SIZE);
-		(readerStates[i])->readerID = 0;
-		(readerStates[i])->readerState = 0;
-		(readerStates[i])->lockState = 0;
-		(readerStates[i])->readerSharing = 0;
-		(readerStates[i])->cardAtrLength = 0;
-		(readerStates[i])->cardProtocol = SCARD_PROTOCOL_UNSET;
-	}
-
+        if (pcscCfg.useMappedMemory) {
+        	fd = 0;
+        	i = 0;
+        	pageSize = 0;
+        
+               	SYS_RemoveFile(pcscCfg.pcscdMemMappedFile);
+                
+               	fd = SYS_OpenFile(pcscCfg.pcscdMemMappedFile,
+                        O_RDWR | O_CREAT, 00644);
+                if (fd < 0)
+                {
+              		Log3(PCSC_LOG_CRITICAL, "Cannot create public shared file %s: %s",
+       		                pcscCfg.pcscdMemMappedFile, strerror(errno));
+       	                exit(1);
+                }
+                
+      	        SYS_Chmod(pcscCfg.pcscdMemMappedFile,
+               	        S_IRGRP | S_IREAD | S_IWRITE | S_IROTH);
+        
+        	pageSize = SYS_GetPageSize();
+        
+        	/*
+	        * Jump to end of file space and allocate zero's 
+	        */
+	        SYS_SeekFile(fd, pageSize * PCSCLITE_MAX_READERS_CONTEXTS);
+	        SYS_WriteFile(fd, "", 1);
+
+	        /*
+	         * Allocate each reader structure in mapped file
+        	 */
+        	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
+        	{
+		        readerStates[i] = (PREADER_STATE)
+        			SYS_MemoryMap(sizeof(READER_STATE), fd, (i * pageSize));
+		        if (readerStates[i] == MAP_FAILED)
+		        {
+        			Log3(PCSC_LOG_CRITICAL, "Cannot memory map public shared file %s: %s",
+				        pcscCfg.pcscdMemMappedFile, 
+                                        strerror(errno));
+			        exit(1);
+		        }
+        
+		        /*
+		        * Zero out each value in the struct 
+		        */
+		        memset((readerStates[i])->readerName, 0, MAX_READERNAME);
+		        memset((readerStates[i])->cardAtr, 0, MAX_ATR_SIZE);
+		        (readerStates[i])->readerID = 0;
+		        (readerStates[i])->readerState = 0;
+		        (readerStates[i])->lockState = 0;
+		        (readerStates[i])->readerSharing = 0;
+		        (readerStates[i])->cardAtrLength = 0;
+		        (readerStates[i])->cardProtocol = SCARD_PROTOCOL_UNSET;
+	        }
+        } else {
+	        /*
+	         * Allocate each reader structure from dynamic memory 
+        	 */
+        	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
+        	{
+		        readerStates[i] = (PREADER_STATE)malloc(sizeof (READER_STATE));
+		        if (readerStates[i] == NULL)
+		        {
+        			Log1(PCSC_LOG_CRITICAL, "Out of memory");
+			        exit(1);
+		        }
+        
+		        /*
+		        * Zero out each value in the struct 
+		        */
+		        memset((readerStates[i])->readerName, 0, MAX_READERNAME);
+		        memset((readerStates[i])->cardAtr, 0, MAX_ATR_SIZE);
+		        (readerStates[i])->readerID = 0;
+		        (readerStates[i])->readerState = 0;
+		        (readerStates[i])->lockState = 0;
+		        (readerStates[i])->readerSharing = 0;
+		        (readerStates[i])->cardAtrLength = 0;
+		        (readerStates[i])->cardProtocol = SCARD_PROTOCOL_UNSET;
+	        }
+        }
 	return SCARD_S_SUCCESS;
 }
 
@@ -109,7 +156,7 @@
 
 	if ('\0' == rContext->readerState->readerName[0])
 	{
-		Log1(PCSC_LOG_INFO, "Thread already stomped.");
+		Log1(PCSC_LOG_DEBUG, "Thread already stomped.");
 		return SCARD_S_SUCCESS;
 	}
 
@@ -118,7 +165,7 @@
 	 */
 	rContext->dwLockId = 0xFFFF;
 
-	Log1(PCSC_LOG_INFO, "Stomping thread.");
+	Log1(PCSC_LOG_DEBUG, "Stomping thread.");
 
 	do
 	{
@@ -147,7 +194,7 @@
 	/* Zero the thread */
 	rContext->pthThread = 0;
 
-	Log1(PCSC_LOG_INFO, "Thread stomped.");
+	Log1(PCSC_LOG_DEBUG, "Thread stomped.");
 
 	return SCARD_S_SUCCESS;
 }
@@ -243,12 +290,12 @@
 
 			if (rContext->readerState->cardAtrLength > 0)
 			{
-				LogXxd(PCSC_LOG_INFO, "Card ATR: ",
+				LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
 					rContext->readerState->cardAtr,
 					rContext->readerState->cardAtrLength);
 			}
 			else
-				Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
+				Log1(PCSC_LOG_DEBUG, "Card ATR: (NULL)");
 		}
 		else
 		{
@@ -275,7 +322,6 @@
 		dwStatus &= ~SCARD_UNKNOWN;
 		rContext->readerState->cardAtrLength = 0;
 		rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
-
 		dwCurrentState = SCARD_ABSENT;
 	}
 
@@ -347,7 +393,7 @@
 				/*
 				 * Change the status structure 
 				 */
-				Log2(PCSC_LOG_INFO, "Card Removed From %s", lpcReader);
+				Log2(PCSC_LOG_DEBUG, "Card Removed From %s", lpcReader);
 				/*
 				 * Notify the card has been removed 
 				 */
@@ -416,18 +462,18 @@
 
 				SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
 
-				Log2(PCSC_LOG_INFO, "Card inserted into %s", lpcReader);
+				Log2(PCSC_LOG_DEBUG, "Card inserted into %s", lpcReader);
 
 				if (rv == IFD_SUCCESS)
 				{
 					if (rContext->readerState->cardAtrLength > 0)
 					{
-						LogXxd(PCSC_LOG_INFO, "Card ATR: ",
+						LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
 							rContext->readerState->cardAtr,
 							rContext->readerState->cardAtrLength);
 					}
 					else
-						Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
+						Log1(PCSC_LOG_DEBUG, "Card ATR: (NULL)");
 				}
 				else
 					Log1(PCSC_LOG_ERROR,"Error powering up card.");
@@ -454,8 +500,11 @@
 			rContext->readerState->readerSharing = dwReaderSharing;
 			SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
 		}
-
-		SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
+#if 0
+		CFGdumpEventState(dwStatus);
+		CFGdumpReaderState(rContext->readerState->readerState);
+#endif		
+               SYS_USleep(pcscCfg.statusPollRate);
 	}
 }
 
@@ -463,3 +512,4 @@
 {
 	rContext->readerState->lockState = dwValue;
 }
+

Modified: branches/Solaris/src/eventhandler.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/eventhandler.h?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/eventhandler.h (original)
+++ branches/Solaris/src/eventhandler.h Thu Jun 12 10:28:09 2008
@@ -41,7 +41,8 @@
 	}
 	READER_STATE, *PREADER_STATE;
 
-	LONG EHInitializeEventStructures(void);
+	LONG EHfetchReaderState(unsigned int, PREADER_STATE);
+        LONG EHInitializeEventStructures(void);
 	LONG EHSpawnEventHandler(PREADER_CONTEXT);
 	LONG EHDestroyEventHandler(PREADER_CONTEXT);
 	void EHSetSharingEvent(PREADER_CONTEXT, DWORD);

Modified: branches/Solaris/src/hotplug_libusb.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/hotplug_libusb.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/hotplug_libusb.c (original)
+++ branches/Solaris/src/hotplug_libusb.c Thu Jun 12 10:28:09 2008
@@ -38,7 +38,9 @@
 #include "sys_generic.h"
 #include "hotplug.h"
 
-#undef DEBUG_HOTPLUG
+/*#define DEBUG_HOTPLUG*/
+
+#define AUTHSVCNAME		"CCID"
 #define ADD_SERIAL_NUMBER
 
 #define BUS_DEVICE_STRSIZE	256
@@ -64,7 +66,6 @@
 {
 	long manuID;
 	long productID;
-
 	char *bundleName;
 	char *libraryPath;
 	char *readerName;
@@ -77,6 +78,7 @@
 static struct _readerTracker
 {
 	char status;
+	struct usb_device *libusbdev;
 	char bus_device[BUS_DEVICE_STRSIZE];	/* device name */
 	char *fullName;	/* full reader name (including serial number) */
 
@@ -98,6 +100,7 @@
 	char keyValue[TOKEN_MAX_VALUE_SIZE];
 	int listCount = 0;
 
+	Log1(PCSC_LOG_DEBUG, "HPReadBundleValues(): Drop Dir: " PCSCLITE_HP_DROPDIR);
 	hpDir = opendir(PCSCLITE_HP_DROPDIR);
 
 	if (hpDir == NULL)
@@ -168,7 +171,7 @@
 				}
 
 #ifdef DEBUG_HOTPLUG
-					Log2(PCSC_LOG_INFO, "Found driver for: %s",
+					Log2(PCSC_LOG_DEBUG, "Found driver for: %s",
 						driverTracker[listCount].readerName);
 #endif
 
@@ -182,7 +185,7 @@
 					/* increase the array size */
 					driverSize += DRIVER_TRACKER_SIZE_STEP;
 #ifdef DEBUG_HOTPLUG
-					Log2(PCSC_LOG_INFO,
+					Log2(PCSC_LOG_DEBUG,
 						"Increase driverTracker to %d entries", driverSize);
 #endif
 					driverTracker = realloc(driverTracker,
@@ -214,13 +217,13 @@
 	rv = TRUE;
 	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");
+		Log1(PCSC_LOG_DEBUG, "No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
+		Log1(PCSC_LOG_DEBUG, "Disabling USB support for pcscd");
 		rv = FALSE;
 	}
 #ifdef DEBUG_HOTPLUG
 	else
-		Log2(PCSC_LOG_INFO, "Found drivers for %d readers", listCount);
+		Log2(PCSC_LOG_DEBUG, "Found drivers for %d readers", listCount);
 #endif
 
 	return rv;
@@ -234,6 +237,9 @@
 	char bus_device[BUS_DEVICE_STRSIZE];
 
 	usb_init();
+#ifdef DEBUG_HOTPLUG
+	putenv("SUN_LIBUSBUT_DEBUG=4");
+#endif
 	while (1)
 	{
 		usb_find_busses();
@@ -246,7 +252,7 @@
 		/* For each USB bus */
 		for (bus = usb_get_busses(); bus; bus = bus->next)
 		{
-			/* For each USB device */
+			/* For each UƒSB device */
 			for (dev = bus->devices; dev; dev = dev->next)
 			{
 				/* check if the device is supported by one driver */
@@ -262,23 +268,23 @@
 						snprintf(bus_device, BUS_DEVICE_STRSIZE, "%s:%s",
 							bus->dirname, dev->filename);
 						bus_device[BUS_DEVICE_STRSIZE - 1] = '\0';
-#ifdef DEBUG_HOTPLUG
+//#ifdef DEBUG_HOTPLUG
 						Log2(PCSC_LOG_DEBUG, "Found matching USB device: %s", bus_device);
-#endif
+//#endif
 						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)
-							{
+							if ((strncmp(readerTracker[j].bus_device,
+							    bus_device, BUS_DEVICE_STRSIZE) == 0) &&
+							    readerTracker[j].libusbdev == dev) {
 								/* The reader is already known */
 								readerTracker[j].status = READER_PRESENT;
 								newreader = FALSE;
-#ifdef DEBUG_HOTPLUG
+//#ifdef DEBUG_HOTPLUG
 								Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s", bus_device);
-#endif
+//#endif
 								break;
 							}
 						}
@@ -358,7 +364,7 @@
 			}
 			free(driverTracker);
 
-			Log1(PCSC_LOG_INFO, "Hotplug stopped");
+			Log1(PCSC_LOG_DEBUG, "Hotplug stopped");
 			pthread_exit(&retval);
 		}
 
@@ -404,7 +410,7 @@
 
 	SYS_MutexLock(&usbNotifierMutex);
 
-	Log2(PCSC_LOG_INFO, "Adding USB device: %s", bus_device);
+	Log2(PCSC_LOG_DEBUG, "Adding USB device: %s", bus_device);
 
 	snprintf(deviceName, sizeof(deviceName), "usb:%04x/%04x:libusb:%s",
 		dev->descriptor.idVendor, dev->descriptor.idProduct, bus_device);
@@ -427,8 +433,9 @@
 	strncpy(readerTracker[i].bus_device, bus_device,
 		sizeof(readerTracker[i].bus_device));
 	readerTracker[i].bus_device[sizeof(readerTracker[i].bus_device) - 1] = '\0';
-   
+
 	readerTracker[i].driver = driver;
+	readerTracker[i].libusbdev = dev;
 
 #ifdef ADD_SERIAL_NUMBER
 	if (dev->descriptor.iSerialNumber)
@@ -451,10 +458,12 @@
 		readerTracker[i].fullName = strdup(driver->readerName);
 
 	if (RFAddReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i,
-		driver->libraryPath, deviceName) == SCARD_S_SUCCESS)
+		driver->libraryPath, deviceName, AUTHSVCNAME) == SCARD_S_SUCCESS) {
 		readerTracker[i].status = READER_PRESENT;
-	else
+
+	} else {
 		readerTracker[i].status = READER_FAILED;
+	}
 
 	SYS_MutexUnLock(&usbNotifierMutex);
 
@@ -465,7 +474,7 @@
 {
 	SYS_MutexLock(&usbNotifierMutex);
 
-	Log3(PCSC_LOG_INFO, "Removing USB device[%d]: %s", index,
+	Log3(PCSC_LOG_DEBUG, "Removing USB device[%d]: %s", index,
 		readerTracker[index].bus_device);
 
 	RFRemoveReader(readerTracker[index].fullName,

Modified: branches/Solaris/src/hotplug_linux.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/hotplug_linux.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/hotplug_linux.c (original)
+++ branches/Solaris/src/hotplug_linux.c Thu Jun 12 10:28:09 2008
@@ -38,6 +38,7 @@
 #include "hotplug.h"
 
 #define PCSCLITE_USB_PATH		"/proc/bus/usb"
+#define AUTHSVCNAME			"Linux_USB"
 
 #define FALSE			0
 #define TRUE			1
@@ -107,9 +108,9 @@
 
 	if (hpDir == NULL)
 	{
-		Log1(PCSC_LOG_INFO,
+		Log1(PCSC_LOG_DEBUG,
 			"Cannot open PC/SC drivers directory: " PCSCLITE_HP_DROPDIR);
-		Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd.");
+		Log1(PCSC_LOG_DEBUG, "Disabling USB support for pcscd.");
 		return -1;
 	}
 
@@ -181,9 +182,9 @@
 
 	if (bundleSize == 0)
 	{
-		Log1(PCSC_LOG_INFO,
+		Log1(PCSC_LOG_DEBUG,
 			"No bundle files in pcsc drivers directory: " PCSCLITE_HP_DROPDIR);
-		Log1(PCSC_LOG_INFO, "Disabling USB support for pcscd");
+		Log1(PCSC_LOG_DEBUG, "Disabling USB support for pcscd");
 	}
 
 	closedir(hpDir);
@@ -365,7 +366,7 @@
 		{
 			int retval;
 
-			Log1(PCSC_LOG_INFO, "Hotplug stopped");
+			Log1(PCSC_LOG_DEBUG, "Hotplug stopped");
 			pthread_exit(&retval);
 		}
 
@@ -405,7 +406,7 @@
 	/* 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, "");
+		bundleTracker[i].libraryPath, "", AUTHSVCNAME);
 
 	return 1;
 }	/* End of function */

Modified: branches/Solaris/src/hotplug_macosx.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/hotplug_macosx.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/hotplug_macosx.c (original)
+++ branches/Solaris/src/hotplug_macosx.c Thu Jun 12 10:28:09 2008
@@ -35,6 +35,7 @@
 
 #undef DEBUG_HOTPLUG
 
+#define	AUTHSVCNAME	"MacOS_USB"
 char ReCheckSerialReaders = FALSE;
 
 /*
@@ -307,8 +308,6 @@
 				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");
@@ -763,7 +762,7 @@
 
 			RFAddReader(a->m_driver->m_friendlyName,
 				PCSCLITE_HP_BASE_PORT + a->m_address, a->m_driver->m_libPath,
-				deviceName);
+				deviceName, AUTHSVCNAME);
 		}
 	}
 

Modified: branches/Solaris/src/ifdwrapper.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/ifdwrapper.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/ifdwrapper.c (original)
+++ branches/Solaris/src/ifdwrapper.c Thu Jun 12 10:28:09 2008
@@ -474,17 +474,18 @@
 	 * END OF LOCKED REGION 
 	 */
 
-	if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
+	if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT) {
 		dwCardStatus |= SCARD_PRESENT;
-	else
-		if (rv == IFD_ICC_NOT_PRESENT)
+	} else {
+		if (rv == IFD_ICC_NOT_PRESENT) {
 			dwCardStatus |= SCARD_ABSENT;
-		else
+		} else
 		{
 			Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
 			return SCARD_E_NOT_TRANSACTED;
 		}
 
+        }
 	/*
 	 * Now lets get the ATR and process it if IFD Handler version 1.0.
 	 * IFD Handler version 2.0 does this immediately after reset/power up
@@ -545,8 +546,7 @@
 	}
 
 	*pdwStatus = dwCardStatus;
-
-	return SCARD_S_SUCCESS;
+        return SCARD_S_SUCCESS;
 }
 
 /*

Added: branches/Solaris/src/instance.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/instance.c?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/instance.c (added)
+++ branches/Solaris/src/instance.c Thu Jun 12 10:28:09 2008
@@ -1,0 +1,531 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ */
+#include "config.h"
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stropts.h>
+#include <syslog.h>
+#include <ucred.h>
+#include <unistd.h>
+#include <wait.h>
+#include <syslog.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/conf.h>
+#include <sys/filio.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <libgen.h>
+#include <thread.h>
+#include <syslog.h>
+#include <sys/time.h>
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+#include "pcsc_config.h"
+#include "pcsclite.h"
+#include "winscard_msg.h"
+#include "winscard_svc.h"
+#include "daemon_utils.h"
+#include "instance.h"
+#include "hotplug.h"
+#include "debuglog.h"
+#include "sys_generic.h"
+#include "powermgt_generic.h"
+
+#define LINEMAX	256
+extern PCSCLITE_MUTEX usbNotifierMutex;
+PCSCLITE_MUTEX contextLookupMutex;
+extern char ReCheckSerialReaders;
+extern char AraKiri;
+extern void at_exit(void);
+static void InstanceSvcRunLoop(int, int);
+static void TimerThread(LPVOID);
+
+extern void SetStdOutErr(char *);
+extern void setupLogging();
+
+char pidPath[LINEMAX];
+
+PCSCLITE_THREAD_T timeoutThreadP;
+PCSCLITE_MUTEX timerMutex;
+#define INFINITE_TIME -1
+int timeRemaining = INFINITE_TIME;
+
+/*
+ * Fifos last the duraction of the instance.
+ */
+char instanceInFifoName[FIFONAME_MAX_BUFSIZE];
+char instanceOutFifoName[FIFONAME_MAX_BUFSIZE];
+int inFifo, outFifo;
+
+#define NONULL(a) (a) ? (a) : "<null>"
+
+
+/*
+ * The following inherits the configuration of the parent
+ * and assumes X Display information is already configured.
+ */
+void
+InitializeInstance(void)
+{
+	static char display[_POSIX_HOST_NAME_MAX + 15];
+	char cmdstr[LINEMAX];
+	char confstr[LINEMAX];
+	char pidbuf[PID_ASCII_SIZE + 1];
+	int  rv, pid;
+	FILE *pidFile;
+
+	Log3(PCSC_LOG_DEBUG,
+		"Initializing new instance: pcscd -I -x :%d, pid=%d\n",
+		pcscCfg.dpyNbr, getpid());
+
+	Log1(PCSC_LOG_DEBUG, "Setup instance signal handlers");
+	SetupSignalHandlers(InstanceExitHandler, 0);
+
+	/*
+	 * Fork to ditch our launcher (ctrun)
+	 */
+	switch(fork()) {
+	case 0:
+		break;
+	case -1:
+		Log1(PCSC_LOG_CRITICAL, "Error forking");
+	default: // Exit if parent or error (fallthru intentional)
+		exit(0);
+	}
+
+	setsid();
+	sprintf(pidPath, "%s/pid", launcherCfg.baseDir);
+	CFGEnsurePathExists(pidPath);
+	sprintf(pidPath, "%s/pid/%d", launcherCfg.baseDir, pcscCfg.dpyNbr);
+	pcscCfg.pcscdPIDFile = strdup(pidPath);
+
+	/*
+	 * Make sure previous instance [if any] isn't running
+	 */
+	if ((pidFile = fopen(pidPath, "rb")) != NULL) {
+		fgets(pidbuf, sizeof (pidbuf), pidFile);
+		fclose(pidFile);
+		pid = atoi(pidbuf);
+		StopInstance(pcscCfg.dpyNbr, pid);
+	}
+	/*
+	 * Replace the file with our pid
+	 */
+	CFGRmPath(pidPath);
+	if ((pidFile = fopen(pidPath, "wb")) != NULL) {
+		fprintf(pidFile, "%u\n", (unsigned) getpid());
+		fclose(pidFile);
+	}
+
+
+	/* If X display # exists, make available to IFD handlers */
+	if (pcscCfg.dpyNbr != -1) {
+		sprintf(display, "DISPLAY=:%d", pcscCfg.dpyNbr);
+		Log2(PCSC_LOG_DEBUG, "putenv(%s)", display);
+		putenv(display);
+	}
+
+	/*
+	 * Resolve wildcard for the base dir
+	 */
+	if (pcscCfg.baseDir != NULL) {
+		if (pcscCfg.baseDirWild) {
+			char dpyNbr[6];
+			if (pcscCfg.dpyNbr == -1) {
+				CFGperror(CFG_UNDEFINED_DISPLAY, "");
+				exit(EXIT_FAILURE);
+			}
+			sprintf(dpyNbr, "%d", pcscCfg.dpyNbr);
+			CFGresolveWildcard(&pcscCfg.baseDir, dpyNbr);
+		}
+	}
+
+	/*
+	 * Look for parent fifos.  We're launched and they're not there,
+	 * something is wrong.
+	 */
+	sprintf(instanceInFifoName, "%s/fifo/%d.o",
+		launcherCfg.baseDir, pcscCfg.dpyNbr);
+
+	sprintf(instanceOutFifoName,"%s/fifo/%d.i",
+		launcherCfg.baseDir, pcscCfg.dpyNbr);
+
+	if ((inFifo = open(instanceInFifoName, O_RDWR)) < 0) {
+		Log2(PCSC_LOG_CRITICAL,
+		     "Couldn't open fifo %s", strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	if ((outFifo = open(instanceOutFifoName, O_RDWR)) < 0) {
+		Log2(PCSC_LOG_CRITICAL,
+		     "Couldn't open fifo %s", strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+
+	/*
+	 * Launch Xserver tag-specific initialization script to
+	 * setup pcscd basedir and environment for this instance.
+	 */
+	Log1(PCSC_LOG_DEBUG, "Launching instance setup script:");
+	Log2(PCSC_LOG_DEBUG, "  script  = %s",
+		NONULL(pcscCfg.instanceScript));
+	Log2(PCSC_LOG_DEBUG, "  conf    = %s",
+		NONULL(pcscCfg.pcscConfigFile));
+	Log2(PCSC_LOG_DEBUG, "  base    = %s",
+		NONULL(pcscCfg.baseDir));
+	Log2(PCSC_LOG_DEBUG, "  display = %d", pcscCfg.dpyNbr);
+	Log2(PCSC_LOG_DEBUG, "  pid     = %d", getpid());
+
+	sprintf(cmdstr, "%s -m START -x :%d -P %s -b %s -p %d",
+	    pcscCfg.instanceScript, pcscCfg.dpyNbr,
+	    pcscCfg.pcscConfigFile, pcscCfg.baseDir,
+	    getpid());
+
+	if (system(cmdstr) < 0)
+		Log3(PCSC_LOG_CRITICAL,
+		"system(\"%s\") failed: %s", cmdstr, strerror(errno));
+
+	/*
+	 * Adapt server configuration file paths, assigning
+	 * a default value (based on header constants) to any path
+	 * unspecified by the administrator.
+	 */
+	if (pcscCfg.readerConfigFile == NULL)
+		pcscCfg.readerConfigFile =
+		    CFGRetrofitPath(
+		       PCSCLITE_CONFIG_DIR "/reader.conf", "/etc");
+	else
+		pcscCfg.readerConfigFile =
+		    CFGRetrofitPath(pcscCfg.readerConfigFile, NULL);
+
+	if (pcscCfg.ifdPluginDir != NULL)
+		pcscCfg.ifdPluginDir =
+		    CFGRetrofitPath(pcscCfg.ifdPluginDir, NULL);
+
+	if (pcscCfg.useMappedMemory) {
+		if (pcscCfg.pcscdMemMappedFile == NULL)
+			pcscCfg.pcscdMemMappedFile =
+			    CFGRetrofitPath(PCSCLITE_PUBSHM_FILE, "/var/run");
+		else
+			pcscCfg.pcscdMemMappedFile =
+			CFGRetrofitPath(pcscCfg.pcscdMemMappedFile, NULL);
+	} else {
+		pcscCfg.pcscdMemMappedFile = NULL;
+	}
+
+	if (pcscCfg.transportType == SOCKET_UNIX) {
+		if (pcscCfg.netBindFile == NULL) {
+			pcscCfg.netBindFile =
+			    CFGRetrofitPath(PCSCLITE_CSOCK_NAME, "/var/run");
+		} else {
+			pcscCfg.netBindFile =
+			    CFGRetrofitPath(pcscCfg.netBindFile, NULL);
+		}
+	}
+
+	if (pcscCfg.useMappedMemory) {
+		CFGEnsurePathExists(
+		    SYS_Dirname(pcscCfg.pcscdMemMappedFile));
+	}
+
+
+	/*
+	 * Display this instance's configuration context.
+	 */
+	CFGdumpCfg(NULL);
+	/*
+	 * Allocate memory for reader structures
+	 */
+
+	RFAllocateReaderSpace();
+	/*
+	 * Load reader.conf for this instance and start
+	 * ifd handlers.
+	 */
+	if (pcscCfg.readerConfigFile && strlen(pcscCfg.readerConfigFile) > 0 &&
+	    CFGDoesFileExist(pcscCfg.readerConfigFile))  {
+		Log2(PCSC_LOG_DEBUG, "Loading static readers from %s\n",
+			pcscCfg.readerConfigFile);
+		rv = RFStartSerialReaders(pcscCfg.readerConfigFile);
+		if (rv != 0) {
+			Log3(PCSC_LOG_CRITICAL,
+			     "Invalid reader config file:%s: %s",
+			     pcscCfg.readerConfigFile, strerror(errno));
+			at_exit();
+		}
+		Log1(PCSC_LOG_DEBUG, "Readers loaded\n");
+
+	} else {
+		Log1(PCSC_LOG_DEBUG, "No static readers configured");
+	}
+	usleep(200000);
+	/*
+	 * Set the default globals
+	 */
+	g_rgSCardT0Pci.dwProtocol = SCARD_PROTOCOL_T0;
+	g_rgSCardT1Pci.dwProtocol = SCARD_PROTOCOL_T1;
+	g_rgSCardRawPci.dwProtocol = SCARD_PROTOCOL_RAW;
+
+	InstanceSvcRunLoop(inFifo, outFifo);
+
+}
+
+/**
+ * @brief The Server's Message Queue Listener function.
+ *
+ * An endless loop calls the function \c SHMProcessEventsServer() to check for
+ * messages sent by clients.
+ * If the message is valid, \c CreateContextThread() is called to serve this
+ * request.
+ */
+static void
+InstanceSvcRunLoop(int inFifo, int outFifo)
+{
+	int rv = 0;
+	DWORD dwClientID; /* Connection ID used to reference the Client */
+
+	Log1(PCSC_LOG_DEBUG, "Main Instance run loop starting...\n");
+	/*
+	 * Start instance timer thread, and begin timeout countdown
+	 * If we don't get any connections, we'll eventually timeout.
+	 */
+	if (SYS_ThreadCreate(&timeoutThreadP, THREAD_ATTR_DETACHED,
+		(PCSCLITE_THREAD_FUNCTION( )) TimerThread,
+		(LPVOID) pcscCfg.instanceTimeout) != 1) {
+			Log1(PCSC_LOG_CRITICAL, "SYS_ThreadCreate failed");
+	}
+
+	StartInstanceTimer();
+
+	if (ContextsInitialize() == -1) {
+		Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
+		exit(EXIT_FAILURE);
+	}
+
+	signal(SIGALRM, SIG_IGN); // Ignore SIGALRM (which Solaris sends)
+	signal(SIGPIPE, SIG_IGN);
+
+	/*
+	 * This function always returns zero
+	 */
+	rv = SYS_MutexInit(&usbNotifierMutex);
+
+	/*
+	 * Set up the search for USB/PCMCIA devices
+	 */
+	HPSearchHotPluggables();
+	HPRegisterForHotplugEvents();
+
+	/*
+	 * Set up the power management callback routine
+	 */
+	PMRegisterForPowerEvents();
+
+	for (;;) {
+		switch (rv = ReceiveClientFd(inFifo, outFifo,
+		    (int *)&dwClientID, pcscCfg.fifoPingTimeout)) {
+		case 0:
+			/*
+			 * Send ACK message to client
+			 */
+			SendMsg(dwClientID, CONNECTOK);
+
+			Log2(PCSC_LOG_DEBUG,
+				"Client fd=%d received from launcher",
+				dwClientID);
+			Log2(PCSC_LOG_DEBUG,
+				"Creating context fd=%d", dwClientID);
+
+			rv = CreateContextThread(&dwClientID);
+			if (rv != SCARD_S_SUCCESS) {
+				Log1(PCSC_LOG_ERROR,
+				   "Problem during context thread creation");
+				AraKiri = TRUE;
+			}
+			break;
+		case ERROR:
+			Log1(PCSC_LOG_ERROR,
+			     "Error in ReceiveClientFD");
+			break;
+		case TIMEOUT:
+			Log1(PCSC_LOG_ERROR,
+			     "Timed out reading non-FD message");
+			break;
+		case INTERRUPTED:
+			// Interrupted by "PING", silently re-start
+			break;
+		case TERMINATED:
+			Log1(PCSC_LOG_DEBUG,
+				"InstanceSvcRunLoop: pcscd Terminated");
+			sleep(3600);  //If we're not dead already, wait for it
+			break;
+		case SEVERE:
+			/* Don't display if exiting or re-reading config */
+			if ((!AraKiri) && (!ReCheckSerialReaders))
+				Log1(PCSC_LOG_ERROR, "Err in ReceiveClientFd");
+			break;
+		}
+
+		if (AraKiri) {
+			/*
+			 * Stop hotplug thread, wait for exit.
+			 */
+			HPStopHotPluggables();
+			SYS_Sleep(1);
+			/*
+			 * Stop all drivers
+			 */
+			RFCleanupReaders(1);
+		}
+	}
+}
+
+
+void
+InstanceExitHandler(int signo)
+{
+	char cmdstr[1024], outFifoName[256];
+
+	if (signo != 0)
+		Log2(PCSC_LOG_DEBUG, "Received signal %d. Cleaning up\n", signo);
+	/*
+	 * This helps the launcher detect instance death faster
+	 * than having to time out on a PING.
+	 */
+	Log1(PCSC_LOG_DEBUG, "Sending INSTANCE_DIED to fifo\n");
+	SendCmd(outFifo, INSTANCE_DIED_TOKEN);
+
+	/*
+	 * Remove fifos (after queing message to them)
+	 * so launcher doesn't try to
+	 * contact us over them after we're gone.
+	 */
+	(void) CFGRmPath(instanceOutFifoName);
+	(void) CFGRmPath(instanceInFifoName);
+
+	/*
+	 * Remove our pid tracking file
+	 */
+	(void) CFGRmPath(pcscCfg.pcscdPIDFile);
+
+	/*
+	 * Run the helper script in termination mode
+	 */
+	sprintf(cmdstr, "%s -m STOP -x :%d -P %s -b %s -p %d",
+	    pcscCfg.instanceScript,  pcscCfg.dpyNbr,
+	    pcscCfg.pcscConfigFile,  pcscCfg.baseDir,
+	    getpid());
+
+	Log2(PCSC_LOG_DEBUG, "Invoking instance script to clean-up:\n%s\n", cmdstr);
+
+	if (system(cmdstr) < 0)  {
+		Log3(PCSC_LOG_CRITICAL,
+		    "system(\"%s\") failed: %s", cmdstr, strerror(errno));
+	}
+
+
+	Log1(PCSC_LOG_DEBUG, "Instance shutdown complete. Exiting...\n");
+	pcscCfg.pcscdExiting = 1;
+	kill(getpid(), SIGKILL);
+	exit(0); // just in case
+
+/*
+ * We don't want to get hung up in this code... probably just remove it
+	HPStopHotPluggables();
+	SYS_Sleep(1);
+	RFCleanupReaders(0); // Unload reader drivers
+	exit(0);
+*/
+}
+
+/**
+ * @brief Thread to terminate process after some period inactivty
+ *
+ * This is only used in 'launcher mode' and if enabled.
+ * One thread lasts the duration of the process.
+ * The timeout can be canceled or reinstated at will.
+ */
+static void TimerThread(LPVOID arg)
+{
+	for (;;) {
+		SYS_MutexLock(&timerMutex);
+		if (timeRemaining != INFINITE_TIME) {
+			if (--timeRemaining == 0) {
+				Log2(PCSC_LOG_DEBUG,
+				    "instance (pid=%d): "
+				    "Inactivity timer expired.", getpid());
+				InstanceExitHandler(0);
+			}
+		}
+		SYS_MutexUnLock(&timerMutex);
+		sleep(1);
+	}
+}
+
+void StartInstanceTimer()
+{
+	SYS_MutexLock(&timerMutex);
+	if (pcscCfg.instanceTimeout > 0)
+		timeRemaining = pcscCfg.instanceTimeout;
+	SYS_MutexUnLock(&timerMutex);
+	if (pcscCfg.instanceTimeout > 0) {
+		Log3(PCSC_LOG_DEBUG,
+			"instance (pid=%d): %d sec exit timer started",
+			getpid(), pcscCfg.instanceTimeout);
+	}
+}
+
+void CancelInstanceTimer()
+{
+	int saveRemaining;
+
+	SYS_MutexLock(&timerMutex);
+	saveRemaining = timeRemaining;
+	timeRemaining = INFINITE_TIME;
+	SYS_MutexUnLock(&timerMutex);
+
+	if (saveRemaining != INFINITE_TIME) {
+		Log2(PCSC_LOG_DEBUG,
+			"pcscd pid=%d inactivity timeout canceled", getpid());
+
+		Log3(PCSC_LOG_DEBUG, "%d out of %d secs remaining.",
+			saveRemaining, pcscCfg.instanceTimeout);
+	}
+}
+
+void
+LockContextLookup()
+{
+	SYS_MutexLock(&contextLookupMutex);
+}
+
+void
+UnlockContextLookup()
+{
+	SYS_MutexUnLock(&contextLookupMutex);
+}
+
+

Added: branches/Solaris/src/instance.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/instance.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/instance.h (added)
+++ branches/Solaris/src/instance.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,37 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2000-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * <NEED TO FIX KEYWORDS>
+ */
+
+
+#ifndef	__instance_h__
+#define	__instance_h__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define PID_ASCII_SIZE 11
+
+void InitializeInstance(void);
+void StartInstanceTimer(void);
+void CancelInstanceTimer(void);
+void LockContextLookup(void);
+void UnlockContextLookup(void);
+void InstanceExitHandler(int);
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif
+
+#endif

Added: branches/Solaris/src/launcher.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/launcher.c?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/launcher.c (added)
+++ branches/Solaris/src/launcher.c Thu Jun 12 10:28:09 2008
@@ -1,0 +1,1014 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ *
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ */
+
+
+#include "config.h"
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stropts.h>
+#include <syslog.h>
+#include <ucred.h>
+#include <unistd.h>
+#include <wait.h>
+#include <syslog.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/conf.h>
+#include <sys/filio.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <libgen.h>
+#include <thread.h>
+#include <syslog.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+#include "pcsc_config.h"
+#include "pcsclite.h"
+#include "clientcred.h"
+#include "auth.h"
+#include "launcher.h"
+#include "daemon_utils.h"
+#include "misc.h"
+#include "debuglog.h"
+#include "validate.h"
+#include "sys_generic.h"
+#include "thread_generic.h"
+#include "pcscd-validate.h"
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#define NONULL(a) (a) ? (a) : "<null>"
+
+
+extern char *execPath;
+extern int Init;
+
+struct {
+	int nbrInstancesLaunched;
+	int nbrInstancesActive;
+} LauncherStats;
+
+typedef struct fdQ {
+	struct fdQ *next;
+	int fd;
+} fdQ_t;
+
+//#define DEFER_FD_CLOSE
+
+typedef struct pcscd {
+	struct pcscd *next;		// pointer to next entry
+	int dpyNbr;			// display instance services
+	int pid;			// pid obtained from ping
+	int inFifo;			// Receive fifo
+	int outFifo;			// Xmit fifo
+	time_t launchTime;		// Time of last launch
+	char inFifoName[256];		// Receive fifo Name
+	char outFifoName[256];		// Xmit fifo Name
+	int nbrFdsSentToInstance;	// Total fds  sent to instance
+	char logbuf[256];		// Holds messages
+	int fdToSend;			// most recent fd to send to instance
+	int nbrFdsQueued;		// Count of fd's in queue
+	fdQ_t *fdQhead;			// List of fds to send to instance
+	PCSCLITE_THREAD_T tid		; // instance timeout thread
+	PCSCLITE_MUTEX  fdQLock;	// Locks access to fdQ
+	PCSCLITE_COND   fdQNotify;	// Notify that queue has data
+#ifdef DEFER_FD_CLOSE
+	fdQ_t *garbageFdQhead;		// List of fds to close
+	PCSCLITE_MUTEX  garbageFdQlock; // Locks access to garbageFdQ
+#endif
+} pcscd_t;
+
+PCSCLITE_MUTEX instDBm;			// instance database lock
+pcscd_t *instanceQ;			// Instance queue listhead
+
+#undef ERROR
+#define ERROR -1
+#undef SUCCESS
+#define SUCCESS 0
+
+static int  PopFd(fdQ_t **);
+static void QueueFd(fdQ_t **, int);
+static pcscd_t *FindInstanceByDpy(pcscd_t **, int);
+static void AddInstance(pcscd_t **, pcscd_t *);
+static void RemoveInstance(pcscd_t **, pcscd_t *);
+static void QueueFdToInstance(int, int);
+static void IncomingClientConnect(LPVOID);
+static void LauncherExitHandler(int);
+static void ManageInstance(LPVOID);
+static int  IsPrefixed(char *f, char *);
+static void ExecInstance(pcscd_t *inst);
+static int  ConnectInstance(pcscd_t *);
+static int  ForwardClientToInstance(int fdToSend, pcscd_t *);
+static int  LaunchInstanceDaemon(pcscd_t *);
+static void CloseInstanceFifos(pcscd_t *);
+static int  WaitForEnqueuedFd(pcscd_t *);
+static void AbortInstance(pcscd_t *);
+static void EradicateInstance(pcscd_t *);
+static void PeriodicCleanup(LPVOID);
+static int IsInstanceRunning(pcscd_t *);
+
+void signal_trap(int);
+int wellKnownPortSocket;
+
+
+static void
+ManageInstance(LPVOID context) {
+	pcscd_t *inst = (pcscd_t *)context;
+	int rv, fd = 0;
+	char fifoDirPath[MAXPATHLEN];
+
+	bzero(fifoDirPath, MAXPATHLEN);
+
+	sprintf(fifoDirPath, "%s/fifo", pcscCfg.baseDir);
+	if (CFGEnsurePathExists(fifoDirPath) < 0) {
+		Log2(PCSC_LOG_CRITICAL, "Err creating dir %s\n", fifoDirPath);
+		return; // thread exit;
+	}
+	sprintf(inst->outFifoName, "%s/%d.o", fifoDirPath, inst->dpyNbr);
+	sprintf(inst->inFifoName,  "%s/%d.i", fifoDirPath, inst->dpyNbr);
+
+	for(;;) {
+		while (ConnectInstance(inst) == ERROR) {
+			if (LaunchInstanceDaemon(inst) == ERROR) {
+				if (inst->dpyNbr >= 0) {
+					Log1(PCSC_LOG_ERROR,
+					     "Terminating instance thread");
+					EradicateInstance(inst);
+					return;
+				}
+			}
+		}
+		do {
+			if (fd == 0)
+				fd = WaitForEnqueuedFd(inst);
+			if ((rv = ForwardClientToInstance(fd, inst)) == SUCCESS)
+				fd = 0;
+		} while (rv == SUCCESS);
+	}
+}
+
+static int
+ConnectInstance(pcscd_t *inst)
+{
+	int rv, pid;
+
+	if (inst->dpyNbr < 0) {
+		Log3(PCSC_LOG_DEBUG,
+		    "<%4.4x> Error: Cannot connect to :%d",
+		    thr_self(), inst->dpyNbr);
+
+	}
+	Log3(PCSC_LOG_DEBUG,
+	    "<%4.4x> Connect to :%d fifos", thr_self(), inst->dpyNbr);
+
+	inst->pid = 0;
+	if (inst->inFifo == 0 &&
+	    (inst->inFifo = OpenFifo(inst->inFifoName, 0)) < 0) {
+		Log3(PCSC_LOG_DEBUG, "<%4.4x> No in fifo for :%d",
+		    thr_self(), inst->dpyNbr);
+		return ERROR;
+	}
+
+	if (inst->outFifo == 0 &&
+	    (inst->outFifo = OpenFifo(inst->outFifoName, 1)) < 0) {
+		Log3(PCSC_LOG_DEBUG, "<%4.4x> No out fifo for :%d",
+		    thr_self(), inst->dpyNbr);
+		return ERROR;
+	}
+
+	if (!IsInstanceRunning(inst))
+		return ERROR;
+
+	rv = PingFifo(inst->outFifo, inst->inFifo, pcscCfg.fifoPingTimeout);
+	if (rv == INSTANCE_DIED) {
+		AbortInstance(inst);
+		Log3(PCSC_LOG_DEBUG, "<%4.4x> Instance :%d dead or dying",
+		    thr_self(), inst->dpyNbr);
+		return ERROR;
+
+	} else if (rv < 0) {
+		AbortInstance(inst);
+		syslog(LOG_ERR, "Err contacting instance :%d. Abandoning", inst->dpyNbr);
+		Log3(PCSC_LOG_DEBUG,
+		    "<%4.4x> Ping :%d fail. Abandoning", thr_self(), inst->dpyNbr);
+		return ERROR;
+
+	}
+	pid = rv;
+	if (pid != inst->pid) {
+		/* Make sure old instance is gone */
+		if (inst->pid != 0)
+			StopInstance(inst->dpyNbr, inst->pid);
+		sprintf(inst->logbuf,
+		    "<%4.4x> Using new pid=%d for :%d, prev=%d",
+		    thr_self(), pid, inst->dpyNbr, inst->pid);
+		Log2(PCSC_LOG_DEBUG, "%s", inst->logbuf);
+	}
+	inst->pid = pid;
+	return SUCCESS;
+}
+
+static int
+ForwardClientToInstance(int fdToSend, pcscd_t *inst)
+{
+	int sendStat;
+	if (pcscCfg.verbose) {
+		sprintf(inst->logbuf,
+			"<%4.4x> XMIT#:%d fd=%d->instance :%d (pid=%d)",
+			thr_self(), inst->nbrFdsSentToInstance,
+			inst->fdToSend, inst->dpyNbr, inst->pid);
+		Log2(PCSC_LOG_DEBUG, "%s", inst->logbuf);
+	}
+
+	if (!IsInstanceRunning(inst))
+		return ERROR;
+
+	inst->fdToSend = fdToSend;
+	sendStat = SendClientFd(inst->outFifo, inst->inFifo, inst->fdToSend,
+	    pcscCfg.fifoPingTimeout);
+
+	if (sendStat < 0) {
+		if (sendStat == INSTANCE_DIED) {
+			Log2(PCSC_LOG_DEBUG, "Fifo message: :%d dead or dying",
+			    inst->dpyNbr);
+		} else {
+			Log2(PCSC_LOG_CRITICAL,  "Unexpected failure to send fd to "
+			    "pcscd instance :%d abandoning\n", inst->dpyNbr);
+		}
+		return ERROR;
+	}
+	++inst->nbrFdsSentToInstance;
+
+#ifndef DEFER_FD_CLOSE
+	SYS_CloseFile(inst->fdToSend);
+#else
+{
+	int fdToClose;
+	if (pcscCfg.verbose)
+		Log3(PCSC_LOG_DEBUG, "<%4.4x> Queue fd=%d to close",
+		    thr_self(), inst->fdToSend);
+	SYS_MutexLock(&inst->garbageFdQlock);
+	if ((fdToClose = PopFd(&inst->garbageFdQhead)) != -1) {
+		if (pcscCfg.verbose)
+			Log3(PCSC_LOG_DEBUG,
+			    "<%4.4x> Completing deferred "
+			    "close of fd: %d",
+			    thr_self(), fdToClose);
+		SYS_CloseFile(fdToClose);
+	}
+	SYS_MutexUnLock(&inst->garbageFdQlock);
+
+	SYS_MutexLock(&inst->garbageFdQlock);
+	QueueFd(&inst->garbageFdQhead, inst->fdToSend);
+	SYS_MutexUnLock(&inst->garbageFdQlock);
+}
+#endif
+
+	return SUCCESS;
+}
+
+static int
+LaunchInstanceDaemon(pcscd_t *inst)
+{
+	int hyperbole = 0, chkcnt = 0, pid;
+	/*
+	 * Clean up old fifos and pid - makes for faster start up.
+	 */
+	CloseInstanceFifos(inst);
+	CFGRmPath(inst->inFifoName);
+	CFGRmPath(inst->outFifoName);
+	DeletePidFile(inst->dpyNbr);
+	StopInstance(inst->dpyNbr, 0);
+
+	 /*
+	  * If we've relaunched too many times too fast, terminate instance.
+	  */
+	if (time(NULL) - inst->launchTime < pcscCfg.relaunchInterval) {
+	    if (++hyperbole > pcscCfg.relaunchThreshold) {
+		Log1(PCSC_LOG_ERROR,
+		    "**************************************");
+		syslog(LOG_ERR, "Re-launching pcscd instance :%d "
+			"too frequencly.  Abandoning\n", pcscCfg.dpyNbr);
+		Log2(PCSC_LOG_ERROR,
+		    "Relaunching instance :%d too frequently",
+		    inst->dpyNbr);
+		Log1(PCSC_LOG_ERROR,
+		    "**************************************");
+		return ERROR;
+	    }
+	}
+
+	Log1(PCSC_LOG_DEBUG,"**************************************");
+	Log2(PCSC_LOG_DEBUG,"Launching new instance for dpy :%d", inst->dpyNbr);
+	Log1(PCSC_LOG_DEBUG,"**************************************");
+
+	Log3(PCSC_LOG_DEBUG, "<%4.4x> Making new fifos for :%d",
+	    thr_self(), inst->dpyNbr);
+
+	if (mkfifo(inst->inFifoName, S_IWUSR | S_IRUSR) < 0) {
+		Log4(PCSC_LOG_ERROR,
+		    "Couldn't create fifo %s for instance :%d: %s",
+		     inst->inFifoName, inst->dpyNbr, strerror(errno));
+	}
+	if (mkfifo(inst->outFifoName, S_IWUSR | S_IRUSR) < 0) {
+		Log4(PCSC_LOG_ERROR,
+		    "Couldn't create fifo %s for instance :%d: %s",
+		     inst->outFifoName, inst->dpyNbr, strerror(errno));
+	}
+
+	/*
+	 * Exec the new instance in such way as to prevent zombies
+	 */
+	Log2(PCSC_LOG_DEBUG, "Forking new pcscd instance for display :%d",
+		inst->dpyNbr);
+	switch(fork()) {
+	case 0: // child
+		setsid(); // Become session leader w/o controlling tty
+		switch(fork()) {
+		case 0: // child
+			ExecInstance(inst);
+		case -1:
+			Log2(PCSC_LOG_CRITICAL,
+			     "Can't fork: %s", strerror(errno));
+			return ERROR;
+		default:  // parrent: Allow session leader to exit
+			exit(0);
+		}
+	case -1:
+		Log2(PCSC_LOG_CRITICAL,
+		     "Can't fork: %s", strerror(errno));
+		return ERROR;
+	}
+
+	inst->launchTime = time(NULL);
+	/*
+	 * Wait for pid file to appear
+	 */
+	Log1(PCSC_LOG_DEBUG, "Waiting for pid file to appear");
+	while ((pid = GetPidFromFile(inst->dpyNbr)) == 0 &&
+		++chkcnt < MAX_INST_CHECKS)
+			usleep(100000);
+
+	++LauncherStats.nbrInstancesLaunched;
+
+	if (chkcnt >= MAX_INST_CHECKS) {
+		Log3(PCSC_LOG_CRITICAL,
+		    "FATAL: Instance pid file for :%d not created within %d seconds",
+		     inst->dpyNbr, MAX_INST_CHECKS);
+		return ERROR;
+	}
+
+	Log3(PCSC_LOG_DEBUG, "Found pid=%d for new instance (launch #%d)",
+		pid, LauncherStats.nbrInstancesLaunched);
+	return SUCCESS;
+}
+
+static void
+IncomingClientConnect(LPVOID context) {
+
+	int rv, clientSockFd = (int)context;
+	PCSCLITE_CRED_T cred;
+	char line[LINEMAX], logbuf[LINEMAX], *cp;
+	int dpyNbr, screenNbr;
+	in_addr_t xHostIp;
+	thread_t tid = thr_self();
+
+	if (pcscCfg.verbose) {
+		write(2, "\n", 1);
+		Log3(PCSC_LOG_DEBUG,
+			"<%4.4x> Validation thread started for (fd=%d) ",
+			tid, clientSockFd);
+	}
+	/*
+	 * Protocol requires connecting clients to immediately
+	 * present X display that owns reader.
+	 */
+	memset(line, 0, sizeof (line));
+	if ((rv = read(clientSockFd, line, sizeof(line))) < 0) {
+		while (rv < 0 && (errno == EINTR || errno == EAGAIN)) {
+			sleep(50000);
+			rv = read(clientSockFd, line, sizeof(line));
+		}
+		if (rv < 0) {
+			Log3(PCSC_LOG_ERROR,
+			    "<%4.4x> Error reading from client sock: %s",
+			    tid, strerror(errno));
+			Log3(PCSC_LOG_ERROR,
+			    "<%4.4x> closed (fd=%d), thread exiting",
+			    tid, clientSockFd);
+			SYS_CloseFile(clientSockFd);
+		}
+		return;
+	}
+
+	/*
+	 * Parse display info.  Terminate conn. immediately on err.
+	 */
+	if ((cp = strchr(line, '\r')) != NULL)
+	     *cp = '\0';
+	/*
+	 * If we got pinged, reply and exit (don't need to log it)
+	 */
+	if (strncasecmp(line, "PING", 4) == 0) {
+		int pid;
+		char resp[20], logresp[20];
+		if (line[5] == '\0') {
+			SYS_CloseFile(clientSockFd);
+			return;
+		}
+		pid = atoi(line + 4);
+
+		if (pcscCfg.verbose > 1)
+			Log4(PCSC_LOG_DEBUG,
+			    "<%4.4x> Validation (fd=%d) recvd: \"%s\"",
+			    tid, clientSockFd, line);
+
+		sprintf(logresp, "ACK %d", pid);
+		sprintf(resp, "%s\n", logresp);
+
+		if (pcscCfg.verbose > 1)
+			Log4(PCSC_LOG_DEBUG,
+			    "<%4.4x> Validation (fd=%d) reply: \"%s\"",
+			    tid, clientSockFd, logresp);
+
+		SendMsg(clientSockFd, resp);
+		SYS_CloseFile(clientSockFd);
+		return;
+	}
+
+	if (pcscCfg.verbose)
+		Log4(PCSC_LOG_DEBUG,
+			"<%4.4x> Validation thr (fd=%d) received: \"%s\"",
+			tid, clientSockFd, line);
+	/*
+	 * Parse X Display parameter from client.
+	 */
+	rv = CFGParseXdisplay(line, &dpyNbr, &screenNbr, &xHostIp);
+	if (rv != CFG_SUCCESS || dpyNbr == -1) {
+
+		Log3(PCSC_LOG_ERROR,
+		    "<%4.4x> Received invalid $DISPLAY info: %s", tid, line);
+		Log3(PCSC_LOG_ERROR,
+		    "<%4.4x> closed (fd=%d), thread exiting",
+		    tid, clientSockFd);
+		syslog(LOG_ERR,
+			"Launcher: Receive invalid $DISPLAY: %s", line);
+		Log3(PCSC_LOG_ERROR,
+		    "<%4.4x> closed (fd=%d), thread exiting",
+		    tid, clientSockFd);
+		SYS_CloseFile(clientSockFd);
+		return;
+	}
+	if (pcscCfg.useAuthentication) {
+		void *ctx;
+
+		if (AUTHGetClientCreds(clientSockFd, &cred) < 0) {
+			Log3(PCSC_LOG_ERROR,
+			    "<%4.4x> Error getting creds %s", tid, strerror(errno));
+			Log2(PCSC_LOG_ERROR,
+			    "<%4.4x> Couldn't get client creds. Terminating "
+			    "client conn.", tid);
+			Log3(PCSC_LOG_ERROR,
+			    "<%4.4x> closed (fd=%d), thread exiting",
+			    tid, clientSockFd);
+			SYS_CloseFile(clientSockFd);
+			return;
+		}
+		cred.dpyNbr = dpyNbr;
+		cred.screenNbr = screenNbr;
+		cred.clientXhostIP = xHostIp;
+
+		sprintf(logbuf,	"<%4.4x> [ PID:%d uid:(%d, %d) %s:%d.%d ]",
+		      tid, (int)cred.pid, (int)cred.euid, (int)cred.egid,
+		      inet_ntoa(*(struct in_addr *)&cred.clientXhostIP),
+		      cred.dpyNbr, cred.screenNbr);
+
+		write(2, "\n", 1);
+		Log2(PCSC_LOG_DEBUG, "%s", logbuf);
+
+		char *facilityTag = NULL;
+		void *resource = NULL;
+		unsigned int flags;
+
+		if (VALgetDisplayStatus(dpyNbr, &ctx, &flags) != DISPLAY_IS_VALID ||
+		    VALgetDisplayTag(dpyNbr, ctx, &facilityTag) == NULL) {
+			Log3(PCSC_LOG_ERROR,
+			    "<%4.4x> Display :%d failed validation check",
+			    tid, dpyNbr);
+			SendMsg(clientSockFd, AUTHFAIL);
+			SYS_CloseFile(clientSockFd);
+			Log3(PCSC_LOG_DEBUG,
+			    "<%4.4x> closed (fd=%d), thread exiting",
+			    tid, clientSockFd);
+			if (facilityTag != NULL)
+				free(facilityTag);
+			return;
+		}
+		VALgetDisplayResource(cred.dpyNbr, ctx, &resource);
+		if (AUTHCheckDaemon((const char *)facilityTag, &cred,
+		    resource) < 0) {
+			Log2(PCSC_LOG_ERROR,
+			    "<%4.4x> Auth check failed. Terminating client",
+			    tid);
+			SendMsg(clientSockFd, AUTHFAIL);
+			SYS_CloseFile(clientSockFd);
+			Log3(PCSC_LOG_DEBUG,
+			    "<%4.4x> closed (fd=%d), thread exiting",
+			    tid, clientSockFd);
+			if (facilityTag != NULL)
+				free(facilityTag);
+			if (resource != NULL)
+				free(resource);
+			return;
+		}
+		Log3(PCSC_LOG_DEBUG,
+		    "<%4.4x> Authenticated client \"%s\"",
+		    tid, NONULL(facilityTag));
+
+		if (flags & DISPLAY_HAS_NEW_PROVIDER) {
+			 Log3(PCSC_LOG_DEBUG,
+				 "\"%s\" display :%d has a new provider",
+				 facilityTag, dpyNbr);
+			 StopInstance(dpyNbr, 0);
+		 }
+		 if (facilityTag != NULL)
+			free(facilityTag);
+		 if (resource != NULL)
+			free(resource);
+	}
+	QueueFdToInstance(dpyNbr, clientSockFd);
+}
+
+
+void
+Launcher(int wellKnownPort)
+{
+	struct sockaddr_in ipaddr, clientIp;
+	struct linger l = {0, 0};
+	static socklen_t len;
+	unsigned int threadp;
+	unsigned int mode;
+	int clientSockFd;
+	int sndbufsize = 4096;
+	int rcvbufsize = 4096;
+	l.l_onoff  = 1;
+	l.l_linger = 0;
+
+	Log1(PCSC_LOG_DEBUG, "Setup launcher signal handlers\n");
+	SetupSignalHandlers(LauncherExitHandler, 1);
+
+	/*
+	 * Create client connect socket
+	 */
+	if ((wellKnownPortSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		Log2(PCSC_LOG_CRITICAL,
+			"Create socket: %s", strerror(errno));
+		return;
+	}
+	/*
+	 * Don't get stuck on CLOSED_WAIT / TIMED_WAIT
+	 */
+	mode = 1;
+	if (setsockopt(wellKnownPortSocket, SOL_SOCKET, SO_REUSEADDR,
+	    &mode, sizeof (mode)) < 0) {
+	       Log2(PCSC_LOG_CRITICAL,
+		   "setsockopt()/SO_REUSEADDR: %s", strerror(errno));
+	       return;
+	}
+	/*
+	 * No reason to linger, turn off for quicker recovery.
+	 */
+	if (setsockopt(wellKnownPortSocket, SOL_SOCKET, SO_LINGER,
+	     &l, sizeof (l)) < 0) {
+		Log2(PCSC_LOG_CRITICAL,
+		    "setsockopt()/SO_LINGER: %s", strerror(errno));
+		return;
+	}
+	/*
+	 * Since launched instances don't need this socket.
+	 * make sure it is automatically closed when we exec.
+	 */
+	if (fcntl(wellKnownPortSocket, F_SETFD, FD_CLOEXEC) < 0) {
+		Log2(PCSC_LOG_CRITICAL,
+		    "fcntl(FD_CLOEXEC) %s", strerror(errno));
+		return;
+	}
+
+	/*
+	 * Bind client connect socket to well known port
+	 */
+	bzero((char *)&ipaddr, sizeof (ipaddr));
+
+	ipaddr.sin_family = AF_UNIX;
+	ipaddr.sin_addr.s_addr = INADDR_ANY;
+	ipaddr.sin_port = htons(wellKnownPort);
+
+	if (bind(wellKnownPortSocket, (struct sockaddr *) &ipaddr,
+	    sizeof(ipaddr)) < 0) {
+		Log2(PCSC_LOG_CRITICAL,
+		    "Bind to socket: %s", strerror(errno));
+		return;
+	 }
+	/*
+	 * Listen for client connections forever.
+	 */
+	for(;;) {
+
+		if (pcscCfg.verbose) {
+			write(2, "\n", 1);
+			Log1(PCSC_LOG_DEBUG, "(Listen for client connection)");
+		}
+
+		if (listen(wellKnownPortSocket, 5) < 0)  {
+			Log2(PCSC_LOG_DEBUG,
+			    "Listen on socket: %s", strerror(errno));
+			return;
+		}
+		/*
+		 * Accept connections on well-known port.
+		 */
+
+		errno = 0;
+		len = sizeof (clientIp);
+		do {
+			if ((clientSockFd = accept(wellKnownPortSocket,
+			    (struct sockaddr *) &clientIp, &len)) < 0 &&
+			     errno != EINTR) {
+				     Log2(PCSC_LOG_CRITICAL,
+					  "Accept on socket: %s", strerror(errno));
+				     return;
+			}
+		} while (clientSockFd < 0 && errno == EINTR);
+
+		if (pcscCfg.verbose) {
+			Log2(PCSC_LOG_DEBUG,
+			    "(Accepted connection [new fd=%d])", clientSockFd);
+		}
+		if (setsockopt(
+			clientSockFd, SOL_SOCKET, SO_LINGER,
+		     &l, sizeof (l)) < 0) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "setsockopt()/SO_LINGER: %s", strerror(errno));
+			return;
+		}
+		if (setsockopt(clientSockFd, SOL_SOCKET, SO_SNDBUF,
+		     &sndbufsize, sizeof (sndbufsize)) < 0) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "setsockopt()/SO_SNDBUF: %s", strerror(errno));
+			return;
+		}
+		if (setsockopt(clientSockFd, SOL_SOCKET, SO_RCVBUF,
+		     &rcvbufsize, sizeof (rcvbufsize)) < 0) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "setsockopt()/SO_RCVBUF: %s", strerror(errno));
+			return;
+		}
+
+		/*
+		 * Don't get stuck on CLOSED_WAIT / TIMED_WAIT
+		 */
+		mode = 1;
+		if (setsockopt(clientSockFd, SOL_SOCKET, SO_REUSEADDR,
+		    &mode, sizeof (mode)) < 0) {
+		       Log2(PCSC_LOG_CRITICAL,
+			   "setsockopt()/SO_REUSEADDR: %s", strerror(errno));
+		       return;
+		}
+		if (fcntl(clientSockFd, F_SETFD, FD_CLOEXEC) < 0) {
+			char cmd[64];
+			Log3(PCSC_LOG_CRITICAL, "fcntl(fd=%d, FD_CLOEXEC) %s",
+				clientSockFd, strerror(errno));
+			return;
+		}
+		if (SYS_ThreadCreate(&threadp,
+		    THREAD_ATTR_DETACHED,
+		    (PCSCLITE_THREAD_FUNCTION()) IncomingClientConnect,
+		    (LPVOID) clientSockFd) != 1) {
+				Log1(PCSC_LOG_CRITICAL,
+				     "SYS_ThreadCreate failed");
+				exit(EXIT_FAILURE);
+		}
+		if (pcscCfg.verbose)
+			Log3(PCSC_LOG_DEBUG,
+			    "(Created thread <%4.4x> to handle fd=%d)",
+			    (int)threadp, clientSockFd);
+	}
+}
+
+
+/**
+ * @brief queues fd to end of list
+ *
+ * Must be called with newInst->fdQLock held.
+ */
+static void
+QueueFd(fdQ_t **qHead, int fd) {
+	fdQ_t *fdq, **ppfdq;
+
+	ppfdq = qHead;
+	fdq = malloc(sizeof (struct fdQ));
+	if (fdq == NULL) {
+		Log1(PCSC_LOG_CRITICAL, "Out of Memory");
+		exit(EXIT_FAILURE);
+	}
+	fdq->fd = fd;
+	fdq->next = NULL;
+
+	while(*ppfdq != NULL)
+		ppfdq = &(*ppfdq)->next;
+
+	*ppfdq = fdq;
+	fdq->next = NULL;
+}
+
+/**
+ * @brief pops fd of top of list and returns it (null if no entry)
+ *
+ * Must be called with newInst->fdQLock held.
+ *
+ */
+static int
+PopFd(fdQ_t **qHead) {
+	int fd;
+	fdQ_t *fdq;
+	if ((fdq = *qHead) == NULL)
+		return -1;
+	fd = fdq->fd;
+	*qHead = (*qHead)->next;
+	free(fdq);
+	return fd;
+}
+
+
+/**
+ * @brief Looks up instance data in our cache
+ */
+static pcscd_t *
+FindInstanceByDpy(pcscd_t **qhead, int dpy) {
+	pcscd_t *pi = *qhead;
+	SYS_MutexLock(&instDBm);
+	while(pi != NULL) {
+		if (pi->dpyNbr == dpy) {
+			SYS_MutexUnLock(&instDBm);
+			return pi;
+		}
+		pi = pi->next;
+	}
+	SYS_MutexUnLock(&instDBm);
+	return NULL;
+}
+
+static void
+AddInstance(pcscd_t **qhead, pcscd_t *newInst) {
+	pcscd_t **ppi = qhead;
+
+	SYS_MutexLock(&instDBm);
+	while(*ppi != NULL)
+		ppi = &(*ppi)->next;
+	*ppi = newInst;
+	SYS_MutexUnLock(&instDBm);
+	++LauncherStats.nbrInstancesActive;
+}
+
+static void
+RemoveInstance(pcscd_t **qhead, pcscd_t *inst) {
+	pcscd_t **pprev, **ppi = qhead;
+
+	SYS_MutexLock(&instDBm);
+	if (*qhead == inst) {
+		*qhead = inst->next;
+		SYS_MutexUnLock(&instDBm);
+		return;
+	}
+	while (*ppi != inst && *ppi != NULL)  {
+		pprev = ppi;
+		ppi = &(*ppi)->next;
+	}
+
+	(*pprev)->next = (*ppi)->next;
+	SYS_MutexUnLock(&instDBm);
+	--LauncherStats.nbrInstancesActive;
+}
+
+static void
+CloseInstanceFifos(pcscd_t *inst)
+{
+	if (inst->inFifo != 0) {
+		close(inst->inFifo);
+		inst->inFifo = 0;
+	}
+	if (inst->outFifo != 0) {
+		close(inst->outFifo);
+		inst->outFifo = 0;
+	}
+}
+
+static int
+WaitForEnqueuedFd(pcscd_t *inst)
+{
+	int fdToSend;
+	SYS_MutexLock(&inst->fdQLock);
+	while((fdToSend = PopFd(&inst->fdQhead)) == -1)
+		SYS_CondWait(&inst->fdQNotify, &inst->fdQLock);
+	--inst->nbrFdsQueued;
+	SYS_MutexUnLock(&inst->fdQLock);
+	return fdToSend;
+}
+
+static void
+LauncherExitHandler(int signo)
+{
+
+	Log1(PCSC_LOG_DEBUG, "LauncherExitHandler called\n");
+	SYS_CloseFile(wellKnownPortSocket);
+	signal_trap(signo);
+}
+
+void dumpContexts()
+{
+}
+
+/**
+ * @brief sends Fd to instance, creating instance if necessary.
+ */
+static void
+QueueFdToInstance(int dpyNbr, int clientFd)
+{
+	pcscd_t *newInst, *inst;
+	int rv;
+
+	Log4(PCSC_LOG_DEBUG,
+	    "<%4.4x> QueueFdToInstance(:%d, fd=%d)",
+	    thr_self(), dpyNbr, clientFd);
+
+	if ((inst = FindInstanceByDpy(&instanceQ, dpyNbr)) == NULL) {
+
+		Log3(PCSC_LOG_DEBUG,
+		    "<%4.4x> No instance cached for :%d", thr_self(), dpyNbr);
+		newInst =(pcscd_t *)malloc(sizeof (struct pcscd));
+
+		if (newInst == NULL) {
+			Log1(PCSC_LOG_CRITICAL, "Out Of Memory");
+			exit(EXIT_FAILURE);
+		}
+		bzero(newInst, sizeof(struct pcscd));
+		newInst->dpyNbr = dpyNbr;
+		SYS_MutexLock(&newInst->fdQLock);
+		QueueFd(&newInst->fdQhead, clientFd);
+		++newInst->nbrFdsQueued;
+		SYS_MutexUnLock(&newInst->fdQLock);
+		AddInstance(&instanceQ, newInst);
+
+		/*
+		 * Create a per-instance thread to handle sending fds
+		 */
+		if ((rv = SYS_ThreadCreate(&newInst->tid,
+		    THREAD_ATTR_DETACHED,
+		    (PCSCLITE_THREAD_FUNCTION()) ManageInstance,
+		    (LPVOID) newInst)) != 1) {
+			  Log2(PCSC_LOG_CRITICAL,
+			     "<%4.4x> SYS_ThreadCreate failed",thr_self());
+			  exit(EXIT_FAILURE);
+		}
+	} else {
+		char logbuf[LINEMAX];
+		sprintf(logbuf,
+			"<%4.4x> Instance :%d found (pid=%d) send fd=%d",
+		    thr_self(), dpyNbr, inst->pid, clientFd);
+		Log2(PCSC_LOG_DEBUG, "%s", logbuf);
+		SYS_MutexLock(&inst->fdQLock);
+		QueueFd(&inst->fdQhead, clientFd);
+		++inst->nbrFdsQueued;
+		SYS_CondSignal(&inst->fdQNotify);
+		SYS_MutexUnLock(&inst->fdQLock);
+	}
+}
+
+static void
+AbortInstance(pcscd_t *inst)
+{
+	Log3(PCSC_LOG_ERROR, "AbortInstance() Stopping instance :%d (pid=%d)",
+		inst->dpyNbr, inst->pid);
+	StopInstance(inst->dpyNbr, inst->pid);
+	StopInstance(inst->dpyNbr, 0);
+}
+
+static void
+EradicateInstance(pcscd_t *inst) {
+	int clientFd;
+	Log3(PCSC_LOG_ERROR, "EradicateInstance() Stopping instance :%d (pid=%d)",
+		inst->dpyNbr, inst->pid);
+	StopInstance(inst->dpyNbr, inst->pid);
+	StopInstance(inst->dpyNbr, 0);
+	Log2(PCSC_LOG_ERROR, "EradicateInstance(): Removing instance :%d", inst->dpyNbr);
+	SYS_MutexLock(&inst->fdQLock);
+	RemoveInstance(&instanceQ, inst);
+	if (inst->fdToSend != 0)
+		SYS_CloseFile(inst->fdToSend);
+	while((clientFd = PopFd(&inst->fdQhead)) != -1) {
+		--inst->nbrFdsQueued;
+		SendMsg(clientFd, LAUNCHFAIL);
+		SYS_CloseFile(clientFd);
+	}
+	SYS_MutexUnLock(&inst->fdQLock);
+	SYS_MutexDestroy(&inst->fdQLock);
+#ifdef DEFER_FD_CLOSE
+	SYS_MutexDestroy(&inst->garbageFdQlock);
+#endif
+	free(inst);
+}
+
+
+
+static void
+ExecInstance(pcscd_t *inst)
+{
+	char disp[256], *argv[8];
+	char *envp[] = { disp, 0 };
+	char buf[10];
+	int pid, rv;
+
+	Log3(PCSC_LOG_DEBUG,
+		"(as FORKED Child): Launching new pcscd instance:\n\n"
+		"(as FORKED Child): exec():  %s -I -x :%d\n",
+		execPath, inst->dpyNbr);
+	/*
+	 * ctrun (Solaris) is used here to exempt child from the Launcher's
+	 * SMF contract, so that SMF doesn't try to manage our instances for us.
+	 */
+	argv[0] = "/bin/ctrun";
+	argv[1] = "-l";
+	argv[2] = "none";
+	argv[3] = execPath;
+	argv[4] = "-I";
+	argv[5] = "-x";
+	argv[6] = buf;
+	argv[7] = 0;
+
+	sprintf(disp, "DISPLAY=:%d", inst->dpyNbr);
+	sprintf(buf, ":%d", inst->dpyNbr);
+
+	rv = execve("/bin/ctrun", argv, envp);
+	if (rv < 0) {
+		Log3(PCSC_LOG_CRITICAL,
+			"FORKED Child: Error execing /bin/ctrun %s -I -x %s",
+			execPath, buf);
+		exit(EXIT_FAILURE);
+	}
+
+	Log2(PCSC_LOG_CRITICAL, "FORKED Child: execve(): %s", strerror(errno));
+	exit(EXIT_FAILURE);
+}
+
+int
+IsInstanceRunning(pcscd_t *inst)
+{
+	int pid;
+
+	Log2(PCSC_LOG_DEBUG, "-> isInstanceRunning(%d)", inst->dpyNbr);
+	if ((pid = GetPidFromFile(inst->dpyNbr)) == 0) {
+		Log2(PCSC_LOG_DEBUG,
+			"  Couldn't find pid for display :%d", inst->dpyNbr);
+		if (inst->pid != 0) {
+			Log2(PCSC_LOG_DEBUG,
+				"  Terminating prev instance pid=%d", inst->pid);
+			StopInstance(inst->dpyNbr, inst->pid);
+		}
+		return 0;
+	}
+	/*
+	 * Check to see if PID is running (but don't actually send signal)
+	 */
+	 if (kill(pid, 0) < 0) {
+		 Log4(PCSC_LOG_DEBUG, "  pid=%d (from :%d pid file) : \"%s\"",
+			 pid, inst->dpyNbr, strerror(errno));
+		 return 0;
+	 }
+	Log3(PCSC_LOG_DEBUG, " PID=%d is running for display :%d", pid, inst->dpyNbr);
+	return 1;
+}
+
+

Added: branches/Solaris/src/launcher.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/launcher.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/launcher.h (added)
+++ branches/Solaris/src/launcher.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,37 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2000-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * <NEED TO FIX KEYWORDS>
+ */
+
+
+#ifndef	__launcher_h__
+#define	__launcher_h__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*
+ * Misc constants
+ */        
+#define LINEMAX                 256        // buffer size constraint
+#define MAX_INST_CHECKS 300  // 30 seconds worth of 100000 usec waits
+
+void Launcher();
+
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif
+
+#endif

Propchange: branches/Solaris/src/launcher.h
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/src/modules/Makefile.am
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/modules/Makefile.am?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/modules/Makefile.am (added)
+++ branches/Solaris/src/modules/Makefile.am Thu Jun 12 10:28:09 2008
@@ -1,0 +1,21 @@
+# Process this file with automake to create Makefile.in.
+
+lib_LTLIBRARIES = libPcscdAuth.la libIfdAuth.la libValidate.la
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/PCSC -I$(top_builddir)/src/PCSC
+
+libPcscdAuth_la_SOURCES = pcscdAuth_generic.c
+libPcscdAuth_la_CFLAGS = $(CFLAGS) -D_RENTRANT -Kpic
+libPcscdAuth_la_LIBADD = $(LIBSOCKET) $(LIBNSL)
+
+libIfdAuth_la_SOURCES = ifdAuth_generic.c
+libIfdAuth_la_CFLAGS = $(CFLAGS) -D_RENTRANT -Kpic
+libIfdAuth_la_LIBADD = $(LIBSOCKET) $(LIBNSL)
+	
+libValidate_la_SOURCES = validate_generic.c
+libValidate_la_CFLAGS = $(CFLAGS) -D_REENTRANT -Kpic
+libValidate_la_LIBADD = $(LIBSOCKET) $(LIBNSL) 
+
+confdir = $(datadir)
+conf_DATA = pcscd_validate.conf
+

Propchange: branches/Solaris/src/modules/Makefile.am
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/src/modules/Makefile.in
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/modules/Makefile.in?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/modules/Makefile.in (added)
+++ branches/Solaris/src/modules/Makefile.in Thu Jun 12 10:28:09 2008
@@ -1,0 +1,572 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006  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.
+
+ at SET_MAKE@
+
+# Process this file with automake to create Makefile.in.
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@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 = src/modules
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acx_pthread.m4 \
+	$(top_srcdir)/m4/as-ac-expand.m4 \
+	$(top_srcdir)/m4/check_modules.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+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 = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(confdir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libIfdAuth_la_DEPENDENCIES =
+am_libIfdAuth_la_OBJECTS = libIfdAuth_la-ifdAuth_generic.lo
+libIfdAuth_la_OBJECTS = $(am_libIfdAuth_la_OBJECTS)
+libIfdAuth_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libIfdAuth_la_CFLAGS) \
+	$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+libPcscdAuth_la_DEPENDENCIES =
+am_libPcscdAuth_la_OBJECTS = libPcscdAuth_la-pcscdAuth_generic.lo
+libPcscdAuth_la_OBJECTS = $(am_libPcscdAuth_la_OBJECTS)
+libPcscdAuth_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libPcscdAuth_la_CFLAGS) \
+	$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+libValidate_la_DEPENDENCIES =
+am_libValidate_la_OBJECTS = libValidate_la-validate_generic.lo
+libValidate_la_OBJECTS = $(am_libValidate_la_OBJECTS)
+libValidate_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libValidate_la_CFLAGS) \
+	$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libIfdAuth_la_SOURCES) $(libPcscdAuth_la_SOURCES) \
+	$(libValidate_la_SOURCES)
+DIST_SOURCES = $(libIfdAuth_la_SOURCES) $(libPcscdAuth_la_SOURCES) \
+	$(libValidate_la_SOURCES)
+confDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(conf_DATA)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COREFOUNDATION = @COREFOUNDATION@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+HAVE_RUNPID = @HAVE_RUNPID@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IOKIT = @IOKIT@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBDL = @LIBDL@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSMARTCARD = @LIBSMARTCARD@
+LIBTOOL = @LIBTOOL@
+LIBUSBCONFIG = @LIBUSBCONFIG@
+LIBUSB_CFLAGS = @LIBUSB_CFLAGS@
+LIBUSB_LIBS = @LIBUSB_LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYMBOL_VISIBILITY = @SYMBOL_VISIBILITY@
+TEST_MINUS_S_SH = @TEST_MINUS_S_SH@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+acx_pthread_config = @acx_pthread_config@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+confdir = $(datadir)
+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@
+libdir = @libdir@
+libdir_exp = @libdir_exp@
+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@
+rtlibdir = @rtlibdir@
+rtlibdir_exp = @rtlibdir_exp@
+runpid = @runpid@
+sbindir = @sbindir@
+sbindir_exp = @sbindir_exp@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+sysconfdir_exp = @sysconfdir_exp@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+usbdropdir = @usbdropdir@
+xservers_file_exp = @xservers_file_exp@
+xtag = @xtag@
+lib_LTLIBRARIES = libPcscdAuth.la libIfdAuth.la libValidate.la
+AM_CPPFLAGS = -I$(top_srcdir)/src/PCSC -I$(top_builddir)/src/PCSC
+libPcscdAuth_la_SOURCES = pcscdAuth_generic.c
+libPcscdAuth_la_CFLAGS = $(CFLAGS) -D_RENTRANT -Kpic
+libPcscdAuth_la_LIBADD = $(LIBSOCKET) $(LIBNSL)
+libIfdAuth_la_SOURCES = ifdAuth_generic.c
+libIfdAuth_la_CFLAGS = $(CFLAGS) -D_RENTRANT -Kpic
+libIfdAuth_la_LIBADD = $(LIBSOCKET) $(LIBNSL)
+libValidate_la_SOURCES = validate_generic.c
+libValidate_la_CFLAGS = $(CFLAGS) -D_REENTRANT -Kpic
+libValidate_la_LIBADD = $(LIBSOCKET) $(LIBNSL) 
+conf_DATA = pcscd_validate.conf
+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 \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu  src/modules/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu  src/modules/Makefile
+.PRECIOUS: 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
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libIfdAuth.la: $(libIfdAuth_la_OBJECTS) $(libIfdAuth_la_DEPENDENCIES) 
+	$(libIfdAuth_la_LINK) -rpath $(libdir) $(libIfdAuth_la_OBJECTS) $(libIfdAuth_la_LIBADD) $(LIBS)
+libPcscdAuth.la: $(libPcscdAuth_la_OBJECTS) $(libPcscdAuth_la_DEPENDENCIES) 
+	$(libPcscdAuth_la_LINK) -rpath $(libdir) $(libPcscdAuth_la_OBJECTS) $(libPcscdAuth_la_LIBADD) $(LIBS)
+libValidate.la: $(libValidate_la_OBJECTS) $(libValidate_la_DEPENDENCIES) 
+	$(libValidate_la_LINK) -rpath $(libdir) $(libValidate_la_OBJECTS) $(libValidate_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libIfdAuth_la-ifdAuth_generic.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libPcscdAuth_la-pcscdAuth_generic.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libValidate_la-validate_generic.Plo at am__quote@
+
+.c.o:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c $<
+
+.c.obj:
+ at am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ at am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+libIfdAuth_la-ifdAuth_generic.lo: ifdAuth_generic.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libIfdAuth_la_CFLAGS) $(CFLAGS) -MT libIfdAuth_la-ifdAuth_generic.lo -MD -MP -MF $(DEPDIR)/libIfdAuth_la-ifdAuth_generic.Tpo -c -o libIfdAuth_la-ifdAuth_generic.lo `test -f 'ifdAuth_generic.c' || echo '$(srcdir)/'`ifdAuth_generic.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libIfdAuth_la-ifdAuth_generic.Tpo $(DEPDIR)/libIfdAuth_la-ifdAuth_generic.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='ifdAuth_generic.c' object='libIfdAuth_la-ifdAuth_generic.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libIfdAuth_la_CFLAGS) $(CFLAGS) -c -o libIfdAuth_la-ifdAuth_generic.lo `test -f 'ifdAuth_generic.c' || echo '$(srcdir)/'`ifdAuth_generic.c
+
+libPcscdAuth_la-pcscdAuth_generic.lo: pcscdAuth_generic.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPcscdAuth_la_CFLAGS) $(CFLAGS) -MT libPcscdAuth_la-pcscdAuth_generic.lo -MD -MP -MF $(DEPDIR)/libPcscdAuth_la-pcscdAuth_generic.Tpo -c -o libPcscdAuth_la-pcscdAuth_generic.lo `test -f 'pcscdAuth_generic.c' || echo '$(srcdir)/'`pcscdAuth_generic.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libPcscdAuth_la-pcscdAuth_generic.Tpo $(DEPDIR)/libPcscdAuth_la-pcscdAuth_generic.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='pcscdAuth_generic.c' object='libPcscdAuth_la-pcscdAuth_generic.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libPcscdAuth_la_CFLAGS) $(CFLAGS) -c -o libPcscdAuth_la-pcscdAuth_generic.lo `test -f 'pcscdAuth_generic.c' || echo '$(srcdir)/'`pcscdAuth_generic.c
+
+libValidate_la-validate_generic.lo: validate_generic.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libValidate_la_CFLAGS) $(CFLAGS) -MT libValidate_la-validate_generic.lo -MD -MP -MF $(DEPDIR)/libValidate_la-validate_generic.Tpo -c -o libValidate_la-validate_generic.lo `test -f 'validate_generic.c' || echo '$(srcdir)/'`validate_generic.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libValidate_la-validate_generic.Tpo $(DEPDIR)/libValidate_la-validate_generic.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='validate_generic.c' object='libValidate_la-validate_generic.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libValidate_la_CFLAGS) $(CFLAGS) -c -o libValidate_la-validate_generic.lo `test -f 'validate_generic.c' || echo '$(srcdir)/'`validate_generic.c
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+install-confDATA: $(conf_DATA)
+	@$(NORMAL_INSTALL)
+	test -z "$(confdir)" || $(MKDIR_P) "$(DESTDIR)$(confdir)"
+	@list='$(conf_DATA)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  f=$(am__strip_dir) \
+	  echo " $(confDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(confdir)/$$f'"; \
+	  $(confDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(confdir)/$$f"; \
+	done
+
+uninstall-confDATA:
+	@$(NORMAL_UNINSTALL)
+	@list='$(conf_DATA)'; for p in $$list; do \
+	  f=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(confdir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(confdir)/$$f"; \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+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 $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$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 $(LTLIBRARIES) $(DATA)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(confdir)"; 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:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_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-libLTLIBRARIES clean-libtool \
+	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
+
+info: info-am
+
+info-am:
+
+install-data-am: install-confDATA
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: 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: uninstall-confDATA uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-confDATA 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-libLTLIBRARIES 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 uninstall uninstall-am uninstall-confDATA \
+	uninstall-libLTLIBRARIES
+
+# 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:

Added: branches/Solaris/src/modules/ifdAuth_generic.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/modules/ifdAuth_generic.c?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/modules/ifdAuth_generic.c (added)
+++ branches/Solaris/src/modules/ifdAuth_generic.c Thu Jun 12 10:28:09 2008
@@ -1,0 +1,46 @@
+#include "pcsclite.h"
+#include "clientcred.h"
+#include "ifd-auth.h"
+#include "debuglog.h"
+
+int dbgFlag = 0;
+int allowRootAlways = 0;
+
+/*
+ * 
+ * This function initializes this ifd handler authentication plugin, and 
+ * recognizes the following two KVP keys (each set to true or false):
+ *
+ *      DEBUG:		If true debug logging is enabled.
+ *
+ *      ALLOW_ROOT:	If true, root is automatically authorized to access
+ *                      the ifd handler bypassing the normal authentication
+ *                      steps.
+ */
+int
+init(kvp_t *kvps) {
+	dbgFlag = isKeyValueTrue(kvps, "debug");
+	allowRootAlways = isKeyValueTrue(kvps, "allow_root");
+
+	if (dbgFlag) {
+		Log2(PCSC_LOG_DEBUG, "initDaemonAuth(): debug = %d", dbgFlag);
+		Log2(PCSC_LOG_DEBUG, "initDaemonAuth(): allow_root = %d", dbgFlag);
+	}
+	return 1;
+}
+
+/*
+ * Functionality is T.B.D.  Currently access is always granted to all 
+ * readers on the console.
+ */
+int
+isAuthorized(PCSCLITE_CRED_T *cred, 
+    const char *ifdHandlerName, const void *resource) {
+
+	if (dbgFlag)
+		Log4(PCSC_LOG_DEBUG, "isAuthorizedForIfd():"
+		       "euid:%d, dpy:%d, ifd:%s", 
+		        cred->euid, cred->dpyNbr, ifdHandlerName);
+	
+	return 1;
+}

Propchange: branches/Solaris/src/modules/ifdAuth_generic.c
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/src/modules/pcscdAuth_generic.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/modules/pcscdAuth_generic.c?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/modules/pcscdAuth_generic.c (added)
+++ branches/Solaris/src/modules/pcscdAuth_generic.c Thu Jun 12 10:28:09 2008
@@ -1,0 +1,47 @@
+#include "pcsclite.h"
+#include "clientcred.h"
+#include "pcscd-auth.h"
+#include "debuglog.h"
+
+
+int dbgFlag = 0;
+int allowRootAlways = 0;
+
+
+/*
+ * 
+ * This function initializes this ifd handler authentication plugin, and 
+ * recognizes the following two KVP keys (each set to true or false):
+ *
+ *      DEBUG:		If true debug logging is enabled.
+ *
+ *      ALLOW_ROOT:	If true, root is automatically authorized to access
+ *                      the ifd handler bypassing the normal authentication
+ *                      steps.
+ */
+
+int
+init(kvp_t *kvps) {
+	dbgFlag = isKeyValueTrue(kvps, "debug");
+	allowRootAlways = isKeyValueTrue(kvps, "allow_root");
+
+	if (dbgFlag) {
+		Log2(PCSC_LOG_DEBUG, "initDaemonAuth(): debug = %d", dbgFlag);
+		Log2(PCSC_LOG_DEBUG, "initDaemonAuth(): allow_root = %d", dbgFlag);
+	}
+	return 1;
+}
+
+/*
+ * Functionality is T.B.D.  Currently access is always granted to all 
+ * the daemon for all console displays.
+ */
+
+int
+isAuthorized(PCSCLITE_CRED_T *cred, const  void *resource) {
+
+	if (dbgFlag)
+		Log3(PCSC_LOG_DEBUG, "isAuthorizedForDaemon():"
+			"euid:%d, dpy:%d", cred->euid, cred->dpyNbr);
+	return 1;
+}

Propchange: branches/Solaris/src/modules/pcscdAuth_generic.c
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/src/modules/pcscd_validate.conf
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/modules/pcscd_validate.conf?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/modules/pcscd_validate.conf (added)
+++ branches/Solaris/src/modules/pcscd_validate.conf Thu Jun 12 10:28:09 2008
@@ -1,0 +1,3 @@
+# pcscd_validate.conf
+
+pcscdValidate.so.1 -s 0 -e 9999

Added: branches/Solaris/src/modules/validate_generic.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/modules/validate_generic.c?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/modules/validate_generic.c (added)
+++ branches/Solaris/src/modules/validate_generic.c Thu Jun 12 10:28:09 2008
@@ -1,0 +1,216 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "pcsclite.h"
+#include "pcscd-validate.h"
+#include "debuglog.h"
+#define LINEMAX 256
+
+static char *lookupTag(int, char **, void **);
+static char *xservers_file;
+static void *resource;
+static int dbgFlag = 0;
+static int startDpyNbr = -1;
+static int endDpyNbr = -1;
+static int alwaysInvalidate = 0;
+static int rangeCheck = 0;
+
+
+/*
+ * Usage:
+ *
+ * -s <dpy#>	Specifies starting display # of the recognized range.
+ *              If -s is specified, -e must also be specified.
+ *
+ * -e <dpy#>    Specified the ending display # of the range.
+ *              If -e is specified, -s must also be specified.
+ *
+ * -n           If specified the plugin always returns NULL when
+ *              getDisplayTag() or getDisplayResource() are called.
+ *              (ie. invalidates all access to the display)
+ *
+ * -d           Switches on debug logging.
+ *
+ */
+int
+initValidate(int argc, char **argv) {
+
+	int i, c;
+	while ((c = getopt(argc, argv, ":x:s:e:nd")) != -1) {
+		switch(c) {
+		case 's':
+			rangeCheck = 1;
+			startDpyNbr = atoi(optarg);
+			break;
+		case 'e':
+			rangeCheck = 1;
+			endDpyNbr = atoi(optarg);
+			break;
+		case 'n':
+			alwaysInvalidate = 1;
+			break;
+		case 'd':
+			dbgFlag = 1;
+			break;
+		case 'x':
+			xservers_file = optarg;
+			break;
+		default:
+		case '?':
+			Log1(PCSC_LOG_DEBUG,
+			       "bad flag passed.  valid options are:\n"
+			       "-s <startdpy#> -e <enddpy#> -d -n\n"
+			       "-d = debug, -n = always invalidate\n");
+			return 0;
+		}
+	}
+
+	if (rangeCheck & (startDpyNbr < 0 || endDpyNbr < 0)) {
+		Log1(PCSC_LOG_ERROR,
+			"-s can only be specified with -e option & vice versa");
+		return 0;
+	}
+
+	if (dbgFlag) {
+		Log1(PCSC_LOG_DEBUG, "initValidate() called with args:");
+		for (i = 0; i < argc; i++)
+			Log3(PCSC_LOG_DEBUG, "   argv[%d] = %s", i, argv[i]);
+	}
+	return 1;
+}
+
+/*
+ * This function looks up the display # in the Xservers file.  If it is
+ * defined, the corresponding display tag name is returned.
+ */
+char *
+getDisplayTag(int dpyNbr, char **facilityTag)
+{
+	void *resource;
+	if (dbgFlag)
+		Log2(PCSC_LOG_DEBUG, "getDisplayTag(%d) called", dpyNbr);
+	if (alwaysInvalidate)
+		*facilityTag = NULL;
+	else
+		lookupTag(dpyNbr, facilityTag, &resource);
+	return *facilityTag;
+}
+
+
+/*
+ * This function retured the resource defined for the display.  For this
+ * plugin the exact text of the line that defined the display in the Xservers
+ * file is returned.
+ */
+void *
+getDisplayResource(int dpyNbr, void **resource)
+{
+	char *facilityTag = NULL;
+	if (dbgFlag)
+		Log2(PCSC_LOG_DEBUG,"getDisplayResource(%d) called", dpyNbr);
+	if (alwaysInvalidate)
+		*resource = NULL;
+	else
+		lookupTag(dpyNbr, &facilityTag, resource);
+	return *resource;
+}
+
+int
+getDisplayStatus(int dpyNbr, unsigned int *flags)
+{
+	char *facilityTag;
+	if (getDisplayTag(dpyNbr, &facilityTag) == NULL)
+		return DISPLAY_NOT_VALID;
+	free(facilityTag);
+	*flags = 0;
+	return DISPLAY_IS_VALID;
+}
+
+
+static char *
+lookupTag(int dpyNbr, char **facilityTag, void **resource) {
+	int i;
+	char readbuf[LINEMAX];
+	char chkTag[10];
+	char *cp1, *cp2;
+	char *xServerTag = NULL;
+	FILE *fp;
+
+	if (rangeCheck && (dpyNbr < startDpyNbr || dpyNbr > endDpyNbr)) {
+		Log4(PCSC_LOG_ERROR,
+			"lookupTag(): Failed display range check :%d (%d,%d)",
+			dpyNbr, startDpyNbr, endDpyNbr);
+		goto err_exit;
+	}
+
+	/*
+	 * Attempt to open Xservers file.  If it wasn't specified as an argument
+	 * to the plugin, use the one specified at build time (ie. the default
+	 * for the platform).  The plugin gives the administrator the ability
+	 * to override the default Xservers placement for the architecture.
+	 *
+	 * Since this is the generic module, we don't return an error,
+	 * but instead return the tag "Local", if the XServers file can't be
+	 * accessed in the specified location, because it might be a system
+	 * where X hasn't been installed, but access to the Smart Card reader is
+	 * still required.
+	 */
+	if (xservers_file == NULL)
+		xservers_file = XSERVERS_FILE;
+	if ((fp = fopen(xservers_file, "r")) == NULL) {
+		Log4(PCSC_LOG_DEBUG,
+		    "Can't open Xservers file %s: errno:%d = %s",
+		     xservers_file, errno, strerror(errno));
+		*facilityTag = strdup("Local");
+		*resource = strdup("");
+		return *facilityTag;
+	}
+
+	/*
+	 * Look up display tag name in Xservers file
+	 */
+	if (resource != NULL)
+		*resource = NULL;
+	xServerTag = NULL;
+	sprintf(chkTag, ":%d", dpyNbr);
+	while (fgets(cp1 = readbuf, LINEMAX, fp) != NULL) {
+		while (*cp1 == ' ' || *cp1 == '\t')
+			++cp1;
+		if (strncmp(cp1, chkTag, strlen (chkTag)) == 0 &&
+		    (cp1[strlen(chkTag)] == ' ' ||
+		     cp1[strlen(chkTag)] == '\t')) {
+			cp1 += strlen(chkTag);
+			cp1 += strspn(cp1, " \t");
+			cp2 = cp1;
+			while(*cp2 != '\0' && *cp2 != ' ' && *cp2 != '\t')
+			     cp2++;
+			*cp2 = '\0';
+			fclose(fp);
+			if (resource != NULL) {
+				if (dbgFlag)
+					Log2(PCSC_LOG_DEBUG,
+						"display resource: %s\n",
+						(char *)readbuf);
+				*resource = strdup(readbuf);
+			}
+			if (dbgFlag)
+				Log3(PCSC_LOG_DEBUG,
+					"Tag \"%s\" located for dpy :%d",
+					cp1, dpyNbr);
+			if (facilityTag) {
+				*facilityTag = strdup(cp1);
+				return *facilityTag;
+			}
+			goto err_exit;
+		}
+	}
+	fclose(fp);
+
+err_exit:
+	if (facilityTag)
+		*facilityTag = NULL;
+	return NULL;
+}
+

Added: branches/Solaris/src/pcsc_config.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/pcsc_config.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/pcsc_config.h (added)
+++ branches/Solaris/src/pcsc_config.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,369 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2000-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * <NEED TO FIX KEYWORDS>
+ */
+
+
+#ifndef	__pcsc_config_h__
+#define	__pcsc_config_h__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <netdb.h>
+#include <stdio.h>
+
+/*
+ * pcscd global configuration data
+ * (Also referred to as the "Global Configuration Block")
+ */
+extern struct pcsc_cfg_data {
+	int  consumer;			// Indicates who's using this data
+	int  launchMode;		// Launcher, Instance or Client?
+	int  runInForeground;		// Foreground mode state
+	int  instanceTimeout;		// Max. instance inactivity in seconds
+	int  transportType;		// Client / Instance comm. mode
+	int  portNbr;			// Port No, if using TCP/IP
+	int  dpyNbr;			// Client display number
+	int  screenNbr;			// Client screen number (not used yet)
+	in_addr_t xHostIp;		// Client IP address
+	int  useMappedMemory;		// Memory mapped mode
+	int  portNbrWild;		// Port numbering is wildcard based
+	int  baseDirWild;		// Base directory is indexed
+	char *baseDir;			// Root base directory
+	char *instanceScript;		// Script to invoke when launching inst
+	char *pcscConfigFile;		// Master configuration file
+	char *validateConf;		// Validation plugin configuration file
+	char *readerConfigFile;		// Reader conf file used by us
+	char *pcscdMemMappedFile;	// Optional memory-mapped file
+	char *pcscdPIDFile;		// PID file
+	char *netBindFile;		// UNIX-domain socket file if applicable
+	char *ifdPluginDir; 		// Where IFD handlers live
+	char *logFile;			// Optional log file path
+	char *argv0;			// Name of launched program
+	int  apduDebug;			// APDU debugging mode
+	int  verbose;			// Debug verbosity level
+	int  useAuthentication;		// Are we using authentication?
+	char *statusPollRate;		// How fast the daemon polls
+	int logLevel;			// Logging level
+	int logType;			// Logging type
+	int pcscdExiting;		// Set when we receive exit-type signal
+	int fifoPingTimeout;		// Time in seconds before ping times out
+	int relaunchThreshold;		// Max. number instance relaunch tries
+	int relaunchInterval;		// Sets when instance relaunch too fast
+} pcscCfg, launcherCfg;
+
+#define AUTHFAIL    "AUTHENTICATION FAILURE"
+#define LAUNCHFAIL  "SERVER INSTANCE COULD NOT BE STARTED"
+#define CONNECTOK   "CLIENT CONNECTED TO SERVER INSTANCE"
+
+extern FILE *dbgFp;
+void dbg(const char *, ...);
+#define WINSCARD_CLNT 0
+void dbg2(int, const char *, ...);
+void d(const char *, ...);
+
+#define DBG0(fmt) \
+		(void) Log1(PCSC_LOG_DEBUG, fmt)
+#define DBG1(fmt, d1) \
+		(void) Log2(PCSC_LOG_DEBUG, fmt, d1)
+#define DBG2(fmt, d1, d2) \
+		(void) Log3(PCSC_LOG_DEBUG, fmt, d1, d2)
+#define DBG3(fmt, d1, d2, d3) \
+		(void) Log4(PCSC_LOG_DEBUG, fmt, d1, d2, d3)
+#define DBG4(fmt, d1, d2, d3, d4) \
+		(void) Log5(PCSC_LOG_DEBUG, fmt, d1, d2, d3, d4)
+
+void CFGperror(int, char *);
+char *CFGRetrofitPath(char *, char *);
+int   CFGEnsurePathExists(char *);
+int   CFGLoadConfigFile( const char *);
+int   CFGProcessKvp(const char *, const char *, int);
+int   CFGSetArg(const int opt, const char *, const char *, int);
+int   CFGParseXdisplay(char *, int *, int *, in_addr_t *);
+void  CFGErrChkCritical(int);
+void  CFGErrChk(int, int);
+void  CFGErrChkMsg(int, int, char *, ...);
+char *CFGErrText(int);
+void  CFGDefault(const char *, const char *);
+int   CFGRmPath(char *);
+void  CFGSetConfigConsumer(int);
+int   CFGresolveWildcard(void *, void *);
+void  CFGdumpCfg(FILE *);
+char *CFGSubstitute(char *, char *, char *);
+char *CFGListConstants(void *);
+void  CFGdumpEventState(int);
+void  CFGdumpReaderState(int);
+int   CFGDoesFileExist(char *);
+
+
+/*
+ * All constant values used in parsing must be defined
+ * as enums or macros
+ */
+enum llvl        { CRITICAL, ERROR, INFO, DEBUG };
+enum ltype       { STDERR, SYSLOG };
+enum nopFlag     { NORMAL = 0 };
+enum consumer    { DEFAULT = 0, CLIENT, LAUNCHER, INSTANCE };
+enum cliser      { SERVER, LIBRARY, MUTUAL };
+enum boolean     { FALSE  = 0, TRUE };
+enum provider    { USER, ENGINE };
+enum wildcard    { X_DISPLAY_NUMBER };
+enum visibility  { PARAM = 0, INTERN };
+enum wildoffset  { WILD_DECREMENT, WILD_INCREMENT };
+enum KVPtypes    { _CONSTANT = 1, _NUMERIC, _STRING, _BOOLEAN, _IPADDR };
+enum transports  { SOCKET_UNIX, SOCKET_INETV4 };
+enum pathTypes   { PATH_OPTIONAL, PATH_REQUIRED, DIR_PATH_REQUIRED,
+		   FILE_PATH_REQUIRED };
+enum validations { PARSE_CONST = 1, PARSE_RANGE, PARSE_NUMBER, PARSE_QUOTED,
+		   PARSE_WILD, PARSE_PATH };
+/*
+ * The following Macros are used to initialize the struct array
+ * for the tabularized parsing engine.  That struct array is configured
+ * below.
+
+ * The macros describe the data types and RHS (Right Hand Side) constraints
+ * of different types of key value pairs (KVPs).  At least be one of these
+ * Macros (initializers) must be provided for each KVP keyword in the table
+ * below, even if it is just the EOL Macro.
+ */
+#define CONST(C)               { #C, PARSE_CONST,        0,    0,    0,  0, 0, 0, C, 0 }
+#define RANGE(low, high)       { "", PARSE_RANGE,        0,  low, high,  0, 0, 0, 0, 0 }
+#define INTWILD(typ, tok, trg) { "", PARSE_WILD,  _NUMERIC,  typ, tok, trg, 0, 0, 0, 0 }
+#define STRWILD(typ, tok, trg) { "", PARSE_WILD,   _STRING,  typ, tok, trg, 0, 0, 0, 0 }
+#define NUMBER(flags)          { "", PARSE_NUMBER,   flags,    0,   0,   0, 0, 0, 0, 0 }
+#define QUOTED(flags)          { "", PARSE_QUOTED,   flags,    0,   0,   0, 0, 0, 0, 0 }
+#define PATH(flags)            { "", PARSE_PATH,     flags,    0,   0,   0, 0, 0, 0, 0 }
+#define EOL                    { "", 0, 0, 0, 0, 0, 0, 0, 0, 1 }
+
+/* TABULARIZED PARSING ENGINE CONTROL TABLE
+ *
+ * Each of the struct arrays below, for example TRANSPORT[], LAUNCH_MODE[],
+ * etc..., represents a valid keyword (L.H.S. of KVP).  The array contains an
+ * arbitrary number of initializes, selected from the macros defined above.
+ * These array initializers lists (which may otherwise be empty) must always
+ * be terminated with the EOL initializer macro.
+ *
+ * For example if an array TRANSPORT[] is defined and initialized with
+ * CONST(SOCKET_UNIX), CONST(SOCKET_INETV4), KVPs "TRANSPORT = SOCKET_UNIX"
+ * and "TRANSPORT = SOCKET_INETV4" will be allowed in the main conf file.
+ * are allowed in the configuration file.  A corresponding definition entry in
+ * the main parsing tables indicates the TRANSPORT value updates the global
+ * data struct pcscCfg.transport field (the value is translated according to
+ * to the type indicated in the array initiaizer list).
+ *
+ * When a KVP like "LOG_LEVEL = INFO" is run through the KVP parser, the engine"
+ * compares LOG_LEVEL to each key in the key list to find a match.  Each
+ * validation step indicated by the list of macro initializers is performed
+ * on the value.
+ *
+ * The most complicated parsing validatio type is wildcarding. For example,
+ * for the BASE_DIR key, STRWILD specifies that the substring "$DISPLAY" is
+ * the formal arg representing the wildcard portion of the RHS actual argument,
+ * syntactically.  If a wildcard argument is found, a corresponding specified
+ * flag is set  in the global data struct (pcscCfg).  Wildcard parsing is
+ * handled in phases.  For example, at the time the conf file is parsed,
+ * we don't know the display the $DISPLAY wildcard placeholder refers to yet,
+ * so state is set up to complete the parsing later.
+ *
+ * Later, when the X Display # becomes known, if pcscCfg.baseDirWild is set,
+ * CFGResolveWildcard() is called passing in the display number.  The state
+ * tables will be used to determine how to complete the wildcard substittution
+ * and where to store the final value.
+ */
+
+static struct kvpValidation {
+	char *key;     /* Key name of this element */
+	int process;   /* Additional validation processing category */
+	int option;    /* Processing sub-category */
+	void *arg1;    /* Option-dependent input param #1 */
+	void *arg2;    /* Option-dependent input param #2 */
+	void *arg3;    /* Option-dependent input param #3 */
+	void *datum1;  /* Pre-process output parameter 1 */
+	void *datum2;  /* Pre-process output parameter 2 */
+	int constVal;  /* Value of constant if this defiens one */
+	int eolFlag;   /* Set for last elem in list (if set ignore other fields) */
+
+}  TRANSPORT[] = {
+	CONST(SOCKET_UNIX),
+	CONST(SOCKET_INETV4),
+	EOL
+
+}, LAUNCH_MODE[] = {
+	CONST(LAUNCHER),
+	CONST(INSTANCE),
+	CONST(DEFAULT),
+	EOL
+
+}, LOG_LEVEL[] = {
+	CONST(DEBUG),
+	CONST(INFO),
+	CONST(ERROR),
+	CONST(CRITICAL),
+	EOL
+
+}, LOG_TYPE[] = {
+	CONST(STDERR),
+	CONST(SYSLOG),
+	EOL
+
+}, PORT_NUMBER[] = {
+	RANGE("0", "65535"),    /* Enforce range limit on port number value */
+	INTWILD(X_DISPLAY_NUMBER, "$DISPLAY", &pcscCfg.portNbrWild),
+	EOL
+
+}, BASE_DIR[] = {
+	PATH(PATH_OPTIONAL),
+	STRWILD(X_DISPLAY_NUMBER, "$DISPLAY", &pcscCfg.baseDirWild),
+	EOL
+
+}, IFD_PLUGIN_PATH[] = {
+	PATH(PATH_OPTIONAL),    /* Can't validate presence during initial parsing  */
+	EOL
+
+}, READER_CONFIG_FILE[] = {
+	PATH(PATH_OPTIONAL),    /* Can't validate presence during initial parsing */
+	EOL
+
+}, MEMORY_MAPPED_FILE[] = {
+	PATH(PATH_OPTIONAL),    /* Can't validate presence during initial parsing */
+	EOL
+
+}, CONSUMER[] = {
+	CONST(LAUNCHER),
+	CONST(INSTANCE),
+	CONST(DEFAULT),
+	CONST(CLIENT),
+	EOL
+
+}, BASE_DIR_WILD[]          = { EOL },
+   PORT_NUMBER_WILD[]       = { EOL },
+   LOG_FILE[]               = { EOL },
+   RUN_IN_FOREGROUND[]      = { EOL },
+   VERBOSE[] 		    = { EOL },
+   PCSCD_CONFIG_FILE[]      = { EOL },
+   SCREEN_NUMBER[]          = { EOL },
+   DISPLAY_NUMBER[]         = { EOL },
+   PCSCD_PID_FILE[]         = { EOL },
+   NET_BIND_FILE[]          = { EOL },
+   USE_MAPPED_MEMORY[]      = { EOL },
+   X_HOST_IP[]              = { EOL },
+   USE_AUTHENTICATION[]     = { EOL },
+   INSTANCE_TIMEOUT[]       = { EOL },
+   HELPER_SCRIPT[]          = { EOL },
+   STATUS_POLL_RATE[]       = { EOL },
+   APDU_DEBUG[]             = { EOL },
+   RELAUNCH_THRESHOLD[]     = { EOL },
+   FIFO_PING_TIMEOUT[]      = { EOL },
+   RELAUNCH_INTERVAL[]      = { EOL },
+   ARGV0[]		    = { EOL };
+
+
+/*
+ * List of valid KVPs, indicating consumer, visibility,
+ * validation method and data type for the RHS part.  Also indicates
+ * for each KVP, the address at which to store the parsed result for
+ * the KVP if the KVP is encountered during configuration processing.
+ * These values are all conveniently stored in a global configuation
+ * block (ie. a global struct) so that the configuation state can be
+ * accessed from anywhere in the code.
+ *
+ * This table is used to determine the format of the data to
+ * display.  The CFGdump() function matches the address of a
+ * config block variable in this table to get the type.
+ */
+
+#define KVP(key, consumer, visibility, type, result) \
+	  { #key, consumer, visibility, type, \
+	    (struct kvpValidation *)&key, (void *)result }
+
+
+static struct kvp {
+	char *key;                        /* key name of this KVP */
+	int  consumer;                    /* Who can access, client, server or both? */
+	int  visibility;                  /* Is this a user or internal-only option? */
+	int  type;                        /* What is the resultant data type */
+	struct kvpValidation *validation; /* Optional validation processing for val */
+	void *result;                     /* Where the parsed result is stored */
+} kvps[] = {
+	KVP(READER_CONFIG_FILE,     SERVER, PARAM,  _STRING,   &pcscCfg.readerConfigFile),
+	KVP(IFD_PLUGIN_PATH,        SERVER, PARAM,  _STRING,   &pcscCfg.ifdPluginDir),
+	KVP(APDU_DEBUG,             SERVER, PARAM,  _BOOLEAN,  &pcscCfg.apduDebug),
+	KVP(PCSCD_PID_FILE,         SERVER, PARAM,  _STRING,   &pcscCfg.pcscdPIDFile),
+	KVP(RUN_IN_FOREGROUND,      SERVER, PARAM,  _BOOLEAN,  &pcscCfg.runInForeground),
+	KVP(INSTANCE_TIMEOUT,       SERVER, PARAM,  _NUMERIC,  &pcscCfg.instanceTimeout),
+	KVP(PCSCD_CONFIG_FILE,      SERVER, INTERN, _STRING,   &pcscCfg.pcscConfigFile),
+	KVP(ARGV0, 		    MUTUAL, INTERN, _STRING,   &pcscCfg.argv0),
+	KVP(HELPER_SCRIPT,          SERVER, INTERN, _STRING,   &pcscCfg.instanceScript),
+	KVP(STATUS_POLL_RATE,       SERVER, PARAM,  _NUMERIC,  &pcscCfg.statusPollRate),
+	KVP(USE_AUTHENTICATION,     SERVER, PARAM,  _BOOLEAN,  &pcscCfg.useAuthentication),
+	KVP(LOG_LEVEL,              SERVER, PARAM,  _CONSTANT, &pcscCfg.logLevel),
+	KVP(LOG_TYPE,               SERVER, PARAM,  _CONSTANT, &pcscCfg.logType),
+	KVP(FIFO_PING_TIMEOUT,      SERVER, PARAM,  _NUMERIC,  &pcscCfg.fifoPingTimeout),
+	KVP(RELAUNCH_THRESHOLD,     SERVER, PARAM,  _NUMERIC,  &pcscCfg.relaunchThreshold),
+	KVP(RELAUNCH_INTERVAL,      SERVER, PARAM,  _NUMERIC,  &pcscCfg.relaunchInterval),
+	KVP(LOG_FILE,               MUTUAL, PARAM,  _STRING,   &pcscCfg.logFile),
+	KVP(TRANSPORT,              MUTUAL, PARAM,  _CONSTANT, &pcscCfg.transportType),
+	KVP(BASE_DIR_WILD,          MUTUAL, INTERN, _BOOLEAN,  &pcscCfg.baseDirWild),
+	KVP(USE_MAPPED_MEMORY,      MUTUAL, PARAM,  _BOOLEAN,  &pcscCfg.useMappedMemory),
+	KVP(PORT_NUMBER,            MUTUAL, PARAM,  _NUMERIC,  &pcscCfg.portNbr),
+	KVP(PORT_NUMBER_WILD,       MUTUAL, INTERN, _BOOLEAN,  &pcscCfg.portNbrWild),
+	KVP(MEMORY_MAPPED_FILE,     MUTUAL, PARAM,  _STRING,   &pcscCfg.pcscdMemMappedFile),
+	KVP(X_HOST_IP,              MUTUAL, PARAM,  _IPADDR,   &pcscCfg.xHostIp),
+	KVP(DISPLAY_NUMBER,         MUTUAL, PARAM,  _NUMERIC,  &pcscCfg.dpyNbr),
+	KVP(SCREEN_NUMBER,          MUTUAL, PARAM,  _NUMERIC,  &pcscCfg.screenNbr),
+	KVP(NET_BIND_FILE,          MUTUAL, INTERN, _STRING,   &pcscCfg.netBindFile),
+	KVP(CONSUMER,               MUTUAL, INTERN, _CONSTANT, &pcscCfg.consumer),
+	KVP(BASE_DIR,               MUTUAL, PARAM,  _STRING,   &pcscCfg.baseDir),
+	KVP(LAUNCH_MODE,            MUTUAL, PARAM,  _CONSTANT, &pcscCfg.launchMode),
+	KVP(VERBOSE,                MUTUAL, PARAM,  _NUMERIC,  &pcscCfg.verbose),
+};
+
+
+enum CFGerrors {
+	CFG_SUCCESS = 0,
+	CFG_NULL_POINTER = -3000,
+	CFG_OUT_OF_MEMORY,
+	CFG_SYNTAX_ERROR,
+	CFG_FILE_NOT_FOUND,
+	CFG_NON_INTEGER,
+	CFG_UNRECOGNIZED_CONSTANT,
+	CFG_MISSING_VALUE,
+	CFG_BAD_PARAM,
+	CFG_DISALLOWED_PARAM,
+	CFG_ILLEGAL_OPTION,
+	CFG_VALUE_OUT_OF_RANGE,
+	CFG_UNRECOGNIZED_KEY,
+	CFG_UNTERMINATED_QUOTE,
+	CFG_MISSING_DELIMITER,
+	CFG_INVALID_PATH,
+	CFG_INVALID_FILE_PATH,
+	CFG_INVALID_DIR_PATH,
+	CFG_FILE_CREATION_ERROR,
+	CFG_DIR_CREATION_ERROR,
+	CFG_CANNOT_REMOVE_PATH,
+	CFG_BAD_DISPLAY_VALUE,
+	CFG_UNDEFINED_DISPLAY,
+	CFG_TABLE_ERROR,
+	CFG_INTERNAL_ERROR,
+	CFG_UNDEFINED_PORT,
+	CFG_BAD_WILDCARD_OFFSET,
+};
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif
+
+#endif
+

Modified: branches/Solaris/src/pcscdaemon.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/pcscdaemon.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/pcscdaemon.c (original)
+++ branches/Solaris/src/pcscdaemon.c Thu Jun 12 10:28:09 2008
@@ -4,11 +4,10 @@
  * Copyright (C) 1999-2005
  *  David Corcoran <corcoran at linuxnet.com>
  *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
  *
  * $Id$
- */
-
-/**
+ *
  * @file
  * @brief This is the main pcscd daemon.
  *
@@ -17,24 +16,44 @@
  * Client connection a call to \c CreateContextThread() is done.
  */
 
+
 #include "config.h"
-#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <syslog.h>
 #include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/varargs.h>
+#include <strings.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+#include <limits.h>
+#include <syslog.h>
+
+
+#include <dlfcn.h>
+#include <link.h>
+
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
 #endif
 
 #include "misc.h"
 #include "pcsclite.h"
+#include "pcsc_config.h"
+#include "daemon_utils.h"
 #include "debuglog.h"
+#include "instance.h"
 #include "winscard_msg.h"
 #include "winscard_svc.h"
 #include "sys_generic.h"
@@ -43,95 +62,58 @@
 #include "readerfactory.h"
 #include "configfile.h"
 #include "powermgt_generic.h"
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
+#include "pcscdaemon.h"
+#include "validate.h"
+
+PCSCLITE_MUTEX usbNotifierMutex;
+char *execPath;
+struct pcsc_cfg_data pcscCfg;
+struct pcsc_cfg_data launcherCfg;
 
 char AraKiri = FALSE;
 static char Init = TRUE;
 extern char ReCheckSerialReaders;
-
-/*
- * Some internal functions 
- */
-void SVCServiceRunLoop(void);
-void SVCClientCleanup(psharedSegmentMsg);
-void at_exit(void);
-void clean_temp_files(void);
-void signal_reload(int sig);
-void signal_trap(int);
-void print_version (void);
-void print_usage (char const * const);
-
-PCSCLITE_MUTEX usbNotifierMutex;
-
-/*
- * Cleans up messages still on the queue when a client dies 
- */
-void SVCClientCleanup(psharedSegmentMsg msgStruct)
-{
-	/*
-	 * May be implemented in future releases 
-	 */
-}
+static int column = 0;
+
+void printWrap(const char *, ...);
+void ListInvocationModes();
+void usage(char const * const);
+
 
 /**
  * @brief The Server's Message Queue Listener function.
  *
- * An endless loop calls the function \c SHMProcessEventsServer() to check for
- * messages sent by clients.
- * If the message is valid, \c CreateContextThread() is called to serve this 
- * request.
+ * An endless loop calls the function \c SHMProcessEventsServer() to
+ * check for messages sent by clients.
+ *
+ * If the message is valid, \c CreateContextThread() is called to
+ * serve this request.
  */
-void SVCServiceRunLoop(void)
-{
-	int rsp;
-	LONG rv;
-	DWORD dwClientID;	/* Connection ID used to reference the Client */
-	
-	rsp = 0;
-	rv = 0;
-
-	/*
-	 * Initialize the comm structure 
-	 */
-	rsp = SHMInitializeCommonSegment();
-
-	if (rsp == -1)
-	{
+void
+SVCServiceRunLoop(void)
+{
+	int rsp = 0;
+	LONG rv = 0;
+	DWORD dwClientID;  /* Connection ID (fd) used to reference Client */
+
+	if (SHMInitializeCommonSegment() == -1) {
 		Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
 		exit(-1);
 	}
 
-	/*
-	 * Initialize the contexts structure 
-	 */
-	rv = ContextsInitialize();
-
-	if (rv == -1)
-	{
+	if (ContextsInitialize() == -1) {
 		Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
 		exit(-1);
 	}
 
-	/*
-	 * Solaris sends a SIGALRM and it is annoying 
-	 */
-
-	signal(SIGALRM, SIG_IGN);
+	signal(SIGALRM, SIG_IGN); // Disable SIGALRM sent by Solaris
 	signal(SIGPIPE, SIG_IGN);
-	signal(SIGHUP, SIG_IGN);	/* needed for Solaris. The signal is sent
-				 * when the shell is existed */
-
-	/*
-	 * This function always returns zero 
-	 */
-	rsp = SYS_MutexInit(&usbNotifierMutex);
-
-	/*
-	 * Set up the search for USB/PCMCIA devices 
+	signal(SIGHUP,  SIG_IGN); // Disable SIGHUP sent by Solaris if shell
+
+	(void) SYS_MutexInit(&usbNotifierMutex);
+
+	/*
+	 * Set up the search for USB/PCMCIA devices
 	 */
 	HPSearchHotPluggables();
 	HPRegisterForHotplugEvents();
@@ -141,256 +123,677 @@
 	 */
 	PMRegisterForPowerEvents();
 
-	while (TRUE)
-	{
-
-		switch (rsp = SHMProcessEventsServer(&dwClientID, 0))
-		{
-
+	while (TRUE) {
+		switch (rsp = SHMProcessEventsServer(&dwClientID, 0)) {
 		case 0:
-			Log2(PCSC_LOG_DEBUG, "A new context thread creation is requested: %d", dwClientID);
+			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");
+			if (rv != SCARD_S_SUCCESS)  {
+				Log1(PCSC_LOG_ERROR,
+				     "Problem in context thread creation");
 				AraKiri = TRUE;
 			}
-
 			break;
 
 		case 2:
 			/*
-			 * timeout in SHMProcessEventsServer(): do nothing
-			 * this is used to catch the Ctrl-C signal at some time when
-			 * nothing else happens
+			 * Timeout in SHMProcessEventsServer(): do nothing
+			 * this is used to catch the Ctrl-C signal at some
+			 * time when nothing else happens
 			 */
 			break;
 
 		case -1:
-			/* do not display if we are exiting or re-reading the config */
+			/* Don't display if exiting or re-reading config */
 			if ((!AraKiri) && (!ReCheckSerialReaders))
-				Log1(PCSC_LOG_ERROR, "Error in SHMProcessEventsServer");
+				Log1(PCSC_LOG_ERROR,
+				     "Error in SHMProcessEventsServer");
 			break;
 
 		default:
-			Log2(PCSC_LOG_ERROR, "SHMProcessEventsServer unknown retval: %d",
-				rsp);
-			break;
-		}
-
-		if (AraKiri)
-		{
+			Log2(PCSC_LOG_ERROR,
+			    "SHMProcessEventsServer unknown retval: %d", rsp);
+			break;
+		}
+		if (AraKiri) {
 			/* stop the hotpug thread and waits its exit */
 			HPStopHotPluggables();
 			SYS_Sleep(1);
 
-			/* now stop all the drivers */
-			RFCleanupReaders(1);
-		}
-	}
-}
-
-int main(int argc, char **argv)
-{
-	int rv;
-	char setToForeground;
-	char *newReaderConfig;
-	struct stat fStatBuf;
-	int opt;
-#ifdef HAVE_GETOPT_LONG
-	int option_index = 0;
-	static struct option long_options[] = {
-		{"config", 1, 0, 'c'},
-		{"foreground", 0, 0, 'f'},
-		{"help", 0, 0, 'h'},
-		{"version", 0, 0, 'v'},
-		{"apdu", 0, 0, 'a'},
-		{"debug", 0, 0, 'd'},
-		{"info", 0, 0, 0},
-		{"error", 0, 0, 'e'},
-		{"critical", 0, 0, 'C'},
-		{0, 0, 0, 0}
-	};
+			RFCleanupReaders(1);  // Stop all driver
+		}
+	}
+}
+
+
+int
+main(int argc, char **argv)
+{
+	char args[LINEMAX];
+	char cwd[LINEMAX];
+	char name[LINEMAX];
+	char tmp[MAXPATHLEN];
+	char *cp;
+	int i, opt, servicePort = 0;
+	int stopInstFlag = 0, rv;
+	int dpyNbr, screenNbr;
+	int instpid = 0;
+	in_addr_t xHostIp;
+
+#ifdef PCSCLITE_PORTSVC_PORTNO
+	servicePort = PCSCLITE_PORTSVC_PORTNO;
+#else
+	servicePort = 0;
 #endif
-	
-	rv = 0;
-	newReaderConfig = 0;
-	setToForeground = 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);
-
+
+	pcscCfg.argv0 = strdup(argv[0]);
+	ChkVersion();
+
+	/*
+	 * Build list of the valid options.
+	 */
+	bzero(args, sizeof (args));
+	for (i = 0; longOpts[i].name != NULL; i++) {
+		char item[4];
+		if (longOpts[i].has_arg)
+			sprintf(item, "%c:", longOpts[i].val);
+		else
+			sprintf(item, "%c", longOpts[i].val);
+		strcat(args, item);
+	}
+
+	/*
+	 * Check for these options first
+	 */
+	CFGSetConfigConsumer(DEFAULT);
+	while ((opt = GETOPT(argc, argv, args, longOpts, optIndex)) != -1) {
+		switch(opt) {
+		case OPT_INSTANCE:
+			CFGSetConfigConsumer(INSTANCE);
+			break;
+		case OPT_LAUNCHER:
+			CFGSetConfigConsumer(LAUNCHER);
+			break;
+		}
+	}
+
+	/*
+	 * Set up defaults
+	 */
+	DebugLogSetLogType(DEBUGLOG_SYSLOG_DEBUG);
+	DebugLogSetLevel(PCSC_LOG_CRITICAL);
+
+	CFGDefault("USE_AUTHENTICATION",	"FALSE");
+	CFGDefault("TRANSPORT",			"SOCKET_UNIX");
+	CFGDefault("USE_MAPPED_MEMORY",		"TRUE");
+	CFGDefault("PORT_NUMBER_WILD",		"FALSE");
+	CFGDefault("INSTANCE_TIMEOUT",		"0");
+	CFGDefault("BASE_DIR_WILD",		"FALSE");
+	CFGDefault("LOG_LEVEL",			"CRITICAL");
+	CFGDefault("LOG_TYPE",			"SYSLOG");
+	CFGDefault("STATUS_POLL_RATE",		"400000");
+	CFGDefault("FIFO_PING_TIMEOUT",         "4");
+	CFGDefault("RELAUNCH_THRESHOLD",        "2");
+	CFGDefault("RELAUNCH_INTERVAL",         "1");
+
+	pcscCfg.pcscConfigFile = PCSCLITE_CONFIG_DIR "/pcscd.conf";
+
+
+	/*
+	 * Scan options for arguments to process prior to loading config file
+	 */
+	 optind = 0;  // Reset for re-processing cmd line args
+	 while ((opt = GETOPT(argc, argv, args, longOpts, optIndex)) != -1) {
+		switch(opt) {
+		case OPT_STOPINST:
+			/*
+			 * Defer geting X display #
+			 */
+			stopInstFlag = TRUE;
+			break;
+
+		case OPT_LAUNCHER:  //Intentionally handled before & after file load.
+			if (servicePort > 0) {
+				rv = CFGSetArg(opt, "LAUNCH_MODE", "LAUNCHER", USER);
+				if (rv != CFG_SUCCESS) {
+					CFGperror(rv, "OPT_LAUNCHER");
+					exit(EXIT_FAILURE);
+				}
+			} else {
+				Log2(PCSC_LOG_ERROR,
+				     "-%c option not enabled. See "
+				     "'configure --enable-portsvc'",
+				     OPT_LAUNCHER);
+				exit(EXIT_FAILURE);
+			}
+			break;
+		case OPT_INSTANCE:  //Intentionally handled before & after file load.
+
+			if (servicePort > 0) {
+				rv = CFGSetArg(opt, "LAUNCH_MODE", "INSTANCE", USER);
+				if (rv != CFG_SUCCESS) {
+					CFGperror(rv, "OPT_INSTANCE");
+					exit(EXIT_FAILURE);
+				}
+			} else {
+				Log2(PCSC_LOG_ERROR,
+				     "-%c option not enabled. See "
+				     "'configure --enable-portsvc'",
+				     OPT_INSTANCE);
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_DISPLAY:
+			rv = CFGParseXdisplay(optarg,
+				 &dpyNbr, &screenNbr, &xHostIp);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_DISPLAY");
+				exit(EXIT_FAILURE);
+			}
+			pcscCfg.dpyNbr = dpyNbr;
+			pcscCfg.screenNbr = screenNbr;
+			pcscCfg.xHostIp = xHostIp;
+			break;
+
+		case OPT_CONFIG:
+			pcscCfg.pcscConfigFile = strdup(optarg);
+			break;
+
+		case OPT_PID:
+			instpid = atoi(optarg);
+			if (instpid == 0) {
+				Log1(PCSC_LOG_CRITICAL, "Invalid PID");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_LOGFILE:
+			rv = CFGSetArg(opt, "LOG_FILE", optarg, USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "LOG_FILE");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_FOREGROUND:
+			DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG);
+			rv = CFGSetArg(opt, "RUN_IN_FOREGROUND", "TRUE",  USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_FOREGROUND");
+				exit(EXIT_FAILURE);
+			}
+
+			rv = CFGProcessKvp("LOG_TYPE", "STDERR", USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_FOREGROUND");
+				exit(EXIT_FAILURE);
+			}
+
+			break;
+
+		case OPT_LOGTYPE:
+			rv = CFGSetArg(opt, "LOG_TYPE", optarg,  USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_LOGTYPE");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_LOGLEVEL:
+			DebugLogSetLevel(PCSC_LOG_DEBUG);
+			rv = CFGSetArg(opt, "LOG_LEVEL", optarg,  USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_SET_LOGLEVEL");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	/*
+	 * Load main config file, used by both launcher and instance.
+	 * (instance also loads instance-specific conf later).
+	 */
+	rv = CFGLoadConfigFile(pcscCfg.pcscConfigFile);
+	if (rv != CFG_SUCCESS) {
+		CFGperror(rv, "Error loading configuration file");
+		exit(EXIT_FAILURE);
+	}
+	bcopy(&pcscCfg, &launcherCfg, sizeof (pcscCfg));
+
+	CFGSetupLogging();
+	if (pcscCfg.logType == STDERR && pcscCfg.logFile != NULL) {
+		pcscCfg.logFile = CFGRetrofitPath(pcscCfg.logFile, NULL);
+		CFGStdOutErr(pcscCfg.logFile);
+	}
+
+	sprintf(tmp, "%s/pcscd_validate.conf", 	PCSCLITE_LIB_DIR);
+	pcscCfg.validateConf = strdup(tmp);
+
+	VALloadPlugins();
+
+	if (pcscCfg.launchMode == INSTANCE) {
+		char *cfg, *inst;
+		if (VALfindInstanceFiles(pcscCfg.dpyNbr, &cfg, &inst) < 0) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "Couldn't find instance files for display %d",
+			    pcscCfg.dpyNbr);
+			exit(EXIT_FAILURE);
+		}
+		pcscCfg.pcscConfigFile = cfg;
+		pcscCfg.instanceScript = inst;
+		(void) CFGLoadConfigFile(pcscCfg.pcscConfigFile);
+		if (pcscCfg.baseDir != NULL) {
+		       if (pcscCfg.baseDirWild) {
+			    char dpyNbr[6];
+			    if (pcscCfg.dpyNbr == -1) {
+				    CFGperror(CFG_UNDEFINED_DISPLAY, "");
+				    exit(EXIT_FAILURE);
+			    }
+			    sprintf(dpyNbr, "%d", pcscCfg.dpyNbr);
+			    CFGresolveWildcard(&pcscCfg.baseDir, dpyNbr);
+			}
+		}
+		CFGSetupLogging();
+		if (pcscCfg.logType == STDERR && pcscCfg.logFile != NULL) {
+			pcscCfg.logFile = CFGRetrofitPath(pcscCfg.logFile, NULL);
+			CFGStdOutErr(pcscCfg.logFile);
+		}
+		Log2(PCSC_LOG_DEBUG, "pcscd PID=%d logging...\n", getpid());
+		if (pcscCfg.apduDebug) {
+			Log1(PCSC_LOG_DEBUG,
+				"Setting APDU debug mode");
+			DebugLogSetCategory(DEBUG_CATEGORY_APDU);
+		}
+	}
+
+
+	if (stopInstFlag) {
+		if (instpid == 0) {
+			fprintf(stderr, "Must specify valid PID\n");
+			exit(-1);
+		}
+		StopInstance(pcscCfg.dpyNbr, instpid);
+		exit(0);
+	} else if (pcscCfg.launchMode == LAUNCHER) {
+		if (*argv[0] != '/') {
+			Log1(PCSC_LOG_CRITICAL,
+			     "Must invoke with full path to executable\n"
+			     "in launcher mode");
+			exit(EXIT_FAILURE);
+		}
+		execPath = strdup(argv[0]);
+
+		if (pcscCfg.portNbr == 0 && servicePort > 0)
+			pcscCfg.portNbr =  servicePort;
+
+		pcscCfg.dpyNbr = -1;
+		pcscCfg.screenNbr = -1;
+		pcscCfg.xHostIp = -1;
+
+		if (strlen(XSERVERS_FILE) == 0) {
+		    Log1(PCSC_LOG_CRITICAL,
+			 "Must configure with --enable-xtag=<Xservers PATH>\n"
+			 "To run in port service/daemon-launcher mode (-#)");
+		    exit(EXIT_FAILURE);
+		}
+	} else if (pcscCfg.launchMode != INSTANCE) {
+		/*
+		* Attempt to read DISPLAY from the environment.
+		* We excuse it here if it's not defined, because it may
+		* be passed as an argv[] option, or simply not required
+		* depending on other options pcscd was launched with.
+		*/
+		int rv = CFGParseXdisplay(SYS_Getenv("DISPLAY"),
+			&dpyNbr, &screenNbr, &xHostIp);
+		pcscCfg.dpyNbr = dpyNbr;
+		pcscCfg.screenNbr = screenNbr;
+		pcscCfg.xHostIp = xHostIp;
+		switch(rv) {
+		case CFG_SUCCESS:
+		case CFG_UNDEFINED_DISPLAY:
+			break;
+		default:
+			CFGperror(rv, "Error parsing display");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+
+
+	/*
+	 * Re-scan command line arguments for remaining arguments.
+	 * Arguments found in this scan override the conf file
+	 * settings.
+	 */
+	optind = 0;  // Reset for re-processing cmd line args
+	while ((opt = GETOPT(argc, argv, args, longOpts, optIndex)) != -1) {
+		switch (opt) {
+		case OPT_LAUNCHER: //handled before & after file load.
+
+			if (servicePort > 0) {
+				rv = CFGSetArg(opt, "LAUNCH_MODE", "LAUNCHER", USER);
+				if (rv != CFG_SUCCESS) {
+					CFGperror(rv, "OPT_LAUNCHER");
+					exit(EXIT_FAILURE);
+				}
+			} else {
+				Log2(PCSC_LOG_ERROR,
+				     "-%c option not enabled. See "
+				     "'configure --enable-portsvc'",
+				     OPT_LAUNCHER);
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_INSTANCE:  //Instance processing both before & after file load.
+
+			if (servicePort > 0) {
+				rv = CFGSetArg(opt, "LAUNCH_MODE", "INSTANCE", USER);
+				if (rv != CFG_SUCCESS) {
+					CFGperror(rv, "OPT_INSTANCE");
+					exit(EXIT_FAILURE);
+				}
+			} else {
+				Log2(PCSC_LOG_ERROR,
+				     "-%c option not enabled. See "
+				     "'configure --enable-portsvc'",
+				     OPT_INSTANCE);
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_USEAUTH:
+			rv =  CFGSetArg(opt, "USE_AUTHENTICATION", "TRUE", USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_USEAUTH");
+				exit(EXIT_FAILURE);
+			}
+			break;
+		case OPT_READERCFG:
+			Log2(PCSC_LOG_DEBUG, "using new config file: %s",
+			     optarg);
+			rv = CFGSetArg(opt, "READER_CONFIG_FILE", optarg, USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_READERCFG");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_BASEDIR:
+			rv = CFGSetArg(opt, "BASE_DIR", optarg, USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_BASEDIR");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_IFDLIBDIR:
+			rv = CFGSetArg(opt, "IFD_PLUGIN_PATH", optarg, USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_IFDLIBDIR");
+				exit(EXIT_FAILURE);
+			}
+			break;
+		case OPT_PORT:
+			rv = CFGSetArg(opt, "PORT_NUMBER", optarg, USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_PORT");
+				exit(EXIT_FAILURE);
+			}
+			break;
+		case OPT_VERBOSE:
+			rv = CFGSetArg(opt, "VERBOSE", optarg, USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_VERBOSE");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_TRANSPORT:
+			rv = CFGSetArg(opt, "TRANSPORT", optarg, USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_TRANSPORT");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_TIMEOUT:
+			rv = CFGSetArg(opt, "INSTANCE_TIMEOUT", optarg, USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_TIMEOUT");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_MAPFILE:
+			rv = CFGSetArg(opt, "MEMORY_USEMAPPED_FILE", optarg, USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_MAPFILE");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_USEMAPPED:
+			rv = CFGSetArg(opt, "USE_MAPPED_MEMORY", optarg, USER);
+			if (rv != CFG_SUCCESS) {
+				CFGperror(rv, "OPT_USEMAPPED");
+				exit(EXIT_FAILURE);
+			}
+			break;
+
+		case OPT_HELP:
+			usage(argv[0]);
+			return EXIT_SUCCESS;
+
+		case OPT_VERSION:
+			print_version();
+			return EXIT_SUCCESS;
+
+		case OPT_APDU:
+			DebugLogSetCategory(DEBUG_CATEGORY_APDU);
+			break;
+
+		case OPT_FOREGROUND:    /* Ignore (processed earlier) */
+		case OPT_STOPINST:      /* Ignore (processed earlier) */
+		case OPT_DISPLAY:       /* Ignore (processed earlier) */
+		case OPT_CONFIG:        /* Ignore (processed earlier) */
+		case OPT_LOGTYPE:       /* Ignore (processed earlier) */
+		case OPT_LOGLEVEL:      /* Ignore (processed earlier) */
+		case OPT_LOGFILE:       /* Ignore (processed earlier) */
+			break;
+		default:
+			usage (argv[0]);
+			return EXIT_FAILURE;
+		}
+	}
+
+	if (argv[optind]) {
+		printf("Unknown option: %s\n\n", argv[optind]);
+		usage(argv[0]);
+		return EXIT_SUCCESS;
+	}
+	/*
+	 * Create subdirectory under specified base dir if
+	 * a wildcard was specified and set that as the new
+	 * base dir.
+	 */
+	if (pcscCfg.baseDir != NULL) {
+		if (pcscCfg.baseDirWild) {
+			char dpyNbr[6];
+			if (pcscCfg.dpyNbr == -1) {
+				Log1(PCSC_LOG_CRITICAL, "Undefined $DISPLAY");
+				return EXIT_FAILURE;
+			}
+			sprintf(dpyNbr, "%d", pcscCfg.dpyNbr);
+			CFGresolveWildcard(&pcscCfg.baseDir, dpyNbr);
+		}
+		rv = CFGEnsurePathExists(pcscCfg.baseDir);
+	}
+
+
+	chdir(pcscCfg.baseDir);
+
+	/*
+	 * These commands need to be deferred until this point
+	 * to allow all the options from the command line to be
+	 * provided, along with the loading of the configuration
+	 * file, and the overrides applied if any.
+	 */
+	if (pcscCfg.launchMode == INSTANCE) {
+		InitializeInstance();
+		exit(0);
+	}
+
+	/*
+	 * Adjust port number by the wildcard specifier, if any.
+	 */
+	 if (pcscCfg.portNbrWild) {
+		    if (pcscCfg.dpyNbr == -1) {
+			  Log1(PCSC_LOG_CRITICAL, "Undefined $DISPLAY");
+			  return EXIT_FAILURE;
+		    }
+		    CFGresolveWildcard(&pcscCfg.portNbr,
+			(void *)pcscCfg.dpyNbr);
+	 }
+
+	/* If X display # exists, make available to IFD handlers */
+	if (pcscCfg.dpyNbr != -1) {
+		static char display[_POSIX_HOST_NAME_MAX + 15];
+		sprintf(display, "DISPLAY=:%d", pcscCfg.dpyNbr);
+		putenv(display);
+	}
+
+	/*
+	 * Adapt all of the server configuration file paths, assigning
+	 * a default value (based on header constants) to any path
+	 * unspecified by the administrator.
+	 *.
+	 * If a base directory was specified, adapt resultant filepaths
+	 * to be relative to it using the following method:
+	 *
+	 *   a. Unspecified files which were assigned default names in the
+	 *      first step are put into *default* subtree locations under
+	 *      the base dir.
+	 *
+	 *   b. Filepaths that were specified by the administrator are
+	 *      converted from absolute paths to relative paths under the
+	 *      base dir.
+	 *
+	 * Note: If the IFD library plugin dir is specified by the admin,
+	 *       it overrides any dir locations specified in readers.conf
+	 */
+	if (pcscCfg.readerConfigFile == NULL)
+		pcscCfg.readerConfigFile =
+		    CFGRetrofitPath(
+		       PCSCLITE_CONFIG_DIR "/reader.conf", "/etc");
+	else
+		pcscCfg.readerConfigFile =
+		    CFGRetrofitPath(pcscCfg.readerConfigFile, NULL);
+
+	if (pcscCfg.ifdPluginDir != NULL)
+		pcscCfg.ifdPluginDir =
+		    CFGRetrofitPath(pcscCfg.ifdPluginDir, NULL);
+
+	if (pcscCfg.useMappedMemory) {
+		if (pcscCfg.pcscdMemMappedFile == NULL)
+			pcscCfg.pcscdMemMappedFile =
+			    CFGRetrofitPath(PCSCLITE_PUBSHM_FILE, "/var/run");
+		else
+			pcscCfg.pcscdMemMappedFile =
+			CFGRetrofitPath(pcscCfg.pcscdMemMappedFile, NULL);
+	} else {
+		pcscCfg.pcscdMemMappedFile = NULL;
+	}
+
+	if (pcscCfg.transportType == SOCKET_UNIX ||
+	    pcscCfg.launchMode == LAUNCHER) {
+		if (pcscCfg.netBindFile == NULL) {
+			pcscCfg.netBindFile =
+			    CFGRetrofitPath(PCSCLITE_CSOCK_NAME, "/var/run");
+		} else {
+			pcscCfg.netBindFile =
+			    CFGRetrofitPath(pcscCfg.netBindFile, NULL);
+		}
+	}
+#ifdef USE_RUN_PID
+	if (pcscCfg.pcscdPIDFile == NULL) {
+		pcscCfg.pcscdPIDFile =
+		    CFGRetrofitPath(USE_RUN_PID, "/var/run");
+	} else {
+		pcscCfg.pcscdPIDFile =
+		    CFGRetrofitPath(pcscCfg.pcscdPIDFile, NULL);
+	}
+#endif
+	if (pcscCfg.launchMode == LAUNCHER) {
+		pcscCfg.readerConfigFile = NULL;
+		pcscCfg.ifdPluginDir = NULL;
+		pcscCfg.pcscdMemMappedFile = NULL;
+		pcscCfg.netBindFile = NULL;
+		pcscCfg.useMappedMemory = FALSE;
+	}
+
+	/*
+	 * Make sure directory exists for these files.
+	 * Depending on the paths configured by the admin, these
+	 * directories may overlap or even refer multiply to the
+	 * same directory, but it is harmless, since it won't create
+	 * directories that exist.
+	 */
+	if (pcscCfg.netBindFile != NULL) {
+		CFGEnsurePathExists(
+		    cp = SYS_Dirname(pcscCfg.netBindFile));
+		if (cp != NULL)
+			free(cp);
+	}
+
+	if (pcscCfg.useMappedMemory) {
+		CFGEnsurePathExists(
+		    cp = SYS_Dirname(pcscCfg.pcscdMemMappedFile));
+		if (cp != NULL)
+			free(cp);
+	}
+
+#ifdef USE_RUN_PID
+	if (pcscCfg.pcscdPIDFile != NULL) {
+		CFGEnsurePathExists(
+		    cp = SYS_Dirname(pcscCfg.pcscdPIDFile));
+		if (cp != NULL)
+			free(cp);
+	}
+#endif
+
+	CFGdumpCfg(NULL);
+
+	if (DoRunCheck() < 0)
 		return EXIT_FAILURE;
-	}
-
-	/*
-	 * 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, "c:fdhvaeC", long_options, &option_index)) != -1) {
-#else
-	while ((opt = getopt (argc, argv, "c:fdhvaeC")) != -1) {
-#endif
-		switch (opt) {
-			case 'c':
-				Log2(PCSC_LOG_INFO, "using new config file: %s", optarg);
-				newReaderConfig = optarg;
-				break;
-
-			case 'f':
-				setToForeground = TRUE;
-				/* debug to stderr instead of default syslog */
-				DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG);
-				Log1(PCSC_LOG_INFO,
-					"pcscd set to foreground with debug send to stderr");
-				break;
-
-			case 'd':
-				DebugLogSetLevel(PCSC_LOG_DEBUG);
-				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;
-
-			default:
-				print_usage (argv[0]);
-				return EXIT_FAILURE;
-		}
-
-	}
-	
-	if (argv[optind])
-	{
-		printf("Unknown option: %s\n\n", argv[optind]);
-		print_usage(argv[0]);
-		return EXIT_SUCCESS;
-	}
-
-	/*
-	 * test the presence of /var/run/pcsc.pub
-	 */
-
-	rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &fStatBuf);
-
-	if (rv == 0)
-	{
-#ifdef USE_RUN_PID
-
-		/* read the pid file to get the old pid and test if the old pcscd is
-		 * still running 
-		 */
-		FILE *f;
-		/* pids are only 15 bits but 4294967296
-		 * (32 bits in case of a new system use it) is on 10 bytes
-		 */
-#define PID_ASCII_SIZE 11
-		char pid_ascii[PID_ASCII_SIZE];
-		int pid;
-
-		if ((f = fopen(USE_RUN_PID, "rb")) != NULL)
-		{
-			fgets(pid_ascii, PID_ASCII_SIZE, f);
-			fclose(f);
-
-			pid = atoi(pid_ascii);
-
-			if (kill(pid, 0) == 0)
-			{
-				Log1(PCSC_LOG_CRITICAL,
-					"file " PCSCLITE_PUBSHM_FILE " already exists.");
-				Log2(PCSC_LOG_CRITICAL,
-					"Another pcscd (pid: %d) seems to be running.", pid);
-				return EXIT_FAILURE;
-			}
-			else
-				/* the old pcscd is dead. make some cleanup */
-				clean_temp_files();
-		}
-		else
-		{
-			Log1(PCSC_LOG_CRITICAL,
-				"file " PCSCLITE_PUBSHM_FILE " already exists.");
-			Log1(PCSC_LOG_CRITICAL,
-				"Maybe another pcscd is running?");
-			Log1(PCSC_LOG_CRITICAL, 
-				"I can't read process pid from " USE_RUN_PID);
-			Log1(PCSC_LOG_CRITICAL,
-				"Remove " PCSCLITE_PUBSHM_FILE " and " PCSCLITE_CSOCK_NAME);
-			Log1(PCSC_LOG_CRITICAL,
-				"if pcscd is not running to clear this message.");
-			return EXIT_FAILURE;
-		}
-#else
-		Log1(PCSC_LOG_CRITICAL,
-			"file " PCSCLITE_PUBSHM_FILE " already exists.");
-		Log1(PCSC_LOG_CRITICAL,
-			"Maybe another pcscd is running?");
-		Log1(PCSC_LOG_CRITICAL,
-			"Remove " PCSCLITE_PUBSHM_FILE " and " PCSCLITE_CSOCK_NAME);
-		Log1(PCSC_LOG_CRITICAL,
-			"if pcscd is not running to clear this message.");
-		return EXIT_FAILURE;
-#endif
-	}
-
-	/*
-	 * If this is set to one the user has asked it not to fork 
-	 */
-	if (!setToForeground)
-	{
-		if (SYS_Daemon(0, 0))
-			Log2(PCSC_LOG_CRITICAL, "SYS_Daemon() failed: %s",
-				strerror(errno));
-	}
-
-	/*
-	 * cleanly remove /tmp/pcsc when exiting 
+
+	if (!pcscCfg.runInForeground) {
+		Daemonize();
+	}
+
+	/*
+	 * cleanly remove /tmp/pcsc when exiting
 	 */
 	signal(SIGQUIT, signal_trap);
 	signal(SIGTERM, signal_trap);
-	signal(SIGINT, signal_trap);
-	signal(SIGHUP, signal_trap);
+	signal(SIGINT,  signal_trap);
 
 #ifdef USE_RUN_PID
 	/*
-	 * Record our pid to make it easier
-	 * to kill the correct pcscd
+	 * Record our pid to make it easier to kill the correct pcscd
 	 */
 	{
 		FILE *f;
-
-		if ((f = fopen(USE_RUN_PID, "wb")) != NULL)
+		if ((f = fopen(pcscCfg.pcscdPIDFile, "wb")) != NULL)
 		{
 			fprintf(f, "%u\n", (unsigned) getpid());
 			fclose(f);
@@ -398,84 +801,47 @@
 	}
 #endif
 
-	/*
-	 * If PCSCLITE_IPC_DIR does not exist then create it
-	 */
-	rv = SYS_Stat(PCSCLITE_IPC_DIR, &fStatBuf);
-	if (rv < 0)
-	{
-		rv = SYS_Mkdir(PCSCLITE_IPC_DIR, S_ISVTX | S_IRWXO | S_IRWXG | S_IRWXU);
-		if (rv != 0)
-		{
-			Log2(PCSC_LOG_CRITICAL,
-				"cannot create " PCSCLITE_IPC_DIR ": %s", strerror(errno));
-			return EXIT_FAILURE;
-		}
+	if (pcscCfg.launchMode == LAUNCHER) {
+		Init = FALSE;
+		Launcher(pcscCfg.portNbr);
+		return 0;
 	}
 
 	/* cleanly remove /var/run/pcsc.* files when exiting */
 	if (atexit(at_exit))
-		Log2(PCSC_LOG_CRITICAL, "atexit() failed: %s", strerror(errno));
-
-	/*
-	 * Allocate memory for reader structures 
-	 */
-	RFAllocateReaderSpace();
-
-	/*
-	 * 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));
+		Log2(PCSC_LOG_CRITICAL,
+		     "atexit() failed: %s", strerror(errno));
+
+	RFAllocateReaderSpace(); // Allocate memory for reader structs
+
+	/*
+	 * Grab the information from the reader.conf
+	 */
+	if (pcscCfg.readerConfigFile) {
+		if ( RFStartSerialReaders(pcscCfg.readerConfigFile) != 0) {
+			Log3(PCSC_LOG_CRITICAL,
+			     "Invalid reader config file:\n%s: %s",
+			     pcscCfg.readerConfigFile, strerror(errno));
 			at_exit();
 		}
 	}
-	else
-	{
-		rv = RFStartSerialReaders(PCSCLITE_READER_CONFIG);
-
-#if 0
-		if (rv == 1)
-		{
-			Log1(PCSC_LOG_INFO,
-				"warning: no " PCSCLITE_READER_CONFIG " found");
-			/*
-			 * Token error in file 
-			 */
-		}
-		else
-#endif
-			if (rv == -1)
-				at_exit();
-	}
-
-	/*
-	 * Set the default globals 
-	 */
-	g_rgSCardT0Pci.dwProtocol = SCARD_PROTOCOL_T0;
-	g_rgSCardT1Pci.dwProtocol = SCARD_PROTOCOL_T1;
+	/*
+	 * Set the default globals
+	 */
+	g_rgSCardT0Pci.dwProtocol  = SCARD_PROTOCOL_T0;
+	g_rgSCardT1Pci.dwProtocol  = SCARD_PROTOCOL_T1;
 	g_rgSCardRawPci.dwProtocol = SCARD_PROTOCOL_RAW;
 
-	Log1(PCSC_LOG_INFO, "pcsc-lite " VERSION " daemon ready.");
-
-	/*
-	 * post initialistion 
-	 */
-	Init = FALSE;
-
-	/*
-	 * signal_trap() does just set a global variable used by the main loop 
+	Log1(PCSC_LOG_DEBUG, "pcsc-lite " VERSION " daemon ready.");
+
+	Init = FALSE;  // Post initialization
+	/*
+	 * signal_trap() merely sets a global var, used by main loop
 	 */
 	signal(SIGQUIT, signal_trap);
 	signal(SIGTERM, signal_trap);
-	signal(SIGINT, signal_trap);
-	signal(SIGHUP, signal_trap);
-
+	signal(SIGINT,  signal_trap);
+	signal(SIGHUP,  signal_trap);
 	signal(SIGUSR1, signal_reload);
 
 	SVCServiceRunLoop();
@@ -484,93 +850,415 @@
 	return EXIT_FAILURE;
 }
 
-void at_exit(void)
-{
-	Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR);
-
-	clean_temp_files();
-
-	SYS_Exit(EXIT_SUCCESS);
-}
-
-void clean_temp_files(void)
+void
+Daemonize()
+{
+	int si, so, se;
+
+	Log2(PCSC_LOG_DEBUG,
+		"Sending daemon to background: %d\n",getpid());
+	/*
+	* First fork guarantees we're not process group leader.
+	*/
+	switch(fork()) {
+	case 0:
+		break;
+	case -1:
+		fprintf(stderr, "Bad fork: %s\n", strerror(errno));
+	default:
+		exit(0);
+	}
+	setsid(); // Become session leader w/o controlling tty
+	/*
+	 * 2nd fork - allow session leader to exit.
+	 * Now we        are forever detached from a controlling tty.
+	 */
+	switch(fork()) {
+	case 0:
+		break;
+	case -1:
+		fprintf(stderr, "Bad fork: %s\n", strerror(errno));
+	default:
+		exit(0);
+	}
+	/*
+	 * Assign sysin, sysout, syserr to mute (leaving them
+	 * closed is bad practice).  They can be connected to
+	 * other source or targets subsequently, depending on
+	 * configuration settings.
+	 */
+	if ((si = open("/dev/null", O_RDWR)) >= 0)
+		dup2(si, 0);
+
+	if ((so = open("/dev/null", O_RDWR)) >= 0)
+		dup2(si, 1);
+
+	if ((se = open("/dev/null", O_RDWR)) >= 0)
+		dup2(si, 2);
+
+	chdir(pcscCfg.baseDir);
+
+}
+
+void
+ChkVersion()
+{
+	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);
+		exit(EXIT_FAILURE);
+	}
+}
+
+int
+DoRunCheck()
 {
 	int rv;
-
-	rv = SYS_Unlink(PCSCLITE_PUBSHM_FILE);
-	if (rv != 0)
-		Log2(PCSC_LOG_ERROR, "Cannot unlink " PCSCLITE_PUBSHM_FILE ": %s",
-			strerror(errno));
-
-	rv = SYS_Unlink(PCSCLITE_CSOCK_NAME);
-	if (rv != 0)
-		Log2(PCSC_LOG_ERROR, "Cannot unlink " PCSCLITE_CSOCK_NAME ": %s",
-			strerror(errno));
-
+	struct stat fStatBuf;
+	/*
+	 * Test the presence of file that flags that the daemon is running.
+	 * Default for single instance server is /var/run/pcsc.pub
+	 */
+	rv = SYS_Stat(pcscCfg.netBindFile, &fStatBuf);
+
+	if (SYS_Stat(pcscCfg.pcscdMemMappedFile, &fStatBuf) == 0)
+	{
 #ifdef USE_RUN_PID
-	rv = SYS_Unlink(USE_RUN_PID);
-	if (rv != 0)
-		Log2(PCSC_LOG_ERROR, "Cannot unlink " USE_RUN_PID ": %s",
-			strerror(errno));
+/* pids are only 15 bits but 4294967296
+ * (32 bits in case of a new system use it) is on 10 bytes
+ */
+#define PID_ASCII_SIZE 11
+
+		/* Read pid file to get the old pid and test
+		 * if the old pcscd is still running
+		 */
+		FILE *f;
+		char pid_ascii[PID_ASCII_SIZE];
+		int pid;
+
+		if ((f = fopen(pcscCfg.pcscdPIDFile, "rb")) != NULL) {
+			fgets(pid_ascii, PID_ASCII_SIZE, f);
+			fclose(f);
+
+			pid = atoi(pid_ascii);
+
+			if (kill(pid, 0) == 0)  {
+				Log3(PCSC_LOG_CRITICAL,
+				     "File %s already exists.\nAnother"
+				     "pcscd (pid: %d) seems to be running.",
+				     pcscCfg.pcscdMemMappedFile, pid);
+				return -1;
+			} else
+				CleanTempFiles();  //Prev pcscd is gone
+		} else {
+			char buf[LINEMAX];
+			sprintf(buf,
+			    "File %s already exists.\nMaybe another pcscd "
+			    " is running?\nCan't read process pid from %s\n"
+			    "Remove %s  %s\nif pcscd is not running, "
+			    "to clear this message.",
+				    NONULL(pcscCfg.pcscdMemMappedFile),
+				    rv < 0 ? "" : NONULL(pcscCfg.netBindFile),
+				    pcscCfg.pcscdMemMappedFile,
+				    pcscCfg.pcscdPIDFile);
+			Log2(PCSC_LOG_CRITICAL, "%s", buf);
+			return -1;
+		}
+#else
+		Log4(PCSC_LOG_CRITICAL,
+		    "File %s already exists.\nMaybe another pcscd is "
+		    "running?\nRemove %s   %s\nif pcscd is not running,"
+		    "to clear this message.",
+		       pcscCfg.pcscdMemMappedFile,
+		       NONULL(pcscCfg.pcscdMemMappedFile),
+		       rv < 0 ? "" : NONULL(pcscCfg.netBindFile));
+		return -1;
 #endif
-}
-
-void signal_reload(int sig)
-{
-	Log1(PCSC_LOG_INFO, "Reload serial configuration");
+
+	}
+	return 0;
+}
+
+void
+CFGSetupLogging()
+{
+	switch (pcscCfg.logType) {
+	case STDERR:
+		DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG);
+		break;
+	case SYSLOG:
+		DebugLogSetLogType(DEBUGLOG_SYSLOG_DEBUG);
+		break;
+	default:
+		DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG);
+
+	}
+
+	switch (pcscCfg.logLevel) {
+	case DEBUG:
+		DebugLogSetLevel(PCSC_LOG_DEBUG);
+		break;
+	case INFO:
+		DebugLogSetLevel(PCSC_LOG_DEBUG);
+		break;
+	case ERROR:
+		DebugLogSetLevel(PCSC_LOG_ERROR);
+		break;
+	case CRITICAL:
+		DebugLogSetLevel(PCSC_LOG_CRITICAL);
+		break;
+	default:
+		DebugLogSetLevel(PCSC_LOG_DEBUG);
+
+	}
+}
+
+void
+CFGStdOutErr(char *filename)
+{
+	if (filename != NULL && strlen(filename) > 0) {
+		int fd;
+		DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG);
+		if ((fd = open(filename, O_WRONLY | O_CREAT | O_APPEND | O_SYNC,
+		    S_IRWXU)) < 0) {
+			fprintf(stderr, "Error opening logfile %s: %s",
+			    pcscCfg.logFile, strerror(errno));
+		}
+		dup2(fd, 1);
+		dup2(fd, 2);
+	}
+}
+
+/*
+ * Cleans up messages still on the queue when a client dies
+ */
+void
+SVCClientCleanup(psharedSegmentMsg msgStruct)
+{
+	/*
+	 * May be implemented in future releases
+	 */
+}
+
+void
+at_exit(void)
+{
+	Log1(PCSC_LOG_DEBUG, "Cleaning per-instance files\n");
+	CleanTempFiles();
+}
+
+void
+CleanTempFiles(void)
+{
+	int rv;
+#ifdef USE_RUN_PID
+	if (pcscCfg.launchMode == LAUNCHER) {
+		rv = CFGRmPath(pcscCfg.pcscdPIDFile);
+		if (rv != CFG_SUCCESS) {
+			Log3(PCSC_LOG_DEBUG, "Cannot unlink %s:\n%s",
+			    pcscCfg.pcscdPIDFile, strerror(errno));
+		}
+	}
+#endif
+
+	/*
+	 * Clean up the network binding file if
+	 * the transport type indicates that one
+	 * was required.
+	 */
+	switch(pcscCfg.transportType) {
+	case SOCKET_UNIX:
+		rv = CFGRmPath(pcscCfg.netBindFile);
+		if (rv != CFG_SUCCESS) {
+			Log3(PCSC_LOG_DEBUG, "Cannot unlink %s:\n%s",
+			    pcscCfg.pcscdPIDFile, strerror(errno));
+		}
+		break;
+	default:
+		break;
+	}
+
+	if (pcscCfg.useMappedMemory) {
+		rv = CFGRmPath(pcscCfg.pcscdMemMappedFile);
+		if (rv != CFG_SUCCESS) {
+			Log3(PCSC_LOG_DEBUG, "Cannot unlink %s:\n%s",
+			    pcscCfg.pcscdPIDFile, strerror(errno));
+		}
+	}
+}
+
+void
+signal_reload(int sig) {
+	Log1(PCSC_LOG_DEBUG, "Reload serial configuration");
 	HPReCheckSerialReaders();
-} /* signal_reload */
-
-void signal_trap(int sig)
-{
-	/* the signal handler is called several times for the same Ctrl-C */
-	if (AraKiri == FALSE)
-	{
-		Log1(PCSC_LOG_INFO, "Preparing for suicide");
+}
+
+
+void
+signal_trap(int sig)
+{
+	/* Signal handler is called several times for the same Ctrl-C */
+	if (AraKiri == FALSE)  {
+		Log1(PCSC_LOG_DEBUG, "Preparing for suicide");
 		AraKiri = TRUE;
-
-		/* if still in the init/loading phase the AraKiri will not be
-		 * seen by the main event loop
+		/* If still in the init/loading phase
+		 * AraKiri flag won't be seen by main event loop
 		 */
-		if (Init)
-		{
-			Log1(PCSC_LOG_INFO, "Suicide during init");
+		if (Init) {
+			Log1(PCSC_LOG_DEBUG, "Suicide during init");
 			at_exit();
 		}
 	}
 }
 
-void print_version (void)
-{
-	printf("%s version %s.\n",  PACKAGE, VERSION);
-	printf("Copyright (C) 1999-2002 by David Corcoran <corcoran at linuxnet.com>.\n");
-	printf("Copyright (C) 2001-2005 by Ludovic Rousseau <ludovic.rousseau at free.fr>.\n");
-	printf("Copyright (C) 2003-2004 by Damien Sauveron <sauveron at labri.fr>.\n");
-	printf("Report bugs to <sclinux at linuxnet.com>.\n");
-}
-
-void print_usage (char const * const progname)
-{
-	printf("Usage: %s options\n", progname);
-	printf("Options:\n");
+void
+print_version (void)
+{
+	printf("%s version %s_%s.\n",  PACKAGE, VERSION, BUILD);
+	printf("Copyright (C) 2007-2008 by Sun Microsystems, Inc.\n");
+	printf("Copyright (C) 2003-2004 "
+	       "by Damien Sauveron <sauveron at labri.fr>.\n");
+	printf("Copyright (C) 2001-2005 "
+	       "by Ludovic Rousseau <ludovic.rousseau at free.fr>.\n");
+	printf("Copyright (C) 1999-2002 "
+	       "by David Corcoran <corcoran at linuxnet.com>.\n");
+//	printf("Report bugs to <sclinux at linuxnet.com>.\n");
+}
+
+char
+*getLongOptName(int opt)
+{
+	int i;
+	for (i = 0; longOpts[i].name != NULL; i++)
+		if (longOpts[i].val == opt)
+			return longOpts[i].name;
+	return "";
+}
+
+void
+usage(char const * const progname)
+{
+	int i;
+	printf("\n Usage: %s options\n\n",
+		(char *)SYS_Basename((char *)progname));
+
+	ListInvocationModes();
+	printf("   Options:\n\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 stderr instead of syslog\n");
-	printf("  -h, --help		display usage information\n");
-	printf("  -v, --version		display the program version number\n");
-	printf("  -d, --debug	 	display lower level debug messages\n"); 
-	printf("      --info	 	display info level debug messages (default level)\n"); 
-	printf("  -e  --error	 	display error level debug messages\n"); 
-	printf("  -C  --critical 	display critical only level debug messages\n"); 
+	for (i = 0; usageMsgs[i].usage != NULL; i++)
+		printf("       -%c   --%-14s   %s\n", usageMsgs[i].opt,
+		   getLongOptName(usageMsgs[i].opt), usageMsgs[i].usage);
+
 #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 stderr instead of syslog\n");
-	printf("  -d 	display debug messages. Output may be:\n"); 
-	printf("  -h 	display usage information\n");
-	printf("  -v 	display the program version number\n");
+	for (i = 0; usageMsgs[i].usage != NULL; i++)
+		printf("       -%c   %s\n", usageMsgs[i].opt,
+		   usageMsgs[i].usage);
 #endif
-}
-
+	printf("\n");
+}
+
+/*
+ * The function formats the usage arguments so that they will be displayed
+ * well if the valid argument counts, names and values change.
+ */
+void
+ListInvocationModes()
+{
+	char buf[LINEMAX], arg[10], *cp, *c2;
+	int i, j, k, reqFlag = 0, loopedBack;
+	for (i = 0; invocationModes[i].name != NULL; i++) {
+		struct invocation *invoked = &invocationModes[i];
+		column = 1;
+		printWrap("   pcscd ");
+		for (j = 0; invoked->optList[j] != 0; j++) {
+			int opt = invoked->optList[j];
+			bzero(buf, sizeof (buf));
+			if (j > 0)
+				strcat(buf, "  ");
+			else if (opt > 0)
+				strcat(buf, "    ");
+			if (opt > 0) {
+				reqFlag = 0;
+				strcat(buf, "[ ");
+			} else {
+				reqFlag = 1;
+				opt = -opt;
+			}
+
+			sprintf(arg, "-%c", opt);
+			strcat(buf, arg);
+			for (k = 0; paramDesc[k].opt != 0; k++) {
+			     struct paramDescriptions *pd = &paramDesc[k];
+			     if (pd->opt == opt) {
+				     if (pd->text != NULL) {
+					     strcat(buf, " ");
+					     strcat(buf, pd->text);
+				     } else if (pd->cfgvar != NULL) {
+					     strcat(buf, " {");
+					     cp = CFGListConstants(pd->cfgvar);
+					     c2 = strtok(cp, ",");
+					     loopedBack = 0;
+					     while(c2 != NULL) {
+						     if (loopedBack)
+							 strcat(buf, " | ");
+						     strcat(buf, c2);
+						     printWrap(buf);
+						     c2 = strtok(0, ",");
+						     bzero(buf, sizeof (buf));
+						     loopedBack = 1;
+					     }
+					     printWrap("}");
+				     }
+			     }
+			}
+			if (!reqFlag)
+				strcat(buf, " ]");
+			printWrap(buf);
+		}
+		printWrap("\n\n");
+	}
+
+}
+
+void
+printWrap(const char *fmt, ...) {
+	char buf[LINEMAX], *cp;
+	int len;
+	va_list ap;
+
+	va_start(ap, fmt);
+
+#ifndef WIN32
+	vsnprintf(buf, LINEMAX, fmt, ap);
+#else
+#if HAVE_VSNPRINTF
+	vsnprintf(buf, LINEMAX, fmt, ap);
+#else
+	vsprintf(buf, fmt, argptr);
+#endif
+#endif
+	va_end(ap);
+	if ((cp = strrchr(buf, '\n')) != NULL)
+		len = strlen(cp + 1);
+	else
+		len = strlen(buf);
+
+	column += len;
+	if (column > 55) {
+		printf("\n           ");
+		column = 13;
+		if (*buf == ' ' && buf[1] == '|') {
+			printf("     ...");
+			column += 9;
+		}
+	}
+	printf(buf);
+}
+
+

Added: branches/Solaris/src/pcscdaemon.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/pcscdaemon.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/pcscdaemon.h (added)
+++ branches/Solaris/src/pcscdaemon.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,270 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2000-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * <NEED TO FIX KEYWORDS>
+ */
+
+
+#ifndef	__pcscdaemon_h__
+#define	__pcscdaemon_h__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "pcsc_config.h"
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#define NONULL(a) (a) ? (a) : ""
+#define LINEMAX 256
+
+#ifdef HAVE_GETOPT_LONG
+#  define GETOPT(argc, argv, args, longopts, optindex) \
+		getopt_long (argc, argv, args, longopts, &optindex)
+#else
+#  define GETOPT(argc, argv, args, longopts, optidx) \
+		getopt(argc, argv, args)
+#endif
+
+
+void SVCServiceRunLoop(void);
+void SVCClientCleanup();
+void at_exit(void);
+void CleanTempFiles(void);
+void signal_reload(int sig);
+void signal_trap(int);
+void print_version (void);
+void print_usage (char const * const);
+void Launcher(int);
+void ChkVersion();
+void CFGSetupLogging();
+void CFGStdOutErr(char *);
+int  DoRunCheck();
+void Daemonize();
+void ListInvocationModes();
+int  ChkArg(int, char *);
+char *FmtValue(int opt, char *val);
+
+
+/*
+ * Command line options
+ */
+
+#define OPT_READERCFG  'r'
+#define OPT_FOREGROUND 'f'
+#define OPT_HELP       '?'
+#define OPT_VERSION    'v'
+#define OPT_APDU       'a'
+#define OPT_LOGLEVEL   'd'
+#define OPT_BASEDIR    'b'
+#define OPT_IFDLIBDIR  'i'
+#define OPT_PORT       'p'
+#define OPT_DISPLAY    'x'
+#define OPT_TRANSPORT  't'
+#define OPT_CONFIG     'c'
+#define OPT_USEAUTH    'A'
+#define OPT_STOPINST   'k'
+#define OPT_TIMEOUT    'T'
+#define OPT_INSTANCE   'I'
+#define OPT_LAUNCHER   'L'
+#define OPT_MAPFILE    'm'
+#define OPT_USEMAPPED  'M'
+#define OPT_LOGFILE    'o'
+#define OPT_LOGTYPE    'l'
+#define OPT_VERBOSE    'V'
+#define OPT_LAUNCHTHR  'R'
+#define OPT_LAUNCHINT  'N'
+#define OPT_FIFOTIME   'F'
+#define OPT_PID	       'P'
+
+
+/*
+ * The struct defined by getopt_long() is also use
+ * for automating building the valid argument
+ * list and automating our usage function, so
+ * if it isn't defined, we'll define it.
+ */
+#ifndef HAVE_GETOPT_LONG
+struct option {
+	char *name;
+	int has_arg;
+	int *flag;
+	int val;
+
+};
+#endif
+
+int optIndex = 0;
+static struct option longOpts[] = {
+    { "help",       0, 0, OPT_HELP       },
+    { "version",    0, 0, OPT_VERSION    },
+    { "foreground", 0, 0, OPT_FOREGROUND },
+    { "apdu",       0, 0, OPT_APDU       },
+    { "launcher",   0, 0, OPT_LAUNCHER   },
+    { "instance",   0, 0, OPT_INSTANCE   },
+    { "stop",       0, 0, OPT_STOPINST   },
+    { "verbose",    0, 0, OPT_VERBOSE    },
+    { "useauth",    0, 0, OPT_USEAUTH    },
+    { "usemap",     0, 0, OPT_USEMAPPED  },
+    { "loglevel",   1, 0, OPT_LOGLEVEL   },
+    { "logtype",    1, 0, OPT_LOGTYPE    },
+    { "logfile",    1, 0, OPT_LOGFILE    },
+    { "reader",     1, 0, OPT_READERCFG  },
+    { "basedir",    1, 0, OPT_BASEDIR    },
+    { "ifd",        1, 0, OPT_IFDLIBDIR  },
+    { "port",       1, 0, OPT_PORT       },
+    { "display",    1, 0, OPT_DISPLAY    },
+    { "transport",  1, 0, OPT_TRANSPORT  },
+    { "config",     1, 0, OPT_CONFIG     },
+    { "timeout",    1, 0, OPT_TIMEOUT    },
+    { "mapfile",    1, 0, OPT_MAPFILE    },
+    { "launchint",  1, 0, OPT_LAUNCHTHR  },
+    { "launchthr",  1, 0, OPT_LAUNCHINT  },
+    { "fifotime",   1, 0, OPT_FIFOTIME   },
+    { "pid",        1, 0, OPT_PID        },
+    { 0, 0, 0, 0}
+};
+
+struct {
+	int opt;
+	char *usage;
+} usageMsgs[] = {
+    { OPT_LAUNCHER,   "Run in launcher mode"                              },
+    { OPT_INSTANCE,   "Run as instance (mode is used by launcher)"        },
+    { OPT_STOPINST,   "Terminate instance handling specified display"     },
+    { OPT_PID,        "PID of instance to stop"                           },
+    { OPT_CONFIG,     "Specify hierarchical server config file location"  },
+    { OPT_BASEDIR,    "Specify hierarchical server base dir location"     },
+    { OPT_READERCFG,  "Specify abs. or relative reader conf. location"    },
+    { OPT_FOREGROUND, "Run in foreground (no daemon)"                     },
+    { OPT_IFDLIBDIR,  "Specify abs. or rel. IFD handler plugin path"      },
+    { OPT_DISPLAY,    "X display that owns reader(s) of interest"         },
+    { OPT_TRANSPORT,  "Specify IPC comm. transport type"                  },
+    { OPT_PORT,       "Specify INETV4 port number to use"                 },
+    { OPT_TIMEOUT,    "Specify Instance timeout"                          },
+    { OPT_USEAUTH,    "Enable authentication"                             },
+    { OPT_MAPFILE,    "Specify memory map file name"                      },
+    { OPT_USEMAPPED,  "Enable memory-mapped reader state conveyance"      },
+    { OPT_LOGLEVEL,   "Set logging minimum severity level"                },
+    { OPT_LOGTYPE,    "Specify facility to send logging output to"        },
+    { OPT_LOGFILE,    "Specify target of stderr"                          },
+    { OPT_APDU,       "Log APDU commands and results"                     },
+    { OPT_VERBOSE,    "Debug verbosity level"                             },
+    { OPT_LAUNCHINT,  "Launched instance min time req. to assume success" },
+    { OPT_LAUNCHTHR,  "Instance, max. allowed failed launches + retries"  },
+    { OPT_FIFOTIME,   "Number of seconds to time out on fifo ping"    },
+    { OPT_VERSION,    "Display the program version number"                },
+    { OPT_HELP,       "Display usage information"                         },
+    { 0, 0 }
+};
+
+struct paramDescriptions {
+	int opt;
+	char *text;
+	void *cfgvar;
+} paramDesc[] = {
+    { OPT_LAUNCHER,   0,                    0 },
+    { OPT_INSTANCE,   0,                    0 },
+    { OPT_STOPINST,   0,                    0 },
+    { OPT_BASEDIR,    "basedir",            0 },
+    { OPT_IFDLIBDIR,  "ifd_plugin_dir",     0 },
+    { OPT_CONFIG,     "config_file_path",   0 },
+    { OPT_READERCFG,  "reader_config_path", 0 },
+    { OPT_MAPFILE,    "mapfile_path",       0 },
+    { OPT_LOGFILE,    "logfile",            0 },
+    { OPT_TIMEOUT,    "timeout_seconds",    0 },
+    { OPT_PORT,       "port_number",        0 },
+    { OPT_DISPLAY,    ":display_number",    0 },
+    { OPT_LAUNCHINT,  "time_secs",          0 },
+    { OPT_LAUNCHTHR,  "time_secs",          0 },
+    { OPT_FIFOTIME,   "timeout_secs",       0 },
+    { OPT_PID,        "pid",                0 },
+    { OPT_FOREGROUND, 0,                    0 },
+    { OPT_USEAUTH,    0,                    0 },
+    { OPT_USEMAPPED,  0,                    0 },
+    { OPT_APDU,       0,                    0 },
+    { OPT_VERSION,    0,                    0 },
+    { OPT_VERBOSE,    0,                    0 },
+    { OPT_HELP,       0,                    0 },
+    { OPT_TRANSPORT,  0,                    &pcscCfg.transportType },
+    { OPT_LOGTYPE,    0,                    &pcscCfg.logType },
+    { OPT_LOGLEVEL,   0,                    &pcscCfg.logLevel },
+    { 0, 0 }
+};
+
+
+/*
+ * Describes valid combinations of options for various
+ * invocation modes.  Required options for a mode should
+ * be prefixed with '-' (ie. negated)
+ */
+#define MAXOPTS 32
+struct invocation {
+	char *name;
+	int optList[MAXOPTS];
+} invocationModes[] = {
+	{
+	  "Help on Usage",
+		{ -OPT_HELP, 0  }
+
+	}, {
+
+	  "Display Version",
+		{ -OPT_VERSION, 0  }
+	}, {
+
+	  "Stop Instance",
+		{ -OPT_STOPINST, -OPT_DISPLAY, OPT_PID, 0 }
+	}, {
+
+	  "Launcher Mode",
+		{
+		  -OPT_LAUNCHER, OPT_CONFIG, OPT_BASEDIR, OPT_MAPFILE,
+		   OPT_LOGFILE, OPT_USEAUTH, OPT_PORT, OPT_TRANSPORT,
+		   OPT_FOREGROUND, OPT_USEMAPPED, OPT_LOGTYPE,
+		   OPT_LOGLEVEL, OPT_APDU, OPT_LAUNCHINT, OPT_LAUNCHTHR,
+		   OPT_FIFOTIME, OPT_VERBOSE, 0
+		}
+	}, {
+
+	  "Instance Mode",
+		{
+		  -OPT_INSTANCE, OPT_DISPLAY, OPT_CONFIG, OPT_BASEDIR,
+		   OPT_MAPFILE, OPT_IFDLIBDIR, OPT_READERCFG,
+		   OPT_LOGFILE, OPT_USEAUTH, OPT_PORT, OPT_TRANSPORT,
+		   OPT_FOREGROUND, OPT_USEMAPPED, OPT_LOGTYPE,
+		   OPT_LOGLEVEL, OPT_APDU, OPT_VERBOSE, 0
+		}
+	}, {
+
+	  "Server Mode",
+		{
+		   OPT_CONFIG, OPT_BASEDIR, OPT_MAPFILE,
+		   OPT_IFDLIBDIR, OPT_READERCFG,
+		   OPT_LOGFILE, OPT_USEAUTH, OPT_PORT, OPT_TRANSPORT,
+		   OPT_FOREGROUND, OPT_USEMAPPED, OPT_LOGTYPE,
+		   OPT_LOGLEVEL, OPT_APDU, OPT_VERBOSE, 0
+		}
+	},
+	{ 0, 0 }
+};
+
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif
+
+#endif

Propchange: branches/Solaris/src/pcscdaemon.h
------------------------------------------------------------------------------
    svn:executable = *

Modified: branches/Solaris/src/powermgt_macosx.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/powermgt_macosx.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/powermgt_macosx.c (original)
+++ branches/Solaris/src/powermgt_macosx.c Thu Jun 12 10:28:09 2008
@@ -58,14 +58,14 @@
           IOAllowPowerChange(root_port,(long)messageArgument);
           break;
     case kIOMessageSystemWillSleep:
-          Log1(PCSC_LOG_INFO, "system going into sleep");
+          Log1(PCSC_LOG_DEBUG, "system going into sleep");
           SYS_MutexLock(&usbNotifierMutex);
           RFSuspendAllReaders();
           IOAllowPowerChange(root_port,(long)messageArgument);
-          Log1(PCSC_LOG_INFO, "system allowed to sleep");
+          Log1(PCSC_LOG_DEBUG, "system allowed to sleep");
           break;
     case kIOMessageSystemHasPoweredOn: 
-        Log1(PCSC_LOG_INFO, "system coming out of sleep");
+        Log1(PCSC_LOG_DEBUG, "system coming out of sleep");
         HPSearchHotPluggables();
         RFAwakeAllReaders();
         SYS_MutexUnLock(&usbNotifierMutex);

Modified: branches/Solaris/src/prothandler.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/prothandler.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/prothandler.c (original)
+++ branches/Solaris/src/prothandler.c Thu Jun 12 10:28:09 2008
@@ -126,7 +126,7 @@
 			/* App wants unsupported protocol */
 			return SET_PROTOCOL_WRONG_ARGUMENT;
 
-	Log2(PCSC_LOG_INFO, "Attempting PTS to T=%d",
+	Log2(PCSC_LOG_DEBUG, "Attempting PTS to T=%d",
 		(SCARD_PROTOCOL_T0 == ucChosen ? 0 : 1));
 	rv = IFDSetPTS(rContext, ucChosen, 0x00, 0x00, 0x00, 0x00);
 
@@ -134,15 +134,15 @@
 		protocol = ucChosen;
 	else
 		if (IFD_NOT_SUPPORTED == rv)
-			Log2(PCSC_LOG_INFO, "PTS not supported by driver, using T=%d",
+			Log2(PCSC_LOG_DEBUG, "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",
+				Log2(PCSC_LOG_DEBUG, "PTS protocol not supported, using T=%d",
 					(SCARD_PROTOCOL_T0 == protocol) ? 0 : 1);
 			else
 			{
-				Log3(PCSC_LOG_INFO, "PTS failed (%d), using T=%d", rv,
+				Log3(PCSC_LOG_DEBUG, "PTS failed (%d), using T=%d", rv,
 					(SCARD_PROTOCOL_T0 == protocol) ? 0 : 1);
 
 				/* ISO 7816-3:1997 ch. 7.2 PPS protocol page 14

Modified: branches/Solaris/src/readerfactory.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/readerfactory.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/readerfactory.c (original)
+++ branches/Solaris/src/readerfactory.c Thu Jun 12 10:28:09 2008
@@ -26,6 +26,7 @@
 
 #include "misc.h"
 #include "pcsclite.h"
+#include "pcsc_config.h"
 #include "ifdhandler.h"
 #include "debuglog.h"
 #include "thread_generic.h"
@@ -43,6 +44,8 @@
 #define FALSE 0
 #endif
 
+#define NONULL(s) s ? s : "<null>"
+
 static PREADER_CONTEXT sReadersContexts[PCSCLITE_MAX_READERS_CONTEXTS];
 static DWORD dwNumReadersContexts = 0;
 static char *ConfigFile = NULL;
@@ -53,7 +56,7 @@
 	int i;   					/* Counter */
 
 	/*
-	 * Allocate each reader structure 
+	 * Allocate each reader structure
 	 */
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
@@ -63,12 +66,14 @@
 	}
 
 	/*
-	 * Create public event structures 
+	 * Create public event structures
 	 */
 	return EHInitializeEventStructures();
 }
 
-LONG RFAddReader(LPSTR lpcReader, DWORD dwPort, LPSTR lpcLibrary, LPSTR lpcDevice)
+LONG RFAddReader(LPSTR lpcReader, DWORD dwPort,
+		 LPSTR lpcLibrary, LPSTR lpcDevice,
+		 LPSTR lpcAuthSvc)
 {
 	DWORD dwContext = 0, dwGetSize;
 	UCHAR ucGetData[1], ucThread[1];
@@ -103,7 +108,7 @@
 	}
 
 	/*
-	 * Same name, same port - duplicate reader cannot be used 
+	 * Same name, same port - duplicate reader cannot be used
 	 */
 	if (dwNumReadersContexts != 0)
 	{
@@ -131,7 +136,7 @@
 	}
 
 	/*
-	 * We must find an empty slot to put the reader structure 
+	 * We must find an empty slot to put the reader structure
 	 */
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
@@ -145,13 +150,13 @@
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
 		/*
-		 * No more spots left return 
+		 * No more spots left return
 		 */
 		return SCARD_E_NO_MEMORY;
 	}
 
 	/*
-	 * Check and set the readername to see if it must be enumerated 
+	 * Check and set the readername to see if it must be enumerated
 	 */
 	parentNode = RFSetReaderName(sReadersContexts[dwContext], lpcReader,
 		lpcLibrary, dwPort, 0);
@@ -160,6 +165,17 @@
 		sizeof((sReadersContexts[dwContext])->lpcLibrary));
 	strlcpy((sReadersContexts[dwContext])->lpcDevice, lpcDevice,
 		sizeof((sReadersContexts[dwContext])->lpcDevice));
+
+
+	if (lpcAuthSvc != NULL) {
+		strlcpy((sReadersContexts[dwContext])->lpcAuthSvc, lpcAuthSvc,
+			sizeof((sReadersContexts[dwContext])->lpcAuthSvc));
+	} else {
+		memset((sReadersContexts[dwContext])->lpcAuthSvc, 0,
+			sizeof((sReadersContexts[dwContext])->lpcAuthSvc));
+	}
+
+
 	(sReadersContexts[dwContext])->dwVersion = 0;
 	(sReadersContexts[dwContext])->dwPort = dwPort;
 	(sReadersContexts[dwContext])->mMutex = 0;
@@ -178,22 +194,22 @@
 		(sReadersContexts[dwContext])->psHandles[i].hCard = 0;
 
 	/*
-	 * If a clone to this reader exists take some values from that clone 
+	 * If a clone to this reader exists take some values from that clone
 	 */
 	if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		(sReadersContexts[dwContext])->pdwFeeds = 
+		(sReadersContexts[dwContext])->pdwFeeds =
 		  (sReadersContexts[parentNode])->pdwFeeds;
 		*(sReadersContexts[dwContext])->pdwFeeds += 1;
-		(sReadersContexts[dwContext])->vHandle = 
+		(sReadersContexts[dwContext])->vHandle =
 		  (sReadersContexts[parentNode])->vHandle;
-		(sReadersContexts[dwContext])->mMutex = 
+		(sReadersContexts[dwContext])->mMutex =
 		  (sReadersContexts[parentNode])->mMutex;
-		(sReadersContexts[dwContext])->pdwMutex = 
+		(sReadersContexts[dwContext])->pdwMutex =
 		  (sReadersContexts[parentNode])->pdwMutex;
 
 		/*
-		 * Call on the driver to see if it is thread safe 
+		 * Call on the driver to see if it is thread safe
 		 */
 		dwGetSize = sizeof(ucThread);
 		rv = IFDGetCapabilities((sReadersContexts[parentNode]),
@@ -201,7 +217,7 @@
 
 		if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)
 		{
-			Log1(PCSC_LOG_INFO, "Driver is thread safe");
+			Log1(PCSC_LOG_DEBUG, "Driver is thread safe");
 			(sReadersContexts[dwContext])->mMutex = 0;
 			(sReadersContexts[dwContext])->pdwMutex = NULL;
 		}
@@ -213,8 +229,8 @@
 	{
 		(sReadersContexts[dwContext])->pdwFeeds = malloc(sizeof(DWORD));
 
-		/* Initialize pdwFeeds to 1, otherwise multiple 
-		   cloned readers will cause pcscd to crash when 
+		/* Initialize pdwFeeds to 1, otherwise multiple
+		   cloned readers will cause pcscd to crash when
 		   RFUnloadReader unloads the driver library
 		   and there are still devices attached using it --mikeg*/
 
@@ -238,13 +254,14 @@
 	dwNumReadersContexts += 1;
 
 	rv = RFInitializeReader(sReadersContexts[dwContext]);
+
 	if (rv != SCARD_S_SUCCESS)
 	{
 		/*
-		 * Cannot connect to reader exit gracefully 
-		 */
-		/*
-		 * Clean up so it is not using needed space 
+		 * Cannot connect to reader exit gracefully
+		 */
+		/*
+		 * Clean up so it is not using needed space
 		 */
 		Log2(PCSC_LOG_ERROR, "%s init failed.", lpcReader);
 
@@ -255,7 +272,7 @@
 		(sReadersContexts[dwContext])->dwIdentity = 0;
 
 		/*
-		 * Destroy and free the mutex 
+		 * Destroy and free the mutex
 		 */
 		if (*(sReadersContexts[dwContext])->pdwMutex == 1)
 		{
@@ -289,7 +306,7 @@
 		return rv;
 
 	/*
-	 * Call on the driver to see if there are multiple slots 
+	 * Call on the driver to see if there are multiple slots
 	 */
 
 	dwGetSize = sizeof(ucGetData);
@@ -299,23 +316,23 @@
 	if (rv != IFD_SUCCESS || dwGetSize != 1 || ucGetData[0] == 0)
 		/*
 		 * Reader does not have this defined.  Must be a single slot
-		 * reader so we can just return SCARD_S_SUCCESS. 
+		 * reader so we can just return SCARD_S_SUCCESS.
 		 */
 		return SCARD_S_SUCCESS;
 
 	if (rv == IFD_SUCCESS && dwGetSize == 1 && ucGetData[0] == 1)
 		/*
-		 * Reader has this defined and it only has one slot 
+		 * Reader has this defined and it only has one slot
 		 */
 		return SCARD_S_SUCCESS;
 
 	/*
-	 * Check the number of slots and create a different 
-	 * structure for each one accordingly 
-	 */
-
-	/*
-	 * Initialize the rest of the slots 
+	 * Check the number of slots and create a different
+	 * structure for each one accordingly
+	 */
+
+	/*
+	 * Initialize the rest of the slots
 	 */
 
 	for (j = 1; j < ucGetData[0]; j++)
@@ -324,8 +341,8 @@
 		DWORD dwContextB = 0;
 
 		/*
-		 * We must find an empty spot to put the 
-		 * reader structure 
+		 * We must find an empty spot to put the
+		 * reader structure
 		 */
 		for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 		{
@@ -339,7 +356,7 @@
 		if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 		{
 			/*
-			 * No more spots left return 
+			 * No more spots left return
 			 */
 			rv = RFRemoveReader(lpcReader, dwPort);
 			return SCARD_E_NO_MEMORY;
@@ -370,7 +387,7 @@
 		sReadersContexts[dwContextB]->dwSlot =
 			sReadersContexts[dwContext]->dwSlot + j;
 
-		/* 
+		/*
 		 * Added by Dave - slots did not have a pdwFeeds
 		 * parameter so it was by luck they were working
 		 */
@@ -392,7 +409,7 @@
 			(sReadersContexts[dwContextB])->psHandles[i].hCard = 0;
 
 		/*
-		 * Call on the driver to see if the slots are thread safe 
+		 * Call on the driver to see if the slots are thread safe
 		 */
 
 		dwGetSize = sizeof(ucThread);
@@ -417,10 +434,10 @@
 		if (rv != SCARD_S_SUCCESS)
 		{
 			/*
-			 * Cannot connect to slot exit gracefully 
+			 * Cannot connect to slot exit gracefully
 			 */
 			/*
-			 * Clean up so it is not using needed space 
+			 * Clean up so it is not using needed space
 			 */
 			Log2(PCSC_LOG_ERROR, "%s init failed.", lpcReader);
 
@@ -431,7 +448,7 @@
 			(sReadersContexts[dwContextB])->dwIdentity = 0;
 
 			/*
-			 * Destroy and free the mutex 
+			 * Destroy and free the mutex
 			 */
 			if (*(sReadersContexts[dwContextB])->pdwMutex == 1)
 			{
@@ -480,16 +497,15 @@
 		int i;
 
 		/*
-		 * Try to destroy the thread 
+		 * Try to destroy the thread
 		 */
 		rv = EHDestroyEventHandler(sContext);
 
 		rv = RFUnInitializeReader(sContext);
 		if (rv != SCARD_S_SUCCESS)
 			return rv;
-
-		/*
-		 * Destroy and free the mutex 
+		/*
+		 * Destroy and free the mutex
 		 */
 		if ((NULL == sContext->pdwMutex) || (NULL == sContext->pdwFeeds))
 		{
@@ -554,7 +570,7 @@
 	int i;
 
 	/*
-	 * Clear the list 
+	 * Clear the list
 	 */
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 		usedDigits[i] = FALSE;
@@ -571,7 +587,7 @@
 					LONG ret;
 
 					/*
-					 * Ask the driver if it supports multiple channels 
+					 * Ask the driver if it supports multiple channels
 					 */
 					valueLength = sizeof(tagValue);
 					ret = IFDGetCapabilities((sReadersContexts[i]),
@@ -582,7 +598,7 @@
 						(tagValue[0] > 1))
 					{
 						supportedChannels = tagValue[0];
-						Log2(PCSC_LOG_INFO,
+						Log2(PCSC_LOG_DEBUG,
 							"Support %d simultaneous readers", tagValue[0]);
 					}
 					else
@@ -590,7 +606,7 @@
 
 					/*
 					 * Check to see if it is a hotplug reader and
-					 * different 
+					 * different
 					 */
 					if (((((sReadersContexts[i])->dwPort & 0xFFFF0000) ==
 							PCSCLITE_HP_BASE_PORT)
@@ -602,19 +618,19 @@
 						/*
 						 * tells the caller who the parent of this
 						 * clone is so it can use it's shared
-						 * resources like mutex/etc. 
+						 * resources like mutex/etc.
 						 */
 						parent = i;
 
 						/*
-						 * If the same reader already exists and it is 
+						 * If the same reader already exists and it is
 						 * hotplug then we must look for others and
-						 * enumerate the readername 
+						 * enumerate the readername
 						 */
 						currentDigit = strtol(lpcReader + strlen(lpcReader) - 5, NULL, 16);
 
 						/*
-						 * This spot is taken 
+						 * This spot is taken
 						 */
 						usedDigits[currentDigit] = TRUE;
 					}
@@ -644,7 +660,7 @@
 	sprintf(rContext->lpcReader, "%s %02X %02lX", readerName, i, dwSlot);
 
 	/*
-	 * Set the slot in 0xDDDDCCCC 
+	 * Set the slot in 0xDDDDCCCC
 	 */
 	rContext->dwSlot = (i << 16) + dwSlot;
 
@@ -662,7 +678,7 @@
 		return SCARD_E_READER_UNAVAILABLE;
 
 	/*
-	 * Ignore the groups for now, return all readers 
+	 * Ignore the groups for now, return all readers
 	 */
 	dwCSize = 0;
 	p = 0;
@@ -678,23 +694,23 @@
 
 	if (p > dwNumReadersContexts)
 		/*
-		 * We are severely hosed here 
-		 */
-		/*
-		 * Hopefully this will never be true 
+		 * We are severely hosed here
+		 */
+		/*
+		 * Hopefully this will never be true
 		 */
 		return SCARD_F_UNKNOWN_ERROR;
 
 	/*
-	 * Added for extra NULL byte on MultiString 
+	 * Added for extra NULL byte on MultiString
 	 */
 	dwCSize += 1;
 
 	/*
-	 * If lpcReaders is not allocated then just 
-	 */
-	/*
-	 * return the amount needed to allocate 
+	 * If lpcReaders is not allocated then just
+	 */
+	/*
+	 * return the amount needed to allocate
 	 */
 	if (lpcReaders == 0)
 	{
@@ -710,7 +726,7 @@
 	p = 0;
 
 	/*
-	 * Creating MultiString 
+	 * Creating MultiString
 	 */
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
@@ -732,10 +748,8 @@
 LONG RFReaderInfo(LPSTR lpcReader, PREADER_CONTEXT * sReader)
 {
 	int i;
-
 	if (lpcReader == 0)
 		return SCARD_E_UNKNOWN_READER;
-
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		if ((sReadersContexts[i])->vHandle != 0)
@@ -747,7 +761,6 @@
 			}
 		}
 	}
-
 	return SCARD_E_UNKNOWN_READER;
 }
 
@@ -785,7 +798,7 @@
 	int i;
 
 	/*
-	 * Strip off the lower nibble and get the identity 
+	 * Strip off the lower nibble and get the identity
 	 */
 	dwIdentity = dwIdentity >> (sizeof(DWORD) / 2) * 8;
 	dwIdentity = dwIdentity << (sizeof(DWORD) / 2) * 8;
@@ -808,11 +821,10 @@
 	{
 		Log1(PCSC_LOG_ERROR, "Warning library pointer not NULL");
 		/*
-		 * Another reader exists with this library loaded 
+		 * Another reader exists with this library loaded
 		 */
 		return SCARD_S_SUCCESS;
 	}
-
 	return DYN_LoadLibrary(&rContext->vHandle, rContext->lpcLibrary);
 }
 
@@ -824,7 +836,7 @@
 	/*
 	 * Use this function as a dummy to determine the IFD Handler version
 	 * type  1.0/2.0/3.0.  Suppress error messaging since it can't be 1.0,
-	 * 2.0 and 3.0. 
+	 * 2.0 and 3.0.
 	 */
 
 	DebugLogSuppress(DEBUGLOG_IGNORE_ENTRIES);
@@ -838,7 +850,7 @@
 	if (rv1 != SCARD_S_SUCCESS && rv2 != SCARD_S_SUCCESS && rv3 != SCARD_S_SUCCESS)
 	{
 		/*
-		 * Neither version of the IFD Handler was found - exit 
+		 * Neither version of the IFD Handler was found - exit
 		 */
 		Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing");
 
@@ -846,31 +858,31 @@
 	} else if (rv1 == SCARD_S_SUCCESS)
 	{
 		/*
-		 * Ifd Handler 1.0 found 
+		 * Ifd Handler 1.0 found
 		 */
 		rContext->dwVersion = IFD_HVERSION_1_0;
 	} else if (rv3 == SCARD_S_SUCCESS)
 	{
 		/*
-		 * Ifd Handler 3.0 found 
+		 * Ifd Handler 3.0 found
 		 */
 		rContext->dwVersion = IFD_HVERSION_3_0;
 	}
 	else
 	{
 		/*
-		 * Ifd Handler 2.0 found 
+		 * Ifd Handler 2.0 found
 		 */
 		rContext->dwVersion = IFD_HVERSION_2_0;
 	}
 
 	/*
-	 * The following binds version 1.0 of the IFD Handler specs 
+	 * The following binds version 1.0 of the IFD Handler specs
 	 */
 
 	if (rContext->dwVersion == IFD_HVERSION_1_0)
 	{
-		Log1(PCSC_LOG_INFO, "Loading IFD Handler 1.0");
+		Log1(PCSC_LOG_DEBUG, "Loading IFD Handler 1.0");
 
 #define GET_ADDRESS_OPTIONALv1(field, function, code) \
 { \
@@ -909,7 +921,7 @@
 	else if (rContext->dwVersion == IFD_HVERSION_2_0)
 	{
 		/*
-		 * The following binds version 2.0 of the IFD Handler specs 
+		 * The following binds version 2.0 of the IFD Handler specs
 		 */
 
 #define GET_ADDRESS_OPTIONALv2(s, code) \
@@ -927,7 +939,7 @@
 		Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
 		exit(1); )
 
-		Log1(PCSC_LOG_INFO, "Loading IFD Handler 2.0");
+		Log1(PCSC_LOG_DEBUG, "Loading IFD Handler 2.0");
 
 		GET_ADDRESSv2(CreateChannel)
 		GET_ADDRESSv2(CloseChannel)
@@ -943,7 +955,7 @@
 	else if (rContext->dwVersion == IFD_HVERSION_3_0)
 	{
 		/*
-		 * The following binds version 3.0 of the IFD Handler specs 
+		 * The following binds version 3.0 of the IFD Handler specs
 		 */
 
 #define GET_ADDRESS_OPTIONALv3(s, code) \
@@ -961,7 +973,7 @@
 		Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \
 		exit(1); )
 
-		Log1(PCSC_LOG_INFO, "Loading IFD Handler 3.0");
+		Log1(PCSC_LOG_DEBUG, "Loading IFD Handler 3.0");
 
 		GET_ADDRESSv2(CreateChannel)
 		GET_ADDRESSv2(CloseChannel)
@@ -978,19 +990,18 @@
 	else
 	{
 		/*
-		 * Who knows what could have happenned for it to get here. 
+		 * Who knows what could have happenned for it to get here.
 		 */
 		Log1(PCSC_LOG_CRITICAL, "IFD Handler not 1.0/2.0 or 3.0");
 		exit(1);
 	}
-
 	return SCARD_S_SUCCESS;
 }
 
 LONG RFUnBindFunctions(PREADER_CONTEXT rContext)
 {
 	/*
-	 * Zero out everything 
+	 * Zero out everything
 	 */
 
 	memset(&rContext->psFunctions, 0, sizeof(rContext->psFunctions));
@@ -1001,12 +1012,12 @@
 LONG RFUnloadReader(PREADER_CONTEXT rContext)
 {
 	/*
-	 * Make sure no one else is using this library 
+	 * Make sure no one else is using this library
 	 */
 
 	if (*rContext->pdwFeeds == 1)
 	{
-		Log1(PCSC_LOG_INFO, "Unloading reader driver.");
+		Log1(PCSC_LOG_DEBUG, "Unloading reader driver.");
 		DYN_CloseLibrary(&rContext->vHandle);
 	}
 
@@ -1027,12 +1038,30 @@
 
 	if (rContext->dwLockId == 0 || rContext->dwLockId == hCard)
 		return SCARD_S_SUCCESS;
+	else {
+		return SCARD_E_SHARING_VIOLATION;
+	}
+
+}
+
+LONG RFLockSharing(DWORD hCard)
+{
+	PREADER_CONTEXT rContext = NULL;
+
+	RFReaderInfoById(hCard, &rContext);
+
+	if (RFCheckSharing(hCard) == SCARD_S_SUCCESS)
+	{
+		EHSetSharingEvent(rContext, 1);
+		rContext->dwLockId = hCard;
+	}
 	else
 		return SCARD_E_SHARING_VIOLATION;
 
-}
-
-LONG RFLockSharing(DWORD hCard)
+	return SCARD_S_SUCCESS;
+}
+
+LONG RFUnlockSharing(DWORD hCard)
 {
 	PREADER_CONTEXT rContext = NULL;
 
@@ -1040,8 +1069,8 @@
 
 	if (RFCheckSharing(hCard) == SCARD_S_SUCCESS)
 	{
-		EHSetSharingEvent(rContext, 1);
-		rContext->dwLockId = hCard;
+		EHSetSharingEvent(rContext, 0);
+		rContext->dwLockId = 0;
 	}
 	else
 		return SCARD_E_SHARING_VIOLATION;
@@ -1049,23 +1078,6 @@
 	return SCARD_S_SUCCESS;
 }
 
-LONG RFUnlockSharing(DWORD hCard)
-{
-	PREADER_CONTEXT rContext = NULL;
-
-	RFReaderInfoById(hCard, &rContext);
-
-	if (RFCheckSharing(hCard) == SCARD_S_SUCCESS)
-	{
-		EHSetSharingEvent(rContext, 0);
-		rContext->dwLockId = 0;
-	}
-	else
-		return SCARD_E_SHARING_VIOLATION;
-
-	return SCARD_S_SUCCESS;
-}
-
 LONG RFUnblockContext(SCARDCONTEXT hContext)
 {
 	int i;
@@ -1087,14 +1099,14 @@
 	LONG rv;
 
 	/*
-	 * Spawn the event handler thread 
-	 */
-	Log3(PCSC_LOG_INFO, "Attempting startup of %s using %s",
+	 * Spawn the event handler thread
+	 */
+	Log3(PCSC_LOG_DEBUG, "Attempting startup of %s using %s",
 		rContext->lpcReader, rContext->lpcLibrary);
 
   /******************************************/
 	/*
-	 * This section loads the library 
+	 * This section loads the library
 	 */
   /******************************************/
 	rv = RFLoadReader(rContext);
@@ -1103,7 +1115,7 @@
 
   /*******************************************/
 	/*
-	 * This section binds the functions 
+	 * This section binds the functions
 	 */
   /*******************************************/
 	rv = RFBindFunctions(rContext);
@@ -1116,7 +1128,7 @@
 
   /*******************************************/
 	/*
-	 * This section tries to open the port 
+	 * This section tries to open the port
 	 */
   /*******************************************/
 
@@ -1124,30 +1136,29 @@
 
 	if (rv != IFD_SUCCESS)
 	{
-		Log3(PCSC_LOG_CRITICAL, "Open Port %X Failed (%s)",
+		Log3(PCSC_LOG_ERROR, "Open Port %X Failed (%s)",
 			rContext->dwPort, rContext->lpcDevice);
 		RFUnBindFunctions(rContext);
 		RFUnloadReader(rContext);
 		return SCARD_E_INVALID_TARGET;
 	}
-
 	return SCARD_S_SUCCESS;
 }
 
 LONG RFUnInitializeReader(PREADER_CONTEXT rContext)
 {
-	Log2(PCSC_LOG_INFO, "Attempting shutdown of %s.",
+	Log2(PCSC_LOG_DEBUG, "Attempting shutdown of %s.",
 		rContext->lpcReader);
 
 	/*
-	 * Close the port, unbind the functions, and unload the library 
+	 * Close the port, unbind the functions, and unload the library
 	 */
 
 	/*
 	 * If the reader is getting uninitialized then it is being unplugged
 	 * so I can't send a IFDPowerICC call to it
-	 * 
-	 * IFDPowerICC( rContext, IFD_POWER_DOWN, Atr, &AtrLen ); 
+	 *
+	 * IFDPowerICC( rContext, IFD_POWER_DOWN, Atr, &AtrLen );
 	 */
 	IFDCloseIFD(rContext);
 	RFUnBindFunctions(rContext);
@@ -1162,7 +1173,7 @@
 
 	/*
 	 * Create a random handle with 16 bits check to see if it already is
-	 * used. 
+	 * used.
 	 */
 	randHandle = SYS_RandomInt(10, 65000);
 
@@ -1182,7 +1193,7 @@
 						(sReadersContexts[i])->psHandles[j].hCard)
 					{
 						/*
-						 * Get a new handle and loop again 
+						 * Get a new handle and loop again
 						 */
 						randHandle = SYS_RandomInt(10, 65000);
 						continue;
@@ -1193,7 +1204,7 @@
 
 		/*
 		 * Once the for loop is completed w/o restart a good handle was
-		 * found and the loop can be exited. 
+		 * found and the loop can be exited.
 		 */
 
 		if (i == PCSCLITE_MAX_READERS_CONTEXTS)
@@ -1276,7 +1287,7 @@
 	int i;
 
 	/*
-	 * Set all the handles for that reader to the event 
+	 * Set all the handles for that reader to the event
 	 */
 	for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)
 	{
@@ -1345,7 +1356,6 @@
 {
 	int i;
 
-	Log1(PCSC_LOG_INFO, "entering cleaning function");
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		if (sReadersContexts[i]->vHandle != 0)
@@ -1353,13 +1363,13 @@
 			LONG rv;
 			char lpcStripReader[MAX_READERNAME];
 
-			Log2(PCSC_LOG_INFO, "Stopping reader: %s",
+			Log2(PCSC_LOG_DEBUG, "Stopping reader: %s",
 				sReadersContexts[i]->lpcReader);
 
 			strncpy(lpcStripReader, (sReadersContexts[i])->lpcReader,
 				sizeof(lpcStripReader));
 			/*
-			 * strip the 6 last char ' 00 00' 
+			 * strip the 6 last char ' 00 00'
 			 */
 			lpcStripReader[strlen(lpcStripReader) - 6] = '\0';
 
@@ -1371,10 +1381,10 @@
 	}
 
 	/*
-	 * exit() will call at_exit() 
-	 */
-
-	if (shouldExit) 
+	 * exit() will call at_exit()
+	 */
+
+	if (shouldExit)
 		exit(0);
 }
 
@@ -1383,9 +1393,8 @@
 	SerialReader *reader_list;
 	int i, rv;
 
-	/* remember the ocnfiguration filename for RFReCheckReaderConf() */
+	/* remember the configuration filename for RFReCheckReaderConf() */
 	ConfigFile = strdup(readerconf);
-
 	rv = DBGetReaderList(readerconf, &reader_list);
 
 	/* the list is empty */
@@ -1395,9 +1404,26 @@
 	for (i=0; reader_list[i].pcFriendlyname; i++)
 	{
 		int j;
-
-		RFAddReader(reader_list[i].pcFriendlyname, reader_list[i].dwChannelId,
-			reader_list[i].pcLibpath, reader_list[i].pcDevicename);
+		char adjustedLibPath[256];
+		/*
+		 * If a IFD library plugin path was specified in pcscd.conf
+		 * or on the pcscd command line, override the directory
+		 * portion of IFD path specified for the reader in the
+		 * reader configuration file.
+		 */
+		if (pcscCfg.ifdPluginDir != NULL) {
+			strcpy(adjustedLibPath, pcscCfg.ifdPluginDir);
+			strcat(adjustedLibPath, "/");
+			strcat(adjustedLibPath, SYS_Basename(reader_list[i].pcLibpath));
+		} else {
+			strcpy(adjustedLibPath, reader_list[i].pcLibpath);
+		}
+		RFAddReader(
+		    reader_list[i].pcFriendlyname,
+		    reader_list[i].dwChannelId,
+		    adjustedLibPath,
+		    reader_list[i].pcDevicename,
+		    reader_list[i].pcAuthSvcName);
 
 		/* update the ConfigFileCRC (this false "CRC" is very weak) */
 		for (j=0; j<reader_list[i].pcFriendlyname[j]; j++)
@@ -1406,11 +1432,14 @@
 			ConfigFileCRC += reader_list[i].pcLibpath[j];
 		for (j=0; j<reader_list[i].pcDevicename[j]; j++)
 			ConfigFileCRC += reader_list[i].pcDevicename[j];
+		for (j=0; j<reader_list[i].pcAuthSvcName[j]; j++)
+			ConfigFileCRC += reader_list[i].pcAuthSvcName[j];
 
 		/* free strings allocated by DBGetReaderList() */
 		free(reader_list[i].pcFriendlyname);
 		free(reader_list[i].pcLibpath);
 		free(reader_list[i].pcDevicename);
+		free(reader_list[i].pcAuthSvcName);
 	}
 	free(reader_list);
 
@@ -1440,6 +1469,8 @@
 			crc += reader_list[i].pcLibpath[j];
 		for (j=0; j<reader_list[i].pcDevicename[j]; j++)
 			crc += reader_list[i].pcDevicename[j];
+		for (j=0; j<reader_list[i].pcAuthSvcName[j]; j++)
+			crc += reader_list[i].pcAuthSvcName[j];
 	}
 
 	/* cancel if the configuration file has been modified */
@@ -1486,7 +1517,7 @@
 					if (IFDStatusICC(sReadersContexts[r], &dwStatus, ucAtr,
 						&dwAtrLen) != SCARD_S_SUCCESS)
 					{
-						Log2(PCSC_LOG_INFO, "Reader %s disappeared",
+						Log2(PCSC_LOG_DEBUG, "Reader %s disappeared",
 							reader_list[i].pcFriendlyname);
 						RFRemoveReader(reader_list[i].pcFriendlyname,
 							reader_list[r].dwChannelId);
@@ -1500,17 +1531,18 @@
 			/* we try to add it */
 			RFAddReader(reader_list[i].pcFriendlyname,
 				reader_list[i].dwChannelId, reader_list[i].pcLibpath,
-				reader_list[i].pcDevicename);
+				reader_list[i].pcDevicename, reader_list[i].pcAuthSvcName);
 
 		/* free strings allocated by DBGetReaderList() */
 		free(reader_list[i].pcFriendlyname);
 		free(reader_list[i].pcLibpath);
 		free(reader_list[i].pcDevicename);
+		free(reader_list[i].pcAuthSvcName);
 	}
 	free(reader_list);
 }
 
-void RFSuspendAllReaders(void) 
+void RFSuspendAllReaders(void)
 {
 	int i;
 
@@ -1525,12 +1557,12 @@
 
 }
 
-void RFAwakeAllReaders(void) 
+void RFAwakeAllReaders(void)
 {
 	LONG rv = IFD_SUCCESS;
 	int i;
 	int initFlag;
-        
+
 	initFlag = 0;
 
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
@@ -1544,12 +1576,12 @@
 			for (j=0; j < i; j++)
 			{
 				if (((sReadersContexts[j])->vHandle == (sReadersContexts[i])->vHandle)&&
-					((sReadersContexts[j])->dwPort   == (sReadersContexts[i])->dwPort)) 
+					((sReadersContexts[j])->dwPort   == (sReadersContexts[i])->dwPort))
 				{
 					initFlag = 1;
 				}
 			}
-                        
+
 			if (initFlag == 0)
 				rv = IFDOpenIFD(sReadersContexts[i]);
 			else

Modified: branches/Solaris/src/readerfactory.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/readerfactory.h?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/readerfactory.h (original)
+++ branches/Solaris/src/readerfactory.h Thu Jun 12 10:28:09 2008
@@ -30,6 +30,7 @@
 		char *pcFriendlyname;
 		char *pcDevicename;
 		char *pcLibpath;
+		char *pcAuthSvcName;
 		int dwChannelId;
 	} SerialReader;
 
@@ -143,6 +144,7 @@
 		char lpcReader[MAX_READERNAME];	/* Reader Name */
 		char lpcLibrary[MAX_LIBNAME];	/* Library Path */
 		char lpcDevice[MAX_DEVICENAME];	/* Device Name */
+		char lpcAuthSvc[MAX_AUTHSVCNAME]; /* Auth service name */
 		PCSCLITE_THREAD_T pthThread;	/* Event polling thread */
 		PCSCLITE_MUTEX_T mMutex;	/* Mutex for this connection */
 		RDR_CLIHANDLES psHandles[PCSCLITE_MAX_READER_CONTEXT_CHANNELS];	
@@ -180,7 +182,7 @@
 	typedef struct ReaderContext READER_CONTEXT, *PREADER_CONTEXT;
 
 	LONG RFAllocateReaderSpace(void);
-	LONG RFAddReader(LPSTR, DWORD, LPSTR, LPSTR);
+	LONG RFAddReader(LPSTR, DWORD, LPSTR, LPSTR, LPSTR);
 	LONG RFRemoveReader(LPSTR, DWORD);
 	LONG RFSetReaderName(PREADER_CONTEXT, LPSTR, LPSTR, DWORD, DWORD);
 	LONG RFListReaders(LPSTR, LPDWORD);

Modified: branches/Solaris/src/sys_generic.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/sys_generic.h?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/sys_generic.h (original)
+++ branches/Solaris/src/sys_generic.h Thu Jun 12 10:28:09 2008
@@ -51,6 +51,8 @@
 
 	int SYS_GetGID(void);
 
+	char *SYS_Getenv(char *);
+
 	int SYS_Chown(const char *, int, int);
 
 	int SYS_ChangePermissions(char *, int);
@@ -97,6 +99,10 @@
 
 	int SYS_Unlink(char *pcFile);
 
+        char *SYS_Basename(char *fullpath);
+
+        char *SYS_Dirname(char *fullpath);
+
 #ifdef __cplusplus
 }
 #endif

Modified: branches/Solaris/src/sys_unix.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/sys_unix.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/sys_unix.c (original)
+++ branches/Solaris/src/sys_unix.c Thu Jun 12 10:28:09 2008
@@ -21,6 +21,7 @@
 #include <sys/wait.h>
 #include <sys/time.h>
 #include <sys/file.h>
+#include <libgen.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
@@ -60,7 +61,7 @@
  */
 INTERNAL int SYS_Mkdir(char *path, int perms)
 {
-	return mkdir(path, perms);
+	return mkdir(path, perms); 
 }
 
 /**
@@ -534,3 +535,30 @@
 	return unlink(pcFile);
 }
 
+INTERNAL char *SYS_Getenv(char *name)
+{
+        return getenv(name);
+}
+
+INTERNAL char *SYS_Dirname(char *fullpath) 
+{
+	char *rv, path[255];
+	if (fullpath == NULL)
+		return NULL;
+	strcpy(path, fullpath);
+	if ((rv = dirname(path)) == NULL)
+		return NULL;
+	return strdup(rv);
+}
+
+INTERNAL char *SYS_Basename(char *fullpath) 
+{
+	char *rv, path[255];
+	if (fullpath == NULL)
+		return NULL;
+	strcpy(path, fullpath);
+	if ((rv = basename(path)) == NULL)
+		return NULL;
+	return strdup(rv);
+}
+

Modified: branches/Solaris/src/thread_generic.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/thread_generic.h?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/thread_generic.h (original)
+++ branches/Solaris/src/thread_generic.h Thu Jun 12 10:28:09 2008
@@ -38,6 +38,8 @@
 #define PCSCLITE_THREAD_T                pthread_t
 #define PCSCLITE_MUTEX                   pthread_mutex_t
 #define PCSCLITE_MUTEX_T                 pthread_mutex_t*
+#define PCSCLITE_COND			 pthread_cond_t
+#define PCSCLITE_COND_T			 pthread_cond_t*
 #define PCSCLITE_THREAD_FUNCTION(f)      void *(*f)(void *)
 #endif
 
@@ -45,6 +47,10 @@
 #define THREAD_ATTR_DEFAULT			0
 #define THREAD_ATTR_DETACHED		1
 
+	int SYS_CondInit(PCSCLITE_COND_T mCond); 
+	int SYS_CondWait(PCSCLITE_COND_T mCond, PCSCLITE_MUTEX_T mMutex); 
+	int SYS_CondSignal(PCSCLITE_COND_T mCond);
+	int SYS_CondBroadcast(PCSCLITE_COND_T mCond);
 	int SYS_MutexInit(PCSCLITE_MUTEX_T);
 	int SYS_MutexDestroy(PCSCLITE_MUTEX_T);
 	int SYS_MutexLock(PCSCLITE_MUTEX_T);

Modified: branches/Solaris/src/thread_unix.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/thread_unix.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/thread_unix.c (original)
+++ branches/Solaris/src/thread_unix.c Thu Jun 12 10:28:09 2008
@@ -23,6 +23,27 @@
 #define TRUE 1
 #define FALSE 0
 #endif
+
+
+INTERNAL int SYS_CondInit(PCSCLITE_COND_T mCond) 
+{
+        return pthread_cond_init(&mCond, NULL);
+}
+
+INTERNAL int SYS_CondWait(PCSCLITE_COND_T mCond, PCSCLITE_MUTEX_T mMutex) 
+{
+        return pthread_cond_wait(mCond, mMutex);
+}
+
+INTERNAL int SYS_CondSignal(PCSCLITE_COND_T mCond)
+{
+        return pthread_cond_signal(mCond);
+}
+
+INTERNAL int SYS_CondBroadcast(PCSCLITE_COND_T mCond)
+{
+        return pthread_cond_broadcast(mCond);
+}
 
 INTERNAL int SYS_MutexInit(PCSCLITE_MUTEX_T mMutex)
 {
@@ -56,10 +77,13 @@
 		attributes & THREAD_ATTR_DETACHED ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE))
 		return FALSE;
 	
-	if (0 == pthread_create(pthThread, &attr, pvFunction, pvArg))
-		return TRUE;
-	else
+	if (0 != pthread_create(pthThread, &attr, pvFunction, pvArg)) {
+		pthread_attr_destroy(&attr);
 		return FALSE;
+	}
+	pthread_attr_destroy(&attr);
+	return TRUE;
+	
 }
 
 INTERNAL int SYS_ThreadCancel(PCSCLITE_THREAD_T * pthThread)

Added: branches/Solaris/src/util.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/util.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/util.h (added)
+++ branches/Solaris/src/util.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,60 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2000-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * <NEED TO FIX KEYWORDS>
+ */
+
+
+#ifndef	__util_h__
+#define	__util_h__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif                                  
+
+#define LIST_INIT(hd)   	 (hd)->nx = (hd)->pv = (hd)
+#define LIST_NEEDS_INIT(hd)      ((hd)->nx == NULL) || ((hd->pv = NULL))
+#define LIST_EMPTY(hd)  	 ((hd)->nx == (hd))
+
+#define LIST_INS_BEFORE(p1, p2)               \
+ { (p1)->nx = (p2); (p1)->pv = (p2)->pv; (p2)->pv->nx = (p1); (p2)->pv = (p1); }
+
+ #define LIST_INS_AFTER(p1, p2)               \
+ { (p1)->pv = (p2); (p1)->nx = (p2)->nx; (p2)->nx->pv = (p1); (p2)->nx = (p1); }
+
+#define LIST_INSERT_FIRST(p, hd)    LIST_INS_AFTER(p, hd) 
+#define LIST_INSERT_LAST(p, hd)     LIST_INS_BEFORE(p, hd)
+#define LIST_FIRST(hd) 		 ((hd)->nx != (hd) ? (hd)->nx : 0)
+#define LIST_LAST(hd)  		 ((hd)->pv != (hd) ? (hd)->pv : 0)
+
+#define LIST_FOREACH(iter, hd)                \
+  for (iter = (hd)->nx; iter != (hd); iter = iter->nx) 
+
+#define LIST_REMOVE(p)                        \
+ { (p)->nx->pv = (p)->pv; (p)->pv->nx = (p)->nx; }
+
+#define LIST_MV(old_hd, new_hd) {             \
+        if (LIST_EMPTY(old_hd)) {             \
+                LIST_INIT(new_hd);            \
+        } else {                              \
+                (new_hd)->nx = (old_hd)->nx;  \
+                (new_hd)->pv = (old_hd)->pv;  \
+                (new_hd)->pv->nx = (new_hd);  \
+                (new_hd)->nx->pv = (new_hd);  \
+                LIST_INIT(old_hd,nx,pv);      \
+        }                                     \
+}
+#ifdef __cplusplus
+extern "C"
+}
+#endif
+
+#endif

Propchange: branches/Solaris/src/util.h
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/src/validate.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/validate.c?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/validate.c (added)
+++ branches/Solaris/src/validate.c Thu Jun 12 10:28:09 2008
@@ -1,0 +1,384 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2000-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * <NEED TO FIX KEYWORDS>
+ */
+
+/**
+ * @file
+ * @brief This handles thread function abstraction.
+ */
+
+#include <ucred.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <thread.h>
+#include <synch.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <strings.h>
+#include <link.h>
+#include "auth.h"
+#include <errno.h>
+#include <stdlib.h>
+#include "pcsclite.h"
+#include "validate.h"
+#include "pcscd-validate.h"
+#include "clientcred.h"
+#include "debuglog.h"
+#include "pcsc_config.h"
+#include "util.h"
+
+#define LINEMAX 256
+#define MAXARGS 100
+#define NONULL(s) (s ? s : "<null>")
+
+static time_t getFileCtime(char *);
+static int havPluginsChanged();
+static void reloadPlugins();
+static void acquirePluginsAccess();
+static void releasePluginsAccess();
+static void initArgv(char **);
+static void freeArgv(char **);
+
+typedef struct validatePlugin {
+	struct validatePlugin *nx;
+	struct validatePlugin *pv;
+	void *handle;
+	char *path;
+	char *tag;
+	time_t ctime;
+	initValidate_t initValidate;
+	getDisplayResource_t getDisplayResource;
+	getDisplayStatus_t getDisplayStatus;
+	getDisplayTag_t getDisplayTag;
+} plugin_t;
+
+static plugin_t plist;
+static mutex_t plugins_lock;
+static mutex_t plugins_refcnt_lock;
+static int pluginsRefCnt;
+static time_t conf_ctime;
+
+char *
+VALgetDisplayTag(int dpyNbr, void *ctx, char **facilityTag)
+{
+	plugin_t *pp = (plugin_t *)ctx;
+	acquirePluginsAccess();
+	if (pp->getDisplayTag(dpyNbr, facilityTag) != NULL) {
+		releasePluginsAccess();
+		return *facilityTag;
+	}
+	releasePluginsAccess();
+	return NULL;
+}
+void *
+VALgetDisplayResource(int dpyNbr, void *ctx, void **resource)
+{
+	plugin_t *pp = (plugin_t *)ctx;
+	acquirePluginsAccess();
+	if (pp->getDisplayResource(dpyNbr, resource) != NULL) {
+		releasePluginsAccess();
+		return *resource;
+	}
+	releasePluginsAccess();
+	return NULL;
+}
+int
+VALgetDisplayStatus(int dpyNbr, void **ctx, unsigned int *flags)
+{
+	plugin_t *pp;
+	acquirePluginsAccess();
+	LIST_FOREACH(pp, &plist) {
+		if (pp->getDisplayStatus(dpyNbr, flags) == DISPLAY_IS_VALID) {
+			releasePluginsAccess();
+			*ctx = (void *)pp;
+			return DISPLAY_IS_VALID;
+		}
+	}
+	*ctx = NULL;
+	releasePluginsAccess();
+	return DISPLAY_NOT_VALID;
+}
+int
+VALfindInstanceFiles(int dpyNbr, char **configFile, char **instanceScript) {
+	char buf[LINEMAX];
+	char *facilityTag;
+	void *ctx;
+	unsigned int flags;
+
+	if (VALgetDisplayStatus(dpyNbr, &ctx, &flags) != DISPLAY_IS_VALID ||
+	    VALgetDisplayTag(dpyNbr, ctx, &facilityTag) == NULL) {
+		Log2(PCSC_LOG_CRITICAL,
+			"Can't find tag for dpy :%d in Xservers file",
+		     pcscCfg.dpyNbr);
+		return -1;
+	}
+	sprintf(buf, "%s/pcscd-%s.conf", PCSCLITE_CONFIG_DIR, facilityTag);
+	*configFile = strdup(buf);
+	sprintf(buf, "%s/pcscd-%s", PCSCLITE_LIB_DIR, facilityTag);
+	*instanceScript = strdup(buf);
+	if (facilityTag != NULL)
+		free(facilityTag);
+	return 0;
+}
+
+void
+VALloadPlugins()
+{
+	FILE *fp = NULL;
+	char pluginPath[MAXPATHLEN];
+	char pluginTag[32], *cp2;
+	char *cp, *argp, *argv[MAXARGS], line[LINEMAX], temp[LINEMAX];
+	void *pluginHandle = NULL;
+	int i, j, argc;
+	plugin_t *pp;
+
+	LIST_INIT(&plist);
+
+	if ((fp = fopen(pcscCfg.validateConf, "r")) == NULL) {
+		Log3(PCSC_LOG_CRITICAL,	"Opening %s FAILED: %s\n",
+		   pcscCfg.validateConf, strerror(errno));
+		return;
+	}
+	conf_ctime = getFileCtime(pcscCfg.validateConf);
+
+	initArgv(argv);
+	while (fgets(temp, 256, fp) != NULL) {
+
+		memset(line, 0, sizeof(line));
+		if ((cp = strchr(temp, '\n')) != NULL)
+		    *cp = '\0';
+
+		freeArgv(argv);
+
+		if (strlen(temp) == 0 ||
+		    strncmp(temp, "#", 1) == 0)  /* Discard comments */
+			continue;
+
+		optind = 1; // Need to reset since main() called getopt()
+		argc = 0;
+		argp = temp;
+		while((cp = strtok(argp, " \t")) != NULL && argc < MAXARGS) {
+			argv[argc++] = strdup(cp);
+			argp = NULL;
+		}
+		argv[argc] = 0;
+		Log3(PCSC_LOG_DEBUG, "PCSCLITE_LIB_DIR=%s, argv[0]:%s",
+	PCSCLITE_LIB_DIR, argv[0]);
+
+		sprintf(pluginPath, "%s/%s", PCSCLITE_LIB_DIR, argv[0]);
+
+		if ((pluginHandle = dlopen(pluginPath,
+		    RTLD_LOCAL | RTLD_PARENT | RTLD_LAZY)) == NULL) {
+			Log2(PCSC_LOG_CRITICAL,
+				"Error opening plugin %s\n", pluginPath);
+			Log2(PCSC_LOG_CRITICAL,
+				"Error was: %s\n", dlerror());
+			freeArgv(argv);
+			continue;
+		}
+
+		if ((cp = strchr(argv[0], '-')) == NULL)
+			cp = "";
+		else {
+			++cp;
+			if ((cp2 = strchr(pluginTag, '.')) != NULL)
+				*cp2 = '\0';
+		}
+
+		if ((pp = malloc(sizeof (plugin_t))) == NULL) {
+			Log1(PCSC_LOG_CRITICAL, "Out of Memory");
+			return;
+		}
+		bzero(pp, sizeof (plugin_t));
+		pp->handle = pluginHandle;
+		pp->path = strdup(pluginPath);
+		pp->ctime = getFileCtime(pluginPath);
+		pp->tag = strdup(cp);
+
+		if ((pp->initValidate = (initValidate_t)dlsym(pluginHandle,
+			"initValidate")) == NULL) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "Error finding init() in plugin %s\n",
+			    pluginPath);
+			Log2(PCSC_LOG_CRITICAL, "Error was: %s\n", dlerror());
+			dlclose(pluginHandle);
+			freeArgv(argv);
+			free(pp);
+			continue;
+		}
+		if ((pp->getDisplayTag = (getDisplayTag_t)dlsym(pluginHandle,
+			"getDisplayTag")) == NULL) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "Error finding getDisplayTag() in plugin %s\n",
+			    pluginPath);
+			Log2(PCSC_LOG_CRITICAL, "Error was: %s\n", dlerror());
+			dlclose(pluginHandle);
+			freeArgv(argv);
+			free(pp);
+			continue;
+		}
+		if ((pp->getDisplayResource = (getDisplayResource_t)dlsym(pluginHandle,
+			"getDisplayResource")) == NULL) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "Error finding getDisplayResource() in plugin %s\n",
+			    pluginPath);
+			Log2(PCSC_LOG_CRITICAL, "Error was: %s\n", dlerror());
+			dlclose(pluginHandle);
+			free(pp);
+			freeArgv(argv);
+			continue;
+		}
+		if ((pp->getDisplayStatus = (getDisplayStatus_t)dlsym(pluginHandle,
+			"getDisplayStatus")) == NULL) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "Error finding getDisplayStatus() in plugin %s\n",
+			    pluginPath);
+			Log2(PCSC_LOG_CRITICAL, "Error was: %s\n", dlerror());
+			dlclose(pluginHandle);
+			freeArgv(argv);
+			free(pp);
+			continue;
+		}
+
+		if (pp->initValidate(argc, argv) < 0) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "Initialization failure for plugin %s\n",
+			    pluginPath);
+			dlclose(pluginHandle);
+			freeArgv(argv);
+			free(pp);
+			continue;
+		}
+
+		LIST_INSERT_LAST(pp, &plist);
+	}
+	fclose(fp);
+	freeArgv(argv);
+}
+
+static time_t
+getFileCtime(char *path)
+{
+	struct stat statbuf;
+	if (stat(path, &statbuf) < 0) {
+		Log2(PCSC_LOG_DEBUG, "Error stat()'ing %s", path);
+		return 0;
+	}
+	return statbuf.st_ctime;
+}
+
+static int
+havePluginsChanged()
+{
+	plugin_t *pp;
+	if (getFileCtime(pcscCfg.validateConf) != conf_ctime)
+		return 1;
+
+	LIST_FOREACH(pp, &plist)   {
+		if (getFileCtime(pp->path) != pp->ctime)
+			return 1;
+	}
+
+	return 0;
+}
+
+static void
+reloadPlugins()
+{
+	plugin_t *pp;
+
+	/*
+	 * Block new attempts to access plugin
+	 */
+	mutex_lock(&plugins_lock);
+	/*
+	 * Wait for any plugin access in progess to complete
+	 */
+	for(;;) {
+		mutex_lock(&plugins_refcnt_lock);
+		if (pluginsRefCnt == 0) {
+			mutex_unlock(&plugins_refcnt_lock);
+			break;
+		}
+		mutex_unlock(&plugins_refcnt_lock);
+		usleep(10000);
+	}
+	/*
+	 * We now have exclusive access to plugins.
+	 * Unload all plugins
+	 */
+	LIST_FOREACH(pp, &plist) {
+		dlclose(pp->handle);
+		if (pp->path)
+			free(pp->path);
+		if (pp->tag)
+			free(pp->tag);
+		LIST_REMOVE(pp);
+		free(pp);
+	}
+	/*
+	 * Load all plugins to get refreshed data
+	 */
+	VALloadPlugins();
+	/*
+	 * Allow plugins access again
+	 */
+	mutex_unlock(&plugins_lock);
+
+}
+
+static void
+acquirePluginsAccess() {
+	plugin_t *pp;
+	int rv;
+	if (havePluginsChanged())
+		reloadPlugins();
+	/*
+	 * Acquire/release lock immediately.  Goal is to wait
+	 * but not to block others.
+	 */
+	mutex_lock(&plugins_lock);
+	mutex_unlock(&plugins_lock);
+	mutex_lock(&plugins_refcnt_lock);
+	++pluginsRefCnt;
+	mutex_unlock(&plugins_refcnt_lock);
+}
+
+static void
+releasePluginsAccess() {
+	mutex_lock(&plugins_refcnt_lock);
+	--pluginsRefCnt;
+	mutex_unlock(&plugins_refcnt_lock);
+}
+
+void
+initArgv(char **argv)
+{
+	int i;
+	for (i = 0; i < MAXARGS; i++)
+		argv[i] = NULL;
+}
+
+void
+freeArgv(char **argv)
+{
+	int i;
+	for (i = 0; i < MAXARGS; i++) {
+		if (argv[i] != NULL) {
+			free(argv[i]);
+			argv[i] = NULL;
+		}
+	}
+}
+

Propchange: branches/Solaris/src/validate.c
------------------------------------------------------------------------------
    svn:executable = *

Added: branches/Solaris/src/validate.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/validate.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/validate.h (added)
+++ branches/Solaris/src/validate.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,37 @@
+/*
+ * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ *
+ * Copyright (C) 2000-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Ludovic Rousseau <ludovic.rousseau at free.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ *  Michael Bender <michael.bender at sun.com>
+ *
+ * <NEED TO FIX KEYWORDS>
+ */
+
+
+#ifndef	__validate_h__
+#define	__validate_h__
+
+#include "clientcred.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+void VALloadPlugins();
+int VALfindInstanceFiles(int, char **, char **);
+char *VALgetDisplayTag(int, void *, char **);
+void *VALgetDisplayResource(int, void *, void **);
+int VALgetDisplayStatus(int, void **, unsigned int *);
+
+#ifdef __cplusplus
+extern "C"
+}
+#endif
+
+#endif

Propchange: branches/Solaris/src/validate.h
------------------------------------------------------------------------------
    svn:executable = *

Modified: branches/Solaris/src/winscard.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/winscard.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/winscard.c (original)
+++ branches/Solaris/src/winscard.c Thu Jun 12 10:28:09 2008
@@ -10,7 +10,7 @@
 
 /**
  * @mainpage MUSCLE PC/SC-Lite API Documentation
- * 
+ *
  * @section Introduction
  *
  * This document contains the reference API calls for communicating to the
@@ -29,7 +29,7 @@
  *
  * I would really like to hear from you. If you have any feedback either on
  * this documentation or on the MUSCLE project please feel free to email me at:
- * corcoran at musclecard.com. 
+ * corcoran at musclecard.com.
  *
  *
  * @section API Routines
@@ -45,10 +45,10 @@
  *
  * For a human readable representation of an error the function
  * pcsc_stringify_error() is declared in pcsclite.h. This function is not
- * available on Microsoft(R) winscard API and is pcsc-lite specific. 
+ * available on Microsoft(R) winscard API and is pcsc-lite specific.
  *
  * @section Internals
- * 
+ *
  * PC/SC Lite is formed by a server deamon (<tt>pcscd</tt>) and a client
  * library (<tt>libpcsclite.so</tt>) that communicate via IPC.
  *
@@ -82,17 +82,34 @@
 #include <stdlib.h>
 #include <sys/time.h>
 #include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <arpa/inet.h>
+
 
 #include "pcsclite.h"
+#include "pcsc_config.h"
+#include "clientcred.h"
 #include "winscard.h"
+#include "winscard_client.h"
 #include "ifdhandler.h"
 #include "debuglog.h"
 #include "readerfactory.h"
 #include "prothandler.h"
 #include "ifdwrapper.h"
 #include "atrhandler.h"
+#include "validate.h"
+#include "auth.h"
 #include "sys_generic.h"
 #include "eventhandler.h"
+#include "pcscd-validate.h"
+#include "pcscd-auth.h"
+
 
 /** used for backward compatibility */
 #define SCARD_PROTOCOL_ANY_OLD	 0x1000
@@ -111,11 +128,23 @@
 SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
 
 /**
+ * @brief Represents the an Application Context on the Server side.
+ *
+ * An Application Context contains Channels (\c hCard).
+ */
+static struct _psContext
+{
+	int is_allocated;                       /* flag */
+	PCSCLITE_CRED_T cred;                   /* Client credentials struct */
+} psContext[PCSCLITE_MAX_APPLICATIONS_CONTEXTS];
+
+
+/**
  * @brief Creates an Application Context for a client.
  *
  * This must be the first function called in a PC/SC application.
  *
- * @param[in] dwScope Scope of the establishment. 
+ * @param[in] dwScope Scope of the establishment.
  * This can either be a local or remote connection.
  * <ul>
  *   <li>SCARD_SCOPE_USER - Not used.
@@ -135,6 +164,10 @@
 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
 	LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
 {
+	int i;
+	char buf[80];
+	PCSCLITE_CRED_T *cred;
+
 	/*
 	 * Check for NULL pointer
 	 */
@@ -144,30 +177,79 @@
 	if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
 		dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
 	{
-
 		*phContext = 0;
 		return SCARD_E_INVALID_VALUE;
 	}
 
-	/*
-	 * Unique identifier for this server so that it can uniquely be
-	 * identified by clients and distinguished from others
-	 */
-
-	*phContext = (PCSCLITE_SVC_IDENTITY + SYS_RandomInt(1, 65535));
-
-	Log2(PCSC_LOG_DEBUG, "Establishing Context: %d", *phContext);
-
+
+	/*
+	 * GeFt a unique identifier for this context
+	 */
+	for (i = 0; i < PCSCLITE_MAX_APPLICATIONS_CONTEXTS; i++)
+	{
+	      if (!psContext[i].is_allocated) {
+		      *phContext = PCSCLITE_SVC_IDENTITY + i;
+		      psContext[i].is_allocated = 1;
+		      break;
+	      }
+	}
+	cred = &psContext[i].cred;
+	memcpy(cred, (PCSCLITE_CRED_T *)pvReserved2, sizeof(struct pcsc_client_cred));
+	if (pcscCfg.useAuthentication && (pcscCfg.launchMode != INSTANCE))
+	{
+		char *facilityTag = NULL;
+		void *resource = NULL;
+		char credinfo[80];
+		void *ctx;
+		unsigned int flags;
+
+		char *ipaddr =  inet_ntoa(*(struct in_addr *)&cred->clientXhostIP);
+
+		sprintf(credinfo, "[ <%s>:%d.%d, EUID: %d, EGID: %d ]",
+		    ipaddr, cred->dpyNbr, cred->screenNbr,
+		    cred->euid, cred->egid);
+
+		if (VALgetDisplayStatus(cred->dpyNbr, &ctx, &flags) != DISPLAY_IS_VALID ||
+		    VALgetDisplayTag(cred->dpyNbr, ctx, &facilityTag) == NULL) {
+			Log2(PCSC_LOG_ERROR,
+				"Validation Failed: Display "
+				":%d not configured as valid", cred->dpyNbr);
+			return SCARD_E_NO_PERMISSION;
+		}
+		VALgetDisplayResource(cred->dpyNbr, ctx, &resource);
+		if (AUTHCheckDaemon((const char *)facilityTag, cred, resource) < 0) {
+			Log3(PCSC_LOG_ERROR,
+			     "\n\"%s\" authentication FAILED\n"
+			     "Client creds: %s\n",
+			     facilityTag, credinfo);
+			free(facilityTag);
+			if (resource)
+				free(resource);
+			return SCARD_E_NO_PERMISSION;
+		}
+		Log3(PCSC_LOG_DEBUG,
+		     "\"%s\" authentication SUCCEEDED\n"
+		     " Client creds: %s\n",
+		     facilityTag, credinfo);
+		free(facilityTag);
+		if (resource)
+			free(resource);
+	}
+	Log2(PCSC_LOG_DEBUG, "Establishing Context: 0x%x", *phContext);
 	return SCARD_S_SUCCESS;
 }
 
 LONG SCardReleaseContext(SCARDCONTEXT hContext)
 {
-	/*
-	 * Nothing to do here RPC layer will handle this
-	 */
-
-	Log2(PCSC_LOG_DEBUG, "Releasing Context: %d", hContext);
+	int i = hContext - PCSCLITE_SVC_IDENTITY;
+
+	if (i < 0 || i > PCSCLITE_MAX_APPLICATIONS_CONTEXTS)
+		return SCARD_E_INVALID_PARAMETER;
+
+	psContext[i].is_allocated = 0;
+	memset(&psContext[i].cred, 0, sizeof(struct pcsc_client_cred));
+
+	Log2(PCSC_LOG_DEBUG, "Releasing Context: 0x%x", hContext);
 
 	return SCARD_S_SUCCESS;
 }
@@ -189,7 +271,8 @@
 	LONG rv;
 	PREADER_CONTEXT rContext = NULL;
 	DWORD dwStatus;
-
+	int ctxidx;
+	int cnt = 0;
 	/*
 	 * Check for NULL parameters
 	 */
@@ -197,6 +280,11 @@
 		return SCARD_E_INVALID_PARAMETER;
 	else
 		*phCard = 0;
+
+	ctxidx = (unsigned int)hContext - PCSCLITE_SVC_IDENTITY;
+	if (ctxidx > PCSCLITE_MAX_APPLICATIONS_CONTEXTS)
+		return SCARD_E_NO_PERMISSION;
+
 
 	if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
 			!(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
@@ -211,7 +299,6 @@
 
 	Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %d",
 		szReader, dwPreferredProtocols);
-
 	rv = RFReaderInfo((LPSTR) szReader, &rContext);
 
 	if (rv != SCARD_S_SUCCESS)
@@ -219,6 +306,7 @@
 		Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader);
 		return rv;
 	}
+
 
 	/*
 	 * Make sure the reader is working properly
@@ -259,12 +347,64 @@
 		}
 	}
 
+	/***************************************************
+	 *
+	 * This section authenticates access to the reader
+	 * if authentication option is enabled
+	 *
+	 ***************************************************/
+#if 0
+	if (pcscCfg.useAuthentication) {
+
+		PCSCLITE_CRED_T *cred = &psContext[ctxidx].cred;
+		char *ipaddr =  inet_ntoa(*(struct in_addr *)&cred->clientXhostIP);
+		char *facilityTag = NULL;
+		char credinfo[80];
+		int status;
+
+		sprintf(credinfo, "[ <%s>:%d.%d, EUID: %d, EGID: %d ]",
+		    ipaddr, cred->dpyNbr, cred->screenNbr,
+		    cred->euid, cred->egid);
+
+		if ((VALgetDisplayTag(cred->dpyNbr, &facilityTag)) == NULL) {
+			Log2(PCSC_LOG_ERROR,
+				"Validation Failed: Display "
+				":%d not configured as valid", cred->dpyNbr);
+			return SCARD_E_NO_PERMISSION;
+		}
+		status = AUTHCheckIfd(facilityTag, cred, szReader,
+		    rContext->lpcAuthSvc);
+		if (status < 0) {
+			Log3(PCSC_LOG_DEBUG,
+				"IFD authentication FAILED for reader:\n\"%s\""
+				"\nClient creds: %s\n",
+				szReader, credinfo);
+
+			return SCARD_E_NO_PERMISSION;
+		} else {
+			Log3(PCSC_LOG_DEBUG,
+				"IFD authentication SUCCEEDED for reader: \n\"%s\"\n"
+				"Client creds: %s\n",
+				szReader, credinfo);
+		}
+		if (facilityTag != NULL)
+			free(facilityTag);
+	}
+#endif
+
 	/*******************************************
 	 *
 	 * This section tries to decode the ATR
 	 * and set up which protocol to use
 	 *
 	 *******************************************/
+
+	/*
+	 * Give the IFD handler a chance to initialize before proceeding
+	 */
+	while(rContext->readerState->cardAtrLength == 0 && ++cnt < 25)
+		usleep(200000);
+
 	if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
 		rContext->readerState->cardProtocol = SCARD_PROTOCOL_RAW;
 	else
@@ -685,22 +825,26 @@
 	LONG rv;
 	PREADER_CONTEXT rContext = NULL;
 
-	if (hCard == 0)
+	if (hCard == 0) {
 		return SCARD_E_INVALID_HANDLE;
+	}
 
 	rv = RFReaderInfoById(hCard, &rContext);
-	if (rv != SCARD_S_SUCCESS)
-		return rv;
+	if (rv != SCARD_S_SUCCESS) {
+		return rv;
+	}
 
 	rv = RFFindReaderHandle(hCard);
-	if (rv != SCARD_S_SUCCESS)
-		return rv;
+	if (rv != SCARD_S_SUCCESS) {
+		return rv;
+	}
 
 	if ((dwDisposition != SCARD_LEAVE_CARD)
 		&& (dwDisposition != SCARD_UNPOWER_CARD)
 		&& (dwDisposition != SCARD_RESET_CARD)
-		&& (dwDisposition != SCARD_EJECT_CARD))
+		&& (dwDisposition != SCARD_EJECT_CARD)) {
 		return SCARD_E_INVALID_VALUE;
+	}
 
 	/*
 	 * Unlock any blocks on this context
@@ -832,14 +976,14 @@
 	 */
 	rContext->dwContexts -= 1;
 
-	if (rContext->dwContexts < 0)
+	if (rContext->dwContexts < 0) {
 		rContext->dwContexts = 0;
+	}
 
 	/*
 	 * Allow the status thread to convey information
 	 */
 	SYS_USleep(PCSCLITE_STATUS_POLL_RATE + 10);
-
 	return SCARD_S_SUCCESS;
 }
 
@@ -878,8 +1022,7 @@
 
 	rv = RFLockSharing(hCard);
 
-	Log2(PCSC_LOG_DEBUG, "Status: %d.", rv);
-
+//	Log2(PCSC_LOG_DEBUG, "SCardBeginTransaction() status: 0x%x.", rv);
 	return rv;
 }
 
@@ -907,6 +1050,9 @@
 	 */
 	if (rv != SCARD_S_SUCCESS)
 		return rv;
+
+//	Log3(PCSC_LOG_DEBUG, "SCardEndTransaction() hContext=0x%x, hCard=0x%x",
+//		rContext, hCard);
 
 	rv = RFFindReaderHandle(hCard);
 	if (rv != SCARD_S_SUCCESS)
@@ -1026,7 +1172,7 @@
 	 */
 	RFUnlockSharing(hCard);
 
-	Log2(PCSC_LOG_DEBUG, "Status: %d.", rv);
+	Log2(PCSC_LOG_DEBUG, "Status: 0x%x.", rv);
 
 	return rv;
 }

Added: branches/Solaris/src/winscard_client.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/winscard_client.h?rev=2989&op=file
==============================================================================
--- branches/Solaris/src/winscard_client.h (added)
+++ branches/Solaris/src/winscard_client.h Thu Jun 12 10:28:09 2008
@@ -1,0 +1,45 @@
+/*
+ * Copyright (C) 2001-2004
+ *  David Corcoran <corcoran at linuxnet.com>
+ *  Damien Sauveron <damien.sauveron at labri.fr>
+ *  Paul Klissner <paul.klissner at sun.com>
+ * 
+ * $Id: winscard_svc.h 1421 2005-04-12 12:09:21Z rousseau $
+ */
+
+/**
+ * @file
+ * @brief This contains internal information conveyed between
+ * the service and the server side API implementation.
+ */
+
+#ifndef __winscard_client_h__
+#define __winscard_client_h__
+
+#ifdef  __cplusplus
+extern "C"
+{
+#endif	
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+        
+        struct client_struct
+	{
+		SCARDCONTEXT hContext;
+		in_addr_t hostIpv4;
+		LONG xDispNbr;
+		LONG xSubDispNbr;
+		uid_t euid;
+		gid_t egid;
+	};
+	typedef struct client_struct client_struct;
+        
+#ifdef  __cplusplus
+}
+#endif
+
+#endif

Propchange: branches/Solaris/src/winscard_client.h
------------------------------------------------------------------------------
    svn:executable = *

Modified: branches/Solaris/src/winscard_clnt.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/winscard_clnt.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/winscard_clnt.c (original)
+++ branches/Solaris/src/winscard_clnt.c Thu Jun 12 10:28:09 2008
@@ -17,18 +17,32 @@
  * Here is exposed the API for client applications.
  */
 
+#include <stdio.h>
 #include "config.h"
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include <sys/types.h>
+#include <signal.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/un.h>
 #include <errno.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <strings.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <thread.h>
+#include <syslog.h>
 
 #include "misc.h"
 #include "pcsclite.h"
 #include "winscard.h"
+#include "pcsc_config.h"
 #include "debug.h"
 #include "thread_generic.h"
 
@@ -36,6 +50,9 @@
 #include "eventhandler.h"
 #include "sys_generic.h"
 #include "winscard_msg.h"
+#include "profile.h"
+
+struct pcsc_cfg_data pcscCfg;
 
 /** used for backward compatibility */
 #define SCARD_PROTOCOL_ANY_OLD	0x1000
@@ -49,78 +66,7 @@
 #define FALSE 0
 #endif
 
-#undef DO_PROFILE
-#ifdef DO_PROFILE
-
-#define PROFILE_FILE "/tmp/pcsc_profile"
-#include <stdio.h>
-#include <sys/time.h>
-
-struct timeval profile_time_start;
-FILE *fd;
-char profile_tty;
-
-#define PROFILE_START profile_start(__FUNCTION__);
-#define PROFILE_END profile_end(__FUNCTION__);
-
-static void profile_start(const char *f)
-{
-	static char initialized = FALSE;
-
-	if (!initialized)
-	{
-		initialized = TRUE;
-		fd = fopen(PROFILE_FILE, "a+");
-		if (NULL == fd)
-		{
-			fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
-				PROFILE_FILE, strerror(errno));
-			exit(-1);
-		}
-		fprintf(fd, "\nStart a new profile\n");
-
-		if (isatty(fileno(stderr)))
-			profile_tty = TRUE;
-		else
-			profile_tty = FALSE;
-	}
-
-	gettimeofday(&profile_time_start, NULL);
-} /* profile_start */
-
-/* r = a - b */
-static long int time_sub(struct timeval *a, struct timeval *b)
-{
-	struct timeval r;
-	r.tv_sec = a -> tv_sec - b -> tv_sec;
-	r.tv_usec = a -> tv_usec - b -> tv_usec;
-	if (r.tv_usec < 0)
-	{
-		r.tv_sec--;
-		r.tv_usec += 1000000;
-	}
-
-	return r.tv_sec * 1000000 + r.tv_usec;
-} /* time_sub */
-	
-
-static void profile_end(const char *f)
-{
-	struct timeval profile_time_end;
-	long d;
-
-	gettimeofday(&profile_time_end, NULL);
-	d = time_sub(&profile_time_end, &profile_time_start);
-
-	if (profile_tty)
-		fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m\n", f, d);
-	fprintf(fd, "%s %ld\n", f, d);
-} /* profile_end */
-
-#else
-#define PROFILE_START
-#define PROFILE_END
-#endif
+FILE *dbgFp;
 
 /**
  * Represents an Application Context Channel.
@@ -155,7 +101,7 @@
 
 /**
  * Memory mapped address used to read status information about the readers.
- * Each element in the vector \c readerStates makes references to a part of 
+ * Each element in the vector \c readerStates makes references to a part of
  * the memory mapped.
  */
 static int mapAddr = 0;
@@ -169,15 +115,16 @@
 /**
  * Pointers to a memory mapped area used to read status information about the
  * readers.
- * Each element in the vector \c readerStates makes references to a part of 
+ * Each element in the vector \c readerStates makes references to a part of
  * the memory mapped \c mapAddr.
  */
 static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
+static PCSCLITE_MUTEX readerStateMutex = PTHREAD_MUTEX_INITIALIZER;
+
 
 PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
 PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
 PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
-
 
 static LONG SCardAddContext(SCARDCONTEXT, DWORD);
 static LONG SCardGetContextIndice(SCARDCONTEXT);
@@ -185,30 +132,176 @@
 static LONG SCardRemoveContext(SCARDCONTEXT);
 
 static LONG SCardAddHandle(SCARDHANDLE, DWORD, LPSTR);
-static LONG SCardGetIndicesFromHandle(SCARDHANDLE, PDWORD, PDWORD);
+static LONG SCardGetIndicesFromHandle(SCARDHANDLE, PDWORD, PDWORD, PDWORD);
 static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE, PDWORD, PDWORD);
 static LONG SCardRemoveHandle(SCARDHANDLE);
 
 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
 	LPBYTE pbAttr, LPDWORD pcbAttrLen);
 
-static LONG SCardCheckDaemonAvailability(void);
+static LONG SCardCheckDaemonAvailability(DWORD);
+
+static PCSCLITE_MUTEX contextMutex = PTHREAD_MUTEX_INITIALIZER;
+static void (*prevSIGPIPEhand)(int);
 
 /*
- * Thread safety functions
- */
-inline static LONG SCardLockThread(void);
-inline static LONG SCardUnlockThread(void);
+ * Configuration routine debug logging routine. * Doesn't enforce line feeds as the global debugging
+ * functions do, and only logs to stderr, and
+ * and uses and independent debugging switch
+ */
+
+#include <stdarg.h>
+#define NONULL(a) (a) ? (a) : "<null>"
+
+//#define EXTRA_DEBUGGING
+#ifdef EXTRA_DEBUGGING
+#define DBG DBG_FUNC
+#define DBGERR dbg
+#else
+#define DBG
+#define DBGERR
+#endif
+
+void
+DBG_FUNC(SCARDCONTEXT hContext, SCARDHANDLE hCard, const char *fmt, ...) {
+	char buf[256], tmp[256];
+	va_list ap;
+
+	bzero(buf, 256);
+	va_start(ap, fmt);
+	vsnprintf(buf, 256, fmt, ap);
+	va_end(ap);
+
+	if (hContext == 0 && hCard != 0) {
+		int i;
+		for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++) {
+			if (psContextMap[i].hContext != NULL) {
+				int j;
+				for (j = 0; j < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; j++) {
+					if (psContextMap[i].psChannelMap[j].hCard == hCard) {
+						hContext = psContextMap[i].hContext;
+						break;
+					}
+				}
+			}
+
+		}
+	}
+
+	if (hContext != 0)
+		sprintf(tmp,"\n[%8.8x, %x] ",
+			hContext, thr_self());
+	else
+		sprintf(tmp,"           ", hContext);
+#if 0
+	write(2, tmp, strlen(tmp));
+	write(2, NONULL(buf), strlen(NONULL(buf)));
+#endif
+	fprintf(stdout, "%s", tmp);
+	fprintf(stdout, "%s", NONULL(buf));
+	fflush(stdout);
+}
+
+/*
+ * Assumes item being fetched is a pointer
+ * If memory mapping is enabled, this MACRO is effectively
+ * a NOP.
+ */
+#define FETCH(readerStatePtr, clientId) \
+	(fetchReaderState((readerStatePtr), (clientId), __LINE__))
+
+/*
+ * This allows us to transparently retrieve the contents of
+ * an arbitrary amount of the shared memory from the server
+ * over the transport (as an alternative to the memory-mapped
+ * file approach.
+ */
+PREADER_STATE
+fetchReaderState(PREADER_STATE rsp, DWORD dwClientID, int dbgline)
+{
+	int i, rsi, rv;
+	static unsigned long fn;
+
+	++fn;
+
+	if (pcscCfg.useMappedMemory)
+		return rsp;
+
+	SYS_MutexLock(&readerStateMutex);
+	/*
+	 * Find readerState array index based on pointer passed.
+	 */
+	for(rsi = -1, i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) {
+		if (rsp == readerStates[i]) {
+			rsi = i;
+			break;
+		}
+	}
+	/*
+	 * Try to fetch reader state from server.
+	 * If that fails, return NULL.
+	 * Disregard and re-try if EINTR and EAGAIN status is received.
+	 */
+	do {
+		rv = SHMfetchReaderState(rsp, rsi, dwClientID);
+		if (rv < 0) {
+			switch(errno) {
+			case EINTR:
+			case EAGAIN:
+				continue;
+			default:
+				/*
+				 * This is a serious condition, but until
+				 * we know the synchronization issues are
+				 * worked out, we need to try to insulate
+				 * the user while not losing track of them.
+				 */
+				syslog(LOG_ERR,
+				    "libpcsclite.so <-> pcscd connection failed."
+				    "  Couldn't fetch readerstate thr:%d, #%d\n%s",
+					thr_self(), fn, strerror(errno));
+				Log4(PCSC_LOG_DEBUG,
+				    "libpcsclite.so <-> pcscd connection failed."
+				    "  thr:%d, #%d\n%s", thr_self(), fn, strerror(errno));
+				SYS_MutexUnLock(&readerStateMutex);
+				return NULL;
+			}
+		}
+	} while (rv < 0);
+	SYS_MutexUnLock(&readerStateMutex);
+	return rsp;
+}
+
+void dumpContexts()
+{
+	int i;
+	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++) {
+		printf("#%d: context:%x fd=%d\n",
+			i, psContextMap[i].hContext, psContextMap[i].dwClientID);
+	}
+	printf("\n");
+}
+
+void
+sigpipeHandler(int sig)
+{
+	void (*hand)(int);
+
+	if (prevSIGPIPEhand != NULL && prevSIGPIPEhand != sigpipeHandler)
+		prevSIGPIPEhand(sig);
+	hand = sigset(SIGPIPE, sigpipeHandler);
+
+}
 
 static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT);
 
 /**
  * @brief Creates an Application Context to the PC/SC Resource Manager.
- 
+
  * This must be the first function called in a PC/SC application.
  * This is a thread-safe wrapper to the function \c SCardEstablishContextTH().
  *
- * @param[in] dwScope Scope of the establishment. 
+ * @param[in] dwScope Scope of the establishment.
  * This can either be a local or remote connection.
  * <ul>
  *   <li>SCARD_SCOPE_USER - Not used.
@@ -240,25 +333,22 @@
 	LONG rv;
 
 	PROFILE_START
-
-	SCardLockThread();
 	rv = SCardEstablishContextTH(dwScope, pvReserved1,
 		pvReserved2, phContext);
-	SCardUnlockThread();
-
 	PROFILE_END
 
 	return rv;
+
 }
 
 /**
- * @brief Creates a communication context to the PC/SC Resource 
+ * @brief Creates a communication context to the PC/SC Resource
  * Manager.
  *
  * This function shuld not be called directly. Instead, the thread-safe
  * function \c SCardEstablishContext() should be called.
  *
- * @param[in] dwScope Scope of the establishment. 
+ * @param[in] dwScope Scope of the establishment.
  * This can either be a local or remote connection.
  * <ul>
  *   <li>SCARD_SCOPE_USER - Not used.
@@ -280,10 +370,133 @@
 	LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
 {
 	LONG rv;
-	int i;
+	int i, cfgLoaded = 0;
 	establish_struct scEstablishStruct;
-	sharedSegmentMsg msgStruct;
 	DWORD dwClientID = 0;
+	int dpyNbr, screenNbr;
+	in_addr_t xHostIp;
+	char *homedir, homeconf[256];
+
+	char *cfgSearchPaths[] = {
+		"pcscd.conf",
+		PCSCLITE_CONFIG_DIR "/pcscd.conf",
+	};
+
+	homedir = getenv("HOME");
+	if (homedir != NULL) {
+		sprintf(homeconf, "%s/pcscd.conf", homedir);
+		cfgSearchPaths[0] = homeconf;
+	}
+	DBG(NULL, NULL, "SCardEstablishContextTH()/\n");
+
+	CFGSetConfigConsumer(CLIENT);
+
+	/*
+	 * Get information about display. In some situation
+	 * this determines which daemon to conact.
+	 */
+	 CFGParseXdisplay(SYS_Getenv("DISPLAY"), &dpyNbr, &screenNbr, &xHostIp);
+	 pcscCfg.dpyNbr = dpyNbr;
+	 pcscCfg.screenNbr = screenNbr;
+	 pcscCfg.xHostIp = xHostIp;
+
+	 /*
+	  * Do this section only once
+	  */
+	 if (!isExecuted) {
+#ifdef PCSCLITE_PORTSVC_PORTNO
+		pcscCfg.portNbr = PCSCLITE_PORTSVC_PORTNO;
+		pcscCfg.portNbrWild = 0;
+		pcscCfg.launchMode = LAUNCHER;
+		CFGDefault("TRANSPORT", "SOCKET_INETV4");
+		CFGDefault("USE_MAPPED_MEMORY", "FALSE");
+#else
+
+		CFGDefault("PORT_NUMBER", "0");
+		CFGDefault("PORT_NUMBER_WILD", "FALSE");
+		CFGDefault("TRANSPORT", "SOCKET_UNIX");
+		CFGDefault("USE_MAPPED_MEMORY", "TRUE");
+#endif
+
+		for (i = 0; i < sizeof(cfgSearchPaths) / sizeof(char *) && !cfgLoaded;
+		    i++) {
+			switch(rv = CFGLoadConfigFile(cfgSearchPaths[i])) {
+			case CFG_SUCCESS:
+				pcscCfg.pcscConfigFile = cfgSearchPaths[i];
+				cfgLoaded = 1;
+				break;
+			case CFG_FILE_NOT_FOUND:
+				break;
+			}
+		}
+	}
+
+#ifndef PCSCLITE_PORTSVC_PORTNO
+	/* Try to figure out where server base directory is in case
+	 * we are using that location to try to find the memory mapped
+	 * file.
+	 */
+	if (pcscCfg.baseDir != NULL) {
+	       if (pcscCfg.baseDirWild) {
+		       char dpyNbr[6];
+		       if (pcscCfg.dpyNbr == -1)
+			      CFGErrChkCritical(CFG_UNDEFINED_DISPLAY);
+		       sprintf(dpyNbr, "%d", pcscCfg.dpyNbr);
+		       CFGresolveWildcard(&pcscCfg.baseDir, dpyNbr);
+	       }
+	}
+
+	/*
+	* Adjust port number by the wildcard specifier, if any.
+	*/
+	if (pcscCfg.portNbrWild) {
+		if (pcscCfg.dpyNbr == -1)
+			 CFGErrChkCritical(CFG_UNDEFINED_DISPLAY);
+		CFGresolveWildcard(&pcscCfg.portNbr, (void *)pcscCfg.dpyNbr);
+	}
+
+	/*
+	 * Adapt all of the client configuration file paths, assigning
+	 * a default value (based on header constants) to any path
+	 * unspecified by the administrator.
+	 *.
+	 * If a base directory was specified, adapt resultant filepaths
+	 * to be relative to it using the following method:
+	 *
+	 *   a. Unspecified files which were assigned default names in the
+	 *      first step are put into *default* subtree locations under
+	 *      the base dir.
+	 *
+	 *   b. Filepaths that were specified by the administrator are
+	 *      converted from absolute paths to relative paths under the
+	 *      base dir.
+	 *
+	 * Note: If the IFD library plugin dir is specified by the admin,
+	 *       it overrides any dir locations specified in readers.conf
+	 */
+	if (pcscCfg.useMappedMemory) {
+	       if (pcscCfg.pcscdMemMappedFile == NULL)
+		       pcscCfg.pcscdMemMappedFile =
+		       CFGRetrofitPath(PCSCLITE_PUBSHM_FILE, "/var/run");
+	       else
+		       pcscCfg.pcscdMemMappedFile =
+		       CFGRetrofitPath(pcscCfg.pcscdMemMappedFile, NULL);
+	} else {
+		pcscCfg.pcscdMemMappedFile = NULL;
+	}
+
+	if (pcscCfg.transportType == SOCKET_UNIX) {
+		if (pcscCfg.netBindFile == NULL) {
+			pcscCfg.netBindFile =
+			    CFGRetrofitPath(PCSCLITE_CSOCK_NAME, "/var/run");
+		} else {
+			pcscCfg.netBindFile =
+			    CFGRetrofitPath(pcscCfg.netBindFile, NULL);
+		}
+	}
+#endif
+	if (pcscCfg.logLevel == INFO || pcscCfg.logLevel == DEBUG)
+		CFGdumpCfg(NULL);
 
 	if (phContext == NULL)
 		return SCARD_E_INVALID_PARAMETER;
@@ -291,7 +504,7 @@
 		*phContext = 0;
 
 	/* Check if the server is running */
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
+	if (SCardCheckDaemonAvailability(0) != SCARD_S_SUCCESS)
 		return SCARD_E_NO_SERVICE;
 
 	/*
@@ -310,35 +523,62 @@
 		 */
 		SYS_Initialize();
 
-		/*
-		 * Set up the memory mapped reader stats structures
-		 */
-		mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);
-		if (mapAddr < 0)
-		{
-			Log2(PCSC_LOG_CRITICAL, "Cannot open public shared file: %s",
-				PCSCLITE_PUBSHM_FILE);
-			return SCARD_E_NO_SERVICE;
-		}
-
-		pageSize = SYS_GetPageSize();
-
-		/*
-		 * Allocate each reader structure in the memory map
-		 */
-		for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
-		{
-			readerStates[i] = (PREADER_STATE)
-				SYS_PublicMemoryMap(sizeof(READER_STATE),
-				mapAddr, (i * pageSize));
-			if (readerStates[i] == NULL)
+		prevSIGPIPEhand = sigset(SIGPIPE, sigpipeHandler);
+
+
+		SYS_MutexLock(&readerStateMutex);
+
+		if (pcscCfg.useMappedMemory) {
+			/*
+			* Set up the memory mapped reader stats structures
+			*/
+			mapAddr = SYS_OpenFile(pcscCfg.pcscdMemMappedFile,
+				O_RDONLY, 0);
+			if (mapAddr < 0)
 			{
-				Log1(PCSC_LOG_CRITICAL, "Cannot public memory map");
-				SYS_CloseFile(mapAddr);	/* Close the memory map file */
-				return SCARD_F_INTERNAL_ERROR;
+				Log2(PCSC_LOG_CRITICAL,
+				"Cannot open public shared file: %s",
+				pcscCfg.pcscdMemMappedFile);
+				SYS_MutexUnLock(&readerStateMutex);
+				return SCARD_E_NO_SERVICE;
 			}
-		}
-
+			pageSize = SYS_GetPageSize();
+
+			/*
+			* Allocate each reader structure in the memory map
+			*/
+			for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
+			{
+				readerStates[i] = (PREADER_STATE)
+					SYS_PublicMemoryMap(sizeof(READER_STATE),
+					mapAddr, (i * pageSize));
+				if (readerStates[i] == NULL)
+				{
+				      Log1(PCSC_LOG_CRITICAL,
+					   "Cannot public memory map");
+				      SYS_CloseFile(mapAddr);
+				      SYS_MutexUnLock(&readerStateMutex);
+				      return SCARD_F_INTERNAL_ERROR;
+				}
+			}
+
+		} else {
+			for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
+			{
+				readerStates[i] =
+				   (PREADER_STATE)malloc(sizeof(READER_STATE));
+				if (readerStates[i] == NULL)
+				{
+					Log1(PCSC_LOG_CRITICAL,
+						"Out of memory");
+					SYS_MutexUnLock(&readerStateMutex);
+					return SCARD_F_INTERNAL_ERROR;
+				}
+
+			}
+		}
+
+		SYS_MutexUnLock(&readerStateMutex);
 		/*
 		 * Initializes the application contexts and all channels for each one
 		 */
@@ -365,8 +605,8 @@
 		}
 
 	}
-
-	/*
+	SYS_MutexLock(&contextMutex);
+       /*
 	 * Is there a free slot for this connection ?
 	 */
 
@@ -375,58 +615,39 @@
 		if (psContextMap[i].dwClientID == 0)
 			break;
 	}
-
 	if (i == PCSCLITE_MAX_APPLICATION_CONTEXTS)
 	{
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_NO_MEMORY;
 	}
 
+
 	/* Establishes a connection to the server */
-	if (SHMClientSetupSession(&dwClientID) != 0)
-	{
-		SYS_CloseFile(mapAddr);
+	if ((rv = SHMClientSetupSession(&dwClientID)) != 0)
+	{
+		if (pcscCfg.useMappedMemory)
+			SYS_CloseFile(mapAddr);
+		Log1(PCSC_LOG_INFO, "SCardEstablishContext(): client setup err");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_NO_SERVICE;
 	}
-
-	{	/* exchange client/server protocol versions */
-		sharedSegmentMsg msgStruct;
-		version_struct *veStr;
-
-		memset(&msgStruct, 0, sizeof(msgStruct));
-		msgStruct.mtype = CMD_VERSION;
-		msgStruct.user_id = SYS_GetUID();
-		msgStruct.group_id = SYS_GetGID();
-		msgStruct.command = 0;
-		msgStruct.date = time(NULL);
-
-		veStr = (version_struct *) msgStruct.data;
-		veStr->major = PROTOCOL_VERSION_MAJOR;
-		veStr->minor = PROTOCOL_VERSION_MINOR;
-
-		if (-1 == SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
-			PCSCLITE_MCLIENT_ATTEMPTS))
-			return SCARD_E_NO_SERVICE;
-
-		/*
-		 * Read a message from the server
-		 */
-		if (-1 == SHMMessageReceive(&msgStruct, sizeof(msgStruct), dwClientID,
-			PCSCLITE_CLIENT_ATTEMPTS))
-		{
-			Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
-			return SCARD_F_COMM_ERROR;
-		}
-
-		Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
-			veStr->major, veStr->minor);
-
-		isExecuted = 1;
-	}
+	isExecuted = 1;
+	if ((rv = SHMCheckProtocolVersion(
+			PROTOCOL_VERSION_MAJOR, PROTOCOL_VERSION_MINOR,
+			dwClientID)) < 0)  {
+			Log3(PCSC_LOG_CRITICAL,
+			      "Returning error SHMCheckProtocolVersion(): 0x%x (%d)",
+				rv, rv);
+			SYS_MutexUnLock(&contextMutex);
+			return rv;
+	}
+	isExecuted = 1;
 
 
 	if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
 		dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
 	{
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_VALUE;
 	}
 
@@ -436,33 +657,30 @@
 	scEstablishStruct.dwScope = dwScope;
 	scEstablishStruct.phContext = 0;
 	scEstablishStruct.rv = 0;
-
-	rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,
-		sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,
-		(void *) &scEstablishStruct);
-
-	if (rv == -1)
-		return SCARD_E_NO_SERVICE;
-
-	/*
-	 * Read the response from the server
-	 */
-	rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-	if (rv == -1)
-		return SCARD_F_COMM_ERROR;
-
-	memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));
-
-	if (scEstablishStruct.rv != SCARD_S_SUCCESS)
+	scEstablishStruct.clientXhostIP = pcscCfg.xHostIp;
+	scEstablishStruct.screenNbr = pcscCfg.screenNbr;
+	scEstablishStruct.dpyNbr = pcscCfg.dpyNbr;
+	if ((rv = SHMrpc(SCARD_ESTABLISH_CONTEXT,
+		dwClientID, &scEstablishStruct, sizeof (scEstablishStruct))) == -1) {
+			Log1(PCSC_LOG_INFO, "SCardEstablish(): SHMrpc() returned error");
+			SYS_MutexUnLock(&contextMutex);
+			return SCARD_F_COMM_ERROR;
+	}
+
+	if (scEstablishStruct.rv != SCARD_S_SUCCESS) {
+		Log1(PCSC_LOG_INFO, "Returning error from scEstablishStruct.rv");
+		SYS_MutexUnLock(&contextMutex);
 		return scEstablishStruct.rv;
+	}
 
 	*phContext = scEstablishStruct.phContext;
-
+	Log3(PCSC_LOG_DEBUG, "Establish: context:%x, fd=%d\n", *phContext, dwClientID);
 	/*
 	 * Allocate the new hContext - if allocator full return an error
 	 */
 	rv = SCardAddContext(*phContext, dwClientID);
+
+	SYS_MutexUnLock(&contextMutex);
 
 	return rv;
 }
@@ -482,63 +700,59 @@
  * LONG rv;
  * ...
  * rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
- * rv = SCardReleaseContext(hContext); 
+ * rv = SCardReleaseContext(hContext);
  * @endcode
  */
 LONG SCardReleaseContext(SCARDCONTEXT hContext)
 {
 	LONG rv;
 	release_struct scReleaseStruct;
-	sharedSegmentMsg msgStruct;
 	DWORD dwContextIndex;
 
 	PROFILE_START
 
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
+	DBG(hContext, NULL, "SCardReleaseContext()/\n");
+
+	SYS_MutexLock(&contextMutex);
 	/*
 	 * Make sure this context has been opened
 	 */
 	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	if (dwContextIndex == -1) {
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+
+	Log3(PCSC_LOG_DEBUG, "Release: context:%x, fd=%d\n", hContext,
+		psContextMap[dwContextIndex].dwClientID);
+
+	if (SCardCheckDaemonAvailability(
+		psContextMap[dwContextIndex].dwClientID) != SCARD_S_SUCCESS) {
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
 
 	scReleaseStruct.hContext = hContext;
 	scReleaseStruct.rv = 0;
 
-	rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT, psContextMap[dwContextIndex].dwClientID,
-			  sizeof(scReleaseStruct),
-			  PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_E_NO_SERVICE;
-	}
-
-	/*
-	 * Read a message from the server
-	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-	memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_F_COMM_ERROR;
-	}
-	
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	if ((rv = SHMrpc(SCARD_RELEASE_CONTEXT,
+			 psContextMap[dwContextIndex].dwClientID,
+			 &scReleaseStruct, sizeof (scReleaseStruct))) == -1) {
+				Log1(PCSC_LOG_INFO, "SCardReleaseContext(): SHMrpc() returned error");
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				SYS_MutexUnLock(&contextMutex);
+				return SCARD_F_COMM_ERROR;
+	}
 
 	/*
 	 * Remove the local context from the stack
 	 */
-	SCardLockThread();
 	SCardRemoveContext(hContext);
-	SCardUnlockThread();
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	PROFILE_END
 
@@ -549,14 +763,14 @@
  * @deprecated
  * This function is not in Microsoft(R) WinSCard API and is deprecated
  * in pcsc-lite API.
- * The function does not do anything except returning \c SCARD_S_SUCCESS. 
+ * The function does not do anything except returning \c SCARD_S_SUCCESS.
  *
  * @param[in] hContext Connection context to the PC/SC Resource Manager.
  * @param[in] dwTimeout New timeout value.
  *
  * @return Error code.
  * @retval SCARD_S_SUCCESS Successful.
- */ 
+ */
 LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
 {
 	/*
@@ -567,8 +781,8 @@
 }
 
 /**
- * This function establishes a connection to the friendly name of the reader 
- * specified in szReader. The first connection will power up and perform a 
+ * This function establishes a connection to the friendly name of the reader
+ * specified in szReader. The first connection will power up and perform a
  * reset on the card.
  *
  * @param[in] hContext Connection context to the PC/SC Resource Manager.
@@ -588,8 +802,8 @@
  *   <li>SCARD_PROTOCOL_T1 - Use the T=1 protocol.
  *   <li>SCARD_PROTOCOL_RAW - Use with memory type cards.
  * </ul>
- * dwPreferredProtocols is a bit mask of acceptable protocols for the 
- * connection. You can use (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if you 
+ * dwPreferredProtocols is a bit mask of acceptable protocols for the
+ * connection. You can use (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) if you
  * do not have a preferred protocol.
  * @param[out] phCard Handle to this connection.
  * @param[out] pdwActiveProtocol Established protocol to this connection.
@@ -601,7 +815,7 @@
  * @retval SCARD_E_NOT_READY Could not allocate the desired port.
  * @retval SCARD_E_READER_UNAVAILABLE Could not power up the reader or card.
  * @retval SCARD_E_SHARING_VIOLATION Someone else has exclusive rights.
- * @retval SCARD_E_UNSUPPORTED_FEATURE Protocol not supported.
+ * @retval SCARD_E_UNSUPPORTED_FEATURE Protocol not supged.
  *
  * @test
  * @code
@@ -611,7 +825,8 @@
  * LONG rv;
  * ...
  * rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
- * rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
+ * rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
+      SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
  * @endcode
  */
 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
@@ -620,47 +835,60 @@
 {
 	LONG rv;
 	connect_struct scConnectStruct;
-	sharedSegmentMsg msgStruct;
 	DWORD dwContextIndex;
 
 	PROFILE_START
 
+	DBG(hContext, NULL, "SCardConnect()/\n");
 	/*
 	 * Check for NULL parameters
 	 */
-	if (phCard == NULL || pdwActiveProtocol == NULL)
+	if (phCard == NULL || pdwActiveProtocol == NULL) {
+		DBGERR("SCardConnect(SCARD_E_INVALID_PARAMETER)\n");
 		return SCARD_E_INVALID_PARAMETER;
-	else
+	} else
 		*phCard = 0;
 
-	if (szReader == NULL)
+	if (szReader == NULL) {
+		DBGERR("SCardConnect(SCARD_E_UNKNOWN_READER)\n");
 		return SCARD_E_UNKNOWN_READER;
-
+	}
 	/*
 	 * Check for uninitialized strings
 	 */
-	if (strlen(szReader) > MAX_READERNAME)
+	if (strlen(szReader) > MAX_READERNAME) {
+		DBGERR("SCardConnect(MAX_READERNAME)\n");
 		return SCARD_E_INVALID_VALUE;
+	}
 
 	if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
 		!(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
 		!(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
 		!(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
 	{
+		DBGERR("SCardConnect(SCARD_E_INVALID_VALUE)\n");
 		return SCARD_E_INVALID_VALUE;
 	}
 
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
+	SYS_MutexLock(&contextMutex);
 	/*
 	 * Make sure this context has been opened
 	 */
 	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
-		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	if (dwContextIndex == -1) {
+	    DBGERR("SCardConnect(SCARD_E_INVALID_HANDLE)\n");
+	    SYS_MutexUnLock(&contextMutex);
+	    return SCARD_E_INVALID_HANDLE;
+	}
+
+	if (SCardCheckDaemonAvailability(
+	    psContextMap[dwContextIndex].dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardConnect(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	strncpy(scConnectStruct.szReader, szReader, MAX_READERNAME);
 
@@ -670,27 +898,12 @@
 	scConnectStruct.phCard = *phCard;
 	scConnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
 
-	rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
-		sizeof(scConnectStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_E_NO_SERVICE;
-	}
-
-	/*
-	 * Read a message from the server
-	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_F_COMM_ERROR;
+	if ((rv = SHMrpc(SCARD_CONNECT,
+	    psContextMap[dwContextIndex].dwClientID,
+	    &scConnectStruct, sizeof (scConnectStruct))) == -1) {
+		    Log1(PCSC_LOG_INFO, "SCardConnect(): SHMrpc() returned error");
+		    SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		    return SCARD_F_COMM_ERROR;
 	}
 
 	*phCard = scConnectStruct.phCard;
@@ -702,27 +915,28 @@
 		 * Keep track of the handle locally
 		 */
 		rv = SCardAddHandle(*phCard, dwContextIndex, (LPSTR) szReader);
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 		PROFILE_END
-
+		DBGERR("SCardConnect(%lx)\n", rv);
 		return rv;
 	}
 
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END
 
+	DBGERR("SCardConnect(%lx)\n", rv);
 	return scConnectStruct.rv;
 }
 
 /**
- * @brief This function reestablishes a connection to a reader that was previously 
+ * @brief This function reestablishes a connection to a reader that was previously
  * connected to using SCardConnect().
  *
  * In a multi application environment it is possible for an application to reset
- * the card in shared mode. When this occurs any other application trying to 
- * access certain commands will be returned the value SCARD_W_RESET_CARD. When 
+ * the card in shared mode. When this occurs any other application trying to
+ * access certain commands will be returned the value SCARD_W_RESET_CARD. When
  * this occurs SCardReconnect() must be called in order to acknowledge that
  * the card was reset and allow it to change it's state accordingly.
  *
@@ -736,9 +950,9 @@
  * <ul>
  *   <li>SCARD_PROTOCOL_T0 - Use the T=0 protocol.
  *   <li>SCARD_PROTOCOL_T1 - Use the T=1 protocol.
- *   <li>SCARD_PROTOCOL_RAW - Use with memory type cards. 
+ *   <li>SCARD_PROTOCOL_RAW - Use with memory type cards.
  * </ul>
- * \p dwPreferredProtocols is a bit mask of acceptable protocols for 
+ * \p dwPreferredProtocols is a bit mask of acceptable protocols for
  * the connection. You can use (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
  * if you do not have a preferred protocol.
  * @param[in] dwInitialization Desired action taken on the card/reader.
@@ -787,17 +1001,19 @@
 {
 	LONG rv;
 	reconnect_struct scReconnectStruct;
-	sharedSegmentMsg msgStruct;
 	int i;
-	DWORD dwContextIndex, dwChannelIndex;
+	DWORD dwContextIndex, dwChannelIndex, dwClientID;
 
 	PROFILE_START
+
+	DBG(NULL, hCard, "SCardReconnect()/\n");
 
 	if (dwInitialization != SCARD_LEAVE_CARD &&
 		dwInitialization != SCARD_RESET_CARD &&
 		dwInitialization != SCARD_UNPOWER_CARD &&
 		dwInitialization != SCARD_EJECT_CARD)
 	{
+		DBGERR("SCardReconnect(SCARD_E_INVALID_VALUE)\n");
 		return SCARD_E_INVALID_VALUE;
 	}
 
@@ -806,38 +1022,54 @@
 		!(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
 		!(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
 	{
+		DBGERR("SCardReconnect(SCARD_E_INVALID_VALUE)\n");
 		return SCARD_E_INVALID_VALUE;
 	}
 
-	if (pdwActiveProtocol == NULL)
+	if (pdwActiveProtocol == NULL) {
+		DBGERR("SCardReconnect(SCARD_E_INVALID_PARAMETER)\n");
 		return SCARD_E_INVALID_PARAMETER;
-
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
+	}
+
+	SYS_MutexLock(&contextMutex);
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
-
-	if (rv == -1)
+	rv = SCardGetIndicesFromHandle(
+		hCard, &dwContextIndex, &dwChannelIndex, &dwClientID);
+
+	if (SCardCheckDaemonAvailability(dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardReconnect(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	if (rv == -1) {
+		DBGERR("SCardReconnect(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
-
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, prs->readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardReconnect(SCARD_E_READER_UNAVAILABLE)\n");
 		return SCARD_E_READER_UNAVAILABLE;
 	}
 
@@ -847,40 +1079,26 @@
 	scReconnectStruct.dwInitialization = dwInitialization;
 	scReconnectStruct.pdwActiveProtocol = *pdwActiveProtocol;
 
-	rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
-		sizeof(scReconnectStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_E_NO_SERVICE;
-	}
-
-	/*
-	 * Read a message from the server
-	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_F_COMM_ERROR;
+	if ((rv = SHMrpc(SCARD_RECONNECT,
+			 psContextMap[dwContextIndex].dwClientID,
+			 &scReconnectStruct, sizeof (scReconnectStruct))) == -1) {
+				Log1(PCSC_LOG_INFO, "SCardRecoonnect(): SHMrpc() returned error");
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				return SCARD_F_COMM_ERROR;
 	}
 
 	*pdwActiveProtocol = scReconnectStruct.pdwActiveProtocol;
 
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END
-	
+
+	DBGERR("SCardReconnect(%lx)\n", scReconnectStruct.rv);
 	return scReconnectStruct.rv;
 }
 
 /**
- * This function terminates a connection to the connection made through 
+ * This function terminates a connection to the connection made through
  * SCardConnect(). dwDisposition can have the following values:
  *
  * @param[in] hCard Connection made from SCardConnect.
@@ -896,7 +1114,7 @@
  * @retval SCARD_S_SUCCESS Successful.
  * @retval SCARD_E_INVALID_HANDLE Invalid \p hCard handle.
  * @retval SCARD_E_INVALID_VALUE - Invalid \p dwDisposition.
- * 
+ *
  * @test
  * @code
  * SCARDCONTEXT hContext;
@@ -913,65 +1131,59 @@
 {
 	LONG rv;
 	disconnect_struct scDisconnectStruct;
-	sharedSegmentMsg msgStruct;
-	DWORD dwContextIndex, dwChannelIndex;
+	DWORD dwContextIndex, dwChannelIndex, dwClientID;
 
 	PROFILE_START
+	DBG(NULL, hCard, "SCardDisconnect()/\n");
 
 	if (dwDisposition != SCARD_LEAVE_CARD &&
 		dwDisposition != SCARD_RESET_CARD &&
 		dwDisposition != SCARD_UNPOWER_CARD &&
 		dwDisposition != SCARD_EJECT_CARD)
 	{
+		DBGERR("SCardDisconnect(SCARD_E_INVALID_VALUE)\n");
 		return SCARD_E_INVALID_VALUE;
 	}
 
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
+	SYS_MutexLock(&contextMutex);
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
-
-	if (rv == -1)
+	rv = SCardGetIndicesFromHandle(
+		hCard, &dwContextIndex, &dwChannelIndex, &dwClientID);
+
+	if (SCardCheckDaemonAvailability(dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardDisconnect(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	if (rv == -1) {
+		DBGERR("SCardReconnect(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	scDisconnectStruct.hCard = hCard;
 	scDisconnectStruct.dwDisposition = dwDisposition;
 
-	rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
-		sizeof(scDisconnectStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_E_NO_SERVICE;
-	}
-
-	/*
-	 * Read a message from the server
-	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scDisconnectStruct, &msgStruct.data,
-		sizeof(scDisconnectStruct));
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_F_COMM_ERROR;
+	if ((rv = SHMrpc(SCARD_DISCONNECT,
+			psContextMap[dwContextIndex].dwClientID,
+			&scDisconnectStruct, sizeof (scDisconnectStruct))) == -1 ) {
+				Log1(PCSC_LOG_INFO, "SCardDisconnect(): SHMrpc() returned error");
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				return SCARD_F_COMM_ERROR;
 	}
 
 	SCardRemoveHandle(hCard);
 
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END
 
+	DBGERR("SCardDisconnects(%lx)\n", scDisconnectStruct.rv);
 	return scDisconnectStruct.rv;
 }
 
@@ -982,7 +1194,7 @@
  * You might want to use this when you are selecting a few files and then
  * writing a large file so you can make sure that another application will
  * not change the current file. If another application has a lock on this
- * reader or this application is in \c SCARD_SHARE_EXCLUSIVE there will be no 
+ * reader or this application is in \c SCARD_SHARE_EXCLUSIVE there will be no
  * action taken.
  *
  * @param[in] hCard Connection made from SCardConnect.
@@ -992,7 +1204,7 @@
  * @retval SCARD_E_INVALID_HANDLE Invalid hCard handle.
  * @retval SCARD_E_SHARING_VIOLATION Someone else has exclusive rights.
  * @retval SCARD_E_READER_UNAVAILABLE The reader has been removed.
- * 
+ *
  * @test
  * @code
  * SCARDCONTEXT hContext;
@@ -1013,112 +1225,125 @@
 	LONG rv;
 	begin_struct scBeginStruct;
 	int i;
-	sharedSegmentMsg msgStruct;
-	DWORD dwContextIndex, dwChannelIndex;
+	DWORD dwContextIndex, dwChannelIndex, dwClientID;
 
 	PROFILE_START
 
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
+	DBG(NULL, hCard, "SCardBeginTransaction()/\n");
+	SYS_MutexLock(&contextMutex);
 
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
-
-	if (rv == -1)
+	rv = SCardGetIndicesFromHandle(
+		hCard, &dwContextIndex, &dwChannelIndex, &dwClientID);
+
+	if (SCardCheckDaemonAvailability(dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardReconnect(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	if (rv == -1) {
+		DBGERR("SCardReconnect(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r &&
+		    strcmp(r, prs->readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardBeginTransaction(SCARD_E_READER_UNAVAILABLE)\n");
 		return SCARD_E_READER_UNAVAILABLE;
 	}
 
 	scBeginStruct.hCard = hCard;
-
 	/*
 	 * Query the server every so often until the sharing violation ends
 	 * and then hold the lock for yourself.
 	 */
-
 	do
 	{
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
+
 		/*
 		 * Look to see if it is locked before polling the server for
 		 * admission to the readers resources
 		 */
-		if ((readerStates[i])->lockState != 0)
+		if (prs->lockState != 0)
 		{
 			int randnum = 0;
 			int j;
 
 			for (j = 0; j < 100; j++)
 			{
-				/*
-				 * This helps prevent starvation
-				 */
-				randnum = SYS_RandomInt(1000, 10000);
-				SYS_USleep(randnum);
-
-				if ((readerStates[i])->lockState == 0)
-				{
+			       SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			       randnum = SYS_RandomInt(1000, 10000);
+			       SYS_USleep(randnum);
+			       SYS_MutexLock(&contextMutex);
+			       /*
+				* Make sure this handle has been opened
+			       */
+			       rv = SCardGetIndicesFromHandle(
+				       hCard, &dwContextIndex,
+				       &dwChannelIndex, &dwClientID);
+
+			       if (rv == -1) {
+				       DBGERR("SCardReconnect(SCARD_E_INVALID_HANDLE)\n");
+				       SYS_MutexUnLock(&contextMutex);
+				       return SCARD_E_INVALID_HANDLE;
+			       }
+
+			       SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+			       SYS_MutexUnLock(&contextMutex);
+
+			       if (prs->lockState == 0)
 					break;
-				}
 			}
 		}
 
-		rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
-			sizeof(scBeginStruct),
-			PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
-
-		if (rv == -1)
-		{
-			
-			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-			return SCARD_E_NO_SERVICE;
-		}
-
-		/*
-		 * Read a message from the server
-		 */
-		rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-
-		memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
-
-		if (rv == -1)
-		{
-			
-			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-			return SCARD_F_COMM_ERROR;
-		}
-
+		if ((rv = SHMrpc(SCARD_BEGIN_TRANSACTION,
+				psContextMap[dwContextIndex].dwClientID,
+				&scBeginStruct, sizeof (scBeginStruct))) == -1) {
+					Log1(PCSC_LOG_INFO, "SCardBeginTransaction(): SHMrpc() returned error");
+					SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+					return SCARD_F_COMM_ERROR;
+		}
 	}
 	while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
-
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 	PROFILE_END
 
+	DBGERR("SCardBeginTransaction(%lx)\n", scBeginStruct.rv);
 	return scBeginStruct.rv;
 }
 
 /**
  * @brief This function ends a previously begun transaction.
  *
- * The calling application must be the owner of the previously begun 
+ * The calling application must be the owner of the previously begun
  * transaction or an error will occur.
  *
  * @param[in] hCard Connection made from SCardConnect.
@@ -1150,19 +1375,19 @@
  * ...
  * / * Do some transmit commands * /
  * ...
- * rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); 
+ * rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
  * @endcode
  */
 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
 {
 	LONG rv;
 	end_struct scEndStruct;
-	sharedSegmentMsg msgStruct;
 	int randnum, i;
-	DWORD dwContextIndex, dwChannelIndex;
+	DWORD dwContextIndex, dwChannelIndex, dwClientID;
 
 	PROFILE_START
 
+	DBG(NULL, hCard, "SCardEndTransaction()/\n");
 	/*
 	 * Zero out everything
 	 */
@@ -1173,73 +1398,73 @@
 		dwDisposition != SCARD_UNPOWER_CARD &&
 		dwDisposition != SCARD_EJECT_CARD)
 	{
+		DBGERR("SCardEndTransaction(SCARD_E_INVALID_VALUE)\n");
 		return SCARD_E_INVALID_VALUE;
 	}
 
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
+	SYS_MutexLock(&contextMutex);
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
-
-	if (rv == -1)
+	rv = SCardGetIndicesFromHandle(
+		hCard, &dwContextIndex, &dwChannelIndex, &dwClientID);
+
+	if (SCardCheckDaemonAvailability(dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardReconnect(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	if (rv == -1) {
+		DBGERR("SCardReconnect(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, prs->readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardEndTransaction(SCARD_E_READER_UNAVAILABLE)\n");
 		return SCARD_E_READER_UNAVAILABLE;
 	}
 
 	scEndStruct.hCard = hCard;
 	scEndStruct.dwDisposition = dwDisposition;
 
-	rv = WrapSHMWrite(SCARD_END_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
-		sizeof(scEndStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_E_NO_SERVICE;
-	}
-
-	/*
-	 * Read a message from the server
-	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_F_COMM_ERROR;
-	}
-
+	if ((rv = SHMrpc(SCARD_END_TRANSACTION,
+			psContextMap[dwContextIndex].dwClientID,
+			&scEndStruct, sizeof (scEndStruct))) == -1) {
+				Log1(PCSC_LOG_INFO, "SCardEndTransaction(): SHMrpc() returned error");
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				return SCARD_F_COMM_ERROR;
+	}
 	/*
 	 * This helps prevent starvation
 	 */
 	randnum = SYS_RandomInt(1000, 10000);
 	SYS_USleep(randnum);
 
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END
 
+	DBGERR("SCardEndTransaction(%lx)\n", scEndStruct.rv);
 	return scEndStruct.rv;
 }
 
@@ -1252,69 +1477,68 @@
 {
 	LONG rv;
 	cancel_struct scCancelStruct;
-	sharedSegmentMsg msgStruct;
 	int i;
-	DWORD dwContextIndex, dwChannelIndex;
+	DWORD dwContextIndex, dwChannelIndex, dwClientID;
 
 	PROFILE_START
 
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
+	DBG(NULL, hCard, "SCancelTransaction()/\n");
+	SYS_MutexLock(&contextMutex);
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
-
-	if (rv == -1)
+	rv = SCardGetIndicesFromHandle(
+		hCard, &dwContextIndex, &dwChannelIndex, &dwClientID);
+
+	if (SCardCheckDaemonAvailability(dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardReconnect(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	if (rv == -1) {
+		DBGERR("SCardReconnect(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
-
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r &&  strcmp(r, prs->readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardCancelTransaction(SCARD_E_READER_UNAVAILABLE)\n");
 		return SCARD_E_READER_UNAVAILABLE;
 	}
 
 	scCancelStruct.hCard = hCard;
 
-	rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
-		sizeof(scCancelStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_E_NO_SERVICE;
-	}
-
-	/*
-	 * Read a message from the server
-	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_F_COMM_ERROR;
-	}
-
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	if ((rv = SHMrpc(SCARD_CANCEL_TRANSACTION,
+			psContextMap[dwContextIndex].dwClientID,
+			&scCancelStruct, sizeof (scCancelStruct))) == -1) {
+				Log1(PCSC_LOG_INFO, "SCardCancelTransaction(): SHMrpc() returned error");
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				return SCARD_F_COMM_ERROR;
+	}
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END
 
+	DBGERR("SCardCancelTransaction(%lx)\n", scCancelStruct.rv);
 	return scCancelStruct.rv;
 }
 
@@ -1339,7 +1563,7 @@
  *                       moved into position for use.
  *   <li>SCARD_SWALLOWED - There is a card in the reader in position for use.
  *                         The card is not powered.
- *   <li>SCARD_POWERED - Power is being provided to the card, but the reader 
+ *   <li>SCARD_POWERED - Power is being provided to the card, but the reader
  *                       driver is unaware of the mode of the card.
  *   <li>SCARD_NEGOTIABLE - The card has been reset and is awaiting PTS negotiation.
  *   <li>SCARD_SPECIFIC - The card has been reset and specific communication
@@ -1382,17 +1606,20 @@
 	LONG rv;
 	int i;
 	status_struct scStatusStruct;
-	sharedSegmentMsg msgStruct;
-	DWORD dwContextIndex, dwChannelIndex;
+	DWORD dwContextIndex, dwChannelIndex, dwClientID;
 
 	PROFILE_START
+
+	DBG(NULL, hCard, "SCardStatus()\n");
 
 	/*
 	 * Check for NULL parameters
 	 */
 
-	if (pcchReaderLen == NULL || pcbAtrLen == NULL)
+	if (pcchReaderLen == NULL || pcbAtrLen == NULL) {
+		DBGERR("SCardStatus(SCARD_E_INVALID_PARAMETER)\n");
 		return SCARD_E_INVALID_PARAMETER;
+	}
 
 	/* length passed from caller */
 	dwReaderLen = *pcchReaderLen;
@@ -1407,32 +1634,45 @@
 
 	*pcchReaderLen = 0;
 	*pcbAtrLen = 0;
-
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
+	SYS_MutexLock(&contextMutex);
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
-
-	if (rv == -1)
+	rv = SCardGetIndicesFromHandle(
+		hCard, &dwContextIndex, &dwChannelIndex, &dwClientID);
+
+	if (SCardCheckDaemonAvailability(dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardReconnect(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	if (rv == -1) {
+		DBGERR("SCardReconnect(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
-
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, prs->readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardStatus(SCARD_E_READER_UNAVAILABLE)\n");
 		return SCARD_E_READER_UNAVAILABLE;
 	}
 
@@ -1444,27 +1684,12 @@
 	scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
 	scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
 
-	rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
-		sizeof(scStatusStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_E_NO_SERVICE;
-	}
-
-	/*
-	 * Read a message from the server
-	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_F_COMM_ERROR;
+	if ((rv = SHMrpc(SCARD_STATUS,
+			psContextMap[dwContextIndex].dwClientID,
+			&scStatusStruct, sizeof (scStatusStruct))) == -1) {
+				Log1(PCSC_LOG_INFO, "SCardStatus() :SHMrpc() returned error");
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				return SCARD_F_COMM_ERROR;
 	}
 
 	rv = scStatusStruct.rv;
@@ -1473,7 +1698,8 @@
 		/*
 		 * An event must have occurred
 		 */
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardStatus(%lx)\n", rv);
 		return rv;
 	}
 
@@ -1482,45 +1708,64 @@
 	 */
 
 	*pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
-	*pcbAtrLen = (readerStates[i])->cardAtrLength;
-
-	if (pdwState)
-		*pdwState = (readerStates[i])->readerState;
-
-	if (pdwProtocol)
-		*pdwProtocol = (readerStates[i])->cardProtocol;
-
+	{
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
+
+		*pcbAtrLen = prs->cardAtrLength;
+		if (pdwState) {
+			*pdwState = prs->readerState;
+#ifdef EXTRA_DEBUGGING
+			CFGdumpReaderState(*pdwState);
+#endif
+		}
+		if (pdwProtocol)
+			*pdwProtocol = prs->cardProtocol;
+
+	}
 	/* return SCARD_E_INSUFFICIENT_BUFFER only if buffer pointer is non NULL */
 	if (mszReaderNames)
 	{
 		if (*pcchReaderLen > dwReaderLen)
 			rv = SCARD_E_INSUFFICIENT_BUFFER;
 
-		strncpy(mszReaderNames, 
-			psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName, 
+		strncpy(mszReaderNames,
+			psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName,
 			dwReaderLen);
 	}
 
 	if (pbAtr)
 	{
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
+
 		if (*pcbAtrLen > dwAtrLen)
 			rv = SCARD_E_INSUFFICIENT_BUFFER;
 
-		memcpy(pbAtr, (readerStates[i])->cardAtr,
-			min(*pcbAtrLen, dwAtrLen));
-	}
-	
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		memcpy(pbAtr, prs->cardAtr, min(*pcbAtrLen, dwAtrLen));
+	}
+
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END
 
+#ifdef EXTRA_DEBUGGING
+	CFGdumpEventState(*pdwState);
+#endif
+	DBGERR("SCardStatus(%lx)\n", rv);
 	return rv;
 }
 
 /**
  * @brief This function receives a structure or list of structures containing
  * reader names. It then blocks for a change in state to occur on any of the
- * OR'd values contained in dwCurrentState for a maximum blocking time of 
+ * OR'd values contained in dwCurrentState for a maximum blocking time of
  * dwTimeout or forever if INFINITE is used.
  *
  * The new event state will be contained in dwEventState. A status change might
@@ -1545,7 +1790,7 @@
  *
  * Value of dwCurrentState and dwEventState:
  * <ul>
- *   <li>SCARD_STATE_UNAWARE The application is unaware of the current 
+ *   <li>SCARD_STATE_UNAWARE The application is unaware of the current
  *       state, and would like to know. The use of this value results in an
  *       immediate return from state transition monitoring services. This is
  *       represented by all bits set to zero.
@@ -1567,7 +1812,7 @@
  *       \c SCARD_STATE_PRESENT will also be set. This bit is only returned on
  *       the \c SCardLocateCards function.
  *   <li>SCARD_STATE_EXCLUSIVE The card in the reader is allocated for
- *       exclusive use by another application. If this bit is set, 
+ *       exclusive use by another application. If this bit is set,
  *       \c SCARD_STATE_PRESENT will also be set.
  *   <li>SCARD_STATE_INUSE The card in the reader is in use by one or more
  *       other applications, but may be connected to in shared mode. If this
@@ -1602,6 +1847,8 @@
  * printf("reader state: 0x%04X\n", rgReaderStates[0].dwEventState);
  * @endcode
  */
+
+
 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
 	LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
 {
@@ -1611,29 +1858,45 @@
 	DWORD dwState;
 	DWORD dwBreakFlag = 0;
 	int j;
-	DWORD dwContextIndex;
+	DWORD dwContextIndex, dwClientID;
 	int currentReaderCount = 0;
 
 	PROFILE_START
-
-	if (rgReaderStates == NULL && cReaders > 0)
+	DBG(hContext, NULL, "SCardGetStatusChange()/\n");
+
+	if (rgReaderStates == NULL && cReaders > 0) {
+		DBGERR("SCardGetStatusChange(SCARD_E_INVALID_PARAMETER)\n");
 		return SCARD_E_INVALID_PARAMETER;
-
-	if (cReaders < 0)
+	}
+
+	if (cReaders < 0) {
+		DBGERR("SCardGetStatusChange(SCARD_E_INVALID_VALUE)\n");
 		return SCARD_E_INVALID_VALUE;
-
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
+	}
 
 	/*
 	 * Make sure this context has been opened
 	 */
+	SYS_MutexLock(&contextMutex);
 
 	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	if (dwContextIndex == -1) {
+		DBGERR("SCardGetStatusChange(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+
+	if (SCardCheckDaemonAvailability(
+	    psContextMap[dwContextIndex].dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardGetStatusChange(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	dwClientID = psContextMap[dwContextIndex].dwClientID;
+
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	/*
 	 * Application is waiting for a reader - return the first available
@@ -1642,27 +1905,41 @@
 
 	if (cReaders == 0)
 	{
+		psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
 		while (1)
 		{
 			int i;
 
-			if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
+			if (psContextMap[dwContextIndex].contextBlockStatus == BLOCK_STATUS_RESUME) {
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				DBGERR("SCardGetStatusChange(SCARD_E_CANCELLED)\n");
+				return SCARD_E_CANCELLED;
+			}
+
+			if (SCardCheckDaemonAvailability(
+			    psContextMap[dwContextIndex].dwClientID) != SCARD_S_SUCCESS)
 			{
-				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				DBGERR("SCardGetStatusChange(SCARD_E_NO_SERVICE)\n");
 				return SCARD_E_NO_SERVICE;
 			}
 
 			for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 			{
-				if ((readerStates[i])->readerID != 0)
+				PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+				if (prs == NULL) {
+					SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+					return SCARD_E_READER_UNAVAILABLE;
+				}
+				if (prs->readerID != 0)
 				{
 					/*
 					 * Reader was found
 					 */
-					SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+					SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 					PROFILE_END
-
+					DBGERR("SCardGetStatusChange(SCARD_S_SUCCESS)\n");
 					return SCARD_S_SUCCESS;
 				}
 			}
@@ -1672,11 +1949,13 @@
 				/*
 				 * return immediately - no reader available
 				 */
-				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				DBGERR("SCardGetStatusChange(SCARD_E_READER_UNAVAILABLE)\n");
 				return SCARD_E_READER_UNAVAILABLE;
 			}
 
 			SYS_USleep(PCSCLITE_STATUS_WAIT);
+
 
 			if (dwTimeout != INFINITE)
 			{
@@ -1684,10 +1963,10 @@
 
 				if (dwTime >= (dwTimeout * 1000))
 				{
-					SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+					SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 					PROFILE_END
-
+					DBGERR("SCardGetStatusChange(SCARD_E_TIMEOUT)\n");
 					return SCARD_E_TIMEOUT;
 				}
 			}
@@ -1696,7 +1975,8 @@
 	else
 		if (cReaders >= PCSCLITE_MAX_READERS_CONTEXTS)
 		{
-			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			DBGERR("SCardGetStatusChange(SCARD_E_INVALID_VALUE)\n");
 			return SCARD_E_INVALID_VALUE;
 		}
 
@@ -1707,10 +1987,9 @@
 	for (j = 0; j < cReaders; j++)
 	{
 		currReader = &rgReaderStates[j];
-
 		if (currReader->szReader == NULL)
 		{
-			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 			return SCARD_E_INVALID_VALUE;
 		}
 	}
@@ -1737,9 +2016,15 @@
 	psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;
 
 	/* Get the initial reader count on the system */
-	for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
-		if ((readerStates[j])->readerID != 0)
+	for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++) {
+		PREADER_STATE prs = FETCH(readerStates[j], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
+		if (prs->readerID != 0)
 			currentReaderCount++;
+	}
 
 	j = 0;
 
@@ -1748,26 +2033,31 @@
 		int newReaderCount = 0;
 		char ReaderCountChanged = FALSE;
 
-		if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
+		if (SCardCheckDaemonAvailability(
+			psContextMap[dwContextIndex].dwClientID) != SCARD_S_SUCCESS)
 		{
-			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-	
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+
 			PROFILE_END
-
+			DBGERR("SCardGetStatusChange(SCARD_E_NO_SERVICE)\n");
 			return SCARD_E_NO_SERVICE;
 		}
 
 		if (j == 0)
 		{
 			int i;
-
-			for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
-				if ((readerStates[i])->readerID != 0)
+			for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) {
+				PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+				if (prs == NULL) {
+					SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+					return SCARD_E_READER_UNAVAILABLE;
+				}
+				if (prs->readerID != 0)
 					newReaderCount++;
-
+			}
 			if (newReaderCount != currentReaderCount)
 			{
-				Log1(PCSC_LOG_INFO, "Reader list changed");
+				Log1(PCSC_LOG_DEBUG, "Reader list changed");
 				ReaderCountChanged = TRUE;
 				currentReaderCount = newReaderCount;
 			}
@@ -1790,8 +2080,12 @@
 
 			for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 			{
-				if (strcmp(lpcReaderName,
-						(readerStates[i])->readerName) == 0)
+				PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+				if (prs == NULL) {
+					SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+					return SCARD_E_READER_UNAVAILABLE;
+				}
+				if (strcmp(lpcReaderName, prs->readerName) == 0)
 				{
 					break;
 				}
@@ -1834,8 +2128,11 @@
 				/*
 				 * Set the reader status structure
 				 */
-				rContext = readerStates[i];
-
+				rContext = FETCH(readerStates[i], dwClientID);
+				if (rContext == NULL) {
+					SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+					return SCARD_E_READER_UNAVAILABLE;
+				}
 				/*
 				 * Now we check all the Reader States
 				 */
@@ -1956,7 +2253,7 @@
 							}
 							dwBreakFlag = 1;
 						}
-					} else
+					}
 					{
 						/*
 						 * App thinks card is mute but it is not
@@ -2053,7 +2350,7 @@
 		 */
 
 		if (psContextMap[dwContextIndex].contextBlockStatus ==
-			BLOCK_STATUS_RESUME)
+		    BLOCK_STATUS_RESUME)
 			break;
 
 		/*
@@ -2076,7 +2373,8 @@
 			 */
 			if ((dwTime >= (dwTimeout * 1000)) && (j == 0))
 			{
-				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				DBGERR("SCardGetStatusChange(SCARD_E_TIMEOUT)\n");
 				return SCARD_E_TIMEOUT;
 			}
 		}
@@ -2097,14 +2395,19 @@
 	if (psContextMap[dwContextIndex].contextBlockStatus ==
 			BLOCK_STATUS_RESUME)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardGetStatusChange(SCARD_E_CANCELLED)\n");
 		return SCARD_E_CANCELLED;
 	}
 
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+
 
 	PROFILE_END
-
+#ifdef EXTRA_DEBUGGING
+	CFGdumpEventState(currReader->dwEventState);
+#endif
+	DBGERR("SCardGetStatusChange(SCARD_S_SUCCESS)\n");
 	return SCARD_S_SUCCESS;
 }
 
@@ -2116,13 +2419,13 @@
  * PIN pads, biometrics, or other extensions to the normal smart card reader
  * that are not normally handled by PC/SC.
  *
- * @note the API of this function changed. In pcsc-lite 1.2.0 and before the 
+ * @note the API of this function changed. In pcsc-lite 1.2.0 and before the
  * API was not Windows(R) PC/SC compatible. This has been corrected.
  *
  * @param[in] hCard Connection made from SCardConnect.
  * @param[in] dwControlCode Control code for the operation.\n
  * <a href="http://pcsclite.alioth.debian.org/pcsc-lite/node26.html#Some_SCardControl_commands">
- * Click here</a> for a list of supported commands by some drivers. 
+ * Click here</a> for a list of supported commands by some drivers.
  * @param[in] pbSendBuffer Command to send to the reader.
  * @param[in] cbSendLength Length of the command.
  * @param[out] pbRecvBuffer Response from the reader.
@@ -2153,7 +2456,7 @@
  * dwRecvLength = sizeof(pbRecvBuffer);
  * rv = SCardControl(hCard, 0x42000001, pbSendBuffer, dwSendLength, pbRecvBuffer, sizeof(pbRecvBuffer), &dwRecvLength);
  * @endcode
- */ 
+ */
 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
 	DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
 	LPDWORD lpBytesReturned)
@@ -2162,45 +2465,62 @@
 	control_struct scControlStruct;
 	sharedSegmentMsg msgStruct;
 	int i;
-	DWORD dwContextIndex, dwChannelIndex;
+	DWORD dwContextIndex, dwChannelIndex, dwClientID;
 
 	PROFILE_START
+	DBG(NULL, hCard, "SCardControl()/\n");
 
 	/* 0 bytes received by default */
 	if (NULL != lpBytesReturned)
 		*lpBytesReturned = 0;
 
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
+	SYS_MutexLock(&contextMutex);
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
-
-	if (rv == -1)
+	rv = SCardGetIndicesFromHandle(
+		hCard, &dwContextIndex, &dwChannelIndex, &dwClientID);
+
+	if (SCardCheckDaemonAvailability(dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardReconnect(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	if (rv == -1) {
+		DBGERR("SCardReconnect(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r &&  strcmp(r, prs->readerName) != 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardControl(SCARD_E_READER_UNAVAILABLE)\n");
 		return SCARD_E_READER_UNAVAILABLE;
 	}
 
 	if (cbSendLength > MAX_BUFFER_SIZE)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardControl(SCARD_E_INSUFFICIENT_BUFFER)\n");
 		return SCARD_E_INSUFFICIENT_BUFFER;
 	}
 
@@ -2210,27 +2530,16 @@
 	scControlStruct.cbRecvLength = cbRecvLength;
 	memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
 
-	rv = WrapSHMWrite(SCARD_CONTROL, psContextMap[dwContextIndex].dwClientID,
-		sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_E_NO_SERVICE;
-	}
-
-	/*
-	 * Read a message from the server
-	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_F_COMM_ERROR;
-	}
 
 	memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
+
+	if ((rv = SHMrpc(SCARD_CONTROL,
+			psContextMap[dwContextIndex].dwClientID,
+			&scControlStruct, sizeof (scControlStruct))) == -1) {
+				Log1(PCSC_LOG_INFO, "SCardControl(): SHMrpc() returned error");
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				return SCARD_F_COMM_ERROR;
+	}
 
 	if (NULL != lpBytesReturned)
 		*lpBytesReturned = scControlStruct.dwBytesReturned;
@@ -2246,15 +2555,16 @@
 			sizeof(scControlStruct.pbRecvBuffer));
 	}
 
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END
 
+	DBGERR("SCardControl(%lx)\n", scControlStruct.rv);
 	return scControlStruct.rv;
 }
 
 /**
- * This function get an attribute from the IFD Handler. The list of possible 
+ * This function get an attribute from the IFD Handler. The list of possible
  * attributes is available in the file \c pcsclite.h.
  *
  * @param[in] hCard Connection made from \c SCardConnect.
@@ -2305,9 +2615,9 @@
  *   <li>SCARD_ATTR_VENDOR_IFD_VERSION
  *   <li>SCARD_ATTR_VENDOR_NAME
  * </ul>
- * 
+ *
  * Not all the dwAttrId values listed above may be implemented in the IFD
- * Handler you are using. And some dwAttrId values not listed here may be 
+ * Handler you are using. And some dwAttrId values not listed here may be
  * implemented.
  *
  * @param[out] pbAttr Pointer to a buffer that receives the attribute.
@@ -2332,14 +2642,19 @@
  *                           SCARD_PROTOCOL_RAW &hCard, &dwActiveProtocol);
  * rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAtr, &dwAtrLen);
  * @endcode
- */ 
+ */
 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
 	LPDWORD pcbAttrLen)
 {
+	LONG rv;
 	PROFILE_START
 
-	if (NULL == pcbAttrLen)
+	DBG(NULL, hCard, "SCardGetAttrib()/\n");
+
+	if (NULL == pcbAttrLen) {
+		DBGERR("SCardGetAttrib(SCARD_E_INVALID_PARAMETER)\n");
 		return SCARD_E_INVALID_PARAMETER;
+	}
 
 	/* if only get the length */
 	if (NULL == pbAttr)
@@ -2348,8 +2663,13 @@
 
 	PROFILE_END
 
-	return SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, pbAttr,
+	rv = SCardGetSetAttrib(hCard, SCARD_GET_ATTRIB, dwAttrId, pbAttr,
 		pcbAttrLen);
+
+	DBGERR("SCardGetAttrib(%lx)\n", rv);
+
+	return rv;
+
 }
 
 /**
@@ -2362,7 +2682,7 @@
  * @param[in] dwAttrId Identifier for the attribute to set.
  * @param[in] pbAttr Pointer to a buffer that receives the attribute.
  * @param[in] cbAttrLen Length of the \p pbAttr buffer in bytes.
- * 
+ *
  * @return Error code
  * @retval SCARD_S_SUCCESS Successful.
  * @retval SCARD_E_NOT_TRANSACTED Data exchange not successful.
@@ -2386,14 +2706,17 @@
 	DWORD cbAttrLen)
 {
 	PROFILE_START
-
+	LONG rv;
+	DBG(NULL, hCard, "SCardSetAttrib()/\n");
 	if (NULL == pbAttr || 0 == cbAttrLen)
 		return SCARD_E_INVALID_PARAMETER;
 
 	PROFILE_END
 
-	return SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
+	rv = SCardGetSetAttrib(hCard, SCARD_SET_ATTRIB, dwAttrId, (LPBYTE)pbAttr,
 		&cbAttrLen);
+	DBGERR("SCardSetAttrib(%lx)\n", rv);
+	return rv;
 }
 
 static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
@@ -2403,41 +2726,58 @@
 
 	LONG rv;
 	getset_struct scGetSetStruct;
-	sharedSegmentMsg msgStruct;
 	int i;
-	DWORD dwContextIndex, dwChannelIndex;
-
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
+	DWORD dwContextIndex, dwChannelIndex, dwClientID;
+
+	DBG(NULL, hCard, "SCardGetSetAttrib()/\n");
+
+	SYS_MutexLock(&contextMutex);
 
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
-
-	if (rv == -1)
+	rv = SCardGetIndicesFromHandle(
+		hCard, &dwContextIndex, &dwChannelIndex, &dwClientID);
+
+	if (SCardCheckDaemonAvailability(dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardReconnect(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	if (rv == -1) {
+		DBGERR("SCardReconnect(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
-
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r &&  strcmp(r, prs->readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardGetSetAttrib(SCARD_E_READER_UNAVAILABLE)\n");
 		return SCARD_E_READER_UNAVAILABLE;
 	}
 
 	if (*pcbAttrLen > MAX_BUFFER_SIZE)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardGetSetAttrib(SCARD_E_INSUFFICIENT_BUFFER)\n");
 		return SCARD_E_INSUFFICIENT_BUFFER;
 	}
 
@@ -2448,28 +2788,14 @@
 	if (SCARD_SET_ATTRIB == command)
 		memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
 
-	rv = WrapSHMWrite(command,
-		psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_E_NO_SERVICE;
-	}
-
-	/*
-	 * Read a message from the server
-	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-	if (rv == -1)
-	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-		return SCARD_F_COMM_ERROR;
-	}
-
-	memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
+
+	if ((rv = SHMrpc(command,
+			psContextMap[dwContextIndex].dwClientID,
+			&scGetSetStruct, sizeof (scGetSetStruct))) == -1) {
+				Log1(PCSC_LOG_INFO, "SCardGetSetAttrib(): SHMrpc() returned error");
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				return SCARD_F_COMM_ERROR;
+	}
 
 	if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
 	{
@@ -2490,10 +2816,10 @@
 		memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
 	}
 
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END
-
+	DBGERR("SCardGetSetAttrib(%lx)\n",scGetSetStruct.rv);
 	return scGetSetStruct.rv;
 }
 
@@ -2502,7 +2828,7 @@
  * connected to by SCardConnect().
  *
  * The card responds from the APDU and stores this response in pbRecvBuffer
- * and it's length in SpcbRecvLength. 
+ * and it's length in SpcbRecvLength.
  * SSendPci and SRecvPci are structures containing the following:
  * @code
  * typedef struct {
@@ -2510,7 +2836,7 @@
  *    DWORD cbPciLength;   // Length of this structure - not used
  * } SCARD_IO_REQUEST;
  * @endcode
- * 
+ *
  * @param[in] hCard Connection made from SCardConnect().
  * @param pioSendPci [inout] Structure of protocol information.
  * <ul>
@@ -2557,56 +2883,75 @@
 {
 	LONG rv;
 	int i;
-	DWORD dwContextIndex, dwChannelIndex;
+	DWORD dwContextIndex, dwChannelIndex, dwClientID;
 
 	PROFILE_START
 
+	DBG(NULL, hCard, "SCartTransmit()/\n");
+
 	if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
-			pcbRecvLength == NULL || pioSendPci == NULL)
+			pcbRecvLength == NULL || pioSendPci == NULL) {
+		DBGERR("SCardTransmit(SCARD_E_INVALID_PARAMETER)\n");
 		return SCARD_E_INVALID_PARAMETER;
-
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
+	}
+
+	SYS_MutexLock(&contextMutex);
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndex, &dwChannelIndex);
-
-	if (rv == -1)
-	{
-		*pcbRecvLength = 0;
+	rv = SCardGetIndicesFromHandle(
+		hCard, &dwContextIndex, &dwChannelIndex, &dwClientID);
+
+	if (SCardCheckDaemonAvailability(dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardReconnect(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	if (rv == -1) {
+		DBGERR("SCardReconnect(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
 	}
 
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
+		PREADER_STATE prs = FETCH(readerStates[i], dwClientID);
+		if (prs == NULL) {
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_E_READER_UNAVAILABLE;
+		}
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, prs->readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardTransmit(SCARD_E_READER_UNAVAILABLE)\n");
 		return SCARD_E_READER_UNAVAILABLE;
 	}
 
 	if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
 		|| (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
 	{
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardTransmit(SCARD_E_INSUFFICIENT_BUFFER)\n");
 		return SCARD_E_INSUFFICIENT_BUFFER;
 	}
 
 	if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
 	{
 		/* extended APDU */
-		unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
+		long buffer0[(sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED)/sizeof(long)+1];
+		// unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
+		unsigned char* buffer = &buffer0[0];
 		transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
 		sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
 
@@ -2626,43 +2971,52 @@
 		else
 			scTransmitStructExtended->pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;
 
-		rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
-			psContextMap[dwContextIndex].dwClientID,
-			scTransmitStructExtended->size,
-			PCSCLITE_CLIENT_ATTEMPTS, buffer);
-
-		if (rv == -1)
-		{
-			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-			return SCARD_E_NO_SERVICE;
-		}
-
-		/*
-		 * Read a message from the server
-		 */
-		/* read the first block */
-		rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-		if (rv == -1)
-		{
-			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-			return SCARD_F_COMM_ERROR;
-		}
-
-		/* we receive a sharedSegmentMsg and not a transmit_struct_extended */
-		scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
-
-		/* a second block is present */
-		if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
-		{
-			rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
-				scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
+		switch(pcscCfg.transportType) {
+		case SOCKET_UNIX:
+		case SOCKET_INETV4:
+			rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
 				psContextMap[dwContextIndex].dwClientID,
-				PCSCLITE_CLIENT_ATTEMPTS);
+				scTransmitStructExtended->size,
+				PCSCLITE_CLIENT_ATTEMPTS, buffer);
+
 			if (rv == -1)
 			{
-				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				DBGERR("SCardTransmit(SCARD_E_NO_SERVICE)\n");
+				return SCARD_E_NO_SERVICE;
+			}
+
+			/*
+			* Read a message from the server
+			*/
+			/* read the first block */
+			rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg),
+			psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
+			if (rv == -1)
+			{
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				DBGERR("SCardTransmit(SCARD_F_COMM_ERROR)\n");
 				return SCARD_F_COMM_ERROR;
 			}
+
+			/* we receive a sharedSegmentMsg and not a transmit_struct_extended */
+			scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
+
+			/* a second block is present */
+			if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
+			{
+				rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
+					scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
+					psContextMap[dwContextIndex].dwClientID,
+					PCSCLITE_CLIENT_ATTEMPTS);
+				if (rv == -1)
+				{
+					SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+					DBGERR("SCardTransmit(SCARD_F_COMM_ERROR)\n");
+					return SCARD_F_COMM_ERROR;
+				}
+			}
+			break;
 		}
 
 		if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
@@ -2681,7 +3035,7 @@
 		}
 
 		*pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 		rv = scTransmitStructExtended -> rv;
 	}
@@ -2689,7 +3043,6 @@
 	{
 		/* short APDU */
 		transmit_struct scTransmitStruct;
-		sharedSegmentMsg msgStruct;
 
 		scTransmitStruct.hCard = hCard;
 		scTransmitStruct.cbSendLength = cbSendLength;
@@ -2706,27 +3059,12 @@
 		else
 			scTransmitStruct.pioRecvPci.dwProtocol = SCARD_PROTOCOL_ANY;
 
-		rv = WrapSHMWrite(SCARD_TRANSMIT,
-			psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
-			PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
-
-		if (rv == -1)
-		{
-			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-			return SCARD_E_NO_SERVICE;
-		}
-
-		/*
-		 * Read a message from the server
-		 */
-		rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-
-		memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
-
-		if (rv == -1)
-		{
-			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
-			return SCARD_F_COMM_ERROR;
+
+		if ((rv = SHMrpc(SCARD_TRANSMIT, dwClientID,
+			(void *) &scTransmitStruct, sizeof (scTransmitStruct))) == -1) {
+				Log1(PCSC_LOG_INFO, "SCardTransmit(): SHMrpc() returned error");
+				SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+				return SCARD_F_COMM_ERROR;
 		}
 
 		/*
@@ -2750,20 +3088,21 @@
 		}
 
 		*pcbRecvLength = scTransmitStruct.pcbRecvLength;
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 		rv = scTransmitStruct.rv;
 	}
 
 	PROFILE_END
 
+	DBGERR("SCardTransmit(%lx)\n", rv);
 	return rv;
 }
 
 /**
- * This function returns a list of currently available readers on the system. 
- * \p mszReaders is a pointer to a character string that is allocated by the application. 
- * If the application sends mszGroups and mszReaders as NULL then this function will 
+ * This function returns a list of currently available readers on the system.
+ * \p mszReaders is a pointer to a character string that is allocated by the application.
+ * If the application sends mszGroups and mszReaders as NULL then this function will
  * return the size of the buffer needed to allocate in pcchReaders.
  *
  * @param[in] hContext Connection context to the PC/SC Resource Manager.
@@ -2786,7 +3125,7 @@
  * rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
  * rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
  * mszReaders = malloc(sizeof(char)*dwReaders);
- * rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders); 
+ * rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
  * @endcode
  */
 LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
@@ -2794,71 +3133,101 @@
 {
 	DWORD dwReadersLen;
 	int i, lastChrPtr;
-	DWORD dwContextIndex;
+	DWORD dwContextIndex, dwClientID;
+	void *dummy;
 
 	PROFILE_START
 
-	/*
-	 * Check for NULL parameters
-	 */
-	if (pcchReaders == NULL)
+	DBG(hContext, NULL, "SCardListReaders()/\n");
+
+	/* * Check for NULL parameters */
+	if (pcchReaders == NULL) {
+		DBGERR("SCardListReaders(SCARD_E_INVALID_PARAMETER)\n");
 		return SCARD_E_INVALID_PARAMETER;
-
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
-	/*
-	 * Make sure this context has been opened
-	 */
+	}
+
+	SYS_MutexLock(&contextMutex);
+
 	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+
+	if (SCardCheckDaemonAvailability(dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardListReaders(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE; /* * Make sure this context has been opened */
+	}
+
+	if (dwContextIndex == -1)   {
+		DBGERR("SCardListReaders(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
+
+	dwClientID = psContextMap[dwContextIndex].dwClientID;
+
+	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) {
+		dummy = FETCH(readerStates[i], dwClientID);
+		/*
+		 * If this fails, there is no appropriate error code
+		 * to return so we adjust the returned reader list
+		 * and length to reflect no readers found, accordingly.
+		 */
+		if (dummy == NULL) {
+			if (mszReaders != NULL) {
+				if (*pcchReaders > 0)
+					mszReaders[0] = '\0';
+				if (*pcchReaders > 1)
+					mszReaders[1] = '\0';
+			} else
+				*pcchReaders = 0;
+
+			SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+			return SCARD_S_SUCCESS;
+		}
+	}
 
 	dwReadersLen = 0;
-	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
-		if ((readerStates[i])->readerID != 0)
-			dwReadersLen += strlen((readerStates[i])->readerName) + 1;
-
+	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) {
+		if (readerStates[i]->readerID != 0) {
+			dwReadersLen += strlen(readerStates[i]->readerName) + 1;
+		}
+	}
 	/* for the last NULL byte */
 	dwReadersLen += 1;
 
-	if ((mszReaders == NULL)	/* text array not allocated */
-		|| (*pcchReaders == 0))	/* size == 0 */
-	{
+	if ((mszReaders == NULL) || (*pcchReaders == 0)) {
 		*pcchReaders = dwReadersLen;
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 		return SCARD_S_SUCCESS;
 	}
-	
-	if (*pcchReaders < dwReadersLen)
-	{
+
+	if (*pcchReaders < dwReadersLen){
 		*pcchReaders = dwReadersLen;
-		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+		SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
+		DBGERR("SCardListReaders(SCARD_E_INSUFFICIENT_BUFFER)\n");
 		return SCARD_E_INSUFFICIENT_BUFFER;
 	}
 
 	lastChrPtr = 0;
-	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
-	{
-		if ((readerStates[i])->readerID != 0)
-		{
+	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) {
+		if (readerStates[i]->readerID != 0) {
 			/*
 			 * Build the multi-string
 			 */
-			strcpy(&mszReaders[lastChrPtr], (readerStates[i])->readerName);
-			lastChrPtr += strlen((readerStates[i])->readerName)+1;
-		}
-	}
-	mszReaders[lastChrPtr] = '\0';	/* Add the last null */
+			strcpy(&mszReaders[lastChrPtr],
+			   readerStates[i]->readerName);
+			lastChrPtr += strlen(&mszReaders[lastChrPtr]) + 1;
+		}
+	}
+
+	mszReaders[lastChrPtr] = '\0';
+	mszReaders[lastChrPtr + 1] = '\0'; /* Add the dbl termination null */
 
 	*pcchReaders = dwReadersLen;
-
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END
-
 	return SCARD_S_SUCCESS;
 }
 
@@ -2869,7 +3238,7 @@
  * will return the size of the buffer needed to allocate in pcchGroups.
  *
  * The group names is a multi-string and separated by a nul character ('\\0') and ended by
- * a double nul character. "SCard$DefaultReaders\\0Group 2\\0\\0". 
+ * a double nul character. "SCard$DefaultReaders\\0Group 2\\0\\0".
  *
  * @param[in] hContext Connection context to the PC/SC Resource Manager.
  * @param[out] mszGroups List of groups to list readers.
@@ -2904,17 +3273,28 @@
 	const char ReaderGroup[] = "SCard$DefaultReaders";
 	const int dwGroups = strlen(ReaderGroup) + 2;
 
-	if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
-		return SCARD_E_NO_SERVICE;
-
+	DBG(hContext, NULL, "SCarListReaderGroups()/\n");
+
+	SYS_MutexLock(&contextMutex);
 	/*
 	 * Make sure this context has been opened
 	 */
 	dwContextIndex = SCardGetContextIndice(hContext);
-	if (dwContextIndex == -1)
+	if (dwContextIndex == -1) {
+		DBGERR("SCardListReaderGroups(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
-	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);	
+	}
+
+	if (SCardCheckDaemonAvailability(
+	    psContextMap[dwContextIndex].dwClientID) != SCARD_S_SUCCESS) {
+		DBGERR("SCardListReaderGroups(SCARD_E_NO_SERVICE)\n");
+		SYS_MutexUnLock(&contextMutex);
+		return SCARD_E_NO_SERVICE;
+	}
+
+	SYS_MutexLock(psContextMap[dwContextIndex].mMutex);
+	SYS_MutexUnLock(&contextMutex);
 
 	if (mszGroups)
 	{
@@ -2930,10 +3310,11 @@
 
 	*pcchGroups = dwGroups;
 
-	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);	
+	SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END
 
+	DBGERR("SCardListReaderGroups(%lx)\n", rv);
 	return rv;
 }
 
@@ -2969,12 +3350,16 @@
 	DWORD dwContextIndex;
 
 	PROFILE_START
-
+	SYS_MutexLock(&contextMutex);
+
+	DBG(hContext, NULL, "SCardCancel()/\n");
 	dwContextIndex = SCardGetContextIndice(hContext);
 
-	if (dwContextIndex == -1)
+	if (dwContextIndex == -1) {
+		DBGERR("SCardCancel(SCARD_E_INVALID_HANDLE)\n");
+		SYS_MutexUnLock(&contextMutex);
 		return SCARD_E_INVALID_HANDLE;
-
+	}
 	/*
 	 * Set the block status for this Context so blocking calls will
 	 * complete
@@ -2982,12 +3367,63 @@
 	psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
 
 	PROFILE_END
-
+	SYS_MutexUnLock(&contextMutex);
+
+	DBGERR("SCardCancel(SCARD_S_SUCCESS)\n");
 	return SCARD_S_SUCCESS;
 }
 
 /**
- * Functions for managing instances of SCardEstablishContext These functions 
+ * @brief Get the index from the Application Context vector \c psContextMap
+ * for the passed context.
+ *
+ * This function is a thread-safe wrapper to the function
+ * \c SCardGetContextIndiceTH().
+ *
+ * @param[in] hContext Application Context whose index will be find.
+ *
+ * @return Index corresponding to the Application Context or -1 if it is
+ * not found.
+ */
+static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
+{
+	LONG rv;
+
+	rv = SCardGetContextIndiceTH(hContext);
+
+	return rv;
+}
+
+/**
+ * @brief Get the index from the Application Context vector \c psContextMap
+ * for the passed context.
+ *
+ * This functions is not thread-safe and should not be called. Instead, call
+ * the function \c SCardGetContextIndice().
+ *
+ * @param[in] hContext Application Context whose index will be find.
+ *
+ * @return Index corresponding to the Application Context or -1 if it is
+ * not found.
+ */
+static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
+{
+	int i;
+
+	/*
+	 * Find this context and return it's spot in the array
+	 */
+	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
+	{
+		if ((hContext == psContextMap[i].hContext) && (hContext != 0))
+			return i;
+	}
+
+	return -1;
+}
+
+/**
+ * Functions for managing instances of SCardEstablishContext These functions
  * keep track of Context handles and associate the blocking
  * variable contextBlockStatus to an hContext
  */
@@ -3013,64 +3449,15 @@
 			psContextMap[i].hContext = hContext;
 			psContextMap[i].dwClientID = dwClientID;
 			psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
-			psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
-			SYS_MutexInit(psContextMap[i].mMutex);
+			if (psContextMap[i].mMutex == NULL) {
+				psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
+				SYS_MutexInit(psContextMap[i].mMutex);
+			}
 			return SCARD_S_SUCCESS;
 		}
 	}
 
 	return SCARD_E_NO_MEMORY;
-}
-
-/**
- * @brief Get the index from the Application Context vector \c psContextMap
- * for the passed context.
- *
- * This function is a thread-safe wrapper to the function
- * \c SCardGetContextIndiceTH().
- *
- * @param[in] hContext Application Context whose index will be find.
- *
- * @return Index corresponding to the Application Context or -1 if it is
- * not found.
- */
-static LONG SCardGetContextIndice(SCARDCONTEXT hContext)
-{
-	LONG rv;
-
-	SCardLockThread();
-	rv = SCardGetContextIndiceTH(hContext);
-	SCardUnlockThread();
-
-	return rv;
-}
-
-/**
- * @brief Get the index from the Application Context vector \c psContextMap
- * for the passed context.
- *
- * This functions is not thread-safe and should not be called. Instead, call
- * the function \c SCardGetContextIndice().
- *
- * @param[in] hContext Application Context whose index will be find.
- *
- * @return Index corresponding to the Application Context or -1 if it is
- * not found.
- */
-static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
-{
-	int i;
-
-	/*
-	 * Find this context and return it's spot in the array
-	 */
-	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
-	{
-		if ((hContext == psContextMap[i].hContext) && (hContext != 0))
-			return i;
-	}
-
-	return -1;
 }
 
 /**
@@ -3097,8 +3484,6 @@
 		psContextMap[retIndice].hContext = 0;
 		SHMClientCloseSession(psContextMap[retIndice].dwClientID);
 		psContextMap[retIndice].dwClientID = 0;
-		free(psContextMap[retIndice].mMutex);
-		psContextMap[retIndice].mMutex = NULL;
 		psContextMap[retIndice].contextBlockStatus = BLOCK_STATUS_RESUME;
 
 		for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
@@ -3115,58 +3500,20 @@
 	}
 }
 
-/*
- * Functions for managing hCard values returned from SCardConnect.
- */
-
-static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
-	LPSTR readerName)
-{
-	int i;
-
-	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
-	{
-		if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
-		{
-			psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
-			psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
-			return SCARD_S_SUCCESS;
-		}
-	}
-
-	return SCARD_E_NO_MEMORY;
-}
-
-static LONG SCardRemoveHandle(SCARDHANDLE hCard)
-{
-	DWORD dwContextIndice, dwChannelIndice;
-	LONG rv;
-
-	rv = SCardGetIndicesFromHandle(hCard, &dwContextIndice, &dwChannelIndice);
-
-	if (rv == -1)
-		return SCARD_E_INVALID_HANDLE;
-	else
-	{
-		psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].hCard = 0;
-		free(psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName);
-		psContextMap[dwContextIndice].psChannelMap[dwChannelIndice].readerName = NULL;
-		return SCARD_S_SUCCESS;
-	}
-}
-
-static LONG SCardGetIndicesFromHandle(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
+static LONG SCardGetIndicesFromHandle(
+	SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice,
+	PDWORD pdwClientID)
 {
 	LONG rv;
 
-	SCardLockThread();
 	rv = SCardGetIndicesFromHandleTH(hCard, pdwContextIndice, pdwChannelIndice);
-	SCardUnlockThread();
-
+	if (rv >= 0)
+		*pdwClientID = psContextMap[*pdwContextIndice].dwClientID;
 	return rv;
 }
 
-static LONG SCardGetIndicesFromHandleTH(SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
+static LONG SCardGetIndicesFromHandleTH(
+	SCARDHANDLE hCard, PDWORD pdwContextIndice, PDWORD pdwChannelIndice)
 {
 	int i;
 
@@ -3182,36 +3529,59 @@
 				{
 					*pdwContextIndice = i;
 					*pdwChannelIndice = j;
+
 					return SCARD_S_SUCCESS;
 				}
 			}
-			
-		}
-	}
-
+
+		}
+	}
 	return -1;
 }
 
-/**
- * @brief This function locks a mutex so another thread must wait to use this
- * function.
- *
- * Wrapper to the function \c SYS_MutexLock().
- */
-inline static LONG SCardLockThread(void)
+
+/*
+ * Functions for managing hCard values returned from SCardConnect.
+ */
+
+static LONG SCardAddHandle(SCARDHANDLE hCard, DWORD dwContextIndex,
+	LPSTR readerName)
 {
-	return SYS_MutexLock(&clientMutex);
+	int i;
+
+	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
+	{
+		if (psContextMap[dwContextIndex].psChannelMap[i].hCard == 0)
+		{
+			psContextMap[dwContextIndex].psChannelMap[i].hCard = hCard;
+			psContextMap[dwContextIndex].psChannelMap[i].readerName = strdup(readerName);
+			return SCARD_S_SUCCESS;
+		}
+	}
+
+	return SCARD_E_NO_MEMORY;
 }
 
-/**
- * @brief This function unlocks a mutex so another thread may use the client.
- *
- * Wrapper to the function \c SYS_MutexUnLock().
- */
-inline static LONG SCardUnlockThread(void)
+static LONG SCardRemoveHandle(SCARDHANDLE hCard)
 {
-	return SYS_MutexUnLock(&clientMutex);
+	DWORD dwContextIndex, dwChannelIndex, dwClientID;
+	LONG rv;
+
+	rv = SCardGetIndicesFromHandle(
+		hCard, &dwContextIndex, &dwChannelIndex, &dwClientID);
+	if (rv == -1)
+		return SCARD_E_INVALID_HANDLE;
+
+	else
+	{
+		psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].hCard = 0;
+		free(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName);
+		psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName = NULL;
+		return SCARD_S_SUCCESS;
+	}
 }
+
+
 
 /**
  * @brief Checks if the Server is running.
@@ -3220,19 +3590,31 @@
  * @retval SCARD_S_SUCCESS Server is running.
  * @retval SCARD_E_NO_SERVICE Server is not running.
  */
-static LONG SCardCheckDaemonAvailability(void)
+static LONG SCardCheckDaemonAvailability(DWORD dwClientID)
 {
-	LONG rv;
+	int fd;
 	struct stat statBuffer;
 
-	rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);
-
-	if (rv != 0)
-	{
-		Log1(PCSC_LOG_ERROR, "PCSC Not Running");
-		return SCARD_E_NO_SERVICE;
-	}
-
+
+	if (pcscCfg.useMappedMemory) {
+		if (SYS_Stat(pcscCfg.pcscdMemMappedFile, &statBuffer) != 0) {
+			Log1(PCSC_LOG_ERROR, "PCSC Not Running");
+			return SCARD_E_NO_SERVICE;
+		}
+	} else {
+		int rv, pingRetry = 0;
+		while((rv = SHMping()) != 0) {
+			usleep(50000);
+			if (++pingRetry > 10)
+				break;
+		}
+		if (rv != 0) {
+			Log1(PCSC_LOG_ERROR,
+				"SCardCheckDaemonAvailability(): PCSC Not Running");
+			return SCARD_E_NO_SERVICE;
+		}
+		return SCARD_S_SUCCESS;
+	}
 	return SCARD_S_SUCCESS;
 }
 
@@ -3257,12 +3639,18 @@
 	{
 		if (readerStates[i] != NULL)
 		{
-			SYS_PublicMemoryUnmap(readerStates[i], sizeof(READER_STATE));
-			readerStates[i] = NULL;
-		}
-	}
-
-	SYS_CloseFile(mapAddr);
+			if (pcscCfg.useMappedMemory) {
+				SYS_PublicMemoryUnmap(
+					readerStates[i], sizeof(READER_STATE));
+				readerStates[i] = NULL;
+			}
+		} else {
+			      free(readerStates[i]);
+			       readerStates[i] = NULL;
+		}
+	}
+	if (pcscCfg.useMappedMemory)
+		SYS_CloseFile(mapAddr);
 	isExecuted = 0;
 }
 

Modified: branches/Solaris/src/winscard_msg.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/winscard_msg.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/winscard_msg.c (original)
+++ branches/Solaris/src/winscard_msg.c Thu Jun 12 10:28:09 2008
@@ -13,7 +13,7 @@
  * @file
  * @brief This is responsible for client/server communication.
  *
- * A file based socket (\c commonSocket) is used to send/receive only messages 
+ * A file based socket (\c commonSocket) is used to send/receive only messages
  * among clients and server.\n
  * The messages' data are passed throw a memory mapped file: \c sharedSegmentMsg.
  */
@@ -31,17 +31,48 @@
 #include <stdio.h>
 #include <time.h>
 #include <string.h>
+#include <strings.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <ucred.h>
+#include <thread.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #ifdef HAVE_SYS_FILIO_H
 #include <sys/filio.h>
 #endif
+#ifdef HAVE_SYS_DOOR_H
+#include <door.h>
+#endif
 
 #include "misc.h"
 #include "pcsclite.h"
+#include "pcsc_config.h"
 #include "winscard.h"
+#include "clientcred.h"
 #include "debug.h"
 #include "winscard_msg.h"
 #include "sys_generic.h"
 
+#define CONNECT_TIMEOUT 30
+
+int MessageSendSocket(void *, size_t,int, int);
+int MessageReceiveSocket(void *, size_t, int, int);
+int MessageSendDoor(void *, size_t,int, int);
+int MessageReceiveDoor(void *, size_t, int, int);
+
+void dumpContexts();
+
+
+static PCSCLITE_MUTEX fdMutex[256];
+static PCSCLITE_MUTEX clientSessionMutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+void traceback();
+
+
 /**
  * @brief Wrapper for the SHMMessageReceive() function.
  *
@@ -51,21 +82,24 @@
  * @param[in] dwClientID Client socket handle.
  * @param[in] blockamount Timeout in milliseconds.
  *
- * @return Same error codes as SHMMessageReceive().
+ * @return Same error codesj as SHMMessageReceive().
  */
 INTERNAL int SHMClientRead(psharedSegmentMsg msgStruct, DWORD dwClientID, int blockamount)
 {
 	return SHMMessageReceive(msgStruct, sizeof(*msgStruct), dwClientID, blockamount);
 }
 
+
 /**
  * @brief Prepares a communication channel for the client to talk to the server.
  *
  * This is called by the application to create a socket for local IPC with the
- * server. The socket is associated to the file \c PCSCLITE_CSOCK_NAME.
+ * server. The socket is associated to the file \c PCSCLITE_CSOCK_NAME by default
+ * but this can be overridden in the global configuration file pcscd.conf, and
+ * affected by the -b or INSTANCE_BASE_DIR key-value setting in pcscd.conf
  *
  * @param[out] pdwClientID Client Connection ID.
- * 
+ *
  * @retval 0 Success.
  * @retval -1 Can not create the socket.
  * @retval -1 The socket can not open a connection.
@@ -73,38 +107,237 @@
  */
 INTERNAL int SHMClientSetupSession(PDWORD pdwClientID)
 {
-	struct sockaddr_un svc_addr;
-	int one;
-
-	if ((*pdwClientID = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
-	{
-		Log2(PCSC_LOG_CRITICAL, "Error: create on client socket: %s",
-			strerror(errno));
-		return -1;
-	}
-
-	svc_addr.sun_family = AF_UNIX;
-	strncpy(svc_addr.sun_path, PCSCLITE_CSOCK_NAME,
-		sizeof(svc_addr.sun_path));
-
-	if (connect(*pdwClientID, (struct sockaddr *) &svc_addr,
-			sizeof(svc_addr.sun_family) + strlen(svc_addr.sun_path) + 1) < 0)
-	{
-		Log2(PCSC_LOG_CRITICAL, "Error: connect to client socket: %s",
-			strerror(errno));
-		SYS_CloseFile(*pdwClientID);
-		return -1;
-	}
-
-	one = 1;
-	if (ioctl(*pdwClientID, FIONBIO, &one) < 0)
-	{
-		Log2(PCSC_LOG_CRITICAL, "Error: cannot set socket nonblocking: %s",
-			strerror(errno));
-		SYS_CloseFile(*pdwClientID);
-		return -1;
-	}
-
+	int rv;
+
+	SYS_MutexLock(&clientSessionMutex);
+	switch(pcscCfg.transportType) {
+	case SOCKET_UNIX:
+	    {
+		struct sockaddr_un svc_addr;
+		int one;
+		if ((*pdwClientID = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)  {
+			Log2(PCSC_LOG_CRITICAL, "Error: create on client socket: %s",
+				strerror(errno));
+			SYS_MutexUnLock(&clientSessionMutex);
+			return -1;
+		}
+
+		SYS_MutexLock(&fdMutex[*pdwClientID]);
+
+		svc_addr.sun_family = AF_UNIX;
+		strncpy(svc_addr.sun_path, pcscCfg.netBindFile,
+			sizeof(svc_addr.sun_path));
+
+		if ((rv = connect(*pdwClientID, (struct sockaddr *) &svc_addr,
+			sizeof(svc_addr.sun_family) +
+			strlen(svc_addr.sun_path) + 1)) < 0) {
+				Log2(PCSC_LOG_CRITICAL,
+				     "Error: connect to client socket: %s",
+				     strerror(errno));
+				SYS_CloseFile(*pdwClientID);
+				SYS_MutexUnLock(&clientSessionMutex);
+				SYS_MutexUnLock(&fdMutex[*pdwClientID]);
+				return -1;
+		}
+
+		one = 1;
+		if (ioctl(*pdwClientID, FIONBIO, &one) < 0)  {
+			Log2(PCSC_LOG_CRITICAL,
+			    "Error: cannot set socket nonblocking: %s",
+			    strerror(errno));
+			SYS_CloseFile(*pdwClientID);
+			SYS_MutexUnLock(&clientSessionMutex);
+			SYS_MutexUnLock(&fdMutex[*pdwClientID]);
+
+			return -1;
+		}
+		SYS_MutexUnLock(&fdMutex[*pdwClientID]);
+		break;
+
+	    }
+	case SOCKET_INETV4:
+	    {
+		union {
+		     struct sockaddr s;
+		     struct sockaddr_in i;
+		} serv_addr;
+		int one;
+		struct linger l = {0, 0};
+		int sndbufsize = 4096;
+		int rcvbufsize = 4096;
+		l.l_onoff  = 1;
+		l.l_linger = 0;
+
+		if ((*pdwClientID = socket(AF_INET, SOCK_STREAM, 0)) < 0)  {
+			Log2(PCSC_LOG_CRITICAL,
+				"Error: create on client socket: %s",
+				strerror(errno));
+			SYS_MutexUnLock(&clientSessionMutex);
+			return -1;
+		}
+
+		if (setsockopt(*pdwClientID, SOL_SOCKET, SO_LINGER,
+		     &l, sizeof (l)) < 0) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "setsockopt()/SO_LINGER: %s", strerror(errno));
+			return -1;
+		}
+		if (setsockopt(*pdwClientID, SOL_SOCKET, SO_SNDBUF,
+		     &sndbufsize, sizeof (sndbufsize)) < 0) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "setsockopt()/SO_SNDBUF: %s", strerror(errno));
+			return -1;
+		}
+		if (setsockopt(*pdwClientID, SOL_SOCKET, SO_RCVBUF,
+		     &rcvbufsize, sizeof (rcvbufsize)) < 0) {
+			Log2(PCSC_LOG_CRITICAL,
+			    "setsockopt()/SO_RCVBUF: %s", strerror(errno));
+			return -1;
+		}
+
+		SYS_MutexLock(&fdMutex[*pdwClientID]);
+
+		serv_addr.i.sin_family = AF_INET;
+		serv_addr.i.sin_port = htons(pcscCfg.portNbr);
+		bcopy((char *)&pcscCfg.xHostIp, (char *)&serv_addr.i.sin_addr.s_addr,
+		     sizeof (pcscCfg.xHostIp));
+
+
+		if ((rv = connect(*pdwClientID, &serv_addr.s, sizeof (serv_addr))) < 0) {
+			int errcnt = 0;
+			// If EADDRUSE encountered re-try in case system socket resources
+			// are temporarily exhausted
+			while (rv < 0 &&
+				(errno == EADDRINUSE || errno == EINTR || errno == EAGAIN)
+				&& errcnt++ < 100) {
+					usleep(50000);
+					rv = connect(*pdwClientID, &serv_addr.s, sizeof (serv_addr));
+			}
+			if (rv < 0) {
+				Log3(PCSC_LOG_INFO,
+				"SHMClientSetupSession: Server connect err:\n%d: %s",
+				errno, strerror(errno));
+				SYS_CloseFile(*pdwClientID);
+				SYS_MutexUnLock(&clientSessionMutex);
+				SYS_MutexUnLock(&fdMutex[*pdwClientID]);
+				return -1;
+			}
+		}
+
+		Log3(PCSC_LOG_DEBUG,
+			"SHMClientSetupSession(%d) thr:%x",
+			*pdwClientID, thr_self());
+
+#ifdef PCSCLITE_PORTSVC_PORTNO
+		/*
+		 * If we're in daemon launcher mode, we need to
+		 * identify the display we need to contact.  If the launcher
+		 * can't authenticate us, it will shut down the connection
+		 * immediately.
+		 */
+		if (pcscCfg.launchMode == LAUNCHER) {
+			char buf[256];
+			char *ipaddr =  inet_ntoa(*(struct in_addr *)&pcscCfg.xHostIp);
+			sprintf(buf, "%s:%d.%d\r", ipaddr, pcscCfg.dpyNbr, pcscCfg.screenNbr);
+			 if (pcscCfg.logLevel == DEBUG) {
+				Log2(PCSC_LOG_DEBUG,
+				    "[Client send connect msg to launcher]: %s\n",
+				    buf);
+				Log2(PCSC_LOG_DEBUG,
+					"Waiting for %d secs for reply from launcher",
+					CONNECT_TIMEOUT);
+
+			 }
+			 /*
+			 * Read reply from launcher
+			 */
+			write(*pdwClientID, buf, strlen(buf));
+			{
+				fd_set read_fd;
+				struct timeval tv;
+				int rv;
+				tv.tv_sec = CONNECT_TIMEOUT;
+				tv.tv_usec = 0;
+
+				FD_ZERO(&read_fd);
+				FD_SET(*pdwClientID, &read_fd);
+
+				rv = select(*pdwClientID + 1, &read_fd, NULL, NULL, &tv);
+				if (rv < 0) {
+					while (rv < 0 && (errno == EINTR || errno == EAGAIN)) {
+						usleep(50000);
+						rv = select(*pdwClientID + 1, &read_fd, NULL, NULL, &tv);
+					}
+					if (rv < 0) {
+						Log2(PCSC_LOG_CRITICAL,
+						    "Launcher reply select() error: %s",
+						    strerror(errno));
+						SYS_CloseFile(*pdwClientID);
+						SYS_MutexUnLock(&clientSessionMutex);
+						SYS_MutexUnLock(&fdMutex[*pdwClientID]);
+						return -1;      // Error
+					}
+				} else if (rv == 0) {
+					Log2(PCSC_LOG_INFO,
+					    "Launcher reply timed out after %d sec.",
+					    CONNECT_TIMEOUT);
+					SYS_CloseFile(*pdwClientID);
+					SYS_MutexUnLock(&clientSessionMutex);
+					SYS_MutexUnLock(&fdMutex[*pdwClientID]);
+					return -1;      // Timeout
+				}
+
+				if (FD_ISSET(*pdwClientID, &read_fd)) {
+					if ((rv = read(*pdwClientID, buf, sizeof (buf))) < 0) {
+						while (rv < 0 && (errno == EINTR || errno == EAGAIN)) {
+							usleep(50000);
+							rv = read(*pdwClientID, buf, sizeof (buf));
+						}
+						if (rv < 0) {
+							Log3(PCSC_LOG_INFO,
+							    "read() err on launcher reply after select(fd=%d): %s",
+							    *pdwClientID, strerror(errno));
+							SYS_MutexUnLock(&clientSessionMutex);
+							SYS_MutexUnLock(&fdMutex[*pdwClientID]);
+							return -1;      // Error
+						}
+					}
+				}
+			}
+			if (pcscCfg.logLevel == DEBUG) {
+				Log2(PCSC_LOG_DEBUG,
+				    "[Client received handshake from instance]:\n%s", buf);
+			}
+			if (strncmp(buf, CONNECTOK, strlen(CONNECTOK)) != 0) {
+				Log1(PCSC_LOG_INFO,
+					"Error: Didn't get CONNECT OK message from instance.");
+				Log2(PCSC_LOG_INFO,
+					"Received following buffer instead:\n%s", buf);
+				Log2(PCSC_LOG_INFO,
+					"Closing FD: %d", *pdwClientID);
+				SYS_CloseFile(*pdwClientID);
+				SYS_MutexUnLock(&clientSessionMutex);
+				SYS_MutexUnLock(&fdMutex[*pdwClientID]);
+				return -1;
+			}
+		}
+#endif
+		one = 1;
+		if (ioctl(*pdwClientID, FIONBIO, &one) < 0)  {
+			Log2(PCSC_LOG_CRITICAL,
+				"Error: cannot set socket nonblocking: %s",
+				strerror(errno));
+			SYS_CloseFile(*pdwClientID);
+			SYS_MutexUnLock(&clientSessionMutex);
+			SYS_MutexUnLock(&fdMutex[*pdwClientID]);
+			return -1;
+		}
+		break;
+	    }
+	}
+
+	SYS_MutexUnLock(&clientSessionMutex);
+	SYS_MutexUnLock(&fdMutex[*pdwClientID]);
 	return 0;
 }
 
@@ -117,12 +350,19 @@
  */
 INTERNAL int SHMClientCloseSession(DWORD dwClientID)
 {
+	Log3(PCSC_LOG_DEBUG,
+		"SHMClientCloseSession(%d) thr:%x", dwClientID, thr_self());
+	SYS_MutexLock(&clientSessionMutex);
+	SYS_MutexLock(&fdMutex[dwClientID]);
 	SYS_CloseFile(dwClientID);
+	SYS_MutexUnLock(&clientSessionMutex);
+	SYS_MutexUnLock(&fdMutex[dwClientID]);
 	return 0;
 }
 
+
 /**
- * @brief Sends a menssage from client to server or vice-versa.
+ * @brief Sends a menssage over UNIX or INETV4 domain socket
  *
  * Writes the message in the shared file \c filedes.
  *
@@ -136,24 +376,29 @@
  * @retval -1 Socket is closed.
  * @retval -1 A signal was received.
  */
+
 INTERNAL int SHMMessageSend(void *buffer, size_t buffer_size,
 	int filedes, int blockAmount)
+
 {
-	/*
-	 * default is success 
+	char *pBuf = (char *)buffer;
+	SYS_MutexLock(&fdMutex[filedes]);
+
+	/*
+	 * default is success
 	 */
 	int retval = 0;
 	/*
-	 * record the time when we started 
+	 * record the time when we started
 	 */
 	time_t start = time(0);
 	/*
-	 * how many bytes remains to be written 
+	 * how many bytes remains to be written
 	 */
 	size_t remaining = buffer_size;
 
 	/*
-	 * repeat until all data is written 
+	 * repeat until all data is written
 	 */
 	while (remaining > 0)
 	{
@@ -168,8 +413,9 @@
 		if ((timeout.tv_sec = start + blockAmount - time(0)) < 0)
 		{
 			/*
-			 * we already timed out 
+			 * we already timed out
 			 */
+			errno = ETIMEDOUT;
 			retval = -1;
 			break;
 		}
@@ -177,7 +423,7 @@
 		selret = select(filedes + 1, NULL, &write_fd, NULL, &timeout);
 
 		/*
-		 * try to write only when the file descriptor is writable 
+		 * try to write only when the file descriptor is writable
 		 */
 		if (selret > 0)
 		{
@@ -186,32 +432,33 @@
 			if (!FD_ISSET(filedes, &write_fd))
 			{
 				/*
-				 * very strange situation. it should be an assert really 
+				 * very strange situation. it should be an assert really
 				 */
 				retval = -1;
 				break;
 			}
-			written = write(filedes, buffer, remaining);
+			written = write(filedes, pBuf, remaining);
 
 			if (written > 0)
 			{
 				/*
-				 * we wrote something 
+				 * we wrote something
 				 */
-				buffer += written;
+				pBuf += written;
 				remaining -= written;
 			} else if (written == 0)
 			{
 				/*
-				 * peer closed the socket 
+				 * peer closed the socket
 				 */
+				errno = ECONNRESET;
 				retval = -1;
 				break;
 			} else
 			{
 				/*
 				 * we ignore the signals and socket full situations, all
-				 * other errors are fatal 
+				 * other errors are fatal
 				 */
 				if (errno != EINTR && errno != EAGAIN)
 				{
@@ -222,39 +469,44 @@
 		} else if (selret == 0)
 		{
 			/*
-			 * timeout 
+			 * timeout
 			 */
+			errno = ETIMEDOUT;
 			retval = -1;
 			break;
 		} else
 		{
 			/*
-			 * ignore signals 
+			 * ignore signals
 			 */
 			if (errno != EINTR)
 			{
-				Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
-					strerror(errno));
+				Log4(PCSC_LOG_ERROR,
+					"select(fd=%d) thr=%x returns with failure: %s",
+					filedes, thr_self(), strerror(errno));
+				traceback(thr_self());
+				dumpContexts();
 				retval = -1;
 				break;
 			}
 		}
 	}
-
+	SYS_MutexUnLock(&fdMutex[filedes]);
 	return retval;
 }
 
+
 /**
- * @brief Called by the Client to get the reponse from the server or vice-versa.
- *
- * Reads the message from the file \c filedes.
- *
- * @param[out] buffer Message read.
- * @param[in] buffer_size Size to read
+ * @brief Receives a menssage over UNIX or INETV4 domain socket
+ *
+ * Writes the message in the shared file \c filedes.
+ *
+ * @param[in] buffer Message to be sent.
+ * @param[in] buffer_size Size of the message to send
  * @param[in] filedes Socket handle.
  * @param[in] blockAmount Timeout in milliseconds.
  *
- * @retval 0 Success.
+ * @retval 0 Success
  * @retval -1 Timeout.
  * @retval -1 Socket is closed.
  * @retval -1 A signal was received.
@@ -262,21 +514,25 @@
 INTERNAL int SHMMessageReceive(void *buffer, size_t buffer_size,
 	int filedes, int blockAmount)
 {
-	/*
-	 * default is success 
+	char *pBuf = (char *)buffer;
+
+	SYS_MutexLock(&fdMutex[filedes]);
+
+	/*
+	 * default is success
 	 */
 	int retval = 0;
 	/*
-	 * record the time when we started 
+	 * record the time when we started
 	 */
 	time_t start = time(0);
 	/*
-	 * how many bytes we must read 
+	 * how many bytes we must read
 	 */
 	size_t remaining = buffer_size;
 
 	/*
-	 * repeate until we get the whole message 
+	 * repeate until we get the whole message
 	 */
 	while (remaining > 0)
 	{
@@ -291,8 +547,9 @@
 		if ((timeout.tv_sec = start + blockAmount - time(0)) < 0)
 		{
 			/*
-			 * we already timed out 
+			 * we already timed out
 			 */
+			errno = ETIMEDOUT;
 			retval = -1;
 			break;
 		}
@@ -300,7 +557,7 @@
 		selret = select(filedes + 1, &read_fd, NULL, NULL, &timeout);
 
 		/*
-		 * try to read only when socket is readable 
+		 * try to read only when socket is readable
 		 */
 		if (selret > 0)
 		{
@@ -309,32 +566,36 @@
 			if (!FD_ISSET(filedes, &read_fd))
 			{
 				/*
-				 * very strange situation. it should be an assert really 
+				 * very strange situation. it should be an assert really
 				 */
+				Log2(PCSC_LOG_CRITICAL,
+					"SHMMessageReceive(fd=%d): Unexpected select() result",
+					filedes);
 				retval = -1;
 				break;
 			}
-			readed = read(filedes, buffer, remaining);
+			readed = read(filedes, pBuf, remaining);
 
 			if (readed > 0)
 			{
 				/*
-				 * we got something 
+				 * we got something
 				 */
-				buffer += readed;
+				pBuf += readed;
 				remaining -= readed;
 			} else if (readed == 0)
 			{
 				/*
-				 * peer closed the socket 
+				 * peer closed the socket
 				 */
+				errno = ECONNRESET;
 				retval = -1;
 				break;
 			} else
 			{
 				/*
 				 * we ignore the signals and empty socket situations, all
-				 * other errors are fatal 
+				 * other errors are fatal
 				 */
 				if (errno != EINTR && errno != EAGAIN)
 				{
@@ -345,27 +606,32 @@
 		} else if (selret == 0)
 		{
 			/*
-			 * timeout 
+			 * timeout
 			 */
 			retval = -1;
+			errno = ETIMEDOUT;
 			break;
 		} else
 		{
 			/*
-			 * we ignore signals, all other errors are fatal 
+			 * we ignore signals, all other errors are fatal
 			 */
 			if (errno != EINTR)
 			{
-				Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
-					strerror(errno));
+				Log4(PCSC_LOG_ERROR,
+					"SHMMessageReceive(): select(fd=%d) thr:%x, failed: %s",
+					filedes, thr_self(), strerror(errno));
+				traceback(thr_self());
+				dumpContexts();
 				retval = -1;
 				break;
 			}
 		}
 	}
-
+	SYS_MutexUnLock(&fdMutex[filedes]);
 	return retval;
 }
+
 
 /**
  * @brief Wrapper for the SHMMessageSend() function.
@@ -387,9 +653,10 @@
 {
 	sharedSegmentMsg msgStruct;
 	int ret;
-
-	/*
-	 * Set the appropriate packet parameters 
+	char *pData = data;
+
+	/*
+	 * Set the appropriate packet parameters
 	 */
 
 	memset(&msgStruct, 0, sizeof(msgStruct));
@@ -401,7 +668,7 @@
 	if (SCARD_TRANSMIT_EXTENDED == command)
 	{
 		/* first block */
-		memcpy(msgStruct.data, data, PCSCLITE_MAX_MESSAGE_SIZE);
+		memcpy(msgStruct.data, pData, PCSCLITE_MAX_MESSAGE_SIZE);
 		ret = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
 			blockAmount);
 		if (ret)
@@ -411,7 +678,7 @@
 		if (size > PCSCLITE_MAX_MESSAGE_SIZE)
 		{
 			/* second block */
-			ret = SHMMessageSend(data+PCSCLITE_MAX_MESSAGE_SIZE,
+			ret = SHMMessageSend(pData+PCSCLITE_MAX_MESSAGE_SIZE,
 				size-PCSCLITE_MAX_MESSAGE_SIZE, dwClientID, blockAmount);
 			if (ret)
 				return ret;
@@ -419,13 +686,200 @@
 	}
 	else
 	{
-		memcpy(msgStruct.data, data, size);
+		memcpy(msgStruct.data, pData, size);
 
 		ret = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
 			blockAmount);
 	}
 	return ret;
 }
+
+/*
+ * @brief Does a remote procedure call based on transport type.
+ *
+ * This is called by the client to invoke a function on the server.
+ *
+ * @param command
+ * @param dwClientID
+ * @param pData
+ * @param size
+ * @param blockAmount
+ * @param pMutex
+ */
+INTERNAL int SHMrpc(unsigned int command, DWORD dwClientID,
+		    void *pData, unsigned int size)
+{
+	sharedSegmentMsg msgStruct;
+	int rv;
+
+	switch (pcscCfg.transportType) {
+	case SOCKET_UNIX:
+	case SOCKET_INETV4:
+		/*
+		 * Write command describing remote function call to server.
+		 */
+		if ((rv = WrapSHMWrite(command, dwClientID, size,
+		     PCSCLITE_CLIENT_ATTEMPTS, pData)) == -1) {
+			Log4(PCSC_LOG_INFO,
+			     "SHMrpc(): WrapSHMWrite(fd=%d) returned errno=%d: %s",
+			     dwClientID, errno, strerror(errno));
+			return -1;
+		}
+		/*
+		 * Read RPC return message from the server
+		 */
+		bzero(&msgStruct, sizeof (sharedSegmentMsg));
+		rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
+
+		/*
+		 * Copy received server data back to caller's buffer
+		 */
+		memcpy(pData, &msgStruct.data, size);
+
+		if (rv == -1) {
+			Log4(PCSC_LOG_INFO,
+			     "SHMrpc(): SHMClientReader(fd=%d) returned errno=%d: %s",
+			     dwClientID, errno, strerror(errno));
+			 return -1;
+		}
+	       break;
+	}
+	return(0);
+}
+
+/**
+ * @brief Called by client to peek memory in the server's exportable memory
+ *
+ *  Build and sends request to server to peek at memory.
+ *
+ * @param[in] dwClientID Client socket handle.
+ * @param[in] addr it the location to store retrieved contents
+ * @param[in] offset is the offset into the shared memory to start at.
+ * @param[in] size is the length of the memory segment
+ *
+ * @return Same error codes as SHMMessageSend() or SHMMessageReceive()
+ */
+INTERNAL int SHMfetchReaderState(PREADER_STATE localReaderState,
+				 unsigned int readerStateIdx, DWORD dwClientID) {
+	int rv;
+	sharedSegmentMsg msgStruct;
+	fetch_struct fetch, *pfetch;
+
+	/*
+	 * Set up the message type for server-side shared
+	 * memory peek
+	 */
+
+	memset(&msgStruct, 0, sizeof(msgStruct));
+	msgStruct.mtype = CMD_FETCH;
+	msgStruct.user_id = SYS_GetUID();
+	msgStruct.group_id = SYS_GetGID();
+	msgStruct.command = FETCH_READER_STATE;
+	msgStruct.date = time(NULL);
+
+	fetch.type.index = readerStateIdx;
+	memcpy(msgStruct.data, &fetch, sizeof (struct fetch_struct));
+	/*
+	 * Send the request
+	 */
+	rv = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID, 100);
+	if (rv < 0) {
+		Log2(PCSC_LOG_INFO,
+			"SHMfetchReaderState(): SHMMessageSend(fd=%d) failed",
+				dwClientID);
+		Log3(PCSC_LOG_INFO, "errno: %d: %s",errno, strerror( errno));
+		return rv;
+	}
+	/*
+	 * Receive requested memory segment
+	 */
+	if ((rv = SHMClientRead(&msgStruct, dwClientID, 100)) < 0) {
+		Log1(PCSC_LOG_INFO,
+			"SHMfetchReaderState(): SHMClientRead() failed.");
+		Log3(PCSC_LOG_INFO, "errno=%d: %s", errno, strerror(errno));
+		return rv;
+	}
+	pfetch = (fetch_struct *)msgStruct.data;
+
+	if (pfetch->rv < 0) {
+		Log1(PCSC_LOG_INFO,
+			"SHMfetchReaderState(): Server got bad request parameters");
+		return pfetch->rv;
+	}
+
+	/*
+	 * Return memory to caller's buffer
+	 */
+	memcpy(localReaderState, pfetch->data, sizeof (READER_STATE));
+	return 0;
+}
+
+
+INTERNAL int SHMCheckProtocolVersion(int major, int minor, DWORD dwClientID)
+{
+
+	switch(pcscCfg.transportType) {
+	case SOCKET_UNIX:
+	case SOCKET_INETV4:
+	  {
+		  /* exchange client/server protocol versions */
+		  sharedSegmentMsg msgStruct;
+		  version_struct *veStr;
+		  int rv;
+		  do {
+			memset(&msgStruct, 0, sizeof(msgStruct));
+			msgStruct.mtype = CMD_VERSION;
+			msgStruct.user_id = SYS_GetUID();
+			msgStruct.group_id = SYS_GetGID();
+			msgStruct.command = 0;
+			msgStruct.date = time(NULL);
+
+			veStr = (version_struct *) msgStruct.data;
+			veStr->major = major;
+			veStr->minor = minor;
+
+			if ((rv = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
+				PCSCLITE_MCLIENT_ATTEMPTS)) == -1) {
+				Log1(PCSC_LOG_CRITICAL,
+					"Error trying sending protocol version request to server: ");
+				Log3(PCSC_LOG_CRITICAL,
+					"errno=%d: %x", errno, strerror(errno));
+				if (errno == EPIPE) {
+					Log1(PCSC_LOG_CRITICAL, "Re-trying");
+					usleep(250000);
+					continue;
+				}
+				return SCARD_E_NO_SERVICE;
+			}
+
+			/*
+			 * Read a message from the server
+			 */
+			if ((rv = SHMMessageReceive(&msgStruct, sizeof(msgStruct), dwClientID,
+				PCSCLITE_CLIENT_ATTEMPTS)) == -1) {
+				Log1(PCSC_LOG_CRITICAL,
+					"Error trying to read protocol version from server: ");
+				Log3(PCSC_LOG_CRITICAL,
+					"errno=%d: %x", errno, strerror(errno));
+				if (errno == EPIPE) {
+					Log1(PCSC_LOG_CRITICAL, "Re-trying");
+					usleep(250000);
+					continue;
+				}
+				return SCARD_F_COMM_ERROR;
+			}
+
+		    } while(rv == -1 && errno == EPIPE);
+
+		    Log3(PCSC_LOG_DEBUG, "Server is protocol version %d:%d",
+			veStr->major, veStr->minor);
+		    break;
+	  }
+
+	}
+	return SCARD_S_SUCCESS;
+}
+
 
 /**
  * @brief Closes the communications channel used by the server to talk to the
@@ -438,7 +892,111 @@
  */
 INTERNAL void SHMCleanupSharedSegment(int sockValue, char *pcFilePath)
 {
+	Log2(PCSC_LOG_DEBUG, "SHMCleanupSharedSegment(fd=%d)", sockValue);
 	SYS_CloseFile(sockValue);
 	SYS_Unlink(pcFilePath);
 }
 
+
+/*
+ * This is used to determine the availability of the PCSClite
+ * service.  It only ping the launcher.
+ */
+ INTERNAL int SHMping() {
+	union {
+	     struct sockaddr s;
+	     struct sockaddr_in i;
+	} serv_addr;
+	int one, fd, rv;
+	fd_set read_fd;
+	struct timeval tv;
+	char buf[20], cmp[80];
+
+
+	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)  {
+		Log2(PCSC_LOG_CRITICAL,
+			"ping: Error creating client socket: %s",
+			strerror(errno));
+		return -1;
+	}
+	serv_addr.i.sin_family = AF_INET;
+	serv_addr.i.sin_port = htons(pcscCfg.portNbr);
+	bcopy((char *)&pcscCfg.xHostIp, (char *)&serv_addr.i.sin_addr.s_addr,
+	     sizeof (pcscCfg.xHostIp));
+
+	if ((rv = connect(fd, &serv_addr.s, sizeof (serv_addr))) < 0) {
+		if (rv < 0) {
+			while (rv < 0 && (errno == EINTR || errno == EAGAIN)) {
+				usleep(50000);
+				rv = connect(fd, &serv_addr.s, sizeof (serv_addr));
+			}
+			if (rv < 0) {
+				Log3(PCSC_LOG_INFO,
+					"ping: Server connect err:\n%d: %s",
+					errno, strerror(errno));
+				close(fd);
+				return -1;
+			}
+		}
+	}
+	bzero(buf, sizeof (buf));
+	sprintf(cmp, "PING %d\r", getpid());
+	write(fd, cmp, strlen(cmp));
+
+	tv.tv_sec = CONNECT_TIMEOUT;
+	tv.tv_usec = 0;
+
+	FD_ZERO(&read_fd);
+	FD_SET(fd, &read_fd);
+	rv = select(fd + 1, &read_fd, NULL, NULL, &tv);
+	if (rv < 0) {
+		int connreset = 0;
+		while (rv < 0 && (errno == EINTR || errno == EAGAIN || errno == ECONNRESET)) {
+			if (errno == ECONNRESET && ++connreset > 20)
+				break;
+			usleep(50000);
+			rv = select(fd + 1, &read_fd, NULL, NULL, &tv);
+		}
+		if (rv < 0) {
+			Log2(PCSC_LOG_INFO,
+				"ping: select() error: %s", strerror(errno));
+			close(fd);
+			return -1;      // Error
+		}
+	} else if (rv == 0) {
+		Log2(PCSC_LOG_ERROR,
+			"ping: Launcher reply timed out after %d sec.",
+			CONNECT_TIMEOUT);
+		close(fd);
+		return -1;      // Timeout
+	}
+	if (FD_ISSET(fd, &read_fd)) {
+		int connreset = 0;
+		if ((rv = read(fd, buf, sizeof (buf))) < 0) {
+			while (rv < 0 && (errno == EINTR || errno == EAGAIN || errno == ECONNRESET)) {
+				if (errno == ECONNRESET && ++connreset > 20)
+					break;
+				usleep(50000);
+				rv = read(fd, buf, sizeof (buf));
+			}
+			if (rv < 0) {
+				Log3(PCSC_LOG_INFO,
+					"ping: Err reading launcher "
+					"reply after select (reset cnt=%d): %s",
+					 connreset, strerror(errno));
+				close(fd);
+				return -1;      // Error
+			}
+		}
+	}
+
+	sprintf(cmp, "ACK %d", getpid());
+	if (strncmp(buf, cmp, strlen(cmp)) == 0) {
+		close(fd);
+		return 0;
+	}
+	Log2(PCSC_LOG_INFO, "Error pinging launcher."
+		"Reply was: %s\n", buf);
+	close(fd);
+	return -1;
+}

Modified: branches/Solaris/src/winscard_msg.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/winscard_msg.h?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/winscard_msg.h (original)
+++ branches/Solaris/src/winscard_msg.h Thu Jun 12 10:28:09 2008
@@ -18,6 +18,11 @@
 #ifndef __winscard_msg_h__
 #define __winscard_msg_h__
 
+#include <netdb.h>
+#include "clientcred.h"
+#include "readerfactory.h"
+#include "eventhandler.h"
+
 /** Major version of the current message protocol */
 #define PROTOCOL_VERSION_MAJOR 2
 /** Minor version of the current message protocol */
@@ -52,6 +57,7 @@
 	}
 	sharedSegmentMsg, *psharedSegmentMsg;
 
+
 	/**
 	 * Command types available to use in the field \c sharedSegmentMsg.mtype.
 	 */
@@ -64,7 +70,8 @@
 		CMD_READER_EVENT = 0xF5,
 		CMD_SYN = 0xF6,
 		CMD_ACK = 0xF7,
-		CMD_VERSION = 0xF8
+		CMD_VERSION = 0xF8,
+		CMD_FETCH = 0xF9
 	};
 
 	/**
@@ -88,8 +95,29 @@
 		SCARD_CANCEL_TRANSACTION = 0x0E,
 		SCARD_GET_ATTRIB = 0x0F,
 		SCARD_SET_ATTRIB = 0x10,
-		SCARD_TRANSMIT_EXTENDED = 0x11
-	};
+		SCARD_TRANSMIT_EXTENDED = 0x11,
+		FETCH_READER_STATE = 0x12
+	};
+
+
+	/**
+	 * @brief Information transmitted in \c CMD_VERSION Messages.
+	 */
+	struct fetch_struct
+	{       union {
+			struct {
+				size_t size;
+				void *addr;
+			} mem;
+			unsigned int index;
+
+		} type;
+		unsigned char
+		     data[PCSCLITE_MAX_MESSAGE_SIZE - 256];
+		LONG rv;
+	};
+	typedef struct fetch_struct fetch_struct;
+
 
 	/**
 	 * @brief Information transmitted in \c CMD_VERSION Messages.
@@ -102,12 +130,6 @@
 	};
 	typedef struct version_struct version_struct;
 
-	struct client_struct
-	{
-		SCARDCONTEXT hContext;
-	};
-	typedef struct client_struct client_struct;
-
 	/**
 	 * @brief Information contained in \c SCARD_ESTABLISH_CONTEXT Messages.
 	 *
@@ -118,6 +140,10 @@
 		DWORD dwScope;
 		SCARDCONTEXT phContext;
 		LONG rv;
+		in_addr_t clientXhostIP;
+		LONG dpyNbr;
+		LONG screenNbr;
+
 	};
 	typedef struct establish_struct establish_struct;
 
@@ -266,7 +292,7 @@
 		DWORD pcbRecvLength;
 		LONG rv;
 		size_t size;
-		BYTE data[0];
+		BYTE data[1];
 	};
 	typedef struct transmit_struct_extended transmit_struct_extended;
 
@@ -304,15 +330,20 @@
 	typedef struct getset_struct getset_struct;
 
 	/*
-	 * Now some function definitions 
-	 */
-
+	 * Now some function definitions
+	 */
+
+	int SHMrpc(unsigned int, DWORD, void *, unsigned int);
+	int SHMping();
+	int SHMCheckProtocolVersion(int, int, DWORD);
+	int SHMfetchReaderState(PREADER_STATE, unsigned int, DWORD);
 	int SHMClientRead(psharedSegmentMsg, DWORD, int);
 	int SHMClientSetupSession(PDWORD);
 	int SHMClientCloseSession(DWORD);
 	int SHMInitializeCommonSegment(void);
-	int SHMProcessEventsContext(PDWORD, psharedSegmentMsg, int);
+	int SHMProcessEventsContext(PDWORD, DWORD, psharedSegmentMsg, int);
 	int SHMProcessEventsServer(PDWORD, int);
+	int SHMGetClientCreds(int, PCSCLITE_CRED_T *);
 	int SHMMessageSend(void *buffer, size_t buffer_size, int filedes,
 		int blockAmount);
 	int SHMMessageReceive(void *buffer, size_t buffer_size,

Modified: branches/Solaris/src/winscard_msg_srv.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/winscard_msg_srv.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/winscard_msg_srv.c (original)
+++ branches/Solaris/src/winscard_msg_srv.c Thu Jun 12 10:28:09 2008
@@ -34,9 +34,12 @@
 #ifdef HAVE_SYS_FILIO_H
 #include <sys/filio.h>
 #endif
-
+#ifdef HAVE_SYS_DOOR_H
+#include <door.h>
+#endif
 #include "misc.h"
 #include "pcsclite.h"
+#include "pcsc_config.h"
 #include "winscard.h"
 #include "debuglog.h"
 #include "winscard_msg.h"
@@ -96,60 +99,102 @@
 /**
  * @brief Prepares the communication channel used by the server to talk to the
  * clients.
- *
+ *  
  * This is called by the server to create a socket for local IPC with the
- * clients. The socket is associated to the file \c PCSCLITE_CSOCK_NAME.
+ * clients. The socket is associated to the file \c PCSCLITE_CSOCK_NAME by default
+ * but this can be overridden in the global configuration file pcscd.conf, and
+ * affected by the -b or INSTANCE_BASE_DIR key-value setting in pcscd.conf
+ *
  * Each client will open a connection to this socket.
  * 
  * @return Error code.
  * @retval 0 Success
  * @retval -1 Can not create the socket.
- * @retval -1 Can not bind the socket to the file \c PCSCLITE_CSOCK_NAME.
+ * @retval -1 Can not bind the socket to the file
  * @retval -1 Can not put the socket in listen mode.
  */
 INTERNAL int SHMInitializeCommonSegment(void)
 {
-	static struct sockaddr_un serv_adr;
-
-	/*
-	 * Create the common shared connection socket 
-	 */
-	if ((commonSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
-	{
-		Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
-			strerror(errno));
-		return -1;
-	}
-
-	serv_adr.sun_family = AF_UNIX;
-	strncpy(serv_adr.sun_path, PCSCLITE_CSOCK_NAME,
-		sizeof(serv_adr.sun_path));
-	SYS_Unlink(PCSCLITE_CSOCK_NAME);
-
-	if (bind(commonSocket, (struct sockaddr *) &serv_adr,
-			sizeof(serv_adr.sun_family) + strlen(serv_adr.sun_path) + 1) < 0)
-	{
-		Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
-			strerror(errno));
-		SHMCleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
-		return -1;
-	}
-
-	if (listen(commonSocket, 1) < 0)
-	{
-		Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
-			strerror(errno));
-		SHMCleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
-		return -1;
-	}
-
-	/*
-	 * Chmod the public entry channel 
-	 */
-	SYS_Chmod(PCSCLITE_CSOCK_NAME, S_IRWXO | S_IRWXG | S_IRWXU);
-
-	return 0;
-}
+        switch(pcscCfg.transportType) {
+        case SOCKET_UNIX: {
+        	static struct sockaddr_un serv_adr;
+
+	        /*
+	         * Create the common shared connection socket 
+	         */
+	        if ((commonSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+        		Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
+	                    strerror(errno));
+		        return -1;
+	        }
+
+	        serv_adr.sun_family = AF_UNIX;
+	        strncpy(serv_adr.sun_path, pcscCfg.netBindFile,
+        		sizeof(serv_adr.sun_path));
+        	
+                SYS_Unlink(pcscCfg.netBindFile);
+
+        	if (bind(commonSocket, (struct sockaddr *) &serv_adr,
+		    sizeof(serv_adr.sun_family) + strlen(serv_adr.sun_path) + 1) < 0) {
+        		Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
+	        	    strerror(errno));
+		        SHMCleanupSharedSegment(commonSocket, pcscCfg.netBindFile);
+		        return -1;
+	        }
+
+	        if (listen(commonSocket, 1) < 0)  {
+		        Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
+			   strerror(errno));
+		        SHMCleanupSharedSegment(commonSocket, pcscCfg.netBindFile);
+		        return -1;
+	        }
+
+	        /*
+	         * Chmod the public entry channel 
+	         */
+	        SYS_Chmod(pcscCfg.netBindFile, S_IRWXO | S_IRWXG | S_IRWXU);
+
+                return 0;
+        }
+        case SOCKET_INETV4: {
+                union {
+                     struct sockaddr s;
+                     struct sockaddr_in i;
+                } serv_adr;
+                
+                /*
+	         * Create the common shared connection socket 
+	         */
+	        if ((commonSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+        		Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
+	                    strerror(errno));
+		        return -1;
+	        }
+
+                serv_adr.i.sin_family = AF_INET;
+                serv_adr.i.sin_port = htons(pcscCfg.portNbr);
+                serv_adr.i.sin_addr.s_addr = INADDR_ANY;
+                
+        	if (bind(commonSocket, (struct sockaddr *) &serv_adr,sizeof(serv_adr)) < 0) {
+        		Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
+	        	    strerror(errno));
+		        SHMCleanupSharedSegment(commonSocket, pcscCfg.netBindFile);
+		        return -1;
+	        }
+	        
+                if (listen(commonSocket, 1) < 0)  {
+		        Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
+			   strerror(errno));
+		        SHMCleanupSharedSegment(commonSocket, pcscCfg.netBindFile);
+		        return -1;
+	        }
+                return 0;
+          }
+        }
+        return -1;
+}
+
+
 
 /**
  * @brief Looks for messages sent by clients.
@@ -167,114 +212,163 @@
  */
 INTERNAL int SHMProcessEventsServer(PDWORD pdwClientID, int blocktime)
 {
-	fd_set read_fd;
-	int selret;
-	struct timeval tv;
 	
-	tv.tv_sec = 1;
-	tv.tv_usec = 0;
-
-	FD_ZERO(&read_fd);
-
-	/*
-	 * Set up the bit masks for select 
-	 */
-	FD_SET(commonSocket, &read_fd);
-
-	selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
-		(fd_set *) NULL, &tv);
-
-	if (selret < 0)
-	{
-		if ((!AraKiri) && (!ReCheckSerialReaders))
-			Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
-				strerror(errno));
-		return -1;
+       fd_set read_fd;
+       int selret;
+       struct timeval tv;
+
+       tv.tv_sec = 1;
+       tv.tv_usec = 0;
+
+       FD_ZERO(&read_fd);
+
+       /*
+        * Set up the bit masks for select 
+        */
+       FD_SET(commonSocket, &read_fd);
+
+       selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
+               (fd_set *) NULL, &tv);
+
+       if (selret < 0)
+       {
+               if ((!AraKiri) && (!ReCheckSerialReaders))
+                       Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
+                               strerror(errno));
+               return -1;
+       }
+
+       if (selret == 0)
+               /* timeout */
+               return 2;
+       /*
+        * A common pipe packet has arrived - it could be a new application  
+        */
+       if (FD_ISSET(commonSocket, &read_fd))
+       {
+               Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
+               if (SHMProcessCommonChannelRequest(pdwClientID) == -1)
+               {
+                       Log2(PCSC_LOG_ERROR,
+                            "error in SHMProcessCommonChannelRequest: %d", 
+                            *pdwClientID);
+                       return -1;
+               } else
+               {
+                       Log2(PCSC_LOG_DEBUG,
+                            "SHMProcessCommonChannelRequest detects: %d", 
+                            *pdwClientID);
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+INTERNAL char *getRPCname(int rpcIndex) 
+{
+	switch(rpcIndex) {
+        case SCARD_ESTABLISH_CONTEXT:
+		return "ESTABLISH_CONTEXT";
+	case SCARD_RELEASE_CONTEXT:
+		return "RELEASE_CONTEXT";
+	case SCARD_CONNECT:
+		return "CONNECT";
+	case SCARD_RECONNECT:
+		return "RECONNECT";
+	case SCARD_DISCONNECT:
+		return "DISCONNECT";
+	case SCARD_BEGIN_TRANSACTION:
+		return "BEGIN_TRANSACTION";
+	case SCARD_END_TRANSACTION:
+		return "END_TRANSACTION";
+	case SCARD_CANCEL_TRANSACTION:
+		return "CANCEL_TRANSACTION";
+	case SCARD_STATUS:
+		return "STATUS";
+	case SCARD_TRANSMIT:
+		return "TRANSMIT";
+	case SCARD_CONTROL:
+		return "CONTROL";
+	case SCARD_GET_ATTRIB:
+		return "GET_ATTRIB";
+	case SCARD_SET_ATTRIB:
+		return "SET_ATTRIB";
+	case SCARD_TRANSMIT_EXTENDED:
+		return "TRANSMIT_EXTENDED";
+	default:
+		return "UNKNOWN";
 	}
 
-	if (selret == 0)
-		/* timeout */
-		return 2;
-	/*
-	 * A common pipe packet has arrived - it could be a new application  
-	 */
-	if (FD_ISSET(commonSocket, &read_fd))
-	{
-		Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
-		if (SHMProcessCommonChannelRequest(pdwClientID) == -1)
-		{
-			Log2(PCSC_LOG_ERROR,
-				"error in SHMProcessCommonChannelRequest: %d", *pdwClientID);
-			return -1;
-		} else
-		{
-			Log2(PCSC_LOG_DEBUG,
-				"SHMProcessCommonChannelRequest detects: %d", *pdwClientID);
-			return 0;
-		}
-	}
-	
-	return -1;
-}
-
+}
 /**
  * @brief 
  *
  * Called by \c ContextThread().
  */
-INTERNAL int SHMProcessEventsContext(PDWORD pdwClientID, psharedSegmentMsg msgStruct, int blocktime)
-{
-	fd_set read_fd;
-	int selret, rv;
-	struct timeval tv;
-
-	tv.tv_sec = 1;
-	tv.tv_usec = 0;
-
-	FD_ZERO(&read_fd);
-	FD_SET(*pdwClientID, &read_fd);
-
-	selret = select(*pdwClientID + 1, &read_fd, (fd_set *) NULL,
-		(fd_set *) NULL, &tv);
-
-	if (selret < 0)
-	{
-		Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
-			strerror(errno));
-		return -1;
-	}
-
-	if (selret == 0)
-		/* timeout */
-		return 2;
-
-	if (FD_ISSET(*pdwClientID, &read_fd))
-	{
-		/*
-		 * Return the current handle 
-		 */
-		rv = SHMMessageReceive(msgStruct, sizeof(*msgStruct), *pdwClientID,
-				       PCSCLITE_SERVER_ATTEMPTS);
-		
-		if (rv == -1)
-		{	/* The client has died */
-			Log2(PCSC_LOG_DEBUG, "Client has disappeared: %d",
-				*pdwClientID);
-			msgStruct->mtype = CMD_CLIENT_DIED;
-			msgStruct->command = 0;
-			SYS_CloseFile(*pdwClientID);
-
-			return 0;
-		}
-		
-		/*
-		 * Set the identifier handle 
-		 */
-		Log2(PCSC_LOG_DEBUG, "correctly processed client: %d",
-			*pdwClientID);
-		return 1;
-	}
-	
-	return -1;
-}
-
+INTERNAL int SHMProcessEventsContext(PDWORD pdwClientID, DWORD dwContextIndex,
+                                     psharedSegmentMsg msgStruct, int blocktime)
+{
+       fd_set read_fd;
+       int selret, rv;
+       struct timeval tv;
+
+       tv.tv_sec = 1;
+       tv.tv_usec = 0;
+
+       FD_ZERO(&read_fd);
+       FD_SET(*pdwClientID, &read_fd);
+
+       selret = select(*pdwClientID + 1, &read_fd, (fd_set *) NULL,
+               (fd_set *) NULL, &tv);
+       if (selret < 0)
+       {
+               Log3(PCSC_LOG_ERROR, "Error from select() on fd=%d: %s",
+                       *pdwClientID, strerror(errno));
+               return -1;
+       }                                      
+
+       if (selret == 0) 
+               /* timeout */
+               return 2;
+       if (FD_ISSET(*pdwClientID, &read_fd))
+       {
+               /*
+                * Return the current handle 
+                */
+               rv = SHMMessageReceive(msgStruct, sizeof(*msgStruct), *pdwClientID,
+                                      PCSCLITE_SERVER_ATTEMPTS);		
+               if (rv == -1)
+               {	/* The client has died */
+                       Log3(PCSC_LOG_DEBUG, "Client fd=%d died:\n %s",
+                               *pdwClientID, strerror(errno));
+                       msgStruct->mtype = CMD_CLIENT_DIED;
+                       msgStruct->command = 0;
+ /**** PKK: ERROR this redundance close with MSGCleanupClient() is bad 
+  **** When this close() happens it allows accept() or ioctl( .. RECVFD ..)
+  **** to be assigned the new fd.  If a new SCardEstablishContext() is comming
+  **** along in between this close and the next that will be following shortly
+  **** the SCardEstablishContext() thread will get trashed, rarely and 
+  **** intermittantly, unless there is very heavy traffic as is the case
+  **** with SRC */
+//		       SYS_CloseFile(*pdwClientID);
+                       return 0;
+               }
+
+               switch(msgStruct->mtype) {
+               case CMD_FETCH:
+                       return 1;  /* Return without logging a message */
+	       case CMD_VERSION:
+		       Log2(PCSC_LOG_DEBUG, 
+			       "Version request OK (Client fd=%d)", 
+			       *pdwClientID);
+		       return 1;
+	       case CMD_FUNCTION:
+		       Log3(PCSC_LOG_DEBUG, 
+				"RPC OK for client %d: %s", 
+					*pdwClientID, getRPCname(msgStruct->command));
+                       return 1;
+               }
+       }
+       return -1;
+}
+

Modified: branches/Solaris/src/winscard_scf.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/winscard_scf.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/winscard_scf.c (original)
+++ branches/Solaris/src/winscard_scf.c Thu Jun 12 10:28:09 2008
@@ -591,7 +591,6 @@
 	int i;
 	DWORD dwReaderLen;
 	SCF_Card_t SCF_hCard;
-
 	if (SCARD_S_SUCCESS != isOCFServerRunning())
 		return SCARD_E_NO_SERVICE;
 	/* Zero out everything   */

Modified: branches/Solaris/src/winscard_svc.c
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/winscard_svc.c?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/winscard_svc.c (original)
+++ branches/Solaris/src/winscard_svc.c Thu Jun 12 10:28:09 2008
@@ -23,14 +23,28 @@
 #include <time.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+
 
 #include "pcsclite.h"
+#include "auth.h"
+#include "pcsc_config.h"
+#include "instance.h"
+#include "clientcred.h"
 #include "winscard.h"
 #include "debuglog.h"
 #include "winscard_msg.h"
 #include "winscard_svc.h"
+#include "winscard_client.h"
 #include "sys_generic.h"
 #include "thread_generic.h"
+#include "wintypes.h"
+#include "readerfactory.h"
+#include "eventhandler.h"
+#include "launcher.h"
+
 
 /**
  * @brief Represents the an Application Context on the Server side.
@@ -39,10 +53,15 @@
  */
 static struct _psContext
 {
+#ifdef _HAVE_SYS_DOORS_H
+	PCSCLITE_MUTEX mMutex;
+	PCSCLITE_COND  mCond;
+#endif
 	SCARDCONTEXT hContext;
 	SCARDHANDLE hCard[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
 	DWORD dwClientID;			/* Connection ID used to reference the Client. */
 	PCSCLITE_THREAD_T pthThread;		/* Event polling thread's ID */
+	PCSCLITE_CRED_T cred;                   /* Client credentials struct */
 	sharedSegmentMsg msgStruct;		/* Msg sent by the Client */
 	int protocol_major, protocol_minor;	/* Protocol number agreed between client and server*/
 } psContext[PCSCLITE_MAX_APPLICATIONS_CONTEXTS];
@@ -59,7 +78,8 @@
 
 LONG ContextsInitialize(void)
 {
-	memset(psContext, 0, sizeof(struct _psContext)*PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
+	memset(psContext, 0,
+	    sizeof(struct _psContext)*PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
 	return 1;
 }
 
@@ -70,13 +90,21 @@
  *
  * @return Error code.
  * @retval SCARD_S_SUCCESS Success.
- * @retval SCARD_F_INTERNAL_ERROR Exceded the maximum number of simultaneous Application Contexts.
+ * @retval SCARD_F_INTERNAL_ERROR Exceded the maximum number of
+ *         simultaneous Application Contexts.
  * @retval SCARD_E_NO_MEMORY Error creating the Context Thread.
  */
-LONG CreateContextThread(PDWORD pdwClientID)
+
+LONG
+CreateContextThread(PDWORD pdwClientID)
 {
 	int i;
 
+
+	/*
+	 * If we're running as launcher the context lookup lock
+	 * is already held.
+	 */
 	for (i = 0; i < PCSCLITE_MAX_APPLICATIONS_CONTEXTS; i++)
 	{
 		if (psContext[i].dwClientID == 0)
@@ -87,21 +115,24 @@
 		}
 	}
 
+	if (pcscCfg.launchMode == INSTANCE)
+		UnlockContextLookup();
+
 	if (i == PCSCLITE_MAX_APPLICATIONS_CONTEXTS)
 	{
 		SYS_CloseFile(psContext[i].dwClientID);
-		psContext[i].dwClientID = 0; 
+		psContext[i].dwClientID = 0;
 		Log2(PCSC_LOG_CRITICAL, "No more context available (max: %d)",
 			PCSCLITE_MAX_APPLICATIONS_CONTEXTS);
 		return SCARD_F_INTERNAL_ERROR;
 	}
-	
+
 	if (SYS_ThreadCreate(&psContext[i].pthThread, THREAD_ATTR_DETACHED,
 		(PCSCLITE_THREAD_FUNCTION( )) ContextThread,
 		(LPVOID) i) != 1)
 	{
 		SYS_CloseFile(psContext[i].dwClientID);
-		psContext[i].dwClientID = 0; 
+		psContext[i].dwClientID = 0;
 		Log1(PCSC_LOG_CRITICAL, "SYS_ThreadCreate failed");
 		return SCARD_E_NO_MEMORY;
 	}
@@ -109,9 +140,11 @@
 	return SCARD_S_SUCCESS;
 }
 
+
+
 /*
  * A list of local functions used to keep track of clients and their
- * connections 
+ * connections
  */
 
 /**
@@ -119,7 +152,7 @@
  *
  * For each Client message a new instance of this thread is created.
  *
- * @param[in] dwIndex Index of an avaiable Application Context slot in 
+ * @param[in] dwIndex Index of an avaiable Application Context slot in
  * \c psContext.
  */
 static void ContextThread(LPVOID dwIndex)
@@ -127,13 +160,17 @@
 	LONG rv;
 	sharedSegmentMsg msgStruct;
 	DWORD dwContextIndex = (DWORD)dwIndex;
-
-	Log2(PCSC_LOG_DEBUG, "Thread is started: %d",
+	int saveRemaining;
+	static unsigned long fn;
+
+	Log2(PCSC_LOG_DEBUG, "Context thread started for client (fd=%d)",
 		psContext[dwContextIndex].dwClientID);
-	
+
 	while (1)
 	{
-		switch (rv = SHMProcessEventsContext(&psContext[dwContextIndex].dwClientID, &msgStruct, 0))
+		switch (rv = SHMProcessEventsContext(
+			&psContext[dwContextIndex].dwClientID,
+			dwContextIndex, &msgStruct, 0))
 		{
 		case 0:
 			if (msgStruct.mtype == CMD_CLIENT_DIED)
@@ -141,11 +178,12 @@
 				/*
 				 * Clean up the dead client
 				 */
-				Log2(PCSC_LOG_DEBUG, "Client die: %d",
+				Log2(PCSC_LOG_DEBUG,
+					"Client fd=%d died. Shutting down thread",
 					psContext[dwContextIndex].dwClientID);
 				MSGCleanupClient(dwContextIndex);
 				SYS_ThreadExit((LPVOID) NULL);
-			} 
+			}
 			break;
 
 		case 1:
@@ -156,42 +194,78 @@
 				 */
 				MSGFunctionDemarshall(&msgStruct, dwContextIndex);
 
-				/* the SCARD_TRANSMIT_EXTENDED anwser is already sent by
-				 * MSGFunctionDemarshall */
-				if (msgStruct.command != SCARD_TRANSMIT_EXTENDED)
-					rv = SHMMessageSend(&msgStruct, sizeof(msgStruct),
-						psContext[dwContextIndex].dwClientID,
-						PCSCLITE_SERVER_ATTEMPTS);
+				switch(pcscCfg.transportType) {
+				case SOCKET_UNIX:
+				case SOCKET_INETV4:
+					/* the SCARD_TRANSMIT_EXTENDED anwser is already sent by
+					* MSGFunctionDemarshall */
+					if (msgStruct.command != SCARD_TRANSMIT_EXTENDED)
+						rv = SHMMessageSend(&msgStruct, sizeof(msgStruct),
+							psContext[dwContextIndex].dwClientID,
+							PCSCLITE_SERVER_ATTEMPTS);
+
+					break;
+				}
 			}
 			else
-				/* pcsc-lite client/server protocol version */
-				if (msgStruct.mtype == CMD_VERSION)
-				{
-					version_struct *veStr;
-					veStr = (version_struct *) msgStruct.data;
-
-					/* get the client protocol version */
-					psContext[dwContextIndex].protocol_major = veStr->major;
-					psContext[dwContextIndex].protocol_minor = veStr->minor;
-
-					Log3(PCSC_LOG_DEBUG,
-						"Client is protocol version %d:%d",
-						veStr->major, veStr->minor);
-
-					/* set the server protocol version */
-					veStr->major = PROTOCOL_VERSION_MAJOR;
-					veStr->minor = PROTOCOL_VERSION_MINOR;
-					veStr->rv = SCARD_S_SUCCESS;
-
+			if (msgStruct.mtype == CMD_VERSION) /* client/server protocol version */
+			{
+				version_struct *veStr;
+				veStr = (version_struct *) msgStruct.data;
+
+				/* get the client protocol version */
+				psContext[dwContextIndex].protocol_major = veStr->major;
+				psContext[dwContextIndex].protocol_minor = veStr->minor;
+
+				Log3(PCSC_LOG_DEBUG,
+					"Client is protocol version %d:%d ",
+					veStr->major, veStr->minor);
+
+
+				/* set the server protocol version */
+				veStr->major = PROTOCOL_VERSION_MAJOR;
+				veStr->minor = PROTOCOL_VERSION_MINOR;
+				veStr->rv = SCARD_S_SUCCESS;
+
+				switch(pcscCfg.transportType) {
+				case SOCKET_UNIX:
+				case SOCKET_INETV4:
 					/* send back the response */
 					rv = SHMMessageSend(&msgStruct, sizeof(msgStruct),
 						psContext[dwContextIndex].dwClientID,
-					    PCSCLITE_SERVER_ATTEMPTS);
+							PCSCLITE_SERVER_ATTEMPTS);
+					break;
 				}
-				else
-					continue;
-
-			break;
+			}
+			else
+		if (msgStruct.mtype == CMD_FETCH) /* Request data */
+			{
+				++fn;
+				fetch_struct *pfetch;
+				pfetch = (fetch_struct *)msgStruct.data;
+
+				switch(msgStruct.command) {
+				case FETCH_READER_STATE: {
+					pfetch->rv = EHfetchReaderState(
+							pfetch->type.index,
+							(PREADER_STATE)pfetch->data);
+					break;
+				   }
+				}
+				switch(pcscCfg.transportType) {
+				case SOCKET_UNIX:
+				case SOCKET_INETV4:
+					/* send back the response */
+					rv = SHMMessageSend(&msgStruct, sizeof(msgStruct),
+						psContext[dwContextIndex].dwClientID,
+							PCSCLITE_SERVER_ATTEMPTS);
+					break;
+				}
+			}
+			else
+				continue;
+
+
 
 		case 2:
 			/*
@@ -200,14 +274,30 @@
 			 * nothing else happens
 			 */
 			break;
-			
+
 		case -1:
+			if (pcscCfg.pcscdExiting) {
+				Log1(PCSC_LOG_ERROR,
+					"SHMProcessEventsContext: Exit flag set."
+					"Context thread terminating\n");
+				return;
+			}
 			Log1(PCSC_LOG_ERROR, "Error in SHMProcessEventsContext");
+			if (msgStruct.mtype == CMD_FETCH)
+				Log2(PCSC_LOG_ERROR, "Fetch seq# %ld", fn);
 			break;
-			
+
 		default:
+			if (pcscCfg.pcscdExiting) {
+				Log1(PCSC_LOG_ERROR,
+					"SHMProcessEventsContext: Exit flag set."
+					"Context thread terminating\n");
+				return;
+			}
 			Log2(PCSC_LOG_ERROR,
 				"SHMProcessEventsContext unknown retval: %d", rv);
+			if (msgStruct.mtype == CMD_FETCH)
+				Log2(PCSC_LOG_ERROR, "Fetch seq# %ld", fn);
 			break;
 		}
 	}
@@ -220,17 +310,17 @@
  * cast the message data to the correct struct so that is can be demarshalled.
  * Then call the appropriate function to handle the request.
  *
- * Possible structs are: \c establish_struct \c release_struct 
+ * Possible structs are: \c establish_struct \c release_struct
  * \c connect_struct \c reconnect_struct \c disconnect_struct \c begin_struct
  * \c cancel_struct \c end_struct \c status_struct \c transmit_struct
  * \c control_struct \c getset_struct.
  *
  * @param[in] msgStruct Message to be demarshalled and executed.
- * @param[in] dwContextIndex 
+ * @param[in] dwContextIndex
  */
 LONG MSGFunctionDemarshall(psharedSegmentMsg msgStruct, DWORD dwContextIndex)
 {
-	LONG rv;
+	LONG rv = 0;
 	establish_struct *esStr;
 	release_struct *reStr;
 	connect_struct *coStr;
@@ -243,18 +333,23 @@
 	transmit_struct *trStr;
 	control_struct *ctStr;
 	getset_struct *gsStr;
-
-	/*
-	 * Zero out everything 
-	 */
-	rv = 0;
+	PCSCLITE_CRED_T *cred;
+
 	switch (msgStruct->command)
 	{
 
 	case SCARD_ESTABLISH_CONTEXT:
 		esStr = ((establish_struct *) msgStruct->data);
-		esStr->rv = SCardEstablishContext(esStr->dwScope, 0, 0,
-			&esStr->phContext);
+
+		cred = &psContext[dwContextIndex].cred;
+		cred->dpyNbr = esStr->dpyNbr;
+		cred->screenNbr = esStr->screenNbr;
+		cred->clientXhostIP = esStr->clientXhostIP;
+
+		AUTHGetClientCreds(psContext[dwContextIndex].dwClientID, cred);
+
+		esStr->rv = SCardEstablishContext(esStr->dwScope, 0,
+			(LPVOID *)cred, &esStr->phContext);
 
 		if (esStr->rv == SCARD_S_SUCCESS)
 			esStr->rv =
@@ -286,8 +381,10 @@
 	case SCARD_RECONNECT:
 		rcStr = ((reconnect_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(rcStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-
+		if (rv != 0) {
+			rcStr->rv = rv;
+			return rv;
+		}
 		rcStr->rv = SCardReconnect(rcStr->hCard, rcStr->dwShareMode,
 			rcStr->dwPreferredProtocols,
 			rcStr->dwInitialization, &rcStr->pdwActiveProtocol);
@@ -296,25 +393,35 @@
 	case SCARD_DISCONNECT:
 		diStr = ((disconnect_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(diStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
+		if (rv != 0) {
+			diStr->rv = 0; /* make idempotent */
+			return rv;
+		}
 		diStr->rv = SCardDisconnect(diStr->hCard, diStr->dwDisposition);
 
 		if (diStr->rv == SCARD_S_SUCCESS)
 			diStr->rv =
 				MSGRemoveHandle(diStr->hCard, dwContextIndex);
+
 		break;
 
 	case SCARD_BEGIN_TRANSACTION:
 		beStr = ((begin_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(beStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
+		if (rv != 0) {
+			beStr->rv = rv;
+			return rv;
+		}
 		beStr->rv = SCardBeginTransaction(beStr->hCard);
 		break;
 
 	case SCARD_END_TRANSACTION:
 		enStr = ((end_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(enStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
+		if (rv != 0) {
+			enStr->rv = rv;
+			return rv;
+		}
 		enStr->rv =
 			SCardEndTransaction(enStr->hCard, enStr->dwDisposition);
 		break;
@@ -322,14 +429,20 @@
 	case SCARD_CANCEL_TRANSACTION:
 		caStr = ((cancel_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(caStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
+		if (rv != 0) {
+			caStr->rv = rv;
+			return rv;
+		}
 		caStr->rv = SCardCancelTransaction(caStr->hCard);
 		break;
 
 	case SCARD_STATUS:
 		stStr = ((status_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(stStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
+		if (rv != 0) {
+			stStr->rv = rv;
+			return rv;
+		}
 		stStr->rv = SCardStatus(stStr->hCard, stStr->mszReaderNames,
 			&stStr->pcchReaderLen, &stStr->pdwState,
 			&stStr->pdwProtocol, stStr->pbAtr, &stStr->pcbAtrLen);
@@ -338,7 +451,10 @@
 	case SCARD_TRANSMIT:
 		trStr = ((transmit_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(trStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
+		if (rv != 0) {
+			trStr->rv = rv;
+			return rv;
+		}
 		trStr->rv = SCardTransmit(trStr->hCard, &trStr->pioSendPci,
 			trStr->pbSendBuffer, trStr->cbSendLength,
 			&trStr->pioRecvPci, trStr->pbRecvBuffer,
@@ -348,7 +464,10 @@
 	case SCARD_CONTROL:
 		ctStr = ((control_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(ctStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
+		if (rv != 0) {
+			ctStr->rv = rv;
+			return rv;
+		}
 		ctStr->rv = SCardControl(ctStr->hCard, ctStr->dwControlCode,
 			ctStr->pbSendBuffer, ctStr->cbSendLength,
 			ctStr->pbRecvBuffer, ctStr->cbRecvLength,
@@ -358,7 +477,10 @@
 	case SCARD_GET_ATTRIB:
 		gsStr = ((getset_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
+		if (rv != 0) {
+			gsStr->rv = rv;
+			return rv;
+		}
 		gsStr->rv = SCardGetAttrib(gsStr->hCard, gsStr->dwAttrId,
 			gsStr->pbAttr, &gsStr->cbAttrLen);
 		break;
@@ -366,7 +488,10 @@
 	case SCARD_SET_ATTRIB:
 		gsStr = ((getset_struct *) msgStruct->data);
 		rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
+		if (rv != 0) {
+			gsStr->rv = rv;
+			return rv;
+		}
 		gsStr->rv = SCardSetAttrib(gsStr->hCard, gsStr->dwAttrId,
 			gsStr->pbAttr, gsStr->cbAttrLen);
 		break;
@@ -379,7 +504,10 @@
 
 			treStr = ((transmit_struct_extended *) msgStruct->data);
 			rv = MSGCheckHandleAssociation(treStr->hCard, dwContextIndex);
-			if (rv != 0) return rv;
+			if (rv != 0) {
+				treStr->rv = rv;
+				return rv;
+			}
 
 			/* on more block to read? */
 			if (treStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
@@ -420,7 +548,7 @@
 
 				rv = SHMMessageSend(pbRecvBuffer + PCSCLITE_MAX_MESSAGE_SIZE
 					- sizeof(*treStr),
-					treStr->size - PCSCLITE_MAX_MESSAGE_SIZE, 
+					treStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
 					psContext[dwContextIndex].dwClientID,
 					PCSCLITE_SERVER_ATTEMPTS);
 				if (rv)
@@ -437,6 +565,8 @@
 				if (rv)
 					Log1(PCSC_LOG_CRITICAL, "transmission failed");
 			}
+			if (rv)
+				treStr->rv = rv;
 		}
 		break;
 
@@ -465,27 +595,28 @@
 		for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
 		{
 			/*
-			 * Disconnect each of these just in case 
+			 * Disconnect each of these just in case
 			 */
-			
+
 			if (psContext[dwContextIndex].hCard[i] != 0)
 			{
-				
+
 				/*
-				 * We will use SCardStatus to see if the card has been 
+				 * We will use SCardStatus to see if the card has been
 				 * reset there is no need to reset each time
-				 * Disconnect is called 
+				 * Disconnect is called
 				 */
-				
 				rv = SCardStatus(psContext[dwContextIndex].hCard[i], 0, 0, 0, 0, 0, 0);
-				
+
 				if (rv == SCARD_W_RESET_CARD
 				    || rv == SCARD_W_REMOVED_CARD)
 				{
-					SCardDisconnect(psContext[dwContextIndex].hCard[i], SCARD_LEAVE_CARD);
+					SCardDisconnect(psContext[dwContextIndex].hCard[i],
+							SCARD_LEAVE_CARD);
 				} else
 				{
-					SCardDisconnect(psContext[dwContextIndex].hCard[i], SCARD_RESET_CARD);
+					SCardDisconnect(psContext[dwContextIndex].hCard[i],
+							SCARD_RESET_CARD);
 				}
 
 				psContext[dwContextIndex].hCard[i] = 0;
@@ -495,8 +626,7 @@
 
 		psContext[dwContextIndex].hContext = 0;
 		return SCARD_S_SUCCESS;
-	} 
-
+	}
 	return SCARD_E_INVALID_VALUE;
 }
 
@@ -506,9 +636,9 @@
 
 	if (psContext[dwContextIndex].hContext == hContext)
 	{
-		
+
 		/*
-		 * Find an empty spot to put the hCard value 
+		 * Find an empty spot to put the hCard value
 		 */
 		for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
 		{
@@ -518,7 +648,7 @@
 				break;
 			}
 		}
-		
+
 		if (i == PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS)
 		{
 			return SCARD_F_INTERNAL_ERROR;
@@ -528,7 +658,6 @@
 		}
 
 	}
-	
 	return SCARD_E_INVALID_VALUE;
 }
 
@@ -544,7 +673,6 @@
 			return SCARD_S_SUCCESS;
 		}
 	}
-
 	return SCARD_E_INVALID_VALUE;
 }
 
@@ -560,7 +688,7 @@
 			return 0;
 		}
 	}
-	
+
 	/* Must be a rogue client, debug log and sleep a couple of seconds */
 	Log1(PCSC_LOG_ERROR, "Client failed to authenticate");
 	SYS_Sleep(2);
@@ -568,17 +696,44 @@
 	return -1;
 }
 
+
 LONG MSGCleanupClient(DWORD dwContextIndex)
 {
-	if (psContext[dwContextIndex].hContext != 0)
-	{
-		SCardReleaseContext(psContext[dwContextIndex].hContext);	
+	int i, tally = 0;
+
+	Log3(PCSC_LOG_DEBUG,
+	     "MSGCleanupClient(%d) close fd=%d.",
+	     dwContextIndex, psContext[dwContextIndex].dwClientID );
+
+	LockContextLookup();
+
+	if (psContext[dwContextIndex].hContext != 0) {
+		SCardReleaseContext(psContext[dwContextIndex].hContext);
 		MSGRemoveContext(psContext[dwContextIndex].hContext, dwContextIndex);
 	}
 
+	SYS_CloseFile(psContext[dwContextIndex].dwClientID);
 	psContext[dwContextIndex].dwClientID = 0;
 	psContext[dwContextIndex].protocol_major = 0;
 	psContext[dwContextIndex].protocol_minor = 0;
-	
+
+	for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS; i++)
+		if (psContext[i].dwClientID != 0)
+			++tally;
+
+	Log3(PCSC_LOG_DEBUG, "MSGCleanupClient(%d): Active contexts: %d",
+	    dwContextIndex, tally);
+
+	if (tally < 1 && pcscCfg.instanceTimeout > -1) {
+		if (pcscCfg.instanceTimeout == 0) {
+			Log1(PCSC_LOG_DEBUG,
+				"Instance configured for immediate exit");
+			InstanceExitHandler(0);
+		} else {
+			StartInstanceTimer();
+		}
+	}
+	UnlockContextLookup();
+
 	return 0;
 }

Modified: branches/Solaris/src/winscard_svc.h
URL: http://svn.debian.org/wsvn/pcsclite/branches/Solaris/src/winscard_svc.h?rev=2989&op=diff
==============================================================================
--- branches/Solaris/src/winscard_svc.h (original)
+++ branches/Solaris/src/winscard_svc.h Thu Jun 12 10:28:09 2008
@@ -23,6 +23,10 @@
 #endif
 	LONG ContextsInitialize(void);
 	LONG CreateContextThread(PDWORD);
+#ifdef _HAVE_SYS_DOOR_H
+        void ContextWaitForDoorRecv(DWORD);
+        void ContextSignalDoorRecv(char *, size_t);
+#endif        
 #ifdef __cplusplus
 }
 #endif




More information about the Pcsclite-cvs-commit mailing list