Project import
diff --git a/dbus/.mailmap b/dbus/.mailmap
new file mode 100644
index 0000000..4f386b9
--- /dev/null
+++ b/dbus/.mailmap
@@ -0,0 +1,10 @@
+Benjamin Reed <rangerrick@befunk.com> Benjamin Reed <ranger@befunk.com>
+Benjamin Reed <rangerrick@befunk.com> Benjamin Reed <ranger@Sin.local>
+Christian Dywan <christian.dywan@lanedo.com> Christian Dywan <christian@lanedo.com>
+Colin Walters <walters@verbum.org> Colin Walters <walters@lightbox.localdomain>
+Colin Walters <walters@verbum.org> Colin Walters <walters@space-ghost.verbum.private>
+Havoc Pennington <hp@pobox.com> Havoc Pennington <hp@localhost.localdomain>
+Ralf Habacker <ralf.habacker@freenet.de> Ralf Habacker <Ralf.Habacker@freenet.de>
+Ralf Habacker <ralf.habacker@freenet.de> Ralf Habacker <ralf@s15291359.onlinehome-server.info>
+Ralf Habacker <ralf.habacker@freenet.de> unknown <Administrator@.(none)>
+Ralf Habacker <ralf.habacker@freenet.de> unknown <Habacker@.(none)>
diff --git a/dbus/AUTHORS b/dbus/AUTHORS
new file mode 100644
index 0000000..ed8afdf
--- /dev/null
+++ b/dbus/AUTHORS
@@ -0,0 +1,122 @@
+Alban Crequy <alban.crequy@collabora.co.uk>
+Alexander Larsson <alexl@redhat.com>
+Anders Carlsson <andersca@codefactory.se>
+Andre Heinecke <aheinecke@intevation.de>
+Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
+Aurelien Jarno <aurel32@debian.org>
+Benjamin Reed <rangerrick@befunk.com>
+Brian Cameron <brian.cameron@oracle.com>
+Brian Cameron <brian.cameron@sun.com>
+Chris Mayo <aklhfex gmail com>
+Christian Dywan <christian.dywan@lanedo.com>
+Christian Ehrlicher <Ch.Ehrlicher@gmx.de>
+Christian Persch (GNOME) <chpe@gnome.org>
+Colin Walters <walters@verbum.org>
+Colin Watson <cjwatson@ubuntu.com>
+Cosimo Alfarano <cosimo.alfarano@collabora.co.uk>
+Cristian Rodríguez <cristian.rodriguez@opensuse.org>
+Cyril Brulebois <kibi@debian.org>
+Daniel P. Berrange <dan@berrange.com>
+Daniel Reed <djr@redhat.com>
+David Zeuthen <davidz@redhat.com>
+Dennis Kaarsemaker <dennis@kaarsemaker.net>
+Diego E. 'Flameeyes' Pettenò <flameeyes@gmail.com>
+Eamon Walsh <ewalsh@tycho.nsa.gov>
+Federico Mena Quintero <federico@novell.com>
+Frank Osterfeld <frank@kdab.net>
+Frederic Crozat <fcrozat@mandriva.com>
+Fridrich Štrba <fridrich.strba@bluewin.ch>
+Grzegorz Dąbrowski <gdx@poczta.fm>
+Harald Fernengel <harry@kdevelop.org>
+Harri Porten <porten@kde.org>
+Hasso Tepper <hasso@estpak.ee>
+Havoc Pennington <hp@pobox.com>
+Havoc Pennington <hp@redhat.com>
+Hendrik Buschmeier <hbuschme@TechFak.Uni-Bielefeld.DE>
+James Carter <jwcart2@tycho.nsa.gov>
+James Westby <jw+debian@jameswestby.net>
+James Willcox <jwillcox@gnome.org>
+Jens Granseuer <jensgr@gmx.net>
+Jérémie Dimino <jeremie@dimino.org>
+Jiří Klimeš <jklimes@redhat.com>
+Joe Marcus Clarke <marcus@freedesktop.org>
+Joe Shaw <joeshaw@novell.com>
+Johan Gyllenspetz <johangy@axis.com>
+Johannes Carlsson <johannes.carlsson.x@sonyericsson.com>
+John (J5) Palmieri <johnp@redhat.com>
+Jon Gosting <yukarionsen@gmail.com>
+Jon Trowbridge <trow@ximian.com>
+Kay Sievers <kay.sievers@vrfy.org>
+Kimmo Hämäläinen <kimmo.hamalainen@nokia.com>
+Kjartan Maraas <kmaraas@gnome.org>
+Kristian Høgsberg <krh@redhat.com>
+Kristian Rietveld <kris@gtk.org>
+Kurt Miller <kurt@intricatesoftware.com>
+Lawrence R. Steeger <lsteeger@gmail.com>
+Lennart Poettering <lennart@poettering.net>
+Lennart Poettering <mzqohf@0pointer.de>
+Lionel Landwerlin <lionel.landwerlin@openwide.fr>
+Luiz Augusto Von Dentz <luiz.dentz-von@nokia.com>
+Marc Brockschmidt <he@debian.org>
+Marc Mutz <marc@kdab.net>
+Marcus Brinkmann <marcus.brinkmann@ruhr-uni-bochum.de>
+Mark Brand <mabrand@mabrand.nl>
+Mark McLoughlin <mark@skynet.ie>
+Matthias Clasen <mclasen@redhat.com>
+Matt McCutchen <matt@mattmccutchen.net>
+Michael Meeks <michael.meeks@novell.com>
+Michael Meeks <michael@ximian.com>
+Mikael Hallendal <micke@codefactory.se>
+Mikael Hallendal <micke@imendio.com>
+Mike McQuaid <mike@mikemcquaid.com>
+Miloslav Trmac <mitr@volny.cz>
+Murray Cumming <murrayc@murrayc.com>
+Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
+Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
+Olivier Andrieu <oliv__a@users.sourceforge.net>
+Oswald Buddenhagen <ossi@kde.org>
+Owen Fraser-Green <owen@discobabe.net>
+Patrick von Reth <patrick.vonreth@gmail.com>
+Pau Garcia i Quiles <pgquiles@elpauer.org>
+Paul Bolle <pebolle@tiscali.nl>
+Peter Breitenlohner <peb@mppmu.mpg.de>
+Peter Kümmel <syntheticpp@gmx.net>
+Peter McCurdy <pmccurdy@skeptopotamus>
+Philip Blundell <philb@gnu.org>
+Plácido Revilla <unknown@unknown.domain>
+Ralf Habacker <ralf.habacker@freenet.de>
+Ray Strode <rstrode@redhat.com>
+Richard A. Hankins <richard.a.hankins@gmail.com>
+Richard Hughes <richard@hughsie.com>
+Richard Hult <rhult@codefactory.se>
+Richard Hult <richard@imendio.com>
+Robert McQueen <robot101@debian.org>
+Roberto Guido <bob4job@gmail.com>
+Romain Pokrzywka <romain@kdab.com>
+Ross Burton <ross@openedhand.com>
+Ryan Lortie <desrt@desrt.ca>
+Sascha Silbe <sascha-pgp@silbe.org>
+Sascha Silbe <sascha-web-bugs.freedesktop.org@silbe.org>
+Scott James Remnant <scott@netsplit.com>
+Scott James Remnant <scott@ubuntu.com>
+Sebastian Sauer <sebsauer@kdab.net>
+Seth Nickell <seth@gnome.org>
+Simon McVittie <simon.mcvittie@collabora.co.uk>
+Sjoerd Simons <sjoerd@luon.net>
+Sledz <sledz@MOBIL-400-586.intern.dresearch.de>
+Steve Grubb <sgrubb@redhat.com>
+Sven Herzberg <sven@imendio.com>
+Thiago Macieira <thiago@kde.org>
+Tim Dijkstra <tim@famdijkstra.org>
+Tobias Mueller <fdo-bugs@cryptobitch.de>
+Tomas Hoger <thoger@redhat.com>
+Tomas Pelka <tpelka@redhat.com>
+Tom Hughes <tom.hughes@palm.com>
+Tor Lillqvist <tml@iki.fi>
+Waldo Bastian <bastian@kde.org>
+William Lachance <wrlach@gmail.com>
+Will Thompson <will.thompson@collabora.co.uk>
+Wulf C. Krueger <philantrop@exherbo.org>
+Xan Lopez <xan@gnome.org>
+Yaakov Selkowitz <yselkowitz@users.sourceforge.net>
+Zack Rusin <zack@kde.org>
diff --git a/dbus/Android.bp b/dbus/Android.bp
new file mode 100644
index 0000000..35c4c91
--- /dev/null
+++ b/dbus/Android.bp
@@ -0,0 +1,9 @@
+subdirs = [
+    "bus",
+    "dbus",
+]
+
+cc_library_static {
+    name: "libdbus-headers",
+    export_include_dirs: ["."],
+}
diff --git a/dbus/Android.mk b/dbus/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/dbus/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/dbus/COPYING b/dbus/COPYING
new file mode 100644
index 0000000..8260b10
--- /dev/null
+++ b/dbus/COPYING
@@ -0,0 +1,552 @@
+D-Bus is licensed to you under your choice of the Academic Free
+License version 2.1, or the GNU General Public License version 2
+(or, at your option any later version).
+
+Both licenses are included here. Some of the standalone binaries are
+under the GPL only; in particular, but not limited to,
+tools/dbus-cleanup-sockets.c and test/decode-gcov.c. Each source code
+file is marked with the proper copyright information - if you find a
+file that isn't marked please bring it to our attention.
+
+The Academic Free License
+v. 2.1
+
+This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
+
+Licensed under the Academic Free License version 2.1
+
+1) Grant of Copyright License. Licensor hereby grants You a
+world-wide, royalty-free, non-exclusive, perpetual, sublicenseable
+license to do the following:
+
+a) to reproduce the Original Work in copies;
+
+b) to prepare derivative works ("Derivative Works") based upon the Original Work;
+
+c) to distribute copies of the Original Work and Derivative Works to the public;
+
+d) to perform the Original Work publicly; and
+
+e) to display the Original Work publicly.
+
+2) Grant of Patent License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license, under
+patent claims owned or controlled by the Licensor that are embodied in
+the Original Work as furnished by the Licensor, to make, use, sell and
+offer for sale the Original Work and Derivative Works.
+
+3) Grant of Source Code License. The term "Source Code" means the
+preferred form of the Original Work for making modifications to it and
+all available documentation describing how to modify the Original
+Work. Licensor hereby agrees to provide a machine-readable copy of the
+Source Code of the Original Work along with each copy of the Original
+Work that Licensor distributes. Licensor reserves the right to satisfy
+this obligation by placing a machine-readable copy of the Source Code
+in an information repository reasonably calculated to permit
+inexpensive and convenient access by You for as long as Licensor
+continues to distribute the Original Work, and by publishing the
+address of that information repository in a notice immediately
+following the copyright notice that applies to the Original Work.
+
+4) Exclusions From License Grant. Neither the names of Licensor, nor
+the names of any contributors to the Original Work, nor any of their
+trademarks or service marks, may be used to endorse or promote
+products derived from this Original Work without express prior written
+permission of the Licensor. Nothing in this License shall be deemed to
+grant any rights to trademarks, copyrights, patents, trade secrets or
+any other intellectual property of Licensor except as expressly stated
+herein. No patent license is granted to make, use, sell or offer to
+sell embodiments of any patent claims other than the licensed claims
+defined in Section 2. No right is granted to the trademarks of
+Licensor even if such marks are included in the Original Work. Nothing
+in this License shall be interpreted to prohibit Licensor from
+licensing under different terms from this License any Original Work
+that Licensor otherwise would have a right to license.
+
+5) This section intentionally omitted.
+
+6) Attribution Rights. You must retain, in the Source Code of any
+Derivative Works that You create, all copyright, patent or trademark
+notices from the Source Code of the Original Work, as well as any
+notices of licensing and any descriptive text identified therein as an
+"Attribution Notice." You must cause the Source Code for any
+Derivative Works that You create to carry a prominent Attribution
+Notice reasonably calculated to inform recipients that You have
+modified the Original Work.
+
+7) Warranty of Provenance and Disclaimer of Warranty. Licensor
+warrants that the copyright in and to the Original Work and the patent
+rights granted herein by Licensor are owned by the Licensor or are
+sublicensed to You under the terms of this License with the permission
+of the contributor(s) of those copyrights and patent rights. Except as
+expressly stated in the immediately proceeding sentence, the Original
+Work is provided under this License on an "AS IS" BASIS and WITHOUT
+WARRANTY, either express or implied, including, without limitation,
+the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL
+WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential
+part of this License. No license to Original Work is granted hereunder
+except under this disclaimer.
+
+8) Limitation of Liability. Under no circumstances and under no legal
+theory, whether in tort (including negligence), contract, or
+otherwise, shall the Licensor be liable to any person for any direct,
+indirect, special, incidental, or consequential damages of any
+character arising as a result of this License or the use of the
+Original Work including, without limitation, damages for loss of
+goodwill, work stoppage, computer failure or malfunction, or any and
+all other commercial damages or losses. This limitation of liability
+shall not apply to liability for death or personal injury resulting
+from Licensor's negligence to the extent applicable law prohibits such
+limitation. Some jurisdictions do not allow the exclusion or
+limitation of incidental or consequential damages, so this exclusion
+and limitation may not apply to You.
+
+9) Acceptance and Termination. If You distribute copies of the
+Original Work or a Derivative Work, You must make a reasonable effort
+under the circumstances to obtain the express assent of recipients to
+the terms of this License. Nothing else but this License (or another
+written agreement between Licensor and You) grants You permission to
+create Derivative Works based upon the Original Work or to exercise
+any of the rights granted in Section 1 herein, and any attempt to do
+so except under the terms of this License (or another written
+agreement between Licensor and You) is expressly prohibited by
+U.S. copyright law, the equivalent laws of other countries, and by
+international treaty. Therefore, by exercising any of the rights
+granted to You in Section 1 herein, You indicate Your acceptance of
+this License and all of its terms and conditions.
+
+10) Termination for Patent Action. This License shall terminate
+automatically and You may no longer exercise any of the rights granted
+to You by this License as of the date You commence an action,
+including a cross-claim or counterclaim, against Licensor or any
+licensee alleging that the Original Work infringes a patent. This
+termination provision shall not apply for an action alleging patent
+infringement by combinations of the Original Work with other software
+or hardware.
+
+11) Jurisdiction, Venue and Governing Law. Any action or suit relating
+to this License may be brought only in the courts of a jurisdiction
+wherein the Licensor resides or in which Licensor conducts its primary
+business, and under the laws of that jurisdiction excluding its
+conflict-of-law provisions. The application of the United Nations
+Convention on Contracts for the International Sale of Goods is
+expressly excluded. Any use of the Original Work outside the scope of
+this License or after its termination shall be subject to the
+requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101
+et seq., the equivalent laws of other countries, and international
+treaty. This section shall survive the termination of this License.
+
+12) Attorneys Fees. In any action to enforce the terms of this License
+or seeking damages relating thereto, the prevailing party shall be
+entitled to recover its costs and expenses, including, without
+limitation, reasonable attorneys' fees and costs incurred in
+connection with such action, including any appeal of such action. This
+section shall survive the termination of this License.
+
+13) Miscellaneous. This License represents the complete agreement
+concerning the subject matter hereof. If any provision of this License
+is held to be unenforceable, such provision shall be reformed only to
+the extent necessary to make it enforceable.
+
+14) Definition of "You" in This License. "You" throughout this
+License, whether in upper or lower case, means an individual or a
+legal entity exercising rights under, and complying with all of the
+terms of, this License. For legal entities, "You" includes any entity
+that controls, is controlled by, or is under common control with
+you. For purposes of this definition, "control" means (i) the power,
+direct or indirect, to cause the direction or management of such
+entity, whether by contract or otherwise, or (ii) ownership of fifty
+percent (50%) or more of the outstanding shares, or (iii) beneficial
+ownership of such entity.
+
+15) Right to Use. You may use the Original Work in all ways not
+otherwise restricted or conditioned by this License or by law, and
+Licensor promises not to interfere with or be responsible for such
+uses by You.
+
+This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights
+reserved. Permission is hereby granted to copy and distribute this
+license without modification. This license may not be modified without
+the express written permission of its copyright owner.
+
+
+-- 
+END OF ACADEMIC FREE LICENSE. The following is intended to describe the essential 
+differences between the Academic Free License (AFL) version 1.0 and other 
+open source licenses:
+
+The Academic Free License is similar to the BSD, MIT, UoI/NCSA and Apache 
+licenses in many respects but it is intended to solve a few problems with 
+those licenses.
+    
+* The AFL is written so as to make it clear what software is being 
+licensed (by the inclusion of a statement following the copyright notice 
+in the software). This way, the license functions better than a template 
+license. The BSD, MIT and UoI/NCSA licenses apply to unidentified software.
+    
+* The AFL contains a complete copyright grant to the software. The BSD 
+and Apache licenses are vague and incomplete in that respect.
+    
+* The AFL contains a complete patent grant to the software. The BSD, MIT, 
+UoI/NCSA and Apache licenses rely on an implied patent license and contain 
+no explicit patent grant.
+    
+* The AFL makes it clear that no trademark rights are granted to the 
+licensor's trademarks. The Apache license contains such a provision, but the 
+BSD, MIT and UoI/NCSA licenses do not.
+    
+* The AFL includes the warranty by the licensor that it either owns the 
+copyright or that it is distributing the software under a license. None of 
+the other licenses contain that warranty. All other warranties are disclaimed, 
+as is the case for the other licenses.
+
+* The AFL is itself copyrighted (with the right granted to copy and distribute 
+without modification). This ensures that the owner of the copyright to the 
+license will control changes. The Apache license contains a copyright notice, 
+but the BSD, MIT and UoI/NCSA licenses do not. 
+--
+START OF GNU GENERAL PUBLIC LICENSE
+--
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/dbus/ChangeLog b/dbus/ChangeLog
new file mode 100644
index 0000000..0bc33d4
--- /dev/null
+++ b/dbus/ChangeLog
@@ -0,0 +1,5 @@
+2008-04-16  John (J5) Palmieri <johnp@redhat.com>
+
+	* tools/dbus-monitor.c: take out the trailing comma in the
+	  ProfileAttributeFlags enum as it isn't in our style guides
+	  and causes some compilers to error out
diff --git a/dbus/ChangeLog.pre-1-0 b/dbus/ChangeLog.pre-1-0
new file mode 100644
index 0000000..eab5982
--- /dev/null
+++ b/dbus/ChangeLog.pre-1-0
@@ -0,0 +1,15146 @@
+2006-11-09  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 1.0.0
+
+2006-11-09  John (J5) Palmieri  <johnp@redhat.com>
+
+	* AUTHORS: added Peter and Tor of windows porting fame
+
+2006-11-08  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.xml: add a note about protocol stability
+
+	* doc/TODO: Remove "important for 1.0" section, replace with
+	"important for 1.2" section
+	
+2006-11-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* README: remove some of the out of date flags
+
+	* doc/TODO: Remove todo items which are done
+
+2006-11-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/dbus-monitor.c: Handle sigint so we flush stdout
+	(Patch from Olli Salli <olli dot salli at collabora dot co dot uk>)
+
+2006-11-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/dbus-monitor.1: update the manpage for dbus-monitor
+	(Patch from Olli Salli <olli dot salli at collabora dot co dot uk>)
+
+2006-11-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* AUTHORS: Update with all people listed in the ChangeLog
+
+2006-11-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/dbus-monitor.c: add profiling tools to dbus-monitor
+	(Patch from Olli Salli <olli dot salli at collabora dot co dot uk>)
+
+2006-11-07  Havoc Pennington  <hp@redhat.com>
+
+	* HACKING: Update release instructions to include stuff about
+	stable releases, branching, etc. May not be totally correct,
+	please fix if needed, but keep instructions up-to-date so we do
+	each stable release consistently in the future.
+
+2006-11-07  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.xml, doc/dbus-faq.xml, README: various
+	documentation updates. Bump faq/spec versions (not to 1.0; I don't
+	think the spec will be "finished"/1.0 when we ship the 1.0 library).
+
+2006-11-06  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/bus.c: Missed patch - pass in the context to the directory watch
+
+2006-11-02  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released D-Bus 1.0 RC 3(0.95)
+
+2006-11-02  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/activation.c (bus_activation_new): don't fail if we can not read
+	the directory as it may not exist
+
+2006-11-02  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/config-parser.c (service_dirs_find_dir): use 
+	_dbus_list_get_next_link so we don't get stuck in an infinite loop
+	(start_busconfig_child): move processing of standard_session_servicedirs
+	tags here because they have no content
+	(bus_config_parser_content): check we don't have content in 
+	standard_session_servicedirs tag
+
+2006-11-02  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/Makefile.am: Make sure the /var/lib/dbus directory is created
+	Packagers need to own this directory
+
+2006-11-02  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/run-with-tmp-session-bus.sh: fixed script to replace the 
+	<standard_session_servicedirs> tag with a <sevicedir> tag that
+	points to the test service directory
+
+2006-11-02  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: Add a check for DIR *dirp->dd_fd
+
+	* dbus/dbus-sysdeps-util-unix: if HAVE_DDFD is defined use 
+	DIR *dirp->dd_fd else use DIR *dirp->__dd_fd.  This takes care
+	of both Solaris and Irix
+
+2006-11-01  Havoc Pennington  <hp@redhat.com>
+
+	* bus/dbus-daemon.1.in: document standard_session_servicedirs
+
+2006-11-01  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: expose DBUS_DATADIR
+	
+	* bus/config-parser.c: add the standard_session_servicedirs element
+	to the parser
+	(bus_config_parser_content): process the standard_session_servicedirs
+	element by getting the standard directories from sysdeps and merging
+	them into the service directory list
+	(test_default_session_servicedirs): make sure we get what we expect
+
+	* bus/session.conf.in: replace the servicedir tag with the 
+	standard_session_servicedirs tag
+
+	* dbus/dbus-list.h: remove the typedef of DBusList and place it in
+	dbus-sysdeps.h to avoid circular header dependencies
+
+	* dbus/dbus-sysdeps.h: add the typedef of DBusList
+
+	* dbus/dbus-sysdeps-unix.c (split_paths_and_append): utility function
+	which takes a string of directories delimited by colons, parses them 
+	out, appends a suffix and puts them in a list ignoring empty elements
+	(_dbus_get_standard_session_servicedirs): returns the standard 
+	directories for a session bus to look for service activation files
+	on Unix which includes the XDG_DATA_HOME, XDG_DATA_DIRS and 
+	DBUS_DATADIR directories
+
+	* test/data/valid-config-files/many-rules.conf: add the 
+	standard_session_servicedirs tag to the valid config file tests
+
+2006-10-30  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-launch.1, doc/TODO: capture intent to change the
+	command line options of dbus-launch a bit post 1.0
+
+2006-10-27  Havoc Pennington  <hp@redhat.com>
+	
+	* dbus/dbus-connection.c (dbus_connection_open_private): document
+	how to choose shared vs. private connections
+
+2006-10-27  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-test.c: enclose more of the file in the
+	DBUS_BUILD_TESTS check.
+
+	* dbus/dbus-sysdeps-pthread.c (PTHREAD_CHECK): fix for
+	DBUS_DISABLE_ASSERT case.
+
+	* dbus/dbus-connection.c (dbus_connection_get_unix_user): document
+	that it only works on the server side
+
+	* dbus/dbus-bus.c: add a global lock covering the BusData we
+	attach to each connection
+	(internal_bus_get): lock our access to the BusData
+	(dbus_bus_register): lock the entire registration process
+	with _DBUS_LOCK(bus_datas). If we get the lock and 
+	registration is already complete, silently return (vs. previous
+	behavior of aborting).
+	(dbus_bus_set_unique_name): lock the BusData
+	(dbus_bus_get_unique_name): lock the BusData
+
+2006-10-27  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/config-parser.c (service_dirs_find_dir, 
+	service_dirs_append_unique_or_free, 
+	service_dirs_append_link_unique_or_free): New static methods
+	for only appending unique service directory names into
+	the service directory list
+	(merge_included, bus_config_parser_content): Only add unique
+	service directory names into the list
+
+2006-10-27  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps-pthread.c: make the "count" and "holder"
+	variables volatile, suggested by Thiago. Document struct fields.
+	(PTHREAD_CHECK): remove pthread error checking if assertions are
+	disabled, should reduce the no-assertions case to the bare
+	minimum code.
+
+2006-10-26  Havoc Pennington  <hp@redhat.com>
+	
+	* dbus/dbus-sysdeps-pthread.c (_dbus_pthread_mutex_lock): change
+	to be recursive
+	(_dbus_pthread_mutex_unlock): make it recursive
+	(_dbus_pthread_condvar_wait): save/restore the recursion count
+	(_dbus_pthread_condvar_wait_timeout): save/restore the recursion count
+
+2006-10-26  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.xml: clarify the UUID text slightly
+
+	* dbus/dbus-sysdeps-pthread.c: check for and mostly abort on
+	pthread errors. Add DBusMutexPThread and DBusCondVarPThread 
+	in preparation for being able to extend them for e.g. recursive
+	mutexes.
+
+2006-10-26  Havoc Pennington  <hp@redhat.com>
+
+        * dbus/dbus-threads.[hc]: Documentation improvements. Clarify how 
+	condition variables relate to recursive mutexes.
+	
+        * dbus/dbus-sysdeps-pthread.c, dbus/dbus-sysdeps-win-thread.c, 
+	dbus/dbus-threads.c: Split the platforms-specific thread 
+	implementations into their own files.
+	
+	* dbus/dbus-sysdeps-pthread.c
+	(_dbus_pthread_condvar_wait_timeout): invert the return value, it
+	was backward. Not that anything uses it.
+
+2006-10-26  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus-sysdeps-unix.c (_dbus_set_local_creds): Clean up the
+	LOCAL_CREDS vs CMSGCRED stuff a bit.  Prefer CMSGCRED.  This
+	needs to be cleaned up more.
+
+	* doc/TODO: Add a todo that *BSD hackers should look at cleaning
+	up the CREDS issue.
+
+2006-10-26  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in, dbus-1.pc.in: Check to see if thread methods 
+	are in glibc or libpthread and add -lpthread to the link stage 
+	if it is the latter
+
+2006-10-26  Thiago Macieira  <thiago@kde.org>
+
+	* dbus/dbus-connection.c (_dbus_connection_open_internal): Fix
+        bug 8780: the connection lock is only required while recording
+        the shared connection, so protect only that code
+        section. Don't require connection_lookup_shared to return a
+        locked connection.
+
+2006-10-26  Thiago Macieira  <thiago@kde.org>
+
+	* tools/dbus-launch-x11.c (get_session_file, init_x_atoms):
+        check if get_machine_uuid() returns NULL before proceeding any
+        further: we can't init the X atoms or create a session file
+        name if there is no machine ID.
+	This solves a crash reported by some users if
+        --exit-with-session was used without --autolaunch=<machine-id>
+
+2006-10-26  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/dbus-launch.c (main): run the dbus-daemon in the builddir
+	if tests are enabled and the DBUS_USE_TEST_BINARY env variable is set
+
+	* tools/run-with-tmp-session-bus.sh: set DBUS_USE_TEST_BINARY
+	before we run dbus-launch
+
+	* configure.in: define TEST_BUS_BINARY to be the full path to 
+	dbus-daemon in the build root 
+
+2006-10-25  Sjoerd Simons  <sjoerd@luon.net>
+
+	* dbus/Makefile.am:
+	* tools/Makefile.am:
+	* toos/dbus-uuidgen.1:
+		Move the machine-id file to /var/lib/dbus 
+
+2006-10-24  David Zeuthen  <davidz@redhat.com>
+
+	* dbus/dbus-threads.c (init_uninitialized_locks): Fix typo so it's
+	_dbus_assert (thread_init_generation != _dbus_current_generation)
+	not _dbus_assert (thread_init_generation == _dbus_current_generation)
+
+2006-10-24  Thiago Macieira  <thiago@kde.org>
+
+	* dbus/dbus-sysdeps.h:
+	* dbus/dbus-sysdeps-unix.c: Add function
+	_dbus_make_file_world_readable that chmods a file to 0644.
+
+	* dbus/dbus-sysdeps-unix.c (_dbus_get_autolaunch_address):
+        Avoid writing to the static "argv" array, thereby avoiding a
+        COW on the child process.
+
+	* dbus/dbus-internals.c (_dbus_create_uuid_file_exclusively):
+        call _dbus_make_file_world_readable on the created file.
+
+2006-10-23  David Zeuthen  <davidz@redhat.com>
+
+	* dbus/dbus-memory.c: Use atomic variable to protect
+	n_blocks_outstanding otherwise OOM will be reported using SMP on
+	some arches
+	
+	* bus/dispatch.c: Add missing end of line characters
+
+	* bus/desktop-file.c (parse_section_start, parse_key_value) 
+	(bus_desktop_file_load): Propertly handle OOM
+
+	* dbus/dbus-threads.c (init_uninitialized_locks): Check that
+	thread_init_generation equals _dbus_current_generation, not 0
+
+2006-10-22  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection-internal.h: move prototype of
+	_dbus_bus_notify_shared_connection_disconnected_unlocked() here so
+	it isn't in a public header and doesn't end up in the DBusBus
+	group in Doxygen
+
+2006-10-21  Havoc Pennington  <hp@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): dist cleanup-man-pages.sh so it's in
+	the tarball if packagers want to run it
+
+	* cleanup-man-pages.sh: Add a script which munges all the internal
+	API man pages out of the Doxygen output. This reduces the size of
+	the installed man pages from 7 to 2 megs, and avoids
+	namespace-polluting pages. Right now (like Doxygen) this script
+	isn't in the build, it's something packagers can do manually.
+
+2006-10-21  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.h: don't include the watch/timeout
+	functions in connection section
+
+2006-10-21  Havoc Pennington  <hp@redhat.com>
+
+	* Documentation! Whee! Doxygen now 100% silent. If you make it
+	angry again, you will be punished.
+	
+2006-10-21  Havoc Pennington  <hp@redhat.com>
+
+	* More documentation - all public API now documented according to
+	Doxygen
+
+2006-10-21  Havoc Pennington  <hp@redhat.com>
+
+	* Document a bunch of undocumented stuff
+	
+2006-10-21  Havoc Pennington  <hp@redhat.com>
+
+	* Clean up Doxygen group markers for public API so Doxygen finds
+	everything (not comprehensively fixed for private API).
+	Means all remaining Doxygen warnings are just about missing docs
+	and thus pretty simple to resolve.
+	
+2006-10-21  Havoc Pennington  <hp@redhat.com>
+	
+	* dbus/dbus-macros.h: add DBUS_GNUC_DEPRECATED macro
+
+	* dbus/dbus-message.h: mark dbus_message_iter_get_array_len() 
+	as DBUS_GNUC_DEPRECATED
+
+2006-10-21  Havoc Pennington  <hp@redhat.com>
+
+        * Move all private API into the private Doxygen group sections of
+	the files, so they don't show up in the public API docs
+	
+2006-10-21  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.h: put #ifndef DBUS_DISABLE_DEPRECATED around 
+	dbus_message_iter_get_array_len().
+
+	* throughout: documentation improvements.
+
+2006-10-20  Havoc Pennington  <hp@redhat.com>
+
+	* doc/TODO: remove the int64 thing from 1.0 since it doesn't
+	matter, and the message-loader-breaker thing since nobody is going
+	to do it.  Add an item to 1.0 about supporting recursive locks
+	in dbus_threads_init_default() though, since it should be easy.
+
+	* dbus/dbus-connection.c (_dbus_connection_read_write_dispatch):
+	Fix this in the !dispatch case to avoid busy-looping after
+	disconnection
+
+        * More misc docs improvements
+
+2006-10-19  Havoc Pennington  <hp@redhat.com>
+
+	* more Doxygen-related fixes (lots of moving things from the
+	public to internal section in dbus-connection.c)
+
+2006-10-19  Havoc Pennington  <hp@redhat.com>
+
+	* Fix a pile of Doxygen warnings and missing docs
+
+2006-10-19  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/dir-watch-default.c, bus/dir-watch-dnotify.c, 
+	bus/dir-watch-kqueue.c (bus_watch_directory): Pass in a BusContext 
+	instead of a void *.  kqueue uses this to get the context's loop
+	while the other modules ignore the parameter.  This allows us to
+	avoid platform conditionals
+
+	* bus/bus.c (process_config_postinit): Pass in the context to the 
+	watch
+
+2006-10-19  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/messagebus.in, bus/rc.messagebus.in: run dbus-uuidgen --ensure
+	when starting the system bus
+
+2006-10-18  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: More fixups for cross compile (Patch from 
+	Marco Pracucci <development at pracucci dot com>)
+
+2006-10-17  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-send.c (main): don't close shared connection, fix
+	from Timo Hoenig
+
+2006-10-17  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in (CPPFLAGS): don't do -DDBUS_API_SUBJECT_TO_CHANGE here
+
+	* dbus/dbus.h: drop the DBUS_API_SUBJECT_TO_CHANGE requirement,
+	since realistically it doesn't look like we'll be changing it
+	anymore.
+
+2006-10-17  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-internals.c (_dbus_warn_check_failed): new function to
+	be used for return_if_fail type warnings; prefixes the pid, and
+	fatal by default.
+
+2006-10-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: Released 1.0 RC 2(0.94)
+	Add check for -fPIC and enable it if available
+
+2006-10-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* doc/TODO: Remove the check TODO item
+
+2006-10-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus-transport-socket.c (exchange_credentials):
+	Print out more detailed errors if reading or sending
+	credentials fail (Patch from Julio M. Merino Vidal 
+	<jmmv at NetBSD dot org>)
+
+2006-10-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: when checking for posix getpwnam_r assume true
+	for cross compiles
+
+2006-10-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: Check for gethostbyname first before we check for it
+	in libnsl.  On gnu systems it is implemeneted 
+
+2006-10-13  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c
+	(dbus_connection_send_with_reply_and_block): fix to handle closed
+	connections, from Tambet Ingo bug #8631
+
+2006-10-11  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: use AC_TRY_COMPILE for dirfd instead of AC_TRY_RUN
+
+2006-10-11  John (J5) Palmieri  <johnp@redhat.com>
+
+	* test/name-test/Makefile.am: don't link against both libdbus and
+	libdbus-convenience
+
+2006-10-11  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: check for dirfd even if it is a macro
+	(Patch from Timothy Redaelli <drizzt at gufi dot org>)
+
+2006-10-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: define _POSIX_PTHREAD_SEMANTICS on solaris
+	avoid using dirfd on systems that don't have dirfd 
+	(Patch by Brian Cameron <brian dot cameron at sun dot com>) 
+
+2006-10-02  John (J5) Palmieir  <johnp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_abort): Remove from 
+	#ifndef DBUS_DISABLE_ASSERTS macro to fix distcheck
+
+	* dbus/dbus-sysdeps-unix.c (_dbus_print_backtrace): Remove from
+	#if !defined (DBUS_DISABLE_ASSERT) || defined(DBUS_BUILD_TESTS)
+	macro because _dbus_abort calls it
+
+	* tools/Makefile.am: Add dbus-launch.h to the source list so distcheck
+	works
+
+2006-10-02  John (J5) Palmieir  <johnp@redhat.com>
+
+	* dbus/dbus-sysdeps-util-unix.c (dirent_buf_size): Add check for
+	MAXNAMELEN for Mac OSX.  (Patch from Jonas B <sanoix at gmail dot com>)
+
+2006-10-02  Thiago Macieira  <thiago@kde.org>
+
+	* tools/dbus-launch.c (main): make it complain and abort
+	execution in case an unknown option is given. Also, process
+	the '--' argument as the end of arguments.
+
+2006-10-01  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-launch.c (print_variables): if no syntax is given,
+	don't print something that's sort-of-half-sh-syntax, just print
+	a plain key-value pairs thing.
+
+	* tools/dbus-launch-x11.c: use machine ID rather than hostname for
+	the local machine representation (but still have the hostname in
+	the display). Remove the hostname from the display if it is
+	localhost. Change session files to be named
+	~/.dbus/session-bus/machine-display. Change X atoms to be
+	underscore-prefixed so nobody whines about ICCCM compliance.
+	Otherwise name them the same as the env variables.
+	Change session file format to include key-value pairs and an
+	explanatory comment. Keys are the same as the env variables.
+	(set_address_in_x11): X property format can't depend on
+	sizeof(pid_t) on a particular machine, fix to always be 32 bits
+
+	* tools/dbus-launch.c: make --autolaunch take a machine id
+	argument. If --autolaunch is used with a program to run, complain
+	for now (but add a FIXME). Also, don't look for existing bus if 
+	there's a program to run (but add a FIXME).
+
+	* dbus/dbus-sysdeps-unix.c (_dbus_get_autolaunch_address): pass
+	machine uuid to dbus-launch (avoids linking dbus-launch to libdbus
+	just to get this, and avoids duplicating uuid-reading code).
+
+	* tools/dbus-launch.1: clarify various things
+	
+2006-10-01  Havoc Pennington  <hp@redhat.com>
+
+	* test/test-service.c (path_message_func): remove broken extra
+	unref that was hidden by the bugs in dbus-connection.c/dbus-bus.c
+
+	* test/test-shell-service.c (path_message_func): same fix
+	
+	* dbus/dbus-connection.c
+	(_dbus_connection_get_dispatch_status_unlocked): break up the
+	function a little for clarity and fix the notification of
+	dbus-bus.c to not require dispatch to be complete
+
+	* dbus/dbus-connection.c (dbus_connection_unref): improve the
+	warning when you try to finalize an open connection.
+	
+2006-10-01  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-bus.c
+	(internal_bus_get): only weak ref the connection; this means 
+	_dbus_bus_notify_shared_connection_disconnected_unlocked can be
+	called safely in any context
+	(_dbus_bus_notify_shared_connection_disconnected_unlocked): don't
+	unref
+
+	* dbus/dbus-connection.c
+	(_dbus_connection_get_dispatch_status_unlocked): move
+	_dbus_bus_notify_shared_connection_disconnected_unlocked here
+	when queuing Disconnected instead of when the Disconnected message
+	arrives, so dbus_bus_get() won't return closed connections.
+	
+2006-10-01  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c (_dbus_connection_close_if_only_one_ref): 
+	Add a hack to make DBusNewConnectionFunction work right.
+
+	* dbus/dbus-server-socket.c (handle_new_client_fd_and_unlock): use
+	the hack here. Also, fix the todo about refcount leak.
+	
+	* dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new):
+	and use the hack here
+	
+        * dbus/dbus-connection.c: Kill the "shared" flag vs. the
+	"shareable" flag; this was completely broken, since it meant 
+	dbus_connection_open() returned a connection of unknown
+	shared-ness. Now, we always hold a ref on anything opened 
+	as shareable.
+
+	Move the call to notify dbus-bus.c into
+	connection_forget_shared_unlocked, so libdbus consistently forgets
+	all its knowledge of a connection at once. This exposed numerous
+	places where things were totally broken if we dropped a ref inside
+	get_dispatch_status_unlocked where
+	connection_forget_shared_unlocked was previously, so move
+	connection_forget_shared_unlocked into
+	_dbus_connection_update_dispatch_status_and_unlock. Also move the
+	exit_on_disconnect here.
+
+	(shared_connections_shutdown): this assumed weak refs to the
+	shared connections; since we have strong refs now, the assertion 
+	was failing and stuff was left in the hash. Fix it to close
+	still-open shared connections.
+	
+	* bus/dispatch.c: fixup to use dbus_connection_open_private on the 
+	debug pipe connections
+	
+	* dbus/dbus-connection.c (dbus_connection_dispatch): only notify
+	dbus-bus.c if the closed connection is in fact shared
+	(_dbus_connection_close_possibly_shared): rename from 
+	_dbus_connection_close_internal
+	(dbus_connection_close, dbus_connection_open,
+	dbus_connection_open_private): Improve docs to explain the deal
+	with when you should close or unref or both
+
+	* dbus/dbus-bus.c
+	(_dbus_bus_notify_shared_connection_disconnected_unlocked): rename
+	from _dbus_bus_check_connection_and_unref_unlocked and modify to
+	loop over all connections
+
+	* test/test-utils.c (test_connection_shutdown): don't try to close
+	shared connections.
+
+	* test/name-test/test-threads-init.c (main): fix warnings in here
+
+	* dbus/dbus-sysdeps.c (_dbus_abort): support DBUS_BLOCK_ON_ABORT
+	env variable to cause blocking waiting for gdb; drop
+	DBUS_PRINT_BACKTRACE and just call _dbus_print_backtrace() 
+	unconditionally.
+
+	* configure.in: add -export-dynamic to libtool flags if assertions enabled
+	so _dbus_print_backtrace works.
+
+	* dbus/dbus-sysdeps-unix.c (_dbus_print_backtrace): use fprintf
+	instead of _dbus_verbose to print the backtrace, and diagnose lack 
+	of -rdynamic/-export-dynamic
+	
+2006-09-30  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-bus.c (dbus_bus_get_private, dbus_bus_get) 
+	(internal_bus_get): fix screwy code formatting. whoever committed
+	that was not paying attention!
+
+2006-09-30  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in (LT_CURRENT, LT_AGE): increment current and age to
+	reflect addition of interfaces.
+
+	* doc/dbus-specification.xml: describe a new
+	org.freedesktop.DBus.Peer.GetMachineId method
+
+	* dbus/dbus-string.c (_dbus_string_skip_white_reverse): new function
+	(_dbus_string_skip_white, _dbus_string_skip_blank): use new
+	DBUS_IS_ASCII_BLANK, DBUS_IS_ASCII_WHITE macros and fix assertion
+	at end of skip_white
+	(_dbus_string_chop_white): new function
+
+	* bus/connection.c (bus_connections_setup_connection): call
+	dbus_connection_set_route_peer_messages.
+
+	* dbus/dbus-connection.c
+	(_dbus_connection_peer_filter_unlocked_no_update): modify to
+	support a GetMachineId method.
+
+	Also, support a new flag to let the bus pass peer methods through
+	to apps on the bus, which can be set with
+	dbus_connection_set_route_peer_messages.
+
+	Finally, handle and return an error for anything unknown on the
+	Peer interface, which will allow us to extend the Peer interface
+	in the future without fear that we're now intercepting something
+	apps were wanting to see.
+	
+	* tools/dbus-uuidgen.c: a thin wrapper around the functions in 
+	dbus/dbus-uuidgen.c
+
+	* dbus/dbus-uuidgen.c: implement the bulk of the dbus-uuidgen
+	binary here, since most of the code is already in libdbus
+
+	* dbus/dbus-sysdeps.c (_dbus_read_local_machine_uuid): read the
+	uuid from the system config file
+
+	* dbus/dbus-internals.c (_dbus_generate_uuid, _dbus_uuid_encode) 
+	(_dbus_read_uuid_file_without_creating) 
+	(_dbus_create_uuid_file_exclusively, _dbus_read_uuid_file): new
+	uuid-related functions, partly factored out from dbus-server.c
+
+	* dbus/dbus-sysdeps.c (_dbus_error_from_errno): convert EEXIST to
+	DBUS_ERROR_FILE_EXISTS instead of EEXIST
+
+	* dbus/dbus-protocol.h (DBUS_ERROR_FILE_EXISTS): add file exists error
+
+	* tools/dbus-cleanup-sockets.1: explain what the point of this
+	thing is a bit more
+
+	* autogen.sh (run_configure): add --config-cache to default
+	configure args
+
+	* dbus/dbus-internals.h (_DBUS_ASSERT_ERROR_IS_SET): disable the
+	error set/clear assertions when DBUS_DISABLE_CHECKS is defined
+
+	* tools/dbus-launch.c (main): if xdisplay hasn't been opened,
+	don't try to save address, fixes crash in make check
+	
+2006-09-30  Thiago Macieira  <thiago@kde.org>
+
+	* configure.in: add DBUS_BINDIR as a #define to C source code.
+
+	* tools/dbus-launch.c
+	* tools/dbus-launch.h
+	* tools/dbus-launch-x11.c:
+	* tools/dbus-launch.1: Add the --autolaunch option to
+	dbus-launch, which makes it scan for an existing session
+	started with --autolaunch. With that option, it also creates
+	an X11 window and saves the bus address and PID to it.
+
+	* dbus/dbus-sysdeps.h:
+	* dbus/dbus-sysdeps-unix.c (_dbus_get_autolaunch_address): Add
+	a function that runs "dbus-launch --autolaunch" to retrieve
+	the running D-Bus session address (or start one if none was running)
+
+	* dbus/dbus-transport.c: Add the handler for the "autolaunch:"
+        address protocol, which tries to get the running session from
+        dbus-launch.
+
+	* dbus/dbus-bus.c:
+	* dbus/dbus-internals.h: Make "autolaunch:" be the default
+	D-Bus session bus address.
+
+	* dbus/dbus-connection.c: Fix horrible typo in error message.
+
+2006-09-18  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/Makefile.am: use @EXPANDED_DATADIR@ instead of @DATADIRNAME@  
+
+2006-09-17  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-transport.c (_dbus_transport_get_is_authenticated):
+	fix so that if unix_user_function is set on windows, we still
+	do the default check that the auth identity matches the bus identity
+
+2006-09-16  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-transport.c (_dbus_transport_open): modify to delegate
+	to _dbus_transport_open_platform_specific,
+	_dbus_transport_open_socket,
+	and _dbus_transport_open_debug_pipe
+
+	* dbus/dbus-transport-protected.h: add _dbus_transport_open_platform_specific
+
+2006-09-16  Havoc Pennington  <hp@redhat.com>
+
+        Attempt auditing public API to remove all cases where a Unix
+	function returns weird emulated goo to Windows. This probably 
+	breaks the bus daemon on Windows, to fix it again we may 
+	need to stop processing unix-specific config options on Windows,
+	and may need to add Windows-specific public API or config options.
+	
+	* configure.in (LT_CURRENT, LT_AGE): increment current and age,
+	to reflect added interfaces; should not break soname.
+	
+	* dbus/dbus-transport.c (_dbus_transport_get_is_authenticated): do
+	not invoke unix user function on Windows. Kind of a hacky fix, but 
+	we don't want a "unix uid" leaking out on Windows.
+
+	* dbus/dbus-connection.c (dbus_connection_get_socket): add new API
+	to get the socket fd on Windows or UNIX
+	(dbus_connection_get_unix_fd): make this always fail on Windows
+
+2006-09-16  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-server.c (dbus_server_listen): change how this works
+	to be able to delegate to a set of handlers that can succeed,
+	fail, or choose not to handle. Allows us to have 
+	dbus_server_listen_platform_specific.
+
+	* dbus/dbus-server-socket.c (_dbus_server_new_for_tcp_socket):
+	factor out the tcp socket stuff to be used on windows, leaving
+	unix domain socket only in dbus-socket-unix.c
+
+	* dbus/dbus-transport-socket.c
+	(_dbus_transport_new_for_tcp_socket): factor out the tcp socket
+	stuff to be used on windows, leaving unix domain socket only 
+	in dbus-transport-unix.c
+
+	* dbus/dbus-connection.c (dbus_connection_get_unix_user): insert
+	temporary hack to be sure this fails on windows
+	(dbus_connection_get_unix_process_id): ditto
+
+2006-09-16  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps-unix.c (_dbus_open_tcp_socket) 
+	(_dbus_open_unix_socket, _dbus_open_socket): change API for 
+	_dbus_open_socket so the domain/type/protocol from system headers
+	are not required. This is kind of pointless though unless we move
+	part of _dbus_connect_tcp_socket into sysdeps.c instead of
+	sysdeps-unix.c, which would mean adding a wrapper around
+	bind/listen/etc.
+	Also, add DBusError to the socket-opening functions so they 
+	don't require use of errno.
+
+2006-09-16  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps-unix.h: small change to Peter's patch to make
+	dbus-sysdeps-unix-util.c build, add unix-specific sysdeps header.
+
+	* dbus/dbus-sysdeps.h, dbus-sysdeps-unix.c: patch from Peter 
+	Kümmel bug #8249 to make the sysdeps.h read/write/open/close
+	functions specifically for sockets only, and move generic 
+	read/write/open/close into unix-specific code.
+
+2006-09-14  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-transport-unix.c (unix_do_iteration): fix a valgrind
+	complaint about accessing revents when poll returns 0, from Julian Seward.
+
+2006-09-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 1.0 RC 1 (0.93) 
+
+2006-09-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-sysdeps-util-unix.c (_dbus_write_pid_file):
+	use _dbus_close instead of close
+
+2006-09-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-sysdeps.c: Add support for LOCAL_CREDS socket
+	credentials.  Fixes "external" authentication under e.g. NetBSD
+	which does not support any other socket credentials mechanism.
+	(Patch from Julio M. Merino Vidal  <jmmv at NetBSD dot org>)
+
+2006-09-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-threads.c: Allow recursive mutex's to be passed into
+	dbus_threads_init and be used by the dbus mutex functions to
+	avoid deadlocks.
+
+	* doc/TODO: Remove recursive mutex dbus_connection_dispatch TODO item
+
+2006-09-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-sysdeps-util-unix.c (_dbus_directory_get_next_file):
+	use threadsafe readdir_r instead of readdir
+
+2006-09-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus-threads.c (dbus_threads_init_default): New method for
+	initializing the internal thread implementation (Patch from
+	Alexander Larsson <alexl at redhat dot com>)
+
+2006-09-11  John (J5) Palmieri  <johnp@redhat.com>
+
+	* remove a bunch of todo items from the 1.0 list
+
+2006-09-11  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/activation.c, bus/desktop-file.c: Distinguish between OOM and
+	key not found
+
+2006-09-11  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-internal.c: Add dbus_is_verbose so we can have more
+	complex debugging code
+
+	* dbus/dbus-marshal-basic.c (_dbus_marshal_read_fixed_multi): Move
+	between the test suite ifdefs
+	(_dbus_verbose_bytes): return if verbosity is not enabled 
+
+2006-09-11  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-marshal-recursive-util.c, dbus/dbus-marshal-recursive.c:
+	remove DBusMark
+
+2006-09-10  Havoc Pennington  <hp@redhat.com>
+
+       patch mostly by Peter Kümmel, bug #8211
+	
+	* dbus/dbus-sysdeps-unix.c: new file, which splits out
+	unix-specific stuff in dbus-sysdeps.c
+
+	* dbus/dbus-sysdeps.c: don't include any UNIX-only headers, 
+	and move unix-specific stuff to dbus-sysdeps-unix.c
+
+	* configure.in: check HAVE_ERRNO_H
+	
+2006-09-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/test-main.c (main): Initialize threading during tests
+
+	* dbus/dbus-connection.c (_dbus_connection_new_for_transport):
+	Unlock connection on error
+	(generate_local_error_message): static method for generating
+	an error message when we don't have a message to reply to
+	(_dbus_connection_block_pending_call): Send a disconnect error
+	instead of just a timeout (NULL) when the bus gets disconnected
+	while blocking for a reply.
+	
+2006-09-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-connection.c (dbus_connection_dispatch): Properly remove
+	filters (Patch from Kimmo Hämäläinen 
+	<kimmo dot hamalainen at nokia dot com>)
+
+2006-09-07  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-connection-internal.h: Add prototype for 
+	_dbus_connection_test_get_locks to remove warning
+
+2006-09-07  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-spawn.c (_dbus_spawn_async_with_babysitter): Make sure we
+	close child_err_report_pipe[WRITE_END] on exec (Patch from 
+	Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>)
+
+2006-09-07  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Clean up close calls to use _dbus_close (Patch from 
+	Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>)
+
+2006-09-06  John (J5) Palmieri  <johnp@redhat.com>
+
+	* doc/TODO:
+	- Remove pending call locking todo item
+	- dbus_connection_open now holds hard ref.  Remove todo item
+	- do proper locking on _dbus_bus_check_connection_and_unref
+	  and handle DBUS_BUS_STARTER. Remove todo item
+	- Warn on closing of a shared connection.  Remove todo item
+
+	* bus/bus.c, bus/connection.c, bus/dispatch.c, dbus/dbus-bus.c,
+	dbus/dbus-connection.c: Use the dbus_connection_close_internal
+	so we don't get the warning when closing shared connections
+
+	* test/test-service.c, test/test-shell-service.c: Applications
+	don't close shared connections themselves so we unref instead of
+	close
+
+	* test/test-utils.c (test_connection_shutdown): Close the connection
+
+	* dbus/dbus-bus.c (_dbus_bus_check_connection_and_unref): Changed to
+	_dbus_bus_check_connection_and_unref_unlocked since we only call this
+	method on a locked connection.  
+	Make sure we call _dbus_connection_unref_unlocked instead of 
+	dbus_connection_unref also.
+	Handle DBUS_BUS_STARTER correctly
+
+	* dbus/dbus-connection.c (connection_record_shared_unlocked):
+	Mark as shared and hard ref the connection
+	(connection_forget_shared_unlocked): Remove the hard ref from the 
+	connection
+	(_dbus_connection_close_internal_and_unlock):  New internal function
+	which takes a locked connection and unlocks it after closing it
+	(_dbus_connection_close_internal): New internal function which acts
+	like the origonal dbus_connection_close method by grabbing a connection
+	lock and calling _dbus_connection_close_internal_and_unlock
+	(dbus_connection_close): Public close method, warns when the app
+	trys to close a shared connection
+
+2006-09-06  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/driver.c:
+	(bus_driver_generate_introspect_string): New method for populating
+	a DBusString with the introspect data
+	(bus_driver_handle_introspect): Move introspect generation code to 
+	bus_driver_generate_introspect_string
+
+	* bus/main.c:
+	(introspect): New function which prints out the intropect data and
+	exits
+	(main): Add a --introspect switch
+
+2006-09-06  John (J5) Palmieri  <johnp@redhat.com>
+
+	* doc/TODO: Removed dtd publishing item.  
+	It seems the dtd has already been added at
+	http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd
+
+2006-09-05  John (J5) Palmieri  <johnp@redhat.com>
+
+	* doc/TODO, various source files: Audited todo's and FIXME's and
+	prepended the ones we should be looking at with 1.0.  Those
+	prepended with 1.0? need clerification or might not be needed
+	for 1.0
+
+2006-09-05  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-pending-call.c: Add some checks so we don't crash on
+	NULL in the public API (Patch from Kimmo Hämäläinen 
+	<kimmo dot hamalainen at nokia dot com>)
+
+2006-09-05  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: Fix for OS-X compile time endian issues (patch from
+	Benjamin Reed <ranger at befunk dot com>)
+
+2006-09-05  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: Check for no-common compiler flag (OS-X fix from
+	Benjamin Reed <ranger at befunk dot com>)
+
+2006-09-01  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/dbus-launch.c: Add a sigterm handler (patch from Frederic Crozat
+	<fcrozat at mandriva dot com>)
+
+2006-08-29  Havoc Pennington  <hp@redhat.com>
+
+	* test/test-service.c (path_message_func): fix lack of return value
+
+	* dbus/dbus-sysdeps.c (_dbus_printf_string_upper_bound): fix
+	formatting, remove #ifdef, and fix docs. #ifdef doesn't make
+	any more sense than on anything else in this file.
+	(_dbus_get_tmpdir): add const to return value, and keep the
+	results of the various getenv around in a static variable.
+
+2006-08-29  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps-util.c, dbus/dbus-sysdeps-util-unix.c: change
+	from Ralf Habacker to move UNIX-specific sysdeps into a separate file.
+
+2006-08-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* test/Makefile.am: change find to use syntax that works with non
+	gnu versions of find
+
+2006-08-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-transport.c: fix invalid deref when checking if
+	a vtable method exists (Patch from Christian Ehrlicher 
+	<ch dot ehrlicher at gmx dot de>)
+
+2006-08-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in, dbus/Makefile.am, test/name-test/run-test.sh, 
+	test/name-test/Makefile.am: Fixed some issues with getting get dbus 
+	to build with builddir != srcdir (Taken from a patch by Bernard Leak
+	<bernard at brenda-arkle dot demon dot co dot uk>)
+
+2006-08-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: Fix DBUS_DAEMONDIR to use EXPANDED_BINDIR for the
+	default case
+
+2006-08-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.ac, bus/Makefile.am: Generalize kqueue support so that
+	it works on any system providing this interface, not only FreeBSD.
+	For example, NetBSD. (Patch by Julio M. Merino Vidal  <jmmv at NetBSD dot org>)
+
+2006-08-20  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-faq.xml, doc/dbus-tutorial.xml: some improvements to
+	the docs
+
+2006-08-18  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 0.92 
+
+2006-08-18  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-threads.c (dbus_threads_init): change the documentation
+	to reflect the init late change
+
+	* bus/bus.c (bus_context_new): Check user before we fork so we can
+	print out an error message a user will be able to see
+
+2006-08-18  John (J5) Palmieri  <johnp@redhat.com>
+
+	Patch provided by Ralf Habacker (ralf dot habacker at freenet dot de) 
+
+	* dbus/dbus-sysdeps.c, dbus/dbus-threads.c, dbus/dbus-internals.h:
+	Add two more global locks for use on windows platforms.  These are
+	unused on non-windows platforms but are not ifdefed out to avoid
+	potential bugs (i.e. the few bytes lost does not warrent the extra
+	maintanence and complexity that having seperate sets of locks would
+	cause)
+
+2006-08-18  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/services.c (bus_registry_acquire_service): Return an error
+	when an application tries to register the org.freedesktop.DBus Bus Name
+
+	* bus/services.c (bus_registry_release_service): Return an error
+	when an application tries to release the org.freedesktop.DBus Bus Name
+
+2006-08-17  Alp Toker  <alp@atoker.com>
+
+	* doc/dbus-specification.xml: Fix some minor typos.
+
+2006-08-17  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: use $with_init_scripts instead of $operating_system
+	to determine where to store the pid since the init scripts manipulate 
+	the pid file (patch from Marcelo Ricardo Leitner 
+	<marcelo dot leitner at terra dot com dot br>.  
+
+2006-08-16  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-threads.c: Add static DBusList *uninitialized_mutex_list and
+	static DBusList *uninitialized_condvar_list to support new late 
+	initialization threading model.  In this model threads can be initialized
+	even after the D-Bus API has been used but still needs to be initialized 
+	before the second thread has been started.  Mutexes and condvar addresses
+	are stored in the two static lists and are replaced with actuall locks
+	when threads are initalized.
+	(_dbus_mutex_new_at_location): New method for creating a mutex and placing
+	the location into the static list
+	(_dbus_mutex_free_at_location): New method for removing a mutex location 
+	from the static list and freeing the mutex
+	(_dbus_condvar_new_at_location): New method for creating a conditional 
+	variable and placing the location into the static list
+	(_dbus_condvar_free_at_location): New method for removing a conditional
+	variable location from the static list and freeing the conditional variable 
+	(init_uninitialized_locks): Atomic method which goes through the static 
+	lists of mutex and condvar location and updates them with actuall locks
+	(init_global_locks): changed to init_locks
+	
+	* dbus/dbus-connection.c:
+	(_dbus_connection_test_get_locks): New method for tests to check connections
+	(_dbus_connection_new_for_transport): Use the new at_location mutex and
+	condvar API
+	(dbus_connection_allocate_data_slot): Pass in the global lock address
+	to _dbus_data_slot_allocator_alloc
+
+	* dbus/dbus-dataslot.c:
+	(_dbus_data_slot_allocator_alloc): Use the address of the mutex
+	instead of the mutex itself
+
+	* dbus/dbus-message.c:
+	(dbus_message_allocate_data_slot): Pass in the global lock address
+	to _dbus_data_slot_allocator_alloc
+
+	* dbus/dbus-pending-call.c:
+	(dbus_pending_call_allocate_data_slot): Pass in the global lock address
+	to _dbus_data_slot_allocator_alloc
+
+	* dbus/dbus-server.c:
+	(_dbus_server_init_base): Use the new at_location mutex API
+	(dbus_server_allocate_data_slot): Pass in the global lock address
+	to _dbus_data_slot_allocator_alloc
+
+	* test/name-test/test-threads-init.c: New test case for late thread
+	initialization
+
+2006-08-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-dataslot.c (_dbus_data_slot_allocator_alloc):
+	Change _dbus_abort to _dbus_assert_not_reached because _dbus_abort
+	causes compile problems when asserts are turned off
+	Keeping _dbus_warn for printing out the message so even if
+	asserts are turned off the user gets the messages that something is 
+	wrong 
+
+2006-08-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	Patches by Kjartan Maraas <kmaraas at gnome dot org>
+
+	* bus/services.c (bus_service_list_queued_owners):
+	Add a pointer cast to fix compiler warning
+
+	* dbus/dbus-dataslot.c (_dbus_data_slot_list_get):
+	return a NULL instead of FALSE since the return type
+	is not expecting a boolean
+
+	* dbus/dbus-marshal-basic.c (_dbus_marshal_test):
+	Remove unused variable
+
+	* dbus/dbus-marshal-recursive-util.c (node_new):
+	return a NULL instead of FALSE since the return type
+	is not expecting a boolean
+
+	* dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new):
+	Send a NULL into _dbus_transport_new_for_fd instead of a FALSE
+	because we are expecting a pointer not a boolean
+
+	* dbus/dbus-sysdeps-util.c (_dbus_get_tmpdir): 
+	add void as the parameter so some compilers
+	don't complain
+
+	* dbus/dbus-transport-unix.c (_dbus_transport_new_for_domain_socket,
+	  _dbus_transport_new_for_tcp_socket):
+	Send a NULL into _dbus_transport_new_for_fd instead of a FALSE
+	because we are expecting a pointer not a boolean
+
+	* test/shell-test.c (test_command_line):
+	cast the second argument to _dbus_list_append to avoid compiler
+	warnings
+
+	* test/test-names.c (main): remove unused variable
+
+	* test/test-service.c (check_hello_from_self_reply):
+	Initialize echo_message and echo_reply to NULL
+	
+	* test/test-shell-service.c (handle_echo):
+	Remove unused variable and cast the third parameter passed to
+	dbus_connection_get_object_path_data to avoid compiler warrnings
+
+	* test/name-test/test-names.c (clear_message_queue):
+	Remove unused function
+
+	* test/name-test/test-pending-call-dispatch.c:
+	Fix format string in printf
+
+
+2006-08-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-bus.c:
+	* test/name-test/test-names.c:
+	Remove test method dbus_bus_connection_get_unique_name because 
+	we already have public method dbus_bus_get_unique_name that 
+	does the exact same thing
+
+2006-08-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-signature.c:
+	fix typos in Julio's previous patch which cause make check to fail
+
+2006-08-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-address.c (_dbus_address_test): Revert leaking strcmp.  
+	In any case it was wrong since this is a test checking to see if
+	address parsing is correct.  There was no need to get the true
+	tmp directory.  
+
+2006-08-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-macros.h: Revert the addition of stddef.h
+	as we should not be adding it to library headers 
+
+2006-08-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-signature.c:
+	Fix the unit tests so that they work if assertions are not enabled.
+	(patch from Julio M. Merino Vidal  <jmmv at NetBSD dot org>)
+
+2006-08-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/run-with-tmp-session-bus.sh:
+	* test/name-test/run-test.sh:
+	Remove bashisms (patch from Julio M. Merino Vidal
+	<jmmv at NetBSD dot org>)
+
+2006-08-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: add a version (>= 2.6.0) check for libxml2
+
+2006-08-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: make sure the compiler supports -Wfloat-equal
+	
+	* bus/dir-watch-dnotify.c: move functional code after 
+	variable declerations (C99 fix)  (patches from Jens Granseuer
+	<jensgr at gmx dot net>
+
+2006-08-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-macros.h:
+	add #include <stddef.h> so that Sun compilers don't complain about
+	the defining NULL
+
+2006-08-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-sysdeps.c:
+	* dbus/dbus-address.c:
+	* bus/activation.c:
+	* test/shell-test.c:
+	don't hardcode tmp directory (patch from Dave Meikle 
+	<dmk at davemeikle dot co dot uk>)
+
+2006-08-09  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-dataslot.c (_dbus_data_slot_allocator_alloc):
+	Change an assert to a detailed warning and abort.  
+	When allocator->lock != mutex it indicates that the user has failed
+	to initalize threads before using the D-Bus library.  This warning
+	helps the user identify the issue and fix their app.
+
+2006-08-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	These are all patches from Kjartan Maraas <kmaraas at gnome dot org>
+	with cleanups of bugs found from Coverity reports:
+
+	* dbus/dbus-sysdeps-util.c (_dbus_write_pid_file):
+	close the file on error to avoid a leak
+
+	* bus/expirelist.c (bus_expire_list_test):
+	Check for NULL on dbus_new0
+
+	* bus/activation.c (update_directory):
+	remove dead code
+
+	* bus/config-parser.c (merge_service_context_hash, start_selinux_child):
+	Fix some leaks
+
+	* bus/bus.c (process_config_every_time):
+	Fixed a leak
+
+	* bus/desktop-file.c (parse_key_value):
+	Fixed leak
+
+	* bus/selinux.c (bus_selinux_id_table_insert):
+	Fixed leak
+
+2006-08-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-object-tree.c (_dbus_object_subtree_new):
+	remove dead code
+
+2006-08-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/run-with-tmp-session-bus.sh: use #!/bin/sh instead of
+	#!/bin/bash
+
+2006-08-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Doxyfile.in: fix the INPUT line so we can generate docs 
+	when sourcedir != builddir (patch from Cygwin Ports maintainer
+	<yselkowitz at users dot sourceforge dot net>
+
+2006-08-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-sysdeps.h:
+	* dbus/dbus-sysdeps.c: 
+	* dbus/dbus-string.c: 
+	s/_dbus_printf_length/_dbus_printf_string_upper_bound to comform with
+	GLib's function which does the same thing
+
+	* configure.in:
+	* bus/Makefile.am:
+	* bus/dir-watch-default.c:
+	* bus/dir-watch-dnotify.c:
+	* bus/dir-watch-kqueue.c:
+	Add kqueue directory watching for freebsd and split the directory
+	watching code into seperate files per method/arch
+	(patches from Timothy Redaelli <drizzt at gufi dotorg>)
+
+2006-08-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in:
+	* tools/Makefile.am:
+	* tools/dbus-launch.c:
+	* bus/Makefile.am:
+	allow --with-dbus-daemondir switch to be used to make the
+	daemon install to a seperate bindir like /usr/libexec
+	(patch from Brian Cameron <brian dot cameron at sun dot com)
+
+2006-08-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/Makefile.am (install-data-hook): removed the slash after 
+	$(DESTDIR) so we don't get the double slash which does not work
+	in windows (patch from Andras Porjesz 
+	<andras dot porjesz at siemens dot com>)
+
+2006-08-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-sysdeps.h:
+	* dbus/dbus-sysdeps.c: 
+	  add _dbus_printf_length (patch from Peter Kümmel 
+	  <syntheticpp at gmx dot net>)
+
+2006-08-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-internals.c: unistd.h is not used 
+	(_dbus_verbose_real): only enable verbose printing 
+	if DBUS_VERBOSE environment var is set to '1'
+	(patch from Peter Kümmel <syntheticpp at gmx dot net>)
+
+2006-08-08  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: add a GCC flag check for -Wdeclaration-after-statement
+	so we still compile on older gcc (patch from Frederic Peters 
+	<fpeters at 0d dot be>
+
+2006-08-04  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: add -Wdeclaration-after-statement
+
+	* dbus/dbus-connection.c: change all the pending call stuff to
+	reflect the fact that pending call operations use the connection
+	lock
+
+	* dbus/dbus-pending-call.c: add locking here
+
+	* dbus/dbus-errors.c (struct DBusRealError): don't make the name
+	field const consistent with how message field is done
+
+2006-08-03  John (J5) Palmieri  <johnp@redhat.com>
+
+	* s/D-BUS/D-Bus/g
+
+2006-08-03  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-object-tree.c: Patch by Benjamin Otte 
+	<in7y118 at public.uni-hamburg dot de> - fix invalid
+	read/write reported by valgrind
+
+2006-07-24  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 0.91
+
+2006-07-22  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-connection.c:
+	(_dbus_connection_attach_pending_call_unlocked):
+	(connection_timeout_and_complete_all_pending_calls_unlocked):
+	Make sure we set timeout_added on pending calls to FALSE when
+	we remove the timeout from the connection
+
+2006-07-21  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Removed some extra bindings stuff lingering around (thanks timo)
+	* dbus-pendingcall.c (_dbus_pending_call_new): 
+	s/dbus_connection_ref/_dbus_connection_ref_unlocked fixes assertion
+	when we tried to take a lock on an already locked connection
+
+2006-07-17  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 0.90
+
+2006-07-17  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-marshal-basic.c (_dbus_type_to_string): support 64-bit
+	ints, reported by Owen Taylor
+
+2006-07-17  John (J5) Palmieri  <johnp@redhat.com>
+
+	* doc/TODO:
+	* dbus/dbus-bus.c:
+	* dbus-errors.c:
+	* dbus/dbus-marshal-validate.c:
+	  Removed TODO items which were fixed or are no longer relevent
+
+2006-07-17  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus-qt4-1.pc.in, dbus-sharp.pc.in:
+	Remove stray files from the stripped bindings
+
+2006-07-16  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-pending-call.c (_dbus_pending_call_set_timeout_error):
+	Improve the error message on reply timeout
+
+2006-07-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Remove all bindings
+
+2006-07-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus-connection.c (dbus_connection_send_with_reply): return TRUE
+	and set pending_reply out arg to NULL is connection is disconnected
+	(connection_timeout_and_complete_all_pending_calls_unlocked): New
+	static method for cleaning up pending calls on disconnect
+	(_dbus_connection_get_dispatch_status_unlocked): If we have pending 
+	calls queued timeouts on disconnect 
+
+	 * dbus/dbus-pending-call.c (_dbus_pending_call_set_connection):
+	Remove 
+
+2006-07-13  Carlos Garcia Campos  <carlosgc@gnome.org>
+
+	* bus/activation.[ch] (bus_activation_list_services): new function to 
+	get the list of services that can be activated
+
+	* bus/dispatch.c: test coverage for the new bus method
+	ListActivatableNames
+
+	* bus/driver.c: new bus method ListActivatableNames to get the list of
+	services that can be activated
+
+	* doc/dbus-specification.xml: ListActivatableNames method documentation
+
+2006-07-12  John (J5) Palmieri  <johnp@redhat.com>
+	* dbus/Makefile.am: add dbus-pending-call-internal.h to the list of
+	source files
+
+2006-07-12  John (J5) Palmieri  <johnp@redhat.com>
+	* dbus/dbus-message-factory.c:
+	Fix index into an array (patch by Peter Kümmel <syntheticpp at gmx.net>)
+
+2006-07-12  John (J5) Palmieri  <johnp@redhat.com>
+	* dbus/dbus-connection-internal.h:
+	* dbus/dbus-connection.c:
+	* file dbus/dbus-pending-call.c:
+	* dbus/dbus-pending-call.h:
+	Make DBusPendingCall an opaque type even to D-Bus internals
+
+2006-07-07  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-connection.h: remove connection_disconnect and replace with
+	connection_close
+
+	* dbus/dbus-connection.c: include dbus-bus.h
+	(_dbus_connection_read_write_dispatch): make static
+
+2006-07-07  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-connection.c (dbus_connection_close): removed deprecated
+	function
+	(dbus_connection_dispatch): On disconnect unref any shared connections
+
+	* dbus/dbus-bus.c (_dbus_bus_check_connection_and_unref): new function
+	for cleaning up shared connections on disconnect
+	(internal_bus_get): get a hard refrence to shared connections when
+	they are created
+	
+	* doc/TODO: Remove items which are no longer relevent or have been fixed
+	Split 1.0 todo items with a 0.90 freeze todo list
+ 
+2006-06-14  Ross Burton  <ross@openedhand.com>
+
+	* glib/dbus-gobject.c:
+	Free a leaking GArray (surely not!) in dbus_g_method_return.
+
+2006-06-14  Ross Burton  <ross@openedhand.com>
+
+	* tools/Makefile.am:
+	* tools/dbus-monitor.c:
+	Don't use the GLib bindings in dbus-monitor (patch from Ralf
+	Habacker).
+	
+2006-06-14  Ross Burton  <ross@openedhand.com>
+
+	* tools/dbus-print-message.c:
+	Also print the object path when outputting signals or method calls.
+
+2006-06-13  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* qt/src/Makefile.am: install the qdbus.h header.
+	This allows people to actually use the installed code.
+
+2006-06-12  Ross Burton  <ross@openedhand.com>
+
+	* glib/dbus-gproxy.c:
+	Don't leak a GArray when firing signals (thank Rob Taylor for review).
+
+2006-06-12  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* Released 0.62
+
+2006-06-12  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* dbus/dbus-arch-deps.h.in: Remove spurious semi-colons that
+        break pedantic builds. Closes bug 6043 (patch approved by
+        Havoc back in February).
+
+2006-06-12  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* qt/src/qdbusintegrator.cpp: Fix bug in parsing async methods
+        that took a QDBusMessage parameter.
+	* qt/src/qdbusbus.h: Add a default flag for RequestName.
+	* qt/tools/dbus.cpp: Don't use automatic call because we might
+        be calling an async method: request a reply.
+
+2006-06-11  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* test/qt/*: Update the testcases, including testing the new
+        functionality of sending null QByteArray and QString over the
+        bus. Add new headertest test and restore the old
+        qdbusxmlparser test.
+
+2006-06-11  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* qt/tools/dbuscpp2xml.cpp: Compile on Windows.
+	* qt/tools/dbusidl2cpp.cpp: Add missing newline.
+
+	* qt/examples/Makefile.am:
+	* qt/examples/chat.h: Use UI-generated files with the ui_*.h
+	form.
+
+	* qt/src/qdbusmarshall.cpp: Allow sending of QString() and
+	QByteArray() (nulls) over the bus.
+	* qt/src/qdbusabstractinterface.cpp: Use the correct variable,
+	the one that has the signature suffix stripped.
+	* qt/src/qdbusreply.h: Make some methods const.
+
+2006-06-09  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	Patch from Timo Hoenig <thoenig@suse.de>.
+
+	* qt/dbus/Makefile.am: New file.  Fix "make dist", add all headers
+	required during build to EXTRA_DIST.
+	* qt/src/Makefile.am: Fix "make dist", add 'qdbus.h' to EXTRA_DIST.
+	* qt/Makefile.am: Fix "make dist", add 'dbus' to DIST_SUBDIRS.
+	* configure.in: Fix "make dist", take care that the Makefile for
+	qt/dbus is being generated.
+
+2006-06-07  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/bus.c: Fix eavesdropping on method calls
+
+2006-06-07  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in:
+	* dbus/dbus-userdb-util.c:
+	Add Solaris console owner patch from Artem Kachitchkine
+
+2006-06-07  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* qt/Makfile.am:
+	* qt/src/Makefile.am: Fix the EXTRA_DIST after the
+	reorganisation. Thanks to Timo Hoenig for pointing this out.
+
+2006-06-06  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-gtype-specialized.c: Fix obvious leak of GArray in every
+	  call to dbus_g_type_get_struct.
+
+2006-06-06  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-gvalue-utils.c: Fix the failing test where static string
+	  pointers were put into a GPtrArray-based specialised collection, and
+	  then freed along with the array. GValues which you add into
+	  collections or maps which have the NOCOPY flag set are assumed to not
+	  belong to the caller, so rather than the existing pointer-stealing
+	  semantics, they are copied instead. Given that the main consumers of
+	  this abstraction are the bindings themselves, I don't think this is
+	  too bad, but others should watch their choice of take vs set_static.
+
+2006-06-06  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-gvalue-utils.c: Spotted a warning about the return value
+	  of g_slist_prepend not being used. Fixed copying of slist-based
+	  specialised collections, then wrote a test case and found that it was
+	  all broken. Went on to fix iterating and appending too. Good thing
+	  nobody uses this code yet.
+
+2006-06-06  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-gvalue-utils.c: Remove duplicated code by having all of
+	  the iterators use gvalue_take_ptrarray_value (the GValues themselves
+	  are discarded without unsetting, so it makes no difference whether
+	  we take or set_static). Remove cases for G_TYPE_POINTER because
+	  there really is nothing useful we can do with them in our
+	  specialised types - we *need* boxed copy/free functions at the very
+	  least.
+
+2006-06-05  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* qt/dbus: Add directory. I had forgotten to add this
+	yesterday after the move...
+
+	* qt/examples/Makefile.am:
+	* qt/examples/dbus.cpp: Moved to qt/tools/dbus.cpp.
+
+	* qt/tools/Makefile.am:
+	* qt/tools/dbus.cpp: Moved from qt/examples/dbus.cpp.
+	Added feature to get and set properties.
+	Added validation of service, object path and interface names.
+
+	* qt/tools/dbusidl2cpp.cpp: Two new features:
+	1) Allow specifying both the header and the source file names,
+	by separating them with a colon.
+	2) Don't write an interface output if the -p switch wasn't
+	given, but the -a was.
+
+	* qt/src/*: Fix usage of Iterators and ConstIterators.
+	Fix shadowing of variables by other variables (-Wshadow).
+	Fix keyword-cleanliness in headers.
+	Fix ASCII-cast (QLatin1String, QLatin1Char).
+	Fix validation of member names.
+	Add extra checking of introspection data during XML parsing.
+	Various bug fixes.
+
+2006-06-04  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* dbus/Makefile.am:
+	* dbus/qdbus.h: Remove unnecessary file. This is mirrored into
+        qt/dbus/qdbus.h now.
+
+2006-06-04  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* configure.in: Make --disable-qt actually do
+          something. Patch inspired by Zack Rusin.
+
+2006-06-04  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* qt/: Update to Subversion r548032.
+	This includes a big reorganisation of the files inside the
+	subdir.
+
+2006-05-30  Sjoerd Simons  <sjoerd@luon.net>
+
+	* dbus/dbus-sysdeps.c: Make tcp socket connection error somewhat more
+	clear:  
+	"Failed to connect to socket <host>:<port> <error>" instead of
+	"Failed to connect to socket <host>: <error>:<port>"
+
+	* dbus/dbus-transport-unix.c: Fix crash when no host option is given
+	for a tcp transport. 
+
+2006-05-29  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/*: Update the QtDBus bindings up to revision 546310 in
+        Subversion.
+	This adds the dbuscpp2xml tool, that parses a C++ header and
+        outputs a D-BUS Introspection XML.
+
+2006-05-21  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gproxy.c: Put in a pile of assertions that the proxy name
+	is not NULL when it shouldn't be. Also a couple of possible fixes
+	for #4637 though I don't understand why the bug happens, to be
+	honest... also the object constructor has an assert name != NULL
+	and the name is only currently NULL for peer-to-peer proxies that 
+	I don't think anyone uses? So it should be asserting.
+	Anyway, for now at least see if we get an earlier assertion failure.
+
+	* glib/dbus-gvalue-utils.c: Put in a couple of assertions for
+	apparently broken code to be sure the tests fail and someone 
+	will fix them...
+
+2006-05-07  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/qdbusmarshall.cpp: Fix a problem of demarshalling lists
+        and arrays when they had a single element: has_next returns
+        false, even before you read the element. So, instead, check
+        the array length.
+
+2006-05-06  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/qdbusmessage.cpp:
+	* qt/qdbustypehelper_p.h:
+	* qt/qdbusintegrator.cpp: gcc 3.4 doesn't like Q_FOREACH when
+	the list is a const-reference
+
+2006-05-03  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Adding old doc patch that never got applied
+	
+	* dbus/bus.c (dbus_bus_add_match): Add documentation
+
+	* doc/dbus-specification.xml: Add documentation for the match rules
+	  and the AddMatch and RemoveMatch methods
+
+2006-05-02  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/dbusidl2cpp.cpp: There's no callAsync. Use the correct
+        call (r535506)
+
+	* qt/dbusidl2cpp.cpp:
+	* qt/qdbusabstractadaptor.cpp:
+	* qt/qdbusabstractadaptor.h: Make QDBusAdaptorConnector be a
+        sibling of the QDBusAbstractAdaptor objects instead of the
+        parent. (r535848)
+
+	* qt/dbusidl2cpp.cpp:
+	* qt/qdbusabstractinterface.cpp:
+	* qt/qdbusabstractinterface.h:
+	* qt/qdbusabstractinterface_p.h:
+	* qt/qdbusinterface.cpp: Make properties in interfaces
+        actually work. The code that was generated would not compile,
+        due to moc calls to functions that did not exist. They now
+        shall. (r536571)
+
+2006-04-30  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* Makefile.am:
+	* configure.in:
+	* dbus-qt4-1.pc.in: Add a pkg-config file for libdbus-qt4-1.
+	Thanks to Brad Hards for providing the patch
+
+2006-04-29  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/dbusidl2cpp.cpp: There's no callAsync. Use the correct
+        call. (r535506)
+
+2006-04-29  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/examples/dbus.cpp: Enhance error messages and use
+        QDBusInterfacePtr.
+
+2006-04-29  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/qdbusinterface.h: Rename QDBusRef to QDBusInterfacePtr
+        and disable the copy operators. (r533772, r534746)
+
+	* qt/qdbuserror.h: Remove the automatic cast to bool. (r533929)
+
+	* qt/qdbusabstractinterface.cpp:
+	* qt/qdbusabstractinterface.h: Change the default call mode to
+        not use the event loop. Add convenience call() methods that
+        take a CallMode parameter. (r534042)
+
+	* qt/qdbusconnection.h: Change the default call mode to not
+        use the event loop. (r534042)
+
+	* qt/qdbusinterface.cpp:
+	* qt/qdbusinterface.h: Add a method to tell us if the
+	interface is valid (since we don't return a null pointer
+	anymore) (r534099)
+
+	* qt/qdbusinterface_p.h: Don't crash if metaObject is 0
+        (r534101)
+
+	* qt/qdbusinternalfilters.cpp: Decouple the introspection
+        function in two so taht we get the chance to introspect
+        without having a QDBusMessage (r534102)
+
+	* qt/qdbusbus.h:
+	* qt/qdbusconnection.cpp:
+	* qt/qdbusconnection_p.h:
+	* qt/qdbusintegrator.cpp: Keep a list of our own names to
+        avoid a round-trip to the server when attempting to introspect
+        one of our own objects. Also make sure the filter functions
+        match the empty interface as well. (r534108)
+	Don't keep the connection names. Instead, trust the unique
+        connection name (r534111)
+	Remove event loop usage (r534112)
+
+2006-04-29  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/qdbusintegrator.cpp: Fix assertion failure spotted by
+	Brad Hards.
+
+2006-04-28  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-gproxy.c: Fix properties so that they can be given in
+	any order, making it easier for people who inherit from this
+	object.
+
+2006-04-28  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-gvalue-utils.c: Patch from Jakub Stachowski to fix leaking
+	of memory from within pointer arrays and lists. Fixes bug #6300.
+
+2006-04-28  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-gvalue.c: Patch from Jakub Stachowski to fix a leak in
+	generating struct signatures. Fixes bug #6083.
+
+2006-04-28  Robert McQueen  <robot101@debian.org>
+
+	* qt/Makefile.am: Tweak CLEANFILES from qdbusconnection.moc
+	to qdbusconnection_p.moc.
+
+2006-04-24 John (J5) Palmieri <johnp@redhat.com>
+
+	* README, INSTALL: Doc fixes
+	Patch from Brad Hards <bradh at frogmouth.net>
+
+2006-04-23  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/examples/dbus.cpp: Use the new merged-interface mode for
+	the dynamic meta object. No need to guess which interface to
+	call.
+
+2006-04-23  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/qdbusconnection_p.h:
+	* qt/qdbusmetaobject.cpp:
+	* qt/qdbusmetaobject_p.h:
+	* qt/qdbusintegrator.cpp: Use the new merged-interface mode
+	for the dynamic meta object. No need to guess which
+	interface to call.
+	* qt/qdbusabstractinterface_p.h:
+	* qt/qdbusconnection.cpp:
+	* qt/qdbusintegrator.cpp:
+	* qt/qdbusinterface.cpp:
+	* qt/qdbusinterface.h: Make findInterface always return a non-null pointer.
+	Add a QDBusRef that looks and behaves like DCOPRef.
+
+2006-04-23  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* dbus/dbus-connection.c: Interfaces are optional in method
+        calls, so don't give up if the interface parameter is NULL.
+	Patch reviewed by Havoc Pennington.
+
+2006-04-23  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/qdbusreply.h: Add default constructor and operator=
+          (r532625)
+	* qt/qdbustypehelper_p.h: Use a clean namespace: no foreach()
+          in public headers (r532952)
+	* qt/qdbusabstractinterface.cpp:
+	* qt/qdbusabstractinterface_p.h: Add the AutoDetect mode and
+          make it the default (r532951)
+
+2006-04-19  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-connection.c: Fix asserts
+	Patch from Tim Moloney <t.moloney at verizon.net>
+
+2006-04-19  John (J5) Palmieri  <johnp@redhat.com>
+
+	* mono/Connection.cs, mono/Message.cs: Check Target type
+	Patch from Aaron Bockover (abockover at novell.com)
+
+2006-04-13  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* INSTALL: fine-tune the requirements for the Qt4 binding.
+
+2006-04-16  Daniel P. Berrange  <dan@berrange.com>
+
+	* tools/dbus-print-message.c: Added support for printing of all 
+	  remaining data types. Fixed logic for indentation of compound
+	  data types.
+	
+2006-04-15  Daniel P. Berrange  <dan@berrange.com>
+
+	* INSTALL: fill out content of file providing DBus specific
+	  build installations, followed by generic Auto* INSTALL file
+	  content
+	
+2006-04-13  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/qdbusintegrator.cpp: Work around g++ 3.3 bug.
+	  Patch by Stefan Eilers. (r529537)
+
+2006-04-13  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/qdbusinternalfilters.cpp: Don't show the parent's
+  	  contents (r528208)
+
+2006-04-10  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/Makefile.am: fix the dependency for
+          qdbusconnection_p.moc. It's included in qdbusintegrator.cpp,
+	  not in qdbusconnection.cpp.
+	  Thanks to Jakub Stachowski <stachowski@hypair.net> for
+          spotting this.
+
+2006-04-10  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/examples/listnames.cpp:
+	* qt/examples/Makefile.am: Three ways to list the names on the
+	  bus.
+
+2006-04-10  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* test/qt/tst_hal.cpp: Remove the waiting, since it's not
+          needed anymore. Requires Qt 4.1.3 to work properly. (r528148)
+
+2006-04-10  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	Merge from Subversion:
+	* qt/qt-dbus.qdocconf: Update Trolltech's webpage link to
+	  something that exists (r526315)
+	* qt/qdbusinternalfilters.cpp: Correctly detect non-scriptable
+	  slots/signals (r526316)
+	* qt/qdbusinternalfilters.cpp: Fix the setProperty call and
+	  also return an unknown-method error if the parameters don't
+	  match for org.freedesktop.DBus.Properties. (r526842)
+	* qt/examples/dbus.cpp: Allow passing of QVariants (r526843)
+	* qt/qdbusintegrator.cpp: Restore the proper order of
+	  delivery: don't make method returns be delivered on priority
+	  (r528150)
+
+2006-03-28  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* configure.in qt/Makefile.am: add qt/examples
+	* qt/examples: Add QtDBus example programs:
+	  - hello: Hello, World
+	  - ping: Simple method-calling program
+	  - pong: Simple object-exporting program (not using adaptors)
+	  - complexping: Interactive method-calling program 
+		(also gets and sets properties).
+	  - complexpong: Sample program exporting methods, signals and
+		properties, using adaptors.
+	  - dbus: Simple implementation of a generic method-calling
+		program, similar to 'dbus-send', but with semantics
+		similar to 'dcop'.
+	  - chat: Simplistic chat program, implemented using signals
+		and the system bus. Looks like IRC.
+
+2006-03-28  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* configure.in: Detect QtGui (necessary for one of the
+          example programs). Note: this increases the minimum required
+          version of Qt to 4.1.3.
+
+2006-03-28  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* test/qt/*: Sync with KDE Subversion revision 523647.
+        Update the testcases to the new API. Remove testcases for
+        classes that are no longer public or have been removed.
+
+2006-03-28  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/*: 
+	* dbus/qdbus.h: Sync with KDE Subversion revision
+	523647. Hopefully, this will be the last of the
+	source-incompatible changes. Documentation has been improved;
+	support for QList<basic-types> has been added; QDBusObject is
+	gone; QDBus(Abstract)Interface is now a QObject with
+	auto-generated meta-object; QDBusIntrospection is marked
+	private, since QMetaObject can be used now; lots of bugfixes.
+
+2006-03-16  John (J5) Palmieri  <johnp@redhat.com>
+
+	Patch from Milosz Derezynski <internalerror at gmail.com>
+	
+	* configure.in:
+	Output the service directory in the configure summary
+
+	* dbus-1.pc.in:
+	Add session_bus_services_dir
+
+2006-03-10  Ross Burton  <ross@openedhand.com>
+
+	* tools/dbus-print-message.c:
+	Add support for object paths and signatures.
+
+2006-03-06  Sjoerd Simons <sjoerd@luon.net>
+
+	* bus/bus.c: (bus_context_reload_config): Flush the user database cache on
+	config reload.
+	* bus/dbus-daemon.1.in: Also note that SIGHUP flushes the user/group
+	information caches
+	* dbus/dbus-hash.c: (_dbus_hash_table_remove_all): 
+	* dbus/dbus-hash.h: Add function to remove all entries from a hash table
+	* dbus/dbus-userdb.c: (_dbus_user_database_flush):
+	* dbus/dbus-userdb.h: Add function to flush all user/group information
+	caches.
+
+2006-03-06  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/dbusidl2cpp.cpp:
+	* qt/Makefile.am: add the dbusidl2cpp tool, the replacement
+	for dcopidl2cpp, found in the KDE installations (or the more
+	modern kalyptus): generate Qt4 C++ code for the input XML
+	introspection. Currently no IDL parsing.
+
+2006-03-06  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* test/qt/*: Update the self-tests.
+
+2006-03-06  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/*: 
+	* dbus/qdbus.h: Sync with KDE Subversion revision 516237. This
+	represents the first feature-complete version of the Qt4
+	bindings since I took ove maintainership.
+
+2006-03-06  Thiago Macieira  <thiago.macieira@trolltech.com>
+
+	* qt/Doxyfile: Adding a Doxyfile for the Qt4 bindings
+        dir. This is C++, so we can't use the DBus ones.
+
+2006-03-02  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx: Remove refrence to sys/cdefs.h
+	(Patch from Artem Kachitchkine <Artem.Kachitchkin at Sun.COM>)
+
+2006-03-02  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-connection.c: 
+	(_dbus_connection_block_pending_call):
+	Check to see if our data has already been read off the connection
+	by another blocking pending call before we block in poll.
+	(check_for_reply_and_update_dispatch_unlocked):
+	Code taken from _dbus_connection_block_pending_call - checks for
+	an already read reply and updates the dispatch if there is one.
+
+	* test/name-test/test-pending-call-dispatch.c:
+	New test for making sure we don't get stuck polling a 
+	dbus connection which has no data on the socket when
+	blocking out of order on two or more pending calls.
+
+2006-02-28  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* qt/Makefile.am: Patch by Sjoerd Simons. More .moc issues:
+        make/automake don't detect that we're talking about the same
+        .lo file if I specify the full path to the source files.
+
+2006-02-26  Havoc Pennington  <hp@redhat.com>
+
+	* bus/dbus-daemon.1.in: improve the language in a couple spots I noticed
+
+	* dbus/dbus-bus.c (internal_bus_get): in the error message if the
+	session bus variable is unset, suggest "man dbus-launch" and "man
+	dbus-daemon" to figure out how to fix the problem
+
+2006-02-25  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-glib-tool.c (usage): fix up the usage message, someone
+	should make this thing use the new glib options parser
+
+2006-02-25  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* qt/Makefile.am: Patch by Sjoerd Simons. Fix the path to the
+        .lo files taking moc sources.
+
+2006-02-25  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus.h, dbus/Makefile.am: add dbus-signature.h to dbus.h
+	and install it as a public header
+
+2006-02-24  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 0.61
+
+2006-02-24  John (J5) Palmieri  <johnp@redhat.com>
+	
+	* proxies.py: Fix the callchain
+
+2006-02-24  John (J5) Palmieri <johnp@redhat.com>
+	
+	* patch from Sjoerd Simons <sjoerd at debian.org>:	
+
+	* dbus/dbus-sysdeps-util.c (_dbus_group_info_free): Moved to 
+	dbus/dbus-sysdeps.c
+
+	* dbus/dbus-userdb.c (_dbus_group_info_free_allocated): Don't
+	call _dbus_group_info_free_allocated which causes infinite loop,
+	correctly call _dbus_group_info_free
+
+2006-02-20  Thiago Macieira <thiago.macieira@trolltech.com>
+
+	* qt/qdbusinterface_p.h:
+	* qt/qdbusinterface.cpp: Use the standard
+	org.freedesktop.DBus.Method.NoReply annotation for the "async"
+	calls instead of creating one for us.
+
+	* qt/qdbusconnection_p.h:
+	* qt/qdbusintegrator.cpp: Remove debugging code.
+
+	* qt/qdbusintegrator.cpp:
+	* qt/qdbusmessage.cpp:
+	* qt/qdbusmessage_p.h:
+	* qt/qdbusmessage.h: Change the behaviour of automatic
+	reply-sending: now a reply is always sent, unless the caller
+	didn't request one or if the user slot has already sent one.
+
+2006-02-16  Robert McQueen  <robot101@debian.org>
+
+	* configure.in: Patch from Debian packages by Sjoerd Simons
+	<sjoerd@debian.org> to add --with-qt-moc and --with-qt3-moc
+	arguments so it's possible to build both bindings in the
+	same tree.
+
+	* qt/Makefile.am: Fix truncated value so that make dist works.
+
+2006-02-16  Robert McQueen  <robot101@debian.org>
+
+	* acinclude.m4, configure.in: Patch from Brad Hards
+	<bradh@frogmouth.net> to avoid warnings from autoconf 1.9 by
+	improving quoting, re-ordering a few checks, and a few other
+	aesthetic tidy-ups.
+
+2006-02-16  Robert McQueen  <robot101@debian.org>
+
+	* dbus/dbus-message.c (dbus_message_iter_get_fixed_array):
+	Patch from Rob Taylor <rob.taylor@collabora.co.uk> to correct a bogus
+	assertion that the next element to read from the iter is fixed in
+	size. This is not the case when you are at the end of the iter,
+	because the next element type is INVALID.
+
+	* dbus/dbus-string.c (_dbus_string_init_const_len): Correct a
+	a bogus assert which means that you may not initialise a 0-length
+	string unless you provide a non-NULL pointer. This prevented
+	you from marshalling messages containing zero-length arrays in
+	some cases.
+
+	* glib/dbus-gvalue.c (demarshal_collection_array): Another patch
+	from Rob to correct bogus asserts when trying to demarshal an
+	array and get_fixed_array got you 0 elements. Append nothing to
+	the GArray in this case.
+
+	* test/glib/test-dbus-glib.c: Add a test case for round-tripping
+	an empty array via the glib bindings. Without all of the above
+	patches, this new test fails.
+
+2006-02-16  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-gmain.c: Make the previous commit compile.
+
+	* python/_dbus.py, python/matchrules.py: Patch from Ole Andre
+	Ravnaas <ole.andre.ravnaas@collabora.co.uk> to allow you to
+	specify sender_keyword="foo", path_keyword="bar" when adding
+	a signal listener, so that you can bind to signals generically
+	but still do something useful in your callback.
+
+	* python/dbus_bindings.pyx: Demarshal the byte type as unsigned
+	chars so that they're not cast to chars and made negative. Thanks
+	to Jakub Stachowski for reporting this and testing the fix.
+
+2006-02-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-glib.h:
+	* glib/dbus-gmain.h:
+	(dbus_g_connection_open): new method for openning
+	a connection to an arbitrary address in the glib bindings
+
+	* ChangeLog: checkin last entry which doesn't seem to be commited
+
+2006-02-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/dbus-launch.c: Fixed sh syntax output
+
+2006-02-13  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-binding-tool-glib.c, glib/dbus-gmain.c,
+	glib/dbus-gsignature.c, glib/dbus-gtype-specialized.c,
+	glib/dbus-gtype-specialized.h, glib/dbus-gvalue-utils.c,
+	glib/dbus-gvalue-utils.h, glib/dbus-gvalue.c:
+	Patch from Rob Taylor <rob.taylor@collabora.co.uk> to add a big
+	missing piece of the glib bindings jigsaw puzzle. This modifies
+	the existing specialised types to have N type parameters (rather
+	than the current 1 or 2 for arrays and dictionaries respectively).
+	You can then use this to get a glib type to represent any arbitrary
+	D-Bus struct type using dbus_g_type_get_struct. The only
+	implementation of these types is with GValueArrays as before,
+	but it's now possible to store these in arrays, emit them in
+	signals, etc.
+
+2006-02-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-signature.c (dbus_signature_iter_recurse): Correctly
+	deal with nested arrays (Bug #5823) Patch by Thiago Macieira 
+	<thiago.macieira at trolltech.com>
+
+2006-02-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* mono/doc/Makefile.am: Fix parallel make problem with mono-doc
+	(Bug #4213) Patch from Doug Goldstein <cardoe at gentoo.org>
+
+2006-02-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/connection.c (bus_connections_expect_reply): Make
+	pending reply limit not common to all connections (Bug #5416)
+	Patch from Kimmo Hämäläinen <kimmo.hamalainen at nokia.com>
+
+2006-02-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/dbus-launch.c: Fixed csh syntax output (Bug #5720)
+
+2006-02-10  John (J5) Palmieri  <johnp@redhat.com>
+
+	* gcj/Makefile.am: point to correct jar command (Bug #4529)
+	patch from Doug Goldstein <cardoe at gentoo.org>
+
+2006-02-09  Joe Shaw  <joeshaw@novell.com>
+
+	* mono/Arguments.cs: Fix a magic number in the mono bindings
+	that doesn't work on 64 bit arches.  Patch from Peter Johanson.
+
+2006-01-27  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-binding-tool-glib.[ch]: Patch based on Ricardo Kekki's
+	patch to use an annotation org.freedesktop.DBus.GLib.ClientCSymbol
+	when generating the client-side methods, instead of overloading
+	CSymbol which broke everything horribly. My apologies.
+
+2006-01-27  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-gtype-specialized.[ch], glib/dbus-gvalue-utils.c: Patch
+	by me and Rob Taylor to add a simple_free function to D-Bus map
+	and collection types, which allows those types which can be freed
+	with a GDestroyNotify (such as GHashTables and GArrays, but not
+	GPtrArrays) to be stored as the values in hashtables.
+
+	* test/glib/test-dbus-glib.c, test/glib/test-service-glib.{c,xml}:
+	Patch by Rob Taylor to add nested dicts to the glib tests to check
+	the above code works, and appears not to leak when called repeatedly.
+
+2006-01-27  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-gvalue.c (demarshal_valuearray): Patch from Rob Taylor
+	to free a D-Bus allocated string with dbus_free () instead of
+	g_free ().
+
+2006-01-27  Iain Holmes  <iain@openedhand.com>
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_dispose): Protect the dispose
+	method from being called multiple times.
+
+2006-01-19  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-binding-tool-glib.c: Patch from Rob Taylor
+	<rob.taylor@collabora.co.uk> to add support for generating bindings
+	to arrays that are represented as GPtrArrays rather than GArrays (ie
+	size-variable things, such as strings, objects, structs, etc).
+
+2006-01-05  Robert McQueen  <robot101@debian.org>
+
+	* dbus/dbus-glib.h, glib/dbus-gproxy.c: Patch from Ricardo Kekki
+	<ricardo.kekki@movial.fi> to make it possible to inherit from
+	DBusGProxy, by splitting the DBusGProxy struct into a public part and
+	a private part, and moving the setting of the DBusGProxyManager into a
+	connection property, allowing proper GObject construction.
+
+2006-01-05  Robert McQueen  <robot101@debian.org>
+
+	* glib/dbus-binding-tool-glib.c: Patch from Ricardo Kekki
+	<ricardo.kekki@movial.fi> to make dbus-binding-tool heed C symbol name
+	annotations when generating glib client bindings.
+
+2005-12-19 John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-shared.h: Call it shared constants instead of shared macros
+
+	* dbus/dbus-protocol.h: add DOxygen markup to quiet warnings
+
+2005-12-19 John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-shared.h: add DOxygen markup to quiet warnings
+
+2005-12-19 John (J5) Palmieri  <johnp@redhat.com> 
+
+	* dbus/dbus-macros.h: correct DOxygen end of section (s/}@/@})
+
+2005-12-19  Ross Burton  <ross@openedhand.com>
+
+	* doc/dbus-tutorial.xml:
+	Document the Glib client-side bindings, and list all possible annotations.
+
+2005-12-19  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/bus.c (dbus_bus_release_name): Add documentation
+
+2005-12-06  Robert McQueen  <robot101@debian.org>
+
+	* python/service.py: s/sucessful/successful/ so we're allocating to
+	and reading from the same variable. Oops.
+
+2005-11-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 0.60
+
+2005-11-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* test/qt/Makefile.am: build from srcdir
+
+	* qt/qtconnection.cpp (requestName): Changed PROHIBIT_REPLACE to ALLOW_REPLACE
+	Note - this code is wrong and needs to be fixed by the Qt binding
+	developers.  The flags should be treated as bitfields and not enums.
+
+	* qt/qtconnection.h: Change ProhibitReplace to AllowReplace
+
+2005-11-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-list.c (_dbus_list_insert_after_link, _dbus_list_insert_after, 
+	  link_after): remove #ifdef DBUS_BUILD_TESTS since we use these methods 
+	  in production code
+
+2005-11-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-connection.c (dbus_connection_read_write): Add new
+	method for getting messages off the bus in the absence of a
+	mainloop.  This method is much like 
+	dbus_connection_read_write_dispatch except it does not dispatch
+	the messages to a registered filter function.  Instead it
+	allows a developer to process messages by directly popping
+	them off the bus.
+
+2005-11-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/desktop-file.c (parse_key_value): Ignore locales allowing 
+	the parser to continue instead of returning error
+	(bus_desktop_file_load): Do not free parser data when
+	parse_section_start or parse_key_value fails because it was 
+	already freed by parser_free (patch from Carlos Garcia Campos  
+	<carlosgc at gnome.org>)
+
+2005-11-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-auth.c, dbus/dbus-connection.c, dbus/dbus-keyring.c,
+	dbus/dbus-server-debug-pipe.c, glib/dbus-binding-tool-glib.c
+	glib/dbus-glib-tool.c, glib/dbus-gparser.c, glib/dbus-gproxy.c
+	test/test-segfault.c, test/test-utils.c,
+	test/glib/test-dbus-glib.c, tools/dbus-cleanup-sockets.c
+	tools/dbus-launch.c, tools/dbus-tree-view.c, tools/dbus-viewer.c:
+	Various cleanup of dead code and compiler warnings (patch from
+	Kjartan Maraas <kmaraas at gnome.org>) 
+
+2005-11-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* glib/dbus-gmain.c (connection_setup_add_watch): plugged a leak
+	(patch from Carlos Garnacho Parro <carlosg at gnome.org>
+
+2005-11-27  Robert McQueen  <robot101@debian.org>
+
+	* python/dbus_bindings.pyx: Repair my previous commit which reverted
+	part of the preceding one. Oops. Merge patch by Johan Hedberg
+	<johan.hedberg@nokia.com> to fix marshalling of 16-bit integer values
+	on big-endian platforms.
+
+	* test/python/test-client.py: Add some 16-bit integers to the test
+	values.
+
+2005-11-27  Carlos Garcia Campos  <carlosgc@gnome.org>
+
+	* glib/dbus-gobject.c: Append a GValue instead of a basic type in
+	method return message for property getters
+
+2005-11-27  Robert McQueen  <robot101@debian.org>
+
+	* python/dbus_bindings.pyx: Fix a bug where doing a strict append
+	with type v of an instance of dbus.Variant(foo, type='x') caused
+	it to be boxed twice before sending over the bus.
+
+	* python/dbus_bindings.pyx, python/service.py,
+	test/python/test-client.py: Update the constants for the new
+	request_name flags, and update comments/test cases now that queueing
+	is the default action.
+
+2005-11-22  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in:
+	- Change version to 0.60 for impending release
+	- upped the sonames because of ABI and API breakage
+
+2005-11-22  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: Add test/name-test/Makefile to the generated
+	Makefile list
+
+	* dbus/dbus-shared.h (#define DBUS_NAME_FLAG_ALLOW_REPLACEMENT):
+	New flag which replaces DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT
+	(#define DBUS_NAME_FLAG_DO_NOT_QUEUE): New flag for specifying
+	not to queue an ower if it can't be the primary owner
+
+	* bus/bus.h: Add new internal BusOwner struct
+
+	* bus/driver.c (bus_driver_handle_hello): Send flags (0 for default)
+	to bus_registry_ensure and don't set the prohibit_replacement flag
+	since they are now set per BusOwner and not per name.
+	(bus_driver_handle_list_queued_owners): bus method (ListQueuedOwners) 
+	that returns the list of connections in a name's connection queue
+	
+	* bus/services.c (struct BusService): remove prohibit_replacement field
+	(struct BusOwner): new struct for keeping track of queued connections
+	and their associated flags for the queue
+	(struct BusRegistry): add a BusOwner memory pool
+	(bus_registry_new): initialize the BusOwner memory pool
+	(bus_registry_unref): free the BusOwner memory pool
+	(_bus_service_find_owner_link): new internal method for
+	searching the queue for a specific connection
+	(bus_owner_set_flags): new method for adding setting the flags on a
+	bus owner
+	(bus_owner_new): new method that creates a BusOwner object from the
+	pool and sets its flags
+	(bus_owner_ref, bus_owner_unref): ref counting for BusOwner objects
+	(bus_registry_ensure): Add the flags parameter
+	(bus_registry_acquire_service): Switch from using raw connections to
+	using the BusOwner struct
+	Add new state machine for dealing with the new set of flags
+	(bus_registry_set_service_context_table, struct OwnershipCancelData, 
+	cancel_ownership, free_ownership_cancel_data, 
+	add_cancel_ownership_to_transaction, struct OwnershipRestoreData, 
+	restore_ownership, free_ownership_restore_data, 
+	add_restore_ownership_to_transaction): Switch to using BusOwner 
+	instead of raw connections
+	(bus_service_add_owner): Add flags parameter
+	Switch to using BusOwner instead of raw connections
+	Add state machine for dealing with the new set of flags
+	(bus_service_swap_owner): Swaps the first and second owners in the
+	queue.  Used to make sure proper signals are sent when a service looses 
+	or gains primary ownership.  We never insert an owner at the top of the
+	queue.  Instead we insert it in the second position and then swap.
+	(bus_service_remove_owner): Remove the owner from the queue sending
+	out the NameLost and NameOwnerChanged signals if the we were the 
+	primary owner
+	(bus_service_get_primary_owners_connection): New method that extracts
+	the connection from the primary owner
+	(bus_service_get_primary_owner): Returns the BusOwner instead of the 
+	connection
+	(bus_service_get_allow_replacement): Changed from the old 
+	bus_service_get_prohibit_replacement method.  Checks the flags of the 
+	primary owner and returns if it can be replaced or not
+	(bus_service_set_prohibit_replacement): removed
+	(bus_service_has_owner): returns TRUE if and owner with
+	the specified connection exists in the queue
+	
+	* dbus/dbus-bus.c (dbus_bus_connection_get_unique_name): New helper
+	method that only compiles if tests are enabled.  Allows us to get the 
+	unique name of a connection so we can check it against the queue when
+	doing regression tests
+
+	* bus/activation.c (bus_activation_send_pending_auto_activate),
+	bus/dispatch.c (bus_dispatch),  
+	bus/driver.c (bus_driver_handle_get_service_owner, 
+	bus_driver_handle_get_connection_unix_user, 
+	bus_driver_handle_get_connection_unix_process_id,
+	bus_driver_handle_get_connection_selinux_security_context),
+	bus/signals.c (connection_is_primary_owner): 
+	use bus_service_get_primary_owners_connection instead of
+	bus_service_get_primary_owner
+
+	* dbus/dbus-sysdeps.c (_dbus_connect_unix_socket, 
+	_dbus_listen_unix_socket): Calculate the length of the socket
+	path and use that instead of using a fixed length which was
+	causing socket names to contain many trailing Nul bytes.
+
+	* dbus/dbus-glib-lowlevel.h, glib/dbus-gobject.c
+	(dbus_g_method_get_sender): New method for extracting the sender 
+	from a DBusGMethodInvocation
+	(dbus_g_method_return_get_reply): changed name to 
+	dbus_g_method_get_reply
+	(dbus_g_method_return_send_reply): changed name to
+	dbus_g_method_send reply
+
+	* doc/dbus-specification.xml: New docs that describe how the new
+	queueing system works and talks about the changes to the how
+	we specify socket names
+
+	* glib/examples/example-service.c, 
+	glib/examples/example-signal-emitter.c,
+	glib/examples/statemachine/statemachine-server.c:
+	Changed the RequestName flags to the new system
+
+	* test/name-test/ (test-names.c, run-test.sh, Makefile.am): New
+	regression test suite for testing various states of the new
+	queueing system
+	
+2005-11-15  Robert McQueen  <robot101@debian.org>
+
+	* dbus/dbus-glib-lowlevel.h, glib/dbus-gobject.c: Patch from Rob
+	Taylor to add two methods, dbus_g_method_return_get_reply and
+	dbus_g_method_return_send_reply, to allow you to get the reply
+	message from a DBusGMethodInvocation, append arbitrary stuff to it,
+	and send it. The GLib bindings can't marshal a return value of
+	something like a(s) if the array is empty - ultimately they should be
+	made to heed the signature of the out arguments as the Python bindings
+	now can, but this is a workable interim solution which might have
+	other applications.
+
+2005-11-15  Robert McQueen  <robot101@debian.org>
+
+	* bus/driver.c, bus/services.c, bus/services.h: Add a ReleaseName
+	method to org.freedesktop.DBus to release a bus name or give up
+	waiting in the queue for it.
+
+	* dbus/dbus-bus.c, dbus/dbus-bus.h, dbus/dbus-shared.h: Add a
+	dbus_bus_release_name method to send the ReleaseName method calls.
+	Add constants for the return values to dbus/dbus-shared.h.
+
+	* doc/dbus-specification.xml: Document the new ReleaseName method
+	in the specification.
+
+	* python/dbus_bindings.pyx: Add a low-level python binding for the
+	release name method.
+
+	* python/exceptions.py, python/service.py: Make freeing BusName
+	objects release the name. Add a NameExistsException, and fix a
+	bug with creating UnknownMethodException.
+
+	* test/python/test-client.py: Add tests for freeing BusName
+	objects causing names to be released.
+
+2005-11-14  Robert McQueen  <robot101@debian.org>
+
+	* python/service.py: Include the traceback in the error reply when we
+	send an exception over the bus. _BEST_ _PATCH_ _EVER_
+
+2005-11-14  David Zeuthen  <davidz@redhat.com>
+
+	Patch from Timo Hoenig <thoenig@suse.de>.
+
+	* bus/bus.c: I've recently investigated why the automatic reload
+	of configuration files does not work as expected.
+
+	Currently, reloading configuration files does only work when
+	running dbus-daemon with --nodaemon.  If we are running as daemon
+	we're hitting a dnotify bug once we fork the process.
+
+	We're initializing the dnotify fds before calling fork().  Once
+	the child process forked it does still have the fds (and they
+	still show up in /proc/`pidof dbus-daemon`/fd/) but we're not
+	getting SIGIO as changes are made to the configuration files.
+
+	The attached patch moves the initialization of the dnotify fds to
+	process_config_postinit().  This is safe for all current code
+	paths and solves the dnotify disfunction.  If we're running
+	dbus-daemon as daemon the fds for dnotify are now being
+	initialized after fork() for the child process.
+
+	* configure.in: The current configure.in check for dnotify probes
+	'x$target_os' for being 'xlinux-gnu'.  I've changed the check to
+	match for 'xlinux', too. Additionally I have adapted the configure
+	option's style to match with the others.
+
+2005-11-14  Robert McQueen  <robot101@debian.org>
+
+	* python/decorators.py, python/service.py: Add a new argument to the
+	dbus.service.method decorator called sender_keyword, which if set,
+	specifies the name of an argument which will be provided the bus
+	name of the method caller.
+
+	* test/python/test-client.py, test/python/test-service.py: Add a
+	method and test to check the sender_keyword functionality.
+
+2005-11-07  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/driver.c (bus_driver_handle_reload_config): Make sure we send an 
+	empty reply so blocking calls don't block forever (Patch from Sjoerd 
+	Simons <sjoerd at luon.net>)
+
+	* AUTHORS: Add Robert McQueen for his work on the Python
+	Bindings and other parts of D-Bus
+
+2005-11-07  Robert McQueen  <robot101@debian.org>
+
+	* python/decorators.py: Change emit_signal function to use the
+	signature annotation of the signal when marhsalling the arguments from
+	the service. Fix a bug where the code checking signature length
+	against argument length referenced the wrong variable.
+
+	* python/introspect_parser.py: Avoid adding the type signature of
+	signal arguments to any methods which occur after them in the
+	introspection data (!) by making the parser a little more careful
+	about its current state.
+
+	* python/service.py: Remove debug prints from last commit (again :D).
+
+	* test/python/test-client.py, test/python/test-service.py: Add test
+	signals with signature decorators to test the strict marshalling code
+	gives errors at the right time. Could do with checking the signals
+	actually get emitted too, given that the test does nothing with
+	signals at the moment...
+
+2005-11-07  Robert McQueen  <robot101@debian.org>
+
+	* python/_dbus.py: Add WeakReferenceDictionary cache of dbus.Bus
+	instances to stop madness of creating new instances representing
+	the same bus connection all the time, rendering any tracking of
+	match rules and bus names quite meaningless. Caught a bug where
+	the private argument to SessionBus() and friends was being passed
+	in as use_default_mainloop by mistake. Still some problems with
+	multiple dbus_binding.Connection instances representing the same
+	low-level connection (eg when you use both SessionBus() and
+	StarterBus() in same process), but it's a lot better now than it
+	was.
+
+	* python/dbus_bindings.pyx: Add constants with the return values
+	for bus_request_name().
+
+	* python/service.py: Store bus name instances in a per-dbus.Bus cache
+	and retrieve the same instances for the same name, so deletion can be
+	done with refcounting. Also now throws some kind of error if you
+	don't actually get the name you requested, unlike previously...
+
+	* test/python/test-client.py: Add tests for instance caching of buses
+	and bus name objects.
+
+2005-11-04  Robert McQueen  <robot101@debian.org>
+
+	* python/dbus_bindings.pyx, test/python/test-client.py: Fix
+	marshalling of boolean values. Add some booleans to the values in
+	the test client.
+
+	* python/decorators.py, python/service.py: Add an 'async_callbacks'
+	argument to the dbus.service.method decorator, which allows you to
+	name arguments to take two callback functions for replying with
+	return values or an exception.
+
+	* test/python/test-client.py, test/python/test-service.py: Add test
+	case using asynchronous method reply functions, both return values and
+	errors, and from within both the function itself and from a mainloop
+	callback.
+
+	* python/decorators.py, python/service.py: Perform checking that the
+	number of method/signal arguments matches the number of types in the
+	signature at class loading time, not when you first introspect the
+	class.
+
+	* python/service.py: Remove debug print left by the last commit.
+
+2005-11-03  Robert McQueen  <robot101@debian.org>
+
+	* python/service.py: Heavy refactoring of method invocation, with
+	hopefully no effect on functionality. Nuked _dispatch_dbus_method_call
+	in favour of a new _message_cb that uses seperate functions for
+	looking up the method to call, marshalling the return values, and
+	sending exceptions as errors, and is easier to follow as a
+	consequence.  Fixes some corner cases about returning things that
+	don't match your declared out_signature, allows exceptions to define
+	_dbus_error_name and have it be sent over the bus as the error name,
+	and paves the way for cool stuff like heeding the message no reply
+	flag, asynchronous method implementations, informing the method of the
+	sender, and including backtraces in the error messages.
+
+	* test/python/test-client.py: Catch and print exceptions thrown in the
+	async callback tests, rather than passing them to the low-level
+	bindings to be ignored in a noisy and frustrating manner.
+
+2005-11-03  Robert McQueen  <robot101@debian.org>
+
+	* python/_dbus.py, python/proxies.py, python/service.py: Add __repr__
+	functions to dbus.Bus, dbus.service.BusName and dbus.service.Object,
+	tweak others to be consistent.
+
+	* test/python/test-client.py: Tweak output of testInheritance.
+
+2005-10-29  Robert McQueen  <robot101@debian.org>
+
+	* python/service.py: Major changes to allow multiple inheritance
+	from classes that define D-Bus interfaces:
+	
+	 1. Create a new Interface class which is the parent class of
+	    Object, and make the ObjectType metaclass into InterfaceType.
+	
+	 2. Patch written with Rob Taylor to replace use of method_vtable
+	    with code that walks the class's __MRO__ (method resolution order)
+	    to behave like Python does when invoking methods and allow
+	    overriding as you'd expect. Code is quite tricky because
+	    we have to find two methods, the one to invoke which has the
+	    right name and isn't decorated with the /wrong/ interface,
+	    and the one to pick up the signatures from which is decorated
+	    with the right interface.
+	
+	    The same caveats apply as to normal multiple inheritance -
+	    this has undefined behaviour if you try and inherit from two
+	    classes that define a method with the same name but are
+	    decorated with different interfaces. You should decorate
+	    your overriding method with the interface you want.
+	
+	 3. Replace grungy introspection XML generation code in the metaclass
+	    with dictionaries that cope correctly with multiple inheritance
+	    and the overriding of methods. This also uses the signature
+	    decorations to provide correct introspection data, including
+	    the debut appearance of the types of your return values. :D
+
+	* test/python/test-client.py, test/python/test-service.py: Add a test
+	case to try invoking an method that overrides one inherited from a
+	D-Bus interface class.
+
+2005-10-29  Robert McQueen  <robot101@debian.org>
+
+	* python/dbus_bindings.pyx: Tweak 'raise AssertionError' to assert().
+	Add checking for the end of struct character when marshalling a
+	struct in MessageIter.append_strict.
+
+	* python/examples/example-service.py,
+	python/examples/gconf-proxy-service.py,
+	python/examples/gconf-proxy-service2.py: Update to use gobject
+	mainloop directly rather than appearing to depend on gtk.
+
+	* python/test/test-client.py, python/test/test-server.py: Remove
+	obsolete and broken test scripts for old bindings. We have up to date
+	and working tests in test/python/.
+
+2005-10-29  Robert McQueen  <robot101@debian.org>
+
+	* python/decorators.py: Add optional arguments to the method and
+	signal decorators to allow you to specify the signature of arguments
+	and return values. Preserve the doc strings of signal functions in the
+	decorated version, for pydoc and friends.
+
+	* python/dbus_bindings.pyx, python/proxies.py: Replace the
+	parse_signature_block function with an iterable dbus.Signature()
+	type. Fix a bug in MessageIter.append_strict where you could append
+	anything by claiming it was a string.
+
+	* python/service.py: Use the out_signature decoration on methods to
+	marshal return values, meaning you no longer require dbus.Array()
+	or dbus.Dictionary() to indicate the type when returning empty
+	arrays or dictionaries. Fix a bug where exceptions which are defined
+	in __main__ are not turned into error replies.
+
+	* test/python/test-client.py, test/python/test-service.py: Add test
+	for correct marshalling of return values according to out_signature.
+	Fix a bug in the async call test where the error_handler is missing a
+	self argument.
+
+2005-10-29  Robert McQueen  <robot101@debian.org>
+
+	* glib/Makefile.am, glib/examples/Makefile.am,
+	glib/examples/statemachine/Makefile.am: Merge patch from Ubuntu by
+	Daniel Stone to replace explicit calls to libtool with $(LIBTOOL).
+
+	* test/python/.cvsignore: Add run-with-tmp-session-bus.conf.
+
+	* tools/dbus-monitor.1, tools/dbus-monitor.c: Merge dbus-monitor patch
+	from Ubuntu by Daniel Silverstone to allow specifying match rules on
+	the command line.
+
+2005-10-27  Ross Burton  <ross@openedhand.com>
+
+	* dbus/dbus-marshal-header.c:
+	Remove dead code.
+
+	* glib/dbus-gobject.c:
+	Stop compiler warning.
+
+2005-10-25  Ross Burton  <ross@openedhand.com>
+
+	* dbus/dbus-auth.c:
+	* dbus/dbus-server-unix.c:
+	* dbus/dbus-transport-unix.c:
+	* glib/dbus-gmain.c:
+	* glib/dbus-gobject.c:
+	Add some const keywords.
+
+2005-10-25  Ross Burton  <ross@openedhand.com>
+
+	* doc/dbus-specification.xml:
+	Document the NoReply annotation.
+
+	* glib/dbus-binding-tool-glib.h:
+	* glib/dbus-binding-tool-glib.c:
+	Respect the NoReply annotation.
+
+2005-10-24  Robert McQueen <robot101@debian.org>
+
+	* python/dbus_bindings.pyx (String, MessageIter): make D-Bus strings
+	derive from unicode instead of str, and encode/decode UTF-8 when
+	marshalling/unmarshalling bus messages
+
+	* python/introspect_parser.py: encode introspection data as UTF-8
+	before passing the buffer into libxml2
+
+	* test/python/test-client.py: add unicode test strings
+
+	* test/data/valid-service-files/.cvsignore, test/python/.cvsignore:
+	ignore generated python test files
+
+2005-10-17  John (J5) Palmieri  <johnp@redhat.com>
+
+	* glib/dbus-gvalue-utils.c (hash_free_from_gtype): handle gdouble
+	and G_TYPE_VALUE_ARRAY (DBUS_TYPE_STRUCT)
+	(gvalue_from_hash_value, hash_value_from_gvalue): handle gdouble
+
+	* glib/dbus-gvalue.c (dbus_gvalue_to_signature): add missing
+	DBUS_STRUCT_BEGIN_CHAR and DBUS_STRUCT_END_CHAR charaters
+	when constructing struct signatures
+
+	* python/_dbus.py (Bus): handle private connections using the
+	private keyword in the constructor. defaults to private=False
+	(Bus::close): new method to close a connection to the bus
+
+	* python/dbus_bindings.pyx (Connection::close): renamed method
+	was previously called disconnect
+	(bus_get): now supports getting a private connection
+
+	* python/proxies.py (ProxyMethod::__call__): check if ignore_reply
+	keyword is set to True.  if it is, execute the method without waiting
+	for a reply
+	(ProxyObject::_introspect_execute_queue): new method for executing
+	all the pending methods that were waiting for the introspect to
+	finish.  this is called when introspect either succeeds or fails
+	(ProxyObject::_introspect_error_handler): call queued methods
+
+2005-10-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx (MessageIter::append_strict): check for
+	STRUCT_BEGIN not TYPE_STRUCT in indicate we are marshalling a struct
+
+	* python/service.py (Object::_message_cb): handle exceptions correctly
+	by sending them over the wire to the calling app.  This makes sure
+	the client returns immediately instead of waiting the 15 seconds to
+	timeout.
+
+	* test/python/test-client.py (TestDBusBindings::testBenchmarkIntrospect): 
+	Add a test to benchmark how long it takes to introspect a service and 
+	call a method which returns a large element (pretty fast)
+
+	* test/python/test-service.py (TestObject::GetComplexArray): new test 
+	method which pushes a lot of data
+
+2005-10-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/service.py(ObjectType::_reflect_on_signal, _reflect_on_method): 	
+	reclaim memory outside of the loop and use del istead of just setting
+	the key to None
+
+2005-10-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/service.py (ObjectType::_reflect_on_signal): Always close
+	signal tag even when there are no arguments
+
+2005-10-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: Set mono, mono-docs and Qt3 to default
+	to no instead of auto when building.  These bindings do not
+	have full time maintainers and will not be supported for the
+	1.0 release.
+
+2005-10-12  John (J5) Palmieri  <johnp@redhat.com>
+
+	patches from Michael Krivoruchko <misha at sun.com>: 
+	
+	* dbus/dbus-connection.c (_dbus_connection_queue_received_message_link,
+	_dbus_connection_message_sent, 
+	_dbus_connection_send_preallocated_unlocked_no_update, 
+	_dbus_connection_pop_message_link_unlocked): handle the case when path 
+	is NULL when calling _dbus_verbose
+
+	* configure.in: check for functions getpeerucred and getpeereid
+
+	* dbus/dbus-sysdeps.c (_dbus_read_credentials_unix_socket): provides 
+	support of auth EXTERNAL on Solaris 10+ (getpeerucred), FreeBSD 4.6+, 
+	OpenBSD 3.0+ and FreeBSD 5.0+ as well as MacOSX 10.2+ (getpeereid). 
+	Patch was only tested on Solaris 10 x86 so it might be issues
+	with other platforms (i.e. BSDs and MacOSX)
+	
+
+2005-10-05  John (J5) Palmieri  <johnp@redhat.com>
+
+	* glib/dbus-gvalue.c (marshal_variant): call _dbus_gvalue_marshal 
+	instead of marshal basic so we can handle recursive types in a variant
+
+	* test/glib/test-dbus-glib.c: Add test for marshaling recurive types
+	in variants
+
+	* test/glib/test-service-glib.c, test-service-glib.xml
+	(my_object_echo_variant [EchoVariant], 
+	my_object_process_variant_of_array_of_ints123
+	[ProcessVariantOfArrayOfInts123]): 
+	Add two test methods
+
+	* python/introspect_parser.py: New module for parsing introspect
+	data.
+
+	* python/dbus_bindings.pyx:
+	(various places): when throwing errors fix to use errormsg instead 
+	of message local variable because Pyrex can get confused with other 
+	message variables (initial patch by Robert McQueen 
+	<robert.mcqueen at collabora.co.uk>)
+	(MessageIter::parse_signature_block): new method for getting the next
+	block in a signiture.
+	(MessageIter::append_strict): new method for appending values strictly
+	using the passed in signature instead of guessing at the type
+	(MessageItter:: append_dict, append_struct, append_array): use 
+	signatures to marshal children if the signature is available
+	
+	* python/exceptions.py (IntrospectionParserException): new exception
+
+	* python/proxies.py (ProxyMethod::__call__): Marshal args with 
+	introspected signatures if available, else we fall back to the
+	old way of doing things.
+	(ProxyObject::_introspect_reply_handler ): parse introspection data
+	
+	* python/service.py (ObjectType::_reflect_on_method): Properly
+	terminate <method> if there are no args in the reflection data
+
+	* test/python/test-client.py: add tests for talking with the GLib
+	test server.  This gives us better coverage for introspection since
+	python to python will always generate arguments as variants.  It also
+	allows us to test the robustness of the GLib bindings and interlanguage
+	communications.
+
+	
+2005-10-03  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/driver.c (bus_driver_handle_introspect): Add signals
+	to the introspect data. (patch from Daniel P. Berrange 
+	<dan at berrange.com>)
+
+	* bus/dispatch.c (check_existent_ping): Add testcase for Ping
+	
+	* dbus/dbus-connection.c (_dbus_connection_peer_filter,
+	_dbus_connection_run_builtin_filters): Changed these to
+	be unlock_no_update functions and call 
+	_dbus_connection_send_unlocked_no_update instead of
+	dbus_connection_send to avoid locking errors.
+	
+	* doc/TODO: Removed the make Ping test TODO
+	
+2005-09-26  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/Python.pyx: Fixed memory leaks when throwing errors.
+	We now copy the message from a DBusError and then free 
+	the error object befor throwing the error
+
+	* glib/dbus-glib-tool.c: removed extra comma at the end of the
+	DBusBindingOutputMode enum which was causing a warning.
+	#include <time.h> so using time_t is explicitly defined
+
+2005-09-26  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Integrate patches from Lennart Poettering <mzsqb at 0pointer.de>:
+	- dbus/dbus-bus.c
+	(internal_bus_get): new method that take over the heavy lifting
+	of dbus_bus_get and adds the ability to get a private connection
+	to the bus
+	(dbus_bus_get): wrapper to internal_bus_get that provides the same
+	interface as in previous versions
+	(dbus_bus_get_private): new method that is a wrapper to 
+	internal_bus_get to get a private connection to the bus
+
+	- dbus/dbus-bus.h
+	(dbus_bus_get_private): add as a public libdbus interface
+
+	- dbus-1.pc.in: output system_bus_default_address and 
+	sysconfdir variables so apps can use them when compiling
+
+2005-09-23  Harald Fernengel  <harry@kdevelop.org>
+	* dbus/qt: New Qt bindings
+
+2005-09-12  Waldo Bastian  <bastian@kde.org>
+
+	* dbus/dbus-marshal-validate.c,
+	doc/dbus-specification.xml, test/Makefile.am,
+	test/test-names.c: allow hyphens in bus names.
+
+2005-09-11  Mark McLoughlin  <mark@skynet.ie>
+
+	* test/data/auth/fallback.auth-script: we don't
+	retry the EXTERNAL method when we know its going
+	to fail anymore.
+
+2005-09-11  Mark McLoughlin  <mark@skynet.ie>
+
+	* dbus/dbus-connection-internal.h: rename
+	(add|remove|toggle)_(watch|timeout) to unlocked()
+	
+	* dbus/dbus-connection.c: ditto.
+	
+	* dbus/dbus-timeout.c, dbus/dbus-transport-unix.c:
+	Update some callers for the renaming.
+
+2005-09-10  Mark McLoughlin  <mark@skynet.ie>
+
+	* dbus/dbus-auth.c: (record_mechanisms): don't
+	retry the first auth mechanism because we know
+	we're just going to get rejected again.
+	
+	* dbus/dbus-keyring.c: (_dbus_keyring_reload):
+	Fix thinko ... and what a nasty little bugger to
+	track down you were ...
+
+	* dbus/dbus-connection.c:
+	(_dbus_connection_add_watch),
+	(_dbus_connection_remove_watch): add note about
+	these needing the connection to be locked.
+	(_dbus_connection_get_dispatch_status_unlocked):
+	set status to DATA_REMAINS when we queue the
+	disconnected message.
+	
+	* bus/dispatch.c:
+	(bus_dispatch): fix warning.
+	(check_existent_service_no_auto_start):
+	Expect ChildSignaled error too.
+	(check_existent_hello_from_self): fix another
+	couple of warnings.
+	
+2005-09-08  Joe Shaw  <joeshaw@novell.com>
+
+	Patches from James Willcox <snorp@snorp.net>
+
+	* mono/Makefile.am: Add Int16.cs and UInt16.cs
+
+	* mono/DBusType/Array.cs: Handle multidimensional arrays, and
+	support array "out" parameters.
+
+	* mono/DBusType/Int16.cs, mono/DBusType/UInt16.cs: New files,
+	for 16-bit int support.
+
+2005-09-06  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 0.50
+
+	* Patch from Steve Grubb:
+	- bus/activation.c (bus_activation_service_reload_test): clean up
+	some indentation
+	- dbus/dbus-keyring.c (_dbus_keyring_reload): fix conditional 
+	- dbus/dbus-message-factory.c (generate_special): fix a couple of
+	buffer overflows in the test suite.  This is non critical because
+	it can not be exploited and this code is only run when doing a 
+	make check.
+
+	* Patch from Yaakov Selkowitz: Build fixes for Cygwin
+	- configure.in: Don't check and link against kdecore, only qt headers
+	- dbus/Makefile.am: Add -no-undefined to libdbus_1_la_LDFLAGS
+	- gcj/org/freedesktop/dbus/Makefile.am:
+	add libdbus_gcj_1_la_LDFLAGS = -no-undefined
+	- glib/Makefile.am: Add -no-undefined to libdbus_glib_1_la_LDFLAGS
+	and $(DBUS_GLIB_LIBS) to dbus_binding_tool_LDADD
+	- qt/Makefile.am: Add -no-undefined to libdbus_qt_1_la_LDFLAGS
+	- tools/Makefile.am: Add platform extentions to binaries 
+	(i.e. .exe on windows)
+
+	* configure.in: 
+	- Make it so if no suitable version of python is found we only 
+	disable building python instead of exiting the configure script
+	- Require version 2.4 of glib for glib bindings
+	- Up version to 0.50
+
+	* python/__init__.py: Sync version with libdbus to (0,50,0)
+	
+2005-09-05  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-object-tree.c (find_subtree_recurse):
+	a couple of optimizations (bug #710):
+	- do a binary search in the tree
+	- insert a new child at the right place directly, no need for
+	  qsort anymore
+	- do the "double alloc" thing when allocating children
+
+2005-08-31  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/Makefile.am: Break on pyrexc errors instead of ignoring them
+
+	* python/dbus_bindings.pyx: Memory management foo
+	(global): remove hacky _user_data_references global list
+	(GIL_safe_cunregister_function_handler): userdata now stuffed into
+	tuples. Unref user_data
+	(GIL_safe_cmessage_function_handler): userdata now stuffed into tuples
+	(Connection::__del__): Remove and replace with __dealloc__ method
+	(Connection::add_filter): Stuff user_data into a tuple.  Use Py_INCREF
+	to keep tuple from being deallocated instead of the global var hack
+	(Connection::register_object_path): Stuff user_data into a tuple.
+	Use Py_INCREF to keep tuple from being deallocated instead of the 
+	global var hack
+	(Connection::register_fallback): Stuff user_data into a tuple.
+	Use Py_INCREF to keep tuple from being deallocated instead of the 
+	global var hack
+	(GIL_safe_pending_call_notification): Don't unref the message
+	because it gets unreffed when going out of scope.  Py_XDECREF
+	the user_data
+	(PendingCall::__del__): Remove and replace with __dealloc__ method
+	(PendingCall::set_notify): ref the pending call because we will
+	need it to stick around for when the notify callback gets called
+	(Message::__del__): Remove and replace with __dealloc__ method
+
+	* python/dbus_glib_bindings.pyx (init_gthreads): Changed to 
+	gthreads_init to match up with the dbus call
+
+	* python/glib.py (init_threads): Changed to threads_init to match
+	up with gobject.threads_init().  init_threads is kept for backwards
+	compat but will most likely be deprecated in the future
+
+	* test/python/test-client.py: 
+	- revamp to use Python's unittest functionality
+	- add async call tests
+	- setup threads in glib and dbus so we make sure locks are working
+	
+2005-08-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx 
+	(_pending_call_notification, cunregister_function_handler, 
+	cmessage_function_handler): All callback functions have been rearranged 
+	to workaround a bug in Pyrex when working with the GIL which is Python's 
+	global lock when dealing with threads.  They have been split into
+	a wrapper function (which assumes the name of the old function) and
+	a _GIL_safe_<function name> function which contains the functionality
+	of the old function.  This ensures that Pyrex does not write code
+	the lock is released.
+	
+
+2005-08-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx (_pending_call_notification): Obtain the
+	GIL global lock when calling back into Python
+
+2005-08-29  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Release 0.36.2
+
+	* Add Havoc's patch that never got applied to HEAD (Bug #2436):
+
+	* bus/policy.c (bus_policy_allow_user): change default "user is
+	allowed" to be "user has same uid as the bus itself"; any
+	allow/deny rules will override.
+
+	* bus/session.conf.in: don't allow all users, since now by default
+	the user that ran the bus can connect.
+
+2005-08-26  Colin Walters  <walters@verbum.org>
+
+	* tools/dbus-print-message.c (print_message): Flush stdout
+	after printing a message, so that redirecting to a file, then
+	hitting Ctrl-C works.
+
+2005-08-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx: Tracked down a major memleak and fixed it
+	(EmptyMessage): new class that subclasses Message.  This is a workaround
+	to a Pyrex bug that fails to call __del__ when the Message object goes out
+	of scope.  For some reason subclassing Message fixes this bug
+	(Bus::send_with_reply_and_block): use EmptyMessage instead of Message
+	- s/Message(_create=0)/EmptyMessage everywhere else
+	
+	* test/python/test-{server|client}.py: add the python/.libs directory
+	to the lookup path so dbus_bindings and dbus_glib_bindings don't
+	get picked up from the system
+
+2005-08-25  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_call): Doc update, thanks
+	to Ryan Lortie for the suggestion.
+
+2005-08-24  John (J5) Palmieri  <johnp@redhat.com>
+
+	* test/python: Add python regression test
+
+	* configure.in: Add test/python/Makefile
+
+	* test/Makefile.am: Add the python directory to SUBDIRS
+
+2005-08-24  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Release 0.36.1
+
+	* python/_dbus.py: 
+	(Interface::connect_to_signal): propigate keywords for match on args
+	(Bus::add_signal_receiver): Fix typo s/dbus_inteface/dbus_interface
+
+	* python/proxies.py (ProxyObject::connect_to_signal):
+	propigate keywords for match on args
+
+	* Makefile.am: point everything to pyexecdir since python borks
+	on multilib
+
+2005-08-23  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Release 0.36
+
+2005-08-23  Colin Walters  <walters@verbum.org>
+
+	* test/glib/Makefile.am: Don't multiply-define EXTRA_DIST.
+
+2005-08-23  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_glib_bindings.pyx: reorder imports and c definitions
+	to fix some wranings. We now use dbus_bindings.DBusConnection instead
+	of defining DBusConnection ourselves.
+
+2005-08-18  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus.pth: New path file to fix up problems when installing
+	c libraries to lib64 and python files to lib.
+
+	* python/Makefile.am: install dbus.pth in the correct spot
+
+2005-08-17  John (J5) Palmieri  <johnp@redhat.com>
+	* ChangeLog: clean up my last entry a bit
+
+	* doc/introspect.xsl: New stylesheet for converting introspection data
+	into browser renderable xhtml. Contributed by Lennart Poettering.
+
+	* doc/introspect.dtd: Fixups in the introspect format from Lennart
+	Poettering.
+
+	* doc/dbus-tutorial.xml: 
+	- Add Colin Walter to the Authors section for authoring the GLib
+	section
+	- Add descriptions of the new signature and type functionality
+	in the Python complex type mapping section
+	- Add a sidenote on the new args matching functionality in 
+	the Python bindings
+	- Fixed up some of the examples to use the gobject.MainLoop
+	instead of gtk.main
+	
+	* python/_dbus.py:
+	(Bus::_create_args_dict): New. Converts a hash of arg matches
+	to a more useable format
+	(Bus::add_signal_receiver): add a **keywords parameter for catching
+	arg match parameters
+	(Bus::remove_signal_receiver): add a **keywords parameter for catching
+	arg match parameters
+	
+	* python/matchrules.py:
+	(MatchTree::exec_matches): Check for arg matches
+	(SignalMatchRule::add_args_match): New method
+	(SignalMatchRule::execute): Added args_list parameter as an optimization
+	so we don't have to marshal the args more than once
+	(SignalMatchRule::match_args_from_list): New method that checks to see
+	if the rule's arg matches match an argument list.  Only arguments
+	set in the rule are checked.
+	(SignalMatchRule::match_args_from_rule): New method that checks to see
+	if the rule's arg matches match another rule's.  All args have to match
+	in order for this method to return true.  If either rule has more args
+	then it is not a match.
+	(SignalMatchRule::is_match): Add args match
+	(SignalMatchRule::repr): Add args to the final output if they exist
+
+2005-08-17  Ross Burton  <ross@burtonini.com>
+
+	* glib/dbus-gproxy.c:
+	(dbus_g_proxy_call_no_reply): unref the message once sent.
+	(dbus_g_proxy_call): protect against NULL proxy.
+
+2005-08-16  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/__init__.py: Version updated (0, 43, 0)
+	
+	* python/dbus_bindings.pyx: 
+	- Fixed type objects to have self passed into __init__
+	- Added the Variant type
+	- Add the ability to specify types or signatures for Array, Variant 
+	and Dictionary
+	(Connection::send_with_reply_handlers): return a PendingCall object
+	(_pending_call_notification): handle the case when an error is returned 
+	without an error message in the body
+	(MessageIter::get_boolean): return True or False instead of an integer
+	(MessageIter::python_value_to_dbus_sig): add direct checking of types 
+	and add checks for objects with embeded signatures or types (Array, 
+	Variant and Dictionary)
+	(MessageIter::append_byte): handle case when the value is a dbus.Byte
+	(MessageIter::append_dict): handle embeded types or signatures
+	(MessageIter::append_array): handle embeded types or signatures
+	(MessageIter::append_variant): new method
+	
+	* python/proxies.py:
+	(DeferedMethod): New. Dummy executable object used when queuing calls 
+	blocking on introspection data
+	(ProxyMethod::__call__): add the timeout keyword for specifying longer 
+	or shorter timeouts for method calls
+	(ProxyObject): Add first pass at an introspection state machine
+	(ProxyObject::__init__): Add introspect keyword for turing off an on 
+	introspection. 
+	(ProxyObject::_Introspect): Internal Introspect call that bypasses 
+	the usual mechanisms for sending messages.  This is to avoid a deadlock
+	where the Intospect call would be queued waiting for the Introspect 
+	call to finish ;-)
+	(ProxyObject::_introspect_reply_handler): New.  This method is called 
+	when introspection returns with no error
+	(ProxyObject::_introspect_error_handler): New.  This method is called 
+	when introspection encounters an error
+	(ProxyObject::__getattr__): Code to handle different introspection 
+	states.  Queue async calls or block blocking calls if we are 
+	introspecting.  Pass through as normal if we are not or are done with 
+	introspecting.
+	
+	* python/service.py: Import signal and method from decorators.py
+
+	* python/types.py: Add Variant type
+
+2005-08-16  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gobject.c (dbus_set_g_error): Don't lose if the
+	DBusError message is NULL.
+
+2005-08-09  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-errors.c: apply patch from Timo Teras to make a
+	malloc'd copy of the name parameter
+
+2005-08-09  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c (dbus_message_set_reply_serial): print
+	warning if the reply serial is set to 0
+
+2005-08-04  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gvalue-utils.h (_dbus_g_type_specialized_builtins_init)
+	(dbus_g_type_is_fixed, dbus_g_type_fixed_get_size)
+	(dbus_gvalue_set_from_pointer, dbus_g_hash_table_value_foreach)
+	(dbus_g_hash_table_insert_values, dbus_g_hash_table_insert_steal_values)
+	(dbus_gtype_is_valid_hash_key, dbus_gtype_is_valid_hash_value)
+	(dbus_g_hash_func_from_gtype, dbus_g_hash_free_from_gtype)
+	(dbus_g_hash_equal_from_gtype, dbus_gvalue_stor, dbus_gvalue_take):
+	* glib/dbus-gvalue.h (dbus_g_value_types_init)
+	(dbus_gvalue_demarshal, dbus_gvalue_demarshal_variant)
+	(dbus_gvalue_demarshal_message, dbus_gvalue_marshal):
+	
+	Prefix name with _ to ensure they're not exported.  All callers
+	updated.
+
+	* glib/dbus-gvalue.c (typecode_to_gtype)
+	(dbus_typecode_maps_to_basic, basic_typecode_to_gtype)
+	(signature_iter_to_g_type_dict)
+	(signature_iter_to_g_type_array)
+	(dbus_gtype_from_signature_iter, dbus_gtype_from_signature)
+	(dbus_gtypes_from_arg_signature):
+	Move to dbus-gsignature.c.
+
+	* glib/dbus-binding-tool-glib.c (dbus_binding_tool_output_glib_server): Call
+	dbus_g_type_specialized_builtins_init instead of dbus_g_value_types_init.
+	(dbus_binding_tool_output_glib_client): Ditto.
+
+	* glib/Makefile.am (DBUS_GLIB_INTERNALS): Add dbus-gsignature.c
+	and dbus-gsignature.h
+
+	* test/glib/test-service-glib.c (my_object_rec_arrays): Delete
+	unused variable.
+
+2005-08-03  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gobject.c: Add tests on hardcoded object info; this should
+	catch any incompatible changes accidentally made.
+
+2005-08-03  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_read_credentials_unix_socket): fix
+	typo, from Julien Puydt
+
+	* bus/connection.c (bus_connection_disconnected): we were always
+	doing a wait_for_memory due to a buggy loop, found by Timo Hoenig
+
+2005-08-01  Colin Walters  <walters@verbum.org>
+
+	Patch from Joe Markus Clarke:	
+	
+	* glib/dbus-gidl.c (property_info_unref, arg_info_unref): Fix
+	use-after-free.
+
+2005-08-01  Colin Walters  <walters@verbum.org>
+	
+	Patch from Joe Markus Clarke:	
+	
+	* tools/dbus-send.c (main): 
+	
+	Don't use C99 style initializers (bug #3933).
+	
+2005-08-01  Colin Walters  <walters@verbum.org>
+
+	Patch from Joe Markus Clarke:	
+
+	* glib/dbus-gvalue.c (dbus_g_value_types_init): 
+	* glib/dbus-gvalue-utils.c (dbus_g_type_specialized_builtins_init) 
+	* glib/dbus-gobject.c (write_interface):
+
+	Don't use C99 style initializers (bug #3933).
+
+2005-07-31  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-viewer.c (load_child_nodes): fix invocation of
+	dbus_g_proxy_call, fix from Piotr Zielinski bug #3920
+
+2005-07-30  Havoc Pennington  <hp@redhat.com>
+
+	* fix a bunch of Doxygen warnings and mistakes
+
+2005-07-30  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_string_parse_uint): remove #ifdef
+	DBUS_BUILD_TESTS since it's now used in production code
+
+2005-07-29  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-profile.c (write_junk): initialize the junk
+	buffer so valgrind doesn't have a breakdown
+
+2005-07-29  Havoc Pennington  <hp@redhat.com>
+
+	* bus/signals.c (bus_signals_test): add match_rule_equal() tests
+	(match_rule_matches): remove unused arg
+	(test_matching): add tests for match_rule_matches()
+
+	* bus/signals.c (bus_match_rule_parse_arg_match): add ability to
+	do arg0='foo' arg5='bar' in the match rules
+	(match_rule_matches): don't match if the arg0='foo' doesn't match.
+
+	* dbus/dbus-protocol.h (DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER): add this
+
+2005-07-29  Ross Burton  <ross@openedhand.com>
+
+	* dbus/dbus-connection.c:
+	Don't create a DBusCondVar which is never used.
+
+2005-07-27  Ross Burton  <ross@openedhand.com>
+
+	* dbus/dbus-message.c:
+	Reduce the size of the maximum cached message to 10K.
+
+2005-07-25  Ross Burton  <ross@openedhand.com>
+
+	* glib/dbus-gproxy.c:
+	Remove matches when all proxies are unregistered.
+
+2005-07-24  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gvalue.c (signature_iter_to_g_type_array): Don't require
+	typedata; recursive arrays won't have it.
+
+	* test/glib/test-dbus-glib.c:
+	* test/glib/test-service-glib.c:
+	* test/glib/test-service-glib.xml: Add recursive arrays tests.
+	
+2005-07-20  John (J5) Palmieir  <johnp@redhat.com>
+
+	* python/_dbus.py, _util.py, decorators.py, extract.py, matchrules.py.
+	proxies.py, service.py: Cleanup of code after running it through the
+	pyflakes code checker mostly dealing with undefined names.  
+	(Bug #3828, Patch from Anthony Baxter <anthony@interlink.com.au>)
+
+2005-07-17  John (J5) Palmieri  <johnp@redhat.com>
+
+	* NEWS: Update to 0.35.2
+
+2005-07-17  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/_dbus.py: Remove import of the dbus.services
+	module as it no longer exists (patch from Dimitur Kirov)
+
+	* python/service.py (Object::__init__): Fixed typo
+	s/name/bus_name (patch from Dimitur Kirov)
+
+	* python/examples/example-signal-emitter.py: import dbus.glib
+	to get the main loop and use glib mainloop instead of gtk so
+	X doesn't have to be running.
+
+	* python/examples/example-signal-recipient.py: import dbus.glib
+	to get the main loop and use glib mainloop instead of gtk so
+	X doesn't have to be running. Import the decorators module
+	directly.
+
+	* test/glib/Makefile.am:  Added DIST_EXTRA files that distcheck
+	didn't pick up on but are needed to build
+
+	* configure.in: upped version to 0.35.2
+
+	* bus/driver.c, bus/selinux.c, bus/selinux.h, dbus/dbus-protocol.h:
+	added Colin Walters' SELinux API rename patch from head 
+	s/unix sercurity context/selinux security context/
+
+2005-07-16  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/Makefile.am: dbus_binding.pxd.in should be included 
+	in EXTRA_DIST not dbus_binding.pxd
+	fix up $(srcdir) hopefully for the last time
+
+	* NEWS: Update to 0.35.1
+
+2005-07-16  Colin Walters  <walters@verbum.org>
+
+	* bus/driver.c (bus_driver_handle_get_connection_selinux_security_context): Renamed
+	from bus_driver_handle_get_connection_unix_security_context.  Update for
+	error usage.
+	(message_handlers): Update for renames.
+
+	* bus/selinux.c (bus_selinux_allows_send): Handle OOM on
+	_dbus_string_init failure correctly.
+	(bus_selinux_append_context): Convert SID to context.  Append it
+	as a byte array.
+	(bus_selinux_shutdown): Handle the case where bus_selinux_full_init
+	hasn't been called.
+
+	* bus/selinux.h: Update prototype.
+
+	* dbus/dbus-protocol.h (DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN): Renamed
+	from DBUS_ERROR_UNIX_SECURITY_CONTEXT_UNKNOWN.
+
+2005-07-15  Colin Walters  <walters@verbum.org>
+
+	* doc/TODO: Add note about convenience wrappers.
+
+2005-07-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* NEWS: Update to 0.35
+
+2005-07-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* glib/Makefile.am: Add make-dbus-glib-error-switch.sh to EXTRA_DIST
+	so distcheck doesn't fail
+
+	* glib/examples/Makefile.am: Add example-service.xml and 
+	example-signal-emitter.xml to EXTRA_DIST so distcheck doesn't fail
+
+	* glib/examples/statemachine/Makefile.am: Add statemachine.xml and
+	statemachine-server.xml to EXTRA_DIST so distcheck doesn't fail
+
+	* python/Makefile.am: Preprend $(srcdir)/ to source files so the
+	compiler looks in the right places during distcheck
+
+2005-07-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* glib/example/Makefile.am: Fix a typo which cause make distcheck
+	to fail
+
+2005-07-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/examples/example-service.py,
+	python/examples/example-signal-emitter.py: Fixed up examples
+	for API changes
+
+2005-07-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/__init__.py: Upped to version (0,42,0) because of
+	the API change
+
+2005-07-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* ChangeLog: fix date in last entry
+
+	* configure.in, bus/system.conf.in: add the ability to configure 
+	the system bus user at compiletime with the --with-dbus-user flag
+	(patch from Kristof Vansant)
+
+2005-07-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/dispatch.c, test/test-service.c: Add testcase
+	for sending messages to oneself (TODO item).
+
+	* python/service.py (class Object): Swap ordering of bus_name 
+	and object_path parameters to better support inheritance.
+
+	* doc/dbus-tutorial.xml: change Python docs to reflect change
+	in parameter ordering and fix the inheritance section.
+
+	* doc/TODO: remove sending message to oneself TODO item
+
+2005-07-15  Ross Burton  <ross@openedhand.com>
+
+	* glib/dbus-gproxy.c:
+	Fix a leak when calling methods via the proxy.
+
+2005-07-15  Colin Walters  <walters@verbum.org>
+
+	* bus/selinux.c (bus_selinux_append_context): Wrap in
+	HAVE_SELINUX.
+
+2005-07-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/_dbus.py (Bus::remove_signal_receiver):
+	don't add a callback to the match if none has been passed in
+	
+	* python/matchrules.py (SignalMatchTree::remove): if the rule
+	being matched does not have a callback treat it as a wildcard
+	fix matching logic
+
+	* doc/dbus-tutorial.xml: Add Python tutorial
+
+2005-07-14  Colin Walters  <walters@verbum.org>
+
+	* bus/driver.c
+	(bus_driver_handle_get_connection_unix_security_context): New function.
+	(message_handlers): Add.
+
+	* bus/selinux.c (bus_selinux_append_context): New function; appends
+	security context to message.
+
+	* bus/selinux.h: Prototype.
+
+	* dbus/dbus-protocol.h (DBUS_ERROR_UNIX_SECURITY_CONTEXT_UNKNOWN): New.
+
+2005-07-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/activation.c: clean up all tabs to be 8 spaces 
+	(bus_activation_activate_service): make sure we clean up
+	if activation fails
+
+	* bus/dispatch.c: clean up all tabs to be 8 spaces 
+	(check_shell_fail_service_auto_start): New function
+	tests to make sure we get fail properly when trying to auto start a service
+	with a faulty command line
+	(check_shell_service_success_auto_start): New function tests to make sure
+	auto started services get the arguments on the command line
+
+	* test/test-shell-service.c: Added service for testing auto-starting with 
+	command line arguments
+
+	* test/data/valid-service-files/debug-shell-echo-fail.service.in, 
+	test/data/valid-service-files/debug-shell-echo-success.service.in:
+	Added service files for testing auto-starting with command line arguments
+
+	* */.cvsignore: added a bunch of generated files to various .cvsignore files
+
+2005-07-14  Rodrigo Moya  <rodrigo@novell.com>
+
+	* dbus/dbus-shell.[ch]: copy/pasted code from GLib.
+	
+	* dbus/Makefile.am: added new files to build.
+
+	* bus/activation.c (bus_activation_activate_service): support
+	activation commands with parameters.
+
+	* test/shell-test.c: added test program for the shell parsing
+	code.
+
+2005-07-13  David Zeuthen  <davidz@redhat.com>
+
+	* tools/dbus-send.c (append_arg, type_from_name): Also support 16 and
+	64 bit signed and unsigned parameters
+
+2005-07-13  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/.cvsignore: remove dbus_bindings.pyx, add dbus_bindings.pxd
+
+	* python/service.py (class Name): renamed BusName to make it clearer
+	what the object is for (a name on the bus)
+
+	* python/examples/example-service.py,
+	python/examples/example-signal-emitter.py: change the Name object to
+	BusName
+
+2005-07-12  Colin Walters  <walters@verbum.org>
+
+	Patch from Jim Gettys <Jim.Gettys@hp.com>.
+
+	* tools/dbus-launch.c: Include sys/select.h.
+
+2005-07-12  John (J5) Palmieri  <johnp@redhat.com>
+	* python/dbus_bindings.pyx.in: removed
+
+	* python/dbus_bindings.pyx: Added.
+	- Fixed some memleaks (patch from 
+	Sean Meiners <sean.meiners@linspireinc.com>)
+	- Broke out the #include "dbus_h_wrapper.h" and put it in its
+	own pxd file (Pyrex definition)
+	- Broke out glib dependancies into its own pyx module
+	
+	* python/dbus_bindings.pdx: Added.
+	- Defines C class Connection for exporting to other modules
+
+	* python/dbus_glib_bindings.pyx: Added.
+	- New module to handle lowlevel dbus-glib mainloop integration
+
+	* python/glib.py: Added.
+	- Registers the glib mainloop when you import this module
+
+	* python/services.py: Removed (renamed to service.py)
+	
+	* python/service.py: Added.
+	- (class Server): renamed Name
+
+	* python/__init__.py: Bump ro version (0,41,0)
+	-don't import the decorators or service module
+	by default.  These now reside in the dbus.service namespace
+
+	* python/_dbus.py (Bus::__init__): Add code run the main loop 
+	setup function on creation 
+
+	* python/examples/example-service.py,
+	python/examples/example-signal-emitter.py: update examples
+
+	* python/examples/gconf-proxy-service.py,
+	python/examples/gconf-proxy-service2.py: TODO fix these up
+
+	* doc/TODO: Addition
+	- Added a Python Bindings 1.0 section
+	- added "Add match on args or match on details to match rules"
+
+
+2005-07-12  Colin Walters  <walters@verbum.org>
+
+	* glib/examples/statemachine/Makefile.am (statemachine-server-glue.h) 
+	(statemachine-glue.h): 
+	* glib/examples/Makefile.am (example-service-glue.h) 
+	(example-signal-emitter-glue.h): 
+	* glib/Makefile.am (dbus-glib-error-switch.h): 
+	Add libtool --mode=execute so we use the built library instead
+	of any installed one.
+
+2005-07-11  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gvalue.c (struct _DBusGValue): Delete.
+	(dbus_g_value_types_init): Remove assertion.
+	(dbus_g_value_get_g_type, dbus_g_value_open)
+	(dbus_g_value_iterator_get_values, dbus_g_value_get_signature)
+	(dbus_g_value_copy, dbus_g_value_free): Delete unimplemented
+	functions related to DBusGValue.  Now we marshal/demarshal
+	structures as GValueArray.
+	(dbus_gtype_from_signature_iter): Return G_TYPE_VALUE_ARRAY for
+	structures.
+	(signature_iter_to_g_type_array): Don't call
+	signature_iter_to_g_type_struct.
+	(signature_iter_to_g_type_struct): Delete.
+	(dbus_gvalue_to_signature): Delete.
+	(dbus_gvalue_to_signature): New function with same name as other
+	one; we can convert structures to signatures.
+	(demarshal_valuearray): New function.
+	(get_type_demarshaller): Use it.
+	(demarshal_recurse): Delete.
+	(marshal_proxy): New function.
+	(marshal_map): Warn if we can't determine signature from type.
+	(marshal_collection_ptrarray): Ditto.
+	(marshal_collection_array): Ditto.
+	(get_type_marshaller): Use marshal_valuearray.
+	(marshal_recurse): Delete.
+	(_dbus_gvalue_test): Add some tests.
+
+	* dbus/dbus-glib.h (struct _DBusGValueIterator): 
+	(dbus_g_value_get_g_type, DBUS_TYPE_G_VALUE)
+	(dbus_g_value_open, dbus_g_value_iterator_get_value)
+	(dbus_g_value_iterator_get_values, dbus_g_value_iterator_recurse)
+	(dbus_g_value_free): Remove prototypes.
+
+	* glib/dbus-binding-tool-glib.c (dbus_g_type_get_lookup_function): Handle
+	G_TYPE_VALUE_ARRAY.
+
+	* glib/examples/example-service.c:
+	* glib/examples/example-client.c: Implement GetTuple.
+
+	* test/glib/test-dbus-glib.c:
+	* test/glib/test-service-glib.c:
+	* test/glib/test-service-glib.xml: Add structure tests.
+
+2005-07-10  Colin Walters  <walters@verbum.org>
+
+	* doc/TODO: Knock off some GLib items with this patch.
+
+	* glib/dbus-gvalue-utils.c (_dbus_gtype_can_signal_error) 
+	(_dbus_gvalue_signals_error): New functions.
+
+	* glib/dbus-gvalue-utils.h: Prototype them.
+
+	* glib/dbus-gobject.c (arg_iterate): Update to handle return vals
+	and change to not output const/retval flags for input args.  All
+	callers updated.
+	(invoke_object_method): Refactor to handle return values.  Add
+	some more comments in various places.  Remove debug g_print.
+
+	* glib/dbus-binding-tool-glib.h (DBUS_GLIB_ANNOTATION_RETURNVAL): New.
+
+	* glib/dbus-binding-tool-glib.c (dbus_g_type_get_marshal_name):
+	Handle G_TYPE_NONE.
+	(compute_gsignature): New function; refactored from code from
+	compute_marshaller and compute_marshaller_name.  Enhance to
+	handle return values and async ops more cleanly.  Update for
+	async ops returning NONE instead of BOOLEAN.
+	(compute_marshaller, compute_marshaller_name): Call compute_gsignature
+	and output appropriate string.
+	(generate_glue): Handle return value annotation.  Also don't dump
+	constness flag for input arguments.
+
+	* glib/Makefile.am (DBUS_GLIB_INTERNALS): New variable; contains
+	files shared between installed library and utilities.
+	(libdbus_glib_1_la_SOURCES): Move some stuf into DBUS_GLIB_INTERNALS.
+	(libdbus_gtool_la_SOURCES): Suck in DBUS_GLIB_INTERNALS so the
+	binding tool can access gtype utility functions.
+
+	* test/glib/test-service-glib.c: 
+	* test/glib/test-service-glib.xml: 
+	* test/glib/test-dbus-glib.c: Add some tests for return values.
+
+2005-07-09  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gparser.c (parse_annotation): Add annotations to
+	argument if available, not method.
+
+	* glib/dbus-gobject.c (arg_iterate): More verbose warnings.
+	(invoke_object_method): First, remove some redundant
+	GValues (object_value, error_value) in favor of working on
+	array directly.  Second, rework constness to be less buggy.
+	Now we iterate directly over the argument metadata instead
+	of parallel iterating over output signature and metadata.
+
+	* glib/dbus-glib-tool.h: Add INVALID_ANNOTATION error.
+
+	* glib/dbus-binding-tool-glib.c (generate_glue): Barf on const
+	annotation on input args.
+	
+2005-07-09  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-binding-tool-glib.h (DBUS_GLIB_ANNOTATION_CONST):
+	Define.
+
+	* glib/dbus-binding-tool-glib.c (generate_glue): Handle Const
+	annotation.
+
+	* glib/dbus-gobject.c (arg_iterate): Update to parse constval too.
+	(method_dir_signature_from_object_info): Handle arg_iterate change.
+	(write_interface): Ditto.
+	(lookup_object_info): Don't barf if format_version is > 0.
+	(invoke_object_method): Handle arg constness.
+
+	* glib/dbus-gidl.c (struct ArgInfo): Add annotations.
+	(arg_info_new): Create.
+	(arg_info_unref): Destroy.
+	(arg_info_get_annotations, arg_info_get_annotation) 
+	(arg_info_add_annotation): New functions.
+
+	* glib/dbus-gidl.h: Prototype them.
+
+	* glib/dbus-gparser.c (parse_annotation): Allow annotations in
+	args, disallow them in properties.
+	(parse_annotation): Handle arg annotations.
+
+	* test/glib/test-service-glib.xml: 
+	* test/glib/test-service-glib.c: Update to make some methods
+	const.
+
+2005-07-08  Colin Walters  <walters@verbum.org>
+
+	* test/glib/test-service-glib.xml: 
+	* test/glib/test-service-glib.c:
+	* test/glib/test-dbus-glib.c: Test a{sv}.
+
+	* glib/examples/statemachine/statemachine.c:
+	* glib/examples/statemachine/statemachine-server.c:
+	* glib/examples/statemachine/statemachine-client.c: Fix some bugs,
+	add progress bar, etc.
+
+	* glib/dbus-gvalue.c (register_array, register_dict): Delete; not
+	needed anymore due to generic array/map marshalling.
+	(dbus_g_value_types_init): Don't register basic arrays or the
+	string/string hash.
+	(dbus_gtype_from_signature_iter): Don't try to recurse into
+	variants.
+	(dbus_gtype_to_signature): Check collection/map before type
+	metadata.
+	(demarshal_garray_basic): Renamed to demarshal_collection_array.
+	(demarshal_ghashtable): Renamed to demarshal_map; fix to use new
+	generic map creation/append functions instead of hash table
+	specifically.
+	(get_type_demarshaller): Handle maps.
+	(demarshal_collection): Dispatch on collection type to either
+	demarshal_collection_ptrarray or demarshal_collection_array.
+	(get_type_marshaller): Handle maps.
+	(marshal_collection): Dispatch collection type to either
+	marshal_collection_ptrarray or marshal_collection_array.
+	(_dbus_gvalue_test): New test.
+
+	* glib/dbus-gvalue-utils.c (unset_and_free_g_value): New function.
+	(hash_free_from_gtype): Use it to free GValues.
+	(hashtable_append): New function.
+	(ptrarray_append): Fix prototype.
+	(slist_append): Ditto.
+	(_dbus_gvalue_utils_test): Extend tests.
+
+	* glib/dbus-gtype-specialized.c
+	(dbus_g_type_specialized_init_append): Renamed from
+	dbus_g_type_specialized_collection_init_append.  Remove const from
+	value, since we steal it.
+	(dbus_g_type_specialized_map_append): New function.
+
+	* glib/dbus-gtype-specialized.h: Update prototypes.
+	Add DBusGTypeSpecializedMapAppendFunc.
+
+	* glib/dbus-gtest.c (dbus_glib_internal_do_not_use_run_tests): Run
+	_dbus_gvalue_test.
+	
+	* glib/dbus-gtest.h: Prototype it.
+
+2005-07-08  Ross Burton  <ross@openedhand.com>
+
+	* dbus/dbus-glib.h:
+	Add DBysGAsyncData for the async bindings.
+
+	* glib/dbus-binding-tool-glib.c:
+	Re-enable the async bindings.
+
+	* test/glib/test-dbus-glib.c:
+	Add a test for the generated async bindings.
+
+2005-07-08  Colin Walters  <walters@verbum.org>
+
+	* doc/TODO: Update GLib todo bits, also add a post-1.0 TODO for a
+	connection concept.
+	
+2005-07-08  Colin Walters  <walters@verbum.org>
+	
+	* tools/Makefile.am: Kill of print-introspect in favor of using
+	dbus-send --print-reply=literal.
+
+	* test/glib/test-service-glib.xml: 
+	* test/glib/test-service-glib.c (my_object_get_objs): New test
+	for "ao".
+
+	* test/glib/test-dbus-glib.c (echo_received_cb): Free echo data.
+	(main): Test GetObjs.
+
+	* glib/examples/statemachine/Makefile.am:
+	* glib/examples/statemachine/sm-marshal.list:
+	* glib/examples/statemachine/statemachine-client.c:
+	* glib/examples/statemachine/statemachine-server.c:
+	* glib/examples/statemachine/statemachine-server.xml:
+	* glib/examples/statemachine/statemachine.c:
+	* glib/examples/statemachine/statemachine.h:
+	* glib/examples/statemachine/statemachine.xml:
+
+	New example.
+
+	* glib/examples/example-service.c (main): Move invocation
+	of dbus_g_object_type_install_info earlier, to emphasize it
+	should only be done once.
+
+	* glib/examples/example-signal-emitter.c (main): Ditto.
+
+	* glib/examples/Makefile.am (SUBDIRS): Include statemachine.
+
+	* glib/dbus-gvalue.h (dbus_gtype_to_signature)
+	(dbus_gvalue_marshal): Update prototypes.
+
+	* glib/dbus-gvalue.c: Update all marshalling functions to take
+	const GValue instead of GValue.
+	(signature_iter_to_g_type_array): Return a GPtrArray for nonfixed
+	types.
+	(dbus_gvalue_to_signature): Update for dbus_gtype_to_signature
+	change.
+	(dbus_gtype_to_signature): Handle generic collecitons and maps.
+	Return a newly-allocated string.
+	(demarshal_proxy, demarshal_object_path, demarshal_object)
+	(demarshal_strv, demarshal_ghashtable): Set error, don't assert if
+	we get the wrong types from message.
+	(get_type_demarshaller): New function, extracted from
+	dbus_gvalue_demarshal.
+	(demarshal_collection): New function, demarshals generic
+	collection.
+	(dbus_gvalue_demarshal): Just invoke result of
+	get_type_demarshaller.  Throw error if we don't have one.
+	(marshal_garray_basic): Abort on OOM.
+	(get_type_marshaller): New function, extracted from
+	dbus_gvalue_marshal.
+	(collection_marshal_iterator, marshal_collection): New functions;
+	implements generic marshalling for an iteratable specialized
+	collection.
+	(dbus_gvalue_marshal): Just invoke result of get_type_marshaller.
+
+	* glib/dbus-gvalue-utils.c (gvalue_from_ptrarray_value): Handle
+	G_TYPE_STRING.
+	(ptrarray_value_from_gvalue): Ditto.
+	(ptrarray_append, ptrarray_free): New functions.
+	(slist_constructor, slist_iterator, slist_copy_elt, slist_copy) 
+	(slist_append, slist_end_append, slist_free): New functions.
+	(dbus_g_type_specialized_builtins_init): Add append fuctions
+	for GPtrArray and GSList.  Register GSList.
+	(test_specialized_hash, _dbus_gvalue_utils_test): New functions.
+
+	* glib/dbus-gtype-specialized.h (DBusGTypeSpecializedAppendContext):
+	New.
+	(dbus_g_type_specialized_collection_init_append)
+	(dbus_g_type_specialized_collection_append)
+	(dbus_g_type_specialized_collection_end_append): Prototype.
+	(DBusGTypeSpecializedCollectionVtable): Add append_func and
+	end_append_func.
+
+	* glib/dbus-gtype-specialized.c (dbus_g_type_specialized_collection_init_append) 
+	(dbus_g_type_specialized_collection_append) 
+	(dbus_g_type_specialized_collection_end_append): New functions.
+	(dbus_g_type_map_value_iterate): Take const GValue.
+	(dbus_g_type_collection_value_iterate): Ditto.
+
+	* glib/dbus-gtest.c (dbus_glib_internal_do_not_use_run_tests): Run
+	_dbus_gvalue_utils_test.
+	
+	* glib/dbus-gtest.h: Prototype it.
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_manager_filter): Avoid
+	using uninitialized owner_list.
+	(dbus_g_proxy_begin_call_internal): Move return_if_fail to
+	public API.
+	(dbus_g_proxy_end_call_internal): Update to use error set
+	from dbus_gvalue_demarshal instead of setting it here.
+	(dbus_g_proxy_begin_call): Move return_if_fail here.
+
+	* glib/dbus-gobject.c (write_interface): Update for
+	dbus_gtype_to_signature returning new string.
+
+	* configure.in: Add glib/examples/statemachine.
+
+2005-07-08  Joe Shaw  <joeshaw@novell.com>
+
+	* configure.in: Add a configure option, --with-console-auth-dir
+	
+	* dbus/dbus-sysdeps-util.c (_dbus_user_at_console): Use the
+	new setting.  Patch from Kay Sievers.
+
+2005-07-06  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-glib.h (DBusGPendingCall, DBusGPendingCallNotify)
+	(DBUS_TYPE_G_PENDING_CALL, dbus_g_pending_call_get_g_type)
+	(dbus_g_pending_call_ref, dbus_g_pending_call_unref): Delete.
+	(dbus_g_pending_call_set_notify, dbus_g_pending_call_cancel):
+	Delete in favor of dbus_g_proxy_begin_call and
+	dbus_g_proxy_cancel_call.
+	(DBusGProxyCall, DBusGProxyCallNotify): New.
+	(dbus_g_proxy_begin_call): Change prototype to take callback, user
+	data, and destroy function.  This replaces
+	dbus_g_pending_call_set_notify.
+	(dbus_g_proxy_cancel_call): Prototype.
+	(DBusGAsyncData): Delete, shouldn't be needed anymore.
+
+	* glib/dbus-gproxy.c (struct _DBusGProxy): Add call_id_counter and
+	pending_calls map.
+	(struct _DBusGProxyManager): Add bus_proxy member, which is an
+	internal proxy for calls to the bus. Remove
+	pending_nameowner_calls, now the internal proxy keeps track.
+	(dbus_g_proxy_manager_unref): Unref bus proxy, remove reference to
+	pending_nameowner_calls.
+	(got_name_owner_cb): Update prototype, and use
+	dbus_g_proxy_end_call.
+	(got_name_owner_cb): Remove reference to pending_nameowner_calls.
+	(dbus_g_proxy_manager_register): Delete directly libdbus code in
+	favor of using internal proxy.
+	(dbus_g_proxy_manager_unregister): Update to use
+	dbus_g_proxy_cancel_call for any pending GetNameOwner call.
+	(dbus_g_proxy_init): Initialize pending calls map.
+	(dbus_g_proxy_constructor): New.
+	(dbus_g_proxy_class_init): Add get/set property functions,
+	constructor, and add NAME, PATH, and INTERFACE properties.
+	(cancel_pending_call): New function.
+	(dbus_g_proxy_dispose): Iterate over any outstanding calls and
+	cancel them.
+	(dbus_g_proxy_set_property, dbus_g_proxy_get_property): New.
+	(GPendingNotifyClosure): New structure.
+	(d_pending_call_notify, d_pending_call_free): Moved here from
+	dbus-glib.c.
+	(DBUS_G_VALUE_ARRAY_COLLECT_ALL): Moved around to satisfy function
+	ordering.
+	(manager_begin_bus_call): New internal function for talking to
+	internal bus proxy.
+	(dbus_g_proxy_new): Construct object using GObjet properties.
+	(dbus_g_proxy_begin_call_internal): Update to take user data, etc.
+	Create closure of same, and insert call into map of pending calls.
+	(dbus_g_proxy_end_call_internal): Take call id instead of pending
+	call.  Look up pending call in current set.  Remove it when we've
+	completed.
+	(dbus_g_pending_call_end, dbus_g_proxy_end_call_internal): Delete.
+	(dbus_g_proxy_begin_call): Change API to take callback, user data,
+	and destroy function directly.
+	(dbus_g_proxy_end_call): Update to take DBusGProxyCall.
+	(dbus_g_proxy_call): Invoke with NULL callback.
+	(dbus_g_proxy_cancel_call): New function, replaces
+	dbus_g_pending_call_cancel.
+
+	* glib/dbus-gparser.c (validate_signature): Fix call to
+	dbus_set_g_error.
+
+	* glib/dbus-gobject.c (dbus_g_object_type_dbus_metadata_quark):
+	New quark for attaching metadata to GType.
+	(info_hash): Delete.
+	(lookup_object_info): Look up using quark.
+	(dbus_g_object_type_install_info): Check that a type is classed,
+	not that it's an object.  Also just install type data using quark
+	instead of using global hash.
+
+	* glib/dbus-glib.c (dbus_g_pending_call_ref) 
+	(dbus_g_pending_call_unref, dbus_pending_call_get_g_type)
+	(GPendingNotifyClosure): Delete.
+	(d_pending_call_notify, d_pending_call_free): Move to dbus-gproxy.c.
+	(dbus_g_pending_call_set_notify, dbus_g_pending_call_cancel): Delete.
+
+	* glib/dbus-binding-tool-glib.c (generate_client_glue): Disable async
+	client method generation until we can fix it...
+	
+	* tools/dbus-viewer.c (load_child_nodes): Use dbus_g_proxy_call.
+	(load_from_service_thread_func): Ditto.
+
+	* tools/dbus-names-model.c (struct NamesModel): Hold
+	DBusGProxyCall.
+	(have_names_notify): Update prototype, use
+	dbus_g_proxy_cancel_call.
+	(names_model_reload): Update for new dbus_g_proxy_begin_call API.
+
+	* tools/dbus-monitor.c (filter_func): Update for print_message
+	API change.
+
+	* test/glib/test-dbus-glib.c: Add more tests for async
+	invocations.  Update many begin_call/end_call pairs to just use
+	dbus_g_proxy_call.
+
+	* tools/dbus-send.c (main): Add --print-reply=literal mode.  This
+	allows us to dump print-introspect.c.
+
+	* tools/dbus-print-message.h (print_message): Add literal argument
+	to print_message which is intended to allow printing arguments without
+	metadata like "string=".
+
+	* tools/dbus-print-message.c (print_iter): Add literal argument.
+	(print_message): Allow printing string messages literally.
+
+2005-07-05  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gproxy.c (marshal_dbus_message_to_g_marshaller):
+	Remove value refcount leak, original patch from Jorn Baayen
+	<jorn@openedhand.com>.  Also remove useless extra value in favor
+	of prepending to value array directly.
+
+2005-07-02  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gmain.c (_dbus_gmain_test): Fix test.
+
+2005-07-01  Colin Walters  <walters@verbum.org>
+
+	Patch from Jonathan Matthew <jonathan@kaolin.hn.org>
+	
+	* glib/dbus-gvalue.c (basic_typecode_to_gtype): Fix return type.
+	(dbus_g_value_types_init): Marshal G_TYPE_CHAR as DBUS_TYPE_BYTE,
+	G_TYPE_LONG as DBUS_TYPE_INT32, G_TYPE_ULONG as DBUS_TYPE_UINT32,
+	and G_TYPE_FLOAT as DBUS_TYPE_DOUBLE.
+
+2005-06-30  Colin Walters  <walters@verbum.org>
+
+	* test/glib/test-dbus-glib.c:
+	* test/glib/test-service-glib.c:
+	* test/glib/test-service-glib.xml: Update tests for new error
+	setting bits, also add async tests (patch from Ross Burton).
+
+	* test/glib/Makefile.am (test_service_glib_LDADD): Add
+	DBUS_GLIB_THREADS_LIBS.
+
+	* glib/dbus-gproxy.c (get_name_owner)
+	(dbus_g_pending_call_end_valist): Ditto.
+
+	* glib/dbus-gobject.c (error_metadata): New mapping from GError
+	domain (GQuark) to DBusGErrorInfo.  
+	(gerror_domaincode_to_dbus_error_name): Attempt to look up error
+	quark in error_metadata.  Take message interface as default
+	error message interface.
+	(gerror_to_dbus_error_message): Pass message interface.
+	(dbus_set_g_error): Resurrected.
+	(dbus_g_error_info_free): New function.
+	(dbus_g_object_type_install_info): Use g_type_class_ref instead
+	of _peek to actually create the object class if it hasn't been
+	created yet.
+	(dbus_g_error_domain_register): New function.
+
+	* glib/dbus-gmain.c (dbus_g_bus_get): Switch to dbus_set_g_error.
+
+	* glib/dbus-gparser.c (validate_signature): Ditto.
+
+	* dbus/dbus-glib.h (dbus_g_error_set): Delete.
+	(dbus_g_error_domain_register): Prototype.
+
+	* glib/dbus-glib.c (dbus_g_error_set): Delete.
+	Update tests.
+
+2005-06-29  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-glib.h: Delete DBUS_TYPE_G_PROXY_ARRAY.  Add
+	DBUS_TYPE_G_OBJECT_PATH.
+
+	* glib/dbus-gvalue.c (dbus_g_value_types_init): Remove marshallers
+	for G_TYPE_OBJECT and DBUS_TYPE_G_PROXY_ARRAY (the latter should
+	be handled more generically).  Add DBUS_TYPE_G_OBJECT_PATH.
+	(dbus_g_object_path_get_g_type): New function.
+	(dbus_gtype_from_signature_iter): Map DBUS_TYPE_OBJECT_PATH
+	to DBUS_TYPE_G_OBJECT_PATH by default.
+	(demarshal_proxy): Remove unused name variable.
+	(demarshal_object_path, marshal_object_path): New functions.
+	(demarshal_proxy_array, marshal_proxy_array): Delete.
+	
+	* glib/dbus-binding-tool-glib.c (dbus_g_type_get_c_name): Map
+	DBUS_TYPE_G_OBJECT_PATH to char *.
+	(dbus_g_type_get_lookup_function): Map builtin
+	DBUS_TYPE_G_OBJECT_PATH.
+
+	* test/glib/test-dbus-glib.c
+	* test/glib/test-service-glib.c (my_object_objpath): 
+	Adapt tests to new object path marshalling.
+
+2005-06-29  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: force check for Python >= 2.4
+
+2005-06-29  Colin Walters  <walters@verbum.org>
+	
+	Patch from Ross Burton <ross@openedhand.com>
+	
+	* glib/dbus-gobject.c (invoke_object_method): Unset object
+	value in all cases, not only in async case.
+
+2005-06-29  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gproxy.c (struct _DBusGProxy): Add new member
+	name_call for keeping track of any outgoing GetNameOwner call.
+	Also add for_owner and associated.
+	(struct _DBusGProxyManager): Add owner_names, which is hash table
+	that maps a base name to a list of names it owns (that we're
+	interested in).  Add pending_nameowner_calls which is a list of
+	all outstanding GetNameOwner; avoids us having to iterate over
+	every proxy.  Add unassociated_proxies which keeps track of name
+	proxies with no associated name owner.
+	(dbus_g_proxy_manager_unref): Destroy owner_names.
+	(struct DBusGProxyNameOwnerInfo): New struct for keeping track of
+	name refcounts.
+	(find_name_in_info, name_owner_foreach)
+	(dbus_g_proxy_manager_lookup_name_owner, insert_nameinfo)
+	(dbus_g_proxy_manager_monitor_name_owner)
+	(dbus_g_proxy_manager_unmonitor_name_owner)
+	(unassociate_proxies, dbus_g_proxy_manager_replace_name_owner):
+	New functions; they manipulate the owner_names mapping.
+	(got_name_owner_cb): New function.
+	(get_name_owner): New function, extracted from
+	dbus_g_proxy_new_for_name_owner.
+	(dbus_g_proxy_manager_register): For now we need to keep track of
+	all NameOwnerChanged.  Also if the proxy is for a name, if we
+	don't already know the name owner, queue a new GetNameOwner
+	request and add it to our list of unassociated proxies.  Otherwise
+	inc the refcount.
+	(dbus_g_proxy_manager_unregister): If this proxy is for a name,
+	cancel any pending GetNameOwner call, etc.
+	(dbus_g_proxy_manager_filter): Handle NameOwnerChanged.  Also use
+	the owner_names mapping to look up the current names for the
+	signal source, and dispatch to any proxies for that name.
+	(dbus_g_proxy_new): Initialize new members.
+	(dbus_g_proxy_new_for_name): Delete unused proxy variable.
+	(dbus_g_proxy_new_for_name_owner): Use get_name_owner.
+	(dbus_g_pending_call_end_valist): New function, extracted from
+	dbus_g_proxy_end_call_internal.  Useful when we don't have a proxy
+	but want to use the GLib infrastructure.  Also note how many
+	arguments in reply were over.
+	(dbus_g_pending_call_end): New function, just call
+	dbus_g_pending_call_end_valist.
+	(dbus_g_proxy_end_call_internal): Just call
+	dbus_g_pending_call_end_valist.
+
+	* glib/dbus-gobject.c (_dbus_gobject_lookup_marshaller): Fix lookup
+	of builtin marshaller for STRING_STRING_STRING.
+
+	* test/glib/test-dbus-glib.c: 
+	* test/glib/test-service-glib.c:
+	* test/glib/test-service-glib.xml:
+	Extend tests to cover name proxies, destruction of owner proxies,
+	etc.
+	
+	* glib/examples/example-signal-recipient.c
+	(dbus_g_proxy_new_for_name_owner): Create a name proxy.
+	
+	* tools/dbus-send.c (main): Print D-BUS error name in addition
+	to message.
+
+2005-06-28  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx.in (cunregister_function_handler,
+	cmessage_function_handler): Patch from 
+	Anthony Baxter <anthony@interlink.com.au> fixes threading problems
+	by using the Py_GILState_Ensure/Release to synchronize with the
+	python runtime.
+	
+2005-06-28  Ray Strode  <rstrode@redhat.com>
+
+	*  dbus/dbus-spawn.c (_dbus_babysitter_unref): kill
+	babysitter helper process on last unref, bug #2813.
+
+2005-06-27  Colin Walters  <walters@verbum.org>
+
+	* test/glib/test-dbus-glib.c: 
+	* test/glib/test-service-glib.c:
+	* test/glib/test-service-glib.xml:
+	Test hash table signal emitting.
+
+	* glib/dbus-gobject.c (_dbus_gobject_lookup_marshaller): Convert
+	types to their fundamental basis types, since this is what
+	marshallers operate on.  Also add an entry for VOID__BOXED.
+	(dbus_g_object_register_marshaller_array): Convert to fundamental.
+
+2005-06-26  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-tutorial.xml: fix names of interface/service/path, fix
+	from Don Park
+
+2005-06-26  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-glib.c (dbus_set_g_error): Delete.
+	(dbus_g_error_set): New public function from its ashes; used by
+	both service-side method implementation and GLib bindings
+	internals.
+	(dbus_g_error_has_name, dbus_g_error_get_name): New function.
+	(_dbus_glib_test): Add some tests.
+
+	* test/glib/test-dbus-glib.c (main): Test dbus_g_error_has_name.
+
+	* test/glib/test-service-glib.c (my_object_throw_error): Use
+	dbus_g_error_set.
+
+	* glib/dbus-gobject.c (gerror_to_dbus_error_message): Handle
+	errors thrown by dbus_g_error_set.
+
+	* glib/dbus-gmain.c (dbus_g_bus_get): Change to dbus_g_error_set.
+
+	* glib/dbus-gparser.c (validate_signature): Ditto.
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_new_for_name_owner) 
+	(dbus_g_proxy_end_call_internal): Ditto.
+
+	* glib/Makefile.am: Generate dbus-glib-error-switch.h, which
+	converts DBUS_ERROR_x to DBUS_GERROR_x.
+	(libdbus_glib_1_la_SOURCES, BUILT_SOURCES, CLEANFILES): Add it.
+
+	* doc/TODO: Remove error TODO.
+
+	* doc/dbus-tutorial.xml: Update with documentation about error
+	handling.
+
+	* dbus/make-dbus-glib-error-enum.sh: Tighten up regexp to make
+	sure we only change DBUS_ERROR to DBUS_GERROR, not all ERROR to
+	GERROR.  Also add DBUS_GERROR_REMOTE_EXCEPTION.
+
+2005-06-22  Colin Walters  <walters@verbum.org>
+	
+	Patch from Ross Burton <ross@openedhand.com>
+
+	* glib/dbus-gobject.c (dbus_g_method_return): Free out_sig.
+
+2005-06-20  Colin Walters  <walters@verbum.org>
+
+	* configure.in: Add glib/examples.
+
+	* glib/Makefile.am: Add examples/
+
+	* glib/examples/.cvsignore
+	* glib/examples/Makefile.am
+	* glib/examples/example-client.c
+	* glib/examples/example-service.c
+	* glib/examples/example-service.xml
+	* glib/examples/example-signal-emitter.c
+	* glib/examples/example-signal-emitter.xml
+	* glib/examples/example-signal-recipient.c:
+	New files; GLib binding examples, ported from
+	python/examples.
+
+2005-06-20  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-glib.h: 
+	* glib/dbus-gproxy.c: Rename dbus_g_proxy_invoke to
+	dbus_g_proxy_call.
+
+	* glib/dbus-binding-tool-glib.c: 
+	* doc/dbus-tutorial.xml: 
+	* test/glib/test-dbus-glib.c: Update for rename.
+	
+2005-06-20  Colin Walters  <walters@verbum.org>
+
+	Patch suggested by Ross Burton <ross@openedhand.com>
+
+	* glib/dbus-gobject.c (export_signals): Free signal name.
+	(g_value_init): Use G_VALUE_NOCOPY_CONTENTS to plug
+	memory leak.  Add a bit of documentation.
+	(dbus_g_method_return_error): Free context, and note we do
+	so.
+
+2005-06-18  Murray Cumming  <murrayc@murrayc.com>
+
+	* dbus/dbus-glib.h:
+	* glib/dbus-gobject.c:
+	* glib/dbus-gproxy.c:
+	* glib/dbus-gvalue.c: Predeclare structs as 
+	typedef struct _Something Something instead of 
+  	typedef struct Something Something, so we can 
+	redeclare the prototypes. Other GNOME libraries 
+	do this already.
+
+2005-06-17  Colin Walters  <walters@verbum.org>
+
+	* tools/dbus-names-model.c (have_names_notify): Fix call
+	to dbus_g_proxy_end_call.
+	
+2005-06-17  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_emit_remote_signal): Don't
+	spew warnings if we get malformed remote signals.
+
+	* glib/dbus-gobject.c (propsig_iterate): New function.
+	(lookup_object_info): New function, extracted from
+	lookup_object_and_method.
+	(introspect_properties, introspect_signals): Delete; these
+	are merged into write_interface.
+	(write_interface): Write out signals and properties here;
+	dump the org.gtk.object stuff and use the interface given
+	in the introspection data blob.  Also fix up property XML.
+	(lookup_values): New function.
+	(introspect_interfaces): Gather a mapping from interface to a
+	list of its methods, signals, and properties, then write out
+	each interface.
+	(lookup_object_and_method): Use lookup_object_info.
+	(struct DBusGSignalClosure): Add interface.
+	(dbus_g_signal_closure_new): Add interface. Don't dup signame;
+	we can just use the constant data.
+	(dbus_g_signal_closure_finalize): Don't free signal name.
+	(signal_emitter_marshaller): Use interface from signal closure.
+	(export_signals): Only export signals mentioned in introspection
+	blob.
+	(dbus_g_connection_register_g_object): Warn if we have no
+	introspection data for an object.
+	(funcsig_equal): Remove unused variable.
+	(dbus_g_object_register_marshaller): Take varargs instead of
+	list.
+	(dbus_g_object_register_marshaller_array): New function,
+	extracted from old dbus_g_object_register_marshaller.
+
+	* glib/dbus-binding-tool-glib.c (struct DBusBindingToolCData): Add
+	signals and property data.
+	(write_quoted_string): New function, extracted from generate_glue.
+	(generate_glue): Write signals and properties to introspection
+	blob.
+
+	* dbus/dbus-glib.h (struct DBusGObjectInfo): Include
+	exported_signals and exported_properties.
+	(dbus_g_object_register_marshaller): Update prototype.
+	(dbus_g_object_register_marshaller_array): Prototype.
+	
+	* test/glib/test-dbus-glib.c: Extend testing to cover new signals.
+
+	* test/glib/test-service-glib.c: Add new test signals and method
+	to emit them.
+
+	* test/glib/test-service-glib.xml: Add some test signals.
+
+	* test/glib/Makefile.am (BUILT_SOURCES): Add my-object-marshal.c
+	and my-object-marshal.h
+	(test_service_glib_SOURCES, test_dbus_glib_SOURCES): Add
+	my-object-marshal.c.
+	(my-object-marshal.c, my-object-marshal.h): Implement.
+
+	* test/glib/.cvsignore: Update.
+
+	* doc/TODO: Remove two GLib TODO items fixed by this
+	patch.
+
+2005-06-16  Colin Walters  <walters@verbum.org>
+
+	* doc/TODO: Update for GLib bindings.
+	
+2005-06-16  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-binding-tool-glib.c:
+	* glib/dbus-gobject.c:
+	* glib/dbus-gproxy.c:  Add Nokia copyright; Patch
+	from Ross Burton, for his GLib bindings work.
+
+2005-06-16  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gobject.c (funcsig_hash, funcsig_equal): Use n_params
+	to iterate instead of walking to G_TYPE_INVALID.
+
+	Patch based on a patch from Ryan Gammon.
+
+2005-06-16  Colin Walters  <walters@verbum.org>
+
+	* bus/bus.c (bus_context_new): Set parser to NULL
+	after we unref it (Patch from Chris Boscolo, #2174).
+	
+2005-06-16  Colin Walters  <walters@verbum.org>
+
+	* python/dbus_bindings.pyx.in: Import size_t,
+	__int64_t, __uint64_t, and __signed.
+
+	* dbus/dbus-sysdeps.c <HAVE_CMSGCRED> (write_credentials_byte):
+	Define cmsg struct, output it.
+	(_dbus_read_credentials_unix_socket):
+	Use cmsg struct.
+	
+	Patch from Joe Markus Clarke for FreeBSD support.
+	
+2005-06-16  Colin Walters  <walters@verbum.org>
+
+	* tools/dbus-send.c (append_array): Use strtok.
+	(append_dict): New function.
+	(type_from_name): New function, extracted from main.
+	(main): Handle sending dicts.
+
+	* tools/dbus-print-message.c (print_iter): Print dict
+	entries.
+	
+2005-06-16  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gvalue.c (marshal_basic): Marshal NULL string
+	values as the empty string (#2948).
+	
+2005-06-16  Colin Walters  <walters@verbum.org>
+
+	* dbus/Makefile.am:
+	* mono/doc/Makefile.am:
+	* test/glib/Makefile.am:
+
+	Fix srcdir != builddir issues (Patch from Chris Wilson, #3477)
+
+2005-06-16  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-marshal-header.c (_dbus_header_load): Set
+	header byte order from expected byte order (Patch from Chris Wilson, #3475).
+
+	* dbus/dbus-marshal-byteswap.c (byteswap_body_helper): 
+	Increment pointer after swapping fixed array.  Add assertion
+	for array length.
+		
+2005-06-15  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-sysdeps.c <HAVE_CMSGCRED> (_dbus_read_credentials_unix_socket):
+	Fix call to dbus_set_error.  (Patch from Michael Banck, #3461)
+	
+2005-06-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* NEWS: Update to 0.34
+
+2005-06-15  David Zeuthen  <davidz@redhat.com>
+
+	* configure.in (LT_CURRENT): Revert back to 1 as the library
+	hasn't changed and we've certainly not committed to protocol
+	stability yet.  All this does is to break ABI. See commit note
+	from hp@redhat.com 2005-05-05 for details.
+	
+2005-06-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-connection.c (_dbus_connection_peer_filter): New method 
+	(_dbus_connection_run_builtin_filters): New method
+	(dbus_connection_dispatch): Run the builtin filters which in turn
+	runs the peer filter which handles Ping messages.
+
+	* doc/TODO: 
+	 - Ping isn't handled: This patch fixes it
+	 
+	 - Add a test case for the Ping message: added TODO item
+
+2005-06-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-message.c:
+	(dbus_message_has_path): New method
+	(dbus_message_has_interface): New method
+	(dbus_message_has_member): New method
+
+	* dbus/dbus/dbus-sysdeps.c (_dbus_check_dir_is_private_to_user):
+	New method
+
+	* dbus/dbus-keyring.c (_dbus_keyring_reload): Check to see that 
+	the keyring directory is private to the user
+
+	* doc/TODO:
+	 - The convenience functions in dbus-bus.h should perhaps have
+	 the signatures that they would have if they were autogenerated
+	 stubs. e.g. the acquire service function. We should also evaluate
+	 which of these functions to include, in light of the fact that
+	 GLib/Qt native stubs will probably also exist.: Punted
+
+	 - add dbus_message_has_path(), maybe has_member/interface:
+	 fixed in this patch
+
+	 - in dbus-keyring.c, enforce that the keyring dir is not
+	 world readable/writable: Fixed in this patch
+
+2005-06-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-marshal-validate.h: Added a new validation
+	error code DBUS_VALIDITY_UNKNOWN_OOM_ERROR = -4 for 
+	out of memory errors when validating signitures
+
+	* dbus/dbus-marshal-header.c: use DBUS_VALIDITY_UNKNOWN_OOM_ERROR
+	in places where we previously used DBUS_VALID and a FALSE return 
+	value to indicate OOM
+	
+	* dbus/dbus-marshal-validate.c (_dbus_validate_signature_with_reason):
+	Use a stack to track the number of elements inside containers.  The 
+	stack values are then used to validate that dict entries have only two
+	elements within them.
+	(validate_body_helper): check the reason for failure when validating
+	varients
+	
+	* dbus/dbus-message.c (load_message): use 
+	DBUS_VALIDITY_UNKNOWN_OOM_ERROR in places where we previously used 
+	DBUS_VALID and a FALSE return value to indicate OOM
+
+	* doc/TODO: remove "- validate dict entry number of fields" as this
+	patch fixes it
+
+2005-06-14  David Zeuthen  <davidz@redhat.com>
+
+	* bus/bus.c (process_config_every_time): Drop existing conf-dir
+	watches (if applicable) and add new watches
+
+	* bus/main.c (signal_handler): Handle SIGIO if using D_NOTIFY
+	(main): Setup SIGIO signal handler if using D_NOTIFY
+
+	* bus/config-parser.h: Add prototype bus_config_parser_get_conf_dirs
+
+	* bus/config-parser.c (struct BusConfigParser): Add conf_dirs list
+	(merge_included): Also merge conf_dirs list
+	(bus_config_parser_unref): Clear conf_dirs list
+	(include_dir): Add directory to conf_dirs list
+	(bus_config_parser_get_conf_dirs): New function
+
+	* bus/dir-watch.[ch]: New files
+
+	* bus/Makefile.am (BUS_SOURCES): Add dir-watch.[ch]
+
+	* configure.in: Add checks for D_NOTIFY on Linux
+
+2005-06-14  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-binding-tool-glib.c:
+	* glib/dbus-gobject.c:
+	* glib/dbus-gvalue.c: Fix indentation and brace style.
+	
+2005-06-14  Ross Burton <ross@openedhand.com>.
+
+	* glib/dbus-glib.h: Make DBusGMethodInvocation
+	a private structure.  Rearrange prototypes a bit.
+	
+	* glib/dbus-gproxy.c (dbus_g_proxy_invoke): Add
+	documentation for first_arg_type.
+	
+	* glib/dbus-gobject.c: Move DBusGMethodInvocation
+	here, add documentation.  Move dbus_g_method_return
+	and dbus_g_method_return_error into public API
+	section.
+
+2005-06-14  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gobject.c (_dbus_gobject_lookup_marshaller):
+	Add missing return statements, noticed by Ross Burton.
+	
+2005-06-13  Ross Burton <ross@openedhand.com>.
+
+	* glib/dbus-gobject.c: Handle errors on message
+	demarshalling by sending error message back.
+	* glib/dbus-gvalue.c: Initialize return variables.
+
+2005-06-13  Colin Walters  <walters@verbum.org>
+
+	* glib/Makefile.am: Fix thinko in last patch.
+
+2005-06-13  Colin Walters  <walters@verbum.org>
+
+	* glib/Makefile.am: Move dbus-gtype-specialized.c
+	and dbus-gtype-specialized.h into a _HEADERS variable,
+	install them.
+
+2005-06-12  Colin Walters  <walters@verbum.org>
+
+	Async signals and various bugfixes and testing by
+	Ross Burton <ross@openedhand.com>.
+
+	* glib/dbus-gvalue.h: (struct DBusBasicGValue): Delete.
+	(dbus_gvalue_genmarshal_name_from_type)
+	(dbus_gvalue_ctype_from_type): Moved to dbus-binding-tool-glib.c.
+	(dbus_gtype_to_dbus_type): Renamed to dbus_gtype_from_signature.
+	(dbus_g_value_types_init, dbus_gtype_from_signature)
+	(dbus_gtype_from_signature_iter, dbus_gtype_to_signature)
+	(dbus_gtypes_from_arg_signature): New function prototypes.
+	(dbus_gvalue_demarshal): Take context and error arguments.
+	(dbus_gvalue_demarshal_variant): New function.
+	(dbus_gvalue_demarshal_message): New function.
+	(dbus_gvalue_store): Delete.
+
+	* glib/dbus-gvalue.c:
+
+	File has been almost entirely rewritten; now we special-case
+	more types such as DBUS_TYPE_SIGNATURE, handle arrays and
+	hash tables correctly, etc.  Full support for recursive values
+	is not yet complete.
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_class_init): Change last
+	argument of signal to G_TYPE_POINTER since we now pass a
+	structure.
+	(lookup_g_marshaller): Delete in favor of
+	_dbus_gobject_lookup_marshaller.
+	(marshal_dbus_message_to_g_marshaller): Use
+	_dbus_gobject_lookup_marshaller and dbus_gvalue_demarshal_message
+	to handle remote signal callbacks.
+	(dbus_g_proxy_new_from_proxy): New function; creates a new
+	DBusGProxy by copying an existing one.
+	(dbus_g_proxy_get_interface, dbus_g_proxy_set_interface)
+	(dbus_g_proxy_get_path): New functions.
+	(dbus_g_proxy_marshal_args_to_message): New function;
+	factored out of existing code.
+	(DBUS_G_VALUE_ARRAY_COLLECT_ALL): Collect all arguments
+	from a varargs array.
+	(dbus_g_proxy_begin_call_internal): New function.
+	(dbus_g_proxy_end_call_internal): New function.
+	(dbus_g_proxy_begin_call): Take GTypes instead of DBus types
+	as arguments; simply invoke dbus_g_proxy_begin_call_internal
+	after collecting args into value array.
+	(dbus_g_proxy_end_call): Take GTypes instead of DBus types;
+	invoke dbus_g_proxy_end_call_internal.
+	(dbus_g_proxy_invoke): Simply invoke begin_call_interanl and
+	end_call_internal.
+	(dbus_g_proxy_call_no_reply): Take GTypes instead of DBus
+	types.
+	(array_free_all): New function.
+	(dbus_g_proxy_add_signal): Take GTypes.
+
+	* glib/dbus-gobject.h:
+	(_dbus_glib_marshal_dbus_message_to_gvalue_array): Delete.
+	(_dbus_gobject_get_path, _dbus_gobject_lookup_marshaller):
+	Prototype.
+
+	* glib/dbus-gobject.c: Add a global marshal_table hash which
+	stores mappings from type signatures to marshallers.  Change lots
+	of invocations of dbus_gtype_to_dbus_type to
+	dbus_gtype_to_signature.
+	(_dbus_glib_marshal_dbus_message_to_gvalue_array): Delete.
+	(introspect_signals): Fix test for query.return_type.
+	(set_object_property): Update invocation of dbus_gvalue_demarshal.
+	(invoke_object_method): Many changes.  Handle asynchronous
+	invocations.  Convert arguments with
+	dbus_gvalue_demarshal_message.  Handle errors.  Use
+	DBusSignatureIter instead of strlen on args. Handle all arguments
+	generically.  Special-case variants.
+	(dbus_g_method_return, dbus_g_method_return_error): New function.
+	(DBusGSignalClosure): New structure, closes over signal
+	information.
+	(dbus_g_signal_closure_new): New function.
+	(dbus_g_signal_closure_finalize): New function.
+	(signal_emitter_marshaller): New function; is special marshaller
+	which emits signals on bus.
+	(export_signals): New function; introspects object signals and
+	connects to them.
+	(dbus_g_object_type_install_info): Take GType instead of
+	GObjectClass.
+	(dbus_g_connection_register_g_object): Invoke export_signals.
+	(dbus_g_connection_lookup_g_object): New function.
+	(DBusGFuncSignature) New structure; used for mapping type
+	signatures to marshallers.
+	(funcsig_hash): New function; hashes DBusGFuncSignature.
+	(funcsig_equal): New function; compares DBusGFuncSignature.
+	(_dbus_gobject_lookup_marshaller): New function.
+	(dbus_g_object_register_marshaller): New function; used to
+	register a marshaller at runtime for a particular signature.
+
+	* glib/dbus-gmain.c (_dbus_gmain_test): Add various tests.
+
+	* glib/dbus-binding-tool-glib.h: Add DBUS_GLIB_ANNOTATION_ASYNC
+	which notes a server method implementation should be
+	asynchronous.
+
+	* glib/dbus-binding-tool-glib.c
+	(dbus_binding_tool_output_glib_server): Call
+	dbus_g_value_types_init.
+	(write_formal_parameters): Use dbus_gtype_from_signature.  Handle
+	variants specially.
+	(dbus_g_type_get_lookup_function): Turn GType into an invocation
+	of a lookup function.
+	(write_args_for_direction): Use dbus_g_type_get_lookup_function.
+	(write_untyped_out_args): New method; write output arguments.
+	(write_formal_declarations_for_direction): Function for
+	writing prototypes.
+	(write_formal_parameters_for_direction): Function for
+	writing implementations.
+	(write_typed_args_for_direction): Function for writing
+	arguments prefixed with GTypes.
+	(write_async_method_client): Write out async version
+	of method.
+
+	* glib/dbus-binding-tool-glib.c: Include dbus-gvalue-utils.h.
+	(dbus_g_type_get_marshal_name): Move mapping from GType
+	to marshal name into here.
+	(dbus_g_type_get_c_name): Move into here.
+	(compute_marshaller): Convert signature to type with
+	dbus_gtype_from_signature, use dbus_g_type_get_marshal_name.
+	(compute_marshaller_name): Ditto.
+	(compute_marshaller): Handle async signal annotations.
+	(gather_marshallers): Return if we don't have a known
+	prefix.
+	(generate_glue): Collect introspection blob here, and
+	write all of the blob at the end.  This allows an object
+	with multiple interfaces to work.
+	Mark async methods in introspection blob.
+
+	* glib/Makefile.am (libdbus_glib_1_la_SOURCES): Add
+	dbus-gtype-specialized.c, dbus-gtype-specialized.h,
+	dbus-gvalue-utils.h, dbus-gvalue-utils.c.
+
+	* dbus/dbus-glib.h: Don't include dbus-protocol.h; this
+	avoids people accidentally using DBUS_TYPE_* which should
+	not be necessary anymore.
+	Do include dbus-gtype-specialized.h, which are utilities
+	for GLib container types.
+	Add various #defines for types such as
+	DBUS_TYPE_G_BOOLEAN_ARRAY.
+	(DBusGValueIterator, DBusGValue): Define, not fully used
+	yet.
+	(dbus_g_value_get_g_type): Type for recursive value.
+	(dbus_g_value_open, dbus_g_value_iterator_get_value)
+	(dbus_g_value_iterator_get_values, dbus_g_value_iterator_recurse)
+	(dbus_g_value_free): Prototypes.
+	(dbus_g_object_register_marshaller, dbus_g_proxy_new_from_proxy): Prototype.
+	(dbus_g_proxy_set_interface): Prototype.
+	(dbus_g_proxy_begin_call, dbus_g_proxy_end_call)
+	(dbus_g_proxy_call_no_reply): Take GLib types instead of DBus
+	types.
+	(dbus_g_proxy_get_path, dbus_g_proxy_get_interface):
+	Accessors.
+	(DBusGAsyncData, DBusGMethodInvocation): Structures for
+	doing async invocations.
+	(dbus_g_method_return, dbus_g_method_return_error):
+	Prototypes.
+	* doc/dbus-tutorial.xml: Update GLib section.
+	
+	* tools/dbus-viewer.c (load_child_nodes): Update
+	for new invocation type of dbus_g_proxy_end_call.
+	(load_from_service_thread_func): Ditto.
+
+	* tools/print-introspect.c (main): Ditto.
+
+	* tools/dbus-names-model.c (have_names_notify)
+	(names_model_reload, names_model_set_connection)
+	Use GTypes.
+
+	* python/Makefile.am (INCLUDES): Define DBUS_COMPILATION,
+	needed since Python bindings use GLib bindings.
+
+	* test/glib/Makefile.am (INCLUDES): Define DBUS_COMPILATION.
+	Add --prefix argument.
+
+	* tools/Makefile.am: Define DBUS_COMPILATION.  Remove
+	unneeded --ignore-unsupported arg.
+	
+	* test/glib/test-service-glib.c: 
+	* test/glib/test-service-glib.xml:
+	* test/glib/test-dbus-glib.c: Add many more tests.
+
+2005-06-06  David Zeuthen  <davidz@redhat.com>
+
+	* doc/TODO: Add item about need to remove deprecated functions.
+
+	* dbus/dbus-connection.h: Add prototype for dbus_connection_disconnect
+
+	* dbus/dbus-connection.c (dbus_connection_disconnect): New function
+	to repair the ABI which was broken with the last commit.
+
+2005-06-02  John (J5) Palmieri <johnp@redhat.com>
+
+	*  dbus/dbus-connection.c, dbus/dbus-connection.h 
+	(dbus_connection_disconnect): renamed to dbus_connection_close 
+	for API symmetry with dbus_connection_open
+	(_dbus_connection_open_internal): 
+	s/dbus_connection_disconnect/dbus_connection_close
+
+	* dbus/dbus-bus.c (dbus_bus_get):
+	s/dbus_connection_disconnect/dbus_connection_close
+
+	* bus/connection.c (bus_connections_unref, 
+	bus_connections_setup_connection, bus_connections_expire_incomplete):
+	s/dbus_connection_disconnect/dbus_connection_close
+
+	* bus/dispatch.c (bus_dispatch, kill_client_connection, 
+	kill_client_connection_unchecked, check_hello_connection):
+	s/dbus_connection_disconnect/dbus_connection_close
+
+	* bus/bus.c (new_connection_callback):
+	s/dbus_connection_disconnect/dbus_connection_close
+
+	* tools/dbus-send.c (main):
+	s/dbus_connection_disconnect/dbus_connection_close
+
+	* test/glib/test-profile.c (no_bus_thread_func, with_bus_thread_func):
+	s/dbus_connection_disconnect/dbus_connection_close
+	
+	* test/test-service.c (path_message_func, filter_func):
+	s/dbus_connection_disconnect/dbus_connection_close
+	
+	* doc/TODO: remove connection_open/connection_disconnect lacks symmetry 	item that was just fixed
+	
+2005-05-25  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-protocol.h: Move various bus service #defines such
+	  as DBUS_SERVICE_DBUS and DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT to
+	  dbus/dbus-shared.h.
+	* dbus/dbus-shared.h: Various defines moved here.
+	* dbus/dbus-marshal-header.c: Include dbus-shared.h.
+
+2005-05-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/__init__.py: Python bindings deserve a minor version
+	update.  Upped to (0, 40, 2)
+
+2005-05-24  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/decorators.py: add explicitly_pass_message decorator
+	for passing in the dbus message as keyword for edge case signal
+	handling
+
+	* python/matchrules.py (SignalMatchRule.__repr__): fix output
+	to conform with what dbus expects for match rules
+	(SignalMatchRule.execute): add the dbus message as a keyword
+	if the signal handler has requested it
+
+	* python/examples/example/signal-recipient.py: added some more
+	examples on how to hook up to signals
+
+2005-05-23  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/decorators.py: import dbus_bindings
+
+	* python/matchrules.py (SignalMatchRule, SignalMatchTree, 
+	SignalMatchNode): new classes that implement wildcard signal
+	callback matching using a tree lookup. Heavily modified from a
+	patch sent by Celso Pinto (fd.o bug #3241)
+
+	* _dbus.py (add_signal_receiver, remove_signal_receiver, _signal_func):
+	use new match classes to handle signals.
+
+2005-05-19  John (J5) Palmieri  <johnp@redhat.com>
+	
+	* python/dbus_bindings.pyx.in: s/TYPE_PATH/TYPE_OBJECT_PATH
+
+2005-05-18  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: use GLIB_GNU_GETTEXT to get INTLLIBS and require
+	gettext. Not really worth requiring yet perhaps, but any
+	production quality 1.0 would require it so we should go ahead and
+	get things set up. We do have a couple token calls to
+	bindtextdomain in the code already.
+
+2005-05-16  John (J5) Palmieri  <johnp@redhat.com>
+
+	* glib/dbus-gmain.c (io_handler_dispatch): fix deadlock
+	when using recursive g_main_loops
+
+	* python/_dbus.py (class Bus): add the ProxyObjectClass
+	alias for ProxyObject to make it easier for the Twisted 
+	networking framework to integrate dbus.
+
+	* python/proxies.py (class ProxyObject): add the ProxyMethodClass
+	alias for ProxyMethod to make it easier for the Twisted 
+	networking framework to integrate dbus. 
+
+2005-05-11  Ross Burton  <ross@openedhand.com>
+
+	* glib/dbus-glib-tool.c: Add --prefix argument.
+	* glib/dbus-binding-tool-glib.h: Add prefix argument.
+	* glib/dbus-binding-tool-glib.c (compute_marshaller_name):
+	Add prefix argument.
+	(generate_glue): Pass prefix argument down.
+	(dbus_binding_tool_output_glib_server): Pass prefix to
+	glib-genmarshal.
+	
+2005-05-11  Colin Walters  <walters@verbum.org>
+
+	* tools/dbus-send.c (append_array): New function.
+	(append_arg): Broken out from main.
+	(main): Add cheesy hack to send arrays and variants.
+	(usage): Update.
+	* tools/dbus-print-message.c (print_iter): Broken out
+	from main.
+
+2005-05-11  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-signature.c (dbus_signature_iter_get_signature):
+	New function, returns signature string for signature iter.
+	* dbus/dbus-signature.h: Prototype it.
+	* dbus/dbus-message.c (dbus_message_iter_get_signature):
+	New function, returns signature string for message iter.
+	(dbus_message_iter_get_array_len): New function, returns
+	length of array.
+	(dbus_message_iter_get_fixed_array): Fix assertion; this
+	function should be used when the iter is pointing to the
+	contents of an array
+	* dbus/dbus-message.h: Prototypes.
+	* dbus/dbus-marshal-recursive.c (_dbus_type_reader_get_array_length):
+	New function; returns length of an array.
+	* dbus/dbus-marshal-recursive.h: Prototype it.
+	
+2005-05-11  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-sysdeps-util.c <!HAVE_POSIX_GETPWNAM_R>: Fix
+	compilation error.
+	
+2005-05-08  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps-util.c (_dbus_become_daemon): write the
+	daemon's pid, not the parent's pid, to the file descriptor.
+	Reported by Taj Morton.
+
+2005-05-05  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in (LT_*): add notes on how the libtool versioning
+	works to save thinking. Increment soname to indicate protocol
+	breakage (though really the library interface hasn't changed I
+	guess)
+
+	* dbus/dbus-transport.c (_dbus_transport_get_is_authenticated):
+	verify the GUID received from server matches what we were
+	expecting, if we had an expectation
+
+	* dbus/dbus-auth.c (send_ok): send GUID along with the OK command
+	(_dbus_auth_get_guid_from_server): new function
+	(send_begin): parse the OK args
+
+	* doc/dbus-specification.xml: add GUID to the auth protocol
+
+2005-05-05  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Fix my name in previous changelog ;)
+
+	* python/proxies.py (ProxyObject.__getattr__): add further patch
+	from Anthony Baxter to throw an AttributeError when python 
+	__special__ functions are called instead of marshling them over 
+	the bus (Bug#1685 comment 3).
+
+2005-05-04  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/Makefile.am: changed to use pyexecdir for the binding
+	shared libraries (Bug#2494)
+
+	* python/exceptions.py: bring exceptions over from the bindings
+	so they can be used in applications (Bug#2036)
+	Make all exceptions derive from DBusException
+
+	* python/_dbus.py, python/proxies.py: implement __repr__ in a couple
+	of classes so that print obj doesn't throw an exception (Bug #1685)
+
+2005-05-03  Ross Burton  <ross@openedhand.com>
+
+	* glib/dbus-gobject.c (dbus_g_connection_register_g_object):
+	Return if we get an error during registration.  Set up a
+	weak reference on object to unregister if object is destroyed.
+	(unregister_gobject): New function.
+	
+2005-05-01  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx.in: 
+	- added new type classes for hinting to the marashaler what type 
+	to send over the wire
+	- added int16 and uint16 marshalers
+	- Fixed a bug in the type constants that caused int32 to go out
+	as uint16 over the wire
+	* python/dbus.py: split up into different files and renamed _dbus.py
+	* python/__init__.py, python/_util.py, python/decorators.py, 
+	python/exceptions.py, python/proxies.py, python/services.py,
+	python/types.py: new files split off from dbus.py
+	* python/Makefile.am: Add new files, remove dbus.py and 
+	install all python files to <python module dir>/dbus
+	* python/examples/*: Added #!/usr/bin/env python to the top of
+	every example.  Patch provided by Tatavarty Kalyan
+
+2005-04-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* NEWS: Update to 0.33
+
+2005-04-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx.in (send_with_reply_handlers): New send
+	method for doing async calls
+	(_pending_call_notification): New C function for handling pendning call
+	callbacks
+	(set_notify): New method for setting pending call notification
+	
+	* python/dbus.py: new version tuple "version" is set at (0, 40, 0)
+	Async capabilities added to remote method calls
+	(Sender): class removed
+	(RemoteService): class removed
+	(ObjectTree): class removed for now
+	(RemoteObject): Renamed to ProxyObject
+	(RemoteMethod): Renamed to ProxyMethod
+	(method): Decorator added for decorating python methods as dbus methods
+	(signal): Decorator added for decorating python methods as signal emitters
+	(ObjectType): Metaclass added for generating introspection data and the
+	method callback vtable
+	(Interface): Wrapper class added to wrap objects in a dbus interface
+	(Object): Uses ObjectType as its metaclass and exports Introspect
+	of the org.freedesktop.DBus.Introspectable interface
+	(ValidationException, UnknownMethodException): new exceptions
+
+	* python/examples/*: Modified to fit with the new bindings
+
+2005-04-23  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c (dbus_message_append_args): fix doc comment,
+	reported by Tony Houghton
+
+	* test/test-service.c (main): test
+	dbus_connection_get_object_path_data()
+
+	* dbus/dbus-object-tree.c (find_handler): be sure we always init
+	the exact_match
+	(_dbus_object_tree_get_user_data_unlocked): new function used by
+	dbus_connection_get_object_path_data()
+	(do_register): add assertion test for get_user_data_unlocked
+	(object_tree_test_iteration): more tests
+
+	* dbus/dbus-connection.c (dbus_connection_get_object_path_data):
+	new function from Dan Reed to let you get the user data from 
+	dbus_connection_register_object_path()
+
+2005-04-23  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-marshal-recursive-util.c: Fixed buffer overflow
+	in numerous places that did not account for the NULL terminator
+	(signature_from_seed): changed the manual string copy loop to 
+	just use strcpy instead
+	make check should now pass
+
+2005-04-19  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-marshal-header.c (_dbus_header_create): Fix assert
+	so that it allows messages that are not signals to pass in 
+	NULL as the interface.
+
+2005-04-18  David Zeuthen  <davidz@redhat.com>
+
+	* glib/dbus-gmain.c (io_handler_destroy_source): 
+	(timeout_handler_destroy_source, connection_setup_free): 
+	Also unref the source to avoid memory leaks.
+
+2005-04-13  David Zeuthen  <davidz@redhat.com>
+
+	* bus/config-parser.c (bus_config_parser_new): Bump this to a
+	more reasonable, yet still totally arbitrary, value :-). 
+
+2005-04-13  David Zeuthen  <davidz@redhat.com>
+
+	* doc/TODO: Added an "important for 1.0" item about selinux
+	allow/deny messages
+
+2005-04-13  David Zeuthen  <davidz@redhat.com>
+
+	* bus/selinux.c: Add c-file-style to top of file
+	(log_audit_callback): Don't free the data here anymore
+	(bus_selinux_check): Don't take spid and tpid since appending
+	that to auxdata may OOM.
+	(bus_selinux_allows_acquire_service): Handle OOM and signal back
+	to the caller if we are OOM by taking an error object.
+	(bus_selinux_allows_send): -do-
+
+	* bus/selinux.h: Fix prototypes for bus_selinux_allows_acquire_service
+	and bus_selinux_allows_send
+
+	* bus/bus.c (bus_context_check_security_policy): Pass error and
+	pass on OOM thrown by bus_selinux_allows_send()
+
+	* bus/services.c (bus_registry_acquire_service): Pass error and
+	pass on OOM thrown by bus_selinux_allows_acquire_service()
+
+2005-04-13  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gmain.c (message_queue_dispatch): only dispatch one
+	message at a time to avoid monopolizing the main loop, bug 
+	#2953 from Benjamin Otte
+
+2005-04-09  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-string.c (copy): change a memcpy to memmove due to
+	possible overlap, fix from Daniel Reed
+	(fixup_alignment): fix signedness warnings
+	(_dbus_string_append_unichar): ditto
+
+2005-04-09  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message-util.c (_dbus_message_test): fix signedness warning
+
+	* glib/dbus-glib-tool.c (main): fix warning
+
+	* glib/dbus-binding-tool-glib.c (generate_glue): fix warning
+
+	* dbus/dbus-connection.c (dbus_connection_read_write_dispatch):
+	add a new function that can be used in simple applications that
+	don't have a main loop and are willing to block
+
+2005-04-05  David Zeuthen  <davidz@redhat.com>
+
+	Fix https://bugs.freedesktop.org/show_bug.cgi?id=2889
+
+	* glib/dbus-gmain.c:
+	(io_handler_destroy_source): Remove from list of IO handlers
+	of the ConnectionSetup object
+	(timeout_handler_destroy_source): -do- for timeout handlers
+	(io_handler_source_finalized): Don't remove from list since
+	we now do that in io_handler_destroy_source(). Renamed from
+	io_handler_source_destroyed
+	(timeout_handler_source_destroyed): -do- for timeout handlers
+	(connection_setup_free): It is now safe to iterate over all
+	IO and timeout handlers as the _destroy_source removes them
+	from the list synchronously
+
+2005-03-30  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: change check to gtk 2.4
+
+	* tools/dbus-viewer.c (name_combo_changed_callback): remove
+	gtk_combo_box_get_active_text() usage to decrement GTK requirement
+	to 2.4
+
+2005-03-29  John (J5) Palmieri  <johnp@redhat.com>
+
+	* News: Update 0.32
+
+	* HACKING: Fixed realease instructions.  configure.in should be updated to
+	  the next release by the person who made the last release.
+
+2005-03-29  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/lvalue_cast_post_process.py - removed.  Patch has been
+	  submitted to Pyrex maintainers that fixes gcc4.0 errors
+
+	* python/Makefile.am: removed refrences to lvalue_cast_post_process.py
+
+2005-03-24  Daniel Reed  <n@ml.org>
+
+	* tools/Makefile.am: Make print-introspect and
+	dbus-bus-introspect.xml building conditional on HAVE_GLIB.
+
+2005-03-22  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/Makefile.am: Patch by Colin Walters that fixes distcheck
+
+	* dbus/dbus-userdb.c, dbus/dbus-userdb-util.c: Add patch we have 
+	  had in Red Hat packages for a while but for some reason never 
+	  got merged upstream
+	  (_dbus_is_a_number): New checks if a string
+	  can be converted to a number and does the conversion if it can
+	  (_dbus_user_database_lookup): Add check to see if the given username
+	  is a udi.  This allows udi's to be used instead of usernames in the
+	  config file.
+	  (_dbus_user_database_lookup_group): Add check to see if the given groupname
+	  is a gdi.  This allows gdi's to be used instead of groupnames in the
+	  config file.
+
+2005-03-21  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/lvalue_cast_post_process.py - added post processor to fix Pyrex
+	  code so that it compiles with gcc4.0
+
+	* python/Makefile.am: Added lvalue_cast_post_process.py to EXTRA_DIST
+	  run dbus_bindings.c through lvalue_cast_post_process.py and copy the
+	  results back to dbus_binding.c
+
+2005-03-20  Colin Walters  <walters@verbum.org>
+
+	Patch suggested by Inguva Rajasekhar <ringuva@novell.com>.
+
+	* configure.in: Require GTK+ 2.6.
+	
+2005-03-20  Colin Walters  <walters@verbum.org>
+
+	* Makefile.am (SUBDIRS, DIST_SUBDIRS): Build tools before test.
+
+2005-03-17  Tom Parker  <palfrey@tevp.net>
+
+	* dbus/dbus-userdb.c (_dbus_user_database_lookup): Don't
+	print DBUS_UID_UNSET; instead print passed username.  Also
+	be sure to actually use gid looked up in cache.
+	
+	* dbus/dbus-userdb-util.c (_dbus_user_database_lookup_group): Ditto
+	for DBUS_GID_UNSET and groupname.
+
+2005-03-17  Colin Walters  <walters@verbum.org>
+
+	* bus/print-introspect.c: Move to tools/.
+	* bus/run-with-tmp-session-bus.sh: Ditto.
+	
+	* glib/Makefile.am (dbus-glib-bindings.h): Move
+	generation to tools/Makefile.am.
+
+	* test/glib/run-test.sh: Update to handle move
+	of run-with-tmp-session-bus.sh.
+
+	* test/glib/test-service-glib.c: Update to handle
+	move of dbus-glib-bindings.h.
+
+	* tools/print-introspect.c: Moved here
+	from bus/, and ported to GLib bindings.
+
+	* tools/run-with-tmp-session-bus.sh: Moved here
+	from bus/.
+
+	* tools/Makefile.am: Generate dbus-glib-bindings.h
+	and dbus-bus-introspect.xml here.
+
+	* tools/.cvsignore, glib/.cvsignore, bus/.cvsignore:
+	Update.
+
+2005-03-17  Colin Walters  <walters@verbum.org>
+
+	* bus/driver.c (write_args_for_direction): Use
+	_dbus_string_get_const_data to retrieve string;
+	_dbus_string_get_const_data_len doesn't actually return
+	a NULL-terminated substring.
+
+	* test/glib/test-service-glib.c: Include dbus-glib-bindings.h.
+	(main): Change to use org_freedesktop_DBus_request_name
+	instead of using g_proxy_begin_call/end_call.
+
+2005-03-15  Joe Shaw  <joeshaw@novell.com>
+
+	* mono/ProxyBuilder.cs (BuildFinalizer): Fix some invalid IL when
+	generating the finalizer.  Fixes from Ben Maurer.
+
+2005-03-12  Joe Shaw  <joeshaw@novell.com>
+
+	* mono/BusDriver.cs: Update method names: ListServices
+	becomes ListNames; GetOwner becomes GetNameOwner.
+
+	* mono/ProxyBuilder.cs (BuildFinalizer): Need to load arg 0
+	onto the eval stack when removing the delegate.
+
+2005-03-12  Joe Shaw  <joeshaw@novell.com>
+
+	* mono/dbus-sharp.dll.config.in: Don't hardcode 0 for
+	LT_CURRENT.  Set it to the autoconf variable.
+                                                                                
+	* mono/ProxyBuilder.cs: Add a finalizer to the generated proxy
+	classes that disconnects the signal handler delegate from the
+	service object.  Fixes a big leak of proxy objects on the
+	client side of things.  Patch from Ben Maurer
+	<bmaurer@ximian.com>
+
+2005-03-12  Colin Walters  <walters@verbum.org>
+
+	* bus/driver.c (write_args_for_direction): New function,
+	parses a type signature into arguments and outputs to
+	XML.
+	(bus_driver_handle_introspect): Use it instead of
+	hardcoding XML for certain signatures.
+	
+	* bus/Makefile.am (dbus-bus-introspect.xml): Add
+	dependency on dbus-daemon.
+
+	* glib/dbus-glib-tool.c (main): Parse ignore_unsupported
+	argument, pass it to dbus_binding_tool_output_glib_client.
+
+	* glib/dbus-binding-tool-glib.c
+	(generate_client_glue): Protect against multiple inclusion.
+	(dbus_binding_tool_output_glib_client): Add
+	G_BEGIN_DECLS/G_END_DECLS.
+
+	* glib/dbus-binding-tool-glib.c (compute_client_method_name):
+	Change to just take iface prefix directly.
+	(write_formal_parameters): Clarify error message.
+	(check_supported_parameters): New function; checks to see type
+	signatures of method parameters are supported.
+	(generate_client_glue): Handle ignore_unsupported flag.
+	(dbus_binding_tool_output_glib_client): Handle ignore_unsupported
+	parameter.
+
+	* glib/Makefile.am (dbus-glib-bindings.h): Pass
+	--ignore-unsupported by default until glib bindings
+	support arrays.
+
+2005-03-11  Colin Walters  <walters@verbum.org>
+
+	* glib/Makefile.am: Generate dbus-glib-bindings.h and
+	install it.
+
+	* bus/print-introspect.c: New file; prints introspection
+	data for a given name and object path.
+
+	* bus/run-with-tmp-session-bus.sh: New file, refactored
+	from test/glib/run-test.sh.  Creates a temporary session
+	bus and runs another program.
+
+	* test/glib/run-test.sh: Refactor to invoke
+	run-with-tmp-session-bus.sh.
+
+	* bus/driver.c (bus_driver_handle_introspect): Fix to print new
+	introspection format.  Also change to use DBUS_TYPE_x_AS_STRING
+	macros instead of hardcoding.
+
+	* glib/.cvsignore, bus/.cvsignore, test/glib/.cvsignore: Update.
+
+2005-03-11  Joe Shaw  <joeshaw@novell.com>
+
+	* dbus/dbus-connection.c (dbus_connection_send_with_reply): Remove
+	this unref; it doesn't match up evenly in some codepaths.
+	(_dbus_connection_block_pending_call): Unref at every exitpoint;
+	this evenly matches with the ref near the top of this function.
+
+2005-03-09  Joe Shaw  <joeshaw@novell.com>
+
+	* dbus/dbus-object-tree.c
+	(_dbus_object_tree_unregister_and_unlock): If checks are enabled
+	and we try to unregister a path that's not registered, still go
+	through the process of unlocking and don't just return.
+
+2005-03-09  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_invoke): New method; calls
+	to this are generated for client-side wrappers.  Invokes a
+	D-BUS method and returns reply values.  
+
+	* glib/dbus-binding-tool-glib.c (write_args_sig_for_direction): New
+	function; writes signature string for argument direction.
+	(write_args_for_direction): Change to pass input values directly
+	instead of via address, and fix indentation.
+	(generate_client_glue): Change to invoke dbus_g_proxy_invoke.  Also
+	make generated wrappers inlineable.
+
+	* dbus/dbus-message.c (dbus_message_iter_get_fixed_array): Add
+	note about using dbus_type_is_fixed.
+
+	* dbus/dbus-marshal-basic.c (_dbus_type_is_fixed): Moved to
+	dbus/dbus-signature.c as dbus_type_is_fixed.
+
+	All callers updated.
+
+	* dbus/dbus-signature.c (dbus_type_is_fixed): Moved here
+	from dbus/dbus-marshal-basic.c:_dbus_type_is_fixed.
+
+	* dbus/dbus-signature.h: Prototype.
+
+	* glib/dbus-binding-tool-glib.c (compute_marshaller_name): Fix
+	error printf code.
+
+	* test/glib/test-dbus-glib.c (main): Be sure to clear error as
+	appropriate instead of just freeing it.
+	(main): Free returned strings using g_free.
+
+	* test/glib/Makefile.am (test-service-glib-glue.h)
+	(test-service-glib-bindings.h): Add dependency on dbus-binding-tool.
+
+	* glib/dbus-gvalue.c (MAP_BASIC): Refactored from MAP_BASIC_INIT;
+	simply maps a simple D-BUS type to GType.
+	(dbus_dbus_type_to_gtype): Function which maps D-BUS type to
+	GType.
+	(dbus_gvalue_init): Just invoke dbus_dbus_type_to_gtype and
+	initialize the value with it.
+	(dbus_gvalue_binding_type_from_type): Unused, delete.
+	(dbus_gvalue_demarshal): Switch to hardcoding demarshalling for
+	various types instead of unmarshalling to value data directly.
+	Remove can_convert boolean.
+	(dbus_gvalue_marshal): Remove duplicate initialization; switch to
+	returning directly instead of using can_convert boolean.
+	(dbus_gvalue_store): New function; not related to D-BUS per-se.
+	Stores a GValue in a pointer to a value of its corresponding C
+	type.
+
+	* glib/dbus-gvalue.h: Remove dbus_gvalue_binding_type_from_type,
+	add dbus_gvalue_store.
+
+2005-03-08  Joe Shaw  <joeshaw@novell.com>
+
+	Fix a bunch of lifecycle and memory management problems
+	in the mono bindings.
+
+	* mono/Arguments.cs (Arguments): Implement IDisposable
+
+	* mono/Bus.cs (Bus): Don't allow public instantiation.  This is
+	strictly a static class.
+
+	* mono/Connection.cs: Move the DBusObjectPathVTable and associated
+	delegates into this file.
+	(Connection): Implement IDisposable.
+	(Dispose): Disconnect the connection and set the raw connection
+	pointer to IntPtr.Zero.
+	(~Connection): Call Dispose().
+	(RegisterObjectPath): Added.  Manages the registration of object
+	paths so we can cleanly disconnect them at dispose/finalize time.
+	(UnregisterObjectPath): Ditto.
+	(set_RawConnection): Unregister all of the object paths when
+	changing the underlying DBusConnection.  Add them back onto the
+	new connection, if any.
+
+	* mono/Handler.cs: Don't implement IDisposable; it doesn't use any
+	more unmanaged resources anymore, so it's not necessary.  Move all
+	the DBusObjectPathVTable stuff out of here.
+	(Handler): Save references to our delegates so that they don't get
+	finalized.  Call Connection.RegisterObjectPath() instead of
+	dbus_connection_register_object_path() directly.
+	(Message_Called): Dispose the message after we're finished with
+	it.
+
+	* mono/Message.cs (Message): Implement IDisposable.
+	(Dispose): Dispose the Arguments, and set the RawMessage to
+	IntPtr.Zero.
+	(SendWithReplyAndBlock): We own the ref to the reply that comes
+	back from dbus_connection_send_with_reply_and_block() so add a
+	comment about that and unref it after we've constructed a managed
+	MethodReturn class around it.  Fixes a big, big leak.
+
+	* mono/ProxyBuilder.cs: Reflect into Message to get the Dispose
+	method.
+	(BuildSignalHandler): After we've sent the Signal message, dispose
+	of it.
+	(BuildMethod): Dispose of the method call and reply messages after
+	we've sent the message and extracted the data we want from the
+	reply.
+
+	* mono/Service.cs (UnregisterObject): Don't call handler.Dispose()
+	anymore.
+	(Service_FilterCalled): Dispose of the message after we're
+	finished with it.
+
+2005-03-08  Joe Shaw  <joeshaw@novell.com>
+
+        * dbus/dbus-connection.c (dbus_connection_send_with_reply):
+        After we attach our pending call to the connection, unref
+        it.  Fixes a leak.
+ 
+        * mono/Connection.cs (set_RawConnection): Disconnect our
+        filter and match callbacks from the old connection and
+        reconnect them to the new connection, if any.
+
+	* mono/DBusType/Array.cs: "Code" is a static member, so
+	don't use "this" to refer to it.  Fix for stricter checking
+	in Mono 1.1.4.
+ 
+        * mono/DBusType/ObjectPath.cs (Append): Don't leak the
+	object path that we pass into unmanaged code.
+ 
+        * mono/DBusType/String.cs (Append): Don't leak the string
+	that we pass into unmanged code.
+
+2005-03-07  John (J5) Palmieri  <johnp@redhat.com>
+	* NEWS: Update for 0.31
+
+	* configure.in: Release 0.31
+	add LT_CURRENT, LT_REVISION, LT_AGE for easy soname bumping
+
+	* qt/Makefile.am: fixed build
+
+	* dbus/Makefile.am: soname bump for libdbus
+
+	* glib/Makefile.am: soname bump for libdbus-glib
+
+2005-03-05  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c:
+	(pseudorandom_generate_random_bytes_buffer): fix to have no return
+	value
+	(_dbus_generate_random_bytes_buffer): fix return value
+
+	* dbus/dbus-sysdeps-util.c: s/GETPWNAME/GETPWNAM/ so configure
+	checks actually work, from Tom Parker <fdo@tevp.net>
+
+2005-03-01  Colin Walters  <walters@verbum.org>
+
+	* test/glib/test-dbus-glib.c (lose, lose_gerror): Utility
+	functions copied from dbus-glib-tool.c.
+	(main): Convert lots of error code to use them.
+	Also add some testing for introspection bits.
+
+2005-03-01  Colin Walters  <walters@verbum.org>
+	
+	* doc/TODO: Remove introspection signature TODO.
+
+2005-02-27  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gidl.c (property_info_get_type, arg_info_get_type):
+	Change return value to const char * instead of int so we can do
+	full signatures.
+	(struct PropertyInfo, struct ArgInfo): Store char *.
+	(property_info_new, arg_info_new): Update parameters, strdup.
+	(property_info_unref, arg_info_unref): Free.
+
+	* glib/dbus-gidl.h: Update prototypes.
+
+	* glib/dbus-gparser.c (basic_type_from_string): Delete.
+	(validate_signature): New function, just validates signature and
+	sets GError.
+	(parse_property, parse_arg): Invoke validate_signature.  Store
+	signature instead of just type code.
+
+	* glib/dbus-gvalue.c (base_type_from_signature): New utility
+	function to return a primary type for a signature, dropping
+	information about types in container types.
+	(dbus_gvalue_genmarshal_name_from_type)
+	(dbus_gvalue_binding_type_from_type)
+	(dbus_gvalue_ctype_from_type): Update to take full signature
+	 instead of type code.
+	(dbus_gtype_to_dbus_type): Moved here from glib/dbus-gobject.c.
+
+	* glib/dbus-gvalue.h: Update prototypes for above.
+
+	* glib/dbus-gobject.c (gtype_to_dbus_type): Moved to
+	glib/dbus-gvalue.c as dbus_gtype_to_dbus_type.
+	(introspect_properties, introspect_signals, write_interface):
+	Update to handle signatures, and remove usage of
+	_dbus_gutils_type_to_string.
+	(handle_introspect): Print out type codes instead of e.g. "string"
+	in hardcoded introspection XML; also use x_AS_STRING constants
+	instead of hardcoding in string.
+
+	* glib/dbus-glib-tool.c (pretty_print): Handle signature change
+	to string.  Remove usage of _dbus_gutils_type_to_string.
+
+	* glib/dbus-gutils.c (_dbus_gutils_type_to_string): Delete.
+
+	* glib/dbus-gutils.h (_dbus_gutils_type_to_string): Update for
+	deletion.
+	
+	* glib/dbus-binding-tool-glib.c (compute_marshaller)
+	(compute_marshaller_name, generate_glue): Handle signature change
+	to string.
+	(write_formal_parameters, write_args_for_direction): Ditto, and
+	remove FIXME.
+
+	* tools/dbus-tree-view.c (type_to_string): Delete.
+	(info_set_func_text): Update to print full signatures.
+
+	* test/glib/test-service-glib.xml: Change types to new
+	introspection format.
+
+2005-02-26  Havoc Pennington  <hp@redhat.com>
+
+	* doc/TODO: remove the "guid" item
+
+	* test/glib/test-profile.c (no_bus_thread_func): use open_private
+	(with_bus_thread_func): use open_private
+
+	* dbus/dbus-connection.c (dbus_connection_open_private): new
+	function that works like the old dbus_connection_open()
+	(dbus_connection_open): now returns an existing connection if
+	possible
+
+	* dbus/dbus-server-unix.c (handle_new_client_fd_and_unlock): pass
+	through the GUID to the transport
+
+	* dbus/dbus-server.c (_dbus_server_init_base): keep around the
+	GUID in hex-encoded form.
+
+	* dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new):
+	pass GUID argument in to the transport
+
+	* dbus/dbus-transport-unix.c (_dbus_transport_new_for_fd): add
+	guid argument
+
+	* dbus/dbus-transport.c (_dbus_transport_init_base): add guid argument
+
+	* dbus/dbus-auth.c (_dbus_auth_server_new): add guid argument
+
+2005-02-25  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.xml: document the GUID thing
+
+	* dbus/dbus-server.c (_dbus_server_init_base): initialize a
+	globally unique ID for the server, and put a "guid=hexencoded"
+	field in the address
+
+	* dbus/dbus-bus.c: fix missing #include of dbus-threads-internal.h
+
+	* dbus/dbus-message.c: ditto
+
+	* dbus/dbus-dataslot.c: ditto
+
+	* dbus/dbus-list.c: ditto
+
+	* dbus/dbus-internals.h: wait, just include
+	dbus-threads-internal.h here
+	
+	* dbus/dbus-string.c (_dbus_string_copy_to_buffer): move back for
+	use in main library
+
+	* dbus/dbus-sysdeps.c (_dbus_generate_random_bytes_buffer): new function
+
+2005-02-24  Colin Walters  <walters@verbum.org>
+
+	* test/glib/Makefile.am (EXTRA_DIST): Add test-service-glib.xml
+
+2005-02-24  John (J5) Palmieir  <johnp@redhat.com>
+
+	* glib/Makefile.am: added dbus-gobject.h to sources list
+	so distcheck doesn't fail
+	
+2005-02-24  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-server.c, dbus/dbus-server-unix.c: change semantics so
+	you must disconnect before unref, since locking and other things
+	are screwed up otherwise. Fix assorted other locking stuff.
+
+	* dbus/dbus-signature.c (dbus_signature_iter_get_element_type):
+	fix compilation
+
+	* dbus/dbus-threads-internal.h: move the mutex/condvar wrappers
+	into a private header and don't export from the library
+
+	* throughout - call _dbus_thread_stuff vs. dbus_thread_stuff
+
+2005-02-24  Colin Walters  <walters@verbum.org>
+	
+	* dbus/dbus-signature.c: New file; implements various functions
+	related to type signatures.  Includes an interator for parsing,
+	validation functions.
+	(dbus_type_is_basic): Moved here from
+	dbus-marshal-basic.c:_dbus_type_is_basic.
+	(dbus_type_is_container): Moved here from
+	dbus-marshal-basic.c:_dbus_type_is_container.
+
+	All callers of _dbus_type_is_container and _dbus_type_is_basic
+	updated, and include dbus-signature.h.
+
+	* dbus/dbus-signature.h: New file; prototypes for the above.
+
+	* dbus/Makefile.am (DBUS_LIB_SOURCES): Add dbus-signature.c,
+	dbus-signature.h.
+
+	* dbus/dbus-marshal-basic.c (map_type_char_to_type): New utility
+	function factored out of _dbus_first_type_in_signature.
+	(_dbus_first_type_in_signature_c_str): New function; returns first
+	type code for a type signature character.
+
+	* dbus/dbus-marshal-basic.h: Prototype _dbus_first_type_in_signature_c_str,
+	handle function moves.
+
+	* dbus/dbus-marshal-recursive.h: Export _dbus_type_signature_next.
+
+	* dbus/dbus-marshal-recursive.c (_dbus_type_signature_next): New
+	function; skips to next complete type in type signature.
+	Implemented using previous skip_one_complete_type.  Now
+	skip_one_complete_type just delegates to
+	_dbus_type_signature_next.
+
+	* dbus/dbus-marshal-basic.c (_dbus_type_is_basic): Moved
+	to dbus-signature.c
+	(_dbus_type_is_container): Ditto.
+
+	* doc/dbus-specification.xml: Update introspection sample to
+	use real type signatures.
+
+	* dbus/dbus-test.h: Prototype signature test.
+
+	* dbus/dbus-test.c (dbus_internal_do_not_use_run_tests): Run
+	signature tests.
+
+	* dbus/dbus-protocol.h (DBUS_ERROR_INVALID_SIGNATURE): New error.
+
+2005-02-23  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx.in (PendingCall::get_reply):
+	s/dbus_pending_call_get_reply/dbus_pending_call_steal_reply
+
+2005-02-21  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-test-main.c (main): Take optional specific test
+	argument.
+
+	* dbus/dbus-test.c (run_test): New function, runs a test function
+	with no data directory.
+	(run_data_test): Like above, but takes data directory.
+	(dbus_internal_do_not_use_run_tests): Take
+	specific test argument.  Replace lots of cut n' paste code
+	with run_test and run_data_test.
+
+	* dbus/dbus-test.h: Update prototype for
+	dbus_internal_do_not_use_run_tests.
+
+2005-02-20  Havoc Pennington  <hp@redhat.com>
+
+        Fix bugs reported by Daniel P. Berrange
+	
+	* dbus/dbus-server.c (_dbus_server_unref_unlocked): new function
+	(protected_change_watch): new function
+	(_dbus_server_toggle_watch, _dbus_server_remove_watch)
+	(_dbus_server_add_watch): change to work like the
+	dbus-connection.c equivalents; like those, probably kind of
+	busted, but should at least mostly work for now
+	(dbus_server_disconnect): drop the lock if we were already
+	disconnected, patch from Daniel P. Berrange
+
+	* dbus/dbus-server.c (_dbus_server_toggle_timeout) 
+	(_dbus_server_remove_timeout, _dbus_server_add_timeout): all the
+	same stuff
+
+	* doc/TODO: todo about unscrewing this mess
+
+2005-02-19  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-binding-tool-glib.c
+	(dbus_binding_tool_output_glib_server): Fix iochannel refcounting.
+
+	* glib/dbus-glib-tool.c: Include dbus-glib-tool.h, as well
+	as errno.h and sys/stat.h.
+	(lose): New function, prints error with
+	newline and exits.
+	(lose_gerror): Similar, but takes GError for message.
+	(main): Add --output argument to specify output file to write to,
+	instead of always printing to stdout.  In this mode, determine
+	timestamps on source files to see whether any are newer than the
+	target file.  If not, exit.  Also convert a number of error
+	messages to use lose (since it's shorter), and switch to using
+	g_io_channel_shutdown.
+
+2005-02-19  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gobject.c
+	(_dbus_glib_marshal_dbus_message_to_gvalue_array): add docs
+
+	* glib/dbus-glib.c: fix doxygen warnings
+
+	* glib/dbus-gparser.c (parse_annotation): error if an annotation
+	is found on an <arg>
+
+2005-02-17  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gobject.h: Don't export
+	_dbus_glib_marshal_dbus_message_to_gvalue_array.
+	
+	* glib/dbus-gobject.c (_dbus_glib_marshal_dbus_message_to_gvalue_array): Do rename.
+	(invoke_object_method): Handle it.
+
+	* glib/dbus-gproxy.c (marshal_dbus_message_to_g_marshaller):
+	Handle rename.
+	
+2005-02-17  Colin Walters  <walters@verbum.org>
+
+	* bus/.cvsignore, doc/.cvsignore
+	* test/data/valid-service-files/.cvsignore, test/glib/.cvsignore:
+	Update.
+
+2005-02-17  Colin Walters  <walters@verbum.org>
+	
+	* dbus/dbus-protocol.h (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS):
+	Rename to DBUS_SERVICE_DBUS.
+	(DBUS_PATH_ORG_FREEDESKTOP_DBUS): Rename to DBUS_PATH_DBUS.
+	(DBUS_PATH_ORG_FREEDESKTOP_LOCAL): Rename to DBUS_PATH_LOCAL.
+	Change the value from "org.freedesktop.Local"
+	to "org.freedesktop.DBus.Local".
+	(DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS): Rename to DBUS_INTERFACE_DBUS.
+	(DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE): Rename to
+	DBUS_INTERFACE_INTROSPECTABLE.
+	Change the value from "org.freedesktop.Introspectable"
+	to "org.freedesktop.DBus.Introspectable".
+	(DBUS_INTERFACE_ORG_FREEDESKTOP_PROPERTIES): Rename to
+	DBUS_INTERFACE_PROPERTIES.
+	Change the value from "org.freedesktop.Properties"
+	to "org.freedesktop.DBus.Properties".
+	(DBUS_INTERFACE_ORG_FREEDESKTOP_PEER): Rename to
+	DBUS_INTERFACE_PEER.
+	Change the value from "org.freedesktop.Peer"
+	to "org.freedesktop.DBus.Peer".
+	(DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL): 
+	DBUS_INTERFACE_LOCAL.
+	Change the value from "org.freedesktop.Local"
+	to "org.freedesktop.DBus.Local".
+
+	All other users of those constants have been changed.
+
+	* bus/driver.c (bus_driver_handle_introspect): Use constants.
+
+	* glib/dbus-gobject.c (handle_introspect): Use constants.
+
+	* doc/dbus-faq.xml, doc/dbus-specification.xml: Update for rename.
+
+2005-02-17  Colin Walters  <walters@verbum.org>
+
+	* glib/dbus-gparser.c (struct Parser): Add in_annotation boolean.
+	(parse_node, parse_interface, parse_method, parse_signal)
+	(parse_property, parse_annotation): Lose if we're currently in an
+	annotation.
+	(parse_annotation): New function.
+	(parser_start_element, parser_end_element): Handle annotation.
+	(parse_method, parse_interface): Remove support for c_name attribute,
+	switch to annotations.
+
+	* glib/dbus-gidl.h (interface_info_get_binding_names)
+	(method_info_get_binding_names)
+	(interface_info_get_binding_name, method_info_get_binding_name)
+	(interface_info_set_binding_name, method_info_set_binding_name):
+	Remove.
+	(interface_info_get_annotations, method_info_get_annotations)
+	(interface_info_get_annotation, method_info_get_annotation)
+	(interface_info_add_annotation, method_info_add_annotation):
+	Prototype.
+
+	* glib/dbus-gidl.c (struct InterfaceInfo): Substitute "annotations"
+	for "bindings".
+	(struct MethodInfo): Ditto.
+	Straightfoward conversion of binding methods into annotation methods
+	as prototyped.
+
+	* glib/dbus-glib-tool.c (pretty_print): Print annotations.
+
+	* glib/dbus-binding-tool-glib.h (DBUS_GLIB_ANNOTATION_C_SYMBOL): Define.
+
+	* glib/dbus-binding-tool-glib.c (gather_marshallers, generate_glue):
+	Use new annotation API.
+
+	* doc/introspect.dtd: Fix a number of DTD syntax errors.  Add
+	annotation element.
+	
+	* doc/dbus-specification.xml: Discuss introspection annotations,
+	include list of well-known annotations.
+
+	* test/glib/test-service-glib.xml: Make validate against new DTD.
+
+2005-02-17  Colin Walters  <walters@verbum.org>
+
+	This patch is based on initial work from
+	Paul Kuliniewicz <kuliniew@purdue.edu>.
+
+	* glib/dbus-gvalue.c (dbus_gvalue_init): New function; move
+	initialization of GValue from dbus type to here.
+	(dbus_gvalue_genmarshal_name_from_type): New function; generates a string
+	for the "glib-genmarshal" program from a DBus type.
+	(dbus_gvalue_binding_type_from_type): New function; turns a DBus type
+	into the C name for it we use in the glib bindings.
+	(dbus_gvalue_ctype_from_type): New function; maps a DBus type into a
+	glib C type (not GValue).
+	(dbus_gvalue_demarshal): invoke dbus_gvalue_init.
+
+	* glib/dbus-gutils.c (_dbus_gutils_wincaps_to_uscore): Moved here
+	from dbus-gobject.c.
+
+	* glib/dbus-gutils.h: Prototype it.
+
+	* glib/dbus-gproxy.c: Include new dbus-gobject.h.
+	(marshal_dbus_message_to_g_marshaller): Use new shared function
+	dbus_glib_marshal_dbus_message_to_gvalue_array.
+
+	* glib/dbus-gparser.c (parse_interface, parse_method): Handle c_name attribute.
+	Will be changed once we have annotations.
+
+	* glib/dbus-gobject.c: Change info_hash_mutex from GStaticMutex to
+	GStaticRWLock.  Callers updated.
+	(wincaps_to_uscore): Move to dbus-gutils.c.  Callers updated.
+	(string_table_next): New function for iterating over zero-terminated
+	string value array.
+	(string_table_lookup): New function; retrieves specific entry in
+	array.
+	(get_method_data): New function; look up method data in object data chunk.
+	(object_error_domain_prefix_from_object_info)
+	(object_error_code_from_object_info): New functions, but not implemented yet.
+	(method_interface_from_object_info): New function; retrieve interface name.
+	(method_name_from_object_info): New function; retrieve method name.
+	(method_arg_info_from_object_info): New function; retrieve argument data.
+	(arg_iterate): New function; iterates over serialized argument data.
+	(method_dir_signature_from_object_info): New function; returns a
+	GString holding type signature for arguments for just one
+	direction (input or output).
+	(method_input_signature_from_object_info)
+	(method_output_signature_from_object_info): New functions.
+	(dbus_glib_marshal_dbus_message_to_gvalue_array): New shared function;
+	converts dbus message arguments into a GValue array.  Used for both
+	signal handling and method invocation.
+	(struct DBusGlibWriteIterfaceData): New utility structure.
+	(write_interface): New function; generate introspection XML for
+	an interface.
+	(introspect_interfaces): New function; gathers all interface->methods,
+	generates introspection XML for them.
+	(handle_introspect): Invoke introspect_interfaces.
+	(get_object_property): Be sure to zero-initalize stack-allocated GValue.
+	(lookup_object_and_method): New function; examines an incoming message
+	and attempts to match it up (via interface, method name, and argument
+	signature) with a known object and method.
+	(gerror_domaincode_to_dbus_error_name): New function; converts a
+	GError domain and code into a DBus error name.  Needs GError data
+	added to object introspection to work well.
+	(gerror_to_dbus_error_message): Creates a DBusMessage error return from
+	GError.
+	(invoke_object_method): New function to invoke an object method
+	looked up via lookup_object_and_method.  Parses the incoming
+	message, turns it into a GValue array, then invokes the marshaller
+	specified in the DBusGMethodInfo.  Creates a new message with
+	either return values or error message as appropriate.
+	(gobject_message_function): Invoke lookup_object_and_method and
+	invoke_object_method.
+
+	* glib/dbus-glib-tool.c: Include dbus-binding-tool-glib.h.
+	(enum DBusBindingOutputMode): New enum for binding output modes.
+	(pretty_print): Print binding names.
+	(dbus_binding_tool_error_quark): GError bits.
+	(version): Fix typo.
+	(main): Create GIOChannel for output.  Parse new --mode argument,
+	possible values are "pretty-print", "glib-server", "glib-client".
+	Use mode to invoke appropriate function.
+	
+	* glib/dbus-gobject.h: Prototype dbus_glib_marshal_dbus_message_to_gvalue_array.
+
+	* glib/dbus-glib-tool.h: New header, just includes GError bits
+	for now.
+
+	* glib/dbus-gidl.c (struct InterfaceInfo): Add bindings hashtable;
+	maps binding style to name.
+	(struct MethodInfo): Ditto.
+	(get_hash_keys, get_hash_key): Utility function, returns keys for
+	a GHashTable.
+	(interface_info_new, method_info_new): Initialize bindings.
+	(interface_info_unref, method_info_unref): Destroy bindings.
+	(method_info_get_binding_names, method_info_get_binding_name)
+	(interface_info_get_binding_names, interface_info_get_binding_name):
+	Functions for retrieving binding names.
+	(method_info_set_binding_name, interface_info_set_binding_name):
+	Functions for setting binding names.
+
+	* glib/dbus-binding-tool-glib.h: New file, has prototypes
+	for glib binding generation.
+
+	* glib/dbus-binding-tool-glib.c: New file, implements server-side
+	and client-side glib glue generation.
+
+	* glib/Makefile.am (dbus_binding_tool_SOURCES): Add
+	dbus-binding-tool-glib.c, dbus-binding-tool-glib.h,
+	dbus-glib-tool.h.
+
+	* dbus/dbus-glib.h (struct DBusGMethodMarshaller): Remove in favor
+	of using GClosureMarshal directly.
+	(struct DBusGObjectInfo): Add n_infos member.
+
+	* test/glib/test-service-glib.xml: New file; contains introspection data
+	for MyTestObject used in test-service-glib.c.
+
+	* test/glib/test-service-glib.c (enum MyObjectError): New GError enum.
+	(my_object_do_nothing, my_object_increment, my_object_throw_error)
+	(my_object_uppercase, my_object_many_args): New test methods.
+	(main): Use dbus_g_object_class_install_info to include generated object
+	info.
+
+	* test/glib/Makefile.am: Generate server-side glue for test-service-glib.c,
+	as well as client-side bindings.
+
+	* test/glib/test-dbus-glib.c: Include test-service-glib-bindings.h.
+	(main): Activate TestSuiteGLibService; test invoke a bunch of its methods
+	using both the dbus_gproxy stuff directly as well as the generated bindings.
+
+2005-02-15  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c (dbus_connection_dispatch): always
+	complete a pending call, don't run filters first.
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_end_call): change to use
+	dbus_pending_call_steal_reply
+
+	* dbus/dbus-pending-call.c (dbus_pending_call_block): just call
+	_dbus_connection_block_pending_call
+	(dbus_pending_call_get_reply): change to steal_reply and return a
+	ref
+
+	* dbus/dbus-connection.c
+	(dbus_connection_send_with_reply_and_block): port to work in terms
+	of DBusPendingCall
+	(_dbus_connection_block_pending_call): replace block_for_reply
+	with this
+
+2005-02-14  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-userdb-util.c (_dbus_user_database_lookup_group):
+	properly handle looking up group information by name; fix 
+	from j@bootlab.org
+
+2005-02-13  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c (dbus_connection_return_message) 
+	(dbus_connection_borrow_message): hold dispatch lock while message
+	is outstanding
+	(_dbus_connection_block_for_reply): hold dispatch lock while we
+	block for the reply, so nobody steals our reply
+	(dbus_connection_pop_message): hold the dispatch lock while we
+	pluck the message
+
+2005-02-13  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c (_dbus_connection_acquire_dispatch)
+	(_dbus_connection_release_dispatch)
+	(_dbus_connection_acquire_io_path)
+	(_dbus_connection_release_io_path): make the mutex and condvar
+	control access to the "acquired" flag. Drop the connection lock
+	while waiting on the condvar. Hopefully these are baby steps in
+	roughly the right direction.
+
+2005-02-13  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c: use separate mutexes for the condition
+	variables; this is some kind of baseline for sanity, but the
+	condition variables still aren't used correctly afaict
+
+2005-02-13  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-object-tree.c (handle_default_introspect_and_unlock):
+	fix a double-unlock
+
+	* dbus/dbus-connection.c
+	(_dbus_connection_detach_pending_call_unlocked): add this
+
+        Initial semi-correct pass through to fix thread locking; there are
+	still some issues with the condition variable paths I'm pretty
+	sure
+	
+	* dbus/dbus-server.c: add a mutex on DBusServer and appropriate
+	lock/unlock calls
+
+	* dbus/dbus-connection.c (_dbus_connection_do_iteration_unlocked):
+	rename to add _unlocked
+	(struct DBusConnection): move "dispatch_acquired" and
+	"io_path_acquired" to use only one bit each.
+	(CONNECTION_LOCK, CONNECTION_UNLOCK): add checks with !DBUS_DISABLE_CHECKS
+	(dbus_connection_set_watch_functions): hacky fix to reentrancy
+	(_dbus_connection_add_watch, _dbus_connection_remove_watch) 
+	(_dbus_connection_toggle_watch, _dbus_connection_add_timeout) 
+	(_dbus_connection_remove_timeout) 
+	(_dbus_connection_toggle_timeout): drop lock when calling out to
+	user functions; done in a hacky/bad way.
+	(_dbus_connection_send_and_unlock): add a missing unlock
+	(_dbus_connection_block_for_reply): add a missing unlock
+
+	* dbus/dbus-transport.c (_dbus_transport_get_is_authenticated):
+	drop lock in a hacky probably unsafe way to call out to user
+	function
+
+2005-02-12  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-tree-view.c (info_set_func_text): display more
+	details on args
+
+	* bus/driver.c (bus_driver_handle_list_services): list the bus
+	driver
+
+	* glib/dbus-gparser.c (parse_arg): generate an arg name if none is supplied
+
+	* glib/dbus-gidl.c (signal_info_get_n_args): new function
+	(method_info_get_n_args): new function
+
+2005-02-12  Havoc Pennington  <hp@redhat.com>
+
+	* bus/driver.c (bus_driver_handle_introspect): add introspection
+	for bus driver
+
+2005-02-12  Havoc Pennington  <hp@redhat.com>
+
+	* bus/driver.c: put the signature of each bus driver method in the
+	table of handlers and check it on incoming calls; this isn't
+	really useful, but going to add introspect support in a minute.
+
+2005-02-11  Joe Shaw  <joeshaw@novell.com>
+
+	* mono/Connection.cs: The unpredictability of finalizers in mono
+	prevents us from deterministically disconnecting the filters from
+	the Service class's finalizer, so move tracking of filters and
+	matches here.  Add API for that.
+
+	* mono/Service.cs: Remove the code, add code which calls the
+	methods now on the Connection class.
+
+2005-02-11  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus.py (class Sender): added to support dbus signals better
+	(Bus::add_signal_receiver): added expand_args parameter which defaults
+	to True.  When expand args is True the signal handler will pass the 
+	message arguments as parameters to the signal handler.  If False
+	revert to previous behavior where the signal handler must get the
+	argument list from the message.  This is to help port applications
+	like HAL that have a tendancy to send variable length argument lists.
+	self._match_rule_to_receivers is now a dict of dicts.
+	(Bus::remove_signal_receiver): pop handler off the dict intead of 
+	removing it from a list
+	(Bus::_signal_func): change signal handlers so that interface,
+	signal_name, service, path and message are packed into a Sender
+	object and that is passed to the handler.  If expand_args is True
+	extract the args list from the message and append it to the parameter
+	list
+	
+	* python/dbus_bindings.pyx.in (class Signature): added to support 
+	signiature types
+	(MessageIter::__init__): changed iteration limit to match D-BUS
+	(MessageIter::get*): added INT16, UINT16, SIGNATURE, DICT_ENTRY, 
+	STRUCT and VARIENT type support
+	(MessageIter::python_value_to_dbus_sig): made recursive to support
+	recursive types
+	(MessageIter::append*): added Signature, dict, tuple 
+	support
+
+	* python/examples/example-client.py: added examples of getting tuples
+	and dicts
+
+	* python/examples/example-service.py: added examples of sending tuples
+	and dicts
+
+	* python/examples/example-signal-recipient.py: Fixed to handle new
+	signal callback format
+
+2005-02-10  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-dbus-glib.c (main): fix so this test doesn't fail
+	(call dbus_g_proxy_add_signal)
+
+	* dbus/dbus-server-unix.c (_dbus_server_new_for_tcp_socket):
+	escape the hostname
+	(_dbus_server_new_for_domain_socket): escape the path
+
+	* dbus/dbus-address.c (dbus_address_escape_value): new
+	(dbus_address_unescape_value): new
+	(dbus_parse_address): unescape values
+
+	* dbus/dbus-string.c (_dbus_string_append_byte_as_hex): new function
+
+	* doc/dbus-specification.xml: explain how to escape values in
+	addresses
+
+2005-02-10  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message-factory.c (generate_special): modify test to
+	avoid using a non-basic dict key
+
+	* dbus/dbus-marshal-validate-util.c: add test for the below
+
+	* doc/dbus-specification.xml: require that dict keys are a basic
+	type
+
+	* dbus/dbus-marshal-validate.c
+	(_dbus_validate_signature_with_reason): require that dict key is a
+	basic type
+
+2005-02-10  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-object-tree.c (handle_default_introspect_and_unlock):
+	change to be _and_unlock instead of _unlocked
+
+	* dbus/dbus-connection.c
+	(_dbus_connection_send_preallocated_unlocked_no_update): rename to
+	have no_update so we can find this bug quickly in future
+
+2005-02-10  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message-util.c (verify_test_message): tests for string
+	array
+
+	* dbus/dbus-message.c (dbus_message_append_args_valist): add
+	support for arrays of string/signature/path
+
+2005-02-10  Joe Shaw  <joeshaw@novell.com>
+
+	* dbus/dbus-connection.c
+	(_dbus_connection_queue_received_message_link,
+	_dbus_connection_message_sent): Add the path to
+	the verbose output.
+	(_dbus_connection_send_preallocated_and_unlock): Added.  Calls
+	_dbus_connection_send_preallocated_unlocked(), updated the
+	dispatch status, and unlocks.  Fixes a bug where certain
+	situations (like a broken pipe) could cause a Disconnect message
+	to not be sent, tricking the bus into thinking a service was still
+	there when the process had quit.
+	(_dbus_connection_send_preallocated): Call
+	_dbus_connection_send_preallocated_and_unlock().
+	(_dbus_connection_send_and_unlock): Added.  Calls
+	_dbus_connection_send_preallocated_and_unlock().
+	(dbus_connection_send): Call _dbus_connection_send_and_unlock().
+	(dbus_connection_send_with_reply): Update the dispatch status and
+	unlock.
+
+	* mono/Service.cs (~Service): Added.  Removes the filter so that
+	we don't get unmanaged code calling back into a GCed delegate.
+	(RemoveFilter); Added.
+
+2005-02-09  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-message.c (dbus_message_iter_open_container):
+	- Removed check for iterator type being an array because
+	get_arg_type does not work with writer iterators
+	- Pass NULL to _dbus_type_writer_recurse if signiture is NULL
+
+2005-02-07  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.xml: some more language cleanups; add
+	stuff about how to deal with invalid protocol and extension
+	points; add _ to allowed chars in auth commands; add EXTENSION_
+	auth command prefix
+
+2005-02-06  Havoc Pennington  <hp@redhat.com>
+
+	* s/expected/required/ in a couple places for clarity
+
+2005-02-07  Colin Walters  <walters@verbum.org>
+
+	* bus/selinux.c (bus_selinux_allows_send): Handle NULL for
+	sender or proposed_recipient.
+
+2005-02-06  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message-factory.c (generate_special): more tests
+
+	* dbus/dbus-marshal-validate.c (validate_body_helper): detect
+	array length that exceeds the maximum
+
+2005-02-05  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message-factory.c (generate_special): more test cases,
+	increasing coverage
+
+	* dbus/dbus-marshal-validate.c (validate_body_helper): return the
+	reason why a signature was invalid
+
+	* dbus/dbus-marshal-header.c (load_and_validate_field): fix to
+	skip the length of the string before we look at it in validation
+
+	* dbus/dbus-string-util.c (_dbus_string_test): add tests for
+	equal_substring
+
+	* dbus/dbus-message.c (_dbus_message_loader_new): default
+	max_message_length to DBUS_MAXIMUM_MESSAGE_LENGTH
+
+2005-02-05  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-marshal-validate.c (validate_body_helper): fix crash
+	if the signature of a variant was empty
+	(_dbus_validate_signature_with_reason): catch "(a)" (array inside
+	struct with no element type)
+
+	* dbus/dbus-message-factory.c (generate_uint32_changed): add more
+	mangled messages to break things
+
+2005-02-04  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_disconnect_signal): use
+	g_quark_try_string() so it actually can return 0
+	(dbus_g_proxy_connect_signal): ditto
+
+2005-02-04  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_emit_remote_signal): fix a
+	bogus warning
+	(tristring_from_message): assert cleanly on null path/interface
+	(should not be possible though I decided later)
+	(dbus_g_proxy_dispose): move proxy manager unregistration here
+	(DBUS_G_PROXY_DESTROYED): add this macro, and use it in a bunch of
+	g_return_if_fail() checks
+
+2005-02-04  Havoc Pennington  <hp@redhat.com>
+
+	* doc/Makefile.am (EXTRA_DIST): add DTDs to makefile
+
+	* doc/introspect.dtd: add introspect.dtd from David A. Wheeler
+	(with some minor changes)
+
+	* doc/dbus-specification.xml: add deprecated attribute to
+	introspection format
+
+2005-01-31  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gproxy.c: rewrite how signals work again, this time I
+	think it's sort of right
+
+2005-01-30  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-viewer.c: kind of half-ass hook up the option menu.
+
+2005-01-30  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-names-model.c: dynamically watch NameOwnerChanged
+
+	* autogen.sh: change to autotools 1.9
+
+	* glib/dbus-gproxy.c: completely change how signals work
+	(dbus_g_proxy_add_signal): new function to specify signature of a
+	signal
+	(dbus_g_proxy_emit_received): marshal the dbus message to GValues,
+	and g_warning if the incoming message has the wrong signature.
+
+2005-01-30  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-names-model.c (have_names_notify): fix this
+
+	* dbus/dbus-message.c (_dbus_message_iter_get_args_valist): clean
+	up the string array handling a bit 
+
+2005-01-30  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-glib.c (dbus_g_pending_call_set_notify): new function
+	(dbus_g_pending_call_cancel): new function
+
+	* dbus/dbus-glib.h: move GType decls for connection/message here;
+	* dbus/dbus-glib.c: move all the g_type and ref/unref stuff in
+	here, just kind of rationalizing how we handle all that
+
+	* tools/dbus-names-model.c: new file for a tree model listing the
+	services on a bus
+
+	* tools/dbus-tree-view.c (model_new): use proper typing on the
+	model rows
+
+2005-01-30  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gmain.c: add a custom GSource back that just checks
+	whether the message queue has anything in it; otherwise, there are 
+	cases where we won't see messages in the queue since there was no 
+	IO visible to the glib main loop
+
+	* dbus/dbus-connection-internal.h (_DBUS_DEFAULT_TIMEOUT_VALUE):
+	increase default message timeout to 25 seconds
+
+2005-01-30  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-profile.c (no_bus_stop_server): remove the
+	warning about the g_warning that I just fixed
+
+	* glib/dbus-gmain.c: rewrite the main loop stuff to avoid the
+	custom source, seems to be a lot easier to understand and work
+	better.
+
+2005-01-30  Havoc Pennington  <hp@redhat.com>
+
+        I think this main loop thing is conceptually broken, but here are 
+	some band aids. I'll maybe rewrite it in a minute.
+	
+	* glib/dbus-gmain.c (add_timeout): timeout stuff doesn't use the
+	custom GSource, so don't pass it in; confusing
+	(gsource_server_finalize, gsource_connection_finalize): add
+	finalize handlers that remove all the watches.	
+
+2005-01-30  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gobject.c (introspect_properties): fix the XML
+	generated
+
+	* dbus/dbus-message.c (dbus_message_unref): add an in_cache flag
+	which effectively detects the use of freed messages
+
+	* glib/dbus-gobject.c (handle_introspect): modify and return the
+	reply message instead of the incoming message
+
+	* dbus/dbus-object-tree.c (handle_default_introspect_unlocked):
+	gee, maybe it should SEND THE XML instead of just making a string
+	and freeing it again ;-)
+
+	* tools/dbus-print-message.c (print_message): improve printing of
+	messages
+
+	* configure.in: add debug-glib.service to the output
+
+2005-01-30  Havoc Pennington  <hp@redhat.com>
+
+        dbus-viewer introspected and displayed the bus driver
+	
+	* dbus/dbus-object-tree.c 
+	(object_tree_test_iteration): add tests for a handler registered on "/"
+
+	* dbus/dbus-object-tree.c
+	(_dbus_decompose_path): fix to handle path "/" properly
+	(run_decompose_tests): add tests for path decomposition
+	
+	* glib/dbus-gutils.c (_dbus_gutils_split_path): fix to handle "/"
+	properly
+
+	* glib/dbus-gobject.c (handle_introspect): fix quotes
+
+	* test/glib/run-test.sh: support launching the bus, then running
+	dbus-viewer
+
+	* test/glib/test-service-glib.c (main): put in a trivial gobject
+	subclass and register it on the connection
+
+	* bus/driver.c (bus_driver_handle_introspect): implement
+	introspection of the bus driver service
+
+	* dbus/dbus-protocol.h: add #defines for the XML namespace,
+	identifiers, doctype decl
+
+	* bus/driver.c (bus_driver_handle_get_service_owner): handle
+	attempts to get owner of DBUS_SERVICE_ORG_FREEDESKTOP_DBUS by 
+	returning the service unchanged.
+	(bus_driver_handle_message): remove old check for reply_serial in
+	method calls, now the message type deals with that
+	(bus_driver_handle_message): handle NULL interface
+
+	* glib/dbus-gproxy.c (dbus_g_proxy_get_bus_name): new function
+
+	* glib/dbus-gloader-expat.c (description_load_from_string): allow
+	-1 for len
+
+	* tools/dbus-viewer.c: add support for introspecting a service on
+	a bus
+
+	* glib/dbus-gproxy.c (dbus_g_pending_call_ref): add
+	(dbus_g_pending_call_unref): add
+
+2005-01-29  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-tree-view.c: add support for displaying properties.
+	(run dbus-viewer with an introspect xml file as arg, then resize
+	the window so the tree elements show up, not sure what that is)
+
+	* glib/dbus-gobject.c (handle_introspect): return
+	org.freedesktop.Properties and org.freedesktop.Introspectable
+	interfaces when we are introspected.
+
+	* doc/dbus-specification.xml: allow empty interface name when 
+	Get/Set a property
+
+2005-01-29  Havoc Pennington  <hp@redhat.com>
+
+	* glib/Makefile.am: rename dbus-glib-tool to dbus-binding-tool;
+	though it uses glib, it could be extended for any binding in
+	principle
+
+	* glib/dbus-gobject.c (gobject_message_function): change to the
+	new way properties work
+
+	* dbus/dbus-protocol.h: add the new interfaces
+
+	* doc/dbus-specification.xml: document the introspection format,
+	Introspectable interface, and add an org.freedesktop.Properties
+	interface.
+
+	* glib/dbus-gparser.c: add support for a <property> element
+
+	* glib/dbus-gidl.c: add PropertyInfo
+
+	* glib/dbus-gobject.c (handle_introspect): put the outermost
+	<node> outside the signal and property descriptions.
+	(introspect_properties): export properties as <property> rather
+	than as method calls
+
+2005-01-28  Havoc Pennington  <hp@redhat.com>
+
+	* doc/TODO, doc/dbus-specification.xml: spec and TODO tweaks
+	related to authentication protocol
+
+2005-01-28  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx.in: Updated to handle new D-BUS type system
+		- BUS_ACTIVATION -> BUS_STARTER
+		- DBUS_BUS_ACTIVATION -> DBUS_BUS_STARTER
+		- class MessageIter (__init__): Added recursion checking 
+		so we throw a nice error instead of just disconnecting from the
+		bus.
+		(get): Added arg_type parameter for recursion.
+		Removed the nil type
+		Added signiture type placeholder (not implemented)
+		Added struct type placeholder (not implemented)
+		Added varient type placeholder (not implemented)
+		Commented out dict type for now	    
+		(get_element_type): renamed from get_array_type
+		(get_*): changed to use the dbus_message_iter_get_basic API
+		(get_*_array): removed in favor of recursive get_array method
+		(get_array): new recursive method which calls get to marshal
+	        the elements of the array
+		(value_to_dbus_sig): New method returns the corrasponding
+		dbus signiture to a python value
+		(append): Comment out dict handling for now
+		Handle lists with the new recursive API
+		Comment out None handling for now
+		(append_nil): removed
+		(append_*): changed to use dbus_message_iter_append_basic API
+		(append_*_array): removed in favor of recursive append_array 
+		method
+		(__str__): Make it easier to print out recursive iterators
+		for debugging
+		- class Message (__str__): moved type inspection to the
+		MessageIter class' __str__ method
+		(get_iter): Added an append parameter wich defaults to False
+		If True use the new API's to create an append iterator
+
+	* python/dbus.py: Update to use new bindings API
+		- TYPE_ACTIVATION -> TYPE_STARTER
+		- class Bus (_get_match_rule): GetServiceOwner -> GetNameOwner
+		- class ActivationBus -> class StarterBus
+		- class RemoteObject (__call__): get an append iterator
+		- (_dispatch_dbus_method_call): get an append iterator
+		- class Object (emit_signal): get an append iterator
+
+	* python/examples/: Fixed up the examples to work with the new API
+		
+2005-01-28  Joe Shaw  <joeshaw@novell.com>
+
+	* configure.in: Bump version up to 0.30.
+
+	* HACKING: Add a release item to bump the version number up after 
+	a release.
+
+2005-01-28  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.xml: update to describe 16-bit types and
+	dict entries
+
+	* dbus/dbus-marshal-basic.c (_dbus_unpack_uint16): fix broken
+	assertion
+
+	* dbus/dbus-protocol.h (DBUS_TYPE_DICT_ENTRY): add DICT_ENTRY as a
+	type
+
+	* dbus/dbus-marshal-recursive.c: implement
+
+2005-01-27  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-arch-deps.h.in: add 16/32-bit types
+
+	* configure.in: find the right type for 16 and 32 bit ints as well
+	as 64
+
+	* dbus/dbus-protocol.h (DBUS_TYPE_INT16, DBUS_TYPE_UINT16): add
+	the 16-bit types so people don't have to stuff them in 32-bit or
+	byte arrays.
+
+2005-01-27  Havoc Pennington  <hp@redhat.com>
+
+        * dbus/dbus-message.c: byteswap the message if you init an
+	iterator to read/write from it
+	
+	* dbus/dbus-marshal-byteswap.c: new file implementing 
+	_dbus_marshal_byteswap()
+
+	* dbus/dbus-marshal-basic.c: add _dbus_swap_array()
+
+2005-01-26  Havoc Pennington  <hp@redhat.com>
+	
+	* dbus/dbus-marshal-validate-util.c: break this out (and fix
+	build, apparently - nobody noticed?)
+	
+2005-01-26  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-marshal-recursive.h: remove todo comment
+
+2005-01-25  Joe Shaw  <joeshaw@novell.com>
+
+	* Land the mono binding changes to conform to the new APIs.
+
+	* mono/Makefile.am: Remove Custom.cs, DBusType/Custom.cs,
+	DBusType/Dict.cs, and DBusType/Nil.cs from the build.
+
+	* mono/Arguments.cs (GetCodeAsString): Added.  Returns the dbus
+	type code as a string.
+	(InitAppending): Rename dbus_message_append_iter_init() to
+	dbus_message_iter_init_append().
+
+	* mono/BusDriver.cs: Rename ServiceEventHandler to
+	NameOwnerChangedHandler.  Rename GetServiceOwner to GetOwner.
+	Rename ServiceOwnerChanged to NameOwnerChanged.
+
+	* mono/Connection.cs: Rename BaseService to UniqueName, and the
+	underlying C call.
+
+	* mono/Custom.cs: Removed.  The CUSTOM type has been removed.
+
+	* mono/Service.cs: Rename Exists to HasOwner, internally rename
+	dbus_bus_acquire_service() to dbus_bus_request_name().
+
+	* mono/DBusType/Array.cs (ctor): Use Type.GetElementType() instead
+	of Type.UnderlyingSystemType to get the correct element type for
+	the array.
+	(ctor): Update code for new APIs: use dbus_message_iter_recurse(),
+	dbus_message_get_{element|arg}_type() instead of
+	dbus_message_iter_init_array_iterator().
+	(Append): Replace dbus_message_iter_append_array() with
+	dbus_message_iter_open_container() and
+	dbus_message_iter_close_container().
+
+	* mono/DBusType/Custom.cs, mono/DBusType/Nil.cs: Removed.  These
+	types have been removed.
+	
+	* mono/DBusType/*.cs: Replace calls of
+	dbus_message_iter_get_[type]() to dbus_message_iter_get_basic(),
+	but specify the type in the DllImport extern declaration.  Ditto
+	for dbus_message_iter_append_[type]() ->
+	dbus_message_iter_append_basic().
+
+	* mono/example/BusListener.cs: Update for ServiceEventHandler ->
+	NameOwnerChangedHandler.
+
+2005-01-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx.in: Rename of methods and bindings
+		- get_base_service -> get_unique_name
+		- bus_get_base_service -> bus_get_unique_name
+		- dbus_bus_get_base_service -> dbus_bus_get_unique_name
+		- ACTIVATION_REPLY_ACTIVATED -> DBUS_START_REPLY_SUCCESS 
+		- ACTIVATION_REPLY_ALREADY_ACTIVE -> DBUS_START_REPLY_ALREADY_RUNNING
+		- bus_activate_service -> bus_start_service_by_name
+		- dbus_bus_activate_service -> dbus_bus_start_service_by_name
+		- bus_acquire_service -> bus_request_name
+		- dbus_bus_acquire_service -> dbus_bus_request_name
+		- bus_service_exists -> bus_name_has_owner
+		- dbus_bus_service_exists -> dbus_bus_name_has_owner
+
+	* python/dbus.py: Rename of methods
+		- activate_service -> start_service_by_name
+		- bus_acquire_service -> bus_request_name
+		- ACTIVATION_REPLY_ACTIVATED -> START_REPLY_SUCCESS 
+		- ACTIVATION_REPLY_ALREADY_ACTIVE -> START_REPLY_ALREADY_RUNNING
+
+	
+2005-01-24  Joe Shaw  <joeshaw@novell.com>
+
+	* dbus/dbus-connection.c (dbus_connection_dispatch): Print out the
+	signature for the method that can't be found.
+
+	* dbus/dbus-message.c (dbus_message_iter_init): To check to see if
+	the message has any arguments, we need to call
+	_dbus_type_reader_get_current_type(), not
+	_dbus_type_reader_has_next().
+
+2005-01-24  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message-factory.c: more testing of message validation
+
+	* dbus/dbus-protocol.h (DBUS_MINIMUM_HEADER_SIZE): move to this
+	header
+
+2005-01-23  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message-factory.c, dbus/dbus-message-util.c: 
+	get this all working, not many tests in the framework yet though
+
+2005-01-22  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-faq.xml, doc/dbus-tutorial: add a FAQ and update
+	tutorial, based on work from David Wheeler.
+
+2005-01-21  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-bus.c: add more return_if_fail checks
+
+	* dbus/dbus-message.c (load_message): have the "no validation"
+	mode (have to edit the code to toggle the mode for now though)
+
+	* dbus/dbus-marshal-header.c (_dbus_header_load): have a mode that
+	skips all validation; I want to use this at least for benchmark
+	baseline, I'm not sure if it should be a publicly-available switch.
+
+2005-01-21  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gmain.c: don't put the GLib bindings in the same
+	toplevel doxygen group as the low-level API stuff
+
+	* dbus/dbus.h: note that libdbus is the low-level API
+
+2005-01-20  Havoc Pennington  <hp@redhat.com>
+
+	* update-dbus-docs.sh: script to update docs on the web site, only
+	works for me though. neener.
+
+2005-01-20  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_poll): amazingly, trying to compile
+	code can reveal bugs in it
+
+2005-01-20  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_poll): fix several bugs in the
+	select() version, patches from Tor Lillqvist
+
+2005-01-20  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-tutorial.xml: replace > with &gt;
+
+	* bus/services.c (bus_registry_acquire_service): validate the name
+	and return a better error if it's no good.
+
+	* doc/dbus-specification.xml: note NO_AUTO_START change
+
+	* dbus/dbus-protocol.h (DBUS_HEADER_FLAG_NO_AUTO_START): change
+	from AUTO_START, we're toggling the default
+
+	* bus/dispatch.c: adapt the tests to change of auto-start default
+
+2005-01-18  Havoc Pennington  <hp@redhat.com>
+
+	* rename dbus-daemon-1 to dbus-daemon throughout
+
+2005-01-18  Havoc Pennington  <hp@redhat.com>
+
+        * Throughout, grand renaming to strip out the use of "service",
+	just say "name" instead (or "bus name" when ambiguous).  Did not
+	change the internal code of the message bus itself, only the
+	programmer-facing API and messages.
+	
+	* doc/dbus-specification.xml: further update the message bus section
+	
+	* bus/config-parser.c (all_are_equiv): fix bug using freed string
+	in error case
+
+2005-01-17  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-types.h: remove 16-bit types since we don't use them
+	ever
+
+	* dbus/dbus-marshal-validate.c (_dbus_validate_path): disallow any
+	"invalid name character" not only non-ASCII
+
+	* doc/dbus-specification.xml: further update spec, message bus 
+	parts are still out-of-date but the marshaling etc. stuff is now
+	accurate-ish
+
+2005-01-17  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.xml: partially update spec
+
+2005-01-17  Havoc Pennington  <hp@redhat.com>
+
+        * Throughout, align variant bodies according to the contained
+	type, rather than always to 8. Should save a fair bit of space in
+	message headers.
+	
+	* dbus/dbus-marshal-validate.c (_dbus_validate_body_with_reason):
+	fix handling of case where p == end
+
+	* doc/TODO: remove the dbus_bool_t item and variant alignment items
+
+2005-01-17  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-types.h: hardcode dbus_bool_t to 32 bits
+
+	* Throughout: modify DBUS_TYPE_BOOLEAN to be a 32-bit type instead
+	of an 8-bit type. Now dbus_bool_t is the type to use whenever you 
+	are marshaling/unmarshaling a boolean.
+
+2005-01-16  Havoc Pennington  <hp@redhat.com>
+
+        This is about it on what can be disabled/deleted from libdbus
+	easily, back below 150K anyhow. Deeper cuts are more work than 
+	just turning the code off as I've done here.
+	
+	* dbus/dbus-marshal-basic.c (_dbus_pack_int32): we don't need the
+	signed int convenience funcs
+
+	* dbus/dbus-internals.c (_dbus_verbose_real): omit when not in
+	verbose mode
+
+	* dbus/dbus-string-util.c, dbus/dbus-string.c: more breaking
+	things out of libdbus
+
+	* dbus/dbus-sysdeps.c, dbus/dbus-sysdeps-util.c: same
+	
+	* dbus/dbus-hash.c: purge the TWO_STRINGS crap (well, make it
+	tests-enabled-only, though it should probably be deleted)
+
+	* dbus/dbus-message-util.c: same stuff
+
+	* dbus/dbus-auth-util.c: same stuff
+
+2005-01-16  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-userdb-util.c: split out part of dbus-userdb.c
+
+	* dbus/dbus-sysdeps.c (_dbus_uid_from_string): move here to pave
+	way for stripping down dbus-userdb.c stuff included in libdbus.
+	Rename _dbus_parse_uid for consistency.
+
+2005-01-16  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-internals.c (_dbus_real_assert): print the function
+	name the assertion failed in
+
+	* dbus/dbus-internals.h (_dbus_return_if_fail) 
+	(_dbus_return_val_if_fail): assert that the name of the function
+	containing the check doesn't start with '_', since we only want to 
+	use checks on public functions
+	
+	* dbus/dbus-connection.c (_dbus_connection_ref_unlocked): change
+	checks to assertions
+
+	* dbus/dbus-marshal-header.c (_dbus_header_set_field_basic):
+	change checks to asserts for private function
+
+	* dbus/dbus-message.c (_dbus_message_set_serial): checks
+	to asserts for private function
+
+	* dbus/dbus-marshal-recursive.c (skip_one_complete_type): remove
+	broken assertion that was breaking make check
+	(_dbus_type_reader_array_is_empty): remove this rather than fix
+	it, was only used in assertions
+
+2005-01-16  Havoc Pennington  <hp@redhat.com>
+
+	* test/unused-code-gc.py: hacky script to find code that's used
+	only by the bus (not libdbus) or used only by tests or not used at
+	all. It has some false alarms, but looks like we can clean up a
+	lot of size from libdbus.
+
+	* dbus/dbus-sysdeps.c, dbus/dbus-sysdeps-utils.c,
+	dbus/Makefile.am: initially move 10K of binary size out of libdbus
+	
+2005-01-16  Havoc Pennington  <hp@redhat.com>
+
+        * Add and fix docs according to Doxygen warnings throughout
+	source.
+	
+	* dbus/dbus-marshal-recursive.c
+	(_dbus_type_reader_array_is_empty): change this to just call
+	array_reader_get_array_len() and make it static
+
+	* dbus/dbus-message.c (dbus_message_iter_get_element_type): rename
+	from get_array_type
+	(dbus_message_iter_init_append): rename from append_iter_init
+
+	* dbus/dbus-marshal-recursive.c
+	(_dbus_type_reader_get_element_type): rename from
+	_dbus_type_reader_get_array_type
+
+2005-01-15  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-profile.c (with_bus_server_filter): fix crash
+
+	* dbus/dbus-marshal-basic.c (_dbus_unpack_uint32): inline as macro
+	when DBUS_DISABLE_ASSERT
+	(_dbus_marshal_set_basic): be sure we align for the string length
+
+	* dbus/dbus-marshal-recursive.c (skip_one_complete_type): make
+	this look faster
+
+	* dbus/dbus-string.c (_dbus_string_get_const_data_len): add an
+	inline macro version
+	(_dbus_string_set_byte): provide inline macro version
+
+2005-01-15  Havoc Pennington  <hp@redhat.com>
+
+	* Land the new message args API and type system.
+
+	This patch is huge, but the public API change is not 
+	really large. The set of D-BUS types has changed somewhat, 
+	and the arg "getters" are more geared toward language bindings;
+	they don't make a copy, etc.
+
+	There are also some known issues. See these emails for details
+	on this huge patch:
+	http://lists.freedesktop.org/archives/dbus/2004-December/001836.html
+        http://lists.freedesktop.org/archives/dbus/2005-January/001922.html
+	
+	* dbus/dbus-marshal-*: all the new stuff
+
+	* dbus/dbus-message.c: basically rewritten
+
+	* dbus/dbus-memory.c (check_guards): with "guards" enabled, init
+	freed blocks to be all non-nul bytes so using freed memory is less
+	likely to work right
+
+	* dbus/dbus-internals.c (_dbus_test_oom_handling): add
+	DBUS_FAIL_MALLOC=N environment variable, so you can do
+	DBUS_FAIL_MALLOC=0 to skip the out-of-memory checking, or
+	DBUS_FAIL_MALLOC=10 to make it really, really, really slow and
+	thorough.
+
+	* qt/message.cpp: port to the new message args API
+	(operator<<): use str.utf8() rather than str.unicode()
+	(pretty sure this is right from the Qt docs?)
+
+	* glib/dbus-gvalue.c: port to the new message args API
+
+	* bus/dispatch.c, bus/driver.c: port to the new message args API
+
+	* dbus/dbus-string.c (_dbus_string_init_const_len): initialize the
+	"locked" flag to TRUE and align_offset to 0; I guess we never
+	looked at these anyhow, but seems cleaner.
+
+	* dbus/dbus-string.h (_DBUS_STRING_ALLOCATION_PADDING):
+	move allocation padding macro to this header; use it to implement
+	(_DBUS_STRING_STATIC): ability to declare a static string.
+
+	* dbus/dbus-message.c (_dbus_message_has_type_interface_member):
+	change to return TRUE if the interface is not set.
+
+	* dbus/dbus-string.[hc]: move the D-BUS specific validation stuff
+	to dbus-marshal-validate.[hc]
+
+	* dbus/dbus-marshal-basic.c (_dbus_type_to_string): move here from
+	dbus-internals.c
+
+	* dbus/Makefile.am: cut over from dbus-marshal.[hc]
+	to dbus-marshal-*.[hc]
+
+	* dbus/dbus-object-tree.c (_dbus_decompose_path): move this
+	function here from dbus-marshal.c
+
+2005-01-12  Joe Shaw  <joeshaw@novell.com>
+
+	* NEWS: Update for 0.23.
+
+	* configure.in: Release 0.23.
+
+2005-01-12  Joe Shaw  <joeshaw@novell.com>
+
+	* mono/Makefile.am, mono/example/Makefile.am: Always build the 
+	dbus DLL with --debug.  Clean up after the .mdb files this leaves
+	behind.
+
+	* mono/doc/Makefile.am: Need to uninstall the docs on "make
+	uninstall"
+
+	* mono/Arguments.cs (GetDBusTypeConstructor): If the type
+	is an enum, get the enum's underlying type.  Another mono
+	1.1.3 fix.
+
+2005-01-11  Joe Shaw  <joeshaw@novell.com>
+
+	Patch from Sjoerd Simons <sjoerd@luon.net>
+
+	* mono/Makefile.am, mono/example/Makefile.am: Don't redefine
+	DESTDIR.  It breaks stuff.
+
+2005-01-11  Joe Shaw  <joeshaw@novell.com>
+
+	Patch from Tambet Ingo <tambet@ximian.com>
+
+	* mono/DBusType/Array.cs (Get): Get the underlying element type by
+	calling type.GetElementType().  The code previously depended on
+	broken Mono behavior, which was fixed in Mono 1.1.3.
+
+	* mono/DBusType/Dict.cs (constructor): Fix the parameters for
+	Activator.CreateInstance() so that the class's constructor is
+	called with the right parameters.
+
+2005-01-11  Joe Shaw  <joeshaw@novell.com>
+
+	Patch from Timo Teräs <ext-timo.teras@nokia.com>
+
+	* dbus/dbus-connection.c
+	(_dbus_connection_queue_received_message_link): Call
+	_dbus_connection_remove_timeout() instead of the _locked()
+	variant, since it's always called from
+	_dbus_connection_handle_watch(), which handles the locking.
+	Removed the _locked() variant since it's no longer used.
+
+2005-01-03  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-internals.h: I'm an idiot, _dbus_assert certainly can
+	return
+	
+2004-12-26  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-internals.h: add _DBUS_GNUC_NORETURN to _dbus_assert
+
+2005-01-03  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_sysdeps_test): fix using == on
+	floating point
+
+	* dbus/dbus-string.c (_dbus_string_insert_alignment): new function
+
+2005-01-02  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-internals.h (_DBUS_ALIGN_OFFSET): new macro
+
+2005-01-01  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: add -Wfloat-equal
+
+2005-01-01  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.h: add _DBUS_DOUBLES_BITWISE_EQUAL macro, 
+	for a variety of reasons '==' doesn't do this.
+
+2004-12-31  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-string.c (_dbus_string_equal_substrings): new function
+	I keep wishing I had
+
+2004-12-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus.py: s/ACTIVATION_REPLY_ACTIVE/ACTIVATION_REPLY_ACTIVATED
+
+2004-12-30  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx.in: Change DBUS_ACTIVATION_REPLY_ACTIVATED
+	and DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE to match the values in
+	dbus-protocol.h.  Because they are defines and not enums they are not
+	autogenerated.
+
+2004-12-26  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx.in (bus_activate_service): Bind
+	dbus_bus_activate_service
+
+	* python/dbus.py (Bus.activate_service): activate a service on the
+	bus.
+
+2004-12-24  Havoc Pennington  <hp@redhat.com>
+
+	* test/decode-gcov.c: change to use .gcno and .gcda files, but the
+	file format has also changed and I haven't adapted to that yet
+	
+	* Makefile.am: load .gcno files from latest gcc
+
+2004-12-23  John (J5) Palmieri  <johnp@redhat.com>
+	* Patch from Rob Taylor <robtaylor@fastmail.fm>
+
+	* python/dbus_bindings.pyx.in (bus_get_unix_user): New
+	lowlevel binding
+
+	* python/dbus.py (get_unix_user): Added binding to 
+	call dbus_bindings.bus_get_unix_user
+
+	* python/extract.py: Modified the proto_pat regex to
+	handle unsigned long
+
+2004-12-21  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/make-dbus-glib-error-enum.sh: omit the function keyword for
+	better POSIX compliance.
+
+2004-12-19  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-string.c (_dbus_string_insert_4_aligned) 
+	(_dbus_string_insert_8_aligned): new functions
+
+	* dbus/dbus-string.c (_dbus_string_alloc_space): new function
+
+2004-12-18  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-string.c (_dbus_string_validate_ascii): use ISASCII
+	macro
+
+	* dbus/dbus-message.c: fix a comment, and add a still-unused
+	not-implemented function
+
+	* dbus/dbus-marshal.h: fix comment
+
+	* dbus/dbus-internals.h (_DBUS_ISASCII): new macro
+
+2004-12-17  Joe Shaw  <joeshaw@novell.com>
+
+	* mono/DBusType/Byte.cs, mono/DBusType/Int32.cs,
+	mono/DBusType/Int64.cs, mono/DBusType/UInt32.cs,
+	mono/DBusType/UInt64.cs: Use Enum.GetUnderlyingType() instead of
+	Type.UnderlyingSystemType to get the actual system type
+	underneath.  This code previously depended on the broken Mono
+	behavior, which was fixed in 1.1.3.
+
+2004-11-27  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-string.h (_dbus_string_get_byte): inline when asserts
+	are disabled
+	(_dbus_string_get_const_data): inline when asserts are disabled
+
+	* dbus/dbus-message.c: record the _dbus_current_generation of
+	creation so we can complain if dbus_shutdown() is used improperly.
+	Do this only if checks are enabled.
+
+	* dbus/dbus-connection.c: ditto
+	
+2004-11-26  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-profile.c: add with_bus mode to profile echoes
+	that go through the bus.
+
+	* test/glib/run-test.sh: add ability to run test-profile
+
+	* bus/dbus-daemon-1.1.in: fix to say that SIGHUP causes partial
+	config file reload.
+
+2004-11-26  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-profile.c: clean up how the fake_malloc_overhead
+	thing was implemented
+
+2004-11-26  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-profile.c: tweak a bit, add support for some
+	made-up minimal malloc overhead with plain sockets, since in 
+	real life some sort of buffers are unavoidable thus we could 
+	count them in the theoretical best case
+
+2004-11-26  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c (dbus_message_cache_or_finalize): fix bug
+	where I was trying to cache one too many messages
+
+2004-11-26  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c: reimplement message cache as an array which 
+	makes the cache about twice as fast and saves maybe 1.5% overall
+
+2004-11-26  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-threads.c (init_global_locks): forgot to put the
+	message cache lock here
+
+2004-11-26  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c (struct DBusMessage): put the locked bit and
+	the "char byte_order" next to each other to save 4 bytes
+	(dbus_message_new_empty_header): reduce preallocation, since the
+	message cache should achieve a similar effect
+	(dbus_message_cache_or_finalize, dbus_message_get_cached): add a
+	message cache that keeps a few DBusMessage around in a pool,
+	another 8% speedup or so.
+
+	* dbus/dbus-dataslot.c (_dbus_data_slot_list_clear): new function
+
+2004-11-25  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-transport-unix.c (unix_do_iteration): if we're going
+	to write, without reading or blocking, try it before the poll()
+	and skip the poll() if nothing remains to write. This is about a
+	3% speedup in the echo client/server
+
+2004-11-25  Havoc Pennington  <hp@redhat.com>
+
+        The primary change here is to always write() once before adding
+	the write watch, which gives us about a 10% performance increase.
+	
+	* dbus/dbus-transport-unix.c: a number of modifications to cope
+	with removing messages_pending
+	(check_write_watch): properly handle
+	DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of
+	messages_pending stuff
+	(check_read_watch): properly handle WAITING_FOR_MEMORY and
+	AUTHENTICATED cases
+	(unix_handle_watch): after writing, see if the write watch can be
+	removed
+	(unix_do_iteration): assert that write_watch/read_watch are
+	non-NULL rather than testing that they aren't, since they 
+	aren't allowed to be NULL. check_write_watch() at the end so 
+	we add the watch if we did not finish writing (e.g. got EAGAIN)
+
+	* dbus/dbus-transport-protected.h: remove messages_pending call,
+	since it resulted in too much inefficient watch adding/removing; 
+	instead we now require that the transport user does an iteration 
+	after queueing outgoing messages, and after trying the first
+	write() we add a write watch if we got EAGAIN or exceeded our 
+	max bytes to write per iteration setting
+
+	* dbus/dbus-string.c (_dbus_string_validate_signature): add this
+	function
+
+	* dbus/dbus-server-unix.c (unix_finalize): the socket name was
+	freed and then accessed, valgrind flagged this bug, fix it
+
+	* dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken
+	as the last valid field plus 1, where really it is equal to the
+	last valid field. Corrects some message corruption issues.
+
+	* dbus/dbus-mainloop.c: verbosity changes
+
+	* dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM
+	instead of aborting in one of the test codepaths
+
+	* dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that
+	caused not printing the pid ever again if a verbose was missing
+	the newline at the end
+	(_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE
+
+	* dbus/dbus-connection.c: verbosity changes; 
+	(dbus_connection_has_messages_to_send): new function
+	(_dbus_connection_message_sent): no longer call transport->messages_pending
+	(_dbus_connection_send_preallocated_unlocked): do one iteration to
+	try to write() immediately, so we can avoid the write watch. This
+	is the core purpose of this patchset
+	(_dbus_connection_get_dispatch_status_unlocked): if disconnected,
+	dump the outgoing message queue, so nobody will get confused
+	trying to send them or thinking stuff is pending to be sent
+
+	* bus/test.c: verbosity changes
+
+	* bus/driver.c: verbosity/assertion changes
+
+	* bus/dispatch.c: a bunch of little tweaks to get it working again
+	because this patchset changes when/where you need to block.
+
+2004-11-23  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-profile.c: modify to accept a plain_sockets
+	argument in which case it will bench plain sockets instead of
+	libdbus, for comparison purposes.
+
+2004-11-22  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-profile.c (N_CLIENT_THREADS): run multiple
+	threads for more time, so sysprof can get a grip on it.
+
+	* dbus/dbus-string.c (_dbus_string_validate_utf8): remove
+	pointless variable
+
+2004-11-13  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-profile.c: fix this thing up a bit
+
+	* dbus/dbus-message.c (dbus_message_new_empty_header): increase
+	preallocation sizes by a fair bit; not sure if this will be an
+	overall performance win or not, but it does reduce reallocs.
+
+	* dbus/dbus-string.c (set_length, reallocate_for_length): ignore
+	the test hack that forced constant realloc if asserts are
+	disabled, so we can profile sanely. Sprinkle in some
+	_DBUS_UNLIKELY() which are probably pointless, but before I
+	noticed the real performance problem I put them in.
+	(_dbus_string_validate_utf8): micro-optimize this thing a little
+	bit, though callgrind says it didn't help; then special-case
+	ascii, which did help a lot; then be sure we detect nul bytes as
+	invalid, which is a bugfix.
+	(align_length_then_lengthen): add some more _DBUS_UNLIKELY
+	superstition; use memset to nul the padding instead of a manual
+	loop.
+	(_dbus_string_get_length): inline this as a
+	macro; it showed up in the profile because it's used for loop
+	tests and so forth
+
+2004-11-10  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-spawn.c (check_babysit_events): Handle EINTR,
+	for extra paranoia.
+
+2004-11-09  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-string.c (_dbus_string_get_length): New
+	function, writes DBusString to C buffer.
+
+	* dbus/dbus-string.h: Prototype it.
+
+	* dbus/dbus-message.c (dbus_message_type_to_string): New
+	function, converts message type into C string.
+
+	* dbus/dbus-message.h: Prototype it.
+
+	* bus/selinux.c (bus_selinux_check): Take source pid,
+	target pid, and audit data.  Pass audit data to
+	avc_has_perm.
+	(log_audit_callback): New function, appends extra
+	audit information.
+	(bus_selinux_allows_acquire_service): Also take
+	service name, add it to audit data.
+	(bus_selinux_allows_send): Also take message
+	type, interface, method member, error name,
+	and destination, and add them to audit data.
+	(log_cb): Initialize func_audit.
+	
+	* bus/selinux.h (bus_selinux_allows_acquire_service)
+	(bus_selinux_allows_send): Update prototypes 
+
+	* bus/services.c (bus_registry_acquire_service): Pass
+	service name to bus_selinux_allows_acquire_service.
+
+	* bus/bus.c (bus_context_check_security_policy): Pass
+	additional audit data.  Move assignment of dest
+	to its own line.
+
+2004-11-07  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-transport-unix.c (do_authentication): Always
+	initialize auth_completed.
+	
+2004-11-07  Colin Walters  <walters@verbum.org>
+
+	* bus/bus.c (load_config): Break into three
+	separate functions: process_config_first_time_only,
+	process_config_every_time, and process_config_postinit.
+	(process_config_every_time): Move call of
+	bus_registry_set_service_context_table into
+	process_config_postinit.
+	(process_config_postinit): New function, does
+	any processing that needs to happen late
+	in initialization (and also on reload).
+	(bus_context_new): Instead of calling load_config,
+	open config parser here and call process_config_first_time_only
+	and process_config_every_time directly.  Later, after
+	we have forked but before changing UID,
+	invoke bus_selinux_full_init, and then call
+	process_config_postinit.
+	(bus_context_reload_config): As in bus_context_new,
+	load parse file inside here, and call process_config_every_time
+	and process_config_postinit.
+
+	* bus/services.h, bus/services.c
+	(bus_registry_set_service_context_table): Rename
+	from bus_registry_set_sid_table.  Take string hash from config
+	parser, and convert them here into SIDs.
+
+	* bus/config-parser.c (struct BusConfigParser): Have
+	config parser only store a mapping of service->context
+	string.
+	(merge_service_context_hash): New function.
+	(merge_included): Merge context string hashes instead
+	of using bus_selinux_id_table_union.
+	(bus_config_parser_new): Don't use bus_selinux_id_table_new;
+	simply create a new string hash.
+	(bus_config_parser_unref): Unref it.
+	(start_selinux_child): Simply insert strings into hash,
+	don't call bus_selinux_id_table_copy_over.
+
+	* bus/selinux.h, bus/selinux.c (bus_selinux_id_table_union)
+	(bus_selinux_id_table_copy_over): Delete.
+
+2004-11-03  Colin Walters  <walters@verbum.org>
+
+	* bus/selinux.c (bus_selinux_pre_init): Kill some unused
+	variables.
+	
+2004-11-03  Colin Walters  <walters@verbum.org>
+
+	* bus/test-main.c (test_pre_hook): Fix test logic,
+	thanks Joerg Barfurth <Joerg.Barfurth@Sun.COM>.
+
+2004-11-02  Colin Walters  <walters@redhat.com>
+
+	* bus/selinux.c (bus_selinux_init): Split into two functions,
+	bus_selinux_pre_init and bus_selinux_post_init.
+	(bus_selinux_pre_init): Just determine whether SELinux is
+	enabled.
+	(bus_selinux_post_init): Do everything else.
+
+	* bus/main.c (main): Call bus_selinux_pre_init before parsing
+	config file, and bus_selinux_post_init after.  This ensures that
+	we don't lose the policyreload notification thread that
+	bus_selinux_init created before forking previously.
+	
+	* bus/test-main.c (test_pre_hook): Update for split.
+
+2004-10-31  Owen Fraser-Green  <owen@discobabe.net>
+
+	Patch from Johan Fischer <linux@fischaz.com>
+	
+	* mono/doc/Makefile.am (install-data-local): Added directory
+	install for DESTDIR
+
+2004-10-29  Colin Walters  <walters@redhat.com>
+
+	* dbus/dbus-sysdeps.h (_dbus_become_daemon): Also take
+	parameter for fd to write pid to.	
+
+	* dbus/dbus-sysdeps.c (_dbus_become_daemon): Implement it.
+	
+	* bus/bus.c (bus_context_new): Pass print_pid_fd
+	to _dbus_become_daemon (bug #1720)
+
+2004-10-29  Colin Walters  <walters@redhat.com>
+
+	Patch from Ed Catmur <ed@catmur.co.uk>
+
+	* mono/doc/Makefile.am (install-data-local): Handle
+	DESTDIR.
+
+2004-10-29  Colin Walters  <walters@redhat.com>
+
+	* bus/.cvsignore, qt/.cvsignore: Update.
+
+2004-10-29  Colin Walters  <walters@redhat.com>
+
+	Patch from Kristof Vansant <de_lupus@pandora.be>
+
+	* configure.in: Detect Slackware.
+	* bus/Makefile.am (SCRIPT_IN_FILES): Add rc.messagebus.in.
+	* bus/rc.messagebus.in: New file.
+
+2004-10-29  Colin Walters  <walters@redhat.com>
+
+	* tools/dbus-monitor.c (filter_func): Return
+	DBUS_HANDLER_RESULT_HANDLED in filter function
+	for now.  See:
+	http://freedesktop.org/pipermail/dbus/2004-August/001433.html
+
+2004-10-29  Colin Walters  <walters@redhat.com>
+
+	Patch from Matthew Rickard <mjricka@epoch.ncsc.mil>
+
+	* bus/services.c (bus_registry_acquire_service): 
+	Correctly retrieve service name from DBusString
+	for printing.
+
+2004-10-29  Colin Walters  <walters@redhat.com>
+
+	* dbus/dbus-glib.h: Update documentation to not
+	refer to internal APIs.
+
+2004-10-27  Joe Shaw  <joeshaw@novell.com>
+
+	* mono/Arguments.cs (GetDBusTypeConstructor):
+	type.UnderlyingSystemType will return "System.Byte" if you do it
+	on "byte[]", which is not what we want.  So check the type.IsArray
+	property and use System.Array instead.
+
+2004-10-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (fill_user_info): On errors do not free
+	the DBusUserInfo structure since this is passed into the function.
+	This would cause a double free when the function that allocated
+	the structure would try to free it when an error occured.
+
+	* (bus/session.conf.in, bus/Makefile.am, dbus/configure.in):
+	use /usr/share/dbus-1/services instead of /usr/lib/dbus-1.0/services
+	for service activation to avoid 32bit/64bit parallel install issues
+
+2004-10-21  Colin Walters  <walters@verbum.org>
+
+	* AUTHORS: Fix my email address, the @gnu.org one
+	has been bouncing for some time.  Also add J5.
+	
+2004-10-21  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-transport-unix.c (do_authentication): Return
+	authentication status to callers.
+	(unix_handle_watch): If we completed authentication this round,
+	don't do another read.  Instead wait until the next iteration,
+	after we've read any pending data in the auth buffer.
+	(unix_do_iteration): Ditto.
+	(unix_handle_watch): Updated for new do_authentication prototype.
+
+2004-10-18  Colin Walters  <walters@verbum.org>
+
+	* bus/selinux.c (bus_selinux_enabled): Handle
+	--disable-selinux case.
+	
+2004-10-18  Colin Walters  <walters@verbum.org>
+
+	* bus/selinux.h: Add bus_selinux_enabled.
+	
+	* bus/selinux.c (bus_selinux_enabled): Implement it.
+	
+	* bus/config-parser.c (struct include): Add
+	if_selinux_enabled member.
+	(start_busconfig_child): Parse if_selinux_enabled
+	attribute for include.
+	(bus_config_parser_content): Handle it.
+
+	* bus/session.conf.in, bus/system.conf.in: Add
+	inclusion of context mapping to default config files;
+	conditional on SELinux being enabled.
+	
+	* doc/busconfig.dtd: Add to if_selinux_enabled to default DTD.
+	
+	* test/data/invalid-config-files/badselinux-1.conf, 
+	test/data/invalid-config-files/badselinux-2.conf:
+	Test files for bad syntax.
+	
+2004-10-17  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-memory.c (_dbus_initialize_malloc_debug, check_guards)
+	(dbus_malloc, dbus_malloc0, dbus_realloc): Fix up printf
+	format specifier mismatches.
+
+2004-10-07  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-sysdeps.c (_dbus_file_get_contents): fix an incorrect
+	format string.
+
+	* glib/dbus-dbus-gmain.c (dbus_g_bus_get): do not mangle NULL
+	pointer (bug #1540, Leonardo Boiko).
+
+2004-09-28  Jon Trowbridge  <trow@ximian.com>
+
+	* mono/BusDriver.cs: Changed BusDriver struct to remove
+	the ServiceCreated and ServiceDeleted events and replace them
+	with the new ServiceOwnerChanged event.
+
+	* mono/example/BusListener.cs: Added a new example program,
+	which listens for and reports any ServiceOwnerChanged events
+	on the bus driver.
+
+	* mono/example/Makefile.am (DESTDIR): Build changes for the
+	new BusListener.cs example.
+
+2004-09-27  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* bus/signals.c (bus_match_rule_parse): validate the components of
+	match rules (bug #1439).
+
+	* dbus/dbus-bus.c (dbus_bus_add_match): add a missing OOM test.
+
+2004-09-24  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* doc/dbus-specification.xml: document ServiceOwnerChanged
+	signal.
+	
+	* bus/driver.c, bus/driver.h, bus/services.c: Use
+	ServiceOwnerChanged signal instead of ServiceCreated and
+	ServiceDeleted.
+	
+	* bus/dispatch.c: update testcase for the new signal.
+
+2004-09-20  Jon Trowbridge  <trow@ximian.com>
+
+	Patch from Nat Friedman <nat@novell.com>
+
+	* mono/Makefile.am: A number of small build fixes to allow "make
+	distcheck" to succeed.
+
+	* mono/example/Makefile.am: "make distcheck" fixes.
+
+	* mono/AssemblyInfo.cs.in: When signing the assembly, look for the
+	key in @srcdir@.
+
+	* test/Makefile.am: "make distcheck" fixes.
+
+2004-09-17  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-sysdeps.c (_dbus_user_at_console): fix memleak in OOM.
+
+	* doc/busconfig.dtd: update the DTD for the at_console attribute.
+
+	* bus/driver.c (bus_driver_handle_hello): correctly handle Hello
+	messages after the first one (bug #1389).
+	
+	* bus/dispatch.c (check_double_hello_message): add a test case for
+	the double hello message bug.
+	(check_existent_service_activation): fix check of spawning error.
+	
+2004-09-16  David Zeuthen  <david@fubar.dk>
+
+	* python/dbus_bindings.pyx.in: Add support for int64 and uint64
+
+2004-09-12  David Zeuthen  <david@fubar.dk>
+
+	Patch from Kay Sievers <kay.sievers@vrfy.org>
+
+	* bus/bus.c (bus_context_new):
+	* bus/bus.h:
+	* bus/main.c (usage)
+	(main):
+	Add commandline option --nofork to override configuration file
+	setting.
+
+2004-09-09  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-*.h: remove the ; after DBUS_(BEGIN|END)_DECLS. Some C
+	compilers don't like it (bug #974).
+
+2004-09-04  Harald Fernengel  <harry@kdevelop.org>
+
+	* qt/connection.*: Applied patch by Jérôme Lodewyck
+	<lodewyck@clipper.ens.fr> to integrate an existing
+	connection into the Qt eventloop
+
+2004-08-30  Jon Trowbridge  <trow@ximian.com>
+
+	* mono/BusDriver.cs: Added.  This is a class for interacting with
+	the org.freedesktop.DBus service.
+
+	* mono/Message.cs: Added a mechanism to expose the message that is
+	currently being dispatched via the static Message.Current
+	property.  Added Message.Sender and Message.Destination
+	properties.
+
+	* mono/Handler.cs: Expose the dispatched message via
+	Message.Current when handling method calls.
+
+	* mono/Service.cs: Expose the dispatched message via
+	Message.Current when handling signal emissions.
+	
+	* mono/Connection.cs: Bind dbus_bus_get_base_service via the
+	Connection.BaseService property.
+
+2004-08-28  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-userdb.c (_dbus_is_console_user): remove unused variable
+
+        More fixes from Steve Grubb
+	
+	* dbus/dbus-sysdeps.c (_dbus_connect_tcp_socket): fix fd leak
+	(_dbus_listen_tcp_socket): fix fd leak
+
+	* dbus/dbus-spawn.c (read_pid, read_ints): move the "again:" for
+	EINTR to a bit lower in the code
+
+2004-08-26  Jon Trowbridge  <trow@ximian.com>
+
+	* bus/driver.c (bus_driver_handle_service_exists): Respond with
+	TRUE if we are inquiring about the existence of the built-in
+	org.freedesktop.DBus service.
+
+2004-08-25  John Palmieri  <johnp@redhat.com>
+	* bus/config-parser.c:
+	(struct PolicyType): Add POLICY_CONSOLE
+	(struct Element.d.policy): s/gid_or_uid/gid_uid_or_at_console
+	(start_busconfig_child): Sets up console element when
+	<policy at_console=""> is encountered in a policy file
+	(append_rule_from_element): Convert console elements to console
+	rules.
+
+	* bus/policy.c: 
+	(bus_policy_create_client_policy): Add console rules to the client
+	policy based on if the client is at the console
+	(bus_policy_append_console_rule): New function for adding a
+	console rule to a policy
+	(bus_policy_merge): Handle console rule merging
+
+	* dbus/dbus-sysdeps.h: Added the DBUS_CONSOLE_DIR constant
+	where we check for console user files
+	
+	* dbus/dbus-sysdeps.c:
+	(_dbus_file_exists): New function which checks if the given
+	file exists
+	(_dbus_user_at_console): New function which does the system
+	specific process of checking if the user is at the console
+
+	* dbus/dbus-userdb.c:
+	(_dbus_is_console_user): New function converts a UID to user name
+	and then calls the system specific _dbus_user_at_console to 
+	see if the user is at the console and therefor a console user
+
+2004-08-25  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* bus/config-parser.c (set_limit):
+	* bus/dbus-daemon-1.1.in:
+	* test/data/valid-config-files/many-rules.conf: set the
+	max_match_rules_per_connection limt from the config file. 
+
+	* doc/busconfig.dtd: update the DTD.
+
+	* bus/driver.c: remove some unused variables.
+
+2004-08-24  Mikael Hallendal  <micke@imendio.com>
+
+	* dbus/dbus-glib-lowlevel.h: Removed dbus_bus_get_with_g_main since 
+	it's been replaced by dbus_g_bus_get
+
+2004-08-23  Colin Walters  <walters@redhat.com>
+
+	Updated SELinux support from Matthew Rickard <mjricka@epoch.ncsc.mil>
+
+	* bus/selinux.h: Prototype bus_selinux_get_policy_root.
+
+	* bus/selinux.c: Create a thread for policy reload notification.
+	(bus_selinux_get_policy_root): Implement.
+
+	* bus/config-parser.c (start_busconfig_child)
+	(bus_config_parser_content): Support SELinux-root relative
+	inclusion.
+
+	* configure.in <HAVE_SELINUX>: Add -lpthread.
+	
+	* bus/test-main.c (test_pre_hook, test_post_hook): New.
+	(test_post_hook): Move memory checking into here.
+	(test_pre_hook, test_post_hook): Move SELinux checks in
+	here, but conditional on a DBUS_TEST_SELINUX environment
+	variable.  Unfortunately we can't run the SELinux checks
+	as a normal user, since they won't have any permissions
+	for /selinux.  So this will have to be tested manually
+	for now, until we have virtualization for most of
+	libselinux.
+	
+2004-08-23  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_change_identity): add setgroups() to
+	drop supplementary groups, suggested by Steve Grubb
+
+2004-08-20  Colin Walters  <walters@redhat.com>
+
+	* bus/config-parser.c (start_busconfig_child): Remove some unused
+	variables.
+	
+	* bus/selinux.c (bus_selinux_id_table_insert): Avoid compiler
+	warning.
+
+2004-08-17  Joe Shaw  <joeshaw@novell.com>
+
+	* configure.in: If --enable-mono is passed in, if we can't find
+	mono error out.
+
+	* mono/Makefile.am: Use /gacutil to install assemblies into the
+	GAC and not /root.
+
+2004-08-12  Havoc Pennington  <hp@redhat.com>
+
+	* NEWS: update for 0.22
+
+	* configure.in: release 0.22
+
+2004-08-11  Colin Walters  <walters@redhat.com>
+
+	* tools/dbus-send.c (main, usage): Add --reply-timeout
+	argument.
+
+2004-08-10  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* bus/bus.c (process_config_first_time_only): get rid of an unused
+	DBusError that was causing a memoy leak (bug #989).
+
+	* dbus/dbus-keyring.c, dbus/dbus-message.c:
+	fix compilation on Solaris/Forte C (bug #974)
+
+	* bus/main.c (main): plug two minuscule memleaks.
+
+2004-08-10  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-tutorial.xml: add some more info on GLib bindings
+
+2004-08-09  Havoc Pennington  <hp@redhat.com>
+
+	* COPYING: switch to Academic Free License version 2.1 instead of
+	2.0, to resolve complaints about patent termination clause.
+
+2004-07-31  John (J5) Palmieri  <johnp@redhat.com>
+
+	* README: added documentation for the --enable-python 
+	configure switch.
+
+2004-07-31  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* bus/config-parser.c (bus_config_parser_new): fix an invalid
+	_unref in the SELinux support.
+
+	* doc/busconfig.dtd: update DTD for SELinux support.
+
+	* bus/config-loader-libxml.c: fix error handler and parser
+	initialisation/cleanup. OOM test now works with libxml2 HEAD.
+
+	* configure.in: remove the warning about libxml2.
+
+	* dbus/dbus-bus.c: silence doxygen warning.
+
+2004-07-31  Colin Walters  <walters@redhat.com>
+
+	* configure.in: Move #error in SELinux check to its own line.
+
+2004-07-31  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-internals.h (_DBUS_SET_OOM):
+	* bus/utils.h (BUS_SET_OOM): use dbus_error_set_const instead of
+	dbus_error_set.
+
+	* bus/dispatch.c (check_send_exit_to_service): fix the test case,
+	broken by the change in the _SET_OOM macros.
+
+2004-07-31  Colin Walters  <walters@redhat.com>
+
+	* bus/selinux.c <HAVE_SELINUX>: Include utils.h to get
+	BUS_SET_OOM.
+
+2004-07-31  Colin Walters  <walters@redhat.com>
+
+	* configure.in: Use AC_TRY_COMPILE instead of AC_EGREP_HEADER
+	to correctly detect DBUS__ACQUIRE_SVC.  Also add an
+	AC_MSG_CHECKING.
+
+2004-07-24  Havoc Pennington  <hp@redhat.com>
+
+	SELinux support from Matthew Rickard <mjricka@epoch.ncsc.mil>
+
+	* bus/selinux.c, bus/selinux.h: new file encapsulating selinux
+	functionality
+
+	* configure.in: add --enable-selinux
+	
+	* bus/policy.c (bus_policy_merge): add FIXME to a comment
+
+	* bus/main.c (main): initialize and shut down selinux
+
+	* bus/connection.c: store SELinux ID on each connection, to avoid 
+	repeated getting of the string context and converting it into 
+	an ID
+
+	* bus/bus.c (bus_context_get_policy): new accessor, though it
+	isn't used
+	(bus_context_check_security_policy): check whether the security
+	context of sender connection can send to the security context of
+	recipient connection
+
+	* bus/config-parser.c: add parsing for <selinux> and <associate>
+	
+	* dbus/dbus-transport.c (_dbus_transport_get_unix_fd): to
+	implement dbus_connection_get_unix_fd()
+
+	* dbus/dbus-connection.c (dbus_connection_get_unix_fd): new
+	function, used by the selinux stuff
+	
+2004-07-29  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* bus/config-loader-libxml.c: complete the implementation of
+	libxml backend for config file loader. Doesn't work with full OOM
+	test yet. 
+	
+	* configure.in: change error when selecting libxml into a warning.
+	
+	* test/data/invalid-config-files: add two non-well-formed XML
+	files. 
+	
+	* glib/Makefile.am: libdbus_gtool always uses expat, not libxml.
+	
+	* dbus/dbus-transport-unix.c (unix_handle_watch): do not
+	disconnect in case of DBUS_WATCH_HANGUP, several do_reading() may
+	be necessary to read all the buffer. (bug #894)
+
+	* bus/activation.c (bus_activation_activate_service): fix a
+	potential assertion failure (bug #896). Small optimization in the
+	case of auto-activation messages.
+
+	* dbus/dbus-message.c (verify_test_message, _dbus_message_test):
+	add test case for byte-through-vararg bug (#901). patch by Kimmo
+	Hämäläinen. 
+
+2004-07-28  Anders Carlsson  <andersca@gnome.org>
+
+	* python/dbus.py:
+	* python/dbus_bindings.pyx.in:
+	Add dbus.init_gthreads (), allow emit_signal to pass
+	arguments to the signal.
+	
+2004-07-24  Havoc Pennington  <hp@redhat.com>
+
+	* AUTHORS: add some people, not really comprehensively, let me
+	know if I missed you
+
+2004-07-24  Havoc Pennington  <hp@redhat.com>
+
+	* Makefile.am (DIST_SUBDIRS): add DIST_SUBDIRS, problem solved by
+	Owen
+
+	* test/Makefile.am (DIST_SUBDIRS): here also
+
+2004-07-22  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-sysdeps.c (fill_user_info): fix inexistent label name,
+	breaking build on Solaris, reported by Farhad Saberi on the ML.
+
+	* dbus/dbus-message.c (dbus_message_append_args_valist): fix the
+	va_arg invocation to account for integer promotion in the case of
+	DBUS_TYPE_BYTE (unsigned char is promoted to int). (bug #901)
+
+	* bus/services.c (bus_service_remove_owner): fix bug #902, use
+	_dbus_list_get_first_link, not _dbus_list_get_first.
+
+	* dbus/dbus-bus.c (dbus_bus_service_exists): plug a memory leak.
+
+	* dbus/dbus-object-tree.c (free_subtree_recurse): always null
+	handler functions so that the asserts in _dbus_object_subtree_unref
+	do not fail.
+
+	* dbus/dbus-transport-unix.c (do_reading):
+	_dbus_transport_queue_messages return value is of type
+	dbus_bool_t, not DBusDispatchStatus.
+	
+2004-07-19  David Zeuthen  <david@fubar.dk>
+
+	* dbus/dbus-protocol.h: Add DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN
+
+	* bus/dispatch.c:
+	(check_get_connection_unix_user): Debug says GetProperty; but the
+	method is called GetConnectionUnixUser
+	(check_get_connection_unix_process_id): New function
+	(bus_dispatch_test): Actually call check_get_connection_unix_user();
+	also call check_get_connection_unix_process_id()
+	
+	* bus/driver.c:
+	(bus_driver_handle_get_connection_unix_process_id): New function,
+	handles GetConnectionUnixProcessID on the org.freedesktop.DBus
+	interface
+	
+	* dbus/dbus-auth.c:
+	(handle_server_data_external_mech): Set pid from the credentials
+	obtained from the socket
+	
+	* dbus/dbus-connection.c:
+	(dbus_connection_get_unix_process_id): New function
+	
+	* dbus/dbus-connection.h: 
+	Add prototype for dbus_connection_get_unix_process_id
+	
+	* dbus/dbus-transport.c:
+	(_dbus_transport_get_unix_process_id): New function
+	
+	* dbus/dbus-transport.h:
+	Add prototype for _dbus_transport_get_unix_process_id
+	
+2004-07-19  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-message.c: Message counter fix, patch by Christian
+	Hammond <chipx86@gnupdate.org>
+
+2004-07-18  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus.py:
+	* python/dbus_bindings.pyx.in:
+	* python/tests/test-client.py:
+
+	Add dbus.ByteArray and dbus_bindings.ByteArray
+	types so that byte streams can be passed back.
+
+	Give jdahlin the heaps of credit that are so
+	rightfully his.
+	
+2004-07-12  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus.py:
+
+	Add message argument to the default object_method_handler
+	function.
+	
+	* python/dbus_bindings.pyx.in:
+
+	Automatically return NIL when passed an empty list
+	(we can't pass back a list since lists are typed
+	and we don't have any idea what type the the client
+	intended the list to be... :-( )
+	
+2004-07-10  Seth Nickell  <seth@gnome.org>
+
+	* python/examples/Makefile.am:
+
+	Fix distcheck breakage caused by new examples.
+
+2004-07-10  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus.py:
+
+	Add "message" argument to service-side dbus.Object
+	methods. This will break existing services written
+	using the python bindings, but will allow extraction
+	of all the message information (e.g. who its from).
+
+	Add improved "object oriented" signal handling/emission.
+	
+	* python/examples/example-service.py:
+
+	Nix this example.
+	
+	* python/examples/example-signal-emitter.py:
+	* python/examples/example-signal-recipient.py:
+
+	Two new examples that show how to emit and receive
+	signals using the new APIs.
+	
+	* python/examples/example-signals.py:
+	* python/examples/gconf-proxy-service.py:
+	* python/examples/gconf-proxy-service2.py:
+
+	Add "message" argument to service methods.
+
+2004-06-28  Kay Sievers <kay.sievers@vrfy.org>
+
+	* bus/driver.c (bus_driver_handle_get_connection_unix_user)
+	* dbus/bus.c (dbus_bus_get_unix_user)
+	* doc/dbus-specification.xml: implement GetConnectionUnixUser
+	method of org.freedesktop.DBus interface.
+
+	* bus/dispatch.c: test case
+
+2004-06-23  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/Makefile.am: switched include directory from glib/ to dbus/
+	since dbus-glib.h moved
+ 
+2004-06-22  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* configure.in: prevent building the gcj stuff and libxml loader
+	since they are broken.
+
+2004-06-20  Havoc Pennington  <hp@redhat.com>
+
+        * dbus/dbus-glib-error-enum.h: autogenerate the GError enum 
+	codes from the dbus error names
+	
+        * glib/dbus-glib.h: move to subdir dbus/ since it's included 
+	as dbus/dbus-glib.h and that breakage is now visible due to 
+	including dbus/dbus-glib.h in dbus-glib-lowlevel.h
+	
+	* glib/dbus-glib.h: s/gproxy/g_proxy/
+
+	* dbus/dbus-shared.h: new header to hold stuff shared with
+	binding APIs
+	
+	* dbus/dbus-protocol.h (DBUS_ERROR_*): move errors here rather
+	than dbus-errors.h
+
+	* glib/dbus-glib.h (dbus_set_g_error): move to
+	dbus-glib-lowlevel.h
+
+	* glib/dbus-glib.h: remove dbus/dbus.h from here; change a bunch
+	of stuff to enable this
+
+	* dbus/dbus-glib-lowlevel.h: put dbus/dbus.h here
+
+	* a bunch of other changes with the same basic "separate glib 
+	bindings from dbus.h" theme
+	
+2004-06-10  Owen Fraser-Green  <owen@discobabe.net>
+
+	* dbus-sharp.pc.in: Removed glib-sharp inclusion in Libs.
+
+	* python/examples/Makefile.am: Fixed typo in EXTRA_DIST.
+
+2004-06-09  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* bus/driver.c, dbus/dbus-bus.c: use BOOLEAN instead of UINT32 for
+	the reply value of the ServiceExists message.
+
+2004-06-07  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus_bindings.pyx.in: No longer need to parse path
+	elements and pass them as arrays of strings.  The C API now
+	accepts plain path strings.
+	(_build_parsed_path): removed 
+
+2004-06-07  Havoc Pennington  <hp@redhat.com>
+
+	* doc/TODO: remove auto-activation item since it's done; sort
+	items by importance/milestone
+
+2004-06-07  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message-builder.c (_dbus_message_data_load): append
+	random signature when using REQUIRED_FIELDS (this hack won't work
+	in the long term)
+
+	* dbus/dbus-message.c: change the signature to be a header field,
+	instead of message->signature special-case string. Incremental
+	step forward. Then we can fix up code to send the signature in the
+	message, then fix up code to validate said signature, then fix up
+	code to not put the typecodes inline, etc.
+	(load_one_message): don't make up the signature after the fact
+	(decode_header_data): require signature field for the known
+	message types
+
+	* dbus/dbus-marshal.c (_dbus_marshal_string_len): new
+
+	* dbus/dbus-protocol.h: add DBUS_HEADER_FIELD_SIGNATURE
+
+2004-06-07  Owen Fraser-Green  <owen@discobabe.net>
+
+	* mono/DBusType/ObjectPath.cs: Renamed PathName argument to Path
+
+	* mono/Handler.cs: Updated to follow new path argument for
+	(un-)registering objects.
+
+	* mono/example/Makefile.am:
+	* mono/Makefile.am:
+	* configure.in: Bumped required version for mono and use new -pkg
+	syntax for deps
+
+2004-06-05  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-connection.h, dbus/dbus-connection.c: have object path
+	registration functions take the path argument as char* instead of
+	char**.
+
+	* dbus/dbus-marshal.h, dbus/dbus-marshal.c (_dbus_decompose_path):
+	split off the path decompostion part of
+	_dbus_demarshal_object_path. Some misc. fixes to silence compiler
+	warnings. 
+
+	* glib/dbus-gobject.c, test/test-service.c: update accordingly.
+	
+2004-06-02  Kristian Høgsberg  <krh@redhat.com>
+ 
+	* dbus/dbus-auth.c: Rewrite auth protocol handling to use a state
+	machine approach.  A state is implemented as a function that
+	handles incoming events as specified for that state.
+	
+	* doc/dbus-specification.xml: Update auth protocol state machine
+	specification to match implementation.  Remove some leftover
+	base64 examples.
+
+2004-06-02  Kristian Høgsberg  <krh@redhat.com>
+
+	* glib/dbus-gproxy.c, glib/dbus-gmain.c, dbus/dbus-string.c,
+	dbus/dbus-object-tree.c, dbus/dbus-message.c: add comments to
+	quiet doxygen.
+
+	* Doxyfile.in: remove deprecated options.
+
+	* dbus/dbus-message-handler.c, dbus/dbus-message-handler.h,
+	glib/test-thread.h, glib/test-thread-client.c,
+	glib/test-thread-server.c, glib/test-profile.c,
+	glib/test-dbus-glib.c: remove these unused files.
+
+2004-06-01  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-object-tree.c
+	(_dbus_object_tree_dispatch_and_unlock): fix dispatch for
+	non-fallback handlers (bug #684).
+	(_dbus_object_subtree_new): initialize invoke_as_fallback field.
+	(find_subtree_recurse): report wether the returned subtree is an
+	exact match or a "fallback" match higher up in the tree.
+	(object_tree_test_iteration): update test case.
+
+2004-06-01  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus_bindings.pyx.in:
+	* python/tests/test-client.py:
+
+	Round off basic type support. Add dicts (yay!), and 
+	remaining array types.
+
+	Make MessageIter more general so it works for dicts too.
+
+	Mark all loop variables as C integers.
+	
+2004-05-31  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gidl.c (method_info_add_arg): keep args sorted with
+	"in" before "out"
+
+	* glib/dbus-gobject.c (dbus_type_to_string): move to dbus-gutils.c
+
+	* glib/dbus-glib-tool.c (main): set up to have a --self-test
+	option that runs the tests, and start filling in some code
+	including for starters just dumping the interfaces to stdout
+
+	* glib/Makefile.am (INCLUDES): define DBUS_LOCALEDIR
+
+	* test/data/valid-introspection-files/lots-of-types.xml: test of
+	an example introspection file
+
+	* glib/dbus-gparser.c (parser_check_doctype): doctype should be
+	"node" (I think...)
+
+2004-05-31  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus_bindings.pyx.in:
+	* python/tests/test-client.py:
+
+	Test Suite: 1
+	Python Bindings: 0
+
+	Fix string array memory trashing bug... oops...
+
+2004-05-30  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus.py:
+
+	Add a nicer-but-less-flexible alternate API for handling 
+	calls to virtual objects in dbus.ObjectTree.
+
+	Screw up the argument order to the dbus.Object constructor
+	for consistency with dbus.ObjectTree (and to make dbus_methods
+	optional for future extension)
+	
+	* python/examples/Makefile.am:
+	* python/examples/gconf-proxy-service.py:
+	* python/examples/gconf-proxy-service2.py:
+
+	Alternate implementation of gconf-proxy-service using the
+	nicer dbus.ObjectTree API.
+	
+	* python/examples/example-service.py:
+	* python/tests/test-server.py
+
+	Reverse the argument order to deal with dbus.Object constructor
+	changes.
+	
+2004-05-30  Seth Nickell  <seth@gnome.org>
+
+	* python/examples/example-client.py:
+	* python/examples/example-service.py:
+
+	Take it back. Lists seem to work but they're broken
+	in the test suite. Make the base examples use
+	lists (works fine).
+
+2004-05-30  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus_bindings.pyx.in:
+	* python/tests/test-client.py:
+
+	Add some more tests and fix errors that crop up.
+	Unfortunately, currently it seems like marshalling
+	and unmarshalling of lists is completely broken :-(
+
+2004-05-30  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus_bindings.pyx.in:
+
+	Add support for ObjectPath type.
+
+	* python/dbus.py:
+
+	Refactor message handling code to a common function.
+	
+	* python/tests/test-client.py:
+	* python/tests/test-server.py:
+
+	Add tests that check to make sure values of all types
+	can be echoed from a service w/o mangling.
+	
+2004-05-29  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus.py:
+
+	Add ObjectTree class which allows implementation
+	of trees of "virtual" objects. Basically the python
+	wrapper for "register_fallback".
+	
+	* python/examples/Makefile.am
+	* python/examples/gconf-proxy-client.py:
+	* python/examples/gconf-proxy-service.py:
+
+	Implement a simple GConf proxy service that supports
+	get/set on string and int GConf keys using the ObjectTree.
+	
+2004-05-29  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus.py:
+	* python/examples/example-client.py:
+	* python/examples/example-service.py:
+	* python/examples/list-system-services.py:
+
+	Add SessionBus, SystemBus and ActivationBus classes
+	so you don't need to know the special little BUS_TYPE
+	flag.
+	
+2004-05-29  Havoc Pennington  <hp@redhat.com>
+
+	* bus/config-parser.c (process_test_valid_subdir): temporarily
+	stop testing config parser OOM handling, since expat has issues
+	http://freedesktop.org/pipermail/dbus/2004-May/001153.html
+
+	* bus/dbus-daemon-1.1.in: change requested_reply to
+	send_requested_reply/receive_requested_reply so we can send the
+	replies, not just receive them.
+
+	* bus/config-parser.c: parse the new
+	send_requested_reply/receive_requested_reply
+
+	* bus/policy.c (bus_client_policy_check_can_send): add
+	requested_reply argument and use it
+
+	* bus/bus.c (bus_context_check_security_policy): pass through
+	requested_reply status to message send check
+
+	* bus/system.conf.in: adapt to requested_reply change
+	
+2004-05-28  Havoc Pennington  <hp@redhat.com>
+
+	* test/glib/test-service-glib.c (main): remove unused variable
+
+	* glib/dbus-gidl.c (base_info_ref): fix a silly compiler warning
+
+	* dbus/dbus-auth.h (enum): remove AUTHENTICATED_WITH_UNUSED_BYTES
+	from the enum, no longer in use.
+
+	* dbus/dbus-sysdeps.h: include config.h so DBUS_VA_COPY actually
+	works right.
+
+	* dbus/dbus-message.c: add various _dbus_return_val_if_fail for
+	whether error_name passed in is a valid error name.
+
+2004-05-28  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-message.c (dbus_message_get_args): Added support for
+	OBJECT_PATH and OBJECT_PATH_ARRAY
+
+2004-05-28  Seth Nickell  <seth@gnome.org>
+
+	* python/examples/Makefile.am:
+
+	Forget to add Makefile.am. Do not pass go.
+
+2004-05-28  Michael Meeks  <michael@ximian.com>
+
+	* glib/dbus-gvalue.c (dbus_gvalue_marshal, dbus_gvalue_demarshal): 
+	fix no int64 case.
+
+	* dbus/dbus-string.c (_dbus_string_parse_basic_type): impl.
+
+	* dbus/dbus-message.c (_dbus_message_iter_get_basic_type),
+	(_dbus_message_iter_get_basic_type_array): impl.
+	drastically simplify ~all relevant _get methods to use these.
+	(_dbus_message_iter_append_basic_array),
+	(dbus_message_iter_append_basic): impl
+	drastically simplify ~all relevant _append methods to use these.
+
+	* dbus/dbus-message-builder.c (parse_basic_type) 
+	(parse_basic_array, lookup_basic_type): impl.
+	(_dbus_message_data_load): prune scads of duplicate /
+	cut & paste coding.
+
+	* dbus/dbus-marshal.c (_dbus_demarshal_basic_type_array) 
+	(_dbus_demarshal_basic_type): implement,
+	(demarshal_and_validate_len/arg): beef up debug.
+	(_dbus_marshal_basic_type, _dbus_marshal_basic_type_array): impl.
+
+2004-05-27  Seth Nickell  <seth@gnome.org>
+
+	* configure.in:
+	* python/Makefile.am:
+
+	Include the example python apps in the tarball.
+	
+	* python/examples/list-system-services.py
+
+	Add a python new example that fetches the list of services
+	from the system bus.
+	
+2004-05-27  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus.py:
+	* python/dbus_bindings.pyx.in:
+
+	Fix failure to notify that a signal was not handled,
+	resulted in hung functions.
+	
+2004-05-25  Colin Walters  <walters@redhat.com>
+
+	* tools/dbus-monitor.c (main): Monitor all types of messages.
+
+2004-05-23  Owen Fraser-Green  <owen@discobabe.net>
+
+	* mono/Handler.cs, mono/Service.cs: Added UnregisterObject method
+	which unregisters the object path and disposes the handler.
+
+2004-05-23  Kristian Høgsberg  <krh@redhat.com>
+ 
+        Patch from Timo Teräs <ext-timo.teras@nokia.com> (#614):
+         
+	* dbus/dbus-message.c (dbus_message_iter_get_args_valist): Swap
+        operands to && so we call dbus_message_iter_next () for the last
+        argument also.
+
+2004-05-21  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-object-tree.c
+	(_dbus_object_tree_list_registered_unlock, lookup_subtree): return
+	children even if the requested path isn't registered.
+	(object_tree_test_iteration): test object_tree_list_registered.
+
+	* configure.in: undefine HAVE_ABSTRACT_SOCKETS instead of defining
+	it to 0.
+	
+2004-05-20  Kristian Høgsberg  <krh@redhat.com>
+
+	* doc/TODO: Remove resolved items.
+
+	* bus/expirelist.h (struct BusExpireList): remove unused n_items
+	field.
+	
+	* bus/connection.c (bus_connections_expect_reply): Enforce the
+	per-connection limit on pending replies.
+	
+	Patch from Jon Trowbridge <trow@ximian.com>:
+ 
+ 	* bus/main.c (setup_reload_pipe): Added.  Creates a pipe and sets
+ 	up a watch that triggers a config reload when one end of the pipe
+ 	becomes readable.
+ 	(signal_handler): Instead of doing the config reload in our SIGHUP
+ 	handler, just write to the reload pipe and let the associated
+ 	watch handle the reload when control returns to the main loop.
+ 
+ 	* bus/driver.c (bus_driver_handle_reload_config): Added.
+ 	Implements a ReloadConfig method for requesting a configuration
+ 	file reload via the bus driver.
+ 
+2004-05-19  Owen Fraser-Green  <owen@discobabe.net>
+
+	* HACKING: Updated release instructions concerning the wiki page.
+
+2004-05-18  Kristian Høgsberg  <krh@redhat.com>
+
+ 	* dbus/dbus-auth.c (client_try_next_mechanism): Remove logic to
+	filter against auth->allowed_mechs; we only add allowed mechs in
+	record_mechanisms().
+ 
+ 	* dbus/dbus-auth-script.c (_dbus_auth_script_run): Add an
+	ALLOWED_MECHS to auth-script format so we can set the list of
+	allowed mechanisms.
+ 
+ 	* data/auth/client-out-of-mechanisms.auth-script: New test to
+	check client disconnects when it is out of mechanisms to try.
+ 
+ 	* dbus/dbus-auth.c (process_command): Remove check for lines
+	longer that 1 MB; we only buffer up maximum 16 kB.
+ 
+ 	* dbus/dbus-transport.c, dbus/dbus-transport-unix.c,
+	dbus/dbus-auth-script.c, dbus/dbus-auth.c, dbus/dbus-auth.h:
+	Remove auth state AUTHENTICATED_WITH_UNUSED_BYTES, instead always
+	assume there might be unused bytes.
+ 
+ 	* dbus/dbus-auth.c (_dbus_auth_do_work): Remove check for
+	client-out-of-mechs, it is handled in process_reject(). Move check
+	for max failures to send_rejected(), as it's a server-only thing.
+
+	* dbus/dbus-auth.c: Factor out protocol reply code into functions
+	send_auth(), send_data(), send_rejected(), send_error(),
+	send_ok(), send_begin() and send_cancel().
+
+2004-05-17  Kristian Høgsberg  <krh@redhat.com>
+
+	Remove base64 encoding, replace with hex encoding. Original patch
+	from trow@ximian.com, added error handling.
+
+	* dbus/dbus-string.c (_dbus_string_base64_encode)
+	(_dbus_string_base64_decode): Remove.
+	(_dbus_string_hex_decode): Add end_return argument so we can
+	distinguish between OOM and invalid hex encoding.
+	(_dbus_string_test): Remove base64 tests and add test case for
+	invalid hex.
+
+	* dbus/dbus-keyring.c, dbus/dbus-auth-script.c, dbus/dbus-auth.c:
+	Replace base64 with hex.
+
+	* test/data/auth/invalid-hex-encoding.auth-script: New test case
+	for invalid hex encoded data in auth protocol.
+
+2004-05-17  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-connection.c (check_for_reply_unlocked): plug a memory
+	leak.
+
+2004-05-15  Owen Fraser-Green  <owen@discobabe.net>
+
+	* mono/dbus-sharp.dll.config.in: Added for GAC
+	* mono/dbus-sharp.snk: Added for GAC
+	* mono/Assembly.cs.in: Added for GAC
+	* mono/Makefile.am: Changes for GAC installation	
+	* configure.in: Added refs for dbus-sharp.dll.config.in and
+	Assembly.cs.in. More fixes for mono testing
+	* mono/example/Makefile.am: Changed var to CSC
+	* Makefile.am: Changed flag name to DBUS_USE_CSC
+
+2004-05-15  Owen Fraser-Green  <owen@discobabe.net>
+
+	* mono/Makefile.am: Added SUBDIRS for docs. Changed SUBDIRS order
+	* mono/doc/*: Added documentation framework
+	* configure.in: Added monodoc check
+	* README: Added description of mono configure flags
+
+2004-05-11  John (J5) Palmieri  <johnp@redhat.com>:
+
+	* doc/dbus-specification.xml: Added a "Required" column to the 
+	header fields table and changed the "zero or more" verbage in
+	the above paragraph to read "The header must contain the required 
+	named header fields and zero or more of the optional named header 
+	fields".
+	* test/data/invalid-messages/*.message: Added the required PATH 
+	named header field to the tests so that they don't fail on 
+	'Missing path field'
+
+2004-05-07  John (J5) Palmieri  <johnp@redhat.com>
+
+	* python/dbus-bindings.pyx.in: Stopped the bindings from trashing
+	the stack by implicitly defining variable and parameter types and
+	removing the hack of defining C pointers as python objects and later
+	casting them.
+
+2004-05-02  Owen Fraser-Green  <owen@discobabe.net>
+
+	* mono/Makefile.am: Removed test-dbus-sharp.exe from all target
+
+2004-05-01  Owen Fraser-Green  <owen@discobabe.net>
+
+	* mono/DBusType/Dict.cs: Handle empty dicts
+	* mono/DBusType/Array.cs: Handle empty arrays
+	* mono/Arguments.cs: Handle empty arguments
+
+2004-04-30  Owen Fraser-Green  <owen@discobabe.net>
+
+	* dbus-sharp.pc.in: Modified to include include Libs and Requires
+	field
+
+2004-04-25  Kristian Høgsberg  <krh@redhat.com>
+
+	* test/data/valid-messages/standard-*.message: Update message
+	test scripts to new header field names.
+
+2004-04-22  John (J5) Palmieri  <johnp@redhat.com>
+
+	* test/break-loader.c (randomly_do_n_things): tracked down buffer
+	overflow to times_we_did_each_thing array which would chop off the
+	first character of the failure_dir string. Increased the size of
+	the array to 7 to reflect the number of random mutation functions
+	we have.
+
+2004-04-21  Kristian Høgsberg  <krh@redhat.com>
+
+	* dbus/dbus-server-unix.c (unix_finalize): Don't unref
+	unix_server->watch here, it is unreffed in disconnect.
+	(_dbus_server_new_for_tcp_socket): convert NULL host to
+	"localhost" here so we don't append NULL to address.
+	
+	* dbus/dbus-server.c (_dbus_server_test): Add test case for
+	various addresses, including tcp with no explicit host.
+
+2004-04-21  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-message.c (decode_header_data, decode_string_field):
+	fix incorrect setting of .name_offset in the HeaderField (it was
+	off by two bytes, positioned right after the name and typecode)
+
+	* bus/bus.c (bus_context_new, bus_context_unref): test before
+	calling dbus_server_free_data_slot and _dbus_user_database_unref
+	in case of an error.
+
+	* tools/Makefile.am: add $(DBUS_GLIB_TOOL_LIBS), xml libs needed
+	by libdbus-gtool.
+
+2004-04-19  Kristian Høgsberg  <krh@redhat.com>
+
+	* dbus/dbus-transport-unix.c (unix_do_iteration): Rewrite to use
+	_dbus_poll() instead of select().
+
+2004-04-15  Jon Trowbridge  <trow@ximian.com>
+
+	* bus/main.c (signal_handler): Reload the configuration files
+	on SIGHUP.
+	(main): Set up our SIGHUP handler.
+
+	* bus/bus.c (struct BusContext): Store the config file, user and
+	fork flag in the BusContext.
+	(process_config_first_time_only): Added.  Contains the code
+	(previously in bus_context_new) for setting up the BusContext from
+	the BusConfigParser that should only be run the first time the
+	config files are read.
+	(process_config_every_time): Added.  Contains the code (previously
+	in bus_context_new) for setting up the BusContext from the
+	BusConfigParser that should be run every time the config files are
+	read.
+	(load_config): Added.  Builds a BusConfigParser from the config
+	files and passes the resulting structure off to
+	process_config_first_time_only (assuming this is the first time)
+	and process_config_every_time.
+	(bus_context_new): All of the config-related code has been moved
+	to process_config_first_time_only and process_config_every_time.
+	Now this function just does the non-config-related initializations
+	and calls load_config.
+	(bus_context_reload_config): Added.
+
+2004-04-15  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* bus/driver.c (bus_driver_handle_get_service_owner):
+	implement a GetServiceOwner method.
+	* doc/dbus-specification.xml: document it.
+	* dbus/dbus-errors.h: add a 'ServiceHasNoOwner' error.
+	
+	* glib/dbus-gproxy.c (dbus_gproxy_new_for_service_owner):
+	implement, using the bus GetServiceOwner method.
+
+	* test/glib/test-dbus-glib.c:
+	use dbus_gproxy_new_for_service_owner so that we can receive the
+	signal. 
+
+2004-04-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-internals.c, dbus/dbus-message-builder.c,
+	dbus/dbus-message.c, dbus/dbus-protocol.h
+	(DBUS_HEADER_FIELD_SERVICE): renamed DBUS_HEADER_FIELD_DESTINATION
+
+	* dbus/dbus-internals.c, dbus/dbus-message-builder.c,
+	dbus/dbus-message.c, dbus/dbus-protocol.h
+	(DBUS_HEADER_FIELD_SENDER_SERVICE): renamed DBUS_HEADER_FIELD_SENDER
+
+	* dbus/dbus-internals.c (_dbus_header_field_to_string):
+	DBUS_HEADER_FIELD_DESTINATION resolves to "destination"
+	DBUS_HEADER_FIELD_SENDER resolves to "sender"
+
+	* doc/dbus-specification.xml (Header Fields Table):
+	s/SERVICE/DESTINATION
+	s/SENDER_SERVICE/SENDER
+
+
+2004-04-14  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* test/glib/test-dbus-glib.c (timed_exit): fail the test after
+	a few seconds.
+
+2004-04-13  Michael Meeks  <michael@ximian.com>
+
+	* glib/dbus-gobject.c (handle_introspect): split out
+	(introspect_properties): this.
+	(handle_introspect): implement this.
+
+	* test/glib/Makefile.am: use the absolute path so the bus
+	daemon's chdir ("/") doesn't kill us dead.
+
+	* configure.in: subst ABSOLUTE_TOP_BUILDDIR
+
+2004-04-12  Jon Trowbridge  <trow@ximian.com>
+
+	* bus/config-parser.c (struct BusConfigParser): Added
+	included_files field.
+	(seen_include): Added.  Checks whether or not a file has already
+	been included by any parent BusConfigParser.
+	(bus_config_parser_new): Copy the parent's included_files.
+	(include_file): Track which files have been included, and fail on
+	circular inclusions.
+	(process_test_valid_subdir): Changed printf to report if we are
+	testing valid or invalid conf files.
+	(all_are_equiv): Changed printf to be a bit clearer about
+	what we are actually doing.
+	(bus_config_parser_test): Test invalid configuration files.
+
+2004-04-09  Jon Trowbridge  <trow@ximian.com>
+
+	* bus/config-parser.c (bus_config_parser_new): Added a 'parent'
+	argument.  If non-null, the newly-constructed BusConfigParser will
+	be initialized with the parent's BusLimits instead of the default
+	values.
+	(include_file): When including a config file, pass in
+	the current parser as the parent and then copy the BusLimits
+	from the included BusConfigParser pack to the current parser.
+	(process_test_valid_subdir): Renamed from process_test_subdir.
+	(process_test_equiv_subdir): Added.  Walks through a directory,
+	descending into each subdirectory and loading the config files
+	it finds there.  If any subdirectory contains two config files
+	that don't produce identical BusConfigParser structs, fail.
+	For now, the BusConfigParser's BusPolicies are not compared.
+	(bus_config_parser_test): Call both process_test_valid_subdir and
+	process_test_equiv_subdir.
+
+	* bus/config-loader-libxml.c (bus_config_load): Take a parent
+	argument and pass it along to the call to bus_config_parser_new.
+	Also made a few small changes to allow this code to compile.
+
+	* bus/config-loader-expat.c (bus_config_load): Take a parent
+	argument and pass it along to the call to bus_config_parser_new.
+
+	* bus/bus.c (bus_context_new): Load the config file
+	with a NULL parent argument.
+
+2004-03-29  Michael Meeks  <michael@ximian.com>
+
+	* glib/dbus-gobject.c (introspect_properties): split
+	out, fix mangled 'while' flow control.
+	(introspect_signals): implement.
+	(handle_introspect): update.
+
+2004-03-29  Michael Meeks  <michael@ximian.com>
+
+	* glib/dbus-gobject.c (set_object_property): split out / 
+	re-work, use the property type, and not the message type(!)
+	(get_object_property): ditto.
+
+        * glib/dbus-gvalue.c (dbus_gvalue_demarshal),
+	(dbus_gvalue_marshal): make this code re-usable, needed
+	for signals too, also on both proxy and server side.
+	Re-write for more efficiency / readability.
+
+2004-03-29  Michael Meeks  <michael@ximian.com>
+
+	* dbus/dbus-message.c
+	(dbus_message_new_error_printf): impl.
+
+	* dbus/dbus-connection.c
+	(dbus_connection_unregister_object_path): fix warning.
+
+	* configure.in: fix no-mono-installed situation.
+
+2004-03-27  Havoc Pennington  <hp@redhat.com>
+
+	Patch from Timo Teräs:
+	
+	* tools/dbus-send.c (main): if --print-reply, assume type is
+	method call; support boolean type args
+	
+	* dbus/dbus-connection.c (dbus_connection_send_with_reply): fix a
+	bunch of memleak and logic bugs
+	
+2004-03-23  Owen Fraser-Green  <owen@discobabe.net>
+
+        * mono/Arguments.cs:
+	* mono/Introspector.cs:
+	* mono/Handler.cs:
+	* mono/InterfaceProxy.cs:
+	* mono/Message.cs
+	* mono/ProxyBuilder.cs:
+	* mono/Service.cs:
+	Added InterfaceProxy class to avoid building proxies for every
+	object.
+
+	* dbus-message.h:
+	* dbus-message.c (dbus_message_append_args_valist)
+	(dbus_message_iter_get_object_path)
+	(dbus_message_iter_get_object_path_array)
+	(dbus_message_iter_append_object_path)
+	(dbus_message_iter_append_object_path_array):
+	Added object_path iter functions to handle OBJECT_PATH arguments
+	
+2004-03-23  Owen Fraser-Green  <owen@discobabe.net>
+
+	First checkin of mono bindings.
+	* configure.in:
+	* Makefile.am:
+	Build stuff for the bindings
+	* dbus-sharp.pc.in: Added for pkgconfig
+	
+2004-03-21  Havoc Pennington  <hp@redhat.com>
+
+	* test/test-service.c (main): remove debug spew
+
+2004-03-21  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-marshal.c (_dbus_marshal_validate_arg): accept empty
+	arrays
+
+	* dbus/dbus-message.h, bus/dbus-message.c (dbus_message_iter_init)
+	(dbus_message_iter_init_array_iterator)
+	(dbus_message_iter_init_dict_iterator): return a dbus_bool_t to
+	indicate whether the iterator is empty
+
+	* dbus/dbus-pending-call.c, dbus/dbus-server.c: silence compiler
+	warnings
+
+2004-03-19  Havoc Pennington  <hp@redhat.com>
+
+	* NEWS: 0.21 updates
+
+	* configure.in: 0.21
+
+	* doc/Makefile.am: add all XMLTO usage to DBUS_XML_DOCS_ENABLED
+	
+	* python/Makefile.am: change to avoid dist of dbus_bindings.c so
+	you don't need pyrex to make dist
+
+	* qt/Makefile.am (libdbus_qt_1_la_SOURCES): add integrator.h to
+	sources; run moc
+	
+2004-03-18  Richard Hult  <richard@imendio.com>
+
+	* dbus/dbus-message.c (dbus_message_get_auto_activation) 
+	(dbus_message_set_auto_activation): Add doxygen docs.
+
+2004-03-16  Richard Hult  <richard@imendio.com>
+
+	* bus/activation.c: (bus_activation_service_created),
+	(bus_activation_send_pending_auto_activation_messages),
+	(bus_activation_activate_service):
+	* bus/activation.h:
+	* bus/dispatch.c: (bus_dispatch),
+	(check_nonexistent_service_auto_activation),
+	(check_service_auto_activated),
+	(check_segfault_service_auto_activation),
+	(check_existent_service_auto_activation), (bus_dispatch_test):
+	* bus/driver.c: (bus_driver_handle_activate_service):
+	* bus/services.c: (bus_registry_acquire_service):
+	* dbus/dbus-message.c: (dbus_message_set_auto_activation),
+	(dbus_message_get_auto_activation):
+	* dbus/dbus-message.h:
+	* dbus/dbus-protocol.h: Implement auto-activation.
+	
+	* doc/dbus-specification.xml: Add auto-activation to the spec.
+
+2004-03-12  Olivier Andrieu  <oliv__a@users.sourceforge.net>
+
+	* dbus/dbus-marshal.c (_dbus_marshal_get_arg_end_pos):
+	fix a bug with CUSTOM types.
+
+	* dbus/dbus-message.c (message_iter_test, _dbus_message_test): add
+	a unit test for this bug (used to fail).
+
+2004-03-12  Mikael Hallendal  <micke@imendio.com>
+
+	* bus/activation.c:
+	(babysitter_watch_callback): notify all pending activations waiting for
+	  the same exec that the activation failed.
+	(bus_activation_activate_service): shortcut the activation if we 
+	  already waiting for the same executable to start up.
+
+2004-03-12  Mikael Hallendal  <micke@imendio.com>
+
+	* bus/activation.c: 
+	- Added service file reloading. 
+	  Each service files directory is kept in an hash table in 
+	  BusActivation and each BusActivationEntry knows what .service-file it
+	  was read from. So when you try to activate a service the bus will 
+	  check if it's been updated, removed or if new .service-files has 
+	  been installed.
+	- Test code at the bottom for the service file reloading.
+	* bus/test-main.c: (main):
+	* bus/test.h:
+	- added service reloading test.
+	* dbus/dbus-sysdeps.c: 
+	* dbus/dbus-sysdeps.h: (_dbus_delete_directory): Added.
+
+2004-03-08  Michael Meeks  <michael@ximian.com>
+
+	* dbus/dbus-connection.c (_dbus_connection_block_for_reply): 
+	bail immediately if disconnected, to avoid busy loop.
+
+	* dbus/dbus-message.c (dbus_message_iter_get_args_valist):
+	cleanup cut/paste/inefficiency.
+
+2004-03-01  David Zeuthen  <david@fubar.dk>
+
+	* dbus/dbus-string.c (_dbus_string_append_printf_valist): Fix a
+	bug where args were used twice. This bug resulted in a segfault
+	on a Debian/PPC system when starting the messagebus daemon. Include
+	dbus-sysdeps.h for DBUS_VA_COPY
+
+	* dbus/dbus-sysdeps.h: Define DBUS_VA_COPY if neccessary. From GLib
+
+	* configure.in: Check for va_copy; define DBUS_VA_COPY to the
+	appropriate va_copy implementation. From GLib
+ 	
+2004-02-24  Joe Shaw  <joe@ximian.com>
+
+	* bus/services.c (bus_registry_acquire_service): We need to pass
+	in the service name to dbus_set_error() to prevent a crash.
+
+2003-12-26  Anders Carlsson  <andersca@gnome.org>
+
+	* AUTHORS: Reveal my True identity.
+
+2003-12-17  Mikael Hallendal  <micke@imendio.com>
+
+	* dbus/dbus-message.c: (dbus_message_append_args_valist): 
+	- Added case for DBUS_TYPE_BYTE, patch from Johan Hedberg.
+
+2003-12-13  Mikael Hallendal  <micke@imendio.com>
+
+	* doc/TODO: Added not about better error check of configuration files.
+
+2003-12-02  Richard Hult  <richard@imendio.com>
+
+	* Update AFL version to 2.0 throughout the source files to reflect
+	the update that was done a while ago.
+
+2003-12-02  Richard Hult  <richard@imendio.com>
+
+	* dbus/dbus-message.c (dbus_message_iter_append_dict): Set
+	wrote_dict_key to FALSE on the iter that the dict is appended to,
+	just like when appending other types. Fixes a bug where a dict
+	couldn't be put inside a dict.
+	(dbus_message_iter_append_dict_key): Fix typo in warning message.
+	(message_iter_test, _dbus_message_test): Add test case for dict
+	inside dict.
+
+2003-12-01  David Zeuthen  <david@fubar.dk>
+
+	* python/dbus.py: Add the actual message when calling the reciever
+	of a signal such that parameters can be inspected. Add the method
+	remove_signal_receiver
+	
+2003-11-26  Mikael Hallendal  <micke@imendio.com>
+
+	* bus/*.[ch]:
+	* dbus/*.[ch]:
+	* glib/*.[ch]: Made ref functions return the pointer
+
+2003-11-25  Zack Rusin  <zack@kde.org>
+
+	* qt/integrator.h, qt/integrator.cpp: Adding handling of DBusServer,
+
+	* qt/server.h, qt/server.cpp, qt/Makefile.am: Adding DBusServer 
+	wrappers,
+
+	* qt/connection.h, qt/connection.cpp: Adjusting to changes in 
+	the Integrator and to better fit with the server,
+
+2003-11-24  Zack Rusin  <zack@kde.org>
+
+	* qt/connection.h, qt/connection.cpp: removing initDbus method since
+	the integrator handles it now
+
+	* qt/integrator.h, qt/integrator.cpp: reworking handling of timeouts,
+	since QTimer wasn't really meant to be used the way DBusTimeout is
+
+2003-11-24  Zack Rusin  <zack@kde.org>
+
+	* qt/integrator.h, qt/integrator.cpp, Makefile.am: Adding 
+	Integrator class which integrates D-BUS with the Qt event loop,
+
+	* qt/connection.h, qt/connection.cpp: Move all the code which
+	was dealing with D-BUS integration to the Integrator class,
+	and start using Integrator,
+
+2003-11-23  Zack Rusin  <zack@kde.org>
+
+	* qt/connection.h, qt/connection.cpp: Adding the DBusConnection 
+	wrapper
+
+	* qt/message.h, qt/message.cpp: updating to the current D-BUS api,
+	switching namespaces to DBusQt, reworking the class,
+
+	* Makefile.cvs: switching dependencies so that it matches KDE 
+	schematics,
+	
+	* qt/Makefile.am: adding connection.{h,cpp} and message.{h,cpp} to 
+	the library
+
+2003-11-19  Havoc Pennington  <hp@redhat.com>
+
+	* NEWS: update
+
+        * configure.in: bump version to 0.20
+
+	* configure.in (have_qt): add yet another place to look for qt
+	(someone hand trolltech a .pc file...)
+
+2003-11-01  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.xml: add state machine docs on the auth
+	protocol; just a first draft, I'm sure it's wrong.	
+
+2003-10-28  David Zeuthen  <david@fubar.dk>
+
+	* python/dbus_bindings.pyx.in: add get_dict to handle dictionaries
+	return types. Fixup TYPE_* to reflect changes in dbus/dbus-protocol.h
+	
+2003-10-28  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c (get_next_field): delete unused function
+
+2003-10-28  Havoc Pennington  <hp@redhat.com>
+
+	* bus/expirelist.c (do_expiration_with_current_time): detect
+	failure of the expire_func due to OOM
+
+	* bus/connection.c (bus_pending_reply_expired): return FALSE on OOM
+
+	* bus/dispatch.c (check_send_exit_to_service): fix to handle the
+	NoReply error that's now created by the bus when the service exits
+
+2003-10-28  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c (_dbus_message_test): enable and fix the
+	tests for set_path, set_interface, set_member, etc.
+
+	* dbus/dbus-string.c (_dbus_string_insert_bytes): allow 0 bytes
+
+	* dbus/dbus-message.c (set_string_field): always just delete and
+	re-append the field; accept NULL for deletion
+	(re_align_fields_recurse): reimplement
+	
+2003-10-26  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c: fix docs to properly describe the
+	disconnected message
+	(_dbus_connection_notify_disconnected): remove this function; 
+	we can't synchronously add the disconnected message, we have to 
+	do it after we've queued any remaining real messages
+	(_dbus_connection_get_dispatch_status_unlocked): queue the
+	disconnect message only if the transport has finished queueing all
+	its real messages and is disconnected.
+	(dbus_connection_disconnect): update the dispatch status here
+
+2003-10-22  Havoc Pennington  <hp@redhat.com>
+
+	* bus/bus.c (bus_context_check_security_policy): fix up assertion
+
+	* bus/connection.c (bus_transaction_send_from_driver): set the
+	destination to the connection's base service
+
+2003-10-20  Havoc Pennington  <hp@redhat.com>
+
+        hmm, make check is currently not passing.
+	
+	* doc/dbus-specification.xml: add requirement that custom type
+	names follow the same rules as interface names.
+
+	* dbus/dbus-protocol.h: change some of the byte codes, to avoid
+	duplication and allow 'c' to be 'custom'; dict is now 'm' for
+	'map'
+
+	* doc/dbus-specification.xml: update type codes to match
+	dbus-protocol.h, using the ASCII byte values. Rename type NAMED to
+	CUSTOM. Add type OBJECT_PATH to the spec.
+
+2003-10-17  Havoc Pennington  <hp@redhat.com>
+
+	* bus/driver.c (create_unique_client_name): use "." as separator
+	in base service names instead of '-'
+
+	* dbus/dbus-string.c (_dbus_string_get_byte): allow getting nul
+	byte at the end of the string
+
+	* dbus/dbus-internals.h (_DBUS_LIKELY, _DBUS_UNLIKELY): add
+	optimization macros since string validation seems to be a slow
+	point.
+	
+	* doc/dbus-specification.xml: restrict valid
+	service/interface/member/error names. Add test suite code for the
+	name validation.
+
+	* dbus/dbus-string.c: limit service/interface/member/error names 
+	to [0-9][A-Z][a-z]_
+
+	* dbus/dbus-connection.c (dbus_connection_dispatch): add missing
+	format arg to verbose spew
+
+	* glib/dbus-gproxy.c (dbus_gproxy_call_no_reply): if not out of
+	memory, return instead of g_error
+
+	* test/test-service.c (path_message_func): support emitting a
+	signal on request
+
+	* dbus/dbus-bus.c (init_connections_unlocked): only fill in
+	activation bus type if DBUS_BUS_ACTIVATION was set; default to
+	assuming the activation bus was the session bus so that services
+	started manually will still register.
+	(init_connections_unlocked): fix so that in OOM situation we get
+	the same semantics when retrying the function
+	
+	* test/test-service.c (main): change to use path registration, to
+	test those codepaths; register with DBUS_BUS_ACTIVATION rather
+	than DBUS_BUS_SESSION
+
+2003-10-16  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gtest-main.c: bracket with #ifdef DBUS_BUILD_TESTS
+
+	* Makefile.am (GCOV_DIRS): remove "test", we don't care about test
+	coverage of the tests
+	(coverage-report.txt): don't move the .da and .bbg files around
+
+2003-10-16  Havoc Pennington  <hp@redhat.com>
+
+	* bus/bus.c (struct BusContext): remove struct field I didn't mean
+	to put there
+
+2003-10-16  Havoc Pennington  <hp@redhat.com>
+
+	* bus/connection.c (bus_pending_reply_expired): either cancel or
+	execute, not both
+	(bus_connections_check_reply): use unlink, not remove_link, as we
+	don't want to free the link; fixes double free mess
+
+	* dbus/dbus-pending-call.c (dbus_pending_call_block): fix in case
+	where no reply was received
+
+	* dbus/dbus-connection.c (_dbus_pending_call_complete_and_unlock):
+	fix a refcount leak
+
+	* bus/signals.c (match_rule_matches): add special cases for the
+	bus driver, so you can match on sender/destination for it.
+
+	* dbus/dbus-sysdeps.c (_dbus_abort): print backtrace if
+	DBUS_PRINT_BACKTRACE is set
+
+	* dbus/dbus-internals.c: add pid to assertion failure messages
+
+	* dbus/dbus-connection.c: add message type code to the debug spew
+
+	* glib/dbus-gproxy.c (gproxy_get_match_rule): match rules want
+	sender=foo not service=foo
+
+	* dbus/dbus-bus.c (dbus_bus_get): if the activation bus is the
+	session bus but DBUS_SESSION_BUS_ADDRESS isn't set, use 
+	DBUS_ACTIVATION_ADDRESS instead
+
+	* bus/activation.c: set DBUS_SESSION_BUS_ADDRESS,
+	DBUS_SYSTEM_BUS_ADDRESS if appropriate
+
+	* bus/bus.c (bus_context_new): handle OOM copying bus type into
+	context struct
+
+	* dbus/dbus-message.c (dbus_message_iter_get_object_path): new function
+	(dbus_message_iter_get_object_path_array): new function (half
+	finished, disabled for the moment)
+	
+	* glib/dbus-gproxy.c (dbus_gproxy_end_call): properly handle
+	DBUS_MESSAGE_TYPE_ERROR
+
+	* tools/dbus-launch.c (babysit): support DBUS_DEBUG_OUTPUT to
+	avoid redirecting stderr to /dev/null
+	(babysit): close stdin if not doing the "exit_with_session" thing
+
+	* dbus/dbus-sysdeps.c (_dbus_become_daemon): delete some leftover
+	debug code; change DBUS_DEBUG_OUTPUT to only enable stderr, not
+	stdout/stdin, so things don't get confused
+	
+	* bus/system.conf.in: fix to allow replies, I modified .conf
+	instead of .conf.in again.
+
+2003-10-14  David Zeuthen  <david@fubar.dk>
+
+	* python/dbus_bindings.pyx.in (MessageIter.get): fixed typo in
+	argtype to arg_type when raising unknown arg type exception.
+	Changed type list to reflect the changes in dbus-protocol.h so 
+	the bindings actually work.
+
+2003-10-14  Havoc Pennington  <hp@redhat.com>
+
+	* test/decode-gcov.c: support gcc 3.3 also, though gcc 3.3 seems
+	to have a bug keeping it from outputting the .da files sometimes
+	(string_get_string): don't append garbage nul bytes to the string.
+
+2003-10-15  Seth Nickell  <seth@gnome.org>
+
+	* python/Makefile.am:
+
+	Include dbus_h_wrapper.h in the dist tarball.
+
+2003-10-14  Havoc Pennington  <hp@redhat.com>
+
+	* bus/bus.c (bus_context_check_security_policy): revamp this to
+	work more sanely with new policy-based requested reply setup
+
+	* bus/connection.c (bus_transaction_send_from_driver): set bus
+	driver messages as no reply
+
+	* bus/policy.c (bus_client_policy_check_can_receive): handle a
+	requested_reply attribute on allow/deny rules
+
+	* bus/system.conf: add <allow requested_reply="true"/>
+
+	* bus/driver.c (bus_driver_handle_message): fix check for replies
+	sent to the bus driver, which was backward. How did this ever work
+	at all though? I think I'm missing something.
+
+	* dbus/dbus-message.c (decode_header_data): require error and
+	method return messages to have a reply serial field to be valid
+	(_dbus_message_loader_queue_messages): break up this function;
+	validate that reply serial and plain serial are nonzero; 
+	clean up the OOM/error handling.
+	(get_uint_field): don't return -1 from this
+	(dbus_message_create_header): fix signed/unsigned bug
+
+	* bus/connection.c (bus_connections_expect_reply): save serial of
+	the incoming message, not reply serial
+
+2003-10-14  Havoc Pennington  <hp@redhat.com>
+
+	* bus/connection.c: implement pending reply tracking using
+	BusExpireList
+
+	* bus/bus.c (bus_context_check_security_policy): verify that a
+	reply is pending in order to allow a reply to be sent. Deny 
+	messages of unknown type.
+
+	* bus/dbus-daemon-1.1.in: update to mention new resource limits
+
+	* bus/bus.c (bus_context_get_max_replies_per_connection): new
+	(bus_context_get_reply_timeout): new
+
+2003-10-13  Seth Nickell  <seth@gnome.org>
+
+	* python/Makefile.am:
+
+	Pass "make distcheck": remove a couple files from DIST_FILES
+	that weren't included in the final version.
+
+2003-10-12  Havoc Pennington  <hp@pobox.com>
+
+        Added test code that 1) starts an actual bus daemon and 2) uses
+	DBusGProxy; fixed bugs that were revealed by the test. Lots 
+	more testing possible, but this is the basic framework.
+	
+	* glib/dbus-gproxy.c (dbus_gproxy_manager_unregister): remove
+	empty proxy lists from the proxy list hash
+
+	* dbus/dbus-message.c (dbus_message_iter_get_args_valist): add a
+	couple of return_if_fail checks
+
+	* dbus/dbus-pending-call.c (_dbus_pending_call_new): use dbus_new0
+	to allocate, so everything is cleared to NULL as it should be.
+
+	* glib/dbus-gmain.c (dbus_connection_setup_with_g_main): pass
+	source as data to dbus_connection_set_timeout_functions() as the 
+	timeout functions expected
+
+	* test/glib/run-test.sh: add a little script to start up a message
+	bus and run tests using it
+
+	* tools/dbus-launch.1: updates
+
+	* tools/dbus-launch.c (main): add --config-file option
+
+	* tools/dbus-launch.c (main): remove confusing else if (runprog)
+	that could never be reached.
+
+	* dbus/dbus-message.c (dbus_message_new_method_return) 
+	(dbus_message_new_error, dbus_message_new_signal): set the
+	no-reply-expected flag on all these. Redundant, but may
+	as well be consistent.
+
+2003-10-11  Havoc Pennington  <hp@pobox.com>
+
+	* test/decode-gcov.c (function_solve_graph): make broken block
+	graph a nonfatal error since it seems to be broken. Need to debug
+	this.
+
+	* dbus/dbus-marshal.c (_dbus_type_is_valid): new function since we
+	can't just check type > INVALID < LAST anymore
+
+	* dbus/dbus-message.c (dbus_message_get_signature): new function
+	(dbus_message_has_signature): new function
+	(struct DBusMessage): add signature field (right now it isn't sent
+	over the wire, just generated on the fly)
+	(dbus_message_copy): copy the signature, and init strings to
+	proper length to avoid some reallocs
+	(dbus_message_iter_init_array_iterator): return void, since it
+	can't fail
+	(dbus_message_iter_init_dict_iterator): return void since it can't fail
+	(_dbus_message_loader_queue_messages): add silly temporary hack to
+	fill in message->signature on load
+
+	* dbus/dbus-protocol.h: change DBUS_TYPE_* values to be ASCII
+	characters, so they are relatively human-readable.
+
+2003-10-11  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (_dbus_message_test): add more test
+	coverage, but #if 0 for now since they uncover a bug 
+	not fixed yet; I think in re_align_field_recurse()
+	(re_align_field_recurse): add FIXME about broken assertion
+
+	* dbus/dbus-sysdeps.c (_dbus_sysdeps_test): add more test coverage
+
+	* bus/connection.c: share a couple code bits with expirelist.c
+
+	* bus/expirelist.h, bus/expirelist.c: implement a generic
+	expire-items-after-N-seconds facility, was going to share between
+	expiring connections and replies, decided not to use for expiring
+	connections for now.
+
+	* COPYING: include AFL 2.0 (still need to change all the file headers)
+
+2003-10-09  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: define DBUS_HAVE_GCC33_GCOV if we have
+	gcc 3.3. Not that we do anything about it yet.
+
+	* bus/signals.c (bus_match_rule_parse): impose max length on the
+	match rule text
+
+	* dbus/dbus-protocol.h: add DBUS_MAXIMUM_MATCH_RULE_LENGTH
+
+2003-10-09  Havoc Pennington  <hp@redhat.com>
+
+        Make matching rules theoretically work (add parser).
+	
+	* bus/bus.c (bus_context_check_security_policy): fix up to handle
+	the case where destination is explicitly specified as bus driver
+	and someone else is eavesdropping.
+	
+	* bus/policy.c (bus_client_policy_check_can_receive): fix up
+	definition of eavesdropping and assertion
+
+	* tools/dbus-send.c (main): use dbus_message_type_from_string
+
+	* bus/signals.c (bus_match_rule_parse): implement
+
+	* dbus/dbus-message.c (dbus_message_type_from_string): new
+
+	* dbus/dbus-errors.h (DBUS_ERROR_MATCH_RULE_INVALID): add
+
+2003-10-02  Havoc Pennington  <hp@pobox.com>
+
+	* glib/dbus-gproxy.c (dbus_gproxy_call_no_reply): rename from
+	dbus_gproxy_oneway_call
+
+	* glib/dbus-gmain.c (dbus_connection_setup_with_g_main) 
+	(dbus_server_setup_with_g_main): fix to allow calling them more
+	than once on the same args
+	(dbus_bus_get_with_g_main): new function
+
+2003-10-02  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-tutorial.xml: write some stuff
+
+2003-09-29  Havoc Pennington  <hp@pobox.com>
+
+	* configure.in: split checks for Doxygen from XML docs, check for
+	xmlto
+
+	* doc/Makefile.am: XML-ify all the docs, and add a blank
+	dbus-tutorial.xml
+
+2003-09-29  Havoc Pennington  <hp@pobox.com>
+
+	* Merge dbus-object-names branch. To see the entire patch 
+	do cvs diff -r DBUS_OBJECT_NAMES_BRANCHPOINT -r dbus-object-names,
+	it's huuuuge though.
+	To revert, I tagged DBUS_BEFORE_OBJECT_NAMES_MERGE.
+	
+2003-09-28  Havoc Pennington  <hp@pobox.com>
+
+	* HACKING: update to reflect new server
+
+2003-09-26  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus.py:
+	* python/examples/example-signals.py:
+
+	Start implementing some notions of signals. The API
+	is really terrible, but they sort of work (with the
+	exception of being able to filter by service, and to
+	transmit signals *as* a particular service). Need to
+	figure out how to make messages come from the service
+	we registered :-(
+	
+	* python/dbus_bindings.pyx.in:
+
+	Removed duplicate message_handler callbacks.
+	
+2003-09-25  Havoc Pennington  <hp@redhat.com>
+
+	* bus/session.conf.in: fix my mess
+
+2003-09-25  Havoc Pennington  <hp@pobox.com>
+
+	* bus/session.conf.in: fix security policy, reported by Seth Nickell
+
+2003-09-25  Seth Nickell  <seth@gnome.org>
+
+	* python/examples/example-service.py:
+
+	Johan notices complete wrong code in example-service, but
+	completely wrong in a way that works exactly the same (!).
+	Johan is confused, how could this possibly work? Example
+	code fails to serve purpose of making things clear.
+	Seth fixes.
+
+2003-09-25  Mark McLoughlin  <mark@skynet.ie>
+
+	* doc/dbus-specification.sgml: don't require header fields
+	to be 4-byte aligned and specify that fields should be
+	distinguished from padding by the fact that zero is not
+	a valid field name.
+	
+	* doc/TODO: remove re-alignment item and add item to doc
+	the OBJECT_PATH type.
+	
+	* dbus/dbus-message.c:
+	(HeaderField): rename the original member to value_offset
+	and introduce a name_offset member to keep track of where
+	the field actually begins.
+	(adjust_field_offsets): remove.
+	(append_int_field), (append_uint_field),
+	(append_string_field): don't align the start of the header
+	field to a 4-byte boundary.
+	(get_next_field): impl finding the next marhsalled field
+	after a given field.
+	(re_align_field_recurse): impl re-aligning a number of
+	already marshalled fields.
+	(delete_field): impl deleting a field of any type and
+	re-aligning any following fields.
+	(delete_int_or_uint_field), (delete_string_field): remove.
+	(set_int_field), (set_uint_field): no need to re-check
+	that we have the correct type for the field.
+	(set_string_field): ditto and impl re-aligning any
+	following fields.
+	(decode_header_data): update to take into account that
+	the fields aren't 4-byte aligned any more and the new
+	way to distinguish padding from header fields. Also,
+	don't exit when there is too much header padding.
+	(process_test_subdir): print the directory.
+	(_dbus_message_test): add test to make sure a following
+	field is re-aligned correctly after field deletion.
+	
+	* dbus/dbus-string.[ch]:
+	(_dbus_string_insert_bytes): rename from insert_byte and
+	allow the insert of multiple bytes.
+	(_dbus_string_test): test inserting multiple bytes.
+
+	* dbus/dbus-marshal.c: (_dbus_marshal_set_string): add
+	warning note to docs about having to re-align any
+	marshalled values following the string.
+	
+	* dbus/dbus-message-builder.c:
+	(append_string_field), (_dbus_message_data_load):
+	don't align the header field.
+	
+	* dbus/dbus-auth.c: (process_test_subdir): print the
+	directory.
+	
+	* test/break-loader.c: (randomly_add_one_byte): upd. for
+	insert_byte change.
+	
+	* test/data/invalid-messages/bad-header-field-alignment.message:
+	new test case.
+	
+	* test/data/valid-messages/unknown-header-field.message: shove
+	a dict in the unknown field.
+
+2003-09-25  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus.py:
+	* python/dbus_bindings.pyx.in:
+
+	Handle return values.
+	
+	* python/examples/example-client.py:
+	* python/examples/example-service.py:
+
+	Pass back return values from the service to the client.
+	
+2003-09-24  Seth Nickell  <seth@gnome.org>
+
+	* python/dbus.py:
+
+	Connect Object methods (when you are sharing an object) up... pass
+	in a list of methods to be shared. Sharing all the methods just
+	worked out too weird. You can now create nice Services over the
+	DBus in Python. :-)
+	
+	* python/dbus_bindings.pyx.in:
+
+	Keep references to user_data tuples passed into C functions so 
+	Python doesn't garbage collect on us.
+
+	Implement MethodReturn and Error subclasses of Message for creating
+	DBusMessage's of those types.
+	
+	* python/examples/example-client.py:
+	* python/examples/example-service.py:
+
+	Simple example code showing both how create DBus services and objects,
+	and how to use them.
+
+2003-09-23  Havoc Pennington  <hp@pobox.com>
+
+	* glib/dbus-gproxy.c (dbus_gproxy_manager_filter): implement
+
+2003-09-23  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gproxy.c (dbus_gproxy_connect_signal): implement
+	(dbus_gproxy_disconnect_signal): implement
+	(dbus_gproxy_manager_remove_signal_match): implement
+	(dbus_gproxy_manager_add_signal_match): implement
+	(dbus_gproxy_oneway_call): implement
+
+2003-09-23  Havoc Pennington  <hp@pobox.com>
+
+	* glib/dbus-gproxy.c (struct DBusGProxy): convert to a GObject
+	subclass. This means dropping the transparent thread safety of the
+	proxy; you now need a separate proxy per-thread, or your own
+	locking on the proxy. Probably right anyway.
+	(dbus_gproxy_ref, dbus_gproxy_unref): nuke, just use g_object_ref
+
+2003-09-22  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gproxy.c (dbus_gproxy_manager_get): implement
+
+2003-09-21  Seth Nickell  <seth@gnome.org>
+
+        First checkin of the Python bindings.
+	
+	* python/.cvsignore:
+	* python/Makefile.am:
+	* python/dbus_bindings.pyx.in:
+	* python/dbus_h_wrapper.h:
+
+	Pieces for Pyrex to operate on, building a dbus_bindings.so
+	python module for low-level access to the DBus APIs.
+	
+	* python/dbus.py:
+
+	High-level Python module for accessing DBus objects.
+
+	* configure.in:
+	* Makefile.am:
+
+	Build stuff for the python bindings.
+
+	* acinclude.m4:
+
+	Extra macro needed for finding the Python C header files.
+
+2003-09-21  Havoc Pennington  <hp@pobox.com>
+
+	* glib/dbus-gproxy.c (dbus_gproxy_manager_new): start
+	implementing the proxy manager, didn't get very far.
+
+	* dbus/dbus-bus.c (dbus_bus_add_match): new
+	(dbus_bus_remove_match): new
+
+	* glib/dbus-gproxy.c (dbus_gproxy_new_for_service): add a
+	path_name argument; adjust the other not-yet-implemented 
+	gproxy constructors to be what I think they should be.
+
+2003-09-21  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-bus.c (dbus_bus_get): set exit_on_disconnect to TRUE
+	by default for message bus connections.
+
+	* dbus/dbus-connection.c (dbus_connection_dispatch): exit if
+	exit_on_disconnect flag is set and we process the disconnected
+	signal.
+	(dbus_connection_set_exit_on_disconnect): new function
+
+2003-09-21  Havoc Pennington  <hp@pobox.com>
+
+	Get matching rules mostly working in the bus; only actually
+	parsing the rule text remains. However, the client side of
+	"signal connections" hasn't been started, this patch is only the
+	bus side.
+	
+	* dbus/dispatch.c: fix for the matching rules changes
+	
+	* bus/driver.c (bus_driver_handle_remove_match)
+	(bus_driver_handle_add_match): send an ack reply from these
+	method calls
+
+	* glib/dbus-gproxy.c (dbus_gproxy_begin_call): fix order of
+	arguments, reported by Seth Nickell
+
+	* bus/config-parser.c (append_rule_from_element): support
+	eavesdrop=true|false attribute on policies so match rules 
+	can be prevented from snooping on the system bus.
+
+	* bus/dbus-daemon-1.1.in: consistently use terminology "sender"
+	and "destination" in attribute names; fix some docs bugs; 
+	add eavesdrop=true|false attribute
+
+	* bus/driver.c (bus_driver_handle_add_match)
+	(bus_driver_handle_remove_match): handle AddMatch, RemoveMatch
+	messages
+
+	* dbus/dbus-protocol.h (DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST): get
+	rid of broadcast service concept, signals are just always broadcast
+
+	* bus/signals.c, bus/dispatch.c, bus/connection.c, bus/bus.c:
+	mostly implement matching rules stuff (currently only exposed as signal
+	connections)
+
+2003-09-21  Mark McLoughlin  <mark@skynet.ie>
+
+	* doc/dbus-specification.sgml: Change the header field name
+	to be an enum and update the rest of the spec to reference
+	the fields using the conventinal name.
+
+	* dbus/dbus-protocol.h: update to reflect the spec.
+
+	* doc/TODO: add item to remove the 4 byte alignment requirement.
+	
+	* dbus/dbus-message.c: Remove the code to generalise the
+	header/body length and serial number header fields as named
+	header fields so we can reference field names using the 
+	protocol values.
+	(append_int_field), (append_uint_field), (append_string_field):
+	Append the field name as a byte rather than four chars.
+	(delete_int_or_uint_field), (delete_string_field): reflect the
+	fact that the field name and typecode now occupy 4 bytes instead
+	of 8.
+	(decode_string_field), (decode_header_data): update to reflect
+	protocol changes and move the field specific encoding from
+	decode_string_field() back into decode_header_data().
+	
+	* dbus/dbus-internals.[ch]: (_dbus_header_field_to_string):
+	Add utility to aid debugging.
+	
+	* dbus/dbus-message-builder.c:
+	(append_string_field), (_dbus_message_data_load): Update to
+	reflect protocol changes; Change the FIELD_NAME directive
+	to HEADER_FIELD and allow it to take the field's conventional
+	name rather than the actual value.
+	
+	* test/data/*/*.message: Update to use HEADER_FIELD instead
+	of FIELD_NAME; Always align the header on an 8 byte boundary
+	*before* updating the header length.
+
+2003-09-15  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-pending-call.c: add the get/set object data
+	boilerplate as for DBusConnection, etc. Use generic object data
+	for the notify callback.
+
+	* glib/dbus-gparser.c (parse_node): parse child nodes
+
+	* tools/dbus-viewer.c: more hacking on the dbus-viewer
+	
+	* glib/dbus-gutils.c (_dbus_gutils_split_path): add a file to
+	contain functions shared between the convenience lib and the
+	installed lib
+
+	* glib/Makefile.am (libdbus_glib_1_la_LDFLAGS): add
+	-export-symbols-regex to the GLib library
+
+	* dbus/dbus-object-tree.c (_dbus_object_tree_dispatch_and_unlock):
+	fix the locking in here, and add a default handler for
+	Introspect() that just returns sub-nodes.
+
+2003-09-14  Havoc Pennington  <hp@pobox.com>
+
+	* glib/dbus-gthread.c (dbus_g_thread_init): rename to make g_foo
+	rather than gfoo consistent
+
+	* glib/dbus-gproxy.h: delete for now, move contents to
+	dbus-glib.h, because the include files don't work right since we
+	aren't in the dbus/ subdir.
+	
+	* glib/dbus-gproxy.c (dbus_gproxy_send): finish implementing
+	(dbus_gproxy_end_call): finish
+	(dbus_gproxy_begin_call): finish
+
+	* glib/dbus-gmain.c (dbus_set_g_error): new
+
+	* glib/dbus-gobject.c (handle_introspect): include information
+	about child nodes in the introspection
+
+	* dbus/dbus-connection.c (dbus_connection_list_registered): new
+	function to help in implementation of introspection
+
+	* dbus/dbus-object-tree.c
+	(_dbus_object_tree_list_registered_and_unlock): new function
+
+2003-09-12  Havoc Pennington  <hp@pobox.com>
+
+	* glib/dbus-gidl.h: add common base class for all the foo_info
+	types
+
+        * tools/dbus-viewer.c: add GTK-based introspection UI thingy
+	similar to kdcop
+
+	* test/Makefile.am: try test srcdir -ef . in addition to test
+	srcdir = ., one of them should work (yeah lame)
+	
+        * glib/Makefile.am: build the "idl" parser stuff as a convenience
+	library
+	
+	* glib/dbus-gparser.h: make description_load routines return
+	NodeInfo* not Parser*
+
+	* Makefile.am (SUBDIRS): build test dir after all library dirs
+
+	* configure.in: add GTK+ detection
+
+2003-09-07  Havoc Pennington  <hp@pobox.com>
+
+	* Make Doxygen contented.
+
+2003-09-07  Havoc Pennington  <hp@pobox.com>
+
+	* doc/dbus-specification.sgml: more updates
+
+2003-09-06  Havoc Pennington  <hp@pobox.com>
+
+	* doc/dbus-specification.sgml: partial updates
+
+	* bus/dbus-daemon-1.1.in: fix the config file docs for the
+	zillionth time; hopefully I edited the right file this time.
+
+	* bus/config-parser.c (append_rule_from_element): support
+	send_type, send_path, receive_type, receive_path
+
+	* bus/policy.c: add message type and path to the list of things
+	that can be "firewalled"
+
+2003-09-06  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c (dbus_connection_register_fallback): add this
+	(dbus_connection_register_object_path): make this not handle
+	messages to paths below the given path
+
+2003-09-03  Havoc Pennington  <hp@pobox.com>
+
+	* test/glib/Makefile.am: add this with random glib-linked test
+	programs
+
+	* glib/Makefile.am: remove the random test programs from here,
+	leave only the unit tests
+
+	* glib/dbus-gobject.c (_dbus_gobject_test): add test for 
+	uscore/javacaps conversion, and fix	
+	(get_object_property, set_object_property): change to .NET
+	convention for mapping props to methods, set_FooBar/get_FooBar, 
+	since one language has such a convention we may as well copy it. 
+	Plus real methods in either getFooBar or get_foo_bar style won't 
+	collide with this convention.
+
+2003-09-01  Havoc Pennington  <hp@pobox.com>
+
+	* glib/dbus-gparser.c: implement
+
+	* glib/dbus-gobject.c: start implementing skeletons support
+
+	* configure.in: when disabling checks/assert, also define
+	G_DISABLE_ASSERT and G_DISABLE_CHECKS
+
+2003-09-01  Havoc Pennington  <hp@pobox.com>
+
+	* glib/Makefile.am: rearrange a bunch of files and get "make
+	check" framework set up
+
+2003-08-31  Havoc Pennington  <hp@pobox.com>
+
+	* fix build with --disable-tests
+
+2003-08-30  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c: purge DBusMessageHandler
+
+	* dbus/dbus-message-handler.c: remove DBusMessageHandler, just 
+	use callbacks everywhere
+
+2003-08-30  Havoc Pennington  <hp@pobox.com>
+
+	* test/data/valid-config-files/system.d/test.conf: change to 
+	root for the user so warnings don't get printed
+
+	* dbus/dbus-message.c: add dbus_message_get_path,
+	dbus_message_set_path
+	
+	* dbus/dbus-object-tree.c (do_test_dispatch): add test of
+	dispatching to a path
+
+	* dbus/dbus-string.c (_dbus_string_validate_path): add
+
+	* dbus/dbus-marshal.c (_dbus_demarshal_object_path): implement
+	(_dbus_marshal_object_path): implement
+
+	* dbus/dbus-protocol.h (DBUS_HEADER_FIELD_PATH): new header field 
+	to contain the path to the target object
+	(DBUS_HEADER_FIELD_SENDER_SERVICE): rename
+	DBUS_HEADER_FIELD_SENDER to explicitly say it's the sender service
+
+2003-08-30  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-object-tree.c: write tests and fix the discovered bugs
+
+2003-08-29  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-object-tree.c: modify to allow overlapping paths to be
+	registered
+	(struct DBusObjectSubtree): shrink this
+	a lot, since we may have a lot of them
+	(_dbus_object_tree_free_all_unlocked): implement
+	(_dbus_object_tree_dispatch_and_unlock): implement
+
+2003-08-29  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-internals.h: fix _DBUS_N_GLOBAL_LOCKS
+
+2003-08-28  Havoc Pennington  <hp@pobox.com>
+
+	purge DBusObjectID
+	
+	* dbus/dbus-connection.c: port to no ObjectID, create a
+	DBusObjectTree, rename ObjectTree to ObjectPath in public API
+
+	* dbus/dbus-connection.h (struct DBusObjectTreeVTable): delete 
+	everything except UnregisterFunction and MessageFunction
+	
+	* dbus/dbus-marshal.c: port away from DBusObjectID, 
+	add DBUS_TYPE_OBJECT_PATH
+	
+	* dbus/dbus-object-registry.[hc], dbus/dbus-object.[hc], 
+	dbus/dbus-objectid.[hc]: remove these, we are moving to 
+	path-based object IDs
+
+2003-08-25  Havoc Pennington  <hp@pobox.com>
+
+        Just noticed that dbus_message_test is hosed, I wonder when I
+	broke that. I thought make check was passing earlier...
+	
+	* dbus/dbus-object-tree.c: add new "object tree" to match DCOP 
+	container tree, will replace most of dbus-object-registry
+
+	* dbus/dbus-string.c (_dbus_string_append_printf_valist): fix C99
+	screwup
+
+2003-08-19  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (decode_string_field): support FIELD_SENDER
+	(dbus_message_is_error): fix this function
+
+	* bus/dbus-daemon-1.1: clarify logic on when <deny>/<allow> rules
+	match
+
+	* bus/policy.c (bus_client_policy_check_can_receive): fix code to
+	reflect clarified man page
+	(bus_client_policy_check_can_send): ditto
+	
+	* bus/session.conf.in: fixup
+
+	* bus/system.conf.in: fixup
+
+2003-08-18  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-hash.c (_dbus_hash_table_insert_two_strings): fix
+
+	* dbus/dbus-message.c (_dbus_message_loader_queue_messages): fix
+	dumb bug created earlier (wrong order of args to
+	decode_header_data())
+	
+	* tools/dbus-send.c: port
+
+	* tools/dbus-print-message.c (print_message): port
+
+        * test/data/*messages: port all messages over
+	
+        * dbus/dbus-message-builder.c: support including 
+	message type
+	
+        * bus/driver.c: port over
+	
+	* bus/dispatch.c: port over to new stuff
+
+	* dbus/dbus-connection.c (_dbus_connection_new_for_transport):
+	rename disconnect signal to "Disconnected"
+
+2003-08-17  Havoc Pennington  <hp@pobox.com>
+
+	This doesn't compile yet, but syncing up so I can hack on it from
+	work. What are branches for if not broken code? ;-)
+	
+	* dbus/dbus-protocol.h: remove DBUS_HEADER_FIELD_NAME, add
+	DBUS_HEADER_FIELD_INTERFACE, DBUS_HEADER_FIELD_MEMBER,
+	DBUS_HEADER_FIELD_ERROR_NAME
+	
+	* dbus/dbus-hash.c: Introduce DBUS_HASH_TWO_STRINGS as hack to use
+	for the interface+member pairs
+	(string_hash): change to use g_str_hash algorithm
+	(find_direct_function, find_string_function): refactor these to
+	share most code.
+	
+	* dbus/dbus-message.c: port all of this over to support 
+	interface/member fields instead of name field
+
+	* dbus/dbus-object-registry.c: port over
+	
+	* dbus/dbus-string.c (_dbus_string_validate_interface): rename
+	from _dbus_string_validate_name
+
+	* bus/dbus-daemon-1.1: change file format for the 
+	<deny>/<allow> stuff to match new message naming scheme
+
+	* bus/policy.c: port over
+
+	* bus/config-parser.c: parse new format
+	
+2003-08-16  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-object-registry.c (add_and_remove_objects): remove
+	broken assertion
+
+	* glib/dbus-gproxy.c: some hacking
+
+2003-08-15  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-pending-call.c (dbus_pending_call_block): implement
+
+	* dbus/dbus-connection.c
+	(dbus_connection_send_with_reply_and_block): factor out internals;
+	change to convert any error replies to DBusError instead of 
+	returning them as a message
+
+2003-08-15  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c, 
+	dbus/dbus-pending-call.c: Finish the pending call stuff
+
+2003-08-14  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-pending-call.c: start on new object that will replace
+	DBusMessageHandler and ReplyHandlerData for tracking outstanding
+	replies
+
+	* dbus/dbus-gproxy.c: start on proxy object used to communicate
+	with remote interfaces
+
+	* dbus/dbus-gidl.c: do the boring boilerplate in here
+	
+2003-08-12  Havoc Pennington  <hp@pobox.com>
+
+	* bus/dispatch.c (bus_dispatch): make this return proper 
+	DBusHandlerResult to avoid DBUS_ERROR_UNKNOWN_METHOD
+
+	* dbus/dbus-errors.c (dbus_set_error): use
+	_dbus_string_append_printf_valist
+
+	* dbus/dbus-string.c (_dbus_string_append_printf_valist)
+	(_dbus_string_append_printf): new
+
+	* dbus/dbus-errors.h (DBUS_ERROR_UNKNOWN_MESSAGE): change to
+	UNKNOWN_METHOD
+
+	* dbus/dbus-connection.c (dbus_connection_dispatch): handle
+	DBUS_HANDLER_RESULT_NEED_MEMORY; send default error reply if a
+	message is unhandled.
+
+2003-08-11  Havoc Pennington  <hp@pobox.com>
+
+	* bus/test.c (client_disconnect_handler): change to return
+	HANDLED (would have been REMOVE_MESSAGE)
+
+	* dbus/dbus-object.h (enum DBusHandlerResult): rename to
+	HANDLED/NOT_YET_HANDLED instead of
+	REMOVE_MESSAGE/ALLOW_MORE_HANDLERS to make it clearer how it 
+	should be used.
+
+2003-08-10  Havoc Pennington  <hp@pobox.com>
+
+	* tools/dbus-send.c (main): add --type argument, for now
+	supporting only method_call and signal types.
+
+	* tools/dbus-print-message.c: print message type
+
+	* dbus/dbus-connection.c (_dbus_connection_new_for_transport):
+	init connection->objects
+
+	* doc/dbus-specification.sgml: fix sgml
+
+	* bus/*.c: port over to object-instance API changes
+
+	* test/test-service.c: ditto
+	
+	* dbus/dbus-message.c (dbus_message_create_header): allow #NULL
+	name, we will have to fix up the rest of the code to also handle
+	this
+	(dbus_message_new): generic message-creation call
+	(set_string_field): allow appending name field
+
+2003-08-06  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-object-registry.c: implement signal connection 
+	and dispatch
+
+	* dbus/dbus-connection.c (_dbus_connection_unref_unlocked): new
+
+	* dbus/dbus-internals.c (_dbus_memdup): new function
+
+2003-08-02  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (dbus_message_get_no_reply)
+	(dbus_message_set_no_reply): add these and remove
+	set_is_error/get_is_error
+
+	* dbus/dbus-protocol.h, doc/dbus-specification.sgml: 
+	remove the ERROR flag, since there's now an ERROR type
+
+2003-08-01  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-object-registry.c (_dbus_object_registry_handle_and_unlock):
+	implement
+
+	* dbus/dbus-message.c (dbus_message_get_type): new function
+
+	* doc/dbus-specification.sgml: add "type" byte to messages
+
+2003-08-01  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-protocol.h (DBUS_MESSAGE_TYPE_*): introduce
+	a message type enum to distinguish kinds of message
+	(DBUS_HEADER_FLAG_NO_REPLY_EXPECTED): flag for a message 
+	that need not be replied to
+
+2003-08-01  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-marshal.c: adapt to DBusObjectID changes
+	(unpack_8_octets): fix no-64-bit-int bug
+
+	* dbus/dbus-object-registry.c (validate_id): validate the 
+	connection ID bits, not just the instance ID.
+
+	* dbus/dbus-connection.c (_dbus_connection_init_id): initialize
+	the connection-global 33 bits of the object ID
+
+	* dbus/dbus-object-registry.c (info_from_entry): fill in 
+	object ID in the new way
+
+	* dbus/dbus-objectid.h: rather than high/low bits, specifically 
+	define server/client/instance bits.
+
+2003-07-30  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c (dbus_connection_register_object): fix
+	build
+
+2003-07-13  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-object.h (struct DBusObjectVTable): add padding
+	fields to DBusObjectVTable and DBusObjectInfo
+
+2003-07-12  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-object-registry.c: implement unit test,
+	fix bugs discovered in process
+
+	* dbus/dbus-connection.c: remove handler_table and
+	register_handler(), add DBusObjectRegistry usage
+
+	* dbus/dbus-objectid.c (dbus_object_id_is_null)
+	(dbus_object_id_set_null): new functions
+
+2003-07-08  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-object.c: implement some of this
+
+	* dbus/dbus-object-registry.c
+	(_dbus_object_registry_add_and_unlock): fill in the object_id out
+	param
+	(_dbus_object_registry_new): handle OOM
+
+2003-07-08  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-object.h: sketch out an API for registering objects
+	with a connection, that allows us to use as little as 24 bytes
+	per object and lets application code represent an object in 
+	any conceivable way.
+
+	* dbus/dbus-object-registry.c: implement the hard bits of the
+	DBusConnection aspect of object API. Not yet wired up.
+	
+2003-07-06  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-marshal.c (_dbus_marshal_set_object_id): new function
+	(_dbus_marshal_object_id): new
+	(_dbus_demarshal_object_id): new
+	(_dbus_marshal_get_arg_end_pos): support object ID type, and
+	consolidate identical switch cases. Don't conditionalize handling
+	of DBUS_TYPE_UINT64, need to handle the type always.
+	(_dbus_marshal_validate_arg): consolidate identical cases, and
+	handle DBUS_TYPE_OBJECT_ID
+
+	* dbus/dbus-objectid.c: new file with DBusObjectID data type.
+
+	* dbus/dbus-protocol.h: add DBUS_TYPE_OBJECT_ID
+
+2003-09-28  Havoc Pennington  <hp@pobox.com>
+
+	* real 0.13 release
+
+2003-09-28  Havoc Pennington  <hp@pobox.com>
+
+	* doc/Makefile.am (dbus-specification.html): testing a funky hack
+	to work with Debian db2html
+
+2003-09-28  Havoc Pennington  <hp@pobox.com>
+
+	* configure.in: 0.13
+
+	* doc/Makefile.am (dbus-test-plan.html): accept nonexistence of
+	stylesheet-images for benefit of Debian
+	
+	Change back to using filesystem-linked sockets for the system
+	bus, so only root can create the default system bus address.
+	
+	* bus/system.conf.in: change to use
+	DBUS_SYSTEM_BUS_DEFAULT_ADDRESS
+
+	* dbus/Makefile.am (INCLUDES): remove DBUS_SYSTEM_BUS_PATH define
+	from here.
+
+	* configure.in: define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS
+	here, and AC_DEFINE DBUS_SYSTEM_PATH
+
+2003-08-09  Anders Carlsson  <andersca@codefactory.se>
+
+	* doc/TODO:
+	* doc/busconfig.dtd:
+	Add busconfig DTD.
+	
+2003-08-09  Anders Carlsson  <andersca@codefactory.se>
+
+	* doc/dbus-specification.sgml:
+	Add activation reply values.
+	
+2003-08-05  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: 0.12
+
+2003-08-05  Anders Carlsson  <andersca@codefactory.se>
+
+	* glib/dbus-gmain.c: (watch_fd_new), (watch_fd_ref),
+	(watch_fd_unref), (dbus_gsource_check), (dbus_gsource_dispatch),
+	(add_watch), (remove_watch), (create_source):
+	Refcount fds, fixes some reentrancy issues.
+	
+2003-07-30  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-bus.c (init_connections_unlocked): fix default system
+	bus address to be abstract if we have abstract sockets
+
+	* NEWS: update
+
+2003-07-28  Havoc Pennington  <hp@redhat.com>
+
+	* bus/messagebus.in: fix to avoid processname/servicename 
+	confusion, from Michael Kearey
+	https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=100965
+	
+2003-07-23  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (dbus_message_iter_get_named): 
+	fix from Andy Hanton to remove broken "+1"
+
+2003-07-16  Havoc Pennington  <hp@pobox.com>
+
+	* tools/dbus-launch.c (babysit): close stdout/stderr in the
+	babysitter process, as suggested by Thomas Leonard, so 
+	an "eval `dbus-launch --exit-with-session`" will actually 
+	return
+
+2003-07-16  Havoc Pennington  <hp@pobox.com>
+
+	* configure.in: print out EXPANDED_* variables in the summary at
+	the end; clean up the code that computes EXPANDED_ variables and
+	get the ones using exec_prefix right. Should make things work
+	when you build without --prefix
+
+2003-06-29  Havoc Pennington  <hp@pobox.com>
+
+	* mono/Test.cs (class Test): fire up a main loop and run it
+
+	* mono/DBus.cs (DBus): don't g_thread_init since it can only be
+	done once, the app has to do it
+
+2003-06-26  Havoc Pennington  <hp@pobox.com>
+
+	* mono/Connection.cs: set up connection with the glib main loop
+
+2003-07-01  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.sgml: clarify the format of a type code,
+	change suggested by Jim Blandy
+
+2003-06-29  Miloslav Trmac  <mitr@volny.cz>
+
+	* doc/Makefile.am:
+	* tools/Makefile.am: Don't assume srcdir == builddir.
+
+	* dbus/dbus-memory.c (dbus_realloc): Don't check guards after shrinking
+	the allocated block.
+	(_dbus_memory_test): New function.
+	* dbus/dbus-test.h: Add _dbus_memory_test ().
+	* dbus/dbus-test.c (dbus_internal_do_not_use_run_tests): Call it.
+
+	* dbus/dbus-message.c (decode_header_data): Use %.4s instead
+	of %c%c%c%c.
+	(dbus_message_new): Remove obsolete @todo.
+
+	* dbus/dbus-marshal.c (_dbus_marshal_set_int64)
+	(_dbus_marshal_set_uint64): Fix comment.
+
+	* dbus/dbus-message.c (append_int_field, append_uint_field): Don't
+	hardcode FIELD_REPLY_SERIAL.
+
+	* dbus/dbus-mainloop.c (_dbus_loop_remove_watch)
+	(_dbus_loop_remove_timeout): Cast function pointers to (void *) for %p
+
+	* configure.in: Add -D_POSIX_C_SOURCE=199309L -DBSD_SOURCE to CFLAGS
+	and disable DBUS_USE_ATOMIC_INT_486 when --enable-ansi is used
+
+2003-06-24  Havoc Pennington  <hp@pobox.com>
+
+	* mono/*.cs: Use IntPtr.Zero instead of ((IntPtr) 0)
+
+2003-06-23  Anders Carlsson  <andersca@codefactory.se>
+
+	* configure.in:
+	* gcj/.cvsignore:
+	* gcj/Hello.java:
+	* gcj/Makefile.am:
+	* gcj/TestMessage.java: (TestMessage), (TestMessage.main):
+	* gcj/org/.cvsignore:
+	* gcj/org/Makefile.am:
+	* gcj/org/freedesktop/.cvsignore:
+	* gcj/org/freedesktop/Makefile.am:
+	* gcj/org/freedesktop/dbus/.cvsignore:
+	* gcj/org/freedesktop/dbus/Makefile.am:
+	* gcj/org/freedesktop/dbus/Message.java: (Message),
+	(Message.Message):
+	* gcj/org/freedesktop/dbus/natMessage.cc:
+	Fix the build system.
+
+2003-06-22  Havoc Pennington  <hp@pobox.com>
+
+	* mono/Connection.cs: add more bindings
+
+	* dbus/dbus-threads.c (dbus_threads_init): allow calling this
+	more than once.
+
+2003-06-22  Havoc Pennington  <hp@pobox.com>
+
+	* mono/Connection.cs, mono/DBus.cs, mono/Error.cs:
+	Start wrapping more stuff.
+
+2003-06-22  Havoc Pennington  <hp@pobox.com>
+
+	* mono/Message.cs: implement Message.Wrap() that ensures we only
+	have a single C# wrapper per DBusMessage, assuming it works which
+	it probably doesn't.
+
+	* dbus/dbus-message.c (dbus_message_allocate_data_slot): new
+	(dbus_message_free_data_slot): new
+	(dbus_message_set_data): new
+	(dbus_message_get_data): new
+
+2003-06-22  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-dataslot.c (_dbus_data_slot_allocator_unref)
+	(_dbus_data_slot_allocator_alloc): rework these to keep a
+	reference count on each slot and automatically manage a global
+	slot ID variable passed in by address
+
+	* bus/bus.c: convert to new dataslot API
+
+	* dbus/dbus-bus.c: convert to new dataslot API
+
+	* dbus/dbus-connection.c: convert to new dataslot API
+
+	* dbus/dbus-server.c: convert to new dataslot API
+
+	* glib/dbus-gmain.c: ditto
+
+	* bus/test.c: ditto
+
+	* bus/connection.c: ditto
+
+2003-06-22  Anders Carlsson  <andersca@codefactory.se>
+
+	* configure.in: Add AM_PROG_GCJ and move AM_PROG_LIBTOOL
+	after the gcj checks so that the correct configuration tags
+	will be added to libtool.
+
+	* dbus-glib-1.pc.in: No need to specify any includes since
+	dbus-1.pc.in has those.
+
+2003-06-22  Havoc Pennington  <hp@pobox.com>
+
+	* mono/*, gcj/*, configure.in, Makefile.am:
+	Check in makefiles and subdirs for mono and gcj bindings.
+	Neither binding actually exists, just trying to get through
+	all the build and other boring bits.
+
+2003-06-21  Philip Blundell  <philb@gnu.org>
+
+	* tools/dbus-monitor.1: Updated.
+
+	* tools/dbus-send.1: Likewise.
+
+2003-06-20  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-transport-unix.c (unix_handle_watch): Check
+	for hangup and error after checking read so we won't discard
+	pending data if both hangup and read are set.
+
+2003-06-19  Philip Blundell  <philb@gnu.org>
+
+	* tools/dbus-print-message.c (print_message): Handle BOOLEAN.
+
+	* tools/dbus-send.c: Accept both --system and --session.
+
+	* tools/dbus-monitor.c: Same here.
+
+2003-06-19  Anders Carlsson  <andersca@codefactory.se>
+
+	* glib/dbus-glib.h: Fix so that dbus-glib.h can be used
+	from C++ (Patch by Miloslav Trmac).
+
+2003-06-15  Joe Shaw  <joe@assbarn.com>
+
+	* configure.in: Check for socklen_t.
+
+	* dbus/dbus-sysdeps.c: Define socklen_t if it's not defined.
+
+	* test/test-segfault.c: Add #include <sys/time.h>
+
+	* tools/Makefile.am: Add DBUS_X_CFLAGS to the INCLUDES since
+	dbus-launch needs it.
+
+2003-06-09  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_listen_unix_socket): don't use
+	SUN_LEN, it breaks abstract socket usage
+
+	* dbus/dbus-internals.c (_dbus_verbose_real): only print PID at
+	starts of lines.
+
+2003-06-04  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-server.c (dbus_server_listen): allow abstract sockets
+	using unix:abstract=/foo, and when listening in a tmpdir
+	i.e. unix:tmpdir=/tmp, always use abstract sockets if we can.
+
+	* dbus/dbus-transport.c (_dbus_transport_open): support
+	unix:abstract=/foo
+
+	* dbus/dbus-server-unix.c (_dbus_server_new_for_domain_socket):
+	support abstract sockets
+
+	* dbus/dbus-transport-unix.c
+	(_dbus_transport_new_for_domain_socket): support abstract sockets
+
+	* dbus/dbus-sysdeps.c (_dbus_connect_unix_socket): add "abstract"
+	toggle as an argument, implement abstract namespace support
+	(_dbus_listen_unix_socket): ditto
+
+	* configure.in: add --enable-abstract-sockets and implement
+	a configure check for autodetection of the right value.
+
+2003-06-01  Havoc Pennington  <hp@pobox.com>
+
+	* tools/dbus-cleanup-sockets.c: add utility to clean up sockets
+	in /tmp (though on Linux this will end up being useless,
+	when we add abstract namespace support)
+
+	* configure.in: define DBUS_SESSION_SOCKET_DIR in addition to
+	subst'ing it
+
+2003-05-28  Colin Walters  <walters@verbum.org>
+
+	* tools/dbus-monitor.c (main): Fix silly typo (s/--session/--system/).
+
+2003-05-18  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-message.c (dbus_message_new): Remove @todo.
+
+2003-05-17  Colin Walters  <walters@gnu.org>
+
+	* tools/dbus-send.c: Don't exit with an error code if --help was
+	passed.  Default to using the session bus instead of the system
+	one.
+
+	* tools/dbus-launch.c: Ditto.
+
+	* tools/dbus-monitor.c: Ditto.
+
+	* tools/dbus-send.1: Update with new arguments.
+
+	* tools/dbus-launch.c: Emit code to export variables.  New
+	arguments -s and -c to specify shell syntax, and a bit of code to
+	autodetect syntax.  Also, allow specifying a program to run.
+
+	* tools/dbus-launch.1: Update with new arguments.
+
+	* tools/dbus-send.1: Ditto.
+
+	* tools/dbus-monitor.1: Ditto.
+
+2003-05-17  Havoc Pennington  <hp@pobox.com>
+
+	* bus/config-parser.c (merge_included): merge in policies from
+	child configuration file.
+
+	* bus/policy.c (bus_policy_merge): function to merge two policies
+	together
+
+2003-05-16  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c: disable verbose lock spew
+
+	* tools/dbus-send.c: add --print-reply command line option
+
+	* tools/dbus-print-message.h (print_message): new util function
+	shared by dbus-send and dbus-monitor
+
+	* tools/dbus-monitor.c (handler_func): exit on disconnect
+
+	* dbus/dbus-transport-unix.c (do_reading): if the transport is
+	disconnected, don't try to use the read_watch
+
+	* dbus/dbus-watch.c (dbus_watch_get_enabled): assert watch != NULL
+	so we can find this bug more easily
+
+2003-05-16  Havoc Pennington  <hp@redhat.com>
+
+	* bus/policy.c (free_rule_list_func): avoid a crash when passed
+	NULL as DBusHashTable is annoyingly likely to do.
+
+2003-05-16  Colin Walters  <walters@verbum.org>
+
+	* tools/dbus-monitor.c: Add --session argument and usage()
+	function.
+
+	* tools/dbus-monitor.1: Update with new --session arg.
+
+	* bus/Makefile.am (install-data-hook): Create
+	$(libdir)/dbus-1.0/services so that the session bus is happy.
+
+2003-05-15  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_atomic_dec, _dbus_atomic_inc): work
+	on non-x86. ifdef's are evil.
+
+2003-05-15  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: 0.11
+
+	* NEWS: update
+
+	* bus/Makefile.am (initddir): apparently we are supposed to put
+	init scripts in /etc/rc.d/init.d not /etc/init.d
+
+	* bus/Makefile.am: remove the "you must --enable-tests to make
+	check" as it broke distcheck
+
+	* bus/Makefile.am (install-data-hook): create /etc/dbus-1/system.d
+
+2003-05-13  James Willcox  <jwillcox@gnome.org>
+
+	* configure.in:
+	* bus/activation.c: (bus_activation_service_created),
+	(bus_activation_activate_service):
+	* bus/driver.c: (bus_driver_send_service_deleted),
+	(bus_driver_send_service_created), (bus_driver_send_service_lost),
+	(bus_driver_send_service_acquired),
+	(bus_driver_send_welcome_message),
+	(bus_driver_handle_list_services):
+	* bus/session.conf.in:
+	* dbus/dbus-bus.c: (dbus_bus_acquire_service),
+	(dbus_bus_service_exists), (dbus_bus_activate_service):
+	* dbus/dbus-bus.h:
+
+	Add some convenience API which lets you activate a service, and did a
+	bunch of s/0/DBUS_TYPE_INVALID/ in calls to dbus_message_append_args()
+	and dbus_message_get_args()
+
+2003-05-11  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-marshal.c (_dbus_marshal_validate_arg): fix to avoid
+	calling _dbus_marshal_validate_arg() for every byte in a byte
+	array, etc.
+
+	* dbus/dbus-message-handler.c: use atomic reference counting to
+	reduce number of locks slightly; the global lock in here sucks
+
+	* dbus/dbus-connection.c
+	(_dbus_connection_update_dispatch_status_and_unlock): variant of
+	update_dispatch_status that can be called with lock held; then use
+	in a couple places to reduce locking/unlocking
+	(dbus_connection_send): hold the lock over the whole function
+	instead of acquiring it twice.
+
+	* dbus/dbus-timeout.c (_dbus_timeout_new): handle OOM
+
+	* bus/connection.c (bus_connections_setup_connection): fix access
+	to already-freed memory.
+
+	* dbus/dbus-connection.c: keep a little cache of linked list
+	nodes, to avoid using the global linked list alloc lock in the
+	normal send-message case. Instead we just use the connection lock
+	that we already have to take.
+
+	* dbus/dbus-list.c (_dbus_list_find_last): new function
+
+	* dbus/dbus-sysdeps.c (_dbus_atomic_inc, _dbus_atomic_dec):
+	change to use a struct for the atomic type; fix docs,
+	they return value before increment, not after increment.
+
+	* dbus/dbus-string.c (_dbus_string_append_4_aligned)
+	(_dbus_string_append_8_aligned): new functions to try to
+	microoptimize this operation.
+	(reallocate_for_length): break this out of set_length(), to
+	improve profile info, and also so we can consider inlining the
+	set_length() part.
+
+	* dbus/dbus-message.c (dbus_message_new_empty_header): init data
+	strings with some preallocation, cuts down on our calls to realloc
+	a fair bit. Though if we can get the "move entire string to empty
+	string" optimization below to kick in here, it would be better.
+
+	* dbus/dbus-string.c (_dbus_string_move): just call
+	_dbus_string_move_len
+	(_dbus_string_move_len): add a special case for moving
+	an entire string into an empty string; we can just
+	swap the string data instead of doing any reallocs.
+	(_dbus_string_init_preallocated): new function
+
+2003-05-11  Havoc Pennington  <hp@pobox.com>
+
+	Write a "test-profile" that does echo client-server with threads;
+	profile reveals lock contention, memcpy/realloc of buffers, and
+	UTF-8 validation as hot spots. 20% of lock contention eliminated
+	with dbus_atomic_inc/dec implementation on x86.  Much remaining
+	contention is global mempool locks for GList and DBusList.
+
+	* dbus/dbus-sysdeps.c (_dbus_atomic_inc, _dbus_atomic_dec): add
+	x86 implementation
+
+	* dbus/dbus-connection.c (struct DBusConnection): use
+	dbus_atomic_t for the reference count
+
+	* dbus/dbus-message.c (struct DBusMessage): declare
+	dbus_atomic_t values as volatile
+
+	* configure.in: code to detect ability to use atomic integer
+	operations in assembly, from GLib patch
+
+	* dbus/dbus-internals.c (_dbus_verbose_real): call getpid every
+	time, tired of it being wrong in threads and forked processes
+
+	* glib/test-profile.c: a little program to bounce messages back
+	and forth between threads and eat CPU
+
+	* dbus/dbus-connection.c: add debug spew macros for debugging
+	thread locks; include config.h at top; fix deadlock in
+	dbus_connection_flush()
+
+2003-05-08  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-spawn.c: s/_exit/exit/ because it was keeping gcov
+	data from getting written, and there wasn't a good reason to
+	use _exit really.
+
+	* test/decode-gcov.c (mark_inside_dbus_build_tests): don't count
+	dbus_verbose lines in test coverage
+	(main): add list of functions sorted by # of untested blocks
+	to the coverage report
+
+	* dbus/dbus-mempool.c: put some test-only code in DBUS_BUILD_TESTS
+
+	* dbus/dbus-marshal.c (_dbus_marshal_test): extend test coverage
+
+	* dbus/dbus-message-handler.c (_dbus_message_handler_test):
+	extend test coverage
+
+	* test/data/auth/cancel.auth-script: test canceling an
+	authentication
+
+	* dbus/Makefile.am: remove dbus-server-debug.[hc] for now, as they
+	aren't used. in CVS history if we end up needing them.
+
+2003-05-04  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message-handler.c (_dbus_message_handler_test): add
+	unit test
+
+	* dbus/dbus-marshal.c (_dbus_demarshal_string_array): fix this
+	function, which assumed length was in # of strings, not bytes
+
+	* dbus/dbus-message.c (_dbus_message_test): add tests for some
+	missing coverage
+
+	* dbus/dbus-connection.c
+	(_dbus_connection_queue_received_message): disable function for
+	now, we are only using it in test mode
+
+	* dbus/dbus-message.c (_dbus_message_loader_queue_messages):
+	remove a mistaken FIXME
+
+2003-05-04  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c (dbus_connection_preallocate_send):
+	unlock mutex on successful return, patch from Anders Gustafsson
+
+2003-05-04  Havoc Pennington  <hp@pobox.com>
+
+	* dbus-glib-1.pc.in (Requires): fix dependencies, from
+	Anders Gustafsson
+
+2003-05-04  Havoc Pennington  <hp@pobox.com>
+
+	* tools/dbus-launch.c: implement
+
+	* bus/main.c (main), bus/bus.c (bus_context_new):
+	implement --print-pid and --fork
+
+2003-05-03  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-address.c (dbus_parse_address): fix bug when a key in
+	the address had no value, and add to test suite. Fix and
+	regression test from Miloslav Trmac
+
+2003-05-03  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-watch.c (dbus_watch_handle): warn and return if a
+	watch is invalid when handled
+
+	* tools/Makefile.am, tools/dbus-launch.c, tools/dbus-launch.1: add
+	dbus-launch utility to launch the bus from a shell script.  Didn't
+	actually implement dbus-launch yet, it's just a placeholder still.
+
+2003-05-03  Havoc Pennington  <hp@pobox.com>
+
+	* bus/Makefile.am, bus/dbus-daemon-1.1.in: man page for the
+	daemon; also documents daemon config file, so replaces
+	doc/config-file.txt. Corrected some stuff from config-file.txt in
+	the process of moving it.
+
+2003-05-03  Havoc Pennington  <hp@pobox.com>
+
+	* tools/Makefile.am, tools/dbus-send.1, tools/dbus-monitor.1:
+	add some man pages
+
+2003-05-03  Colin Walters  <walters@verbum.org>
+
+	* dbus/dbus-sysdeps.c (fill_user_info): Test against
+	DBUS_UID_UNSET to determine whether to do a uid lookup or not.
+
+	* Makefile.am: Update to use new .pc versioning scheme.
+
+2003-05-02  Havoc Pennington  <hp@redhat.com>
+
+	* bus/system.conf.in: allow send/receive to/from message bus
+	service
+
+2003-04-30  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: print a note when building with unit tests and
+	without assertions
+
+2003-04-30  Havoc Pennington  <hp@redhat.com>
+
+	* Makefile.am: add a check-local that complains if you didn't
+	configure with --enable-tests
+
+2003-04-29  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gmain.c: docs cleanups
+
+	* dbus/dbus-types.h: add docs on int64 types
+
+	* dbus/dbus-memory.c: fix docs to avoid putting private API in
+	public API docs section
+
+2003-04-29  Havoc Pennington  <hp@redhat.com>
+
+	* dbus-1.pc.in, dbus-glib-1.pc.in: rename these from
+	dbus-1.0.pc.in, dbus-glib-1.0.pc.in. As these change with the
+	parallel install API version, not with the D-BUS package version.
+
+	* HACKING: move some of README over here
+
+	* README: updates, and document API/ABI policy
+
+	* configure.in: reindentation
+
+2003-04-29  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus.h: add "you have to define DBUS_API_SUBJECT_TO_CHANGE
+	to use this library" to be sure people have the right
+	expectations.
+
+2003-04-28  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: add --enable-docs which by default is auto yes if
+	doxygen and db2html found, no otherwise; but can be forced on/off
+
+	* doc/Makefile.am: conditionalize whether to build docs on
+	--enable-docs
+
+2003-04-28  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: 0.10
+
+	* NEWS: update
+
+	* bus/system.conf.in: add <includedir>system.d</includedir>
+
+	* dbus/dbus-userdb.c (_dbus_user_database_lookup): fix bug when
+	username was provided but not uid
+
+	* bus/config-parser.c (struct BusConfigParser): keep track of
+	whether the parser is toplevel or was included; change some
+	of the error handling if it's included.
+
+2003-04-27  Havoc Pennington  <hp@pobox.com>
+
+	Unbreak my code...
+
+	* dbus/dbus-transport.c (_dbus_transport_get_dispatch_status):
+	report correct status if we finish processing authentication
+	inside this function.
+
+	* bus/activation.c (try_send_activation_failure): use
+	bus_transaction_send_error_reply
+
+	* bus/connection.c (bus_connection_get_groups): return an error
+	explaining the problem
+
+	* bus/bus.c (bus_context_check_security_policy): implement
+	restriction here that inactive connections can only send the
+	hello message. Also, allow bus driver to send anything to
+	any recipient.
+
+	* bus/connection.c (bus_connection_complete): create the
+	BusClientPolicy here instead of on-demand.
+	(bus_connection_get_policy): don't return an error
+
+	* dbus/dbus-message.c (dbus_message_new_error_reply): allow NULL
+	sender field in message being replied to
+
+	* bus/bus.c (bus_context_check_security_policy): fix silly typo
+	causing it to return FALSE always
+
+	* bus/policy.c (bus_client_policy_check_can_send): fix bug where
+	we checked sender rather than destination
+
+2003-04-25  Havoc Pennington  <hp@redhat.com>
+
+        test suite is slightly hosed at the moment, will fix soon
+
+	* bus/connection.c (bus_connections_expire_incomplete): fix to
+	properly disable the timeout when required
+	(bus_connection_set_name): check whether we can remove incomplete
+	connections timeout after we complete each connection.
+
+	* dbus/dbus-mainloop.c (check_timeout): fix this up a bit,
+	probably still broken.
+
+	* bus/services.c (bus_registry_acquire_service): implement max
+	number of services owned, and honor allow/deny rules on which
+	services a connection can own.
+
+	* bus/connection.c (bus_connection_get_policy): report errors here
+
+	* bus/activation.c: implement limit on number of pending
+	activations
+
+2003-04-25  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-transport.c (_dbus_transport_get_unix_user): fix bug
+	where we used >= 0 instead of != DBUS_UID_UNSET.
+
+2003-04-25  Havoc Pennington  <hp@redhat.com>
+
+	* glib/dbus-gmain.c (remove_watch): fix for a crash when watches
+	were toggled without add/remove, fix from Anders Gustafsson
+
+2003-04-24  Havoc Pennington  <hp@redhat.com>
+
+	* test/data/valid-config-files/basic.conf: add <limit> tags to
+	this test
+
+	* bus/config-parser.h, bus/config-parser.c, bus/bus.c: Implement
+	<limit> tag in configuration file.
+
+2003-04-24  Havoc Pennington  <hp@redhat.com>
+
+	* bus/dispatch.c: somehow missed some name_is
+
+	* dbus/dbus-timeout.c (_dbus_timeout_set_enabled)
+	(_dbus_timeout_set_interval): new
+
+	* bus/connection.c (bus_connections_setup_connection): record time
+	when each connection is first set up, and expire them after the
+	auth timeout passes.
+
+2003-04-24  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c (dbus_message_name_is): rename
+	(dbus_message_service_is): rename
+	(dbus_message_sender_is): rename
+	(dbus_message_get_service): rename
+
+2003-04-24  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: add --enable-checks
+
+	* dbus/dbus-message.c (dbus_message_new): reverse name/service arguments
+
+	* dbus/dbus-connection.c (dbus_connection_preallocate_send): fix
+	to use thread locks.
+	(_dbus_connection_handler_destroyed_locked): move some private
+	functions into proper docs group
+
+	* dbus/dbus-internals.h: add _dbus_return_if_fail,
+	_dbus_return_val_if_fail
+
+	Throughout: use dbus_return_if_fail
+
+2003-04-23  James Willcox  <jwillcox@gnome.org>
+
+	* glib/dbus-glib.h:
+	* glib/dbus-gmain.c: (add_timeout), (wakeup_main), (create_source),
+	(dbus_connection_setup_with_g_main),
+	(dbus_server_setup_with_g_main):
+	* glib/test-dbus-glib.c: (main):
+	* glib/test-thread-client.c: (main):
+	* glib/test-thread-server.c: (new_connection_callback), (main):
+	* tools/dbus-monitor.c: (main):
+
+	Added a GMainContext argument to dbus_connection_setup_with_g_main()
+	and dbus_server_setup_with_g_main().
+
+2003-04-20  Havoc Pennington  <hp@pobox.com>
+
+	* doc/dbus-specification.sgml: document the restrictions on
+	message and service names
+
+2003-04-22  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c, dbus/dbus-marshal.c: add 64-bit integer
+	support, and do some code cleanups to share more code and
+	speed up array marshal/demarshal.
+
+	* dbus-1.0.pc.in (Cflags): put libdir include file in cflags
+
+	* configure.in: generate dbus-arch-deps.h
+
+	* dbus/dbus-protocol.h (DBUS_TYPE_INT64, DBUS_TYPE_UINT64): add
+	64-bit typecodes
+
+2003-04-22  Havoc Pennington  <hp@redhat.com>
+
+	* test/data/valid-messages/opposite-endian.message: fix test
+	to use proper type for rply field
+
+        * test/data/invalid-messages: add tests for below validation
+
+	* dbus/dbus-message.c (decode_header_data): validate field types,
+	and validate that named fields are valid names
+	(decode_name_field): consider messages in the
+	org.freedesktop.Local. namespace to be invalid.
+
+	* dbus/dbus-string.c (_dbus_string_validate_name): new
+
+2003-04-19  Havoc Pennington  <hp@pobox.com>
+
+	* bus/driver.c (bus_driver_handle_hello): check limits and
+	return an error if they are exceeded.
+
+	* bus/connection.c: maintain separate lists of active and inactive
+	connections, and a count of each. Maintain count of completed
+	connections per user. Implement code to check connection limits.
+
+	* dbus/dbus-list.c (_dbus_list_unlink): export
+
+	* bus/bus.c (bus_context_check_security_policy): enforce a maximum
+	number of bytes in the message queue for a connection
+
+2003-04-18  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-auth.c (record_mechanisms): memleak fixes
+
+	* dbus/dbus-sysdeps.c (_dbus_string_save_to_file): fix some
+	memleaks
+
+	* dbus/dbus-keyring.c (add_new_key): fix a memleak, and
+	on realloc be sure to update the pointer in the keyring
+
+	* dbus/dbus-string.c (_dbus_string_zero): compensate for align
+	offset to avoid writing to unallocated memory
+
+	* dbus/dbus-auth.c (process_rejected): return FALSE if we fail to
+	try the next mechanism, so we properly handle OOM
+
+	* dbus/dbus-keyring.c (_dbus_keyring_new_homedir): fix double-free
+	on OOM.
+	(_dbus_keyring_new): fix OOM bug
+	(_dbus_keyring_new_homedir): always set error; impose a maximum
+	number of keys we'll load from the file, mostly to speed up the
+	test suite and make its OOM checks more useful, but also for
+	general sanity.
+
+	* dbus/dbus-auth.c (process_error_server): reject authentication
+	if we get an error from the client
+	(process_cancel): on cancel, send REJECTED, per the spec
+	(process_error_client): send CANCEL if we get an error from the
+	server.
+
+2003-04-18  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-mainloop.c (_dbus_loop_iterate): fix UMR in verbose
+	debug spew
+
+	* dbus/dbus-auth.c (handle_client_data_cookie_sha1_mech): fix OOM
+	handling problem
+
+	* dbus/dbus-keyring.c (_dbus_keyring_new_homedir): only whine
+	about DBUS_TEST_HOMEDIR once
+
+	* bus/Makefile.am (TESTS_ENVIRONMENT): put DBUS_TEST_HOMEDIR in
+	the environment
+
+	* bus/dispatch.c (bus_dispatch_sha1_test): actually load sha1
+	config file so we test the right thing
+
+	Throughout: assorted docs improvements
+
+2003-04-18  Havoc Pennington  <hp@pobox.com>
+
+	* glib/dbus-gmain.c: adapt to watch changes
+
+	* bus/bus.c, bus/activation.c, etc.: adjust to watch changes
+
+	* dbus/dbus-server.h: remove dbus_server_handle_watch
+
+	* dbus/dbus-connection.h: remove dbus_connection_handle_watch
+
+	* dbus/dbus-watch.c (dbus_watch_handle): change DBusWatch to work
+	like DBusTimeout, so we don't need dbus_connection_handle_watch
+	etc.
+
+2003-04-17  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-userdb.c, dbus/dbus-sysdeps.c: redo all the passwd
+	database usage so it all goes via the DBusUserDatabase cache.
+
+2003-04-17  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-mainloop.c (_dbus_loop_iterate): fix logic so that if
+	there was an OOM watch we skipped, we always return TRUE so we
+	iterate again to have a look at it again. Fixes test suite hang.
+	Code rearrangement also lets us lose some memset and only iterate
+	over callbacks once.
+
+	* bus/driver.c (bus_driver_handle_message): sense of test for
+	reply was backward
+
+2003-04-16  Havoc Pennington  <hp@pobox.com>
+
+	* doc/dbus-specification.sgml: make spec say serials are unsigned
+
+	* dbus/dbus-message.h: change message serials to unsigned
+
+	* dbus/dbus-connection.c: adapt to message serials being unsigned
+
+2003-04-15  Havoc Pennington  <hp@pobox.com>
+
+	* bus/bus.c: create and keep around a shared DBusUserDatabase
+	object.
+
+	* bus/connection.c (bus_connection_get_groups): don't cache
+	groups for user in the connection object, since user database
+	object now does that.
+
+2003-04-16  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c (_dbus_message_add_size_counter): keep a
+	list of size counters
+	(_dbus_message_loader_putback_message_link): put back a popped link
+
+	* dbus/dbus-connection.c
+	(dbus_connection_set_max_live_messages_size): rename
+	max_received_size
+	(dbus_connection_get_outgoing_size): get size of outgoing
+	queue
+	(_dbus_connection_set_connection_counter): remove this cruft
+
+2003-04-14  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-userdb.c: user database abstraction, mostly to get
+	caching, but at some point we might want to be able to use a
+	different database.
+
+	* bus/dispatch.c (bus_dispatch_sha1_test): add a test that uses
+	SHA1 conf file to test the sha1 auth mechanism, since the regular
+	test always uses EXTERNAL when available.
+
+	* configure.in,
+	test/data/valid-config-files/debug-allow-all-sha1.conf.in:
+	add conf file that requires use of sha1 auth
+
+2003-04-13  Havoc Pennington  <hp@pobox.com>
+
+        * tools/dbus-send.c, tools/dbus-monitor.c: two utility programs
+	from Philip Blundell to send messages and monitor them.
+
+2003-04-13  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-mainloop.c: fix some reentrancy issues by refcounting
+	callbacks
+
+	* test/data/valid-config-files/debug-allow-all.conf.in: allow all
+	users
+
+	* dbus/dbus-transport.c (_dbus_transport_get_dispatch_status):
+	fix to only recover unused bytes if we're already authenticated
+	(_dbus_transport_get_is_authenticated): fix to still mark us
+	authenticated if there are unused bytes.
+
+	* bus/dispatch.c: implement security policy checking
+
+	* bus/connection.c (bus_transaction_send_from_driver): new
+
+	* bus/bus.c (bus_context_check_security_policy): new
+
+	* bus/dispatch.c (send_service_nonexistent_error): delete this,
+	now we just set the DBusError and it gets converted to an error
+	reply.
+
+	* bus/connection.c (allow_user_function): enable code using actual
+	data from the config file
+
+	* bus/policy.c (list_allows_user): handle wildcard rules for
+	user/group connection perms
+
+2003-04-13  Havoc Pennington  <hp@pobox.com>
+
+	* bus/config-parser.c: Load up the BusPolicy and BusPolicyRules
+
+	* dbus/dbus-sysdeps.c (_dbus_get_user_id): new function
+
+	* bus/policy.c (bus_policy_append_mandatory_rule)
+	(bus_policy_append_default_rule, bus_policy_append_user_rule)
+	(bus_policy_append_group_rule): new functions
+
+2003-04-12  Havoc Pennington  <hp@pobox.com>
+
+	* bus/config-parser.c (bus_config_parser_new): fix a memleak
+
+	* dbus/dbus-sysdeps.c: change DBusCredentials to use longs for
+	the pid/gid/uid, just for paranoia.
+
+	* test/break-loader.c (randomly_do_n_things): find a byte
+	containing a type code, and randomly change it to a different
+	type code.
+
+2003-04-12  Havoc Pennington  <hp@pobox.com>
+
+	* bus/policy.h: change BusPolicy to be the thing from the config
+	file, and rename old BusPolicy to BusClientPolicy
+
+	* bus/bus.c, bus/connection.c, bus/config-parser.c: change to
+	match change in how policy works
+
+	* dbus/dbus-internals.h: mark assert_not_reached as
+	__attribute((noreturn))__
+
+2003-04-11  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.sgml: fix a spot with the wrong name for
+	the broadcast service. Use boolean return for ServiceExists.
+
+2003-04-11  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: add another directory to look for qt in.
+
+2003-04-11  Havoc Pennington  <hp@redhat.com>
+
+	* AUTHORS: add Colin Walters
+
+2003-04-11  Havoc Pennington  <hp@redhat.com>
+
+	* NEWS: update
+
+	* configure.in: 0.9
+
+2003-04-11  Havoc Pennington  <hp@redhat.com>
+
+	* bus/messagebus.in: remove pid file when stopping the
+	message bus, since the bus won't have privileges to remove it
+	itself.
+
+2003-04-11  Havoc Pennington  <hp@redhat.com>
+
+	* bus/bus.c (bus_context_new): move credentials change after
+	creating pidfile
+
+2003-04-11  Havoc Pennington  <hp@pobox.com>
+
+	* test/decode-gcov.c: add "below average functions" to the
+	coverage report, and change how some of the code works.
+
+	* bus/test-main.c: bracket some stuff in DBUS_BUILD_TESTS so it's
+	not in the coverage stats.
+
+	* test/test-service.c (main): use _dbus_verbose not fprintf in a
+	couple places so running the test suite doesn't result in megaspam.
+
+2003-04-11  Havoc Pennington  <hp@pobox.com>
+
+	* bus/dispatch.c (check_existent_service_activation): accept a no
+	memory error in a place we didn't before
+
+	* bus/test.c (bus_test_run_everything): remove hacky "do it twice
+	in case the first one failed," since the test suite is less
+	broken now.
+
+2003-04-10  Havoc Pennington  <hp@pobox.com>
+
+	* bus/dispatch.c (check_segfault_service_activation): add test
+	for launching an executable that just crashes.
+
+	* test/test-segfault.c (main): try setting coredumpsize to 0 so we
+	don't leave a million cores. We'll see how portable this is.
+
+2003-04-10  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-spawn.c (_dbus_spawn_async_with_babysitter): move all
+	the possible parent failures before we fork, so that we don't
+	fail to create a babysitter after creating the child.
+
+	* bus/activation.c (bus_activation_activate_service): kill child
+	if we don't successfully complete the activation.
+
+2003-04-10  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c (dbus_connection_flush): don't spin on
+	the connection if it's disconnected
+
+	* bus/activation.c (bus_activation_service_created): use new
+	transaction features to roll back removal of pending activation if
+	we don't successfully create the service after all. Don't remove
+	pending activation if the function fails.
+
+	* dbus/dbus-list.c (_dbus_list_insert_before_link)
+	(_dbus_list_insert_after_link): new code to facilitate
+	services.c fixes
+
+	* dbus/dbus-hash.c (_dbus_hash_table_insert_string_preallocated):
+	new functionality, so we can preallocate the ability to insert
+	into a hash table.
+
+	* bus/connection.c (bus_transaction_add_cancel_hook): new function
+	allowing us to put custom hooks in a transaction to be used for
+	cancelling said transaction
+
+	* doc/dbus-specification.sgml: add some discussion of secondary
+	service owners, and disallow zero-length service names
+
+	* bus/services.c (bus_registry_acquire_service): new function,
+	splits out part of bus_driver_handle_acquire_service() and fixes
+	a bug where we didn't remove the service doing the acquiring
+	from the secondary queue if we failed to remove the current owner
+	from the front of the queue.
+
+2003-04-10  Alexander Larsson  <alexl@redhat.com>
+
+	* doc/dbus-specification.sgml:
+	s/org.freedesktop.Broadcast/org.freedesktop.DBus.Broadcast/
+
+2003-04-10  Alexander Larsson  <alexl@redhat.com>
+
+	* bus/.cvsignore:
+	* glib/.cvsignore:
+	* test/.cvsignore:
+	Added files to cvsignore
+
+	* dbus/dbus-message.h:
+	* dbus/dbus-message.c: (dbus_message_iter_get_named):
+	Make get_named() take two out argument and return a boolean.
+	(dbus_message_iter_get_args_valist):
+	Update usage of get_named().
+	(dbus_message_iter_append_byte):
+	Fix typo
+	(dbus_message_iter_append_named)
+	Fix typo
+	(message_iter_test), (check_message_handling_type), (_dbus_message_test):
+	More tests.
+
+2003-04-10  Alexander Larsson  <alexl@redhat.com>
+
+	* dbus/dbus-marshal.[ch]:
+	Add array_type_pos argument to _dbus_marshal_validate_arg.
+	Let you pass a NULL end_pos to _dbus_marshal_validate_type.
+
+	* dbus/dbus-message.[ch]:
+	Multi-dimensional arrays have full type specification in the
+	outermost array. Iter code re-arranged to handle this.
+	Added some more iter tests.
+
+	* doc/dbus-specification.sgml:
+	Add me to authors.
+	Remove old FIXME.
+	Update new array encoding description.
+	Correct DBUS_SERVICE_FLAGS_REPLACE_EXISTING description.
+
+	* test/data/invalid-messages/array-with-mixed-types.message:
+	* test/data/valid-messages/array-of-array-of-uint32.message:
+	Change to the new array format.
+
+	* test/data/invalid-messages/too-short-dict.message:
+	Fix bug in test.
+
+	* test/data/valid-messages/recursive-types.message:
+	Fix up and extend test.
+
+2003-04-10  Havoc Pennington  <hp@pobox.com>
+
+	* bus/dispatch.c: lots of fixes
+
+	* dbus/dbus-mainloop.c (_dbus_loop_dispatch): export
+	(_dbus_loop_iterate): remove old "quit if no callbacks" code,
+	that was crack, broke the test service.
+
+	* dbus/dbus-transport.c (_dbus_transport_open): fix error
+	handling to avoid piling up errors if we get a failure on the
+	first address.
+
+	* dbus/dbus-internals.c (_dbus_real_assert_not_reached): include
+	pid in assertion failures.
+
+	* dbus/dbus-mainloop.c (_dbus_loop_iterate): use static arrays up
+	to some fixed size of file descriptor array. Don't return TRUE
+	anytime a timeout exists, that led to lots of busy loop silliness
+	in the tests.
+
+2003-04-09  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-mainloop.c (check_timeout): fix timeouts, I thought
+	I'd checked this in earlier but hadn't.
+
+2003-04-09  Havoc Pennington  <hp@redhat.com>
+
+	* bus/dispatch.c (bus_dispatch_test): get a bit further through
+	the activation test (man this is getting old!)
+
+2003-04-09  Havoc Pennington  <hp@redhat.com>
+
+	* test/test-utils.c: use dispatch status function to fix this up
+
+	* bus/connection.c (connection_watch_callback): don't dispatch
+	from here
+	(connection_timeout_callback): don't dispatch from here
+	(bus_connections_setup_connection): set the dispatch status function
+	(bus_connection_disconnected): unset it
+
+	* dbus/dbus-mainloop.c (_dbus_loop_queue_dispatch): new function
+	used to add a connection to be dispatched
+	(_dbus_loop_iterate): do the dispatching at the end of each
+	iteration
+
+	* dbus/dbus-connection.c
+	(dbus_connection_set_dispatch_status_function): new function
+	allowing us to fix up main loop usage
+	(_dbus_connection_last_unref): free all the various function
+	user data
+	(dbus_connection_dispatch): call the DispatchStatusFunction
+	whenever this function returns
+	(dbus_connection_handle_watch): call DispatchStatusFunction
+	(dbus_connection_send_with_reply_and_block): call DispatchStatusFunction
+	(reply_handler_timeout): call DispatchStatusFunction
+	(dbus_connection_flush): call DispatchStatusFunction
+
+2003-04-09  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-bus.c (dbus_bus_register): fix up error handling and
+	a memory leak
+
+	* bus/dispatch.c (check_service_activated): fix bug in test
+
+	* dbus/dbus-mainloop.c (check_timeout): fix this up
+
+	* dbus/dbus-internals.c (_dbus_verbose_real): include PID in
+	verbose output so we can sort out output from different processes,
+	e.g. in the activation case.
+
+2003-04-08  Colin Walters  <walters@gnu.org>
+
+ 	* bus/bus.c (struct BusContext) [pidfile]: New member, to store
+ 	the pid file.
+ 	(bus_context_new): Set it.
+ 	(bus_context_unref): Use it to delete the pid file.
+
+2003-04-08  Havoc Pennington  <hp@redhat.com>
+
+	* test/data/invalid-messages/array-with-mixed-types.message:
+	regression test that fails for the moment
+
+	* dbus/dbus-test.c (dbus_internal_do_not_use_run_tests): reorder
+	tests for convenience
+
+	* dbus/dbus-marshal.c (_dbus_marshal_validate_arg): don't allow
+	array of nil, it broke things.
+
+	* test/data/invalid-messages/array-of-nil.message: regression test
+
+	* test/data/valid-messages/array-of-array-of-uint32.message:
+	happened to write this so added it to suite
+
+2003-04-08  Havoc Pennington  <hp@redhat.com>
+
+	* bus/driver.c (bus_driver_handle_acquire_service): init
+	retval/reply before checking name
+
+	* dbus/dbus-marshal.c (_dbus_marshal_validate_arg): add a
+	recursion depth argument
+
+	* dbus/dbus-message.h (struct DBusMessageIter): put some padding
+	in the public struct for future extension
+
+	* dbus/dbus-message-builder.c (_dbus_message_data_load): fix
+	typo
+
+	* dbus/dbus-marshal.c (_dbus_marshal_validate_arg): fix a verbose
+	message
+
+	* doc/dbus-specification.sgml: fix typo
+
+2003-04-08  Alexander Larsson  <alexl@redhat.com>
+
+	Implemented recursive types, named types and new-style iters
+
+	* bus/driver.c:
+	* glib/test-thread-client.c: (thread_func):
+	* glib/test-thread-server.c: (handle_test_message):
+	* test/test-service.c: (handle_echo):
+	Update to new api
+
+	* dbus/Makefile.am:
+	* dbus/dbus-dict.c:
+	* dbus/dbus-dict.h:
+	* dbus/dbus.h
+	Remove DBusDict
+
+	* dbus/dbus-internals.c: (_dbus_type_to_string):
+	Update for new types.
+
+	* dbus/dbus-marshal.[ch]:
+	Implement recursive types and the new marshalling format.
+	Remove hardcoded dict marshalling.
+	Marshal named types.
+
+	* dbus/dbus-message-builder.c:
+	Add BYTE_ARRAY.
+	Remove references to old types
+
+	* dbus/dbus-message.[ch]:
+	New non-refcounted iter API that supports recursive iters.
+	Use iters for appending, including support for recursive
+	iters.
+	Add byte and named type support.
+	Update everything to new marshalling formats.
+	Add tests for new API.
+
+	* dbus/dbus-protocol.h:
+	Remove old array types.
+	Add types: BYTE, ARRAY, DICT, NAMED
+
+	* dbus/dbus-string.c:
+	* dbus/dbus-sysdeps.c:
+	Make parse_double locale safe.
+
+	* dbus/dbus-test-main.c:
+	Call setlocale.
+
+	* dbus/dbus-test.c:
+	Kill dict test
+
+	* doc/dbus-specification.sgml:
+	Update spec
+
+	* test/data/incomplete-messages/missing-body.message:
+	* test/data/invalid-messages/bad-boolean.message:
+	* test/data/invalid-messages/bad-boolean-array.message:
+	* test/data/invalid-messages/boolean-array-length-too-long.message-raw:
+	* test/data/invalid-messages/boolean-has-no-value.message-raw:
+	* test/data/invalid-messages/too-short-dict.message:
+	* test/data/valid-messages/dict-simple.message:
+	* test/data/valid-messages/dict.message:
+	* test/data/valid-messages/emptiness.message:
+	* test/data/valid-messages/lots-of-arguments.message:
+	* test/data/valid-messages/no-padding.message:
+	* test/data/valid-messages/recursive-types.message:
+	Add missing NAME fields
+	Fix up dicts & arrays
+
+	* test/data/invalid-messages/dict-with-nil-value.message:
+	Removed, this is not invalid anymore.
+
+	* test/data/valid-messages/recursive-types.message:
+	Add new test for deeply recursive types.
+
+2003-04-07  Havoc Pennington  <hp@pobox.com>
+
+	* bus/driver.c (bus_driver_handle_acquire_service): return an
+	error if you try to acquire a service that starts with ':'
+
+2003-04-07  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.sgml: require that base service names
+	start with ':' and that the base service is created/deleted
+	as first and last things a connection does on the bus
+
+	* bus/dispatch.c (check_existent_service_activation): lots more
+	work on the activation test; it doesn't fully pass yet...
+
+	* test/test-service.c (main): fix so we don't memleak the
+	connection to the message bus
+	(filter_func): accept a message asking us to exit
+
+2003-04-06  Havoc Pennington  <hp@pobox.com>
+
+	* qt/Makefile.am (dbusinclude_HEADERS): install dbus-qt.h,
+	from Colin Walters
+
+	* configure.in: fixes to Qt detection from Colin Walters
+
+	* doc/Makefile.am: Only remove generated docbook dirs if they
+	exist, from Colin Walters
+
+	* dbus/dbus-bus.c: change how we set well-known connections to
+	NULL, so that it works if a single connection is stored in
+	two well-known array slots.
+
+	* test/Makefile.am: remove a lot of stuff that isn't immediately
+	useful, it's in CVS history if we want it.
+
+	* test/test-service.c: use dbus-mainloop instead of that
+	watch.[hc] crack
+
+2003-04-06  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/Makefile.am: split lists of sources into stuff that goes in
+	the library, util functions that go in the lib and are also used
+	elsewhere, and util functions that are used in tests/daemon but
+	don't go in the lib.
+
+	* dbus/dbus-mainloop.h, dbus/dbus-mainloop.c: move bus/loop.[hc]
+	here so it can be used in test binaries also
+
+2003-04-06  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_become_daemon): write the pidfile
+	here in the parent process, so we can return an error if it
+	fails. Also, move some of the code into the child so the parent
+	is less hosed if we fail midway through.
+
+	* bus/bus.c (bus_context_new): move pidfile detection further up
+	in the function, before we start overwriting sockets and such.
+
+	* bus/messagebus.in: adjust this a bit, not sure if it will work.
+
+	* configure.in: add --with-system-pid-file and --with-system-socket
+
+2003-04-06  Colin Walters  <walters@verbum.org>
+
+	* configure.in (DBUS_SYSTEM_PID_FILE): New variable.
+
+	* bus/system.conf.in: Declare a pidfile.
+
+	* bus/bus.c (bus_context_new): Test for an existing pid file, and
+	create one (if appropriate).
+
+	* bus/config-parser.c (enum ElementType) [ELEMENT_PIDFILE]: New.
+	(struct BusConfigParser) [pidfile]: New.
+	(element_type_to_name, merge_included, start_busconfig_child)
+	(bus_config_parser_end_element, bus_config_parser_content): Handle it.
+	(bus_config_parser_unref): Free it.
+	(bus_config_parser_get_pidfile): New function.
+
+	* bus/config-parser.h (_dbus_write_pid_file): Prototype.
+
+	* dbus/dbus-errors.h (DBUS_ERROR_PIDFILE_EXISTS): New error.
+
+	* dbus/dbus-sysdeps.c (_dbus_write_pid_file): New function.
+
+	* dbus/dbus-sysdeps.h: Prototype it.
+
+2003-04-06  Havoc Pennington  <hp@pobox.com>
+
+	* bus/bus.c (bus_context_new): print the address in here, rather
+	than in main(), because we need to do it before forking the daemon
+
+	* bus/dispatch.c (send_service_nonexistent_error): set the sender
+	on the service nonexistent error
+
+	* bus/driver.c (bus_driver_handle_acquire_service): set the
+	sender on the AcquireService reply
+
+	* test/data/valid-config-files/debug-allow-all.conf.in: Make test
+	server also listen on a UNIX socket so services can connect to it.
+
+2003-04-06  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-threads.c: Redo how the fake debug mutexes are done
+	so it detects deadlocks and also we actually init threads when
+	debugging.
+
+2003-04-06  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-server-unix.c (_dbus_server_new_for_domain_socket):
+	save the domain socket name, and unlink it when we disconnect the
+	server. Means that at least when we exit normally, we won't leave
+	a bunch of junk in /tmp
+
+	* dbus/dbus-transport-unix.c
+	(_dbus_transport_new_for_domain_socket): code cleanup (nicer
+	memory management). (I was making a real change here but then
+	didn't)
+
+2003-04-06  Havoc Pennington  <hp@pobox.com>
+
+	* bus/bus.c (bus_context_new): fix wrong handling of
+	server_data_slot_unref() in the error case.
+
+	* dbus/dbus-internals.h (_dbus_assert): change so it passes
+	"(condition) != 0" to _dbus_real_assert so that
+	"_dbus_assert (pointer)" doesn't cause a warning
+
+	* bus/main.c (main): accept --print-address option to print out
+	the message bus address
+
+	* dbus/dbus-sysdeps.c (_dbus_generate_random_ascii): export this
+
+	* dbus/dbus-transport.c (_dbus_transport_open): special error for
+	"tmpdir" option to unix: address on client side
+
+	* dbus/dbus-server.c (dbus_server_listen): handle "tmpdir" option
+	to unix: address
+
+	* configure.in (TEST_SOCKET_DIR): locate a temporary directory
+	we can use to create sockets in the test suite.
+
+	* bus/main.c (signal_handler): on SIGTERM, exit the daemon
+	cleanly. To be used for testing.
+
+	* dbus/dbus-spawn.c (babysit): use _dbus_set_signal_handler()
+
+	* dbus/dbus-sysdeps.c (_dbus_set_signal_handler): new
+
+	* dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new):
+	handle trying to call this when there's no servers active
+
+2003-04-05  Havoc Pennington  <hp@pobox.com>
+
+	* NEWS: update
+
+	* configure.in: 0.8
+
+2003-04-05  Havoc Pennington  <hp@pobox.com>
+
+	* bus/bus.c (setup_server): fix this so dbus-daemon-1 doesn't
+	crash on startup. Need to get "try starting the daemon"
+	in the test suite I guess. ;-)
+
+	* dbus/dbus-server.h, dbus/dbus-server.c: remove the stuff that
+	tracked the number of open connections; it's better done in
+	application-specific code as you want it to span all servers etc.
+
+2003-04-05  Havoc Pennington  <hp@pobox.com>
+
+	* bus/Makefile.am (install-data-hook): add missing DESTDIR,
+	patch from Colin Walters
+
+2003-04-05  Havoc Pennington  <hp@pobox.com>
+
+	* doc/config-file.txt (Elements): fix docs of <auth> to reflect
+	reality; in fact multiple mechanisms are allowed.
+
+	* dbus/dbus-internals.c (_dbus_real_assert)
+	(_dbus_real_assert_not_reached): move guts of _dbus_assert() and
+	_dbus_assert_not_reached() into functions, so that they don't show
+	up in basic block counts for test coverage, and don't use up as
+	much disk space. Does mean slower execution speed though, so
+	assumes --disable-asserts is the normal production case.
+
+2003-04-05  Havoc Pennington  <hp@pobox.com>
+
+	* test/Makefile.am (dist-hook): also dist *.in files
+
+	* NEWS: update
+
+	* configure.in: 0.7
+
+2003-04-05  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-string.c: docs warning
+
+	* dbus/dbus-spawn.c: missing docs
+
+	* dbus/dbus-memory.c (struct ShutdownClosure): missing docs
+
+2003-04-05  Havoc Pennington  <hp@pobox.com>
+
+	* bus/loop.c (bus_loop_iterate): fix the timeout code, using
+	magic from GLib
+
+	* dbus/dbus-spawn.c (_dbus_babysitter_unref): set sitter_pid
+	to -1 once we've reaped the babysitter
+	(_dbus_babysitter_handle_watch): do as much work as we can, not
+	just one go of it
+
+	* bus/activation.c: add code using DBusBabysitter so that we
+	handle it when a service fails to start up properly.
+	(bus_activation_service_created): don't remove the activation
+	entries as we go, just let them get removed when we free the pending
+	activation. Unref reply messages after sending them.
+
+2003-04-05  Havoc Pennington  <hp@pobox.com>
+
+	* test/decode-gcov.c (main): print per-directory stats in the report
+
+	* Makefile.am (coverage-report.txt): don't include test/* in gcov stats
+
+2003-04-05  Havoc Pennington  <hp@pobox.com>
+
+	* Makefile.am (coverage-report.txt): add target "coverage-report.txt"
+
+	* test/decode-gcov.c: hack up a little program to suck data
+	out of gcov files. Yes this is sort of silly.
+
+	* configure.in: define something in config.h and do an
+	AM_CONDITIONAL when gcov is enabled
+
+2003-04-04  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-spawn.c, dbus/dbus-spawn.h: Change dbus_spawn to
+	return a "babysitter" object that is used to monitor the status of
+	the spawned process and reap it when required.
+
+	* test/test-segfault.c, test/test-exit.c,
+	test/test-sleep-forever.c: binaries that do various lame things,
+	used in the test suite.
+
+	* dbus/dbus-sysdeps.c: kill _dbus_errno_to_string()
+
+2003-04-03  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-spawn.c: Move dbus-spawn into a separate file
+	in preparation for modifying it, dbus-sysdeps is getting
+	a bit unmanageable.
+
+2003-04-03  Havoc Pennington  <hp@redhat.com>
+
+	* bus/loop.h, bus/loop.c: make the mainloop an object so we can
+	have multiple ones
+
+	* bus/*.[hc]: adapt to mainloop change
+
+2003-04-03  Havoc Pennington  <hp@redhat.com>
+
+	* bus/activation.c (load_directory): fix up memleaks
+	(bus_activation_entry_free): free the entry
+
+	* dbus/dbus-bus.c (dbus_bus_acquire_service): return an error if
+	we get one from the message bus; fix memleaks.
+
+	* dbus/dbus-message.c (dbus_set_error_from_message): new function
+
+2003-04-03  Havoc Pennington  <hp@pobox.com>
+
+	* bus/config-parser.c (bus_config_parser_unref): free
+	list of mechanisms, bug discovered by test suite enhancements
+	(putting system.conf and session.conf into suite)
+
+	* test/Makefile.am, test/test-service.c: add placeholder for a
+	test service that we'll activate as part of test suite. Doesn't
+	do anything yet.
+
+	* dbus/dbus-sysdeps.c (_dbus_setenv): support unsetenv by
+	setting NULL value, and use system malloc not dbus_malloc()
+	when we have unavoidable memleakage.
+
+	* dbus/dbus-bus.c (dbus_bus_get): fix bug where bus type of 0
+	didn't work, and support DBUS_BUS_ACTIVATION.
+
+	* bus/activation.c (child_setup): pass our well-known bus type to
+	the child
+
+	* bus/config-parser.c: support <type> to specify well-known type
+
+	* doc/dbus-specification.sgml: document the env variables to
+	locate well-known buses and find service activator
+
+2003-04-02  Havoc Pennington  <hp@redhat.com>
+
+	* test/Makefile.am (all-local): add a rule to copy tests to
+	builddir, so we can have generated tests. Use this to remove the
+	silly hack for testing system.conf and session.conf. Will use this
+	shortly to generate .service files pointing to test binaries.
+
+2003-04-02  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-string.c (set_length): fix a bug - we allocated max of
+	current alloc and needed new length, not max of the doubled
+	allocation and needed new length. Also, when building tests,
+	don't do the double-allocation stuff, just realloc every time.
+
+2003-04-02  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_file_get_contents): include filenames
+	in error messages
+	(_dbus_string_get_dirname): new
+	(_dbus_sysdeps_test): new
+	(_dbus_directory_open): include dirnames in error messages
+
+	* bus/config-parser.c: interpret <include> and <includedir> and
+	<servicedir> relative to config file location if the given
+	filename is not absolute.
+
+	* dbus/dbus-string.c (_dbus_string_find_byte_backward): new
+
+2003-04-02  Havoc Pennington  <hp@redhat.com>
+
+	* bus/connection.c (bus_transaction_send_error_reply): set sender
+	service for the error, and unref the reply on success
+
+	* bus/activation.c: convert to use BusTransaction so OOM can be
+	handled correctly
+	(bus_activation_service_created): set sender of the message
+
+2003-04-01  Havoc Pennington  <hp@redhat.com>
+
+	* bus/config-parser.c, bus/bus.c: implement <servicedir> and
+	<includedir> (at least mostly)
+
+	* dbus/dbus-sysdeps.c (_dbus_change_identity): set the group ID
+	first, then the user ID
+
+2003-04-01  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-server.c (dbus_server_set_auth_mechanisms): new
+	function
+
+	* dbus/dbus-auth.c (_dbus_auth_set_mechanisms): new
+
+	* dbus/dbus-internals.c (_dbus_dup_string_array): new function
+
+	* dbus/dbus-sysdeps.c (_dbus_listen_unix_socket): chmod the
+	socket 0777, and unlink any existing socket.
+
+	* bus/bus.c (bus_context_new): change our UID/GID and fork if
+	the configuration file so specifies; set up auth mechanism
+	restrictions
+
+	* bus/config-parser.c (bus_config_parser_content): add support
+	for <fork> option and fill in code for <auth>
+
+	* bus/system.conf.in: add <fork/> to default configuration,
+	and limit auth mechanisms to EXTERNAL
+
+	* doc/config-file.txt (Elements): add <fork>
+
+	* dbus/dbus-sysdeps.c (_dbus_become_daemon): new function
+	(_dbus_change_identity): new function
+
+2003-03-31  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_connect_unix_socket)
+	(_dbus_listen_unix_socket): fix off-by-one error in null
+	termination spotted by Nalin
+
+2003-03-31  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-keyring.c (_dbus_keyring_new_homedir): allow setting
+	DBUS_TEST_HOMEDIR when tests are enabled, so we can test without
+	having a real home directory available.
+
+2003-03-31  Havoc Pennington  <hp@redhat.com>
+
+	* bus/Makefile.am (install-data-hook): create /var/run/dbus
+
+	* bus/messagebus.in: add init script for Red Hat /etc/init.d
+
+	* configure.in: add support for specifying a style of init script
+	to install
+
+2003-03-31  Havoc Pennington  <hp@redhat.com>
+
+        Fix some annoying DBusString API and fix all affected code.
+
+	* dbus/dbus-string.c (_dbus_string_init): get rid of annoying
+	max_length argument
+	(_dbus_string_get_data): change to return string instead of using
+	an out param
+	(_dbus_string_get_const_data): ditto
+	(_dbus_string_get_data_len): ditto
+	(_dbus_string_get_const_data_len): ditto
+
+2003-03-31  Havoc Pennington  <hp@redhat.com>
+
+	* bus/main.c (main): fix up the command line arguments to be nicer
+
+2003-03-31  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/Makefile.am (INCLUDES): use EXPANDED_LOCALSTATEDIR to
+	define DBUS_SYSTEM_BUS_PATH as we want to compile in the same
+	final location that lands in the config file
+
+	* bus/config-loader-expat.c (bus_config_load): fix type of
+	XML_Parser variable
+
+	* doc/TODO: remove TODO item for dbus_bus_get()
+
+	* dbus/dbus-bus.c (bus_data_free): add missing lock/unlock
+
+2003-03-31  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-transport-unix.c (_dbus_transport_new_for_domain_socket)
+	(_dbus_transport_new_for_tcp_socket): these didn't need the "server"
+	argument since they are always client side
+
+	* dbus/dbus-server.c (dbus_server_get_address): new function
+
+	* bus/main.c (main): take the configuration file as an argument.
+
+	* test/data/valid-config-files/debug-allow-all.conf: new file to
+	use with dispatch.c tests for example
+
+	* bus/test-main.c (main): require test data dir
+
+	* bus/bus.c (bus_context_new): change this to take a
+	configuration file name as argument
+
+	* doc/config-file.txt (Elements): add <servicedir>
+
+	* bus/system.conf, bus/session.conf: new files
+
+	* dbus/dbus-bus.c (dbus_bus_get): look for system bus on
+	well-known socket if none set
+
+	* configure.in: create system.conf and session.conf
+
+2003-03-30  Havoc Pennington  <hp@pobox.com>
+
+	* bus/config-parser.c: hacking
+
+	* dbus/dbus-memory.c: don't use DBusList for the list of stuff
+	to shut down, since it could cause weirdness with the DBusList
+	lock
+
+	* dbus/dbus-list.c (_dbus_list_test): add tests for the
+	link-oriented stack routines
+	(alloc_link): free the mempool if the first alloc from it fails
+
+	* dbus/dbus-mempool.c (struct DBusMemBlock): fix alignment issue
+
+	* dbus/dbus-string.c (UNICODE_VALID): sync new version of this
+	from GLib
+	(_dbus_string_skip_white): new
+
+	* doc/config-file.txt (Elements): add <includedir>
+
+2003-03-28  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-string.c (_dbus_string_copy_data_len)
+	(_dbus_string_copy_data): new functions
+
+2003-03-28  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-bus.c: (bus_data_free), (dbus_bus_get):
+	* dbus/dbus-bus.h:
+	Add dbus_bus_get.
+
+	* dbus/dbus-memory.c:
+	Fix a doc comment.
+
+2003-03-28  Havoc Pennington  <hp@pobox.com>
+
+	* bus/test.c (bus_test_flush_bus): remove the sleep from here,
+	I think it may have just been superstition. Not sure.
+
+	* dbus/dbus-string.c (_dbus_string_base64_decode): catch some OOM
+	failures that were not being handled.
+
+	* dbus/dbus-auth.c (process_auth): fix a memleak in OOM handling
+
+	* dbus/dbus-memory.c: add ability to set number of mallocs in a
+	row that will fail on out-of-memory.
+
+	* dbus/dbus-internals.c (_dbus_test_oom_handling): convenience
+	function for testing out-of-memory handling.
+
+	* bus/config-loader-expat.c (memsuite): don't wrap the dbus
+	allocation functions, they do map exactly to the expat ones.
+
+2003-03-27  Havoc Pennington  <hp@redhat.com>
+
+	* bus/config-loader-libxml.c (bus_config_load): add another error
+	check
+
+2003-03-26  Anders Carlsson  <andersca@codefactory.se>
+
+	* doc/TODO:
+	Add note about automatic service activation.
+
+	* doc/dbus-specification.sgml:
+	Rename the specification and clarify a few things.
+
+2003-03-26  Anders Carlsson  <andersca@codefactory.se>
+
+	* Doxyfile.in:
+	* dbus/dbus-address.c:
+	* dbus/dbus-dict.c:
+	* dbus/dbus-marshal.c:
+	* dbus/dbus-server-debug-pipe.c:
+	* dbus/dbus-transport-unix.c:
+	Fix documentation warnings.
+
+2003-03-26  Havoc Pennington  <hp@pobox.com>
+
+	* bus/test-main.c, dbus/dbus-test.c (main): check memleaks
+	after every test so it's quick and easy to see which leaked, and
+	so we test multiple dbus_shutdown() calls
+
+	* configure.in: change configure.in XML stuff to also support
+	expat
+
+	* config-loader-libxml.c: some hacking
+
+	* config-loader-expat.c: some hacking
+
+	* config-parser.c: some hacking, plus tests
+
+2003-03-25  Havoc Pennington  <hp@redhat.com>
+
+        * throughout - add more _DBUS_ASSERT_ERROR_IS_CLEAR
+
+	* configure.in: add --with-xml option to specify XML library,
+	right now only libxml is supported.
+
+	* bus/config-loader-libxml.c, config-parser.c: sync some minor
+	nonworking code between home and work, still just stubs
+
+2003-03-24  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_set_fd_nonblocking): move to this
+	file
+
+	* dbus/dbus-errors.c (dbus_set_error, dbus_set_error_const): allow
+	NULL argument for "message" if the error is a well-known one,
+	fill in a generic message in this case.
+
+	* dbus/dbus-errors.h (DBusResultCode): Kill DBusResultCode in
+	favor of DBusError
+
+	* bus/test.c (bus_test_flush_bus): add
+
+	* bus/policy.c (bus_policy_test): test code stub
+
+2003-03-24  Havoc Pennington  <hp@pobox.com>
+
+	* bus/connection.c (bus_connections_setup_connection): set up
+	the "can this user connect" function, but it always returns
+	TRUE until we have a config file parser so we can have a config
+	file that allows connections.
+
+2003-03-23  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-threads.c (dbus_mutex_new, dbus_condvar_new): with
+	DBUS_BUILD_TESTS, actually alloc/free a block of memory for
+	the mutex, so we can check for proper memory management
+	and OOM handling.
+
+	* dbus/dbus-dataslot.c: remove the mutex from
+	DBusDataSlotAllocator and lock it manually when using it,
+	to simplify fitting it into the global slots framework.
+
+	* dbus/dbus-threads.c (init_static_locks): rework how we're
+	handling global locks so they are easily shut down.
+
+	* bus/policy.c (bus_policy_append_rule): fix
+
+	* bus/test-main.c (main): check for memleaks
+
+	* dbus/dbus-test.c (dbus_internal_do_not_use_run_tests): make
+	test suite check for memleaks
+
+	* dbus/dbus-memory.c: add support in test mode for tracking
+	number of outstanding blocks
+
+2003-03-23  Havoc Pennington  <hp@pobox.com>
+
+	* bus/policy.c, bus/bus.c, bus/connection.c: implement allow/deny
+	policies code
+
+	* dbus/dbus-hash.h: add ULONG hash keys
+
+	* dbus/dbus-sysdeps.c (_dbus_get_groups): new
+	(_dbus_get_group_id): new function
+
+2003-03-20  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c (dbus_connection_set_unix_user_function):
+	new function
+	(dbus_connection_get_unix_user): new function
+
+2003-03-20  Havoc Pennington  <hp@pobox.com>
+
+	* bus/connection.c (bus_connection_send_oom_error): assert that
+	message has a sender
+	(connection_execute_transaction): ditto
+	(bus_connection_preallocate_oom_error): fix to set the sender, and
+	set recipient to the destination service, not the bus driver
+
+	* bus/policy.c: hacking
+
+	* dbus/dbus-message.c (dbus_message_service_is): new function
+	(dbus_message_sender_is): new
+
+2003-03-19  Havoc Pennington  <hp@redhat.com>
+
+	* bus/policy.c: start sketching code for policy restrictions on
+	what connections can do.
+
+2003-03-18  Havoc Pennington  <hp@redhat.com>
+
+	* doc/TODO: some notes on high-level todo items. Little nitpick
+	stuff is all in @todo, so no need to add it here.
+
+	* doc/config-file.txt: some notes on how config file might look
+
+2003-03-18  Anders Carlsson  <andersca@codefactory.se>
+
+	* configure.in: 0.6
+
+	* NEWS: Update.
+
+2003-03-17  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-internals.h: add gcc attributes so that
+	our printf-style functions warn on bad arguments to
+	format
+
+	* dbus/dbus-sysdeps.c (_dbus_connect_tcp_socket): fix printf
+	format bug
+
+	* dbus/dbus-message.c (_dbus_message_loader_queue_messages): fix
+	printf format bug
+
+2003-03-17  Havoc Pennington  <hp@redhat.com>
+
+	* bus/test-main.c (main): make it print something as it runs
+	so make check doesn't look stuck
+
+	* doc/negotiation.txt, doc/dbus-sasl-profile.txt: remove
+	from CVS, now obsolete
+
+2003-03-17  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/dispatch.c: (bus_dispatch):
+	Refetch the service name since it may have been reallocated
+	when dbus_message_set_sender was called.
+
+	* dbus/dbus-sysdeps.c: (_dbus_accept):
+	Add address and address length variables and use them to stop
+	valgrind from complaining.
+
+2003-03-17  Havoc Pennington  <hp@pobox.com>
+
+	All tests pass, no memleaks, no valgrind complaints.
+
+	* bus/test.c: refcount handler_slot
+
+	* bus/connection.c (bus_connections_new): refcount
+	connection_data_slot
+
+	* dbus/dbus-auth-script.c (_dbus_auth_script_run): delete unused
+	bytes so that auth scripts pass.
+
+	* bus/dispatch.c: init message_handler_slot so it gets allocated
+	properly
+
+	* bus/dispatch.c (message_handler_slot_ref): fix memleak
+
+	* dbus/dbus-server-debug-pipe.c (_dbus_server_debug_pipe_new):
+	dealloc server_pipe_hash when no longer used for benefit of
+	leak checking
+
+	* dbus/dbus-auth.c (process_command): memleak fix
+
+	* bus/dispatch.c (check_hello_message): memleak fix
+
+2003-03-16  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-bus.c (ensure_bus_data): fix double-unref of the data slot
+
+2003-03-17  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/activation.c (bus_activation_activate_service): Append
+	the pending activation entry to the list of pending activations.
+
+2003-03-16  Havoc Pennington  <hp@pobox.com>
+
+	* bus/dispatch.c (bus_dispatch_test): remove double-unrefs of
+	connections
+
+	* dbus/dbus-address.c (create_entry): fix OOM handling when
+	failing to alloc entry->method
+
+2003-03-16  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-watch.c (_dbus_watch_new): handle failure to malloc
+	the watch
+
+	* dbus/dbus-server-debug-pipe.c (_dbus_transport_debug_pipe_new):
+	add some missing dbus_set_result
+
+	* bus/dispatch.c (bus_dispatch_add_connection): handle failure to
+	alloc the DBusMessageHandler
+
+	* dbus/dbus-transport.c (_dbus_transport_disconnect): don't ref
+	the transport here, since we call this from the finalizer; it
+	resulted in a double-finalize.
+
+	* dbus/dbus-transport.c (_dbus_transport_disconnect): fix a bug
+	where we tried to use transport->connection that was NULL,
+	happened when transport was disconnected early on due to OOM
+
+	* bus/*.c: adapt to handle OOM for watches/timeouts
+
+	* dbus/dbus-transport-unix.c: port to handle OOM during
+	watch handling
+
+	* dbus/dbus-auth.c (_dbus_auth_get_unused_bytes): return a
+	reference to unused bytes instead of a copy
+
+	* dbus/dbus-server.c (dbus_server_handle_watch): return FALSE for
+	out of memory
+
+	* dbus/dbus-connection.c (dbus_connection_handle_watch): return
+	FALSE on OOM
+
+	* dbus/dbus-timeout.c (dbus_timeout_handle): return FALSE for out
+	of memory
+
+2003-03-16  Anders Carlsson  <andersca@codefactory.se>
+
+	* doc/dbus-specification.sgml:
+	Document reply message for ActivateService.
+
+2003-03-16  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/activation.c: (bus_pending_activation_entry_free),
+	(bus_pending_activation_free), (bus_activation_new),
+	(bus_activation_unref), (bus_activation_service_created),
+	(bus_activation_activate_service):
+	* bus/activation.h:
+	* bus/bus.c: (bus_context_new):
+	* bus/desktop-file.c: (new_section):
+	* bus/driver.c: (bus_driver_send_service_deleted),
+	(bus_driver_handle_activate_service):
+	* bus/services.c: (bus_registry_new), (bus_registry_ensure):
+	* bus/services.h:
+	* dbus/dbus-connection.c:
+	(dbus_connection_send_with_reply_and_block):
+	* dbus/dbus-message.c: (dbus_message_append_args_valist):
+	* dbus/dbus-protocol.h:
+	Make activation work better. Now pending activations will be queued
+	and the daemon won't try to activate services that are already registered.
+
+2003-03-16  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-bus.c (ensure_bus_data): handle failure to set
+	connection data
+
+	* dbus/dbus-memory.c (_dbus_initialize_malloc_debug): support
+	DBUS_MALLOC_BACKTRACES to print trace when failing an alloc
+
+2003-03-16  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-string.c (_dbus_string_validate_utf8): oops, unbreak
+	this. always run the test suite before commit...
+
+	* bus/*: adapt to DBusConnection API changes
+
+	* glib/dbus-gmain.c: adapt to DBusConnection API changes,
+	requires renaming stuff to avoid dbus_connection_dispatch name
+	conflict.
+
+	* dbus/dbus-transport.c (_dbus_transport_queue_messages): new
+	function
+
+	* dbus/dbus-message.c (_dbus_message_loader_queue_messages):
+	separate from _dbus_message_loader_return_buffer()
+
+	* dbus/dbus-connection.c (dbus_connection_get_n_messages): remove
+	this, because it's now always broken to use; the number of
+	messages in queue vs. the number still buffered by the message
+	loader is undefined/meaningless. Should use
+	dbus_connection_get_dispatch_state().
+	(dbus_connection_dispatch): rename from
+	dbus_connection_dispatch_message
+
+2003-03-16  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-string.c (_dbus_string_validate_utf8): copy in a real
+	implementation
+
+2003-03-16  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-connection.c:
+	(dbus_connection_send_with_reply_and_block):
+	Decrease connection->n_incoming when removing an entry
+	from the list.
+	* dbus/dbus-dict.c: (dbus_dict_entry_free),
+	(dbus_dict_set_boolean_array), (dbus_dict_set_int32_array),
+	(dbus_dict_set_uint32_array), (dbus_dict_set_double_array),
+	(dbus_dict_set_byte_array), (dbus_dict_set_string_array),
+	(dbus_dict_get_boolean_array), (dbus_dict_get_double_array),
+	(dbus_dict_get_byte_array):
+	Handle NULL arrays and strings. Also add support for byte arrays.
+
+	* dbus/dbus-marshal.c: (_dbus_marshal_byte_array),
+	(_dbus_marshal_dict), (_dbus_demarshal_byte_array),
+	(_dbus_demarshal_int32_array), (_dbus_demarshal_uint32_array),
+	(_dbus_demarshal_double_array), (_dbus_demarshal_string_array),
+	(_dbus_demarshal_dict), (demarshal_and_validate_len),
+	(_dbus_marshal_validate_arg), (_dbus_marshal_test):
+	* dbus/dbus-marshal.h:
+	Add support for marshalling and demarshalling empty arrays and strings.
+
+	* dbus/dbus-message.c: (dbus_message_append_args_valist),
+	(dbus_message_append_string_array),
+	(dbus_message_iter_get_boolean),
+	(dbus_message_iter_get_boolean_array),
+	(dbus_message_iter_get_int32_array),
+	(dbus_message_iter_get_uint32_array),
+	(dbus_message_iter_get_double_array),
+	(dbus_message_iter_get_byte_array),
+	(dbus_message_iter_get_string_array), (dbus_message_iter_get_dict),
+	(check_message_handling):
+	Add support for getting empty arrays and dicts.
+
+	* dbus/dbus-string.c: (_dbus_string_validate_utf8):
+	Don't do any validation at all for now, that's better than just checking
+	for ASCII.
+
+	* test/data/valid-messages/emptiness.message:
+	New test message with lots of empty arrays.
+
+2003-03-16  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c
+	(_dbus_connection_queue_received_message_link): new function that
+	can't fail due to OOM
+
+	* dbus/dbus-message.c (_dbus_message_loader_pop_message_link):
+	new function pops a message together with a list link
+	containing it.
+
+	* dbus/dbus-transport-unix.c (queue_messages): use new link-based
+	message queuing functions to avoid needing to alloc memory
+
+2003-03-16  Havoc Pennington  <hp@pobox.com>
+
+	Oops - test code was only testing failure of around 30 of the
+	mallocs in the test path, but it turns out there are 500+
+	mallocs. I believe this was due to misguided linking setup such
+	that there was one copy of dbus_malloc etc. in the daemon and one
+	in the shared lib, and only daemon mallocs were tested. In any
+	case, the test case now tests all 500+ mallocs, and doesn't pass
+	yet, though there are lots of fixes in this patch.
+
+	* dbus/dbus-connection.c (dbus_connection_dispatch_message): fix
+	this so that it doesn't need to allocate memory, since it
+	has no way of indicating failure due to OOM (and would be
+	annoying if it did).
+
+	* dbus/dbus-list.c (_dbus_list_pop_first_link): new function
+
+	* bus/Makefile.am: rearrange to create two self-contained
+	libraries, to avoid having libraries with overlapping symbols.
+	that was resulting in weirdness, e.g. I'm pretty sure there
+	were two copies of global static variables.
+
+	* dbus/dbus-internals.c: move the malloc debug stuff to
+	dbus-memory.c
+
+	* dbus/dbus-list.c (free_link): free list mempool if it becomes
+	empty.
+
+	* dbus/dbus-memory.c (_dbus_disable_mem_pools): new function
+
+	* dbus/dbus-address.c (dbus_parse_address): free list nodes
+	on failure.
+
+	* bus/dispatch.c (bus_dispatch_add_connection): free
+	message_handler_slot when no longer using it, so
+	memory leak checkers are happy for the test suite.
+
+	* dbus/dbus-server-debug-pipe.c (debug_finalize): free server name
+
+	* bus/bus.c (new_connection_callback): disconnect in here if
+	bus_connections_setup_connection fails.
+
+	* bus/connection.c (bus_connections_unref): fix to free the
+	connections
+	(bus_connections_setup_connection): if this fails, don't
+	disconnect the connection, just be sure there are no side
+	effects.
+
+	* dbus/dbus-string.c (undo_alignment): unbreak this
+
+	* dbus/dbus-auth.c (_dbus_auth_unref): free some stuff we were
+	leaking
+	(_dbus_auth_new): fix the order in which we free strings
+	on OOM failure
+
+	* bus/connection.c (bus_connection_disconnected): fix to
+	not send ServiceDeleted multiple times in case of memory
+	allocation failure
+
+	* dbus/dbus-bus.c (dbus_bus_get_base_service): new function to
+	get the base service name
+	(dbus_bus_register_client): don't return base service name,
+	instead store it on the DBusConnection and have an accessor
+	function for it.
+	(dbus_bus_register_client): rename dbus_bus_register()
+
+	* bus/dispatch.c (check_hello_message): verify that other
+	connections on the bus also got the correct results, not
+	just the one sending hello
+
+2003-03-15  Havoc Pennington  <hp@pobox.com>
+
+	Make it pass the Hello handling test including all OOM codepaths.
+	Now to do other messages...
+
+	* bus/services.c (bus_service_remove_owner): fix crash when
+	removing owner from an empty list of owners
+	(bus_registry_ensure): don't leave service in the list of
+	a connection's owned services if we fail to put the service
+	in the hash table.
+
+	* bus/connection.c (bus_connection_preallocate_oom_error): set
+	error flag on the OOM error.
+
+	* dbus/dbus-connection.c (_dbus_connection_new_for_transport):
+	handle _dbus_transport_set_connection failure
+
+	* dbus/dbus-transport-unix.c (_dbus_transport_new_for_fd): modify
+	to create watches up front and simply enable/disable them as
+	needed.
+	(unix_connection_set): this can now fail on OOM
+
+	* dbus/dbus-timeout.c, dbus/dbus-watch.c: add concept
+	of enabling/disabling a watch or timeout.
+
+	* bus/loop.c (bus_loop_iterate): don't touch disabled
+	watches/timeouts
+
+	* glib/dbus-gmain.c: adapt to enable/disable watches and timeouts
+
+2003-03-15  Havoc Pennington  <hp@pobox.com>
+
+	* bus/dispatch.c (bus_dispatch_test): OK, now finally actually
+	write useful test code, after all that futzing around ;-)
+
+	Test does not yet pass because we can't handle OOM in
+	_dbus_transport_messages_pending (basically,
+	dbus_connection_preallocate_send() does not prealloc the write
+	watch). To fix this, I think we need to add new stuff to
+	set_watch_functions, namely a SetEnabled function so we can alloc
+	the watch earlier, then enable it later.
+
+	* dbus/Makefile.am (libdbus_convenience_la_SOURCES): move
+	dbus-memory.c to the convenience lib
+
+	* bus/test.c: rename some static functions to keep them clearly
+	distinct from stuff in connection.c. Handle client disconnection.
+
+2003-03-14  Havoc Pennington  <hp@pobox.com>
+
+	* bus/dispatch.c (bus_dispatch_test): do test using debug-pipe
+	transport, tests more of the real codepath. Set up clients
+	with bus_setup_debug_client.
+
+	* bus/test.c (bus_setup_debug_client): function to set up debug
+	"clients" on the main loop
+
+	* dbus/dbus-transport.c (_dbus_transport_open): add debug-pipe
+	support
+
+	* dbus/dbus-server.c (dbus_server_listen): add debug-pipe
+	server type
+
+	* dbus/dbus-server-debug.c: support a debug server based on pipes
+
+	* dbus/dbus-sysdeps.c (_dbus_full_duplex_pipe): new function
+	(_dbus_close): new function
+
+	* configure.in: check for socketpair
+
+2003-03-14  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-memory.c: add a "detect buffer overwrites on free"
+	cheesy hack
+
+	* dbus/dbus-transport-debug.c: rework this a good bit to be
+	less complicated. hopefully still works.
+
+	* dbus/dbus-server-debug.c (handle_new_client): remove timeout
+	manually
+
+	* glib/dbus-gmain.c (timeout_handler): don't remove timeout
+	after running it
+
+	* dbus/dbus-message.c (dbus_message_copy): rename from
+	dbus_message_new_from_message, fix it up to copy
+	all the message fields, add test case
+
+	* bus/dispatch.c (bus_dispatch_test): add some more test code,
+	not quite passing yet
+
+2003-03-14  Havoc Pennington  <hp@pobox.com>
+
+	* bus/loop.c (bus_loop_iterate): add this so we can "run loop
+	until no work remains" in test code. (the large diff here
+	is just code movement, no actual changes)
+
+	* dbus/dbus-server-debug.c (DEFAULT_INTERVAL): change interval to
+	1, no point waiting around for test code.
+	(_dbus_server_debug_accept_transport): unref the timeout
+	after adding it (right?)
+
+	* dbus/dbus-transport-debug.c (DEFAULT_INTERVAL): ditto
+
+2003-03-13  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-timeout.c (_dbus_timeout_list_set_functions): handle
+	out of memory
+
+	* dbus/dbus-watch.c (_dbus_watch_list_set_functions): handle out
+	of memory
+
+	* dbus/dbus-connection.h: Make AddWatchFunction and
+	AddTimeoutFunction return a bool so they can fail on out-of-memory
+
+	* bus/bus.c (bus_context_new): set up timeout handlers
+
+	* bus/connection.c (bus_connections_setup_connection): set up
+	timeout handlers
+
+	* glib/dbus-gmain.c: adapt to the fact that set_functions stuff
+	can fail
+
+	* bus/bus.c (bus_context_new): adapt to changes
+
+	* bus/connection.c: adapt to changes
+
+	* test/watch.c: adapt to DBusWatch changes
+
+	* bus/dispatch.c (bus_dispatch_test): started adding this but
+	didn't finish
+
+2003-03-14  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/dispatch.c (send_service_nonexistent_error): Fix typo.
+
+2003-03-13  Havoc Pennington  <hp@pobox.com>
+
+	* bus/test.c, bus/test.h, bus/Makefile.am, bus/test-main.c:
+	set up a test framework as for the library
+
+2003-03-12  Havoc Pennington  <hp@pobox.com>
+
+	Throughout: purge global variables, introduce BusActivation,
+	BusConnections, BusRegistry, etc. objects instead.
+
+	* bus/bus.h, bus/bus.c: introduce BusContext as a global
+	message bus object
+
+	* test/Makefile.am (TEST_BINARIES): disable bus-test for now,
+	going to redo this a bit differently I think
+
+2003-03-12  Havoc Pennington  <hp@redhat.com>
+
+        Mega-patch that gets the message bus daemon initially handling
+	out-of-memory. Work still needed. Also lots of random
+	moving stuff to DBusError instead of ResultCode.
+
+	* dbus/dbus-list.c (_dbus_list_length_is_one): new function
+
+	* dbus/dbus-connection.c
+	(dbus_connection_send_with_reply_and_block): use DBusError
+
+	* dbus/dbus-bus.c: adapt to API changes, make it use DBusError not
+	DBusResultCode
+
+	* dbus/dbus-connection.c (dbus_connection_send): drop the result
+	code here, as the only failure possible is OOM.
+
+	* bus/connection.c (bus_connection_disconnect):
+	rename bus_connection_disconnected as it's a notification only
+
+	* bus/driver.c (bus_driver_handle_acquire_service): don't free
+	"name" on get_args failure, should be done by get_args;
+	don't disconnect client for bad args, just return an error.
+	(bus_driver_handle_service_exists): ditto
+
+	* bus/services.c (bus_services_list): NULL-terminate returned array
+
+	* bus/driver.c (bus_driver_send_service_lost)
+	(bus_driver_send_service_acquired): send messages from driver to a
+	specific client to the client's unique name, not to the broadcast
+	service.
+
+	* dbus/dbus-message.c (decode_header_data): reject messages that
+	contain no name field
+	(_dbus_message_get_client_serial): rename to
+	dbus_message_get_serial and make public
+	(_dbus_message_set_serial): rename from set_client_serial
+	(_dbus_message_set_reply_serial): make public
+	(_dbus_message_get_reply_serial): make public
+
+	* bus/connection.c (bus_connection_foreach): allow stopping
+	iteration by returning FALSE from foreach function.
+
+	* dbus/dbus-connection.c (dbus_connection_send_preallocated)
+	(dbus_connection_free_preallocated_send)
+	(dbus_connection_preallocate_send): new API for sending a message
+	without possibility of malloc failure.
+	(dbus_connection_send_message): rename to just
+	dbus_connection_send (and same for whole function family)
+
+	* dbus/dbus-errors.c (dbus_error_free): make this reinit the error
+
+	* dbus/dbus-sysdeps.c (_dbus_exit): new function
+
+	* bus/activation.c: handle/return errors
+
+	* dbus/dbus-errors.h: add more DBUS_ERROR #define
+
+	* dbus/dbus-sysdeps.c (_dbus_directory_open) (_dbus_file_get_contents)
+	(_dbus_directory_get_next_file): use DBusError instead of DBusResultCode
+	(_dbus_result_from_errno): move to this file
+
+2003-03-10  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-marshal.c:
+	(_dbus_marshal_set_string):
+	Take a length argument so we can marshal the correct string
+	length.
+
+	(_dbus_marshal_dict), (_dbus_demarshal_dict),
+	(_dbus_marshal_get_arg_end_pos), (_dbus_marshal_validate_arg),
+	(_dbus_marshal_test):
+	* dbus/dbus-marshal.h:
+	Add support for marshalling and demarshalling dicts.
+
+	* dbus/dbus-message-builder.c: (_dbus_message_data_load):
+	Add support for TYPE DICT.
+
+	* dbus/dbus-message.c: (set_string_field):
+	Adjust header padding.
+
+	(dbus_message_append_args_valist), (dbus_message_append_dict),
+	(dbus_message_get_args_valist), (dbus_message_iter_get_arg_type),
+	(dbus_message_iter_get_dict), (_dbus_message_loader_return_buffer),
+	(check_message_handling), (check_have_valid_message):
+	* dbus/dbus-message.h:
+	Add functions for setting and getting dicts.
+
+	* dbus/dbus-protocol.h:
+	Add DBUS_TYPE_DICT.
+
+	* dbus/dbus.h:
+	Add dbus-dict.h
+
+	* doc/dbus-specification.sgml:
+	Add information about how dicts are marshalled.
+
+	* test/data/invalid-messages/dict-with-nil-value.message:
+	* test/data/invalid-messages/too-short-dict.message:
+	* test/data/valid-messages/dict-simple.message:
+	* test/data/valid-messages/dict.message:
+	Add sample messages containing dicts.
+
+2003-03-08  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-dict.h: Add DBUS_END_DECLS.
+
+2003-03-07  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/Makefile.am:
+	* dbus/dbus-dict.c: (dbus_dict_entry_free), (dbus_dict_new),
+	(dbus_dict_get_keys), (insert_entry), (dbus_dict_set_boolean),
+	(dbus_dict_set_int32), (dbus_dict_set_uint32),
+	(dbus_dict_set_double), (dbus_dict_set_string),
+	(dbus_dict_set_boolean_array), (dbus_dict_set_int32_array),
+	(dbus_dict_set_uint32_array), (dbus_dict_set_double_array),
+	(dbus_dict_set_string_array), (_dbus_dict_test):
+	* dbus/dbus-dict.h:
+	Fix according to comments from Havoc.
+
+2003-03-06  Michael Meeks  <michael@server.home>
+
+	* configure.in: if we don't have kde-config, disable have_qt.
+
+2003-03-07  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/Makefile.am:
+	Add dbus-dict.[ch]
+
+	* dbus/dbus-dict.c: (dbus_dict_entry_free), (dbus_dict_new),
+	(dbus_dict_ref), (dbus_dict_unref), (dbus_dict_contains),
+	(dbus_dict_remove), (dbus_dict_get_value_type),
+	(dbus_dict_get_keys), (dbus_dict_put_boolean),
+	(dbus_dict_put_int32), (dbus_dict_put_uint32),
+	(dbus_dict_put_double), (dbus_dict_put_string),
+	(dbus_dict_put_boolean_array), (dbus_dict_put_int32_array),
+	(dbus_dict_put_uint32_array), (dbus_dict_put_double_array),
+	(dbus_dict_put_string_array), (dbus_dict_get_boolean),
+	(dbus_dict_get_int32), (dbus_dict_get_uint32),
+	(dbus_dict_get_double), (dbus_dict_get_string),
+	(dbus_dict_get_boolean_array), (dbus_dict_get_int32_array),
+	(dbus_dict_get_uint32_array), (dbus_dict_get_double_array),
+	(dbus_dict_get_string_array), (_dbus_dict_test):
+	* dbus/dbus-dict.h:
+	Add DBusDict implementation
+
+	* dbus/dbus-test.c: (dbus_internal_do_not_use_run_tests):
+	* dbus/dbus-test.h:
+	Add _dbus_dict_test
+
+2003-03-04  Havoc Pennington  <hp@pobox.com>
+
+	* test/data/auth/*: adapt to changes
+
+	* dbus/dbus-auth-script.c (_dbus_auth_script_run): add
+	USERID_BASE64 and change USERNAME_BASE64 to put in username not
+	userid
+
+	* dbus/dbus-keyring.c (_dbus_keyring_validate_context): prevent
+	more stuff from being in a context name, to make the protocol
+	simpler to deal with
+
+	* dbus/dbus-errors.c (dbus_error_has_name): new function
+	(dbus_error_is_set): new function
+
+	* dbus/dbus-auth.c: replace DBUS_STUPID_TEST_MECH auth
+	with DBUS_COOKIE_SHA1, implement DBUS_COOKIE_SHA1
+
+	* dbus/dbus-connection.c (dbus_connection_flush): also read
+	messages during a flush operation
+
+	* dbus/Makefile.am: remove dbus-md5 since it isn't currently used.
+
+2003-03-05  Anders Carlsson  <andersca@codefactory.se>
+
+	* configure.in: Check for gethostbyname on Solaris.
+
+	* dbus/dbus-transport.c: (_dbus_transport_open):
+	Remove duplicate "tcp" entry.
+
+	* doc/dbus-specification.sgml:
+	Clarify some things.
+
+2003-03-05  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-auth.c: (send_rejected), (process_test_subdir):
+	* dbus/dbus-keyring.c: (_dbus_keyring_new_homedir),
+	(_dbus_keyring_test):
+	* dbus/dbus-md5.c: (_dbus_md5_compute):
+	* dbus/dbus-sha.c: (_dbus_sha_compute):
+	Plug memory leaks.
+
+2003-03-05  Anders Carlsson  <andersca@codefactory.se>
+
+	* README: Add some things.
+
+2003-03-04  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-message.c (dbus_message_append_args_valist): Add a break;
+	after case DBUS_TYPE_BOOELAN.
+
+2003-03-02  Havoc Pennington  <hp@pobox.com>
+
+	* test/break-loader.c (randomly_set_extreme_ints): add test that
+	sets really huge and small integers
+
+	* dbus/dbus-marshal.c (_dbus_marshal_validate_arg): add check
+	that length of boolean array fits in the string, and that
+	string has room for boolean value in single-bool case.
+
+	* dbus/dbus-message-builder.c (_dbus_message_data_load): add
+	optional value to "ALIGN" command which is what to fill the
+	alignment with.
+
+	* test/data/valid-messages/no-padding.message: add regression
+	test for the message padding problem
+
+2003-03-02  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (decode_header_data): fix to always init
+	message_padding, from Benjamin Dauvergne
+
+2003-03-02  Havoc Pennington  <hp@pobox.com>
+
+	* configure.in: 0.5
+
+	* NEWS: Update.
+
+2003-03-01  Joe Shaw  <joe@assbarn.com>
+
+	* configure.in: Check for "struct cmsgcred" and try to access its
+	members for BSD-like unices.
+
+	* dbus/dbus-sysdeps.c (read_credentials_byte): Fold this back into
+	_dbus_read_credentials_unix_socket().
+	(_dbus_read_credentials_unix_socket): Use recvmsg() instead of
+	read() for reading the credential byte off the unix socket.  Use
+	struct cmsgcred on systems that support it.
+
+2003-02-27  Alexander Larsson  <alexl@redhat.com>
+
+	* glib/Makefile.am:
+	* configure.in:
+	Make gthreads-2.0 dependency optional. Don't build thread test if
+	its not found.
+
+2003-02-27  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c
+	(dbus_connection_send_message_with_reply_and_block): fix doh!
+	doh! doh! bug that resulted in never removing a reply from the
+	queue, no wonder we called get_reply_serial so much ;-)
+
+	* dbus/dbus-message.c (struct DBusMessage): cache reply serial
+	and client serial instead of demarshaling them every time
+
+2003-02-27  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-marshal.c (_dbus_demarshal_int32): rewrite to be much
+	more inlined, using dbus-string-private.h, speeds things up
+	substantially
+
+	* dbus/dbus-string.c (_dbus_string_free): apply align offset
+	when freeing the string
+	(_dbus_string_steal_data): fix for align offset
+	(undo_alignment): new function
+
+2003-02-26  Havoc Pennington  <hp@redhat.com>
+
+        All kinds of audit fixes from Owen, plus initial attempt to
+	handle unaligned memory returned from malloc.
+
+	* dbus/dbus-string.c (_dbus_string_init): clamp max length to
+	leave room for align_offset and nul byte
+	(fixup_alignment): function to track an align_offset and
+	ensure real->str is aligned
+	(DBUS_GENERIC_STRING_PREAMBLE): len must be less than allocated,
+	to allow a nul byte plus align offset
+	(_dbus_string_lock): fix overflow issue
+	(_dbus_string_init_const_len): add assertions on sanity of len,
+	assign allocated to be ALLOCATION_PADDING larger than len
+	(set_length): fixup the overflow handling
+	(_dbus_string_get_data_len): fix overflow in assertion
+	(open_gap): detect overflow in size of gap to be opened
+	(_dbus_string_lengthen): add overflow check
+	(_dbus_string_align_length): fix overflow with _DBUS_ALIGN_VALUE
+	(_dbus_string_append): add overflow check
+	(_dbus_string_append_unichar): overflow
+	(_dbus_string_delete): fix overflow in assertion
+	(_dbus_string_copy_len): overflow in assertion
+	(_dbus_string_replace_len): overflows in assertions
+	(_dbus_string_find): change to implement in terms of
+	_dbus_string_find_to
+	(_dbus_string_find_to): assorted fixage
+	(_dbus_string_equal_c_str): assert c_str != NULL,
+	fix logic so the function works
+	(_dbus_string_ends_with_c_str): fix overflow thingy
+	(_dbus_string_base64_encode): overflow fix
+	(_dbus_string_validate_ascii): overflow
+	(_dbus_string_validate_nul): overflow
+
+2003-02-26  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-marshal.c (_dbus_marshal_test): fix to work with DISABLE_ASSERTS
+
+2003-02-26  Alexander Larsson  <alexl@redhat.com>
+
+	* configure.in:
+	Set DBUS_GLIB_THREADS_LIBS for apps using gthread-2.0
+
+	* dbus/dbus-connection.c:
+	* dbus/dbus-connection.h:
+	Fix _dbus_connection_acquire_io_path and _dbus_connection_acquire_dispatch.
+	Add dbus_connection_set_wakeup_main_function and use it when queueing
+	incoming and outgoing messages.
+
+
+	* dbus/dbus-dataslot.c:
+	Threadsafe usage of DBusDataSlotAllocator
+
+	* dbus/dbus-message.c: (dbus_message_get_args_iter):
+	dbus_new can fail.
+
+	* dbus/dbus-server-unix.c:
+	Add todo comment
+
+	* glib/dbus-gmain.c:
+	Implement the new wakeup functions for glib.
+
+	* glib/Makefile.am:
+	* glib/test-thread-client.c:
+	* glib/test-thread-server.c:
+	* glib/test-thread.h:
+	Initial cut at some thread test code. Not really done yet.
+
+2003-02-26  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c
+	(dbus_connection_send_message_with_reply_and_block): fix crash
+	where we ref'd the outgoing message instead of the returned reply
+
+	* dbus/dbus-transport-unix.c (do_authentication): check read watch
+	at the end of this function, so if we didn't need to read for
+	authentication, we reinstall it for receiving messages
+
+	* dbus/dbus-message.c (dbus_message_new_reply): allow replies to
+	a NULL sender for peer-to-peer case
+
+	* dbus/dbus-transport-unix.c (check_read_watch): handle
+	!authenticated case correctly
+
+	* glib/dbus-gmain.c: add support for DBusServer
+
+	* dbus/dbus-server.c: add data slot support
+
+	* glib/dbus-gmain.c (dbus_connection_setup_with_g_main): check
+	return values and handle errors
+
+	* dbus/dbus-dataslot.c: factor out the data slot stuff from
+	DBusConnection
+
+	* Doxyfile.in (INPUT): add glib subdir
+
+	* glib/dbus-gmain.c (dbus_connection_setup_with_g_main): rename
+	setup_with_g_main instead of hookup_with_g_main; write docs
+
+2003-02-24  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-marshal.c: (_dbus_marshal_validate_arg):
+	* dbus/dbus-message-builder.c: (_dbus_message_data_load):
+	* dbus/dbus-message.c: (dbus_message_append_boolean),
+	(dbus_message_append_boolean_array),
+	(dbus_message_get_args_valist), (_dbus_message_test):
+	* dbus/dbus-message.h:
+	* doc/dbus-specification.sgml:
+	Various fixes as pointed out by Havoc.
+
+	* test/data/invalid-messages/bad-boolean-array.message:
+	* test/data/invalid-messages/bad-boolean.message:
+	Add invalid boolean value test cases.
+
+2003-02-24  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-internals.c: (_dbus_type_to_string):
+	* dbus/dbus-marshal.c: (_dbus_marshal_get_arg_end_pos),
+	(_dbus_marshal_validate_arg):
+	* dbus/dbus-message-builder.c: (_dbus_message_data_load):
+	* dbus/dbus-message.c: (dbus_message_append_args_valist),
+	(dbus_message_append_boolean), (dbus_message_append_boolean_array),
+	(dbus_message_get_args_valist), (dbus_message_iter_get_boolean),
+	(dbus_message_iter_get_int32), (dbus_message_iter_get_uint32),
+	(dbus_message_iter_get_double),
+	(dbus_message_iter_get_boolean_array), (message_iter_test):
+	* dbus/dbus-message.h:
+	* dbus/dbus-protocol.h:
+	* doc/dbus-specification.sgml:
+	* test/data/valid-messages/lots-of-arguments.message:
+	Add support for boolean and boolean array types.
+
+2003-02-23  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-keyring.c: finish most of this implementation and
+	simple unit test
+
+	* dbus/dbus-errors.c (dbus_set_error_const, dbus_set_error): make
+	these barf if the error isn't cleared to NULL
+
+	* dbus/dbus-sysdeps.c (_dbus_delete_file): set error on failure
+	(_dbus_create_directory): new function
+
+	* dbus/dbus-errors.c (dbus_set_error): fix warning
+
+	* dbus/dbus-string.c (_dbus_string_hex_encode): new function
+	(_dbus_string_hex_decode): new function
+	(test_hex_roundtrip): test code
+
+	* dbus/dbus-sha.c (_dbus_sha_compute): use dbus_string_hex_encode
+
+	* dbus/dbus-md5.c (_dbus_md5_compute): use dbus_string_hex_encode
+
+	* dbus/dbus-sysdeps.c (_dbus_string_save_to_file): make this use
+	the save-to-temp/rename trick to atomically write the new file
+	(_dbus_string_parse_uint): new function
+
+2003-02-22  Havoc Pennington  <hp@pobox.com>
+
+	* test/Makefile.am (dist-hook): fix dist for test/data/sha-1
+
+2003-02-22  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (dbus_message_iter_get_string_array):
+	(dbus_message_iter_get_byte_array): Fix up doxygen warnings
+
+	* dbus/dbus-sha.c: add implementation of SHA-1 algorithm
+
+	* dbus/test/data/sha-1: add US government test suite for SHA-1
+
+2003-02-21  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-marshal.c: (_dbus_demarshal_string_array):
+	Make string arrays NULL-terminated.
+
+	* dbus/dbus-memory.c: (dbus_free_string_array):
+	* dbus/dbus-memory.h:
+	New function for freeing NULL-terminated string arrays.
+
+	* dbus/dbus-message-builder.c: (append_quoted_string),
+	(_dbus_message_data_load):
+	Add support for array types.
+
+	* dbus/dbus-message.c: (check_message_handling):
+	Add more types as test cases.
+
+	* dbus/dbus-sysdeps.c: (_dbus_string_parse_int),
+	(_dbus_string_parse_double):
+	Add the start offset to the end offset.
+
+	* test/data/valid-messages/lots-of-arguments.message:
+	New test message with lots of arguments.
+
+2003-02-21  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-message.c: (dbus_message_append_nil),
+	(dbus_message_append_int32), (dbus_message_append_uint32),
+	(dbus_message_append_double), (dbus_message_append_string),
+	(dbus_message_append_int32_array),
+	(dbus_message_append_uint32_array),
+	(dbus_message_append_double_array),
+	(dbus_message_append_byte_array),
+	(dbus_message_append_string_array):
+	Fix all out-of-memory handling in these functions.
+
+2003-02-21  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-message.c: (dbus_message_append_nil):
+	Fix a silly.
+
+2003-02-21  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-message.c: (dbus_message_append_args_valist),
+	(dbus_message_append_nil), (dbus_message_append_int32_array),
+	(dbus_message_append_uint32_array),
+	(dbus_message_append_double_array),
+	(dbus_message_append_byte_array),
+	(dbus_message_append_string_array), (dbus_message_get_args_valist),
+	(dbus_message_iter_get_int32_array),
+	(dbus_message_iter_get_uint32_array),
+	(dbus_message_iter_get_double_array),
+	(dbus_message_iter_get_byte_array),
+	(dbus_message_iter_get_string_array):
+
+	* dbus/dbus-message.h:
+	Add functions for appending and getting arrays.
+
+2003-02-21  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-mempool.c (_dbus_mem_pool_new): Make the
+	element size at least 8 bytes, fixes mempool tests on
+	64-bit machines.
+
+2003-02-20  Alexander Larsson  <alexl@redhat.com>
+
+	* dbus/dbus-transport-unix.c (unix_do_iteration):
+	Unlock the connection mutex during a blocking select call.
+	Add todo about how we need a way to wake up the select.
+
+	* dbus/dbus-connection-internal.h:
+	* dbus/dbus-connection.c:
+	Add _dbus_connection_lock and _dbus_connection_unlock.
+
+2003-02-19  Havoc Pennington  <hp@pobox.com>
+
+	* Doxyfile.in (PREDEFINED): put DOXYGEN_SHOULD_SKIP_THIS in
+	Doxyfile.in, not Doxyfile
+
+	* dbus/dbus-keyring.c: do some hacking on this
+
+	* dbus/dbus-sysdeps.c (_dbus_delete_file): new
+
+	* dbus/dbus-errors.c (dbus_set_error_const): do not call
+	dbus_error_init
+	(dbus_set_error): remove dbus_error_init, check for message ==
+	NULL *before* we sprintf into it, and add @todo about including
+	system headers in this file
+
+	* dbus/dbus-sysdeps.c (_dbus_create_file_exclusively): new
+
+	* dbus/dbus-errors.h (DBUS_ERROR_FAILED): add
+
+	* dbus/dbus-sysdeps.c (get_user_info): break this function out to
+	get various bits of user information based on either username
+	or user ID
+	(_dbus_homedir_from_username): new function
+
+2003-02-19  Anders Carlsson  <andersca@codefactory.se>
+
+	* configure.in:
+	Add check for nonposix getpwnam_r
+
+	* dbus/dbus-mempool.c: (_dbus_mem_pool_new):
+	Align the pool element size to a sizeof (void *) boundary.
+
+	* dbus/dbus-sysdeps.c: (_dbus_setenv), (_dbus_connect_unix_socket),
+	(_dbus_listen_unix_socket), (_dbus_credentials_from_username):
+	General Solaris fixes.
+
+	* test/data/valid-messages/simplest-manual.message:
+	Explicitly state that we want little-endian packing.
+
+2003-02-19  Mikael Hallendal  <micke@codefactory.se>
+
+	* dbus/dbus-server.c (dbus_server_listen): Support tcp: addresses.
+
+	* dbus/dbus-transport-unix.c (_dbus_transport_new_for_tcp_socket):
+	Added to create a transport connecting using a tcp/ip socket.
+
+	* dbus/dbus-sysdeps.c (_dbus_connect_tcp_socket): Added to connect
+	to a tcp socket at given host and port.
+	(_dbus_listen_tcp_socket): added to listen on tcp socket for given
+	hostname and port.
+
+	* dbus/dbus-server.c (dbus_server_listen): Support tcp: addresses.
+
+	* dbus/dbus-server-unix.c (_dbus_server_new_for_tcp_socket):
+	Added to create a server listening on a TCP/IP socket.
+
+2003-02-19  Havoc Pennington  <hp@pobox.com>
+
+	Throughout: mop up all the Doxygen warnings and undocumented
+	stuff.
+
+	* dbus/dbus-sysdeps.c (do_exec): do not use execvp, we don't want
+	to search any paths.
+
+	* dbus/dbus-threads.c: move global mutex initializers to
+	dbus-internals.h, multiple prototypes was confusing doxygen
+	besides being kind of ugly
+
+	* Doxyfile (PREDEFINED): have Doxygen define
+	DOXYGEN_SHOULD_SKIP_THIS so we can exclude things from
+	docs with #ifndef DOXYGEN_SHOULD_SKIP_THIS
+	(do not abuse the feature! it's for stuff like the autogenerated
+	macros in dbus-md5.c, not just for things you don't feel like
+	documenting...)
+
+2003-02-18  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-string.c (_dbus_string_zero): new function
+
+	* dbus/dbus-md5.c: include MD5 implementation by L. Peter Deutsch,
+	wrap it in some dbus-friendly API
+
+	* dbus/dbus-types.h: add 16-bit types
+
+2003-02-18  Joe Shaw  <joe@assbarn.com>
+
+	* dbus/dbus-auth.c (handle_server_data_stupid_test_mech): Just get
+	credentials from our currently running process.
+	(get_word): Fix a buglet where we were copying the entire length
+	instead of relative to our position.
+
+	* dbus/dbus-hash.c (_dbus_hash_test): Don't try to allocate the
+	keys on the stack... it's 640k of data.
+
+	* dbus/dbus-sysdeps.c (_dbus_read_credentials_unix_socket): Always
+	read the credentials byte off the socket, even if we don't have
+	SO_PEERCRED.
+	(_dbus_poll): Implement poll() using select() for systems which
+	don't have it.
+
+	* glib/test-dbus-glib.c (main): Print out an error if no
+	parameters are given.
+
+	* test/data/auth/fallback.auth-script: Added.  Tests that a client
+	can fallback to a secondary auth mechanism if the first fails.
+
+2003-02-18  Havoc Pennington  <hp@pobox.com>
+
+	* AUTHORS: add Alex
+
+2003-02-17  Havoc Pennington  <hp@pobox.com>
+
+	* doc/dbus-specification.sgml: lots of cosmetic
+	cleanups/rearrangement, add assorted FIXME, change DBUS_ADDRESS
+	env variable to DBUS_BUS_ADDRESS, s/client/application/,
+	s/server/bus/ (except in authentication section). Add a section
+	"Message Bus Message Routing"
+
+2003-02-17  Anders Carlsson  <andersca@codefactory.se.>
+
+	Release 0.4
+
+	* NEWS: Update
+
+2003-02-17  Anders Carlsson  <andersca@codefactory.se>
+
+	* doc/dbus-specification.sgml:
+	Specification updates.
+
+2003-02-17  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/activation.c: (bus_activation_init), (child_setup),
+	(bus_activation_activate_service):
+	* bus/activation.h:
+	* bus/main.c: (main):
+	Set DBUS_ADDRESS environment variable.
+
+	* dbus/dbus-errors.c: (dbus_set_error):
+	Don't use va_copy since that's a C99 feature.
+
+	* dbus/dbus-sysdeps.c: (_dbus_setenv), (do_exec),
+	(_dbus_spawn_async):
+	* dbus/dbus-sysdeps.h:
+	Add child_setup_func to _dbus_spawn_async.
+
+	* doc/dbus-specification.sgml:
+	Update specification.
+
+	* test/spawn-test.c: (setup_func), (main):
+	Fix test.
+
+2003-02-17  Alexander Larsson  <alexl@redhat.com>
+
+	* dbus/dbus-connection.c (_dbus_connection_handler_destroyed_locked):
+	Added todo.
+
+2003-02-17  Anders Carlsson  <andersca@codefactory.se>
+
+	* doc/.cvsignore:
+	* doc/Makefile.am:
+	* doc/dbus-test-plan.sgml:
+	Add test plan document.
+
+	* test/Makefile.am:
+	Fix distcheck.
+
+2003-02-17  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-message.c: (decode_header_data),
+	(_dbus_message_loader_return_buffer):
+	Set the header padding amount when loading a message.
+
+2003-02-16  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/dispatch.c: (send_one_message):
+	Only send broadcast messages to registered connections.
+
+	* dbus/dbus-message.c: (dbus_message_name_is):
+	* dbus/dbus-message.h:
+	New convenience function.
+
+	* dbus/dbus-transport-debug.c: (do_reading):
+	Only dispatch one message per run.
+
+	* test/Makefile.am:
+	* test/bus-test.c: (new_connection_callback), (die),
+	(test_hello_client1_handler), (test_hello_client2_handler),
+	(test_hello_replies), (main):
+
+	* test/bus-test-loop.[ch]:
+	Add these.
+
+2003-02-16  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c (dbus_connection_dispatch_message): fix
+	backward conditional
+
+2003-02-16  Alexander Larsson  <alexl@redhat.com>
+
+	* dbus/dbus-connection.c:
+	Implement sent_message_with_reply. (with_reply_and block is still
+	busted).
+	Made dispatch_message not lose message if OOM.
+
+	* dbus/dbus-errors.h:
+	Add NoReply error (for reply timeouts).
+
+2003-02-16  Alexander Larsson  <alexl@redhat.com>
+
+	* dbus/dbus-hash.c (_dbus_hash_table_unref):
+	Actually free keys and values when destroying hashtable.
+
+2003-02-16  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-auth.c: (client_try_next_mechanism):
+	Plug a leak.
+
+	* dbus/dbus-threads.c: (dbus_condvar_wait_timeout):
+	Return TRUE if there's no thread implementation around.
+
+	* glib/dbus-gmain.c: (free_source),
+	(dbus_connection_hookup_with_g_main):
+	Make sure to remove the GSource when the connection is finalized.
+
+2003-02-16  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/dispatch.c: (bus_dispatch_message_handler):
+	* dbus/dbus-errors.h:
+	Return an error if someone tries to send a message to a service
+	that doesn't exist.
+
+2003-02-16  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/activation.c: (load_directory), (bus_activation_init),
+	(bus_activation_activate_service):
+	* bus/activation.h:
+	* bus/driver.c:
+	(bus_driver_handle_activate_service), (bus_driver_handle_message):
+	More work on the activation handling.
+
+	* dbus/dbus-errors.h:
+	Add some error messages
+
+	* dbus/dbus-message.c: (dbus_message_new_error_reply):
+	* dbus/dbus-message.h:
+	New function that creates an error message.
+
+	* dbus/dbus-protocol.h:
+	Add ACTIVATE_SERVER message.
+
+	* dbus/dbus-server-unix.c: (unix_handle_watch),
+	(_dbus_server_new_for_domain_socket):
+	Call _dbus_fd_set_close_on_exec.
+
+	* dbus/dbus-sysdeps.c: (make_pipe), (do_exec),
+	(_dbus_spawn_async), (_dbus_disable_sigpipe),
+	(_dbus_fd_set_close_on_exec):
+	* dbus/dbus-sysdeps.h:
+	Add _dbus_fd_set_close_on exec function. Also add function that checks
+	that all open fds are set to close-on-exec and warns otherwise.
+
+	* dbus/dbus-transport-unix.c:
+	(_dbus_transport_new_for_domain_socket):
+	Call _dbus_fd_set_close_on_exec.
+
+2003-02-16  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c (dbus_connection_set_change_sigpipe):
+	allow people to avoid setting SIGPIPE to SIG_IGN
+	(_dbus_connection_new_for_transport): disable SIGPIPE unless
+	we've been asked not to
+
+2003-02-15  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-list.c: (_dbus_list_append_link),
+	(_dbus_list_prepend_link):
+	* dbus/dbus-memory.c: (dbus_malloc), (dbus_malloc0),
+	(dbus_realloc):
+	Warning fixes.
+
+2003-02-15  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/Makefile.am:
+	* bus/activation.c: (bus_activation_entry_free),
+	(add_desktop_file_entry), (load_directory), (bus_activation_init):
+	* bus/activation.h:
+	* bus/main.c: (main):
+	Add simple activation support, doesn't work yet though.
+
+2003-02-15   Zack Rusin  <zack@kde.org>
+
+	* qt/dbus-qthread.cpp:  small casting fix
+
+2003-02-15  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-errors.c: (dbus_set_error):
+	* dbus/dbus-errors.h:
+	Add a few errors and make dbus_set_error void.
+
+	* dbus/dbus-sysdeps.c:
+	(_dbus_errno_to_string), (close_and_invalidate), (make_pipe),
+	(write_err_and_exit), (read_ints), (do_exec), (_dbus_spawn_async):
+	* dbus/dbus-sysdeps.h:
+	Add _dbus_spawn_async.
+
+	* test/spawn-test.c: (main):
+	Test for _dbus_spawn_async.
+
+2003-02-15  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-internals.h:
+	Fix build without tests.
+
+	* dbus/dbus-list.c: (alloc_link):
+	Fix a segfault when a malloc fails.
+
+	* dbus/dbus-memory.c: (initialize_malloc_debug), (dbus_malloc),
+	(dbus_malloc0), (dbus_realloc):
+	Add support for malloc debugging.
+
+2003-02-15  Alexander Larsson  <alexl@redhat.com>
+
+	* dbus/dbus-threads.c:
+	* dbus/dbus-threads.h:
+	Add condvars. Remove static mutext from API.
+	Implement static mutexes by initializing them from threads_init.
+
+	* glib/dbus-gthread.c:
+	* qt/dbus-qthread.cpp:
+	Update with the thread api changes.
+
+
+	* dbus/dbus-list.c:
+	* dbus/dbus-list.h:
+	Turn StaticMutex into normal mutex + init function.
+	Export new functions _dbus_list_alloc_link, _dbus_list_free_link,
+	_dbus_list_append_link, _dbus_list_prepend_link
+
+
+	* dbus/dbus-sysdeps.c:
+	* dbus/dbus-sysdeps.h:
+	New type dbus_atomic_t, and new functions _dbus_atomic_inc,
+	_dbus_atomic_dec. Only slow fallback implementation at the moment.
+
+	* dbus/dbus-protocol.h:
+	Add DBUS_MESSAGE_LOCAL_DISCONNECT define
+
+	* dbus/dbus-message.c:
+	Make ref/unref atomic.
+	Fix some docs.
+
+	* dbus/dbus-connection-internal.h:
+	* dbus/dbus-connection.c:
+	* dbus/dbus-connection.h:
+	Make threadsafe.
+	Change _peek to _borrow,_return & _steal_borrowed.
+	Change disconnect callback to event.
+	Make dbus_connection_dispatch_messages reentrant.
+
+	* dbus/dbus-transport.c:
+	Don't ref the connection on calls to the transport
+	implementation.
+
+	* dbus/dbus-message-handler.c:
+	Make threadsafe.
+
+	* glib/dbus-gmain.c:
+	Don't use peek_message anymore
+
+	* test/Makefile.am:
+	* test/debug-thread.c:
+	* test/debug-thread.h:
+	Simple thread implementation that asserts() on deadlocks in
+	single-threaded code.
+
+	* test/bus-test.c:
+	(main) Call debug_threads_init.
+
+	* test/watch.c:
+	Use disconnect message instead of disconnect callback.
+
+	* bus/connection.c:
+	* bus/connection.h:
+	Don't call dbus_connection_set_disconnect_function. Instead export
+	bus_connection_disconnect.
+
+	* bus/dispatch.c:
+	Call bus_connection_disconnect when we get a disconnected message.
+
+2003-02-15  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (dbus_message_new): fool around with the
+	docs
+
+2003-02-14  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-mempool.c: fail if the debug functions so indicate
+
+	* dbus/dbus-memory.c: fail if the debug functions indicate we
+	should
+
+	* dbus/dbus-internals.c (_dbus_set_fail_alloc_counter)
+	(_dbus_decrement_fail_alloc_counter): debug functions to
+	simulate memory allocation failures
+
+2003-02-14  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-errors.h (struct DBusError): add a word of padding
+	to DBusError
+
+2003-02-13  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/driver.c: (bus_driver_handle_hello):
+	* bus/driver.h:
+	* bus/services.c: (bus_service_lookup):
+	Reorder message sending so we get a more sane order.
+
+	* test/bus-test.c: (message_handler):
+	Fix tyop.
+
+2003-02-13  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/driver.c: (bus_driver_send_service_deleted),
+	(bus_driver_send_service_created), (bus_driver_send_service_lost),
+	(bus_driver_send_service_acquired), (bus_driver_handle_hello),
+	(bus_driver_send_welcome_message),
+	(bus_driver_handle_list_services),
+	(bus_driver_handle_acquire_service),
+	(bus_driver_handle_service_exists):
+	* dbus/dbus-bus.c: (dbus_bus_register_client),
+	(dbus_bus_acquire_service), (dbus_bus_service_exists):
+	* dbus/dbus-errors.c: (dbus_result_to_string):
+	* dbus/dbus-errors.h:
+	* dbus/dbus-message.c: (dbus_message_append_args),
+	(dbus_message_append_args_valist), (dbus_message_get_args),
+	(dbus_message_get_args_valist), (dbus_message_get_args_iter),
+	(dbus_message_iter_get_arg_type), (dbus_message_iter_get_string),
+	(dbus_message_iter_get_byte_array),
+	(dbus_message_iter_get_string_array), (message_iter_test),
+	(check_message_handling), (_dbus_message_test):
+	* dbus/dbus-message.h:
+	* test/bus-test.c: (main):
+	Change fields to arguments in messages, so that they won't be
+	confused with header fields.
+
+	* glib/test-dbus-glib.c: (main):
+	Remove append_fields from hello message.
+
+2003-02-13  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-errors.c:
+	* dbus/dbus-message.c:
+	* dbus/dbus-string.c:
+	Documentation fixes.
+
+2003-02-13  Anders Carlsson  <andersca@codefactory.se>
+
+	* glib/dbus-gmain.c: (timeout_handler), (add_timeout),
+	(remove_timeout):
+	Implement support for timeouts in dbus-glib.
+
+2003-02-13  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-message-builder.c: (_dbus_message_data_load):
+	* dbus/dbus-message.c: (process_test_subdir):
+	* test/break-loader.c: (find_breaks_based_on):
+	Plug some memory leaks.
+
+2003-02-13  Richard Hult  <rhult@codefactory.se>
+
+	* bus/main.c: Fix build.
+
+	* dbus/dbus-errors.h:
+	* dbus/dbus-errors.c: Fix copyright for Anders.
+
+2003-02-13  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/Makefile.am:
+	Add utils.[ch]
+
+	* bus/connection.c: (bus_connection_foreach):
+	Fix a warning.
+
+	* bus/desktop-file.c: (grow_lines_in_section), (grow_sections),
+	(unescape_string), (new_section), (parse_section_start),
+	(parse_key_value), (report_error), (bus_desktop_file_load),
+	(bus_desktop_file_get_string):
+	* bus/desktop-file.h:
+	Use DBusError for error reporting.
+
+	* bus/dispatch.c: (send_one_message),
+	(bus_dispatch_message_handler):
+	* bus/driver.c: (bus_driver_send_service_deleted),
+	(bus_driver_send_service_created), (bus_driver_send_service_lost),
+	(bus_driver_send_service_acquired), (bus_driver_handle_hello),
+	(bus_driver_send_welcome_message),
+	(bus_driver_handle_list_services),
+	(bus_driver_handle_acquire_service),
+	(bus_driver_handle_service_exists):
+	* bus/loop.c: (bus_loop_run):
+	* bus/main.c:
+	Use BUS_HANDLE_OOM instead of _DBUS_HANDLE_OOM.
+
+	* bus/utils.c: (bus_wait_for_memory):
+	* bus/utils.h:
+	New files with general utility functions.
+
+	* dbus/dbus-internals.h:
+	Remove _DBUS_HANDLE_OOM.
+
+2003-02-13  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-errors.c: (dbus_result_to_string), (dbus_error_init),
+	(dbus_error_free), (dbus_set_error_const), (dbus_set_error):
+	* dbus/dbus-errors.h:
+	Add DBusError structure.
+
+2003-02-13  Anders Carlsson  <andersca@codefactory.se>
+
+	* test/data/valid-messages/standard-acquire-service.message:
+	* test/data/valid-messages/standard-hello.message:
+	* test/data/valid-messages/standard-list-services.message:
+	* test/data/valid-messages/standard-service-exists.message:
+	Add some standard messages.
+
+2003-02-13  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/driver.c: (bus_driver_send_welcome_message),
+	(bus_driver_handle_list_services),
+	(bus_driver_handle_acquire_service),
+	(bus_driver_handle_service_exists), (bus_driver_handle_message):
+	Update for API changes in libdbus.
+
+	* dbus/dbus-message.c: (dbus_message_new_reply):
+	* dbus/dbus-message.h:
+	Remove the name argument. The spec states that replies shouldn't
+	have a name.
+
+2003-02-13  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/desktop-file.c: (parse_section_start), (parse_key_value),
+	(report_error), (bus_desktop_file_load), (lookup_section),
+	(lookup_line), (bus_desktop_file_get_raw),
+	(bus_desktop_file_get_string):
+	* bus/desktop-file.h:
+	Some fixes, and new functions for getting a key value from a section.
+
+2003-02-13  Havoc Pennington  <hp@pobox.com>
+
+	* test/data/auth/fail-after-n-attempts.auth-script: new test
+
+	* dbus/dbus-auth.c (send_rejected): shutdown_mech() when we
+	reject the client.
+
+2003-02-13  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-auth.c (handle_server_data_external_mech): args to
+	dbus_credentials_match were backward
+
+	* dbus/dbus-auth-script.c (_dbus_auth_script_run): support
+	NO_CREDENTIALS and ROOT_CREDENTIALS
+
+	* dbus/dbus-auth.c (_dbus_auth_do_work): move get_state() routine
+	into here. Never process more commands after we've reached an
+	end state; store further data as unused bytes.
+
+	* test/data/auth/*: add more auth tests
+
+	* dbus/dbus-auth-script.c (_dbus_auth_script_run): support EXPECT
+	command to match exact string and EXPECT_UNUSED to match unused
+	bytes
+
+	* test/Makefile.am (dist-hook): fix to dist all the test stuff
+
+2003-02-12  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-string.c (_dbus_string_pop_line): fix to also strip
+	\r off of popped lines
+
+	* dbus/dbus-auth.c (_dbus_auth_test): write code to run auth
+	scripts
+
+	* dbus/dbus-auth-script.c (_dbus_auth_script_run): when doing a
+	SEND, append \r\n
+
+2003-02-12  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/Makefile.am: remove break-loader from the build, since it
+	moved.
+
+	* configure.in: add --enable-gcov to turn on coverage profiling
+	flags and disable optimization
+
+2003-02-10  Havoc Pennington  <hp@pobox.com>
+
+        * dbus/dbus-auth-script.c, dbus/dbus-auth-script.h: sync
+	initial cut at test framework for DBusAuth from laptop.
+	Doesn't quite work yet but it compiles and I need to get
+	it off the 266mhz laptop. ;-)
+
+	* dbus/dbus-server-debug.c (_dbus_server_debug_accept_transport):
+	fix a memleak in error case
+
+2003-02-12  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/Makefile.am:
+	* bus/desktop-file.c:
+	* bus/desktop-file.h:
+	Add a desktop file parser.
+
+2003-02-11  Zack Rusin  <zack@kde.org>
+
+	* qt/message.[h|cpp]: sample implementation
+	of the KDE wrapper for DBusMessage
+
+2003-02-09  Zack Rusin  <zack@kde.org>
+
+	* test/bus-test.c: make_it_compile
+	* doc/dbus-specification.sgml: minimal semantic fix
+
+2003-02-06  Anders Carlsson  <andersca@codefactory.se>
+
+	Release 0.3
+
+	* NEWS: Update
+
+2003-02-06  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/Makefile.am:
+	* dbus/dbus-break-loader.c:
+	* test/Makefile.am:
+	* test/break-loader.c:
+	Move dbus-break-loader to test/ and rename it to break-loader.
+
+2003-02-02  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-keyring.c, dbus/dbus-keyring.h: template files
+	for code to manage cookies in your home directory
+
+	* dbus/dbus-sysdeps.c (_dbus_generate_random_bytes): new function
+
+	* dbus/dbus-auth.c (get_state): impose a maximum number of tries
+	to authenticate, then disconnect the client.
+
+2003-02-03  Alexander Larsson  <alexl@redhat.com>
+
+	* dbus/dbus-message.c (dbus_message_append_fields):
+	Correct docs.
+
+2003-02-02  Anders Carlsson  <andersca@codefactory.se>
+
+	* doc/dbus-specification.sgml:
+	Update address format section.
+
+2003-02-02  Anders Carlsson  <andersca@codefactory.se>
+
+	* test/Makefile.am:
+	* test/bus-test.c: (get_time), (add_timeout), (remove_timeout),
+	(message_handler), (new_connection_callback), (loop_quit),
+	(loop_run), (main):
+	Add bus test.
+
+2003-02-02  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/driver.c: (bus_driver_handle_service_exists):
+	Simplify the code a bit.
+
+	* dbus/dbus-bus.c: (dbus_bus_service_exists):
+	Fix a silly.
+
+2003-02-02  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/Makefile.am:
+	Add libdbus-daemon.la and link to it.
+
+2003-02-01  James Willcox  <jwillcox@gnome.org>
+
+	* bus/driver.c: (bus_driver_handle_own_service):
+	Actually include the service reply code in the message.
+
+2003-02-02  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/driver.c: (bus_driver_handle_service_exists):
+	Don't unref the incoming message.
+
+2003-02-02  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus.h: Add dbus-address.h and dbus-bus.h
+
+2003-02-02  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-server.c: (dbus_server_listen):
+	* dbus/dbus-transport.c: (_dbus_transport_open):
+	ifdef out the calls to the debug transport and server.
+
+2003-02-02  Alexander Larsson  <alexl@redhat.com>
+
+	* dbus/dbus-watch.c (dbus_watch_get_flags):
+	Add note in the docs that ERROR or HANGUP won't be returned
+	and are assumed always on.
+
+	* glib/dbus-gmain.c (add_watch):
+	Always add IO_ERR | IO_HUP
+
+	* dbus/dbus-message.h:
+	Add semicolon after dbus_message_iter_get_string_array().
+	Makes qt code build again
+
+2003-02-01  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/driver.c: (create_unique_client_name),
+	(bus_driver_handle_hello):
+	Don't take a name, just use a numeric id to identify
+	each client.
+
+	* dbus/Makefile.am:
+	* dbus/dbus-bus.c: (dbus_bus_register_client),
+	(dbus_bus_acquire_service), (dbus_bus_service_exists):
+	* dbus/dbus-bus.h:
+	Add new convenience functions for communicating with the bus.
+
+	* dbus/dbus-message.h:
+
+	* dbus/dbus-protocol.h:
+	Fix a typo.
+
+2003-02-01  Alexander Larsson  <alexl@redhat.com>
+
+	* dbus/dbus-message.c (dbus_message_append_fields):
+	Add some more doc comments.
+
+2003-02-01  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-break-loader.c (randomly_modify_length): change
+	a 4-byte value in the message as if it were a length
+
+	* dbus/dbus-sysdeps.c (_dbus_string_save_to_file): don't set
+	execute bit on saved files
+
+2003-02-01  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-break-loader.c (main): new program to find messages
+	that break the loader.
+
+	* dbus/dbus-sysdeps.c (_dbus_string_append_uint): new function
+	* dbus/dbus-sysdeps.c (_dbus_string_save_to_file): new function
+
+	* dbus/dbus-string.c (_dbus_string_set_byte): new
+
+2003-01-31  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c: refactor the test code to be more general,
+	in preparation for writing a "randomly permute test cases to
+	try to break the loader" program.
+
+2003-01-31  Havoc Pennington  <hp@pobox.com>
+
+	* doc/dbus-specification.sgml: work on the specification
+
+	* dbus/dbus-message.c (_dbus_message_loader_return_buffer): check
+	the protocol version of the message.
+
+	* dbus/dbus-protocol.h: drop special _REPLY names, the spec
+	no longer specifies that.
+	(DBUS_SERVICE_REPLY_SERVICE_EXISTS): fix flags (1/2/4/8 not
+	1/2/3/4)
+
+	* dbus/dbus-marshal.c (_dbus_marshal_get_arg_end_pos): add missing
+	"break" for DBUS_TYPE_NIL, remove @todo
+
+2003-01-31  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (dbus_message_set_is_error_reply): rename
+	just set_is_error/get_is_error as this is a commonly-used
+	function, and write docs.
+
+2003-01-31  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-address.c: (dbus_address_entry_free):
+	Free key and value lists.
+
+	* dbus/dbus-internals.c: (_dbus_type_to_string):
+	Add the types we didn't have.
+
+	* dbus/dbus-marshal.c: (_dbus_marshal_get_arg_end_pos),
+	(_dbus_marshal_validate_arg):
+	Add NIL types.
+
+	* dbus/dbus-message.c: (dbus_message_set_sender):
+	Remove todo about being able to set sender to NULL.
+
+	(dbus_message_set_is_error_reply),
+	(dbus_message_get_is_error_reply):
+	* dbus/dbus-message.h:
+	New functions.
+
+	* dbus/dbus-protocol.h:
+	Add error reply flag.
+
+	* test/data/valid-messages/opposite-endian.message:
+	Add NIL type to test.
+
+2003-01-31  Havoc Pennington  <hp@pobox.com>
+
+	* doc/dbus-specification.sgml: fully specify the header.  Add
+	flags and major protocol version, and change header/body len to
+	unsigned.
+
+	* dbus/dbus-message-builder.c (append_saved_length): append length
+	as uint32
+
+	* dbus/dbus-message.c (dbus_message_create_header): change header
+	length and body length to unsigned. Add the new fields from the
+	spec
+	(_dbus_message_loader_return_buffer): unsigned header/body len
+
+2003-01-30  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-auth.c: rework to use only REJECTED, no
+	MECHANISMS
+
+	* doc/dbus-sasl-profile.txt: drop MECHANISMS and just
+	use REJECTED, suggested by Mark McLoughlin
+
+2003-01-30  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-server.c (dbus_server_listen): @todo about how we need
+	a better way to report errors here. e.g.  "unix address lacks
+	path" or something. also "no such file" when the path doesn't
+	exist, etc.
+
+	* dbus/dbus-address.c (dbus_address_entries_free): add @todo about
+	leaking list nodes
+	(dbus_parse_address): add @todo about documenting address format,
+	and allowing , and ; to be escaped
+
+2003-01-30  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/Makefile.am:
+	Add dbus-address.[ch]
+
+	* dbus/dbus-address.c: (dbus_address_entry_free),
+	(dbus_address_entries_free), (create_entry),
+	(dbus_address_entry_get_method), (dbus_address_entry_get_value),
+	(dbus_parse_address), (_dbus_address_test):
+	* dbus/dbus-address.h:
+	New files for dealing with address parsing.
+
+	* dbus/dbus-connection.c:
+	Document timeout functions.
+
+	* dbus/dbus-message.c:
+	Document dbus_message_new_from_message.
+
+	* dbus/dbus-server-debug.c:
+	Document.
+
+	* dbus/dbus-server.c: (dbus_server_listen):
+	Parse address and use correct server implementation.
+
+	* dbus/dbus-string.c: (_dbus_string_find_to), (_dbus_string_test):
+	* dbus/dbus-string.h:
+	New function with test.
+
+	* dbus/dbus-test.c: (dbus_internal_symbol_do_not_use_run_tests):
+	* dbus/dbus-test.h:
+	Add address tests.
+
+	* dbus/dbus-transport-debug.c:
+	Document.
+
+	* dbus/dbus-transport.c: (_dbus_transport_open):
+	Parse address and use correct transport implementation.
+
+2003-01-30  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c: use message->byte_order instead of
+	DBUS_COMPILER_BYTE_ORDER throughout.
+	(dbus_message_create_header): pad header to align the
+	start of the body of the message to 8-byte boundary
+
+	* dbus/dbus-marshal.h: make all the demarshalers take const
+	DBusString arguments.
+
+	* dbus/dbus-message.c (_dbus_message_loader_return_buffer):
+	validate message args here, so we don't have to do slow validation
+	later, and so we catch bad messages as they are incoming. Also add
+	better checks on header_len and body_len. Also fill in
+	message->byte_order
+
+	* dbus/dbus-string.c (_dbus_string_validate_utf8): new (not
+	implemented properly)
+	(_dbus_string_validate_nul): new function to check all-nul
+
+	* dbus/dbus-marshal.c (_dbus_marshal_get_field_end_pos): rename
+	get_arg_end_pos and remove all validation
+	(_dbus_marshal_validate_arg): actually do validation here.
+
+2003-01-29  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (check_message_handling): fix assertion
+	failure on set_client_serial
+
+2003-01-28  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-server-debug.c: Add doc section comments
+
+	* dbus/dbus-transport-debug.c: add doc section comments
+
+2003-01-28  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-string.c (_dbus_string_base64_decode): append bytes in
+	the reverse order from how I had it
+	(_dbus_string_base64_encode): reverse encoding order. I was
+	basically byteswapping everything during encoding.
+
+2003-01-28  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-connection-internal.h:
+	* dbus/dbus-connection.c: (_dbus_connection_add_timeout),
+	(_dbus_connection_remove_timeout):
+	Add functions for adding and removing timeouts.
+
+	* dbus/dbus-message.c: (dbus_message_new_from_message):
+	Add new function that takes a message and creates an exact
+	copy of it, but with the refcount set to 1.
+	(check_message_handling):
+	Fix build error.
+
+	* dbus/dbus-server-protected.h:
+	* dbus/dbus-server.c: (_dbus_server_init_base),
+	(_dbus_server_finalize_base), (_dbus_server_add_timeout),
+	(dbus_server_set_timeout_functions):
+	(_dbus_server_remove_timeout):
+	New functions so that a server can add and remove timeouts.
+
+	(dbus_server_listen):
+	Add commented out call to dbus_server_debug_new.
+
+	* dbus/dbus-timeout.c: (_dbus_timeout_new):
+	Actually set the handler, doh.
+
+	* dbus/dbus-transport.c: (_dbus_transport_open):
+	Add commented out call to dbus_transport_debug_client_new.
+
+	* dbus/Makefile.am:
+	Add dbus-transport-debug.[ch] and dbus-server-debug.[ch]
+
+2003-01-28  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (check_message_handling): function to check
+	on the loaded message, iterates over it etc.
+
+2003-01-28  Havoc Pennington  <hp@pobox.com>
+
+	* test/Makefile.am (dist-hook): fix make distdir
+
+	* dbus/Makefile.am (TESTS_ENVIRONMENT): fix make check
+
+2003-01-27  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-mempool.c (time_for_size): replace printf with
+	_dbus_verbose
+
+	* dbus/dbus-message-builder.c (_dbus_message_data_load): allow
+	empty lines; fix the SAVE_LENGTH stuff to be
+	START_LENGTH/END_LENGTH so it actually works; couple other
+	bugfixes
+
+	* test/Makefile.am (dist-hook): add dist-hook for .message files
+
+	* dbus/dbus-string.c (DBUS_STRING_COPY_PREAMBLE): source of a copy
+	can be constant or locked.
+	(_dbus_string_free): allow freeing a const string as
+	documented/intended
+
+	* dbus/dbus-sysdeps.c (_dbus_concat_dir_and_file): utility
+
+	* dbus/dbus-test-main.c (main): take an argument which is the
+	directory containing test data
+
+	* dbus/dbus-message.c (_dbus_message_test): pass a test_data_dir
+	argument to this and load all the messages in test/data/
+	checking that they can be loaded or not loaded as appropriate.
+
+2003-01-27  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/dispatch.c: (bus_dispatch_message_handler):
+	Dispatch messages sent to services.
+
+	* bus/driver.c: (bus_driver_send_service_deleted),
+	(bus_driver_send_service_created), (bus_driver_send_service_lost),
+	(bus_driver_send_service_acquired):
+	Add helper functions for sending service related messages.
+
+	(bus_driver_send_welcome_message):
+	Send HELLO_REPLY instead of WELCOME.
+
+	(bus_driver_handle_list_services):
+	Send LIST_SERVICES_REPLY instead of SERVICES.
+
+	(bus_driver_handle_own_service),
+	(bus_driver_handle_service_exists):
+	New message handlers.
+
+	(bus_driver_handle_message):
+	Invoke new message handlers.
+
+	(bus_driver_remove_connection):
+	Don't remove any services here since that's done automatically
+	by bus_service_remove_owner now.
+
+	* bus/driver.h:
+	New function signatures.
+
+	* bus/services.c: (bus_service_add_owner):
+	Send ServiceAcquired message if we're the only primary owner.
+
+	(bus_service_remove_owner):
+	Send ServiceAcquired/ServiceLost messages.
+
+	(bus_service_set_prohibit_replacement),
+	(bus_service_get_prohibit_replacement):
+	Functions for setting prohibit replacement.
+
+	(bus_service_has_owner):
+	New function that checks if a connection is in the owner queue of
+	a certain service.
+
+	* bus/services.h:
+	Add new function signatures.
+
+	* dbus/dbus-list.c: (_dbus_list_test):
+	Add tests for _dbus_list_remove_last and traversing the list backwards.
+
+	* dbus/dbus-list.h:
+	Fix a typo in _dbus_list_get_prev_link, if we're at the first element we can't
+	go any further, so return NULL then.
+
+	* dbus/dbus-protocol.h:
+	Add new messages, service flags and service replies.
+
+2003-01-26  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message-builder.c: implement, completely untested.
+
+	* test/data/*: add data to be used in testing.
+	".message" files are our simple loadable text format.
+	".message-raw" will be binary dumps of messages.
+
+	* dbus/dbus-string.c (_dbus_string_starts_with_c_str): new
+
+2003-01-26  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_file_get_contents): new function
+
+	* dbus/dbus-errors.c (dbus_result_to_string): add
+	file errors
+
+	* dbus/dbus-message-builder.c: new file, will contain code to load
+	up messages from files. Not implemented yet.
+
+2003-01-26  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.c (dbus_message_set_sender): support deleting
+	the sender by setting to NULL
+
+2003-01-26  Havoc Pennington  <hp@pobox.com>
+
+        The unit tests pass, but otherwise untested.  If it breaks, the
+	tests should have been better. ;-)
+
+	* bus/driver.c (bus_driver_handle_hello): return if we disconnect
+	the connection.
+
+	* dbus/dbus-message.c: redo everything so we maintain
+	message->header as the only copy of the various fields.
+	This avoids the possibility of out-of-memory in some cases,
+	for example dbus_message_lock() can't run out of memory anymore,
+	and avoids extra copying. Figured I may as well go ahead and do
+	this since it was busted for dbus_message_lock to not return
+	failure on OOM, and dbus_message_write_header was totally
+	unchecked for OOM. Also fixed some random other bugs.
+
+	* dbus/dbus-marshal.c (_dbus_marshal_get_field_end_pos): verify
+	that strings are nul-terminated. Also, end_pos can be equal
+	to string length just not greater than, I think.
+	(_dbus_marshal_set_int32): new function
+	(_dbus_marshal_set_uint32): new function
+	(_dbus_marshal_set_string): new function
+
+	* dbus/dbus-connection.c (_dbus_connection_new_for_transport): fix
+	a warning, init timeout_list to NULL
+	(dbus_connection_send_message): don't use uninitialized variable
+	"serial"
+
+	* dbus/dbus-string.c (_dbus_string_replace_len): new function
+
+2003-01-26  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/driver.c: (bus_driver_handle_hello),
+	(bus_driver_send_welcome_message):
+	Plug leaks
+
+2003-01-26  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-auth.c: (process_auth), (_dbus_auth_unref):
+	* dbus/dbus-connection.c: (_dbus_connection_new_for_transport),
+	(dbus_connection_unref):
+	* dbus/dbus-marshal.c: (_dbus_marshal_test):
+	* dbus/dbus-message.c: (dbus_message_unref),
+	Plug memory leaks.
+
+	(dbus_message_get_fields):
+	Remove debugging printout.
+
+	(_dbus_message_loader_return_buffer):
+	Don't store the header string.
+
+	(_dbus_message_test):
+	Plug leaks.
+
+2003-01-26  Richard Hult  <rhult@codefactory.se>
+
+	* glib/dbus-gmain.c (dbus_connection_dispatch): Traverse a copy of
+	the file descriptor list, since it can change under us.
+
+2003-01-25  Anders Carlsson  <andersca@codefactory.se>
+
+	* glib/dbus-gmain.c: (dbus_connection_prepare),
+	(dbus_connection_check), (dbus_connection_dispatch), (add_watch),
+	(remove_watch), (dbus_connection_hookup_with_g_main):
+	Rewrite the glib handling to use its own GSource instead of a
+	GIOChannel so we can catch messages put in the queue while waiting
+	for a reply.
+
+2003-01-25  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/Makefile.am:
+	* bus/connection.c: (connection_disconnect_handler),
+	(connection_watch_callback), (bus_connection_setup):
+	* bus/dispatch.c: (send_one_message),
+	(bus_dispatch_broadcast_message), (bus_dispatch_message_handler),
+	(bus_dispatch_add_connection), (bus_dispatch_remove_connection):
+	* bus/dispatch.h:
+	* bus/driver.c: (bus_driver_send_service_deleted),
+	(bus_driver_send_service_created), (bus_driver_handle_hello),
+	(bus_driver_send_welcome_message),
+	(bus_driver_handle_list_services), (bus_driver_remove_connection),
+	(bus_driver_handle_message):
+	* bus/driver.h:
+	Refactor code, put the message dispatching in its own file. Use
+	_DBUS_HANDLE_OOM. Also send ServiceDeleted messages when a client
+	is disconnected.
+
+2003-01-25  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-internals.h:
+	Add _DBUS_HANDLE_OOM macro, it doesn't do anything currently.
+
+	* dbus/dbus-message.c: (dbus_message_get_sender):
+	* dbus/dbus-message.h:
+	Implement dbus_message_get_sender.
+
+	* dbus/dbus-protocol.h:
+	Add message and service defines.
+
+2003-01-25  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-connection.c: (dbus_connection_send_message):
+	* dbus/dbus-message-internal.h:
+	* dbus/dbus-message.c: (_dbus_message_get_client_serial),
+	(dbus_message_write_header):
+	Remove _dbus_messag_unlock and don't set the client serial on a
+	message if one already exists.
+
+2003-01-24  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-list.c (alloc_link): put a thread lock on the global
+	list_pool
+
+	* bus/driver.c (bus_driver_handle_list_services): fix a leak
+	on OOM
+
+2003-01-25  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-list.c: (alloc_link), (free_link):
+	Use a memory pool for the links.
+
+2003-01-25  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/connection.c: (bus_connection_foreach):
+	* bus/connection.h:
+	Add new bus_connection_foreach function.
+
+	* bus/driver.c: (send_one_message), (bus_driver_broadcast_message):
+	Add function that broadcasts a message to all clients.
+
+	(bus_driver_send_service_created), (bus_driver_handle_hello),
+	(bus_driver_send_welcome_message),
+	(bus_driver_handle_list_services), (bus_driver_message_handler):
+	Implement functions that take care of listing services, and notifying
+	clients when new services are created.
+
+	* bus/services.c: (bus_services_list):
+	* bus/services.h:
+	Add new function that returns an array of strings with the currently
+	registered services.
+
+	* glib/dbus-glib.h:
+	* glib/dbus-gmain.c:
+	Update copyright year.
+
+2003-01-25  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-connection.c: (dbus_connection_send_message):
+	Unlock the message in case it was sent earlier.
+
+	(dbus_connection_send_message_with_reply_and_block):
+	Remove the reply message from the list.
+
+	* dbus/dbus-marshal.c: (_dbus_demarshal_string_array):
+	Set array_len and new_pos correctly.
+
+	(_dbus_marshal_test):
+	Remove debug output.
+
+	* dbus/dbus-message-internal.h:
+	* dbus/dbus-message.c: (_dbus_message_get_reply_serial):
+	New function that returns the reply serial.
+
+	(_dbus_message_unlock):
+	New function that unlocks a message and resets its header.
+
+	(dbus_message_append_string_array),
+	(dbus_message_get_fields_valist),
+	(dbus_message_iter_get_field_type),
+	(dbus_message_iter_get_string_array),
+	(dbus_message_get_fields),
+	(dbus_message_append_fields_valist):
+	Handle string arrays.
+
+	(dbus_message_set_sender):
+	Make this function public since the bus daemon needs it.
+
+	(decode_header_data):
+	Set the reply serial to -1 initially.
+
+	* dbus/dbus-message.h:
+	Add dbus_message_set_sender.
+
+2003-01-24  Havoc Pennington  <hp@pobox.com>
+
+	* doc/dbus-specification.sgml: add some stuff
+
+2003-01-22  Havoc Pennington  <hp@pobox.com>
+
+	* doc/dbus-specification.sgml: Start to document the protocol.
+
+2003-01-22  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c
+	(dbus_connection_send_message_with_reply_and_block): add some @todo
+
+	* bus/driver.c (bus_driver_add_connection): add a FIXME about memleak
+
+2003-01-21  Havoc Pennington  <hp@pobox.com>
+
+        (patch untested because can't compile)
+
+	* bus/driver.c (create_unique_client_name): make this function
+	never recycle client names. Also, caller should initialize
+	the DBusString.
+
+	* dbus/dbus-sysdeps.c (_dbus_get_current_time): new function
+
+2003-01-21  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-marshal.c: (_dbus_marshal_double),
+	(_dbus_marshal_int32), (_dbus_marshal_uint32),
+	(_dbus_marshal_int32_array), (_dbus_marshal_uint32_array),
+	(_dbus_marshal_double_array), (_dbus_marshal_string_array),
+	(_dbus_demarshal_int32_array), (_dbus_demarshal_uint32_array),
+	(_dbus_demarshal_double_array), (_dbus_demarshal_string_array),
+	(_dbus_marshal_get_field_end_pos), (_dbus_marshal_test):
+	* dbus/dbus-marshal.h:
+	* dbus/dbus-protocol.h:
+	Add support for marshalling and demarshalling integer, double
+	and string arrays.
+
+2003-01-21  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/Makefile.am:
+	Add driver.[ch]
+
+	* bus/connection.c: (connection_disconnect_handler):
+	Remove the connection from the bus driver's list.
+
+	(connection_watch_callback): Dispatch messages.
+
+	(free_connection_data): Free connection name.
+
+	(bus_connection_setup): Add connection to the bus driver's list.
+	(bus_connection_remove_owned_service):
+	(bus_connection_set_name), (bus_connection_get_name):
+	Add functions for setting and getting the connection's name.
+
+	* bus/connection.h:
+	Add function headers.
+
+	* bus/driver.c: (create_unique_client_name),
+	(bus_driver_handle_hello_message),
+	(bus_driver_send_welcome_message), (bus_driver_message_handler),
+	(bus_driver_add_connection), (bus_driver_remove_connection):
+	* bus/driver.h:
+	* bus/main.c:
+	* bus/services.c: (bus_service_free):
+	* bus/services.h:
+	New file that handles communication and registreation with the bus
+	itself.
+
+2003-01-21  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-connection.c: (dbus_connection_send_message):
+	Add a new client_serial parameter.
+
+	(dbus_connection_send_message_with_reply):
+	Remove a @todo since we've implemented the blocking function.
+
+	(dbus_connection_send_message_with_reply_and_block):
+	New function that sends a message and waits for a reply and
+	then returns the reply.
+
+	* dbus/dbus-connection.h:
+	Add new functions.
+
+	* dbus/dbus-errors.c: (dbus_result_to_string):
+	* dbus/dbus-errors.h:
+	Add new DBUS_RESULT.
+
+	* dbus/dbus-message-internal.h:
+	* dbus/dbus-message.c: (_dbus_message_get_reply_serial),
+	(_dbus_message_set_sender), (dbus_message_write_header),
+	(dbus_message_new_reply), (decode_header_data),
+	(_dbus_message_loader_return_buffer), (_dbus_message_test):
+	* dbus/dbus-message.h:
+	Add new functions that set the reply serial and sender.
+	Also marshal and demarshal them correctly and add test.
+
+	* dbus/dbus-protocol.h:
+	Add new DBUS_MESSAGE_TYPE_SENDER.
+
+	* glib/dbus-glib.h:
+	* glib/dbus-gmain.c: (watch_callback), (free_callback_data),
+	(add_watch), (remove_watch), (add_timeout), (remove_timeout),
+	(dbus_connection_hookup_with_g_main):
+	* glib/test-dbus-glib.c: (main):
+	Rewrite to use GIOChannel and remove the GSource crack.
+
+	* test/echo-client.c: (main):
+	* test/watch.c: (check_messages):
+	Update for changed APIs
+
+2003-01-19  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/Makefile.am: Add dbus-timeout.[cħ]
+
+	* dbus/dbus-connection.c: (_dbus_connection_new_for_transport):
+	Create a DBusTimeoutList.
+	(dbus_connection_set_timeout_functions): Add new function to
+	set timeout callbacks
+
+	* dbus/dbus-connection.h: Add public DBusTimeout API.
+
+	* dbus/dbus-message.c: (dbus_message_get_service):
+	* dbus/dbus-message.h:	New function.
+
+	* dbus/dbus-server.c: Fix small doc typo.
+
+	* dbus/dbus-timeout.[ch]: New files for mainloop timeouts.
+
+2003-01-19  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-string.c (_dbus_string_move_len): Don't delete all
+	of the string, just as long as specified.
+
+2003-01-19  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c (dbus_connection_get_is_authenticated):
+	new function
+
+	* dbus/dbus-server.c (dbus_server_set_max_connections)
+	(dbus_server_get_max_connections, dbus_server_get_n_connections):
+	keep track of current number of connections, and add API for
+	setting a max (but haven't implemented enforcing the max yet)
+
+2003-01-18  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-transport-unix.c (unix_do_iteration): only do the
+	reading/writing if read_watch != NULL or write_watch != NULL.
+
+	* dbus/dbus-message.c (_dbus_message_loader_return_buffer): fix
+	the message loader code to actually load message->header and
+	message->body into the newly-created message.
+
+	* dbus/dbus-transport-unix.c (check_write_watch): fix a mem leak
+	in OOM case
+
+	* dbus/dbus-connection.c (dbus_connection_set_max_message_size)
+	(dbus_connection_get_max_message_size)
+	(dbus_connection_set_max_live_messages_size)
+	(dbus_connection_get_max_live_messages_size): implement some
+	resource limitation functions
+
+	* dbus/dbus-resources.c: new file implementing some of the
+	resource limits stuff
+
+	* dbus/dbus-message.c (dbus_message_iter_get_byte_array): add
+	missing docs, add @todo to handle OOM etc.
+
+	* dbus/dbus-marshal.c (_dbus_demarshal_byte_array): add missing
+	docs
+
+2003-01-18  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-connection.c (dbus_connection_unref): disconnect the
+	connection if it hasn't been already.
+
+	* dbus/dbus-connection.h: kill off the idea of an ErrorFunction,
+	replace with DisconnectFunction.
+
+2003-01-18  Havoc Pennington  <hp@pobox.com>
+
+        Building --disable-verbose-mode --disable-asserts --disable-tests
+	cuts the library from 112K to 45K or so
+
+	* configure.in: check for varargs macro support,
+	add --enable-verbose-mode, --enable-asserts.
+
+	* dbus/dbus-internals.h (_dbus_assert): support
+	DBUS_DISABLE_ASSERT
+	(_dbus_verbose): support DBUS_ENABLE_VERBOSE_MODE
+
+2003-01-18  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-test.c: include config.h so that tests actually run
+
+	* dbus/dbus-string.c: add assertions that stuff is 8-byte aligned,
+	so the failure mode when that assumption fails will be plenty
+	obvious.
+
+2003-01-18  Havoc Pennington  <hp@pobox.com>
+
+	* configure.in: default --enable-tests to $USE_MAINTAINER_MODE
+
+	* dbus/Makefile.am: fix it up so dubs-test-main.c is included in
+	the distribution
+
+	* test/Makefile.am: don't use special variable "TESTS" for echo-*
+	since we don't want to use those in make check
+
+2003-01-15  Havoc Pennington  <hp@redhat.com>
+
+        Release 0.2
+
+	* NEWS: update
+
+2003-01-15  Havoc Pennington  <hp@redhat.com>
+
+	* test/Makefile.am: fix so that test source code ends up in the
+	distribution on make distcheck
+
+2003-01-15  Havoc Pennington  <hp@redhat.com>
+
+        Release 0.1.
+
+	* NEWS: update
+
+2003-01-15  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-test.c (dbus_internal_symbol_do_not_use_run_tests):
+	fix build when --disable-tests
+
+	* Makefile.am (EXTRA_DIST): put HACKING in here
+
+	* HACKING: document procedure for making a tarball release.
+
+2003-01-14  Anders Carlsson  <andersca@codefactory.se>
+
+	* bus/connection.c: (connection_error_handler),
+	(bus_connection_setup):
+	* bus/main.c: (main):
+	Make sure that the DBusConnectionData struct is NULLed
+	out to prevent a segfault.
+
+	* dbus/dbus-errors.c: (dbus_result_to_string):
+	* dbus/dbus-errors.h:
+	* dbus/dbus-message.c: (dbus_message_get_fields),
+	(dbus_message_get_fields_valist), (_dbus_message_test):
+	* dbus/dbus-message.h:
+	Make dbus_message_get_fields return a result code so we can
+	track invalid fields as well as oom.
+
+2003-01-11  Havoc Pennington  <hp@pobox.com>
+
+	* configure.in: change --enable-test/--enable-ansi action-if-given
+	to enable_foo=$enableval instead of enable_foo=yes
+
+2003-01-08  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-string.c (_dbus_string_align_length): new function
+
+	* dbus/dbus-test-main.c: move main() for test app here
+	* dbus/dbus-test.c
+	(dbus_internal_symbol_do_not_use_run_tests): we have to export a
+	symbol to run tests, because dbus-test isn't in the main
+	library
+
+        Code review nitpicks.
+
+	* dbus/dbus-message.c (dbus_message_write_header): add newlines
+	for people with narrow emacs ;-). Assert client_serial was filled
+	in. Assert message->name != NULL.
+	(dbus_message_append_fields): have "first_field_type" arg separate
+	from va list, needed for C++ binding that also uses varargs IIRC
+	and helps with type safety
+	(dbus_message_new): add @todo about using DBusString to store
+	service/name internally
+	(dbus_message_new): don't leak ->service and ->name on OOM later
+	in the function
+	(dbus_message_unref): free the service name
+	(dbus_message_get_fields): same change to varargs
+	i.e. first_field_type
+	(_dbus_message_loader_return_buffer): assert that the message data
+	is aligned (if not it's a bug in our code). Put in verbose griping
+	about why we set corrupted = TRUE.
+	(decode_header_data): add FIXME that char* is evil.  Was going to
+	add FIXME about evil locale-specific string.h strncmp, but just
+	switched to wacky string-as-uint32 optimization. Move check for
+	"no room for field name" above get_const_data_len() to avoid
+	assertion failure in get_const_data_len if we have trailing 2
+	bytes or the like. Check for service and name fields being
+	provided twice. Don't leak service/name on error. Require field
+	names to be aligned to 4 bytes.
+
+	* dbus/dbus-marshal.c: move byte swap stuff to header
+	(_dbus_pack_int32): uscore-prefix
+	(_dbus_unpack_int32): uscore-prefix
+	(_dbus_unpack_uint32): export
+	(_dbus_demarshal_string): add @todo complaining about use of
+	memcpy()
+	(_dbus_marshal_get_field_end_pos): add @todo about bad error
+	handling allowing corrupt data to go unchecked
+
+2003-01-08  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-transport-unix.c (unix_do_iteration): add read/write
+	to the select() as needed for authentication. (should be using
+	_dbus_poll() not select, but for another day)
+
+	* dbus/dbus.h: include dbus/dbus-protocol.h
+
+2003-01-08  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/Makefile.am (dbusinclude_HEADERS): Install
+	dbus-connection.h
+
+2003-01-08  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-internals.c: (_dbus_type_to_string):
+	New function that returns a string describing a type.
+
+	* dbus/dbus-marshal.c: (_dbus_demarshal_byte_array):
+	* dbus/dbus-marshal.h:
+	* dbus/dbus-message.c: (dbus_message_get_fields_valist),
+	(dbus_message_iter_get_field_type), (dbus_message_iter_get_double),
+	(dbus_message_iter_get_byte_array):
+	* dbus/dbus-message.h:
+	Add new convenience functions for appending and getting message fields.
+	Also add demarshalling routines for byte arrays.
+
+2003-01-07  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-connection-internal.h:
+	* dbus/dbus-connection.c: (_dbus_connection_new_for_transport),
+	(_dbus_connection_get_next_client_serial),
+	(dbus_connection_send_message):
+	* dbus/dbus-internals.h:
+	* dbus/dbus-marshal.c: (unpack_uint32), (dbus_unpack_int32),
+	(dbus_pack_int32), (_dbus_marshal_double), (_dbus_marshal_int32),
+	(_dbus_marshal_uint32), (_dbus_demarshal_double),
+	(_dbus_demarshal_int32), (_dbus_demarshal_uint32),
+	(_dbus_demarshal_string), (_dbus_marshal_get_field_end_pos),
+	(_dbus_verbose_bytes), (_dbus_marshal_test):
+	* dbus/dbus-marshal.h:
+	* dbus/dbus-message-internal.h:
+	* dbus/dbus-message.c: (_dbus_message_set_client_serial),
+	(dbus_message_write_header), (_dbus_message_lock),
+	(dbus_message_new), (dbus_message_ref), (dbus_message_unref),
+	(dbus_message_get_name), (dbus_message_append_int32),
+	(dbus_message_append_uint32), (dbus_message_append_double),
+	(dbus_message_append_string), (dbus_message_append_byte_array),
+	(dbus_message_get_fields_iter), (dbus_message_iter_ref),
+	(dbus_message_iter_unref), (dbus_message_iter_has_next),
+	(dbus_message_iter_next), (dbus_message_iter_get_field_type),
+	(dbus_message_iter_get_string), (dbus_message_iter_get_int32),
+	(dbus_message_iter_get_uint32), (dbus_message_iter_get_double),
+	(decode_header_data), (_dbus_message_loader_return_buffer),
+	(message_iter_test), (_dbus_message_test):
+	* dbus/dbus-message.h:
+	* dbus/dbus-protocol.h:
+	* dbus/dbus-test.c: (main):
+	* dbus/dbus-test.h:
+	* glib/test-dbus-glib.c: (message_handler), (main):
+	* test/echo-client.c: (main):
+	* test/watch.c: (check_messages):
+	Make messages sendable and receivable for real.
+
+2003-01-07  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-marshal.c: (_dbus_marshal_double),
+	(_dbus_marshal_string), (_dbus_marshal_byte_array):
+	* dbus/dbus-message.c: (dbus_message_append_int32),
+	(dbus_message_append_uint32), (dbus_message_append_double),
+	(dbus_message_append_string), (dbus_message_append_byte_array):
+	Handle OOM restoration.
+
+2003-01-07  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-marshal.c: (_dbus_marshal_string),
+	(_dbus_demarshal_string), (_dbus_marshal_test):
+	* dbus/dbus-marshal.h:
+	* dbus/dbus-message.c: (dbus_message_get_name),
+	Document these functions.
+
+	(dbus_message_append_int32), (dbus_message_append_uint32),
+	(dbus_message_append_double), (dbus_message_append_string),
+	(dbus_message_append_byte_array):
+	* dbus/dbus-message.h:
+	Add functions for adding message fields of different types.
+
+	* dbus/dbus-protocol.h:
+	Add the different types.
+
+2003-01-05  Havoc Pennington  <hp@pobox.com>
+
+	* bus/connection.c: implement routines for handling connections,
+	first thing is keeping a list of owned services on each connection
+	and setting up watches etc.
+
+	* bus/services.c: implement a mapping from service names to lists
+	of connections
+
+	* dbus/dbus-hash.c: add DBUS_HASH_POINTER
+
+	* dbus/dbus-threads.c (dbus_static_mutex_lock): add functions
+	to use static mutexes for global data
+
+	* dbus/dbus-connection.c (dbus_connection_set_data): add new
+	collection of functions to set/get application-specific data
+	on the DBusConnection.
+
+2003-01-04  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_sleep_milliseconds): new function
+	(_dbus_poll): new function
+
+	* dbus/dbus-internals.h (_DBUS_STRUCT_OFFSET): new macro
+	copied from GLib
+
+	* bus/loop.c: initial code for the daemon main loop
+
+2003-01-04  Havoc Pennington  <hp@pobox.com>
+
+	* test/watch.c (error_handler): make it safe if the error handler
+	is called multiple times (if we s/error handler/disconnect
+	handler/ we should just guarantee it's called only once)
+
+	* dbus/dbus-transport.c (_dbus_transport_disconnect): call the
+	error handler on disconnect (it's quite possible we should
+	just change the error handler to a "disconnect handler," I'm
+	not sure we have any other meaningful errors)
+
+	* configure.in: check for getpwnam_r
+
+	* dbus/dbus-transport.c, dbus/dbus-transport-unix.c,
+	dbus/dbus-auth.c: add credentials support, add EXTERNAL auth
+	mechanism as in SASL spec, using socket credentials
+
+	* dbus/dbus-sysdeps.c (_dbus_read_credentials_unix_socket): new function
+	(_dbus_send_credentials_unix_socket): new function
+
+	* dbus/dbus-sysdeps.c (_dbus_accept_unix_socket): rename just
+	dbus_accept()
+	(_dbus_write): only check errno if <0 returned
+	(_dbus_write_two): ditto
+
+2003-01-02  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-marshal.c: (_dbus_marshal_utf8_string),
+	(_dbus_marshal_byte_array), (_dbus_demarshal_utf8_string),
+	(_dbus_marshal_test):
+	* dbus/dbus-marshal.h:
+	Add _dbus_marshal_byte_array and rename _dbus_marshal_string
+	to _dbus_marshal_utf8_string. Also fix some tests.
+
+2002-12-28  Harri Porten  <porten@kde.org>
+
+	* configure.in: added check for C++ compiler and a very cheesy
+	check for the Qt integration
+
+	* Makefile.am (SUBDIRS): compile qt subdir if support is enabled
+
+	* qt/Makefile.am: added
+
+	* qt/.cvsignore: added
+
+	* qt/dbus-qthread.cc, qt/dbus-qthread.cpp: renamed former to
+	latter, added #ifdef QT_THREAD_SUPPORT guard.
+
+	* dbus/Makefile.am: added missing headers for make dist
+
+2002-12-28  Kristian Rietveld  <kris@gtk.org>
+
+	* dbus/Makefile.am: fixup export-symbols-regex.
+
+2002-12-27  Anders Carlsson  <andersca@codefactory.se>
+
+	* acinclude.m4: Add this file and put the
+	PKG_CHECK_MODULE macro in it.
+
+2002-12-27  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-marshal.c: (_dbus_marshal_string),
+	(_dbus_demarshal_double), (_dbus_demarshal_int32),
+	(_dbus_demarshal_uint32), (_dbus_demarshal_string),
+	(_dbus_marshal_test):
+	Make the demarshalling routines align the pos argument.
+	Add string marshalling tests and fix the obvious bugs
+	discovered.
+
+2002-12-26  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-auth.c: fixes fixes fixes
+
+	* dbus/dbus-transport-unix.c: wire up support for
+	encoding/decoding data on the wire
+
+	* dbus/dbus-auth.c (_dbus_auth_encode_data)
+	(_dbus_auth_decode_data): append to target string
+	instead of nuking it.
+
+2002-12-26  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-marshal.h (DBUS_COMPILER_BYTE_ORDER): #ifdef
+	WORDS_BIGENDIAN then compiler byte order is DBUS_BIG_ENDIAN,
+	doh
+
+	* dbus/dbus-marshal.c: Add macros to do int swapping in-place and
+	avoid swap_bytes() overhead (ignoring possible assembly stuff for
+	now). Main point is because I wanted unpack_uint32 to implement
+	_dbus_verbose_bytes
+	(_dbus_verbose_bytes): new function
+
+	* dbus/dbus-string.c (_dbus_string_validate_ascii): new function
+
+	* dbus/dbus-message.c (_dbus_message_loader_get_is_corrupted): add
+	mechanism to handle a corrupt message stream
+	(_dbus_message_loader_new): fix preallocation to only prealloc,
+	not prelengthen
+
+	* dbus/dbus-string.c (_dbus_string_skip_blank): fix this function
+	(_dbus_string_test): enhance tests for copy/move and fix the
+	functions
+
+	* dbus/dbus-transport-unix.c: Hold references in more places to
+	avoid reentrancy problems
+
+	* dbus/dbus-transport.c: ditto
+
+	* dbus/dbus-connection.c (dbus_connection_dispatch_message): don't
+	leak reference count in no-message case
+
+	* test/watch.c (do_mainloop): handle adding/removing watches
+	during iteration over the watches. Also, ref the connection/server
+	stored on a watch, so we don't try to mangle a destroyed one.
+
+	* dbus/dbus-transport-unix.c (do_authentication): perform
+	authentication
+
+	* dbus/dbus-auth.c (get_state): add a state
+	AUTHENTICATED_WITH_UNUSED_BYTES and return it if required
+	(_dbus_auth_get_unused_bytes): append the unused bytes
+	to the passed in string, rather than prepend
+
+	* dbus/dbus-transport.c (_dbus_transport_init_base): create
+	the auth conversation DBusAuth
+
+	* dbus/dbus-transport-unix.c (_dbus_transport_new_for_fd)
+	(_dbus_transport_new_for_domain_socket): when creating a
+	transport, pass in whether it's a client-side or server-side
+	transport so we know which DBusAuth to create
+
+2002-12-03  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-transport-unix.c (unix_finalize): finalize base
+	_after_ finalizing the derived members
+	(unix_connection_set): unref watch if we fail to add it
+
+	* dbus/dbus-connection.c (dbus_connection_unref): delete the
+	transport first, so that the connection owned by the
+	transport will be valid as the transport finalizes.
+
+	* dbus/dbus-transport-unix.c (unix_finalize): free the write_watch
+	if necessary, and remove watches from the connection.
+
+	* dbus/dbus-watch.c (_dbus_watch_list_free): improve a comment
+
+2002-12-26  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/dbus-marshal.c: (_dbus_marshal_string),
+	(_dbus_demarshal_double), (_dbus_demarshal_int32),
+	(_dbus_demarshal_uint32), (_dbus_demarshal_string),
+	(_dbus_marshal_test):
+	* dbus/dbus-marshal.h:
+	Add string marshal functions and have the demarshal functions
+	return the new position.
+
+2002-12-25  Havoc Pennington  <hp@pobox.com>
+
+	* doc/dbus-sasl-profile.txt: docs on the authentication protocol,
+	it is a simple protocol that just maps directly to SASL.
+
+	* dbus/dbus-auth.h, dbus/dbus-auth.c: authentication protocol
+	initial implementation, not actually used yet.
+
+	* dbus/dbus-string.c (_dbus_string_find): new function
+	(_dbus_string_equal): new function
+	(_dbus_string_base64_encode): new function
+	(_dbus_string_base64_decode): new function
+
+2002-12-25  Anders Carlsson  <andersca@codefactory.se>
+
+	* dbus/Makefile.am:
+	* dbus/dbus-marshal.c: (swap_bytes), (_dbus_marshal_double),
+	(_dbus_marshal_int32), (_dbus_marshal_uint32),
+	(_dbus_demarshal_double), (_dbus_demarshal_int32),
+	(_dbus_demarshal_uint32), (_dbus_marshal_test):
+	* dbus/dbus-marshal.h:
+	* dbus/dbus-protocol.h:
+	* dbus/dbus-test.c: (main):
+	* dbus/dbus-test.h:
+	Add un-optimized marshalling/demarshalling routines.
+
+2002-12-25  Harri Porten  <porten@kde.org>
+
+	* qt/dbus-qt.h: adjusted ctor and getter to KDE/Qt conventions
+
+2002-12-24  Zack Rusin  <zack@kde.org>
+
+	* qt/dbus-qthread.cc: adding - integrates QMutex into Dbus
+	* qt/dbus-qt.h: skeleton with two sample implemenatation of the
+	main loop stuff
+
+2002-12-24  Havoc Pennington  <hp@pobox.com>
+
+	* glib/dbus-gthread.c: fix include
+
+	* glib/dbus-glib.h: rename DBusMessageHandler for now.
+	I think glib API needs to change, though, as you don't
+	want to use DBusMessageFunction, you want to use the
+	DBusMessageHandler object. Probably
+	dbus_connection_open_with_g_main_loop()
+	and dbus_connection_setup_g_main_loop() or something like that
+	(but think of better names...) that just create a connection
+	that has watch/timeout functions etc. already set up.
+
+	* dbus/dbus-connection.c
+	(dbus_connection_send_message_with_reply): new function just to
+	show how the message handler helps us deal with replies.
+
+	* dbus/dbus-list.c (_dbus_list_remove_last): new function
+
+	* dbus/dbus-string.c (_dbus_string_test): free a string that
+	wasn't
+
+	* dbus/dbus-hash.c: use memory pools for the hash entries
+	(rebuild_table): be more paranoid about overflow, and
+	shrink table when we can
+	(_dbus_hash_test): reduce number of sprintfs and write
+	valid C89. Add tests for case where we grow and then
+	shrink the hash table.
+
+	* dbus/dbus-mempool.h, dbus/dbus-mempool.c: memory pools
+
+	* dbus/dbus-connection.c (dbus_connection_register_handler)
+	(dbus_connection_unregister_handler): new functions
+
+	* dbus/dbus-message.c (dbus_message_get_name): new
+
+	* dbus/dbus-list.c: fix docs typo
+
+	* dbus/dbus-message-handler.h, dbus/dbus-message-handler.c:
+	an object representing a handler for messages.
+
+2002-12-16  Anders Carlsson  <andersca@codefactory.se>
+
+	* glib/dbus-glib.h:
+	* glib/dbus-gthread.c: (dbus_gthread_init):
+	Don't use the gdbus prefix for public functions.
+
+2002-12-16  Anders Carlsson  <andersca@codefactory.se>
+
+	* Makefile.am:
+	* configure.in:
+	Add GLib checks and fixup .pc files
+
+	* glib/Makefile.am:
+	* glib/dbus-glib.h:
+	* glib/dbus-gmain.c: (gdbus_connection_prepare),
+	(gdbus_connection_check), (gdbus_connection_dispatch),
+	(gdbus_add_connection_watch), (gdbus_remove_connection_watch),
+	(dbus_connection_gsource_new):
+	* glib/dbus-gthread.c: (dbus_gmutex_new), (dbus_gmutex_free),
+	(dbus_gmutex_lock), (dbus_gmutex_unlock), (dbus_gthread_init):
+	* glib/test-dbus-glib.c: (message_handler), (main):
+	Add GLib support.
+
+2002-12-15  Harri Porten  <porten@kde.org>
+
+	* autogen.sh: check for libtoolize before attempting to use it
+
+	* dbus/dbus-transport-unix.c: include <sys/time.h> for timeval
+	struct.
+
+	* .cvsignore: ignore more stamp files
+
+	* dbus/dbus-watch.c (_dbus_watch_list_new): fixed doc error
+
+	* test/Makefile.am: added -I$(top_srcdir) to be able to compile
+	without make install.
+
+2002-12-15  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-threads.c: add thread stubs that a higher library
+	layer can fill in. e.g. the GLib wrapper might fill them in with
+	GThread stuff. We still need to use this thread API to
+	thread-safe-ize the library.
+
+2002-12-12  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-transport-unix.c, dbus/dbus-server-unix.c: use the
+	below new interfaces and include fewer system headers.
+
+	* dbus/dbus-sysdeps.c (_dbus_read): new function
+	(_dbus_write): new function
+	(_dbus_write_two): new function
+	(_dbus_connect_unix_socket): new function
+	(_dbus_listen_unix_socket): new function
+
+	* dbus/dbus-message-internal.h: change interfaces to use
+	DBusString
+
+2002-12-11  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-types.h: add dbus_unichar
+
+	* dbus/dbus-internals.c (_dbus_verbose): use _dbus_getenv
+
+	* dbus/dbus-connection.c (dbus_connection_send_message): return
+	TRUE on success
+
+	* dbus/dbus-transport.c: include dbus-watch.h
+
+	* dbus/dbus-connection.c: include dbus-message-internal.h
+
+	* HACKING: add file with coding guidelines stuff.
+
+	* dbus/dbus-string.h, dbus/dbus-string.c: Encapsulate all string
+	handling here, for security purposes (as in vsftpd). Not actually
+	using this class yet.
+
+	* dbus/dbus-sysdeps.h, dbus/dbus-sysdeps.c: Encapsulate all
+	system/libc usage here, as in vsftpd, for ease of auditing (and
+	should also simplify portability). Haven't actually moved all the
+	system/libc usage into here yet.
+
+2002-11-25  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-internals.c (_dbus_verbose): fix to not
+	always print the first verbose message.
+
+2002-11-24  Havoc Pennington  <hp@pobox.com>
+
+        * test/echo-client.c, test/echo-server.c: cheesy test
+	clients.
+
+	* configure.in (AC_CHECK_FUNCS): check for writev
+
+	* dbus/dbus-message.c (_dbus_message_get_network_data): new
+	function
+
+	* dbus/dbus-list.c (_dbus_list_foreach): new function
+
+	* dbus/dbus-internals.c (_dbus_verbose): new function
+
+	* dbus/dbus-server.c, dbus/dbus-server.h: public object
+	representing a server that listens for connections.
+
+	* dbus/.cvsignore: create
+
+	* dbus/dbus-errors.h, dbus/dbus-errors.c:
+	public API for reporting errors
+
+	* dbus/dbus-connection.h, dbus/dbus-connection.c:
+	public object representing a connection that
+	sends/receives messages. (Same object used for
+	both client and server.)
+
+	* dbus/dbus-transport.h, dbus/dbus-transport.c:
+	Basic abstraction for different kinds of stream
+	that we might read/write messages from.
+
+2002-11-23  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-internals.h (_DBUS_INT_MAX): add _DBUS_INT_MIN
+	_DBUS_INT_MAX
+
+	* dbus/dbus-test.c (main): add list test, and include
+	dbus-test.h as intended
+
+	* dbus/dbus-hash.c (_dbus_hash_table_remove_string)
+	(_dbus_hash_table_remove_int): return value indicates
+	whether the entry existed to remove
+
+	* dbus/dbus-list.c: add linked list utility class,
+	with docs and tests
+
+	* dbus/dbus-hash.c: add TODO item about shrinking the hash bucket
+	array sometimes.
+
+2002-11-23  Havoc Pennington  <hp@pobox.com>
+
+	* Doxyfile.in (INCLUDE_FILE_PATTERNS): expand DBUS_BEGIN_DECLS/
+	DBUS_END_DECLS to nothing, that should fix this once and for all
+
+	* Doxyfile.in (JAVADOC_AUTOBRIEF): set to YES
+
+	* dbus/dbus-message.c, dbus/dbus-hash.c:
+	add some missing @brief
+
+2002-11-23  Havoc Pennington  <hp@pobox.com>
+
+	* dbus/dbus-message.h: put semicolons after DEBUG_BEGIN_DECLS
+	to avoid confusing Doxygen
+
+	* dbus/dbus-hash.c: @} not }@
+
+	* dbus/dbus-message.c (struct DBusMessage): split out
+	internals docs
+
+2002-11-23  Havoc Pennington  <hp@pobox.com>
+
+	* configure.in: pile on more warning flags if using gcc
+
+	* Doxyfile.in (EXTRACT_STATIC): set to NO, so we don't have
+	to document static functions
+
+	* configure.in: add summary to end of configure so it
+	looks nice and attractive
+
+	* dbus/dbus-hash.c: finish implementation and write unit
+	tests and docs
+
+	* configure.in: add --enable-tests to enable unit tests
+
+	* dbus/dbus-test.c: test program to run unit tests
+	for all files in dbus/*, initially runs a test for
+	dbus-hash.c
+
+	* dbus/dbus-internals.h: file to hold some internal utility stuff
+
+2002-11-22  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-hash.c: copy in Tcl hash table, not yet
+	"ported" away from Tcl
+
+	* dbus/dbus-types.h: header for types such as dbus_bool_t
+
+2002-11-22  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus.h: fixups for doc warnings
+
+	* Doxyfile.in (FILE_PATTERNS): we need to scan .h to pick up
+	macros
+	(QUIET): make it quiet so we can see warnings
+
+	* dbus/dbus-memory.c: teach D-BUS to allocate and free memory
+
+2002-11-22  Havoc Pennington  <hp@redhat.com>
+
+	* Makefile.am: include "Doxyfile" target in all-local
+
+	* configure.in: generate the Doxyfile
+
+	* Doxyfile.in: move Doxyfile here, so we can use
+	configure to generate a Doxyfile with the right
+	version number etc.
+
+2002-11-22  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c: move inline docs into .c file
+
+	* Doxyfile (OUTPUT_DIRECTORY): move output to doc/api
+	so all docs are under doc/
+	(MAN_EXTENSION): generate man pages. Use extension
+	".3dbus" which matches ".3qt" on my system,
+	I guess this is OK, I don't know really.
+	(FILE_PATTERNS): look for .c files not .h, makes sense
+	for plain C I think
+
+2002-11-22  Havoc Pennington  <hp@pobox.com>
+
+	* Makefile.am (SUBDIRS): rename subdir "server" to "bus"
+	because any app can be a server, and any app can be a client,
+	the bus is a special kind of server.
+
+Thu Nov 21 23:35:31 2002  Zack Rusin  <zack@kde.org>
+
+	* Doxyfile : adding. Still needs Makefile rules to be generated
+	automatically (just run "doxygen" in the toplevel dir for now to
+	generate docs)
+
+	* dbus/dbus-message.h : Adding sample docs (javadoc since
+	resembles gtk-doc a little more)
+
+	* dbus/dbus.h : Adding sample docs
+
+2002-11-21  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/Makefile.am (INCLUDES): define DBUS_COMPILATION
+	so we can allow ourselves to include files directly,
+	instead of having to use dbus.h
+
+	* dbus/dbus.h: fill in
+
+	* dbus/dbus-message.h: sketch out a sample header file.
+	Include griping if you include it directly instead of
+	via dbus.h
+
+	* dbus/dbus-macros.h: new file with macros for extern "C",
+	TRUE/FALSE, NULL, etc.
+
+	* doc/file-boilerplate.c: put include guards in here
+
+2002-11-21  Havoc Pennington  <hp@redhat.com>
+
+	* doc/file-boilerplate.c: include both AFL and GPL boilerplate.
+
+	* COPYING: include the GPL as well, and license code
+	under both AFL and GPL.
+
+2002-11-21  Havoc Pennington  <hp@redhat.com>
+
+	* acconfig.h: get rid of this
+
+	* autogen.sh (run_configure): add --no-configure option
+
+	* configure.in: remove AC_ARG_PROGRAM to make
+	autoconf complain less. add AC_PREREQ.
+	add AC_DEFINE third arg.
+
+2002-11-21  Anders Carlsson  <andersca@codefactory.se>
+
+	* doc/Makefile.am:
+	Fix references so we can distcheck.
+
+2002-11-21  Havoc Pennington  <hp@redhat.com>
+
+	* Initial module creation
+
diff --git a/dbus/ChangeLog.pre-1-2 b/dbus/ChangeLog.pre-1-2
new file mode 100644
index 0000000..b220448
--- /dev/null
+++ b/dbus/ChangeLog.pre-1-2
@@ -0,0 +1,2027 @@
+2008-04-04  John (J5) Palmieri <johnp@redhat.com>
+
+	* Released 1.2.1
+
+2008-04-03  John (J5) Palmieri <johnp@redhat.com>
+
+	Patch from Sumit <sumitskj_20@yahoo.com>, comments added
+
+	* dbus/dbus-transport.c(_dbus_transport_open): fix mem leak
+
+2008-04-03  John (J5) Palmieri <johnp@redhat.com>
+
+	* dbus/dbus-connection.c (dbus_connection_send): add documentation
+	  to describe when to call dbus_connection_flush and
+	  dbus_connection_unref after a call to dbus_connection_send is made
+	  Initial wording by Stanislav Brabec <sbrabec at suse.cz> 
+	  (fd.o bug#13558)
+
+2008-04-03  John (J5) Palmieri <johnp@redhat.com>
+
+	Patch from Kimmo Hämäläinen <kimmo.hamalainen at nokia.com>
+
+	* bus/expirelist.c
+	  (do_expiration_with_current_time): calculate correct min wait time
+	  and next interval
+	  (bus_expire_list_add, bus_expire_list_add_link): if the timeout is 
+	  disabled when we add an item to the expire list, enable the timeout
+	  (do_expiration_with_current_time): only set timeout if there are
+	  items to expire
+
+2008-04-01  Timo Hoenig  <thoenig@suse.de>
+
+	Patch from Frederic Crozat <fcrozat@mandriva.com>
+
+	* bus/dir-watch-inotify.c (bus_watch_directory): Only monitor
+	  IN_CLOSE_WRITE, IN_DELETE, IN_MOVE_TO and IN_MOVE_FROM events. This
+	  way, only atomic changes to configuration file are monitored.
+	* bus/dir-watch-inotify.c (_handle_inotify_watch): Fix typo in
+	  _dbus_verbose function call
+	* bus/dir-watch-inotify.c (bus_drop_all_directory_watches): Use
+	  _dbus_strerror instead of perror
+
+2008-03-04  Havoc Pennington  <hp@redhat.com>
+
+	* bus/connection.c, bus/expirelist.c: Make the BusExpireList
+	struct opaque, adding accessors for manipulating the list. In this
+	commit there should be no change in functionality or behavior. The
+	purpose of this change is to improve encapsulation prior to fixing
+	some bugs Kimmo Hämäläinen found where the timeout is not properly
+	updated, since we need to e.g. take some action whenever adding
+	and removing stuff from the expire list.
+
+2008-03-31  Colin Walters  <walters@verbum.org>
+
+	Patch from Owen Taylor <otaylor@redhat.com>
+
+	* tools/dbus-launch-x11.c: Check for X11 events before
+	selecting (FDO bug #15293)
+
+2008-03-31  Colin Walters  <walters@verbum.org>
+
+	Patch from Owen Taylor <otaylor@redhat.com>
+
+	* tools/dbus-launch-x11.c: Make sure we call XFlush()
+	on all code paths (FDO bug #15293)
+
+2008-03-27  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-send.c (append_dict): Do not provide a signature to
+	dbus_message_iter_open_container() when opening a dict entry.
+
+2008-03-26  Colin Walters  <walters@verbum.org>
+
+	Patch from Scott James Remnant <scott@netsplit.com>
+
+	* dbus/dbus-bus.c: Set default exit_on_disconnect after registration with
+	the bus, not before.  This ensures that programs which wish to set
+	exit_on_disconnect to FALSE will not be terminated if the bus exits
+	during registration.  (FDO Bug #15112)
+
+2008-03-04  John (J5) Palmieri  <johnp@redhat.com>
+
+	* fix broken poll on Mac OSX - build patch by Benjamin Reed
+	* configure.in: check for OSX's deadlocking poll
+	* dbus/dbus-sysdeps-unix.c (_dbus_poll): if we have a broken poll
+	  don't use poll
+
+2008-03-04  John (J5) Palmieri  <johnp@redhat.com>
+
+	* check if the linker supports a flag instead of just checking for GNU
+	  ld
+	* configure.in: move AM_PROG_LIBTOOL to the top
+	  (ld_supports_flag): new function for checking if the linker supports
+	  a given flag
+
+2008-03-04  John (J5) Palmieri  <johnp@redhat.com>
+
+	* add a changelog for Benjamin Reed's git patch RANT: Change Logs are
+	  handled by git and having an external changelog just screws up
+	  merging.  We should write down rules for doing git commit messages
+	  and leave it at that.
+	* configure.in: Platform build fixes for Mac OS X
+	  the Darwin linker does not understand the -z option; wrap it in 
+	  a check for $with_gnu_ld.
+	  environ is only available at runtime, so you need to make a
+	  reference to _NSGetEnviron instead for symbols to resolve properly.
+
+2008-03-04  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: add $THREAD_LIBS to DBUS_LAUNCHER_LIBS so we link 
+	  correctly
+
+2008-03-04  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/dbus-launch.c: wrap X'ism in #ifdef so we can compile 
+	  without X
+
+2008-02-28  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-sysdeps-unix.c: define _AI_ADDRCONFIG as 0 if not
+	  defined so that we can compile with an older glibc 
+
+2008-02-26  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 1.1.20
+
+2008-02-26  John (J5) Palmieri  <johnp@redhat.com>
+
+	* CVE-2008-0595 - security policy of the type <allow send_interface=
+	  "some.interface.WithMethods"/> work as an implicit allow for
+	  messages sent without an interface bypassing the default deny rules
+	  and potentially allowing restricted methods exported on the bus to be
+	  executed by unauthorized users.  This patch fixes the issue.
+	* bus/policy.c (bus_client_policy_check_can_send,
+	  bus_client_policy_check_can_receive): skip messages without an 
+	  interface when evaluating an allow rule, and thus pass it to the
+	  default deny rules
+
+2008-02-26  John (J5) Palmieri  <johnp@redhat.com>
+
+	* correctly unref connections without guids during shutdown
+	* dbus/dbus-connection.c (close_connection_on_shutdown): new method
+	  split out from shared_connections_shutdown
+	  (shared_connections_shutdown): shutdown all shared connections
+	  without guids
+	  (_dbus_connection_ref_unlocked): handle OOM when prepending no guid
+	  connections to the shared_connections_no_guid list
+	* Patch by  Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+2008-02-21  John (J5) Palmieri  <johnp@redhat.com>
+	
+	* fix build against the latest gcc/glibc
+	* dbus/dbus-sysdeps-unix.c: define _GNU_SOURCE
+	* bus/selinux.c: include limits.h
+	* Patch by Matthias Clasen <mclasen at redhat.com>
+
+2008-02-21  John (J5) Palmieri  <johnp@redhat.com>
+
+	* fixes dbus-launch so the bus goes away when X does
+	  (Red Hat Bug #430412)
+	* tools/dbus-launch.c (main): set xdisplay = NULL
+	* Patch by Matthias Clasen <mclasen at redhat.com>
+
+2008-01-17  John (J5) Palmieri  <johnp@redhat.com>
+	
+	* Released 1.1.4
+
+2008-01-17  Timo Hoenig  <thoenig@suse.de>
+	* fix inotify support
+	* bus/dir-watch-inotify.c (_handle_inotify_watch): fix reading of the
+	inotify events. Also, use ssize_t not size_t for 'ret'.
+	* bus/dir-watch-inotify.c (bus_watch_directory): watch not only for
+	IN_MODIFY but also for IN_CREATE and IN_DELETE
+	* bus/dir-watch-inotify.c (bus_drop_all_directory_watches): drop the
+	inotify watches more elegantly by closing inotify:_fd, set inotify_fd to
+	-1 after dropping the watches
+
+2008-01-15 John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: post-release version bump
+
+2008-01-15 John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 1.1.3 (1.2.0RC1)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* fix hacking to say git instead of cvs
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Sébastien Couret <10function at gmail dot com>
+
+	* dbus/dbus-marshal-recursive.c (all_reader_classes[]): wrap in 
+	#ifndef DBUS_DISABLE_ASSERT since it is only used in asserts which
+	are noop
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Magnus Henoch <henoch plus bfdo at dtek dot chalmers dot se>
+
+	* dbus/dbus-auth.c (handle_server_data_external_mech): handle SASL
+	EXTERNAL's inital empty responce (FDO Bug #9945)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/messagebus.in: add lsb headers (FDO Bug #11491)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Peter O'Gorman <pogma at thewrittenword dot com>
+
+	* dbus/dbus-spawn.c (babysit_signal_handler): check write return value
+	so we don't hang (FDO Bug #11665)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Peter O'Gorman <pogma at thewrittenword dot com>
+
+	* dbus/dbus-sysdeps.h: support for AIX poll implementation (FDO Bug 
+	#11666)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tests/name-test/run-test.sh: make more portable (FDO Bug #11667)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* dbus/dbus-connection.c (_dbus_connection_get_next_client_serial):
+	don't check for < 0 on an unsigned variable (FDO Bug #12924)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+	
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* bus/bus.c (setup_server): check failed allocation (FDO Bug #12920)
+	
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+	
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* dbus/dbus-spawn.c (_dbus_spawn_async_with_babysitter): the API 
+	contract says sitter_p can be NULL, so let's check it (FDO Bug #12919)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+	
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* dbus/dbus-spawn.c (read_ints, read_pid): use correct ssize_t type
+	instead of size_t (FDO Bug #12862)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+	
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* dbus/dbus-errors.c (dbus_set_error): make sure to call va_end if we
+	hit an OOM error inside va_start (FDO Bug #12846)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+	
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* dbus/dbus-connection.c (dbus_connection_send_with_reply): 
+	fix possible crash if pending_return is NULL (FDO Bug #12673)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* portions of patch submitted by Tim Mooney 
+	<enchanter at users dot sourceforge dot net>
+
+	* configure.in: never auto-select libxml (FDO Bug #12479)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patches by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* dbus/dbus-sysdeps-unix (_dbus_get_autolaunch_address): handle OOM
+	(FDO Bug #12945)
+
+	* dbus/dbus-uuidgen.c (return_uuid): handle OOM (FDO Bug #12928)
+
+	* dbus/dbus-misc.c (dbus_get_local_machine_id): handle OOM, fix return
+	value to return NULL not FALSE (FDO Bug #12946)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/bus.c (bus_context_check_security_policy): rewrite selinux error
+	handling to not abort due to a NULL read and to set the error only if
+	it is not already set (Based off of FDO Bug #12430)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* dbus/dbus-internals.c (_dbus_read_uuid_file_without_creating,
+	_dbus_create_uuid_file_exclusively): add OOM handling (FDO Bug #12952)
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* dbus/dbus-spawn.c (babysit, babysitter_iteration): add error
+	handling when polling (FDO Bug #12954) 
+
+2008-01-15  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* bus/config-parser.c (locate_attributes): remove dead code which
+	always evaluated to TRUE
+
+	* dbus/dbus-shell.c (_dbus_shell_quote): remove unused code
+
+2008-01-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* bus/connection.c (bus_connection_complete): plug a possible 
+	BusClientPolicy leak (FDO Bug #13242)
+
+2008-01-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Frederic Crozat <fcrozat at mandriva dot com> (FDO Bz#
+	13268)
+
+	* add inotify support
+
+	* bus/Makefile.am: add inotify module to the build
+
+	* bus/dir-watch-inotify.c: inotify module based off the dnotify and
+	kqueue modules
+
+	* configure.in: add checks and switch for inotify
+	also add a printout at the end of configure if inotify and kqueue
+	support is being built in (dnotify already had this)
+
+2008-01-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Frederic Crozat <fcrozat at mandriva dot com>
+
+	* bus/dir-watch-dnotify.c (bus_watch_directory): watch for file
+	creates also
+
+2008-01-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* patch by Kimmo Hämäläinen <kimmo dot hamalainen at nokia dot com>
+
+	* dbus/dbus-transport-socket.c(do_reading): return message 
+	loader buffer in case of OOM (FDO Bug#12666)
+
+2008-01-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* configure.in: add warning to output when libxml is selected since
+	we don't have a libxml maintainer and expat works perfectly fine
+	for what we need an xml parser for
+
+2008-01-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Patch by Andrea Luzzardi  <scox at sig11 dot org>: creates a
+	_dbus_geteuid function to fix EXTERNAL authentication in setuid
+	applications
+
+	*  dbus/dbus-sysdeps-unix.c (_dbus_geteuid): used to get the effective
+	uid of the running program
+	(_dbus_credentials_add_from_current_process): use geteuid instead of
+	getuid
+	(_dbus_append_user_from_current_process): use geteuid instead of
+	getuid
+
+	* dbus/dbus-sysdeps-util-unix.c (_dbus_change_to_daemon_user): use
+	geteuid instead of getuid
+	(_dbus_unix_user_is_at_console): use geteuid instead of getuid
+
+	* dbus/dbus-sysdeps-win.c (_dbus_geteuid): add a windows equivilant
+	that returns DBUS_UID_UNSET
+
+2007-12-18  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c (_dbus_connection_block_pending_call):
+	fix location of curly braces
+
+2007-11-23  Sjoerd Simons  <sjoerd@luon.net>
+
+	* tools/dbus-launch.c: let both a normal dbus-launch and an
+	autolaunched bus save their parameters in X11 if possible. This makes
+	the autolaunch and non-autolaunch behaviour more similar. With the
+	exception that on a normal launch there will always be a new session
+	bus and not being able to save parameters is not fatal. This also
+	enables to launch programs directly with autolaunch (not very usefull
+	though).
+
+2007-10-31  Havoc Pennington  <hp@redhat.com>
+
+	* bus/selinux.c (log_audit_callback): rewrite to use
+	_dbus_string_copy_to_buffer_with_nul()
+
+	* dbus/dbus-string.c (_dbus_string_copy_to_buffer): change to NOT
+	nul-terminate the buffer; fail an assertion if there is not enough
+	space in the target buffer. This fixes two bugs where
+	copy_to_buffer was used to copy the binary bytes in a UUID, where
+	nul termination did not make sense. Bug reported by David Castelow.
+	(_dbus_string_copy_to_buffer_with_nul): new function that always
+	nul-terminates the buffer, and fails an assertion if there is not 
+	enough space in the buffer.
+
+2007-10-23  Havoc Pennington  <hp@redhat.com>
+
+	* bus/bus.c (bus_context_new): use the new name here
+
+	* bus/selinux.c (bus_selinux_audit_init): rename from audit_init()
+	to avoid possible libc conflict, and declare it in .h file to
+	avoid a warning
+
+2007-10-19  Havoc Pennington  <hp@redhat.com>	
+	
+	* bus/bus.c (bus_context_new): put audit_init() in HAVE_SELINUX
+	
+2007-10-19  Havoc Pennington  <hp@redhat.com>	
+
+	* bus/bus.c (bus_context_new): put the audit_init() in here
+	instead, which I believe ends up being the same as where it was
+	before, though I'm not sure I understand why it goes here.
+
+	* dbus/dbus-sysdeps-util-unix.c (_dbus_change_to_daemon_user):
+	remove audit_init() from here, this file can't depend on code in
+	bus/ directory
+
+2007-10-16  Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* configure.in: *Actually* fix detection of i486 atomic ops -
+	my previous attempt at a fix would always enable them due to wrong
+	quoting. Patch from Colin Walters <walters@verbum.org>
+
+2007-10-11  Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* configure.in: enable Autoconf's AC_C_INLINE to avoid compilation
+	failure with gcc -ansi
+	* dbus/dbus-macros.h, dbus/dbus-arch-deps.h.in: Use new macro
+	_DBUS_GNUC_EXTENSION (the same as G_GNUC_EXTENSION) to avoid -ansi
+	warnings about use of "long long".
+	* dbus/dbus-server-socket.c: remove unused variable when assertions
+	are disabled
+	* dbus/dbus-marshal-validate.c: avoid empty statements by removing
+	stray semicolons
+	* tools/dbus-launch.c: convert C++-style comment to C-style, add {}
+	for clarity
+	* .gitignore: ignore vi swapfiles
+	* dbus/dbus-errors.h, dbus/dbus-errors.c: Add DBUS_ERROR_INIT macro,
+	equivalent to calling dbus_error_init() on an uninitialized DBusError
+	* dbus/dbus-address.c, dbus/dbus-auth-script.c, dbus/dbus-auth-util.c,
+	dbus/dbus-connection.c, dbus/dbus-internals.c, dbus/dbus-keyring.c,
+	dbus/dbus-message-util.c, dbus/dbus-server.c, dbus/dbus-sha.c,
+	dbus/dbus-spawn-win.c, dbus/dbus-spawn.c,
+	dbus/dbus-sysdeps-util-win.c, dbus/dbus-transport-socket.c,
+	dbus/dbus-transport.c, dbus/dbus-userdb.c: use that macro instead of
+	calling dbus_error_init() where it's clearly equivalent
+	* configure.in, dbus/dbus-sysdeps.h, dbus/dbus-sysdeps-unix.c: Fix
+	detection of i486 atomic ops. Previously, the attempts to determine
+	support at compile-time on Darwin were causing the i486 atomic ops to
+	be used on *all* i386 or x86-64 GCC builds (AH_VERBATIM can't be
+	conditionalized like we were trying to).
+
+2007-10-10  Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* dbus/dbus-errors.c, dbus/dbus-protocol.h: Add new error
+	org.freedesktop.DBus.Error.ObjectPathInUse
+	* dbus/dbus-object-tree.h, dbus/dbus-object-tree.c,
+	dbus/dbus-connection.c, dbus/dbus-connection.h: add new functions
+	dbus_connection_try_register_object_path and
+	dbus_connection_try_register_fallback, which raise ObjectPathInUse
+	rather than asserting, to make object path registration less painful
+	for bindings
+	* .gitignore: add various things that weren't in .cvsignore because
+	CVS implicitly ignored them; generally bring up to date
+
+2007-10-09  John (J5) Palmieri  <johnp@redhat.com>
+
+	* tools/run-with-tmp-session-bus.sh: Fix env exports for better
+	portability (#9280)
+	* tools/dbus-send.1: Document syntax for container types in dbus-send
+	man file (#9553) - patch from Jack Spaar <jspaar at
+	users.sourceforge.net>
+
+	[Both OK for MIT/X11 relicensing -smcv]
+
+2007-10-09  Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* doc/dbus-specification.xml: Specifically forbid empty structs (#7969)
+	* doc/dbus-specification.xml: Patches from Kristoffer Lundén to clarify
+	description of DBUS_COOKIE_SHA1 (#10184) and allowable contents of a
+	variant (#10185, amended as per Havoc's comments)
+
+	[All of the above are OK for MIT/X11 licensing]
+
+2007-10-03  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-internals.h: fd.o bug #11678 Don't error out if compiler
+	does not support vararg macros. _dbus_verbose is the only function
+	that does this so make it a noop if vararg macros are not supported
+	* bus/selinux.c, dbus/dbus-sysdeps-util-unix.c: fd.o bug #12429
+	Reverse check to setpcap and only init audit if we were root
+	(patch by Dan Walsh <dwalsh@redhat.com>,
+	https://bugs.freedesktop.org/show_bug.cgi?id=12429). Reverse
+	we_were_root check to setpcap if we were root.  Also only init audit
+	if we were root.  So error dbus message will not show up when policy
+	reload happens.  dbus -session will no longer try to send audit
+	message, only system will.
+	* configure.in: fd.o bug #11872 improve linker test for --gc-sections.
+	Patch by Tim Mooney <enchanter at users.sourceforge.net>
+	* configure.in, dbus/dbus-sysdeps.c: fd.o bug #11872 fix clearenv for
+	systems that do not have it. Patch from Brian Cameron <brian.cameron
+	at sun.com>
+	* tools/dbus-launch.c: fd.o bug #12547 remove superfluous if.
+	Also convert tabs to spaces
+	* configure.in, bus/Makefile.am, dbus/Makefile.am: Correctly implement
+	-fPIC and -fPIE. For security reasons we want possition independent
+	code for libraries and possition independent executable for
+	executables. Before we were just enabling -fPIC. Now we correctly
+	enable -fPIC and -PIE for libdbus and the bus respectively. Proper
+	LD_FLAGS are set for each also.
+
+2007-09-20  Ryan Lortie  <desrt@desrt.ca>
+
+	Add argument path matching support.  Bug #11066.
+
+	* dbus/signals.c (struct DBusMatchRule, bus_match_rule_new,
+	bus_match_rule_set_arg, bus_match_rule_parse_arg_match,
+	match_rule_matches): Add support for parsing and matching on
+	arg0path='/some/path' type rules.
+
+	* dbus/signals.h (bus_match_rule_set_arg): change to take const
+	DBusString instead of const char * for the string to match against.
+
+	* dbus/dbus-bus.c: add a quick note to dbus_bus_add_match
+	documentation about the path matching.
+
+	* doc/dbus-specification.xml: add a more detailed description of the
+	changes here.
+
+2007-09-19  Ryan Lortie  <desrt@desrt.ca>
+
+	Add support for compacting DBusStrings to release wasted memory.
+
+	* dbus/dbus-string.[ch] (compact, _dbus_string_compact,
+	_dbus_string_lock): new compact function to free up allocated memory
+	that is no longer used.
+
+	* dbus/dbus-message.c (load_message): call _dbus_string_compact on the
+	message loader buffer.
+
+	* dbus/dbus-transport-socket.c (do_reading, do_writing): call
+	_dbus_string_compact on the incoming/outgoing "encoded" buffers.
+
+	* dbus/dbus-string-util.c (_dbus_string_test): add a few tests for
+	string compacting.
+
+2007-09-13  Ryan Lortie  <desrt@desrt.ca>
+
+	* HACKING: add more explicit git branch/tag instructions
+
+2007-09-13  Ryan Lortie  <desrt@desrt.ca>
+
+	migrate from cvs to git (cvs2svn -> git-svnimport).
+
+	* HACKING: update release/branch/tag instructions
+	* */.cvsignore: rename to .gitignore
+
+	also, clean up tags and branch names to conform to HACKING
+
+2007-08-17  William Jon McCann  <mccann@jhu.edu>
+
+	* update-dbus-docs.sh: upload DTD to server
+
+2007-08-17  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-launch-x11.c (set_address_in_x11): fix from Michael
+	Lorenz to use long not int with XChangeProperty format 32
+
+	* dbus/dbus-sysdeps-util-unix.c
+	(_dbus_write_pid_to_file_and_pipe): factor this out, and use the
+	same code in _dbus_become_daemon (where the parent writes the pid
+	file and to the pid pipe) and in bus_context_new (where the daemon
+	writes its own pid file and to its own pid pipe)
+
+	* bus/bus.c (bus_context_new): close the pid pipe after we print
+	to it. Also, don't write the pid to the pipe twice when we fork,
+	someone reported this bug a long time ago.
+
+2007-08-03  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: add major/minor/micro version number AC_SUBST
+
+	* dbus/dbus-arch-deps.h.in (DBUS_MAJOR_VERSION,
+	DBUS_MINOR_VERSION, DBUS_MICRO_VERSION, DBUS_VERSION_STRING,
+	DBUS_VERSION): collection of macros to get version of library we
+	are compiled against.
+
+	* dbus/dbus-misc.c (dbus_get_version): new function, to get
+	version of library we are linked against at runtime.
+
+2007-07-30  Havoc Pennington  <hp@redhat.com>
+
+	* bus/activation-helper.c (check_bus_name): don't use
+	_dbus_check_valid_bus_name() which is only around with
+	--enable-checks, instead use _dbus_validate_bus_name().
+	Bug #11766 from Diego <diego@pemas.net>
+
+2007-07-27  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: post-release version bump
+
+2007-07-27  Havoc Pennington  <hp@redhat.com>
+
+	* release 1.1.2
+
+2007-07-26  Havoc Pennington  <hp@redhat.com>
+
+	* bus/config-parser-trivial.c (check_return_values): disable a
+	test that hardcoded the bus user's name
+
+	* bus/dispatch.c (bus_dispatch_test_conf): remove the "if
+	(!use_launcher)" around the tests, they were only failing because
+	we didn't pass through all the expected errors from the helper.
+
+	* bus/activation-exit-codes.h
+	(BUS_SPAWN_EXIT_CODE_CHILD_SIGNALED): add a code for child segfaulting
+	(BUS_SPAWN_EXIT_CODE_GENERIC_FAILURE): make "1" be a generic
+	failure code, so if a third party launch helper were written it
+	could just always return 1 on failure.
+	
+2007-07-24  Daniel P. Berrange <dan@berrange.com>
+
+	* bus/dbus-daemon.1: Add docs on new syntax options for the bus
+	address strings
+
+	* dbus/dbus-address.c: Allow * in addresses (for binding to all
+	addresses).
+
+	* dbus/dbus-sysdeps.h:
+	* dbus/dbus-sysdeps-unix.c: Re-write to use getaddrinfo instead
+	of gethostbyname to enable protocol independant name lookup,
+	making IPv6 work
+
+	* dbus/dbus-server-socket.h:
+	* dbus/dbus-server-socket.c: Add support for 'family' in the
+	address string to specify ipv4 vs ipv6. Use a port string to
+	allow for service resolution. Allow for binding to multiple
+	sockets at once in case of dual IPv4 & IPv6 stacks.
+
+	* dbus/dbus-server-unix.c: Pass in an array of file descriptors
+	instead of a single one.
+
+	* dbus/dbus-transport-socket.h:
+	* dbus/dbus-transport-socket.c: Add support for 'family' in the
+	address string to specify ipv4 vs ipv6. Use a port string to
+	allow for service resolution.
+
+2007-07-24  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: add AM_PROG_CC_C_O to allow per-target CPPFLAGS
+
+	* bus/dispatch.c (bus_dispatch_test_conf): Fix up setting
+	TEST_LAUNCH_HELPER_CONFIG to include the full path, and enable
+	test shell_fail_service_auto_start when use_launcher==TRUE
+
+	* bus/activation-helper-bin.c (convert_error_to_exit_code): pass
+	through the INVALID_ARGS error so the test suite works
+
+	* bus/activation.c (handle_activation_exit_error): return
+	DBUS_ERROR_NO_MEMORY if we get BUS_SPAWN_EXIT_CODE_NO_MEMORY
+
+	* dbus/dbus-spawn.c (_dbus_babysitter_get_child_exit_status):
+	return only the exit code of the child, not the entire thingy from 
+	waitpid(), and make the return value indicate whether the child 
+	exited normally (with a status code)
+
+	* bus/bus.c (process_config_first_time_only): _dbus_strdup works
+	on NULL so no need to check
+	(process_config_every_time): move servicehelper init here, so we
+	reload it on HUP or config file change
+
+	* bus/Makefile.am (install-data-hook): remove comment because
+	Emacs make mode seems to be grumpy about it
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/Makefile.am:
+	* bus/test-system.c: (die), (check_memleaks), (test_pre_hook),
+	(test_post_hook), (main):
+	Add back the test-system.c file - not sure now this got ignored in the
+	diff. I blame git.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* configure.in:
+	Use ustar to generate the tarball; this fixes the make distcheck
+	problem when the data files do not fit in the archive:
+	tar: dbus-1.1.2/test/data/valid-service-files/org.freedesktop.DBus.
+	TestSuiteShellEchoServiceFail.service.in: file name is too
+	long (max 99); not dumped
+
+	We have to have the 'long' names as the service helper matches by
+	filename rather than by the name in the service file.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* configure.in:
+	* test/Makefile.am:
+	* test/data/invalid-service-files-system/org.freedesktop.DBus.TestS
+	uiteNoExec.service.in:
+	* test/data/invalid-service-files-system/org.freedesktop.DBus.TestS
+	uiteNoService.service.in:
+	* test/data/invalid-service-files-system/org.freedesktop.DBus.TestS
+	uiteNoUser.service.in:
+	* test/data/valid-config-files-system/debug-allow-all-fail.conf.in:
+	* test/data/valid-config-files-system/debug-allow-all-pass.conf.in:
+	* test/data/valid-config-files/debug-allow-all-sha1.conf.in:
+	* test/data/valid-config-files/debug-allow-all.conf.in:
+	* test/data/valid-service-files-system/org.freedesktop.DBus.TestSui
+	teEchoService.service.in:
+	* test/data/valid-service-files-system/org.freedesktop.DBus.TestSui
+	teSegfaultService.service.in:
+	* test/data/valid-service-files-system/org.freedesktop.DBus.TestSui
+	teShellEchoServiceFail.service.in:
+	* test/data/valid-service-files-system/org.freedesktop.DBus.TestSui
+	teShellEchoServiceSuccess.service.in:
+	* test/data/valid-service-files/debug-echo.service.in:
+	* test/data/valid-service-files/debug-segfault.service.in:
+	* test/data/valid-service-files/debug-shell-echo-fail.service.in:
+	* test/data/valid-service-files/debug-shell-echo-success.service.in:
+	* test/data/valid-service-files/org.freedesktop.DBus.TestSuiteEchoS
+	ervice.service.in:
+	* test/data/valid-service-files/org.freedesktop.DBus.TestSuiteSegfa
+	ultService.service.in:
+	* test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShell
+	EchoServiceFail.service.in:
+	* test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShell
+	EchoServiceSuccess.service.in:
+	Add the data files needed by the system activation unit checks.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/dispatch.c: (check_segfault_service_no_auto_start),
+	(check_launch_service_file_missing),
+	(check_launch_service_user_missing),
+	(check_launch_service_exec_missing),
+	(check_launch_service_service_missing), (bus_dispatch_test_conf),
+	(bus_dispatch_test_conf_fail), (bus_dispatch_test):
+	Add unit tests for system activation. Most are copied from the
+	session activation tests, but some didn't apply when using a laucher.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/activation.c: (bus_activation_activate_service):
+	If the bus uses a service-laucher, then use the setuid laucher.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* configure.in:
+	Add the needed library exports for the new laucher.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* configure.in:
+	Check for -Wl,--gc-sections so we can really reduce the size of the
+	setuid binary.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/activation.c: (handle_activation_exit_error),
+	(babysitter_watch_callback):
+	Map the child exit status integer to a proper dbus error.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/bus.c: (process_config_first_time_only),
+	(process_config_every_time), (bus_context_unref),
+	(bus_context_get_servicehelper):
+	* bus/bus.h:
+	Add the concept of a service-helper and allow it's value to be read.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/activation.c: (bus_activation_entry_unref),
+	(update_desktop_file_entry):
+	Add the concept of, and read the value of user from the desktop file.
+	The user string is not required unless we are using system activation.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/activation.c:
+	* bus/desktop-file.h:
+	Move the defines into the header file, as we use these in the lauch
+	helper as well as the desktop file parsing.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/.cvsignore:
+	Add the autogenerated binary files.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/Makefile.am:
+	* bus/test.h:
+	Add the build glue for the lauch helper, and also add the launch-helper
+	OOM checks into make check. I've probably broken the build, give me 2.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/test-launch-helper.c: (die), (check_memleaks),
+	(test_post_hook), (bus_activation_helper_oom_test), (main):
+	Add a test wrapper to allow OOM checks on the launch helper.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/activation-helper-bin.c: (convert_error_to_exit_code),
+	(main):
+	* bus/activation-helper.c: (desktop_file_for_name),
+	(clear_environment), (check_permissions), (check_service_name),
+	(get_parameters_for_service), (switch_user),
+	(exec_for_correct_user), (check_bus_name), (get_correct_parser),
+	(launch_bus_name), (check_dbus_user), (run_launch_helper):
+	* bus/activation-helper.h:
+	Add the initial launch-helper. This is split into a main section and a
+	binary loader that allows us to lauch the main section in another test
+	harness to do stuff like OOM testing. No build glue yet.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/Makefile.am:
+	* bus/config-parser.c: (bus_config_parser_unref),
+	(start_busconfig_child), (bus_config_parser_end_element),
+	(servicehelper_path), (bus_config_parser_content),
+	(bus_config_parser_finished),
+	(bus_config_parser_get_servicehelper),
+	(test_default_session_servicedirs),
+	(test_default_system_servicedirs), (bus_config_parser_test):
+	* bus/config-parser.h:
+	Make the config-parser code use the common config code.
+	Also add the session and systemdirs stuff, and make the config parser
+	aware of the servicehelper field.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/system.conf.in:
+	Add new servicehelper fields to the default system.conf file.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/config-parser-trivial.c: (service_dirs_find_dir),
+	(service_dirs_append_link_unique_or_free), (bus_config_parser_new),
+	(bus_config_parser_unref), (bus_config_parser_start_element),
+	(bus_config_parser_end_element), (bus_config_parser_content),
+	(bus_config_parser_finished), (bus_config_parser_get_user),
+	(bus_config_parser_get_type), (bus_config_parser_get_service_dirs),
+	(check_return_values), (do_load), (check_loader_oom_func),
+	(process_test_valid_subdir), (make_full_path), (check_file_valid),
+	(bus_config_parser_trivial_test):
+	* bus/config-parser-trivial.h:
+	Add a security sensitive stripped down config parser for the setuid
+	launcher. This file only reads what it needs, and doesn't try to do
+	anything remotely clever like including external files.
+	It is not intended to validate the config file; it is expected that
+	config-parser will do that before the setuid program tries to read it.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/config-parser-common.c:
+	(bus_config_parser_element_name_to_type),
+	(bus_config_parser_element_type_to_name):
+	* bus/config-parser-common.h:
+	We don't want to run the whole config parser with all it's deps in the
+	setuid program. We need to implement a stripped down config parser just
+	for the launcher, and to do so I need some common functions and
+	defines; add them here.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* dbus/dbus-sysdeps-unix.c:
+	(_dbus_get_standard_system_servicedirs):
+	* dbus/dbus-sysdeps-win.c:
+	Provide a way to get the standard system servicedirs, just like we do
+	for the session service dirs. These should be seporate, as there may
+	be a security issue starting up some session stuff as root.
+	The use-case for the same binary starting up per-system _and_
+	per-session is also not valid.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/dbus-daemon.1.in:
+	Add standard_system_servicedirs and servicehelper into the man file
+	and explain what each does.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* doc/busconfig.dtd:
+	Add servicehelper into the dtd, it will soon be a valid part of the
+	config file.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* dbus/dbus-spawn.c: (read_data),
+	(_dbus_babysitter_get_child_exit_status):
+	* dbus/dbus-spawn.h:
+	Add a function so we can get access to the exit status of the launch
+	helper.
+	By providing the return code and not the error we can leave the
+	'what does this mean?' to the bus launch code and not include it in the
+	dbus directory.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* bus/activation-exit-codes.h:
+	Add defines which specify the output codes of the launch helper.
+	We have to use exit codes as this is the only way we can return failure
+	type without going grotty things like redirecting possibly-nonsecure
+	stderr into the error.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* dbus/dbus-protocol.h:
+	Add new error names needed for the launch helper.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* dbus/dbus-sysdeps.c: (_dbus_clearenv):
+	* dbus/dbus-sysdeps.h:
+	Add a wrapper for clearenv.
+
+2007-07-24  Richard Hughes  <richard@hughsie.com>
+
+	* doc/system-activation.txt:
+	Add design document for the system activation parts. I'll shortly be
+	committing many patches that add system activation using a setuid
+	launcher into CVS, so expect things to be broken for a few hours.
+
+2007-07-19  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/modules/FindKDEWIN.cmake: fixed comment
+	* cmake/modules/FindKDEWIN32.cmake: removed obsolate cmake module
+
+2007-07-18  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c (dbus_message_get_cached)
+	(dbus_message_cache_or_finalize): don't mess with message from
+	message cache outside of the cache lock. Bug #9164 from Jonathan
+	Matthew.
+
+2007-07-13  Havoc Pennington  <hp@redhat.com>
+
+	* Add indent-tabs-mode: nil to all file headers.
+
+2007-07-12  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps-util.c (_dbus_sysdeps_test): invert the test
+	for parsing hex as double to be sure it fails to work
+
+	* dbus/dbus-sysdeps.c (_dbus_string_parse_double): don't allow hex numbers.
+
+2007-07-10  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-connection.c (struct DBusConnection): Fix from Olivier
+	Hochreutiner to avoid trying to protect individual bits in a word
+	with different locks (make dispatch_acquired and io_path_acquired
+	dbus_bool_t rather than bitfields)
+
+2007-07-09  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c,dbus-sysdeps-win.h,dbus-sysdeps-win-util.c,
+	dbus-sysdeps-spawn-win.c: synced with windbus sources 
+
+2007-07-07  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c 
+		(_dbus_getsid): remove unused jump label
+		(_dbus_read_credentials_socket): _dbus_string_init could fail, 
+	        check initialisation
+		(_dbus_get_working_dir, _dbus_init_working_dir): remove unused 
+			functions
+
+2007-07-04  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/modules/FindKDEWIN.cmake: search in <program files dir>\win32libs 
+	for windows supplementary packages too
+
+2007-06-30  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/dbus/CMakeLists.txt: handle userdb as unix file
+
+2007-06-30  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c,dbus/dbus-sysdeps-win.h: removed obsolate 
+	DBusUserInfo code
+
+2007-06-30  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c (_dbus_daemon_init): reduced compiler warnings
+
+2007-06-23  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-auth-script.c (_dbus_auth_script_run): added UNIX_ONLY and 
+	WIN_ONLY commands for auth scripts
+	* test/data/auth/external-root.auth-script: limit execution to unix
+
+2007-06-21  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-tranport.c (auth_via_default_rules): made the verbose spam
+	cross-platform
+
+2007-06-21  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-watch.c (dbus_watch_get_fd): 1) its behavior should
+	not be the same as before, the ABI has never been declared stable
+	on Windows and 2) do not commit to cross-platform files without
+	posting the exact patch to the mailing list
+	
+	* dbus/dbus-sysdeps-util.c (_dbus_sysdeps_test): as I have pointed
+	out before, either 0xff needs to work on both platforms, or none
+	of the dbus code can rely on it working. That means the options
+	are 1) audit the code for anywhere that relies on 0xff working, if
+	none found ideally add a test that it *doesn't* work and make unix
+	reject it explicitly, but in any case this test would go away or
+	2) make it work on Windows also, then we don't have to figure out 
+	whether we rely on it.
+
+	And in either case, post the exact patch to the mailing list and
+	don't just commit.
+
+2007-06-21 Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/CMakeLists.txt: added VERSION_PATCH to be able to 
+	distinguish win32 binary release from dbus versioning
+
+2007-06-21 Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c: deleted local DBusCredentials structure
+	    (_dbus_getsid): new function
+	    (_dbus_read_credentials_socket): used correct function
+	    (_dbus_append_user_from_current_process, 
+	        _dbus_credentials_add_from_current_process): added real 
+	            sid reading
+	    (_dbus_credentials_parse_and_add_desired,_dbus_parse_uid): 
+	        deleted
+
+2007-06-21 Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-util.c (_dbus_sysdeps_test): don't check 
+	0xff as floating point, this isn't supported on win32 math 
+	implementation
+
+2007-06-21 Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c (_dbus_homedir_from_username, 
+	_dbus_homedir_from_current_process, _dbus_append_desired_identity): 
+	removed obsolate functions
+
+2007-06-21 Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c, dbus/dbus-sysdeps-util-win.c, 
+	dbus/dbus-sysdeps-win.h: disabled uid/sid conversation stuff
+	implementation by Peter Kuemmel 
+
+2007-06-21  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-watch.c (dbus_watch_get_fd): this function is 
+	deprecated and its behavior should be as before until all 
+	client code is migrated. 
+
+2007-06-19  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-util-win.c, tools/dbus-launch-win.c: 
+	msvc7.1 fixes by Jaroslaw Staniek tested with mingw 
+
+2007-06-19  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c, dbus/dbus-sysdeps-spawn-win.c, 
+	dbus/dbus-sysdeps-win.h: disabled DBusSocket implementation
+	by Peter Kuemmel 
+
+2007-06-18  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus-win.patch: removed obsolate patches
+
+2007-06-18  Havoc Pennington  <hp@redhat.com>
+
+	* configure.in: bump version to 1.1.2 so CVS is higher than last
+	release (this is not the 1.1.2 release)
+
+2007-06-18  Havoc Pennington  <hp@redhat.com>
+
+	* Release 1.1.1
+
+2007-06-18  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.xml: document org.freedesktop.DBus.GetId()
+
+	* bus/driver.c (bus_driver_handle_get_id): implement org.freedesktop.DBus.GetId()
+
+	* bus/bus.c (bus_context_new): generate a unique ID for each bus context
+
+	* dbus/dbus-connection.c (dbus_connection_get_server_id): new function
+
+	* dbus/dbus-bus.c (dbus_bus_get_id): new function
+
+	* dbus/dbus-server.c (dbus_server_get_id): new function
+
+2007-06-18  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps-unix.c (_dbus_read_credentials_socket): clean
+	this up a little bit, to try and understand why telnet'ing to a
+	server and sending a non-nul byte didn't disconnect immediately;
+	now it seems that it does disconnect immediately as it should,
+	though I don't understand what has changed.
+
+2007-06-18  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-watch.c (dbus_watch_get_socket)
+	(dbus_watch_get_unix_fd): new API to match DBusConnection
+	(dbus_watch_get_fd): deprecate this
+
+	Throughout: just s/dbus_watch_get_fd/dbus_watch_get_socket/g for
+	now since all the transports use sockets anyway
+	
+2007-06-16  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-macros.h, dbus/dbus-message.c, 
+	dbus/dbus-message.h: renamed DBUS_GNUC_DEPRECATED 
+	to DBUS_DEPRECATED and extended to msvc compiler
+
+2007-06-15  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/CMakeLists.txt: use local include header first
+
+	* dbus/dbus-sysdeps-win.c: mingw fix of DBusCredential struct
+
+2007-06-15  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/ConfigureChecks.cmake,cmake/config.h.cmake: 
+	added check for HAVE_ERRNO_H
+
+	* cmake/dbus/CMakeLists.txt: added missing files 
+	
+	* dbus/dbus-transport-win.c/.h: new files
+
+	* dbus/dbus-sysdeps-win.c,.h: added required _unix functions 
+	to make dbus compilable on win32 
+	
+	* dbus/dbus-sysdeps-win-utils.c,.h: moved some functions to 
+	dbus-sysdeps-win.c
+	
+	* dbus-win.patch: removed applied or obsolate patches
+	
+	Note: dbus-win32 is now compilable, no guarantee that it runs 
+	without any problems 
+
+2007-06-15  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps-unix.c (_dbus_append_session_config_file)
+	(_dbus_append_system_config_file): new functions
+
+	* bus/main.c (main): use _dbus_append_system_config_file() and 
+	_dbus_append_session_config_file()
+
+	* dbus/Makefile.am (INCLUDES): move DBUS_SYSTEM_CONFIG_FILE and
+	DBUS_SESSION_CONFIG_FILE into this makefile
+
+2007-06-15  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps.c (_dbus_set_errno_to_zero)
+	(_dbus_get_is_errno_nonzero, _dbus_get_is_errno_eintr)
+	(_dbus_strerror_from_errno): family of functions to abstract
+	errno, though these are somewhat bogus (really we should make our
+	socket wrappers not use errno probably - the issue is that any
+	usage of errno that isn't socket-related probably is not
+	cross-platform, so should either be in a unix-only file that can
+	use errno directly, or is a bug - these general errno wrappers
+	hide issues of this nature in non-socket code, while
+	socket-specific API changes would not since sockets are allowed
+	cross-platform)
+
+2007-06-14  Havoc Pennington  <hp@redhat.com>
+
+	* bus/dispatch.c (check_get_connection_unix_process_id): mop up
+	getpid() (noticed by Peter Kümmel) and adapt the test to 
+	expect a "pid unknown" error when running on Windows.
+
+2007-06-14  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps-unix.c (_dbus_credentials_parse_and_add_user):
+	delete this function since it was effectively the same as
+	_dbus_credentials_add_from_username()
+
+2007-06-14  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-auth.c: adapt to keyring changes
+
+	* dbus/dbus-keyring.c: change to avoid using user ID and home
+	directory directly; instead use a
+	keyring-location-from-credentials function in dbus-sysdeps
+
+	* fix to use _dbus_append_user_from_current_process() instead of 
+	_dbus_username_from_current_process() or _dbus_append_desired_identity().
+	
+2007-06-14  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* reverted global rename of function _dbus_username_from_current_process. 
+	It needs too much tests to verify that the change does not break anything. 
+	I had overseen that the signatures are different and requires non
+	trivial changes. 
+	This is one *major* disadvantage of emulating oop functionality with c. 
+	You are responsible for cleaning every object on every function return point
+	which could be a nightmare if you are not working with dbus all the days.
+
+2007-06-14  Ralf Habacker  <ralf.habacker@freenet.de>
+    
+	* dbus/dbus-auth.c (handle_client_initial_response_cookie_sha1_mech): 
+	fixed usage of _dbus_append_desired_identity()
+
+	* dbus/dbus-sysdeps.h (_dbus_username_from_current_process): removed prototype
+
+2007-06-14  Ralf Habacker  <ralf.habacker@freenet.de>
+    
+	* dbus/dbus-sysdeps.c: moved global lock system_users from dbus-userdb.c
+
+2007-06-14  Ralf Habacker  <ralf.habacker@freenet.de>
+    
+	* global rename of function _dbus_username_from_current_process
+	to _dbus_append_desired_identity. 
+	Approved by Havoc Pennington
+
+2007-06-14  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c: disabled DBusUserInfo related code
+		(_dbus_append_desired_identity,	_dbus_windows_user_is_process_owner):
+    		new win32 functions as counterpart of unix related 
+		(_dbus_send_credentials_socket,_dbus_read_credentials_socket): 
+	    	renamed from ..._unix_socket
+		(_dbus_send_credentials_unix_socket): removed obsolate function
+	
+	* dbus/dbus-sysdeps-win-util.c: disabled DBusGroupInfo related code
+		(_dbus_verify_daemon_user,_dbus_change_to_daemon_user): 
+		    new win32 functions as counterpart of unix related
+	
+2007-06-14  Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* doc/dbus-specification.xml: say the protocol version is 1 instead of
+	0 (patch from Kristoffer Lundén, fd.o#10033) and remove the FIXME
+	about removing protocol version from messages (as per Havoc's comment
+	on that bug)
+
+2007-06-14  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c (_dbus_pid_for_log,_dbus_flush_caches): 
+	new win32 functions as counterpart of unix related
+
+2007-06-14  Ralf Habacker  <ralf.habacker@freenet.de>
+	
+	* cmake/modules/FindKDEWIN.cmake,
+	  cmake/modules/FindKDEWIN_Packager.cmake, 
+	  cmake/modules/Win32Macros.cmake: new files from the 
+	  kdewin32 project
+	* cmake/CMakeLists.txt: cleaned support for kdewin installer and 
+	  win32 explorer wrapper
+
+2007-06-13  Havoc Pennington  <hp@redhat.com>
+	
+	* dbus/dbus-message.c (dbus_message_iter_open_container): Fix
+	broken return_if_fail (kind of scary that test suite does not
+	cover this)
+
+2007-06-13  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-server-socket.c (_dbus_server_listen_socket): support
+	all_interfaces=true|false for tcp servers
+
+	* dbus/dbus-sysdeps-unix.c (_dbus_listen_tcp_socket): support
+	inaddr_any flag
+
+	* bus/selinux.c: fix some missing includes
+
+	* dbus/dbus-server-socket.c (_dbus_server_listen_socket): allow
+	port to simply be omitted in addition to specifying 0
+
+2007-06-13  Havoc Pennington  <hp@redhat.com>
+
+	* configure.ac, bus/selinux.c, dbus/dbus-sysdeps-unix-util.c: add
+	libaudit support, no clue what this means really but now we have
+	it. Patches from Fedora package.
+
+	* bus/bus.c (bus_context_new): move selinux initialization after
+	changing to daemon user, patch from Fedora package
+
+	* dbus/dbus-transport.c (auth_via_unix_user_function): fix a typo
+
+2007-06-12  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c (dbus_message_iter_open_container): improve
+	the checks/warnings for contained_signature a bit
+
+2007-06-12  Havoc Pennington  <hp@redhat.com>
+	
+	* dbus/dbus-marshal-recursive.c (write_or_verify_typecode):
+	improve the warning a bit if you write extra data into a message
+
+2007-06-12  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-auth.c (sha1_handle_second_client_response)
+	(handle_server_data_anonymous_mech): add the process ID from
+	socket credentials, if available, even if not using EXTERNAL
+
+	* dbus/dbus-transport.c (auth_via_default_rules): support
+	allow_anonymous flag
+
+	* dbus/dbus-connection.c (dbus_connection_get_is_anonymous)
+	(dbus_connection_set_allow_anonymous): new API for controlling
+	anonymous access
+
+2007-06-09  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-string.c (_dbus_string_pop_line): fix this not to
+	think an empty line is the end of the file.
+	Also, fix some whitespace.
+
+	* dbus/dbus-string-util.c: add more tests for
+	_dbus_string_pop_line() revealing that it thinks an empty line is
+	the end of the file, which broke dbus-auth-script.c so 
+	it didn't really run the scripts
+
+	* dbus/dbus-auth.c: add ANONYMOUS mechanism
+
+	* dbus/dbus-auth-script.c (_dbus_auth_script_run): fix to detect
+	an empty/no-op auth script; add commands to check that we have or
+	don't have the expected credentials	
+
+2007-06-09  Havoc Pennington  <hp@redhat.com>
+
+	* bus/policy.c (bus_policy_create_client_policy): gracefully
+	continue if the connection has no unix user - just don't apply 
+	any unix user dependent rules.
+
+	* bus/config-parser.c: remove dbus-userdb.h usage
+
+	* bus/bus.c: remove dbus-userdb.h usage
+
+	* dbus/dbus-transport.c (_dbus_transport_get_is_authenticated):
+	support Windows user function; also, fix the logic for checking
+	auth as root in the default auth code (broken in the previous
+	commit)
+
+	* dbus/dbus-connection.c
+	(dbus_connection_set_windows_user_function): new function
+	(dbus_connection_get_windows_user): new function
+
+2007-06-09  Havoc Pennington  <hp@redhat.com>
+
+	* bus/dispatch.c (check_get_connection_unix_process_id): adapt
+	since sysdeps-unix.h stuff isn't included anymore
+
+	* bus/bus.c (bus_context_new): use more abstract functions to
+	change user, so they can be no-ops on Windows
+
+	* dbus/dbus-credentials.c, dbus/dbus-credentials.h,
+	dbus/dbus-credentials-util.c: new files containing a fully opaque
+	DBusCredentials data type to replace the old not opaque one.
+
+	* configure.in (DBUS_UNIX): define DBUS_UNIX to match DBUS_WIN on
+	windows
+
+	* dbus/dbus-userdb.h: prohibit on Windows, next step is to clean
+	up the uses of it in bus/*.c and factor out the parts of 
+	cookie auth that depend on it
+	
+2007-06-07  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-message.c: improve some docs related to reading values
+	from a message iter
+
+2007-06-02  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake: added cygwin compile support
+
+2007-06-01  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* tools/dbus-launch-win.c: new file, replaces script wrapper on win32.
+
+	* cmake/dbus-launch.bat.cmake: removed obsolate file
+
+2007-05-31  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* bus/main.c (main): uses _dbus_get_config_file_name() to detect 
+	session.conf location on win32. 
+
+	* dbus-sysdeps-win.h (_dbus_get_config_file_name,_dbus_file_exists): 
+	new prototyp, undefined interface after including windows.h because 
+	it makes trouble when a paramater is named interface.
+
+	* dbus-sysdeps-win.c (_dbus_get_install_root,
+	_dbus_get_config_file_name,_dbus_file_exists): 	new functions.
+
+2007-05-27  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* bus/policy.c,dbus/dbus-internals.c: fixed inconsistant line endings 
+	as reported by Peter Kümmel.
+
+2007-05-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Released 1.1.0
+
+2007-05-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* Split NEWS and ChangeLog into a .pre-1-0 file as per HACKING
+	We forgot to do this during the 1.0 release and it makes sense
+	now as we get ready to release the first 1.1.0 development tarball
+
+2007-05-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* create directory test/data/valid-config-files/session.d so that
+	make check passes
+
+2007-05-25  John (J5) Palmieri  <johnp@redhat.com>
+
+	* INSTALL: remove dependancies for bindings since they no longer
+	are a part of core
+
+2007-05-25  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-server-win.c,dbus/dbus-server-win.h: new file 
+	with empty function _dbus_server_listen_platform_specific(). 
+
+	* dbus/dbus-server.c (listen_funcs): uses 
+	_dbus_server_listen_platform_specific on any platform.
+
+2007-05-25  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c (fill_win_user_info_homedir): not getting 
+	user info from a domain controller isn't an error, the computer 
+	may run in a non domain context. 
+
+2007-05-25  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c (_dbus_full_duplex_pipe): fixed assertation.
+
+2007-05-24  Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* bus/config-parser.c (test_service_dir_matches): fixed ordering for unix.
+
+	* bus/config-parser.c (test_default_session_servicedirs): made allocation 
+	of _progs platform independent.
+
+2007-05-23  Havoc Pennington  <hp@redhat.com>
+
+	* bus/Makefile.am (install-data-hook): create session.d
+
+	* bus/session.conf.in: add session.d for the session bus, so
+	security policy can be extended
+
+2007-05-22 Ralf.Habacker <ralf.habacker@freenet.de>
+
+	* cmake/CMakeLists.txt: fixed creating of TEST_..._BINARY to make 
+	bus-test able to find the binaries.
+
+2007-05-21 Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* acinclude.m4, configure.in: In recent autotools, ${datadir} is
+	defined in terms of ${datarootdir}, so EXPANDED_DATADIR needs to be
+	expanded recursively. Rather than fixing configure.in to do this, I
+	grabbed the AS_AC_EXPAND macro from autostars.sf.net, which seems to be
+	commonly used.
+
+2007-05-21 Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* update-dbus-docs.sh: Assorted improvements:
+	- Default user if $FDUSER is not set is the ssh default
+	  (set in ~/.ssh/config or based on the local username), not a
+	  hard-coded "johnp"
+	- Temporary checkout directory is created securely (preventing symlink
+	  attacks), if mktemp(1) is available
+	- Use make -C rather than cd && make && cd ..
+
+2007-05-21 Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* HACKING: Point to correct mailing list
+
+2007-05-21 Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* doc/dbus-specification.xml: explicitly specify that STRING cannot
+	contain embedded NULs.
+
+2007-05-20 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-internal.c: fix inline problem on win32.
+
+2007-05-20 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c (fill_win_user_info_homedir): not reaching 
+	domain controller isn't an error, converted error message to verbose 
+	message.
+
+2007-05-19 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-test.c (dbus_internal_do_not_use_run_tests): disabled 
+	tests not running on wince.
+
+2007-05-19 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-internals.c (_dbus_verbose_init): win32 requires 'varname=' 
+	to unset a environment variable. 
+
+2007-05-19 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps.c (_dbus_setenv): win32 requires 'varname=' 
+	to unset a environment variable. 
+
+2007-05-19 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* bus/policy.c (bus_policy_create_client_policy): 
+	win32 temporary fix until the userdb stuff is ported completly.
+
+2007-05-19  Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-server.c (listen_funcs): 
+	_dbus_server_listen_platform_specific is empty on win32, 
+	limited to unix only.
+
+	* dbus/dbus-server.c (valid_addresses): limit unix 
+	only addresses to unix. 
+
+2007-05-18  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-specification.xml: add a GetAll to the Properties
+	interface.
+
+2007-05-17 Ralf.Habacker  <ralf.habacker@freenet.de>
+ 
+	* bus\config-parser.c (test_default_session_servicedirs):
+	win32 fix.
+
+2007-05-17 Ralf.Habacker  <ralf.habacker@freenet.de>
+ 
+	* configure.in: define constant DBUS_UNIX.
+
+2007-05-14  Ralf Habacker <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c (_dbus_printf_string_upper_bound):
+	compile fix for MS Platform SDK 6 
+	patch from Michael Luschas <mluschas@gmail.com>
+
+2007-05-10  John (J5) Palmieri <johnp@redhat.com>
+
+	* dbus-1.pc.in: add daemondir to pc file
+	patch from Brian Cameron <brian.cameron at sun.com>
+
+2007-05-04  Simon McVittie <simon.mcvittie@collabora.co.uk>
+
+	* doc/dbus-specification.xml: mention the reserved o.fd.DBus.Local
+	interface and the corresponding /o/fd/DBus/Local object path;
+	describe them as reserved and forbid using them in a sent message,
+	mentioning that in the reference implementation this will cause the
+	connection to be dropped. Patch approved by Havoc.
+
+2007-04-28  Ralf Habacker <ralf.habacker@freenet.de>
+
+	* cmake/: don't install test applications and service files,
+	moved CMAKE_DEBUG_POSTFIX to top level CMakeLists.txt
+
+2007-04-27  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-sysdeps-unix.c (_dbus_open_socket): fix #10781 from
+	Tobias Nygren, checking pointer to fd vs. 0 rather than checking
+	the fd itself
+
+2007-04-26 Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/: added debug postfixes to debug exe's for 
+	easier debugging.
+	* dbus\dbus-sysdeps-win.c (_dbus_win_set_error_from_win_error): 
+	print error code in case no string message is available.
+
+2007-04-06 Simon McVittie <simon.mcvittie@collabora.co.uk>
+
+	* dbus/dbus-message-util.c, dbus/dbus-message.c,
+	dbus/dbus-message.h: Add API to convert a DBusMessage to/from a
+	byte array. Patch from Dafydd Harries <dafydd.harries@collabora.co.uk>,
+	approved by Havoc Pennington.
+
+2007-04-03  Timo Hoenig  <thoenig@suse.de>
+
+	* dbus/dbus-address.c (dbus_parse_address): Do not accept zero-
+	  length address.
+	* dbus/dbus-address.c (_dbus_address_test): Add test for zero-
+	  length address.
+
+2007-03-25 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/dbus/CMakeLists.txt: debug postfix also for mingw.
+
+2007-03-16 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/modules/FindExpat.cmake: fix package detection on win32.
+
+	* README.win: update install instructions. 
+
+2007-03-16 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps.h (_dbus_split_paths_and_append):
+	new prototyp
+	(_DBUS_PATH_SEPARATOR): new macro. 
+
+	* dbus/dbus-sysdeps.c (_dbus_split_paths_and_append): merged 
+	from dbus/dbus-sysdeps-unix.c and dbus/dbus-sysdeps-win.c. 
+
+2007-03-15 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* bus/config-parser.c, bus/policy.c,  
+	bus/policy.h, bus/dbus-daemon.1.in,
+	bus/session.conf.in: added eavesdrop support 
+	for replies - patch by olli.salli at collabora.co.uk
+	approved by Havoc Pennington. 
+
+2007-03-15 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus\dbus-sysdeps-win-thread.c: renamed to 
+	dbus-sysdeps-thread-win.c, it is a platform depending file 
+	similar	to dbus-sysdeps-pthread.c.
+
+2007-03-15 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* cmake\doc\CMakeLists.txt: added prelimary xml doc 
+	support, needs cmake Find script.
+
+2007-03-14 Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* cmake: add doxygen support
+
+2007-03-14  Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/config.h.cmake: WINCE fixes, defined DBUS_UNIX.
+
+2007-03-13  Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-util-win.c (dbus_become_daemon): 
+	win32 compile fix. 
+
+2007-03-13  Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus-win.patch: removed obsolate patches. 
+
+2007-03-13  Ralf.Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c: added zero byte sending 
+	and receiving after connection start up
+
+2007-03-11  Havoc Pennington  <hp@redhat.com>
+
+	* tools/dbus-launch.c (do_close_stderr): fix C89 problem and
+	formatting problem
+
+	* Mostly fix the DBusPipe mess.
+	- put line break after function return types
+	- put space before parens
+	- do not pass structs around by value
+	- don't use dbus_strerror after calling supposedly cross-platform
+	api
+	- don't name pipe variables "fd"
+	- abstract special fd numbers like -1 and 1
+
+2007-03-12  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.h, dbus/dbus-sysdeps-win.c, 
+	dbus/dbus-sysdeps-util-win.c: renamed functions 
+	_dbus_xxx_file() to _dbus_file_xxx() to reflect 
+	struct name DBusFile. 
+
+2007-03-12  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-util-unix.c (_dbus_become_daemon):
+	fix _dbus_pid_fd check. 
+
+2007-03-10  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* tools/dbus-print-message.c (print_message):
+	added printing of the reply serial to method returns and 
+	errors, so you can actually figure out the message/reply 
+	pairs - patch by olli.salli at collabora.co.uk.
+
+2007-03-10  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus-win.patch: removed committed patches. 
+
+2007-03-10  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* bus/bus.c, bus/bus.h, bus/main.c, bus/test.c,
+	dbus/dbus-sysdeps-unix.c, dbus/dbus-sysdeps-util-unix.c,
+	dbus/dbus-sysdeps-util-win.c, dbus/dbus-sysdeps-win.c,
+	dbus/dbus-sysdeps.h: renamed _dbus_xxx_pipe to _dbus_pipe_xxx,
+	completed _dbus_pipe support. 
+
+2007-03-10  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps.h (_dbus_listen_tcp_socket):
+	changed type or port to pointer, because the port is given back.
+
+	* dbus/dbus-server-socket.c (_dbus_server_new_for_tcp_socket):
+	implemented returning tcp port. Skipping port parameter
+	and non integer port values in config <listen> statement
+	needs more effort.
+
+	* dbus/dbus-sysdeps-unix.c, dbus/dbus-sysdeps-win.c
+	(_dbus_listen_tcp_socket): return the real used tcp port.
+
+	* bus/dbus-daemon.1.in: added <listen> tcp examples
+
+2007-03-09  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/config.h.cmake: win32 msvc bug fix
+
+2007-03-09  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/config.h.cmake: fixed DBUS_WINxx defines,
+	using _WINCE does not work.
+
+2007-03-08  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus-win.patch: removed _dbus_write_pipe() patch, it is now 
+	committed.
+
+2007-03-08  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* bus/bus.c, dbus/dbus-sysdeps-unix.c, dbus/dbus-sysdeps.h:
+	rename pipe related write() function calls to _dbus_write_pipe().
+
+2007-03-08  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus-win.patch: added bus/config-loader-libexpat.c patch, 
+	uses DBUS_WIN for alls win32 related #ifdefs, 
+	some minor cleanups
+
+2007-03-08  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus-win.patch: updated patch for bus/dispatch.c.
+
+2007-03-08  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus-win.patch: dbus-connection.c (dbus_connection_get_unix_user,
+	dbus_connection_get_unix_process_id): Let return them valid user id's, 
+	otherwise bus-test fails. How to replace on win32 ?.
+	
+	* dbus/dbus-sysdeps-win.c (fill_win_user_info_homedir):
+	fix memory leak.
+
+2007-03-08  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win.c (_dbus_win_set_error_from_win_error):
+	use dbus friendly error name.
+	(fill_win_user_info_homedir): print user name in error case too.
+
+2007-03-08  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/ConfigureChecks.cmake: fixed socketpair check
+
+2007-03-08  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* bus/dispatch.c: disabled segfault test on win32 for now
+
+2007-03-08  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* configure.in, cmake/ConfigureChecks.cmake: added check 
+	for setrlimit. 
+	* test/test-segfault.c: only include setrlimit stuff only 
+	when available.  
+
+2007-03-07  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* test/test-segfault.c: unix compile fix.
+	* dbus-win.patch: removed obsolate patches.
+
+2007-03-07  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* bus/activation.c: removed obsolate include header.
+	* test/test-segfault.c: win32 compile fix, rlimit 
+	isn't available on win32.
+	* dbus-win.patch: removed some more patches, they
+	are applied or obsolate 
+
+2007-03-06  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* bus-win.patch: fixes unix listen problems, dbus-test 
+	now runs.
+
+2007-03-06  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake/dbus/CMakeLists.txt,cmake/bus/CMakeLists.txt,
+	cmake/CMakeLists.txt: win32 compile fix
+
+2007-03-04  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus-win.patch, README.win: added available win32 
+	patches from windbus project (http://sf.net/projects/windbus)
+
+2007-03-04  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* bus/activation.c: (bus_activation_activate_service):
+	fixed call to _dbus_spawn_async_with_babysitter().
+
+2007-03-04  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-spawn.c,dbus/dbus-spawn.h (_dbus_spawn_async_with_babysitter):
+	added environment pointer as function parameter, used on win32.
+
+	* test/spawn-test.c: fixed call to above mentioned function.
+
+2007-03-04  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* configure.in,test/test-sleep-forever.c,test/test-names.c: 
+	added configure check for unistd.h.
+
+2007-03-04  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* test/Makefile.am: fixed test data copy problem in 
+	out of source build, when sources came from svn or cvs. 
+
+2007-03-03  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/*-win.*,bus/*-win.*: added win32 platform related
+	files. These files are only added to the cmake build system.  
+	The missing dbus-win.patch file will be added later. 
+
+2007-03-03  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* cmake: new directory, contains cmake build support.
+	See http://www.cmake.org for more informations.
+	Currently only unix will be buildable because some 
+	win32 required files are still missing. 
+
+2007-03-03  Thiago Macieira  <thiago@kde.org>
+
+	* dbus/dbus-sysdeps-unix.c: capture the dbus-launch stderr
+        output and add it to the DBusError message we return.
+
+	* tools/dbus-launch.1:
+	* tools/dbus-launch.c: Add option --close-stderr to, well,
+	close stderr before starting dbus-daemon.
+
+2007-01-31  Havoc Pennington  <hp@redhat.com>
+
+	* bus/dbus-daemon.1.in: write a section in the man page on running
+	a test daemon for debugging purposes
+
+2007-01-26  Havoc Pennington  <hp@redhat.com>
+
+	* bus/session.conf.in: override all the default limits with much
+	higher limits on the session bus, there is no reason the session
+	bus should have low limits
+
+	* bus/config-parser.c (bus_config_parser_new): increase default
+	limits so they are less likely to be hit; in particular the max
+	replies per connection was way too low
+
+2006-01-25  Simon McVittie  <simon.mcvittie@collabora.co.uk>
+
+	* doc/dbus-tutorial.xml: Replace Python section of tutorial with
+	a pointer to the tutorial maintained as part of dbus-python
+
+2006-12-31  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-unix.c: unix compile fix, moved 
+	atomic_exchange_and_add() from dbus/dbus-sysdeps.c 
+	to here, it's used by _dbus_atomic_inc() and _dbus_atomic_dec().
+
+2006-12-31  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* tools/dbus-monitor.c: gettimeofday() is not available 
+	on windows so we have to provide our own. It's taken from 
+	lgpl'd kdewin32 package. - Patches from Christian Ehrlicher
+
+2006-12-31  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-unix.c: moved _dbus_atomic_inc/dec() 
+	from dbus/dbus-sysdeps.c, windows version of _dbus_atomic_inc/dec() 
+	is in dbus-sysdeps-win.c (not in this patch).
+
+	* dbus/dbus-sysdeps.h: DBusAtomic::value is long on windows to fit 
+	with InterlockedInc/Decrement. 
+	- Patches from Christian Ehrlicher
+	
+2006-12-31  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* tools/dbus-send.c, tools/dbus-monitor.c: win32 compile fix.
+
+2006-12-31  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-marshal-recursive.c (type DBusTypeReaderClass):
+	fix mispaced const statement. - Patch from Peter Kümmel
+
+2006-12-19  Ray Strode  <rstrode@redhat.com>
+
+	* bus/bus.c (process_config_every_time):
+	don't overwrite existing bus context activation object
+	until after we've checked that the new activation is
+	valid.
+
+	* bus/main.c 
+	(signal_handler), (handle_reload_watch):
+	don't call exit() on failure, instead make do and keep
+	going.
+	(close_reload_pipe): new function to turn off
+	hangup-causes-config-reload behavior if an unexpected
+	error occurs
+
+2006-12-13  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-sysdeps-win-thread.c (_dbus_condvar_wait_win32):
+	correctness fix. - Patch from Christian Ehrlicher
+
+2006-12-13  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-internals.h: msvc also knows about __FUNCTION__, 
+	we should also use it. - Patch from Christian Ehrlicher
+
+2006-12-13  Ralf Habacker  <ralf.habacker@freenet.de>
+  
+	* dbus-sysdeps-util.c: added win32 related tests
+
+2006-12-12  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-string.c (_dbus_string_pop_line),
+	bus/desktop-file.c (parse_section_start,
+	parse_comment_or_blank,parse_key_value,): uses
+	_dbus_string_find_eol() to support platform independent eol style.
+
+2006-12-12  Ralf Habacker  <ralf.habacker@freenet.de>
+
+	* dbus/dbus-string.[ch] (_dbus_string_find_eol): new function. 
+	* dbus/dbus-string-util.c (_dbus_string_test): added testcases for 
+	      _dbus_string_find_eol().
+	Approved by: Havoc Pennington.
+
+2006-12-12  Tim Dijkstra <tim@famdijkstra.org>
+
+	* configure.in: Added switch to disable user_database caching.
+
+	* dbus/dbus-userdb-util.c, dbus/dbus-userdb.c: Add ifdefs to
+	be able disable user_dabase caching.
+
+2006-12-12  Tim Dijkstra <tim@famdijkstra.org>
+
+	* bus/bus.c, bus/bus.h: Remove DBusUserDatabase from the BusContext 
+	struct. It is unnecessary we have a global one already. Also remove 
+	bus_context_get_user_database function, it is no longer needed.
+	Flush the global database on reload.
+
+	* dbus/dbus-userdb-util.c: Replace _dbus_user_database_get_groups 
+	with _dbus_groups_from_uid. It no longer needs a DBusUserDatabase.
+
+	* dbus/dbus-userdb.c, dbus/dbus-userdb.h: 
+	Add _dbus_user_database_flush_system. 
+	Make more functions DBUS_USERDB_INCLUDES_PRIVATE. 
+	Small unrelated change in _dbus_is_a_number: change 
+	_dbus_string_parse_int to _dbus_string_parse_uint. 
+
+	* bus/connection.c: Change call to _dbus_user_database_get_groups to 
+	_dbus_groups_from_uid.
+
+	* bus/policy.c, bus/policy.h: Change call to 
+	_dbus_user_database_get_groups to _dbus_groups_from_uid. Remove 
+	DBusUserDatabase from bus_policy_allow_user prototype, it no longer 
+	needs it.
+
+2006-12-12  John (J5) Palmieri  <johnp@redhat.com>
+
+	* bus/signal.c: Fix match_rule_equal errata
+	(CVE-2006-6107 - Patch from Kimmo Hämäläinen 
+	<kimmo.hamalainen@nokia.com>)
+
+2006-11-19  Thiago Macieira  <thiago@kde.org>
+
+	* dbus/dbus-sysdeps-pthread.c (_dbus_pthread_mutex_lock,
+        _dbus_pthread_condvar_wait,
+        _dbus_pthread_condvar_wait_timeout): set pmutex->holder to
+        pthread_self() after coming back from a conditional variable
+        wait as well as in one codepath where it was forgotten.
+	Approved by: Havoc Pennington.
+
+2006-11-17  Havoc Pennington  <hp@redhat.com>
+
+	* update-dbus-docs.sh: allow setting fd.org username via env
+	variable. Make it run autogen with --enable-xml-docs=yes
+	--enable-doxygen-docs=yes so configure will fail if the required
+	tools are missing.
+
+2006-11-17  Havoc Pennington  <hp@redhat.com>
+
+	* doc/dbus-faq.xml: minor FAQ tweaks
+
+2006-11-14  Havoc Pennington  <hp@redhat.com>
+	
+	* dbus/dbus-misc.c, dbus/dbus-misc.h: Move
+	dbus_get_local_machine_id() to its own file, no substantive
+	changes. There are a couple other things we might want to add that
+	are "misc" so moving out of dbus-connection.[hc] which is big
+	enough already.
+	
+2006-11-14  Havoc Pennington  <hp@redhat.com>
+
+	* dbus/dbus-internals.c (_dbus_generate_uuid): The spec said the
+	UUID had the timestamp last, but the implementation had it first;
+	move it to last since I think it's a tiny bit nicer (easier to
+	compare at a glance, faster to sort, less code), and will not
+	cause any practical compatibility problems. Also, always convert
+	the timestamp to big endian.
+
+	* doc/dbus-specification.xml: Clean up the docs on the UUID.
+
+	* tools/dbus-uuidgen.1: more prominently say it is not suitable
+	as a replacement for regular uuidgen/RFC4122.
+
+2006-11-14  John (J5) Palmieri  <johnp@redhat.com>
+
+	* dbus/dbus-threads.h: fix DBUS_THREAD_FUNCTIONS_ALL_MASK to have
+	the correct value so we don't assert when initalizing recursive threads
+
+	* test/name-test/test-thread-init.c: call dbus_threads_init_default
+	instead of _dbus_threads_init_debug since it is more of a real world
+	test
+
diff --git a/dbus/CleanSpec.mk b/dbus/CleanSpec.mk
new file mode 100644
index 0000000..b84e1b6
--- /dev/null
+++ b/dbus/CleanSpec.mk
@@ -0,0 +1,49 @@
+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/dbus/Doxyfile.in b/dbus/Doxyfile.in
new file mode 100644
index 0000000..afac639
--- /dev/null
+++ b/dbus/Doxyfile.in
@@ -0,0 +1,181 @@
+# Doxyfile 0.1
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = D-Bus
+PROJECT_NUMBER         = @VERSION@
+OUTPUT_DIRECTORY       = doc/api
+OUTPUT_LANGUAGE        = English
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+STRIP_CODE_COMMENTS    = YES
+CASE_SENSE_NAMES       = YES
+SHORT_NAMES            = NO
+HIDE_SCOPE_NAMES       = NO
+VERBATIM_HEADERS       = YES
+SHOW_INCLUDE_FILES     = YES
+JAVADOC_AUTOBRIEF      = YES
+INHERIT_DOCS           = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+ALIASES                = 
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = YES
+SHOW_USED_FILES        = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = YES
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_FORMAT            = 
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = @top_srcdir@/dbus
+FILE_PATTERNS          = *.c *.h
+RECURSIVE              = YES
+#EXCLUDE                = test
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = Makefile.* ChangeLog CHANGES CHANGES.* README \
+                         README.* *.png AUTHORS DESIGN DESIGN.* *.desktop \
+                         DESKTOP* COMMENTS HOWTO magic NOTES TODO THANKS
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = 
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = 
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = 
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = YES
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3dbus
+MAN_LINKS              = YES
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = YES
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = YES
+EXPAND_ONLY_PREDEF     = YES
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = "DBUS_BEGIN_DECLS=" 			\
+			 "DBUS_END_DECLS=" 			\
+			 "DOXYGEN_SHOULD_SKIP_THIS" 		\
+                         "DBUS_GNUC_DEPRECATED="                \
+			 "_DBUS_DEFINE_GLOBAL_LOCK(name)="	\
+			 "_DBUS_GNUC_PRINTF(from,to)="
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+PERL_PATH              = 
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+TEMPLATE_RELATIONS     = YES
+HIDE_UNDOC_RELATIONS   = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+GRAPHICAL_HIERARCHY    = YES
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 640
+MAX_DOT_GRAPH_HEIGHT   = 1024
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
diff --git a/dbus/HACKING b/dbus/HACKING
new file mode 100644
index 0000000..805fd2e
--- /dev/null
+++ b/dbus/HACKING
@@ -0,0 +1,351 @@
+The guidelines in this file are the ideals; it's better to send a
+not-fully-following-guidelines patch than no patch at all, though.  We
+can always polish it up.
+
+Mailing list
+===
+
+The D-Bus mailing list is dbus@lists.freedesktop.org; discussion
+of patches, etc. should go there.
+
+Security
+===
+
+Most of D-Bus is security sensitive.  Guidelines related to that:
+
+ - avoid memcpy(), sprintf(), strlen(), snprintf, strlcat(),
+   strstr(), strtok(), or any of this stuff. Use DBusString. 
+   If DBusString doesn't have the feature you need, add it 
+   to DBusString. 
+
+   There are some exceptions, for example
+   if your strings are just used to index a hash table 
+   and you don't do any parsing/modification of them, perhaps
+   DBusString is wasteful and wouldn't help much. But definitely 
+   if you're doing any parsing, reallocation, etc. use DBusString.
+
+ - do not include system headers outside of dbus-memory.c, 
+   dbus-sysdeps.c, and other places where they are already 
+   included. This gives us one place to audit all external 
+   dependencies on features in libc, etc.
+
+ - do not use libc features that are "complicated" 
+   and may contain security holes. For example, you probably shouldn't
+   try to use regcomp() to compile an untrusted regular expression.
+   Regular expressions are just too complicated, and there are many 
+   different libc's out there.
+
+ - we need to design the message bus daemon (and any similar features)
+   to use limited privileges, run in a chroot jail, and so on.
+
+http://vsftpd.beasts.org/ has other good security suggestions.
+
+Coding Style
+===
+
+ - The C library uses GNU coding conventions, with GLib-like
+   extensions (e.g. lining up function arguments). The
+   Qt wrapper uses KDE coding conventions.
+
+ - Write docs for all non-static functions and structs and so on. try
+   "doxygen Doxyfile" prior to commit and be sure there are no
+   warnings printed.
+
+ - All external interfaces (network protocols, file formats, etc.)
+   should have documented specifications sufficient to allow an
+   alternative implementation to be written. Our implementation should
+   be strict about specification compliance (should not for example
+   heuristically parse a file and accept not-well-formed
+   data). Avoiding heuristics is also important for security reasons;
+   if it looks funny, ignore it (or exit, or disconnect).
+
+Development
+===
+
+D-Bus uses Git as its version control system. The main repository is
+hosted at git.freedesktop.org/dbus/dbus. To clone D-Bus, execute the
+following command:
+
+    git clone git://git.freedesktop.org/dbus/dbus
+OR
+    git clone git.freedesktop.org:dbus/dbus
+
+The latter form is the one that allows pushing, but it also requires
+an SSH account on the server. The former form allows anonymous
+checkouts.
+
+D-Bus development happens in two branches in parallel: the current
+stable branch, with an even minor number (like 1.0, 1.2 and 1.4), and
+the next development branch, with the next odd number.
+
+The stable branch is named after the version number itself (dbus-1.2,
+dbus-1.4), whereas the development branch is simply known as "master".
+
+When making a change to D-Bus, do the following:
+
+ - check out the earliest branch of D-Bus that makes sense to have
+   your change in. If it's a bugfix, it's normally the current stable
+   branch; if it's a feature, it's normally the "master" branch. If
+   you have an important security fix, you may want to apply to older
+   branches too.
+
+ - for large changes:
+     if you're developing a new, large feature, it's recommended
+     to create a new branch and do your development there. Publish
+     your branch at a suitable place and ask others to help you
+     develop and test it. Once your feature is considered finalised,
+     you may merge it into the "master" branch.
+
+- for small changes:
+    . make your change to the source code
+    . execute tests to guarantee that you're not introducing a
+      regression. For that, execute: make check
+      (if possible, add a new test to check the fix you're
+      introducing)
+    . commit your change using "git commit"
+      in the commit message, write a short sentence describing what
+      you did in the first line. Then write a longer description in
+      the next paragraph(s).
+    . repeat the previous steps if necessary to have multiple commits
+
+ - extract your patches and send to the D-Bus mailing list for
+   review or post them to the D-Bus Bugzilla, attaching them to a bug
+   report. To extract the patches, execute:
+     git format-patch origin/master
+
+ - once your code has been reviewed, you may push it to the Git
+   server:
+     git push origin my-branch:remote
+   OR
+     git push origin dbus-X.Y
+   OR
+     git push origin master
+   (consult the Git manual to know which command applies)
+
+ - (Optional) if you've not worked on "master", merge your changes to
+   that branch. If you've worked on an earlier branch than the current
+   stable, merge your changes upwards towards the stable branch, then
+   from there into "master".
+
+    . execute: git checkout master
+    . ensure that you have the latest "master" from the server, update
+      if you don't
+    . execute: git merge dbus-X.Y
+    . if you have any conflicts, resolve them, git add the conflicted
+      files and then git commit
+    . push the "master" branch to the server as well
+
+  Executing this merge is recommended, but not necessary for all
+  changes. You should do this step if your bugfix is critical for the
+  development in "master", or if you suspect that conflicts will arise
+  (you're usually the best person to resolve conflicts introduced by
+  your own code), or if it has been too long since the last merge.
+
+
+Making a release
+===
+
+To make a release of D-Bus, do the following:
+
+ - check out a fresh copy from Git
+
+ - verify that the libtool versioning/library soname is 
+   changed if it needs to be, or not changed if not
+
+ - update the file NEWS based on the git history
+
+ - verify that the version number of dbus-specification.xml is
+   changed if it needs to be; if changes have been made, update the
+   release date in that file
+
+ - update the AUTHORS file with "make update-authors" if necessary
+
+ - the version number should have major.minor.micro, even
+   if micro is 0, i.e. "1.0.0" and "1.2.0" not "1.0"/"1.2"; the micro
+   version should be even for releases, and odd for intermediate snapshots
+
+ - "make distcheck" (DO NOT just "make dist" - pass the check!)
+
+ - if make distcheck fails, fix it.
+
+ - once distcheck succeeds, "git commit -a".  This is the version
+   of the tree that corresponds exactly to the released tarball.
+
+ - tag the tree with "git tag -s -m 'Released X.Y.Z' dbus-X.Y.Z"
+   where X.Y.Z is the version of the release.  If you can't sign
+   then simply created an unsigned annotated tag:
+   "git tag -a -m 'Released X.Y.Z' dbus-X.Y.Z".
+
+ - bump the version number up in configure.ac (so the micro version is odd),
+   and commit it.  Make sure you do this *after* tagging the previous
+   release! The idea is that git has a newer version number
+   than anything released. Similarly, bump the version number of
+   dbus-specification.xml and set the release date to "(not finalized)".
+
+ - merge the branch you've released to the chronologically-later
+   branch (usually "master"). You'll probably have to fix a merge
+   conflict in configure.ac (the version number).
+
+ - push your changes and the tag to the central repository with
+     git push origin master dbus-X.Y dbus-X.Y.Z
+
+ - scp your tarball to freedesktop.org server and copy it to
+   dbus.freedesktop.org:/srv/dbus.freedesktop.org/www/releases/dbus/dbus-X.Y.Z.tar.gz.
+   This should be possible if you're in group "dbus"
+
+ - Update the online documentation with `make -C doc maintainer-upload-docs`.
+
+ - update the wiki page http://www.freedesktop.org/Software/dbus by
+   adding the new release under the Download heading. Then, cut the
+   link and changelog for the previous that was there.
+
+ - update the wiki page
+   http://www.freedesktop.org/Software/DbusReleaseArchive pasting the
+   previous release. Note that bullet points for each of the changelog
+   items must be indented three more spaces to conform to the
+   formatting of the other releases there.
+  
+ - post to dbus@lists.freedesktop.org announcing the release.
+ 
+
+Making a ".0" stable release
+===
+
+We create a branch for each stable release. The branch name should be
+dbus-X.Y which is a branch that has releases versioned X.Y.Z;
+changes on a stable branch should be limited to significant bug fixes.
+
+Because we won't make minor changes like keeping up with the latest
+deprecations on a stable branch, stable branches should turn off the
+gcc warning for deprecated declarations (e.g. see commit 4ebb275ab7).
+
+Be extra-careful not to merge master (or any branch based on master) into a
+stable branch.
+
+To branch:
+  git branch dbus-X.Y
+and upload the branch tag to the server:
+  git push origin dbus-X.Y
+
+To develop in this branch:
+  git checkout dbus-X.Y
+
+Environment variables
+===
+
+These are the environment variables that are used by the D-Bus client library
+
+DBUS_VERBOSE=1
+Turns on printing verbose messages. This only works if D-Bus has been
+compiled with --enable-verbose-mode
+
+DBUS_MALLOC_FAIL_NTH=n
+Can be set to a number, causing every nth call to dbus_alloc or
+dbus_realloc to fail. This only works if D-Bus has been compiled with
+--enable-tests.
+
+DBUS_MALLOC_FAIL_GREATER_THAN=n
+Can be set to a number, causing every call to dbus_alloc or
+dbus_realloc to fail if the number of bytes to be allocated is greater
+than the specified number. This only works if D-Bus has been compiled with
+--enable-tests.
+
+DBUS_TEST_MALLOC_FAILURES=n
+Many of the D-Bus tests will run over and over, once for each malloc
+involved in the test. Each run will fail a different malloc, plus some
+number of mallocs following that malloc (because a fair number of bugs
+only happen if two or more mallocs fail in a row, e.g. error recovery
+that itself involves malloc).  This env variable sets the number of
+mallocs to fail.
+Here's why you care: If set to 0, then the malloc checking is skipped,
+which makes the test suite a heck of a lot faster. Just run with this
+env variable unset before you commit.
+
+Tests
+===
+
+These are the test programs that are built if dbus is compiled using
+--enable-tests.
+
+dbus/dbus-test
+This is the main unit test program that tests all aspects of the D-Bus
+client library.
+
+dbus/bus-test
+This it the unit test program for the message bus.
+
+test/break-loader
+A test that tries to break the message loader by passing it randomly
+created invalid messages.
+
+test/name-test/*
+This is a suite of programs which are run with a temporary session bus.
+If your test involves multiple processes communicating, your best bet
+is to add a test in here.
+
+"make check" runs all the deterministic test programs (i.e. not break-loader).
+
+"make lcov-check" is available if you configure with --enable-compiler-coverage
+and gives a complete report on test suite coverage.
+
+Patches
+===
+
+Please file them at http://bugzilla.freedesktop.org under component
+dbus, and also post to the mailing list for discussion.  The commit
+rules are:
+
+ - for fixes that don't affect API or protocol, they can be committed
+   if any one qualified reviewer other than patch author
+   reviews and approves
+
+ - for fixes that do affect API or protocol, two people
+   in the reviewer group have to review and approve the commit, and 
+   posting to the list is definitely mandatory
+
+ - if there's a live unresolved controversy about a change,
+   don't commit it while the argument is still raging.
+
+ - at their discretion, members of the reviewer group may also commit
+   branches/patches under these conditions:
+
+   - the branch does not add or change API, ABI or wire-protocol
+
+   - the branch solves a known problem and is covered by the regression tests
+
+   - there are no objections from the rest of the review group within
+     a week of the patches being attached to Bugzilla
+
+   - the committer gets a positive review on Bugzilla from someone they
+     consider qualified to review the change (e.g. a colleague with D-Bus
+     experience; not necessarily a member of the reviewer group)
+
+ - regardless of reviews, to commit a patch:
+    - make check must pass
+    - the test suite must be extended to cover the new code
+      as much as reasonably feasible (see Tests above)
+    - the patch has to follow the portability, security, and 
+      style guidelines
+    - the patch should as much as reasonable do one thing, 
+      not many unrelated changes
+   No reviewer should approve a patch without these attributes, and
+   failure on these points is grounds for reverting the patch.
+
+The reviewer group that can approve patches:
+
+Havoc Pennington <hp@pobox.net>
+Michael Meeks <michael.meeks@novell.com>
+Alexander Larsson  <alexl@redhat.com>
+Zack Rusin <zack@kde.org>
+Joe Shaw <joe@assbarn.com>
+Mikael Hallendal <micke@imendio.com>
+Richard Hult <richard@imendio.com>
+Owen Fraser-Green <owen@discobabe.net>
+Olivier Andrieu <oliv__a@users.sourceforge.net>
+Colin Walters <walters@verbum.org>
+Thiago Macieira <thiago@kde.org>
+John Palmieri <johnp@redhat.com>
+Scott James Remnant <scott@netsplit.com>
+Will Thompson <will.thompson@collabora.co.uk>
+Simon McVittie <simon.mcvittie@collabora.co.uk>
+David Zeuthen <davidz@redhat.com>
diff --git a/dbus/INSTALL b/dbus/INSTALL
new file mode 100644
index 0000000..e182f98
--- /dev/null
+++ b/dbus/INSTALL
@@ -0,0 +1,252 @@
+           DBus Installation
+           =================
+
+Quick start
+===========
+
+DBus could be build with GNU AutoTools or with cmake for its build system,
+thus the basic install procedure can be summarized as:
+
+with autotools:
+
+    ./configure --prefix=/usr
+    make
+    su make install
+
+The configure script will automatically determine whether to try and
+build bindings for GLib, Qt, Qt3, Python and Mono based on what tools
+are installed on the host system. The default build behaviour can be
+overridden using the --enable-XXX/--disable-XXX arguments to configure.
+A typical scenario in which it is desirable to override automatic
+detection, is during packaging of binary builds, where a predictable
+dependancy chain is required. For more details on GNU AutoTools
+installation, consult the generic instructions later in this document
+
+with cmake:
+    mkdir dbus-build-dir
+    cd dbus-build-dir
+    cmake -G <makefile-generator-name> [-D<option>] <dbus-src-root>/cmake
+    make
+    make install
+
+cmake will automatically determine whether to build some features
+based on what tools and/or libraries are installed on the host system. 
+The default build behaviour can be overridden using the 
+-DENABLE_<XXX> arguments to cmake.
+A typical scenario in which it is desirable to override automatic
+detection, is during packaging of binary builds, where a predictable
+dependancy chain is required. For more details on cmake installation, 
+consult http://www.cmake.org/cmake/help/help.html. 
+
+External software dependancies
+==============================
+
+The only fundamental requirement to build DBus is an XML parser,
+however, there are a number of other software packages which (if
+present) will enhance functionality.
+
+Core library
+------------
+
+ Requisite:
+
+  - Gettext
+  - expat or libxml-2
+
+ NB, expat is the recommended XML parser because it has more robust
+ handling of OOM conditions.
+
+ Optional:
+
+  - libselinux           (for SELinux integration)
+  - dnotify              (for automatic service file reload)
+  - doxygen              (for API documentation)
+  - xmlto or meinproc4   (for Spec & other XML documentation)
+
+====================================================================
+
+The rest of this document contains the generic GNU AutoTools install
+insructions....
+
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   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').
+
+   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'.
+
+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.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+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
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as 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.
+
+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'.
+
+   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.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' 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.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+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:
+     CPU-COMPANY-SYSTEM
+
+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.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--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.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/dbus/MODULE_LICENSE_AFL_AND_GPL b/dbus/MODULE_LICENSE_AFL_AND_GPL
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dbus/MODULE_LICENSE_AFL_AND_GPL
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
new file mode 100644
index 0000000..10b9670
--- /dev/null
+++ b/dbus/Makefile.am
@@ -0,0 +1,33 @@
+SUBDIRS=dbus bus tools test doc
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = dbus-1.pc
+
+DISTCLEANFILES = 		\
+	dbus-1.pc
+
+EXTRA_DIST =			\
+	HACKING			\
+	dbus-1.pc.in		\
+	cleanup-man-pages.sh    \
+        ChangeLog.pre-1-0       \
+        NEWS.pre-1-0            \
+	ChangeLog.pre-1-2       \
+        NEWS.pre-1-2		\
+	README.win		\
+	README.wince		\
+	README.cygwin		\
+	README.launchd		\
+	cmake
+
+all-local: Doxyfile
+
+update-authors:
+	git shortlog -s -e | cut -c 8- | sort > AUTHORS
+
+DISTCHECK_CONFIGURE_FLAGS = \
+	--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
+
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+include tools/lcov.am
diff --git a/dbus/Makefile.cvs b/dbus/Makefile.cvs
new file mode 100644
index 0000000..d44e565
--- /dev/null
+++ b/dbus/Makefile.cvs
@@ -0,0 +1,8 @@
+## -*- makefile -*-
+
+configure:
+	./autogen.sh --no-configure
+
+.SILENT: 
+
+.PHONY: configure
diff --git a/dbus/NEWS b/dbus/NEWS
new file mode 100644
index 0000000..02fa145
--- /dev/null
+++ b/dbus/NEWS
@@ -0,0 +1,598 @@
+D-Bus 1.6.8 (2012-09-28)
+==
+
+The "Fix one thing, break another" release.
+
+• Follow up to CVE-2012-3524: The additional hardening
+  work to use __secure_getenv() as a followup to bug #52202
+  broke certain configurations of gnome-keyring.  Given
+  the difficulty of making this work without extensive
+  changes to gnome-keyring, use of __secure_getenv() is
+  deferred.
+
+D-Bus 1.6.6 (2012-09-28)
+==
+
+The "Clear the environment in your setuid binaries, please" release.
+
+• CVE-2012-3524: Don't access environment variables (fd.o #52202)
+  Thanks to work and input from Colin Walters, Simon McVittie,
+  Geoffrey Thomas, and others.
+• Unix-specific:
+  · Fix compilation on Solaris (fd.o #53286, Jonathan Perkin)
+  · Work around interdependent headers on OpenBSD by including sys/types.h
+    before each use of sys/socket.h (fd.o #54418, Brad Smith)
+
+D-Bus 1.6.4 (2012-07-18)
+==
+
+• Detect that users are "at the console" correctly when configured with
+  a non-default path such as --enable-console-auth-dir=/run/console
+  (fd.o #51521, Dave Reisner)
+
+• Remove an incorrect assertion from DBusTransport (fd.o #51657,
+  Simon McVittie)
+
+• Make --enable-developer default to "no" (regression in 1.6.2;
+  fd.o #51657, Simon McVittie)
+
+• Windows-specific:
+  · Launch dbus-daemon correctly if its path contains a space
+    (fd.o #49450, Wolfgang Baron)
+
+D-Bus 1.6.2 (2012-06-27)
+==
+
+The "Ice Cabbage" release.
+
+• Change how we create /var/lib/dbus so it works under Automake >= 1.11.4
+  (fd.o #51406, Simon McVittie)
+
+• Don't return from dbus_pending_call_set_notify with a lock held on OOM
+  (fd.o #51032, Simon McVittie)
+
+• Disconnect "developer mode" (assertions, verbose mode etc.) from
+  Automake maintainer mode. D-Bus developers should now configure with
+  --enable-developer. Automake maintainer mode is now on by default;
+  distributions can disable it with --disable-maintainer-mode.
+  (fd.o #34671, Simon McVittie)
+
+• Automatically define DBUS_STATIC_BUILD in static-only Autotools builds,
+  fixing linking when targeting Windows (fd.o #33973; william, Simon McVittie)
+
+• Unix-specific:
+  · Check for libpthread under CMake on Unix (fd.o #47237, Simon McVittie)
+
+D-Bus 1.6.0 (2012-06-05)
+==
+
+The “soul of this machine has improved” release.
+
+This version starts a new stable branch of D-Bus: only bug fixes will
+be accepted into 1.6.x. Other changes will now go to the 1.7.x branch.
+
+Summary of changes since 1.4.x:
+
+• New requirements
+  · PTHREAD_MUTEX_RECURSIVE on Unix
+  · compiler support for 64-bit integers (int64_t or equivalent)
+
+• D-Bus Specification v0.19
+
+• New dbus-daemon features
+  · <allow own_prefix="com.example.Service"/> rules allow the service to
+    own names like com.example.Service.Instance3
+  · optional systemd integration when checking at_console policies
+  · --nopidfile option, mainly for use by systemd
+  · path_namespace and arg0namespace may appear in match rules
+  · eavesdropping is disabled unless the match rule contains eavesdrop=true
+
+• New public API
+  · functions to validate various string types (dbus_validate_path() etc.)
+  · dbus_type_is_valid()
+  · DBusBasicValue, a union of every basic type
+
+• Bug fixes
+  · removed an unsafe reimplementation of recursive mutexes
+  · dbus-daemon no longer busy-loops if it has far too many file descriptors
+  · dbus-daemon.exe --print-address works on Windows
+  · all the other bug fixes from 1.4.20
+
+• Other major implementation changes
+  · on Linux, dbus-daemon uses epoll if supported, for better scalability
+  · dbus_threads_init() ignores its argument and behaves like
+    dbus_threads_init_default() instead
+  · removed the per-connection link cache, improving dbus-daemon performance
+
+• Developer features
+  · optional Valgrind instrumentation (--with-valgrind)
+  · optional Stats interface on the dbus-daemon (--enable-stats)
+  · optionally abort whenever malloc() fails (--enable-embedded-tests
+    and export DBUS_MALLOC_CANNOT_FAIL=1)
+
+Changes since 1.5.12:
+
+• Be more careful about monotonic time vs. real time, fixing DBUS_COOKIE_SHA1
+  spec-compliance (fd.o #48580, David Zeuthen)
+
+• Don't use install(1) within the source/build trees, fixing the build as
+  non-root when using OpenBSD install(1) (fd.o #48217, Antoine Jacoutot)
+
+• Add missing commas in some tcp and nonce-tcp addresses, and remove
+  an unused duplicate copy of the nonce-tcp transport in Windows builds
+  (fd.o #45896, Simon McVittie)
+
+D-Bus 1.5.12 (2012-03-27)
+==
+
+The “Big Book of Science” release.
+
+• Add public API to validate various string types:
+  dbus_validate_path(), dbus_validate_interface(), dbus_validate_member(),
+  dbus_validate_error_name(), dbus_validate_bus_name(), dbus_validate_utf8()
+  (fd.o #39549, Simon McVittie)
+
+• Turn DBusBasicValue into public API so bindings don't need to invent their
+  own "union of everything" type (fd.o #11191, Simon McVittie)
+
+• Enumerate data files included in the build rather than using find(1)
+  (fd.o #33840, Simon McVittie)
+
+• Add support for policy rules like <allow own_prefix="com.example.Service"/>
+  in dbus-daemon (fd.o #46273, Alban Crequy)
+
+• Windows-specific:
+  · make dbus-daemon.exe --print-address (and --print-pid) work again
+    on Win32, but not on WinCE (fd.o #46049, Simon McVittie)
+  · fix duplicate case value when compiling against mingw-w64
+    (fd.o #47321, Andoni Morales Alastruey)
+
+D-Bus 1.5.10 (2012-02-21)
+==
+
+The "fire in Delerium" release.
+
+On Unix platforms, PTHREAD_MUTEX_RECURSIVE (as specified in POSIX 2008 Base
+and SUSv2) is now required.
+
+• D-Bus Specification 0.19:
+  · Formally define unique connection names and well-known bus names,
+    and document best practices for interface, bus, member and error names,
+    and object paths (fd.o #37095, Simon McVittie)
+  · Document the search path for session and system services on Unix, and
+    where they should be installed by build systems (fd.o #21620, fd.o #35306;
+    Simon McVittie)
+  · Document the systemd transport (fd.o #35232, Lennart Poettering)
+
+• Make dbus_threads_init() use the same built-in threading implementation
+  as dbus_threads_init_default(); the user-specified primitives that it
+  takes as a parameter are now ignored (fd.o #43744, Simon McVittie)
+
+• Allow all configured auth mechanisms, not just one (fd.o #45106,
+  Pavel Strashkin)
+
+• Improve cmake build system (Ralf Habacker):
+  · simplify XML parser dependencies (fd.o #41027)
+  · generate build timestamp (fd.o #41029)
+  · only create batch files on Windows
+  · fix option and cache syntax
+  · add help-options target
+  · share dbus-arch-deps.h.in with autotools rather than having our
+    own version (fd.o #41033)
+
+• Build tests successfully with older GLib, as found in e.g. Debian 6
+  (fd.o #41219, Simon McVittie)
+
+• Avoid use of deprecated GThread API (fd.o #44413, Martin Pitt)
+
+• Build documentation correctly if man2html doesn't support filenames on
+  its command-line (fd.o #43875, Jack Nagel)
+
+• Improve test coverage. To get even more coverage, run the tests with
+  DBUS_TEST_SLOW=1 (fd.o #38285, #42811; Simon McVittie)
+
+• Reduce the size of the shared library by moving functionality only used
+  by dbus-daemon, tests etc. into their internal library and deleting
+  unused code (fd.o #34976, #39759; Simon McVittie)
+
+• Add dbus-daemon --nopidfile option, overriding the configuration, for
+  setups where the default configuration must include <pidfile/> to avoid
+  breaking traditional init, but the pid file is in fact unnecessary; use
+  it under systemd to improve startup time a bit (fd.o #45520,
+  Lennart Poettering)
+
+• Optionally (if configured --with-valgrind) add instrumentation to debug
+  libdbus and associated tools more meaningfully under Valgrind
+  (fd.o #37286, Simon McVittie)
+
+• Improve the dbus-send(1) man page (fd.o #14005, Simon McVittie)
+
+• Make dbus-protocol.h compatible with C++11 (fd.o #46147, Marc Mutz)
+
+• If tests are enabled and DBUS_MALLOC_CANNOT_FAIL is set in the environment,
+  abort on failure to malloc() (like GLib does), to turn runaway memory leaks
+  into a debuggable core-dump if a resource limit is applied (fd.o #41048,
+  Simon McVittie)
+
+• Don't crash if realloc() returns NULL in a debug build (fd.o #41048,
+  Simon McVittie)
+
+• Unix-specific:
+  · Replace our broken reimplementation of recursive mutexes, which has
+    been broken since 2006, with an ordinary pthreads recursive mutex
+    (fd.o #43744; Sigmund Augdal, Simon McVittie)
+  · Use epoll(7) for a more efficient main loop in Linux; equivalent patches
+    welcomed for other OSs' equivalents like kqueue, /dev/poll, or Solaris
+    event ports (fd.o #33337; Simon McVittie, Ralf Habacker)
+  · When running under systemd, use it instead of ConsoleKit to check
+    whether to apply at_console policies (fd.o #39609, Lennart Poettering)
+  · Avoid a highly unlikely fd leak (fd.o #29881, Simon McVittie)
+  · Don't close invalid fd -1 if getaddrinfo fails (fd.o #37258, eXeC001er)
+  · Don't touch ~/.dbus and ~/.dbus-keyrings when running 'make installcheck'
+    (fd.o #41218, Simon McVittie)
+  · Stop pretending we respect XDG_DATA_DIRS for system services: the launch
+    helper doesn't obey environment variables to avoid privilege escalation
+    attacks, so make the system bus follow the same rules
+    (fd.o #21620, Simon McVittie)
+
+• Windows-specific:
+  · Find the dbus-daemon executable next to the shared library (fd.o #41558;
+    Jesper Dam, Ralf Habacker)
+  · Remove the faulty implementation of _dbus_condvar_wake_all (fd.o #44609,
+    Simon McVittie)
+
+D-Bus 1.5.8 (2011-09-21)
+==
+
+The "cross-metering" release.
+
+In addition to dead code removal and refactoring, this release contains all
+of the bugfixes from 1.4.16.
+
+• Clean up dead code, and make more warnings fatal in development builds
+  (fd.o #39231, fd.o #41012; Simon McVittie)
+
+• If full test coverage is requested via --enable-tests, strictly require
+  Python, pygobject and dbus-python, which are required by some tests; if not,
+  and Python is missing, skip those tests rather than failing
+  (fd.o #37847, Simon McVittie)
+
+• When using cmake, provide the same version-info API in the installed headers
+  as for autotools (DBUS_VERSION, etc.) (fd.o #40905, Ralf Habacker)
+
+• Add a regression test for fd.o #38005 (fd.o #39836, Simon McVittie)
+
+• Make "NOCONFIGURE=1 ./autogen.sh" not run configure (Colin Walters)
+
+• Add _DBUS_STATIC_ASSERT and use it to check invariants (fd.o #39636,
+  Simon McVittie)
+
+• Fix duplicates in authors list (Ralf Habacker)
+
+• Fix broken links from dbus-tutorial.html if $(htmldir) != $(docdir)
+  (fd.o #39879, Chris Mayo)
+
+• Fix a small memory leak, and a failure to report errors, when updating
+  a service file entry for activation (fd.o #39230, Simon McVittie)
+
+• Unix-specific:
+  · Clean up (non-abstract) Unix sockets on bus daemon exit (fd.o #38656;
+    Brian Cameron, Simon McVittie)
+  · On systems that use libcap-ng but not systemd, drop supplemental groups
+    when switching to the daemon user (Red Hat #726953, Steve Grubb)
+  · Make the cmake build work again on GNU platforms (fd.o #29228,
+    Simon McVittie)
+  · Fix compilation on non-C99 systems that have inttypes.h but not stdint.h,
+    like Solaris (fd.o #40313, Dagobert Michelsen)
+  · Define CMSG_ALIGN, CMSG_LEN, CMSG_SPACE on Solaris < 10
+    (fd.o #40235, Simon McVittie)
+  · Cope with Unixes that don't have LOG_PERROR, like Solaris 10
+    (fd.o #39987, Simon McVittie)
+  · Cope with platforms whose vsnprintf violates both POSIX and C99, like
+    Tru64, IRIX and HP-UX (fd.o #11668, Simon McVittie)
+
+• Windows-specific:
+  · Fix compilation on MSVC, which doesn't understand "inline" with its
+    C99 meaning (fd.o #40000; Ralf Habacker, Simon McVittie)
+  · Fix misuse of GPid in test/dbus-daemon.c (fd.o #40003, Simon McVittie)
+  · Fix cross-compilation to Windows with Automake (fd.o #40003, Simon McVittie)
+
+D-Bus 1.5.6 (2011-07-29)
+==
+
+The "weird, gravy-like aftertaste" release.
+
+In addition to new features and refactoring, this release contains all of the
+bugfixes from 1.4.14.
+
+Potentially incompatible (Bustle and similar debugging tools will need
+changes to work as intended):
+
+• Do not allow match rules to "eavesdrop" (receive messages intended for a
+  different recipient) by mistake: eavesdroppers must now opt-in to this
+  behaviour by putting "eavesdrop='true'" in the match rule, which will
+  not have any practical effect on buses where eavesdropping is not allowed
+  (fd.o #37890, Cosimo Alfarano)
+
+Other changes:
+
+• D-Bus Specification version 0.18 (fd.o #37890, fd.o #39450, fd.o #38252;
+  Cosimo Alfarano, Simon McVittie)
+  · add the "eavesdrop" keyword to match rules
+  · define eavesdropping, unicast messages and broadcast messages
+  · stop claiming that match rules are needed to match unicast messages to you
+  · promote the type system to be a top-level section
+
+• Use DBUS_ERROR_OBJECT_PATH_IN_USE if dbus_connection_try_register_object_path
+  or dbus_connection_try_register_fallback fails, not ...ADDRESS_IN_USE,
+  and simplify object-path registration (fd.o #38874, Jiří Klimeš)
+
+• Consistently use atomic operations on everything that is ever manipulated
+  via atomic ops, as was done for changes to DBusConnection's refcount in
+  1.4.12 (fd.o #38005, Simon McVittie)
+
+• Fix a file descriptor leak when connecting to a TCP socket (fd.o #37258,
+  Simon McVittie)
+
+• Make "make check" in a clean tree work, by not running tests until
+  test data has been set up (fd.o #34405, Simon McVittie)
+
+• The dbus-daemon no longer busy-loops if it has a very large number of file
+  descriptors (fd.o #23194, Simon McVittie)
+
+• Refactor message flow through dispatching to avoid locking violations if
+  the bus daemon's message limit is hit; remove the per-connection link cache,
+  which was meant to improve performance, but now reduces it (fd.o #34393,
+  Simon McVittie)
+
+• Some cmake fixes (Ralf Habacker)
+
+• Remove dead code, mainly from DBusString (fd.o #38570, fd.o #39610;
+  Simon McVittie, Lennart Poettering)
+
+• Stop storing two extra byte order indicators in each D-Bus message
+  (fd.o #38287, Simon McVittie)
+
+• Add an optional Stats interface which can be used to get statistics from
+  a running dbus-daemon if enabled at configure time with --enable-stats
+  (fd.o #34040, Simon McVittie)
+
+• Fix various typos (fd.o #27227, fd.o #38284; Sascha Silbe, Simon McVittie)
+
+• Documentation (fd.o #36156, Simon McVittie):
+  · let xsltproc be overridden as usual: ./configure XSLTPROC=myxsltproc
+  · install more documentation automatically, including man2html output
+  · put dbus.devhelp in the right place (it must go in ${htmldir})
+
+• Unix-specific:
+  · look for system services in /lib/dbus-1/system-services in addition to all
+    the other well-known locations; note that this should always be /lib,
+    even on platforms where shared libraries on the root FS would go in /lib64,
+    /lib/x86_64-linux-gnu or similar (fd.o #35229, Lennart Poettering)
+  · opt-in to fd passing on Solaris (fd.o #33465, Simon McVittie)
+
+• Windows-specific (Ralf Habacker):
+  · fix use of a mutex for autolaunch server detection
+  · don't crash on malloc failure in _dbus_printf_string_upper_bound
+
+D-Bus 1.5.4 (2011-06-10)
+==
+
+Security (local denial of service):
+
+• Byte-swap foreign-endian messages correctly, preventing a long-standing
+  local DoS if foreign-endian messages are relayed through the dbus-daemon
+  (backporters: this is git commit c3223ba6c401ba81df1305851312a47c485e6cd7)
+  (CVE-2011-2200, fd.o #38120, Debian #629938; Simon McVittie)
+
+New things:
+
+• The constant to use for an infinite timeout now has a name,
+  DBUS_TIMEOUT_INFINITE. It is numerically equivalent to 0x7fffffff (INT32_MAX)
+  which can be used for source compatibility with older versions of libdbus.
+
+• If GLib and DBus-GLib are already installed, more tests will be built,
+  providing better coverage. The new tests can also be installed via
+      ./configure --enable-installed-tests
+  for system integration testing, if required. (fd.o #34570, Simon McVittie)
+
+Changes:
+
+• Consistently use atomic operations for the DBusConnection's refcount,
+  fixing potential threading problems (fd.o #38005, Simon McVittie)
+
+• Don't use -Wl,--gc-sections by default: in practice the size decrease is
+  small (300KiB on x86-64) and it frequently doesn't work in unusual
+  toolchains. To optimize for minimum installed size, you should benchmark
+  various possibilities for CFLAGS and LDFLAGS, and set the best flags for
+  your particular toolchain at configure time. (fd.o #33466, Simon McVittie)
+
+• Use #!/bin/sh for run-with-tmp-session-bus.sh, making it work on *BSD
+  (fd.o #35880, Timothy Redaelli)
+
+• Use ln -fs to set up dbus for systemd, which should fix reinstallation
+  when not using a DESTDIR (fd.o #37870, Simon McVittie)
+
+• Windows-specific changes:
+  · don't try to build dbus-daemon-launch-helper (fd.o #37838, Mark Brand)
+
+D-Bus 1.5.2 (2011-06-01)
+==
+
+The "Boar Hunter" release.
+
+Notes for distributors:
+
+  This version of D-Bus no longer uses -fPIE by default. Distributions wishing
+  to harden the dbus-daemon and dbus-launch-helper can re-enable this if their
+  toolchain supports it reliably, via something like:
+
+    ./configure CFLAGS=-fPIE LDFLAGS="-pie -Wl,-z,relro"
+
+  or by using distribution-specific wrappers such as Debian's hardening-wrapper.
+
+Changes:
+
+  • D-Bus Specification v0.17
+    · Reserve the extra characters used in signatures by GVariant
+      (fd.o #34529, Simon McVittie)
+    · Define the ObjectManager interface (fd.o #34869, David Zeuthen)
+  • Don't force -fPIE: distributions and libtool know better than we do whether
+    it's desirable (fd.o #16621, fd.o #27215; Simon McVittie)
+  • Allow --disable-gc-sections, in case your toolchain offers the
+    -ffunction-sections, -fdata-sections and -Wl,--gc-sections options
+    but they're broken, as seen on Solaris (fd.o #33466, Simon McVittie)
+  • Install dbus-daemon and dbus-daemon-launch-helper in a more normal way
+    (fd.o #14512; Simon McVittie, loosely based on a patch from Luca Barbato)
+  • Ensure that maintainers upload documentation with the right permissions
+    (fd.o #36130, Simon McVittie)
+  • Don't force users of libdbus to be linked against -lpthread, -lrt
+    (fd.o #32827, Simon McVittie)
+  • Log system-bus activation information to syslog (fd.o #35705,
+    Colin Walters)
+  • Log messages dropped due to quotas to syslog (fd.o #35358,
+    Simon McVittie)
+  • Make the nonce-tcp transport work on Unix (fd.o #34569, Simon McVittie)
+  • On Unix, if /var/lib/dbus/machine-id cannot be read, try /etc/machine-id
+    (fd.o #35228, Lennart Poettering)
+  • In the regression tests, don't report fds as "leaked" if they were open
+    on startup (fd.o #35173, Simon McVittie)
+  • Make dbus-monitor bail out if asked to monitor more than one bus,
+    rather than silently using the last one (fd.o #26548, Will Thompson)
+  • Clarify documentation (fd.o #35182, Simon McVittie)
+  • Clean up minor dead code and some incorrect error handling
+    (fd.o #33128, fd.o #29881; Simon McVittie)
+  • Check that compiler options are supported before using them (fd.o #19681,
+    Simon McVittie)
+  • Windows:
+    • Remove obsolete workaround for winioctl.h (fd.o #35083, Ralf Habacker)
+
+D-Bus 1.5.0 (2011-04-11)
+==
+
+The "you never know when you need to tow something from your giant
+flying shark" release.
+
+  • D-Bus Specification v0.16
+    · Add support for path_namespace and arg0namespace in match rules
+      (fd.o #24317, #34870; Will Thompson, David Zeuthen, Simon McVittie)
+    · Make argNpath support object paths, not just object-path-like strings,
+      and document it better (fd.o #31818, Will Thompson)
+  • Let the bus daemon implement more than one interface (fd.o #33757,
+    Simon McVittie)
+  • Optimize _dbus_string_replace_len to reduce waste (fd.o #21261,
+    Roberto Guido)
+  • Require user intervention to compile with missing 64-bit support
+    (fd.o #35114, Simon McVittie)
+  • Add dbus_type_is_valid as public API (fd.o #20496, Simon McVittie)
+  • Raise UnknownObject instead of UnknownMethod for calls to methods on
+    paths that are not part of the object tree, and UnknownInterface for calls
+    to unknown interfaces in the bus daemon (fd.o #34527, Lennart Poettering)
+
+D-Bus 1.4.8 (2011-04-08)
+==
+
+The "It's like the beginning of a lobster" release.
+
+  • Rename configure.in to configure.ac, and update it to modern conventions
+    (fd.o #32245; Javier Jardón, Simon McVittie)
+  • Correctly give XDG_DATA_HOME priority over XDG_DATA_DIRS (fd.o #34496,
+    Anders Kaseorg)
+  • Prevent X11 autolaunching if $DISPLAY is unset or empty, and add
+    --disable-x11-autolaunch configure option to prevent it altogether
+    in embedded environments (fd.o #19997, NB#219964; Simon McVittie)
+  • Install the documentation, and an index for Devhelp (fd.o #13495,
+    Debian #454142; Simon McVittie, Matthias Clasen)
+  • If checks are not disabled, check validity of string-like types and
+    booleans when sending them (fd.o #16338, NB#223152; Simon McVittie)
+  • Add UnknownObject, UnknownInterface, UnknownProperty and PropertyReadOnly
+    errors to dbus-shared.h (fd.o #34527, Lennart Poettering)
+  • Break up a huge conditional in config-parser so gcov can produce coverage
+    data (fd.o #10887, Simon McVittie)
+  • List which parts of the Desktop Entry specification are applicable to
+    .service files (fd.o #19159, Sven Herzberg)
+  • Don't suppress service activation if two services have the same Exec=
+    (fd.o #35750, Colin Walters)
+  • Windows:
+    · Avoid the name ELEMENT_TYPE due to namespace-pollution from winioctl.h
+      (Andre Heinecke)
+    · Include _dbus_path_is_absolute in libdbus on Windows, fixing compilation
+      (fd.o #32805, Mark Brand)
+
+D-Bus 1.4.6 (2010-02-17)
+==
+
+The "1, 2, miss a few, 99, 100" release.
+
+  • Remove unfinished changes intended to support GTest-based tests,
+    which were mistakenly included in 1.4.4
+
+D-Bus 1.4.4 (2010-02-17)
+==
+
+  • Switch back to using even micro versions for stable releases; 1.4.1
+    should have been called 1.4.2, so skip that version number
+  • Don't leave bad file descriptors being watched when spawning processes,
+    which could result in a busy-loop (fd.o #32992, NB#200248; possibly
+    also LP#656134, LP#680444, LP#713157)
+  • Check for MSG_NOSIGNAL correctly
+  • Fix failure to detect abstract socket support (fd.o #29895)
+  • Make _dbus_system_logv actually exit with DBUS_SYSTEM_LOG_FATAL
+    (fd.o #32262, NB#180486)
+  • Improve some error code paths (fd.o #29981, fd.o #32264, fd.o #32262,
+    fd.o #33128, fd.o #33277, fd.o #33126, NB#180486)
+  • Avoid possible symlink attacks in /tmp during compilation (fd.o #32854)
+  • Tidy up dead code (fd.o #25306, fd.o #33128, fd.o #34292, NB#180486)
+  • Improve gcc malloc annotations (fd.o #32710)
+  • If the system bus is launched via systemd, protect it from the OOM killer
+  • Documentation improvements (fd.o #11190)
+  • Avoid readdir_r, which is difficult to use correctly (fd.o #8284,
+    fd.o #15922, LP#241619)
+  • Cope with invalid files in session.d, system.d (fd.o #19186,
+    Debian #230231)
+  • Don't distribute generated files that embed our builddir (fd.o #30285,
+    fd.o #34292)
+  • Raise the system bus's fd limit to be sufficient for its configuration
+    (fd.o #33474, LP#381063)
+  • Fix syslog string processing
+  • Ignore -Waddress
+  • Remove broken gcov parsing code and --enable-gcov, and replace them
+    with lcov HTML reports and --enable-compiler-coverage (fd.o #10887)
+  • Windows:
+    · avoid live-lock in Windows CE due to unfair condition variables
+  • OpenBSD:
+    · support credentials-passing (fd.o #32542)
+  • Solaris:
+    · opt-in to thread safety (fd.o #33464)
+
+D-Bus 1.4.1 (20 December 2010)
+==
+
+ • Fix for CVE-2010-4352: sending messages with excessively-nested variants can
+   crash the bus. The existing restriction to 64-levels of nesting previously
+   only applied to the static type signature; now it also applies to dynamic
+   nesting using variants. Thanks to Rémi Denis-Courmont for discoving this
+   issue.
+ • OS X portability fixes, including launchd support.
+ • Windows autolaunch improvements.
+ • Various bug fixes.
+
+D-Bus 1.4.0 (6 Sep 2010)
+==
+ - systemd hookup
+
+D-Bus 1.3.1 (23 June 2010)
+==
+ - New standardized PropertiesChanged signal in the properties interface
+ - Various portability fixes, in particular to Windows platforms
+ - Support forking bus services, for compatibility
+
+D-Bus 1.3.0 (29 July 2009)
+==
+ - ability for dbus-send to send to any bus (--address)
+ - file descriptor passing on Unix socket transports
+ - use of GCC atomic intrinsics for better processor support
+   (requires -march=i486 or above for x86 compilation)
+ - thread-safe FD_CLOEXEC setting on recent Linux kernels (2.6.24-27 and up)
+   and glibc (2.9 for pipe2 and 2.10 for accept4)
+ - feature negotiation in the bus daemon
diff --git a/dbus/NEWS.pre-1-0 b/dbus/NEWS.pre-1-0
new file mode 100644
index 0000000..7105bc5
--- /dev/null
+++ b/dbus/NEWS.pre-1-0
@@ -0,0 +1,614 @@
+D-Bus 1.0.0 (08 November 2006)
+==
+- Documents updated with API/ABI garuntees 
+- Added missing patch FreeBSD need to run out of the box
+- dbus-monitor now has a profile mode
+- AUTHORS file updated with names from the ChangeLog
+  Thanks to everyone who helped get us here
+
+D-Bus 1.0 RC 3 (0.95) (02 November 2006)
+==
+- DBUS_API_SUBJECT_TO_CHANGE no longer needs to be defined when building apps
+- ./configure checks now work when cross compiling
+- dbus-uuidgen --ensure is now run in the init script so there is no need to
+  run it in a post script
+- dbus-uuidgen now writes out to /var/lib/dbus to work with systems that do not
+  have a writable /etc. Packages should install and own the /var/lib/dbus 
+  directory
+- recursive locks are now used when dbus_threads_init_default is called
+- standard_session_servicedirs tag added to the session.conf
+  under a normal build this specifies these service directories:
+    /usr/local/share/dbus-1/services
+    /usr/share/dbus-1/services
+    $HOME/.local/share/dbus-1/services
+- fixed crash when a service directory is specified more than once
+- fixed a crash in *BSD when watching config directories for changes
+- fixed Irix build by using dirp->__dd_fd to get the file descriptor
+- cleaned up the LOCAL_CREDS vs CMGCRED credential code so *BSD's don't 
+  crash here anymore
+- dbus_message_iter_get_array_len deprecated
+- cleanup-man-pages.sh added so packagers can clean up Doxygen man page output
+  from 7 to 2 megs
+- large documentation improvements
+- numerous bug fixes
+
+D-Bus 1.0 RC 2 (0.94) (14 October 2006)
+==
+- dbus-uuidgen binary added for future remote machine identification
+  packagers should call dbus-uuidgen --ensure in their post
+- GetMachineId peer method added to the bus API
+- dbus_connection_set_route_peer_messages API added to let the bus send
+  peer messages directly to an app
+- Autolaunch abilities added to dbus-launch with the --autolaunch flag
+  This feature allows libdbus to start a session bus if none can be found
+  This is an internal feature and should not be used by scripts
+  DBUS_SESSION_BUS_ADDRESS is still the correct way to specify a session bus
+- dbus-launch now prints out a simple key value pairs instead of shell scripts
+  if one of the shell flags aren't used
+- support DBUS_BLOCK_ON_ABORT env variable to cause blocking waiting for gdb
+- weak ref are now held for shared connections so the right things happen
+  this fixes some pretty major bugs with the way connections were handled
+- Some refactoring for Windows (doesn't effect Unix)
+- Solaris build fixes
+- MacOSX build fixes
+- Cross compile build fixes.  We now assume getpwnam_r is posix and va_lists
+  can be copied by value since we can't check this in a cross compile.  If
+  this is not true for a particular target is up to the developer to patch.
+- Bug fixing all around
+
+D-Bus 1.0 RC 1 (0.93) (14 September 2006)
+==
+- dbus_threads_init_default added for initalizing threads without the need for
+  bindings
+- Filters are now properly removed
+- dbus_connection_open now holds a hard ref to shared connections
+- We now print out a warning and do nothing when someone tries to close a 
+  shared connection
+- The --introspect switch has been added to the bus for printing out 
+  introspection data without actually running the bus
+- LOCAL_CREDS socket credentials are now supported for systems which 
+  support it such as NetBSD
+- Generalize kqueue support so it works with NetBSD as well as FreeBSD
+- Numerous bug fixes and memory leaks patched
+
+D-Bus 0.92 (18 August 2006)
+==
+- Proper thread locking added to pending calls
+- Threading semantics changed from init early to init before the second thread
+  is started
+- Correctly error out when an application tries to acquire or release the
+  org.freedesktop.DBus name instead of sending false result codes
+- kqueue directory watching code can now be used to monitor config file changes
+  on FreeBSD
+- --with-dbus-daemondir configure switch added so the daemon can be installed
+  separate from the user binaries
+- Makefiles fixed for cygwin 
+- Various fixes for the ongoing Windows port 
+- Fixed docs and comments to use the D-Bus spelling instead of D-BUS
+- Many memleaks and bugs fixed
+
+D-Bus 0.91 (24 July 2006)
+==
+- Remove some lingering bits left over from the bindings split
+- Fix assertion causing D-Bus applications to crash when checks are enabled
+- Fix a timeout bug which would block applications from being auto started
+
+D-Bus 0.90 (17 July 2006)
+==
+- API/ABI freeze for 1.0
+- Bindings are now split out into seperate packages
+- ListActivatableNames added as a method on the bus
+- Removed deprecated dbus_connection_disconnect (use dbus_connection_close)
+- Shared connections are now unreffed on disconnect
+- Fixed pending calls for threaded enviornments
+- Pending calls get timed out on connection disconnect
+- dbus_connection_send_with_reply returns TRUE and a NULL pending call
+  if you call it on a connection object which has been disconnected already
+  (it returns FALSE on Out of Memory errors only)
+- dbus-monitor now correctly catches methods, not just signals
+- dbus-monitor now prints object paths 
+
+D-BUS 0.62 (12 June 2006)
+==
+- Doc fixes
+- Added support for all data-types for the dbus tools
+- Fixed eavesdropping on method calls (dbus-monitor)
+- Fixed silent dropping of method calls with interface=NULL
+- Fixed console ownership problems in Solaris
+- Fixed installation of dbus-signature.h and #include it in dbus/dbus.h
+- Flush the user database cache on config reload
+- GLib bindings:
+  - Fix memory leaks
+  - Fix properties in DBusGProxy so that they can be given in any
+    order
+  - Added lots of assertions to ensure correct use
+  - Remove duplicated code
+  - Fix static string pointer uses in GPtrArray-based collections
+- Python bindings:
+  - Remove reference to sys/cdefs.h
+- Qt4 bindings:
+  - Code reorganized
+  - Added the dbusidl2cpp, dbuscpp2xml and dbus tools
+  - Added example programs (ping-pong, complex ping-pong, listnames, chat)
+  - Updated selftests
+  - Fixed compilation and .moc- and .ui-file processing and cleaning
+  - Made central classes derive from QObject
+  - Enhance error reporting
+  - Many bugfixes
+- Mono bindings:
+  - Minor bugfixes
+
+D-BUS 0.61 (24 Febuary 2006)
+==
+- Documentation all around
+- dbus-launch now produces correct sh and csh syntax
+- Nested arrays now work correctly
+- GLib bindings:
+  - Inheriting from DBusGProxy is now possible
+  - GPtrArrays can now be marshalled
+  - org.freedesktop.DBus.GLib.ClientCSymbol annotation added
+  - Openning connections to arbitrary addresses now supported
+- Python bindings:
+  - sender_keyword and path_keyword keywords added to signal listener API
+  - Byte types now demarshal to unsigned char
+  - calling methods now do the correct thing
+- Qt bindings:
+  - both Qt3 and Qt4 bindings can be built at the same time
+  - Use the standard org.freedesktop.DBus.Method.NoReply annotation 
+    for the "async" calls instead of creating one for us.
+- Mono bindings:
+  - 64bit arch fixes
+- Massive bug fixing all around
+
+D-BUS 0.60 (30 November 2005)
+==
+
+- major ABI/API changes - sonames changed
+- RequestName queuing behavior has changed (refer to dbus-specification)
+  - DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT has been removed and
+    DBUS_NAME_FLAG_ALLOW_REPLACEMENT has been added to the flags
+- signals emitted by the bus now show up in the introspect data
+- auth EXTERNAL now supported on BSD varients
+- ReleaseName method added to the bus to allow a service
+  to remove itself as owner of a bus name
+- dbus_connection_read_write added for getting messages off the bus 
+  in the absence of a mainloop
+- Qt4 bindings added and the Qt3 bindings have been depricated
+- python bindings:
+  - marshal using introspect data if available
+  - better exception handling and propigation
+  - private connections are now supported
+  - UTF-8 cleanups
+  - out_signature added to method decorators for specifying
+    how the return values should be marshaled
+  - sender_keyword added to method decorators for specifying
+    and argument to provide the unique name of the method caller
+  - async_callbacks added to method decorators 
+  - multiple inheritance of classes now supported 
+- GLib bindings:
+  - respect NoReply annotations
+  - dbus_g_method_return_get_reply and dbus_g_method_return_send_reply
+    added to the lowlevel code for use when the dbus-glib marshalling
+    code is not adiquate
+- numerous bug fixes all around
+
+D-BUS 0.50 (06 September 2005)
+===
+This is a minor release from 0.36.2.  The series number has changed 
+not because of any technical reasons but as an indication that we
+are moving closer to 1.0.  It is hoped that this will be the last
+series to see major changes, most of which will be isolated to the
+GLib and Python bindings, as we transition to concentrate more on
+bug busting and code auditing.
+
+- D-Bus builds on the Cygwin platform
+- Makefile cleanups
+- Various bug fixes
+- Optimization of the dbus object tree 
+- Memleaks and GIL crasher bugs have been fixed in the Python bindings
+
+D-BUS 0.36.2 (29 August 2005)
+===
+- Security: Restrict other users from connecting to another users 
+  session bus
+
+D-BUS 0.36.1 (24 August 2005)
+===
+- Python Bindings:
+  - fixed to work with hal-device-manager
+  - For 64bit builds everything is installed to lib64/python2.4/
+    since Python can't handle multilib
+
+D-BUS 0.36 (23 August 2005)
+===
+- Maximum sized of cached messages have been reduced to 10K
+- Match rules now allow matching on arguments inside the message
+- introspect.xsl XSLT style sheet added for formatting introspection
+  data into XHTML for analysis
+- Python bindings:
+  - now have working type objects for explicit
+    typecasting
+  - Variant type has been added
+  - Dictionaries, Variants and Arrays can all be passed the signiture or
+    type(s) of their children
+  - the optional timeout= keyword has been added when making method calls
+  - match on args has been implemented
+  - a .pth file has been added for dealing with libraries and python files
+    being in different directories such as in 64bit installs
+  - various bug fixes
+- GLib bindings:
+  - deeply recursive types now supported
+  - many symbols are no longer exported as part of the public API
+  - various memleak and other bug fixes
+
+D-BUS 0.35.2 (17 July 2005)
+===
+- Rename Unix Security Context to SELinux Security Context in API
+- Fixed more dist errors that distcheck didn't pick up on
+- Fixed various bugs in the python bindings that prevented them from working
+
+D-BUS 0.35.1 (16 July 2005)
+===
+- Fixed dist error where python/dbus_bindings.pxd was being shipped 
+  instead of dbus_bindings.pxd.in
+- Use this instead of the 0.35 tarball 
+
+D-BUS 0.35 (15 July 2005)
+===
+- --with-dbus-user added to the configure scripts for configuring the 
+  user the system bus runs on
+- --with-console-auth-dir added to configure scripts for configuring the
+  directory to look in for console user locks
+- service files for auto-starting D-Bus services now has the ability to pass
+  in command line arguments to the executable
+- Huge auto-start bug squashed which caused some services not to start when
+  requested in rapid succession
+- SE-Linux security contexts can now be appended to messages for inspection
+  by services that enforce their own security policies
+- Colin says the GLib binding are ready for general consumption
+- New GLib tutorial
+- New GLib example code
+- Python bindings are now version (0,42,0)
+- Python bindings API has changed on the service side
+- dbus.service has been split out as a seperate module
+- dbus.service.Service is renamed to dbus.service.BusName
+- dbus.service.Object has swapped the bus_name and object_path constructor
+  parameters to make it easier to do inheritance over the bus
+- dbus.glib has been seperated out in order to lessen the dependency on glib
+  and to allow other mainloops to be integrated with the bindings including
+  a planned generic mainloop for non-gui apps.
+- Python bindings now aquire the GIL when calling back into the python
+  interpreter.  Fixes crashes when using threading and other random segfaults.
+- New Python tutorial
+- Numerous D-Bus bug fixes all around
+
+D-BUS 0.34 (15 June 2005)
+===
+- dbus_connection_disconnect is deprecated in favor of dbus_connection_close
+- The bus can now use D_NOTIFY (if available) to check when configuration files 
+  have changed and reload them
+- New dbus_message_has_path/member/interface API added
+- The Ping message from the org.freedesktop.DBus.Peer interface is now handled
+- Complete glib bindings overhaul (and are still under construction)
+- Tutorial now has an updated GLib section 
+- GLib bindings can now send/receive hash tables, arrays and other complex types
+- Python bindings overhaul (most public facing API's done)
+- Python bindings have been split up into separate files
+- Python added new type classes for hinting to the marshaler what type
+  to send over the wire
+- Python bindings now have decorators for specifying exported methods and signals
+- Numerous bug fixes
+
+D-BUS 0.33 (25 Apr 2005)
+===
+
+- downgrade requirement from GTK+-2.6 to 2.4 for building gtk components
+- python binding API's have been overhalled to be more "pythonic" and cleaner
+- python bindings now export dbus.version which is set to (0,40,0)
+- python bindings now implement the org.freedesktop.DBus.Introspectable interface
+- python binding match rules are now more flexable
+- make check has been fixed
+- many, many major bug fixes
+
+D-BUS 0.32 (29 Mar 2005)
+===
+
+- mono bindings now compiles correctly
+- mono binding cleanups
+- glib bindings generates wrappers for bus methods in dbus-glib-bindings.h
+- glib binding cleanus
+- users and groups can now be specified by UID and GID in config files
+- numerous memory leak fixes
+- various other fixes
+
+D-BUS 0.31 (07 Mar 2005)
+===
+
+- land the new message args API and recursive type system
+- add docs and fixed Doxygen warnings throught source
+- split out some functions not needed in libdbus to *-util.c source files
+- take out type convienience functions
+- libdbus now back below 150K
+- booleans are now 32-bit instead of 8-bit
+- specification updated
+- grand renaming to strip out the use of "service"
+  just say "name" instead (or "bus name" when ambiguous)
+- rename dbus-daemon-1 to dbus-daemon throughout
+- rename activation to auto-start
+- auto-start on by default now
+- note that libdbus is the low-level API
+- python bindings updated to the new API
+- mono bindings updated to the new API
+- add 16 bit types
+- dictionaries are now ARRAYS of DICT_ENTRY
+- dbus-glib-tool renamed to dbus-binding-tool
+- massive rewrite of the glib bindings
+- saner names for the dbus interface, object path and service defines
+- new functions for handling type signitures
+- bump sonames for libdbus and libdbus-glib
+- various small fixes
+
+D-BUS 0.23 (11 Jan 2005)
+===
+
+- add setgroups() to drop supplementary groups
+- updated SELinux support
+- add an "at console" security policy
+- fix a bug where org.freedesktop.DBus wasn't recognized as an existing
+  service.
+- error out if --enable-mono is explicitly set and mono libs can't be found
+- set the max_match_rules_per_connection limit from the config file.
+- removed dbus_bug_get_with_g_main since it's been replaced by
+  dbus_g_bus_get
+- fix fd leaks in socket code
+- lots and lots of mono binding updates, including fixes to make it
+  compatible with Mono 1.1.3
+- added --nofork option to override config file setting at runtime
+- added support for int64 and uint64 to the python bindings
+- lots of python binding updates
+- config file DTD updates
+- use SerivceOwnerChanges signal instead of ServiceCreated and
+  ServiceDeleted
+- fixes to the authentication code
+- new init script for Slackware
+- print out the pid even when --fork is passed
+- increase preallocation sizes in DBusMessage to heavily reduce
+  reallocs
+- lots of performance enhancements
+- lots more small bug fixes
+
+D-BUS 0.22
+===
+
+- add --reply-timeout to dbus-send
+- fix a memleak
+- fix Solaris/Forte build
+- switch to AFL 2.1 rather than 2.0 to address patent termination clause 
+  concerns
+- add SELinux support
+- mostly repair libxml backend for config parser, still doesn't 
+  pass out of memory tests
+- fix distcheck to include language bindings
+- add GetConnectionUnixUser method on bus driver
+- also for UnixProcessID
+- lots of Python, Mono, other binding fixes
+- change GLib bindings to not include dbus/dbus.h (fully encapsulate libdbus)
+- pass paths as strings, not arrays of string
+- add message signature header field
+- cleanups to marshaling code
+- clean up authentication code
+- reload conf files on SIGHUP
+- rename SERVICE/SENDER_SERVICE to DESTINATION/SENDER
+- fix circular conf file inclusion
+- allow empty arrays
+- tons of other small bugfixes
+
+D-BUS 0.21
+===
+
+- implement "auto activation" flag on messages, so the destination 
+  service can be launched automatically
+- fix a bug in custom type marshaling
+- optimize case where multiple apps activate the same service
+  (avoid "thundering herd")
+- add dynamic service file discovery/reloading
+- fix a busy loop when blocking for a reply
+- fix a 64-bit crash involving varargs
+- fix a bus crash when processing an AcquireService
+- allow appending TYPE_BYTE via append_args_valist
+- fix dicts-inside-dicts
+- enhancements to Python and Qt bindings
+
+D-BUS 0.20
+===
+
+This release lands some very large API changes and numerous bugfixes.
+The list of changes is too large to fully document here; please refer
+to the documentation, and message-bus-list archives.
+
+D-BUS 0.13
+===
+
+This is probably the last release before landing the large API changes
+on the "dbus-object-names" branch.
+
+- fix system bus to always use filesystem socket; anyone 
+  can create any abstract socket, which isn't secure 
+  since if you can crash the system bus you'd be able
+  to replace it.
+- add DTD for configuration file
+- improve specification a bit
+
+D-BUS 0.12
+===
+
+- fix "service messagebus status" on Red Hat
+- fix demarshaling of DBUS_TYPE_NAMED
+- fix "eval `dbus-launch --exit-with-session`" to exit properly
+- fix build without --prefix
+- useless fooling with Mono bindings
+- useless fooling with gcj bindings
+- fix srcdir != builddir
+- fix various compiler warnings and other issues
+- add get/set data to DBusMessage
+- fix headers for C++
+- OS X build fixes
+- abstract domain sockets support (Linux only)
+- add dbus-cleanup-sockets utility for people
+  not using linux
+- be consistent about defaulting to --session/--system 
+  with command line tools
+- merge in policies from included config files
+- fix build on non-x86
+- docs updates
+- lots of other bugfixes
+
+D-BUS 0.11
+===
+
+- add --enable-docs to turn off/on the docbook stuff
+  (doesn't cover doxygen stuff yet)
+- make people define DBUS_API_SUBJECT_TO_CHANGE
+  and read warning in README so they don't 
+  expect the API to be frozen already
+- rename .pc files to "dbus-1.pc" instead of 
+  "dbus-1.0.pc" etc. - this will require changing 
+  pkg-config invocations
+- some docs cleanups
+- add man pages for all executables
+- allow send to/from bus driver in the default system.conf
+- fix user lookup bug
+- implement dbus-launch to launch the session message bus
+- fix some thread deadlocks
+- some performance profiling/optimization
+- add dbus_bus_activate_service() function
+- fix some minor bugs here and there
+- install Red Hat initscript in the right place
+
+D-BUS 0.10
+===
+
+- reversed order of args to dbus_message_new()
+- renamed dbus_message_name_is() and some other
+  functions
+- change DBusWatch to have dbus_watch_handle() 
+  similar to dbus_timeout_handle(), drop 
+  connection/server-specific handle routines
+- change message serials to be unsigned
+- implemented <allow>/<deny>/<limit> features for 
+  config file; system bus now has a deny-all policy 
+  by default.
+- system.conf has <includedir>system.d</includedir>
+  so packages can install additions to the default 
+  policy to <allow> the messages they need. e.g.
+  CUPS might install a cups.conf - see 
+  test/data/valid-config-files/system.d/test.conf 
+  for an example.
+- add timeouts for authentication, activation
+- add glib-style "checks" on public API, enable 
+  those by default, disable assertions by default
+- add GMainContext argument to GLib setup functions, 
+  can be NULL for default context. Needed for threads.
+- add 64-bit integer type
+- validate type of standard message header fields
+- consider messages in the org.freedesktop.Local
+  namespace to be invalid (to avoid fake disconnect 
+  messages for example)
+- fix assorted memory leaks and other bugs in 
+  the SHA-1 auth mechanism
+- cache user database information (groups user is 
+  in, etc.) helps a lot with NIS
+- always store uid_t, pid_t, gid_t in "ulong" 
+  rather than "int"
+- implement config file settings for which 
+  users can connect
+- SHA-1 unit test
+- dbus-send, dbus-monitor command line utilities
+- fixed lots of misc crashes and other bugs
+
+D-BUS 0.9
+===
+
+- implemented a test case for service activation,
+  and fixed many bugs exposed by that
+- implemented recursive argument marshaling/demarshaling 
+  for messages, allowing multidimensional arrays
+- fixed up integration of message dispatch with 
+  main loop by adding a callback on change of 
+  dispatch status
+- add a pidfile feature to daemon
+- some build fixes
+- clean up unix domain sockets on exit
+- add --print-address and the ability 
+  to create a random server address 
+  in a temporary directory
+
+D-BUS 0.8
+===
+
+- fix dumb bug in 0.7
+
+D-BUS 0.7
+===
+
+- implement configuration file used to control bus characteristics
+- implement daemon mode, changing user ID, and other system
+  bus features
+- add init scripts for systemwide bus
+- add "make check-coverage" target to check test coverage
+- more test suite additions
+- many, many bugfixes
+- many API changes/fixes
+
+D-BUS 0.6
+===
+- Vastly improved bus daemon test suite
+- Lots of misc. bugfixes and memory leak fixes
+- Support for marshalling key/value data
+- Activation improvements.
+
+D-BUS 0.5
+===
+
+- Specification updates
+- port to OS X and other BSD variants
+- port to Solaris
+- Partial work on cookie-based authentication
+- Thread safety fixes
+- Lots of misc. bugfixes
+- Support for more array types
+- Add data slots to DBusServer
+- DBusString security audit fixes
+- Fix for systems (or valgrind) with unaligned malloc blocks
+
+D-BUS 0.4
+===
+
+- Preliminary activation support.
+- Better authentication test suite
+- Bus test program
+- Specification updates
+- Thread safety
+- Bug fixes
+
+D-BUS 0.3
+===
+
+ - Preliminary limitations 
+ - Message sending works
+ - Bus client
+ - Array marshalling/demarshalling
+ - Services
+ - Better OOM handling in the bus
+ - In-proc debug transport
+ - Transport/server address support
+
+D-BUS 0.2
+===
+
+ - Include test code in the tarball.
+
+D-BUS 0.1
+===
+
+ - Initial release.
diff --git a/dbus/NEWS.pre-1-2 b/dbus/NEWS.pre-1-2
new file mode 100644
index 0000000..d9898f8
--- /dev/null
+++ b/dbus/NEWS.pre-1-2
@@ -0,0 +1,153 @@
+D-Bus 1.2.1 (04 April)
+==
+- Due to issues putting the re-licensing effort on hold indefinitely, it has 
+  been decided to move to 1.2.x versioning scheme.  Being that 1.1.20 is 
+  considered to also be 1.2.0 and this being the second release in the 1.2.x 
+  stable series we have versioned this release 1.2.1. This release contains a 
+  number of bug fixes identified after 1.1.20.
+- compiles under some older versions of glibc
+- compiles without X support once again
+- fix stuck server grab if dbus-launch is run in an existing D-Bus X session
+- various Mac OSX build fixes added
+- don't use the broken poll call on Mac OSX
+- better checks for linker flag support should allow D-Bus to link under
+  various linkers
+- exit_on_disconnect is set after the connection registers with a bus so we 
+  don't exit if we get a disconnect during the handshake
+- dicts now work correctly with dbus-send
+- inotify backend is now less aggressive
+- pending calls expire correctly
+- memleak of uuid when the bus is autolaunched fixed
+
+D-Bus 1.1.20 - "Conisten Water" (27 Febuary)
+==
+
+- This is the next generation supported STABLE release of D-Bus. For all 
+  intents and purposes this is the 1.2.0 release WITHOUT the planned X11/MIT 
+  license change due to a couple of license holders who have yet to respond.
+  For the most part this license change is being persued to simplify licensing
+  issues and fix a couple of licensing courner cases.  When this happens D-Bus
+  will be released under the 1.2.0 version.
+
+- D-Bus 1.0.x effectively goes into security fix mode and will only be
+  updated for major issues.
+
+- Fixed CVE-2008-0595 - security policy of the type <allow send_interface=
+  "some.interface.WithMethods"/> work as an implicit allow for
+  messages sent without an interface bypassing the default deny rules and 
+  potentially allowing restricted methods exported on the bus to be executed
+  by unauthorized users. 
+
+- Fixes dbus-launch so the session bus goes away so does D-Bus
+
+- Builds against latest gcc/glibc changes
+
+- Correctly unref connections without guids during shutdown
+
+- About the name: Submitted by Greg K Nicholson, Conisten Water is a lake in 
+  Cumbria, England where several water speed records have been broken. Between 
+  1956 and 1959 Sir Malcolm's son Donald Campbell set four successive records on  the lake in Bluebird K7, a hydroplane.
+  (Wikipedia http://en.wikipedia.org/wiki/Coniston_Water#Waterspeed_record)
+
+D-Bus 1.1.4 - 1.2.0RC2 (17 January 2007)
+==
+- Fixes inotify support
+
+D-Bus 1.1.3 - 1.2.0RC1 (15 January 2007)
+==
+
+- This release is intended to be Release Candidate 1 of major release
+  D-Bus 1.2.0.  If nothing is found to be wrong with this release it
+  will become 1.2.0 within a week.  If we need to make major changes
+  we will release an RC2 and start the process over again.
+
+- This is a development release, so API's may still change if problems
+  are found (though this is extreamly unlikely).
+
+- DTD for the introspection format is fixed and uploaded to the servers
+
+- Sources now reside in a git repository at 
+  http://gitweb.freedesktop.org/?p=dbus/dbus.git;a=summary
+
+- Argument path matching of the type arg0path='/aa/bb/' is now supported
+  (see the specification for more information)
+
+- New error org.freedesktop.DBus.Error.ObjectPathInUse added
+
+- Autolaunched busses now save their parameters in X11 if possible making them
+  behave closer to busses launched through the normal mechanisms 
+
+- inotify is now the default backend for watching configuration file changes
+
+- More support for the AIX platform has been added
+
+- Numerous bug fixes and performance enhancements
+
+D-Bus 1.1.2 (27 July 2007)
+==
+
+- This release is intended to be a feature complete beta for stable
+  release 1.2.0, please test it. 1.2.0 will follow pretty soon if no
+  major problems are found.  We'll do more betas if significant
+  changes are made.
+
+- This is a development release, so API's may still change if problems
+  are found (though we will try hard not to).
+
+- The system bus now supports starting services on demand. This uses a
+  setuid helper program because system bus daemon runs as a nobody
+  user, while services it launches may need to run as a different
+  user.
+
+  ***Extra eyes auditing the setuid helper are encouraged and would be
+  timely right now, before 1.2.0***
+
+  A design doc is available in doc/system-activation.txt
+
+- The TCP address format has been enhanced, such that TCP may be
+  actually usable.  The dbus-daemon man page describes the new
+  elements in the address format.  1.1.1 had added an all_interfaces
+  flag to the format, which has been removed in favor of a cleaner
+  approach.
+
+- Some thread-related bugs have been fixed, these are important fixes
+  if you are using multiple threads with libdbus, and not important
+  otherwise.
+
+
+D-Bus 1.1.1 (18 June 2007)
+==
+- This is a development release, unless you need specific 
+  functionality please use the stable releases as API's may change
+  (though we will try hard not to)
+- The bus daemon now generates a globally-unique ID for itself, which is available 
+  using the convenience function dbus_bus_get_id(). Use this as a unique ID 
+  for a user's session, for example.
+- dbus_server_get_id(), dbus_connection_get_server_id() now available to access
+  the unique ID of a particular address
+- dbus_watch_get_fd() deprecated since it had unclear cross-platform semantics.
+  dbus_watch_get_unix_fd() and dbus_watch_get_socket() replace it.
+- support ANONYMOUS mechanism for authentication, which allows a client to 
+  authenticate as nobody in particular
+- add API dbus_connection_set_allow_anonymous() which will allow the message
+  stream to begin if the client auths as anonymous (otherwise, the client 
+  will be dropped unless they auth as a user).
+- the ANONYMOUS support means you can now use D-Bus (without a bus daemon) as 
+  a protocol for a network service provided to anonymous Internet or LAN  
+  clients
+- many internal changes to better support the Windows port, though the 
+  port is still not complete in this release
+- some improved documentation and return_if_fail checks
+- some small bug fixes
+
+D-Bus 1.1.0 (25 May 2007)
+==
+- first release in the development series, unless you need specific 
+  functionality please use the stable releases as API's may change
+  (though we will try hard not to)
+- better eavesdropping support now picks up reply messages for debugging
+- .pc file now lists the directory the daemon is installed into (daemondir)
+- GetAll call added to the properties interface
+- support for message serialization added for use with external transports like
+  TUBES!!!
+- many bugs fixed
diff --git a/dbus/NOTICE b/dbus/NOTICE
new file mode 100644
index 0000000..a91ca1d
--- /dev/null
+++ b/dbus/NOTICE
@@ -0,0 +1,551 @@
+D-Bus is licensed to you under your choice of the Academic Free
+License version 2.1, or the GNU General Public License version 2.
+Both licenses are included here. Some of the standalone binaries are
+under the GPL only; in particular, but not limited to,
+tools/dbus-cleanup-sockets.c and test/decode-gcov.c. Each source code
+file is marked with the proper copyright information - if you find a
+file that isn't marked please bring it to our attention.
+
+
+The Academic Free License
+v. 2.1
+
+This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
+
+Licensed under the Academic Free License version 2.1
+
+1) Grant of Copyright License. Licensor hereby grants You a
+world-wide, royalty-free, non-exclusive, perpetual, sublicenseable
+license to do the following:
+
+a) to reproduce the Original Work in copies;
+
+b) to prepare derivative works ("Derivative Works") based upon the Original Work;
+
+c) to distribute copies of the Original Work and Derivative Works to the public;
+
+d) to perform the Original Work publicly; and
+
+e) to display the Original Work publicly.
+
+2) Grant of Patent License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license, under
+patent claims owned or controlled by the Licensor that are embodied in
+the Original Work as furnished by the Licensor, to make, use, sell and
+offer for sale the Original Work and Derivative Works.
+
+3) Grant of Source Code License. The term "Source Code" means the
+preferred form of the Original Work for making modifications to it and
+all available documentation describing how to modify the Original
+Work. Licensor hereby agrees to provide a machine-readable copy of the
+Source Code of the Original Work along with each copy of the Original
+Work that Licensor distributes. Licensor reserves the right to satisfy
+this obligation by placing a machine-readable copy of the Source Code
+in an information repository reasonably calculated to permit
+inexpensive and convenient access by You for as long as Licensor
+continues to distribute the Original Work, and by publishing the
+address of that information repository in a notice immediately
+following the copyright notice that applies to the Original Work.
+
+4) Exclusions From License Grant. Neither the names of Licensor, nor
+the names of any contributors to the Original Work, nor any of their
+trademarks or service marks, may be used to endorse or promote
+products derived from this Original Work without express prior written
+permission of the Licensor. Nothing in this License shall be deemed to
+grant any rights to trademarks, copyrights, patents, trade secrets or
+any other intellectual property of Licensor except as expressly stated
+herein. No patent license is granted to make, use, sell or offer to
+sell embodiments of any patent claims other than the licensed claims
+defined in Section 2. No right is granted to the trademarks of
+Licensor even if such marks are included in the Original Work. Nothing
+in this License shall be interpreted to prohibit Licensor from
+licensing under different terms from this License any Original Work
+that Licensor otherwise would have a right to license.
+
+5) This section intentionally omitted.
+
+6) Attribution Rights. You must retain, in the Source Code of any
+Derivative Works that You create, all copyright, patent or trademark
+notices from the Source Code of the Original Work, as well as any
+notices of licensing and any descriptive text identified therein as an
+"Attribution Notice." You must cause the Source Code for any
+Derivative Works that You create to carry a prominent Attribution
+Notice reasonably calculated to inform recipients that You have
+modified the Original Work.
+
+7) Warranty of Provenance and Disclaimer of Warranty. Licensor
+warrants that the copyright in and to the Original Work and the patent
+rights granted herein by Licensor are owned by the Licensor or are
+sublicensed to You under the terms of this License with the permission
+of the contributor(s) of those copyrights and patent rights. Except as
+expressly stated in the immediately proceeding sentence, the Original
+Work is provided under this License on an "AS IS" BASIS and WITHOUT
+WARRANTY, either express or implied, including, without limitation,
+the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL
+WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential
+part of this License. No license to Original Work is granted hereunder
+except under this disclaimer.
+
+8) Limitation of Liability. Under no circumstances and under no legal
+theory, whether in tort (including negligence), contract, or
+otherwise, shall the Licensor be liable to any person for any direct,
+indirect, special, incidental, or consequential damages of any
+character arising as a result of this License or the use of the
+Original Work including, without limitation, damages for loss of
+goodwill, work stoppage, computer failure or malfunction, or any and
+all other commercial damages or losses. This limitation of liability
+shall not apply to liability for death or personal injury resulting
+from Licensor's negligence to the extent applicable law prohibits such
+limitation. Some jurisdictions do not allow the exclusion or
+limitation of incidental or consequential damages, so this exclusion
+and limitation may not apply to You.
+
+9) Acceptance and Termination. If You distribute copies of the
+Original Work or a Derivative Work, You must make a reasonable effort
+under the circumstances to obtain the express assent of recipients to
+the terms of this License. Nothing else but this License (or another
+written agreement between Licensor and You) grants You permission to
+create Derivative Works based upon the Original Work or to exercise
+any of the rights granted in Section 1 herein, and any attempt to do
+so except under the terms of this License (or another written
+agreement between Licensor and You) is expressly prohibited by
+U.S. copyright law, the equivalent laws of other countries, and by
+international treaty. Therefore, by exercising any of the rights
+granted to You in Section 1 herein, You indicate Your acceptance of
+this License and all of its terms and conditions.
+
+10) Termination for Patent Action. This License shall terminate
+automatically and You may no longer exercise any of the rights granted
+to You by this License as of the date You commence an action,
+including a cross-claim or counterclaim, against Licensor or any
+licensee alleging that the Original Work infringes a patent. This
+termination provision shall not apply for an action alleging patent
+infringement by combinations of the Original Work with other software
+or hardware.
+
+11) Jurisdiction, Venue and Governing Law. Any action or suit relating
+to this License may be brought only in the courts of a jurisdiction
+wherein the Licensor resides or in which Licensor conducts its primary
+business, and under the laws of that jurisdiction excluding its
+conflict-of-law provisions. The application of the United Nations
+Convention on Contracts for the International Sale of Goods is
+expressly excluded. Any use of the Original Work outside the scope of
+this License or after its termination shall be subject to the
+requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101
+et seq., the equivalent laws of other countries, and international
+treaty. This section shall survive the termination of this License.
+
+12) Attorneys Fees. In any action to enforce the terms of this License
+or seeking damages relating thereto, the prevailing party shall be
+entitled to recover its costs and expenses, including, without
+limitation, reasonable attorneys' fees and costs incurred in
+connection with such action, including any appeal of such action. This
+section shall survive the termination of this License.
+
+13) Miscellaneous. This License represents the complete agreement
+concerning the subject matter hereof. If any provision of this License
+is held to be unenforceable, such provision shall be reformed only to
+the extent necessary to make it enforceable.
+
+14) Definition of "You" in This License. "You" throughout this
+License, whether in upper or lower case, means an individual or a
+legal entity exercising rights under, and complying with all of the
+terms of, this License. For legal entities, "You" includes any entity
+that controls, is controlled by, or is under common control with
+you. For purposes of this definition, "control" means (i) the power,
+direct or indirect, to cause the direction or management of such
+entity, whether by contract or otherwise, or (ii) ownership of fifty
+percent (50%) or more of the outstanding shares, or (iii) beneficial
+ownership of such entity.
+
+15) Right to Use. You may use the Original Work in all ways not
+otherwise restricted or conditioned by this License or by law, and
+Licensor promises not to interfere with or be responsible for such
+uses by You.
+
+This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights
+reserved. Permission is hereby granted to copy and distribute this
+license without modification. This license may not be modified without
+the express written permission of its copyright owner.
+
+
+-- 
+END OF ACADEMIC FREE LICENSE. The following is intended to describe the essential 
+differences between the Academic Free License (AFL) version 1.0 and other 
+open source licenses:
+
+The Academic Free License is similar to the BSD, MIT, UoI/NCSA and Apache 
+licenses in many respects but it is intended to solve a few problems with 
+those licenses.
+    
+* The AFL is written so as to make it clear what software is being 
+licensed (by the inclusion of a statement following the copyright notice 
+in the software). This way, the license functions better than a template 
+license. The BSD, MIT and UoI/NCSA licenses apply to unidentified software.
+    
+* The AFL contains a complete copyright grant to the software. The BSD 
+and Apache licenses are vague and incomplete in that respect.
+    
+* The AFL contains a complete patent grant to the software. The BSD, MIT, 
+UoI/NCSA and Apache licenses rely on an implied patent license and contain 
+no explicit patent grant.
+    
+* The AFL makes it clear that no trademark rights are granted to the 
+licensor's trademarks. The Apache license contains such a provision, but the 
+BSD, MIT and UoI/NCSA licenses do not.
+    
+* The AFL includes the warranty by the licensor that it either owns the 
+copyright or that it is distributing the software under a license. None of 
+the other licenses contain that warranty. All other warranties are disclaimed, 
+as is the case for the other licenses.
+
+* The AFL is itself copyrighted (with the right granted to copy and distribute 
+without modification). This ensures that the owner of the copyright to the 
+license will control changes. The Apache license contains a copyright notice, 
+but the BSD, MIT and UoI/NCSA licenses do not. 
+--
+START OF GNU GENERAL PUBLIC LICENSE
+--
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/dbus/README b/dbus/README
new file mode 100644
index 0000000..fd832ca
--- /dev/null
+++ b/dbus/README
@@ -0,0 +1,163 @@
+Sections in this file describe:
+ - introduction and overview
+ - low-level vs. high-level API
+ - version numbers
+ - options to the configure script
+ - ABI stability policy
+
+Introduction
+===
+
+D-Bus is a simple system for interprocess communication and coordination.
+
+The "and coordination" part is important; D-Bus provides a bus daemon that does things like:
+ - notify applications when other apps exit
+ - start services on demand
+ - support single-instance applications
+
+See http://www.freedesktop.org/software/dbus/ for lots of documentation, 
+mailing lists, etc.
+
+See also the file HACKING for notes of interest to developers working on D-Bus.
+
+If you're considering D-Bus for use in a project, you should be aware
+that D-Bus was designed for a couple of specific use cases, a "system
+bus" and a "desktop session bus." These are documented in more detail
+in the D-Bus specification and FAQ available on the web site.
+
+If your use-case isn't one of these, D-Bus may still be useful, but
+only by accident; so you should evaluate carefully whether D-Bus makes
+sense for your project.
+
+Note: low-level API vs. high-level binding APIs
+===
+
+A core concept of the D-Bus implementation is that "libdbus" is
+intended to be a low-level API. Most programmers are intended to use
+the bindings to GLib, Qt, Python, Mono, Java, or whatever. These
+bindings have varying levels of completeness and are maintained as
+separate projects from the main D-Bus package. The main D-Bus package
+contains the low-level libdbus, the bus daemon, and a few command-line
+tools such as dbus-launch.
+
+If you use the low-level API directly, you're signing up for some
+pain. Think of the low-level API as analogous to Xlib or GDI, and the
+high-level API as analogous to Qt/GTK+/HTML.
+
+Version numbers
+===
+
+D-Bus uses the common "Linux kernel" versioning system, where
+even-numbered minor versions are stable and odd-numbered minor
+versions are development snapshots.
+
+So for example, development snapshots: 1.1.1, 1.1.2, 1.1.3, 1.3.4
+Stable versions: 1.0, 1.0.1, 1.0.2, 1.2.1, 1.2.3
+
+All pre-1.0 versions were development snapshots.
+
+Development snapshots make no ABI stability guarantees for new ABI
+introduced since the last stable release. Development snapshots are
+likely to have more bugs than stable releases, obviously.
+
+Configuration 
+===
+
+dbus could be build by using autotools or cmake. 
+
+When using autotools the configure step is initiated by running ./configure 
+with or without additional configuration flags. 
+
+When using cmake the configure step is initiated by running the cmake 
+program with or without additional configuration flags. 
+
+Configuration flags
+===
+
+When using autotools, run "./configure --help" to see the possible
+configuration options and environment variables.
+
+When using cmake, inspect README.cmake to see the possible
+configuration options and environment variables.
+    
+API/ABI Policy
+===
+
+Now that D-Bus has reached version 1.0, the objective is that all
+applications dynamically linked to libdbus will continue working
+indefinitely with the most recent system and session bus daemons.
+
+ - The protocol will never be broken again; any message bus should 
+   work with any client forever. However, extensions are possible
+   where the protocol is extensible.
+
+ - If the library API is modified incompatibly, we will rename it 
+   as in http://ometer.com/parallel.html - in other words, 
+   it will always be possible to compile against and use the older 
+   API, and apps will always get the API they expect.
+
+Interfaces can and probably will be _added_. This means both new
+functions and types in libdbus, and new methods exported to
+applications by the bus daemon.
+
+The above policy is intended to make D-Bus as API-stable as other
+widely-used libraries (such as GTK+, Qt, Xlib, or your favorite
+example). If you have questions or concerns they are very welcome on
+the D-Bus mailing list.
+
+NOTE ABOUT DEVELOPMENT SNAPSHOTS AND VERSIONING
+
+Odd-numbered minor releases (1.1.x, 1.3.x, 2.1.x, etc. -
+major.minor.micro) are devel snapshots for testing, and any new ABI
+they introduce relative to the last stable version is subject to
+change during the development cycle.
+
+Any ABI found in a stable release, however, is frozen.
+
+ABI will not be added in a stable series if we can help it. i.e. the
+ABI of 1.2.0 and 1.2.5 you can expect to be the same, while the ABI of
+1.4.x may add more stuff not found in 1.2.x.
+
+NOTE ABOUT STATIC LINKING
+
+We are not yet firmly freezing all runtime dependencies of the libdbus
+library. For example, the library may read certain files as part of
+its implementation, and these files may move around between versions.
+
+As a result, we don't yet recommend statically linking to
+libdbus. Also, reimplementations of the protocol from scratch might
+have to work to stay in sync with how libdbus behaves.
+
+To lock things down and declare static linking and reimplementation to
+be safe, we'd like to see all the internal dependencies of libdbus
+(for example, files read) well-documented in the specification, and
+we'd like to have a high degree of confidence that these dependencies
+are supportable over the long term and extensible where required.
+
+NOTE ABOUT HIGH-LEVEL BINDINGS
+
+Note that the high-level bindings are _separate projects_ from the
+main D-Bus package, and have their own release cycles, levels of
+maturity, and ABI stability policies. Please consult the documentation
+for your binding.
+
+Bootstrapping D-Bus on new platforms
+===
+
+A full build of D-Bus, with all regression tests enabled and run, has some
+dependencies which themselves depend on D-Bus, either for compilation or
+for some of *their* regression tests: GLib, dbus-glib and dbus-python are
+currently affected.
+
+To avoid circular dependencies, when bootstrapping D-Bus for the first time
+on a new OS or CPU architecture, you can either cross-compile some of
+those components, or choose the build order and options carefully:
+
+* build and install D-Bus without tests
+  - do not use the --enable-modular-tests=yes configure option
+  - do not use the --enable-tests=yes configure option
+* build and install GLib, again without tests
+* use those versions of libdbus and GLib to build and install dbus-glib
+* ... and use those to install dbus-python
+* rebuild libdbus; this time you can run all of the tests
+* rebuild GLib; this time you can run all of the tests
diff --git a/dbus/README.cmake b/dbus/README.cmake
new file mode 100644
index 0000000..5feaf55
--- /dev/null
+++ b/dbus/README.cmake
@@ -0,0 +1,171 @@
+This file describes how to compile dbus using the cmake build system
+
+Requirements
+------------
+- cmake version >= 2.4.4 see http://www.cmake.org
+- installed libexpat see http://sourceforge.net/projects/expat/ 
+    unsupported RelWithDebInfo builds could be fetched 
+    from http://sourceforge.net/projects/kde-windows/files/expat/
+
+Building
+--------
+
+Win32 MinGW-w64|32
+1. install mingw-w64 from http://sourceforge.net/projects/mingw-w64/
+2. install cmake and libexpat
+3. get dbus sources
+4. unpack dbus sources into a sub directory (referred as <dbus-src-root> later)
+5. mkdir dbus-build
+6. cd dbus-build
+7. run 
+    cmake -G "MinGW Makefiles" [<options, see below>] <dbus-src-root>/cmake
+    mingw32-make
+    mingw32-make install
+
+Win32 Microsoft nmake
+1. install MSVC 2010 Express Version from http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express
+2. install cmake and libexpat
+3. get dbus sources
+4. unpack dbus sources into a sub directory (referred as <dbus-src-root> later)
+5. mkdir dbus-build
+6. cd dbus-build
+7. run 
+    cmake -G "NMake Makefiles" [<options, see below>] <dbus-src-root>/cmake
+    nmake
+    nmake install
+
+Win32 Visual Studio 2010 Express IDE
+1. install MSVC 2010 Express Version from http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express
+2. install cmake and libexpat
+3. get dbus sources
+4. unpack dbus sources into a sub directory (referred as <dbus-src-root> later)
+5. mkdir dbus-build
+6. cd dbus-build
+7. run
+      cmake -G "Visual Studio 10" [<options, see below>] <dbus-src-root>/cmake
+8a. open IDE with
+      vcexpress dbus.sln
+8b. for immediate build run
+      vcexpress dbus.sln /build
+
+Win32 Visual Studio 2010 Professional IDE
+1. install MSVC 2010 Professional Version
+2. install cmake and libexpat
+3. get dbus sources
+4. unpack dbus sources into a sub directory (referred as <dbus-src-root> later)
+5. mkdir dbus-build
+6. cd dbus-build
+7. run 
+      cmake -G "Visual Studio 10" [<options, see below>] <dbus-src-root>/cmake
+8a. open IDE with
+      devenv dbus.sln
+8b. for immediate build run
+      devenv dbus.sln /build
+
+Linux
+1. install cmake and libexpat
+2. get dbus sources
+3. unpack dbus sources into a sub directory (referred as <dbus-src-root> later)
+4. mkdir dbus-build
+5. cd dbus-build
+6. run 
+    cmake -G "<for available targets, see cmake --help for a list>" [<options, see below>] <dbus-src-root>/cmake
+    make
+    make install
+
+For other compilers see cmake --help in the Generators section
+
+Configuration flags
+-------------------
+
+When using the cmake build system the dbus-specific configuration flags that can be given 
+to the cmake program are these (use -D<key>=<value> on command line). The listed values 
+are the defaults.
+
+// Choose the type of build, options are: None(CMAKE_CXX_FLAGS or
+// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.
+CMAKE_BUILD_TYPE:STRING=Debug
+
+// Include path for 3rdparty packages
+CMAKE_INCLUDE_PATH:PATH=
+
+// Library path for 3rdparty packages
+CMAKE_LIBRARY_PATH:PATH=
+
+// Install path prefix, prepended onto install directories.
+CMAKE_INSTALL_PREFIX:PATH=C:/Program Files/dbus
+
+
+// enable unit test code
+DBUS_BUILD_TESTS:BOOL=ON
+
+// The name of the dbus daemon executable
+DBUS_DAEMON_NAME:STRING=dbus-daemon
+
+// Disable assertion checking
+DBUS_DISABLE_ASSERTS:BOOL=OFF
+
+// Disable public API sanity checking
+DBUS_DISABLE_CHECKS:BOOL=OFF
+
+// enable -ansi -pedantic gcc flags
+DBUS_ENABLE_ANSI:BOOL=OFF
+
+// build DOXYGEN documentation (requires Doxygen)
+DBUS_ENABLE_DOXYGEN_DOCS:BOOL=OFF
+
+// enable bus daemon usage statistics
+DBUS_ENABLE_STATS:BOOL=OFF
+
+// support verbose debug mode
+DBUS_ENABLE_VERBOSE_MODE:BOOL=ON
+
+// build XML  documentation (requires xmlto or meinproc4)
+DBUS_ENABLE_XML_DOCS:BOOL=ON
+
+// Some atomic integer implementation present
+DBUS_HAVE_ATOMIC_INT:BOOL=OFF
+
+// install required system libraries
+DBUS_INSTALL_SYSTEM_LIBS:BOOL=OFF
+
+// session bus default address
+DBUS_SESSION_BUS_DEFAULT_ADDRESS:STRING=nonce-tcp:
+
+// system bus default address
+DBUS_SYSTEM_BUS_DEFAULT_ADDRESS:STRING=nonce-tcp:
+
+// Use atomic integer implementation for 486
+DBUS_USE_ATOMIC_INT_486:BOOL=OFF
+
+// Use expat (== ON) or libxml2 (==OFF)
+DBUS_USE_EXPAT:BOOL=ON
+
+win32 only:
+// enable win32 debug port for message output
+DBUS_USE_OUTPUT_DEBUG_STRING:BOOL=OFF
+
+gcc only:
+// compile with coverage profiling instrumentation
+DBUS_GCOV_ENABLED:BOOL=OFF
+
+linux only:
+// build with dnotify support 
+DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX:BOOL=ON
+
+solaris only:
+// enable console owner file 
+HAVE_CONSOLE_OWNER_FILE:BOOL=ON
+
+// Directory to check for console ownership
+DBUS_CONSOLE_OWNER_FILE:STRING=/dev/console
+
+x11 only:
+// Build with X11 auto launch support
+DBUS_BUILD_X11:BOOL=ON
+
+
+Note: The above mentioned options could be extracted after 
+configuring from the output of running "<maketool> help-options" 
+in the build directory. The related entries start with 
+CMAKE_ or DBUS_. 
diff --git a/dbus/README.cygwin b/dbus/README.cygwin
new file mode 100755
index 0000000..904cbb4
--- /dev/null
+++ b/dbus/README.cygwin
@@ -0,0 +1,6 @@
+The cygwin dbus port is included in master branch of
+dbus git repository since 1.3.1.
+
+The cygwin port of dbus is maintained by:
+
+http://sourceware.org/cygwinports/
diff --git a/dbus/README.launchd b/dbus/README.launchd
new file mode 100644
index 0000000..701e57d
--- /dev/null
+++ b/dbus/README.launchd
@@ -0,0 +1,61 @@
+Launchd[1,2] replaces init, inetd and cron on Mac OS X since 10.4 "Tiger".
+dbus uses this service to provide a common session bus address for each user
+and so deprecates the X11 enabled dbus-launcher.
+
+[1] http://developer.apple.com/MacOsX/launchd.html
+[2] http://launchd.macosforge.org/
+
+
+Setup
+===
+
+Configure with --enable-launchd and --without-x (X11 should not harm but it's
+simply not necessary any more)
+After installation, to prevent a reboot, load the dbus session starter into
+launchd by executing:
+$ launchctl load /Library/LaunchAgents/org.freedesktop.dbus-session.plist
+
+You can change the launch agent dir via configure, but it's not recommended.
+Make sure to execute the above line as the actual user for which you want to
+use a session bus since launchd manages its agents on a per user basis.
+
+
+How it works
+===
+
+Launchd allocates a socket and provides the unix path to it via the variable
+DBUS_LAUNCHD_SESSION_BUS_SOCKET in launchd's environment. Every process
+spawned by launchd (or dbus-daemon, if stared by launchd) can access it through
+its own environment. Other processes can query launchd for it by executing:
+$ launchctl getenv DBUS_LAUNCHD_SESSION_BUS_SOCKET
+However, this is normally done by the dbus client lib for you.
+
+If launchd start dbus-daemon with a config file containing a "launchd:env=FOO"
+address, as the default session config does with env=DBUS_LAUNCHD_SESSION_BUS_SOCKET,
+the daemon will get the file descriptor from launchd and start listening on it.
+The environment variable is used to get the actual socket path which is passed
+to every service spawned by dbus-daemon as a result from autolaunch messages.
+Please note that it's not possible to start dbus-daemon manually when using a
+"launchd:" address. Only child processes of launchd can access the above
+mentioned file descriptor!
+
+To create custom buses just set up an other launch agent. As a quick start copy
+/Library/LaunchAgents/org.freedesktop.dbus-session.plist, change the label
+to i.e. "org.freedesktop.dbus-foo" and change the SecureSocketWithKey value,
+i.e. to "DBUS_LAUNCHD_FOO_BUS_SOCKET". This environment variable has to be set
+in the config file for your new bus in the <listen> element (see session.config).
+Then edit your /Library/LaunchAgents/org.freedesktop.dbus-foo.plist to start
+dbus-daemon with "--config-file=/opt/local/etc/dbus-1/foo.conf" instead of
+"--session". Now load the new plist onto launchd as described in the setup
+section of this document.
+Executing "launchctl export" should now give you two sockets, one in
+DBUS_LAUNCHD_SESSION_BUS_SOCKET and the new DBUS_LAUNCHD_FOO_BUS_SOCKET.
+To connect to this new bus use "launchd:env=DBUS_LAUNCHD_FOO_BUS_SOCKET".
+
+Since Mac OS X 10.5 "Leopard" you can also configure launchd to start
+dbus-daemon on demand as soon as some process connects to the socket. Since
+it's broken on 10.4 this feature is disabled per default. Look at
+/Library/LaunchAgents/org.freedesktop.dbus-session.plist to change it.
+
+On the client side, the envvar DBUS_SESSION_BUS_ADDRESS can be normally used
+but if it's not set, launchd is queried for the session bus socket.
diff --git a/dbus/README.win b/dbus/README.win
new file mode 100644
index 0000000..d18f23d
--- /dev/null
+++ b/dbus/README.win
@@ -0,0 +1,111 @@
+-----------------------------------------
+Windows port of the freedesktop.org D-Bus
+-----------------------------------------
+
+Features and completeness
+-------------------------
+The windows port of dbus provides the dbus-1 library and mostly
+applications which are already available on unix. These applications
+are: dbus-daemon, dbus-launch, dbus-monitor and dbus-send.
+DBus comes with a test suite which is used on unix to guarantate
+production quality and this test suite runs mostly. There are some
+test not running yet and there is help needed to get them running.
+
+Supported compilers
+-------------------
+On windows Microsoft Visual Studio 2010 (Express and professional variants) 
+and mingw-w64|32 are known to work.
+
+Building
+--------
+DBus can be built on windows using automake or cmake. See the
+file README for more information.
+Special cmake build instructions can be found in cmake/readme-cmake.txt
+
+
+windbus and dbus4win Ports
+--------------------------
+The Windows ports from the windbus and dbus4win projects has been merged
+into the freedesktop git master branch, as applicable. The spec has been
+updated with windows specific stuff.
+
+
+Tests
+-----
+ - dbus library check
+    bin\dbus-test.exe <build-root>\test\data
+
+ - bus daemon check
+    bin\bus-test.exe <build-root>\test\data
+
+ - check available names
+    bin\test_names.exe
+
+ - check if dbus-daemon is accessable
+    bin\dbus-send.exe --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.ListNames method return sender=org.freedesktop.DBus -> dest=:1.4 array [ string "org.freedesktop.DBus"string ":1.4"]
+
+ - start session dbus-daemon
+    either by running
+        bin\dbus-launch
+    or
+        start bin\dbus-daemon --session
+
+    Before running these commands you may execute
+        set DBUS_VERBOSE=1
+    for getting debug infos
+
+
+ - call function registerd in dbus
+    bin\dbus-send.exe  --dest=org.freedesktop.DBus --print-reply --type=method_call / org.freedesktop.DBus.StartServiceByName string:org.freedesktop.DBus.TestSuiteEchoService  uint32:455 method return sender=org.freedesktop.DBus -> dest=:1.8 uint32 2
+
+    note: When building with the Visual C++ IDE the *.exe files are in
+          the bin/Debug and bin/Release folder, not in the bin folder.
+
+
+FAQ
+---
+
+- How far is WinDBus from being usable for production ?
+
+  dbus comes with a test suite which is used on unix to guarantate
+  production quality and this test suite runs mostly. There are some
+  test not running and we need help to get them running.
+  In the pratice I and some other people are using dbus for at least more
+  than four years in conjunction with kde on windows without any problems.
+
+- On UNIX D-Bus uses UNIX sockets to communicate (correct me if I'm wrong).
+  What is used on Windows ?
+
+  tcp sockets, there are some efforts to get named pipe running, but some
+  design problems of the win32 api, we are not able to solve without
+  bigger changes to the dbus code base let us stop this effort.
+
+- Do you have any clue if dbus-win32 can run in a Windows CE environment?
+
+  dbus has been ported to wince, see README.wince for more information
+
+- Do you know if the C++ binding made by OpenWengo will be easily portable to Windows?
+
+  The OpenWengo dbus-c++ binding has been ported to windows see in WinDBus svn
+  (http://sf.net/projects/windbus)
+  The related test applicationa are running well.
+
+
+TODO
+----
+
+Oktober 2010:
+
+- the code wrapped with DBUS_WIN_FIXME should be inspected if it required for windows
+
+- create a dbus setup installer
+
+- implement system bus and system bus service starter
+  see http://windbus.svn.sourceforge.net/viewvc/windbus/trunk/bus/bus-service-win.c
+  for a starting point
+
+- implement a real login session bus
+  The scope parameter of the autolaunch meta protocol could be extended to support user
+  specific session busses (like already done with the amarok bundled dbus which use a
+  shared memory area named "DBusDaemonAddressInfo:<username>".
+  Also the dbus installer should start a session bus on user login.
diff --git a/dbus/README.wince b/dbus/README.wince
new file mode 100644
index 0000000..5790dcf
--- /dev/null
+++ b/dbus/README.wince
@@ -0,0 +1,81 @@
+DBus Daemon for Windows CE/Windows Mobile 6.5
+=============================================
+
+Bugs in upstream for any window version:
+* MoveFileExA < 0 result check bug
+* double dbus_free somewhere I forgot where (check in -ugly)
+* alignment issue
+* CreateProcess process information handle leak
+* _dbus_getsid NULL vs INVALID_HANDLE_VALUE
+* win_account_to_sid
+
+Customisation
+=============
+
+1) At installation, the following registry value should be set to the
+installation directory of the dbus installation (the directory
+containing the bin, etc, share folders):
+
+HKLM\Software\freedesktop\DBus\Install Directory
+
+2) Instead of environment variable DBUS_VERBOSE, use
+HKLM\Software\freedesktop\DBus\Verbose
+
+2) The keyring directory is MYDOCUMENTS\dbus-keyrings, not
+HOMEPATH\.dbus-keyrings.
+
+
+Compilation
+===========
+
+./configure --host=arm-mingw32ce CPPFLAGS=-I/path/to/expat/include LDFLAGS=-L/path/to/expat/lib
+
+A recent version of libtool is required, with this change:
+
+2010-02-28  Pierre Ossman  <ossman@ossman.lkpg.cendio.se>  (tiny change)
+            Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
+
+       Fix deplibs check fallback for 64-bit Windows and Windows CE.
+       * libltdl/m4/libtool.m4 (_LT_CHECK_MAGIC_METHOD): Accept file formats
+       'pe-arm-wince' and 'pe-x86-64'.  Add note about consistency with ...
+       * libltdl/config/ltmain.m4sh (func_win32_libid): ... the respective
+       pattern here; sync pattern from the former.
+       * tests/deplibs-mingw.at (deplibs without file command): New
+       file, new test.
+       * Makefile.am (TESTSUITE_AT): Update.
+       * NEWS: Update.
+
+
+MB vs WCHAR
+===========
+
+Windows CE only supports the Unicode interface, while DBus Daemon uses
+the Multi-Byte interface on Windows by default.  The glue code does
+not support multibyte in all cases.  In particular, the _mbsrchr
+function is not correctly implemented.  It could be correctly
+implemented, or dbus daemon could use the wchar interface more
+consistently on all Windows targets.  For now, the Windows CE port
+will only work for filesystems without some weird characters in file
+names.  Is this a serious limitation?
+
+
+Known Issues
+============
+
+Autolaunch is broken so far.
+
+Environment variables are faked.  Some are punted to the registry, but
+in any case they can not be used reliably for IPC.
+
+The test suite is not ported yet.
+
+dbus-pipe.c:
+ * Uses libc file descriptors.  Needed for --print-address and
+   --print-pid which probably don't work yet.
+
+dbus-sysdeps-win.c:
+ * Backtraces have been disabled.
+ * _dbus_fd_set_close_on_exec Not supported, maybe we should disable
+   the warning.
+ * SearchPathA: Uses HKLM\\Software\\freedesktop\\DBus\\Install Directory
+   to locate binaries.
diff --git a/dbus/autogen.sh b/dbus/autogen.sh
new file mode 100755
index 0000000..1558112
--- /dev/null
+++ b/dbus/autogen.sh
@@ -0,0 +1,111 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+PROJECT=dbus
+TEST_TYPE=-f
+FILE=dbus-1.pc.in
+
+DIE=0
+
+if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then
+    echo "Activating pre-commit hook."
+    cp -av .git/hooks/pre-commit.sample .git/hooks/pre-commit
+    chmod -c +x  .git/hooks/pre-commit
+fi
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+	echo
+	echo "You must have autoconf installed to compile $PROJECT."
+	echo "Download the appropriate package for your distribution,"
+	echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+	DIE=1
+}
+
+# If the user hasn't explicitly chosen an Automake version, use 1.11. This is
+# the earliest version that gives us silent rules.
+if test -z "$AUTOMAKE"; then
+    AUTOMAKE=automake-1.11
+    ACLOCAL=aclocal-1.11
+fi
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+        AUTOMAKE=automake
+        ACLOCAL=aclocal
+}
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+	echo
+	echo "You must have automake installed to compile $PROJECT."
+	echo "Get ftp://ftp.cygnus.com/pub/home/tromey/automake-1.2d.tar.gz"
+	echo "(or a newer version if it is available)"
+	DIE=1
+}
+
+LIBTOOLIZE=`which libtoolize`
+if ! test -f $LIBTOOLIZE; then
+	LIBTOOLIZE=`which glibtoolize`
+fi
+
+($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+	echo
+	echo "You must have libtoolize installed to compile $PROJECT."
+	echo "Install the libtool package from ftp.gnu.org or a mirror."
+	DIE=1
+}
+
+if test "$DIE" -eq 1; then
+	exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+	echo "You must run this script in the top-level $PROJECT directory"
+	exit 1
+}
+
+if test -z "$*"; then
+	echo "I am going to run ./configure with no arguments - if you wish "
+        echo "to pass any to it, please specify them on the $0 command line."
+fi
+
+$LIBTOOLIZE --copy --force
+
+$ACLOCAL -I m4 $ACLOCAL_FLAGS
+
+## optionally feature autoheader
+(autoheader --version)  < /dev/null > /dev/null 2>&1 && autoheader
+
+$AUTOMAKE -a $am_opt
+autoconf || echo "autoconf failed - version 2.5x is probably required"
+
+cd $ORIGDIR
+
+if test x"$NOCONFIGURE" = x; then
+  run_configure=true
+  for arg in $*; do
+    case $arg in 
+        --no-configure)
+            run_configure=false
+            ;;
+        *)
+            ;;
+    esac
+  done
+else
+  run_configure=false
+fi
+
+if $run_configure; then
+    $srcdir/configure --enable-developer --config-cache "$@"
+    echo 
+    echo "Now type 'make' to compile $PROJECT."
+else
+    echo
+    echo "Now run 'configure' and 'make' to compile $PROJECT."
+fi
+
diff --git a/dbus/bus/Android.bp b/dbus/bus/Android.bp
new file mode 100644
index 0000000..7ab773b
--- /dev/null
+++ b/dbus/bus/Android.bp
@@ -0,0 +1,41 @@
+cc_binary {
+    name: "dbus-daemon",
+
+    cflags: [
+        "-O3",
+        "-DDBUS_COMPILATION",
+        "-DDBUS_DAEMON_NAME=\\\"dbus-daemon\\\"",
+        "-DDBUS_SYSTEM_CONFIG_FILE=\\\"/system/etc/dbus.conf\\\"",
+        "-DDBUS_SESSION_CONFIG_FILE=\\\"/system/etc/session.conf\\\"",
+        "-Wno-address",
+        "-Wno-empty-body",
+        "-Wno-pointer-sign",
+        "-Wno-sign-compare",
+        "-Wno-unused-parameter",
+    ],
+
+    srcs: [
+        "activation.c",
+        "bus.c",
+        "config-loader-expat.c",
+        "config-parser.c",
+        "config-parser-common.c",
+        "connection.c",
+        "desktop-file.c",
+        "dir-watch-default.c",
+        "dispatch.c",
+        "driver.c",
+        "expirelist.c",
+        "main.c",
+        "policy.c",
+        "selinux.c",
+        "services.c",
+        "signals.c",
+        "utils.c",
+    ],
+
+    shared_libs: [
+        "libexpat",
+        "libdbus",
+    ],
+}
diff --git a/dbus/bus/Makefile.am b/dbus/bus/Makefile.am
new file mode 100644
index 0000000..6cbc09a
--- /dev/null
+++ b/dbus/bus/Makefile.am
@@ -0,0 +1,292 @@
+configdir=$(sysconfdir)/dbus-1
+dbus_daemon_execdir = $(DBUS_DAEMONDIR)
+
+DBUS_BUS_LIBS = \
+	$(XML_LIBS) \
+	$(SELINUX_LIBS) \
+	$(THREAD_LIBS) \
+	$(ADT_LIBS) \
+	$(NETWORK_libs) \
+	$(NULL)
+
+DBUS_LAUNCHER_LIBS = \
+	$(XML_LIBS) \
+	$(THREAD_LIBS) \
+	$(NETWORK_libs) \
+	$(NULL)
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir) \
+	$(XML_CFLAGS) \
+	-DDBUS_SYSTEM_CONFIG_FILE=\""$(configdir)/system.conf"\" \
+	-DDBUS_COMPILATION \
+	-DDBUS_STATIC_BUILD \
+	$(NULL)
+
+# if assertions are enabled, improve backtraces
+AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
+
+EFENCE=
+
+CONFIG_IN_FILES=				\
+	session.conf.in				\
+	system.conf.in				\
+	org.freedesktop.dbus-session.plist.in
+
+config_DATA=					\
+	session.conf				\
+	system.conf
+
+if DBUS_ENABLE_LAUNCHD
+agentdir=$(LAUNCHD_AGENT_DIR)
+agent_DATA=org.freedesktop.dbus-session.plist
+endif
+
+if DBUS_USE_LIBXML
+XML_SOURCES=config-loader-libxml.c
+endif
+if DBUS_USE_EXPAT
+XML_SOURCES=config-loader-expat.c
+endif
+
+if DBUS_BUS_ENABLE_KQUEUE
+DIR_WATCH_SOURCE=dir-watch-kqueue.c
+else
+if DBUS_BUS_ENABLE_INOTIFY
+DIR_WATCH_SOURCE=dir-watch-inotify.c
+else
+if DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX
+DIR_WATCH_SOURCE=dir-watch-dnotify.c
+else
+DIR_WATCH_SOURCE=dir-watch-default.c
+endif
+endif
+endif
+
+BUS_SOURCES=					\
+	activation.c				\
+	activation.h				\
+	activation-exit-codes.h			\
+	bus.c					\
+	bus.h					\
+	config-parser.c				\
+	config-parser.h				\
+	config-parser-common.c			\
+	config-parser-common.h			\
+	connection.c				\
+	connection.h				\
+	desktop-file.c				\
+	desktop-file.h				\
+	$(DIR_WATCH_SOURCE)			\
+	dir-watch.h				\
+	dispatch.c				\
+	dispatch.h				\
+	driver.c				\
+	driver.h				\
+	expirelist.c				\
+	expirelist.h				\
+	policy.c				\
+	policy.h				\
+	selinux.h				\
+	selinux.c				\
+	services.c				\
+	services.h				\
+	signals.c				\
+	signals.h				\
+	stats.c					\
+	stats.h					\
+	test.c					\
+	test.h					\
+	utils.c					\
+	utils.h					\
+	$(XML_SOURCES)
+
+dbus_daemon_SOURCES=				\
+	$(BUS_SOURCES)				\
+	main.c
+
+dbus_daemon_LDADD=					\
+	$(top_builddir)/dbus/libdbus-internal.la	\
+	$(EFENCE)					\
+	$(DBUS_BUS_LIBS)
+
+LAUNCH_HELPER_SOURCES=				\
+	$(XML_SOURCES)				\
+	config-parser-common.c			\
+	config-parser-common.h			\
+	config-parser-trivial.c			\
+	config-parser-trivial.h			\
+	desktop-file.c				\
+	desktop-file.h				\
+	utils.c					\
+	utils.h					\
+	activation-exit-codes.h			\
+	activation-helper.h	  		\
+	activation-helper.c
+
+## This is the installed launch helper with the setuid checks
+dbus_daemon_launch_helper_SOURCES=		\
+	activation-helper-bin.c			\
+	$(LAUNCH_HELPER_SOURCES)
+
+dbus_daemon_launch_helper_LDADD=		\
+	$(top_builddir)/dbus/libdbus-internal.la \
+	$(DBUS_LAUNCHER_LIBS)
+
+## we build another binary so we can do the launch testing without root privs.
+## DO NOT INSTALL THIS FILE
+dbus_daemon_launch_helper_test_SOURCES=		\
+	activation-helper-bin.c			\
+	$(LAUNCH_HELPER_SOURCES)
+
+dbus_daemon_launch_helper_test_LDADD=		\
+	$(top_builddir)/dbus/libdbus-internal.la \
+	$(DBUS_LAUNCHER_LIBS)
+
+dbus_daemon_launch_helper_test_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	-DACTIVATION_LAUNCHER_TEST
+
+## we build yet another binary so we can do the OOM tests
+## DO NOT INSTALL THIS FILE
+bus_test_launch_helper_SOURCES=		\
+	test-launch-helper.c   		\
+	$(LAUNCH_HELPER_SOURCES)
+
+bus_test_launch_helper_LDADD=		\
+	$(top_builddir)/dbus/libdbus-internal.la \
+	$(DBUS_LAUNCHER_LIBS)
+
+bus_test_launch_helper_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	-DACTIVATION_LAUNCHER_TEST	\
+	-DACTIVATION_LAUNCHER_DO_OOM
+
+noinst_PROGRAMS =
+dbus_daemon_exec_PROGRAMS = dbus-daemon
+if DBUS_UNIX
+libexec_PROGRAMS = dbus-daemon-launch-helper
+endif DBUS_UNIX
+
+## Note that TESTS has special meaning (stuff to use in make check).
+## We don't actually want to run any of these tests until test/ has been
+## compiled, so we don't put them in TESTS here; we run them in test/
+## instead.
+
+if DBUS_BUILD_TESTS
+## we use noinst_PROGRAMS not check_PROGRAMS so that we build
+## even when not doing "make check"
+
+# run as a test by test/Makefile.am
+noinst_PROGRAMS += bus-test bus-test-system
+
+if DBUS_UNIX
+# run as a test by test/Makefile.am
+noinst_PROGRAMS += bus-test-launch-helper
+# this is used by the tests but is not,itself, a test
+noinst_PROGRAMS += dbus-daemon-launch-helper-test
+endif DBUS_UNIX
+
+endif DBUS_BUILD_TESTS
+
+bus_test_system_SOURCES=			\
+	$(XML_SOURCES)				\
+	config-parser-common.c			\
+	config-parser-common.h			\
+	config-parser-trivial.c			\
+	config-parser-trivial.h			\
+	utils.c					\
+	utils.h					\
+	test-system.c
+
+bus_test_system_LDADD=$(top_builddir)/dbus/libdbus-internal.la $(DBUS_BUS_LIBS)
+
+bus_test_SOURCES=				\
+	$(BUS_SOURCES)				\
+	test-main.c
+
+bus_test_LDADD=$(top_builddir)/dbus/libdbus-internal.la $(DBUS_BUS_LIBS)
+
+## mop up the gcov files
+clean-local:
+	/bin/rm *.bb *.bbg *.da *.gcov || true
+
+install-data-hook:
+	$(mkinstalldirs) $(DESTDIR)$(localstatedir)/run/dbus
+	$(mkinstalldirs) $(DESTDIR)$(configdir)/system.d
+	$(mkinstalldirs) $(DESTDIR)$(configdir)/session.d
+	$(mkinstalldirs) $(DESTDIR)$(datadir)/dbus-1/services
+	$(mkinstalldirs) $(DESTDIR)$(datadir)/dbus-1/system-services
+if HAVE_SYSTEMD
+# Install dbus.socket as default implementation of a D-Bus stack.
+# Deliberately not using $(LN_S) here: ln -fs is not universally portable,
+# but neither is systemd, so it's OK to assume here that ln complies with SUS.
+	$(mkinstalldirs) $(DESTDIR)$(systemdsystemunitdir)/dbus.target.wants
+	ln -fs ../dbus.socket $(DESTDIR)$(systemdsystemunitdir)/dbus.target.wants/dbus.socket
+# Unconditionally enable D-Bus on systemd installations
+	$(mkinstalldirs) $(DESTDIR)$(systemdsystemunitdir)/sockets.target.wants
+	ln -fs ../dbus.socket $(DESTDIR)$(systemdsystemunitdir)/sockets.target.wants/dbus.socket
+	$(mkinstalldirs) $(DESTDIR)$(systemdsystemunitdir)/multi-user.target.wants
+	ln -fs ../dbus.service $(DESTDIR)$(systemdsystemunitdir)/multi-user.target.wants/dbus.service
+endif
+
+if DBUS_UNIX
+install-exec-hook:
+	if test `id -u` -eq 0; then \
+		chown root:$(DBUS_USER) $(DESTDIR)$(libexecdir)/dbus-daemon-launch-helper$(EXEEXT); \
+		chmod 4750 $(DESTDIR)$(libexecdir)/dbus-daemon-launch-helper$(EXEEXT); \
+	else \
+		echo "Not installing $(DESTDIR)$(libexecdir)/dbus-daemon-launch-helper binary setuid!"; \
+		echo "You'll need to manually set permissions to root:$(DBUS_USER) and permissions 4750"; \
+	fi
+endif
+
+#### Init scripts fun
+SCRIPT_IN_FILES=messagebus.in \
+		messagebus-config.in \
+		rc.messagebus.in
+
+## Red Hat start
+if DBUS_INIT_SCRIPTS_RED_HAT
+
+initddir=$(sysconfdir)/rc.d/init.d
+
+initd_SCRIPTS= 	\
+	messagebus
+
+endif
+ ## Red Hat end
+
+## Slackware start
+if DBUS_INIT_SCRIPTS_SLACKWARE
+
+initddir=$(sysconfdir)/rc.d/
+
+initd_SCRIPTS= 	\
+	rc.messagebus
+
+endif
+## Slackware end
+
+## Cygwin start
+if DBUS_INIT_SCRIPTS_CYGWIN
+
+bin_SCRIPTS= 	\
+	messagebus-config
+
+endif
+## Cygwin end
+
+if HAVE_SYSTEMD
+SCRIPT_IN_FILES += \
+	dbus.service.in \
+	dbus.socket.in
+
+systemdsystemunit_DATA = \
+	dbus.service \
+	dbus.socket
+endif
+
+#### Extra dist
+
+EXTRA_DIST=$(CONFIG_IN_FILES) $(SCRIPT_IN_FILES)
diff --git a/dbus/bus/NOTICE b/dbus/bus/NOTICE
new file mode 100644
index 0000000..a91ca1d
--- /dev/null
+++ b/dbus/bus/NOTICE
@@ -0,0 +1,551 @@
+D-Bus is licensed to you under your choice of the Academic Free
+License version 2.1, or the GNU General Public License version 2.
+Both licenses are included here. Some of the standalone binaries are
+under the GPL only; in particular, but not limited to,
+tools/dbus-cleanup-sockets.c and test/decode-gcov.c. Each source code
+file is marked with the proper copyright information - if you find a
+file that isn't marked please bring it to our attention.
+
+
+The Academic Free License
+v. 2.1
+
+This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
+
+Licensed under the Academic Free License version 2.1
+
+1) Grant of Copyright License. Licensor hereby grants You a
+world-wide, royalty-free, non-exclusive, perpetual, sublicenseable
+license to do the following:
+
+a) to reproduce the Original Work in copies;
+
+b) to prepare derivative works ("Derivative Works") based upon the Original Work;
+
+c) to distribute copies of the Original Work and Derivative Works to the public;
+
+d) to perform the Original Work publicly; and
+
+e) to display the Original Work publicly.
+
+2) Grant of Patent License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license, under
+patent claims owned or controlled by the Licensor that are embodied in
+the Original Work as furnished by the Licensor, to make, use, sell and
+offer for sale the Original Work and Derivative Works.
+
+3) Grant of Source Code License. The term "Source Code" means the
+preferred form of the Original Work for making modifications to it and
+all available documentation describing how to modify the Original
+Work. Licensor hereby agrees to provide a machine-readable copy of the
+Source Code of the Original Work along with each copy of the Original
+Work that Licensor distributes. Licensor reserves the right to satisfy
+this obligation by placing a machine-readable copy of the Source Code
+in an information repository reasonably calculated to permit
+inexpensive and convenient access by You for as long as Licensor
+continues to distribute the Original Work, and by publishing the
+address of that information repository in a notice immediately
+following the copyright notice that applies to the Original Work.
+
+4) Exclusions From License Grant. Neither the names of Licensor, nor
+the names of any contributors to the Original Work, nor any of their
+trademarks or service marks, may be used to endorse or promote
+products derived from this Original Work without express prior written
+permission of the Licensor. Nothing in this License shall be deemed to
+grant any rights to trademarks, copyrights, patents, trade secrets or
+any other intellectual property of Licensor except as expressly stated
+herein. No patent license is granted to make, use, sell or offer to
+sell embodiments of any patent claims other than the licensed claims
+defined in Section 2. No right is granted to the trademarks of
+Licensor even if such marks are included in the Original Work. Nothing
+in this License shall be interpreted to prohibit Licensor from
+licensing under different terms from this License any Original Work
+that Licensor otherwise would have a right to license.
+
+5) This section intentionally omitted.
+
+6) Attribution Rights. You must retain, in the Source Code of any
+Derivative Works that You create, all copyright, patent or trademark
+notices from the Source Code of the Original Work, as well as any
+notices of licensing and any descriptive text identified therein as an
+"Attribution Notice." You must cause the Source Code for any
+Derivative Works that You create to carry a prominent Attribution
+Notice reasonably calculated to inform recipients that You have
+modified the Original Work.
+
+7) Warranty of Provenance and Disclaimer of Warranty. Licensor
+warrants that the copyright in and to the Original Work and the patent
+rights granted herein by Licensor are owned by the Licensor or are
+sublicensed to You under the terms of this License with the permission
+of the contributor(s) of those copyrights and patent rights. Except as
+expressly stated in the immediately proceeding sentence, the Original
+Work is provided under this License on an "AS IS" BASIS and WITHOUT
+WARRANTY, either express or implied, including, without limitation,
+the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL
+WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential
+part of this License. No license to Original Work is granted hereunder
+except under this disclaimer.
+
+8) Limitation of Liability. Under no circumstances and under no legal
+theory, whether in tort (including negligence), contract, or
+otherwise, shall the Licensor be liable to any person for any direct,
+indirect, special, incidental, or consequential damages of any
+character arising as a result of this License or the use of the
+Original Work including, without limitation, damages for loss of
+goodwill, work stoppage, computer failure or malfunction, or any and
+all other commercial damages or losses. This limitation of liability
+shall not apply to liability for death or personal injury resulting
+from Licensor's negligence to the extent applicable law prohibits such
+limitation. Some jurisdictions do not allow the exclusion or
+limitation of incidental or consequential damages, so this exclusion
+and limitation may not apply to You.
+
+9) Acceptance and Termination. If You distribute copies of the
+Original Work or a Derivative Work, You must make a reasonable effort
+under the circumstances to obtain the express assent of recipients to
+the terms of this License. Nothing else but this License (or another
+written agreement between Licensor and You) grants You permission to
+create Derivative Works based upon the Original Work or to exercise
+any of the rights granted in Section 1 herein, and any attempt to do
+so except under the terms of this License (or another written
+agreement between Licensor and You) is expressly prohibited by
+U.S. copyright law, the equivalent laws of other countries, and by
+international treaty. Therefore, by exercising any of the rights
+granted to You in Section 1 herein, You indicate Your acceptance of
+this License and all of its terms and conditions.
+
+10) Termination for Patent Action. This License shall terminate
+automatically and You may no longer exercise any of the rights granted
+to You by this License as of the date You commence an action,
+including a cross-claim or counterclaim, against Licensor or any
+licensee alleging that the Original Work infringes a patent. This
+termination provision shall not apply for an action alleging patent
+infringement by combinations of the Original Work with other software
+or hardware.
+
+11) Jurisdiction, Venue and Governing Law. Any action or suit relating
+to this License may be brought only in the courts of a jurisdiction
+wherein the Licensor resides or in which Licensor conducts its primary
+business, and under the laws of that jurisdiction excluding its
+conflict-of-law provisions. The application of the United Nations
+Convention on Contracts for the International Sale of Goods is
+expressly excluded. Any use of the Original Work outside the scope of
+this License or after its termination shall be subject to the
+requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101
+et seq., the equivalent laws of other countries, and international
+treaty. This section shall survive the termination of this License.
+
+12) Attorneys Fees. In any action to enforce the terms of this License
+or seeking damages relating thereto, the prevailing party shall be
+entitled to recover its costs and expenses, including, without
+limitation, reasonable attorneys' fees and costs incurred in
+connection with such action, including any appeal of such action. This
+section shall survive the termination of this License.
+
+13) Miscellaneous. This License represents the complete agreement
+concerning the subject matter hereof. If any provision of this License
+is held to be unenforceable, such provision shall be reformed only to
+the extent necessary to make it enforceable.
+
+14) Definition of "You" in This License. "You" throughout this
+License, whether in upper or lower case, means an individual or a
+legal entity exercising rights under, and complying with all of the
+terms of, this License. For legal entities, "You" includes any entity
+that controls, is controlled by, or is under common control with
+you. For purposes of this definition, "control" means (i) the power,
+direct or indirect, to cause the direction or management of such
+entity, whether by contract or otherwise, or (ii) ownership of fifty
+percent (50%) or more of the outstanding shares, or (iii) beneficial
+ownership of such entity.
+
+15) Right to Use. You may use the Original Work in all ways not
+otherwise restricted or conditioned by this License or by law, and
+Licensor promises not to interfere with or be responsible for such
+uses by You.
+
+This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights
+reserved. Permission is hereby granted to copy and distribute this
+license without modification. This license may not be modified without
+the express written permission of its copyright owner.
+
+
+-- 
+END OF ACADEMIC FREE LICENSE. The following is intended to describe the essential 
+differences between the Academic Free License (AFL) version 1.0 and other 
+open source licenses:
+
+The Academic Free License is similar to the BSD, MIT, UoI/NCSA and Apache 
+licenses in many respects but it is intended to solve a few problems with 
+those licenses.
+    
+* The AFL is written so as to make it clear what software is being 
+licensed (by the inclusion of a statement following the copyright notice 
+in the software). This way, the license functions better than a template 
+license. The BSD, MIT and UoI/NCSA licenses apply to unidentified software.
+    
+* The AFL contains a complete copyright grant to the software. The BSD 
+and Apache licenses are vague and incomplete in that respect.
+    
+* The AFL contains a complete patent grant to the software. The BSD, MIT, 
+UoI/NCSA and Apache licenses rely on an implied patent license and contain 
+no explicit patent grant.
+    
+* The AFL makes it clear that no trademark rights are granted to the 
+licensor's trademarks. The Apache license contains such a provision, but the 
+BSD, MIT and UoI/NCSA licenses do not.
+    
+* The AFL includes the warranty by the licensor that it either owns the 
+copyright or that it is distributing the software under a license. None of 
+the other licenses contain that warranty. All other warranties are disclaimed, 
+as is the case for the other licenses.
+
+* The AFL is itself copyrighted (with the right granted to copy and distribute 
+without modification). This ensures that the owner of the copyright to the 
+license will control changes. The Apache license contains a copyright notice, 
+but the BSD, MIT and UoI/NCSA licenses do not. 
+--
+START OF GNU GENERAL PUBLIC LICENSE
+--
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/dbus/bus/activation-exit-codes.h b/dbus/bus/activation-exit-codes.h
new file mode 100644
index 0000000..bbb98dc
--- /dev/null
+++ b/dbus/bus/activation-exit-codes.h
@@ -0,0 +1,45 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* activation-exit-codes.h  Return values for the launch helper which is set
+ *                          in the helper and read in dbus-spawn.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_ACTIVATION_EXIT_CODES_H
+#define BUS_ACTIVATION_EXIT_CODES_H
+
+/** Return codes from the launch helper - not public API. However,
+ *  presumably if some third party did write their own launch helper,
+ *  they would have to rely on these, or at least always return
+ *  1 for GENERIC_FAILURE.
+ */
+#define BUS_SPAWN_EXIT_CODE_GENERIC_FAILURE      1
+#define BUS_SPAWN_EXIT_CODE_NO_MEMORY            2
+#define BUS_SPAWN_EXIT_CODE_CONFIG_INVALID       3
+#define BUS_SPAWN_EXIT_CODE_SETUP_FAILED         4
+#define BUS_SPAWN_EXIT_CODE_NAME_INVALID         5
+#define BUS_SPAWN_EXIT_CODE_SERVICE_NOT_FOUND    6
+#define BUS_SPAWN_EXIT_CODE_PERMISSIONS_INVALID  7
+#define BUS_SPAWN_EXIT_CODE_FILE_INVALID         8
+#define BUS_SPAWN_EXIT_CODE_EXEC_FAILED          9
+#define BUS_SPAWN_EXIT_CODE_INVALID_ARGS         10
+#define BUS_SPAWN_EXIT_CODE_CHILD_SIGNALED       11
+
+#endif /* BUS_ACTIVATION_EXIT_CODES_H */
diff --git a/dbus/bus/activation-helper-bin.c b/dbus/bus/activation-helper-bin.c
new file mode 100644
index 0000000..a360acc
--- /dev/null
+++ b/dbus/bus/activation-helper-bin.c
@@ -0,0 +1,100 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* activation-helper-bin.c  Setuid helper for launching programs as a custom
+ *                          user. This file is security sensitive.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include "utils.h"
+#include "activation-helper.h"
+#include "activation-exit-codes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int
+convert_error_to_exit_code (DBusError *error)
+{
+  if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
+    return BUS_SPAWN_EXIT_CODE_NO_MEMORY;
+
+  if (dbus_error_has_name (error, DBUS_ERROR_SPAWN_CONFIG_INVALID))
+    return BUS_SPAWN_EXIT_CODE_CONFIG_INVALID;
+
+  if (dbus_error_has_name (error, DBUS_ERROR_SPAWN_SETUP_FAILED))
+    return BUS_SPAWN_EXIT_CODE_SETUP_FAILED;
+
+  if (dbus_error_has_name (error, DBUS_ERROR_SPAWN_SERVICE_INVALID))
+    return BUS_SPAWN_EXIT_CODE_SERVICE_NOT_FOUND;
+
+  if (dbus_error_has_name (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID))
+    return BUS_SPAWN_EXIT_CODE_PERMISSIONS_INVALID;
+
+  if (dbus_error_has_name (error, DBUS_ERROR_SPAWN_FILE_INVALID))
+    return BUS_SPAWN_EXIT_CODE_FILE_INVALID;
+
+  if (dbus_error_has_name (error, DBUS_ERROR_SPAWN_EXEC_FAILED))
+    return BUS_SPAWN_EXIT_CODE_EXEC_FAILED;
+
+  if (dbus_error_has_name (error, DBUS_ERROR_INVALID_ARGS))
+    return BUS_SPAWN_EXIT_CODE_INVALID_ARGS;
+
+  if (dbus_error_has_name (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED))
+    return BUS_SPAWN_EXIT_CODE_CHILD_SIGNALED;
+  
+  /* should we assert? */
+  fprintf(stderr, "%s: %s\n", error->name, error->message);
+  
+  return BUS_SPAWN_EXIT_CODE_SETUP_FAILED;
+}
+
+int
+main (int argc, char **argv)
+{
+  DBusError error;
+  int retval;
+
+  /* default is all okay */
+  retval = 0;
+
+  /* have we used a help option or not specified the correct arguments? */
+  if (argc != 2 ||
+      strcmp (argv[1], "--help") == 0 ||
+      strcmp (argv[1], "-h") == 0 ||
+      strcmp (argv[1], "-?") == 0)
+    {
+        fprintf (stderr, "dbus-daemon-activation-helper service.to.activate\n");
+        exit (0);
+    }
+
+  dbus_error_init (&error);
+  if (!run_launch_helper (argv[1], &error))
+    {
+      /* convert error to an exit code */
+      retval = convert_error_to_exit_code (&error);
+      dbus_error_free (&error);
+    }
+
+  return retval;
+}
+
diff --git a/dbus/bus/activation-helper.c b/dbus/bus/activation-helper.c
new file mode 100644
index 0000000..cbc00d2
--- /dev/null
+++ b/dbus/bus/activation-helper.c
@@ -0,0 +1,548 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* activation-helper.c  Setuid helper for launching programs as a custom
+ *                      user. This file is security sensitive.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include "bus.h"
+#include "driver.h"
+#include "utils.h"
+#include "desktop-file.h"
+#include "config-parser-trivial.h"
+#include "activation-helper.h"
+#include "activation-exit-codes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <dbus/dbus-shell.h>
+#include <dbus/dbus-marshal-validate.h>
+
+static BusDesktopFile *
+desktop_file_for_name (BusConfigParser *parser,
+                       const char *name,
+                       DBusError  *error)
+{
+  BusDesktopFile *desktop_file;
+  DBusList **service_dirs;
+  DBusList *link;
+  DBusError tmp_error;
+  DBusString full_path;
+  DBusString filename;
+  const char *dir;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  desktop_file = NULL;
+
+  if (!_dbus_string_init (&filename))
+    {
+      BUS_SET_OOM (error);
+      goto out_all;
+    }
+
+  if (!_dbus_string_init (&full_path))
+    {
+      BUS_SET_OOM (error);
+      goto out_filename;
+    }
+
+  if (!_dbus_string_append (&filename, name) ||
+      !_dbus_string_append (&filename, ".service"))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  service_dirs = bus_config_parser_get_service_dirs (parser);
+  for (link = _dbus_list_get_first_link (service_dirs);
+       link != NULL;
+       link = _dbus_list_get_next_link (service_dirs, link))
+    {
+      dir = link->data;
+      _dbus_verbose ("Looking at '%s'\n", dir);
+
+      dbus_error_init (&tmp_error);
+
+      /* clear the path from last time */
+      _dbus_string_set_length (&full_path, 0);
+
+      /* build the full path */
+      if (!_dbus_string_append (&full_path, dir) ||
+          !_dbus_concat_dir_and_file (&full_path, &filename))
+        {
+          BUS_SET_OOM (error);
+          goto out;
+        }
+
+      _dbus_verbose ("Trying to load file '%s'\n", _dbus_string_get_data (&full_path));
+      desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
+      if (desktop_file == NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+          _dbus_verbose ("Could not load %s: %s: %s\n",
+                         _dbus_string_get_const_data (&full_path),
+                         tmp_error.name, tmp_error.message);
+
+          /* we may have failed if the file is not found; this is not fatal */
+          if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_move_error (&tmp_error, error);
+              /* we only bail out on OOM */
+              goto out;
+            }
+          dbus_error_free (&tmp_error);
+        }
+
+      /* did we find the desktop file we want? */
+      if (desktop_file != NULL)
+        break;
+    }
+
+  /* Didn't find desktop file; set error */
+  if (desktop_file == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
+                      "The name %s was not provided by any .service files",
+                      name);
+    }
+
+out:
+  _dbus_string_free (&full_path);
+out_filename:
+  _dbus_string_free (&filename);
+out_all:
+  return desktop_file;
+}
+
+/* Clears the environment, except for DBUS_STARTER_x,
+ * which we hardcode to the system bus.
+ */
+static dbus_bool_t
+clear_environment (DBusError *error)
+{
+#ifndef ACTIVATION_LAUNCHER_TEST
+  /* totally clear the environment */
+  if (!_dbus_clearenv ())
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
+                      "could not clear environment\n");
+      return FALSE;
+    }
+#endif
+
+  /* Ensure the bus is set to system */
+  _dbus_setenv ("DBUS_STARTER_ADDRESS", DBUS_SYSTEM_BUS_DEFAULT_ADDRESS);
+  _dbus_setenv ("DBUS_STARTER_BUS_TYPE", "system");
+
+  return TRUE;
+}
+
+static dbus_bool_t
+check_permissions (const char *dbus_user, DBusError *error)
+{
+#ifndef ACTIVATION_LAUNCHER_TEST
+  uid_t uid, euid;
+  struct passwd *pw;
+
+  pw = NULL;
+  uid = 0;
+  euid = 0;
+
+  /* bail out unless the dbus user is invoking the helper */
+  pw = getpwnam(dbus_user);
+  if (!pw)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
+                      "cannot find user '%s'", dbus_user);
+      return FALSE;
+    }
+  uid = getuid();
+  if (pw->pw_uid != uid)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
+                      "not invoked from user '%s'", dbus_user);
+      return FALSE;
+    }
+
+  /* bail out unless we are setuid to user root */
+  euid = geteuid();
+  if (euid != 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
+                      "not setuid root");
+      return FALSE;
+    }
+#endif
+
+  return TRUE;
+}
+
+static dbus_bool_t
+check_service_name (BusDesktopFile *desktop_file,
+                    const char     *service_name,
+                    DBusError      *error)
+{
+  char *name_tmp;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  /* try to get Name */
+  if (!bus_desktop_file_get_string (desktop_file,
+                                    DBUS_SERVICE_SECTION,
+                                    DBUS_SERVICE_NAME,
+                                    &name_tmp,
+                                    error))
+    goto failed;
+
+  /* verify that the name is the same as the file service name */
+  if (strcmp (service_name, name_tmp) != 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_FILE_INVALID,
+                      "Service '%s' does not match expected value", name_tmp);
+      goto failed_free;
+    }
+
+  retval = TRUE;
+
+failed_free:
+  /* we don't return the name, so free it here */
+  dbus_free (name_tmp);
+failed:
+  return retval;
+}
+
+static dbus_bool_t
+get_parameters_for_service (BusDesktopFile *desktop_file,
+                            const char     *service_name,
+                            char          **exec,
+                            char          **user,
+                            DBusError      *error)
+{
+  char *exec_tmp;
+  char *user_tmp;
+
+  exec_tmp = NULL;
+  user_tmp = NULL;
+
+  /* check the name of the service */
+  if (!check_service_name (desktop_file, service_name, error))
+    goto failed;
+
+  /* get the complete path of the executable */
+  if (!bus_desktop_file_get_string (desktop_file,
+                                    DBUS_SERVICE_SECTION,
+                                    DBUS_SERVICE_EXEC,
+                                    &exec_tmp,
+                                    error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+
+  /* get the user that should run this service - user is compulsary for system activation */
+  if (!bus_desktop_file_get_string (desktop_file,
+                                    DBUS_SERVICE_SECTION,
+                                    DBUS_SERVICE_USER,
+                                    &user_tmp,
+                                    error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+
+  /* only assign if all the checks passed */
+  *exec = exec_tmp;
+  *user = user_tmp;
+  return TRUE;
+
+failed:
+  dbus_free (exec_tmp);
+  dbus_free (user_tmp);
+  return FALSE;
+}
+
+static dbus_bool_t
+switch_user (char *user, DBusError *error)
+{
+#ifndef ACTIVATION_LAUNCHER_TEST
+  struct passwd *pw;
+
+  /* find user */
+  pw = getpwnam (user);
+  if (!pw)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
+                      "cannot find user '%s'\n", user);
+      return FALSE;
+    }
+
+  /* initialize the group access list */
+  if (initgroups (user, pw->pw_gid))
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
+                      "could not initialize groups");
+      return FALSE;
+    }
+
+  /* change to the primary group for the user */
+  if (setgid (pw->pw_gid))
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
+                      "cannot setgid group %i", pw->pw_gid);
+      return FALSE;
+    }
+
+  /* change to the user specified */
+  if (setuid (pw->pw_uid) < 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
+                      "cannot setuid user %i", pw->pw_uid);
+      return FALSE;
+    }
+#endif
+  return TRUE;
+}
+
+static dbus_bool_t
+exec_for_correct_user (char *exec, char *user, DBusError *error)
+{
+  char **argv;
+  int argc;
+  dbus_bool_t retval;
+
+  argc = 0;
+  retval = TRUE;
+  argv = NULL;
+
+  if (!switch_user (user, error))
+    return FALSE;
+
+  /* convert command into arguments */
+  if (!_dbus_shell_parse_argv (exec, &argc, &argv, error))
+    return FALSE;
+
+#ifndef ACTIVATION_LAUNCHER_DO_OOM
+  /* replace with new binary, with no environment */
+  if (execv (argv[0], argv) < 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
+                      "Failed to exec: %s", argv[0]);
+      retval = FALSE;
+    }
+#endif
+
+  dbus_free_string_array (argv);
+  return retval;
+}
+
+static dbus_bool_t
+check_bus_name (const char *bus_name,
+                DBusError  *error)
+{
+  DBusString str;
+
+  _dbus_string_init_const (&str, bus_name);
+  if (!_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
+                      "bus name '%s' is not a valid bus name\n",
+                      bus_name);
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+get_correct_parser (BusConfigParser **parser, DBusError *error)
+{
+  DBusString config_file;
+  dbus_bool_t retval;
+#ifdef ACTIVATION_LAUNCHER_TEST
+  const char *test_config_file;
+#endif
+
+  retval = FALSE;
+
+#ifdef ACTIVATION_LAUNCHER_TEST
+  test_config_file = NULL;
+
+  /* there is no _way_ we should be setuid if this define is set.
+   * but we should be doubly paranoid and check... */
+  if (getuid() != geteuid())
+    _dbus_assert_not_reached ("dbus-daemon-launch-helper-test binary is setuid!");
+
+  /* this is not a security hole. The environment variable is only passed in the
+   * dbus-daemon-lauch-helper-test NON-SETUID launcher */
+  test_config_file = _dbus_getenv ("TEST_LAUNCH_HELPER_CONFIG");
+  if (test_config_file == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
+                      "the TEST_LAUNCH_HELPER_CONFIG env variable is not set");
+      goto out;
+    }
+#endif
+
+  /* we _only_ use the predefined system config file */
+  if (!_dbus_string_init (&config_file))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+#ifndef ACTIVATION_LAUNCHER_TEST
+  if (!_dbus_string_append (&config_file, DBUS_SYSTEM_CONFIG_FILE))
+    {
+      BUS_SET_OOM (error);
+      goto out_free_config;
+    }
+#else
+  if (!_dbus_string_append (&config_file, test_config_file))
+    {
+      BUS_SET_OOM (error);
+      goto out_free_config;
+    }
+#endif
+
+  /* where are we pointing.... */
+  _dbus_verbose ("dbus-daemon-activation-helper: using config file: %s\n",
+                 _dbus_string_get_const_data (&config_file));
+
+  /* get the dbus user */
+  *parser = bus_config_load (&config_file, TRUE, NULL, error);
+  if (*parser == NULL)
+    {
+      goto out_free_config;
+    }
+
+  /* woot */
+  retval = TRUE;
+
+out_free_config:
+  _dbus_string_free (&config_file);
+out:
+  return retval;
+}
+
+static dbus_bool_t
+launch_bus_name (const char *bus_name, BusConfigParser *parser, DBusError *error)
+{
+  BusDesktopFile *desktop_file;
+  char *exec, *user;
+  dbus_bool_t retval;
+
+  exec = NULL;
+  user = NULL;
+  retval = FALSE;
+
+  /* get the correct service file for the name we are trying to activate */
+  desktop_file = desktop_file_for_name (parser, bus_name, error);
+  if (desktop_file == NULL)
+    return FALSE;
+
+  /* get exec and user for service name */
+  if (!get_parameters_for_service (desktop_file, bus_name, &exec, &user, error))
+    goto finish;
+
+  _dbus_verbose ("dbus-daemon-activation-helper: Name='%s'\n", bus_name);
+  _dbus_verbose ("dbus-daemon-activation-helper: Exec='%s'\n", exec);
+  _dbus_verbose ("dbus-daemon-activation-helper: User='%s'\n", user);
+
+  /* actually execute */
+  if (!exec_for_correct_user (exec, user, error))
+    goto finish;
+
+  retval = TRUE;
+
+finish:
+  dbus_free (exec);
+  dbus_free (user);
+  bus_desktop_file_free (desktop_file);
+  return retval;
+}
+
+static dbus_bool_t
+check_dbus_user (BusConfigParser *parser, DBusError *error)
+{
+  const char *dbus_user;
+
+  dbus_user = bus_config_parser_get_user (parser);
+  if (dbus_user == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_CONFIG_INVALID,
+                      "could not get user from config file\n");
+      return FALSE;
+    }
+
+  /* check to see if permissions are correct */
+  if (!check_permissions (dbus_user, error))
+    return FALSE;
+
+  return TRUE;
+}
+
+dbus_bool_t
+run_launch_helper (const char *bus_name,
+                   DBusError  *error)
+{
+  BusConfigParser *parser;
+  dbus_bool_t retval;
+
+  parser = NULL;
+  retval = FALSE;
+
+  /* clear the environment, apart from a few select settings */
+  if (!clear_environment (error))
+    goto error;
+
+  /* check to see if we have a valid bus name */
+  if (!check_bus_name (bus_name, error))
+    goto error;
+
+  /* get the correct parser, either the test or default parser */
+  if (!get_correct_parser (&parser, error))
+    goto error;
+
+  /* check we are being invoked by the correct dbus user */
+  if (!check_dbus_user (parser, error))
+    goto error_free_parser;
+
+  /* launch the bus with the service defined user */
+  if (!launch_bus_name (bus_name, parser, error))
+    goto error_free_parser;
+
+  /* woohoo! */
+  retval = TRUE;
+
+error_free_parser:
+  bus_config_parser_unref (parser);
+error:
+  return retval;
+}
+
diff --git a/dbus/bus/activation-helper.h b/dbus/bus/activation-helper.h
new file mode 100644
index 0000000..361a4c6
--- /dev/null
+++ b/dbus/bus/activation-helper.h
@@ -0,0 +1,31 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* activation-helper.h  The actual activation helper split from the main
+ *                      function for testing.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_ACTIVATION_HELPER_H
+#define BUS_ACTIVATION_HELPER_H
+
+dbus_bool_t run_launch_helper (const char *bus_name, DBusError *error);
+
+
+#endif /* BUS_ACTIVATION_HELPER_H */
diff --git a/dbus/bus/activation.c b/dbus/bus/activation.c
new file mode 100644
index 0000000..3dfba78
--- /dev/null
+++ b/dbus/bus/activation.c
@@ -0,0 +1,2573 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* activation.c  Activation of services
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2004  Imendio HB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "activation.h"
+#include "activation-exit-codes.h"
+#include "desktop-file.h"
+#include "dispatch.h"
+#include "services.h"
+#include "test.h"
+#include "utils.h"
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-hash.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-shell.h>
+#include <dbus/dbus-spawn.h>
+#include <dbus/dbus-timeout.h>
+#include <dbus/dbus-sysdeps.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+struct BusActivation
+{
+  int refcount;
+  DBusHashTable *entries;
+  DBusHashTable *pending_activations;
+  char *server_address;
+  BusContext *context;
+  int n_pending_activations; /**< This is in fact the number of BusPendingActivationEntry,
+                              * i.e. number of pending activation requests, not pending
+                              * activations per se
+                              */
+  DBusHashTable *directories;
+  DBusHashTable *environment;
+};
+
+typedef struct
+{
+  int refcount;
+  char *dir_c;
+  DBusHashTable *entries;
+} BusServiceDirectory;
+
+typedef struct
+{
+  int refcount;
+  char *name;
+  char *exec;
+  char *user;
+  char *systemd_service;
+  unsigned long mtime;
+  BusServiceDirectory *s_dir;
+  char *filename;
+} BusActivationEntry;
+
+typedef struct BusPendingActivationEntry BusPendingActivationEntry;
+
+struct BusPendingActivationEntry
+{
+  DBusMessage *activation_message;
+  DBusConnection *connection;
+
+  dbus_bool_t auto_activation;
+};
+
+typedef struct
+{
+  int refcount;
+  BusActivation *activation;
+  char *service_name;
+  char *exec;
+  char *systemd_service;
+  DBusList *entries;
+  int n_entries;
+  DBusBabysitter *babysitter;
+  DBusTimeout *timeout;
+  unsigned int timeout_added : 1;
+} BusPendingActivation;
+
+#if 0
+static BusServiceDirectory *
+bus_service_directory_ref (BusServiceDirectory *dir)
+{
+  _dbus_assert (dir->refcount);
+
+  dir->refcount++;
+
+  return dir;
+}
+#endif
+
+static void
+bus_service_directory_unref (BusServiceDirectory *dir)
+{
+  if (dir == NULL)
+    return;
+
+  _dbus_assert (dir->refcount > 0);
+  dir->refcount--;
+
+  if (dir->refcount > 0)
+    return;
+
+  if (dir->entries)
+    _dbus_hash_table_unref (dir->entries);
+
+  dbus_free (dir->dir_c);
+  dbus_free (dir);
+}
+
+static void
+bus_pending_activation_entry_free (BusPendingActivationEntry *entry)
+{
+  if (entry->activation_message)
+    dbus_message_unref (entry->activation_message);
+
+  if (entry->connection)
+    dbus_connection_unref (entry->connection);
+
+  dbus_free (entry);
+}
+
+static BusPendingActivation *
+bus_pending_activation_ref (BusPendingActivation *pending_activation)
+{
+  _dbus_assert (pending_activation->refcount > 0);
+  pending_activation->refcount += 1;
+
+  return pending_activation;
+}
+
+static void
+bus_pending_activation_unref (BusPendingActivation *pending_activation)
+{
+  DBusList *link;
+
+  if (pending_activation == NULL) /* hash table requires this */
+    return;
+
+  _dbus_assert (pending_activation->refcount > 0);
+  pending_activation->refcount -= 1;
+
+  if (pending_activation->refcount > 0)
+    return;
+
+  if (pending_activation->timeout_added)
+    {
+      _dbus_loop_remove_timeout (bus_context_get_loop (pending_activation->activation->context),
+                                 pending_activation->timeout);
+      pending_activation->timeout_added = FALSE;
+    }
+
+  if (pending_activation->timeout)
+    _dbus_timeout_unref (pending_activation->timeout);
+
+  if (pending_activation->babysitter)
+    {
+      if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
+                                                 NULL, NULL, NULL,
+                                                 pending_activation->babysitter,
+                                                 NULL))
+        _dbus_assert_not_reached ("setting watch functions to NULL failed");
+
+      _dbus_babysitter_unref (pending_activation->babysitter);
+    }
+
+  dbus_free (pending_activation->service_name);
+  dbus_free (pending_activation->exec);
+  dbus_free (pending_activation->systemd_service);
+
+  link = _dbus_list_get_first_link (&pending_activation->entries);
+
+  while (link != NULL)
+    {
+      BusPendingActivationEntry *entry = link->data;
+
+      bus_pending_activation_entry_free (entry);
+
+      link = _dbus_list_get_next_link (&pending_activation->entries, link);
+    }
+  _dbus_list_clear (&pending_activation->entries);
+
+  pending_activation->activation->n_pending_activations -=
+    pending_activation->n_entries;
+
+  _dbus_assert (pending_activation->activation->n_pending_activations >= 0);
+
+  dbus_free (pending_activation);
+}
+
+static BusActivationEntry *
+bus_activation_entry_ref (BusActivationEntry *entry)
+{
+  _dbus_assert (entry->refcount > 0);
+  entry->refcount++;
+
+  return entry;
+}
+
+static void
+bus_activation_entry_unref (BusActivationEntry *entry)
+{
+  if (entry == NULL) /* hash table requires this */
+    return;
+
+  _dbus_assert (entry->refcount > 0);
+  entry->refcount--;
+
+  if (entry->refcount > 0)
+    return;
+
+  dbus_free (entry->name);
+  dbus_free (entry->exec);
+  dbus_free (entry->user);
+  dbus_free (entry->filename);
+  dbus_free (entry->systemd_service);
+
+  dbus_free (entry);
+}
+
+static dbus_bool_t
+update_desktop_file_entry (BusActivation       *activation,
+                           BusServiceDirectory *s_dir,
+                           DBusString          *filename,
+                           BusDesktopFile      *desktop_file,
+                           DBusError           *error)
+{
+  char *name, *exec, *user, *exec_tmp, *systemd_service;
+  BusActivationEntry *entry;
+  DBusStat stat_buf;
+  DBusString file_path;
+  DBusError tmp_error;
+  dbus_bool_t retval;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  retval = FALSE;
+  name = NULL;
+  exec = NULL;
+  user = NULL;
+  exec_tmp = NULL;
+  entry = NULL;
+  systemd_service = NULL;
+
+  dbus_error_init (&tmp_error);
+
+  if (!_dbus_string_init (&file_path))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_append (&file_path, s_dir->dir_c) ||
+      !_dbus_concat_dir_and_file (&file_path, filename))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (!_dbus_stat (&file_path, &stat_buf, NULL))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Can't stat the service file\n");
+      goto out;
+    }
+
+  if (!bus_desktop_file_get_string (desktop_file,
+                                    DBUS_SERVICE_SECTION,
+                                    DBUS_SERVICE_NAME,
+                                    &name,
+                                    error))
+    goto out;
+
+  if (!bus_desktop_file_get_string (desktop_file,
+                                    DBUS_SERVICE_SECTION,
+                                    DBUS_SERVICE_EXEC,
+                                    &exec_tmp,
+                                    error))
+    goto out;
+
+  exec = _dbus_strdup (_dbus_replace_install_prefix (exec_tmp));
+  dbus_free (exec_tmp);
+  exec_tmp = NULL;
+
+  /* user is not _required_ unless we are using system activation */
+  if (!bus_desktop_file_get_string (desktop_file,
+                                    DBUS_SERVICE_SECTION,
+                                    DBUS_SERVICE_USER,
+                                    &user, &tmp_error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+      /* if we got OOM, then exit */
+      if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+        {
+          dbus_move_error (&tmp_error, error);
+          goto out;
+        }
+      else
+        {
+          /* if we have error because we didn't find anything then continue */
+          dbus_error_free (&tmp_error);
+          dbus_free (user);
+          user = NULL;
+        }
+    }
+  _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+
+  /* systemd service is never required */
+  if (!bus_desktop_file_get_string (desktop_file,
+                                    DBUS_SERVICE_SECTION,
+                                    DBUS_SERVICE_SYSTEMD_SERVICE,
+                                    &systemd_service, &tmp_error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+      /* if we got OOM, then exit */
+      if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+        {
+          dbus_move_error (&tmp_error, error);
+          goto out;
+        }
+      else
+        {
+          /* if we have error because we didn't find anything then continue */
+          dbus_error_free (&tmp_error);
+          dbus_free (systemd_service);
+          systemd_service = NULL;
+        }
+    }
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+
+  entry = _dbus_hash_table_lookup_string (s_dir->entries,
+                                          _dbus_string_get_const_data (filename));
+
+  if (entry == NULL) /* New file */
+    {
+      /* FIXME we need a better-defined algorithm for which service file to
+       * pick than "whichever one is first in the directory listing"
+       */
+      if (_dbus_hash_table_lookup_string (activation->entries, name))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Service %s already exists in activation entry list\n", name);
+          goto out;
+        }
+
+      entry = dbus_new0 (BusActivationEntry, 1);
+      if (entry == NULL)
+        {
+          BUS_SET_OOM (error);
+          goto out;
+        }
+
+      entry->name = name;
+      entry->exec = exec;
+      entry->user = user;
+      entry->systemd_service = systemd_service;
+      entry->refcount = 1;
+
+      /* ownership has been transferred to entry, do not free separately */
+      name = NULL;
+      exec = NULL;
+      user = NULL;
+      systemd_service = NULL;
+
+      entry->s_dir = s_dir;
+      entry->filename = _dbus_strdup (_dbus_string_get_const_data (filename));
+      if (!entry->filename)
+        {
+          BUS_SET_OOM (error);
+          goto out;
+        }
+
+      if (!_dbus_hash_table_insert_string (activation->entries, entry->name, bus_activation_entry_ref (entry)))
+        {
+          BUS_SET_OOM (error);
+          goto out;
+        }
+
+      if (!_dbus_hash_table_insert_string (s_dir->entries, entry->filename, bus_activation_entry_ref (entry)))
+        {
+          /* Revert the insertion in the entries table */
+          _dbus_hash_table_remove_string (activation->entries, entry->name);
+          BUS_SET_OOM (error);
+          goto out;
+        }
+
+      _dbus_verbose ("Added \"%s\" to list of services\n", entry->name);
+    }
+  else /* Just update the entry */
+    {
+      bus_activation_entry_ref (entry);
+      _dbus_hash_table_remove_string (activation->entries, entry->name);
+
+      if (_dbus_hash_table_lookup_string (activation->entries, name))
+        {
+          _dbus_verbose ("The new service name \"%s\" of service file \"%s\" is already in cache, ignoring\n",
+                         name, _dbus_string_get_const_data (&file_path));
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "The new service name \"%s\" of service file \"%s\" is already in cache, ignoring\n",
+                          name, _dbus_string_get_const_data (&file_path));
+          goto out;
+        }
+
+      /* ownership has been transferred to entry, do not free separately */
+      dbus_free (entry->name);
+      entry->name = name;
+      name = NULL;
+
+      dbus_free (entry->exec);
+      entry->exec = exec;
+      exec = NULL;
+
+      dbus_free (entry->user);
+      entry->user = user;
+      user = NULL;
+
+      dbus_free (entry->systemd_service);
+      entry->systemd_service = systemd_service;
+      systemd_service = NULL;
+
+      if (!_dbus_hash_table_insert_string (activation->entries,
+                                           entry->name, bus_activation_entry_ref(entry)))
+        {
+          BUS_SET_OOM (error);
+          /* Also remove path to entries hash since we want this in sync with
+           * the entries hash table */
+          _dbus_hash_table_remove_string (entry->s_dir->entries,
+                                          entry->filename);
+          goto out;
+        }
+    }
+
+  entry->mtime = stat_buf.mtime;
+  retval = TRUE;
+
+out:
+  /* if these have been transferred into entry, the variables will be NULL */
+  dbus_free (name);
+  dbus_free (exec);
+  dbus_free (user);
+  dbus_free (systemd_service);
+  _dbus_string_free (&file_path);
+
+  if (entry)
+    bus_activation_entry_unref (entry);
+
+  return retval;
+}
+
+static dbus_bool_t
+check_service_file (BusActivation       *activation,
+                    BusActivationEntry  *entry,
+                    BusActivationEntry **updated_entry,
+                    DBusError           *error)
+{
+  DBusStat stat_buf;
+  dbus_bool_t retval;
+  BusActivationEntry *tmp_entry;
+  DBusString file_path;
+  DBusString filename;
+
+  retval = TRUE;
+  tmp_entry = entry;
+
+  _dbus_string_init_const (&filename, entry->filename);
+
+  if (!_dbus_string_init (&file_path))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_append (&file_path, entry->s_dir->dir_c) ||
+      !_dbus_concat_dir_and_file (&file_path, &filename))
+    {
+      BUS_SET_OOM (error);
+      retval = FALSE;
+      goto out;
+    }
+
+  if (!_dbus_stat (&file_path, &stat_buf, NULL))
+    {
+      _dbus_verbose ("****** Can't stat file \"%s\", removing from cache\n",
+                     _dbus_string_get_const_data (&file_path));
+
+      _dbus_hash_table_remove_string (activation->entries, entry->name);
+      _dbus_hash_table_remove_string (entry->s_dir->entries, entry->filename);
+
+      tmp_entry = NULL;
+      retval = TRUE;
+      goto out;
+    }
+  else
+    {
+      if (stat_buf.mtime > entry->mtime)
+        {
+          BusDesktopFile *desktop_file;
+          DBusError tmp_error;
+
+          dbus_error_init (&tmp_error);
+
+          desktop_file = bus_desktop_file_load (&file_path, &tmp_error);
+          if (desktop_file == NULL)
+            {
+              _dbus_verbose ("Could not load %s: %s\n",
+                             _dbus_string_get_const_data (&file_path),
+                             tmp_error.message);
+              if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+                {
+                  dbus_move_error (&tmp_error, error);
+                  retval = FALSE;
+                  goto out;
+                }
+              dbus_error_free (&tmp_error);
+              retval = TRUE;
+              goto out;
+            }
+
+          /* @todo We can return OOM or a DBUS_ERROR_FAILED error
+           *       Handle these both better
+           */
+          if (!update_desktop_file_entry (activation, entry->s_dir, &filename, desktop_file, &tmp_error))
+            {
+              bus_desktop_file_free (desktop_file);
+              if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+                {
+                  dbus_move_error (&tmp_error, error);
+                  retval = FALSE;
+                  goto out;
+                }
+              dbus_error_free (&tmp_error);
+              retval = TRUE;
+              goto out;
+            }
+
+          bus_desktop_file_free (desktop_file);
+          retval = TRUE;
+        }
+    }
+
+out:
+  _dbus_string_free (&file_path);
+
+  if (updated_entry != NULL)
+    *updated_entry = tmp_entry;
+  return retval;
+}
+
+
+/* warning: this doesn't fully "undo" itself on failure, i.e. doesn't strip
+ * hash entries it already added.
+ */
+static dbus_bool_t
+update_directory (BusActivation       *activation,
+                  BusServiceDirectory *s_dir,
+                  DBusError           *error)
+{
+  DBusDirIter *iter;
+  DBusString dir, filename;
+  BusDesktopFile *desktop_file;
+  DBusError tmp_error;
+  dbus_bool_t retval;
+  BusActivationEntry *entry;
+  DBusString full_path;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  iter = NULL;
+  desktop_file = NULL;
+
+  _dbus_string_init_const (&dir, s_dir->dir_c);
+
+  if (!_dbus_string_init (&filename))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&full_path))
+    {
+      BUS_SET_OOM (error);
+      _dbus_string_free (&filename);
+      return FALSE;
+    }
+
+  retval = FALSE;
+
+  /* from this point it's safe to "goto out" */
+
+  iter = _dbus_directory_open (&dir, error);
+  if (iter == NULL)
+    {
+      _dbus_verbose ("Failed to open directory %s: %s\n",
+                     s_dir->dir_c,
+                     error ? error->message : "unknown");
+      goto out;
+    }
+
+  /* Now read the files */
+  dbus_error_init (&tmp_error);
+  while (_dbus_directory_get_next_file (iter, &filename, &tmp_error))
+    {
+      _dbus_assert (!dbus_error_is_set (&tmp_error));
+
+      _dbus_string_set_length (&full_path, 0);
+
+      if (!_dbus_string_ends_with_c_str (&filename, ".service"))
+        {
+          _dbus_verbose ("Skipping non-.service file %s\n",
+                         _dbus_string_get_const_data (&filename));
+          continue;
+        }
+
+      entry = _dbus_hash_table_lookup_string (s_dir->entries, _dbus_string_get_const_data (&filename));
+      if (entry) /* Already has this service file in the cache */
+        {
+          if (!check_service_file (activation, entry, NULL, error))
+            goto out;
+
+          continue;
+        }
+
+      if (!_dbus_string_append (&full_path, s_dir->dir_c) ||
+          !_dbus_concat_dir_and_file (&full_path, &filename))
+        {
+          BUS_SET_OOM (error);
+          goto out;
+        }
+
+      /* New file */
+      desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
+      if (desktop_file == NULL)
+        {
+          _dbus_verbose ("Could not load %s: %s\n",
+                         _dbus_string_get_const_data (&full_path),
+                         tmp_error.message);
+
+          if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_move_error (&tmp_error, error);
+              goto out;
+            }
+
+          dbus_error_free (&tmp_error);
+          continue;
+        }
+
+      /* @todo We can return OOM or a DBUS_ERROR_FAILED error
+       *       Handle these both better
+       */
+      if (!update_desktop_file_entry (activation, s_dir, &filename, desktop_file, &tmp_error))
+        {
+          bus_desktop_file_free (desktop_file);
+          desktop_file = NULL;
+
+          _dbus_verbose ("Could not add %s to activation entry list: %s\n",
+                         _dbus_string_get_const_data (&full_path), tmp_error.message);
+
+          if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_move_error (&tmp_error, error);
+              goto out;
+            }
+
+          dbus_error_free (&tmp_error);
+          continue;
+        }
+      else
+        {
+          bus_desktop_file_free (desktop_file);
+          desktop_file = NULL;
+          continue;
+        }
+    }
+
+  if (dbus_error_is_set (&tmp_error))
+    {
+      dbus_move_error (&tmp_error, error);
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (!retval)
+    _DBUS_ASSERT_ERROR_IS_SET (error);
+  else
+    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (iter != NULL)
+    _dbus_directory_close (iter);
+  _dbus_string_free (&filename);
+  _dbus_string_free (&full_path);
+
+  return retval;
+}
+
+static dbus_bool_t
+populate_environment (BusActivation *activation)
+{
+  DBusString   key;
+  DBusString   value;
+  int          i;
+  char       **environment;
+  dbus_bool_t  retval = FALSE;
+
+  environment = _dbus_get_environment ();
+
+  if (environment == NULL)
+    return FALSE;
+
+  if (!_dbus_string_init (&key))
+    {
+        dbus_free_string_array (environment);
+        return FALSE;
+    }
+
+  if (!_dbus_string_init (&value))
+    {
+      _dbus_string_free (&key);
+      dbus_free_string_array (environment);
+      return FALSE;
+    }
+
+  for (i = 0; environment[i] != NULL; i++)
+    {
+      if (!_dbus_string_append (&key, environment[i]))
+        break;
+
+      if (_dbus_string_split_on_byte (&key, '=', &value))
+        {
+          char *hash_key, *hash_value;
+
+          if (!_dbus_string_steal_data (&key, &hash_key))
+            break;
+
+          if (!_dbus_string_steal_data (&value, &hash_value))
+            break;
+
+          if (!_dbus_hash_table_insert_string (activation->environment,
+                                               hash_key, hash_value))
+            break;
+        }
+      _dbus_string_set_length (&key, 0);
+      _dbus_string_set_length (&value, 0);
+    }
+
+  if (environment[i] != NULL)
+    goto out;
+
+  retval = TRUE;
+out:
+
+  _dbus_string_free (&key);
+  _dbus_string_free (&value);
+  dbus_free_string_array (environment);
+
+  return retval;
+}
+
+dbus_bool_t
+bus_activation_reload (BusActivation     *activation,
+                       const DBusString  *address,
+                       DBusList         **directories,
+                       DBusError         *error)
+{
+  DBusList      *link;
+  char          *dir;
+
+  if (activation->server_address != NULL)
+    dbus_free (activation->server_address);
+  if (!_dbus_string_copy_data (address, &activation->server_address))
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  if (activation->entries != NULL)
+    _dbus_hash_table_unref (activation->entries);
+  activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
+                                             (DBusFreeFunction)bus_activation_entry_unref);
+  if (activation->entries == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  if (activation->directories != NULL)
+    _dbus_hash_table_unref (activation->directories);
+  activation->directories = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
+                                                  (DBusFreeFunction)bus_service_directory_unref);
+
+  if (activation->directories == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  link = _dbus_list_get_first_link (directories);
+  while (link != NULL)
+    {
+      BusServiceDirectory *s_dir;
+
+      dir = _dbus_strdup ((const char *) link->data);
+      if (!dir)
+        {
+          BUS_SET_OOM (error);
+          goto failed;
+        }
+
+      s_dir = dbus_new0 (BusServiceDirectory, 1);
+      if (!s_dir)
+        {
+          dbus_free (dir);
+          BUS_SET_OOM (error);
+          goto failed;
+        }
+
+      s_dir->refcount = 1;
+      s_dir->dir_c = dir;
+
+      s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
+                                             (DBusFreeFunction)bus_activation_entry_unref);
+
+      if (!s_dir->entries)
+        {
+          bus_service_directory_unref (s_dir);
+          BUS_SET_OOM (error);
+          goto failed;
+        }
+
+      if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir))
+        {
+          bus_service_directory_unref (s_dir);
+          BUS_SET_OOM (error);
+          goto failed;
+        }
+
+      /* only fail on OOM, it is ok if we can't read the directory */
+      if (!update_directory (activation, s_dir, error))
+        {
+          if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
+            goto failed;
+          else
+            dbus_error_free (error);
+        }
+
+      link = _dbus_list_get_next_link (directories, link);
+    }
+
+  return TRUE;
+ failed:
+  return FALSE;
+}
+
+BusActivation*
+bus_activation_new (BusContext        *context,
+                    const DBusString  *address,
+                    DBusList         **directories,
+                    DBusError         *error)
+{
+  BusActivation *activation;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  activation = dbus_new0 (BusActivation, 1);
+  if (activation == NULL)
+    {
+      BUS_SET_OOM (error);
+      return NULL;
+    }
+
+  activation->refcount = 1;
+  activation->context = context;
+  activation->n_pending_activations = 0;
+
+  if (!bus_activation_reload (activation, address, directories, error))
+    goto failed;
+
+   /* Initialize this hash table once, we don't want to lose pending
+   * activations on reload. */
+  activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
+                                                          (DBusFreeFunction)bus_pending_activation_unref);
+
+  if (activation->pending_activations == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  activation->environment = _dbus_hash_table_new (DBUS_HASH_STRING,
+                                                  (DBusFreeFunction) dbus_free,
+                                                  (DBusFreeFunction) dbus_free);
+
+  if (activation->environment == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  if (!populate_environment (activation))
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  return activation;
+
+ failed:
+  bus_activation_unref (activation);
+  return NULL;
+}
+
+BusActivation *
+bus_activation_ref (BusActivation *activation)
+{
+  _dbus_assert (activation->refcount > 0);
+
+  activation->refcount += 1;
+
+  return activation;
+}
+
+void
+bus_activation_unref (BusActivation *activation)
+{
+  _dbus_assert (activation->refcount > 0);
+
+  activation->refcount -= 1;
+
+  if (activation->refcount > 0)
+    return;
+
+  dbus_free (activation->server_address);
+  if (activation->entries)
+    _dbus_hash_table_unref (activation->entries);
+  if (activation->pending_activations)
+    _dbus_hash_table_unref (activation->pending_activations);
+  if (activation->directories)
+    _dbus_hash_table_unref (activation->directories);
+  if (activation->environment)
+    _dbus_hash_table_unref (activation->environment);
+
+  dbus_free (activation);
+}
+
+static dbus_bool_t
+add_bus_environment (BusActivation *activation,
+                     DBusError     *error)
+{
+  const char *type;
+
+  if (!bus_activation_set_environment_variable (activation,
+                                                "DBUS_STARTER_ADDRESS",
+                                                activation->server_address,
+                                                error))
+    return FALSE;
+
+  type = bus_context_get_type (activation->context);
+  if (type != NULL)
+    {
+      if (!bus_activation_set_environment_variable (activation,
+                                                    "DBUS_STARTER_BUS_TYPE", type,
+                                                    error))
+        return FALSE;
+
+      if (strcmp (type, "session") == 0)
+        {
+          if (!bus_activation_set_environment_variable (activation,
+                                                        "DBUS_SESSION_BUS_ADDRESS",
+                                                        activation->server_address,
+                                                        error))
+            return FALSE;
+        }
+      else if (strcmp (type, "system") == 0)
+        {
+          if (!bus_activation_set_environment_variable (activation,
+                                                        "DBUS_SYSTEM_BUS_ADDRESS",
+                                                        activation->server_address,
+                                                        error))
+            return FALSE;
+        }
+    }
+
+  return TRUE;
+}
+
+typedef struct
+{
+  BusPendingActivation *pending_activation;
+  DBusPreallocatedHash *hash_entry;
+} RestorePendingData;
+
+static void
+restore_pending (void *data)
+{
+  RestorePendingData *d = data;
+
+  _dbus_assert (d->pending_activation != NULL);
+  _dbus_assert (d->hash_entry != NULL);
+
+  _dbus_verbose ("Restoring pending activation for service %s, has timeout = %d\n",
+                 d->pending_activation->service_name,
+                 d->pending_activation->timeout_added);
+
+  _dbus_hash_table_insert_string_preallocated (d->pending_activation->activation->pending_activations,
+                                               d->hash_entry,
+                                               d->pending_activation->service_name, d->pending_activation);
+
+  bus_pending_activation_ref (d->pending_activation);
+
+  d->hash_entry = NULL;
+}
+
+static void
+free_pending_restore_data (void *data)
+{
+  RestorePendingData *d = data;
+
+  if (d->hash_entry)
+    _dbus_hash_table_free_preallocated_entry (d->pending_activation->activation->pending_activations,
+                                              d->hash_entry);
+
+  bus_pending_activation_unref (d->pending_activation);
+
+  dbus_free (d);
+}
+
+static dbus_bool_t
+add_restore_pending_to_transaction (BusTransaction       *transaction,
+                                    BusPendingActivation *pending_activation)
+{
+  RestorePendingData *d;
+
+  d = dbus_new (RestorePendingData, 1);
+  if (d == NULL)
+    return FALSE;
+
+  d->pending_activation = pending_activation;
+  d->hash_entry = _dbus_hash_table_preallocate_entry (d->pending_activation->activation->pending_activations);
+
+  bus_pending_activation_ref (d->pending_activation);
+
+  if (d->hash_entry == NULL ||
+      !bus_transaction_add_cancel_hook (transaction, restore_pending, d,
+                                        free_pending_restore_data))
+    {
+      free_pending_restore_data (d);
+      return FALSE;
+    }
+
+  _dbus_verbose ("Saved pending activation to be restored if the transaction fails\n");
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_activation_service_created (BusActivation  *activation,
+                                const char     *service_name,
+                                BusTransaction *transaction,
+                                DBusError      *error)
+{
+  BusPendingActivation *pending_activation;
+  DBusMessage *message;
+  DBusList *link;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  /* Check if it's a pending activation */
+  pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
+
+  if (!pending_activation)
+    return TRUE;
+
+  bus_context_log (activation->context,
+                   DBUS_SYSTEM_LOG_INFO, "Successfully activated service '%s'",
+                   service_name);
+
+  link = _dbus_list_get_first_link (&pending_activation->entries);
+  while (link != NULL)
+    {
+      BusPendingActivationEntry *entry = link->data;
+      DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
+
+      if (dbus_connection_get_is_connected (entry->connection))
+        {
+          /* Only send activation replies to regular activation requests. */
+          if (!entry->auto_activation)
+            {
+              dbus_uint32_t result;
+
+              message = dbus_message_new_method_return (entry->activation_message);
+              if (!message)
+                {
+                  BUS_SET_OOM (error);
+                  goto error;
+                }
+
+              result = DBUS_START_REPLY_SUCCESS;
+
+              if (!dbus_message_append_args (message,
+                                             DBUS_TYPE_UINT32, &result,
+                                             DBUS_TYPE_INVALID))
+                {
+                  dbus_message_unref (message);
+                  BUS_SET_OOM (error);
+                  goto error;
+                }
+
+              if (!bus_transaction_send_from_driver (transaction, entry->connection, message))
+                {
+                  dbus_message_unref (message);
+                  BUS_SET_OOM (error);
+                  goto error;
+                }
+
+              dbus_message_unref (message);
+            }
+        }
+
+      link = next;
+    }
+
+  return TRUE;
+
+ error:
+  return FALSE;
+}
+
+dbus_bool_t
+bus_activation_send_pending_auto_activation_messages (BusActivation  *activation,
+                                                      BusService     *service,
+                                                      BusTransaction *transaction,
+                                                      DBusError      *error)
+{
+  BusPendingActivation *pending_activation;
+  DBusList *link;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  /* Check if it's a pending activation */
+  pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations,
+                                                       bus_service_get_name (service));
+
+  if (!pending_activation)
+    return TRUE;
+
+  link = _dbus_list_get_first_link (&pending_activation->entries);
+  while (link != NULL)
+    {
+      BusPendingActivationEntry *entry = link->data;
+      DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
+
+      if (entry->auto_activation && dbus_connection_get_is_connected (entry->connection))
+        {
+          DBusConnection *addressed_recipient;
+
+          addressed_recipient = bus_service_get_primary_owners_connection (service);
+
+          /* Resume dispatching where we left off in bus_dispatch() */
+          if (!bus_dispatch_matches (transaction,
+                                     entry->connection,
+                                     addressed_recipient,
+                                     entry->activation_message, error))
+            goto error;
+        }
+
+      link = next;
+    }
+
+  if (!add_restore_pending_to_transaction (transaction, pending_activation))
+    {
+      _dbus_verbose ("Could not add cancel hook to transaction to revert removing pending activation\n");
+      BUS_SET_OOM (error);
+      goto error;
+    }
+
+  _dbus_hash_table_remove_string (activation->pending_activations, bus_service_get_name (service));
+
+  return TRUE;
+
+ error:
+  return FALSE;
+}
+
+/**
+ * FIXME @todo the error messages here would ideally be preallocated
+ * so we don't need to allocate memory to send them.
+ * Using the usual tactic, prealloc an OOM message, then
+ * if we can't alloc the real error send the OOM error instead.
+ */
+static dbus_bool_t
+try_send_activation_failure (BusPendingActivation *pending_activation,
+                             const DBusError      *how)
+{
+  BusActivation *activation;
+  DBusList *link;
+  BusTransaction *transaction;
+
+  activation = pending_activation->activation;
+
+  transaction = bus_transaction_new (activation->context);
+  if (transaction == NULL)
+    return FALSE;
+
+  link = _dbus_list_get_first_link (&pending_activation->entries);
+  while (link != NULL)
+    {
+      BusPendingActivationEntry *entry = link->data;
+      DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
+
+      if (dbus_connection_get_is_connected (entry->connection))
+        {
+          if (!bus_transaction_send_error_reply (transaction,
+                                                 entry->connection,
+                                                 how,
+                                                 entry->activation_message))
+            goto error;
+        }
+
+      link = next;
+    }
+
+  bus_transaction_execute_and_free (transaction);
+
+  return TRUE;
+
+ error:
+  if (transaction)
+    bus_transaction_cancel_and_free (transaction);
+  return FALSE;
+}
+
+/**
+ * Free the pending activation and send an error message to all the
+ * connections that were waiting for it.
+ */
+static void
+pending_activation_failed (BusPendingActivation *pending_activation,
+                           const DBusError      *how)
+{
+  /* FIXME use preallocated OOM messages instead of bus_wait_for_memory() */
+  while (!try_send_activation_failure (pending_activation, how))
+    _dbus_wait_for_memory ();
+
+  /* Destroy this pending activation */
+  _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
+                                  pending_activation->service_name);
+}
+
+/**
+ * Depending on the exit code of the helper, set the error accordingly
+ */
+static void
+handle_servicehelper_exit_error (int        exit_code,
+                                 DBusError *error)
+{
+  switch (exit_code)
+    {
+    case BUS_SPAWN_EXIT_CODE_NO_MEMORY:
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                      "Launcher could not run (out of memory)");
+      break;
+    case BUS_SPAWN_EXIT_CODE_SETUP_FAILED:
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
+                      "Failed to setup environment correctly");
+      break;
+    case BUS_SPAWN_EXIT_CODE_NAME_INVALID:
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_INVALID,
+                      "Bus name is not valid or missing");
+      break;
+    case BUS_SPAWN_EXIT_CODE_SERVICE_NOT_FOUND:
+      dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
+                      "Bus name not found in system service directory");
+      break;
+    case BUS_SPAWN_EXIT_CODE_PERMISSIONS_INVALID:
+      dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
+                      "The permission of the setuid helper is not correct");
+      break;
+    case BUS_SPAWN_EXIT_CODE_FILE_INVALID:
+      dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
+                      "The service file is incorrect or does not have all required attributes");
+      break;
+    case BUS_SPAWN_EXIT_CODE_EXEC_FAILED:
+      dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
+                      "Cannot launch daemon, file not found or permissions invalid");
+      break;
+    case BUS_SPAWN_EXIT_CODE_INVALID_ARGS:
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Invalid arguments to command line");
+      break;
+    case BUS_SPAWN_EXIT_CODE_CHILD_SIGNALED:
+      dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
+                      "Launched child was signaled, it probably crashed");
+      break;
+    default:
+      dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
+                      "Launch helper exited with unknown return code %i", exit_code);
+      break;
+    }
+}
+
+static void
+pending_activation_finished_cb (DBusBabysitter *babysitter,
+                                void           *data)
+{
+  BusPendingActivation *pending_activation = data;
+  dbus_bool_t uses_servicehelper;
+
+  _dbus_assert (babysitter == pending_activation->babysitter);
+  _dbus_babysitter_ref (babysitter);
+
+  /* There are two major cases here; are we the system bus or the session?  Here this
+   * is distinguished by whether or not we use a setuid helper launcher.  With the launch helper,
+   * some process exit codes are meaningful, processed by handle_servicehelper_exit_error.
+   *
+   * In both cases though, just ignore when a process exits with status 0; it's possible for
+   * a program to (misguidedly) "daemonize", and that appears to us as an exit.  This closes a race
+   * condition between this code and the child process claiming the bus name.
+   */
+  uses_servicehelper = bus_context_get_servicehelper (pending_activation->activation->context) != NULL;
+
+  /* strictly speaking this is redundant with the check in dbus-spawn now */
+  if (_dbus_babysitter_get_child_exited (babysitter))
+    {
+      DBusError error;
+      DBusHashIter iter;
+      dbus_bool_t activation_failed;
+      int exit_code = 0;
+
+      dbus_error_init (&error);
+
+      _dbus_babysitter_set_child_exit_error (babysitter, &error);
+
+      /* Explicitly check for SPAWN_CHILD_EXITED to avoid overwriting an
+       * exec error */
+      if (dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)
+          && _dbus_babysitter_get_child_exit_status (babysitter, &exit_code))
+        {
+          activation_failed = exit_code != 0;
+
+          dbus_error_free(&error);
+
+          if (activation_failed)
+            {
+              if (uses_servicehelper)
+                handle_servicehelper_exit_error (exit_code, &error);
+              else
+                _dbus_babysitter_set_child_exit_error (babysitter, &error);
+            }
+        }
+      else
+        {
+          activation_failed = TRUE;
+        }
+
+      if (activation_failed)
+        {
+          bus_context_log (pending_activation->activation->context,
+                           DBUS_SYSTEM_LOG_INFO, "Activated service '%s' failed: %s",
+                           pending_activation->service_name,
+                           error.message);
+
+          /* Destroy all pending activations with the same exec */
+          _dbus_hash_iter_init (pending_activation->activation->pending_activations,
+                                &iter);
+          while (_dbus_hash_iter_next (&iter))
+            {
+              BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
+
+              if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0)
+                pending_activation_failed (p, &error);
+            }
+
+          /* Destroys the pending activation */
+          pending_activation_failed (pending_activation, &error);
+
+          dbus_error_free (&error);
+        }
+    }
+
+  _dbus_babysitter_unref (babysitter);
+}
+
+static dbus_bool_t
+add_babysitter_watch (DBusWatch      *watch,
+                      void           *data)
+{
+  BusPendingActivation *pending_activation = data;
+
+  return _dbus_loop_add_watch (
+      bus_context_get_loop (pending_activation->activation->context),
+      watch);
+}
+
+static void
+remove_babysitter_watch (DBusWatch      *watch,
+                         void           *data)
+{
+  BusPendingActivation *pending_activation = data;
+
+  _dbus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context),
+                           watch);
+}
+
+static void
+toggle_babysitter_watch (DBusWatch      *watch,
+                         void           *data)
+{
+  BusPendingActivation *pending_activation = data;
+
+  _dbus_loop_toggle_watch (bus_context_get_loop (pending_activation->activation->context),
+                           watch);
+}
+
+static dbus_bool_t
+pending_activation_timed_out (void *data)
+{
+  BusPendingActivation *pending_activation = data;
+  DBusError error;
+
+  /* Kill the spawned process, since it sucks
+   * (not sure this is what we want to do, but
+   * may as well try it for now)
+   */
+  if (pending_activation->babysitter)
+    _dbus_babysitter_kill_child (pending_activation->babysitter);
+
+  dbus_error_init (&error);
+
+  dbus_set_error (&error, DBUS_ERROR_TIMED_OUT,
+                  "Activation of %s timed out",
+                  pending_activation->service_name);
+  bus_context_log (pending_activation->activation->context,
+                   DBUS_SYSTEM_LOG_INFO,
+                   "Failed to activate service '%s': timed out",
+                   pending_activation->service_name);
+
+  pending_activation_failed (pending_activation, &error);
+
+  dbus_error_free (&error);
+
+  return TRUE;
+}
+
+static void
+cancel_pending (void *data)
+{
+  BusPendingActivation *pending_activation = data;
+
+  _dbus_verbose ("Canceling pending activation of %s\n",
+                 pending_activation->service_name);
+
+  if (pending_activation->babysitter)
+    _dbus_babysitter_kill_child (pending_activation->babysitter);
+
+  _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
+                                  pending_activation->service_name);
+}
+
+static void
+free_pending_cancel_data (void *data)
+{
+  BusPendingActivation *pending_activation = data;
+
+  bus_pending_activation_unref (pending_activation);
+}
+
+static dbus_bool_t
+add_cancel_pending_to_transaction (BusTransaction       *transaction,
+                                   BusPendingActivation *pending_activation)
+{
+  if (!bus_transaction_add_cancel_hook (transaction, cancel_pending,
+                                        pending_activation,
+                                        free_pending_cancel_data))
+    return FALSE;
+
+  bus_pending_activation_ref (pending_activation);
+
+  _dbus_verbose ("Saved pending activation to be canceled if the transaction fails\n");
+
+  return TRUE;
+}
+
+static dbus_bool_t
+update_service_cache (BusActivation *activation, DBusError *error)
+{
+  DBusHashIter iter;
+
+  _dbus_hash_iter_init (activation->directories, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      DBusError tmp_error;
+      BusServiceDirectory *s_dir;
+
+      s_dir = _dbus_hash_iter_get_value (&iter);
+
+      dbus_error_init (&tmp_error);
+      if (!update_directory (activation, s_dir, &tmp_error))
+        {
+          if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_move_error (&tmp_error, error);
+              return FALSE;
+            }
+
+          dbus_error_free (&tmp_error);
+          continue;
+        }
+    }
+
+  return TRUE;
+}
+
+static BusActivationEntry *
+activation_find_entry (BusActivation *activation,
+                       const char    *service_name,
+                       DBusError     *error)
+{
+  BusActivationEntry *entry;
+
+  entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
+  if (!entry)
+    {
+      if (!update_service_cache (activation, error))
+        return NULL;
+
+      entry = _dbus_hash_table_lookup_string (activation->entries,
+                                              service_name);
+    }
+  else
+    {
+      BusActivationEntry *updated_entry;
+
+      if (!check_service_file (activation, entry, &updated_entry, error))
+        return NULL;
+
+      entry = updated_entry;
+    }
+
+  if (!entry)
+    {
+      dbus_set_error (error, DBUS_ERROR_SERVICE_UNKNOWN,
+                      "The name %s was not provided by any .service files",
+                      service_name);
+      return NULL;
+    }
+
+  return entry;
+}
+
+static char **
+bus_activation_get_environment (BusActivation *activation)
+{
+  char **environment;
+  int i, length;
+  DBusString entry;
+  DBusHashIter iter;
+
+  length = _dbus_hash_table_get_n_entries (activation->environment);
+
+  environment = dbus_new0 (char *, length + 1);
+
+  if (environment == NULL)
+    return NULL;
+
+  i = 0;
+  _dbus_hash_iter_init (activation->environment, &iter);
+
+  if (!_dbus_string_init (&entry))
+    {
+      dbus_free_string_array (environment);
+      return NULL;
+    }
+
+  while (_dbus_hash_iter_next (&iter))
+    {
+      const char *key, *value;
+
+      key = (const char *) _dbus_hash_iter_get_string_key (&iter);
+      value = (const char *) _dbus_hash_iter_get_value (&iter);
+
+      if (!_dbus_string_append_printf (&entry, "%s=%s", key, value))
+        break;
+
+      if (!_dbus_string_steal_data (&entry, environment + i))
+        break;
+      i++;
+    }
+
+  _dbus_string_free (&entry);
+
+  if (i != length)
+    {
+      dbus_free_string_array (environment);
+      environment = NULL;
+    }
+
+  return environment;
+}
+
+dbus_bool_t
+bus_activation_set_environment_variable (BusActivation     *activation,
+                                         const char        *key,
+                                         const char        *value,
+                                         DBusError         *error)
+{
+  char        *hash_key;
+  char        *hash_value;
+  dbus_bool_t  retval;
+
+  retval = FALSE;
+  hash_key = NULL;
+  hash_value = NULL;
+  hash_key = _dbus_strdup (key);
+
+  if (hash_key == NULL)
+    goto out;
+
+  hash_value = _dbus_strdup (value);
+
+  if (hash_value == NULL)
+    goto out;
+
+  if (!_dbus_hash_table_insert_string (activation->environment,
+                                       hash_key, hash_value))
+    goto out;
+
+  retval = TRUE;
+out:
+  if (retval == FALSE)
+    {
+      dbus_free (hash_key);
+      dbus_free (hash_value);
+      BUS_SET_OOM (error);
+    }
+
+  return retval;
+}
+
+dbus_bool_t
+bus_activation_activate_service (BusActivation  *activation,
+                                 DBusConnection *connection,
+                                 BusTransaction *transaction,
+                                 dbus_bool_t     auto_activation,
+                                 DBusMessage    *activation_message,
+                                 const char     *service_name,
+                                 DBusError      *error)
+{
+  DBusError tmp_error;
+  BusActivationEntry *entry;
+  BusPendingActivation *pending_activation;
+  BusPendingActivationEntry *pending_activation_entry;
+  DBusMessage *message;
+  DBusString service_str;
+  const char *servicehelper;
+  char **argv;
+  char **envp = NULL;
+  int argc;
+  dbus_bool_t retval;
+  dbus_bool_t was_pending_activation;
+  DBusString command;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (activation->n_pending_activations >=
+      bus_context_get_max_pending_activations (activation->context))
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                      "The maximum number of pending activations has been reached, activation of %s failed",
+                      service_name);
+      return FALSE;
+    }
+
+  entry = activation_find_entry (activation, service_name, error);
+  if (!entry)
+    return FALSE;
+
+  /* Bypass the registry lookup if we're auto-activating, bus_dispatch would not
+   * call us if the service is already active.
+   */
+  if (!auto_activation)
+    {
+      /* Check if the service is active */
+      _dbus_string_init_const (&service_str, service_name);
+      if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL)
+        {
+          dbus_uint32_t result;
+
+          _dbus_verbose ("Service \"%s\" is already active\n", service_name);
+
+          message = dbus_message_new_method_return (activation_message);
+
+          if (!message)
+            {
+              _dbus_verbose ("No memory to create reply to activate message\n");
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          result = DBUS_START_REPLY_ALREADY_RUNNING;
+
+          if (!dbus_message_append_args (message,
+                                         DBUS_TYPE_UINT32, &result,
+                                         DBUS_TYPE_INVALID))
+            {
+              _dbus_verbose ("No memory to set args of reply to activate message\n");
+              BUS_SET_OOM (error);
+              dbus_message_unref (message);
+              return FALSE;
+            }
+
+          retval = bus_transaction_send_from_driver (transaction, connection, message);
+          dbus_message_unref (message);
+          if (!retval)
+            {
+              _dbus_verbose ("Failed to send reply\n");
+              BUS_SET_OOM (error);
+            }
+
+          return retval;
+        }
+    }
+
+  pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1);
+  if (!pending_activation_entry)
+    {
+      _dbus_verbose ("Failed to create pending activation entry\n");
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  pending_activation_entry->auto_activation = auto_activation;
+
+  pending_activation_entry->activation_message = activation_message;
+  dbus_message_ref (activation_message);
+  pending_activation_entry->connection = connection;
+  dbus_connection_ref (connection);
+
+  /* Check if the service is being activated */
+  pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
+  was_pending_activation = (pending_activation != NULL);
+  if (was_pending_activation)
+    {
+      if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
+        {
+          _dbus_verbose ("Failed to append a new entry to pending activation\n");
+
+          BUS_SET_OOM (error);
+          bus_pending_activation_entry_free (pending_activation_entry);
+          return FALSE;
+        }
+
+      pending_activation->n_entries += 1;
+      pending_activation->activation->n_pending_activations += 1;
+    }
+  else
+    {
+      pending_activation = dbus_new0 (BusPendingActivation, 1);
+      if (!pending_activation)
+        {
+          _dbus_verbose ("Failed to create pending activation\n");
+
+          BUS_SET_OOM (error);
+          bus_pending_activation_entry_free (pending_activation_entry);
+          return FALSE;
+        }
+
+      pending_activation->activation = activation;
+      pending_activation->refcount = 1;
+
+      pending_activation->service_name = _dbus_strdup (service_name);
+      if (!pending_activation->service_name)
+        {
+          _dbus_verbose ("Failed to copy service name for pending activation\n");
+
+          BUS_SET_OOM (error);
+          bus_pending_activation_unref (pending_activation);
+          bus_pending_activation_entry_free (pending_activation_entry);
+          return FALSE;
+        }
+
+      pending_activation->exec = _dbus_strdup (entry->exec);
+      if (!pending_activation->exec)
+        {
+          _dbus_verbose ("Failed to copy service exec for pending activation\n");
+          BUS_SET_OOM (error);
+          bus_pending_activation_unref (pending_activation);
+          bus_pending_activation_entry_free (pending_activation_entry);
+          return FALSE;
+        }
+
+      if (entry->systemd_service)
+        {
+          pending_activation->systemd_service = _dbus_strdup (entry->systemd_service);
+          if (!pending_activation->systemd_service)
+            {
+              _dbus_verbose ("Failed to copy systemd service for pending activation\n");
+              BUS_SET_OOM (error);
+              bus_pending_activation_unref (pending_activation);
+              bus_pending_activation_entry_free (pending_activation_entry);
+              return FALSE;
+            }
+        }
+
+      pending_activation->timeout =
+        _dbus_timeout_new (bus_context_get_activation_timeout (activation->context),
+                           pending_activation_timed_out,
+                           pending_activation,
+                           NULL);
+      if (!pending_activation->timeout)
+        {
+          _dbus_verbose ("Failed to create timeout for pending activation\n");
+
+          BUS_SET_OOM (error);
+          bus_pending_activation_unref (pending_activation);
+          bus_pending_activation_entry_free (pending_activation_entry);
+          return FALSE;
+        }
+
+      if (!_dbus_loop_add_timeout (bus_context_get_loop (activation->context),
+                                   pending_activation->timeout))
+        {
+          _dbus_verbose ("Failed to add timeout for pending activation\n");
+
+          BUS_SET_OOM (error);
+          bus_pending_activation_unref (pending_activation);
+          bus_pending_activation_entry_free (pending_activation_entry);
+          return FALSE;
+        }
+
+      pending_activation->timeout_added = TRUE;
+
+      if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
+        {
+          _dbus_verbose ("Failed to add entry to just-created pending activation\n");
+
+          BUS_SET_OOM (error);
+          bus_pending_activation_unref (pending_activation);
+          bus_pending_activation_entry_free (pending_activation_entry);
+          return FALSE;
+        }
+
+      pending_activation->n_entries += 1;
+      pending_activation->activation->n_pending_activations += 1;
+
+      if (!_dbus_hash_table_insert_string (activation->pending_activations,
+                                           pending_activation->service_name,
+                                           pending_activation))
+        {
+          _dbus_verbose ("Failed to put pending activation in hash table\n");
+
+          BUS_SET_OOM (error);
+          bus_pending_activation_unref (pending_activation);
+          return FALSE;
+        }
+    }
+
+  if (!add_cancel_pending_to_transaction (transaction, pending_activation))
+    {
+      _dbus_verbose ("Failed to add pending activation cancel hook to transaction\n");
+      BUS_SET_OOM (error);
+      _dbus_hash_table_remove_string (activation->pending_activations,
+                                      pending_activation->service_name);
+
+      return FALSE;
+    }
+
+  if (was_pending_activation)
+    return TRUE;
+
+  if (bus_context_get_systemd_activation (activation->context))
+    {
+      if (strcmp (service_name, "org.freedesktop.systemd1") == 0)
+          /* systemd itself is missing apparently. That can happen
+             only during early startup. Let's just wait until systemd
+             connects to us and do nothing. */
+        return TRUE;
+
+      if (entry->systemd_service)
+        {
+          BusTransaction *activation_transaction;
+          DBusString service_string;
+          BusService *service;
+          BusRegistry *registry;
+
+          /* OK, we have a systemd service configured for this entry,
+             hence let's enqueue an activation request message. This
+             is implemented as a directed signal, not a method call,
+             for three reasons: 1) we don't expect a response on
+             success, where we just expect a name appearing on the
+             bus; 2) at this time the systemd service might not yet
+             have connected, so we wouldn't know the message serial at
+             this point to set up a pending call; 3) it is ugly if the
+             bus suddenly becomes the caller of a remote method. */
+
+          message = dbus_message_new_signal (DBUS_PATH_DBUS,
+                                             "org.freedesktop.systemd1.Activator",
+                                             "ActivationRequest");
+          if (!message)
+            {
+              _dbus_verbose ("No memory to create activation message\n");
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
+              !dbus_message_set_destination (message, "org.freedesktop.systemd1") ||
+              !dbus_message_append_args (message,
+                                         DBUS_TYPE_STRING, &entry->systemd_service,
+                                         DBUS_TYPE_INVALID))
+            {
+              _dbus_verbose ("No memory to set args of activation message\n");
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          /* Create our transaction */
+          activation_transaction = bus_transaction_new (activation->context);
+          if (activation_transaction == NULL)
+            {
+              _dbus_verbose ("No memory to create activation transaction\n");
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          /* Check whether systemd is already connected */
+          registry = bus_connection_get_registry (connection);
+          _dbus_string_init_const (&service_string, "org.freedesktop.systemd1");
+          service = bus_registry_lookup (registry, &service_string);
+
+          if (service != NULL)
+            {
+              bus_context_log (activation->context,
+                               DBUS_SYSTEM_LOG_INFO, "Activating via systemd: service name='%s' unit='%s'",
+                               service_name,
+                               entry->systemd_service);
+              /* Wonderful, systemd is connected, let's just send the msg */
+              retval = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service),
+                                             message, error);
+            }
+          else
+            {
+              bus_context_log (activation->context,
+                               DBUS_SYSTEM_LOG_INFO, "Activating systemd to hand-off: service name='%s' unit='%s'",
+                               service_name,
+                               entry->systemd_service);
+              /* systemd is not around, let's "activate" it. */
+              retval = bus_activation_activate_service (activation, connection, activation_transaction, TRUE,
+                                                        message, "org.freedesktop.systemd1", error);
+            }
+
+          dbus_message_unref (message);
+
+          if (!retval)
+            {
+              bus_context_log (activation->context,
+                               DBUS_SYSTEM_LOG_INFO, "Failed to activate via systemd: service name='%s' unit='%s'",
+                               service_name,
+                               entry->systemd_service);
+              _DBUS_ASSERT_ERROR_IS_SET (error);
+              _dbus_verbose ("failed to send activation message: %s\n", error->name);
+              bus_transaction_cancel_and_free (activation_transaction);
+              return FALSE;
+            }
+
+          bus_transaction_execute_and_free (activation_transaction);
+          return TRUE;
+        }
+
+      /* OK, we have no configured systemd service, hence let's
+         proceed with traditional activation. */
+    }
+
+  /* use command as system and session different */
+  if (!_dbus_string_init (&command))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  /* does the bus use a helper? */
+  servicehelper = bus_context_get_servicehelper (activation->context);
+  if (servicehelper != NULL)
+    {
+      if (entry->user == NULL)
+        {
+          _dbus_string_free (&command);
+          dbus_set_error (error, DBUS_ERROR_SPAWN_FILE_INVALID,
+                          "Cannot do system-bus activation with no user\n");
+          return FALSE;
+        }
+
+      /* join the helper path and the service name */
+      if (!_dbus_string_append (&command, servicehelper))
+        {
+          _dbus_string_free (&command);
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+      if (!_dbus_string_append (&command, " "))
+        {
+          _dbus_string_free (&command);
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+      if (!_dbus_string_append (&command, service_name))
+        {
+          _dbus_string_free (&command);
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+    }
+  else
+    {
+      /* the bus does not use a helper, so we can append arguments with the exec line */
+      if (!_dbus_string_append (&command, entry->exec))
+        {
+          _dbus_string_free (&command);
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+    }
+
+  /* convert command into arguments */
+  if (!_dbus_shell_parse_argv (_dbus_string_get_const_data (&command), &argc, &argv, error))
+    {
+      _dbus_verbose ("Failed to parse command line: %s\n", entry->exec);
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+
+      _dbus_hash_table_remove_string (activation->pending_activations,
+                                      pending_activation->service_name);
+
+      _dbus_string_free (&command);
+      return FALSE;
+    }
+  _dbus_string_free (&command);
+
+  if (!add_bus_environment (activation, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_free_string_array (argv);
+      return FALSE;
+    }
+
+  envp = bus_activation_get_environment (activation);
+
+  if (envp == NULL)
+    {
+      BUS_SET_OOM (error);
+      dbus_free_string_array (argv);
+      return FALSE;
+    }
+
+  _dbus_verbose ("Spawning %s ...\n", argv[0]);
+  if (servicehelper != NULL)
+    bus_context_log (activation->context,
+                     DBUS_SYSTEM_LOG_INFO, "Activating service name='%s' (using servicehelper)",
+                     service_name);
+  else
+    bus_context_log (activation->context,
+                     DBUS_SYSTEM_LOG_INFO, "Activating service name='%s'",
+                     service_name);
+
+  dbus_error_init (&tmp_error);
+
+  if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv,
+                                          envp,
+                                          NULL, activation,
+                                          &tmp_error))
+    {
+      _dbus_verbose ("Failed to spawn child\n");
+      bus_context_log (activation->context,
+                       DBUS_SYSTEM_LOG_INFO, "Failed to activate service %s: %s",
+                       service_name,
+                       tmp_error.message);
+      _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+      dbus_move_error (&tmp_error, error);
+      dbus_free_string_array (argv);
+      dbus_free_string_array (envp);
+
+      return FALSE;
+    }
+
+  dbus_free_string_array (argv);
+  envp = NULL;
+
+  _dbus_assert (pending_activation->babysitter != NULL);
+
+  _dbus_babysitter_set_result_function (pending_activation->babysitter,
+                                        pending_activation_finished_cb,
+                                        pending_activation);
+
+  if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
+                                             add_babysitter_watch,
+                                             remove_babysitter_watch,
+                                             toggle_babysitter_watch,
+                                             pending_activation,
+                                             NULL))
+    {
+      BUS_SET_OOM (error);
+      _dbus_verbose ("Failed to set babysitter watch functions\n");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_activation_list_services (BusActivation *activation,
+			      char        ***listp,
+			      int           *array_len)
+{
+  int i, j, len;
+  char **retval;
+  DBusHashIter iter;
+
+  len = _dbus_hash_table_get_n_entries (activation->entries);
+  retval = dbus_new (char *, len + 1);
+
+  if (retval == NULL)
+    return FALSE;
+
+  _dbus_hash_iter_init (activation->entries, &iter);
+  i = 0;
+  while (_dbus_hash_iter_next (&iter))
+    {
+      BusActivationEntry *entry = _dbus_hash_iter_get_value (&iter);
+
+      retval[i] = _dbus_strdup (entry->name);
+      if (retval[i] == NULL)
+	goto error;
+
+      i++;
+    }
+
+  retval[i] = NULL;
+
+  if (array_len)
+    *array_len = len;
+
+  *listp = retval;
+  return TRUE;
+
+ error:
+  for (j = 0; j < i; j++)
+    dbus_free (retval[i]);
+  dbus_free (retval);
+
+  return FALSE;
+}
+
+dbus_bool_t
+dbus_activation_systemd_failure (BusActivation *activation,
+                                 DBusMessage   *message)
+{
+  DBusError error;
+  const char *code, *str, *unit = NULL;
+
+  dbus_error_init(&error);
+
+  /* This is called whenever the systemd activator sent us a
+     response. We'll invalidate all pending activations that match the
+     unit name. */
+
+  if (dbus_message_get_args (message, &error,
+                             DBUS_TYPE_STRING, &unit,
+                             DBUS_TYPE_STRING, &code,
+                             DBUS_TYPE_STRING, &str,
+                             DBUS_TYPE_INVALID))
+    dbus_set_error(&error, code, str);
+
+
+  if (unit)
+    {
+      DBusHashIter iter;
+
+      bus_context_log (activation->context,
+                       DBUS_SYSTEM_LOG_INFO, "Activation via systemd failed for unit '%s': %s",
+                       unit,
+                       str);
+
+      _dbus_hash_iter_init (activation->pending_activations,
+                            &iter);
+
+      while (_dbus_hash_iter_next (&iter))
+        {
+          BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
+
+          if (p->systemd_service && strcmp (p->systemd_service, unit) == 0)
+            pending_activation_failed(p, &error);
+        }
+    }
+
+  dbus_error_free(&error);
+
+  return TRUE;
+}
+
+#ifdef DBUS_BUILD_TESTS
+
+#include <stdio.h>
+
+#define SERVICE_NAME_1 "MyService1"
+#define SERVICE_NAME_2 "MyService2"
+#define SERVICE_NAME_3 "MyService3"
+
+#define SERVICE_FILE_1 "service-1.service"
+#define SERVICE_FILE_2 "service-2.service"
+#define SERVICE_FILE_3 "service-3.service"
+
+static dbus_bool_t
+test_create_service_file (DBusString *dir,
+                          const char *filename,
+                          const char *name,
+                          const char *exec)
+{
+  DBusString  file_name, full_path;
+  FILE        *file;
+  dbus_bool_t  ret_val;
+
+  ret_val = TRUE;
+  _dbus_string_init_const (&file_name, filename);
+
+  if (!_dbus_string_init (&full_path))
+    return FALSE;
+
+  if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
+      !_dbus_concat_dir_and_file (&full_path, &file_name))
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+
+  file = fopen (_dbus_string_get_const_data (&full_path), "w");
+  if (!file)
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+
+  fprintf (file, "[D-BUS Service]\nName=%s\nExec=%s\n", name, exec);
+  fclose (file);
+
+out:
+  _dbus_string_free (&full_path);
+  return ret_val;
+}
+
+static dbus_bool_t
+test_remove_service_file (DBusString *dir, const char *filename)
+{
+  DBusString  file_name, full_path;
+  dbus_bool_t ret_val;
+
+  ret_val = TRUE;
+
+  _dbus_string_init_const (&file_name, filename);
+
+  if (!_dbus_string_init (&full_path))
+    return FALSE;
+
+  if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
+      !_dbus_concat_dir_and_file (&full_path, &file_name))
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+
+  if (!_dbus_delete_file (&full_path, NULL))
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+
+out:
+  _dbus_string_free (&full_path);
+  return ret_val;
+}
+
+static dbus_bool_t
+test_remove_directory (DBusString *dir)
+{
+  DBusDirIter *iter;
+  DBusString   filename, full_path;
+  dbus_bool_t  ret_val;
+
+  ret_val = TRUE;
+
+  if (!_dbus_string_init (&filename))
+    return FALSE;
+
+  if (!_dbus_string_init (&full_path))
+    {
+      _dbus_string_free (&filename);
+      return FALSE;
+    }
+
+  iter = _dbus_directory_open (dir, NULL);
+  if (iter == NULL)
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+
+  while (_dbus_directory_get_next_file (iter, &filename, NULL))
+    {
+      if (!test_remove_service_file (dir, _dbus_string_get_const_data (&filename)))
+        {
+          ret_val = FALSE;
+          goto out;
+        }
+    }
+  _dbus_directory_close (iter);
+
+  if (!_dbus_delete_directory (dir, NULL))
+    {
+      ret_val = FALSE;
+      goto out;
+    }
+
+out:
+  _dbus_string_free (&filename);
+  _dbus_string_free (&full_path);
+
+  return ret_val;
+}
+
+static dbus_bool_t
+init_service_reload_test (DBusString *dir)
+{
+  DBusStat stat_buf;
+
+  if (!_dbus_stat (dir, &stat_buf, NULL))
+    {
+      if (!_dbus_create_directory (dir, NULL))
+        return FALSE;
+    }
+  else
+    {
+      if (!test_remove_directory (dir))
+        return FALSE;
+
+      if (!_dbus_create_directory (dir, NULL))
+        return FALSE;
+    }
+
+  /* Create one initial file */
+  if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_1, "exec-1"))
+    return FALSE;
+
+  return TRUE;
+}
+
+static dbus_bool_t
+cleanup_service_reload_test (DBusString *dir)
+{
+  if (!test_remove_directory (dir))
+    return FALSE;
+
+  return TRUE;
+}
+
+typedef struct
+{
+  BusActivation *activation;
+  const char    *service_name;
+  dbus_bool_t    expecting_find;
+} CheckData;
+
+static dbus_bool_t
+check_func (void *data)
+{
+  CheckData          *d;
+  BusActivationEntry *entry;
+  DBusError           error;
+  dbus_bool_t         ret_val;
+
+  ret_val = TRUE;
+  d = data;
+
+  dbus_error_init (&error);
+
+  entry = activation_find_entry (d->activation, d->service_name, &error);
+  if (entry == NULL)
+    {
+      if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+        {
+          ret_val = TRUE;
+        }
+      else
+        {
+          if (d->expecting_find)
+            ret_val = FALSE;
+        }
+
+      dbus_error_free (&error);
+    }
+  else
+    {
+      if (!d->expecting_find)
+        ret_val = FALSE;
+    }
+
+  return ret_val;
+}
+
+static dbus_bool_t
+do_test (const char *description, dbus_bool_t oom_test, CheckData *data)
+{
+  dbus_bool_t err;
+
+  if (oom_test)
+    err = !_dbus_test_oom_handling (description, check_func, data);
+  else
+    err = !check_func (data);
+
+  if (err)
+    _dbus_assert_not_reached ("Test failed");
+
+  return TRUE;
+}
+
+static dbus_bool_t
+do_service_reload_test (DBusString *dir, dbus_bool_t oom_test)
+{
+  BusActivation *activation;
+  DBusString     address;
+  DBusList      *directories;
+  CheckData      d;
+
+  directories = NULL;
+  _dbus_string_init_const (&address, "");
+
+  if (!_dbus_list_append (&directories, _dbus_string_get_data (dir)))
+    return FALSE;
+
+  activation = bus_activation_new (NULL, &address, &directories, NULL);
+  if (!activation)
+    return FALSE;
+
+  d.activation = activation;
+
+  /* Check for existing service file */
+  d.expecting_find = TRUE;
+  d.service_name = SERVICE_NAME_1;
+
+  if (!do_test ("Existing service file", oom_test, &d))
+    return FALSE;
+
+  /* Check for non-existing service file */
+  d.expecting_find = FALSE;
+  d.service_name = SERVICE_NAME_3;
+
+  if (!do_test ("Nonexisting service file", oom_test, &d))
+    return FALSE;
+
+  /* Check for added service file */
+  if (!test_create_service_file (dir, SERVICE_FILE_2, SERVICE_NAME_2, "exec-2"))
+    return FALSE;
+
+  d.expecting_find = TRUE;
+  d.service_name = SERVICE_NAME_2;
+
+  if (!do_test ("Added service file", oom_test, &d))
+    return FALSE;
+
+  /* Check for removed service file */
+  if (!test_remove_service_file (dir, SERVICE_FILE_2))
+    return FALSE;
+
+  d.expecting_find = FALSE;
+  d.service_name = SERVICE_FILE_2;
+
+  if (!do_test ("Removed service file", oom_test, &d))
+    return FALSE;
+
+  /* Check for updated service file */
+
+  _dbus_sleep_milliseconds (1000); /* Sleep a second to make sure the mtime is updated */
+
+  if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_3, "exec-3"))
+    return FALSE;
+
+  d.expecting_find = TRUE;
+  d.service_name = SERVICE_NAME_3;
+
+  if (!do_test ("Updated service file, part 1", oom_test, &d))
+    return FALSE;
+
+  d.expecting_find = FALSE;
+  d.service_name = SERVICE_NAME_1;
+
+  if (!do_test ("Updated service file, part 2", oom_test, &d))
+    return FALSE;
+
+  bus_activation_unref (activation);
+  _dbus_list_clear (&directories);
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_activation_service_reload_test (const DBusString *test_data_dir)
+{
+  DBusString directory;
+
+  if (!_dbus_string_init (&directory))
+    return FALSE;
+
+  if (!_dbus_string_append (&directory, _dbus_get_tmpdir()))
+    return FALSE;
+
+  if (!_dbus_string_append (&directory, "/dbus-reload-test-") ||
+      !_dbus_generate_random_ascii (&directory, 6))
+     {
+       return FALSE;
+     }
+
+  /* Do normal tests */
+  if (!init_service_reload_test (&directory))
+    _dbus_assert_not_reached ("could not initiate service reload test");
+
+  if (!do_service_reload_test (&directory, FALSE))
+    {
+      /* Do nothing? */
+    }
+
+  /* Do OOM tests */
+  if (!init_service_reload_test (&directory))
+    _dbus_assert_not_reached ("could not initiate service reload test");
+
+  if (!do_service_reload_test (&directory, TRUE))
+    {
+      /* Do nothing? */
+    }
+
+  /* Cleanup test directory */
+  if (!cleanup_service_reload_test (&directory))
+    return FALSE;
+
+  _dbus_string_free (&directory);
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/bus/activation.h b/dbus/bus/activation.h
new file mode 100644
index 0000000..97f25b1
--- /dev/null
+++ b/dbus/bus/activation.h
@@ -0,0 +1,69 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* activation.h  Activation of services
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef BUS_ACTIVATION_H
+#define BUS_ACTIVATION_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-list.h>
+#include "bus.h"
+
+BusActivation* bus_activation_new              (BusContext        *context,
+						const DBusString  *address,
+						DBusList         **directories,
+						DBusError         *error);
+dbus_bool_t bus_activation_reload           (BusActivation     *activation,
+						const DBusString  *address,
+						DBusList         **directories,
+						DBusError         *error);
+BusActivation* bus_activation_ref              (BusActivation     *activation);
+void           bus_activation_unref            (BusActivation     *activation);
+
+dbus_bool_t   bus_activation_set_environment_variable (BusActivation     *activation,
+						const char        *key,
+						const char        *value,
+						DBusError         *error);
+dbus_bool_t    bus_activation_activate_service (BusActivation     *activation,
+						DBusConnection    *connection,
+						BusTransaction    *transaction,
+						dbus_bool_t        auto_activation,
+						DBusMessage       *activation_message,
+						const char        *service_name,
+						DBusError         *error);
+dbus_bool_t    bus_activation_service_created  (BusActivation     *activation,
+						const char        *service_name,
+						BusTransaction    *transaction,
+						DBusError         *error);
+dbus_bool_t    bus_activation_list_services    (BusActivation     *registry,
+						char            ***listp,
+						int               *array_len);
+dbus_bool_t    dbus_activation_systemd_failure (BusActivation     *activation,
+                                                DBusMessage       *message);
+
+dbus_bool_t    bus_activation_send_pending_auto_activation_messages (BusActivation     *activation,
+								     BusService        *service,
+								     BusTransaction    *transaction,
+								     DBusError         *error);
+
+
+#endif /* BUS_ACTIVATION_H */
diff --git a/dbus/bus/bus.c b/dbus/bus/bus.c
new file mode 100644
index 0000000..bc27f46
--- /dev/null
+++ b/dbus/bus/bus.c
@@ -0,0 +1,1671 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* bus.c  message bus context object
+ *
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "bus.h"
+
+#include <stdio.h>
+
+#include "activation.h"
+#include "connection.h"
+#include "services.h"
+#include "utils.h"
+#include "policy.h"
+#include "config-parser.h"
+#include "signals.h"
+#include "selinux.h"
+#include "dir-watch.h"
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-hash.h>
+#include <dbus/dbus-credentials.h>
+#include <dbus/dbus-internals.h>
+
+#ifdef DBUS_CYGWIN
+#include <signal.h>
+#endif
+
+struct BusContext
+{
+  int refcount;
+  DBusGUID uuid;
+  char *config_file;
+  char *type;
+  char *servicehelper;
+  char *address;
+#ifdef WANT_PIDFILE
+  char *pidfile;
+#endif
+  char *user;
+  char *log_prefix;
+  DBusLoop *loop;
+  DBusList *servers;
+  BusConnections *connections;
+  BusActivation *activation;
+  BusRegistry *registry;
+  BusPolicy *policy;
+  BusMatchmaker *matchmaker;
+  BusLimits limits;
+  unsigned int fork : 1;
+  unsigned int syslog : 1;
+  unsigned int keep_umask : 1;
+  unsigned int allow_anonymous : 1;
+  unsigned int systemd_activation : 1;
+};
+
+static dbus_int32_t server_data_slot = -1;
+
+typedef struct
+{
+  BusContext *context;
+} BusServerData;
+
+#define BUS_SERVER_DATA(server) (dbus_server_get_data ((server), server_data_slot))
+
+static BusContext*
+server_get_context (DBusServer *server)
+{
+  BusContext *context;
+  BusServerData *bd;
+
+  if (!dbus_server_allocate_data_slot (&server_data_slot))
+    return NULL;
+
+  bd = BUS_SERVER_DATA (server);
+  if (bd == NULL)
+    {
+      dbus_server_free_data_slot (&server_data_slot);
+      return NULL;
+    }
+
+  context = bd->context;
+
+  dbus_server_free_data_slot (&server_data_slot);
+
+  return context;
+}
+
+static dbus_bool_t
+add_server_watch (DBusWatch  *watch,
+                  void       *data)
+{
+  DBusServer *server = data;
+  BusContext *context;
+
+  context = server_get_context (server);
+
+  return _dbus_loop_add_watch (context->loop, watch);
+}
+
+static void
+remove_server_watch (DBusWatch  *watch,
+                     void       *data)
+{
+  DBusServer *server = data;
+  BusContext *context;
+
+  context = server_get_context (server);
+
+  _dbus_loop_remove_watch (context->loop, watch);
+}
+
+static void
+toggle_server_watch (DBusWatch  *watch,
+                     void       *data)
+{
+  DBusServer *server = data;
+  BusContext *context;
+
+  context = server_get_context (server);
+
+  _dbus_loop_toggle_watch (context->loop, watch);
+}
+
+static dbus_bool_t
+add_server_timeout (DBusTimeout *timeout,
+                    void        *data)
+{
+  DBusServer *server = data;
+  BusContext *context;
+
+  context = server_get_context (server);
+
+  return _dbus_loop_add_timeout (context->loop, timeout);
+}
+
+static void
+remove_server_timeout (DBusTimeout *timeout,
+                       void        *data)
+{
+  DBusServer *server = data;
+  BusContext *context;
+
+  context = server_get_context (server);
+
+  _dbus_loop_remove_timeout (context->loop, timeout);
+}
+
+static void
+new_connection_callback (DBusServer     *server,
+                         DBusConnection *new_connection,
+                         void           *data)
+{
+  BusContext *context = data;
+
+  if (!bus_connections_setup_connection (context->connections, new_connection))
+    {
+      _dbus_verbose ("No memory to setup new connection\n");
+
+      /* if we don't do this, it will get unref'd without
+       * being disconnected... kind of strange really
+       * that we have to do this, people won't get it right
+       * in general.
+       */
+      dbus_connection_close (new_connection);
+    }
+
+  dbus_connection_set_max_received_size (new_connection,
+                                         context->limits.max_incoming_bytes);
+
+  dbus_connection_set_max_message_size (new_connection,
+                                        context->limits.max_message_size);
+
+  dbus_connection_set_max_received_unix_fds (new_connection,
+                                         context->limits.max_incoming_unix_fds);
+
+  dbus_connection_set_max_message_unix_fds (new_connection,
+                                        context->limits.max_message_unix_fds);
+
+  dbus_connection_set_allow_anonymous (new_connection,
+                                       context->allow_anonymous);
+
+  /* on OOM, we won't have ref'd the connection so it will die. */
+}
+
+static void
+free_server_data (void *data)
+{
+  BusServerData *bd = data;
+
+  dbus_free (bd);
+}
+
+static dbus_bool_t
+setup_server (BusContext *context,
+              DBusServer *server,
+              char      **auth_mechanisms,
+              DBusError  *error)
+{
+  BusServerData *bd;
+
+  bd = dbus_new0 (BusServerData, 1);
+  if (bd == NULL || !dbus_server_set_data (server,
+                                           server_data_slot,
+                                           bd, free_server_data))
+    {
+      dbus_free (bd);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  bd->context = context;
+
+  if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  dbus_server_set_new_connection_function (server,
+                                           new_connection_callback,
+                                           context, NULL);
+
+  if (!dbus_server_set_watch_functions (server,
+                                        add_server_watch,
+                                        remove_server_watch,
+                                        toggle_server_watch,
+                                        server,
+                                        NULL))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!dbus_server_set_timeout_functions (server,
+                                          add_server_timeout,
+                                          remove_server_timeout,
+                                          NULL,
+                                          server, NULL))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* This code only gets executed the first time the
+ * config files are parsed.  It is not executed
+ * when config files are reloaded.
+ */
+static dbus_bool_t
+process_config_first_time_only (BusContext       *context,
+				BusConfigParser  *parser,
+                                const DBusString *address,
+                                BusContextFlags   flags,
+				DBusError        *error)
+{
+  DBusString log_prefix;
+  DBusList *link;
+  DBusList **addresses;
+  const char *user, *pidfile;
+  char **auth_mechanisms;
+  DBusList **auth_mechanisms_list;
+  int len;
+  dbus_bool_t retval;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  retval = FALSE;
+  auth_mechanisms = NULL;
+  pidfile = NULL;
+
+  _dbus_init_system_log ();
+
+  if (flags & BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION)
+    context->systemd_activation = TRUE;
+  else
+    context->systemd_activation = FALSE;
+
+#ifdef WANT_PIDFILE
+  /* Check for an existing pid file. Of course this is a race;
+   * we'd have to use fcntl() locks on the pid file to
+   * avoid that. But we want to check for the pid file
+   * before overwriting any existing sockets, etc.
+   */
+
+  if (flags & BUS_CONTEXT_FLAG_WRITE_PID_FILE)
+    pidfile = bus_config_parser_get_pidfile (parser);
+
+  if (pidfile != NULL)
+    {
+      DBusString u;
+      DBusStat stbuf;
+
+      _dbus_string_init_const (&u, pidfile);
+
+      if (_dbus_stat (&u, &stbuf, NULL))
+        {
+#ifdef DBUS_CYGWIN
+          DBusString p;
+          long /* int */ pid;
+
+          _dbus_string_init (&p);
+          _dbus_file_get_contents(&p, &u, NULL);
+          _dbus_string_parse_int(&p, 0, &pid, NULL);
+          _dbus_string_free(&p);
+
+          if ((kill((int)pid, 0))) {
+            dbus_set_error(NULL, DBUS_ERROR_FILE_EXISTS,
+                           "pid %ld not running, removing stale pid file\n",
+                           pid);
+            _dbus_delete_file(&u, NULL);
+          } else {
+#endif
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+		                  "The pid file \"%s\" exists, if the message bus is not running, remove this file",
+                          pidfile);
+	      goto failed;
+#ifdef DBUS_CYGWIN
+          }
+#endif
+        }
+    }
+
+  /* keep around the pid filename so we can delete it later */
+  context->pidfile = _dbus_strdup (pidfile);
+#endif
+
+  /* note that type may be NULL */
+  context->type = _dbus_strdup (bus_config_parser_get_type (parser));
+  if (bus_config_parser_get_type (parser) != NULL && context->type == NULL)
+    goto oom;
+
+  user = bus_config_parser_get_user (parser);
+  if (user != NULL)
+    {
+      context->user = _dbus_strdup (user);
+      if (context->user == NULL)
+        goto oom;
+    }
+
+  /* Set up the prefix for syslog messages */
+  if (!_dbus_string_init (&log_prefix))
+    goto oom;
+  if (context->type && !strcmp (context->type, "system"))
+    {
+      if (!_dbus_string_append (&log_prefix, "[system] "))
+        goto oom;
+    }
+  else if (context->type && !strcmp (context->type, "session"))
+    {
+      DBusCredentials *credentials;
+
+      credentials = _dbus_credentials_new_from_current_process ();
+      if (!credentials)
+        goto oom;
+      if (!_dbus_string_append (&log_prefix, "[session "))
+        {
+          _dbus_credentials_unref (credentials);
+          goto oom;
+        }
+      if (!_dbus_credentials_to_string_append (credentials, &log_prefix))
+        {
+          _dbus_credentials_unref (credentials);
+          goto oom;
+        }
+      if (!_dbus_string_append (&log_prefix, "] "))
+        {
+          _dbus_credentials_unref (credentials);
+          goto oom;
+        }
+      _dbus_credentials_unref (credentials);
+    }
+  if (!_dbus_string_steal_data (&log_prefix, &context->log_prefix))
+    goto oom;
+  _dbus_string_free (&log_prefix);
+
+  /* Build an array of auth mechanisms */
+
+  auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
+  len = _dbus_list_get_length (auth_mechanisms_list);
+
+  if (len > 0)
+    {
+      int i;
+
+      auth_mechanisms = dbus_new0 (char*, len + 1);
+      if (auth_mechanisms == NULL)
+        goto oom;
+
+      i = 0;
+      link = _dbus_list_get_first_link (auth_mechanisms_list);
+      while (link != NULL)
+        {
+          auth_mechanisms[i] = _dbus_strdup (link->data);
+          if (auth_mechanisms[i] == NULL)
+            goto oom;
+          link = _dbus_list_get_next_link (auth_mechanisms_list, link);
+          i += 1;
+        }
+    }
+  else
+    {
+      auth_mechanisms = NULL;
+    }
+
+  /* Listen on our addresses */
+
+  if (address)
+    {
+      DBusServer *server;
+
+      server = dbus_server_listen (_dbus_string_get_const_data(address), error);
+      if (server == NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          goto failed;
+        }
+      else if (!setup_server (context, server, auth_mechanisms, error))
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          goto failed;
+        }
+
+      if (!_dbus_list_append (&context->servers, server))
+        goto oom;
+    }
+  else
+    {
+      addresses = bus_config_parser_get_addresses (parser);
+
+      link = _dbus_list_get_first_link (addresses);
+      while (link != NULL)
+        {
+          DBusServer *server;
+
+          server = dbus_server_listen (link->data, error);
+          if (server == NULL)
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (error);
+              goto failed;
+            }
+          else if (!setup_server (context, server, auth_mechanisms, error))
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (error);
+              goto failed;
+            }
+
+          if (!_dbus_list_append (&context->servers, server))
+            goto oom;
+
+          link = _dbus_list_get_next_link (addresses, link);
+        }
+    }
+
+  context->fork = bus_config_parser_get_fork (parser);
+  context->syslog = bus_config_parser_get_syslog (parser);
+  context->keep_umask = bus_config_parser_get_keep_umask (parser);
+  context->allow_anonymous = bus_config_parser_get_allow_anonymous (parser);
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  retval = TRUE;
+
+ failed:
+  dbus_free_string_array (auth_mechanisms);
+  return retval;
+
+ oom:
+  BUS_SET_OOM (error);
+  dbus_free_string_array (auth_mechanisms);
+  return FALSE;
+}
+
+/* This code gets executed every time the config files
+ * are parsed: both during BusContext construction
+ * and on reloads. This function is slightly screwy
+ * since it can do a "half reload" in out-of-memory
+ * situations. Realistically, unlikely to ever matter.
+ */
+static dbus_bool_t
+process_config_every_time (BusContext      *context,
+			   BusConfigParser *parser,
+			   dbus_bool_t      is_reload,
+			   DBusError       *error)
+{
+  DBusString full_address;
+  DBusList *link;
+  DBusList **dirs;
+  char *addr;
+  const char *servicehelper;
+  char *s;
+
+  dbus_bool_t retval;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  addr = NULL;
+  retval = FALSE;
+
+  if (!_dbus_string_init (&full_address))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  /* get our limits and timeout lengths */
+  bus_config_parser_get_limits (parser, &context->limits);
+
+  if (context->policy)
+    bus_policy_unref (context->policy);
+  context->policy = bus_config_parser_steal_policy (parser);
+  _dbus_assert (context->policy != NULL);
+
+  /* We have to build the address backward, so that
+   * <listen> later in the config file have priority
+   */
+  link = _dbus_list_get_last_link (&context->servers);
+  while (link != NULL)
+    {
+      addr = dbus_server_get_address (link->data);
+      if (addr == NULL)
+        {
+          BUS_SET_OOM (error);
+          goto failed;
+        }
+
+      if (_dbus_string_get_length (&full_address) > 0)
+        {
+          if (!_dbus_string_append (&full_address, ";"))
+            {
+              BUS_SET_OOM (error);
+              goto failed;
+            }
+        }
+
+      if (!_dbus_string_append (&full_address, addr))
+        {
+          BUS_SET_OOM (error);
+          goto failed;
+        }
+
+      dbus_free (addr);
+      addr = NULL;
+
+      link = _dbus_list_get_prev_link (&context->servers, link);
+    }
+
+  if (is_reload)
+    dbus_free (context->address);
+
+  if (!_dbus_string_copy_data (&full_address, &context->address))
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  /* get the service directories */
+  dirs = bus_config_parser_get_service_dirs (parser);
+
+  /* and the service helper */
+  servicehelper = bus_config_parser_get_servicehelper (parser);
+
+  s = _dbus_strdup(servicehelper);
+  if (s == NULL && servicehelper != NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+  else
+    {
+      dbus_free(context->servicehelper);
+      context->servicehelper = s;
+    }
+
+  /* Create activation subsystem */
+  if (context->activation)
+    {
+      if (!bus_activation_reload (context->activation, &full_address, dirs, error))
+        goto failed;
+    }
+  else
+    {
+      context->activation = bus_activation_new (context, &full_address, dirs, error);
+    }
+
+  if (context->activation == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  retval = TRUE;
+
+ failed:
+  _dbus_string_free (&full_address);
+
+  if (addr)
+    dbus_free (addr);
+
+  return retval;
+}
+
+static dbus_bool_t
+list_concat_new (DBusList **a,
+                 DBusList **b,
+                 DBusList **result)
+{
+  DBusList *link;
+
+  *result = NULL;
+
+  for (link = _dbus_list_get_first_link (a); link; link = _dbus_list_get_next_link (a, link))
+    {
+      if (!_dbus_list_append (result, link->data))
+        goto oom;
+    }
+  for (link = _dbus_list_get_first_link (b); link; link = _dbus_list_get_next_link (b, link))
+    {
+      if (!_dbus_list_append (result, link->data))
+        goto oom;
+    }
+
+  return TRUE;
+oom:
+  _dbus_list_clear (result);
+  return FALSE;
+}
+
+static void
+raise_file_descriptor_limit (BusContext      *context)
+{
+
+  /* I just picked this out of thin air; we need some extra
+   * descriptors for things like any internal pipes we create,
+   * inotify, connections to SELinux, etc.
+   */
+  unsigned int arbitrary_extra_fds = 32;
+  unsigned int limit;
+
+  limit = context->limits.max_completed_connections +
+    context->limits.max_incomplete_connections
+    + arbitrary_extra_fds;
+
+  _dbus_request_file_descriptor_limit (limit);
+}
+
+static dbus_bool_t
+process_config_postinit (BusContext      *context,
+			 BusConfigParser *parser,
+			 DBusError       *error)
+{
+  DBusHashTable *service_context_table;
+  DBusList *watched_dirs = NULL;
+
+  raise_file_descriptor_limit (context);
+
+  service_context_table = bus_config_parser_steal_service_context_table (parser);
+  if (!bus_registry_set_service_context_table (context->registry,
+					       service_context_table))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  _dbus_hash_table_unref (service_context_table);
+
+  /* We need to monitor both the configuration directories and directories
+   * containing .service files.
+   */
+  if (!list_concat_new (bus_config_parser_get_conf_dirs (parser),
+                        bus_config_parser_get_service_dirs (parser),
+                        &watched_dirs))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  bus_set_watched_dirs (context, &watched_dirs);
+
+  _dbus_list_clear (&watched_dirs);
+
+  return TRUE;
+}
+
+BusContext*
+bus_context_new (const DBusString *config_file,
+                 BusContextFlags   flags,
+                 DBusPipe         *print_addr_pipe,
+                 DBusPipe         *print_pid_pipe,
+                 const DBusString *address,
+                 DBusError        *error)
+{
+  BusContext *context;
+  BusConfigParser *parser;
+
+  _dbus_assert ((flags & BUS_CONTEXT_FLAG_FORK_NEVER) == 0 ||
+                (flags & BUS_CONTEXT_FLAG_FORK_ALWAYS) == 0);
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  context = NULL;
+  parser = NULL;
+
+  if (!dbus_server_allocate_data_slot (&server_data_slot))
+    {
+      BUS_SET_OOM (error);
+      return NULL;
+    }
+
+  context = dbus_new0 (BusContext, 1);
+  if (context == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+  context->refcount = 1;
+
+  _dbus_generate_uuid (&context->uuid);
+
+  if (!_dbus_string_copy_data (config_file, &context->config_file))
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  context->loop = _dbus_loop_new ();
+  if (context->loop == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  context->registry = bus_registry_new (context);
+  if (context->registry == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  parser = bus_config_load (config_file, TRUE, NULL, error);
+  if (parser == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+
+  if (!process_config_first_time_only (context, parser, address, flags, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+  if (!process_config_every_time (context, parser, FALSE, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+
+  /* we need another ref of the server data slot for the context
+   * to own
+   */
+  if (!dbus_server_allocate_data_slot (&server_data_slot))
+    _dbus_assert_not_reached ("second ref of server data slot failed");
+
+  /* Note that we don't know whether the print_addr_pipe is
+   * one of the sockets we're using to listen on, or some
+   * other random thing. But I think the answer is "don't do
+   * that then"
+   */
+  if (print_addr_pipe != NULL && _dbus_pipe_is_valid (print_addr_pipe))
+    {
+      DBusString addr;
+      const char *a = bus_context_get_address (context);
+      int bytes;
+
+      _dbus_assert (a != NULL);
+      if (!_dbus_string_init (&addr))
+        {
+          BUS_SET_OOM (error);
+          goto failed;
+        }
+
+      if (!_dbus_string_append (&addr, a) ||
+          !_dbus_string_append (&addr, "\n"))
+        {
+          _dbus_string_free (&addr);
+          BUS_SET_OOM (error);
+          goto failed;
+        }
+
+      bytes = _dbus_string_get_length (&addr);
+      if (_dbus_pipe_write (print_addr_pipe, &addr, 0, bytes, error) != bytes)
+        {
+          /* pipe write returns an error on failure but not short write */
+          if (error != NULL && !dbus_error_is_set (error))
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Printing message bus address: did not write all bytes\n");
+            }
+          _dbus_string_free (&addr);
+          goto failed;
+        }
+
+      if (!_dbus_pipe_is_stdout_or_stderr (print_addr_pipe))
+        _dbus_pipe_close (print_addr_pipe, NULL);
+
+      _dbus_string_free (&addr);
+    }
+
+  context->connections = bus_connections_new (context);
+  if (context->connections == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  context->matchmaker = bus_matchmaker_new ();
+  if (context->matchmaker == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  /* check user before we fork */
+  if (context->user != NULL)
+    {
+      if (!_dbus_verify_daemon_user (context->user))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Could not get UID and GID for username \"%s\"",
+                          context->user);
+          goto failed;
+        }
+    }
+
+  /* Now become a daemon if appropriate and write out pid file in any case */
+  {
+#ifdef WANT_PIDFILE
+    DBusString u;
+
+    if (context->pidfile)
+      _dbus_string_init_const (&u, context->pidfile);
+
+    if (((flags & BUS_CONTEXT_FLAG_FORK_NEVER) == 0 && context->fork) ||
+        (flags & BUS_CONTEXT_FLAG_FORK_ALWAYS))
+      {
+        _dbus_verbose ("Forking and becoming daemon\n");
+
+        if (!_dbus_become_daemon (context->pidfile ? &u : NULL,
+                                  print_pid_pipe,
+                                  error,
+                                  context->keep_umask))
+
+          {
+            _DBUS_ASSERT_ERROR_IS_SET (error);
+            goto failed;
+          }
+      }
+    else
+      {
+        _dbus_verbose ("Fork not requested\n");
+
+        /* Need to write PID file and to PID pipe for ourselves,
+         * not for the child process. This is a no-op if the pidfile
+         * is NULL and print_pid_pipe is NULL.
+         */
+        if (!_dbus_write_pid_to_file_and_pipe (context->pidfile ? &u : NULL,
+                                               print_pid_pipe,
+                                               _dbus_getpid (),
+                                               error))
+          {
+            _DBUS_ASSERT_ERROR_IS_SET (error);
+            goto failed;
+          }
+      }
+#else
+    if (((flags & BUS_CONTEXT_FLAG_FORK_NEVER) == 0 && context->fork) ||
+        (flags & BUS_CONTEXT_FLAG_FORK_ALWAYS))
+      {
+        if (!_dbus_become_daemon (NULL,
+                                  0,
+                                  error,
+                                  context->keep_umask))
+          {
+            _DBUS_ASSERT_ERROR_IS_SET (error);
+            goto failed;
+          }
+      }
+#endif
+  }
+
+  if (print_pid_pipe && _dbus_pipe_is_valid (print_pid_pipe) &&
+      !_dbus_pipe_is_stdout_or_stderr (print_pid_pipe))
+    _dbus_pipe_close (print_pid_pipe, NULL);
+
+  if (!bus_selinux_full_init ())
+    {
+      bus_context_log (context, DBUS_SYSTEM_LOG_FATAL, "SELinux enabled but AVC initialization failed; check system log\n");
+    }
+
+  if (!process_config_postinit (context, parser, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+
+  if (parser != NULL)
+    {
+      bus_config_parser_unref (parser);
+      parser = NULL;
+    }
+
+  /* Here we change our credentials if required,
+   * as soon as we've set up our sockets and pidfile
+   */
+  if (context->user != NULL)
+    {
+      if (!_dbus_change_to_daemon_user (context->user, error))
+	{
+	  _DBUS_ASSERT_ERROR_IS_SET (error);
+	  goto failed;
+	}
+
+#ifdef HAVE_SELINUX
+      /* FIXME - why not just put this in full_init() below? */
+      bus_selinux_audit_init ();
+#endif
+    }
+
+  dbus_server_free_data_slot (&server_data_slot);
+
+  return context;
+
+ failed:
+  if (parser != NULL)
+    bus_config_parser_unref (parser);
+  if (context != NULL)
+    bus_context_unref (context);
+
+  if (server_data_slot >= 0)
+    dbus_server_free_data_slot (&server_data_slot);
+
+  return NULL;
+}
+
+dbus_bool_t
+bus_context_get_id (BusContext       *context,
+                    DBusString       *uuid)
+{
+  return _dbus_uuid_encode (&context->uuid, uuid);
+}
+
+dbus_bool_t
+bus_context_reload_config (BusContext *context,
+			   DBusError  *error)
+{
+  BusConfigParser *parser;
+  DBusString config_file;
+  dbus_bool_t ret;
+
+  /* Flush the user database cache */
+  _dbus_flush_caches ();
+
+  ret = FALSE;
+  _dbus_string_init_const (&config_file, context->config_file);
+  parser = bus_config_load (&config_file, TRUE, NULL, error);
+  if (parser == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+
+  if (!process_config_every_time (context, parser, TRUE, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+  if (!process_config_postinit (context, parser, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+  ret = TRUE;
+
+  bus_context_log (context, DBUS_SYSTEM_LOG_INFO, "Reloaded configuration");
+ failed:
+  if (!ret)
+    bus_context_log (context, DBUS_SYSTEM_LOG_INFO, "Unable to reload configuration: %s", error->message);
+  if (parser != NULL)
+    bus_config_parser_unref (parser);
+  return ret;
+}
+
+static void
+shutdown_server (BusContext *context,
+                 DBusServer *server)
+{
+  if (server == NULL ||
+      !dbus_server_get_is_connected (server))
+    return;
+
+  if (!dbus_server_set_watch_functions (server,
+                                        NULL, NULL, NULL,
+                                        context,
+                                        NULL))
+    _dbus_assert_not_reached ("setting watch functions to NULL failed");
+
+  if (!dbus_server_set_timeout_functions (server,
+                                          NULL, NULL, NULL,
+                                          context,
+                                          NULL))
+    _dbus_assert_not_reached ("setting timeout functions to NULL failed");
+
+  dbus_server_disconnect (server);
+}
+
+void
+bus_context_shutdown (BusContext  *context)
+{
+  DBusList *link;
+
+  link = _dbus_list_get_first_link (&context->servers);
+  while (link != NULL)
+    {
+      shutdown_server (context, link->data);
+
+      link = _dbus_list_get_next_link (&context->servers, link);
+    }
+}
+
+BusContext *
+bus_context_ref (BusContext *context)
+{
+  _dbus_assert (context->refcount > 0);
+  context->refcount += 1;
+
+  return context;
+}
+
+void
+bus_context_unref (BusContext *context)
+{
+  _dbus_assert (context->refcount > 0);
+  context->refcount -= 1;
+
+  if (context->refcount == 0)
+    {
+      DBusList *link;
+
+      _dbus_verbose ("Finalizing bus context %p\n", context);
+
+      bus_context_shutdown (context);
+
+      if (context->connections)
+        {
+          bus_connections_unref (context->connections);
+          context->connections = NULL;
+        }
+
+      if (context->registry)
+        {
+          bus_registry_unref (context->registry);
+          context->registry = NULL;
+        }
+
+      if (context->activation)
+        {
+          bus_activation_unref (context->activation);
+          context->activation = NULL;
+        }
+
+      link = _dbus_list_get_first_link (&context->servers);
+      while (link != NULL)
+        {
+          dbus_server_unref (link->data);
+
+          link = _dbus_list_get_next_link (&context->servers, link);
+        }
+      _dbus_list_clear (&context->servers);
+
+      if (context->policy)
+        {
+          bus_policy_unref (context->policy);
+          context->policy = NULL;
+        }
+
+      if (context->loop)
+        {
+          _dbus_loop_unref (context->loop);
+          context->loop = NULL;
+        }
+
+      if (context->matchmaker)
+        {
+          bus_matchmaker_unref (context->matchmaker);
+          context->matchmaker = NULL;
+        }
+
+      dbus_free (context->config_file);
+      dbus_free (context->log_prefix);
+      dbus_free (context->type);
+      dbus_free (context->address);
+      dbus_free (context->user);
+      dbus_free (context->servicehelper);
+
+#ifdef WANT_PIDFILE
+      if (context->pidfile)
+	{
+          DBusString u;
+          _dbus_string_init_const (&u, context->pidfile);
+
+          /* Deliberately ignore errors here, since there's not much
+	   * we can do about it, and we're exiting anyways.
+	   */
+	  _dbus_delete_file (&u, NULL);
+
+          dbus_free (context->pidfile);
+	}
+#endif
+
+      dbus_free (context);
+
+      dbus_server_free_data_slot (&server_data_slot);
+    }
+}
+
+/* type may be NULL */
+const char*
+bus_context_get_type (BusContext *context)
+{
+  return context->type;
+}
+
+const char*
+bus_context_get_address (BusContext *context)
+{
+  return context->address;
+}
+
+const char*
+bus_context_get_servicehelper (BusContext *context)
+{
+  return context->servicehelper;
+}
+
+dbus_bool_t
+bus_context_get_systemd_activation (BusContext *context)
+{
+  return context->systemd_activation;
+}
+
+BusRegistry*
+bus_context_get_registry (BusContext  *context)
+{
+  return context->registry;
+}
+
+BusConnections*
+bus_context_get_connections (BusContext  *context)
+{
+  return context->connections;
+}
+
+BusActivation*
+bus_context_get_activation (BusContext  *context)
+{
+  return context->activation;
+}
+
+BusMatchmaker*
+bus_context_get_matchmaker (BusContext  *context)
+{
+  return context->matchmaker;
+}
+
+DBusLoop*
+bus_context_get_loop (BusContext *context)
+{
+  return context->loop;
+}
+
+dbus_bool_t
+bus_context_allow_unix_user (BusContext   *context,
+                             unsigned long uid)
+{
+  return bus_policy_allow_unix_user (context->policy,
+                                     uid);
+}
+
+/* For now this is never actually called because the default
+ * DBusConnection behavior of 'same user that owns the bus can connect'
+ * is all it would do.
+ */
+dbus_bool_t
+bus_context_allow_windows_user (BusContext       *context,
+                                const char       *windows_sid)
+{
+  return bus_policy_allow_windows_user (context->policy,
+                                        windows_sid);
+}
+
+BusPolicy *
+bus_context_get_policy (BusContext *context)
+{
+  return context->policy;
+}
+
+BusClientPolicy*
+bus_context_create_client_policy (BusContext      *context,
+                                  DBusConnection  *connection,
+                                  DBusError       *error)
+{
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  return bus_policy_create_client_policy (context->policy, connection,
+                                          error);
+}
+
+int
+bus_context_get_activation_timeout (BusContext *context)
+{
+
+  return context->limits.activation_timeout;
+}
+
+int
+bus_context_get_auth_timeout (BusContext *context)
+{
+  return context->limits.auth_timeout;
+}
+
+int
+bus_context_get_max_completed_connections (BusContext *context)
+{
+  return context->limits.max_completed_connections;
+}
+
+int
+bus_context_get_max_incomplete_connections (BusContext *context)
+{
+  return context->limits.max_incomplete_connections;
+}
+
+int
+bus_context_get_max_connections_per_user (BusContext *context)
+{
+  return context->limits.max_connections_per_user;
+}
+
+int
+bus_context_get_max_pending_activations (BusContext *context)
+{
+  return context->limits.max_pending_activations;
+}
+
+int
+bus_context_get_max_services_per_connection (BusContext *context)
+{
+  return context->limits.max_services_per_connection;
+}
+
+int
+bus_context_get_max_match_rules_per_connection (BusContext *context)
+{
+  return context->limits.max_match_rules_per_connection;
+}
+
+int
+bus_context_get_max_replies_per_connection (BusContext *context)
+{
+  return context->limits.max_replies_per_connection;
+}
+
+int
+bus_context_get_reply_timeout (BusContext *context)
+{
+  return context->limits.reply_timeout;
+}
+
+void
+bus_context_log (BusContext *context, DBusSystemLogSeverity severity, const char *msg, ...) _DBUS_GNUC_PRINTF (3, 4);
+
+void
+bus_context_log (BusContext *context, DBusSystemLogSeverity severity, const char *msg, ...)
+{
+  va_list args;
+
+  if (!context->syslog)
+    {
+      /* we're not syslogging; just output to stderr */
+      va_start (args, msg);
+      vfprintf (stderr, msg, args);
+      fprintf (stderr, "\n");
+      va_end (args);
+      return;
+    }
+
+  va_start (args, msg);
+
+  if (context->log_prefix)
+    {
+      DBusString full_msg;
+
+      if (!_dbus_string_init (&full_msg))
+        goto out;
+      if (!_dbus_string_append (&full_msg, context->log_prefix))
+        goto oom_out;
+      if (!_dbus_string_append_printf_valist (&full_msg, msg, args))
+        goto oom_out;
+
+      _dbus_system_log (severity, "%s", _dbus_string_get_const_data (&full_msg));
+    oom_out:
+      _dbus_string_free (&full_msg);
+    }
+  else
+    _dbus_system_logv (severity, msg, args);
+
+out:
+  va_end (args);
+}
+
+static inline const char *
+nonnull (const char *maybe_null,
+         const char *if_null)
+{
+  return (maybe_null ? maybe_null : if_null);
+}
+
+/*
+ * Log something about a message, usually that it was rejected.
+ */
+static void
+complain_about_message (BusContext     *context,
+                        const char     *error_name,
+                        const char     *complaint,
+                        int             matched_rules,
+                        DBusMessage    *message,
+                        DBusConnection *sender,
+                        DBusConnection *proposed_recipient,
+                        dbus_bool_t     requested_reply,
+                        dbus_bool_t     log,
+                        DBusError      *error)
+{
+  DBusError stack_error = DBUS_ERROR_INIT;
+  const char *sender_name;
+  const char *sender_loginfo;
+  const char *proposed_recipient_loginfo;
+
+  if (error == NULL && !log)
+    return;
+
+  if (sender != NULL)
+    {
+      sender_name = bus_connection_get_name (sender);
+      sender_loginfo = bus_connection_get_loginfo (sender);
+    }
+  else
+    {
+      sender_name = "(unset)";
+      sender_loginfo = "(bus)";
+    }
+
+  if (proposed_recipient != NULL)
+    proposed_recipient_loginfo = bus_connection_get_loginfo (proposed_recipient);
+  else
+    proposed_recipient_loginfo = "bus";
+
+  dbus_set_error (&stack_error, error_name,
+      "%s, %d matched rules; type=\"%s\", sender=\"%s\" (%s) "
+      "interface=\"%s\" member=\"%s\" error name=\"%s\" "
+      "requested_reply=\"%d\" destination=\"%s\" (%s)",
+      complaint,
+      matched_rules,
+      dbus_message_type_to_string (dbus_message_get_type (message)),
+      sender_name,
+      sender_loginfo,
+      nonnull (dbus_message_get_interface (message), "(unset)"),
+      nonnull (dbus_message_get_member (message), "(unset)"),
+      nonnull (dbus_message_get_error_name (message), "(unset)"),
+      requested_reply,
+      nonnull (dbus_message_get_destination (message), DBUS_SERVICE_DBUS),
+      proposed_recipient_loginfo);
+
+  /* If we hit OOM while setting the error, this will syslog "out of memory"
+   * which is itself an indication that something is seriously wrong */
+  if (log)
+    bus_context_log (context, DBUS_SYSTEM_LOG_SECURITY, "%s",
+        stack_error.message);
+
+  dbus_move_error (&stack_error, error);
+}
+
+/*
+ * addressed_recipient is the recipient specified in the message.
+ *
+ * proposed_recipient is the recipient we're considering sending
+ * to right this second, and may be an eavesdropper.
+ *
+ * sender is the sender of the message.
+ *
+ * NULL for proposed_recipient or sender definitely means the bus driver.
+ *
+ * NULL for addressed_recipient may mean the bus driver, or may mean
+ * no destination was specified in the message (e.g. a signal).
+ */
+dbus_bool_t
+bus_context_check_security_policy (BusContext     *context,
+                                   BusTransaction *transaction,
+                                   DBusConnection *sender,
+                                   DBusConnection *addressed_recipient,
+                                   DBusConnection *proposed_recipient,
+                                   DBusMessage    *message,
+                                   DBusError      *error)
+{
+  const char *dest;
+  BusClientPolicy *sender_policy;
+  BusClientPolicy *recipient_policy;
+  dbus_int32_t toggles;
+  dbus_bool_t log;
+  int type;
+  dbus_bool_t requested_reply;
+
+  type = dbus_message_get_type (message);
+  dest = dbus_message_get_destination (message);
+
+  /* dispatch.c was supposed to ensure these invariants */
+  _dbus_assert (dest != NULL ||
+                type == DBUS_MESSAGE_TYPE_SIGNAL ||
+                (sender == NULL && !bus_connection_is_active (proposed_recipient)));
+  _dbus_assert (type == DBUS_MESSAGE_TYPE_SIGNAL ||
+                addressed_recipient != NULL ||
+                strcmp (dest, DBUS_SERVICE_DBUS) == 0);
+
+  switch (type)
+    {
+    case DBUS_MESSAGE_TYPE_METHOD_CALL:
+    case DBUS_MESSAGE_TYPE_SIGNAL:
+    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+    case DBUS_MESSAGE_TYPE_ERROR:
+      break;
+
+    default:
+      _dbus_verbose ("security check disallowing message of unknown type %d\n",
+                     type);
+
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "Message bus will not accept messages of unknown type\n");
+
+      return FALSE;
+    }
+
+  requested_reply = FALSE;
+
+  if (sender != NULL)
+    {
+      /* First verify the SELinux access controls.  If allowed then
+       * go on with the standard checks.
+       */
+      if (!bus_selinux_allows_send (sender, proposed_recipient,
+				    dbus_message_type_to_string (dbus_message_get_type (message)),
+				    dbus_message_get_interface (message),
+				    dbus_message_get_member (message),
+				    dbus_message_get_error_name (message),
+				    dest ? dest : DBUS_SERVICE_DBUS, error))
+        {
+          if (error != NULL && !dbus_error_is_set (error))
+            {
+              /* don't syslog this, just set the error: avc_has_perm should
+               * have already written to either the audit log or syslog */
+              complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
+                  "An SELinux policy prevents this sender from sending this "
+                  "message to this recipient",
+                  0, message, sender, proposed_recipient, FALSE, FALSE, error);
+              _dbus_verbose ("SELinux security check denying send to service\n");
+            }
+
+          return FALSE;
+        }
+
+      if (bus_connection_is_active (sender))
+        {
+          sender_policy = bus_connection_get_policy (sender);
+          _dbus_assert (sender_policy != NULL);
+
+          /* Fill in requested_reply variable with TRUE if this is a
+           * reply and the reply was pending.
+           */
+          if (dbus_message_get_reply_serial (message) != 0)
+            {
+              if (proposed_recipient != NULL /* not to the bus driver */ &&
+                  addressed_recipient == proposed_recipient /* not eavesdropping */)
+                {
+                  DBusError error2;
+
+                  dbus_error_init (&error2);
+                  requested_reply = bus_connections_check_reply (bus_connection_get_connections (sender),
+                                                                 transaction,
+                                                                 sender, addressed_recipient, message,
+                                                                 &error2);
+                  if (dbus_error_is_set (&error2))
+                    {
+                      dbus_move_error (&error2, error);
+                      return FALSE;
+                    }
+                }
+            }
+        }
+      else
+        {
+          /* Policy for inactive connections is that they can only send
+           * the hello message to the bus driver
+           */
+          if (proposed_recipient == NULL &&
+              dbus_message_is_method_call (message,
+                                           DBUS_INTERFACE_DBUS,
+                                           "Hello"))
+            {
+              _dbus_verbose ("security check allowing %s message\n",
+                             "Hello");
+              return TRUE;
+            }
+          else
+            {
+              _dbus_verbose ("security check disallowing non-%s message\n",
+                             "Hello");
+
+              dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                              "Client tried to send a message other than %s without being registered",
+                              "Hello");
+
+              return FALSE;
+            }
+        }
+    }
+  else
+    {
+      sender_policy = NULL;
+
+      /* If the sender is the bus driver, we assume any reply was a
+       * requested reply as bus driver won't send bogus ones
+       */
+      if (addressed_recipient == proposed_recipient /* not eavesdropping */ &&
+          dbus_message_get_reply_serial (message) != 0)
+        requested_reply = TRUE;
+    }
+
+  _dbus_assert ((sender != NULL && sender_policy != NULL) ||
+                (sender == NULL && sender_policy == NULL));
+
+  if (proposed_recipient != NULL)
+    {
+      /* only the bus driver can send to an inactive recipient (as it
+       * owns no services, so other apps can't address it). Inactive
+       * recipients can receive any message.
+       */
+      if (bus_connection_is_active (proposed_recipient))
+        {
+          recipient_policy = bus_connection_get_policy (proposed_recipient);
+          _dbus_assert (recipient_policy != NULL);
+        }
+      else if (sender == NULL)
+        {
+          _dbus_verbose ("security check using NULL recipient policy for message from bus\n");
+          recipient_policy = NULL;
+        }
+      else
+        {
+          _dbus_assert_not_reached ("a message was somehow sent to an inactive recipient from a source other than the message bus\n");
+          recipient_policy = NULL;
+        }
+    }
+  else
+    recipient_policy = NULL;
+
+  _dbus_assert ((proposed_recipient != NULL && recipient_policy != NULL) ||
+                (proposed_recipient != NULL && sender == NULL && recipient_policy == NULL) ||
+                (proposed_recipient == NULL && recipient_policy == NULL));
+
+  log = FALSE;
+  if (sender_policy &&
+      !bus_client_policy_check_can_send (sender_policy,
+                                         context->registry,
+                                         requested_reply,
+                                         proposed_recipient,
+                                         message, &toggles, &log))
+    {
+      complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
+          "Rejected send message", toggles,
+          message, sender, proposed_recipient, requested_reply,
+          (addressed_recipient == proposed_recipient), error);
+      _dbus_verbose ("security policy disallowing message due to sender policy\n");
+      return FALSE;
+    }
+
+  if (log)
+    {
+      /* We want to drop this message, and are only not doing so for backwards
+       * compatibility. */
+      complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
+          "Would reject message", toggles,
+          message, sender, proposed_recipient, requested_reply,
+          TRUE, NULL);
+    }
+
+  if (recipient_policy &&
+      !bus_client_policy_check_can_receive (recipient_policy,
+                                            context->registry,
+                                            requested_reply,
+                                            sender,
+                                            addressed_recipient, proposed_recipient,
+                                            message, &toggles))
+    {
+      complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
+          "Rejected receive message", toggles,
+          message, sender, proposed_recipient, requested_reply,
+          (addressed_recipient == proposed_recipient), NULL);
+      _dbus_verbose ("security policy disallowing message due to recipient policy\n");
+      return FALSE;
+    }
+
+  /* See if limits on size have been exceeded */
+  if (proposed_recipient &&
+      ((dbus_connection_get_outgoing_size (proposed_recipient) > context->limits.max_outgoing_bytes) ||
+       (dbus_connection_get_outgoing_unix_fds (proposed_recipient) > context->limits.max_outgoing_unix_fds)))
+    {
+      complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED,
+          "Rejected: destination has a full message queue",
+          0, message, sender, proposed_recipient, requested_reply, TRUE,
+          error);
+      _dbus_verbose ("security policy disallowing message due to full message queue\n");
+      return FALSE;
+    }
+
+  /* Record that we will allow a reply here in the future (don't
+   * bother if the recipient is the bus or this is an eavesdropping
+   * connection). Only the addressed recipient may reply.
+   */
+  if (type == DBUS_MESSAGE_TYPE_METHOD_CALL &&
+      sender &&
+      addressed_recipient &&
+      addressed_recipient == proposed_recipient && /* not eavesdropping */
+      !bus_connections_expect_reply (bus_connection_get_connections (sender),
+                                     transaction,
+                                     sender, addressed_recipient,
+                                     message, error))
+    {
+      _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
+      return FALSE;
+    }
+
+  _dbus_verbose ("security policy allowing message\n");
+  return TRUE;
+}
diff --git a/dbus/bus/bus.h b/dbus/bus/bus.h
new file mode 100644
index 0000000..3597884
--- /dev/null
+++ b/dbus/bus/bus.h
@@ -0,0 +1,129 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* bus.h  message bus context object
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef BUS_BUS_H
+#define BUS_BUS_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-mainloop.h>
+#include <dbus/dbus-pipe.h>
+#include <dbus/dbus-sysdeps.h>
+
+typedef struct BusActivation    BusActivation;
+typedef struct BusConnections   BusConnections;
+typedef struct BusContext       BusContext;
+typedef struct BusPolicy        BusPolicy;
+typedef struct BusClientPolicy  BusClientPolicy;
+typedef struct BusPolicyRule    BusPolicyRule;
+typedef struct BusRegistry      BusRegistry;
+typedef struct BusSELinuxID     BusSELinuxID;
+typedef struct BusService       BusService;
+typedef struct BusOwner		BusOwner;
+typedef struct BusTransaction   BusTransaction;
+typedef struct BusMatchmaker    BusMatchmaker;
+typedef struct BusMatchRule     BusMatchRule;
+
+typedef struct
+{
+  long max_incoming_bytes;          /**< How many incoming message bytes for a single connection */
+  long max_incoming_unix_fds;       /**< How many incoming message unix fds for a single connection */
+  long max_outgoing_bytes;          /**< How many outgoing bytes can be queued for a single connection */
+  long max_outgoing_unix_fds;       /**< How many outgoing unix fds can be queued for a single connection */
+  long max_message_size;            /**< Max size of a single message in bytes */
+  long max_message_unix_fds;        /**< Max number of unix fds of a single message*/
+  int activation_timeout;           /**< How long to wait for an activation to time out */
+  int auth_timeout;                 /**< How long to wait for an authentication to time out */
+  int max_completed_connections;    /**< Max number of authorized connections */
+  int max_incomplete_connections;   /**< Max number of incomplete connections */
+  int max_connections_per_user;     /**< Max number of connections auth'd as same user */
+  int max_pending_activations;      /**< Max number of pending activations for the entire bus */
+  int max_services_per_connection;  /**< Max number of owned services for a single connection */
+  int max_match_rules_per_connection; /**< Max number of match rules for a single connection */
+  int max_replies_per_connection;     /**< Max number of replies that can be pending for each connection */
+  int reply_timeout;                  /**< How long to wait before timing out a reply */
+} BusLimits;
+
+typedef enum
+{
+  BUS_CONTEXT_FLAG_NONE = 0,
+  BUS_CONTEXT_FLAG_FORK_ALWAYS = (1 << 1),
+  BUS_CONTEXT_FLAG_FORK_NEVER = (1 << 2),
+  BUS_CONTEXT_FLAG_WRITE_PID_FILE = (1 << 3),
+  BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION = (1 << 4)
+} BusContextFlags;
+
+BusContext*       bus_context_new                                (const DBusString *config_file,
+                                                                  BusContextFlags   flags,
+                                                                  DBusPipe         *print_addr_pipe,
+                                                                  DBusPipe         *print_pid_pipe,
+                                                                  const DBusString *address,
+                                                                  DBusError        *error);
+dbus_bool_t       bus_context_reload_config                      (BusContext       *context,
+								  DBusError        *error);
+void              bus_context_shutdown                           (BusContext       *context);
+BusContext*       bus_context_ref                                (BusContext       *context);
+void              bus_context_unref                              (BusContext       *context);
+dbus_bool_t       bus_context_get_id                             (BusContext       *context,
+                                                                  DBusString       *uuid);
+const char*       bus_context_get_type                           (BusContext       *context);
+const char*       bus_context_get_address                        (BusContext       *context);
+const char*       bus_context_get_servicehelper                  (BusContext       *context);
+dbus_bool_t       bus_context_get_systemd_activation             (BusContext       *context);
+BusRegistry*      bus_context_get_registry                       (BusContext       *context);
+BusConnections*   bus_context_get_connections                    (BusContext       *context);
+BusActivation*    bus_context_get_activation                     (BusContext       *context);
+BusMatchmaker*    bus_context_get_matchmaker                     (BusContext       *context);
+DBusLoop*         bus_context_get_loop                           (BusContext       *context);
+dbus_bool_t       bus_context_allow_unix_user                    (BusContext       *context,
+                                                                  unsigned long     uid);
+dbus_bool_t       bus_context_allow_windows_user                 (BusContext       *context,
+                                                                  const char       *windows_sid);
+BusPolicy*        bus_context_get_policy                         (BusContext       *context);
+
+BusClientPolicy*  bus_context_create_client_policy               (BusContext       *context,
+                                                                  DBusConnection   *connection,
+                                                                  DBusError        *error);
+int               bus_context_get_activation_timeout             (BusContext       *context);
+int               bus_context_get_auth_timeout                   (BusContext       *context);
+int               bus_context_get_max_completed_connections      (BusContext       *context);
+int               bus_context_get_max_incomplete_connections     (BusContext       *context);
+int               bus_context_get_max_connections_per_user       (BusContext       *context);
+int               bus_context_get_max_pending_activations        (BusContext       *context);
+int               bus_context_get_max_services_per_connection    (BusContext       *context);
+int               bus_context_get_max_match_rules_per_connection (BusContext       *context);
+int               bus_context_get_max_replies_per_connection     (BusContext       *context);
+int               bus_context_get_reply_timeout                  (BusContext       *context);
+void              bus_context_log                                (BusContext       *context,
+                                                                  DBusSystemLogSeverity severity,
+                                                                  const char       *msg,
+                                                                  ...);
+dbus_bool_t       bus_context_check_security_policy              (BusContext       *context,
+                                                                  BusTransaction   *transaction,
+                                                                  DBusConnection   *sender,
+                                                                  DBusConnection   *addressed_recipient,
+                                                                  DBusConnection   *proposed_recipient,
+                                                                  DBusMessage      *message,
+                                                                  DBusError        *error);
+
+#endif /* BUS_BUS_H */
diff --git a/dbus/bus/config-loader-expat.c b/dbus/bus/config-loader-expat.c
new file mode 100644
index 0000000..b571fda
--- /dev/null
+++ b/dbus/bus/config-loader-expat.c
@@ -0,0 +1,294 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* config-loader-expat.c  expat XML loader
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "config-parser.h"
+#include <dbus/dbus-internals.h>
+#include <expat.h>
+
+static XML_Memory_Handling_Suite memsuite;
+
+typedef struct
+{
+  BusConfigParser *parser;
+  const char *filename;
+  DBusString content;
+  DBusError *error;
+  dbus_bool_t failed;
+} ExpatParseContext;
+
+static dbus_bool_t
+process_content (ExpatParseContext *context)
+{
+  if (context->failed)
+    return FALSE;
+
+  if (_dbus_string_get_length (&context->content) > 0)
+    {
+      if (!bus_config_parser_content (context->parser,
+                                      &context->content,
+                                      context->error))
+        {
+          context->failed = TRUE;
+          return FALSE;
+        }
+      _dbus_string_set_length (&context->content, 0);
+    }
+
+  return TRUE;
+}
+
+static void
+expat_StartElementHandler (void            *userData,
+                           const XML_Char  *name,
+                           const XML_Char **atts)
+{
+  ExpatParseContext *context = userData;
+  int i;
+  char **names;
+  char **values;
+
+  /* Expat seems to suck and can't abort the parse if we
+   * throw an error. Expat 2.0 is supposed to fix this.
+   */
+  if (context->failed)
+    return;
+
+  if (!process_content (context))
+    return;
+
+  /* "atts" is key, value, key, value, NULL */
+  for (i = 0; atts[i] != NULL; ++i)
+    ; /* nothing */
+
+  _dbus_assert (i % 2 == 0);
+  names = dbus_new0 (char *, i / 2 + 1);
+  values = dbus_new0 (char *, i / 2 + 1);
+
+  if (names == NULL || values == NULL)
+    {
+      dbus_set_error (context->error, DBUS_ERROR_NO_MEMORY, NULL);
+      context->failed = TRUE;
+      dbus_free (names);
+      dbus_free (values);
+      return;
+    }
+
+  i = 0;
+  while (atts[i] != NULL)
+    {
+      _dbus_assert (i % 2 == 0);
+      names [i / 2] = (char*) atts[i];
+      values[i / 2] = (char*) atts[i+1];
+
+      i += 2;
+    }
+
+  if (!bus_config_parser_start_element (context->parser,
+                                        name,
+                                        (const char **) names,
+                                        (const char **) values,
+                                        context->error))
+    {
+      dbus_free (names);
+      dbus_free (values);
+      context->failed = TRUE;
+      return;
+    }
+
+  dbus_free (names);
+  dbus_free (values);
+}
+
+static void
+expat_EndElementHandler (void           *userData,
+                         const XML_Char *name)
+{
+  ExpatParseContext *context = userData;
+
+  if (!process_content (context))
+    return;
+
+  if (!bus_config_parser_end_element (context->parser,
+                                      name,
+                                      context->error))
+    {
+      context->failed = TRUE;
+      return;
+    }
+}
+
+/* s is not 0 terminated. */
+static void
+expat_CharacterDataHandler (void           *userData,
+                            const XML_Char *s,
+                            int             len)
+{
+  ExpatParseContext *context = userData;
+  if (context->failed)
+    return;
+
+  if (!_dbus_string_append_len (&context->content,
+                                s, len))
+    {
+      dbus_set_error (context->error, DBUS_ERROR_NO_MEMORY, NULL);
+      context->failed = TRUE;
+      return;
+    }
+}
+
+
+BusConfigParser*
+bus_config_load (const DBusString      *file,
+                 dbus_bool_t            is_toplevel,
+                 const BusConfigParser *parent,
+                 DBusError             *error)
+{
+  XML_Parser expat;
+  const char *filename;
+  BusConfigParser *parser;
+  ExpatParseContext context;
+  DBusString dirname;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  parser = NULL;
+  expat = NULL;
+  context.error = error;
+  context.failed = FALSE;
+
+  filename = _dbus_string_get_const_data (file);
+
+  if (!_dbus_string_init (&context.content))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  if (!_dbus_string_init (&dirname))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&context.content);
+      return NULL;
+    }
+
+  memsuite.malloc_fcn = dbus_malloc;
+  memsuite.realloc_fcn = dbus_realloc;
+  memsuite.free_fcn = dbus_free;
+
+  expat = XML_ParserCreate_MM ("UTF-8", &memsuite, NULL);
+  if (expat == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed;
+    }
+
+  if (!_dbus_string_get_dirname (file, &dirname))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed;
+    }
+  
+  parser = bus_config_parser_new (&dirname, is_toplevel, parent);
+  if (parser == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed;
+    }
+  context.parser = parser;
+
+  XML_SetUserData (expat, &context);
+  XML_SetElementHandler (expat,
+                         expat_StartElementHandler,
+                         expat_EndElementHandler);
+  XML_SetCharacterDataHandler (expat,
+                               expat_CharacterDataHandler);
+
+  {
+    DBusString data;
+    const char *data_str;
+
+    if (!_dbus_string_init (&data))
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        goto failed;
+      }
+
+    if (!_dbus_file_get_contents (&data, file, error))
+      {
+        _dbus_string_free (&data);
+        goto failed;
+      }
+
+    data_str = _dbus_string_get_const_data (&data);
+
+    if (!XML_Parse (expat, data_str, _dbus_string_get_length (&data), TRUE))
+      {
+        if (context.error != NULL &&
+            !dbus_error_is_set (context.error))
+          {
+            enum XML_Error e;
+
+            e = XML_GetErrorCode (expat);
+            if (e == XML_ERROR_NO_MEMORY)
+              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+            else
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Error in file %s, line %d, column %d: %s\n",
+                              filename,
+                              XML_GetCurrentLineNumber (expat),
+                              XML_GetCurrentColumnNumber (expat),
+                              XML_ErrorString (e));
+          }
+
+        _dbus_string_free (&data);
+        goto failed;
+      }
+
+    _dbus_string_free (&data);
+
+    if (context.failed)
+      goto failed;
+  }
+
+  if (!bus_config_parser_finished (parser, error))
+    goto failed;
+
+  _dbus_string_free (&dirname);
+  _dbus_string_free (&context.content);
+  XML_ParserFree (expat);
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  return parser;
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+
+  _dbus_string_free (&dirname);
+  _dbus_string_free (&context.content);
+  if (expat)
+    XML_ParserFree (expat);
+  if (parser)
+    bus_config_parser_unref (parser);
+  return NULL;
+}
diff --git a/dbus/bus/config-loader-libxml.c b/dbus/bus/config-loader-libxml.c
new file mode 100644
index 0000000..c73a181
--- /dev/null
+++ b/dbus/bus/config-loader-libxml.c
@@ -0,0 +1,324 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* config-loader-libxml.c  libxml2 XML loader
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "config-parser.h"
+#include <dbus/dbus-internals.h>
+#include <libxml/xmlreader.h>
+#include <libxml/parser.h>
+#include <libxml/globals.h>
+#include <libxml/xmlmemory.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <string.h>
+
+/* About the error handling: 
+ *  - setup a "structured" error handler that catches structural
+ *    errors and some oom errors 
+ *  - assume that a libxml function returning an error code means
+ *    out-of-memory
+ */
+#define _DBUS_MAYBE_SET_OOM(e) (dbus_error_is_set(e) ? (void)0 : _DBUS_SET_OOM(e))
+
+
+static dbus_bool_t
+xml_text_start_element (BusConfigParser   *parser,
+			xmlTextReader     *reader,
+			DBusError         *error)
+{
+  const char *name;
+  int n_attributes;
+  const char **attribute_names, **attribute_values;
+  dbus_bool_t ret;
+  int i, status, is_empty;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  ret = FALSE;
+  attribute_names = NULL;
+  attribute_values = NULL;
+
+  name = xmlTextReaderConstName (reader);
+  n_attributes = xmlTextReaderAttributeCount (reader);
+  is_empty = xmlTextReaderIsEmptyElement (reader);
+
+  if (name == NULL || n_attributes < 0 || is_empty == -1)
+    {
+      _DBUS_MAYBE_SET_OOM (error);
+      goto out;
+    }
+
+  attribute_names = dbus_new0 (const char *, n_attributes + 1);
+  attribute_values = dbus_new0 (const char *, n_attributes + 1);
+  if (attribute_names == NULL || attribute_values == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+  i = 0;
+  while ((status = xmlTextReaderMoveToNextAttribute (reader)) == 1)
+    {
+      _dbus_assert (i < n_attributes);
+      attribute_names[i] = xmlTextReaderConstName (reader);
+      attribute_values[i] = xmlTextReaderConstValue (reader);
+      if (attribute_names[i] == NULL || attribute_values[i] == NULL)
+	{ 
+          _DBUS_MAYBE_SET_OOM (error);
+	  goto out;
+	}
+      i++;
+    }
+  if (status == -1)
+    {
+      _DBUS_MAYBE_SET_OOM (error);
+      goto out;
+    }
+  _dbus_assert (i == n_attributes);
+
+  ret = bus_config_parser_start_element (parser, name,
+					 attribute_names, attribute_values,
+					 error);
+  if (ret && is_empty == 1)
+    ret = bus_config_parser_end_element (parser, name, error);
+
+ out:
+  dbus_free (attribute_names);
+  dbus_free (attribute_values);
+
+  return ret;
+}
+
+static void xml_shut_up (void *ctx, const char *msg, ...)
+{
+    return;
+}
+
+static void
+xml_text_reader_error (void *arg, xmlErrorPtr xml_error)
+{
+  DBusError *error = arg;
+
+#if 0
+  _dbus_verbose ("XML_ERROR level=%d, domain=%d, code=%d, msg=%s\n",
+                 xml_error->level, xml_error->domain,
+                 xml_error->code, xml_error->message);
+#endif
+
+  if (!dbus_error_is_set (error))
+    {
+      if (xml_error->code == XML_ERR_NO_MEMORY)
+        _DBUS_SET_OOM (error);
+      else if (xml_error->level == XML_ERR_ERROR ||
+               xml_error->level == XML_ERR_FATAL)
+        dbus_set_error (error, DBUS_ERROR_FAILED,
+                        "Error loading config file: '%s'",
+                        xml_error->message);
+    }
+}
+
+
+BusConfigParser*
+bus_config_load (const DBusString      *file,
+                 dbus_bool_t            is_toplevel,
+                 const BusConfigParser *parent,
+                 DBusError             *error)
+
+{
+  xmlTextReader *reader;
+  BusConfigParser *parser;
+  DBusString dirname, data;
+  DBusError tmp_error;
+  int ret;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  parser = NULL;
+  reader = NULL;
+
+  if (!_dbus_string_init (&dirname))
+    {
+      _DBUS_SET_OOM (error);
+      return NULL;
+    }
+
+  if (!_dbus_string_init (&data))
+    {
+      _DBUS_SET_OOM (error);
+      _dbus_string_free (&dirname);
+      return NULL;
+    }
+
+  if (is_toplevel)
+    {
+      /* xmlMemSetup only fails if one of the functions is NULL */
+      xmlMemSetup (dbus_free,
+                   dbus_malloc,
+                   dbus_realloc,
+                   _dbus_strdup);
+      xmlInitParser ();
+      xmlSetGenericErrorFunc (NULL, xml_shut_up);
+    }
+
+  if (!_dbus_string_get_dirname (file, &dirname))
+    {
+      _DBUS_SET_OOM (error);
+      goto failed;
+    }
+  
+  parser = bus_config_parser_new (&dirname, is_toplevel, parent);
+  if (parser == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      goto failed;
+    }
+  
+  if (!_dbus_file_get_contents (&data, file, error))
+    goto failed;
+
+  reader = xmlReaderForMemory (_dbus_string_get_const_data (&data), 
+                               _dbus_string_get_length (&data),
+			       NULL, NULL, 0);
+  if (reader == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      goto failed;
+    }
+
+  xmlTextReaderSetParserProp (reader, XML_PARSER_SUBST_ENTITIES, 1);
+
+  dbus_error_init (&tmp_error);
+  xmlTextReaderSetStructuredErrorHandler (reader, xml_text_reader_error, &tmp_error);
+
+  while ((ret = xmlTextReaderRead (reader)) == 1)
+    {
+      int type;
+      
+      if (dbus_error_is_set (&tmp_error))
+        goto reader_out;
+
+      type = xmlTextReaderNodeType (reader);
+      if (type == -1)
+        {
+          _DBUS_MAYBE_SET_OOM (&tmp_error);
+          goto reader_out;
+        }
+
+      switch ((xmlReaderTypes) type) {
+      case XML_READER_TYPE_ELEMENT:
+	xml_text_start_element (parser, reader, &tmp_error);
+	break;
+
+      case XML_READER_TYPE_TEXT:
+      case XML_READER_TYPE_CDATA:
+	{
+	  DBusString content;
+	  const char *value;
+	  value = xmlTextReaderConstValue (reader);
+	  if (value != NULL)
+	    {
+	      _dbus_string_init_const (&content, value);
+	      bus_config_parser_content (parser, &content, &tmp_error);
+	    }
+          else
+            _DBUS_MAYBE_SET_OOM (&tmp_error);
+	  break;
+	}
+
+      case XML_READER_TYPE_DOCUMENT_TYPE:
+	{
+	  const char *name;
+	  name = xmlTextReaderConstName (reader);
+	  if (name != NULL)
+	    bus_config_parser_check_doctype (parser, name, &tmp_error);
+          else
+            _DBUS_MAYBE_SET_OOM (&tmp_error);
+	  break;
+	}
+
+      case XML_READER_TYPE_END_ELEMENT:
+	{
+	  const char *name;
+	  name = xmlTextReaderConstName (reader);
+	  if (name != NULL)
+	    bus_config_parser_end_element (parser, name, &tmp_error);
+          else
+            _DBUS_MAYBE_SET_OOM (&tmp_error);
+	  break;
+	}
+
+      case XML_READER_TYPE_DOCUMENT:
+      case XML_READER_TYPE_DOCUMENT_FRAGMENT:
+      case XML_READER_TYPE_PROCESSING_INSTRUCTION:
+      case XML_READER_TYPE_COMMENT:
+      case XML_READER_TYPE_ENTITY:
+      case XML_READER_TYPE_NOTATION:
+      case XML_READER_TYPE_WHITESPACE:
+      case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
+      case XML_READER_TYPE_END_ENTITY:
+      case XML_READER_TYPE_XML_DECLARATION:
+	/* nothing to do, just read on */
+	break;
+
+      case XML_READER_TYPE_NONE:
+      case XML_READER_TYPE_ATTRIBUTE:
+      case XML_READER_TYPE_ENTITY_REFERENCE:
+	_dbus_assert_not_reached ("unexpected nodes in XML");
+      }
+
+      if (dbus_error_is_set (&tmp_error))
+        goto reader_out;
+    }
+
+  if (ret == -1)
+    _DBUS_MAYBE_SET_OOM (&tmp_error);
+
+ reader_out:
+  xmlFreeTextReader (reader);
+  reader = NULL;
+  if (dbus_error_is_set (&tmp_error))
+    {
+      dbus_move_error (&tmp_error, error);
+      goto failed;
+    }
+  
+  if (!bus_config_parser_finished (parser, error))
+    goto failed;
+  _dbus_string_free (&dirname);
+  _dbus_string_free (&data);
+  if (is_toplevel)
+    xmlCleanupParser();
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  return parser;
+  
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  _dbus_string_free (&dirname);
+  _dbus_string_free (&data);
+  if (is_toplevel)
+    xmlCleanupParser();
+  if (parser)
+    bus_config_parser_unref (parser);
+  _dbus_assert (reader == NULL); /* must go to reader_out first */
+  return NULL;
+}
diff --git a/dbus/bus/config-parser-common.c b/dbus/bus/config-parser-common.c
new file mode 100644
index 0000000..c522ff4
--- /dev/null
+++ b/dbus/bus/config-parser-common.c
@@ -0,0 +1,190 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* config-parser-common.c  Common defines and routines for config file parsing
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+ 
+#include <config.h>
+#include <dbus/dbus-internals.h>
+#include <string.h>
+
+#include "config-parser-common.h"
+#include "utils.h"
+
+ElementType
+bus_config_parser_element_name_to_type (const char *name)
+{
+  if (strcmp (name, "none") == 0)
+    {
+      return ELEMENT_NONE;
+    }
+  else if (strcmp (name, "busconfig") == 0)
+    {
+      return ELEMENT_BUSCONFIG;
+    }
+  else if (strcmp (name, "user") == 0)
+    {
+      return ELEMENT_USER;
+    }
+  else if (strcmp (name, "auth") == 0)
+    {
+      return ELEMENT_AUTH;
+    }
+  else if (strcmp (name, "type") == 0)
+    {
+      return ELEMENT_CONFIGTYPE;
+    }
+  else if (strcmp (name, "fork") == 0)
+    {
+      return ELEMENT_FORK;
+    }
+  else if (strcmp (name, "pidfile") == 0)
+    {
+      return ELEMENT_PIDFILE;
+    }
+  else if (strcmp (name, "listen") == 0)
+    {
+      return ELEMENT_LISTEN;
+    }
+  else if (strcmp (name, "auth") == 0)
+    {
+      return ELEMENT_AUTH;
+    }
+  else if (strcmp (name, "allow") == 0)
+    {
+      return ELEMENT_ALLOW;
+    }
+  else if (strcmp (name, "deny") == 0)
+    {
+      return ELEMENT_DENY;
+    }
+  else if (strcmp (name, "servicehelper") == 0)
+    {
+      return ELEMENT_SERVICEHELPER;
+    }
+  else if (strcmp (name, "includedir") == 0)
+    {
+      return ELEMENT_INCLUDEDIR;
+    }
+  else if (strcmp (name, "standard_session_servicedirs") == 0)
+    {
+      return ELEMENT_STANDARD_SESSION_SERVICEDIRS;
+    }
+  else if (strcmp (name, "standard_system_servicedirs") == 0)
+    {
+      return ELEMENT_STANDARD_SYSTEM_SERVICEDIRS;
+    }
+  else if (strcmp (name, "servicedir") == 0)
+    {
+      return ELEMENT_SERVICEDIR;
+    }
+  else if (strcmp (name, "include") == 0)
+    {
+      return ELEMENT_INCLUDE;
+    }
+  else if (strcmp (name, "policy") == 0)
+    {
+      return ELEMENT_POLICY;
+    }
+  else if (strcmp (name, "limit") == 0)
+    {
+      return ELEMENT_LIMIT;
+    }
+  else if (strcmp (name, "selinux") == 0)
+    {
+      return ELEMENT_SELINUX;
+    }
+  else if (strcmp (name, "associate") == 0)
+    {
+      return ELEMENT_ASSOCIATE;
+    }
+  else if (strcmp (name, "syslog") == 0)
+    {
+      return ELEMENT_SYSLOG;
+    }
+  else if (strcmp (name, "keep_umask") == 0)
+    {
+      return ELEMENT_KEEP_UMASK;
+    }
+  else if (strcmp (name, "allow_anonymous") == 0)
+    {
+      return ELEMENT_ALLOW_ANONYMOUS;
+    }
+  return ELEMENT_NONE;
+}
+
+const char*
+bus_config_parser_element_type_to_name (ElementType type)
+{
+  switch (type)
+    {
+    case ELEMENT_NONE:
+      return NULL;
+    case ELEMENT_BUSCONFIG:
+      return "busconfig";
+    case ELEMENT_INCLUDE:
+      return "include";
+    case ELEMENT_USER:
+      return "user";
+    case ELEMENT_LISTEN:
+      return "listen";
+    case ELEMENT_AUTH:
+      return "auth";
+    case ELEMENT_POLICY:
+      return "policy";
+    case ELEMENT_LIMIT:
+      return "limit";
+    case ELEMENT_ALLOW:
+      return "allow";
+    case ELEMENT_DENY:
+      return "deny";
+    case ELEMENT_FORK:
+      return "fork";
+    case ELEMENT_PIDFILE:
+      return "pidfile";
+    case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
+      return "standard_session_servicedirs";
+    case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS:
+      return "standard_system_servicedirs";
+    case ELEMENT_SERVICEDIR:
+      return "servicedir";
+    case ELEMENT_SERVICEHELPER:
+      return "servicehelper";
+    case ELEMENT_INCLUDEDIR:
+      return "includedir";
+    case ELEMENT_CONFIGTYPE:
+      return "type";
+    case ELEMENT_SELINUX:
+      return "selinux";
+    case ELEMENT_ASSOCIATE:
+      return "associate";
+    case ELEMENT_SYSLOG:
+      return "syslog";
+    case ELEMENT_KEEP_UMASK:
+      return "keep_umask";
+    case ELEMENT_ALLOW_ANONYMOUS:
+      return "allow_anonymous";
+    }
+
+  _dbus_assert_not_reached ("bad element type");
+
+  return NULL;
+}
+
diff --git a/dbus/bus/config-parser-common.h b/dbus/bus/config-parser-common.h
new file mode 100644
index 0000000..186bf4c
--- /dev/null
+++ b/dbus/bus/config-parser-common.h
@@ -0,0 +1,59 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* config-parser-common.h  Common defines and routines for config file parsing
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_CONFIG_PARSER_COMMON_H
+#define BUS_CONFIG_PARSER_COMMON_H
+
+typedef enum
+{
+  ELEMENT_NONE,
+  ELEMENT_BUSCONFIG,
+  ELEMENT_INCLUDE,
+  ELEMENT_USER,
+  ELEMENT_LISTEN,
+  ELEMENT_AUTH,
+  ELEMENT_POLICY,
+  ELEMENT_LIMIT,
+  ELEMENT_ALLOW,
+  ELEMENT_DENY,
+  ELEMENT_FORK,
+  ELEMENT_PIDFILE,
+  ELEMENT_SERVICEDIR,
+  ELEMENT_SERVICEHELPER,
+  ELEMENT_INCLUDEDIR,
+  /* this is really <type>, but winioctl.h defines ELEMENT_TYPE */
+  ELEMENT_CONFIGTYPE,
+  ELEMENT_SELINUX,
+  ELEMENT_ASSOCIATE,
+  ELEMENT_STANDARD_SESSION_SERVICEDIRS,
+  ELEMENT_STANDARD_SYSTEM_SERVICEDIRS,
+  ELEMENT_KEEP_UMASK,
+  ELEMENT_SYSLOG,
+  ELEMENT_ALLOW_ANONYMOUS
+} ElementType;
+
+ElementType bus_config_parser_element_name_to_type (const char *element_name);
+const char* bus_config_parser_element_type_to_name (ElementType type);
+
+#endif /* BUS_CONFIG_PARSER_COMMON_H */
+
diff --git a/dbus/bus/config-parser-trivial.c b/dbus/bus/config-parser-trivial.c
new file mode 100644
index 0000000..6ef50f8
--- /dev/null
+++ b/dbus/bus/config-parser-trivial.c
@@ -0,0 +1,716 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* config-parser-trivial.c  XML-library-agnostic configuration file parser
+ *                  Does not do includes or anything remotely complicated.
+ *
+ * Copyright (C) 2003, 2004, 2007 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+ 
+#include <config.h>
+#include "config-parser-common.h"
+#include "config-parser-trivial.h"
+#include "utils.h"
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-internals.h>
+#include <string.h>
+
+/**
+ * TRIVIAL parser for bus configuration file.
+ */
+struct BusConfigParser
+{
+  ElementType type;
+  DBusString user;                  /**< User the dbus-daemon runs as */
+  DBusString bus_type;              /**< Message bus type */
+  DBusString service_helper;        /**< Location of the setuid helper */
+  DBusList *service_dirs;           /**< Directories to look for services in */
+};
+
+static dbus_bool_t
+service_dirs_find_dir (DBusList **service_dirs,
+                       const char *dir)
+{
+  DBusList *link;
+
+  _dbus_assert (dir != NULL);
+
+  for (link = *service_dirs; link; link = _dbus_list_get_next_link(service_dirs, link))
+    {
+      const char *link_dir;
+
+      link_dir = (const char *)link->data;
+      if (strcmp (dir, link_dir) == 0)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+service_dirs_append_link_unique_or_free (DBusList **service_dirs,
+                                         DBusList *dir_link)
+{
+  if (!service_dirs_find_dir (service_dirs, dir_link->data))
+    {
+      _dbus_list_append_link (service_dirs, dir_link);
+    }
+  else
+    {
+      dbus_free (dir_link->data);
+      _dbus_list_free_link (dir_link);
+    }
+}
+
+BusConfigParser*
+bus_config_parser_new (const DBusString             *basedir,
+                       dbus_bool_t                   is_toplevel,
+                       const BusConfigParser        *parent)
+{
+  BusConfigParser *parser;
+
+  parser = dbus_new0 (BusConfigParser, 1);
+  if (parser == NULL)
+    goto failed;
+
+  parser->type = ELEMENT_NONE;
+
+  /* init the lists */
+  parser->service_dirs = NULL;
+
+  /* init the strings */
+  if (!_dbus_string_init (&parser->user))
+    goto failed_parser;
+  if (!_dbus_string_init (&parser->bus_type))
+    goto failed_type;
+  if (!_dbus_string_init (&parser->service_helper))
+    goto failed_helper;
+
+  /* woot! */
+  return parser;
+
+/* argh. we have do do this carefully because of OOM */
+failed_helper:
+  _dbus_string_free (&parser->bus_type);
+failed_type:
+  _dbus_string_free (&parser->user);
+failed_parser:
+  dbus_free (parser);
+failed:
+  return NULL;
+}
+
+void
+bus_config_parser_unref (BusConfigParser *parser)
+{
+  _dbus_string_free (&parser->user);
+  _dbus_string_free (&parser->service_helper);
+  _dbus_string_free (&parser->bus_type);
+
+  _dbus_list_foreach (&parser->service_dirs,
+                      (DBusForeachFunction) dbus_free,
+                      NULL);
+
+  _dbus_list_clear (&parser->service_dirs);
+
+  dbus_free (parser);
+}
+
+dbus_bool_t
+bus_config_parser_check_doctype (BusConfigParser   *parser,
+                                 const char        *doctype,
+                                 DBusError         *error)
+{
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (strcmp (doctype, "busconfig") != 0)
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_FAILED,
+                      "Configuration file has the wrong document type %s",
+                      doctype);
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
+dbus_bool_t
+bus_config_parser_start_element (BusConfigParser   *parser,
+                                 const char        *element_name,
+                                 const char       **attribute_names,
+                                 const char       **attribute_values,
+                                 DBusError         *error)
+{
+  /* we don't do processing of attribute names, we don't need to */
+  parser->type = bus_config_parser_element_name_to_type (element_name);
+
+  switch (parser->type)
+    {
+    case ELEMENT_SERVICEHELPER:
+    case ELEMENT_USER:
+    case ELEMENT_CONFIGTYPE:
+      /* content about to be handled */
+      break;
+
+    case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS:
+      {
+        DBusList *link;
+        DBusList *dirs;
+        dirs = NULL;
+
+        if (!_dbus_get_standard_system_servicedirs (&dirs))
+          {
+            BUS_SET_OOM (error);
+            return FALSE;
+          }
+
+          while ((link = _dbus_list_pop_first_link (&dirs)))
+            service_dirs_append_link_unique_or_free (&parser->service_dirs, link);
+        break;
+      }
+
+    default:
+      {
+        /* we really don't care about the others... */
+        _dbus_verbose (" START We don't care about '%s' type '%i'\n", element_name, parser->type);
+        break;
+      }
+    }
+  return TRUE;
+}
+
+dbus_bool_t
+bus_config_parser_end_element (BusConfigParser   *parser,
+                               const char               *element_name,
+                               DBusError                *error)
+{
+  /* we don't care */
+  return TRUE;
+}
+
+dbus_bool_t
+bus_config_parser_content (BusConfigParser   *parser,
+                           const DBusString  *content,
+                           DBusError         *error)
+{
+  DBusString content_sane;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  if (!_dbus_string_init (&content_sane))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+  if (!_dbus_string_copy (content, 0, &content_sane, 0))
+    {
+      BUS_SET_OOM (error);
+      goto out_content;
+    }
+
+  /* rip out white space */
+  _dbus_string_chop_white (&content_sane);
+  if (_dbus_string_get_length (&content_sane) == 0)
+    {
+      /* optimise, there is no content */
+      retval = TRUE;
+      goto out_content;
+    }
+
+  switch (parser->type)
+    {
+    case ELEMENT_SERVICEDIR:
+      {
+      	char *cpath;
+
+        /* copy the sane data into a char array */
+        if (!_dbus_string_copy_data(&content_sane, &cpath))
+          {
+            BUS_SET_OOM (error);
+            goto out_content;
+          }
+
+        /* append the dynamic char string to service dirs */
+        if (!_dbus_list_append (&parser->service_dirs, cpath))
+          {
+            dbus_free (cpath);
+            BUS_SET_OOM (error);
+            goto out_content;
+          }
+      }
+      break;
+
+    case ELEMENT_SERVICEHELPER:
+      {
+        if (!_dbus_string_copy (&content_sane, 0, &parser->service_helper, 0))
+          {
+            BUS_SET_OOM (error);
+            goto out_content;
+          }
+      }
+      break;
+
+    case ELEMENT_USER:
+      {
+        if (!_dbus_string_copy (&content_sane, 0, &parser->user, 0))
+          {
+            BUS_SET_OOM (error);
+            goto out_content;
+          }
+      }
+      break;
+
+    case ELEMENT_CONFIGTYPE:
+      {
+        if (!_dbus_string_copy (&content_sane, 0, &parser->bus_type, 0))
+          {
+            BUS_SET_OOM (error);
+            goto out_content;
+          }
+      }
+      break;
+    default:
+      {
+        /* we don't care about the others... really */
+        _dbus_verbose (" CONTENTS We don't care about '%s' type '%i'\n", _dbus_string_get_const_data (&content_sane), parser->type);
+        break;
+      }
+    }
+
+  /* woot! */
+  retval = TRUE;
+
+out_content:
+  _dbus_string_free (&content_sane);
+out:
+  return retval;
+}
+
+dbus_bool_t
+bus_config_parser_finished (BusConfigParser   *parser,
+                            DBusError         *error)
+{
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  _dbus_verbose ("finished scanning!\n");
+  return TRUE;
+}
+
+const char*
+bus_config_parser_get_user (BusConfigParser *parser)
+{
+  return _dbus_string_get_const_data (&parser->user);
+}
+
+const char*
+bus_config_parser_get_type (BusConfigParser *parser)
+{
+  return _dbus_string_get_const_data (&parser->bus_type);
+}
+
+DBusList**
+bus_config_parser_get_service_dirs (BusConfigParser *parser)
+{
+  return &parser->service_dirs;
+}
+
+#ifdef DBUS_BUILD_TESTS
+#include <stdio.h>
+#include "test.h"
+
+typedef enum
+{
+  VALID,
+  INVALID,
+  UNKNOWN
+} Validity;
+
+static dbus_bool_t
+check_return_values (const DBusString *full_path)
+{
+  BusConfigParser *parser;
+  DBusError error;
+  dbus_bool_t retval;
+  const char *user;
+  const char *type;
+  DBusList **dirs;
+
+  dbus_error_init (&error);
+  retval = FALSE;
+
+  printf ("Testing values from: %s\n", _dbus_string_get_const_data (full_path));
+
+  parser = bus_config_load (full_path, TRUE, NULL, &error);
+  if (parser == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&error);
+      if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+        _dbus_verbose ("Failed to load valid file due to OOM\n");
+      goto finish;
+    }
+  _DBUS_ASSERT_ERROR_IS_CLEAR (&error);
+
+  /* check user return value is okay */
+  user = bus_config_parser_get_user (parser);
+  if (user == NULL)
+    {
+      _dbus_warn ("User was NULL!\n");
+      goto finish;
+    }
+#if 0
+  /* the username can be configured in configure.in so this test doesn't work */
+  if (strcmp (user, "dbus") != 0)
+    {
+      _dbus_warn ("User was invalid; '%s'!\n", user);
+      goto finish;
+    }
+  printf ("    <user>dbus</user> OKAY!\n");  
+#endif
+  
+  /* check type return value is okay */
+  type = bus_config_parser_get_type (parser);
+  if (type == NULL)
+    {
+      _dbus_warn ("Type was NULL!\n");
+      goto finish;
+    }
+  if (strcmp (type, "system") != 0)
+    {
+      _dbus_warn ("Type was invalid; '%s'!\n", user);
+      goto finish;
+    }
+  printf ("    <type>system</type> OKAY!\n");
+
+  /* check dirs return value is okay */
+  dirs = bus_config_parser_get_service_dirs (parser);
+  if (dirs == NULL)
+    {
+      _dbus_warn ("Service dirs are NULL!\n");
+      goto finish;
+    }
+  printf ("    <standard_system_service_dirs/> OKAY!\n");
+  /* NOTE: We tested the specific return values in the config-parser tests */
+
+  /* woohoo! */
+  retval = TRUE;
+finish:
+  if (parser != NULL)
+    bus_config_parser_unref (parser);
+  dbus_error_free (&error);
+  return retval;
+}
+
+static dbus_bool_t
+do_load (const DBusString *full_path,
+         Validity          validity,
+         dbus_bool_t       oom_possible)
+{
+  BusConfigParser *parser;
+  DBusError error;
+
+  dbus_error_init (&error);
+
+  parser = bus_config_load (full_path, TRUE, NULL, &error);
+  if (parser == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&error);
+
+      if (oom_possible &&
+          dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+        {
+          _dbus_verbose ("Failed to load valid file due to OOM\n");
+          dbus_error_free (&error);
+          return TRUE;
+        }
+      else if (validity == VALID)
+        {
+          _dbus_warn ("Failed to load valid file but still had memory: %s\n",
+                      error.message);
+
+          dbus_error_free (&error);
+          return FALSE;
+        }
+      else
+        {
+          dbus_error_free (&error);
+          return TRUE;
+        }
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (&error);
+
+      bus_config_parser_unref (parser);
+
+      if (validity == INVALID)
+        {
+          _dbus_warn ("Accepted invalid file\n");
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+}
+
+typedef struct
+{
+  const DBusString *full_path;
+  Validity          validity;
+} LoaderOomData;
+
+static dbus_bool_t
+check_loader_oom_func (void *data)
+{
+  LoaderOomData *d = data;
+
+  return do_load (d->full_path, d->validity, TRUE);
+}
+
+static dbus_bool_t
+process_test_valid_subdir (const DBusString *test_base_dir,
+                           const char       *subdir,
+                           Validity          validity)
+{
+  DBusString test_directory;
+  DBusString filename;
+  DBusDirIter *dir;
+  dbus_bool_t retval;
+  DBusError error;
+
+  retval = FALSE;
+  dir = NULL;
+
+  if (!_dbus_string_init (&test_directory))
+    _dbus_assert_not_reached ("didn't allocate test_directory\n");
+
+  _dbus_string_init_const (&filename, subdir);
+
+  if (!_dbus_string_copy (test_base_dir, 0,
+                          &test_directory, 0))
+    _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
+
+  if (!_dbus_concat_dir_and_file (&test_directory, &filename))
+    _dbus_assert_not_reached ("couldn't allocate full path");
+
+  _dbus_string_free (&filename);
+  if (!_dbus_string_init (&filename))
+    _dbus_assert_not_reached ("didn't allocate filename string\n");
+
+  dbus_error_init (&error);
+  dir = _dbus_directory_open (&test_directory, &error);
+  if (dir == NULL)
+    {
+      _dbus_warn ("Could not open %s: %s\n",
+                  _dbus_string_get_const_data (&test_directory),
+                  error.message);
+      dbus_error_free (&error);
+      goto failed;
+    }
+
+  if (validity == VALID)
+    printf ("Testing valid files:\n");
+  else if (validity == INVALID)
+    printf ("Testing invalid files:\n");
+  else
+    printf ("Testing unknown files:\n");
+
+ next:
+  while (_dbus_directory_get_next_file (dir, &filename, &error))
+    {
+      DBusString full_path;
+      LoaderOomData d;
+
+      if (!_dbus_string_init (&full_path))
+        _dbus_assert_not_reached ("couldn't init string");
+
+      if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
+        _dbus_assert_not_reached ("couldn't copy dir to full_path");
+
+      if (!_dbus_concat_dir_and_file (&full_path, &filename))
+        _dbus_assert_not_reached ("couldn't concat file to dir");
+
+      if (!_dbus_string_ends_with_c_str (&full_path, ".conf"))
+        {
+          _dbus_verbose ("Skipping non-.conf file %s\n",
+                         _dbus_string_get_const_data (&filename));
+          _dbus_string_free (&full_path);
+          goto next;
+        }
+
+      printf ("    %s\n", _dbus_string_get_const_data (&filename));
+
+      _dbus_verbose (" expecting %s\n",
+                     validity == VALID ? "valid" :
+                     (validity == INVALID ? "invalid" :
+                      (validity == UNKNOWN ? "unknown" : "???")));
+
+      d.full_path = &full_path;
+      d.validity = validity;
+
+      /* FIXME hackaround for an expat problem, see
+       * https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=124747
+       * http://freedesktop.org/pipermail/dbus/2004-May/001153.html
+       */
+      /* if (!_dbus_test_oom_handling ("config-loader", check_loader_oom_func, &d)) */
+      if (!check_loader_oom_func (&d))
+        _dbus_assert_not_reached ("test failed");
+      
+      _dbus_string_free (&full_path);
+    }
+
+  if (dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Could not get next file in %s: %s\n",
+                  _dbus_string_get_const_data (&test_directory),
+                  error.message);
+      dbus_error_free (&error);
+      goto failed;
+    }
+
+  retval = TRUE;
+
+ failed:
+
+  if (dir)
+    _dbus_directory_close (dir);
+  _dbus_string_free (&test_directory);
+  _dbus_string_free (&filename);
+
+  return retval;
+}
+
+/* convenience function, do not reuse outside of TEST */
+static dbus_bool_t
+make_full_path (const DBusString *test_data_dir,
+			          const char       *subdir,
+			          const char       *file,
+			          DBusString       *full_path)
+{
+  DBusString filename;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  if (!_dbus_string_init (full_path))
+    {
+      _dbus_warn ("couldn't allocate full path");
+      goto finish;
+    }
+
+  if (!_dbus_string_copy (test_data_dir, 0, full_path, 0))
+    {
+      _dbus_warn ("couldn't allocate full path");
+      goto finish;
+    }
+
+  _dbus_string_init_const (&filename, subdir);
+  if (!_dbus_concat_dir_and_file (full_path, &filename))
+    {
+      _dbus_warn ("couldn't allocate full path");
+      goto finish;
+    }
+  _dbus_string_free (&filename);
+
+  _dbus_string_init_const (&filename, file);
+  if (!_dbus_concat_dir_and_file (full_path, &filename))
+    {
+      _dbus_warn ("couldn't allocate full path");
+      goto finish;
+    }
+
+  /* woot! */
+  retval = TRUE;
+
+finish:
+  _dbus_string_free (&filename);
+  return retval;
+}
+
+static dbus_bool_t
+check_file_valid (DBusString *full_path,
+			            Validity    validity)
+{
+  dbus_bool_t retval;
+
+  if (validity == VALID)
+    printf ("Testing valid file:\n");
+  else if (validity == INVALID)
+    printf ("Testing invalid file:\n");
+  else
+    printf ("Testing unknown file:\n");
+
+  /* print the filename, just so we match the other output */
+  printf ("    %s\n", _dbus_string_get_const_data (full_path));
+
+  /* only test one file */
+  retval = do_load (full_path, validity, TRUE);
+
+  return retval;
+}
+
+dbus_bool_t
+bus_config_parser_trivial_test (const DBusString *test_data_dir)
+{
+  DBusString full_path;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  if (test_data_dir == NULL ||
+      _dbus_string_get_length (test_data_dir) == 0)
+    {
+      printf ("No test data\n");
+      return TRUE;
+    }
+  
+  /* We already test default_session_servicedirs and default_system_servicedirs
+   * in bus_config_parser_test() */
+  if (!process_test_valid_subdir (test_data_dir, "valid-config-files", VALID))
+    goto finish;
+
+  /* we don't process all the invalid files, as the trivial parser can't hope
+   * to validate them all for all different syntaxes. We just check one broken
+   * file to see if junk is received */
+  if (!make_full_path (test_data_dir, "invalid-config-files", "not-well-formed.conf", &full_path))
+    goto finish;
+  if (!check_file_valid (&full_path, INVALID))
+    goto finish;
+  _dbus_string_free (&full_path);
+
+  /* just test if the check_file_valid works okay and we got sane values */
+  if (!make_full_path (test_data_dir, "valid-config-files", "system.conf", &full_path))
+    goto finish;
+  if (!check_file_valid (&full_path, VALID))
+    goto finish;
+  /* check to see if we got the correct values from the parser */
+  if (!check_return_values (&full_path))
+    goto finish;
+
+  /* woot! */
+  retval = TRUE;
+
+finish:
+  _dbus_string_free (&full_path);
+
+  /* we don't process equiv-config-files as we don't handle <include> */
+  return retval;
+}
+
+#endif /* DBUS_BUILD_TESTS */
+
diff --git a/dbus/bus/config-parser-trivial.h b/dbus/bus/config-parser-trivial.h
new file mode 100644
index 0000000..31ddef6
--- /dev/null
+++ b/dbus/bus/config-parser-trivial.h
@@ -0,0 +1,72 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* config-parser-trivial.h  XML-library-agnostic configuration file parser
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_CONFIG_PARSER_TRIVIAL_H
+#define BUS_CONFIG_PARSER_TRIVIAL_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-hash.h>
+
+/* Whatever XML library we're using just pushes data into this API */
+
+typedef struct BusConfigParser BusConfigParser;
+
+BusConfigParser* bus_config_parser_new (const DBusString      *basedir,
+                                        dbus_bool_t            is_toplevel,
+                                        const BusConfigParser *parent);
+
+BusConfigParser* bus_config_parser_ref           (BusConfigParser   *parser);
+void             bus_config_parser_unref         (BusConfigParser   *parser);
+dbus_bool_t      bus_config_parser_check_doctype (BusConfigParser   *parser,
+                                                  const char        *doctype,
+                                                  DBusError         *error);
+dbus_bool_t      bus_config_parser_start_element (BusConfigParser   *parser,
+                                                  const char        *element_name,
+                                                  const char       **attribute_names,
+                                                  const char       **attribute_values,
+                                                  DBusError         *error);
+dbus_bool_t      bus_config_parser_end_element   (BusConfigParser   *parser,
+                                                  const char        *element_name,
+                                                  DBusError         *error);
+dbus_bool_t      bus_config_parser_content       (BusConfigParser   *parser,
+                                                  const DBusString  *content,
+                                                  DBusError         *error);
+dbus_bool_t      bus_config_parser_finished      (BusConfigParser   *parser,
+                                                  DBusError         *error);
+
+/* Functions for extracting the parse results */
+const char* bus_config_parser_get_user         (BusConfigParser *parser);
+const char* bus_config_parser_get_type         (BusConfigParser *parser);
+DBusList**  bus_config_parser_get_service_dirs (BusConfigParser *parser);
+
+/* Loader functions (backended off one of the XML parsers).  Returns a
+ * finished ConfigParser.
+ */
+BusConfigParser* bus_config_load (const DBusString      *file,
+                                  dbus_bool_t            is_toplevel,
+                                  const BusConfigParser *parent,
+                                  DBusError             *error);
+
+#endif /* BUS_CONFIG_PARSER_TRIVIAL_H */
diff --git a/dbus/bus/config-parser.c b/dbus/bus/config-parser.c
new file mode 100644
index 0000000..07e8fbb
--- /dev/null
+++ b/dbus/bus/config-parser.c
@@ -0,0 +1,3633 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* config-parser.c  XML-library-agnostic configuration file parser
+ *
+ * Copyright (C) 2003, 2004 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "config-parser-common.h"
+#include "config-parser.h"
+#include "test.h"
+#include "utils.h"
+#include "policy.h"
+#include "selinux.h"
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-sysdeps.h>
+#include <string.h>
+
+typedef enum
+{
+  /* we ignore policies for unknown groups/users */
+  POLICY_IGNORED,
+
+  /* non-ignored */
+  POLICY_DEFAULT,
+  POLICY_MANDATORY,
+  POLICY_USER,
+  POLICY_GROUP,
+  POLICY_CONSOLE
+} PolicyType;
+
+typedef struct
+{
+  ElementType type;
+
+  unsigned int had_content : 1;
+
+  union
+  {
+    struct
+    {
+      unsigned int ignore_missing : 1;
+      unsigned int if_selinux_enabled : 1;
+      unsigned int selinux_root_relative : 1;
+    } include;
+
+    struct
+    {
+      PolicyType type;
+      unsigned long gid_uid_or_at_console;      
+    } policy;
+
+    struct
+    {
+      char *name;
+      long value;
+    } limit;
+    
+  } d;
+
+} Element;
+
+/**
+ * Parser for bus configuration file. 
+ */
+struct BusConfigParser
+{
+  int refcount;        /**< Reference count */
+
+  DBusString basedir;  /**< Directory we resolve paths relative to */
+  
+  DBusList *stack;     /**< stack of Element */
+
+  char *user;          /**< user to run as */
+
+  char *servicehelper; /**< location of the setuid helper */
+
+  char *bus_type;          /**< Message bus type */
+  
+  DBusList *listen_on; /**< List of addresses to listen to */
+
+  DBusList *mechanisms; /**< Auth mechanisms */
+
+  DBusList *service_dirs; /**< Directories to look for session services in */
+
+  DBusList *conf_dirs;   /**< Directories to look for policy configuration in */
+
+  BusPolicy *policy;     /**< Security policy */
+
+  BusLimits limits;      /**< Limits */
+
+  char *pidfile;         /**< PID file */
+
+  DBusList *included_files;  /**< Included files stack */
+
+  DBusHashTable *service_context_table; /**< Map service names to SELinux contexts */
+
+  unsigned int fork : 1; /**< TRUE to fork into daemon mode */
+
+  unsigned int syslog : 1; /**< TRUE to enable syslog */
+  unsigned int keep_umask : 1; /**< TRUE to keep original umask when forking */
+
+  unsigned int is_toplevel : 1; /**< FALSE if we are a sub-config-file inside another one */
+
+  unsigned int allow_anonymous : 1; /**< TRUE to allow anonymous connections */
+};
+
+static Element*
+push_element (BusConfigParser *parser,
+              ElementType      type)
+{
+  Element *e;
+
+  _dbus_assert (type != ELEMENT_NONE);
+  
+  e = dbus_new0 (Element, 1);
+  if (e == NULL)
+    return NULL;
+
+  if (!_dbus_list_append (&parser->stack, e))
+    {
+      dbus_free (e);
+      return NULL;
+    }
+  
+  e->type = type;
+
+  return e;
+}
+
+static void
+element_free (Element *e)
+{
+  if (e->type == ELEMENT_LIMIT)
+    dbus_free (e->d.limit.name);
+  
+  dbus_free (e);
+}
+
+static void
+pop_element (BusConfigParser *parser)
+{
+  Element *e;
+
+  e = _dbus_list_pop_last (&parser->stack);
+  
+  element_free (e);
+}
+
+static Element*
+peek_element (BusConfigParser *parser)
+{
+  Element *e;
+
+  e = _dbus_list_get_last (&parser->stack);
+
+  return e;
+}
+
+static ElementType
+top_element_type (BusConfigParser *parser)
+{
+  Element *e;
+
+  e = _dbus_list_get_last (&parser->stack);
+
+  if (e)
+    return e->type;
+  else
+    return ELEMENT_NONE;
+}
+
+static dbus_bool_t
+merge_service_context_hash (DBusHashTable *dest,
+			    DBusHashTable *from)
+{
+  DBusHashIter iter;
+  char *service_copy;
+  char *context_copy;
+
+  service_copy = NULL;
+  context_copy = NULL;
+
+  _dbus_hash_iter_init (from, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      const char *service = _dbus_hash_iter_get_string_key (&iter);
+      const char *context = _dbus_hash_iter_get_value (&iter);
+
+      service_copy = _dbus_strdup (service);
+      if (service_copy == NULL)
+        goto fail;
+      context_copy = _dbus_strdup (context);
+      if (context_copy == NULL)
+        goto fail; 
+      
+      if (!_dbus_hash_table_insert_string (dest, service_copy, context_copy))
+        goto fail;
+
+      service_copy = NULL;
+      context_copy = NULL;    
+    }
+
+  return TRUE;
+
+ fail:
+  if (service_copy)
+    dbus_free (service_copy);
+
+  if (context_copy)
+    dbus_free (context_copy);
+
+  return FALSE;
+}
+
+static dbus_bool_t
+service_dirs_find_dir (DBusList **service_dirs,
+                       const char *dir)
+{
+  DBusList *link;
+
+  _dbus_assert (dir != NULL);
+
+  for (link = *service_dirs; link; link = _dbus_list_get_next_link(service_dirs, link))
+    {
+      const char *link_dir;
+      
+      link_dir = (const char *)link->data;
+      if (strcmp (dir, link_dir) == 0)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static dbus_bool_t
+service_dirs_append_unique_or_free (DBusList **service_dirs,
+                                    char *dir)
+{
+  if (!service_dirs_find_dir (service_dirs, dir))
+    return _dbus_list_append (service_dirs, dir);  
+
+  dbus_free (dir);
+  return TRUE;
+}
+
+static void 
+service_dirs_append_link_unique_or_free (DBusList **service_dirs,
+                                         DBusList *dir_link)
+{
+  if (!service_dirs_find_dir (service_dirs, dir_link->data))
+    {
+      _dbus_list_append_link (service_dirs, dir_link);
+    }
+  else
+    {
+      dbus_free (dir_link->data);
+      _dbus_list_free_link (dir_link);
+    }
+}
+
+static dbus_bool_t
+merge_included (BusConfigParser *parser,
+                BusConfigParser *included,
+                DBusError       *error)
+{
+  DBusList *link;
+
+  if (!bus_policy_merge (parser->policy,
+                         included->policy))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!merge_service_context_hash (parser->service_context_table,
+				   included->service_context_table))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (included->user != NULL)
+    {
+      dbus_free (parser->user);
+      parser->user = included->user;
+      included->user = NULL;
+    }
+
+  if (included->bus_type != NULL)
+    {
+      dbus_free (parser->bus_type);
+      parser->bus_type = included->bus_type;
+      included->bus_type = NULL;
+    }
+  
+  if (included->fork)
+    parser->fork = TRUE;
+
+  if (included->keep_umask)
+    parser->keep_umask = TRUE;
+
+  if (included->pidfile != NULL)
+    {
+      dbus_free (parser->pidfile);
+      parser->pidfile = included->pidfile;
+      included->pidfile = NULL;
+    }
+  
+  while ((link = _dbus_list_pop_first_link (&included->listen_on)))
+    _dbus_list_append_link (&parser->listen_on, link);
+
+  while ((link = _dbus_list_pop_first_link (&included->mechanisms)))
+    _dbus_list_append_link (&parser->mechanisms, link);
+
+  while ((link = _dbus_list_pop_first_link (&included->service_dirs)))
+    service_dirs_append_link_unique_or_free (&parser->service_dirs, link);
+
+  while ((link = _dbus_list_pop_first_link (&included->conf_dirs)))
+    _dbus_list_append_link (&parser->conf_dirs, link);
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+seen_include (BusConfigParser  *parser,
+	      const DBusString *file)
+{
+  DBusList *iter;
+
+  iter = parser->included_files;
+  while (iter != NULL)
+    {
+      if (! strcmp (_dbus_string_get_const_data (file), iter->data))
+	return TRUE;
+
+      iter = _dbus_list_get_next_link (&parser->included_files, iter);
+    }
+
+  return FALSE;
+}
+
+BusConfigParser*
+bus_config_parser_new (const DBusString      *basedir,
+                       dbus_bool_t            is_toplevel,
+                       const BusConfigParser *parent)
+{
+  BusConfigParser *parser;
+
+  parser = dbus_new0 (BusConfigParser, 1);
+  if (parser == NULL)
+    return NULL;
+
+  parser->is_toplevel = !!is_toplevel;
+  
+  if (!_dbus_string_init (&parser->basedir))
+    {
+      dbus_free (parser);
+      return NULL;
+    }
+
+  if (((parser->policy = bus_policy_new ()) == NULL) ||
+      !_dbus_string_copy (basedir, 0, &parser->basedir, 0) ||
+      ((parser->service_context_table = _dbus_hash_table_new (DBUS_HASH_STRING,
+							      dbus_free,
+							      dbus_free)) == NULL))
+    {
+      if (parser->policy)
+        bus_policy_unref (parser->policy);
+      
+      _dbus_string_free (&parser->basedir);
+
+      dbus_free (parser);
+      return NULL;
+    }
+
+  if (parent != NULL)
+    {
+      /* Initialize the parser's limits from the parent. */
+      parser->limits = parent->limits;
+
+      /* Use the parent's list of included_files to avoid
+	 circular inclusions. */
+      parser->included_files = parent->included_files;
+    }
+  else
+    {
+
+      /* Make up some numbers! woot! */
+      parser->limits.max_incoming_bytes = _DBUS_ONE_MEGABYTE * 127;
+      parser->limits.max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 127;
+      parser->limits.max_message_size = _DBUS_ONE_MEGABYTE * 32;
+
+      /* We set relatively conservative values here since due to the
+      way SCM_RIGHTS works we need to preallocate an array for the
+      maximum number of file descriptors we can receive. Picking a
+      high value here thus translates directly to more memory
+      allocation. */
+      parser->limits.max_incoming_unix_fds = 1024*4;
+      parser->limits.max_outgoing_unix_fds = 1024*4;
+      parser->limits.max_message_unix_fds = 1024;
+      
+      /* Making this long means the user has to wait longer for an error
+       * message if something screws up, but making it too short means
+       * they might see a false failure.
+       */
+      parser->limits.activation_timeout = 25000; /* 25 seconds */
+
+      /* Making this long risks making a DOS attack easier, but too short
+       * and legitimate auth will fail.  If interactive auth (ask user for
+       * password) is allowed, then potentially it has to be quite long.
+       */
+      parser->limits.auth_timeout = 30000; /* 30 seconds */
+      
+      parser->limits.max_incomplete_connections = 64;
+      parser->limits.max_connections_per_user = 256;
+      
+      /* Note that max_completed_connections / max_connections_per_user
+       * is the number of users that would have to work together to
+       * DOS all the other users.
+       */
+      parser->limits.max_completed_connections = 2048;
+      
+      parser->limits.max_pending_activations = 512;
+      parser->limits.max_services_per_connection = 512;
+
+      /* For this one, keep in mind that it isn't only the memory used
+       * by the match rules, but slowdown from linearly walking a big
+       * list of them. A client adding more than this is almost
+       * certainly a bad idea for that reason, and should change to a
+       * smaller number of wider-net match rules - getting every last
+       * message to the bus is probably better than having a thousand
+       * match rules.
+       */
+      parser->limits.max_match_rules_per_connection = 512;
+      
+      parser->limits.reply_timeout = -1; /* never */
+
+      /* this is effectively a limit on message queue size for messages
+       * that require a reply
+       */
+      parser->limits.max_replies_per_connection = 1024*8;
+    }
+      
+  parser->refcount = 1;
+      
+  return parser;
+}
+
+BusConfigParser *
+bus_config_parser_ref (BusConfigParser *parser)
+{
+  _dbus_assert (parser->refcount > 0);
+
+  parser->refcount += 1;
+
+  return parser;
+}
+
+void
+bus_config_parser_unref (BusConfigParser *parser)
+{
+  _dbus_assert (parser->refcount > 0);
+
+  parser->refcount -= 1;
+
+  if (parser->refcount == 0)
+    {
+      while (parser->stack != NULL)
+        pop_element (parser);
+
+      dbus_free (parser->user);
+      dbus_free (parser->servicehelper);
+      dbus_free (parser->bus_type);
+      dbus_free (parser->pidfile);
+      
+      _dbus_list_foreach (&parser->listen_on,
+                          (DBusForeachFunction) dbus_free,
+                          NULL);
+
+      _dbus_list_clear (&parser->listen_on);
+
+      _dbus_list_foreach (&parser->service_dirs,
+                          (DBusForeachFunction) dbus_free,
+                          NULL);
+
+      _dbus_list_clear (&parser->service_dirs);
+
+      _dbus_list_foreach (&parser->conf_dirs,
+                          (DBusForeachFunction) dbus_free,
+                          NULL);
+
+      _dbus_list_clear (&parser->conf_dirs);
+
+      _dbus_list_foreach (&parser->mechanisms,
+                          (DBusForeachFunction) dbus_free,
+                          NULL);
+
+      _dbus_list_clear (&parser->mechanisms);
+      
+      _dbus_string_free (&parser->basedir);
+
+      if (parser->policy)
+        bus_policy_unref (parser->policy);
+
+      if (parser->service_context_table)
+        _dbus_hash_table_unref (parser->service_context_table);
+      
+      dbus_free (parser);
+    }
+}
+
+dbus_bool_t
+bus_config_parser_check_doctype (BusConfigParser   *parser,
+                                 const char        *doctype,
+                                 DBusError         *error)
+{
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (strcmp (doctype, "busconfig") != 0)
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_FAILED,
+                      "Configuration file has the wrong document type %s",
+                      doctype);
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
+typedef struct
+{
+  const char  *name;
+  const char **retloc;
+} LocateAttr;
+
+static dbus_bool_t
+locate_attributes (BusConfigParser  *parser,
+                   const char       *element_name,
+                   const char      **attribute_names,
+                   const char      **attribute_values,
+                   DBusError        *error,
+                   const char       *first_attribute_name,
+                   const char      **first_attribute_retloc,
+                   ...)
+{
+  va_list args;
+  const char *name;
+  const char **retloc;
+  int n_attrs;
+#define MAX_ATTRS 24
+  LocateAttr attrs[MAX_ATTRS];
+  dbus_bool_t retval;
+  int i;
+
+  _dbus_assert (first_attribute_name != NULL);
+  _dbus_assert (first_attribute_retloc != NULL);
+
+  retval = TRUE;
+
+  n_attrs = 1;
+  attrs[0].name = first_attribute_name;
+  attrs[0].retloc = first_attribute_retloc;
+  *first_attribute_retloc = NULL;
+
+  va_start (args, first_attribute_retloc);
+
+  name = va_arg (args, const char*);
+  retloc = va_arg (args, const char**);
+
+  while (name != NULL)
+    {
+      _dbus_assert (retloc != NULL);
+      _dbus_assert (n_attrs < MAX_ATTRS);
+
+      attrs[n_attrs].name = name;
+      attrs[n_attrs].retloc = retloc;
+      n_attrs += 1;
+      *retloc = NULL;
+
+      name = va_arg (args, const char*);
+      retloc = va_arg (args, const char**);
+    }
+
+  va_end (args);
+
+  i = 0;
+  while (attribute_names[i])
+    {
+      int j;
+      dbus_bool_t found;
+      
+      found = FALSE;
+      j = 0;
+      while (j < n_attrs)
+        {
+          if (strcmp (attrs[j].name, attribute_names[i]) == 0)
+            {
+              retloc = attrs[j].retloc;
+
+              if (*retloc != NULL)
+                {
+                  dbus_set_error (error, DBUS_ERROR_FAILED,
+                                  "Attribute \"%s\" repeated twice on the same <%s> element",
+                                  attrs[j].name, element_name);
+                  retval = FALSE;
+                  goto out;
+                }
+
+              *retloc = attribute_values[i];
+              found = TRUE;
+            }
+
+          ++j;
+        }
+
+      if (!found)
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Attribute \"%s\" is invalid on <%s> element in this context",
+                          attribute_names[i], element_name);
+          retval = FALSE;
+          goto out;
+        }
+
+      ++i;
+    }
+
+ out:
+  return retval;
+}
+
+static dbus_bool_t
+check_no_attributes (BusConfigParser  *parser,
+                     const char       *element_name,
+                     const char      **attribute_names,
+                     const char      **attribute_values,
+                     DBusError        *error)
+{
+  if (attribute_names[0] != NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Attribute \"%s\" is invalid on <%s> element in this context",
+                      attribute_names[0], element_name);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+start_busconfig_child (BusConfigParser   *parser,
+                       const char        *element_name,
+                       const char       **attribute_names,
+                       const char       **attribute_values,
+                       DBusError         *error)
+{
+  ElementType element_type;
+
+  element_type = bus_config_parser_element_name_to_type (element_name);
+
+  if (element_type == ELEMENT_USER)
+    {
+      if (!check_no_attributes (parser, "user", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_USER) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_CONFIGTYPE)
+    {
+      if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_CONFIGTYPE) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_FORK)
+    {
+      if (!check_no_attributes (parser, "fork", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_FORK) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      parser->fork = TRUE;
+      
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_SYSLOG)
+    {
+      if (!check_no_attributes (parser, "syslog", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_SYSLOG) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+      
+      parser->syslog = TRUE;
+      
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_KEEP_UMASK)
+    {
+      if (!check_no_attributes (parser, "keep_umask", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_KEEP_UMASK) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      parser->keep_umask = TRUE;
+      
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_PIDFILE)
+    {
+      if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_PIDFILE) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_LISTEN)
+    {
+      if (!check_no_attributes (parser, "listen", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_LISTEN) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_AUTH)
+    {
+      if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_AUTH) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+      
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_SERVICEHELPER)
+    {
+      if (!check_no_attributes (parser, "servicehelper", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_SERVICEHELPER) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_INCLUDEDIR)
+    {
+      if (!check_no_attributes (parser, "includedir", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_INCLUDEDIR) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_STANDARD_SESSION_SERVICEDIRS)
+    {
+      DBusList *link;
+      DBusList *dirs;
+      dirs = NULL;
+
+      if (!check_no_attributes (parser, "standard_session_servicedirs", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_STANDARD_SESSION_SERVICEDIRS) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      if (!_dbus_get_standard_session_servicedirs (&dirs))
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+        while ((link = _dbus_list_pop_first_link (&dirs)))
+          service_dirs_append_link_unique_or_free (&parser->service_dirs, link);
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_STANDARD_SYSTEM_SERVICEDIRS)
+    {
+      DBusList *link;
+      DBusList *dirs;
+      dirs = NULL;
+
+      if (!check_no_attributes (parser, "standard_system_servicedirs", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_STANDARD_SYSTEM_SERVICEDIRS) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      if (!_dbus_get_standard_system_servicedirs (&dirs))
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+        while ((link = _dbus_list_pop_first_link (&dirs)))
+          service_dirs_append_link_unique_or_free (&parser->service_dirs, link);
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_ALLOW_ANONYMOUS)
+    {
+      if (!check_no_attributes (parser, "allow_anonymous", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_ALLOW_ANONYMOUS) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      parser->allow_anonymous = TRUE;
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_SERVICEDIR)
+    {
+      if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_SERVICEDIR) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_INCLUDE)
+    {
+      Element *e;
+      const char *if_selinux_enabled;
+      const char *ignore_missing;
+      const char *selinux_root_relative;
+
+      if ((e = push_element (parser, ELEMENT_INCLUDE)) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      e->d.include.ignore_missing = FALSE;
+      e->d.include.if_selinux_enabled = FALSE;
+      e->d.include.selinux_root_relative = FALSE;
+
+      if (!locate_attributes (parser, "include",
+                              attribute_names,
+                              attribute_values,
+                              error,
+                              "ignore_missing", &ignore_missing,
+                              "if_selinux_enabled", &if_selinux_enabled,
+                              "selinux_root_relative", &selinux_root_relative,
+                              NULL))
+        return FALSE;
+
+      if (ignore_missing != NULL)
+        {
+          if (strcmp (ignore_missing, "yes") == 0)
+            e->d.include.ignore_missing = TRUE;
+          else if (strcmp (ignore_missing, "no") == 0)
+            e->d.include.ignore_missing = FALSE;
+          else
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "ignore_missing attribute must have value \"yes\" or \"no\"");
+              return FALSE;
+            }
+        }
+
+      if (if_selinux_enabled != NULL)
+        {
+          if (strcmp (if_selinux_enabled, "yes") == 0)
+            e->d.include.if_selinux_enabled = TRUE;
+          else if (strcmp (if_selinux_enabled, "no") == 0)
+            e->d.include.if_selinux_enabled = FALSE;
+          else
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "if_selinux_enabled attribute must have value"
+                              " \"yes\" or \"no\"");
+              return FALSE;
+	    }
+        }
+      
+      if (selinux_root_relative != NULL)
+        {
+          if (strcmp (selinux_root_relative, "yes") == 0)
+            e->d.include.selinux_root_relative = TRUE;
+          else if (strcmp (selinux_root_relative, "no") == 0)
+            e->d.include.selinux_root_relative = FALSE;
+          else
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "selinux_root_relative attribute must have value"
+                              " \"yes\" or \"no\"");
+              return FALSE;
+	    }
+        }
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_POLICY)
+    {
+      Element *e;
+      const char *context;
+      const char *user;
+      const char *group;
+      const char *at_console;
+
+      if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      e->d.policy.type = POLICY_IGNORED;
+      
+      if (!locate_attributes (parser, "policy",
+                              attribute_names,
+                              attribute_values,
+                              error,
+                              "context", &context,
+                              "user", &user,
+                              "group", &group,
+                              "at_console", &at_console,
+                              NULL))
+        return FALSE;
+
+      if (((context && user) ||
+           (context && group) ||
+           (context && at_console)) ||
+           ((user && group) ||
+           (user && at_console)) ||
+           (group && at_console) ||
+          !(context || user || group || at_console))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "<policy> element must have exactly one of (context|user|group|at_console) attributes");
+          return FALSE;
+        }
+
+      if (context != NULL)
+        {
+          if (strcmp (context, "default") == 0)
+            {
+              e->d.policy.type = POLICY_DEFAULT;
+            }
+          else if (strcmp (context, "mandatory") == 0)
+            {
+              e->d.policy.type = POLICY_MANDATORY;
+            }
+          else
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "context attribute on <policy> must have the value \"default\" or \"mandatory\", not \"%s\"",
+                              context);
+              return FALSE;
+            }
+        }
+      else if (user != NULL)
+        {
+          DBusString username;
+          _dbus_string_init_const (&username, user);
+
+          if (_dbus_parse_unix_user_from_config (&username,
+                                                 &e->d.policy.gid_uid_or_at_console))
+            e->d.policy.type = POLICY_USER;
+          else
+            _dbus_warn ("Unknown username \"%s\" in message bus configuration file\n",
+                        user);
+        }
+      else if (group != NULL)
+        {
+          DBusString group_name;
+          _dbus_string_init_const (&group_name, group);
+
+          if (_dbus_parse_unix_group_from_config (&group_name,
+                                                  &e->d.policy.gid_uid_or_at_console))
+            e->d.policy.type = POLICY_GROUP;
+          else
+            _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
+                        group);          
+        }
+      else if (at_console != NULL)
+        {
+           dbus_bool_t t;
+           t = (strcmp (at_console, "true") == 0);
+           if (t || strcmp (at_console, "false") == 0)
+             {
+               e->d.policy.gid_uid_or_at_console = t; 
+               e->d.policy.type = POLICY_CONSOLE;
+             }  
+           else
+             {
+               dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Unknown value \"%s\" for at_console in message bus configuration file",
+                              at_console);
+
+               return FALSE;
+             }
+        }
+      else
+        {
+          _dbus_assert_not_reached ("all <policy> attributes null and we didn't set error");
+        }
+      
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_LIMIT)
+    {
+      Element *e;
+      const char *name;
+
+      if ((e = push_element (parser, ELEMENT_LIMIT)) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+      
+      if (!locate_attributes (parser, "limit",
+                              attribute_names,
+                              attribute_values,
+                              error,
+                              "name", &name,
+                              NULL))
+        return FALSE;
+
+      if (name == NULL)
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "<limit> element must have a \"name\" attribute");
+          return FALSE;
+        }
+
+      e->d.limit.name = _dbus_strdup (name);
+      if (e->d.limit.name == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else if (element_type == ELEMENT_SELINUX)
+    {
+      if (!check_no_attributes (parser, "selinux", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_SELINUX) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Element <%s> not allowed inside <%s> in configuration file",
+                      element_name, "busconfig");
+      return FALSE;
+    }
+}
+
+static dbus_bool_t
+append_rule_from_element (BusConfigParser   *parser,
+                          const char        *element_name,
+                          const char       **attribute_names,
+                          const char       **attribute_values,
+                          dbus_bool_t        allow,
+                          DBusError         *error)
+{
+  const char *log;
+  const char *send_interface;
+  const char *send_member;
+  const char *send_error;
+  const char *send_destination;
+  const char *send_path;
+  const char *send_type;
+  const char *receive_interface;
+  const char *receive_member;
+  const char *receive_error;
+  const char *receive_sender;
+  const char *receive_path;
+  const char *receive_type;
+  const char *eavesdrop;
+  const char *send_requested_reply;
+  const char *receive_requested_reply;
+  const char *own;
+  const char *own_prefix;
+  const char *user;
+  const char *group;
+
+  BusPolicyRule *rule;
+  
+  if (!locate_attributes (parser, element_name,
+                          attribute_names,
+                          attribute_values,
+                          error,
+                          "send_interface", &send_interface,
+                          "send_member", &send_member,
+                          "send_error", &send_error,
+                          "send_destination", &send_destination,
+                          "send_path", &send_path,
+                          "send_type", &send_type,
+                          "receive_interface", &receive_interface,
+                          "receive_member", &receive_member,
+                          "receive_error", &receive_error,
+                          "receive_sender", &receive_sender,
+                          "receive_path", &receive_path,
+                          "receive_type", &receive_type,
+                          "eavesdrop", &eavesdrop,
+                          "send_requested_reply", &send_requested_reply,
+                          "receive_requested_reply", &receive_requested_reply,
+                          "own", &own,
+                          "own_prefix", &own_prefix,
+                          "user", &user,
+                          "group", &group,
+                          "log", &log,
+                          NULL))
+    return FALSE;
+
+  if (!(send_interface || send_member || send_error || send_destination ||
+        send_type || send_path ||
+        receive_interface || receive_member || receive_error || receive_sender ||
+        receive_type || receive_path || eavesdrop ||
+        send_requested_reply || receive_requested_reply ||
+        own || own_prefix || user || group))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Element <%s> must have one or more attributes",
+                      element_name);
+      return FALSE;
+    }
+
+  if ((send_member && (send_interface == NULL && send_path == NULL)) ||
+      (receive_member && (receive_interface == NULL && receive_path == NULL)))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "On element <%s>, if you specify a member you must specify an interface or a path. Keep in mind that not all messages have an interface field.",
+                      element_name);
+      return FALSE;
+    }
+  
+  /* Allowed combinations of elements are:
+   *
+   *   base, must be all send or all receive:
+   *     nothing
+   *     interface
+   *     interface + member
+   *     error
+   * 
+   *   base send_ can combine with send_destination, send_path, send_type, send_requested_reply
+   *   base receive_ with receive_sender, receive_path, receive_type, receive_requested_reply, eavesdrop
+   *
+   *   user, group, own, own_prefix must occur alone
+   *
+   * Pretty sure the below stuff is broken, FIXME think about it more.
+   */
+
+  if ((send_interface && (send_error ||
+                          receive_interface ||
+                          receive_member ||
+                          receive_error ||
+                          receive_sender ||
+                          receive_requested_reply ||
+                          own || own_prefix ||
+                          user ||
+                          group)) ||
+
+      (send_member && (send_error ||
+                       receive_interface ||
+                       receive_member ||
+                       receive_error ||
+                       receive_sender ||
+                       receive_requested_reply ||
+                       own || own_prefix ||
+                       user ||
+                       group)) ||
+
+      (send_error && (receive_interface ||
+                      receive_member ||
+                      receive_error ||
+                      receive_sender ||
+                      receive_requested_reply ||
+                      own || own_prefix ||
+                      user ||
+                      group)) ||
+
+      (send_destination && (receive_interface ||
+                            receive_member ||
+                            receive_error ||
+                            receive_sender ||
+                            receive_requested_reply ||
+                            own || own_prefix ||
+                            user ||
+                            group)) ||
+
+      (send_type && (receive_interface ||
+                     receive_member ||
+                     receive_error ||
+                     receive_sender ||
+                     receive_requested_reply ||
+                     own || own_prefix ||
+                     user ||
+                     group)) ||
+
+      (send_path && (receive_interface ||
+                     receive_member ||
+                     receive_error ||
+                     receive_sender ||
+                     receive_requested_reply ||
+                     own || own_prefix ||
+                     user ||
+                     group)) ||
+
+      (send_requested_reply && (receive_interface ||
+                                receive_member ||
+                                receive_error ||
+                                receive_sender ||
+                                receive_requested_reply ||
+                                own || own_prefix ||
+                                user ||
+                                group)) ||
+
+      (receive_interface && (receive_error ||
+                             own || own_prefix ||
+                             user ||
+                             group)) ||
+
+      (receive_member && (receive_error ||
+                          own || own_prefix ||
+                          user ||
+                          group)) ||
+
+      (receive_error && (own || own_prefix ||
+                         user ||
+                         group)) ||
+
+      (eavesdrop && (own || own_prefix ||
+                     user ||
+                     group)) ||
+
+      (receive_requested_reply && (own || own_prefix ||
+                                   user ||
+                                   group)) ||
+
+      (own && (own_prefix || user || group)) ||
+
+      (own_prefix && (own || user || group)) ||
+
+      (user && group))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Invalid combination of attributes on element <%s>",
+                      element_name);
+      return FALSE;
+    }
+  
+  rule = NULL;
+
+  /* In BusPolicyRule, NULL represents wildcard.
+   * In the config file, '*' represents it.
+   */
+#define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
+
+  if (send_interface || send_member || send_error || send_destination ||
+      send_path || send_type || send_requested_reply)
+    {
+      int message_type;
+      
+      if (IS_WILDCARD (send_interface))
+        send_interface = NULL;
+      if (IS_WILDCARD (send_member))
+        send_member = NULL;
+      if (IS_WILDCARD (send_error))
+        send_error = NULL;
+      if (IS_WILDCARD (send_destination))
+        send_destination = NULL;
+      if (IS_WILDCARD (send_path))
+        send_path = NULL;
+      if (IS_WILDCARD (send_type))
+        send_type = NULL;
+
+      message_type = DBUS_MESSAGE_TYPE_INVALID;
+      if (send_type != NULL)
+        {
+          message_type = dbus_message_type_from_string (send_type);
+          if (message_type == DBUS_MESSAGE_TYPE_INVALID)
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Bad message type \"%s\"",
+                              send_type);
+              return FALSE;
+            }
+        }
+
+      if (eavesdrop &&
+          !(strcmp (eavesdrop, "true") == 0 ||
+            strcmp (eavesdrop, "false") == 0))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Bad value \"%s\" for %s attribute, must be true or false",
+                          "eavesdrop", eavesdrop);
+          return FALSE;
+        }
+
+      if (send_requested_reply &&
+          !(strcmp (send_requested_reply, "true") == 0 ||
+            strcmp (send_requested_reply, "false") == 0))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Bad value \"%s\" for %s attribute, must be true or false",
+                          "send_requested_reply", send_requested_reply);
+          return FALSE;
+        }
+      
+      rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow); 
+      if (rule == NULL)
+        goto nomem;
+      
+      if (eavesdrop)
+        rule->d.send.eavesdrop = (strcmp (eavesdrop, "true") == 0);
+
+      if (log)
+        rule->d.send.log = (strcmp (log, "true") == 0);
+
+      if (send_requested_reply)
+        rule->d.send.requested_reply = (strcmp (send_requested_reply, "true") == 0);
+
+      rule->d.send.message_type = message_type;
+      rule->d.send.path = _dbus_strdup (send_path);
+      rule->d.send.interface = _dbus_strdup (send_interface);
+      rule->d.send.member = _dbus_strdup (send_member);
+      rule->d.send.error = _dbus_strdup (send_error);
+      rule->d.send.destination = _dbus_strdup (send_destination);
+      if (send_path && rule->d.send.path == NULL)
+        goto nomem;
+      if (send_interface && rule->d.send.interface == NULL)
+        goto nomem;
+      if (send_member && rule->d.send.member == NULL)
+        goto nomem;
+      if (send_error && rule->d.send.error == NULL)
+        goto nomem;
+      if (send_destination && rule->d.send.destination == NULL)
+        goto nomem;
+    }
+  else if (receive_interface || receive_member || receive_error || receive_sender ||
+           receive_path || receive_type || eavesdrop || receive_requested_reply)
+    {
+      int message_type;
+      
+      if (IS_WILDCARD (receive_interface))
+        receive_interface = NULL;
+      if (IS_WILDCARD (receive_member))
+        receive_member = NULL;
+      if (IS_WILDCARD (receive_error))
+        receive_error = NULL;
+      if (IS_WILDCARD (receive_sender))
+        receive_sender = NULL;
+      if (IS_WILDCARD (receive_path))
+        receive_path = NULL;
+      if (IS_WILDCARD (receive_type))
+        receive_type = NULL;
+
+      message_type = DBUS_MESSAGE_TYPE_INVALID;
+      if (receive_type != NULL)
+        {
+          message_type = dbus_message_type_from_string (receive_type);
+          if (message_type == DBUS_MESSAGE_TYPE_INVALID)
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Bad message type \"%s\"",
+                              receive_type);
+              return FALSE;
+            }
+        }
+
+
+      if (eavesdrop &&
+          !(strcmp (eavesdrop, "true") == 0 ||
+            strcmp (eavesdrop, "false") == 0))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Bad value \"%s\" for %s attribute, must be true or false",
+                          "eavesdrop", eavesdrop);
+          return FALSE;
+        }
+
+      if (receive_requested_reply &&
+          !(strcmp (receive_requested_reply, "true") == 0 ||
+            strcmp (receive_requested_reply, "false") == 0))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Bad value \"%s\" for %s attribute, must be true or false",
+                          "receive_requested_reply", receive_requested_reply);
+          return FALSE;
+        }
+      
+      rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); 
+      if (rule == NULL)
+        goto nomem;
+
+      if (eavesdrop)
+        rule->d.receive.eavesdrop = (strcmp (eavesdrop, "true") == 0);
+
+      if (receive_requested_reply)
+        rule->d.receive.requested_reply = (strcmp (receive_requested_reply, "true") == 0);
+      
+      rule->d.receive.message_type = message_type;
+      rule->d.receive.path = _dbus_strdup (receive_path);
+      rule->d.receive.interface = _dbus_strdup (receive_interface);
+      rule->d.receive.member = _dbus_strdup (receive_member);
+      rule->d.receive.error = _dbus_strdup (receive_error);
+      rule->d.receive.origin = _dbus_strdup (receive_sender);
+
+      if (receive_path && rule->d.receive.path == NULL)
+        goto nomem;
+      if (receive_interface && rule->d.receive.interface == NULL)
+        goto nomem;
+      if (receive_member && rule->d.receive.member == NULL)
+        goto nomem;
+      if (receive_error && rule->d.receive.error == NULL)
+        goto nomem;
+      if (receive_sender && rule->d.receive.origin == NULL)
+        goto nomem;
+    }
+  else if (own || own_prefix)
+    {
+      rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow); 
+      if (rule == NULL)
+        goto nomem;
+
+      if (own)
+        {
+          if (IS_WILDCARD (own))
+            own = NULL;
+      
+          rule->d.own.prefix = 0;
+          rule->d.own.service_name = _dbus_strdup (own);
+          if (own && rule->d.own.service_name == NULL)
+            goto nomem;
+        }
+      else
+        {
+          rule->d.own.prefix = 1;
+          rule->d.own.service_name = _dbus_strdup (own_prefix);
+          if (rule->d.own.service_name == NULL)
+            goto nomem;
+        }
+    }
+  else if (user)
+    {      
+      if (IS_WILDCARD (user))
+        {
+          rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); 
+          if (rule == NULL)
+            goto nomem;
+
+          rule->d.user.uid = DBUS_UID_UNSET;
+        }
+      else
+        {
+          DBusString username;
+          dbus_uid_t uid;
+          
+          _dbus_string_init_const (&username, user);
+      
+          if (_dbus_parse_unix_user_from_config (&username, &uid))
+            {
+              rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); 
+              if (rule == NULL)
+                goto nomem;
+
+              rule->d.user.uid = uid;
+            }
+          else
+            {
+              _dbus_warn ("Unknown username \"%s\" on element <%s>\n",
+                          user, element_name);
+            }
+        }
+    }
+  else if (group)
+    {
+      if (IS_WILDCARD (group))
+        {
+          rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); 
+          if (rule == NULL)
+            goto nomem;
+
+          rule->d.group.gid = DBUS_GID_UNSET;
+        }
+      else
+        {
+          DBusString groupname;
+          dbus_gid_t gid;
+          
+          _dbus_string_init_const (&groupname, group);
+          
+          if (_dbus_parse_unix_group_from_config (&groupname, &gid))
+            {
+              rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); 
+              if (rule == NULL)
+                goto nomem;
+
+              rule->d.group.gid = gid;
+            }
+          else
+            {
+              _dbus_warn ("Unknown group \"%s\" on element <%s>\n",
+                          group, element_name);
+            }
+        }
+    }
+  else
+    _dbus_assert_not_reached ("Did not handle some combination of attributes on <allow> or <deny>");
+
+  if (rule != NULL)
+    {
+      Element *pe;
+      
+      pe = peek_element (parser);      
+      _dbus_assert (pe != NULL);
+      _dbus_assert (pe->type == ELEMENT_POLICY);
+
+      switch (pe->d.policy.type)
+        {
+        case POLICY_IGNORED:
+          /* drop the rule on the floor */
+          break;
+          
+        case POLICY_DEFAULT:
+          if (!bus_policy_append_default_rule (parser->policy, rule))
+            goto nomem;
+          break;
+        case POLICY_MANDATORY:
+          if (!bus_policy_append_mandatory_rule (parser->policy, rule))
+            goto nomem;
+          break;
+        case POLICY_USER:
+          if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "<%s> rule cannot be per-user because it has bus-global semantics",
+                              element_name);
+              goto failed;
+            }
+          
+          if (!bus_policy_append_user_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
+                                            rule))
+            goto nomem;
+          break;
+        case POLICY_GROUP:
+          if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "<%s> rule cannot be per-group because it has bus-global semantics",
+                              element_name);
+              goto failed;
+            }
+          
+          if (!bus_policy_append_group_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
+                                             rule))
+            goto nomem;
+          break;
+        
+
+        case POLICY_CONSOLE:
+          if (!bus_policy_append_console_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
+                                               rule))
+            goto nomem;
+          break;
+        }
+ 
+      bus_policy_rule_unref (rule);
+      rule = NULL;
+    }
+  
+  return TRUE;
+
+ nomem:
+  BUS_SET_OOM (error);
+ failed:
+  if (rule)
+    bus_policy_rule_unref (rule);
+  return FALSE;
+}
+
+static dbus_bool_t
+start_policy_child (BusConfigParser   *parser,
+                    const char        *element_name,
+                    const char       **attribute_names,
+                    const char       **attribute_values,
+                    DBusError         *error)
+{
+  if (strcmp (element_name, "allow") == 0)
+    {
+      if (!append_rule_from_element (parser, element_name,
+                                     attribute_names, attribute_values,
+                                     TRUE, error))
+        return FALSE;
+      
+      if (push_element (parser, ELEMENT_ALLOW) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+      
+      return TRUE;
+    }
+  else if (strcmp (element_name, "deny") == 0)
+    {
+      if (!append_rule_from_element (parser, element_name,
+                                     attribute_names, attribute_values,
+                                     FALSE, error))
+        return FALSE;
+      
+      if (push_element (parser, ELEMENT_DENY) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+      
+      return TRUE;
+    }
+  else
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Element <%s> not allowed inside <%s> in configuration file",
+                      element_name, "policy");
+      return FALSE;
+    }
+}
+
+static dbus_bool_t
+start_selinux_child (BusConfigParser   *parser,
+                     const char        *element_name,
+                     const char       **attribute_names,
+                     const char       **attribute_values,
+                     DBusError         *error)
+{
+  char *own_copy;
+  char *context_copy;
+
+  own_copy = NULL;
+  context_copy = NULL;
+
+  if (strcmp (element_name, "associate") == 0)
+    {
+      const char *own;
+      const char *context;
+      
+      if (!locate_attributes (parser, "associate",
+                              attribute_names,
+                              attribute_values,
+                              error,
+                              "own", &own,
+                              "context", &context,
+                              NULL))
+        return FALSE;
+      
+      if (push_element (parser, ELEMENT_ASSOCIATE) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      if (own == NULL || context == NULL)
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Element <associate> must have attributes own=\"<servicename>\" and context=\"<selinux context>\"");
+          return FALSE;
+        }
+
+      own_copy = _dbus_strdup (own);
+      if (own_copy == NULL)
+        goto oom;
+      context_copy = _dbus_strdup (context);
+      if (context_copy == NULL)
+        goto oom;
+
+      if (!_dbus_hash_table_insert_string (parser->service_context_table,
+					   own_copy, context_copy))
+        goto oom;
+
+      return TRUE;
+    }
+  else
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Element <%s> not allowed inside <%s> in configuration file",
+                      element_name, "selinux");
+      return FALSE;
+    }
+
+ oom:
+  if (own_copy)
+    dbus_free (own_copy);
+
+  if (context_copy)  
+    dbus_free (context_copy);
+
+  BUS_SET_OOM (error);
+  return FALSE;
+}
+
+dbus_bool_t
+bus_config_parser_start_element (BusConfigParser   *parser,
+                                 const char        *element_name,
+                                 const char       **attribute_names,
+                                 const char       **attribute_values,
+                                 DBusError         *error)
+{
+  ElementType t;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  /* printf ("START: %s\n", element_name); */
+  
+  t = top_element_type (parser);
+
+  if (t == ELEMENT_NONE)
+    {
+      if (strcmp (element_name, "busconfig") == 0)
+        {
+          if (!check_no_attributes (parser, "busconfig", attribute_names, attribute_values, error))
+            return FALSE;
+          
+          if (push_element (parser, ELEMENT_BUSCONFIG) == NULL)
+            {
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          return TRUE;
+        }
+      else
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Unknown element <%s> at root of configuration file",
+                          element_name);
+          return FALSE;
+        }
+    }
+  else if (t == ELEMENT_BUSCONFIG)
+    {
+      return start_busconfig_child (parser, element_name,
+                                    attribute_names, attribute_values,
+                                    error);
+    }
+  else if (t == ELEMENT_POLICY)
+    {
+      return start_policy_child (parser, element_name,
+                                 attribute_names, attribute_values,
+                                 error);
+    }
+  else if (t == ELEMENT_SELINUX)
+    {
+      return start_selinux_child (parser, element_name,
+                                  attribute_names, attribute_values,
+                                  error);
+    }
+  else
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Element <%s> is not allowed in this context",
+                      element_name);
+      return FALSE;
+    }  
+}
+
+static dbus_bool_t
+set_limit (BusConfigParser *parser,
+           const char      *name,
+           long             value,
+           DBusError       *error)
+{
+  dbus_bool_t must_be_positive;
+  dbus_bool_t must_be_int;
+
+  must_be_int = FALSE;
+  must_be_positive = FALSE;
+  
+  if (strcmp (name, "max_incoming_bytes") == 0)
+    {
+      must_be_positive = TRUE;
+      parser->limits.max_incoming_bytes = value;
+    }
+  else if (strcmp (name, "max_incoming_unix_fds") == 0)
+    {
+      must_be_positive = TRUE;
+      parser->limits.max_incoming_unix_fds = value;
+    }
+  else if (strcmp (name, "max_outgoing_bytes") == 0)
+    {
+      must_be_positive = TRUE;
+      parser->limits.max_outgoing_bytes = value;
+    }
+  else if (strcmp (name, "max_outgoing_unix_fds") == 0)
+    {
+      must_be_positive = TRUE;
+      parser->limits.max_outgoing_unix_fds = value;
+    }
+  else if (strcmp (name, "max_message_size") == 0)
+    {
+      must_be_positive = TRUE;
+      parser->limits.max_message_size = value;
+    }
+  else if (strcmp (name, "max_message_unix_fds") == 0)
+    {
+      must_be_positive = TRUE;
+      parser->limits.max_message_unix_fds = value;
+    }
+  else if (strcmp (name, "service_start_timeout") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.activation_timeout = value;
+    }
+  else if (strcmp (name, "auth_timeout") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.auth_timeout = value;
+    }
+  else if (strcmp (name, "reply_timeout") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.reply_timeout = value;
+    }
+  else if (strcmp (name, "max_completed_connections") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.max_completed_connections = value;
+    }
+  else if (strcmp (name, "max_incomplete_connections") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.max_incomplete_connections = value;
+    }
+  else if (strcmp (name, "max_connections_per_user") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.max_connections_per_user = value;
+    }
+  else if (strcmp (name, "max_pending_service_starts") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.max_pending_activations = value;
+    }
+  else if (strcmp (name, "max_names_per_connection") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.max_services_per_connection = value;
+    }
+  else if (strcmp (name, "max_match_rules_per_connection") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.max_match_rules_per_connection = value;
+    }
+  else if (strcmp (name, "max_replies_per_connection") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.max_replies_per_connection = value;
+    }
+  else
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "There is no limit called \"%s\"\n",
+                      name);
+      return FALSE;
+    }
+  
+  if (must_be_positive && value < 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "<limit name=\"%s\"> must be a positive number\n",
+                      name);
+      return FALSE;
+    }
+
+  if (must_be_int &&
+      (value < _DBUS_INT_MIN || value > _DBUS_INT_MAX))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "<limit name=\"%s\"> value is too large\n",
+                      name);
+      return FALSE;
+    }
+
+  return TRUE;  
+}
+
+dbus_bool_t
+bus_config_parser_end_element (BusConfigParser   *parser,
+                               const char        *element_name,
+                               DBusError         *error)
+{
+  ElementType t;
+  const char *n;
+  Element *e;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  /* printf ("END: %s\n", element_name); */
+  
+  t = top_element_type (parser);
+
+  if (t == ELEMENT_NONE)
+    {
+      /* should probably be an assertion failure but
+       * being paranoid about XML parsers
+       */
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "XML parser ended element with no element on the stack");
+      return FALSE;
+    }
+
+  n = bus_config_parser_element_type_to_name (t);
+  _dbus_assert (n != NULL);
+  if (strcmp (n, element_name) != 0)
+    {
+      /* should probably be an assertion failure but
+       * being paranoid about XML parsers
+       */
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "XML element <%s> ended but topmost element on the stack was <%s>",
+                      element_name, n);
+      return FALSE;
+    }
+
+  e = peek_element (parser);
+  _dbus_assert (e != NULL);
+
+  switch (e->type)
+    {
+    case ELEMENT_NONE:
+      _dbus_assert_not_reached ("element in stack has no type");
+      break;
+
+    case ELEMENT_INCLUDE:
+    case ELEMENT_USER:
+    case ELEMENT_CONFIGTYPE:
+    case ELEMENT_LISTEN:
+    case ELEMENT_PIDFILE:
+    case ELEMENT_AUTH:
+    case ELEMENT_SERVICEDIR:
+    case ELEMENT_SERVICEHELPER:
+    case ELEMENT_INCLUDEDIR:
+    case ELEMENT_LIMIT:
+      if (!e->had_content)
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "XML element <%s> was expected to have content inside it",
+                          bus_config_parser_element_type_to_name (e->type));
+          return FALSE;
+        }
+
+      if (e->type == ELEMENT_LIMIT)
+        {
+          if (!set_limit (parser, e->d.limit.name, e->d.limit.value,
+                          error))
+            return FALSE;
+        }
+      break;
+
+    case ELEMENT_BUSCONFIG:
+    case ELEMENT_POLICY:
+    case ELEMENT_ALLOW:
+    case ELEMENT_DENY:
+    case ELEMENT_FORK:
+    case ELEMENT_SYSLOG:
+    case ELEMENT_KEEP_UMASK:
+    case ELEMENT_SELINUX:
+    case ELEMENT_ASSOCIATE:
+    case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
+    case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS:
+    case ELEMENT_ALLOW_ANONYMOUS:
+      break;
+    }
+
+  pop_element (parser);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+all_whitespace (const DBusString *str)
+{
+  int i;
+
+  _dbus_string_skip_white (str, 0, &i);
+
+  return i == _dbus_string_get_length (str);
+}
+
+static dbus_bool_t
+make_full_path (const DBusString *basedir,
+                const DBusString *filename,
+                DBusString       *full_path)
+{
+  if (_dbus_path_is_absolute (filename))
+    {
+      return _dbus_string_copy (filename, 0, full_path, 0);
+    }
+  else
+    {
+      if (!_dbus_string_copy (basedir, 0, full_path, 0))
+        return FALSE;
+      
+      if (!_dbus_concat_dir_and_file (full_path, filename))
+        return FALSE;
+
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
+include_file (BusConfigParser   *parser,
+              const DBusString  *filename,
+              dbus_bool_t        ignore_missing,
+              DBusError         *error)
+{
+  /* FIXME good test case for this would load each config file in the
+   * test suite both alone, and as an include, and check
+   * that the result is the same
+   */
+  BusConfigParser *included;
+  const char *filename_str;
+  DBusError tmp_error;
+        
+  dbus_error_init (&tmp_error);
+
+  filename_str = _dbus_string_get_const_data (filename);
+
+  /* Check to make sure this file hasn't already been included. */
+  if (seen_include (parser, filename))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+		      "Circular inclusion of file '%s'",
+		      filename_str);
+      return FALSE;
+    }
+  
+  if (! _dbus_list_append (&parser->included_files, (void *) filename_str))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  /* Since parser is passed in as the parent, included
+     inherits parser's limits. */
+  included = bus_config_load (filename, FALSE, parser, &tmp_error);
+
+  _dbus_list_pop_last (&parser->included_files);
+
+  if (included == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+
+      if (dbus_error_has_name (&tmp_error, DBUS_ERROR_FILE_NOT_FOUND) &&
+          ignore_missing)
+        {
+          dbus_error_free (&tmp_error);
+          return TRUE;
+        }
+      else
+        {
+          dbus_move_error (&tmp_error, error);
+          return FALSE;
+        }
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+
+      if (!merge_included (parser, included, error))
+        {
+          bus_config_parser_unref (included);
+          return FALSE;
+        }
+
+      /* Copy included's limits back to parser. */
+      parser->limits = included->limits;
+
+      bus_config_parser_unref (included);
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
+servicehelper_path (BusConfigParser   *parser,
+                    const DBusString  *filename,
+                    DBusError         *error)
+{
+  const char *filename_str;
+  char *servicehelper;
+
+  filename_str = _dbus_string_get_const_data (filename);
+
+  /* copy to avoid overwriting with NULL on OOM */
+  servicehelper = _dbus_strdup (filename_str);
+
+  /* check for OOM */
+  if (servicehelper == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  /* save the latest servicehelper only if not OOM */
+  dbus_free (parser->servicehelper);
+  parser->servicehelper = servicehelper;
+
+  /* We don't check whether the helper exists; instead we
+   * would just fail to ever activate anything if it doesn't.
+   * This allows an admin to fix the problem if it doesn't exist.
+   * It also allows the parser test suite to successfully parse
+   * test cases without installing the helper. ;-)
+   */
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+include_dir (BusConfigParser   *parser,
+             const DBusString  *dirname,
+             DBusError         *error)
+{
+  DBusString filename;
+  dbus_bool_t retval;
+  DBusError tmp_error;
+  DBusDirIter *dir;
+  char *s;
+  
+  if (!_dbus_string_init (&filename))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  retval = FALSE;
+  
+  dir = _dbus_directory_open (dirname, error);
+
+  if (dir == NULL)
+    goto failed;
+
+  dbus_error_init (&tmp_error);
+  while (_dbus_directory_get_next_file (dir, &filename, &tmp_error))
+    {
+      DBusString full_path;
+
+      if (!_dbus_string_init (&full_path))
+        {
+          BUS_SET_OOM (error);
+          goto failed;
+        }
+
+      if (!_dbus_string_copy (dirname, 0, &full_path, 0))
+        {
+          BUS_SET_OOM (error);
+          _dbus_string_free (&full_path);
+          goto failed;
+        }      
+
+      if (!_dbus_concat_dir_and_file (&full_path, &filename))
+        {
+          BUS_SET_OOM (error);
+          _dbus_string_free (&full_path);
+          goto failed;
+        }
+      
+      if (_dbus_string_ends_with_c_str (&full_path, ".conf"))
+        {
+          if (!include_file (parser, &full_path, TRUE, error))
+            {
+              if (dbus_error_is_set (error))
+                {
+                  /* We log to syslog unconditionally here, because this is
+                   * the configuration parser, so we don't yet know whether
+                   * this bus is going to want to write to syslog! (There's
+                   * also some layer inversion going on, if we want to use
+                   * the bus context.) */
+                  _dbus_system_log (DBUS_SYSTEM_LOG_INFO,
+                                    "Encountered error '%s' while parsing '%s'\n",
+                                    error->message,
+                                    _dbus_string_get_const_data (&full_path));
+                  dbus_error_free (error);
+                }
+            }
+        }
+
+      _dbus_string_free (&full_path);
+    }
+
+  if (dbus_error_is_set (&tmp_error))
+    {
+      dbus_move_error (&tmp_error, error);
+      goto failed;
+    }
+
+
+  if (!_dbus_string_copy_data (dirname, &s))
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  if (!_dbus_list_append (&parser->conf_dirs, s))
+    {
+      dbus_free (s);
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  retval = TRUE;
+  
+ failed:
+  _dbus_string_free (&filename);
+  
+  if (dir)
+    _dbus_directory_close (dir);
+
+  return retval;
+}
+
+dbus_bool_t
+bus_config_parser_content (BusConfigParser   *parser,
+                           const DBusString  *content,
+                           DBusError         *error)
+{
+  Element *e;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+#if 0
+  {
+    const char *c_str;
+    
+    _dbus_string_get_const_data (content, &c_str);
+
+    printf ("CONTENT %d bytes: %s\n", _dbus_string_get_length (content), c_str);
+  }
+#endif
+  
+  e = peek_element (parser);
+  if (e == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Text content outside of any XML element in configuration file");
+      return FALSE;
+    }
+  else if (e->had_content)
+    {
+      _dbus_assert_not_reached ("Element had multiple content blocks");
+      return FALSE;
+    }
+
+  switch (top_element_type (parser))
+    {
+    case ELEMENT_NONE:
+      _dbus_assert_not_reached ("element at top of stack has no type");
+      return FALSE;
+
+    case ELEMENT_BUSCONFIG:
+    case ELEMENT_POLICY:
+    case ELEMENT_ALLOW:
+    case ELEMENT_DENY:
+    case ELEMENT_FORK:
+    case ELEMENT_SYSLOG:
+    case ELEMENT_KEEP_UMASK:
+    case ELEMENT_STANDARD_SESSION_SERVICEDIRS:    
+    case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS:    
+    case ELEMENT_ALLOW_ANONYMOUS:
+    case ELEMENT_SELINUX:
+    case ELEMENT_ASSOCIATE:
+      if (all_whitespace (content))
+        return TRUE;
+      else
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "No text content expected inside XML element %s in configuration file",
+                          bus_config_parser_element_type_to_name (top_element_type (parser)));
+          return FALSE;
+        }
+
+    case ELEMENT_PIDFILE:
+      {
+        char *s;
+
+        e->had_content = TRUE;
+        
+        if (!_dbus_string_copy_data (content, &s))
+          goto nomem;
+          
+        dbus_free (parser->pidfile);
+        parser->pidfile = s;
+      }
+      break;
+
+    case ELEMENT_INCLUDE:
+      {
+        DBusString full_path, selinux_policy_root;
+
+        e->had_content = TRUE;
+
+	if (e->d.include.if_selinux_enabled
+	    && !bus_selinux_enabled ())
+	  break;
+
+        if (!_dbus_string_init (&full_path))
+          goto nomem;
+
+        if (e->d.include.selinux_root_relative)
+	  {
+            if (!bus_selinux_get_policy_root ())
+	      {
+		dbus_set_error (error, DBUS_ERROR_FAILED,
+				"Could not determine SELinux policy root for relative inclusion");
+		_dbus_string_free (&full_path);
+		return FALSE;
+	      }
+            _dbus_string_init_const (&selinux_policy_root,
+                                     bus_selinux_get_policy_root ());
+            if (!make_full_path (&selinux_policy_root, content, &full_path))
+              {
+                _dbus_string_free (&full_path);
+                goto nomem;
+              }
+          }
+        else if (!make_full_path (&parser->basedir, content, &full_path))
+          {
+            _dbus_string_free (&full_path);
+            goto nomem;
+          }
+
+        if (!include_file (parser, &full_path,
+                           e->d.include.ignore_missing, error))
+          {
+            _dbus_string_free (&full_path);
+            return FALSE;
+          }
+
+        _dbus_string_free (&full_path);
+      }
+      break;
+
+    case ELEMENT_SERVICEHELPER:
+      {
+        DBusString full_path;
+        
+        e->had_content = TRUE;
+
+        if (!_dbus_string_init (&full_path))
+          goto nomem;
+        
+        if (!make_full_path (&parser->basedir, content, &full_path))
+          {
+            _dbus_string_free (&full_path);
+            goto nomem;
+          }
+
+        if (!servicehelper_path (parser, &full_path, error))
+          {
+            _dbus_string_free (&full_path);
+            return FALSE;
+          }
+
+        _dbus_string_free (&full_path);
+      }
+      break;
+      
+    case ELEMENT_INCLUDEDIR:
+      {
+        DBusString full_path;
+        
+        e->had_content = TRUE;
+
+        if (!_dbus_string_init (&full_path))
+          goto nomem;
+        
+        if (!make_full_path (&parser->basedir, content, &full_path))
+          {
+            _dbus_string_free (&full_path);
+            goto nomem;
+          }
+        
+        if (!include_dir (parser, &full_path, error))
+          {
+            _dbus_string_free (&full_path);
+            return FALSE;
+          }
+
+        _dbus_string_free (&full_path);
+      }
+      break;
+      
+    case ELEMENT_USER:
+      {
+        char *s;
+
+        e->had_content = TRUE;
+        
+        if (!_dbus_string_copy_data (content, &s))
+          goto nomem;
+          
+        dbus_free (parser->user);
+        parser->user = s;
+      }
+      break;
+
+    case ELEMENT_CONFIGTYPE:
+      {
+        char *s;
+
+        e->had_content = TRUE;
+
+        if (!_dbus_string_copy_data (content, &s))
+          goto nomem;
+        
+        dbus_free (parser->bus_type);
+        parser->bus_type = s;
+      }
+      break;
+      
+    case ELEMENT_LISTEN:
+      {
+        char *s;
+
+        e->had_content = TRUE;
+        
+        if (!_dbus_string_copy_data (content, &s))
+          goto nomem;
+
+        if (!_dbus_list_append (&parser->listen_on,
+                                s))
+          {
+            dbus_free (s);
+            goto nomem;
+          }
+      }
+      break;
+
+    case ELEMENT_AUTH:
+      {
+        char *s;
+        
+        e->had_content = TRUE;
+
+        if (!_dbus_string_copy_data (content, &s))
+          goto nomem;
+
+        if (!_dbus_list_append (&parser->mechanisms,
+                                s))
+          {
+            dbus_free (s);
+            goto nomem;
+          }
+      }
+      break;
+
+    case ELEMENT_SERVICEDIR:
+      {
+        char *s;
+        DBusString full_path;
+        
+        e->had_content = TRUE;
+
+        if (!_dbus_string_init (&full_path))
+          goto nomem;
+        
+        if (!make_full_path (&parser->basedir, content, &full_path))
+          {
+            _dbus_string_free (&full_path);
+            goto nomem;
+          }
+        
+        if (!_dbus_string_copy_data (&full_path, &s))
+          {
+            _dbus_string_free (&full_path);
+            goto nomem;
+          }
+
+        /* _only_ extra session directories can be specified */
+        if (!service_dirs_append_unique_or_free (&parser->service_dirs, s))
+          {
+            _dbus_string_free (&full_path);
+            dbus_free (s);
+            goto nomem;
+          }
+
+        _dbus_string_free (&full_path);
+      }
+      break;
+
+    case ELEMENT_LIMIT:
+      {
+        long val;
+
+        e->had_content = TRUE;
+
+        val = 0;
+        if (!_dbus_string_parse_int (content, 0, &val, NULL))
+          {
+            dbus_set_error (error, DBUS_ERROR_FAILED,
+                            "<limit name=\"%s\"> element has invalid value (could not parse as integer)",
+                            e->d.limit.name);
+            return FALSE;
+          }
+
+        e->d.limit.value = val;
+
+        _dbus_verbose ("Loaded value %ld for limit %s\n",
+                       e->d.limit.value,
+                       e->d.limit.name);
+      }
+      break;
+    }
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  return TRUE;
+
+ nomem:
+  BUS_SET_OOM (error);
+  return FALSE;
+}
+
+dbus_bool_t
+bus_config_parser_finished (BusConfigParser   *parser,
+                            DBusError         *error)
+{
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (parser->stack != NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Element <%s> was not closed in configuration file",
+                      bus_config_parser_element_type_to_name (top_element_type (parser)));
+
+      return FALSE;
+    }
+
+  if (parser->is_toplevel && parser->listen_on == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Configuration file needs one or more <listen> elements giving addresses"); 
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+const char*
+bus_config_parser_get_user (BusConfigParser *parser)
+{
+  return parser->user;
+}
+
+const char*
+bus_config_parser_get_type (BusConfigParser *parser)
+{
+  return parser->bus_type;
+}
+
+DBusList**
+bus_config_parser_get_addresses (BusConfigParser *parser)
+{
+  return &parser->listen_on;
+}
+
+DBusList**
+bus_config_parser_get_mechanisms (BusConfigParser *parser)
+{
+  return &parser->mechanisms;
+}
+
+DBusList**
+bus_config_parser_get_service_dirs (BusConfigParser *parser)
+{
+  return &parser->service_dirs;
+}
+
+DBusList**
+bus_config_parser_get_conf_dirs (BusConfigParser *parser)
+{
+  return &parser->conf_dirs;
+}
+
+dbus_bool_t
+bus_config_parser_get_fork (BusConfigParser   *parser)
+{
+  return parser->fork;
+}
+
+dbus_bool_t
+bus_config_parser_get_syslog (BusConfigParser   *parser)
+{
+  return parser->syslog;
+}
+
+dbus_bool_t
+bus_config_parser_get_keep_umask (BusConfigParser   *parser)
+{
+  return parser->keep_umask;
+}
+
+dbus_bool_t
+bus_config_parser_get_allow_anonymous (BusConfigParser   *parser)
+{
+  return parser->allow_anonymous;
+}
+
+const char *
+bus_config_parser_get_pidfile (BusConfigParser   *parser)
+{
+  return parser->pidfile;
+}
+
+const char *
+bus_config_parser_get_servicehelper (BusConfigParser   *parser)
+{
+  return parser->servicehelper;
+}
+
+BusPolicy*
+bus_config_parser_steal_policy (BusConfigParser *parser)
+{
+  BusPolicy *policy;
+
+  _dbus_assert (parser->policy != NULL); /* can only steal the policy 1 time */
+  
+  policy = parser->policy;
+
+  parser->policy = NULL;
+
+  return policy;
+}
+
+/* Overwrite any limits that were set in the configuration file */
+void
+bus_config_parser_get_limits (BusConfigParser *parser,
+                              BusLimits       *limits)
+{
+  *limits = parser->limits;
+}
+
+DBusHashTable*
+bus_config_parser_steal_service_context_table (BusConfigParser *parser)
+{
+  DBusHashTable *table;
+
+  _dbus_assert (parser->service_context_table != NULL); /* can only steal once */
+
+  table = parser->service_context_table;
+
+  parser->service_context_table = NULL;
+
+  return table;
+}
+
+#ifdef DBUS_BUILD_TESTS
+#include <stdio.h>
+
+typedef enum
+{
+  VALID,
+  INVALID,
+  UNKNOWN
+} Validity;
+
+static dbus_bool_t
+do_check_own_rules (BusPolicy  *policy)
+{
+  const struct {
+    char *name;
+    dbus_bool_t allowed;
+  } checks[] = {
+    {"org.freedesktop", FALSE},
+    {"org.freedesktop.ManySystem", FALSE},
+    {"org.freedesktop.ManySystems", TRUE},
+    {"org.freedesktop.ManySystems.foo", TRUE},
+    {"org.freedesktop.ManySystems.foo.bar", TRUE},
+    {"org.freedesktop.ManySystems2", FALSE},
+    {"org.freedesktop.ManySystems2.foo", FALSE},
+    {"org.freedesktop.ManySystems2.foo.bar", FALSE},
+    {NULL, FALSE}
+  };
+  int i = 0;
+
+  while (checks[i].name)
+    {
+      DBusString service_name;
+      dbus_bool_t ret;
+
+      if (!_dbus_string_init (&service_name))
+        _dbus_assert_not_reached ("couldn't init string");
+      if (!_dbus_string_append (&service_name, checks[i].name))
+        _dbus_assert_not_reached ("couldn't append string");
+
+      ret = bus_policy_check_can_own (policy, &service_name);
+      printf ("        Check name %s: %s\n", checks[i].name,
+              ret ? "allowed" : "not allowed");
+      if (checks[i].allowed && !ret)
+        {
+          _dbus_warn ("Cannot own %s\n", checks[i].name);
+          return FALSE;
+        }
+      if (!checks[i].allowed && ret)
+        {
+          _dbus_warn ("Can own %s\n", checks[i].name);
+          return FALSE;
+        }
+      _dbus_string_free (&service_name);
+
+      i++;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+do_load (const DBusString *full_path,
+         Validity          validity,
+         dbus_bool_t       oom_possible,
+         dbus_bool_t       check_own_rules)
+{
+  BusConfigParser *parser;
+  DBusError error;
+
+  dbus_error_init (&error);
+
+  parser = bus_config_load (full_path, TRUE, NULL, &error);
+  if (parser == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&error);
+
+      if (oom_possible &&
+          dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+        {
+          _dbus_verbose ("Failed to load valid file due to OOM\n");
+          dbus_error_free (&error);
+          return TRUE;
+        }
+      else if (validity == VALID)
+        {
+          _dbus_warn ("Failed to load valid file but still had memory: %s\n",
+                      error.message);
+
+          dbus_error_free (&error);
+          return FALSE;
+        }
+      else
+        {
+          dbus_error_free (&error);
+          return TRUE;
+        }
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (&error);
+
+      if (check_own_rules && do_check_own_rules (parser->policy) == FALSE)
+        {
+          return FALSE;
+        }
+
+      bus_config_parser_unref (parser);
+
+      if (validity == INVALID)
+        {
+          _dbus_warn ("Accepted invalid file\n");
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+}
+
+typedef struct
+{
+  const DBusString *full_path;
+  Validity          validity;
+  dbus_bool_t       check_own_rules;
+} LoaderOomData;
+
+static dbus_bool_t
+check_loader_oom_func (void *data)
+{
+  LoaderOomData *d = data;
+
+  return do_load (d->full_path, d->validity, TRUE, d->check_own_rules);
+}
+
+static dbus_bool_t
+process_test_valid_subdir (const DBusString *test_base_dir,
+                           const char       *subdir,
+                           Validity          validity)
+{
+  DBusString test_directory;
+  DBusString filename;
+  DBusDirIter *dir;
+  dbus_bool_t retval;
+  DBusError error;
+
+  retval = FALSE;
+  dir = NULL;
+
+  if (!_dbus_string_init (&test_directory))
+    _dbus_assert_not_reached ("didn't allocate test_directory\n");
+
+  _dbus_string_init_const (&filename, subdir);
+
+  if (!_dbus_string_copy (test_base_dir, 0,
+                          &test_directory, 0))
+    _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
+
+  if (!_dbus_concat_dir_and_file (&test_directory, &filename))
+    _dbus_assert_not_reached ("couldn't allocate full path");
+
+  _dbus_string_free (&filename);
+  if (!_dbus_string_init (&filename))
+    _dbus_assert_not_reached ("didn't allocate filename string\n");
+
+  dbus_error_init (&error);
+  dir = _dbus_directory_open (&test_directory, &error);
+  if (dir == NULL)
+    {
+      _dbus_warn ("Could not open %s: %s\n",
+                  _dbus_string_get_const_data (&test_directory),
+                  error.message);
+      dbus_error_free (&error);
+      goto failed;
+    }
+
+  if (validity == VALID)
+    printf ("Testing valid files:\n");
+  else if (validity == INVALID)
+    printf ("Testing invalid files:\n");
+  else
+    printf ("Testing unknown files:\n");
+
+ next:
+  while (_dbus_directory_get_next_file (dir, &filename, &error))
+    {
+      DBusString full_path;
+      LoaderOomData d;
+
+      if (!_dbus_string_init (&full_path))
+        _dbus_assert_not_reached ("couldn't init string");
+
+      if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
+        _dbus_assert_not_reached ("couldn't copy dir to full_path");
+
+      if (!_dbus_concat_dir_and_file (&full_path, &filename))
+        _dbus_assert_not_reached ("couldn't concat file to dir");
+
+      if (!_dbus_string_ends_with_c_str (&full_path, ".conf"))
+        {
+          _dbus_verbose ("Skipping non-.conf file %s\n",
+                         _dbus_string_get_const_data (&filename));
+          _dbus_string_free (&full_path);
+          goto next;
+        }
+
+      printf ("    %s\n", _dbus_string_get_const_data (&filename));
+
+      _dbus_verbose (" expecting %s\n",
+                     validity == VALID ? "valid" :
+                     (validity == INVALID ? "invalid" :
+                      (validity == UNKNOWN ? "unknown" : "???")));
+
+      d.full_path = &full_path;
+      d.validity = validity;
+      d.check_own_rules = _dbus_string_ends_with_c_str (&full_path,
+          "check-own-rules.conf");
+
+      /* FIXME hackaround for an expat problem, see
+       * https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=124747
+       * http://freedesktop.org/pipermail/dbus/2004-May/001153.html
+       */
+      /* if (!_dbus_test_oom_handling ("config-loader", check_loader_oom_func, &d)) */
+      if (!check_loader_oom_func (&d))
+        _dbus_assert_not_reached ("test failed");
+      
+      _dbus_string_free (&full_path);
+    }
+
+  if (dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Could not get next file in %s: %s\n",
+                  _dbus_string_get_const_data (&test_directory),
+                  error.message);
+      dbus_error_free (&error);
+      goto failed;
+    }
+
+  retval = TRUE;
+
+ failed:
+
+  if (dir)
+    _dbus_directory_close (dir);
+  _dbus_string_free (&test_directory);
+  _dbus_string_free (&filename);
+
+  return retval;
+}
+
+static dbus_bool_t
+bools_equal (dbus_bool_t a,
+	     dbus_bool_t b)
+{
+  return a ? b : !b;
+}
+
+static dbus_bool_t
+strings_equal_or_both_null (const char *a,
+                            const char *b)
+{
+  if (a == NULL || b == NULL)
+    return a == b;
+  else
+    return !strcmp (a, b);
+}
+
+static dbus_bool_t
+elements_equal (const Element *a,
+		const Element *b)
+{
+  if (a->type != b->type)
+    return FALSE;
+
+  if (!bools_equal (a->had_content, b->had_content))
+    return FALSE;
+
+  switch (a->type)
+    {
+
+    case ELEMENT_INCLUDE:
+      if (!bools_equal (a->d.include.ignore_missing,
+			b->d.include.ignore_missing))
+	return FALSE;
+      break;
+
+    case ELEMENT_POLICY:
+      if (a->d.policy.type != b->d.policy.type)
+	return FALSE;
+      if (a->d.policy.gid_uid_or_at_console != b->d.policy.gid_uid_or_at_console)
+	return FALSE;
+      break;
+
+    case ELEMENT_LIMIT:
+      if (strcmp (a->d.limit.name, b->d.limit.name))
+	return FALSE;
+      if (a->d.limit.value != b->d.limit.value)
+	return FALSE;
+      break;
+
+    default:
+      /* do nothing */
+      break;
+    }
+
+  return TRUE;
+
+}
+
+static dbus_bool_t
+lists_of_elements_equal (DBusList *a,
+			 DBusList *b)
+{
+  DBusList *ia;
+  DBusList *ib;
+
+  ia = a;
+  ib = b;
+  
+  while (ia != NULL && ib != NULL)
+    {
+      if (elements_equal (ia->data, ib->data))
+	return FALSE;
+      ia = _dbus_list_get_next_link (&a, ia);
+      ib = _dbus_list_get_next_link (&b, ib);
+    }
+
+  return ia == NULL && ib == NULL;
+}
+
+static dbus_bool_t
+lists_of_c_strings_equal (DBusList *a,
+			  DBusList *b)
+{
+  DBusList *ia;
+  DBusList *ib;
+
+  ia = a;
+  ib = b;
+  
+  while (ia != NULL && ib != NULL)
+    {
+      if (strcmp (ia->data, ib->data))
+	return FALSE;
+      ia = _dbus_list_get_next_link (&a, ia);
+      ib = _dbus_list_get_next_link (&b, ib);
+    }
+
+  return ia == NULL && ib == NULL;
+}
+
+static dbus_bool_t
+limits_equal (const BusLimits *a,
+	      const BusLimits *b)
+{
+  return
+    (a->max_incoming_bytes == b->max_incoming_bytes
+     || a->max_incoming_unix_fds == b->max_incoming_unix_fds
+     || a->max_outgoing_bytes == b->max_outgoing_bytes
+     || a->max_outgoing_unix_fds == b->max_outgoing_unix_fds
+     || a->max_message_size == b->max_message_size
+     || a->max_message_unix_fds == b->max_message_unix_fds
+     || a->activation_timeout == b->activation_timeout
+     || a->auth_timeout == b->auth_timeout
+     || a->max_completed_connections == b->max_completed_connections
+     || a->max_incomplete_connections == b->max_incomplete_connections
+     || a->max_connections_per_user == b->max_connections_per_user
+     || a->max_pending_activations == b->max_pending_activations
+     || a->max_services_per_connection == b->max_services_per_connection
+     || a->max_match_rules_per_connection == b->max_match_rules_per_connection
+     || a->max_replies_per_connection == b->max_replies_per_connection
+     || a->reply_timeout == b->reply_timeout);
+}
+
+static dbus_bool_t
+config_parsers_equal (const BusConfigParser *a,
+                      const BusConfigParser *b)
+{
+  if (!_dbus_string_equal (&a->basedir, &b->basedir))
+    return FALSE;
+
+  if (!lists_of_elements_equal (a->stack, b->stack))
+    return FALSE;
+
+  if (!strings_equal_or_both_null (a->user, b->user))
+    return FALSE;
+
+  if (!lists_of_c_strings_equal (a->listen_on, b->listen_on))
+    return FALSE;
+
+  if (!lists_of_c_strings_equal (a->mechanisms, b->mechanisms))
+    return FALSE;
+
+  if (!lists_of_c_strings_equal (a->service_dirs, b->service_dirs))
+    return FALSE;
+  
+  /* FIXME: compare policy */
+
+  /* FIXME: compare service selinux ID table */
+
+  if (! limits_equal (&a->limits, &b->limits))
+    return FALSE;
+
+  if (!strings_equal_or_both_null (a->pidfile, b->pidfile))
+    return FALSE;
+
+  if (! bools_equal (a->fork, b->fork))
+    return FALSE;
+
+  if (! bools_equal (a->keep_umask, b->keep_umask))
+    return FALSE;
+
+  if (! bools_equal (a->is_toplevel, b->is_toplevel))
+    return FALSE;
+
+  return TRUE;
+}
+
+static dbus_bool_t
+all_are_equiv (const DBusString *target_directory)
+{
+  DBusString filename;
+  DBusDirIter *dir;
+  BusConfigParser *first_parser;
+  BusConfigParser *parser;
+  DBusError error;
+  dbus_bool_t equal;
+  dbus_bool_t retval;
+
+  dir = NULL;
+  first_parser = NULL;
+  parser = NULL;
+  retval = FALSE;
+
+  if (!_dbus_string_init (&filename))
+    _dbus_assert_not_reached ("didn't allocate filename string");
+
+  dbus_error_init (&error);
+  dir = _dbus_directory_open (target_directory, &error);
+  if (dir == NULL)
+    {
+      _dbus_warn ("Could not open %s: %s\n",
+		  _dbus_string_get_const_data (target_directory),
+		  error.message);
+      dbus_error_free (&error);
+      goto finished;
+    }
+
+  printf ("Comparing equivalent files:\n");
+
+ next:
+  while (_dbus_directory_get_next_file (dir, &filename, &error))
+    {
+      DBusString full_path;
+
+      if (!_dbus_string_init (&full_path))
+	_dbus_assert_not_reached ("couldn't init string");
+
+      if (!_dbus_string_copy (target_directory, 0, &full_path, 0))
+        _dbus_assert_not_reached ("couldn't copy dir to full_path");
+
+      if (!_dbus_concat_dir_and_file (&full_path, &filename))
+        _dbus_assert_not_reached ("couldn't concat file to dir");
+
+      if (!_dbus_string_ends_with_c_str (&full_path, ".conf"))
+        {
+          _dbus_verbose ("Skipping non-.conf file %s\n",
+                         _dbus_string_get_const_data (&filename));
+	  _dbus_string_free (&full_path);
+          goto next;
+        }
+
+      printf ("    %s\n", _dbus_string_get_const_data (&filename));
+
+      parser = bus_config_load (&full_path, TRUE, NULL, &error);
+
+      if (parser == NULL)
+	{
+	  _dbus_warn ("Could not load file %s: %s\n",
+		      _dbus_string_get_const_data (&full_path),
+		      error.message);
+          _dbus_string_free (&full_path);
+	  dbus_error_free (&error);
+	  goto finished;
+	}
+      else if (first_parser == NULL)
+	{
+          _dbus_string_free (&full_path);
+	  first_parser = parser;
+	}
+      else
+	{
+          _dbus_string_free (&full_path);
+	  equal = config_parsers_equal (first_parser, parser);
+	  bus_config_parser_unref (parser);
+	  if (! equal)
+	    goto finished;
+	}
+    }
+
+  retval = TRUE;
+
+ finished:
+  _dbus_string_free (&filename);
+  if (first_parser)
+    bus_config_parser_unref (first_parser);
+  if (dir)
+    _dbus_directory_close (dir);
+
+  return retval;
+  
+}
+
+static dbus_bool_t
+process_test_equiv_subdir (const DBusString *test_base_dir,
+			   const char       *subdir)
+{
+  DBusString test_directory;
+  DBusString filename;
+  DBusDirIter *dir;
+  DBusError error;
+  dbus_bool_t equal;
+  dbus_bool_t retval;
+
+  dir = NULL;
+  retval = FALSE;
+
+  if (!_dbus_string_init (&test_directory))
+    _dbus_assert_not_reached ("didn't allocate test_directory");
+
+  _dbus_string_init_const (&filename, subdir);
+
+  if (!_dbus_string_copy (test_base_dir, 0,
+			  &test_directory, 0))
+    _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
+
+  if (!_dbus_concat_dir_and_file (&test_directory, &filename))
+    _dbus_assert_not_reached ("couldn't allocate full path");
+
+  _dbus_string_free (&filename);
+  if (!_dbus_string_init (&filename))
+    _dbus_assert_not_reached ("didn't allocate filename string");
+
+  dbus_error_init (&error);
+  dir = _dbus_directory_open (&test_directory, &error);
+  if (dir == NULL)
+    {
+      _dbus_warn ("Could not open %s: %s\n",
+		  _dbus_string_get_const_data (&test_directory),
+		  error.message);
+      dbus_error_free (&error);
+      goto finished;
+    }
+
+  while (_dbus_directory_get_next_file (dir, &filename, &error))
+    {
+      DBusString full_path;
+
+      /* Skip CVS's magic directories! */
+      if (_dbus_string_equal_c_str (&filename, "CVS"))
+	continue;
+
+      if (!_dbus_string_init (&full_path))
+	_dbus_assert_not_reached ("couldn't init string");
+
+      if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
+        _dbus_assert_not_reached ("couldn't copy dir to full_path");
+
+      if (!_dbus_concat_dir_and_file (&full_path, &filename))
+        _dbus_assert_not_reached ("couldn't concat file to dir");
+      
+      equal = all_are_equiv (&full_path);
+      _dbus_string_free (&full_path);
+
+      if (!equal)
+	goto finished;
+    }
+
+  retval = TRUE;
+
+ finished:
+  _dbus_string_free (&test_directory);
+  _dbus_string_free (&filename);
+  if (dir)
+    _dbus_directory_close (dir);
+
+  return retval;
+  
+}
+
+static const char *test_session_service_dir_matches[] = 
+        {
+#ifdef DBUS_UNIX
+         "/testhome/foo/.testlocal/testshare/dbus-1/services",
+         "/testusr/testlocal/testshare/dbus-1/services",
+         "/testusr/testshare/dbus-1/services",
+         DBUS_DATADIR"/dbus-1/services",
+#endif
+/* will be filled in test_default_session_servicedirs() */
+#ifdef DBUS_WIN
+         NULL,
+         NULL,
+#endif
+         NULL
+        };
+
+static dbus_bool_t
+test_default_session_servicedirs (void)
+{
+  DBusList *dirs;
+  DBusList *link;
+  DBusString progs;
+  int i;
+
+#ifdef DBUS_WIN
+  const char *common_progs;
+  char buffer[1024];
+
+  if (_dbus_get_install_root(buffer, sizeof(buffer)))
+    {
+      strcat(buffer,DBUS_DATADIR);
+      strcat(buffer,"/dbus-1/services");
+      test_session_service_dir_matches[0] = buffer;
+    }
+#endif
+
+  /* On Unix we don't actually use this variable, but it's easier to handle the
+   * deallocation if we always allocate it, whether needed or not */
+  if (!_dbus_string_init (&progs))
+    _dbus_assert_not_reached ("OOM allocating progs");
+
+#ifndef DBUS_UNIX
+  common_progs = _dbus_getenv ("CommonProgramFiles");
+
+  if (common_progs) 
+    {
+      if (!_dbus_string_append (&progs, common_progs)) 
+        {
+          _dbus_string_free (&progs);
+          return FALSE;
+        }
+
+      if (!_dbus_string_append (&progs, "/dbus-1/services")) 
+        {
+          _dbus_string_free (&progs);
+          return FALSE;
+        }
+      test_session_service_dir_matches[1] = _dbus_string_get_const_data(&progs);
+    }
+#endif
+  dirs = NULL;
+
+  printf ("Testing retrieving the default session service directories\n");
+  if (!_dbus_get_standard_session_servicedirs (&dirs))
+    _dbus_assert_not_reached ("couldn't get stardard dirs");
+
+  /* make sure our defaults end with share/dbus-1/service */
+  while ((link = _dbus_list_pop_first_link (&dirs)))
+    {
+      DBusString path;
+      
+      printf ("    default service dir: %s\n", (char *)link->data);
+      _dbus_string_init_const (&path, (char *)link->data);
+      if (!_dbus_string_ends_with_c_str (&path, "dbus-1/services"))
+        {
+          printf ("error with default session service directories\n");
+	      dbus_free (link->data);
+    	  _dbus_list_free_link (link);
+          _dbus_string_free (&progs);
+          return FALSE;
+        }
+ 
+      dbus_free (link->data);
+      _dbus_list_free_link (link);
+    }
+
+#ifdef DBUS_UNIX
+  if (!_dbus_setenv ("XDG_DATA_HOME", "/testhome/foo/.testlocal/testshare"))
+    _dbus_assert_not_reached ("couldn't setenv XDG_DATA_HOME");
+
+  if (!_dbus_setenv ("XDG_DATA_DIRS", ":/testusr/testlocal/testshare: :/testusr/testshare:"))
+    _dbus_assert_not_reached ("couldn't setenv XDG_DATA_DIRS");
+#endif
+  if (!_dbus_get_standard_session_servicedirs (&dirs))
+    _dbus_assert_not_reached ("couldn't get stardard dirs");
+
+  /* make sure we read and parse the env variable correctly */
+  i = 0;
+  while ((link = _dbus_list_pop_first_link (&dirs)))
+    {
+      printf ("    test service dir: %s\n", (char *)link->data);
+      if (test_session_service_dir_matches[i] == NULL)
+        {
+          printf ("more directories parsed than in match set\n");
+          dbus_free (link->data);
+          _dbus_list_free_link (link);
+          _dbus_string_free (&progs);
+          return FALSE;
+        }
+ 
+      if (strcmp (test_session_service_dir_matches[i], 
+                  (char *)link->data) != 0)
+        {
+          printf ("%s directory does not match %s in the match set\n", 
+                  (char *)link->data,
+                  test_session_service_dir_matches[i]);
+          dbus_free (link->data);
+          _dbus_list_free_link (link);
+          _dbus_string_free (&progs);
+          return FALSE;
+        }
+
+      ++i;
+
+      dbus_free (link->data);
+      _dbus_list_free_link (link);
+    }
+  
+  if (test_session_service_dir_matches[i] != NULL)
+    {
+      printf ("extra data %s in the match set was not matched\n",
+              test_session_service_dir_matches[i]);
+
+      _dbus_string_free (&progs);
+      return FALSE;
+    }
+    
+  _dbus_string_free (&progs);
+  return TRUE;
+}
+
+static const char *test_system_service_dir_matches[] = 
+        {
+#ifdef DBUS_UNIX
+         "/usr/local/share/dbus-1/system-services",
+         "/usr/share/dbus-1/system-services",
+#endif
+         DBUS_DATADIR"/dbus-1/system-services",
+#ifdef DBUS_UNIX
+         "/lib/dbus-1/system-services",
+#endif
+
+#ifdef DBUS_WIN
+         NULL,
+#endif
+         NULL
+        };
+
+static dbus_bool_t
+test_default_system_servicedirs (void)
+{
+  DBusList *dirs;
+  DBusList *link;
+  DBusString progs;
+#ifndef DBUS_UNIX
+  const char *common_progs;
+#endif
+  int i;
+
+  /* On Unix we don't actually use this variable, but it's easier to handle the
+   * deallocation if we always allocate it, whether needed or not */
+  if (!_dbus_string_init (&progs))
+    _dbus_assert_not_reached ("OOM allocating progs");
+
+#ifndef DBUS_UNIX
+  common_progs = _dbus_getenv ("CommonProgramFiles");
+
+  if (common_progs) 
+    {
+      if (!_dbus_string_append (&progs, common_progs)) 
+        {
+          _dbus_string_free (&progs);
+          return FALSE;
+        }
+
+      if (!_dbus_string_append (&progs, "/dbus-1/system-services")) 
+        {
+          _dbus_string_free (&progs);
+          return FALSE;
+        }
+      test_system_service_dir_matches[1] = _dbus_string_get_const_data(&progs);
+    }
+#endif
+  dirs = NULL;
+
+  printf ("Testing retrieving the default system service directories\n");
+  if (!_dbus_get_standard_system_servicedirs (&dirs))
+    _dbus_assert_not_reached ("couldn't get stardard dirs");
+
+  /* make sure our defaults end with share/dbus-1/system-service */
+  while ((link = _dbus_list_pop_first_link (&dirs)))
+    {
+      DBusString path;
+      
+      printf ("    default service dir: %s\n", (char *)link->data);
+      _dbus_string_init_const (&path, (char *)link->data);
+      if (!_dbus_string_ends_with_c_str (&path, "dbus-1/system-services"))
+        {
+          printf ("error with default system service directories\n");
+	      dbus_free (link->data);
+    	  _dbus_list_free_link (link);
+          _dbus_string_free (&progs);
+          return FALSE;
+        }
+ 
+      dbus_free (link->data);
+      _dbus_list_free_link (link);
+    }
+
+#ifdef DBUS_UNIX
+  if (!_dbus_setenv ("XDG_DATA_HOME", "/testhome/foo/.testlocal/testshare"))
+    _dbus_assert_not_reached ("couldn't setenv XDG_DATA_HOME");
+
+  if (!_dbus_setenv ("XDG_DATA_DIRS", ":/testusr/testlocal/testshare: :/testusr/testshare:"))
+    _dbus_assert_not_reached ("couldn't setenv XDG_DATA_DIRS");
+#endif
+  if (!_dbus_get_standard_system_servicedirs (&dirs))
+    _dbus_assert_not_reached ("couldn't get stardard dirs");
+
+  /* make sure we read and parse the env variable correctly */
+  i = 0;
+  while ((link = _dbus_list_pop_first_link (&dirs)))
+    {
+      printf ("    test service dir: %s\n", (char *)link->data);
+      if (test_system_service_dir_matches[i] == NULL)
+        {
+          printf ("more directories parsed than in match set\n");
+          dbus_free (link->data);
+          _dbus_list_free_link (link);
+          _dbus_string_free (&progs);
+          return FALSE;
+        }
+ 
+      if (strcmp (test_system_service_dir_matches[i], 
+                  (char *)link->data) != 0)
+        {
+          printf ("%s directory does not match %s in the match set\n", 
+                  (char *)link->data,
+                  test_system_service_dir_matches[i]);
+          dbus_free (link->data);
+          _dbus_list_free_link (link);
+          _dbus_string_free (&progs);
+          return FALSE;
+        }
+
+      ++i;
+
+      dbus_free (link->data);
+      _dbus_list_free_link (link);
+    }
+  
+  if (test_system_service_dir_matches[i] != NULL)
+    {
+      printf ("extra data %s in the match set was not matched\n",
+              test_system_service_dir_matches[i]);
+
+      _dbus_string_free (&progs);
+      return FALSE;
+    }
+    
+  _dbus_string_free (&progs);
+  return TRUE;
+}
+		   
+dbus_bool_t
+bus_config_parser_test (const DBusString *test_data_dir)
+{
+  if (test_data_dir == NULL ||
+      _dbus_string_get_length (test_data_dir) == 0)
+    {
+      printf ("No test data\n");
+      return TRUE;
+    }
+
+  if (!test_default_session_servicedirs())
+    return FALSE;
+
+#ifdef DBUS_WIN
+  printf("default system service dir skipped\n");
+#else
+  if (!test_default_system_servicedirs())
+    return FALSE;
+#endif
+
+  if (!process_test_valid_subdir (test_data_dir, "valid-config-files", VALID))
+    return FALSE;
+
+  if (!process_test_valid_subdir (test_data_dir, "invalid-config-files", INVALID))
+    return FALSE;
+
+  if (!process_test_equiv_subdir (test_data_dir, "equiv-config-files"))
+    return FALSE;
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
+
diff --git a/dbus/bus/config-parser.h b/dbus/bus/config-parser.h
new file mode 100644
index 0000000..ba5bf74
--- /dev/null
+++ b/dbus/bus/config-parser.h
@@ -0,0 +1,87 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* config-parser.h  XML-library-agnostic configuration file parser
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_CONFIG_PARSER_H
+#define BUS_CONFIG_PARSER_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-hash.h>
+#include "bus.h"
+
+/* Whatever XML library we're using just pushes data into this API */
+
+typedef struct BusConfigParser BusConfigParser;
+
+BusConfigParser* bus_config_parser_new (const DBusString      *basedir,
+                                        dbus_bool_t            is_toplevel,
+                                        const BusConfigParser *parent);
+
+BusConfigParser* bus_config_parser_ref           (BusConfigParser   *parser);
+void             bus_config_parser_unref         (BusConfigParser   *parser);
+dbus_bool_t      bus_config_parser_check_doctype (BusConfigParser   *parser,
+                                                  const char        *doctype,
+                                                  DBusError         *error);
+dbus_bool_t      bus_config_parser_start_element (BusConfigParser   *parser,
+                                                  const char        *element_name,
+                                                  const char       **attribute_names,
+                                                  const char       **attribute_values,
+                                                  DBusError         *error);
+dbus_bool_t      bus_config_parser_end_element   (BusConfigParser   *parser,
+                                                  const char        *element_name,
+                                                  DBusError         *error);
+dbus_bool_t      bus_config_parser_content       (BusConfigParser   *parser,
+                                                  const DBusString  *content,
+                                                  DBusError         *error);
+dbus_bool_t      bus_config_parser_finished      (BusConfigParser   *parser,
+                                                  DBusError         *error);
+
+/* Functions for extracting the parse results */
+const char* bus_config_parser_get_user         (BusConfigParser *parser);
+const char* bus_config_parser_get_type         (BusConfigParser *parser);
+DBusList**  bus_config_parser_get_addresses    (BusConfigParser *parser);
+DBusList**  bus_config_parser_get_mechanisms   (BusConfigParser *parser);
+dbus_bool_t bus_config_parser_get_fork         (BusConfigParser *parser);
+dbus_bool_t bus_config_parser_get_allow_anonymous (BusConfigParser *parser);
+dbus_bool_t bus_config_parser_get_syslog       (BusConfigParser *parser);
+dbus_bool_t bus_config_parser_get_keep_umask   (BusConfigParser *parser);
+const char* bus_config_parser_get_pidfile      (BusConfigParser *parser);
+const char* bus_config_parser_get_servicehelper (BusConfigParser *parser);
+DBusList**  bus_config_parser_get_service_dirs (BusConfigParser *parser);
+DBusList**  bus_config_parser_get_conf_dirs    (BusConfigParser *parser);
+BusPolicy*  bus_config_parser_steal_policy     (BusConfigParser *parser);
+void        bus_config_parser_get_limits       (BusConfigParser *parser,
+                                                BusLimits       *limits);
+
+DBusHashTable* bus_config_parser_steal_service_context_table (BusConfigParser *parser);
+
+/* Loader functions (backended off one of the XML parsers).  Returns a
+ * finished ConfigParser.
+ */
+BusConfigParser* bus_config_load (const DBusString      *file,
+                                  dbus_bool_t            is_toplevel,
+                                  const BusConfigParser *parent,
+                                  DBusError             *error);
+
+#endif /* BUS_CONFIG_PARSER_H */
diff --git a/dbus/bus/connection.c b/dbus/bus/connection.c
new file mode 100644
index 0000000..d69758c
--- /dev/null
+++ b/dbus/bus/connection.c
@@ -0,0 +1,2385 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* connection.c  Client connections
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "connection.h"
+#include "dispatch.h"
+#include "policy.h"
+#include "services.h"
+#include "utils.h"
+#include "signals.h"
+#include "expirelist.h"
+#include "selinux.h"
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-hash.h>
+#include <dbus/dbus-timeout.h>
+
+/* Trim executed commands to this length; we want to keep logs readable */
+#define MAX_LOG_COMMAND_LEN 50
+
+static void bus_connection_remove_transactions (DBusConnection *connection);
+
+typedef struct
+{
+  BusExpireItem expire_item;
+
+  DBusConnection *will_get_reply;
+  DBusConnection *will_send_reply;
+
+  dbus_uint32_t reply_serial;
+  
+} BusPendingReply;
+
+struct BusConnections
+{
+  int refcount;
+  DBusList *completed;  /**< List of all completed connections */
+  int n_completed;      /**< Length of completed list */
+  DBusList *incomplete; /**< List of all not-yet-active connections */
+  int n_incomplete;     /**< Length of incomplete list */
+  BusContext *context;
+  DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */
+  DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */
+  int stamp;                   /**< Incrementing number */
+  BusExpireList *pending_replies; /**< List of pending replies */
+
+#ifdef DBUS_ENABLE_STATS
+  int total_match_rules;
+  int peak_match_rules;
+  int peak_match_rules_per_conn;
+
+  int total_bus_names;
+  int peak_bus_names;
+  int peak_bus_names_per_conn;
+#endif
+};
+
+static dbus_int32_t connection_data_slot = -1;
+
+typedef struct
+{
+  BusConnections *connections;
+  DBusList *link_in_connection_list;
+  DBusConnection *connection;
+  DBusList *services_owned;
+  int n_services_owned;
+  DBusList *match_rules;
+  int n_match_rules;
+  char *name;
+  DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */
+  DBusMessage *oom_message;
+  DBusPreallocatedSend *oom_preallocated;
+  BusClientPolicy *policy;
+
+  char *cached_loginfo_string;
+  BusSELinuxID *selinux_id;
+
+  long connection_tv_sec;  /**< Time when we connected (seconds component) */
+  long connection_tv_usec; /**< Time when we connected (microsec component) */
+  int stamp;               /**< connections->stamp last time we were traversed */
+
+#ifdef DBUS_ENABLE_STATS
+  int peak_match_rules;
+  int peak_bus_names;
+#endif
+} BusConnectionData;
+
+static dbus_bool_t bus_pending_reply_expired (BusExpireList *list,
+                                              DBusList      *link,
+                                              void          *data);
+
+static void bus_connection_drop_pending_replies (BusConnections  *connections,
+                                                 DBusConnection  *connection);
+
+static dbus_bool_t expire_incomplete_timeout (void *data);
+
+#define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
+
+static DBusLoop*
+connection_get_loop (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+
+  return bus_context_get_loop (d->connections->context);
+}
+
+
+static int
+get_connections_for_uid (BusConnections *connections,
+                         dbus_uid_t      uid)
+{
+  void *val;
+  int current_count;
+
+  /* val is NULL is 0 when it isn't in the hash yet */
+  
+  val = _dbus_hash_table_lookup_uintptr (connections->completed_by_user,
+                                       uid);
+
+  current_count = _DBUS_POINTER_TO_INT (val);
+
+  return current_count;
+}
+
+static dbus_bool_t
+adjust_connections_for_uid (BusConnections *connections,
+                            dbus_uid_t      uid,
+                            int             adjustment)
+{
+  int current_count;
+
+  current_count = get_connections_for_uid (connections, uid);
+
+  _dbus_verbose ("Adjusting connection count for UID " DBUS_UID_FORMAT
+                 ": was %d adjustment %d making %d\n",
+                 uid, current_count, adjustment, current_count + adjustment);
+  
+  _dbus_assert (current_count >= 0);
+  
+  current_count += adjustment;
+
+  _dbus_assert (current_count >= 0);
+
+  if (current_count == 0)
+    {
+      _dbus_hash_table_remove_uintptr (connections->completed_by_user, uid);
+      return TRUE;
+    }
+  else
+    {
+      dbus_bool_t retval;
+      
+      retval = _dbus_hash_table_insert_uintptr (connections->completed_by_user,
+                                              uid, _DBUS_INT_TO_POINTER (current_count));
+
+      /* only positive adjustment can fail as otherwise
+       * a hash entry should already exist
+       */
+      _dbus_assert (adjustment > 0 ||
+                    (adjustment <= 0 && retval));
+
+      return retval;
+    }
+}
+
+void
+bus_connection_disconnected (DBusConnection *connection)
+{
+  BusConnectionData *d;
+  BusService *service;
+  BusMatchmaker *matchmaker;
+  
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+
+  _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",
+                 d->name ? d->name : "(inactive)");
+
+  /* Delete our match rules */
+  if (d->n_match_rules > 0)
+    {
+      matchmaker = bus_context_get_matchmaker (d->connections->context);
+      bus_matchmaker_disconnected (matchmaker, connection);
+    }
+  
+  /* Drop any service ownership. Unfortunately, this requires
+   * memory allocation and there doesn't seem to be a good way to
+   * handle it other than sleeping; we can't "fail" the operation of
+   * disconnecting a client, and preallocating a broadcast "service is
+   * now gone" message for every client-service pair seems kind of
+   * involved.
+   */
+  while ((service = _dbus_list_get_last (&d->services_owned)))
+    {
+      BusTransaction *transaction;
+      DBusError error;
+
+    retry:
+      
+      dbus_error_init (&error);
+        
+      while ((transaction = bus_transaction_new (d->connections->context)) == NULL)
+        _dbus_wait_for_memory ();
+        
+      if (!bus_service_remove_owner (service, connection,
+                                     transaction, &error))
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (&error);
+          
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_error_free (&error);
+              bus_transaction_cancel_and_free (transaction);
+              _dbus_wait_for_memory ();
+              goto retry;
+            }
+          else
+            {
+              _dbus_verbose ("Failed to remove service owner: %s %s\n",
+                             error.name, error.message);
+              _dbus_assert_not_reached ("Removing service owner failed for non-memory-related reason");
+            }
+        }
+        
+      bus_transaction_execute_and_free (transaction);
+    }
+
+  bus_dispatch_remove_connection (connection);
+  
+  /* no more watching */
+  if (!dbus_connection_set_watch_functions (connection,
+                                            NULL, NULL, NULL,
+                                            connection,
+                                            NULL))
+    _dbus_assert_not_reached ("setting watch functions to NULL failed");
+
+  if (!dbus_connection_set_timeout_functions (connection,
+                                              NULL, NULL, NULL,
+                                              connection,
+                                              NULL))
+    _dbus_assert_not_reached ("setting timeout functions to NULL failed");
+  
+  dbus_connection_set_unix_user_function (connection,
+                                          NULL, NULL, NULL);
+  dbus_connection_set_windows_user_function (connection,
+                                             NULL, NULL, NULL);
+  
+  dbus_connection_set_dispatch_status_function (connection,
+                                                NULL, NULL, NULL);
+  
+  bus_connection_remove_transactions (connection);
+
+  if (d->link_in_connection_list != NULL)
+    {
+      if (d->name != NULL)
+        {
+          unsigned long uid;
+          
+          _dbus_list_remove_link (&d->connections->completed, d->link_in_connection_list);
+          d->link_in_connection_list = NULL;
+          d->connections->n_completed -= 1;
+
+          if (dbus_connection_get_unix_user (connection, &uid))
+            {
+              if (!adjust_connections_for_uid (d->connections,
+                                               uid, -1))
+                _dbus_assert_not_reached ("adjusting downward should never fail");
+            }
+        }
+      else
+        {
+          _dbus_list_remove_link (&d->connections->incomplete, d->link_in_connection_list);
+          d->link_in_connection_list = NULL;
+          d->connections->n_incomplete -= 1;
+        }
+      
+      _dbus_assert (d->connections->n_incomplete >= 0);
+      _dbus_assert (d->connections->n_completed >= 0);
+    }
+
+  bus_connection_drop_pending_replies (d->connections, connection);
+  
+  /* frees "d" as side effect */
+  dbus_connection_set_data (connection,
+                            connection_data_slot,
+                            NULL, NULL);
+  
+  dbus_connection_unref (connection);
+}
+
+static dbus_bool_t
+add_connection_watch (DBusWatch      *watch,
+                      void           *data)
+{
+  DBusConnection *connection = data;
+
+  return _dbus_loop_add_watch (connection_get_loop (connection), watch);
+}
+
+static void
+remove_connection_watch (DBusWatch      *watch,
+                         void           *data)
+{
+  DBusConnection *connection = data;
+  
+  _dbus_loop_remove_watch (connection_get_loop (connection), watch);
+}
+
+static void
+toggle_connection_watch (DBusWatch      *watch,
+                         void           *data)
+{
+  DBusConnection *connection = data;
+
+  _dbus_loop_toggle_watch (connection_get_loop (connection), watch);
+}
+
+static dbus_bool_t
+add_connection_timeout (DBusTimeout    *timeout,
+                        void           *data)
+{
+  DBusConnection *connection = data;
+  
+  return _dbus_loop_add_timeout (connection_get_loop (connection), timeout);
+}
+
+static void
+remove_connection_timeout (DBusTimeout    *timeout,
+                           void           *data)
+{
+  DBusConnection *connection = data;
+  
+  _dbus_loop_remove_timeout (connection_get_loop (connection), timeout);
+}
+
+static void
+dispatch_status_function (DBusConnection    *connection,
+                          DBusDispatchStatus new_status,
+                          void              *data)
+{
+  DBusLoop *loop = data;
+  
+  if (new_status != DBUS_DISPATCH_COMPLETE)
+    {
+      while (!_dbus_loop_queue_dispatch (loop, connection))
+        _dbus_wait_for_memory ();
+    }
+}
+
+static dbus_bool_t
+allow_unix_user_function (DBusConnection *connection,
+                          unsigned long   uid,
+                          void           *data)
+{
+  BusConnectionData *d;
+    
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+  
+  return bus_context_allow_unix_user (d->connections->context, uid);
+}
+
+static void
+free_connection_data (void *data)
+{
+  BusConnectionData *d = data;
+
+  /* services_owned should be NULL since we should be disconnected */
+  _dbus_assert (d->services_owned == NULL);
+  _dbus_assert (d->n_services_owned == 0);
+  /* similarly */
+  _dbus_assert (d->transaction_messages == NULL);
+
+  if (d->oom_preallocated)
+    dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated);
+
+  if (d->oom_message)
+    dbus_message_unref (d->oom_message);
+
+  if (d->policy)
+    bus_client_policy_unref (d->policy);
+
+  if (d->selinux_id)
+    bus_selinux_id_unref (d->selinux_id);
+  
+  dbus_free (d->cached_loginfo_string);
+  
+  dbus_free (d->name);
+  
+  dbus_free (d);
+}
+
+BusConnections*
+bus_connections_new (BusContext *context)
+{
+  BusConnections *connections;
+
+  if (!dbus_connection_allocate_data_slot (&connection_data_slot))
+    goto failed_0;
+
+  connections = dbus_new0 (BusConnections, 1);
+  if (connections == NULL)
+    goto failed_1;
+
+  connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_UINTPTR,
+                                                         NULL, NULL);
+  if (connections->completed_by_user == NULL)
+    goto failed_2;
+
+  connections->expire_timeout = _dbus_timeout_new (100, /* irrelevant */
+                                                   expire_incomplete_timeout,
+                                                   connections, NULL);
+  if (connections->expire_timeout == NULL)
+    goto failed_3;
+
+  _dbus_timeout_set_enabled (connections->expire_timeout, FALSE);
+
+  connections->pending_replies = bus_expire_list_new (bus_context_get_loop (context),
+                                                      bus_context_get_reply_timeout (context),
+                                                      bus_pending_reply_expired,
+                                                      connections);
+  if (connections->pending_replies == NULL)
+    goto failed_4;
+  
+  if (!_dbus_loop_add_timeout (bus_context_get_loop (context),
+                               connections->expire_timeout))
+    goto failed_5;
+  
+  connections->refcount = 1;
+  connections->context = context;
+  
+  return connections;
+
+ failed_5:
+  bus_expire_list_free (connections->pending_replies);
+ failed_4:
+  _dbus_timeout_unref (connections->expire_timeout);
+ failed_3:
+  _dbus_hash_table_unref (connections->completed_by_user);
+ failed_2:
+  dbus_free (connections);
+ failed_1:
+  dbus_connection_free_data_slot (&connection_data_slot);
+ failed_0:
+  return NULL;
+}
+
+BusConnections *
+bus_connections_ref (BusConnections *connections)
+{
+  _dbus_assert (connections->refcount > 0);
+  connections->refcount += 1;
+
+  return connections;
+}
+
+void
+bus_connections_unref (BusConnections *connections)
+{
+  _dbus_assert (connections->refcount > 0);
+  connections->refcount -= 1;
+  if (connections->refcount == 0)
+    {
+      /* drop all incomplete */
+      while (connections->incomplete != NULL)
+        {
+          DBusConnection *connection;
+
+          connection = connections->incomplete->data;
+
+          dbus_connection_ref (connection);
+          dbus_connection_close (connection);
+          bus_connection_disconnected (connection);
+          dbus_connection_unref (connection);
+        }
+
+      _dbus_assert (connections->n_incomplete == 0);
+      
+      /* drop all real connections */
+      while (connections->completed != NULL)
+        {
+          DBusConnection *connection;
+
+          connection = connections->completed->data;
+
+          dbus_connection_ref (connection);
+          dbus_connection_close (connection);
+          bus_connection_disconnected (connection);
+          dbus_connection_unref (connection);
+        }
+
+      _dbus_assert (connections->n_completed == 0);
+
+      bus_expire_list_free (connections->pending_replies);
+      
+      _dbus_loop_remove_timeout (bus_context_get_loop (connections->context),
+                                 connections->expire_timeout);
+      
+      _dbus_timeout_unref (connections->expire_timeout);
+      
+      _dbus_hash_table_unref (connections->completed_by_user);
+      
+      dbus_free (connections);
+
+      dbus_connection_free_data_slot (&connection_data_slot);
+    }
+}
+
+/* Used for logging */
+static dbus_bool_t
+cache_peer_loginfo_string (BusConnectionData *d, 
+                           DBusConnection    *connection)
+{
+  DBusString loginfo_buf;
+  unsigned long uid;
+  unsigned long pid;
+  char *windows_sid;
+  dbus_bool_t prev_added;
+
+  if (!_dbus_string_init (&loginfo_buf))
+    return FALSE;
+  
+  prev_added = FALSE;
+  if (dbus_connection_get_unix_user (connection, &uid))
+    {
+      if (!_dbus_string_append_printf (&loginfo_buf, "uid=%ld", uid))
+        goto oom;
+      else
+        prev_added = TRUE;
+    }
+
+  if (dbus_connection_get_unix_process_id (connection, &pid))
+    {
+      if (prev_added)
+        {
+          if (!_dbus_string_append_byte (&loginfo_buf, ' '))
+            goto oom;
+        }
+      if (!_dbus_string_append_printf (&loginfo_buf, "pid=%ld comm=\"", pid))
+        goto oom;
+      /* Ignore errors here; we may not have permissions to read the
+       * proc file. */
+      _dbus_command_for_pid (pid, &loginfo_buf, MAX_LOG_COMMAND_LEN, NULL);
+      if (!_dbus_string_append_byte (&loginfo_buf, '"'))
+        goto oom;
+    }
+
+  if (dbus_connection_get_windows_user (connection, &windows_sid))
+    {
+      dbus_bool_t did_append;
+      did_append = _dbus_string_append_printf (&loginfo_buf,
+                                               "sid=\"%s\" ", windows_sid);
+      dbus_free (windows_sid);
+      if (!did_append)
+        goto oom;
+    }
+
+  if (!_dbus_string_steal_data (&loginfo_buf, &(d->cached_loginfo_string)))
+    goto oom;
+
+  _dbus_string_free (&loginfo_buf); 
+
+  return TRUE;
+oom:
+   _dbus_string_free (&loginfo_buf);
+   return FALSE;
+}
+
+dbus_bool_t
+bus_connections_setup_connection (BusConnections *connections,
+                                  DBusConnection *connection)
+{
+
+  BusConnectionData *d;
+  dbus_bool_t retval;
+  DBusError error;
+
+  
+  d = dbus_new0 (BusConnectionData, 1);
+  
+  if (d == NULL)
+    return FALSE;
+
+  d->connections = connections;
+  d->connection = connection;
+  
+  _dbus_get_monotonic_time (&d->connection_tv_sec,
+                            &d->connection_tv_usec);
+  
+  _dbus_assert (connection_data_slot >= 0);
+  
+  if (!dbus_connection_set_data (connection,
+                                 connection_data_slot,
+                                 d, free_connection_data))
+    {
+      dbus_free (d);
+      return FALSE;
+    }
+
+  dbus_connection_set_route_peer_messages (connection, TRUE);
+  
+  retval = FALSE;
+
+  dbus_error_init (&error);
+  d->selinux_id = bus_selinux_init_connection_id (connection,
+                                                  &error);
+  if (dbus_error_is_set (&error))
+    {
+      /* This is a bit bogus because we pretend all errors
+       * are OOM; this is done because we know that in bus.c
+       * an OOM error disconnects the connection, which is
+       * the same thing we want on any other error.
+       */
+      dbus_error_free (&error);
+      goto out;
+    }
+
+  if (!dbus_connection_set_watch_functions (connection,
+                                            add_connection_watch,
+                                            remove_connection_watch,
+                                            toggle_connection_watch,
+                                            connection,
+                                            NULL))
+    goto out;
+  
+  if (!dbus_connection_set_timeout_functions (connection,
+                                              add_connection_timeout,
+                                              remove_connection_timeout,
+                                              NULL,
+                                              connection, NULL))
+    goto out;
+
+  /* For now we don't need to set a Windows user function because
+   * there are no policies in the config file controlling what
+   * Windows users can connect. The default 'same user that owns the
+   * bus can connect' behavior of DBusConnection is fine on Windows.
+   */
+  dbus_connection_set_unix_user_function (connection,
+                                          allow_unix_user_function,
+                                          NULL, NULL);
+
+  dbus_connection_set_dispatch_status_function (connection,
+                                                dispatch_status_function,
+                                                bus_context_get_loop (connections->context),
+                                                NULL);
+
+  d->link_in_connection_list = _dbus_list_alloc_link (connection);
+  if (d->link_in_connection_list == NULL)
+    goto out;
+  
+  /* Setup the connection with the dispatcher */
+  if (!bus_dispatch_add_connection (connection))
+    goto out;
+
+  if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
+    {
+      if (!_dbus_loop_queue_dispatch (bus_context_get_loop (connections->context), connection))
+        {
+          bus_dispatch_remove_connection (connection);
+          goto out;
+        }
+    }
+
+  _dbus_list_append_link (&connections->incomplete, d->link_in_connection_list);
+  connections->n_incomplete += 1;
+  
+  dbus_connection_ref (connection);
+
+  /* Note that we might disconnect ourselves here, but it only takes
+   * effect on return to the main loop. We call this to free up
+   * expired connections if possible, and to queue the timeout for our
+   * own expiration.
+   */
+  bus_connections_expire_incomplete (connections);
+  
+  /* And we might also disconnect ourselves here, but again it
+   * only takes effect on return to main loop.
+   */
+  if (connections->n_incomplete >
+      bus_context_get_max_incomplete_connections (connections->context))
+    {
+      _dbus_verbose ("Number of incomplete connections exceeds max, dropping oldest one\n");
+      
+      _dbus_assert (connections->incomplete != NULL);
+      /* Disconnect the oldest unauthenticated connection.  FIXME
+       * would it be more secure to drop a *random* connection?  This
+       * algorithm seems to mean that if someone can create new
+       * connections quickly enough, they can keep anyone else from
+       * completing authentication. But random may or may not really
+       * help with that, a more elaborate solution might be required.
+       */
+      dbus_connection_close (connections->incomplete->data);
+    }
+  
+  retval = TRUE;
+
+ out:
+  if (!retval)
+    {
+      if (d->selinux_id)
+        bus_selinux_id_unref (d->selinux_id);
+      d->selinux_id = NULL;
+      
+      if (!dbus_connection_set_watch_functions (connection,
+                                                NULL, NULL, NULL,
+                                                connection,
+                                                NULL))
+        _dbus_assert_not_reached ("setting watch functions to NULL failed");
+      
+      if (!dbus_connection_set_timeout_functions (connection,
+                                                  NULL, NULL, NULL,
+                                                  connection,
+                                                  NULL))
+        _dbus_assert_not_reached ("setting timeout functions to NULL failed");
+
+      dbus_connection_set_unix_user_function (connection,
+                                              NULL, NULL, NULL);
+
+      dbus_connection_set_windows_user_function (connection,
+                                                 NULL, NULL, NULL);
+      
+      dbus_connection_set_dispatch_status_function (connection,
+                                                    NULL, NULL, NULL);
+
+      if (d->link_in_connection_list != NULL)
+        {
+          _dbus_assert (d->link_in_connection_list->next == NULL);
+          _dbus_assert (d->link_in_connection_list->prev == NULL);
+          _dbus_list_free_link (d->link_in_connection_list);
+          d->link_in_connection_list = NULL;
+        }
+      
+      if (!dbus_connection_set_data (connection,
+                                     connection_data_slot,
+                                     NULL, NULL))
+        _dbus_assert_not_reached ("failed to set connection data to null");
+
+      /* "d" has now been freed */
+    }
+  
+  return retval;
+}
+
+void
+bus_connections_expire_incomplete (BusConnections *connections)
+{    
+  int next_interval;
+
+  next_interval = -1;
+  
+  if (connections->incomplete != NULL)
+    {
+      long tv_sec, tv_usec;
+      DBusList *link;
+      int auth_timeout;
+      
+      _dbus_get_monotonic_time (&tv_sec, &tv_usec);
+      auth_timeout = bus_context_get_auth_timeout (connections->context);
+  
+      link = _dbus_list_get_first_link (&connections->incomplete);
+      while (link != NULL)
+        {
+          DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
+          DBusConnection *connection;
+          BusConnectionData *d;
+          double elapsed;
+      
+          connection = link->data;
+      
+          d = BUS_CONNECTION_DATA (connection);
+      
+          _dbus_assert (d != NULL);
+      
+          elapsed = ELAPSED_MILLISECONDS_SINCE (d->connection_tv_sec,
+                                                d->connection_tv_usec,
+                                                tv_sec, tv_usec);
+
+          if (elapsed >= (double) auth_timeout)
+            {
+              _dbus_verbose ("Timing out authentication for connection %p\n", connection);
+              dbus_connection_close (connection);
+            }
+          else
+            {
+              /* We can end the loop, since the connections are in oldest-first order */
+              next_interval = ((double)auth_timeout) - elapsed;
+              _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n",
+                             connection, next_interval);
+          
+              break;
+            }
+      
+          link = next;
+        }
+    }
+
+  bus_expire_timeout_set_interval (connections->expire_timeout,
+                                   next_interval);
+}
+
+static dbus_bool_t
+expire_incomplete_timeout (void *data)
+{
+  BusConnections *connections = data;
+
+  _dbus_verbose ("Running\n");
+  
+  /* note that this may remove the timeout */
+  bus_connections_expire_incomplete (connections);
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_connection_get_unix_groups  (DBusConnection   *connection,
+                                 unsigned long   **groups,
+                                 int              *n_groups,
+                                 DBusError        *error)
+{
+  unsigned long uid;
+
+  *groups = NULL;
+  *n_groups = 0;
+
+  if (dbus_connection_get_unix_user (connection, &uid))
+    {
+      if (!_dbus_unix_groups_from_uid (uid, groups, n_groups))
+        {
+          _dbus_verbose ("Did not get any groups for UID %lu\n",
+                         uid);
+          return FALSE;
+        }
+      else
+        {
+          _dbus_verbose ("Got %d groups for UID %lu\n",
+                         *n_groups, uid);
+          return TRUE;
+        }
+    }
+  else
+    return TRUE; /* successfully got 0 groups */
+}
+
+dbus_bool_t
+bus_connection_is_in_unix_group (DBusConnection *connection,
+                                 unsigned long   gid)
+{
+  int i;
+  unsigned long *group_ids;
+  int n_group_ids;
+
+  if (!bus_connection_get_unix_groups (connection, &group_ids, &n_group_ids,
+                                       NULL))
+    return FALSE;
+
+  i = 0;
+  while (i < n_group_ids)
+    {
+      if (group_ids[i] == gid)
+        {
+          dbus_free (group_ids);
+          return TRUE;
+        }
+      ++i;
+    }
+
+  dbus_free (group_ids);
+  return FALSE;
+}
+
+const char *
+bus_connection_get_loginfo (DBusConnection        *connection)
+{
+  BusConnectionData *d;
+    
+  d = BUS_CONNECTION_DATA (connection);
+
+  if (!bus_connection_is_active (connection))
+    return "inactive";
+  return d->cached_loginfo_string;  
+}
+
+BusClientPolicy*
+bus_connection_get_policy (DBusConnection *connection)
+{
+  BusConnectionData *d;
+    
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+  _dbus_assert (d->policy != NULL);
+  
+  return d->policy;
+}
+
+static dbus_bool_t
+foreach_active (BusConnections               *connections,
+                BusConnectionForeachFunction  function,
+                void                         *data)
+{
+  DBusList *link;
+  
+  link = _dbus_list_get_first_link (&connections->completed);
+  while (link != NULL)
+    {
+      DBusConnection *connection = link->data;
+      DBusList *next = _dbus_list_get_next_link (&connections->completed, link);
+
+      if (!(* function) (connection, data))
+        return FALSE;
+      
+      link = next;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+foreach_inactive (BusConnections               *connections,
+                  BusConnectionForeachFunction  function,
+                  void                         *data)
+{
+  DBusList *link;
+  
+  link = _dbus_list_get_first_link (&connections->incomplete);
+  while (link != NULL)
+    {
+      DBusConnection *connection = link->data;
+      DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
+
+      if (!(* function) (connection, data))
+        return FALSE;
+      
+      link = next;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Calls function on each active connection; if the function returns
+ * #FALSE, stops iterating. Active connections are authenticated
+ * and have sent a Hello message.
+ *
+ * @param connections the connections object
+ * @param function the function
+ * @param data data to pass to it as a second arg
+ */
+void
+bus_connections_foreach_active (BusConnections               *connections,
+                                BusConnectionForeachFunction  function,
+                                void                         *data)
+{
+  foreach_active (connections, function, data);
+}
+
+/**
+ * Calls function on each connection; if the function returns
+ * #FALSE, stops iterating.
+ *
+ * @param connections the connections object
+ * @param function the function
+ * @param data data to pass to it as a second arg
+ */
+void
+bus_connections_foreach (BusConnections               *connections,
+                         BusConnectionForeachFunction  function,
+                         void                         *data)
+{
+  if (!foreach_active (connections, function, data))
+    return;
+
+  foreach_inactive (connections, function, data);
+}
+
+BusContext*
+bus_connections_get_context (BusConnections *connections)
+{
+  return connections->context;
+}
+
+/*
+ * This is used to avoid covering the same connection twice when
+ * traversing connections. Note that it assumes we will
+ * bus_connection_mark_stamp() each connection at least once per
+ * INT_MAX increments of the global stamp, or wraparound would break
+ * things.
+ */
+void
+bus_connections_increment_stamp (BusConnections *connections)
+{
+  connections->stamp += 1;
+}
+
+/* Mark connection with current stamp, return TRUE if it
+ * didn't already have that stamp
+ */
+dbus_bool_t
+bus_connection_mark_stamp (DBusConnection *connection)
+{
+  BusConnectionData *d;
+  
+  d = BUS_CONNECTION_DATA (connection);
+  
+  _dbus_assert (d != NULL);
+
+  if (d->stamp == d->connections->stamp)
+    return FALSE;
+  else
+    {
+      d->stamp = d->connections->stamp;
+      return TRUE;
+    }
+}
+
+BusContext*
+bus_connection_get_context (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+
+  return d->connections->context;
+}
+
+BusConnections*
+bus_connection_get_connections (DBusConnection *connection)
+{
+  BusConnectionData *d;
+    
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+
+  return d->connections;
+}
+
+BusRegistry*
+bus_connection_get_registry (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+
+  return bus_context_get_registry (d->connections->context);
+}
+
+BusActivation*
+bus_connection_get_activation (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+
+  return bus_context_get_activation (d->connections->context);
+}
+
+BusMatchmaker*
+bus_connection_get_matchmaker (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+
+  return bus_context_get_matchmaker (d->connections->context);
+}
+
+BusSELinuxID*
+bus_connection_get_selinux_id (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+
+  return d->selinux_id;
+}
+
+/**
+ * Checks whether the connection is registered with the message bus.
+ *
+ * @param connection the connection
+ * @returns #TRUE if we're an active message bus participant
+ */
+dbus_bool_t
+bus_connection_is_active (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  
+  return d != NULL && d->name != NULL;
+}
+
+dbus_bool_t
+bus_connection_preallocate_oom_error (DBusConnection *connection)
+{
+  DBusMessage *message;
+  DBusPreallocatedSend *preallocated;
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);  
+
+  _dbus_assert (d != NULL);
+
+  if (d->oom_preallocated != NULL)
+    return TRUE;
+  
+  preallocated = dbus_connection_preallocate_send (connection);
+  if (preallocated == NULL)
+    return FALSE;
+
+  message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
+
+  if (message == NULL)
+    {
+      dbus_connection_free_preallocated_send (connection, preallocated);
+      return FALSE;
+    }
+
+  /* d->name may be NULL, but that is OK */
+  if (!dbus_message_set_error_name (message, DBUS_ERROR_NO_MEMORY) ||
+      !dbus_message_set_destination (message, d->name) ||
+      !dbus_message_set_sender (message,
+                                DBUS_SERVICE_DBUS))
+    {
+      dbus_connection_free_preallocated_send (connection, preallocated);
+      dbus_message_unref (message);
+      return FALSE;
+    }
+  
+  /* set reply serial to placeholder value just so space is already allocated
+   * for it.
+   */
+  if (!dbus_message_set_reply_serial (message, 14))
+    {
+      dbus_connection_free_preallocated_send (connection, preallocated);
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  d->oom_message = message;
+  d->oom_preallocated = preallocated;
+  
+  return TRUE;
+}
+
+void
+bus_connection_send_oom_error (DBusConnection *connection,
+                               DBusMessage    *in_reply_to)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);  
+
+  _dbus_assert (d != NULL);  
+  _dbus_assert (d->oom_message != NULL);
+
+  /* should always succeed since we set it to a placeholder earlier */
+  if (!dbus_message_set_reply_serial (d->oom_message,
+                                      dbus_message_get_serial (in_reply_to)))
+    _dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message");
+
+  _dbus_assert (dbus_message_get_sender (d->oom_message) != NULL);
+  
+  dbus_connection_send_preallocated (connection, d->oom_preallocated,
+                                     d->oom_message, NULL);
+
+  dbus_message_unref (d->oom_message);
+  d->oom_message = NULL;
+  d->oom_preallocated = NULL;
+}
+
+#ifdef DBUS_ENABLE_STATS
+static void
+update_peak (int *peak,
+             int n)
+{
+  if (*peak < n)
+    *peak = n;
+}
+#endif
+
+void
+bus_connection_add_match_rule_link (DBusConnection *connection,
+                                    DBusList       *link)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+
+  _dbus_list_append_link (&d->match_rules, link);
+
+  d->n_match_rules += 1;
+
+#ifdef DBUS_ENABLE_STATS
+  update_peak (&d->peak_match_rules, d->n_match_rules);
+  update_peak (&d->connections->peak_match_rules_per_conn, d->n_match_rules);
+
+  d->connections->total_match_rules += 1;
+  update_peak (&d->connections->peak_match_rules,
+               d->connections->total_match_rules);
+#endif
+}
+
+dbus_bool_t
+bus_connection_add_match_rule (DBusConnection *connection,
+                               BusMatchRule   *rule)
+{
+    DBusList *link;
+
+  link = _dbus_list_alloc_link (rule);
+
+  if (link == NULL)
+    return FALSE;
+
+  bus_connection_add_match_rule_link (connection, link);
+
+  return TRUE;
+}
+
+void
+bus_connection_remove_match_rule (DBusConnection *connection,
+                                  BusMatchRule   *rule)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+
+  _dbus_list_remove_last (&d->match_rules, rule);
+
+  d->n_match_rules -= 1;
+  _dbus_assert (d->n_match_rules >= 0);
+
+#ifdef DBUS_ENABLE_STATS
+  d->connections->total_match_rules -= 1;
+#endif
+}
+
+int
+bus_connection_get_n_match_rules (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+  
+  return d->n_match_rules;
+}
+
+void
+bus_connection_add_owned_service_link (DBusConnection *connection,
+                                       DBusList       *link)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+
+  _dbus_list_append_link (&d->services_owned, link);
+
+  d->n_services_owned += 1;
+
+#ifdef DBUS_ENABLE_STATS
+  update_peak (&d->peak_bus_names, d->n_services_owned);
+  update_peak (&d->connections->peak_bus_names_per_conn,
+               d->n_services_owned);
+
+  d->connections->total_bus_names += 1;
+  update_peak (&d->connections->peak_bus_names,
+               d->connections->total_bus_names);
+#endif
+}
+
+dbus_bool_t
+bus_connection_add_owned_service (DBusConnection *connection,
+                                  BusService     *service)
+{
+  DBusList *link;
+
+  link = _dbus_list_alloc_link (service);
+
+  if (link == NULL)
+    return FALSE;
+
+  bus_connection_add_owned_service_link (connection, link);
+
+  return TRUE;
+}
+
+void
+bus_connection_remove_owned_service (DBusConnection *connection,
+                                     BusService     *service)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+
+  _dbus_list_remove_last (&d->services_owned, service);
+
+  d->n_services_owned -= 1;
+  _dbus_assert (d->n_services_owned >= 0);
+
+#ifdef DBUS_ENABLE_STATS
+  d->connections->total_bus_names -= 1;
+#endif
+}
+
+int
+bus_connection_get_n_services_owned (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+  
+  return d->n_services_owned;
+}
+
+dbus_bool_t
+bus_connection_complete (DBusConnection   *connection,
+			 const DBusString *name,
+                         DBusError        *error)
+{
+  BusConnectionData *d;
+  unsigned long uid;
+  
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+  _dbus_assert (d->name == NULL);
+  _dbus_assert (d->policy == NULL);
+
+  _dbus_assert (!bus_connection_is_active (connection));
+  
+  if (!_dbus_string_copy_data (name, &d->name))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  _dbus_assert (d->name != NULL);
+  
+  _dbus_verbose ("Name %s assigned to %p\n", d->name, connection);
+
+  d->policy = bus_context_create_client_policy (d->connections->context,
+                                                connection,
+                                                error);
+
+  /* we may have a NULL policy on OOM or error getting list of
+   * groups for a user. In the latter case we don't handle it so
+   * well currently, as it will just keep failing over and over.
+   */
+
+  if (d->policy == NULL)
+    {
+      _dbus_verbose ("Failed to create security policy for connection %p\n",
+                     connection);
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_free (d->name);
+      d->name = NULL;
+      return FALSE;
+    }
+  
+  if (dbus_connection_get_unix_user (connection, &uid))
+    {
+      if (!adjust_connections_for_uid (d->connections,
+                                       uid, 1))
+        goto fail;
+    }
+
+  /* Create and cache a string which holds information about the 
+   * peer process; used for logging purposes.
+   */
+  if (!cache_peer_loginfo_string (d, connection))
+    goto fail;
+
+  /* Now the connection is active, move it between lists */
+  _dbus_list_unlink (&d->connections->incomplete,
+                     d->link_in_connection_list);
+  d->connections->n_incomplete -= 1;
+  _dbus_list_append_link (&d->connections->completed,
+                          d->link_in_connection_list);
+  d->connections->n_completed += 1;
+
+  _dbus_assert (d->connections->n_incomplete >= 0);
+  _dbus_assert (d->connections->n_completed > 0);
+
+  /* See if we can remove the timeout */
+  bus_connections_expire_incomplete (d->connections);
+
+  _dbus_assert (bus_connection_is_active (connection));
+  
+  return TRUE;
+fail:
+  BUS_SET_OOM (error);
+  dbus_free (d->name);
+  d->name = NULL;
+  if (d->policy)
+    bus_client_policy_unref (d->policy);
+  d->policy = NULL;
+  return FALSE;
+}
+
+const char *
+bus_connection_get_name (DBusConnection *connection)
+{
+  BusConnectionData *d;
+  
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+  
+  return d->name;
+}
+
+/**
+ * Check whether completing the passed-in connection would
+ * exceed limits, and if so set error and return #FALSE
+ */
+dbus_bool_t
+bus_connections_check_limits (BusConnections  *connections,
+                              DBusConnection  *requesting_completion,
+                              DBusError       *error)
+{
+  unsigned long uid;
+
+  if (connections->n_completed >=
+      bus_context_get_max_completed_connections (connections->context))
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                      "The maximum number of active connections has been reached");
+      return FALSE;
+    }
+  
+  if (dbus_connection_get_unix_user (requesting_completion, &uid))
+    {
+      if (get_connections_for_uid (connections, uid) >=
+          bus_context_get_max_connections_per_user (connections->context))
+        {
+          dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                          "The maximum number of active connections for UID %lu has been reached",
+                          uid);
+          return FALSE;
+        }
+    }
+  
+  return TRUE;
+}
+
+static void
+bus_pending_reply_free (BusPendingReply *pending)
+{
+  _dbus_verbose ("Freeing pending reply %p, replier %p receiver %p serial %u\n",
+                 pending,
+                 pending->will_send_reply,
+                 pending->will_get_reply,
+                 pending->reply_serial);
+
+  dbus_free (pending);
+}
+
+static dbus_bool_t
+bus_pending_reply_send_no_reply (BusConnections  *connections,
+                                 BusTransaction  *transaction,
+                                 BusPendingReply *pending)
+{
+  DBusMessage *message;
+  DBusMessageIter iter;
+  dbus_bool_t retval;
+  const char *errmsg;
+
+  retval = FALSE;
+  
+  message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
+  if (message == NULL)
+    return FALSE;
+  
+  dbus_message_set_no_reply (message, TRUE);
+  
+  if (!dbus_message_set_reply_serial (message,
+                                      pending->reply_serial))
+    goto out;
+
+  if (!dbus_message_set_error_name (message,
+                                    DBUS_ERROR_NO_REPLY))
+    goto out;
+
+  errmsg = "Message did not receive a reply (timeout by message bus)";
+  dbus_message_iter_init_append (message, &iter);
+  if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &errmsg))
+    goto out;
+    
+  if (!bus_transaction_send_from_driver (transaction, pending->will_get_reply,
+                                         message))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  dbus_message_unref (message);
+  return retval;
+}
+
+static dbus_bool_t
+bus_pending_reply_expired (BusExpireList *list,
+                           DBusList      *link,
+                           void          *data)
+{
+  BusPendingReply *pending = link->data;
+  BusConnections *connections = data;
+  BusTransaction *transaction;
+  
+  /* No reply is forthcoming. So nuke it if we can. If not,
+   * leave it in the list to try expiring again later when we
+   * get more memory.
+   */
+
+  _dbus_verbose ("Expiring pending reply %p, replier %p receiver %p serial %u\n",
+                 pending,
+                 pending->will_send_reply,
+                 pending->will_get_reply,
+                 pending->reply_serial);
+  
+  transaction = bus_transaction_new (connections->context);
+  if (transaction == NULL)
+    return FALSE;
+  
+  if (!bus_pending_reply_send_no_reply (connections,
+                                        transaction,
+                                        pending))
+    {
+      bus_transaction_cancel_and_free (transaction);
+      return FALSE;
+    }
+
+  bus_expire_list_remove_link (connections->pending_replies, link);
+
+  bus_pending_reply_free (pending);
+  bus_transaction_execute_and_free (transaction);
+
+  return TRUE;
+}
+
+static void
+bus_connection_drop_pending_replies (BusConnections  *connections,
+                                     DBusConnection  *connection)
+{
+  /* The DBusConnection is almost 100% finalized here, so you can't
+   * do anything with it except check for pointer equality
+   */
+  DBusList *link;
+
+  _dbus_verbose ("Dropping pending replies that involve connection %p\n",
+                 connection);
+  
+  link = bus_expire_list_get_first_link (connections->pending_replies);
+  while (link != NULL)
+    {
+      DBusList *next;
+      BusPendingReply *pending;
+
+      next = bus_expire_list_get_next_link (connections->pending_replies,
+                                            link);
+      pending = link->data;
+
+      if (pending->will_get_reply == connection)
+        {
+          /* We don't need to track this pending reply anymore */
+
+          _dbus_verbose ("Dropping pending reply %p, replier %p receiver %p serial %u\n",
+                         pending,
+                         pending->will_send_reply,
+                         pending->will_get_reply,
+                         pending->reply_serial);
+          
+          bus_expire_list_remove_link (connections->pending_replies,
+                                       link);
+          bus_pending_reply_free (pending);
+        }
+      else if (pending->will_send_reply == connection)
+        {
+          /* The reply isn't going to be sent, so set things
+           * up so it will be expired right away
+           */
+          _dbus_verbose ("Will expire pending reply %p, replier %p receiver %p serial %u\n",
+                         pending,
+                         pending->will_send_reply,
+                         pending->will_get_reply,
+                         pending->reply_serial);
+          
+          pending->will_send_reply = NULL;
+          pending->expire_item.added_tv_sec = 0;
+          pending->expire_item.added_tv_usec = 0;
+
+          bus_expire_list_recheck_immediately (connections->pending_replies);
+        }
+      
+      link = next;
+    }
+}
+
+
+typedef struct
+{
+  BusPendingReply *pending;
+  BusConnections  *connections;
+} CancelPendingReplyData;
+
+static void
+cancel_pending_reply (void *data)
+{
+  CancelPendingReplyData *d = data;
+
+  _dbus_verbose ("d = %p\n", d);
+  
+  if (!bus_expire_list_remove (d->connections->pending_replies,
+                               &d->pending->expire_item))
+    _dbus_assert_not_reached ("pending reply did not exist to be cancelled");
+
+  bus_pending_reply_free (d->pending); /* since it's been cancelled */
+}
+
+static void
+cancel_pending_reply_data_free (void *data)
+{
+  CancelPendingReplyData *d = data;
+
+  _dbus_verbose ("d = %p\n", d);
+  
+  /* d->pending should be either freed or still
+   * in the list of pending replies (owned by someone
+   * else)
+   */
+  
+  dbus_free (d);
+}
+
+/*
+ * Record that a reply is allowed; return TRUE on success.
+ */
+dbus_bool_t
+bus_connections_expect_reply (BusConnections  *connections,
+                              BusTransaction  *transaction,
+                              DBusConnection  *will_get_reply,
+                              DBusConnection  *will_send_reply,
+                              DBusMessage     *reply_to_this,
+                              DBusError       *error)
+{
+  BusPendingReply *pending;
+  dbus_uint32_t reply_serial;
+  DBusList *link;
+  CancelPendingReplyData *cprd;
+  int count;
+
+  _dbus_assert (will_get_reply != NULL);
+  _dbus_assert (will_send_reply != NULL);
+  _dbus_assert (reply_to_this != NULL);
+  
+  if (dbus_message_get_no_reply (reply_to_this))
+    return TRUE; /* we won't allow a reply, since client doesn't care for one. */
+  
+  reply_serial = dbus_message_get_serial (reply_to_this);
+
+  link = bus_expire_list_get_first_link (connections->pending_replies);
+  count = 0;
+  while (link != NULL)
+    {
+      pending = link->data;
+
+      if (pending->reply_serial == reply_serial &&
+          pending->will_get_reply == will_get_reply &&
+          pending->will_send_reply == will_send_reply)
+        {
+          dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                          "Message has the same reply serial as a currently-outstanding existing method call");
+          return FALSE;
+        }
+      
+      link = bus_expire_list_get_next_link (connections->pending_replies,
+                                            link);
+      if (pending->will_get_reply == will_get_reply)
+        ++count;
+    }
+  
+  if (count >=
+      bus_context_get_max_replies_per_connection (connections->context))
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+		      "The maximum number of pending replies per connection has been reached");
+      return FALSE;
+    }
+
+  pending = dbus_new0 (BusPendingReply, 1);
+  if (pending == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  /* so we can see a not-yet-added pending reply */
+  pending->expire_item.added_tv_sec = 1;
+  pending->expire_item.added_tv_usec = 1;
+#endif
+
+  pending->will_get_reply = will_get_reply;
+  pending->will_send_reply = will_send_reply;
+  pending->reply_serial = reply_serial;
+  
+  cprd = dbus_new0 (CancelPendingReplyData, 1);
+  if (cprd == NULL)
+    {
+      BUS_SET_OOM (error);
+      bus_pending_reply_free (pending);
+      return FALSE;
+    }
+  
+  if (!bus_expire_list_add (connections->pending_replies,
+                            &pending->expire_item))
+    {
+      BUS_SET_OOM (error);
+      dbus_free (cprd);
+      bus_pending_reply_free (pending);
+      return FALSE;
+    }
+
+  if (!bus_transaction_add_cancel_hook (transaction,
+                                        cancel_pending_reply,
+                                        cprd,
+                                        cancel_pending_reply_data_free))
+    {
+      BUS_SET_OOM (error);
+      bus_expire_list_remove (connections->pending_replies, &pending->expire_item);
+      dbus_free (cprd);
+      bus_pending_reply_free (pending);
+      return FALSE;
+    }
+                                        
+  cprd->pending = pending;
+  cprd->connections = connections;
+  
+  _dbus_get_monotonic_time (&pending->expire_item.added_tv_sec,
+                            &pending->expire_item.added_tv_usec);
+
+  _dbus_verbose ("Added pending reply %p, replier %p receiver %p serial %u\n",
+                 pending,
+                 pending->will_send_reply,
+                 pending->will_get_reply,
+                 pending->reply_serial);
+  
+  return TRUE;
+}
+
+typedef struct
+{
+  DBusList        *link;
+  BusConnections  *connections;
+} CheckPendingReplyData;
+
+static void
+cancel_check_pending_reply (void *data)
+{
+  CheckPendingReplyData *d = data;
+
+  _dbus_verbose ("d = %p\n",d);
+
+  bus_expire_list_add_link (d->connections->pending_replies,
+                            d->link);
+  d->link = NULL;
+}
+
+static void
+check_pending_reply_data_free (void *data)
+{
+  CheckPendingReplyData *d = data;
+
+  _dbus_verbose ("d = %p\n",d);
+  
+  if (d->link != NULL)
+    {
+      BusPendingReply *pending = d->link->data;
+      
+      _dbus_assert (!bus_expire_list_contains_item (d->connections->pending_replies,
+                                                    &pending->expire_item));
+      
+      bus_pending_reply_free (pending);
+      _dbus_list_free_link (d->link);
+    }
+  
+  dbus_free (d);
+}
+
+/*
+ * Check whether a reply is allowed, remove BusPendingReply
+ * if so, return TRUE if so.
+ */
+dbus_bool_t
+bus_connections_check_reply (BusConnections *connections,
+                             BusTransaction *transaction,
+                             DBusConnection *sending_reply,
+                             DBusConnection *receiving_reply,
+                             DBusMessage    *reply,
+                             DBusError      *error)
+{
+  CheckPendingReplyData *cprd;
+  DBusList *link;
+  dbus_uint32_t reply_serial;
+  
+  _dbus_assert (sending_reply != NULL);
+  _dbus_assert (receiving_reply != NULL);
+
+  reply_serial = dbus_message_get_reply_serial (reply);
+
+  link = bus_expire_list_get_first_link (connections->pending_replies);
+  while (link != NULL)
+    {
+      BusPendingReply *pending = link->data;
+
+      if (pending->reply_serial == reply_serial &&
+          pending->will_get_reply == receiving_reply &&
+          pending->will_send_reply == sending_reply)
+        {
+          _dbus_verbose ("Found pending reply with serial %u\n", reply_serial);
+          break;
+        }
+      
+      link = bus_expire_list_get_next_link (connections->pending_replies,
+                                            link);
+    }
+
+  if (link == NULL)
+    {
+      _dbus_verbose ("No pending reply expected\n");
+
+      return FALSE;
+    }
+
+  cprd = dbus_new0 (CheckPendingReplyData, 1);
+  if (cprd == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!bus_transaction_add_cancel_hook (transaction,
+                                        cancel_check_pending_reply,
+                                        cprd,
+                                        check_pending_reply_data_free))
+    {
+      BUS_SET_OOM (error);
+      dbus_free (cprd);
+      return FALSE;
+    }
+
+  cprd->link = link;
+  cprd->connections = connections;
+  
+  bus_expire_list_unlink (connections->pending_replies,
+                          link);
+  
+  _dbus_assert (!bus_expire_list_contains_item (connections->pending_replies, link->data));
+
+  return TRUE;
+}
+
+/*
+ * Transactions
+ *
+ * Note that this is fairly fragile; in particular, don't try to use
+ * one transaction across any main loop iterations.
+ */
+
+typedef struct
+{
+  BusTransaction *transaction;
+  DBusMessage    *message;
+  DBusPreallocatedSend *preallocated;
+} MessageToSend;
+
+typedef struct
+{
+  BusTransactionCancelFunction cancel_function;
+  DBusFreeFunction free_data_function;
+  void *data;
+} CancelHook;
+
+struct BusTransaction
+{
+  DBusList *connections;
+  BusContext *context;
+  DBusList *cancel_hooks;
+};
+
+static void
+message_to_send_free (DBusConnection *connection,
+                      MessageToSend  *to_send)
+{
+  if (to_send->message)
+    dbus_message_unref (to_send->message);
+
+  if (to_send->preallocated)
+    dbus_connection_free_preallocated_send (connection, to_send->preallocated);
+
+  dbus_free (to_send);
+}
+
+static void
+cancel_hook_cancel (void *element,
+                    void *data)
+{
+  CancelHook *ch = element;
+
+  _dbus_verbose ("Running transaction cancel hook\n");
+  
+  if (ch->cancel_function)
+    (* ch->cancel_function) (ch->data);  
+}
+
+static void
+cancel_hook_free (void *element,
+                  void *data)
+{
+  CancelHook *ch = element;
+
+  if (ch->free_data_function)
+    (* ch->free_data_function) (ch->data);
+
+  dbus_free (ch);
+}
+
+static void
+free_cancel_hooks (BusTransaction *transaction)
+{
+  _dbus_list_foreach (&transaction->cancel_hooks,
+                      cancel_hook_free, NULL);
+  
+  _dbus_list_clear (&transaction->cancel_hooks);
+}
+
+BusTransaction*
+bus_transaction_new (BusContext *context)
+{
+  BusTransaction *transaction;
+
+  transaction = dbus_new0 (BusTransaction, 1);
+  if (transaction == NULL)
+    return NULL;
+
+  transaction->context = context;
+  
+  return transaction;
+}
+
+BusContext*
+bus_transaction_get_context (BusTransaction  *transaction)
+{
+  return transaction->context;
+}
+
+BusConnections*
+bus_transaction_get_connections (BusTransaction  *transaction)
+{
+  return bus_context_get_connections (transaction->context);
+}
+
+dbus_bool_t
+bus_transaction_send_from_driver (BusTransaction *transaction,
+                                  DBusConnection *connection,
+                                  DBusMessage    *message)
+{
+  /* We have to set the sender to the driver, and have
+   * to check security policy since it was not done in
+   * dispatch.c
+   */
+  _dbus_verbose ("Sending %s %s %s from driver\n",
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) : "(no interface)",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) : "(no member)",
+                 dbus_message_get_error_name (message) ?
+                 dbus_message_get_error_name (message) : "(no error name)");
+                 
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+    return FALSE;
+
+  if (bus_connection_is_active (connection))
+    {
+      if (!dbus_message_set_destination (message,
+                                         bus_connection_get_name (connection)))
+        return FALSE;
+    }
+  
+  /* bus driver never wants a reply */
+  dbus_message_set_no_reply (message, TRUE);
+  
+  /* If security policy doesn't allow the message, we silently
+   * eat it; the driver doesn't care about getting a reply.
+   */
+  if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
+                                          transaction,
+                                          NULL, connection, connection, message, NULL))
+    return TRUE;
+
+  return bus_transaction_send (transaction, connection, message);
+}
+
+dbus_bool_t
+bus_transaction_send (BusTransaction *transaction,
+                      DBusConnection *connection,
+                      DBusMessage    *message)
+{
+  MessageToSend *to_send;
+  BusConnectionData *d;
+  DBusList *link;
+
+  _dbus_verbose ("  trying to add %s interface=%s member=%s error=%s to transaction%s\n",
+                 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? "error" :
+                 dbus_message_get_reply_serial (message) != 0 ? "reply" :
+                 "message",
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) : "(unset)",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) : "(unset)",
+                 dbus_message_get_error_name (message) ?
+                 dbus_message_get_error_name (message) : "(unset)",
+                 dbus_connection_get_is_connected (connection) ?
+                 "" : " (disconnected)");
+
+  _dbus_assert (dbus_message_get_sender (message) != NULL);
+  
+  if (!dbus_connection_get_is_connected (connection))
+    return TRUE; /* silently ignore disconnected connections */
+  
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+  
+  to_send = dbus_new (MessageToSend, 1);
+  if (to_send == NULL)
+    {
+      return FALSE;
+    }
+
+  to_send->preallocated = dbus_connection_preallocate_send (connection);
+  if (to_send->preallocated == NULL)
+    {
+      dbus_free (to_send);
+      return FALSE;
+    }  
+  
+  dbus_message_ref (message);
+  to_send->message = message;
+  to_send->transaction = transaction;
+
+  _dbus_verbose ("about to prepend message\n");
+  
+  if (!_dbus_list_prepend (&d->transaction_messages, to_send))
+    {
+      message_to_send_free (connection, to_send);
+      return FALSE;
+    }
+
+  _dbus_verbose ("prepended message\n");
+  
+  /* See if we already had this connection in the list
+   * for this transaction. If we have a pending message,
+   * then we should already be in transaction->connections
+   */
+  link = _dbus_list_get_first_link (&d->transaction_messages);
+  _dbus_assert (link->data == to_send);
+  link = _dbus_list_get_next_link (&d->transaction_messages, link);
+  while (link != NULL)
+    {
+      MessageToSend *m = link->data;
+      DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
+      
+      if (m->transaction == transaction)
+        break;
+        
+      link = next;
+    }
+
+  if (link == NULL)
+    {
+      if (!_dbus_list_prepend (&transaction->connections, connection))
+        {
+          _dbus_list_remove (&d->transaction_messages, to_send);
+          message_to_send_free (connection, to_send);
+          return FALSE;
+        }
+    }
+
+  return TRUE;
+}
+
+static void
+connection_cancel_transaction (DBusConnection *connection,
+                               BusTransaction *transaction)
+{
+  DBusList *link;
+  BusConnectionData *d;
+  
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+  
+  link = _dbus_list_get_first_link (&d->transaction_messages);
+  while (link != NULL)
+    {
+      MessageToSend *m = link->data;
+      DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
+      
+      if (m->transaction == transaction)
+        {
+          _dbus_list_remove_link (&d->transaction_messages,
+                                  link);
+          
+          message_to_send_free (connection, m);
+        }
+        
+      link = next;
+    }
+}
+
+void
+bus_transaction_cancel_and_free (BusTransaction *transaction)
+{
+  DBusConnection *connection;
+
+  _dbus_verbose ("TRANSACTION: cancelled\n");
+  
+  while ((connection = _dbus_list_pop_first (&transaction->connections)))
+    connection_cancel_transaction (connection, transaction);
+
+  _dbus_assert (transaction->connections == NULL);
+
+  _dbus_list_foreach (&transaction->cancel_hooks,
+                      cancel_hook_cancel, NULL);
+
+  free_cancel_hooks (transaction);
+  
+  dbus_free (transaction);
+}
+
+static void
+connection_execute_transaction (DBusConnection *connection,
+                                BusTransaction *transaction)
+{
+  DBusList *link;
+  BusConnectionData *d;
+  
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+
+  /* Send the queue in order (FIFO) */
+  link = _dbus_list_get_last_link (&d->transaction_messages);
+  while (link != NULL)
+    {
+      MessageToSend *m = link->data;
+      DBusList *prev = _dbus_list_get_prev_link (&d->transaction_messages, link);
+      
+      if (m->transaction == transaction)
+        {
+          _dbus_list_remove_link (&d->transaction_messages,
+                                  link);
+
+          _dbus_assert (dbus_message_get_sender (m->message) != NULL);
+          
+          dbus_connection_send_preallocated (connection,
+                                             m->preallocated,
+                                             m->message,
+                                             NULL);
+
+          m->preallocated = NULL; /* so we don't double-free it */
+          
+          message_to_send_free (connection, m);
+        }
+        
+      link = prev;
+    }
+}
+
+void
+bus_transaction_execute_and_free (BusTransaction *transaction)
+{
+  /* For each connection in transaction->connections
+   * send the messages
+   */
+  DBusConnection *connection;
+
+  _dbus_verbose ("TRANSACTION: executing\n");
+  
+  while ((connection = _dbus_list_pop_first (&transaction->connections)))
+    connection_execute_transaction (connection, transaction);
+
+  _dbus_assert (transaction->connections == NULL);
+
+  free_cancel_hooks (transaction);
+  
+  dbus_free (transaction);
+}
+
+static void
+bus_connection_remove_transactions (DBusConnection *connection)
+{
+  MessageToSend *to_send;
+  BusConnectionData *d;
+  
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+  
+  while ((to_send = _dbus_list_get_first (&d->transaction_messages)))
+    {
+      /* only has an effect for the first MessageToSend listing this transaction */
+      _dbus_list_remove (&to_send->transaction->connections,
+                         connection);
+
+      _dbus_list_remove (&d->transaction_messages, to_send);
+      message_to_send_free (connection, to_send);
+    }
+}
+
+/**
+ * Converts the DBusError to a message reply
+ */
+dbus_bool_t
+bus_transaction_send_error_reply (BusTransaction  *transaction,
+                                  DBusConnection  *connection,
+                                  const DBusError *error,
+                                  DBusMessage     *in_reply_to)
+{
+  DBusMessage *reply;
+  
+  _dbus_assert (error != NULL);
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  
+  _dbus_verbose ("Sending error reply %s \"%s\"\n",
+                 error->name, error->message);
+
+  reply = dbus_message_new_error (in_reply_to,
+                                  error->name,
+                                  error->message);
+  if (reply == NULL)
+    return FALSE;
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    {
+      dbus_message_unref (reply);
+      return FALSE;
+    }
+
+  dbus_message_unref (reply);
+  
+  return TRUE;
+}
+
+dbus_bool_t
+bus_transaction_add_cancel_hook (BusTransaction               *transaction,
+                                 BusTransactionCancelFunction  cancel_function,
+                                 void                         *data,
+                                 DBusFreeFunction              free_data_function)
+{
+  CancelHook *ch;
+
+  ch = dbus_new (CancelHook, 1);
+  if (ch == NULL)
+    return FALSE;
+
+  _dbus_verbose ("     adding cancel hook function = %p data = %p\n",
+                 cancel_function, data);
+  
+  ch->cancel_function = cancel_function;
+  ch->data = data;
+  ch->free_data_function = free_data_function;
+
+  /* It's important that the hooks get run in reverse order that they
+   * were added
+   */
+  if (!_dbus_list_prepend (&transaction->cancel_hooks, ch))
+    {
+      dbus_free (ch);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+#ifdef DBUS_ENABLE_STATS
+int
+bus_connections_get_n_active (BusConnections *connections)
+{
+  return connections->n_completed;
+}
+
+int
+bus_connections_get_n_incomplete (BusConnections *connections)
+{
+  return connections->n_incomplete;
+}
+
+int
+bus_connections_get_total_match_rules (BusConnections *connections)
+{
+  return connections->total_match_rules;
+}
+
+int
+bus_connections_get_peak_match_rules (BusConnections *connections)
+{
+  return connections->peak_match_rules;
+}
+
+int
+bus_connections_get_peak_match_rules_per_conn (BusConnections *connections)
+{
+  return connections->peak_match_rules_per_conn;
+}
+
+int
+bus_connections_get_total_bus_names (BusConnections *connections)
+{
+  return connections->total_bus_names;
+}
+
+int
+bus_connections_get_peak_bus_names (BusConnections *connections)
+{
+  return connections->peak_bus_names;
+}
+
+int
+bus_connections_get_peak_bus_names_per_conn (BusConnections *connections)
+{
+  return connections->peak_bus_names_per_conn;
+}
+
+int
+bus_connection_get_peak_match_rules (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  return d->peak_match_rules;
+}
+
+int
+bus_connection_get_peak_bus_names (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  return d->peak_bus_names;
+}
+#endif /* DBUS_ENABLE_STATS */
diff --git a/dbus/bus/connection.h b/dbus/bus/connection.h
new file mode 100644
index 0000000..c936021
--- /dev/null
+++ b/dbus/bus/connection.h
@@ -0,0 +1,154 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* connection.h  Client connections
+ *
+ * Copyright (C) 2003, 2004  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_CONNECTION_H
+#define BUS_CONNECTION_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-list.h>
+#include "bus.h"
+
+typedef dbus_bool_t (* BusConnectionForeachFunction) (DBusConnection *connection, 
+                                                      void           *data);
+
+
+BusConnections* bus_connections_new               (BusContext                   *context);
+BusConnections* bus_connections_ref               (BusConnections               *connections);
+void            bus_connections_unref             (BusConnections               *connections);
+dbus_bool_t     bus_connections_setup_connection  (BusConnections               *connections,
+                                                   DBusConnection               *connection);
+void            bus_connections_foreach           (BusConnections               *connections,
+                                                   BusConnectionForeachFunction  function,
+                                                   void                         *data);
+void            bus_connections_foreach_active    (BusConnections               *connections,
+                                                   BusConnectionForeachFunction  function,
+                                                   void                         *data);
+BusContext*     bus_connections_get_context       (BusConnections               *connections);
+void            bus_connections_increment_stamp   (BusConnections               *connections);
+BusContext*     bus_connection_get_context        (DBusConnection               *connection);
+BusConnections* bus_connection_get_connections    (DBusConnection               *connection);
+BusRegistry*    bus_connection_get_registry       (DBusConnection               *connection);
+BusActivation*  bus_connection_get_activation     (DBusConnection               *connection);
+BusMatchmaker*  bus_connection_get_matchmaker     (DBusConnection               *connection);
+const char *    bus_connection_get_loginfo        (DBusConnection        *connection);
+BusSELinuxID*   bus_connection_get_selinux_id     (DBusConnection               *connection);
+dbus_bool_t     bus_connections_check_limits      (BusConnections               *connections,
+                                                   DBusConnection               *requesting_completion,
+                                                   DBusError                    *error);
+void            bus_connections_expire_incomplete (BusConnections               *connections);
+
+dbus_bool_t     bus_connections_expect_reply      (BusConnections               *connections,
+                                                   BusTransaction               *transaction,
+                                                   DBusConnection               *will_get_reply,
+                                                   DBusConnection               *will_send_reply,
+                                                   DBusMessage                  *reply_to_this,
+                                                   DBusError                    *error);
+dbus_bool_t     bus_connections_check_reply       (BusConnections               *connections,
+                                                   BusTransaction               *transaction,
+                                                   DBusConnection               *sending_reply,
+                                                   DBusConnection               *receiving_reply,
+                                                   DBusMessage                  *reply,
+                                                   DBusError                    *error);
+
+dbus_bool_t     bus_connection_mark_stamp         (DBusConnection               *connection);
+
+dbus_bool_t bus_connection_is_active (DBusConnection *connection);
+const char *bus_connection_get_name  (DBusConnection *connection);
+
+dbus_bool_t bus_connection_preallocate_oom_error (DBusConnection *connection);
+void        bus_connection_send_oom_error        (DBusConnection *connection,
+                                                  DBusMessage    *in_reply_to);
+
+/* called by signals.c */
+dbus_bool_t bus_connection_add_match_rule      (DBusConnection *connection,
+                                                BusMatchRule   *rule);
+void        bus_connection_add_match_rule_link (DBusConnection *connection,
+                                                DBusList       *link);
+void        bus_connection_remove_match_rule   (DBusConnection *connection,
+                                                BusMatchRule   *rule);
+int         bus_connection_get_n_match_rules   (DBusConnection *connection);
+
+
+/* called by services.c */
+dbus_bool_t bus_connection_add_owned_service      (DBusConnection *connection,
+                                                   BusService     *service);
+void        bus_connection_remove_owned_service   (DBusConnection *connection,
+                                                   BusService     *service);
+void        bus_connection_add_owned_service_link (DBusConnection *connection,
+                                                   DBusList       *link);
+int         bus_connection_get_n_services_owned   (DBusConnection *connection);
+
+/* called by driver.c */
+dbus_bool_t bus_connection_complete (DBusConnection               *connection,
+				     const DBusString             *name,
+                                     DBusError                    *error);
+
+/* called by dispatch.c when the connection is dropped */
+void        bus_connection_disconnected (DBusConnection *connection);
+
+dbus_bool_t      bus_connection_is_in_unix_group (DBusConnection       *connection,
+                                                  unsigned long         gid);
+dbus_bool_t      bus_connection_get_unix_groups  (DBusConnection       *connection,
+                                                  unsigned long       **groups,
+                                                  int                  *n_groups,
+                                                  DBusError            *error);
+BusClientPolicy* bus_connection_get_policy  (DBusConnection       *connection);
+
+/* transaction API so we can send or not send a block of messages as a whole */
+
+typedef void (* BusTransactionCancelFunction) (void *data);
+
+BusTransaction* bus_transaction_new              (BusContext                   *context);
+BusContext*     bus_transaction_get_context      (BusTransaction               *transaction);
+BusConnections* bus_transaction_get_connections  (BusTransaction               *transaction);
+dbus_bool_t     bus_transaction_send             (BusTransaction               *transaction,
+                                                  DBusConnection               *connection,
+                                                  DBusMessage                  *message);
+dbus_bool_t     bus_transaction_send_from_driver (BusTransaction               *transaction,
+                                                  DBusConnection               *connection,
+                                                  DBusMessage                  *message);
+dbus_bool_t     bus_transaction_send_error_reply (BusTransaction               *transaction,
+                                                  DBusConnection               *connection,
+                                                  const DBusError              *error,
+                                                  DBusMessage                  *in_reply_to);
+void            bus_transaction_cancel_and_free  (BusTransaction               *transaction);
+void            bus_transaction_execute_and_free (BusTransaction               *transaction);
+dbus_bool_t     bus_transaction_add_cancel_hook  (BusTransaction               *transaction,
+                                                  BusTransactionCancelFunction  cancel_function,
+                                                  void                         *data,
+                                                  DBusFreeFunction              free_data_function);
+
+/* called by stats.c, only present if DBUS_ENABLE_STATS */
+int bus_connections_get_n_active                  (BusConnections *connections);
+int bus_connections_get_n_incomplete              (BusConnections *connections);
+int bus_connections_get_total_match_rules         (BusConnections *connections);
+int bus_connections_get_peak_match_rules          (BusConnections *connections);
+int bus_connections_get_peak_match_rules_per_conn (BusConnections *connections);
+int bus_connections_get_total_bus_names           (BusConnections *connections);
+int bus_connections_get_peak_bus_names            (BusConnections *connections);
+int bus_connections_get_peak_bus_names_per_conn   (BusConnections *connections);
+
+int bus_connection_get_peak_match_rules           (DBusConnection *connection);
+int bus_connection_get_peak_bus_names             (DBusConnection *connection);
+
+#endif /* BUS_CONNECTION_H */
diff --git a/dbus/bus/dbus.service.in b/dbus/bus/dbus.service.in
new file mode 100644
index 0000000..160947c
--- /dev/null
+++ b/dbus/bus/dbus.service.in
@@ -0,0 +1,9 @@
+[Unit]
+Description=D-Bus System Message Bus
+Requires=dbus.socket
+After=syslog.target
+
+[Service]
+ExecStart=@EXPANDED_BINDIR@/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
+ExecReload=@EXPANDED_BINDIR@/dbus-send --print-reply --system --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig
+OOMScoreAdjust=-900
diff --git a/dbus/bus/dbus.socket.in b/dbus/bus/dbus.socket.in
new file mode 100644
index 0000000..74cbe58
--- /dev/null
+++ b/dbus/bus/dbus.socket.in
@@ -0,0 +1,5 @@
+[Unit]
+Description=D-Bus System Message Bus Socket
+
+[Socket]
+ListenStream=@DBUS_SYSTEM_SOCKET@
diff --git a/dbus/bus/desktop-file.c b/dbus/bus/desktop-file.c
new file mode 100644
index 0000000..ae441c5
--- /dev/null
+++ b/dbus/bus/desktop-file.c
@@ -0,0 +1,802 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* desktop-file.c  .desktop file parser
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-internals.h>
+#include "desktop-file.h"
+#include "utils.h"
+
+typedef struct
+{
+  char *key;
+  char *value;
+} BusDesktopFileLine;
+
+typedef struct
+{
+  char *section_name;
+  
+  int n_lines;
+  BusDesktopFileLine *lines;
+  int n_allocated_lines;  
+} BusDesktopFileSection;
+
+struct BusDesktopFile
+{
+  int n_sections;
+  BusDesktopFileSection *sections;
+  int n_allocated_sections;
+};
+
+/**
+ * Parser for service files.
+ */
+typedef struct
+{
+  DBusString data; /**< The data from the file */
+
+  BusDesktopFile *desktop_file; /**< The resulting object */
+  int current_section;    /**< The current section being parsed */
+  
+  int pos;          /**< Current position */
+  int len;          /**< Length */
+  int line_num;     /**< Current line number */
+  
+} BusDesktopFileParser;
+
+#define VALID_KEY_CHAR 1
+#define VALID_LOCALE_CHAR 2
+static unsigned char valid[256] = { 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x3 , 0x2 , 0x0 , 
+   0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 
+   0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x2 , 
+   0x0 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 
+   0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x3 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+   0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 
+};
+
+static void report_error (BusDesktopFileParser *parser,
+			  char                 *message,
+			  const char           *error_name,
+			  DBusError            *error);
+
+static void
+parser_free (BusDesktopFileParser *parser)
+{
+  bus_desktop_file_free (parser->desktop_file);
+  
+  _dbus_string_free (&parser->data);
+}
+
+static void
+bus_desktop_file_line_free (BusDesktopFileLine *line)
+{
+  dbus_free (line->key);
+  dbus_free (line->value);
+}
+
+static void
+bus_desktop_file_section_free (BusDesktopFileSection *section)
+{
+  int i;
+
+  for (i = 0; i < section->n_lines; i++)
+    bus_desktop_file_line_free (&section->lines[i]);
+
+  dbus_free (section->lines);
+  dbus_free (section->section_name);
+}
+
+void
+bus_desktop_file_free (BusDesktopFile *desktop_file)
+{
+  int i;
+
+  for (i = 0; i < desktop_file->n_sections; i++)
+    bus_desktop_file_section_free (&desktop_file->sections[i]);
+  dbus_free (desktop_file->sections);
+
+  dbus_free (desktop_file);
+}
+
+static dbus_bool_t
+grow_lines_in_section (BusDesktopFileSection *section)
+{
+  BusDesktopFileLine *lines;
+  
+  int new_n_lines;
+
+  if (section->n_allocated_lines == 0)
+    new_n_lines = 1;
+  else
+    new_n_lines = section->n_allocated_lines*2;
+
+  lines = dbus_realloc (section->lines,
+                        sizeof (BusDesktopFileLine) * new_n_lines);
+
+  if (lines == NULL)
+    return FALSE;
+  
+  section->lines = lines;
+  section->n_allocated_lines = new_n_lines;
+
+  return TRUE;
+}
+
+static dbus_bool_t
+grow_sections (BusDesktopFile *desktop_file)
+{
+  int new_n_sections;
+  BusDesktopFileSection *sections;
+  
+  if (desktop_file->n_allocated_sections == 0)
+    new_n_sections = 1;
+  else
+    new_n_sections = desktop_file->n_allocated_sections*2;
+
+  sections = dbus_realloc (desktop_file->sections,
+                           sizeof (BusDesktopFileSection) * new_n_sections);
+  if (sections == NULL)
+    return FALSE;
+  
+  desktop_file->sections = sections;
+  
+  desktop_file->n_allocated_sections = new_n_sections;
+
+  return TRUE;
+}
+
+static char *
+unescape_string (BusDesktopFileParser *parser,
+                 const DBusString     *str,
+                 int                   pos,
+                 int                   end_pos,
+                 DBusError            *error)
+{
+  char *retval, *q;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  /* len + 1 is enough, because unescaping never makes the
+   * string longer
+   */
+  retval = dbus_malloc (end_pos - pos + 1);
+  if (retval == NULL)
+    {
+      BUS_SET_OOM (error);
+      return NULL;
+    }
+
+  q = retval;
+  
+  while (pos < end_pos)
+    {
+      if (_dbus_string_get_byte (str, pos) == 0)
+	{
+	  /* Found an embedded null */
+	  dbus_free (retval);
+          report_error (parser, "Text to be unescaped contains embedded nul",
+                        BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
+	  return NULL;
+	}
+
+      if (_dbus_string_get_byte (str, pos) == '\\')
+	{
+	  pos ++;
+
+	  if (pos >= end_pos)
+	    {
+	      /* Escape at end of string */
+	      dbus_free (retval);
+              report_error (parser, "Text to be unescaped ended in \\",
+                            BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
+	      return NULL;
+	    }
+
+	  switch (_dbus_string_get_byte (str, pos))
+	    {
+	    case 's':
+              *q++ = ' ';
+              break;
+           case 't':
+              *q++ = '\t';
+              break;
+           case 'n':
+              *q++ = '\n';
+              break;
+           case 'r':
+              *q++ = '\r';
+              break;
+           case '\\':
+              *q++ = '\\';
+              break;
+           default:
+	     /* Invalid escape code */
+	     dbus_free (retval);
+             report_error (parser, "Text to be unescaped had invalid escape sequence",
+                           BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES, error);
+             return NULL;
+	    }
+	  pos++;
+	}
+      else
+	{
+	  *q++ =_dbus_string_get_byte (str, pos);
+
+	  pos++;
+	}
+    }
+
+  *q = 0;
+
+  return retval;
+}
+
+static BusDesktopFileSection* 
+new_section (BusDesktopFile *desktop_file,
+             const char     *name)
+{
+  int n;
+  char *name_copy;
+  
+  if (desktop_file->n_allocated_sections == desktop_file->n_sections)
+    {
+      if (!grow_sections (desktop_file))
+        return NULL;
+    }
+
+  name_copy = _dbus_strdup (name);
+  if (name_copy == NULL)
+    return NULL;
+
+  n = desktop_file->n_sections;
+  desktop_file->sections[n].section_name = name_copy;
+
+  desktop_file->sections[n].n_lines = 0;
+  desktop_file->sections[n].lines = NULL;
+  desktop_file->sections[n].n_allocated_lines = 0;
+
+  if (!grow_lines_in_section (&desktop_file->sections[n]))
+    {
+      dbus_free (desktop_file->sections[n].section_name);
+      desktop_file->sections[n].section_name = NULL;
+      return NULL;
+    }
+
+  desktop_file->n_sections += 1;
+  
+  return &desktop_file->sections[n];  
+}
+
+static BusDesktopFileSection* 
+open_section (BusDesktopFileParser *parser,
+              char                 *name)
+{  
+  BusDesktopFileSection *section;
+
+  section = new_section (parser->desktop_file, name);
+  if (section == NULL)
+    return NULL;
+  
+  parser->current_section = parser->desktop_file->n_sections - 1;
+  _dbus_assert (&parser->desktop_file->sections[parser->current_section] == section);
+  
+  return section;
+}
+
+static BusDesktopFileLine *
+new_line (BusDesktopFileParser *parser)
+{
+  BusDesktopFileSection *section;
+  BusDesktopFileLine *line;
+  
+  section = &parser->desktop_file->sections[parser->current_section];
+
+  if (section->n_allocated_lines == section->n_lines)
+    {
+      if (!grow_lines_in_section (section))
+        return NULL;
+    }
+
+  line = &section->lines[section->n_lines++];
+
+  _DBUS_ZERO(*line);
+    
+  return line;
+}
+
+static dbus_bool_t
+is_blank_line (BusDesktopFileParser *parser)
+{
+  int p;
+  char c;
+  
+  p = parser->pos;
+
+  c = _dbus_string_get_byte (&parser->data, p);
+
+  while (c && c != '\n')
+    {
+      if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f'))
+	return FALSE;
+      
+      p++;
+      c = _dbus_string_get_byte (&parser->data, p);
+    }
+
+  return TRUE;
+}
+
+static void
+parse_comment_or_blank (BusDesktopFileParser *parser)
+{
+  int line_end, eol_len;
+  
+  if (!_dbus_string_find_eol (&parser->data, parser->pos, &line_end, &eol_len))
+    line_end = parser->len;
+
+  if (line_end == parser->len)
+    parser->pos = parser->len;
+  else
+    parser->pos = line_end + eol_len;
+  
+  parser->line_num += 1;
+}
+
+static dbus_bool_t
+is_valid_section_name (const char *name)
+{
+  /* 5. Group names may contain all ASCII characters except for control characters and '[' and ']'. */
+
+  while (*name)
+    {
+      if (!((*name >= 'A' && *name <= 'Z') || (*name >= 'a' || *name <= 'z') ||
+	    *name == '\n' || *name == '\t'))
+	return FALSE;
+      
+      name++;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+parse_section_start (BusDesktopFileParser *parser, DBusError *error)
+{
+  int line_end, eol_len;
+  char *section_name;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+    
+  if (!_dbus_string_find_eol (&parser->data, parser->pos, &line_end, &eol_len))
+    line_end = parser->len;
+  
+  if (line_end - parser->pos <= 2 ||
+      _dbus_string_get_byte (&parser->data, line_end - 1) != ']')
+    {
+      report_error (parser, "Invalid syntax for section header", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
+      parser_free (parser);
+      return FALSE;
+    }
+
+  section_name = unescape_string (parser,
+                                  &parser->data, parser->pos + 1, line_end - 1,
+                                  error);
+
+  if (section_name == NULL)
+    {
+      parser_free (parser);
+      return FALSE;
+    }
+
+  if (!is_valid_section_name (section_name))
+    {
+      report_error (parser, "Invalid characters in section name", BUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error);
+      parser_free (parser);
+      dbus_free (section_name);
+      return FALSE;
+    }
+
+  if (open_section (parser, section_name) == NULL)
+    {
+      dbus_free (section_name);
+      parser_free (parser);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (line_end == parser->len)
+    parser->pos = parser->len;
+  else
+    parser->pos = line_end + eol_len;
+  
+  parser->line_num += 1;
+
+  dbus_free (section_name);
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+parse_key_value (BusDesktopFileParser *parser, DBusError *error)
+{
+  int line_end, eol_len;
+  int key_start, key_end;
+  int value_start;
+  int p;
+  char *value, *tmp;
+  DBusString key;
+  BusDesktopFileLine *line;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  if (!_dbus_string_find_eol (&parser->data, parser->pos, &line_end, &eol_len))
+    line_end = parser->len;
+  
+  p = parser->pos;
+  key_start = p;
+  while (p < line_end &&
+	 (valid[_dbus_string_get_byte (&parser->data, p)] & VALID_KEY_CHAR))
+    p++;
+  key_end = p;
+  
+  if (key_start == key_end)
+    {
+      report_error (parser, "Empty key name", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
+      parser_free (parser);
+      return FALSE;
+    }
+
+  /* We ignore locales for now */
+  if (p < line_end && _dbus_string_get_byte (&parser->data, p) == '[')
+    {
+      if (line_end == parser->len)
+	parser->pos = parser->len;
+      else
+	parser->pos = line_end + eol_len;
+	  
+      parser->line_num += 1;
+
+      return TRUE;
+    }
+  
+  /* Skip space before '=' */
+  while (p < line_end && _dbus_string_get_byte (&parser->data, p) == ' ')
+    p++;
+
+  if (p < line_end && _dbus_string_get_byte (&parser->data, p) != '=')
+    {
+      report_error (parser, "Invalid characters in key name", BUS_DESKTOP_PARSE_ERROR_INVALID_CHARS, error);
+      parser_free (parser);
+      return FALSE;
+    }
+
+  if (p == line_end)
+    {
+      report_error (parser, "No '=' in key/value pair", BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX, error);
+      parser_free (parser);
+      return FALSE;
+    }
+
+  /* Skip the '=' */
+  p++;
+
+  /* Skip space after '=' */
+  while (p < line_end && _dbus_string_get_byte (&parser->data, p) == ' ')
+    p++;
+
+  value_start = p;
+  
+  value = unescape_string (parser, &parser->data, value_start, line_end, error);
+  if (value == NULL)
+    {
+      parser_free (parser);
+      return FALSE;
+    }
+
+  line = new_line (parser);
+  if (line == NULL)
+    {
+      dbus_free (value);
+      parser_free (parser);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!_dbus_string_init (&key))
+    {
+      dbus_free (value);
+      parser_free (parser);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!_dbus_string_copy_len (&parser->data, key_start, key_end - key_start,
+                              &key, 0))
+    {
+      _dbus_string_free (&key);
+      dbus_free (value);
+      parser_free (parser);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!_dbus_string_steal_data (&key, &tmp))
+    {
+      _dbus_string_free (&key);
+      dbus_free (value);
+      parser_free (parser);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  _dbus_string_free (&key);
+  
+  line->key = tmp;
+  line->value = value;
+
+  if (line_end == parser->len)
+    parser->pos = parser->len;
+  else
+    parser->pos = line_end + eol_len;
+  
+  parser->line_num += 1;
+
+  return TRUE;
+}
+
+static void
+report_error (BusDesktopFileParser *parser,
+	      char                 *message,
+	      const char           *error_name,
+	      DBusError            *error)
+{
+  const char *section_name = NULL;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  if (parser->current_section != -1)
+    section_name = parser->desktop_file->sections[parser->current_section].section_name;
+
+  if (section_name)
+    dbus_set_error (error, error_name,
+                    "Error in section %s at line %d: %s\n", section_name, parser->line_num, message);
+  else
+    dbus_set_error (error, error_name,
+                    "Error at line %d: %s\n", parser->line_num, message);
+}
+
+#if 0
+static void
+dump_desktop_file (BusDesktopFile *file)
+{
+  int i;
+
+  for (i = 0; i < file->n_sections; i++)
+    {
+      int j;
+      
+      printf ("[%s]\n", file->sections[i].section_name);
+
+      for (j = 0; j < file->sections[i].n_lines; j++)
+	{
+	  printf ("%s=%s\n", file->sections[i].lines[j].key,
+		  file->sections[i].lines[j].value);
+	}
+    }
+}
+#endif
+
+BusDesktopFile*
+bus_desktop_file_load (DBusString *filename,
+		       DBusError  *error)
+{
+  DBusString str;
+  BusDesktopFileParser parser;
+  DBusStat sb;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  /* Clearly there's a race here, but it's just to make it unlikely
+   * that we do something silly, we still handle doing it below.
+   */
+  if (!_dbus_stat (filename, &sb, error))
+    return NULL;
+
+  if (sb.size > _DBUS_ONE_KILOBYTE * 128)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Desktop file size (%ld bytes) is too large", (long) sb.size);
+      return NULL;
+    }
+  
+  if (!_dbus_string_init (&str))
+    {
+      BUS_SET_OOM (error);
+      return NULL;
+    }
+  
+  if (!_dbus_file_get_contents (&str, filename, error))
+    {
+      _dbus_string_free (&str);
+      return NULL;
+    }
+
+  if (!_dbus_string_validate_utf8 (&str, 0, _dbus_string_get_length (&str)))
+    {
+      _dbus_string_free (&str);
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "invalid UTF-8");   
+      return NULL;
+    }
+  
+  parser.desktop_file = dbus_new0 (BusDesktopFile, 1);
+  if (parser.desktop_file == NULL)
+    {
+      _dbus_string_free (&str);
+      BUS_SET_OOM (error);
+      return NULL;
+    }
+  
+  parser.data = str;
+  parser.line_num = 1;
+  parser.pos = 0;
+  parser.len = _dbus_string_get_length (&parser.data);
+  parser.current_section = -1;
+
+  while (parser.pos < parser.len)
+    {
+      if (_dbus_string_get_byte (&parser.data, parser.pos) == '[')
+	{
+	  if (!parse_section_start (&parser, error))
+            {
+              return NULL;
+            }
+	}
+      else if (is_blank_line (&parser) ||
+	       _dbus_string_get_byte (&parser.data, parser.pos) == '#')
+	parse_comment_or_blank (&parser);
+      else
+	{
+	  if (!parse_key_value (&parser, error))
+            {
+              return NULL;
+            }
+	}
+    }
+
+  _dbus_string_free (&parser.data);
+
+  return parser.desktop_file;
+}
+
+static BusDesktopFileSection *
+lookup_section (BusDesktopFile *desktop_file,
+		const char     *section_name)
+{
+  BusDesktopFileSection *section;
+  int i;
+  
+  if (section_name == NULL)
+    return NULL;
+  
+  for (i = 0; i < desktop_file->n_sections; i ++)
+    {
+      section = &desktop_file->sections[i];
+
+      if (strcmp (section->section_name, section_name) == 0)
+	return section;
+    }
+  
+  return NULL;
+}
+
+static BusDesktopFileLine *
+lookup_line (BusDesktopFile        *desktop_file,
+	     BusDesktopFileSection *section,
+	     const char            *keyname)
+{
+  BusDesktopFileLine *line;
+  int i;
+
+  for (i = 0; i < section->n_lines; i++)
+    {
+      line = &section->lines[i];
+      
+      if (strcmp (line->key, keyname) == 0)
+	return line;
+    }
+  
+  return NULL;
+}
+
+dbus_bool_t
+bus_desktop_file_get_raw (BusDesktopFile  *desktop_file,
+			  const char      *section_name,
+			  const char      *keyname,
+			  const char     **val)
+{
+  BusDesktopFileSection *section;
+  BusDesktopFileLine *line;
+
+  *val = NULL;
+
+  section = lookup_section (desktop_file, section_name);
+  
+  if (!section)
+    return FALSE;
+
+  line = lookup_line (desktop_file,
+		      section,
+		      keyname);
+
+  if (!line)
+    return FALSE;
+  
+  *val = line->value;
+  
+  return TRUE;
+}
+
+dbus_bool_t
+bus_desktop_file_get_string (BusDesktopFile  *desktop_file,
+			     const char      *section,
+			     const char      *keyname,
+			     char           **val,
+			     DBusError       *error)
+{
+  const char *raw;
+ 
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  *val = NULL;
+  
+  if (!bus_desktop_file_get_raw (desktop_file, section, keyname, &raw))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "No \"%s\" key in .service file\n", keyname);
+      return FALSE;
+    }
+
+  *val = _dbus_strdup (raw);
+
+  if (*val == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  return TRUE;
+}
diff --git a/dbus/bus/desktop-file.h b/dbus/bus/desktop-file.h
new file mode 100644
index 0000000..58e78e8
--- /dev/null
+++ b/dbus/bus/desktop-file.h
@@ -0,0 +1,57 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* desktop-file.h  .desktop file parser
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+#ifndef BUS_DESKTOP_FILE_H
+#define BUS_DESKTOP_FILE_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-string.h>
+
+#define BUS_DESKTOP_PARSE_ERROR_INVALID_SYNTAX  "org.freedesktop.DBus.DesktopParseError.InvalidSyntax"
+#define BUS_DESKTOP_PARSE_ERROR_INVALID_ESCAPES "org.freedesktop.DBus.DesktopParseError.InvalidEscapes"
+#define BUS_DESKTOP_PARSE_ERROR_INVALID_CHARS   "org.freedesktop.DBus.DesktopParseError.InvalidChars"
+
+#define DBUS_SERVICE_SECTION  "D-BUS Service"
+#define DBUS_SERVICE_NAME     "Name"
+#define DBUS_SERVICE_EXEC     "Exec"
+#define DBUS_SERVICE_USER     "User"
+#define DBUS_SERVICE_GROUP    "Group"
+#define DBUS_SERVICE_SYSTEMD_SERVICE "SystemdService"
+
+typedef struct BusDesktopFile BusDesktopFile;
+
+BusDesktopFile *bus_desktop_file_load (DBusString     *filename,
+				       DBusError      *error);
+void            bus_desktop_file_free (BusDesktopFile *file);
+
+dbus_bool_t bus_desktop_file_get_raw    (BusDesktopFile  *desktop_file,
+					 const char      *section_name,
+					 const char      *keyname,
+					 const char     **val);
+dbus_bool_t bus_desktop_file_get_string (BusDesktopFile  *desktop_file,
+					 const char      *section,
+					 const char      *keyname,
+					 char           **val,
+					 DBusError       *error);
+
+
+#endif /* BUS_DESKTOP_FILE_H */
diff --git a/dbus/bus/dir-watch-default.c b/dbus/bus/dir-watch-default.c
new file mode 100644
index 0000000..69361b1
--- /dev/null
+++ b/dbus/bus/dir-watch-default.c
@@ -0,0 +1,35 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dir-watch-default.c  OS specific directory change notification for message bus
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include <dbus/dbus-internals.h>
+#include "dir-watch.h"
+
+
+/* NoOp */
+
+void
+bus_set_watched_dirs (BusContext *context, DBusList **directories)
+{
+}
diff --git a/dbus/bus/dir-watch-dnotify.c b/dbus/bus/dir-watch-dnotify.c
new file mode 100644
index 0000000..b38d7d1
--- /dev/null
+++ b/dbus/bus/dir-watch-dnotify.c
@@ -0,0 +1,93 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dir-watch-dnotify.c  OS specific directory change notification for message bus
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <dbus/dbus-internals.h>
+#include "dir-watch.h"
+
+#define MAX_DIRS_TO_WATCH 128
+
+/* use a static array to avoid handling OOM */
+static int fds[MAX_DIRS_TO_WATCH];
+static int num_fds = 0;
+
+void
+bus_watch_directory (const char *dir, BusContext *context)
+{
+  int fd;
+
+  _dbus_assert (dir != NULL);
+
+  if (num_fds >= MAX_DIRS_TO_WATCH )
+    {
+      _dbus_warn ("Cannot watch config directory '%s'. Already watching %d directories\n", dir, MAX_DIRS_TO_WATCH);
+      goto out;
+    }
+
+  fd = open (dir, O_RDONLY);
+  if (fd < 0)
+    {
+      _dbus_warn ("Cannot open directory '%s'; error '%s'\n", dir, _dbus_strerror (errno));
+      goto out;
+    }
+
+  if (fcntl (fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_RENAME|DN_MODIFY) == -1)
+    {
+      _dbus_warn ("Cannot setup D_NOTIFY for '%s' error '%s'\n", dir, _dbus_strerror (errno));
+      close (fd);
+      goto out;
+    }
+  
+  fds[num_fds++] = fd;
+  _dbus_verbose ("Added watch on config directory '%s'\n", dir);
+
+ out:
+  ;
+}
+
+void 
+bus_drop_all_directory_watches (void)
+{
+  int i;
+ 
+  _dbus_verbose ("Dropping all watches on config directories\n");
+ 
+  for (i = 0; i < num_fds; i++)
+    {
+      if (close (fds[i]) != 0)
+	{
+	  _dbus_verbose ("Error closing fd %d for config directory watch\n", fds[i]);
+	}
+    }
+  
+  num_fds = 0;
+}
diff --git a/dbus/bus/dir-watch-inotify.c b/dbus/bus/dir-watch-inotify.c
new file mode 100644
index 0000000..2e9be98
--- /dev/null
+++ b/dbus/bus/dir-watch-inotify.c
@@ -0,0 +1,279 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dir-watch-inotify.c  OS specific directory change notification for message bus
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *           (c) 2006 Mandriva
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/inotify.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-watch.h>
+#include "dir-watch.h"
+
+#define MAX_DIRS_TO_WATCH 128
+#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
+#define INOTIFY_BUF_LEN (1024 * (INOTIFY_EVENT_SIZE + 16))
+
+/* use a static array to avoid handling OOM */
+static int wds[MAX_DIRS_TO_WATCH];
+static char *dirs[MAX_DIRS_TO_WATCH];
+static int num_wds = 0;
+static int inotify_fd = -1;
+static DBusWatch *watch = NULL;
+static DBusLoop *loop = NULL;
+
+static dbus_bool_t
+_handle_inotify_watch (DBusWatch *passed_watch, unsigned int flags, void *data)
+{
+  char buffer[INOTIFY_BUF_LEN];
+  ssize_t ret = 0;
+  int i = 0;
+  pid_t pid;
+  dbus_bool_t have_change = FALSE;
+
+  ret = read (inotify_fd, buffer, INOTIFY_BUF_LEN);
+  if (ret < 0)
+    _dbus_verbose ("Error reading inotify event: '%s'\n", _dbus_strerror(errno));
+  else if (!ret)
+    _dbus_verbose ("Error reading inotify event: buffer too small\n");
+
+  while (i < ret)
+    {
+      struct inotify_event *ev;
+      pid = _dbus_getpid ();
+
+      ev = (struct inotify_event *) &buffer[i];
+      i += INOTIFY_EVENT_SIZE + ev->len;
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+      if (ev->len)
+        _dbus_verbose ("event name: '%s'\n", ev->name);
+      _dbus_verbose ("inotify event: wd=%d mask=%u cookie=%u len=%u\n", ev->wd, ev->mask, ev->cookie, ev->len);
+#endif
+      _dbus_verbose ("Sending SIGHUP signal on reception of a inotify event\n");
+      have_change = TRUE;
+    }
+  if (have_change)
+    (void) kill (pid, SIGHUP);
+
+  return TRUE;
+}
+
+#include <stdio.h>
+
+static void
+_set_watched_dirs_internal (DBusList **directories)
+{
+  int new_wds[MAX_DIRS_TO_WATCH];
+  char *new_dirs[MAX_DIRS_TO_WATCH];
+  DBusList *link;
+  int i, j, wd;
+
+  for (i = 0; i < MAX_DIRS_TO_WATCH; i++)
+    {
+      new_wds[i] = -1;
+      new_dirs[i] = NULL;
+    }
+
+  i = 0;
+  link = _dbus_list_get_first_link (directories);
+  while (link != NULL)
+    {
+      new_dirs[i++] = (char *)link->data;
+      link = _dbus_list_get_next_link (directories, link);
+    }
+
+  /* Look for directories in both the old and new sets, if
+   * we find one, move its data into the new set.
+   */
+  for (i = 0; new_dirs[i]; i++)
+    {
+      for (j = 0; j < num_wds; j++)
+        {
+          if (dirs[j] && strcmp (new_dirs[i], dirs[j]) == 0)
+            {
+              new_wds[i] = wds[j];
+              new_dirs[i] = dirs[j];
+              wds[j] = -1;
+              dirs[j] = NULL;
+              break;
+            }
+        }
+    }
+
+  /* Any directories we find in "wds" with a nonzero fd must
+   * not be in the new set, so perform cleanup now.
+   */
+  for (j = 0; j < num_wds; j++)
+    {
+      if (wds[j] != -1)
+        {
+          inotify_rm_watch (inotify_fd, wds[j]);
+          dbus_free (dirs[j]);
+          wds[j] = -1;
+          dirs[j] = NULL;
+        }
+    }
+
+  for (i = 0; new_dirs[i]; i++)
+    {
+      if (new_wds[i] == -1)
+        {
+          /* FIXME - less lame error handling for failing to add a watch; we may need to sleep. */
+          wd = inotify_add_watch (inotify_fd, new_dirs[i], IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM);
+          if (wd < 0)
+            {
+              /* Not all service directories need to exist. */
+              if (errno != ENOENT)
+                {
+                  _dbus_warn ("Cannot setup inotify for '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno));
+                  goto out;
+                }
+              else
+                {
+                  new_wds[i] = -1;
+                  new_dirs[i] = NULL;
+                  continue;
+                }
+            }
+          new_wds[i] = wd;
+          new_dirs[i] = _dbus_strdup (new_dirs[i]);
+          if (!new_dirs[i])
+            {
+              /* FIXME have less lame handling for OOM, we just silently fail to
+               * watch.  (In reality though, the whole OOM handling in dbus is stupid
+               * but we won't go into that in this comment =) )
+               */
+              inotify_rm_watch (inotify_fd, wd);
+              new_wds[i] = -1;
+            }
+        }
+    }
+
+  num_wds = i;
+
+  for (i = 0; i < MAX_DIRS_TO_WATCH; i++)
+    {
+      wds[i] = new_wds[i];
+      dirs[i] = new_dirs[i];
+    }
+
+ out:;
+}
+
+#include <stdio.h>
+static void
+_shutdown_inotify (void *data)
+{
+  DBusList *empty = NULL;
+
+  if (inotify_fd == -1)
+    return;
+
+  _set_watched_dirs_internal (&empty);
+
+  if (watch != NULL)
+    {
+      _dbus_loop_remove_watch (loop, watch);
+      _dbus_watch_invalidate (watch);
+      _dbus_watch_unref (watch);
+      _dbus_loop_unref (loop);
+    }
+  watch = NULL;
+  loop = NULL;
+
+  close (inotify_fd);
+  inotify_fd = -1;
+}
+
+static int
+_init_inotify (BusContext *context)
+{
+  int ret = 0;
+
+  if (inotify_fd == -1)
+    {
+#ifdef HAVE_INOTIFY_INIT1
+      inotify_fd = inotify_init1 (IN_CLOEXEC);
+      /* This ensures we still run on older Linux kernels.
+       * https://bugs.freedesktop.org/show_bug.cgi?id=23957
+       */
+      if (inotify_fd < 0)
+        inotify_fd = inotify_init ();
+#else
+      inotify_fd = inotify_init ();
+#endif
+      if (inotify_fd <= 0)
+        {
+          _dbus_warn ("Cannot initialize inotify\n");
+          goto out;
+        }
+      loop = bus_context_get_loop (context);
+      _dbus_loop_ref (loop);
+
+      watch = _dbus_watch_new (inotify_fd, DBUS_WATCH_READABLE, TRUE,
+                               _handle_inotify_watch, NULL, NULL);
+
+      if (watch == NULL)
+        {
+          _dbus_warn ("Unable to create inotify watch\n");
+          goto out;
+        }
+
+      if (!_dbus_loop_add_watch (loop, watch))
+        {
+          _dbus_warn ("Unable to add reload watch to main loop");
+          _dbus_watch_unref (watch);
+          watch = NULL;
+          goto out;
+        }
+
+      if (!_dbus_register_shutdown_func (_shutdown_inotify, NULL))
+      {
+          _dbus_warn ("Unable to register shutdown func");
+          _dbus_watch_unref (watch);
+          watch = NULL;
+          goto out;
+      }
+    }
+
+  ret = 1;
+
+out:
+  return ret;
+}
+
+void
+bus_set_watched_dirs (BusContext *context, DBusList **directories)
+{
+  if (!_init_inotify (context))
+    return;
+
+  _set_watched_dirs_internal (directories);
+}
diff --git a/dbus/bus/dir-watch-kqueue.c b/dbus/bus/dir-watch-kqueue.c
new file mode 100644
index 0000000..ac6290c
--- /dev/null
+++ b/dbus/bus/dir-watch-kqueue.c
@@ -0,0 +1,250 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dir-watch-kqueue.c  OS specific directory change notification for message bus
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "bus.h"
+#include <dbus/dbus-watch.h>
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-list.h>
+#include "dir-watch.h"
+
+#define MAX_DIRS_TO_WATCH 128
+
+static int kq = -1;
+static int fds[MAX_DIRS_TO_WATCH];
+static char *dirs[MAX_DIRS_TO_WATCH];
+static int num_fds = 0;
+static DBusWatch *watch = NULL;
+static DBusLoop *loop = NULL;
+
+static dbus_bool_t
+_handle_kqueue_watch (DBusWatch *watch, unsigned int flags, void *data)
+{
+  struct kevent ev;
+  struct timespec nullts = { 0, 0 };
+  int res;
+  pid_t pid;
+
+  res = kevent (kq, NULL, 0, &ev, 1, &nullts);
+
+  /* Sleep for half a second to avoid a race when files are install(1)'d
+   * to system.d. */
+  usleep(500000);
+
+  if (res > 0)
+    {
+      pid = getpid ();
+      _dbus_verbose ("Sending SIGHUP signal on reception of a kevent\n");
+      (void) kill (pid, SIGHUP);
+    }
+  else if (res < 0 && errno == EBADF)
+    {
+      kq = -1;
+      if (watch != NULL)
+	{
+	  _dbus_loop_remove_watch (loop, watch);
+          _dbus_watch_invalidate (watch);
+          _dbus_watch_unref (watch);
+	  watch = NULL;
+	}
+      pid = getpid ();
+      _dbus_verbose ("Sending SIGHUP signal since kqueue has been closed\n");
+      (void) kill (pid, SIGHUP);
+    }
+
+  return TRUE;
+}
+
+static int
+_init_kqueue (BusContext *context)
+{
+  int ret = 0;
+
+  if (kq < 0)
+    {
+
+      kq = kqueue ();
+      if (kq < 0)
+        {
+          _dbus_warn ("Cannot create kqueue; error '%s'\n", _dbus_strerror (errno));
+	  goto out;
+	}
+
+        loop = bus_context_get_loop (context);
+
+        watch = _dbus_watch_new (kq, DBUS_WATCH_READABLE, TRUE,
+                                 _handle_kqueue_watch, NULL, NULL);
+
+	if (watch == NULL)
+          {
+            _dbus_warn ("Unable to create kqueue watch\n");
+	    close (kq);
+	    kq = -1;
+	    goto out;
+	  }
+
+	if (!_dbus_loop_add_watch (loop, watch))
+          {
+            _dbus_warn ("Unable to add reload watch to main loop");
+	    _dbus_watch_invalidate (watch);
+	    _dbus_watch_unref (watch);
+	    watch = NULL;
+	    close (kq);
+	    kq = -1;
+            goto out;
+	  }
+    }
+
+  ret = 1;
+
+out:
+  return ret;
+}
+
+void
+bus_set_watched_dirs (BusContext *context, DBusList **directories)
+{
+  int new_fds[MAX_DIRS_TO_WATCH];
+  char *new_dirs[MAX_DIRS_TO_WATCH];
+  DBusList *link;
+  int i, j, f, fd;
+  struct kevent ev;
+
+  if (!_init_kqueue (context))
+    goto out;
+
+  for (i = 0; i < MAX_DIRS_TO_WATCH; i++)
+    {
+      new_fds[i] = -1;
+      new_dirs[i] = NULL;
+    }
+
+  i = 0;
+  link = _dbus_list_get_first_link (directories);
+  while (link != NULL)
+    {
+      new_dirs[i++] = (char *)link->data;
+      link = _dbus_list_get_next_link (directories, link);
+    }
+
+  /* Look for directories in both the old and new sets, if
+   * we find one, move its data into the new set.
+   */
+  for (i = 0; new_dirs[i]; i++)
+    {
+      for (j = 0; j < num_fds; j++)
+        {
+          if (dirs[j] && strcmp (new_dirs[i], dirs[j]) == 0)
+            {
+              new_fds[i] = fds[j];
+	      new_dirs[i] = dirs[j];
+	      fds[j] = -1;
+	      dirs[j] = NULL;
+	      break;
+	    }
+	}
+    }
+
+  /* Any directory we find in "fds" with a nonzero fd must
+   * not be in the new set, so perform cleanup now.
+   */
+  for (j = 0; j < num_fds; j++)
+    {
+      if (fds[j] != -1)
+        {
+          close (fds[j]);
+	  dbus_free (dirs[j]);
+	  fds[j] = -1;
+	  dirs[j] = NULL;
+	}
+    }
+
+  for (i = 0; new_dirs[i]; i++)
+    {
+      if (new_fds[i] == -1)
+        {
+          /* FIXME - less lame error handling for failing to add a watch;
+	   * we may need to sleep.
+	   */
+          fd = open (new_dirs[i], O_RDONLY);
+          if (fd < 0)
+            {
+              if (errno != ENOENT)
+                {
+                  _dbus_warn ("Cannot open directory '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno));
+                  goto out;
+                }
+              else
+                {
+                  new_fds[i] = -1;
+                  new_dirs[i] = NULL;
+                  continue;
+                }
+            }
+
+          EV_SET (&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
+                  NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_RENAME, 0, 0);
+          if (kevent (kq, &ev, 1, NULL, 0, NULL) == -1)
+            {
+              _dbus_warn ("Cannot setup a kevent for '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno));
+              close (fd);
+              goto out;
+            }
+
+	  new_fds[i] = fd;
+	  new_dirs[i] = _dbus_strdup (new_dirs[i]);
+	  if (!new_dirs[i])
+            {
+              /* FIXME have less lame handling for OOM, we just silently fail to
+	       * watch.  (In reality though, the whole OOM handling in dbus is
+	       * stupid but we won't go into that in this comment =) )
+	       */
+              close (fd);
+	      new_fds[i] = -1;
+	    }
+	}
+    }
+
+  num_fds = i;
+
+  for (i = 0; i < MAX_DIRS_TO_WATCH; i++)
+    {
+      fds[i] = new_fds[i];
+      dirs[i] = new_dirs[i];
+    }
+
+ out:
+  ;
+}
diff --git a/dbus/bus/dir-watch.h b/dbus/bus/dir-watch.h
new file mode 100644
index 0000000..b44529e
--- /dev/null
+++ b/dbus/bus/dir-watch.h
@@ -0,0 +1,40 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dir-watch.h  Watch directories
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include "bus.h"
+
+#ifndef DIR_WATCH_H
+#define DIR_WATCH_H
+
+/**
+ * Update the set of directories to monitor for changes.  The
+ * operating-system-specific implementation of this function should
+ * avoid creating a window where a directory in both the
+ * old and new set isn't monitored.
+ *
+ * @param context The bus context
+ * @param dirs List of strings which are directory paths
+ */
+void bus_set_watched_dirs (BusContext *context, DBusList **dirs);
+
+#endif /* DIR_WATCH_H */
diff --git a/dbus/bus/dispatch.c b/dbus/bus/dispatch.c
new file mode 100644
index 0000000..7a96f9d
--- /dev/null
+++ b/dbus/bus/dispatch.c
@@ -0,0 +1,4910 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dispatch.c  Message dispatcher
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2003, 2004, 2005  Red Hat, Inc.
+ * Copyright (C) 2004  Imendio HB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dispatch.h"
+#include "connection.h"
+#include "driver.h"
+#include "services.h"
+#include "activation.h"
+#include "utils.h"
+#include "bus.h"
+#include "signals.h"
+#include "test.h"
+#include <dbus/dbus-internals.h>
+#include <string.h>
+
+#ifdef HAVE_UNIX_FD_PASSING
+#include <dbus/dbus-sysdeps-unix.h>
+#include <unistd.h>
+#endif
+
+/* This is hard-coded in the files in valid-config-files-*. We have to use
+ * the debug-pipe transport because the tests in this file require that
+ * dbus_connection_open_private() does not block. */
+#define TEST_DEBUG_PIPE "debug-pipe:name=test-server"
+
+static dbus_bool_t
+send_one_message (DBusConnection *connection,
+                  BusContext     *context,
+                  DBusConnection *sender,
+                  DBusConnection *addressed_recipient,
+                  DBusMessage    *message,
+                  BusTransaction *transaction,
+                  DBusError      *error)
+{
+  if (!bus_context_check_security_policy (context, transaction,
+                                          sender,
+                                          addressed_recipient,
+                                          connection,
+                                          message,
+                                          NULL))
+    return TRUE; /* silently don't send it */
+
+  if (dbus_message_contains_unix_fds(message) &&
+      !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD))
+    return TRUE; /* silently don't send it */
+
+  if (!bus_transaction_send (transaction,
+                             connection,
+                             message))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_dispatch_matches (BusTransaction *transaction,
+                      DBusConnection *sender,
+                      DBusConnection *addressed_recipient,
+                      DBusMessage    *message,
+                      DBusError      *error)
+{
+  DBusError tmp_error;
+  BusConnections *connections;
+  DBusList *recipients;
+  BusMatchmaker *matchmaker;
+  DBusList *link;
+  BusContext *context;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  /* sender and recipient can both be NULL for the bus driver,
+   * or for signals with no particular recipient
+   */
+
+  _dbus_assert (sender == NULL || bus_connection_is_active (sender));
+  _dbus_assert (dbus_message_get_sender (message) != NULL);
+
+  context = bus_transaction_get_context (transaction);
+
+  /* First, send the message to the addressed_recipient, if there is one. */
+  if (addressed_recipient != NULL)
+    {
+      if (!bus_context_check_security_policy (context, transaction,
+                                              sender, addressed_recipient,
+                                              addressed_recipient,
+                                              message, error))
+        return FALSE;
+
+      if (dbus_message_contains_unix_fds (message) &&
+          !dbus_connection_can_send_type (addressed_recipient,
+                                          DBUS_TYPE_UNIX_FD))
+        {
+          dbus_set_error (error,
+                          DBUS_ERROR_NOT_SUPPORTED,
+                          "Tried to send message with Unix file descriptors"
+                          "to a client that doesn't support that.");
+          return FALSE;
+      }
+
+      /* Dispatch the message */
+      if (!bus_transaction_send (transaction, addressed_recipient, message))
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+    }
+
+  /* Now dispatch to others who look interested in this message */
+  connections = bus_transaction_get_connections (transaction);
+  dbus_error_init (&tmp_error);
+  matchmaker = bus_context_get_matchmaker (context);
+
+  recipients = NULL;
+  if (!bus_matchmaker_get_recipients (matchmaker, connections,
+                                      sender, addressed_recipient, message,
+                                      &recipients))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  link = _dbus_list_get_first_link (&recipients);
+  while (link != NULL)
+    {
+      DBusConnection *dest;
+
+      dest = link->data;
+
+      if (!send_one_message (dest, context, sender, addressed_recipient,
+                             message, transaction, &tmp_error))
+        break;
+
+      link = _dbus_list_get_next_link (&recipients, link);
+    }
+
+  _dbus_list_clear (&recipients);
+
+  if (dbus_error_is_set (&tmp_error))
+    {
+      dbus_move_error (&tmp_error, error);
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
+static DBusHandlerResult
+bus_dispatch (DBusConnection *connection,
+              DBusMessage    *message)
+{
+  const char *sender, *service_name;
+  DBusError error;
+  BusTransaction *transaction;
+  BusContext *context;
+  DBusHandlerResult result;
+  DBusConnection *addressed_recipient;
+
+  result = DBUS_HANDLER_RESULT_HANDLED;
+
+  transaction = NULL;
+  addressed_recipient = NULL;
+  dbus_error_init (&error);
+
+  context = bus_connection_get_context (connection);
+  _dbus_assert (context != NULL);
+
+  /* If we can't even allocate an OOM error, we just go to sleep
+   * until we can.
+   */
+  while (!bus_connection_preallocate_oom_error (connection))
+    _dbus_wait_for_memory ();
+
+  /* Ref connection in case we disconnect it at some point in here */
+  dbus_connection_ref (connection);
+
+  service_name = dbus_message_get_destination (message);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  {
+    const char *interface_name, *member_name, *error_name;
+
+    interface_name = dbus_message_get_interface (message);
+    member_name = dbus_message_get_member (message);
+    error_name = dbus_message_get_error_name (message);
+
+    _dbus_verbose ("DISPATCH: %s %s %s to %s\n",
+                   interface_name ? interface_name : "(no interface)",
+                   member_name ? member_name : "(no member)",
+                   error_name ? error_name : "(no error name)",
+                   service_name ? service_name : "peer");
+  }
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+
+  /* If service_name is NULL, if it's a signal we send it to all
+   * connections with a match rule. If it's not a signal, there
+   * are some special cases here but mostly we just bail out.
+   */
+  if (service_name == NULL)
+    {
+      if (dbus_message_is_signal (message,
+                                  DBUS_INTERFACE_LOCAL,
+                                  "Disconnected"))
+        {
+          bus_connection_disconnected (connection);
+          goto out;
+        }
+
+      if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
+        {
+          /* DBusConnection also handles some of these automatically, we leave
+           * it to do so.
+           */
+          result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+          goto out;
+        }
+    }
+
+  /* Create our transaction */
+  transaction = bus_transaction_new (context);
+  if (transaction == NULL)
+    {
+      BUS_SET_OOM (&error);
+      goto out;
+    }
+
+  /* Assign a sender to the message */
+  if (bus_connection_is_active (connection))
+    {
+      sender = bus_connection_get_name (connection);
+      _dbus_assert (sender != NULL);
+
+      if (!dbus_message_set_sender (message, sender))
+        {
+          BUS_SET_OOM (&error);
+          goto out;
+        }
+
+      /* We need to refetch the service name here, because
+       * dbus_message_set_sender can cause the header to be
+       * reallocated, and thus the service_name pointer will become
+       * invalid.
+       */
+      service_name = dbus_message_get_destination (message);
+    }
+
+  if (service_name &&
+      strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
+    {
+      if (!bus_context_check_security_policy (context, transaction,
+                                              connection, NULL, NULL, message, &error))
+        {
+          _dbus_verbose ("Security policy rejected message\n");
+          goto out;
+        }
+
+      _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
+      if (!bus_driver_handle_message (connection, transaction, message, &error))
+        goto out;
+    }
+  else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
+    {
+      _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
+      dbus_connection_close (connection);
+      goto out;
+    }
+  else if (service_name != NULL) /* route to named service */
+    {
+      DBusString service_string;
+      BusService *service;
+      BusRegistry *registry;
+
+      _dbus_assert (service_name != NULL);
+
+      registry = bus_connection_get_registry (connection);
+
+      _dbus_string_init_const (&service_string, service_name);
+      service = bus_registry_lookup (registry, &service_string);
+
+      if (service == NULL && dbus_message_get_auto_start (message))
+        {
+          BusActivation *activation;
+          /* We can't do the security policy check here, since the addressed
+           * recipient service doesn't exist yet. We do it before sending the
+           * message after the service has been created.
+           */
+          activation = bus_connection_get_activation (connection);
+
+          if (!bus_activation_activate_service (activation, connection, transaction, TRUE,
+                                                message, service_name, &error))
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (&error);
+              _dbus_verbose ("bus_activation_activate_service() failed: %s\n", error.name);
+              goto out;
+            }
+
+          goto out;
+        }
+      else if (service == NULL)
+        {
+          dbus_set_error (&error,
+                          DBUS_ERROR_NAME_HAS_NO_OWNER,
+                          "Name \"%s\" does not exist",
+                          service_name);
+          goto out;
+        }
+      else
+        {
+          addressed_recipient = bus_service_get_primary_owners_connection (service);
+          _dbus_assert (addressed_recipient != NULL);
+        }
+    }
+
+  /* Now send the message to its destination (or not, if
+   * addressed_recipient == NULL), and match it against other connections'
+   * match rules.
+   */
+  if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error))
+    goto out;
+
+ out:
+  if (dbus_error_is_set (&error))
+    {
+      if (!dbus_connection_get_is_connected (connection))
+        {
+          /* If we disconnected it, we won't bother to send it any error
+           * messages.
+           */
+          _dbus_verbose ("Not sending error to connection we disconnected\n");
+        }
+      else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+        {
+          bus_connection_send_oom_error (connection, message);
+
+          /* cancel transaction due to OOM */
+          if (transaction != NULL)
+            {
+              bus_transaction_cancel_and_free (transaction);
+              transaction = NULL;
+            }
+        }
+      else
+        {
+          /* Try to send the real error, if no mem to do that, send
+           * the OOM error
+           */
+          _dbus_assert (transaction != NULL);
+          if (!bus_transaction_send_error_reply (transaction, connection,
+                                                 &error, message))
+            {
+              bus_connection_send_oom_error (connection, message);
+
+              /* cancel transaction due to OOM */
+              if (transaction != NULL)
+                {
+                  bus_transaction_cancel_and_free (transaction);
+                  transaction = NULL;
+                }
+            }
+        }
+
+
+      dbus_error_free (&error);
+    }
+
+  if (transaction != NULL)
+    {
+      bus_transaction_execute_and_free (transaction);
+    }
+
+  dbus_connection_unref (connection);
+
+  return result;
+}
+
+static DBusHandlerResult
+bus_dispatch_message_filter (DBusConnection     *connection,
+                             DBusMessage        *message,
+                             void               *user_data)
+{
+  return bus_dispatch (connection, message);
+}
+
+dbus_bool_t
+bus_dispatch_add_connection (DBusConnection *connection)
+{
+  if (!dbus_connection_add_filter (connection,
+                                   bus_dispatch_message_filter,
+                                   NULL, NULL))
+    return FALSE;
+
+  return TRUE;
+}
+
+void
+bus_dispatch_remove_connection (DBusConnection *connection)
+{
+  /* Here we tell the bus driver that we want to get off. */
+  bus_driver_remove_connection (connection);
+
+  dbus_connection_remove_filter (connection,
+                                 bus_dispatch_message_filter,
+                                 NULL);
+}
+
+#ifdef DBUS_BUILD_TESTS
+
+#include <stdio.h>
+
+/* This is used to know whether we need to block in order to finish
+ * sending a message, or whether the initial dbus_connection_send()
+ * already flushed the queue.
+ */
+#define SEND_PENDING(connection) (dbus_connection_has_messages_to_send (connection))
+
+typedef dbus_bool_t (* Check1Func) (BusContext     *context);
+typedef dbus_bool_t (* Check2Func) (BusContext     *context,
+                                    DBusConnection *connection);
+
+static dbus_bool_t check_no_leftovers (BusContext *context);
+
+static void
+block_connection_until_message_from_bus (BusContext     *context,
+                                         DBusConnection *connection,
+                                         const char     *what_is_expected)
+{
+  _dbus_verbose ("expecting: %s\n", what_is_expected);
+
+  while (dbus_connection_get_dispatch_status (connection) ==
+         DBUS_DISPATCH_COMPLETE &&
+         dbus_connection_get_is_connected (connection))
+    {
+      bus_test_run_bus_loop (context, TRUE);
+      bus_test_run_clients_loop (FALSE);
+    }
+}
+
+static void
+spin_connection_until_authenticated (BusContext     *context,
+                                     DBusConnection *connection)
+{
+  _dbus_verbose ("Spinning to auth connection %p\n", connection);
+  while (!dbus_connection_get_is_authenticated (connection) &&
+         dbus_connection_get_is_connected (connection))
+    {
+      bus_test_run_bus_loop (context, FALSE);
+      bus_test_run_clients_loop (FALSE);
+    }
+  _dbus_verbose (" ... done spinning to auth connection %p\n", connection);
+}
+
+/* compensate for fact that pop_message() can return #NULL due to OOM */
+static DBusMessage*
+pop_message_waiting_for_memory (DBusConnection *connection)
+{
+  while (dbus_connection_get_dispatch_status (connection) ==
+         DBUS_DISPATCH_NEED_MEMORY)
+    _dbus_wait_for_memory ();
+
+  return dbus_connection_pop_message (connection);
+}
+
+static DBusMessage*
+borrow_message_waiting_for_memory (DBusConnection *connection)
+{
+  while (dbus_connection_get_dispatch_status (connection) ==
+         DBUS_DISPATCH_NEED_MEMORY)
+    _dbus_wait_for_memory ();
+
+  return dbus_connection_borrow_message (connection);
+}
+
+static void
+warn_unexpected_real (DBusConnection *connection,
+                      DBusMessage    *message,
+                      const char     *expected,
+                      const char     *function,
+                      int             line)
+{
+  if (message)
+    _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s\n",
+                function, line,
+                dbus_message_get_interface (message) ?
+                dbus_message_get_interface (message) : "(unset)",
+                dbus_message_get_member (message) ?
+                dbus_message_get_member (message) : "(unset)",
+                dbus_message_get_error_name (message) ?
+                dbus_message_get_error_name (message) : "(unset)",
+                connection,
+                expected);
+  else
+    _dbus_warn ("%s:%d received no message on %p, expecting %s\n",
+                function, line, connection, expected);
+}
+
+#define warn_unexpected(connection, message, expected) \
+  warn_unexpected_real (connection, message, expected, _DBUS_FUNCTION_NAME, __LINE__)
+
+static void
+verbose_message_received (DBusConnection *connection,
+                          DBusMessage    *message)
+{
+  _dbus_verbose ("Received message interface \"%s\" member \"%s\" error name \"%s\" on %p\n",
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) : "(unset)",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) : "(unset)",
+                 dbus_message_get_error_name (message) ?
+                 dbus_message_get_error_name (message) : "(unset)",
+                 connection);
+}
+
+typedef enum
+{
+  SERVICE_CREATED,
+  OWNER_CHANGED,
+  SERVICE_DELETED
+} ServiceInfoKind;
+
+typedef struct
+{
+  ServiceInfoKind expected_kind;
+  const char *expected_service_name;
+  dbus_bool_t failed;
+  DBusConnection *skip_connection;
+} CheckServiceOwnerChangedData;
+
+static dbus_bool_t
+check_service_owner_changed_foreach (DBusConnection *connection,
+                                     void           *data)
+{
+  CheckServiceOwnerChangedData *d = data;
+  DBusMessage *message;
+  DBusError error;
+  const char *service_name, *old_owner, *new_owner;
+
+  if (d->expected_kind == SERVICE_CREATED
+      && connection == d->skip_connection)
+    return TRUE;
+
+  dbus_error_init (&error);
+  d->failed = TRUE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a message on %p, expecting %s\n",
+                  connection, "NameOwnerChanged");
+      goto out;
+    }
+  else if (!dbus_message_is_signal (message,
+                                    DBUS_INTERFACE_DBUS,
+                                    "NameOwnerChanged"))
+    {
+      warn_unexpected (connection, message, "NameOwnerChanged");
+
+      goto out;
+    }
+  else
+    {
+    reget_service_info_data:
+      service_name = NULL;
+      old_owner = NULL;
+      new_owner = NULL;
+
+      dbus_message_get_args (message, &error,
+                             DBUS_TYPE_STRING, &service_name,
+                             DBUS_TYPE_STRING, &old_owner,
+                             DBUS_TYPE_STRING, &new_owner,
+                             DBUS_TYPE_INVALID);
+
+      if (dbus_error_is_set (&error))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_error_free (&error);
+              _dbus_wait_for_memory ();
+              goto reget_service_info_data;
+            }
+          else
+            {
+              _dbus_warn ("Did not get the expected arguments\n");
+              goto out;
+            }
+        }
+
+      if ((d->expected_kind == SERVICE_CREATED    && ( old_owner[0] || !new_owner[0]))
+          || (d->expected_kind == OWNER_CHANGED   && (!old_owner[0] || !new_owner[0]))
+          || (d->expected_kind == SERVICE_DELETED && (!old_owner[0] ||  new_owner[0])))
+        {
+          _dbus_warn ("inconsistent NameOwnerChanged arguments\n");
+          goto out;
+        }
+
+      if (strcmp (service_name, d->expected_service_name) != 0)
+        {
+          _dbus_warn ("expected info on service %s, got info on %s\n",
+                      d->expected_service_name,
+                      service_name);
+          goto out;
+        }
+
+      if (*service_name == ':' && new_owner[0]
+          && strcmp (service_name, new_owner) != 0)
+        {
+          _dbus_warn ("inconsistent ServiceOwnedChanged message (\"%s\" [ %s -> %s ])\n",
+                      service_name, old_owner, new_owner);
+          goto out;
+        }
+    }
+
+  d->failed = FALSE;
+
+ out:
+  dbus_error_free (&error);
+
+  if (message)
+    dbus_message_unref (message);
+
+  return !d->failed;
+}
+
+
+static void
+kill_client_connection (BusContext     *context,
+                        DBusConnection *connection)
+{
+  char *base_service;
+  const char *s;
+  CheckServiceOwnerChangedData socd;
+
+  _dbus_verbose ("killing connection %p\n", connection);
+
+  s = dbus_bus_get_unique_name (connection);
+  _dbus_assert (s != NULL);
+
+  while ((base_service = _dbus_strdup (s)) == NULL)
+    _dbus_wait_for_memory ();
+
+  dbus_connection_ref (connection);
+
+  /* kick in the disconnect handler that unrefs the connection */
+  dbus_connection_close (connection);
+
+  bus_test_run_everything (context);
+
+  _dbus_assert (bus_test_client_listed (connection));
+
+  /* Run disconnect handler in test.c */
+  if (bus_connection_dispatch_one_message (connection))
+    _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
+
+  _dbus_assert (!dbus_connection_get_is_connected (connection));
+  dbus_connection_unref (connection);
+  connection = NULL;
+  _dbus_assert (!bus_test_client_listed (connection));
+
+  socd.expected_kind = SERVICE_DELETED;
+  socd.expected_service_name = base_service;
+  socd.failed = FALSE;
+  socd.skip_connection = NULL;
+
+  bus_test_clients_foreach (check_service_owner_changed_foreach,
+                            &socd);
+
+  dbus_free (base_service);
+
+  if (socd.failed)
+    _dbus_assert_not_reached ("didn't get the expected NameOwnerChanged (deletion) messages");
+
+  if (!check_no_leftovers (context))
+    _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
+}
+
+static void
+kill_client_connection_unchecked (DBusConnection *connection)
+{
+  /* This kills the connection without expecting it to affect
+   * the rest of the bus.
+   */
+  _dbus_verbose ("Unchecked kill of connection %p\n", connection);
+
+  dbus_connection_ref (connection);
+  dbus_connection_close (connection);
+  /* dispatching disconnect handler will unref once */
+  if (bus_connection_dispatch_one_message (connection))
+    _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
+
+  _dbus_assert (!bus_test_client_listed (connection));
+  dbus_connection_unref (connection);
+}
+
+typedef struct
+{
+  dbus_bool_t failed;
+} CheckNoMessagesData;
+
+static dbus_bool_t
+check_no_messages_foreach (DBusConnection *connection,
+                           void           *data)
+{
+  CheckNoMessagesData *d = data;
+  DBusMessage *message;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message != NULL)
+    {
+      warn_unexpected (connection, message, "no messages");
+
+      d->failed = TRUE;
+    }
+
+  if (message)
+    dbus_message_unref (message);
+  return !d->failed;
+}
+
+static dbus_bool_t
+check_no_leftovers (BusContext *context)
+{
+  CheckNoMessagesData nmd;
+
+  nmd.failed = FALSE;
+  bus_test_clients_foreach (check_no_messages_foreach,
+                            &nmd);
+
+  if (nmd.failed)
+    {
+      _dbus_verbose ("leftover message found\n");
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_hello_message (BusContext     *context,
+                     DBusConnection *connection)
+{
+  DBusMessage *message;
+  DBusMessage *name_message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  DBusError error;
+  const char *name;
+  const char *acquired;
+
+  retval = FALSE;
+  dbus_error_init (&error);
+  name = NULL;
+  acquired = NULL;
+  message = NULL;
+  name_message = NULL;
+
+  _dbus_verbose ("check_hello_message for %p\n", connection);
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "Hello");
+
+  if (message == NULL)
+    return TRUE;
+
+  dbus_connection_ref (connection); /* because we may get disconnected */
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      dbus_connection_unref (connection);
+      return TRUE;
+    }
+
+  _dbus_assert (dbus_message_has_signature (message, ""));
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
+
+      dbus_connection_unref (connection);
+
+      return TRUE;
+    }
+
+  /* send our message */
+  bus_test_run_clients_loop (SEND_PENDING (connection));
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
+
+      dbus_connection_unref (connection);
+
+      return TRUE;
+    }
+
+  block_connection_until_message_from_bus (context, connection, "reply to Hello");
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
+
+      dbus_connection_unref (connection);
+
+      return TRUE;
+    }
+
+  dbus_connection_unref (connection);
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "Hello", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+    {
+      _dbus_warn ("Message has wrong sender %s\n",
+                  dbus_message_get_sender (message) ?
+                  dbus_message_get_sender (message) : "(none)");
+      goto out;
+    }
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      CheckServiceOwnerChangedData socd;
+
+      if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+        {
+          ; /* good, expected */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "method return for Hello");
+
+          goto out;
+        }
+
+    retry_get_hello_name:
+      if (!dbus_message_get_args (message, &error,
+                                  DBUS_TYPE_STRING, &name,
+                                  DBUS_TYPE_INVALID))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              _dbus_verbose ("no memory to get service name arg from hello\n");
+              dbus_error_free (&error);
+              _dbus_wait_for_memory ();
+              goto retry_get_hello_name;
+            }
+          else
+            {
+              _dbus_assert (dbus_error_is_set (&error));
+              _dbus_warn ("Did not get the expected single string argument to hello\n");
+              goto out;
+            }
+        }
+
+      _dbus_verbose ("Got hello name: %s\n", name);
+
+      while (!dbus_bus_set_unique_name (connection, name))
+        _dbus_wait_for_memory ();
+
+      socd.expected_kind = SERVICE_CREATED;
+      socd.expected_service_name = name;
+      socd.failed = FALSE;
+      socd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                &socd);
+
+      if (socd.failed)
+        goto out;
+
+      name_message = message;
+      /* Client should also have gotten ServiceAcquired */
+
+      message = pop_message_waiting_for_memory (connection);
+      if (message == NULL)
+        {
+          _dbus_warn ("Expecting %s, got nothing\n",
+                      "NameAcquired");
+          goto out;
+        }
+      if (! dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+                                    "NameAcquired"))
+        {
+          _dbus_warn ("Expecting %s, got smthg else\n",
+                      "NameAcquired");
+          goto out;
+        }
+
+    retry_get_acquired_name:
+      if (!dbus_message_get_args (message, &error,
+                                  DBUS_TYPE_STRING, &acquired,
+                                  DBUS_TYPE_INVALID))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              _dbus_verbose ("no memory to get service name arg from acquired\n");
+              dbus_error_free (&error);
+              _dbus_wait_for_memory ();
+              goto retry_get_acquired_name;
+            }
+          else
+            {
+              _dbus_assert (dbus_error_is_set (&error));
+              _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
+              goto out;
+            }
+        }
+
+      _dbus_verbose ("Got acquired name: %s\n", acquired);
+
+      if (strcmp (acquired, name) != 0)
+        {
+          _dbus_warn ("Acquired name is %s but expected %s\n",
+                      acquired, name);
+          goto out;
+        }
+      acquired = NULL;
+    }
+
+  if (!check_no_leftovers (context))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  _dbus_verbose ("ending - retval = %d\n", retval);
+
+  dbus_error_free (&error);
+
+  if (message)
+    dbus_message_unref (message);
+
+  if (name_message)
+    dbus_message_unref (name_message);
+
+  return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_double_hello_message (BusContext     *context,
+                            DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  DBusError error;
+
+  retval = FALSE;
+  dbus_error_init (&error);
+  message = NULL;
+
+  _dbus_verbose ("check_double_hello_message for %p\n", connection);
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "Hello");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  /* send our message */
+  bus_test_run_clients_loop (SEND_PENDING (connection));
+
+  dbus_connection_ref (connection); /* because we may get disconnected */
+  block_connection_until_message_from_bus (context, connection, "reply to Hello");
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+
+      dbus_connection_unref (connection);
+
+      return TRUE;
+    }
+
+  dbus_connection_unref (connection);
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "Hello", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+    {
+      _dbus_warn ("Message has wrong sender %s\n",
+                  dbus_message_get_sender (message) ?
+                  dbus_message_get_sender (message) : "(none)");
+      goto out;
+    }
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
+    {
+      warn_unexpected (connection, message, "method return for Hello");
+      goto out;
+    }
+
+  if (!check_no_leftovers (context))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  dbus_error_free (&error);
+
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_get_connection_unix_user (BusContext     *context,
+                                DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  DBusError error;
+  const char *base_service_name;
+  dbus_uint32_t uid;
+
+  retval = FALSE;
+  dbus_error_init (&error);
+  message = NULL;
+
+  _dbus_verbose ("check_get_connection_unix_user for %p\n", connection);
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "GetConnectionUnixUser");
+
+  if (message == NULL)
+    return TRUE;
+
+  base_service_name = dbus_bus_get_unique_name (connection);
+
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &base_service_name,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  /* send our message */
+  bus_test_run_clients_loop (SEND_PENDING (connection));
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  dbus_connection_ref (connection); /* because we may get disconnected */
+  block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixUser");
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+
+      dbus_connection_unref (connection);
+
+      return TRUE;
+    }
+
+  dbus_connection_unref (connection);
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "GetConnectionUnixUser", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+        {
+          ; /* good, expected */
+        }
+      else
+        {
+          warn_unexpected (connection, message,
+                           "method_return for GetConnectionUnixUser");
+
+          goto out;
+        }
+
+    retry_get_property:
+
+      if (!dbus_message_get_args (message, &error,
+                                  DBUS_TYPE_UINT32, &uid,
+                                  DBUS_TYPE_INVALID))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              _dbus_verbose ("no memory to get uid by GetConnectionUnixUser\n");
+              dbus_error_free (&error);
+              _dbus_wait_for_memory ();
+              goto retry_get_property;
+            }
+          else
+            {
+              _dbus_assert (dbus_error_is_set (&error));
+              _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixUser\n");
+              goto out;
+            }
+        }
+    }
+
+  if (!check_no_leftovers (context))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  dbus_error_free (&error);
+
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_get_connection_unix_process_id (BusContext     *context,
+                                      DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  DBusError error;
+  const char *base_service_name;
+  dbus_uint32_t pid;
+
+  retval = FALSE;
+  dbus_error_init (&error);
+  message = NULL;
+
+  _dbus_verbose ("check_get_connection_unix_process_id for %p\n", connection);
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "GetConnectionUnixProcessID");
+
+  if (message == NULL)
+    return TRUE;
+
+  base_service_name = dbus_bus_get_unique_name (connection);
+
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &base_service_name,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  /* send our message */
+  bus_test_run_clients_loop (SEND_PENDING (connection));
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  dbus_connection_ref (connection); /* because we may get disconnected */
+  block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixProcessID");
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+
+      dbus_connection_unref (connection);
+
+      return TRUE;
+    }
+
+  dbus_connection_unref (connection);
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "GetConnectionUnixProcessID", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+#ifdef DBUS_WIN
+      else if (dbus_message_is_error (message, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN))
+        {
+          /* We are expecting this error, since we know in the test suite we aren't
+           * talking to a client running on UNIX
+           */
+          _dbus_verbose ("Windows correctly does not support GetConnectionUnixProcessID\n");
+        }
+#endif
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+#ifdef DBUS_WIN
+      warn_unexpected (connection, message, "GetConnectionUnixProcessID to fail on Windows");
+      goto out;
+#else
+      if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+        {
+          ; /* good, expected */
+        }
+      else
+        {
+          warn_unexpected (connection, message,
+                           "method_return for GetConnectionUnixProcessID");
+
+          goto out;
+        }
+
+    retry_get_property:
+
+      if (!dbus_message_get_args (message, &error,
+                                  DBUS_TYPE_UINT32, &pid,
+                                  DBUS_TYPE_INVALID))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              _dbus_verbose ("no memory to get pid by GetConnectionUnixProcessID\n");
+              dbus_error_free (&error);
+              _dbus_wait_for_memory ();
+              goto retry_get_property;
+            }
+          else
+            {
+              _dbus_assert (dbus_error_is_set (&error));
+              _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID\n");
+              goto out;
+            }
+        }
+      else
+        {
+          /* test if returned pid is the same as our own pid
+           *
+           * @todo It would probably be good to restructure the tests
+           *       in a way so our parent is the bus that we're testing
+           *       cause then we can test that the pid returned matches
+           *       getppid()
+           */
+          if (pid != (dbus_uint32_t) _dbus_getpid ())
+            {
+              _dbus_assert (dbus_error_is_set (&error));
+              _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid\n");
+              goto out;
+            }
+        }
+#endif /* !DBUS_WIN */
+    }
+
+  if (!check_no_leftovers (context))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  dbus_error_free (&error);
+
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_add_match_all (BusContext     *context,
+                     DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
+  dbus_uint32_t serial;
+  DBusError error;
+  const char *empty = "";
+
+  retval = FALSE;
+  dbus_error_init (&error);
+  message = NULL;
+
+  _dbus_verbose ("check_add_match_all for %p\n", connection);
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "AddMatch");
+
+  if (message == NULL)
+    return TRUE;
+
+  /* empty string match rule matches everything */
+  if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &empty,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  dbus_connection_ref (connection); /* because we may get disconnected */
+
+  /* send our message */
+  bus_test_run_clients_loop (SEND_PENDING (connection));
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+
+      dbus_connection_unref (connection);
+
+      return TRUE;
+    }
+
+  block_connection_until_message_from_bus (context, connection, "reply to AddMatch");
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+
+      dbus_connection_unref (connection);
+
+      return TRUE;
+    }
+
+  dbus_connection_unref (connection);
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "AddMatch", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+    {
+      _dbus_warn ("Message has wrong sender %s\n",
+                  dbus_message_get_sender (message) ?
+                  dbus_message_get_sender (message) : "(none)");
+      goto out;
+    }
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+        {
+          ; /* good, expected */
+          _dbus_assert (dbus_message_get_reply_serial (message) == serial);
+        }
+      else
+        {
+          warn_unexpected (connection, message, "method return for AddMatch");
+
+          goto out;
+        }
+    }
+
+  if (!check_no_leftovers (context))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  dbus_error_free (&error);
+
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_hello_connection (BusContext *context)
+{
+  DBusConnection *connection;
+  DBusError error;
+
+  dbus_error_init (&error);
+
+  connection = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
+  if (connection == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&error);
+      dbus_error_free (&error);
+      return TRUE;
+    }
+
+  if (!bus_setup_debug_client (connection))
+    {
+      dbus_connection_close (connection);
+      dbus_connection_unref (connection);
+      return TRUE;
+    }
+
+  spin_connection_until_authenticated (context, connection);
+
+  if (!check_hello_message (context, connection))
+    return FALSE;
+
+  if (dbus_bus_get_unique_name (connection) == NULL)
+    {
+      /* We didn't successfully register, so we can't
+       * do the usual kill_client_connection() checks
+       */
+      kill_client_connection_unchecked (connection);
+    }
+  else
+    {
+      if (!check_add_match_all (context, connection))
+        return FALSE;
+
+      kill_client_connection (context, connection);
+    }
+
+  return TRUE;
+}
+
+#define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_nonexistent_service_no_auto_start (BusContext     *context,
+                                         DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  const char *nonexistent = NONEXISTENT_SERVICE_NAME;
+  dbus_uint32_t flags;
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "StartServiceByName");
+
+  if (message == NULL)
+    return TRUE;
+
+  dbus_message_set_auto_start (message, FALSE);
+
+  flags = 0;
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &nonexistent,
+                                 DBUS_TYPE_UINT32, &flags,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+  block_connection_until_message_from_bus (context, connection, "reply to ActivateService on nonexistent");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "StartServiceByName", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+        {
+          _dbus_warn ("Message has wrong sender %s\n",
+                      dbus_message_get_sender (message) ?
+                      dbus_message_get_sender (message) : "(none)");
+          goto out;
+        }
+
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SERVICE_UNKNOWN))
+        {
+          ; /* good, this is expected also */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+          goto out;
+        }
+    }
+  else
+    {
+      _dbus_warn ("Did not expect to successfully activate %s\n",
+                  NONEXISTENT_SERVICE_NAME);
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_nonexistent_service_auto_start (BusContext     *context,
+                                      DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+
+  message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Echo");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+  block_connection_until_message_from_bus (context, connection, "reply to Echo");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "Echo message (auto activation)", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+        {
+          _dbus_warn ("Message has wrong sender %s\n",
+                      dbus_message_get_sender (message) ?
+                      dbus_message_get_sender (message) : "(none)");
+          goto out;
+        }
+
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SERVICE_UNKNOWN))
+        {
+          ; /* good, this is expected also */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+          goto out;
+        }
+    }
+  else
+    {
+      _dbus_warn ("Did not expect to successfully activate %s\n",
+                  NONEXISTENT_SERVICE_NAME);
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+static dbus_bool_t
+check_base_service_activated (BusContext     *context,
+                              DBusConnection *connection,
+                              DBusMessage    *initial_message,
+                              const char    **base_service_p)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
+  DBusError error;
+  const char *base_service, *base_service_from_bus, *old_owner;
+
+  retval = FALSE;
+
+  dbus_error_init (&error);
+  base_service = NULL;
+  old_owner = NULL;
+  base_service_from_bus = NULL;
+
+  message = initial_message;
+  dbus_message_ref (message);
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_DBUS,
+                              "NameOwnerChanged"))
+    {
+      CheckServiceOwnerChangedData socd;
+
+    reget_service_name_arg:
+      base_service = NULL;
+      old_owner = NULL;
+      base_service_from_bus = NULL;
+
+      if (!dbus_message_get_args (message, &error,
+                                  DBUS_TYPE_STRING, &base_service,
+                                  DBUS_TYPE_STRING, &old_owner,
+                                  DBUS_TYPE_STRING, &base_service_from_bus,
+                                  DBUS_TYPE_INVALID))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_error_free (&error);
+              _dbus_wait_for_memory ();
+              goto reget_service_name_arg;
+            }
+          else
+            {
+              _dbus_warn ("Message %s doesn't have a service name: %s\n",
+                          "NameOwnerChanged (creation)",
+                          error.message);
+              goto out;
+            }
+        }
+
+      if (*base_service != ':')
+        {
+          _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
+                      base_service);
+          goto out;
+        }
+
+      if (strcmp (base_service, base_service_from_bus) != 0)
+        {
+          _dbus_warn ("Expected base service activation, got \"%s\" instead with owner \"%s\"\n",
+                      base_service, base_service_from_bus);
+          goto out;
+        }
+
+      if (old_owner[0])
+        {
+          _dbus_warn ("Received an old_owner argument during base service activation, \"%s\"\n",
+                      old_owner);
+          goto out;
+        }
+
+      socd.expected_kind = SERVICE_CREATED;
+      socd.expected_service_name = base_service;
+      socd.failed = FALSE;
+      socd.skip_connection = connection;
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                &socd);
+
+      if (socd.failed)
+        goto out;
+    }
+  else
+    {
+      warn_unexpected (connection, message, "NameOwnerChanged (creation) for base service");
+
+      goto out;
+    }
+
+  if (base_service_p)
+    *base_service_p = base_service;
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+  dbus_error_free (&error);
+
+  return retval;
+}
+
+static dbus_bool_t
+check_service_activated (BusContext     *context,
+                         DBusConnection *connection,
+                         const char     *activated_name,
+                         const char     *base_service_name,
+                         DBusMessage    *initial_message)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
+  DBusError error;
+  dbus_uint32_t activation_result;
+
+  retval = FALSE;
+
+  dbus_error_init (&error);
+
+  message = initial_message;
+  dbus_message_ref (message);
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_DBUS,
+                              "NameOwnerChanged"))
+    {
+      CheckServiceOwnerChangedData socd;
+      const char *service_name, *base_service_from_bus, *old_owner;
+
+    reget_service_name_arg:
+      service_name = NULL;
+      old_owner = NULL;
+      base_service_from_bus = NULL;
+
+      if (!dbus_message_get_args (message, &error,
+                                  DBUS_TYPE_STRING, &service_name,
+                                   DBUS_TYPE_STRING, &old_owner,
+                                  DBUS_TYPE_STRING, &base_service_from_bus,
+                                  DBUS_TYPE_INVALID))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_error_free (&error);
+              _dbus_wait_for_memory ();
+              goto reget_service_name_arg;
+            }
+          else
+            {
+              _dbus_warn ("Message %s doesn't have a service name: %s\n",
+                          "NameOwnerChanged (creation)",
+                          error.message);
+              goto out;
+            }
+        }
+
+      if (strcmp (service_name, activated_name) != 0)
+        {
+          _dbus_warn ("Expected to see service %s created, saw %s instead\n",
+                      activated_name, service_name);
+          goto out;
+        }
+
+      if (strcmp (base_service_name, base_service_from_bus) != 0)
+        {
+          _dbus_warn ("NameOwnerChanged reports wrong base service: %s owner, expected %s instead\n",
+                      base_service_from_bus, base_service_name);
+          goto out;
+        }
+
+      if (old_owner[0])
+        {
+          _dbus_warn ("expected a %s, got a %s\n",
+                      "NameOwnerChanged (creation)",
+                      "NameOwnerChanged (change)");
+          goto out;
+        }
+
+      socd.expected_kind = SERVICE_CREATED;
+      socd.skip_connection = connection;
+      socd.failed = FALSE;
+      socd.expected_service_name = service_name;
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                &socd);
+
+      if (socd.failed)
+        goto out;
+
+      dbus_message_unref (message);
+      service_name = NULL;
+      old_owner = NULL;
+      base_service_from_bus = NULL;
+
+      message = pop_message_waiting_for_memory (connection);
+      if (message == NULL)
+        {
+          _dbus_warn ("Expected a reply to %s, got nothing\n",
+                      "StartServiceByName");
+          goto out;
+        }
+    }
+  else
+    {
+      warn_unexpected (connection, message, "NameOwnerChanged for the activated name");
+
+      goto out;
+    }
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+    {
+      warn_unexpected (connection, message, "reply to StartServiceByName");
+
+      goto out;
+    }
+
+  activation_result = 0;
+  if (!dbus_message_get_args (message, &error,
+                              DBUS_TYPE_UINT32, &activation_result,
+                              DBUS_TYPE_INVALID))
+    {
+      if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+        {
+          _dbus_warn ("Did not have activation result first argument to %s: %s\n",
+                      "StartServiceByName", error.message);
+          goto out;
+        }
+
+      dbus_error_free (&error);
+    }
+  else
+    {
+      if (activation_result == DBUS_START_REPLY_SUCCESS)
+        ; /* Good */
+      else if (activation_result == DBUS_START_REPLY_ALREADY_RUNNING)
+        ; /* Good also */
+      else
+        {
+          _dbus_warn ("Activation result was %u, no good.\n",
+                      activation_result);
+          goto out;
+        }
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  if (!check_no_leftovers (context))
+    {
+      _dbus_warn ("Messages were left over after verifying existent activation results\n");
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+  dbus_error_free (&error);
+
+  return retval;
+}
+
+static dbus_bool_t
+check_service_auto_activated (BusContext     *context,
+                              DBusConnection *connection,
+                              const char     *activated_name,
+                              const char     *base_service_name,
+                              DBusMessage    *initial_message)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
+  DBusError error;
+
+  retval = FALSE;
+
+  dbus_error_init (&error);
+
+  message = initial_message;
+  dbus_message_ref (message);
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_DBUS,
+                              "NameOwnerChanged"))
+    {
+      const char *service_name;
+      CheckServiceOwnerChangedData socd;
+
+    reget_service_name_arg:
+      if (!dbus_message_get_args (message, &error,
+                                  DBUS_TYPE_STRING, &service_name,
+                                  DBUS_TYPE_INVALID))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_error_free (&error);
+              _dbus_wait_for_memory ();
+              goto reget_service_name_arg;
+            }
+          else
+            {
+              _dbus_warn ("Message %s doesn't have a service name: %s\n",
+                          "NameOwnerChanged",
+                          error.message);
+              dbus_error_free (&error);
+              goto out;
+            }
+        }
+
+      if (strcmp (service_name, activated_name) != 0)
+        {
+          _dbus_warn ("Expected to see service %s created, saw %s instead\n",
+                      activated_name, service_name);
+          goto out;
+        }
+
+      socd.expected_kind = SERVICE_CREATED;
+      socd.expected_service_name = service_name;
+      socd.failed = FALSE;
+      socd.skip_connection = connection;
+      bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                &socd);
+
+      if (socd.failed)
+        goto out;
+
+      /* Note that this differs from regular activation in that we don't get a
+       * reply to ActivateService here.
+       */
+
+      dbus_message_unref (message);
+      message = NULL;
+      service_name = NULL;
+    }
+  else
+    {
+      warn_unexpected (connection, message, "NameOwnerChanged for the activated name");
+
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+static dbus_bool_t
+check_service_deactivated (BusContext     *context,
+                           DBusConnection *connection,
+                           const char     *activated_name,
+                           const char     *base_service)
+{
+  dbus_bool_t retval;
+  CheckServiceOwnerChangedData socd;
+
+  retval = FALSE;
+
+  /* Now we are expecting ServiceOwnerChanged (deletion) messages for the base
+   * service and the activated_name.  The base service
+   * notification is required to come last.
+   */
+  socd.expected_kind = SERVICE_DELETED;
+  socd.expected_service_name = activated_name;
+  socd.failed = FALSE;
+  socd.skip_connection = NULL;
+  bus_test_clients_foreach (check_service_owner_changed_foreach,
+                            &socd);
+
+  if (socd.failed)
+    goto out;
+
+  socd.expected_kind = SERVICE_DELETED;
+  socd.expected_service_name = base_service;
+  socd.failed = FALSE;
+  socd.skip_connection = NULL;
+  bus_test_clients_foreach (check_service_owner_changed_foreach,
+                            &socd);
+
+  if (socd.failed)
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  return retval;
+}
+
+static dbus_bool_t
+check_send_exit_to_service (BusContext     *context,
+                            DBusConnection *connection,
+                            const char     *service_name,
+                            const char     *base_service)
+{
+  dbus_bool_t got_error;
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+
+  _dbus_verbose ("Sending exit message to the test service\n");
+
+  retval = FALSE;
+
+  /* Kill off the test service by sending it a quit message */
+  message = dbus_message_new_method_call (service_name,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Exit");
+
+  if (message == NULL)
+    {
+      /* Do this again; we still need the service to exit... */
+      if (!check_send_exit_to_service (context, connection,
+                                       service_name, base_service))
+        goto out;
+
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+
+      /* Do this again; we still need the service to exit... */
+      if (!check_send_exit_to_service (context, connection,
+                                       service_name, base_service))
+        goto out;
+
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  /* send message */
+  bus_test_run_clients_loop (SEND_PENDING (connection));
+
+  /* read it in and write it out to test service */
+  bus_test_run_bus_loop (context, FALSE);
+
+  /* see if we got an error during message bus dispatching */
+  bus_test_run_clients_loop (FALSE);
+  message = borrow_message_waiting_for_memory (connection);
+  got_error = message != NULL && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
+  if (message)
+    {
+      dbus_connection_return_message (connection, message);
+      message = NULL;
+    }
+
+  if (!got_error)
+    {
+      /* If no error, wait for the test service to exit */
+      block_connection_until_message_from_bus (context, connection, "test service to exit");
+
+      bus_test_run_everything (context);
+    }
+
+  if (got_error)
+    {
+      message = pop_message_waiting_for_memory (connection);
+      _dbus_assert (message != NULL);
+
+      if (dbus_message_get_reply_serial (message) != serial)
+        {
+          warn_unexpected (connection, message,
+                           "error with the correct reply serial");
+          goto out;
+        }
+
+      if (!dbus_message_is_error (message,
+                                  DBUS_ERROR_NO_MEMORY))
+        {
+          warn_unexpected (connection, message,
+                           "a no memory error from asking test service to exit");
+          goto out;
+        }
+
+      _dbus_verbose ("Got error %s when asking test service to exit\n",
+                     dbus_message_get_error_name (message));
+
+      /* Do this again; we still need the service to exit... */
+      if (!check_send_exit_to_service (context, connection,
+                                       service_name, base_service))
+        goto out;
+    }
+  else
+    {
+      if (!check_service_deactivated (context, connection,
+                                      service_name, base_service))
+        goto out;
+
+      /* Should now have a NoReply error from the Exit() method
+       * call; it should have come after all the deactivation
+       * stuff.
+       */
+      message = pop_message_waiting_for_memory (connection);
+
+      if (message == NULL)
+        {
+          warn_unexpected (connection, NULL,
+                           "reply to Exit() method call");
+          goto out;
+        }
+      if (!dbus_message_is_error (message,
+                                  DBUS_ERROR_NO_REPLY))
+        {
+          warn_unexpected (connection, message,
+                           "NoReply error from Exit() method call");
+          goto out;
+        }
+
+      if (dbus_message_get_reply_serial (message) != serial)
+        {
+          warn_unexpected (connection, message,
+                           "error with the correct reply serial");
+          goto out;
+        }
+
+      _dbus_verbose ("Got error %s after test service exited\n",
+                     dbus_message_get_error_name (message));
+
+      if (!check_no_leftovers (context))
+        {
+          _dbus_warn ("Messages were left over after %s\n",
+                      _DBUS_FUNCTION_NAME);
+          goto out;
+        }
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+static dbus_bool_t
+check_got_error (BusContext     *context,
+                 DBusConnection *connection,
+                 const char     *first_error_name,
+                 ...)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
+  va_list ap;
+  dbus_bool_t error_found;
+  const char *error_name;
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not get an expected error\n");
+      goto out;
+    }
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
+    {
+      warn_unexpected (connection, message, "an error");
+
+      goto out;
+    }
+
+  error_found = FALSE;
+
+  va_start (ap, first_error_name);
+  error_name = first_error_name;
+  while (error_name != NULL)
+    {
+      if (dbus_message_is_error (message, error_name))
+        {
+          error_found = TRUE;
+          break;
+        }
+      error_name = va_arg (ap, char*);
+    }
+  va_end (ap);
+
+  if (!error_found)
+    {
+      _dbus_warn ("Expected error %s or other, got %s instead\n",
+                  first_error_name,
+                  dbus_message_get_error_name (message));
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+typedef enum
+{
+  GOT_SERVICE_CREATED,
+  GOT_SERVICE_DELETED,
+  GOT_ERROR,
+  GOT_SOMETHING_ELSE
+} GotServiceInfo;
+
+static GotServiceInfo
+check_got_service_info (DBusMessage *message)
+{
+  GotServiceInfo message_kind;
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_DBUS,
+                              "NameOwnerChanged"))
+    {
+      DBusError error;
+      const char *service_name, *old_owner, *new_owner;
+      dbus_error_init (&error);
+
+    reget_service_info_data:
+      service_name = NULL;
+      old_owner = NULL;
+      new_owner = NULL;
+
+      dbus_message_get_args (message, &error,
+                             DBUS_TYPE_STRING, &service_name,
+                             DBUS_TYPE_STRING, &old_owner,
+                             DBUS_TYPE_STRING, &new_owner,
+                             DBUS_TYPE_INVALID);
+      if (dbus_error_is_set (&error))
+        {
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_error_free (&error);
+              goto reget_service_info_data;
+            }
+          else
+            {
+              _dbus_warn ("unexpected arguments for NameOwnerChanged message\n");
+              message_kind = GOT_SOMETHING_ELSE;
+            }
+        }
+      else if (!old_owner[0])
+        message_kind = GOT_SERVICE_CREATED;
+      else if (!new_owner[0])
+        message_kind = GOT_SERVICE_DELETED;
+      else
+        message_kind = GOT_SOMETHING_ELSE;
+
+      dbus_error_free (&error);
+    }
+  else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    message_kind = GOT_ERROR;
+  else
+    message_kind = GOT_SOMETHING_ELSE;
+
+  return message_kind;
+}
+
+#define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_service_no_auto_start (BusContext     *context,
+                                      DBusConnection *connection)
+{
+  DBusMessage *message;
+  DBusMessage *base_service_message;
+  const char *base_service;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  const char *existent = EXISTENT_SERVICE_NAME;
+  dbus_uint32_t flags;
+
+  base_service_message = NULL;
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "StartServiceByName");
+
+  if (message == NULL)
+    return TRUE;
+
+  dbus_message_set_auto_start (message, FALSE);
+
+  flags = 0;
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &existent,
+                                 DBUS_TYPE_UINT32, &flags,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+
+  /* now wait for the message bus to hear back from the activated
+   * service.
+   */
+  block_connection_until_message_from_bus (context, connection, "activated service to connect");
+
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive any messages after %s %d on %p\n",
+                  "StartServiceByName", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+  _dbus_verbose ("  (after sending %s)\n", "StartServiceByName");
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+        {
+          _dbus_warn ("Message has wrong sender %s\n",
+                      dbus_message_get_sender (message) ?
+                      dbus_message_get_sender (message) : "(none)");
+          goto out;
+        }
+
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SPAWN_CHILD_EXITED) ||
+               dbus_message_is_error (message,
+                                      DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
+               dbus_message_is_error (message,
+                                      DBUS_ERROR_SPAWN_EXEC_FAILED))
+        {
+          ; /* good, this is expected also */
+        }
+      else
+        {
+          _dbus_warn ("Did not expect error %s\n",
+                      dbus_message_get_error_name (message));
+          goto out;
+        }
+    }
+  else
+    {
+      GotServiceInfo message_kind;
+
+      if (!check_base_service_activated (context, connection,
+                                         message, &base_service))
+        goto out;
+
+      base_service_message = message;
+      message = NULL;
+
+      /* We may need to block here for the test service to exit or finish up */
+      block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
+
+      message = dbus_connection_borrow_message (connection);
+      if (message == NULL)
+        {
+          _dbus_warn ("Did not receive any messages after base service creation notification\n");
+          goto out;
+        }
+
+      message_kind = check_got_service_info (message);
+
+      dbus_connection_return_message (connection, message);
+      message = NULL;
+
+      switch (message_kind)
+        {
+        case GOT_SOMETHING_ELSE:
+          _dbus_warn ("Unexpected message after ActivateService "
+                      "(should be an error or a service announcement");
+          goto out;
+
+        case GOT_ERROR:
+          if (!check_got_error (context, connection,
+                                DBUS_ERROR_SPAWN_CHILD_EXITED,
+                                DBUS_ERROR_NO_MEMORY,
+                                NULL))
+            goto out;
+          /* A service deleted should be coming along now after this error.
+           * We can also get the error *after* the service deleted.
+           */
+
+          /* fall through */
+
+        case GOT_SERVICE_DELETED:
+          {
+            /* The service started up and got a base address, but then
+             * failed to register under EXISTENT_SERVICE_NAME
+             */
+            CheckServiceOwnerChangedData socd;
+
+            socd.expected_kind = SERVICE_DELETED;
+            socd.expected_service_name = base_service;
+            socd.failed = FALSE;
+            socd.skip_connection = NULL;
+
+            bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                      &socd);
+
+            if (socd.failed)
+              goto out;
+
+            /* Now we should get an error about the service exiting
+             * if we didn't get it before.
+             */
+            if (message_kind != GOT_ERROR)
+              {
+                block_connection_until_message_from_bus (context, connection, "error about service exiting");
+
+                /* and process everything again */
+                bus_test_run_everything (context);
+
+                if (!check_got_error (context, connection,
+                                      DBUS_ERROR_SPAWN_CHILD_EXITED,
+				      DBUS_ERROR_NO_MEMORY,
+                                      NULL))
+                  goto out;
+              }
+            break;
+          }
+
+        case GOT_SERVICE_CREATED:
+          message = pop_message_waiting_for_memory (connection);
+          if (message == NULL)
+            {
+              _dbus_warn ("Failed to pop message we just put back! "
+                          "should have been a NameOwnerChanged (creation)\n");
+              goto out;
+            }
+
+          if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
+                                        base_service, message))
+            goto out;
+
+          dbus_message_unref (message);
+          message = NULL;
+
+          if (!check_no_leftovers (context))
+            {
+              _dbus_warn ("Messages were left over after successful activation\n");
+              goto out;
+            }
+
+	  if (!check_send_exit_to_service (context, connection,
+                                           EXISTENT_SERVICE_NAME, base_service))
+	    goto out;
+
+          break;
+        }
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  if (base_service_message)
+    dbus_message_unref (base_service_message);
+
+  return retval;
+}
+
+#ifndef DBUS_WIN_FIXME
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_segfault_service_no_auto_start (BusContext     *context,
+                                      DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  const char *segv_service;
+  dbus_uint32_t flags;
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "StartServiceByName");
+
+  if (message == NULL)
+    return TRUE;
+
+  dbus_message_set_auto_start (message, FALSE);
+
+  segv_service = "org.freedesktop.DBus.TestSuiteSegfaultService";
+  flags = 0;
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &segv_service,
+                                 DBUS_TYPE_UINT32, &flags,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+  block_connection_until_message_from_bus (context, connection, "reply to activating segfault service");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "StartServiceByName", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+        {
+          _dbus_warn ("Message has wrong sender %s\n",
+                      dbus_message_get_sender (message) ?
+                      dbus_message_get_sender (message) : "(none)");
+          goto out;
+        }
+
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_FAILED))
+        {
+          const char *servicehelper;
+          servicehelper = bus_context_get_servicehelper (context);
+          /* make sure this only happens with the launch helper */
+          _dbus_assert (servicehelper != NULL);
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SPAWN_CHILD_SIGNALED))
+        {
+          ; /* good, this is expected also */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      _dbus_warn ("Did not expect to successfully activate segfault service\n");
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_segfault_service_auto_start (BusContext     *context,
+                                   DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+
+  message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService",
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Echo");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+  block_connection_until_message_from_bus (context, connection, "reply to Echo on segfault service");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "Echo message (auto activation)", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+        {
+          _dbus_warn ("Message has wrong sender %s\n",
+                      dbus_message_get_sender (message) ?
+                      dbus_message_get_sender (message) : "(none)");
+          goto out;
+        }
+
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SPAWN_CHILD_SIGNALED))
+        {
+          ; /* good, this is expected also */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      _dbus_warn ("Did not expect to successfully activate segfault service\n");
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+#endif
+
+#define TEST_ECHO_MESSAGE "Test echo message"
+#define TEST_RUN_HELLO_FROM_SELF_MESSAGE "Test sending message to self"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_hello_from_self (BusContext     *context,
+                                DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  const char *text;
+
+  message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "RunHelloFromSelf");
+
+  if (message == NULL)
+    return TRUE;
+
+  text = TEST_RUN_HELLO_FROM_SELF_MESSAGE;
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &text,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+
+  /* Note: if this test is run in OOM mode, it will block when the bus
+   * doesn't send a reply due to OOM.
+   */
+  block_connection_until_message_from_bus (context, connection, "reply from running hello from self");
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Failed to pop message! Should have been reply from RunHelloFromSelf message\n");
+      return FALSE;
+    }
+
+  if (dbus_message_get_reply_serial (message) != serial)
+    {
+      _dbus_warn ("Wrong reply serial\n");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  return TRUE;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_ping (BusContext     *context,
+                     DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.DBus.Peer",
+                                          "Ping");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+
+  /* Note: if this test is run in OOM mode, it will block when the bus
+   * doesn't send a reply due to OOM.
+   */
+  block_connection_until_message_from_bus (context, connection, "reply from running Ping");
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Failed to pop message! Should have been reply from Ping message\n");
+      return FALSE;
+    }
+
+  if (dbus_message_get_reply_serial (message) != serial)
+    {
+      _dbus_warn ("Wrong reply serial\n");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+    {
+      _dbus_warn ("Unexpected message return during Ping\n");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  return TRUE;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_get_machine_id (BusContext     *context,
+                               DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  const char *machine_id;
+
+  message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.DBus.Peer",
+                                          "GetMachineId");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+
+  /* Note: if this test is run in OOM mode, it will block when the bus
+   * doesn't send a reply due to OOM.
+   */
+  block_connection_until_message_from_bus (context, connection, "reply from running GetMachineId");
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Failed to pop message! Should have been reply from GetMachineId message\n");
+      return FALSE;
+    }
+
+  if (dbus_message_get_reply_serial (message) != serial)
+    {
+      _dbus_warn ("Wrong reply serial\n");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+    {
+      _dbus_warn ("Unexpected message return during GetMachineId\n");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  machine_id = NULL;
+  if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &machine_id, DBUS_TYPE_INVALID))
+    {
+      _dbus_warn ("Did not get a machine ID in reply to GetMachineId\n");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  if (machine_id == NULL || strlen (machine_id) != 32)
+    {
+      _dbus_warn ("Machine id looks bogus: '%s'\n", machine_id ? machine_id : "null");
+      dbus_message_unref (message);
+      return FALSE;
+    }
+
+  /* We can't check that the machine id is correct because during make check it is
+   * just made up for each process separately
+   */
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  return TRUE;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_service_auto_start (BusContext     *context,
+                                   DBusConnection *connection)
+{
+  DBusMessage *message;
+  DBusMessage *base_service_message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  const char *base_service;
+  const char *text;
+
+  base_service_message = NULL;
+
+  message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Echo");
+
+  if (message == NULL)
+    return TRUE;
+
+  text = TEST_ECHO_MESSAGE;
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &text,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+
+  /* now wait for the message bus to hear back from the activated
+   * service.
+   */
+  block_connection_until_message_from_bus (context, connection, "reply to Echo on existent service");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive any messages after auto start %d on %p\n",
+                  serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+  _dbus_verbose ("  (after sending %s)\n", "auto start");
+
+  /* we should get zero or two ServiceOwnerChanged signals */
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
+    {
+      GotServiceInfo message_kind;
+
+      if (!check_base_service_activated (context, connection,
+                                         message, &base_service))
+        goto out;
+
+      base_service_message = message;
+      message = NULL;
+
+      /* We may need to block here for the test service to exit or finish up */
+      block_connection_until_message_from_bus (context, connection, "service to exit");
+
+      /* Should get a service creation notification for the activated
+       * service name, or a service deletion on the base service name
+       */
+      message = dbus_connection_borrow_message (connection);
+      if (message == NULL)
+        {
+          _dbus_warn ("No message after auto activation "
+                      "(should be a service announcement)\n");
+          dbus_connection_return_message (connection, message);
+          message = NULL;
+          goto out;
+        }
+
+      message_kind = check_got_service_info (message);
+
+      dbus_connection_return_message (connection, message);
+      message = NULL;
+
+      switch (message_kind)
+        {
+        case GOT_SERVICE_CREATED:
+          message = pop_message_waiting_for_memory (connection);
+          if (message == NULL)
+            {
+              _dbus_warn ("Failed to pop message we just put back! "
+                          "should have been a NameOwnerChanged (creation)\n");
+              goto out;
+            }
+
+          /* Check that ServiceOwnerChanged (creation) was correctly received */
+          if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME,
+                                             base_service, message))
+            goto out;
+
+          dbus_message_unref (message);
+          message = NULL;
+
+          break;
+
+        case GOT_SERVICE_DELETED:
+          {
+            /* The service started up and got a base address, but then
+             * failed to register under EXISTENT_SERVICE_NAME
+             */
+            CheckServiceOwnerChangedData socd;
+
+            socd.expected_kind = SERVICE_DELETED;
+            socd.expected_service_name = base_service;
+            socd.failed = FALSE;
+            socd.skip_connection = NULL;
+            bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                      &socd);
+
+            if (socd.failed)
+              goto out;
+
+            break;
+          }
+
+        case GOT_ERROR:
+        case GOT_SOMETHING_ELSE:
+          _dbus_warn ("Unexpected message after auto activation\n");
+          goto out;
+        }
+    }
+
+  /* OK, now we've dealt with ServiceOwnerChanged signals, now should
+   * come the method reply (or error) from the initial method call
+   */
+
+  /* Note: if this test is run in OOM mode, it will block when the bus
+   * doesn't send a reply due to OOM.
+   */
+  block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation");
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
+      goto out;
+    }
+
+  if (dbus_message_get_reply_serial (message) != serial)
+    {
+      _dbus_warn ("Wrong reply serial\n");
+      goto out;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  if (!check_existent_ping (context, connection))
+    goto out;
+
+  if (!check_existent_get_machine_id (context, connection))
+    goto out;
+
+  if (!check_existent_hello_from_self (context, connection))
+    goto out;
+
+  if (!check_send_exit_to_service (context, connection,
+                                   EXISTENT_SERVICE_NAME,
+                                   base_service))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  if (base_service_message)
+    dbus_message_unref (base_service_message);
+
+  return retval;
+}
+
+#define SERVICE_FILE_MISSING_NAME "org.freedesktop.DBus.TestSuiteEchoServiceDotServiceFileDoesNotExist"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_launch_service_file_missing (BusContext     *context,
+                                   DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+
+  message = dbus_message_new_method_call (SERVICE_FILE_MISSING_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Echo");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+  block_connection_until_message_from_bus (context, connection, "reply to service file missing should fail to auto-start");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "Echo message (auto activation)", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+        {
+          _dbus_warn ("Message has wrong sender %s\n",
+                      dbus_message_get_sender (message) ?
+                      dbus_message_get_sender (message) : "(none)");
+          goto out;
+        }
+
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SERVICE_UNKNOWN))
+        {
+          _dbus_verbose("got service unknown\n");
+          ; /* good, this is expected (only valid when using launch helper) */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+#define SERVICE_USER_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoUser"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_launch_service_user_missing (BusContext     *context,
+                                   DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+
+  message = dbus_message_new_method_call (SERVICE_USER_MISSING_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Echo");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+  block_connection_until_message_from_bus (context, connection,
+  					   "reply to service which should fail to auto-start (missing User)");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_warn ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "Echo message (auto activation)", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+        {
+          _dbus_warn ("Message has wrong sender %s\n",
+                      dbus_message_get_sender (message) ?
+                      dbus_message_get_sender (message) : "(none)");
+          goto out;
+        }
+
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SPAWN_FILE_INVALID))
+        {
+          _dbus_verbose("got service file invalid\n");
+          ; /* good, this is expected (only valid when using launch helper) */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+#define SERVICE_EXEC_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoExec"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_launch_service_exec_missing (BusContext     *context,
+                                   DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+
+  message = dbus_message_new_method_call (SERVICE_EXEC_MISSING_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Echo");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+  block_connection_until_message_from_bus (context, connection,
+  					   "reply to service which should fail to auto-start (missing Exec)");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_warn ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "Echo message (auto activation)", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+        {
+          _dbus_warn ("Message has wrong sender %s\n",
+                      dbus_message_get_sender (message) ?
+                      dbus_message_get_sender (message) : "(none)");
+          goto out;
+        }
+
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SERVICE_UNKNOWN))
+        {
+          _dbus_verbose("could not activate as invalid service file was not added\n");
+          ; /* good, this is expected as we shouldn't have been added to
+             * the activation list with a missing Exec key */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SPAWN_FILE_INVALID))
+        {
+          _dbus_verbose("got service file invalid\n");
+          ; /* good, this is allowed, and is the message passed back from the
+             * launch helper */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+#define SERVICE_SERVICE_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoService"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_launch_service_service_missing (BusContext     *context,
+                                      DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+
+  message = dbus_message_new_method_call (SERVICE_SERVICE_MISSING_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Echo");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+  block_connection_until_message_from_bus (context, connection,
+  					   "reply to service which should fail to auto-start (missing Service)");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_warn ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "Echo message (auto activation)", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+        {
+          _dbus_warn ("Message has wrong sender %s\n",
+                      dbus_message_get_sender (message) ?
+                      dbus_message_get_sender (message) : "(none)");
+          goto out;
+        }
+
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SERVICE_UNKNOWN))
+        {
+          _dbus_verbose("could not activate as invalid service file was not added\n");
+          ; /* good, this is expected as we shouldn't have been added to
+             * the activation list with a missing Exec key */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_SPAWN_FILE_INVALID))
+        {
+          _dbus_verbose("got service file invalid\n");
+          ; /* good, this is allowed, and is the message passed back from the
+             * launch helper */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      _dbus_warn ("Did not expect to successfully auto-start missing service\n");
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+#define SHELL_FAIL_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceFail"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_shell_fail_service_auto_start (BusContext     *context,
+                                     DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+
+  message = dbus_message_new_method_call (SHELL_FAIL_SERVICE_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Echo");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+  block_connection_until_message_from_bus (context, connection, "reply to shell Echo on service which should fail to auto-start");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "Echo message (auto activation)", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+        {
+          _dbus_warn ("Message has wrong sender %s\n",
+                      dbus_message_get_sender (message) ?
+                      dbus_message_get_sender (message) : "(none)");
+          goto out;
+        }
+
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else if (dbus_message_is_error (message,
+                                      DBUS_ERROR_INVALID_ARGS))
+        {
+          _dbus_verbose("got invalid args\n");
+          ; /* good, this is expected also */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      _dbus_warn ("Did not expect to successfully auto-start shell fail service\n");
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+#define SHELL_SUCCESS_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_shell_service_success_auto_start (BusContext     *context,
+                                        DBusConnection *connection)
+{
+  DBusMessage *message;
+  DBusMessage *base_service_message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  const char *base_service;
+  const char *argv[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+
+  base_service_message = NULL;
+
+  message = dbus_message_new_method_call (SHELL_SUCCESS_SERVICE_NAME,
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "Echo");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+
+  /* now wait for the message bus to hear back from the activated
+   * service.
+   */
+  block_connection_until_message_from_bus (context, connection, "reply to Echo on shell success service");
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive any messages after auto start %d on %p\n",
+                  serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+  _dbus_verbose ("  (after sending %s)\n", "auto start");
+
+  /* we should get zero or two ServiceOwnerChanged signals */
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
+    {
+      GotServiceInfo message_kind;
+
+      if (!check_base_service_activated (context, connection,
+                                         message, &base_service))
+        goto out;
+
+      base_service_message = message;
+      message = NULL;
+
+      /* We may need to block here for the test service to exit or finish up */
+      block_connection_until_message_from_bus (context, connection, "service to exit");
+
+      /* Should get a service creation notification for the activated
+       * service name, or a service deletion on the base service name
+       */
+      message = dbus_connection_borrow_message (connection);
+      if (message == NULL)
+        {
+          _dbus_warn ("No message after auto activation "
+                      "(should be a service announcement)\n");
+          dbus_connection_return_message (connection, message);
+          message = NULL;
+          goto out;
+        }
+
+      message_kind = check_got_service_info (message);
+
+      dbus_connection_return_message (connection, message);
+      message = NULL;
+
+      switch (message_kind)
+        {
+        case GOT_SERVICE_CREATED:
+          message = pop_message_waiting_for_memory (connection);
+          if (message == NULL)
+            {
+              _dbus_warn ("Failed to pop message we just put back! "
+                          "should have been a NameOwnerChanged (creation)\n");
+              goto out;
+            }
+
+          /* Check that ServiceOwnerChanged (creation) was correctly received */
+          if (!check_service_auto_activated (context, connection, SHELL_SUCCESS_SERVICE_NAME,
+                                             base_service, message))
+            goto out;
+
+          dbus_message_unref (message);
+          message = NULL;
+
+          break;
+
+        case GOT_SERVICE_DELETED:
+          {
+            /* The service started up and got a base address, but then
+             * failed to register under SHELL_SUCCESS_SERVICE_NAME
+             */
+            CheckServiceOwnerChangedData socd;
+
+            socd.expected_kind = SERVICE_DELETED;
+            socd.expected_service_name = base_service;
+            socd.failed = FALSE;
+            socd.skip_connection = NULL;
+            bus_test_clients_foreach (check_service_owner_changed_foreach,
+                                      &socd);
+
+            if (socd.failed)
+              goto out;
+
+            break;
+          }
+
+        case GOT_ERROR:
+        case GOT_SOMETHING_ELSE:
+          _dbus_warn ("Unexpected message after auto activation\n");
+          goto out;
+        }
+    }
+
+  /* OK, now we've dealt with ServiceOwnerChanged signals, now should
+   * come the method reply (or error) from the initial method call
+   */
+
+  /* Note: if this test is run in OOM mode, it will block when the bus
+   * doesn't send a reply due to OOM.
+   */
+  block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation");
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
+      goto out;
+    }
+
+  if (dbus_message_get_reply_serial (message) != serial)
+    {
+      _dbus_warn ("Wrong reply serial\n");
+      goto out;
+    }
+
+  if (!dbus_message_get_args (message, NULL,
+                                       DBUS_TYPE_STRING, &argv[0],
+                                       DBUS_TYPE_STRING, &argv[1],
+                                       DBUS_TYPE_STRING, &argv[2],
+                                       DBUS_TYPE_STRING, &argv[3],
+                                       DBUS_TYPE_STRING, &argv[4],
+                                       DBUS_TYPE_STRING, &argv[5],
+                                       DBUS_TYPE_STRING, &argv[6],
+                                       DBUS_TYPE_INVALID))
+    {
+      _dbus_warn ("Error getting arguments from return\n");
+      goto out;
+    }
+
+   /* don't worry about arg[0] as it may be different
+      depending on the path to the tests
+   */
+  if (strcmp("-test", argv[1]) != 0)
+    {
+      _dbus_warn ("Unexpected argv[1] in shell success service test (expected: %s, got: %s)\n",
+                  "-test", argv[1]);
+      goto out;
+    }
+
+  if (strcmp("that", argv[2]) != 0)
+    {
+      _dbus_warn ("Unexpected argv[2] in shell success service test (expected: %s, got: %s)\n",
+                   "that", argv[2]);
+      goto out;
+    }
+
+  if (strcmp("we get", argv[3]) != 0)
+    {
+      _dbus_warn ("Unexpected argv[3] in shell success service test (expected: %s, got: %s)\n",
+                   "we get", argv[3]);
+      goto out;
+    }
+
+  if (strcmp("back", argv[4]) != 0)
+    {
+      _dbus_warn ("Unexpected argv[4] in shell success service test (expected: %s, got: %s)\n",
+                   "back", argv[4]);
+      goto out;
+    }
+
+  if (strcmp("--what", argv[5]) != 0)
+    {
+      _dbus_warn ("Unexpected argv[5] in shell success service test (expected: %s, got: %s)\n",
+                   "--what", argv[5]);
+      goto out;
+    }
+
+  if (strcmp("we put in", argv[6]) != 0)
+    {
+      _dbus_warn ("Unexpected argv[6] in shell success service test (expected: %s, got: %s)\n",
+                   "we put in", argv[6]);
+      goto out;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  if (!check_send_exit_to_service (context, connection,
+                                   SHELL_SUCCESS_SERVICE_NAME,
+                                   base_service))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  if (base_service_message)
+    dbus_message_unref (base_service_message);
+
+  return retval;
+}
+
+typedef struct
+{
+  Check1Func func;
+  BusContext *context;
+} Check1Data;
+
+static dbus_bool_t
+check_oom_check1_func (void *data)
+{
+  Check1Data *d = data;
+
+  if (! (* d->func) (d->context))
+    return FALSE;
+
+  if (!check_no_leftovers (d->context))
+    {
+      _dbus_warn ("Messages were left over, should be covered by test suite\n");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+check1_try_iterations (BusContext *context,
+                       const char *description,
+                       Check1Func  func)
+{
+  Check1Data d;
+
+  d.func = func;
+  d.context = context;
+
+  if (!_dbus_test_oom_handling (description, check_oom_check1_func,
+                                &d))
+    _dbus_assert_not_reached ("test failed");
+}
+
+static dbus_bool_t
+check_get_services (BusContext     *context,
+		    DBusConnection *connection,
+		    const char     *method,
+		    char         ***services,
+		    int            *len)
+{
+  DBusMessage *message;
+  dbus_uint32_t serial;
+  dbus_bool_t retval;
+  DBusError error;
+  char **srvs;
+  int l;
+
+  retval = FALSE;
+  dbus_error_init (&error);
+  message = NULL;
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+					  DBUS_PATH_DBUS,
+					  DBUS_INTERFACE_DBUS,
+					  method);
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  /* send our message */
+  bus_test_run_clients_loop (SEND_PENDING (connection));
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  dbus_connection_ref (connection); /* because we may get disconnected */
+  block_connection_until_message_from_bus (context, connection, "reply to ListActivatableNames/ListNames");
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+
+      dbus_connection_unref (connection);
+
+      return TRUE;
+    }
+
+  dbus_connection_unref (connection);
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+		  method, serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
+	{
+	  ; /* good, this is a valid response */
+	}
+      else
+	{
+	  warn_unexpected (connection, message, "not this error");
+
+	  goto out;
+	}
+    }
+  else
+    {
+      if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+	{
+	  ; /* good, expected */
+	}
+      else
+	{
+	  warn_unexpected (connection, message,
+			   "method_return for ListActivatableNames/ListNames");
+
+	  goto out;
+	}
+
+    retry_get_property:
+
+      if (!dbus_message_get_args (message, &error,
+				  DBUS_TYPE_ARRAY,
+				  DBUS_TYPE_STRING,
+				  &srvs, &l,
+				  DBUS_TYPE_INVALID))
+	{
+	  if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+	    {
+	      _dbus_verbose ("no memory to list services by %s\n", method);
+	      dbus_error_free (&error);
+	      _dbus_wait_for_memory ();
+	      goto retry_get_property;
+	    }
+	  else
+	    {
+	      _dbus_assert (dbus_error_is_set (&error));
+	      _dbus_warn ("Did not get the expected DBUS_TYPE_ARRAY from %s\n", method);
+	      goto out;
+	    }
+	} else {
+	  *services = srvs;
+	  *len = l;
+	}
+    }
+
+  if (!check_no_leftovers (context))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  dbus_error_free (&error);
+
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_list_services (BusContext     *context,
+		     DBusConnection *connection)
+{
+  DBusMessage  *message;
+  DBusMessage  *base_service_message;
+  const char   *base_service;
+  dbus_uint32_t serial;
+  dbus_bool_t   retval;
+  const char   *existent = EXISTENT_SERVICE_NAME;
+  dbus_uint32_t flags;
+  char        **services;
+  int           len;
+
+  _dbus_verbose ("check_list_services for %p\n", connection);
+
+  if (!check_get_services (context, connection, "ListActivatableNames", &services, &len))
+    {
+      return TRUE;
+    }
+
+  if (!_dbus_string_array_contains ((const char **)services, existent))
+    {
+      _dbus_warn ("Did not get the expected %s from ListActivatableNames\n", existent);
+      dbus_free_string_array (services);
+      return FALSE;
+    }
+
+  dbus_free_string_array (services);
+
+  base_service_message = NULL;
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+					  DBUS_PATH_DBUS,
+					  DBUS_INTERFACE_DBUS,
+					  "StartServiceByName");
+
+  if (message == NULL)
+    return TRUE;
+
+  dbus_message_set_auto_start (message, FALSE);
+
+  flags = 0;
+  if (!dbus_message_append_args (message,
+				 DBUS_TYPE_STRING, &existent,
+				 DBUS_TYPE_UINT32, &flags,
+				 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  bus_test_run_everything (context);
+
+  /* now wait for the message bus to hear back from the activated
+   * service.
+   */
+  block_connection_until_message_from_bus (context, connection, "activated service to connect");
+
+  bus_test_run_everything (context);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+
+  retval = FALSE;
+
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive any messages after %s %d on %p\n",
+		  "StartServiceByName", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+  _dbus_verbose ("  (after sending %s)\n", "StartServiceByName");
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
+	{
+	  _dbus_warn ("Message has wrong sender %s\n",
+		      dbus_message_get_sender (message) ?
+		      dbus_message_get_sender (message) : "(none)");
+	  goto out;
+	}
+
+      if (dbus_message_is_error (message,
+				 DBUS_ERROR_NO_MEMORY))
+	{
+	  ; /* good, this is a valid response */
+	}
+      else if (dbus_message_is_error (message,
+				      DBUS_ERROR_SPAWN_CHILD_EXITED) ||
+	       dbus_message_is_error (message,
+				      DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
+	       dbus_message_is_error (message,
+				      DBUS_ERROR_SPAWN_EXEC_FAILED))
+	{
+	  ; /* good, this is expected also */
+	}
+      else
+	{
+	  _dbus_warn ("Did not expect error %s\n",
+		      dbus_message_get_error_name (message));
+	  goto out;
+	}
+    }
+  else
+    {
+      GotServiceInfo message_kind;
+
+      if (!check_base_service_activated (context, connection,
+					 message, &base_service))
+	goto out;
+
+      base_service_message = message;
+      message = NULL;
+
+      /* We may need to block here for the test service to exit or finish up */
+      block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
+
+      message = dbus_connection_borrow_message (connection);
+      if (message == NULL)
+	{
+	  _dbus_warn ("Did not receive any messages after base service creation notification\n");
+	  goto out;
+	}
+
+      message_kind = check_got_service_info (message);
+
+      dbus_connection_return_message (connection, message);
+      message = NULL;
+
+      switch (message_kind)
+	{
+	case GOT_SOMETHING_ELSE:
+	case GOT_ERROR:
+	case GOT_SERVICE_DELETED:
+	  _dbus_warn ("Unexpected message after ActivateService "
+		      "(should be an error or a service announcement)\n");
+	  goto out;
+
+	case GOT_SERVICE_CREATED:
+	  message = pop_message_waiting_for_memory (connection);
+	  if (message == NULL)
+	    {
+	      _dbus_warn ("Failed to pop message we just put back! "
+			  "should have been a NameOwnerChanged (creation)\n");
+	      goto out;
+	    }
+
+	  if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
+					base_service, message))
+	    goto out;
+
+	  dbus_message_unref (message);
+	  message = NULL;
+
+	  if (!check_no_leftovers (context))
+	    {
+	      _dbus_warn ("Messages were left over after successful activation\n");
+	      goto out;
+	    }
+
+	  break;
+	}
+    }
+
+  if (!check_get_services (context, connection, "ListNames", &services, &len))
+    {
+      return TRUE;
+    }
+
+  if (!_dbus_string_array_contains ((const char **)services, existent))
+    {
+      _dbus_warn ("Did not get the expected %s from ListNames\n", existent);
+      goto out;
+    }
+
+  dbus_free_string_array (services);
+
+  if (!check_send_exit_to_service (context, connection,
+				   EXISTENT_SERVICE_NAME, base_service))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  if (message)
+    dbus_message_unref (message);
+
+  if (base_service_message)
+    dbus_message_unref (base_service_message);
+
+  return retval;
+}
+
+typedef struct
+{
+  Check2Func func;
+  BusContext *context;
+  DBusConnection *connection;
+} Check2Data;
+
+static dbus_bool_t
+check_oom_check2_func (void *data)
+{
+  Check2Data *d = data;
+
+  if (! (* d->func) (d->context, d->connection))
+    return FALSE;
+
+  if (!check_no_leftovers (d->context))
+    {
+      _dbus_warn ("Messages were left over, should be covered by test suite\n");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+check2_try_iterations (BusContext     *context,
+                       DBusConnection *connection,
+                       const char     *description,
+                       Check2Func      func)
+{
+  Check2Data d;
+
+  d.func = func;
+  d.context = context;
+  d.connection = connection;
+
+  if (!_dbus_test_oom_handling (description, check_oom_check2_func,
+                                &d))
+    {
+      _dbus_warn ("%s failed during oom\n", description);
+      _dbus_assert_not_reached ("test failed");
+    }
+}
+
+static dbus_bool_t
+setenv_TEST_LAUNCH_HELPER_CONFIG(const DBusString *test_data_dir,
+                                 const char       *filename)
+{
+  DBusString full;
+  DBusString file;
+
+  if (!_dbus_string_init (&full))
+    return FALSE;
+
+  if (!_dbus_string_copy (test_data_dir, 0, &full, 0))
+    {
+      _dbus_string_free (&full);
+      return FALSE;
+    }
+
+  _dbus_string_init_const (&file, filename);
+
+  if (!_dbus_concat_dir_and_file (&full, &file))
+    {
+      _dbus_string_free (&full);
+      return FALSE;
+    }
+
+  _dbus_verbose ("Setting TEST_LAUNCH_HELPER_CONFIG to '%s'\n",
+                 _dbus_string_get_const_data (&full));
+
+  _dbus_setenv ("TEST_LAUNCH_HELPER_CONFIG", _dbus_string_get_const_data (&full));
+
+  _dbus_string_free (&full);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+bus_dispatch_test_conf (const DBusString *test_data_dir,
+		        const char       *filename,
+		        dbus_bool_t       use_launcher)
+{
+  BusContext *context;
+  DBusConnection *foo;
+  DBusConnection *bar;
+  DBusConnection *baz;
+  DBusError error;
+
+  /* save the config name for the activation helper */
+  if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename))
+    _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG");
+
+  dbus_error_init (&error);
+
+  context = bus_context_new_test (test_data_dir, filename);
+  if (context == NULL)
+    return FALSE;
+
+  foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
+  if (foo == NULL)
+    _dbus_assert_not_reached ("could not alloc connection");
+
+  if (!bus_setup_debug_client (foo))
+    _dbus_assert_not_reached ("could not set up connection");
+
+  spin_connection_until_authenticated (context, foo);
+
+  if (!check_hello_message (context, foo))
+    _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_double_hello_message (context, foo))
+    _dbus_assert_not_reached ("double hello message failed");
+
+  if (!check_add_match_all (context, foo))
+    _dbus_assert_not_reached ("AddMatch message failed");
+
+  bar = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
+  if (bar == NULL)
+    _dbus_assert_not_reached ("could not alloc connection");
+
+  if (!bus_setup_debug_client (bar))
+    _dbus_assert_not_reached ("could not set up connection");
+
+  spin_connection_until_authenticated (context, bar);
+
+  if (!check_hello_message (context, bar))
+    _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_add_match_all (context, bar))
+    _dbus_assert_not_reached ("AddMatch message failed");
+
+  baz = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
+  if (baz == NULL)
+    _dbus_assert_not_reached ("could not alloc connection");
+
+  if (!bus_setup_debug_client (baz))
+    _dbus_assert_not_reached ("could not set up connection");
+
+  spin_connection_until_authenticated (context, baz);
+
+  if (!check_hello_message (context, baz))
+    _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_add_match_all (context, baz))
+    _dbus_assert_not_reached ("AddMatch message failed");
+
+#ifdef DBUS_WIN_FIXME
+  _dbus_warn("TODO: testing of GetConnectionUnixUser message skipped for now\n");
+  _dbus_warn("TODO: testing of GetConnectionUnixProcessID message skipped for now\n");
+#else
+  if (!check_get_connection_unix_user (context, baz))
+    _dbus_assert_not_reached ("GetConnectionUnixUser message failed");
+
+  if (!check_get_connection_unix_process_id (context, baz))
+    _dbus_assert_not_reached ("GetConnectionUnixProcessID message failed");
+#endif
+
+  if (!check_list_services (context, baz))
+    _dbus_assert_not_reached ("ListActivatableNames message failed");
+
+  if (!check_no_leftovers (context))
+    {
+      _dbus_warn ("Messages were left over after setting up initial connections\n");
+      _dbus_assert_not_reached ("initial connection setup failed");
+    }
+
+  check1_try_iterations (context, "create_and_hello",
+                         check_hello_connection);
+
+  check2_try_iterations (context, foo, "nonexistent_service_no_auto_start",
+                         check_nonexistent_service_no_auto_start);
+
+#ifdef DBUS_WIN_FIXME
+  _dbus_warn("TODO: dispatch.c segfault_service_no_auto_start test\n");
+#else
+  check2_try_iterations (context, foo, "segfault_service_no_auto_start",
+                         check_segfault_service_no_auto_start);
+#endif
+
+  check2_try_iterations (context, foo, "existent_service_no_auto_start",
+                         check_existent_service_no_auto_start);
+
+  check2_try_iterations (context, foo, "nonexistent_service_auto_start",
+                         check_nonexistent_service_auto_start);
+
+
+#ifdef DBUS_WIN_FIXME
+  _dbus_warn("TODO: dispatch.c segfault_service_auto_start test\n");
+#else
+  /* only do the segfault test if we are not using the launcher */
+  check2_try_iterations (context, foo, "segfault_service_auto_start",
+                         check_segfault_service_auto_start);
+#endif
+
+  /* only do the shell fail test if we are not using the launcher */
+  check2_try_iterations (context, foo, "shell_fail_service_auto_start",
+                         check_shell_fail_service_auto_start);
+
+  /* specific to launcher */
+  if (use_launcher)
+    if (!check_launch_service_file_missing (context, foo))
+      _dbus_assert_not_reached ("did not get service file not found error");
+
+#if 0
+  /* Note: need to resolve some issues with the testing code in order to run
+   * this in oom (handle that we sometimes don't get replies back from the bus
+   * when oom happens, without blocking the test).
+   */
+  check2_try_iterations (context, foo, "existent_service_auto_auto_start",
+                         check_existent_service_auto_start);
+#endif
+
+  if (!check_existent_service_auto_start (context, foo))
+    _dbus_assert_not_reached ("existent service auto start failed");
+
+  if (!check_shell_service_success_auto_start (context, foo))
+    _dbus_assert_not_reached ("shell success service auto start failed");
+
+  _dbus_verbose ("Disconnecting foo, bar, and baz\n");
+
+  kill_client_connection_unchecked (foo);
+  kill_client_connection_unchecked (bar);
+  kill_client_connection_unchecked (baz);
+
+  bus_context_unref (context);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+bus_dispatch_test_conf_fail (const DBusString *test_data_dir,
+		             const char       *filename)
+{
+  BusContext *context;
+  DBusConnection *foo;
+  DBusError error;
+
+  /* save the config name for the activation helper */
+  if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename))
+    _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG");
+
+  dbus_error_init (&error);
+
+  context = bus_context_new_test (test_data_dir, filename);
+  if (context == NULL)
+    return FALSE;
+
+  foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
+  if (foo == NULL)
+    _dbus_assert_not_reached ("could not alloc connection");
+
+  if (!bus_setup_debug_client (foo))
+    _dbus_assert_not_reached ("could not set up connection");
+
+  spin_connection_until_authenticated (context, foo);
+
+  if (!check_hello_message (context, foo))
+    _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_double_hello_message (context, foo))
+    _dbus_assert_not_reached ("double hello message failed");
+
+  if (!check_add_match_all (context, foo))
+    _dbus_assert_not_reached ("AddMatch message failed");
+
+  /* this only tests the activation.c user check */
+  if (!check_launch_service_user_missing (context, foo))
+    _dbus_assert_not_reached ("user missing did not trigger error");
+
+  /* this only tests the desktop.c exec check */
+  if (!check_launch_service_exec_missing (context, foo))
+    _dbus_assert_not_reached ("exec missing did not trigger error");
+
+  /* this only tests the desktop.c service check */
+  if (!check_launch_service_service_missing (context, foo))
+    _dbus_assert_not_reached ("service missing did not trigger error");
+
+  _dbus_verbose ("Disconnecting foo\n");
+
+  kill_client_connection_unchecked (foo);
+
+  bus_context_unref (context);
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_dispatch_test (const DBusString *test_data_dir)
+{
+  /* run normal activation tests */
+  _dbus_verbose ("Normal activation tests\n");
+  if (!bus_dispatch_test_conf (test_data_dir,
+  			       "valid-config-files/debug-allow-all.conf", FALSE))
+    return FALSE;
+
+#ifdef DBUS_WIN
+  _dbus_warn("Info: Launch helper activation tests skipped because launch-helper is not supported yet\n");
+#else
+  /* run launch-helper activation tests */
+  _dbus_verbose ("Launch helper activation tests\n");
+  if (!bus_dispatch_test_conf (test_data_dir,
+  			       "valid-config-files-system/debug-allow-all-pass.conf", TRUE))
+    return FALSE;
+
+  /* run select launch-helper activation tests on broken service files */
+  if (!bus_dispatch_test_conf_fail (test_data_dir,
+  			            "valid-config-files-system/debug-allow-all-fail.conf"))
+    return FALSE;
+#endif
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_dispatch_sha1_test (const DBusString *test_data_dir)
+{
+  BusContext *context;
+  DBusConnection *foo;
+  DBusError error;
+
+  dbus_error_init (&error);
+
+  /* Test SHA1 authentication */
+  _dbus_verbose ("Testing SHA1 context\n");
+
+  context = bus_context_new_test (test_data_dir,
+                                  "valid-config-files/debug-allow-all-sha1.conf");
+  if (context == NULL)
+    return FALSE;
+
+  foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
+  if (foo == NULL)
+    _dbus_assert_not_reached ("could not alloc connection");
+
+  if (!bus_setup_debug_client (foo))
+    _dbus_assert_not_reached ("could not set up connection");
+
+  spin_connection_until_authenticated (context, foo);
+
+  if (!check_hello_message (context, foo))
+    _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_add_match_all (context, foo))
+    _dbus_assert_not_reached ("addmatch message failed");
+
+  if (!check_no_leftovers (context))
+    {
+      _dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n");
+      _dbus_assert_not_reached ("initial connection setup failed");
+    }
+
+  check1_try_iterations (context, "create_and_hello_sha1",
+                         check_hello_connection);
+
+  kill_client_connection_unchecked (foo);
+
+  bus_context_unref (context);
+
+  return TRUE;
+}
+
+#ifdef HAVE_UNIX_FD_PASSING
+
+dbus_bool_t
+bus_unix_fds_passing_test(const DBusString *test_data_dir)
+{
+  BusContext *context;
+  DBusConnection *foo, *bar;
+  DBusError error;
+  DBusMessage *m;
+  int one[2], two[2], x, y, z;
+  char r;
+
+  dbus_error_init (&error);
+
+  context = bus_context_new_test (test_data_dir, "valid-config-files/debug-allow-all.conf");
+  if (context == NULL)
+    _dbus_assert_not_reached ("could not alloc context");
+
+  foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
+  if (foo == NULL)
+    _dbus_assert_not_reached ("could not alloc connection");
+
+  if (!bus_setup_debug_client (foo))
+    _dbus_assert_not_reached ("could not set up connection");
+
+  spin_connection_until_authenticated (context, foo);
+
+  if (!check_hello_message (context, foo))
+    _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_add_match_all (context, foo))
+    _dbus_assert_not_reached ("AddMatch message failed");
+
+  bar = dbus_connection_open_private (TEST_DEBUG_PIPE, &error);
+  if (bar == NULL)
+    _dbus_assert_not_reached ("could not alloc connection");
+
+  if (!bus_setup_debug_client (bar))
+    _dbus_assert_not_reached ("could not set up connection");
+
+  spin_connection_until_authenticated (context, bar);
+
+  if (!check_hello_message (context, bar))
+    _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_add_match_all (context, bar))
+    _dbus_assert_not_reached ("AddMatch message failed");
+
+  if (!(m = dbus_message_new_signal("/", "a.b.c", "d")))
+    _dbus_assert_not_reached ("could not alloc message");
+
+  if (!(_dbus_full_duplex_pipe(one, one+1, TRUE, &error)))
+    _dbus_assert_not_reached("Failed to allocate pipe #1");
+
+  if (!(_dbus_full_duplex_pipe(two, two+1, TRUE, &error)))
+    _dbus_assert_not_reached("Failed to allocate pipe #2");
+
+  if (!dbus_message_append_args(m,
+                                DBUS_TYPE_UNIX_FD, one,
+                                DBUS_TYPE_UNIX_FD, two,
+                                DBUS_TYPE_UNIX_FD, two,
+                                DBUS_TYPE_INVALID))
+    _dbus_assert_not_reached("Failed to attach fds.");
+
+  if (!_dbus_close(one[0], &error))
+    _dbus_assert_not_reached("Failed to close pipe #1 ");
+  if (!_dbus_close(two[0], &error))
+    _dbus_assert_not_reached("Failed to close pipe #2 ");
+
+  if (!(dbus_connection_can_send_type(foo, DBUS_TYPE_UNIX_FD)))
+    _dbus_assert_not_reached("Connection cannot do fd passing");
+
+  if (!(dbus_connection_can_send_type(bar, DBUS_TYPE_UNIX_FD)))
+    _dbus_assert_not_reached("Connection cannot do fd passing");
+
+  if (!dbus_connection_send (foo, m, NULL))
+    _dbus_assert_not_reached("Failed to send fds");
+
+  dbus_message_unref(m);
+
+  bus_test_run_clients_loop (SEND_PENDING (foo));
+
+  bus_test_run_everything (context);
+
+  block_connection_until_message_from_bus (context, foo, "unix fd reception on foo");
+
+  if (!(m = pop_message_waiting_for_memory (foo)))
+    _dbus_assert_not_reached("Failed to receive msg");
+
+  if (!dbus_message_is_signal(m, "a.b.c", "d"))
+    _dbus_assert_not_reached("bogus message received");
+
+  dbus_message_unref(m);
+
+  block_connection_until_message_from_bus (context, bar, "unix fd reception on bar");
+
+  if (!(m = pop_message_waiting_for_memory (bar)))
+    _dbus_assert_not_reached("Failed to receive msg");
+
+  if (!dbus_message_is_signal(m, "a.b.c", "d"))
+    _dbus_assert_not_reached("bogus message received");
+
+  if (!dbus_message_get_args(m,
+                             &error,
+                             DBUS_TYPE_UNIX_FD, &x,
+                             DBUS_TYPE_UNIX_FD, &y,
+                             DBUS_TYPE_UNIX_FD, &z,
+                             DBUS_TYPE_INVALID))
+    _dbus_assert_not_reached("Failed to parse fds.");
+
+  dbus_message_unref(m);
+
+  if (write(x, "X", 1) != 1)
+    _dbus_assert_not_reached("Failed to write to pipe #1");
+  if (write(y, "Y", 1) != 1)
+    _dbus_assert_not_reached("Failed to write to pipe #2");
+  if (write(z, "Z", 1) != 1)
+    _dbus_assert_not_reached("Failed to write to pipe #2/2nd fd");
+
+  if (!_dbus_close(x, &error))
+    _dbus_assert_not_reached("Failed to close pipe #1/other side ");
+  if (!_dbus_close(y, &error))
+    _dbus_assert_not_reached("Failed to close pipe #2/other side ");
+  if (!_dbus_close(z, &error))
+    _dbus_assert_not_reached("Failed to close pipe #2/other size 2nd fd ");
+
+  if (read(one[1], &r, 1) != 1 || r != 'X')
+    _dbus_assert_not_reached("Failed to read value from pipe.");
+  if (read(two[1], &r, 1) != 1 || r != 'Y')
+    _dbus_assert_not_reached("Failed to read value from pipe.");
+  if (read(two[1], &r, 1) != 1 || r != 'Z')
+    _dbus_assert_not_reached("Failed to read value from pipe.");
+
+  if (!_dbus_close(one[1], &error))
+    _dbus_assert_not_reached("Failed to close pipe #1 ");
+  if (!_dbus_close(two[1], &error))
+    _dbus_assert_not_reached("Failed to close pipe #2 ");
+
+  _dbus_verbose ("Disconnecting foo\n");
+  kill_client_connection_unchecked (foo);
+
+  _dbus_verbose ("Disconnecting bar\n");
+  kill_client_connection_unchecked (bar);
+
+  bus_context_unref (context);
+
+  return TRUE;
+}
+#endif
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/bus/dispatch.h b/dbus/bus/dispatch.h
new file mode 100644
index 0000000..fb5ba7a
--- /dev/null
+++ b/dbus/bus/dispatch.h
@@ -0,0 +1,38 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dispatch.h  Message dispatcher
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_DISPATCH_H
+#define BUS_DISPATCH_H
+
+#include <dbus/dbus.h>
+#include "connection.h"
+
+dbus_bool_t bus_dispatch_add_connection    (DBusConnection *connection);
+void        bus_dispatch_remove_connection (DBusConnection *connection);
+dbus_bool_t bus_dispatch_matches           (BusTransaction *transaction,
+                                            DBusConnection *sender,
+                                            DBusConnection *recipient,
+                                            DBusMessage    *message,
+                                            DBusError      *error);
+
+#endif /* BUS_DISPATCH_H */
diff --git a/dbus/bus/driver.c b/dbus/bus/driver.c
new file mode 100644
index 0000000..574e0f3
--- /dev/null
+++ b/dbus/bus/driver.c
@@ -0,0 +1,2035 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* driver.c  Bus client (driver)
+ *
+ * Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "activation.h"
+#include "connection.h"
+#include "driver.h"
+#include "dispatch.h"
+#include "services.h"
+#include "selinux.h"
+#include "signals.h"
+#include "stats.h"
+#include "utils.h"
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-message.h>
+#include <dbus/dbus-marshal-recursive.h>
+#include <string.h>
+
+static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
+                                                    DBusMessage    *hello_message,
+                                                    BusTransaction *transaction,
+                                                    DBusError      *error);
+
+dbus_bool_t
+bus_driver_send_service_owner_changed (const char     *service_name,
+				       const char     *old_owner,
+				       const char     *new_owner,
+				       BusTransaction *transaction,
+				       DBusError      *error)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
+  const char *null_service;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  null_service = "";
+  _dbus_verbose ("sending name owner changed: %s [%s -> %s]\n",
+                 service_name,
+                 old_owner ? old_owner : null_service,
+                 new_owner ? new_owner : null_service);
+
+  message = dbus_message_new_signal (DBUS_PATH_DBUS,
+                                     DBUS_INTERFACE_DBUS,
+                                     "NameOwnerChanged");
+
+  if (message == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+    goto oom;
+
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &service_name,
+                                 DBUS_TYPE_STRING, old_owner ? &old_owner : &null_service,
+                                 DBUS_TYPE_STRING, new_owner ? &new_owner : &null_service,
+                                 DBUS_TYPE_INVALID))
+    goto oom;
+
+  _dbus_assert (dbus_message_has_signature (message, "sss"));
+
+  retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
+  dbus_message_unref (message);
+
+  return retval;
+
+ oom:
+  dbus_message_unref (message);
+  BUS_SET_OOM (error);
+  return FALSE;
+}
+
+dbus_bool_t
+bus_driver_send_service_lost (DBusConnection *connection,
+			      const char     *service_name,
+                              BusTransaction *transaction,
+                              DBusError      *error)
+{
+  DBusMessage *message;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  message = dbus_message_new_signal (DBUS_PATH_DBUS,
+                                     DBUS_INTERFACE_DBUS,
+                                     "NameLost");
+
+  if (message == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
+      !dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &service_name,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_transaction_send_from_driver (transaction, connection, message))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  else
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+}
+
+dbus_bool_t
+bus_driver_send_service_acquired (DBusConnection *connection,
+                                  const char     *service_name,
+                                  BusTransaction *transaction,
+                                  DBusError      *error)
+{
+  DBusMessage *message;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  message = dbus_message_new_signal (DBUS_PATH_DBUS,
+                                     DBUS_INTERFACE_DBUS,
+                                     "NameAcquired");
+
+  if (message == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
+      !dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &service_name,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_transaction_send_from_driver (transaction, connection, message))
+    {
+      dbus_message_unref (message);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  else
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
+create_unique_client_name (BusRegistry *registry,
+                           DBusString  *str)
+{
+  /* We never want to use the same unique client name twice, because
+   * we want to guarantee that if you send a message to a given unique
+   * name, you always get the same application. So we use two numbers
+   * for INT_MAX * INT_MAX combinations, should be pretty safe against
+   * wraparound.
+   */
+  /* FIXME these should be in BusRegistry rather than static vars */
+  static int next_major_number = 0;
+  static int next_minor_number = 0;
+  int len;
+
+  len = _dbus_string_get_length (str);
+
+  while (TRUE)
+    {
+      /* start out with 1-0, go to 1-1, 1-2, 1-3,
+       * up to 1-MAXINT, then 2-0, 2-1, etc.
+       */
+      if (next_minor_number <= 0)
+        {
+          next_major_number += 1;
+          next_minor_number = 0;
+          if (next_major_number <= 0)
+            _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
+        }
+
+      _dbus_assert (next_major_number > 0);
+      _dbus_assert (next_minor_number >= 0);
+
+      /* appname:MAJOR-MINOR */
+
+      if (!_dbus_string_append (str, ":"))
+        return FALSE;
+
+      if (!_dbus_string_append_int (str, next_major_number))
+        return FALSE;
+
+      if (!_dbus_string_append (str, "."))
+        return FALSE;
+
+      if (!_dbus_string_append_int (str, next_minor_number))
+        return FALSE;
+
+      next_minor_number += 1;
+
+      /* Check if a client with the name exists */
+      if (bus_registry_lookup (registry, str) == NULL)
+	break;
+
+      /* drop the number again, try the next one. */
+      _dbus_string_set_length (str, len);
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+bus_driver_handle_hello (DBusConnection *connection,
+                         BusTransaction *transaction,
+                         DBusMessage    *message,
+                         DBusError      *error)
+{
+  DBusString unique_name;
+  BusService *service;
+  dbus_bool_t retval;
+  BusRegistry *registry;
+  BusConnections *connections;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (bus_connection_is_active (connection))
+    {
+      /* We already handled an Hello message for this connection. */
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Already handled an Hello message");
+      return FALSE;
+    }
+
+  /* Note that when these limits are exceeded we don't disconnect the
+   * connection; we just sort of leave it hanging there until it times
+   * out or disconnects itself or is dropped due to the max number of
+   * incomplete connections. It's even OK if the connection wants to
+   * retry the hello message, we support that.
+   */
+  connections = bus_connection_get_connections (connection);
+  if (!bus_connections_check_limits (connections, connection,
+                                     error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&unique_name))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  retval = FALSE;
+
+  registry = bus_connection_get_registry (connection);
+
+  if (!create_unique_client_name (registry, &unique_name))
+    {
+      BUS_SET_OOM (error);
+      goto out_0;
+    }
+
+  if (!bus_connection_complete (connection, &unique_name, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto out_0;
+    }
+
+  if (!dbus_message_set_sender (message,
+                                bus_connection_get_name (connection)))
+    {
+      BUS_SET_OOM (error);
+      goto out_0;
+    }
+
+  if (!bus_driver_send_welcome_message (connection, message, transaction, error))
+    goto out_0;
+
+  /* Create the service */
+  service = bus_registry_ensure (registry,
+                                 &unique_name, connection, 0, transaction, error);
+  if (service == NULL)
+    goto out_0;
+
+  _dbus_assert (bus_connection_is_active (connection));
+  retval = TRUE;
+
+ out_0:
+  _dbus_string_free (&unique_name);
+  return retval;
+}
+
+static dbus_bool_t
+bus_driver_send_welcome_message (DBusConnection *connection,
+                                 DBusMessage    *hello_message,
+                                 BusTransaction *transaction,
+                                 DBusError      *error)
+{
+  DBusMessage *welcome;
+  const char *name;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  name = bus_connection_get_name (connection);
+  _dbus_assert (name != NULL);
+
+  welcome = dbus_message_new_method_return (hello_message);
+  if (welcome == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!dbus_message_append_args (welcome,
+                                 DBUS_TYPE_STRING, &name,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (welcome);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  _dbus_assert (dbus_message_has_signature (welcome, DBUS_TYPE_STRING_AS_STRING));
+
+  if (!bus_transaction_send_from_driver (transaction, connection, welcome))
+    {
+      dbus_message_unref (welcome);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  else
+    {
+      dbus_message_unref (welcome);
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
+bus_driver_handle_list_services (DBusConnection *connection,
+                                 BusTransaction *transaction,
+                                 DBusMessage    *message,
+                                 DBusError      *error)
+{
+  DBusMessage *reply;
+  int len;
+  char **services;
+  BusRegistry *registry;
+  int i;
+  DBusMessageIter iter;
+  DBusMessageIter sub;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_registry_list_services (registry, &services, &len))
+    {
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  dbus_message_iter_init_append (reply, &iter);
+
+  if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+                                         DBUS_TYPE_STRING_AS_STRING,
+                                         &sub))
+    {
+      dbus_free_string_array (services);
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  {
+    /* Include the bus driver in the list */
+    const char *v_STRING = DBUS_SERVICE_DBUS;
+    if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
+                                         &v_STRING))
+      {
+        dbus_free_string_array (services);
+        dbus_message_unref (reply);
+        BUS_SET_OOM (error);
+        return FALSE;
+      }
+  }
+
+  i = 0;
+  while (i < len)
+    {
+      if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
+                                           &services[i]))
+        {
+          dbus_free_string_array (services);
+          dbus_message_unref (reply);
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+      ++i;
+    }
+
+  dbus_free_string_array (services);
+
+  if (!dbus_message_iter_close_container (&iter, &sub))
+    {
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    {
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  else
+    {
+      dbus_message_unref (reply);
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
+bus_driver_handle_list_activatable_services (DBusConnection *connection,
+					     BusTransaction *transaction,
+					     DBusMessage    *message,
+					     DBusError      *error)
+{
+  DBusMessage *reply;
+  int len;
+  char **services;
+  BusActivation *activation;
+  int i;
+  DBusMessageIter iter;
+  DBusMessageIter sub;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  activation = bus_connection_get_activation (connection);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_activation_list_services (activation, &services, &len))
+    {
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  dbus_message_iter_init_append (reply, &iter);
+
+  if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+					 DBUS_TYPE_STRING_AS_STRING,
+					 &sub))
+    {
+      dbus_free_string_array (services);
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  {
+    /* Include the bus driver in the list */
+    const char *v_STRING = DBUS_SERVICE_DBUS;
+    if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
+					 &v_STRING))
+      {
+	dbus_free_string_array (services);
+	dbus_message_unref (reply);
+	BUS_SET_OOM (error);
+	return FALSE;
+      }
+  }
+
+  i = 0;
+  while (i < len)
+    {
+      if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
+					   &services[i]))
+	{
+	  dbus_free_string_array (services);
+	  dbus_message_unref (reply);
+	  BUS_SET_OOM (error);
+	  return FALSE;
+	}
+      ++i;
+    }
+
+  dbus_free_string_array (services);
+
+  if (!dbus_message_iter_close_container (&iter, &sub))
+    {
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    {
+      dbus_message_unref (reply);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+  else
+    {
+      dbus_message_unref (reply);
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
+bus_driver_handle_acquire_service (DBusConnection *connection,
+                                   BusTransaction *transaction,
+                                   DBusMessage    *message,
+                                   DBusError      *error)
+{
+  DBusMessage *reply;
+  DBusString service_name;
+  const char *name;
+  dbus_uint32_t service_reply;
+  dbus_uint32_t flags;
+  dbus_bool_t retval;
+  BusRegistry *registry;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &name,
+                              DBUS_TYPE_UINT32, &flags,
+                              DBUS_TYPE_INVALID))
+    return FALSE;
+
+  _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags);
+
+  retval = FALSE;
+  reply = NULL;
+
+  _dbus_string_init_const (&service_name, name);
+
+  if (!bus_registry_acquire_service (registry, connection,
+                                     &service_name, flags,
+                                     &service_reply, transaction,
+                                     error))
+    goto out;
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (reply)
+    dbus_message_unref (reply);
+  return retval;
+}
+
+static dbus_bool_t
+bus_driver_handle_release_service (DBusConnection *connection,
+                                   BusTransaction *transaction,
+                                   DBusMessage    *message,
+                                   DBusError      *error)
+{
+  DBusMessage *reply;
+  DBusString service_name;
+  const char *name;
+  dbus_uint32_t service_reply;
+  dbus_bool_t retval;
+  BusRegistry *registry;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &name,
+                              DBUS_TYPE_INVALID))
+    return FALSE;
+
+  _dbus_verbose ("Trying to release name %s\n", name);
+
+  retval = FALSE;
+  reply = NULL;
+
+  _dbus_string_init_const (&service_name, name);
+
+  if (!bus_registry_release_service (registry, connection,
+                                     &service_name, &service_reply,
+                                     transaction, error))
+    goto out;
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (reply)
+    dbus_message_unref (reply);
+  return retval;
+}
+
+static dbus_bool_t
+bus_driver_handle_service_exists (DBusConnection *connection,
+                                  BusTransaction *transaction,
+                                  DBusMessage    *message,
+                                  DBusError      *error)
+{
+  DBusMessage *reply;
+  DBusString service_name;
+  BusService *service;
+  dbus_bool_t service_exists;
+  const char *name;
+  dbus_bool_t retval;
+  BusRegistry *registry;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &name,
+                              DBUS_TYPE_INVALID))
+    return FALSE;
+
+  retval = FALSE;
+
+  if (strcmp (name, DBUS_SERVICE_DBUS) == 0)
+    {
+      service_exists = TRUE;
+    }
+  else
+    {
+      _dbus_string_init_const (&service_name, name);
+      service = bus_registry_lookup (registry, &service_name);
+      service_exists = service != NULL;
+    }
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (!dbus_message_append_args (reply,
+                                 DBUS_TYPE_BOOLEAN, &service_exists,
+                                 0))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    {
+      BUS_SET_OOM (error);
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  if (reply)
+    dbus_message_unref (reply);
+
+  return retval;
+}
+
+static dbus_bool_t
+bus_driver_handle_activate_service (DBusConnection *connection,
+                                    BusTransaction *transaction,
+                                    DBusMessage    *message,
+                                    DBusError      *error)
+{
+  dbus_uint32_t flags;
+  const char *name;
+  dbus_bool_t retval;
+  BusActivation *activation;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  activation = bus_connection_get_activation (connection);
+
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &name,
+                              DBUS_TYPE_UINT32, &flags,
+                              DBUS_TYPE_INVALID))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      _dbus_verbose ("No memory to get arguments to StartServiceByName\n");
+      return FALSE;
+    }
+
+  retval = FALSE;
+
+  if (!bus_activation_activate_service (activation, connection, transaction, FALSE,
+                                        message, name, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      _dbus_verbose ("bus_activation_activate_service() failed\n");
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  return retval;
+}
+
+static dbus_bool_t
+send_ack_reply (DBusConnection *connection,
+                BusTransaction *transaction,
+                DBusMessage    *message,
+                DBusError      *error)
+{
+  DBusMessage *reply;
+
+  if (dbus_message_get_no_reply (message))
+    return TRUE;
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    {
+      BUS_SET_OOM (error);
+      dbus_message_unref (reply);
+      return FALSE;
+    }
+
+  dbus_message_unref (reply);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+bus_driver_handle_update_activation_environment (DBusConnection *connection,
+                                                 BusTransaction *transaction,
+                                                 DBusMessage    *message,
+                                                 DBusError      *error)
+{
+  dbus_bool_t retval;
+  BusActivation *activation;
+  DBusMessageIter iter;
+  DBusMessageIter dict_iter;
+  DBusMessageIter dict_entry_iter;
+  int array_type;
+  int key_type;
+  DBusList *keys, *key_link;
+  DBusList *values, *value_link;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  activation = bus_connection_get_activation (connection);
+
+  dbus_message_iter_init (message, &iter);
+
+  /* The message signature has already been checked for us,
+   * so let's just assert it's right.
+   */
+#ifndef DBUS_DISABLE_ASSERT
+    {
+      int msg_type = dbus_message_iter_get_arg_type (&iter);
+
+      _dbus_assert (msg_type == DBUS_TYPE_ARRAY);
+    }
+#endif
+
+  dbus_message_iter_recurse (&iter, &dict_iter);
+
+  retval = FALSE;
+
+  /* Then loop through the sent dictionary, add the location of
+   * the environment keys and values to lists. The result will
+   * be in reverse order, so we don't have to constantly search
+   * for the end of the list in a loop.
+   */
+  keys = NULL;
+  values = NULL;
+  while ((array_type = dbus_message_iter_get_arg_type (&dict_iter)) == DBUS_TYPE_DICT_ENTRY)
+    {
+      dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
+
+      while ((key_type = dbus_message_iter_get_arg_type (&dict_entry_iter)) == DBUS_TYPE_STRING)
+        {
+          char *key;
+          char *value;
+          int value_type;
+
+          dbus_message_iter_get_basic (&dict_entry_iter, &key);
+          dbus_message_iter_next (&dict_entry_iter);
+
+          value_type = dbus_message_iter_get_arg_type (&dict_entry_iter);
+
+          if (value_type != DBUS_TYPE_STRING)
+            break;
+
+          dbus_message_iter_get_basic (&dict_entry_iter, &value);
+
+          if (!_dbus_list_append (&keys, key))
+            {
+              BUS_SET_OOM (error);
+              break;
+            }
+
+          if (!_dbus_list_append (&values, value))
+            {
+              BUS_SET_OOM (error);
+              break;
+            }
+
+          dbus_message_iter_next (&dict_entry_iter);
+        }
+
+      if (key_type != DBUS_TYPE_INVALID)
+        break;
+
+      dbus_message_iter_next (&dict_iter);
+    }
+
+  if (array_type != DBUS_TYPE_INVALID)
+    goto out;
+
+  _dbus_assert (_dbus_list_get_length (&keys) == _dbus_list_get_length (&values));
+
+  key_link = keys;
+  value_link = values;
+  while (key_link != NULL)
+  {
+      const char *key;
+      const char *value;
+
+      key = key_link->data;
+      value = value_link->data;
+
+      if (!bus_activation_set_environment_variable (activation,
+                                                    key, value, error))
+      {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          _dbus_verbose ("bus_activation_set_environment_variable() failed\n");
+          break;
+      }
+      key_link = _dbus_list_get_next_link (&keys, key_link);
+      value_link = _dbus_list_get_next_link (&values, value_link);
+  }
+
+  /* FIXME: We can fail early having set only some of the environment variables,
+   * (because of OOM failure).  It's sort of hard to fix and it doesn't really
+   * matter, so we're punting for now.
+   */
+  if (key_link != NULL)
+    goto out;
+
+  if (!send_ack_reply (connection, transaction,
+                       message, error))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  _dbus_list_clear (&keys);
+  _dbus_list_clear (&values);
+  return retval;
+}
+
+static dbus_bool_t
+bus_driver_handle_add_match (DBusConnection *connection,
+                             BusTransaction *transaction,
+                             DBusMessage    *message,
+                             DBusError      *error)
+{
+  BusMatchRule *rule;
+  const char *text;
+  DBusString str;
+  BusMatchmaker *matchmaker;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  text = NULL;
+  rule = NULL;
+
+  if (bus_connection_get_n_match_rules (connection) >=
+      bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                      "Connection \"%s\" is not allowed to add more match rules "
+                      "(increase limits in configuration file if required)",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)");
+      goto failed;
+    }
+
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &text,
+                              DBUS_TYPE_INVALID))
+    {
+      _dbus_verbose ("No memory to get arguments to AddMatch\n");
+      goto failed;
+    }
+
+  _dbus_string_init_const (&str, text);
+
+  rule = bus_match_rule_parse (connection, &str, error);
+  if (rule == NULL)
+    goto failed;
+
+  matchmaker = bus_connection_get_matchmaker (connection);
+
+  if (!bus_matchmaker_add_rule (matchmaker, rule))
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  if (!send_ack_reply (connection, transaction,
+                       message, error))
+    {
+      bus_matchmaker_remove_rule (matchmaker, rule);
+      goto failed;
+    }
+
+  bus_match_rule_unref (rule);
+
+  return TRUE;
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (rule)
+    bus_match_rule_unref (rule);
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_remove_match (DBusConnection *connection,
+                                BusTransaction *transaction,
+                                DBusMessage    *message,
+                                DBusError      *error)
+{
+  BusMatchRule *rule;
+  const char *text;
+  DBusString str;
+  BusMatchmaker *matchmaker;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  text = NULL;
+  rule = NULL;
+
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &text,
+                              DBUS_TYPE_INVALID))
+    {
+      _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
+      goto failed;
+    }
+
+  _dbus_string_init_const (&str, text);
+
+  rule = bus_match_rule_parse (connection, &str, error);
+  if (rule == NULL)
+    goto failed;
+
+  /* Send the ack before we remove the rule, since the ack is undone
+   * on transaction cancel, but rule removal isn't.
+   */
+  if (!send_ack_reply (connection, transaction,
+                       message, error))
+    goto failed;
+
+  matchmaker = bus_connection_get_matchmaker (connection);
+
+  if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
+    goto failed;
+
+  bus_match_rule_unref (rule);
+
+  return TRUE;
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (rule)
+    bus_match_rule_unref (rule);
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_get_service_owner (DBusConnection *connection,
+				     BusTransaction *transaction,
+				     DBusMessage    *message,
+				     DBusError      *error)
+{
+  const char *text;
+  const char *base_name;
+  DBusString str;
+  BusRegistry *registry;
+  BusService *service;
+  DBusMessage *reply;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  text = NULL;
+  reply = NULL;
+
+  if (! dbus_message_get_args (message, error,
+			       DBUS_TYPE_STRING, &text,
+			       DBUS_TYPE_INVALID))
+      goto failed;
+
+  _dbus_string_init_const (&str, text);
+  service = bus_registry_lookup (registry, &str);
+  if (service == NULL &&
+      _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
+    {
+      /* ORG_FREEDESKTOP_DBUS owns itself */
+      base_name = DBUS_SERVICE_DBUS;
+    }
+  else if (service == NULL)
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_NAME_HAS_NO_OWNER,
+                      "Could not get owner of name '%s': no such name", text);
+      goto failed;
+    }
+  else
+    {
+      base_name = bus_connection_get_name (bus_service_get_primary_owners_connection (service));
+      if (base_name == NULL)
+        {
+          /* FIXME - how is this error possible? */
+          dbus_set_error (error,
+                          DBUS_ERROR_FAILED,
+                          "Could not determine unique name for '%s'", text);
+          goto failed;
+        }
+      _dbus_assert (*base_name == ':');
+    }
+
+  _dbus_assert (base_name != NULL);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  if (! dbus_message_append_args (reply,
+				  DBUS_TYPE_STRING, &base_name,
+				  DBUS_TYPE_INVALID))
+    goto oom;
+
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (reply)
+    dbus_message_unref (reply);
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_list_queued_owners (DBusConnection *connection,
+				      BusTransaction *transaction,
+				      DBusMessage    *message,
+				      DBusError      *error)
+{
+  const char *text;
+  DBusList *base_names;
+  DBusList *link;
+  DBusString str;
+  BusRegistry *registry;
+  BusService *service;
+  DBusMessage *reply;
+  DBusMessageIter iter, array_iter;
+  char *dbus_service_name = DBUS_SERVICE_DBUS;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  base_names = NULL;
+  text = NULL;
+  reply = NULL;
+
+  if (! dbus_message_get_args (message, error,
+			       DBUS_TYPE_STRING, &text,
+			       DBUS_TYPE_INVALID))
+      goto failed;
+
+  _dbus_string_init_const (&str, text);
+  service = bus_registry_lookup (registry, &str);
+  if (service == NULL &&
+      _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
+    {
+      /* ORG_FREEDESKTOP_DBUS owns itself */
+      if (! _dbus_list_append (&base_names, dbus_service_name))
+        goto oom;
+    }
+  else if (service == NULL)
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_NAME_HAS_NO_OWNER,
+                      "Could not get owners of name '%s': no such name", text);
+      goto failed;
+    }
+  else
+    {
+      if (!bus_service_list_queued_owners (service,
+                                           &base_names,
+                                           error))
+        goto failed;
+    }
+
+  _dbus_assert (base_names != NULL);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  dbus_message_iter_init_append (reply, &iter);
+  if (!dbus_message_iter_open_container (&iter,
+                                         DBUS_TYPE_ARRAY,
+                                         DBUS_TYPE_STRING_AS_STRING,
+                                         &array_iter))
+    goto oom;
+
+  link = _dbus_list_get_first_link (&base_names);
+  while (link != NULL)
+    {
+      char *uname;
+
+      _dbus_assert (link->data != NULL);
+      uname = (char *)link->data;
+
+      if (!dbus_message_iter_append_basic (&array_iter,
+                                           DBUS_TYPE_STRING,
+                                           &uname))
+        goto oom;
+
+      link = _dbus_list_get_next_link (&base_names, link);
+    }
+
+  if (! dbus_message_iter_close_container (&iter, &array_iter))
+    goto oom;
+
+
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (reply)
+    dbus_message_unref (reply);
+
+  if (base_names)
+    _dbus_list_clear (&base_names);
+
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
+                                            BusTransaction *transaction,
+                                            DBusMessage    *message,
+                                            DBusError      *error)
+{
+  const char *service;
+  DBusString str;
+  BusRegistry *registry;
+  BusService *serv;
+  DBusConnection *conn;
+  DBusMessage *reply;
+  unsigned long uid;
+  dbus_uint32_t uid32;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  service = NULL;
+  reply = NULL;
+
+  if (! dbus_message_get_args (message, error,
+			       DBUS_TYPE_STRING, &service,
+			       DBUS_TYPE_INVALID))
+      goto failed;
+
+  _dbus_verbose ("asked for UID of connection %s\n", service);
+
+  _dbus_string_init_const (&str, service);
+  serv = bus_registry_lookup (registry, &str);
+  if (serv == NULL)
+    {
+      dbus_set_error (error,
+		      DBUS_ERROR_NAME_HAS_NO_OWNER,
+		      "Could not get UID of name '%s': no such name", service);
+      goto failed;
+    }
+
+  conn = bus_service_get_primary_owners_connection (serv);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  if (!dbus_connection_get_unix_user (conn, &uid))
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_FAILED,
+                      "Could not determine UID for '%s'", service);
+      goto failed;
+    }
+
+  uid32 = uid;
+  if (! dbus_message_append_args (reply,
+                                  DBUS_TYPE_UINT32, &uid32,
+                                  DBUS_TYPE_INVALID))
+    goto oom;
+
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (reply)
+    dbus_message_unref (reply);
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
+						  BusTransaction *transaction,
+						  DBusMessage    *message,
+						  DBusError      *error)
+{
+  const char *service;
+  DBusString str;
+  BusRegistry *registry;
+  BusService *serv;
+  DBusConnection *conn;
+  DBusMessage *reply;
+  unsigned long pid;
+  dbus_uint32_t pid32;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  service = NULL;
+  reply = NULL;
+
+  if (! dbus_message_get_args (message, error,
+			       DBUS_TYPE_STRING, &service,
+			       DBUS_TYPE_INVALID))
+      goto failed;
+
+  _dbus_verbose ("asked for PID of connection %s\n", service);
+
+  _dbus_string_init_const (&str, service);
+  serv = bus_registry_lookup (registry, &str);
+  if (serv == NULL)
+    {
+      dbus_set_error (error,
+		      DBUS_ERROR_NAME_HAS_NO_OWNER,
+		      "Could not get PID of name '%s': no such name", service);
+      goto failed;
+    }
+
+  conn = bus_service_get_primary_owners_connection (serv);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  if (!dbus_connection_get_unix_process_id (conn, &pid))
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
+                      "Could not determine PID for '%s'", service);
+      goto failed;
+    }
+
+  pid32 = pid;
+  if (! dbus_message_append_args (reply,
+                                  DBUS_TYPE_UINT32, &pid32,
+                                  DBUS_TYPE_INVALID))
+    goto oom;
+
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (reply)
+    dbus_message_unref (reply);
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection,
+					      BusTransaction *transaction,
+					      DBusMessage    *message,
+					      DBusError      *error)
+{
+  const char *service;
+  DBusString str;
+  BusRegistry *registry;
+  BusService *serv;
+  DBusConnection *conn;
+  DBusMessage *reply;
+  void *data = NULL;
+  dbus_uint32_t data_size;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  service = NULL;
+  reply = NULL;
+
+  if (! dbus_message_get_args (message, error,
+			       DBUS_TYPE_STRING, &service,
+			       DBUS_TYPE_INVALID))
+      goto failed;
+
+  _dbus_verbose ("asked for audit session data for connection %s\n", service);
+
+  _dbus_string_init_const (&str, service);
+  serv = bus_registry_lookup (registry, &str);
+  if (serv == NULL)
+    {
+      dbus_set_error (error,
+		      DBUS_ERROR_NAME_HAS_NO_OWNER,
+		      "Could not get audit session data for name '%s': no such name", service);
+      goto failed;
+    }
+
+  conn = bus_service_get_primary_owners_connection (serv);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  if (!dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) || data == NULL)
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN,
+                      "Could not determine audit session data for '%s'", service);
+      goto failed;
+    }
+
+  if (! dbus_message_append_args (reply,
+                                  DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, data_size,
+                                  DBUS_TYPE_INVALID))
+    goto oom;
+
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (reply)
+    dbus_message_unref (reply);
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection,
+							   BusTransaction *transaction,
+							   DBusMessage    *message,
+							   DBusError      *error)
+{
+  const char *service;
+  DBusString str;
+  BusRegistry *registry;
+  BusService *serv;
+  DBusConnection *conn;
+  DBusMessage *reply;
+  BusSELinuxID *context;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (connection);
+
+  service = NULL;
+  reply = NULL;
+
+  if (! dbus_message_get_args (message, error,
+			       DBUS_TYPE_STRING, &service,
+			       DBUS_TYPE_INVALID))
+      goto failed;
+
+  _dbus_verbose ("asked for security context of connection %s\n", service);
+
+  _dbus_string_init_const (&str, service);
+  serv = bus_registry_lookup (registry, &str);
+  if (serv == NULL)
+    {
+      dbus_set_error (error,
+		      DBUS_ERROR_NAME_HAS_NO_OWNER,
+		      "Could not get security context of name '%s': no such name", service);
+      goto failed;
+    }
+
+  conn = bus_service_get_primary_owners_connection (serv);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  context = bus_connection_get_selinux_id (conn);
+  if (!context)
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
+                      "Could not determine security context for '%s'", service);
+      goto failed;
+    }
+
+  if (! bus_selinux_append_context (reply, context, error))
+    goto failed;
+
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (reply)
+    dbus_message_unref (reply);
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_reload_config (DBusConnection *connection,
+				 BusTransaction *transaction,
+				 DBusMessage    *message,
+				 DBusError      *error)
+{
+  BusContext *context;
+  DBusMessage *reply;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  reply = NULL;
+
+  context = bus_connection_get_context (connection);
+  if (!bus_context_reload_config (context, error))
+    goto failed;
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (reply)
+    dbus_message_unref (reply);
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_get_id (DBusConnection *connection,
+                          BusTransaction *transaction,
+                          DBusMessage    *message,
+                          DBusError      *error)
+{
+  BusContext *context;
+  DBusMessage *reply;
+  DBusString uuid;
+  const char *v_STRING;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (!_dbus_string_init (&uuid))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  reply = NULL;
+
+  context = bus_connection_get_context (connection);
+  if (!bus_context_get_id (context, &uuid))
+    goto oom;
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  v_STRING = _dbus_string_get_const_data (&uuid);
+  if (!dbus_message_append_args (reply,
+                                 DBUS_TYPE_STRING, &v_STRING,
+                                 DBUS_TYPE_INVALID))
+    goto oom;
+
+  _dbus_assert (dbus_message_has_signature (reply, "s"));
+
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  _dbus_string_free (&uuid);
+  dbus_message_unref (reply);
+  return TRUE;
+
+ oom:
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  BUS_SET_OOM (error);
+
+  if (reply)
+    dbus_message_unref (reply);
+  _dbus_string_free (&uuid);
+  return FALSE;
+}
+
+typedef struct
+{
+  const char *name;
+  const char *in_args;
+  const char *out_args;
+  dbus_bool_t (* handler) (DBusConnection *connection,
+                           BusTransaction *transaction,
+                           DBusMessage    *message,
+                           DBusError      *error);
+} MessageHandler;
+
+/* For speed it might be useful to sort this in order of
+ * frequency of use (but doesn't matter with only a few items
+ * anyhow)
+ */
+static const MessageHandler dbus_message_handlers[] = {
+  { "Hello",
+    "",
+    DBUS_TYPE_STRING_AS_STRING,
+    bus_driver_handle_hello },
+  { "RequestName",
+    DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
+    DBUS_TYPE_UINT32_AS_STRING,
+    bus_driver_handle_acquire_service },
+  { "ReleaseName",
+    DBUS_TYPE_STRING_AS_STRING,
+    DBUS_TYPE_UINT32_AS_STRING,
+    bus_driver_handle_release_service },
+  { "StartServiceByName",
+    DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
+    DBUS_TYPE_UINT32_AS_STRING,
+    bus_driver_handle_activate_service },
+  { "UpdateActivationEnvironment",
+    DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+    "",
+    bus_driver_handle_update_activation_environment },
+  { "NameHasOwner",
+    DBUS_TYPE_STRING_AS_STRING,
+    DBUS_TYPE_BOOLEAN_AS_STRING,
+    bus_driver_handle_service_exists },
+  { "ListNames",
+    "",
+    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+    bus_driver_handle_list_services },
+  { "ListActivatableNames",
+    "",
+    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+    bus_driver_handle_list_activatable_services },
+  { "AddMatch",
+    DBUS_TYPE_STRING_AS_STRING,
+    "",
+    bus_driver_handle_add_match },
+  { "RemoveMatch",
+    DBUS_TYPE_STRING_AS_STRING,
+    "",
+    bus_driver_handle_remove_match },
+  { "GetNameOwner",
+    DBUS_TYPE_STRING_AS_STRING,
+    DBUS_TYPE_STRING_AS_STRING,
+    bus_driver_handle_get_service_owner },
+  { "ListQueuedOwners",
+    DBUS_TYPE_STRING_AS_STRING,
+    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+    bus_driver_handle_list_queued_owners },
+  { "GetConnectionUnixUser",
+    DBUS_TYPE_STRING_AS_STRING,
+    DBUS_TYPE_UINT32_AS_STRING,
+    bus_driver_handle_get_connection_unix_user },
+  { "GetConnectionUnixProcessID",
+    DBUS_TYPE_STRING_AS_STRING,
+    DBUS_TYPE_UINT32_AS_STRING,
+    bus_driver_handle_get_connection_unix_process_id },
+  { "GetAdtAuditSessionData",
+    DBUS_TYPE_STRING_AS_STRING,
+    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
+    bus_driver_handle_get_adt_audit_session_data },
+  { "GetConnectionSELinuxSecurityContext",
+    DBUS_TYPE_STRING_AS_STRING,
+    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
+    bus_driver_handle_get_connection_selinux_security_context },
+  { "ReloadConfig",
+    "",
+    "",
+    bus_driver_handle_reload_config },
+  { "GetId",
+    "",
+    DBUS_TYPE_STRING_AS_STRING,
+    bus_driver_handle_get_id },
+  { NULL, NULL, NULL, NULL }
+};
+
+static dbus_bool_t bus_driver_handle_introspect (DBusConnection *,
+    BusTransaction *, DBusMessage *, DBusError *);
+
+static const MessageHandler introspectable_message_handlers[] = {
+  { "Introspect", "", DBUS_TYPE_STRING_AS_STRING, bus_driver_handle_introspect },
+  { NULL, NULL, NULL, NULL }
+};
+
+#ifdef DBUS_ENABLE_STATS
+static const MessageHandler stats_message_handlers[] = {
+  { "GetStats", "", "a{sv}", bus_stats_handle_get_stats },
+  { "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats },
+  { NULL, NULL, NULL, NULL }
+};
+#endif
+
+typedef struct {
+  const char *name;
+  const MessageHandler *message_handlers;
+  const char *extra_introspection;
+} InterfaceHandler;
+
+/* These should ideally be sorted by frequency of use, although it
+ * probably doesn't matter with this few items */
+static InterfaceHandler interface_handlers[] = {
+  { DBUS_INTERFACE_DBUS, dbus_message_handlers,
+    "    <signal name=\"NameOwnerChanged\">\n"
+    "      <arg type=\"s\"/>\n"
+    "      <arg type=\"s\"/>\n"
+    "      <arg type=\"s\"/>\n"
+    "    </signal>\n"
+    "    <signal name=\"NameLost\">\n"
+    "      <arg type=\"s\"/>\n"
+    "    </signal>\n"
+    "    <signal name=\"NameAcquired\">\n"
+    "      <arg type=\"s\"/>\n"
+    "    </signal>\n" },
+  { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL },
+#ifdef DBUS_ENABLE_STATS
+  { BUS_INTERFACE_STATS, stats_message_handlers, NULL },
+#endif
+  { NULL, NULL, NULL }
+};
+
+static dbus_bool_t
+write_args_for_direction (DBusString *xml,
+			  const char *signature,
+			  dbus_bool_t in)
+{
+  DBusTypeReader typereader;
+  DBusString sigstr;
+  int current_type;
+
+  _dbus_string_init_const (&sigstr, signature);
+  _dbus_type_reader_init_types_only (&typereader, &sigstr, 0);
+
+  while ((current_type = _dbus_type_reader_get_current_type (&typereader)) != DBUS_TYPE_INVALID)
+    {
+      const DBusString *subsig;
+      int start, len;
+
+      _dbus_type_reader_get_signature (&typereader, &subsig, &start, &len);
+      if (!_dbus_string_append_printf (xml, "      <arg direction=\"%s\" type=\"",
+				       in ? "in" : "out"))
+	goto oom;
+      if (!_dbus_string_append_len (xml,
+				    _dbus_string_get_const_data (subsig) + start,
+				    len))
+	goto oom;
+      if (!_dbus_string_append (xml, "\"/>\n"))
+	goto oom;
+
+      _dbus_type_reader_next (&typereader);
+    }
+  return TRUE;
+ oom:
+  return FALSE;
+}
+
+dbus_bool_t
+bus_driver_generate_introspect_string (DBusString *xml)
+{
+  const InterfaceHandler *ih;
+  const MessageHandler *mh;
+
+  if (!_dbus_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
+    return FALSE;
+  if (!_dbus_string_append (xml, "<node>\n"))
+    return FALSE;
+
+  for (ih = interface_handlers; ih->name != NULL; ih++)
+    {
+      if (!_dbus_string_append_printf (xml, "  <interface name=\"%s\">\n",
+                                       ih->name))
+        return FALSE;
+
+      for (mh = ih->message_handlers; mh->name != NULL; mh++)
+        {
+          if (!_dbus_string_append_printf (xml, "    <method name=\"%s\">\n",
+                                           mh->name))
+            return FALSE;
+
+          if (!write_args_for_direction (xml, mh->in_args, TRUE))
+            return FALSE;
+
+          if (!write_args_for_direction (xml, mh->out_args, FALSE))
+            return FALSE;
+
+          if (!_dbus_string_append (xml, "    </method>\n"))
+            return FALSE;
+        }
+
+      if (ih->extra_introspection != NULL &&
+          !_dbus_string_append (xml, ih->extra_introspection))
+        return FALSE;
+
+      if (!_dbus_string_append (xml, "  </interface>\n"))
+        return FALSE;
+    }
+
+  if (!_dbus_string_append (xml, "</node>\n"))
+    return FALSE;
+
+  return TRUE;
+}
+
+static dbus_bool_t
+bus_driver_handle_introspect (DBusConnection *connection,
+                              BusTransaction *transaction,
+                              DBusMessage    *message,
+                              DBusError      *error)
+{
+  DBusString xml;
+  DBusMessage *reply;
+  const char *v_STRING;
+
+  _dbus_verbose ("Introspect() on bus driver\n");
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  reply = NULL;
+
+  if (! dbus_message_get_args (message, error,
+			       DBUS_TYPE_INVALID))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&xml))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_driver_generate_introspect_string (&xml))
+    goto oom;
+
+  v_STRING = _dbus_string_get_const_data (&xml);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto oom;
+
+  if (! dbus_message_append_args (reply,
+                                  DBUS_TYPE_STRING, &v_STRING,
+                                  DBUS_TYPE_INVALID))
+    goto oom;
+
+  if (! bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+  _dbus_string_free (&xml);
+
+  return TRUE;
+
+ oom:
+  BUS_SET_OOM (error);
+
+  if (reply)
+    dbus_message_unref (reply);
+
+  _dbus_string_free (&xml);
+
+  return FALSE;
+}
+
+dbus_bool_t
+bus_driver_handle_message (DBusConnection *connection,
+                           BusTransaction *transaction,
+			   DBusMessage    *message,
+                           DBusError      *error)
+{
+  const char *name, *interface;
+  const InterfaceHandler *ih;
+  const MessageHandler *mh;
+  dbus_bool_t found_interface = FALSE;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (dbus_message_is_signal (message, "org.freedesktop.systemd1.Activator", "ActivationFailure"))
+    {
+      BusContext *context;
+
+      context = bus_connection_get_context (connection);
+      return dbus_activation_systemd_failure(bus_context_get_activation(context), message);
+    }
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
+    {
+      _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
+      return TRUE; /* we just ignore this */
+    }
+
+  /* may be NULL, which means "any interface will do" */
+  interface = dbus_message_get_interface (message);
+
+  _dbus_assert (dbus_message_get_member (message) != NULL);
+
+  name = dbus_message_get_member (message);
+
+  _dbus_verbose ("Driver got a method call: %s\n", name);
+
+  /* security checks should have kept this from getting here */
+#ifndef DBUS_DISABLE_ASSERT
+    {
+      const char *sender = dbus_message_get_sender (message);
+
+      _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
+    }
+#endif
+
+  for (ih = interface_handlers; ih->name != NULL; ih++)
+    {
+      if (interface != NULL && strcmp (interface, ih->name) != 0)
+        continue;
+
+      found_interface = TRUE;
+
+      for (mh = ih->message_handlers; mh->name != NULL; mh++)
+        {
+          if (strcmp (mh->name, name) != 0)
+            continue;
+
+          _dbus_verbose ("Found driver handler for %s\n", name);
+
+          if (!dbus_message_has_signature (message, mh->in_args))
+            {
+              _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+              _dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
+                             name, dbus_message_get_signature (message),
+                             mh->in_args);
+
+              dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                              "Call to %s has wrong args (%s, expected %s)\n",
+                              name, dbus_message_get_signature (message),
+                              mh->in_args);
+              _DBUS_ASSERT_ERROR_IS_SET (error);
+              return FALSE;
+            }
+
+          if ((* mh->handler) (connection, transaction, message, error))
+            {
+              _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+              _dbus_verbose ("Driver handler succeeded\n");
+              return TRUE;
+            }
+          else
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (error);
+              _dbus_verbose ("Driver handler returned failure\n");
+              return FALSE;
+            }
+        }
+    }
+
+  _dbus_verbose ("No driver handler for message \"%s\"\n",
+                 name);
+
+  dbus_set_error (error, found_interface ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_INTERFACE,
+                  "%s does not understand message %s",
+                  DBUS_SERVICE_DBUS, name);
+
+  return FALSE;
+}
+
+void
+bus_driver_remove_connection (DBusConnection *connection)
+{
+  /* FIXME 1.0 Does nothing for now, should unregister the connection
+   * with the bus driver.
+   */
+}
diff --git a/dbus/bus/driver.h b/dbus/bus/driver.h
new file mode 100644
index 0000000..713b276
--- /dev/null
+++ b/dbus/bus/driver.h
@@ -0,0 +1,52 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* driver.h  Bus client (driver)
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_DRIVER_H
+#define BUS_DRIVER_H
+
+#include <dbus/dbus.h>
+#include "connection.h"
+
+void        bus_driver_remove_connection     (DBusConnection *connection);
+dbus_bool_t bus_driver_handle_message        (DBusConnection *connection,
+                                              BusTransaction *transaction,
+                                              DBusMessage    *message,
+                                              DBusError      *error);
+dbus_bool_t bus_driver_send_service_lost     (DBusConnection *connection,
+                                              const char     *service_name,
+                                              BusTransaction *transaction,
+                                              DBusError      *error);
+dbus_bool_t bus_driver_send_service_acquired (DBusConnection *connection,
+                                              const char     *service_name,
+                                              BusTransaction *transaction,
+                                              DBusError      *error);
+dbus_bool_t bus_driver_send_service_owner_changed  (const char     *service_name,
+						    const char     *old_owner,
+						    const char     *new_owner,
+						    BusTransaction *transaction,
+						    DBusError      *error);
+dbus_bool_t bus_driver_generate_introspect_string  (DBusString *xml);
+
+
+
+#endif /* BUS_DRIVER_H */
diff --git a/dbus/bus/expirelist.c b/dbus/bus/expirelist.c
new file mode 100644
index 0000000..1a12ea4
--- /dev/null
+++ b/dbus/bus/expirelist.c
@@ -0,0 +1,402 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* expirelist.c  List of items that expire
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "expirelist.h"
+#include "test.h"
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-mainloop.h>
+#include <dbus/dbus-timeout.h>
+
+struct BusExpireList
+{
+  DBusList      *items; /**< List of BusExpireItem */
+  DBusTimeout   *timeout;
+  DBusLoop      *loop;
+  BusExpireFunc  expire_func;
+  void          *data;
+  int            expire_after; /**< Expire after milliseconds (thousandths) */
+};
+
+static dbus_bool_t expire_timeout_handler (void *data);
+
+BusExpireList*
+bus_expire_list_new (DBusLoop      *loop,
+                     int            expire_after,
+                     BusExpireFunc  expire_func,
+                     void          *data)
+{
+  BusExpireList *list;
+
+  list = dbus_new0 (BusExpireList, 1);
+  if (list == NULL)
+    return NULL;
+
+  list->expire_func = expire_func;
+  list->data = data;
+  list->loop = loop;
+  list->expire_after = expire_after;
+
+  list->timeout = _dbus_timeout_new (100, /* irrelevant */
+                                     expire_timeout_handler,
+                                     list, NULL);
+  if (list->timeout == NULL)
+    goto failed;
+
+  _dbus_timeout_set_enabled (list->timeout, FALSE);
+
+  if (!_dbus_loop_add_timeout (list->loop, list->timeout))
+    goto failed;
+
+  return list;
+
+ failed:
+  if (list->timeout)
+    _dbus_timeout_unref (list->timeout);
+
+  dbus_free (list);
+
+  return NULL;
+}
+
+void
+bus_expire_list_free (BusExpireList *list)
+{
+  _dbus_assert (list->items == NULL);
+
+  _dbus_loop_remove_timeout (list->loop, list->timeout);
+
+  _dbus_timeout_unref (list->timeout);
+
+  dbus_free (list);
+}
+
+void
+bus_expire_timeout_set_interval (DBusTimeout   *timeout,
+                                 int            next_interval)
+{
+  if (next_interval >= 0)
+    {
+      _dbus_timeout_set_interval (timeout,
+                                  next_interval);
+      _dbus_timeout_set_enabled (timeout, TRUE);
+
+      _dbus_verbose ("Enabled an expire timeout with interval %d\n",
+                     next_interval);
+    }
+  else if (dbus_timeout_get_enabled (timeout))
+    {
+      _dbus_timeout_set_enabled (timeout, FALSE);
+
+      _dbus_verbose ("Disabled an expire timeout\n");
+    }
+  else
+    _dbus_verbose ("No need to disable this expire timeout\n");
+}
+
+void
+bus_expire_list_recheck_immediately (BusExpireList *list)
+{
+  _dbus_verbose ("setting interval on expire list to 0 for immediate recheck\n");
+
+  bus_expire_timeout_set_interval (list->timeout, 0);
+}
+
+static int
+do_expiration_with_monotonic_time (BusExpireList *list,
+                                   long           tv_sec,
+                                   long           tv_usec)
+{
+  DBusList *link;
+  int next_interval, min_wait_time, items_to_expire;
+
+  next_interval = -1;
+  min_wait_time = 3600 * 1000; /* this is reset anyway if used */
+  items_to_expire = 0;
+  
+  link = _dbus_list_get_first_link (&list->items);
+  while (link != NULL)
+    {
+      DBusList *next = _dbus_list_get_next_link (&list->items, link);
+      double elapsed;
+      BusExpireItem *item;
+
+      item = link->data;
+
+      elapsed = ELAPSED_MILLISECONDS_SINCE (item->added_tv_sec,
+                                            item->added_tv_usec,
+                                            tv_sec, tv_usec);
+
+      if (((item->added_tv_sec == 0) && (item->added_tv_usec == 0)) ||
+          ((list->expire_after > 0) && (elapsed >= (double) list->expire_after)))
+        {
+          _dbus_verbose ("Expiring an item %p\n", item);
+
+          /* If the expire function fails, we just end up expiring
+           * this item next time we walk through the list. This would
+           * be an indeterminate time normally, so we set up the
+           * next_interval to be "shortly" (just enough to avoid
+           * a busy loop)
+           */
+          if (!(* list->expire_func) (list, link, list->data))
+            {
+              next_interval = _dbus_get_oom_wait ();
+              break;
+            }
+        }
+      else if (list->expire_after > 0)
+        {
+          double to_wait;
+
+          items_to_expire = 1;
+          to_wait = (double) list->expire_after - elapsed;
+          if (min_wait_time > to_wait)
+            min_wait_time = to_wait;
+        }
+
+      link = next;
+    }
+
+  if (next_interval < 0 && items_to_expire)
+    next_interval = min_wait_time;
+
+  return next_interval;
+}
+
+static void
+bus_expirelist_expire (BusExpireList *list)
+{
+  int next_interval;
+
+  next_interval = -1;
+
+  if (list->items != NULL)
+    {
+      long tv_sec, tv_usec;
+
+      _dbus_get_monotonic_time (&tv_sec, &tv_usec);
+
+      next_interval = do_expiration_with_monotonic_time (list, tv_sec, tv_usec);
+    }
+
+  bus_expire_timeout_set_interval (list->timeout, next_interval);
+}
+
+static dbus_bool_t
+expire_timeout_handler (void *data)
+{
+  BusExpireList *list = data;
+
+  _dbus_verbose ("Running\n");
+
+  /* note that this may remove the timeout */
+  bus_expirelist_expire (list);
+
+  return TRUE;
+}
+
+void
+bus_expire_list_remove_link (BusExpireList *list,
+                             DBusList      *link)
+{
+  _dbus_list_remove_link (&list->items, link);
+}
+
+dbus_bool_t
+bus_expire_list_remove (BusExpireList *list,
+                        BusExpireItem *item)
+{
+  return _dbus_list_remove (&list->items, item);
+}
+
+void
+bus_expire_list_unlink (BusExpireList *list,
+                        DBusList      *link)
+{
+  _dbus_list_unlink (&list->items, link);
+}
+
+dbus_bool_t
+bus_expire_list_add (BusExpireList *list,
+                     BusExpireItem *item)
+{
+  dbus_bool_t ret;
+
+  ret = _dbus_list_prepend (&list->items, item);
+  if (ret && !dbus_timeout_get_enabled (list->timeout))
+    bus_expire_timeout_set_interval (list->timeout, 0);
+
+  return ret;
+}
+
+void
+bus_expire_list_add_link (BusExpireList *list,
+                          DBusList      *link)
+{
+  _dbus_assert (link->data != NULL);
+  
+  _dbus_list_prepend_link (&list->items, link);
+
+  if (!dbus_timeout_get_enabled (list->timeout))
+    bus_expire_timeout_set_interval (list->timeout, 0);
+}
+
+DBusList*
+bus_expire_list_get_first_link (BusExpireList *list)
+{
+  return _dbus_list_get_first_link (&list->items);
+}
+
+DBusList*
+bus_expire_list_get_next_link (BusExpireList *list,
+                               DBusList      *link)
+{
+  return _dbus_list_get_next_link (&list->items, link);
+}
+
+dbus_bool_t
+bus_expire_list_contains_item (BusExpireList *list,
+                               BusExpireItem *item)
+{
+  return _dbus_list_find_last (&list->items, item) != NULL;
+}
+
+#ifdef DBUS_BUILD_TESTS
+
+typedef struct
+{
+  BusExpireItem item;
+  int expire_count;
+} TestExpireItem;
+
+static dbus_bool_t
+test_expire_func (BusExpireList *list,
+                  DBusList      *link,
+                  void          *data)
+{
+  TestExpireItem *t;
+
+  t = (TestExpireItem*) link->data;
+
+  t->expire_count += 1;
+
+  return TRUE;
+}
+
+static void
+time_add_milliseconds (long *tv_sec,
+                       long *tv_usec,
+                       int   milliseconds)
+{
+  *tv_sec = *tv_sec + milliseconds / 1000;
+  *tv_usec = *tv_usec + milliseconds * 1000;
+  if (*tv_usec >= 1000000)
+    {
+      *tv_usec -= 1000000;
+      *tv_sec += 1;
+    }
+}
+
+dbus_bool_t
+bus_expire_list_test (const DBusString *test_data_dir)
+{
+  DBusLoop *loop;
+  BusExpireList *list;
+  long tv_sec, tv_usec;
+  long tv_sec_not_expired, tv_usec_not_expired;
+  long tv_sec_expired, tv_usec_expired;
+  long tv_sec_past, tv_usec_past;
+  TestExpireItem *item;
+  int next_interval;
+  dbus_bool_t result = FALSE;
+
+
+  loop = _dbus_loop_new ();
+  _dbus_assert (loop != NULL);
+
+#define EXPIRE_AFTER 100
+  
+  list = bus_expire_list_new (loop, EXPIRE_AFTER,
+                              test_expire_func, NULL);
+  _dbus_assert (list != NULL);
+
+  _dbus_get_monotonic_time (&tv_sec, &tv_usec);
+
+  tv_sec_not_expired = tv_sec;
+  tv_usec_not_expired = tv_usec;
+  time_add_milliseconds (&tv_sec_not_expired,
+                         &tv_usec_not_expired, EXPIRE_AFTER - 1);
+
+  tv_sec_expired = tv_sec;
+  tv_usec_expired = tv_usec;
+  time_add_milliseconds (&tv_sec_expired,
+                         &tv_usec_expired, EXPIRE_AFTER);
+  
+
+  tv_sec_past = tv_sec - 1;
+  tv_usec_past = tv_usec;
+
+  item = dbus_new0 (TestExpireItem, 1);
+
+  if (item == NULL)
+    goto oom;
+
+  item->item.added_tv_sec = tv_sec;
+  item->item.added_tv_usec = tv_usec;
+  if (!bus_expire_list_add (list, &item->item))
+    _dbus_assert_not_reached ("out of memory");
+
+  next_interval =
+    do_expiration_with_monotonic_time (list, tv_sec_not_expired,
+                                       tv_usec_not_expired);
+  _dbus_assert (item->expire_count == 0);
+  _dbus_verbose ("next_interval = %d\n", next_interval);
+  _dbus_assert (next_interval == 1);
+  
+  next_interval =
+    do_expiration_with_monotonic_time (list, tv_sec_expired,
+                                       tv_usec_expired);
+  _dbus_assert (item->expire_count == 1);
+  _dbus_verbose ("next_interval = %d\n", next_interval);
+  _dbus_assert (next_interval == -1);
+
+  next_interval =
+    do_expiration_with_monotonic_time (list, tv_sec_past,
+                                       tv_usec_past);
+  _dbus_assert (item->expire_count == 1);
+  _dbus_verbose ("next_interval = %d\n", next_interval);
+  _dbus_assert (next_interval == 1000 + EXPIRE_AFTER);
+
+  bus_expire_list_remove (list, &item->item);
+  dbus_free (item);
+  
+  bus_expire_list_free (list);
+  _dbus_loop_unref (loop);
+  
+  result = TRUE;
+
+ oom:
+  return result;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/bus/expirelist.h b/dbus/bus/expirelist.h
new file mode 100644
index 0000000..887cb97
--- /dev/null
+++ b/dbus/bus/expirelist.h
@@ -0,0 +1,80 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* expirelist.h  List of stuff that expires
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef BUS_EXPIRE_LIST_H
+#define BUS_EXPIRE_LIST_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-mainloop.h>
+
+typedef struct BusExpireList BusExpireList;
+typedef struct BusExpireItem BusExpireItem;
+
+typedef dbus_bool_t (* BusExpireFunc) (BusExpireList *list,
+                                       DBusList      *link,
+                                       void          *data);
+
+
+/* embed this in a child expire item struct */
+struct BusExpireItem
+{
+  long added_tv_sec;  /**< Time we were added (seconds component) */
+  long added_tv_usec; /**< Time we were added (microsec component) */
+};
+
+BusExpireList* bus_expire_list_new                 (DBusLoop      *loop,
+                                                    int            expire_after,
+                                                    BusExpireFunc  expire_func,
+                                                    void          *data);
+void           bus_expire_list_free                (BusExpireList *list);
+void           bus_expire_list_recheck_immediately (BusExpireList *list);
+void           bus_expire_list_remove_link         (BusExpireList *list,
+                                                    DBusList      *link);
+dbus_bool_t    bus_expire_list_remove              (BusExpireList *list,
+                                                    BusExpireItem *item);
+DBusList*      bus_expire_list_get_first_link      (BusExpireList *list);
+DBusList*      bus_expire_list_get_next_link       (BusExpireList *list,
+                                                    DBusList      *link);
+dbus_bool_t    bus_expire_list_add                 (BusExpireList *list,
+                                                    BusExpireItem *item);
+void           bus_expire_list_add_link            (BusExpireList *list,
+                                                    DBusList      *link);
+dbus_bool_t    bus_expire_list_contains_item       (BusExpireList *list,
+                                                    BusExpireItem *item);
+void           bus_expire_list_unlink              (BusExpireList *list,
+                                                    DBusList      *link);
+
+/* this macro and function are semi-related utility functions, not really part of the
+ * BusExpireList API
+ */
+
+#define ELAPSED_MILLISECONDS_SINCE(orig_tv_sec, orig_tv_usec,   \
+                                   now_tv_sec, now_tv_usec)     \
+ (((double) (now_tv_sec) - (double) (orig_tv_sec)) * 1000.0 +   \
+ ((double) (now_tv_usec) - (double) (orig_tv_usec)) / 1000.0)
+
+void bus_expire_timeout_set_interval (DBusTimeout   *timeout,
+                                      int            next_interval);
+
+#endif /* BUS_EXPIRE_LIST_H */
diff --git a/dbus/bus/main.c b/dbus/bus/main.c
new file mode 100644
index 0000000..ca0be3c
--- /dev/null
+++ b/dbus/bus/main.c
@@ -0,0 +1,641 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* main.c  main() for message bus
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "bus.h"
+#include "driver.h"
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-watch.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>     /* for write() and STDERR_FILENO */
+#endif
+#include "selinux.h"
+
+static BusContext *context;
+
+#ifdef DBUS_UNIX
+
+static int reload_pipe[2];
+#define RELOAD_READ_END 0
+#define RELOAD_WRITE_END 1
+
+static void close_reload_pipe (DBusWatch **);
+
+typedef enum
+ {
+   ACTION_RELOAD = 'r',
+   ACTION_QUIT = 'q'
+ } SignalAction;
+
+static void
+signal_handler (int sig)
+{
+  switch (sig)
+    {
+#ifdef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX
+    case SIGIO:
+      /* explicit fall-through */
+#endif /* DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX  */
+#ifdef SIGHUP
+    case SIGHUP:
+      {
+        DBusString str;
+        char action[2] = { ACTION_RELOAD, '\0' };
+
+        _dbus_string_init_const (&str, action);
+        if ((reload_pipe[RELOAD_WRITE_END] > 0) &&
+            !_dbus_write_socket (reload_pipe[RELOAD_WRITE_END], &str, 0, 1))
+          {
+            /* If we receive SIGHUP often enough to fill the pipe buffer (4096
+             * times on old Linux, 65536 on modern Linux) before it can be
+             * drained, let's just warn and ignore. The configuration will be
+             * reloaded while draining the pipe buffer, which is what we
+             * wanted. It's harmless that it will be reloaded fewer times than
+             * we asked for, since the reload is delayed anyway, so new changes
+             * will be picked up.
+             *
+             * We use write() because _dbus_warn uses vfprintf, which isn't
+             * async-signal-safe.
+             *
+             * This is necessarily Unix-specific, but so are POSIX signals,
+             * so... */
+            static const char message[] =
+              "Unable to write to reload pipe - buffer full?\n";
+
+            write (STDERR_FILENO, message, strlen (message));
+          }
+      }
+      break;
+#endif
+
+    case SIGTERM:
+      {
+        DBusString str;
+        char action[2] = { ACTION_QUIT, '\0' };
+        _dbus_string_init_const (&str, action);
+        if ((reload_pipe[RELOAD_WRITE_END] < 0) ||
+            !_dbus_write_socket (reload_pipe[RELOAD_WRITE_END], &str, 0, 1))
+          {
+            /* If we can't write to the socket, dying seems a more
+             * important response to SIGTERM than cleaning up sockets,
+             * so we exit. We'd use exit(), but that's not async-signal-safe,
+             * so we'll have to resort to _exit(). */
+            static const char message[] =
+              "Unable to write termination signal to pipe - buffer full?\n"
+              "Will exit instead.\n";
+
+            write (STDERR_FILENO, message, strlen (message));
+            _exit (1);
+          }
+      }
+      break;
+    }
+}
+#endif /* DBUS_UNIX */
+
+static void
+usage (void)
+{
+  fprintf (stderr, DBUS_DAEMON_NAME " [--version] [--session] [--system] [--config-file=FILE] [--print-address[=DESCRIPTOR]] [--print-pid[=DESCRIPTOR]] [--fork] [--nofork] [--introspect] [--address=ADDRESS] [--systemd-activation] [--nopidfile]\n");
+  exit (1);
+}
+
+static void
+version (void)
+{
+  printf ("D-Bus Message Bus Daemon %s\n"
+          "Copyright (C) 2002, 2003 Red Hat, Inc., CodeFactory AB, and others\n"
+          "This is free software; see the source for copying conditions.\n"
+          "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
+          DBUS_VERSION_STRING);
+  exit (0);
+}
+
+static void
+introspect (void)
+{
+  DBusString xml;
+  const char *v_STRING;
+
+  if (!_dbus_string_init (&xml))
+    goto oom;
+
+  if (!bus_driver_generate_introspect_string (&xml))
+    {
+      _dbus_string_free (&xml);
+      goto oom;
+    }
+
+  v_STRING = _dbus_string_get_const_data (&xml);
+  printf ("%s\n", v_STRING);
+
+  exit (0);
+
+ oom:
+  _dbus_warn ("Can not introspect - Out of memory\n");
+  exit (1);
+}
+
+static void
+check_two_config_files (const DBusString *config_file,
+                        const char       *extra_arg)
+{
+  if (_dbus_string_get_length (config_file) > 0)
+    {
+      fprintf (stderr, "--%s specified but configuration file %s already requested\n",
+               extra_arg, _dbus_string_get_const_data (config_file));
+      exit (1);
+    }
+}
+
+static void
+check_two_addresses (const DBusString *address,
+                     const char       *extra_arg)
+{
+  if (_dbus_string_get_length (address) > 0)
+    {
+      fprintf (stderr, "--%s specified but address %s already requested\n",
+               extra_arg, _dbus_string_get_const_data (address));
+      exit (1);
+    }
+}
+
+static void
+check_two_addr_descriptors (const DBusString *addr_fd,
+                            const char       *extra_arg)
+{
+  if (_dbus_string_get_length (addr_fd) > 0)
+    {
+      fprintf (stderr, "--%s specified but printing address to %s already requested\n",
+               extra_arg, _dbus_string_get_const_data (addr_fd));
+      exit (1);
+    }
+}
+
+static void
+check_two_pid_descriptors (const DBusString *pid_fd,
+                           const char       *extra_arg)
+{
+  if (_dbus_string_get_length (pid_fd) > 0)
+    {
+      fprintf (stderr, "--%s specified but printing pid to %s already requested\n",
+               extra_arg, _dbus_string_get_const_data (pid_fd));
+      exit (1);
+    }
+}
+
+#ifdef DBUS_UNIX
+static dbus_bool_t
+handle_reload_watch (DBusWatch    *watch,
+		     unsigned int  flags,
+		     void         *data)
+{
+  DBusError error;
+  DBusString str;
+  char *action_str;
+  char action = '\0';
+
+  while (!_dbus_string_init (&str))
+    _dbus_wait_for_memory ();
+
+  if ((reload_pipe[RELOAD_READ_END] > 0) &&
+      _dbus_read_socket (reload_pipe[RELOAD_READ_END], &str, 1) != 1)
+    {
+      _dbus_warn ("Couldn't read from reload pipe.\n");
+      close_reload_pipe (&watch);
+      return TRUE;
+    }
+
+  action_str = _dbus_string_get_data (&str);
+  if (action_str != NULL)
+    {
+      action = action_str[0];
+    }
+  _dbus_string_free (&str);
+
+  /* this can only fail if we don't understand the config file
+   * or OOM.  Either way we should just stick with the currently
+   * loaded config.
+   */
+  dbus_error_init (&error);
+
+  switch (action)
+    {
+    case ACTION_RELOAD:
+      if (! bus_context_reload_config (context, &error))
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (&error);
+          _dbus_assert (dbus_error_has_name (&error, DBUS_ERROR_FAILED) ||
+                        dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY));
+          _dbus_warn ("Unable to reload configuration: %s\n",
+                      error.message);
+          dbus_error_free (&error);
+        }
+      break;
+
+    case ACTION_QUIT:
+      {
+        DBusLoop *loop;
+        /*
+         * On OSs without abstract sockets, we want to quit
+         * gracefully rather than being killed by SIGTERM,
+         * so that DBusServer gets a chance to clean up the
+         * sockets from the filesystem. fd.o #38656
+         */
+        loop = bus_context_get_loop (context);
+        if (loop != NULL)
+          {
+            _dbus_loop_quit (loop);
+          }
+      }
+      break;
+
+    default:
+      break;
+    }
+
+  return TRUE;
+}
+
+static void
+setup_reload_pipe (DBusLoop *loop)
+{
+  DBusError error;
+  DBusWatch *watch;
+
+  dbus_error_init (&error);
+
+  if (!_dbus_full_duplex_pipe (&reload_pipe[0], &reload_pipe[1],
+			       TRUE, &error))
+    {
+      _dbus_warn ("Unable to create reload pipe: %s\n",
+		  error.message);
+      dbus_error_free (&error);
+      exit (1);
+    }
+
+  watch = _dbus_watch_new (reload_pipe[RELOAD_READ_END],
+			   DBUS_WATCH_READABLE, TRUE,
+			   handle_reload_watch, NULL, NULL);
+
+  if (watch == NULL)
+    {
+      _dbus_warn ("Unable to create reload watch: %s\n",
+		  error.message);
+      dbus_error_free (&error);
+      exit (1);
+    }
+
+  if (!_dbus_loop_add_watch (loop, watch))
+    {
+      _dbus_warn ("Unable to add reload watch to main loop: %s\n",
+		  error.message);
+      dbus_error_free (&error);
+      exit (1);
+    }
+
+}
+
+static void
+close_reload_pipe (DBusWatch **watch)
+{
+    _dbus_loop_remove_watch (bus_context_get_loop (context), *watch);
+    _dbus_watch_invalidate (*watch);
+    _dbus_watch_unref (*watch);
+    *watch = NULL;
+
+    _dbus_close_socket (reload_pipe[RELOAD_READ_END], NULL);
+    reload_pipe[RELOAD_READ_END] = -1;
+
+    _dbus_close_socket (reload_pipe[RELOAD_WRITE_END], NULL);
+    reload_pipe[RELOAD_WRITE_END] = -1;
+}
+#endif /* DBUS_UNIX */
+
+int
+main (int argc, char **argv)
+{
+  DBusError error;
+  DBusString config_file;
+  DBusString address;
+  DBusString addr_fd;
+  DBusString pid_fd;
+  const char *prev_arg;
+  DBusPipe print_addr_pipe;
+  DBusPipe print_pid_pipe;
+  int i;
+  dbus_bool_t print_address;
+  dbus_bool_t print_pid;
+  BusContextFlags flags;
+
+  if (!_dbus_string_init (&config_file))
+    return 1;
+
+  if (!_dbus_string_init (&address))
+    return 1;
+
+  if (!_dbus_string_init (&addr_fd))
+    return 1;
+
+  if (!_dbus_string_init (&pid_fd))
+    return 1;
+
+  print_address = FALSE;
+  print_pid = FALSE;
+
+  flags = BUS_CONTEXT_FLAG_WRITE_PID_FILE;
+
+  prev_arg = NULL;
+  i = 1;
+  while (i < argc)
+    {
+      const char *arg = argv[i];
+
+      if (strcmp (arg, "--help") == 0 ||
+          strcmp (arg, "-h") == 0 ||
+          strcmp (arg, "-?") == 0)
+        {
+          usage ();
+        }
+      else if (strcmp (arg, "--version") == 0)
+        {
+          version ();
+        }
+      else if (strcmp (arg, "--introspect") == 0)
+        {
+          introspect ();
+        }
+      else if (strcmp (arg, "--nofork") == 0)
+        {
+          flags &= ~BUS_CONTEXT_FLAG_FORK_ALWAYS;
+          flags |= BUS_CONTEXT_FLAG_FORK_NEVER;
+        }
+      else if (strcmp (arg, "--fork") == 0)
+        {
+          flags &= ~BUS_CONTEXT_FLAG_FORK_NEVER;
+          flags |= BUS_CONTEXT_FLAG_FORK_ALWAYS;
+        }
+      else if (strcmp (arg, "--nopidfile") == 0)
+        {
+          flags &= ~BUS_CONTEXT_FLAG_WRITE_PID_FILE;
+        }
+      else if (strcmp (arg, "--systemd-activation") == 0)
+        {
+          flags |= BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION;
+        }
+      else if (strcmp (arg, "--system") == 0)
+        {
+          check_two_config_files (&config_file, "system");
+
+          if (!_dbus_append_system_config_file (&config_file))
+            exit (1);
+        }
+      else if (strcmp (arg, "--session") == 0)
+        {
+          check_two_config_files (&config_file, "session");
+
+          if (!_dbus_append_session_config_file (&config_file))
+            exit (1);
+        }
+      else if (strstr (arg, "--config-file=") == arg)
+        {
+          const char *file;
+
+          check_two_config_files (&config_file, "config-file");
+
+          file = strchr (arg, '=');
+          ++file;
+
+          if (!_dbus_string_append (&config_file, file))
+            exit (1);
+        }
+      else if (prev_arg &&
+               strcmp (prev_arg, "--config-file") == 0)
+        {
+          check_two_config_files (&config_file, "config-file");
+
+          if (!_dbus_string_append (&config_file, arg))
+            exit (1);
+        }
+      else if (strcmp (arg, "--config-file") == 0)
+        {
+          /* wait for next arg */
+        }
+      else if (strstr (arg, "--address=") == arg)
+        {
+          const char *file;
+
+          check_two_addresses (&address, "address");
+
+          file = strchr (arg, '=');
+          ++file;
+
+          if (!_dbus_string_append (&address, file))
+            exit (1);
+        }
+      else if (prev_arg &&
+               strcmp (prev_arg, "--address") == 0)
+        {
+          check_two_addresses (&address, "address");
+
+          if (!_dbus_string_append (&address, arg))
+            exit (1);
+        }
+      else if (strcmp (arg, "--address") == 0)
+        {
+          /* wait for next arg */
+        }
+      else if (strstr (arg, "--print-address=") == arg)
+        {
+          const char *desc;
+
+          check_two_addr_descriptors (&addr_fd, "print-address");
+
+          desc = strchr (arg, '=');
+          ++desc;
+
+          if (!_dbus_string_append (&addr_fd, desc))
+            exit (1);
+
+          print_address = TRUE;
+        }
+      else if (prev_arg &&
+               strcmp (prev_arg, "--print-address") == 0)
+        {
+          check_two_addr_descriptors (&addr_fd, "print-address");
+
+          if (!_dbus_string_append (&addr_fd, arg))
+            exit (1);
+
+          print_address = TRUE;
+        }
+      else if (strcmp (arg, "--print-address") == 0)
+        {
+          print_address = TRUE; /* and we'll get the next arg if appropriate */
+        }
+      else if (strstr (arg, "--print-pid=") == arg)
+        {
+          const char *desc;
+
+          check_two_pid_descriptors (&pid_fd, "print-pid");
+
+          desc = strchr (arg, '=');
+          ++desc;
+
+          if (!_dbus_string_append (&pid_fd, desc))
+            exit (1);
+
+          print_pid = TRUE;
+        }
+      else if (prev_arg &&
+               strcmp (prev_arg, "--print-pid") == 0)
+        {
+          check_two_pid_descriptors (&pid_fd, "print-pid");
+
+          if (!_dbus_string_append (&pid_fd, arg))
+            exit (1);
+
+          print_pid = TRUE;
+        }
+      else if (strcmp (arg, "--print-pid") == 0)
+        {
+          print_pid = TRUE; /* and we'll get the next arg if appropriate */
+        }
+      else
+        {
+          usage ();
+        }
+
+      prev_arg = arg;
+
+      ++i;
+    }
+
+  if (_dbus_string_get_length (&config_file) == 0)
+    {
+      fprintf (stderr, "No configuration file specified.\n");
+      usage ();
+    }
+
+  _dbus_pipe_invalidate (&print_addr_pipe);
+  if (print_address)
+    {
+      _dbus_pipe_init_stdout (&print_addr_pipe);
+      if (_dbus_string_get_length (&addr_fd) > 0)
+        {
+          long val;
+          int end;
+          if (!_dbus_string_parse_int (&addr_fd, 0, &val, &end) ||
+              end != _dbus_string_get_length (&addr_fd) ||
+              val < 0 || val > _DBUS_INT_MAX)
+            {
+              fprintf (stderr, "Invalid file descriptor: \"%s\"\n",
+                       _dbus_string_get_const_data (&addr_fd));
+              exit (1);
+            }
+
+          _dbus_pipe_init (&print_addr_pipe, val);
+        }
+    }
+  _dbus_string_free (&addr_fd);
+
+  _dbus_pipe_invalidate (&print_pid_pipe);
+  if (print_pid)
+    {
+      _dbus_pipe_init_stdout (&print_pid_pipe);
+      if (_dbus_string_get_length (&pid_fd) > 0)
+        {
+          long val;
+          int end;
+          if (!_dbus_string_parse_int (&pid_fd, 0, &val, &end) ||
+              end != _dbus_string_get_length (&pid_fd) ||
+              val < 0 || val > _DBUS_INT_MAX)
+            {
+              fprintf (stderr, "Invalid file descriptor: \"%s\"\n",
+                       _dbus_string_get_const_data (&pid_fd));
+              exit (1);
+            }
+
+          _dbus_pipe_init (&print_pid_pipe, val);
+        }
+    }
+  _dbus_string_free (&pid_fd);
+
+  if (!bus_selinux_pre_init ())
+    {
+      _dbus_warn ("SELinux pre-initialization failed\n");
+      exit (1);
+    }
+
+  dbus_error_init (&error);
+  context = bus_context_new (&config_file, flags,
+                             &print_addr_pipe, &print_pid_pipe,
+                             _dbus_string_get_length(&address) > 0 ? &address : NULL,
+                             &error);
+  _dbus_string_free (&config_file);
+  if (context == NULL)
+    {
+      _dbus_warn ("Failed to start message bus: %s\n",
+                  error.message);
+      dbus_error_free (&error);
+      exit (1);
+    }
+
+  /* bus_context_new() closes the print_addr_pipe and
+   * print_pid_pipe
+   */
+
+#ifdef DBUS_UNIX
+  setup_reload_pipe (bus_context_get_loop (context));
+
+  /* POSIX signals are Unix-specific, and _dbus_set_signal_handler is
+   * unimplemented (and probably unimplementable) on Windows, so there's
+   * no point in trying to make the handler portable to non-Unix. */
+
+  _dbus_set_signal_handler (SIGTERM, signal_handler);
+#ifdef SIGHUP
+  _dbus_set_signal_handler (SIGHUP, signal_handler);
+#endif
+#ifdef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX
+  _dbus_set_signal_handler (SIGIO, signal_handler);
+#endif /* DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX */
+#endif /* DBUS_UNIX */
+
+  _dbus_verbose ("We are on D-Bus...\n");
+  _dbus_loop_run (bus_context_get_loop (context));
+
+  bus_context_shutdown (context);
+  bus_context_unref (context);
+  bus_selinux_shutdown ();
+
+  return 0;
+}
diff --git a/dbus/bus/messagebus-config.in b/dbus/bus/messagebus-config.in
new file mode 100644
index 0000000..39459dc
--- /dev/null
+++ b/dbus/bus/messagebus-config.in
@@ -0,0 +1,178 @@
+#!/bin/sh
+#
+# messagebus-config, Copyright 2009 Yaakov Selkowitz
+#
+# This file is part of the Cygwin port of dbus.
+
+# ======================================================================
+# Initialization
+# ======================================================================
+PROGNAME=$(basename $0)
+_tdir=$(dirname $0)
+PROGDIR=$(cd $_tdir && pwd)
+
+CSIH_SCRIPT=/usr/share/csih/cygwin-service-installation-helper.sh
+
+# Subdirectory where the new package is being installed
+PREFIX=@prefix@
+
+# Directory where the config files are stored
+SYSCONFDIR=@sysconfdir@/dbus-1
+DEVDIR=/dev
+LOGDIR=/var/log
+RUNDIR=$(dirname @DBUS_SYSTEM_PID_FILE@)
+SOCKDIR=$(dirname @DBUS_SYSTEM_SOCKET@)
+
+source ${CSIH_SCRIPT}
+
+# ======================================================================
+# Routine: install_service
+#   Install messagebus as a service
+# ======================================================================
+install_service() {
+
+  if csih_is_nt
+  then
+
+    # Check if messagebus is installed and remove on user request.
+    if cygrunsrv -Q messagebus > /dev/null 2>&1
+    then
+      csih_warning "The messagebus service is already installed."
+      echo
+      if csih_request "Do you want to reinstall it with different args?"
+      then
+        cygrunsrv -E messagebus
+        cygrunsrv -R messagebus
+      fi
+    fi
+
+    # Install messagebus service if it is not already installed
+    if ! cygrunsrv -Q messagebus > /dev/null 2>&1
+    then
+      echo
+      csih_warning "The following function requires administrator privileges!"
+      if csih_request "Do you want to install messagebus as service?"
+      then
+        if cygrunsrv -I messagebus -d "CYGWIN D-Bus system service" -p @EXPANDED_BINDIR@/dbus-daemon -a "--nofork --system"
+        then
+	  echo
+	  csih_inform "The messagebus service has been installed under the LocalSystem"
+	  csih_inform "account (also known as SYSTEM). To start the service now, call"
+          csih_inform "\`net start messagebus' or \`cygrunsrv -S messagebus'. Otherwise, it"
+          csih_inform "will start automatically after the next reboot."
+	  echo
+	  csih_inform "Check ${SYSCONFDIR}/system.conf first, if it suits your needs."
+        fi
+      fi # user allowed us to install messagebus
+    fi # messagebus already installed
+  fi # csih_is_nt
+} # --- End of install_service --- #
+
+
+# ======================================================================
+# Main Entry Point
+# ======================================================================
+
+
+# Check how the script has been started.  If
+#   (1) it has been started by giving the full path and
+#       that path is /etc/postinstall, OR
+#   (2) Otherwise, if the environment variable
+#       CONFIG_AUTO_ANSWER_NO is set
+# then set auto_answer to "no".  This allows automatic
+# creation of the config files in /etc w/o overwriting
+# them if they already exist.  In both cases, color
+# escape sequences are suppressed, so as to prevent
+# cluttering setup's logfiles.
+if [ "$PROGDIR" = "/etc/postinstall" ]
+then
+  csih_auto_answer="no"
+  csih_disable_color
+fi
+if [ -n "${CONFIG_AUTO_ANSWER_NO}" ]
+then
+  csih_auto_answer="no"
+  csih_disable_color
+fi
+
+
+# ======================================================================
+# Parse options
+# ======================================================================
+while :
+do
+  case $# in
+  0)
+    break
+    ;;
+  esac
+
+  option=$1
+  shift
+
+  case "$option" in
+  -d | --debug )
+    set -x
+    csih_trace_on
+    ;;
+
+  -y | --yes )
+    csih_auto_answer=yes
+    ;;
+
+  -n | --no )
+    csih_auto_answer=no
+    ;;
+
+  *)
+    echo "usage: ${PROGNAME} [OPTION]..."
+    echo
+    echo "This script creates a basic messagebus configuration."
+    echo
+    echo "Options:"
+    echo "    --debug  -d     Enable shell's debug output."
+    echo "    --yes    -y     Answer all questions with \"yes\" automatically."
+    echo "    --no     -n     Answer all questions with \"no\" automatically."
+    echo
+    exit 1
+    ;;
+
+  esac
+done
+
+# ======================================================================
+# Action!
+# ======================================================================
+
+# Check for ${SYSCONFDIR} directory
+csih_make_dir "${SYSCONFDIR}" "Cannot create global configuration files."
+chmod 775 "${SYSCONFDIR}"
+setfacl -m u:system:rwx "${SYSCONFDIR}"
+
+# Check for ${DEVDIR} directory
+csih_make_dir "${DEVDIR}" "Syslogging using messagebus will not work."
+chmod 775 "${DEVDIR}"
+setfacl -m u:system:rwx "${DEVDIR}"
+
+# Check for ${LOGDIR} directory
+csih_make_dir "${LOGDIR}" "Syslogging using messagebus will not work."
+chmod 775 "${LOGDIR}"
+setfacl -m u:system:rwx "${LOGDIR}"
+
+# Check for ${RUNDIR} directory
+csih_make_dir "${RUNDIR}" "PID files of running processes will not be created."
+chmod 775 "${RUNDIR}"
+setfacl -m u:system:rwx "${RUNDIR}"
+
+# Check for ${SOCKDIR} directory
+csih_make_dir "${SOCKDIR}" "SOCKET files of running processes will not be created."
+chmod 775 "${SOCKDIR}"
+setfacl -m u:system:rwx "${SOCKDIR}"
+
+# maybe: csih_auto_answer=no will skip,
+# interactive user will get a chance to override
+install_service
+
+
+echo
+echo "Configuration finished. Have fun!"
diff --git a/dbus/bus/messagebus.in b/dbus/bus/messagebus.in
new file mode 100644
index 0000000..3e2ee07
--- /dev/null
+++ b/dbus/bus/messagebus.in
@@ -0,0 +1,92 @@
+#!/bin/sh
+#
+# messagebus:   The D-BUS systemwide message bus
+#
+# chkconfig: 345 22 85
+# description:  This is a daemon which broadcasts notifications of system events \
+#               and other messages. See http://www.freedesktop.org/software/dbus/
+#
+# processname: dbus-daemon
+# pidfile: @DBUS_SYSTEM_PID_FILE@
+#
+### BEGIN INIT INFO
+# Provides: messagebus
+# Required-Start: $syslog $local_fs
+# Required-Stop: $syslog $local_fs
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: The D-Bus systemwide message bus
+# Description: This is a daemon which broadcasts notifications of system 
+#  events and other messages. See http://www.freedesktop.org/software/dbus
+### END INIT INFO
+
+# Sanity checks.
+[ -x @EXPANDED_BINDIR@/dbus-daemon ] || exit 0
+
+# Source function library.
+. @EXPANDED_SYSCONFDIR@/rc.d/init.d/functions
+
+# so we can rearrange this easily
+processname=dbus-daemon
+servicename=messagebus
+
+RETVAL=0
+
+start() {
+    echo -n $"Starting system message bus: "
+    if [ -x @EXPANDED_BINDIR@/dbus-uuidgen ] ; then
+        @EXPANDED_BINDIR@/dbus-uuidgen --ensure
+    fi
+
+    daemon --check $servicename $processname --system
+    RETVAL=$?
+    echo
+    [ $RETVAL -eq 0 ] && touch @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename
+}
+
+stop() {
+    echo -n $"Stopping system message bus: "
+
+    ## we don't want to kill all the per-user $processname, we want
+    ## to use the pid file *only*; because we use the fake nonexistent 
+    ## program name "$servicename" that should be safe-ish
+    killproc $servicename -TERM
+    RETVAL=$?
+    echo
+    if [ $RETVAL -eq 0 ]; then
+        rm -f @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename
+        rm -f @DBUS_SYSTEM_PID_FILE@
+    fi
+}
+
+# See how we were called.
+case "$1" in
+    start)
+        start
+        ;;
+    stop)
+        stop
+        ;;
+    status)
+        status $servicename
+        RETVAL=$?
+        ;;
+    restart)
+        stop
+        start
+        ;;
+    condrestart)
+        if [ -f @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename ]; then
+            stop
+            start
+        fi
+        ;;
+    reload)
+        echo "Message bus can't reload its configuration, you have to restart it"
+        RETVAL=$?
+        ;;
+    *)
+        echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
+        ;;
+esac
+exit $RETVAL
diff --git a/dbus/bus/org.freedesktop.dbus-session.plist.in b/dbus/bus/org.freedesktop.dbus-session.plist.in
new file mode 100644
index 0000000..40ff370
--- /dev/null
+++ b/dbus/bus/org.freedesktop.dbus-session.plist.in
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>Label</key>
+	<string>org.freedesktop.dbus-session</string>
+
+	<key>ServiceIPC</key>
+	<true/>
+
+	<!-- Please uncomment on 10.4; OnDemand doesn't work properly there. -->
+	<!--
+	<key>OnDemand</key>
+	<false />
+	-->
+
+	<key>ProgramArguments</key>
+	<array>
+		<string>@DBUS_DAEMONDIR@/dbus-daemon</string>
+		<string>--nofork</string>
+		<string>--session</string>
+	</array>
+
+	<key>Sockets</key>
+	<dict>
+		<key>unix_domain_listener</key>
+		<dict>
+			<key>SecureSocketWithKey</key>
+			<string>DBUS_LAUNCHD_SESSION_BUS_SOCKET</string>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/dbus/bus/policy.c b/dbus/bus/policy.c
new file mode 100644
index 0000000..379cea9
--- /dev/null
+++ b/dbus/bus/policy.c
@@ -0,0 +1,1313 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* policy.c  Bus security policy
+ *
+ * Copyright (C) 2003, 2004  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "policy.h"
+#include "services.h"
+#include "test.h"
+#include "utils.h"
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-hash.h>
+#include <dbus/dbus-internals.h>
+
+BusPolicyRule*
+bus_policy_rule_new (BusPolicyRuleType type,
+                     dbus_bool_t       allow)
+{
+  BusPolicyRule *rule;
+
+  rule = dbus_new0 (BusPolicyRule, 1);
+  if (rule == NULL)
+    return NULL;
+
+  rule->type = type;
+  rule->refcount = 1;
+  rule->allow = allow;
+
+  switch (rule->type)
+    {
+    case BUS_POLICY_RULE_USER:
+      rule->d.user.uid = DBUS_UID_UNSET;
+      break;
+    case BUS_POLICY_RULE_GROUP:
+      rule->d.group.gid = DBUS_GID_UNSET;
+      break;
+    case BUS_POLICY_RULE_SEND:
+      rule->d.send.message_type = DBUS_MESSAGE_TYPE_INVALID;
+
+      /* allow rules default to TRUE (only requested replies allowed)
+       * deny rules default to FALSE (only unrequested replies denied)
+       */
+      rule->d.send.requested_reply = rule->allow;
+      break;
+    case BUS_POLICY_RULE_RECEIVE:
+      rule->d.receive.message_type = DBUS_MESSAGE_TYPE_INVALID;
+      /* allow rules default to TRUE (only requested replies allowed)
+       * deny rules default to FALSE (only unrequested replies denied)
+       */
+      rule->d.receive.requested_reply = rule->allow;
+      break;
+    case BUS_POLICY_RULE_OWN:
+      break;
+    }
+  
+  return rule;
+}
+
+BusPolicyRule *
+bus_policy_rule_ref (BusPolicyRule *rule)
+{
+  _dbus_assert (rule->refcount > 0);
+
+  rule->refcount += 1;
+
+  return rule;
+}
+
+void
+bus_policy_rule_unref (BusPolicyRule *rule)
+{
+  _dbus_assert (rule->refcount > 0);
+
+  rule->refcount -= 1;
+  
+  if (rule->refcount == 0)
+    {
+      switch (rule->type)
+        {
+        case BUS_POLICY_RULE_SEND:
+          dbus_free (rule->d.send.path);
+          dbus_free (rule->d.send.interface);
+          dbus_free (rule->d.send.member);
+          dbus_free (rule->d.send.error);
+          dbus_free (rule->d.send.destination);
+          break;
+        case BUS_POLICY_RULE_RECEIVE:
+          dbus_free (rule->d.receive.path);
+          dbus_free (rule->d.receive.interface);
+          dbus_free (rule->d.receive.member);
+          dbus_free (rule->d.receive.error);
+          dbus_free (rule->d.receive.origin);
+          break;
+        case BUS_POLICY_RULE_OWN:
+          dbus_free (rule->d.own.service_name);
+          break;
+        case BUS_POLICY_RULE_USER:
+          break;
+        case BUS_POLICY_RULE_GROUP:
+          break;
+        }
+      
+      dbus_free (rule);
+    }
+}
+
+struct BusPolicy
+{
+  int refcount;
+
+  DBusList *default_rules;         /**< Default policy rules */
+  DBusList *mandatory_rules;       /**< Mandatory policy rules */
+  DBusHashTable *rules_by_uid;     /**< per-UID policy rules */
+  DBusHashTable *rules_by_gid;     /**< per-GID policy rules */
+  DBusList *at_console_true_rules; /**< console user policy rules where at_console="true"*/
+  DBusList *at_console_false_rules; /**< console user policy rules where at_console="false"*/
+};
+
+static void
+free_rule_func (void *data,
+                void *user_data)
+{
+  BusPolicyRule *rule = data;
+
+  bus_policy_rule_unref (rule);
+}
+
+static void
+free_rule_list_func (void *data)
+{
+  DBusList **list = data;
+
+  if (list == NULL) /* DBusHashTable is on crack */
+    return;
+  
+  _dbus_list_foreach (list, free_rule_func, NULL);
+  
+  _dbus_list_clear (list);
+
+  dbus_free (list);
+}
+
+BusPolicy*
+bus_policy_new (void)
+{
+  BusPolicy *policy;
+
+  policy = dbus_new0 (BusPolicy, 1);
+  if (policy == NULL)
+    return NULL;
+
+  policy->refcount = 1;
+  
+  policy->rules_by_uid = _dbus_hash_table_new (DBUS_HASH_UINTPTR,
+                                               NULL,
+                                               free_rule_list_func);
+  if (policy->rules_by_uid == NULL)
+    goto failed;
+
+  policy->rules_by_gid = _dbus_hash_table_new (DBUS_HASH_UINTPTR,
+                                               NULL,
+                                               free_rule_list_func);
+  if (policy->rules_by_gid == NULL)
+    goto failed;
+
+  return policy;
+  
+ failed:
+  bus_policy_unref (policy);
+  return NULL;
+}
+
+BusPolicy *
+bus_policy_ref (BusPolicy *policy)
+{
+  _dbus_assert (policy->refcount > 0);
+
+  policy->refcount += 1;
+
+  return policy;
+}
+
+void
+bus_policy_unref (BusPolicy *policy)
+{
+  _dbus_assert (policy->refcount > 0);
+
+  policy->refcount -= 1;
+
+  if (policy->refcount == 0)
+    {
+      _dbus_list_foreach (&policy->default_rules, free_rule_func, NULL);
+      _dbus_list_clear (&policy->default_rules);
+
+      _dbus_list_foreach (&policy->mandatory_rules, free_rule_func, NULL);
+      _dbus_list_clear (&policy->mandatory_rules);
+
+      _dbus_list_foreach (&policy->at_console_true_rules, free_rule_func, NULL);
+      _dbus_list_clear (&policy->at_console_true_rules);
+
+      _dbus_list_foreach (&policy->at_console_false_rules, free_rule_func, NULL);
+      _dbus_list_clear (&policy->at_console_false_rules);
+
+      if (policy->rules_by_uid)
+        {
+          _dbus_hash_table_unref (policy->rules_by_uid);
+          policy->rules_by_uid = NULL;
+        }
+
+      if (policy->rules_by_gid)
+        {
+          _dbus_hash_table_unref (policy->rules_by_gid);
+          policy->rules_by_gid = NULL;
+        }
+      
+      dbus_free (policy);
+    }
+}
+
+static dbus_bool_t
+add_list_to_client (DBusList        **list,
+                    BusClientPolicy  *client)
+{
+  DBusList *link;
+
+  link = _dbus_list_get_first_link (list);
+  while (link != NULL)
+    {
+      BusPolicyRule *rule = link->data;
+      link = _dbus_list_get_next_link (list, link);
+
+      switch (rule->type)
+        {
+        case BUS_POLICY_RULE_USER:
+        case BUS_POLICY_RULE_GROUP:
+          /* These aren't per-connection policies */
+          break;
+
+        case BUS_POLICY_RULE_OWN:
+        case BUS_POLICY_RULE_SEND:
+        case BUS_POLICY_RULE_RECEIVE:
+          /* These are per-connection */
+          if (!bus_client_policy_append_rule (client, rule))
+            return FALSE;
+          break;
+        }
+    }
+  
+  return TRUE;
+}
+
+BusClientPolicy*
+bus_policy_create_client_policy (BusPolicy      *policy,
+                                 DBusConnection *connection,
+                                 DBusError      *error)
+{
+  BusClientPolicy *client;
+  dbus_uid_t uid;
+  dbus_bool_t at_console;
+
+  _dbus_assert (dbus_connection_get_is_authenticated (connection));
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  client = bus_client_policy_new ();
+  if (client == NULL)
+    goto nomem;
+
+  if (!add_list_to_client (&policy->default_rules,
+                           client))
+    goto nomem;
+
+  /* we avoid the overhead of looking up user's groups
+   * if we don't have any group rules anyway
+   */
+  if (_dbus_hash_table_get_n_entries (policy->rules_by_gid) > 0)
+    {
+      unsigned long *groups;
+      int n_groups;
+      int i;
+      
+      if (!bus_connection_get_unix_groups (connection, &groups, &n_groups, error))
+        goto failed;
+      
+      i = 0;
+      while (i < n_groups)
+        {
+          DBusList **list;
+          
+          list = _dbus_hash_table_lookup_uintptr (policy->rules_by_gid,
+                                                groups[i]);
+          
+          if (list != NULL)
+            {
+              if (!add_list_to_client (list, client))
+                {
+                  dbus_free (groups);
+                  goto nomem;
+                }
+            }
+          
+          ++i;
+        }
+
+      dbus_free (groups);
+    }
+  
+  if (dbus_connection_get_unix_user (connection, &uid))
+    {
+      if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0)
+        {
+          DBusList **list;
+          
+          list = _dbus_hash_table_lookup_uintptr (policy->rules_by_uid,
+                                                uid);
+          
+          if (list != NULL)
+            {
+              if (!add_list_to_client (list, client))
+                goto nomem;
+            }
+        }
+
+      /* Add console rules */
+      at_console = _dbus_unix_user_is_at_console (uid, error);
+      
+      if (at_console)
+        {
+          if (!add_list_to_client (&policy->at_console_true_rules, client))
+            goto nomem;
+        }
+      else if (dbus_error_is_set (error) == TRUE)
+        {
+          goto failed;
+        }
+      else if (!add_list_to_client (&policy->at_console_false_rules, client))
+        {
+          goto nomem;
+        }
+    }
+
+  if (!add_list_to_client (&policy->mandatory_rules,
+                           client))
+    goto nomem;
+
+  bus_client_policy_optimize (client);
+  
+  return client;
+
+ nomem:
+  BUS_SET_OOM (error);
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (client)
+    bus_client_policy_unref (client);
+  return NULL;
+}
+
+static dbus_bool_t
+list_allows_user (dbus_bool_t           def,
+                  DBusList            **list,
+                  unsigned long         uid,
+                  const unsigned long  *group_ids,
+                  int                   n_group_ids)
+{
+  DBusList *link;
+  dbus_bool_t allowed;
+  
+  allowed = def;
+
+  link = _dbus_list_get_first_link (list);
+  while (link != NULL)
+    {
+      BusPolicyRule *rule = link->data;
+      link = _dbus_list_get_next_link (list, link);
+
+      if (rule->type == BUS_POLICY_RULE_USER)
+        {
+          _dbus_verbose ("List %p user rule uid="DBUS_UID_FORMAT"\n",
+                         list, rule->d.user.uid);
+          
+          if (rule->d.user.uid == DBUS_UID_UNSET)
+            ; /* '*' wildcard */
+          else if (rule->d.user.uid != uid)
+            continue;
+        }
+      else if (rule->type == BUS_POLICY_RULE_GROUP)
+        {
+          _dbus_verbose ("List %p group rule gid="DBUS_GID_FORMAT"\n",
+                         list, rule->d.group.gid);
+          
+          if (rule->d.group.gid == DBUS_GID_UNSET)
+            ;  /* '*' wildcard */
+          else
+            {
+              int i;
+              
+              i = 0;
+              while (i < n_group_ids)
+                {
+                  if (rule->d.group.gid == group_ids[i])
+                    break;
+                  ++i;
+                }
+              
+              if (i == n_group_ids)
+                continue;
+            }
+        }
+      else
+        continue;
+
+      allowed = rule->allow;
+    }
+  
+  return allowed;
+}
+
+dbus_bool_t
+bus_policy_allow_unix_user (BusPolicy        *policy,
+                            unsigned long     uid)
+{
+  dbus_bool_t allowed;
+  unsigned long *group_ids;
+  int n_group_ids;
+
+  /* On OOM or error we always reject the user */
+  if (!_dbus_unix_groups_from_uid (uid, &group_ids, &n_group_ids))
+    {
+      _dbus_verbose ("Did not get any groups for UID %lu\n",
+                     uid);
+      return FALSE;
+    }
+
+  /* Default to "user owning bus" can connect */
+  allowed = _dbus_unix_user_is_process_owner (uid);
+
+  allowed = list_allows_user (allowed,
+                              &policy->default_rules,
+                              uid,
+                              group_ids, n_group_ids);
+
+  allowed = list_allows_user (allowed,
+                              &policy->mandatory_rules,
+                              uid,
+                              group_ids, n_group_ids);
+
+  dbus_free (group_ids);
+
+  _dbus_verbose ("UID %lu allowed = %d\n", uid, allowed);
+  
+  return allowed;
+}
+
+/* For now this is never actually called because the default
+ * DBusConnection behavior of 'same user that owns the bus can
+ * connect' is all it would do. Set the windows user function in
+ * connection.c if the config file ever supports doing something
+ * interesting here.
+ */
+dbus_bool_t
+bus_policy_allow_windows_user (BusPolicy        *policy,
+                               const char       *windows_sid)
+{
+  /* Windows has no policies here since only the session bus
+   * is really used for now, so just checking that the
+   * connecting person is the same as the bus owner is fine.
+   */
+  return _dbus_windows_user_is_process_owner (windows_sid);
+}
+
+dbus_bool_t
+bus_policy_append_default_rule (BusPolicy      *policy,
+                                BusPolicyRule  *rule)
+{
+  if (!_dbus_list_append (&policy->default_rules, rule))
+    return FALSE;
+
+  bus_policy_rule_ref (rule);
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_policy_append_mandatory_rule (BusPolicy      *policy,
+                                  BusPolicyRule  *rule)
+{
+  if (!_dbus_list_append (&policy->mandatory_rules, rule))
+    return FALSE;
+
+  bus_policy_rule_ref (rule);
+
+  return TRUE;
+}
+
+
+
+static DBusList**
+get_list (DBusHashTable *hash,
+          unsigned long  key)
+{
+  DBusList **list;
+
+  list = _dbus_hash_table_lookup_uintptr (hash, key);
+
+  if (list == NULL)
+    {
+      list = dbus_new0 (DBusList*, 1);
+      if (list == NULL)
+        return NULL;
+
+      if (!_dbus_hash_table_insert_uintptr (hash, key, list))
+        {
+          dbus_free (list);
+          return NULL;
+        }
+    }
+
+  return list;
+}
+
+dbus_bool_t
+bus_policy_append_user_rule (BusPolicy      *policy,
+                             dbus_uid_t      uid,
+                             BusPolicyRule  *rule)
+{
+  DBusList **list;
+
+  list = get_list (policy->rules_by_uid, uid);
+
+  if (list == NULL)
+    return FALSE;
+
+  if (!_dbus_list_append (list, rule))
+    return FALSE;
+
+  bus_policy_rule_ref (rule);
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_policy_append_group_rule (BusPolicy      *policy,
+                              dbus_gid_t      gid,
+                              BusPolicyRule  *rule)
+{
+  DBusList **list;
+
+  list = get_list (policy->rules_by_gid, gid);
+
+  if (list == NULL)
+    return FALSE;
+
+  if (!_dbus_list_append (list, rule))
+    return FALSE;
+
+  bus_policy_rule_ref (rule);
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_policy_append_console_rule (BusPolicy      *policy,
+                                dbus_bool_t     at_console,
+                                BusPolicyRule  *rule)
+{
+  if (at_console)
+    {
+      if (!_dbus_list_append (&policy->at_console_true_rules, rule))
+        return FALSE;
+    }
+    else
+    {
+      if (!_dbus_list_append (&policy->at_console_false_rules, rule))
+        return FALSE;
+    }
+
+  bus_policy_rule_ref (rule);
+
+  return TRUE;
+
+}
+
+static dbus_bool_t
+append_copy_of_policy_list (DBusList **list,
+                            DBusList **to_append)
+{
+  DBusList *link;
+  DBusList *tmp_list;
+
+  tmp_list = NULL;
+
+  /* Preallocate all our links */
+  link = _dbus_list_get_first_link (to_append);
+  while (link != NULL)
+    {
+      if (!_dbus_list_append (&tmp_list, link->data))
+        {
+          _dbus_list_clear (&tmp_list);
+          return FALSE;
+        }
+      
+      link = _dbus_list_get_next_link (to_append, link);
+    }
+
+  /* Now append them */
+  while ((link = _dbus_list_pop_first_link (&tmp_list)))
+    {
+      bus_policy_rule_ref (link->data);
+      _dbus_list_append_link (list, link);
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+merge_id_hash (DBusHashTable *dest,
+               DBusHashTable *to_absorb)
+{
+  DBusHashIter iter;
+  
+  _dbus_hash_iter_init (to_absorb, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      unsigned long id = _dbus_hash_iter_get_uintptr_key (&iter);
+      DBusList **list = _dbus_hash_iter_get_value (&iter);
+      DBusList **target = get_list (dest, id);
+
+      if (target == NULL)
+        return FALSE;
+
+      if (!append_copy_of_policy_list (target, list))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_policy_merge (BusPolicy *policy,
+                  BusPolicy *to_absorb)
+{
+  /* FIXME Not properly atomic, but as used for configuration files we
+   * don't rely on it quite so much.
+   */
+  
+  if (!append_copy_of_policy_list (&policy->default_rules,
+                                   &to_absorb->default_rules))
+    return FALSE;
+  
+  if (!append_copy_of_policy_list (&policy->mandatory_rules,
+                                   &to_absorb->mandatory_rules))
+    return FALSE;
+
+  if (!append_copy_of_policy_list (&policy->at_console_true_rules,
+                                   &to_absorb->at_console_true_rules))
+    return FALSE;
+
+  if (!append_copy_of_policy_list (&policy->at_console_false_rules,
+                                   &to_absorb->at_console_false_rules))
+    return FALSE;
+
+  if (!merge_id_hash (policy->rules_by_uid,
+                      to_absorb->rules_by_uid))
+    return FALSE;
+  
+  if (!merge_id_hash (policy->rules_by_gid,
+                      to_absorb->rules_by_gid))
+    return FALSE;
+
+  return TRUE;
+}
+
+struct BusClientPolicy
+{
+  int refcount;
+
+  DBusList *rules;
+};
+
+BusClientPolicy*
+bus_client_policy_new (void)
+{
+  BusClientPolicy *policy;
+
+  policy = dbus_new0 (BusClientPolicy, 1);
+  if (policy == NULL)
+    return NULL;
+
+  policy->refcount = 1;
+
+  return policy;
+}
+
+BusClientPolicy *
+bus_client_policy_ref (BusClientPolicy *policy)
+{
+  _dbus_assert (policy->refcount > 0);
+
+  policy->refcount += 1;
+
+  return policy;
+}
+
+static void
+rule_unref_foreach (void *data,
+                    void *user_data)
+{
+  BusPolicyRule *rule = data;
+
+  bus_policy_rule_unref (rule);
+}
+
+void
+bus_client_policy_unref (BusClientPolicy *policy)
+{
+  _dbus_assert (policy->refcount > 0);
+
+  policy->refcount -= 1;
+
+  if (policy->refcount == 0)
+    {
+      _dbus_list_foreach (&policy->rules,
+                          rule_unref_foreach,
+                          NULL);
+
+      _dbus_list_clear (&policy->rules);
+
+      dbus_free (policy);
+    }
+}
+
+static void
+remove_rules_by_type_up_to (BusClientPolicy   *policy,
+                            BusPolicyRuleType  type,
+                            DBusList          *up_to)
+{
+  DBusList *link;
+
+  link = _dbus_list_get_first_link (&policy->rules);
+  while (link != up_to)
+    {
+      BusPolicyRule *rule = link->data;
+      DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
+
+      if (rule->type == type)
+        {
+          _dbus_list_remove_link (&policy->rules, link);
+          bus_policy_rule_unref (rule);
+        }
+      
+      link = next;
+    }
+}
+
+void
+bus_client_policy_optimize (BusClientPolicy *policy)
+{
+  DBusList *link;
+
+  /* The idea here is that if we have:
+   * 
+   * <allow send_interface="foo.bar"/>
+   * <deny send_interface="*"/>
+   *
+   * (for example) the deny will always override the allow.  So we
+   * delete the allow. Ditto for deny followed by allow, etc. This is
+   * a dumb thing to put in a config file, but the <include> feature
+   * of files allows for an "inheritance and override" pattern where
+   * it could make sense. If an included file wants to "start over"
+   * with a blanket deny, no point keeping the rules from the parent
+   * file.
+   */
+
+  _dbus_verbose ("Optimizing policy with %d rules\n",
+                 _dbus_list_get_length (&policy->rules));
+  
+  link = _dbus_list_get_first_link (&policy->rules);
+  while (link != NULL)
+    {
+      BusPolicyRule *rule;
+      DBusList *next;
+      dbus_bool_t remove_preceding;
+
+      next = _dbus_list_get_next_link (&policy->rules, link);
+      rule = link->data;
+      
+      remove_preceding = FALSE;
+
+      _dbus_assert (rule != NULL);
+      
+      switch (rule->type)
+        {
+        case BUS_POLICY_RULE_SEND:
+          remove_preceding =
+            rule->d.send.message_type == DBUS_MESSAGE_TYPE_INVALID &&
+            rule->d.send.path == NULL &&
+            rule->d.send.interface == NULL &&
+            rule->d.send.member == NULL &&
+            rule->d.send.error == NULL &&
+            rule->d.send.destination == NULL;
+          break;
+        case BUS_POLICY_RULE_RECEIVE:
+          remove_preceding =
+            rule->d.receive.message_type == DBUS_MESSAGE_TYPE_INVALID &&
+            rule->d.receive.path == NULL &&
+            rule->d.receive.interface == NULL &&
+            rule->d.receive.member == NULL &&
+            rule->d.receive.error == NULL &&
+            rule->d.receive.origin == NULL;
+          break;
+        case BUS_POLICY_RULE_OWN:
+          remove_preceding =
+            rule->d.own.service_name == NULL;
+          break;
+        case BUS_POLICY_RULE_USER:
+        case BUS_POLICY_RULE_GROUP:
+          _dbus_assert_not_reached ("invalid rule");
+          break;
+        }
+
+      if (remove_preceding)
+        remove_rules_by_type_up_to (policy, rule->type,
+                                    link);
+      
+      link = next;
+    }
+
+  _dbus_verbose ("After optimization, policy has %d rules\n",
+                 _dbus_list_get_length (&policy->rules));
+}
+
+dbus_bool_t
+bus_client_policy_append_rule (BusClientPolicy *policy,
+                               BusPolicyRule   *rule)
+{
+  _dbus_verbose ("Appending rule %p with type %d to policy %p\n",
+                 rule, rule->type, policy);
+  
+  if (!_dbus_list_append (&policy->rules, rule))
+    return FALSE;
+
+  bus_policy_rule_ref (rule);
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_client_policy_check_can_send (BusClientPolicy *policy,
+                                  BusRegistry     *registry,
+                                  dbus_bool_t      requested_reply,
+                                  DBusConnection  *receiver,
+                                  DBusMessage     *message,
+                                  dbus_int32_t    *toggles,
+                                  dbus_bool_t     *log)
+{
+  DBusList *link;
+  dbus_bool_t allowed;
+  
+  /* policy->rules is in the order the rules appeared
+   * in the config file, i.e. last rule that applies wins
+   */
+
+  _dbus_verbose ("  (policy) checking send rules\n");
+  *toggles = 0;
+  
+  allowed = FALSE;
+  link = _dbus_list_get_first_link (&policy->rules);
+  while (link != NULL)
+    {
+      BusPolicyRule *rule = link->data;
+
+      link = _dbus_list_get_next_link (&policy->rules, link);
+      
+      /* Rule is skipped if it specifies a different
+       * message name from the message, or a different
+       * destination from the message
+       */
+      
+      if (rule->type != BUS_POLICY_RULE_SEND)
+        {
+          _dbus_verbose ("  (policy) skipping non-send rule\n");
+          continue;
+        }
+
+      if (rule->d.send.message_type != DBUS_MESSAGE_TYPE_INVALID)
+        {
+          if (dbus_message_get_type (message) != rule->d.send.message_type)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different message type\n");
+              continue;
+            }
+        }
+
+      /* If it's a reply, the requested_reply flag kicks in */
+      if (dbus_message_get_reply_serial (message) != 0)
+        {
+          /* for allow, requested_reply=true means the rule applies
+           * only when reply was requested. requested_reply=false means
+           * always allow.
+           */
+          if (!requested_reply && rule->allow && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
+            {
+              _dbus_verbose ("  (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n");
+              continue;
+            }
+
+          /* for deny, requested_reply=false means the rule applies only
+           * when the reply was not requested. requested_reply=true means the
+           * rule always applies.
+           */
+          if (requested_reply && !rule->allow && !rule->d.send.requested_reply)
+            {
+              _dbus_verbose ("  (policy) skipping deny rule since it only applies to unrequested replies\n");
+              continue;
+            }
+        }
+      
+      if (rule->d.send.path != NULL)
+        {
+          if (dbus_message_get_path (message) != NULL &&
+              strcmp (dbus_message_get_path (message),
+                      rule->d.send.path) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different path\n");
+              continue;
+            }
+        }
+      
+      if (rule->d.send.interface != NULL)
+        {
+          /* The interface is optional in messages. For allow rules, if the message
+           * has no interface we want to skip the rule (and thus not allow);
+           * for deny rules, if the message has no interface we want to use the
+           * rule (and thus deny).
+           */
+          dbus_bool_t no_interface;
+
+          no_interface = dbus_message_get_interface (message) == NULL;
+          
+          if ((no_interface && rule->allow) ||
+              (!no_interface && 
+               strcmp (dbus_message_get_interface (message),
+                       rule->d.send.interface) != 0))
+            {
+              _dbus_verbose ("  (policy) skipping rule for different interface\n");
+              continue;
+            }
+        }
+
+      if (rule->d.send.member != NULL)
+        {
+          if (dbus_message_get_member (message) != NULL &&
+              strcmp (dbus_message_get_member (message),
+                      rule->d.send.member) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different member\n");
+              continue;
+            }
+        }
+
+      if (rule->d.send.error != NULL)
+        {
+          if (dbus_message_get_error_name (message) != NULL &&
+              strcmp (dbus_message_get_error_name (message),
+                      rule->d.send.error) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different error name\n");
+              continue;
+            }
+        }
+      
+      if (rule->d.send.destination != NULL)
+        {
+          /* receiver can be NULL for messages that are sent to the
+           * message bus itself, we check the strings in that case as
+           * built-in services don't have a DBusConnection but messages
+           * to them have a destination service name.
+           */
+          if (receiver == NULL)
+            {
+              if (!dbus_message_has_destination (message,
+                                                 rule->d.send.destination))
+                {
+                  _dbus_verbose ("  (policy) skipping rule because message dest is not %s\n",
+                                 rule->d.send.destination);
+                  continue;
+                }
+            }
+          else
+            {
+              DBusString str;
+              BusService *service;
+              
+              _dbus_string_init_const (&str, rule->d.send.destination);
+              
+              service = bus_registry_lookup (registry, &str);
+              if (service == NULL)
+                {
+                  _dbus_verbose ("  (policy) skipping rule because dest %s doesn't exist\n",
+                                 rule->d.send.destination);
+                  continue;
+                }
+
+              if (!bus_service_has_owner (service, receiver))
+                {
+                  _dbus_verbose ("  (policy) skipping rule because dest %s isn't owned by receiver\n",
+                                 rule->d.send.destination);
+                  continue;
+                }
+            }
+        }
+
+      /* Use this rule */
+      allowed = rule->allow;
+      *log = rule->d.send.log;
+      (*toggles)++;
+
+      _dbus_verbose ("  (policy) used rule, allow now = %d\n",
+                     allowed);
+    }
+
+  return allowed;
+}
+
+/* See docs on what the args mean on bus_context_check_security_policy()
+ * comment
+ */
+dbus_bool_t
+bus_client_policy_check_can_receive (BusClientPolicy *policy,
+                                     BusRegistry     *registry,
+                                     dbus_bool_t      requested_reply,
+                                     DBusConnection  *sender,
+                                     DBusConnection  *addressed_recipient,
+                                     DBusConnection  *proposed_recipient,
+                                     DBusMessage     *message,
+                                     dbus_int32_t    *toggles)
+{
+  DBusList *link;
+  dbus_bool_t allowed;
+  dbus_bool_t eavesdropping;
+
+  eavesdropping =
+    addressed_recipient != proposed_recipient &&
+    dbus_message_get_destination (message) != NULL;
+  
+  /* policy->rules is in the order the rules appeared
+   * in the config file, i.e. last rule that applies wins
+   */
+
+  _dbus_verbose ("  (policy) checking receive rules, eavesdropping = %d\n", eavesdropping);
+  *toggles = 0;
+  
+  allowed = FALSE;
+  link = _dbus_list_get_first_link (&policy->rules);
+  while (link != NULL)
+    {
+      BusPolicyRule *rule = link->data;
+
+      link = _dbus_list_get_next_link (&policy->rules, link);      
+      
+      if (rule->type != BUS_POLICY_RULE_RECEIVE)
+        {
+          _dbus_verbose ("  (policy) skipping non-receive rule\n");
+          continue;
+        }
+
+      if (rule->d.receive.message_type != DBUS_MESSAGE_TYPE_INVALID)
+        {
+          if (dbus_message_get_type (message) != rule->d.receive.message_type)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different message type\n");
+              continue;
+            }
+        }
+
+      /* for allow, eavesdrop=false means the rule doesn't apply when
+       * eavesdropping. eavesdrop=true means always allow.
+       */
+      if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop)
+        {
+          _dbus_verbose ("  (policy) skipping allow rule since it doesn't apply to eavesdropping\n");
+          continue;
+        }
+
+      /* for deny, eavesdrop=true means the rule applies only when
+       * eavesdropping; eavesdrop=false means always deny.
+       */
+      if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop)
+        {
+          _dbus_verbose ("  (policy) skipping deny rule since it only applies to eavesdropping\n");
+          continue;
+        }
+
+      /* If it's a reply, the requested_reply flag kicks in */
+      if (dbus_message_get_reply_serial (message) != 0)
+        {
+          /* for allow, requested_reply=true means the rule applies
+           * only when reply was requested. requested_reply=false means
+           * always allow.
+           */
+          if (!requested_reply && rule->allow && rule->d.receive.requested_reply && !rule->d.receive.eavesdrop)
+            {
+              _dbus_verbose ("  (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n");
+              continue;
+            }
+
+          /* for deny, requested_reply=false means the rule applies only
+           * when the reply was not requested. requested_reply=true means the
+           * rule always applies.
+           */
+          if (requested_reply && !rule->allow && !rule->d.receive.requested_reply)
+            {
+              _dbus_verbose ("  (policy) skipping deny rule since it only applies to unrequested replies\n");
+              continue;
+            }
+        }
+      
+      if (rule->d.receive.path != NULL)
+        {
+          if (dbus_message_get_path (message) != NULL &&
+              strcmp (dbus_message_get_path (message),
+                      rule->d.receive.path) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different path\n");
+              continue;
+            }
+        }
+      
+      if (rule->d.receive.interface != NULL)
+        {
+          /* The interface is optional in messages. For allow rules, if the message
+           * has no interface we want to skip the rule (and thus not allow);
+           * for deny rules, if the message has no interface we want to use the
+           * rule (and thus deny).
+           */
+          dbus_bool_t no_interface;
+
+          no_interface = dbus_message_get_interface (message) == NULL;
+          
+          if ((no_interface && rule->allow) ||
+              (!no_interface &&
+               strcmp (dbus_message_get_interface (message),
+                       rule->d.receive.interface) != 0))
+            {
+              _dbus_verbose ("  (policy) skipping rule for different interface\n");
+              continue;
+            }
+        }      
+
+      if (rule->d.receive.member != NULL)
+        {
+          if (dbus_message_get_member (message) != NULL &&
+              strcmp (dbus_message_get_member (message),
+                      rule->d.receive.member) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different member\n");
+              continue;
+            }
+        }
+
+      if (rule->d.receive.error != NULL)
+        {
+          if (dbus_message_get_error_name (message) != NULL &&
+              strcmp (dbus_message_get_error_name (message),
+                      rule->d.receive.error) != 0)
+            {
+              _dbus_verbose ("  (policy) skipping rule for different error name\n");
+              continue;
+            }
+        }
+      
+      if (rule->d.receive.origin != NULL)
+        {          
+          /* sender can be NULL for messages that originate from the
+           * message bus itself, we check the strings in that case as
+           * built-in services don't have a DBusConnection but will
+           * still set the sender on their messages.
+           */
+          if (sender == NULL)
+            {
+              if (!dbus_message_has_sender (message,
+                                            rule->d.receive.origin))
+                {
+                  _dbus_verbose ("  (policy) skipping rule because message sender is not %s\n",
+                                 rule->d.receive.origin);
+                  continue;
+                }
+            }
+          else
+            {
+              BusService *service;
+              DBusString str;
+
+              _dbus_string_init_const (&str, rule->d.receive.origin);
+              
+              service = bus_registry_lookup (registry, &str);
+              
+              if (service == NULL)
+                {
+                  _dbus_verbose ("  (policy) skipping rule because origin %s doesn't exist\n",
+                                 rule->d.receive.origin);
+                  continue;
+                }
+
+              if (!bus_service_has_owner (service, sender))
+                {
+                  _dbus_verbose ("  (policy) skipping rule because origin %s isn't owned by sender\n",
+                                 rule->d.receive.origin);
+                  continue;
+                }
+            }
+        }
+      
+      /* Use this rule */
+      allowed = rule->allow;
+      (*toggles)++;
+
+      _dbus_verbose ("  (policy) used rule, allow now = %d\n",
+                     allowed);
+    }
+
+  return allowed;
+}
+
+
+
+static dbus_bool_t
+bus_rules_check_can_own (DBusList *rules,
+                         const DBusString *service_name)
+{
+  DBusList *link;
+  dbus_bool_t allowed;
+  
+  /* rules is in the order the rules appeared
+   * in the config file, i.e. last rule that applies wins
+   */
+
+  allowed = FALSE;
+  link = _dbus_list_get_first_link (&rules);
+  while (link != NULL)
+    {
+      BusPolicyRule *rule = link->data;
+
+      link = _dbus_list_get_next_link (&rules, link);
+      
+      /* Rule is skipped if it specifies a different service name from
+       * the desired one.
+       */
+      
+      if (rule->type != BUS_POLICY_RULE_OWN)
+        continue;
+
+      if (!rule->d.own.prefix && rule->d.own.service_name != NULL)
+        {
+          if (!_dbus_string_equal_c_str (service_name,
+                                         rule->d.own.service_name))
+            continue;
+        }
+      else if (rule->d.own.prefix)
+        {
+          const char *data;
+          char next_char;
+          if (!_dbus_string_starts_with_c_str (service_name,
+                                               rule->d.own.service_name))
+            continue;
+
+          data = _dbus_string_get_const_data (service_name);
+          next_char = data[strlen (rule->d.own.service_name)];
+          if (next_char != '\0' && next_char != '.')
+            continue;
+        }
+
+      /* Use this rule */
+      allowed = rule->allow;
+    }
+
+  return allowed;
+}
+
+dbus_bool_t
+bus_client_policy_check_can_own (BusClientPolicy  *policy,
+                                 const DBusString *service_name)
+{
+  return bus_rules_check_can_own (policy->rules, service_name);
+}
+
+#ifdef DBUS_BUILD_TESTS
+dbus_bool_t
+bus_policy_check_can_own (BusPolicy  *policy,
+                          const DBusString *service_name)
+{
+  return bus_rules_check_can_own (policy->default_rules, service_name);
+}
+#endif /* DBUS_BUILD_TESTS */
+
diff --git a/dbus/bus/policy.h b/dbus/bus/policy.h
new file mode 100644
index 0000000..3ff6f48
--- /dev/null
+++ b/dbus/bus/policy.h
@@ -0,0 +1,169 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* policy.h  Bus security policy
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_POLICY_H
+#define BUS_POLICY_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-sysdeps.h>
+#include "bus.h"
+
+typedef enum
+{
+  BUS_POLICY_RULE_SEND,
+  BUS_POLICY_RULE_RECEIVE,
+  BUS_POLICY_RULE_OWN,
+  BUS_POLICY_RULE_USER,
+  BUS_POLICY_RULE_GROUP
+} BusPolicyRuleType;
+
+/** determines whether the rule affects a connection, or some global item */
+#define BUS_POLICY_RULE_IS_PER_CLIENT(rule) (!((rule)->type == BUS_POLICY_RULE_USER || \
+                                               (rule)->type == BUS_POLICY_RULE_GROUP))
+
+struct BusPolicyRule
+{
+  int refcount;
+  
+  BusPolicyRuleType type;
+
+  unsigned int allow : 1; /**< #TRUE if this allows, #FALSE if it denies */
+  
+  union
+  {
+    struct
+    {
+      /* message type can be DBUS_MESSAGE_TYPE_INVALID meaning "any" */
+      int   message_type;
+      /* any of these can be NULL meaning "any" */
+      char *path;
+      char *interface;
+      char *member;
+      char *error;
+      char *destination;
+      unsigned int eavesdrop : 1;
+      unsigned int requested_reply : 1;
+      unsigned int log : 1;
+    } send;
+
+    struct
+    {
+      /* message type can be DBUS_MESSAGE_TYPE_INVALID meaning "any" */
+      int   message_type;
+      /* any of these can be NULL meaning "any" */
+      char *path;
+      char *interface;
+      char *member;
+      char *error;
+      char *origin;
+      unsigned int eavesdrop : 1;
+      unsigned int requested_reply : 1;
+    } receive;
+
+    struct
+    {
+      /* can be NULL meaning "any" */
+      char *service_name;
+      /* if prefix is set, any name starting with service_name can be owned */
+      unsigned int prefix : 1;
+    } own;
+
+    struct
+    {
+      /* can be DBUS_UID_UNSET meaning "any" */
+      dbus_uid_t uid;
+    } user;
+
+    struct
+    {
+      /* can be DBUS_GID_UNSET meaning "any" */
+      dbus_gid_t gid;
+    } group;
+
+  } d;
+};
+
+BusPolicyRule* bus_policy_rule_new   (BusPolicyRuleType type,
+                                      dbus_bool_t       allow);
+BusPolicyRule* bus_policy_rule_ref   (BusPolicyRule    *rule);
+void           bus_policy_rule_unref (BusPolicyRule    *rule);
+
+BusPolicy*       bus_policy_new                   (void);
+BusPolicy*       bus_policy_ref                   (BusPolicy        *policy);
+void             bus_policy_unref                 (BusPolicy        *policy);
+BusClientPolicy* bus_policy_create_client_policy  (BusPolicy        *policy,
+                                                   DBusConnection   *connection,
+                                                   DBusError        *error);
+dbus_bool_t      bus_policy_allow_unix_user       (BusPolicy        *policy,
+                                                   unsigned long     uid);
+dbus_bool_t      bus_policy_allow_windows_user    (BusPolicy        *policy,
+                                                   const char       *windows_sid);
+dbus_bool_t      bus_policy_append_default_rule   (BusPolicy        *policy,
+                                                   BusPolicyRule    *rule);
+dbus_bool_t      bus_policy_append_mandatory_rule (BusPolicy        *policy,
+                                                   BusPolicyRule    *rule);
+dbus_bool_t      bus_policy_append_user_rule      (BusPolicy        *policy,
+                                                   dbus_uid_t        uid,
+                                                   BusPolicyRule    *rule);
+dbus_bool_t      bus_policy_append_group_rule     (BusPolicy        *policy,
+                                                   dbus_gid_t        gid,
+                                                   BusPolicyRule    *rule);
+dbus_bool_t      bus_policy_append_console_rule   (BusPolicy        *policy,
+                                                   dbus_bool_t        at_console,
+                                                   BusPolicyRule    *rule);
+
+dbus_bool_t      bus_policy_merge                 (BusPolicy        *policy,
+                                                   BusPolicy        *to_absorb);
+
+BusClientPolicy* bus_client_policy_new               (void);
+BusClientPolicy* bus_client_policy_ref               (BusClientPolicy  *policy);
+void             bus_client_policy_unref             (BusClientPolicy  *policy);
+dbus_bool_t      bus_client_policy_check_can_send    (BusClientPolicy  *policy,
+                                                      BusRegistry      *registry,
+                                                      dbus_bool_t       requested_reply,
+                                                      DBusConnection   *receiver,
+                                                      DBusMessage      *message,
+                                                      dbus_int32_t     *toggles,
+                                                      dbus_bool_t      *log);
+dbus_bool_t      bus_client_policy_check_can_receive (BusClientPolicy  *policy,
+                                                      BusRegistry      *registry,
+                                                      dbus_bool_t       requested_reply,
+                                                      DBusConnection   *sender,
+                                                      DBusConnection   *addressed_recipient,
+                                                      DBusConnection   *proposed_recipient,
+                                                      DBusMessage      *message,
+                                                      dbus_int32_t     *toggles);
+dbus_bool_t      bus_client_policy_check_can_own     (BusClientPolicy  *policy,
+                                                      const DBusString *service_name);
+dbus_bool_t      bus_client_policy_append_rule       (BusClientPolicy  *policy,
+                                                      BusPolicyRule    *rule);
+void             bus_client_policy_optimize          (BusClientPolicy  *policy);
+
+#ifdef DBUS_BUILD_TESTS
+dbus_bool_t      bus_policy_check_can_own     (BusPolicy  *policy,
+                                               const DBusString *service_name);
+#endif
+
+#endif /* BUS_POLICY_H */
diff --git a/dbus/bus/rc.messagebus.in b/dbus/bus/rc.messagebus.in
new file mode 100644
index 0000000..c52ca77
--- /dev/null
+++ b/dbus/bus/rc.messagebus.in
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# messagebus:   The D-BUS systemwide message bus
+#
+# chkconfig: 345 97 03
+# description:  This is a daemon which broadcasts notifications of system events \
+#               and other messages. See http://www.freedesktop.org/software/dbus/
+#
+# processname: dbus-daemon
+# pidfile: @DBUS_SYSTEM_PID_FILE@
+#
+
+# Sanity checks.
+#[ -x @EXPANDED_BINDIR@/dbus-daemon ] || exit 0
+
+# Source function library.
+#. @EXPANDED_SYSCONFDIR@/rc.d/init.d/functions
+
+# so we can rearrange this easily
+#processname=dbus-daemon
+#servicename=messagebus
+
+#RETVAL=0
+
+start() {
+    echo "Starting system message bus"
+    if [ -x @EXPANDED_BINDIR@/dbus-uuidgen ] ; then
+        @EXPANDED_BINDIR@/dbus-uuidgen --ensure
+    fi
+
+    if [ -x @EXPANDED_BINDIR@/dbus-daemon ];then
+    	@EXPANDED_BINDIR@/dbus-daemon --system
+    fi
+    #daemon --check $servicename $processname --system
+    #RETVAL=$?
+    #echo
+    #[ $RETVAL -eq 0 ] && touch @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename
+}
+
+stop() {
+    echo "Stopping system message bus"
+
+    ## we don't want to kill all the per-user $processname, we want
+    ## to use the pid file *only*; because we use the fake nonexistent 
+    ## program name "$servicename" that should be safe-ish
+    killall dbus-daemon
+    #RETVAL=$?
+    #echo
+    #if [ $RETVAL -eq 0 ]; then
+    #    rm -f @EXPANDED_LOCALSTATEDIR@/lock/subsys/$servicename
+    #    rm -f @DBUS_SYSTEM_PID_FILE@
+    #fi
+}
+
+# See how we were called.
+case "$1" in
+    start)
+        start
+        ;;
+    stop)
+        stop
+        ;;
+    status)
+        status $servicename
+        RETVAL=$?
+        ;;
+    restart)
+        stop
+        start
+        ;;
+    reload)
+        echo "Message bus can't reload its configuration, you have to restart it"
+        RETVAL=$?
+        ;;
+    *)
+        echo $"Usage: $0 {start|stop|status|restart|reload}"
+        ;;
+esac
+exit $RETVAL
diff --git a/dbus/bus/selinux.c b/dbus/bus/selinux.c
new file mode 100644
index 0000000..36287e9
--- /dev/null
+++ b/dbus/bus/selinux.c
@@ -0,0 +1,1093 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ * selinux.c  SELinux security checks for D-Bus
+ *
+ * Author: Matthew Rickard <mjricka@epoch.ncsc.mil>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-string.h>
+#ifndef DBUS_WIN
+#include <dbus/dbus-userdb.h>
+#endif
+#include "selinux.h"
+#include "services.h"
+#include "policy.h"
+#include "utils.h"
+#include "config-parser.h"
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_SELINUX
+#include <sys/types.h>
+#include <unistd.h>
+#include <limits.h>
+#include <pthread.h>
+#include <syslog.h>
+#include <selinux/selinux.h>
+#include <selinux/avc.h>
+#include <selinux/av_permissions.h>
+#include <selinux/flask.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <grp.h>
+#endif /* HAVE_SELINUX */
+#ifdef HAVE_LIBAUDIT
+#include <cap-ng.h>
+#include <libaudit.h>
+#endif /* HAVE_LIBAUDIT */
+
+#define BUS_SID_FROM_SELINUX(sid)  ((BusSELinuxID*) (sid))
+#define SELINUX_SID_FROM_BUS(sid)  ((security_id_t) (sid))
+
+#ifdef HAVE_SELINUX
+/* Store the value telling us if SELinux is enabled in the kernel. */
+static dbus_bool_t selinux_enabled = FALSE;
+
+/* Store an avc_entry_ref to speed AVC decisions. */
+static struct avc_entry_ref aeref;
+
+/* Store the SID of the bus itself to use as the default. */
+static security_id_t bus_sid = SECSID_WILD;
+
+/* Thread to listen for SELinux status changes via netlink. */
+static pthread_t avc_notify_thread;
+
+/* Prototypes for AVC callback functions.  */
+static void log_callback (const char *fmt, ...);
+static void log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft);
+static void *avc_create_thread (void (*run) (void));
+static void avc_stop_thread (void *thread);
+static void *avc_alloc_lock (void);
+static void avc_get_lock (void *lock);
+static void avc_release_lock (void *lock);
+static void avc_free_lock (void *lock);
+
+/* AVC callback structures for use in avc_init.  */
+static const struct avc_memory_callback mem_cb =
+{
+  .func_malloc = dbus_malloc,
+  .func_free = dbus_free
+};
+static const struct avc_log_callback log_cb =
+{
+  .func_log = log_callback,
+  .func_audit = log_audit_callback
+};
+static const struct avc_thread_callback thread_cb =
+{
+  .func_create_thread = avc_create_thread,
+  .func_stop_thread = avc_stop_thread
+};
+static const struct avc_lock_callback lock_cb =
+{
+  .func_alloc_lock = avc_alloc_lock,
+  .func_get_lock = avc_get_lock,
+  .func_release_lock = avc_release_lock,
+  .func_free_lock = avc_free_lock
+};
+#endif /* HAVE_SELINUX */
+
+/**
+ * Log callback to log denial messages from the AVC.
+ * This is used in avc_init.  Logs to both standard
+ * error and syslogd.
+ *
+ * @param fmt the format string
+ * @param variable argument list
+ */
+#ifdef HAVE_SELINUX
+
+#ifdef HAVE_LIBAUDIT
+static int audit_fd = -1;
+#endif
+
+void
+bus_selinux_audit_init(void)
+{
+#ifdef HAVE_LIBAUDIT  
+  audit_fd = audit_open ();
+
+  if (audit_fd < 0)
+    {
+      /* If kernel doesn't support audit, bail out */
+      if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT)
+        return;
+      /* If user bus, bail out */
+      if (errno == EPERM && getuid() != 0)
+        return;
+      _dbus_warn ("Failed opening connection to the audit subsystem");
+    }
+#endif /* HAVE_LIBAUDIT */
+}
+
+static void 
+log_callback (const char *fmt, ...) 
+{
+  va_list ap;
+
+  va_start(ap, fmt);
+
+#ifdef HAVE_LIBAUDIT
+  if (audit_fd >= 0)
+  {
+    capng_get_caps_process();
+    if (capng_have_capability(CAPNG_EFFECTIVE, CAP_AUDIT_WRITE))
+    {
+      char buf[PATH_MAX*2];
+    
+      /* FIXME: need to change this to show real user */
+      vsnprintf(buf, sizeof(buf), fmt, ap);
+      audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL,
+                               NULL, getuid());
+      return;
+    }
+  }
+#endif /* HAVE_LIBAUDIT */
+  
+  vsyslog (LOG_USER | LOG_INFO, fmt, ap);
+  va_end(ap);
+}
+
+/**
+ * On a policy reload we need to reparse the SELinux configuration file, since
+ * this could have changed.  Send a SIGHUP to reload all configs.
+ */
+static int
+policy_reload_callback (u_int32_t event, security_id_t ssid, 
+                        security_id_t tsid, security_class_t tclass, 
+                        access_vector_t perms, access_vector_t *out_retained)
+{
+  if (event == AVC_CALLBACK_RESET)
+    return raise (SIGHUP);
+  
+  return 0;
+}
+
+/**
+ * Log any auxiliary data 
+ */
+static void
+log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft)
+{
+  DBusString *audmsg = data;
+
+  if (bufleft > (size_t) _dbus_string_get_length(audmsg))
+    {
+      _dbus_string_copy_to_buffer_with_nul (audmsg, buf, bufleft);
+    }
+  else
+    {
+      DBusString s;
+
+      _dbus_string_init_const(&s, "Buffer too small for audit message");
+
+      if (bufleft > (size_t) _dbus_string_get_length(&s))
+        _dbus_string_copy_to_buffer_with_nul (&s, buf, bufleft);
+    }
+}
+
+/**
+ * Create thread to notify the AVC of enforcing and policy reload
+ * changes via netlink.
+ *
+ * @param run the thread run function
+ * @return pointer to the thread
+ */
+static void *
+avc_create_thread (void (*run) (void))
+{
+  int rc;
+
+  rc = pthread_create (&avc_notify_thread, NULL, (void *(*) (void *)) run, NULL);
+  if (rc != 0)
+    {
+      _dbus_warn ("Failed to start AVC thread: %s\n", _dbus_strerror (rc));
+      exit (1);
+    }
+  return &avc_notify_thread;
+}
+
+/* Stop AVC netlink thread.  */
+static void
+avc_stop_thread (void *thread)
+{
+  pthread_cancel (*(pthread_t *) thread);
+}
+
+/* Allocate a new AVC lock.  */
+static void *
+avc_alloc_lock (void)
+{
+  pthread_mutex_t *avc_mutex;
+
+  avc_mutex = dbus_new (pthread_mutex_t, 1);
+  if (avc_mutex == NULL)
+    {
+      _dbus_warn ("Could not create mutex: %s\n", _dbus_strerror (errno));
+      exit (1);
+    }
+  pthread_mutex_init (avc_mutex, NULL);
+
+  return avc_mutex;
+}
+
+/* Acquire an AVC lock.  */
+static void
+avc_get_lock (void *lock)
+{
+  pthread_mutex_lock (lock);
+}
+
+/* Release an AVC lock.  */
+static void
+avc_release_lock (void *lock)
+{
+  pthread_mutex_unlock (lock);
+}
+
+/* Free an AVC lock.  */
+static void
+avc_free_lock (void *lock)
+{
+  pthread_mutex_destroy (lock);
+  dbus_free (lock);
+}
+#endif /* HAVE_SELINUX */
+
+/**
+ * Return whether or not SELinux is enabled; must be
+ * called after bus_selinux_init.
+ */
+dbus_bool_t
+bus_selinux_enabled (void)
+{
+#ifdef HAVE_SELINUX
+  return selinux_enabled;
+#else
+  return FALSE;
+#endif /* HAVE_SELINUX */
+}
+
+/**
+ * Do early initialization; determine whether SELinux is enabled.
+ */
+dbus_bool_t
+bus_selinux_pre_init (void)
+{
+#ifdef HAVE_SELINUX
+  int r;
+  _dbus_assert (bus_sid == SECSID_WILD);
+  
+  /* Determine if we are running an SELinux kernel. */
+  r = is_selinux_enabled ();
+  if (r < 0)
+    {
+      _dbus_warn ("Could not tell if SELinux is enabled: %s\n",
+                  _dbus_strerror (errno));
+      return FALSE;
+    }
+
+  selinux_enabled = r != 0;
+  return TRUE;
+#else
+  return TRUE;
+#endif
+}
+
+/**
+ * Initialize the user space access vector cache (AVC) for D-Bus and set up
+ * logging callbacks.
+ */
+dbus_bool_t
+bus_selinux_full_init (void)
+{
+#ifdef HAVE_SELINUX
+  char *bus_context;
+
+  _dbus_assert (bus_sid == SECSID_WILD);
+  
+  if (!selinux_enabled)
+    {
+      _dbus_verbose ("SELinux not enabled in this kernel.\n");
+      return TRUE;
+    }
+
+  _dbus_verbose ("SELinux is enabled in this kernel.\n");
+
+  avc_entry_ref_init (&aeref);
+  if (avc_init ("avc", &mem_cb, &log_cb, &thread_cb, &lock_cb) < 0)
+    {
+      _dbus_warn ("Failed to start Access Vector Cache (AVC).\n");
+      return FALSE;
+    }
+  else
+    {
+      _dbus_verbose ("Access Vector Cache (AVC) started.\n");
+    }
+
+  if (avc_add_callback (policy_reload_callback, AVC_CALLBACK_RESET,
+                       NULL, NULL, 0, 0) < 0)
+    {
+      _dbus_warn ("Failed to add policy reload callback: %s\n",
+                  _dbus_strerror (errno));
+      avc_destroy ();
+      return FALSE;
+    }
+
+  bus_context = NULL;
+  bus_sid = SECSID_WILD;
+
+  if (getcon (&bus_context) < 0)
+    {
+      _dbus_verbose ("Error getting context of bus: %s\n",
+                     _dbus_strerror (errno));
+      return FALSE;
+    }
+      
+  if (avc_context_to_sid (bus_context, &bus_sid) < 0)
+    {
+      _dbus_verbose ("Error getting SID from bus context: %s\n",
+                     _dbus_strerror (errno));
+      freecon (bus_context);
+      return FALSE;
+    }
+
+  freecon (bus_context);
+  
+#endif /* HAVE_SELINUX */
+  return TRUE;
+}
+
+/**
+ * Decrement SID reference count.
+ * 
+ * @param sid the SID to decrement
+ */
+void
+bus_selinux_id_unref (BusSELinuxID *sid)
+{
+#ifdef HAVE_SELINUX
+  if (!selinux_enabled)
+    return;
+
+  _dbus_assert (sid != NULL);
+  
+  sidput (SELINUX_SID_FROM_BUS (sid));
+#endif /* HAVE_SELINUX */
+}
+
+void
+bus_selinux_id_ref (BusSELinuxID *sid)
+{
+#ifdef HAVE_SELINUX
+  if (!selinux_enabled)
+    return;
+
+  _dbus_assert (sid != NULL);
+  
+  sidget (SELINUX_SID_FROM_BUS (sid));
+#endif /* HAVE_SELINUX */
+}
+
+/**
+ * Determine if the SELinux security policy allows the given sender
+ * security context to go to the given recipient security context.
+ * This function determines if the requested permissions are to be
+ * granted from the connection to the message bus or to another
+ * optionally supplied security identifier (e.g. for a service
+ * context).  Currently these permissions are either send_msg or
+ * acquire_svc in the dbus class.
+ *
+ * @param sender_sid source security context
+ * @param override_sid is the target security context.  If SECSID_WILD this will
+ *        use the context of the bus itself (e.g. the default).
+ * @param target_class is the target security class.
+ * @param requested is the requested permissions.
+ * @returns #TRUE if security policy allows the send.
+ */
+#ifdef HAVE_SELINUX
+static dbus_bool_t
+bus_selinux_check (BusSELinuxID        *sender_sid,
+                   BusSELinuxID        *override_sid,
+                   security_class_t     target_class,
+                   access_vector_t      requested,
+		   DBusString          *auxdata)
+{
+  if (!selinux_enabled)
+    return TRUE;
+
+  /* Make the security check.  AVC checks enforcing mode here as well. */
+  if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid),
+                    override_sid ?
+                    SELINUX_SID_FROM_BUS (override_sid) :
+                    SELINUX_SID_FROM_BUS (bus_sid), 
+                    target_class, requested, &aeref, auxdata) < 0)
+    {
+    switch (errno)
+      {
+      case EACCES:
+        _dbus_verbose ("SELinux denying due to security policy.\n");
+        return FALSE;
+      case EINVAL:
+        _dbus_verbose ("SELinux denying due to invalid security context.\n");
+        return FALSE;
+      default:
+        _dbus_verbose ("SELinux denying due to: %s\n", _dbus_strerror (errno));
+        return FALSE;
+      }
+    }
+  else
+    return TRUE;
+}
+#endif /* HAVE_SELINUX */
+
+/**
+ * Returns true if the given connection can acquire a service,
+ * assuming the given security ID is needed for that service.
+ *
+ * @param connection connection that wants to own the service
+ * @param service_sid the SID of the service from the table
+ * @returns #TRUE if acquire is permitted.
+ */
+dbus_bool_t
+bus_selinux_allows_acquire_service (DBusConnection     *connection,
+                                    BusSELinuxID       *service_sid,
+				    const char         *service_name,
+				    DBusError          *error)
+{
+#ifdef HAVE_SELINUX
+  BusSELinuxID *connection_sid;
+  unsigned long spid;
+  DBusString auxdata;
+  dbus_bool_t ret;
+  
+  if (!selinux_enabled)
+    return TRUE;
+  
+  connection_sid = bus_connection_get_selinux_id (connection);
+  if (!dbus_connection_get_unix_process_id (connection, &spid))
+    spid = 0;
+
+  if (!_dbus_string_init (&auxdata))
+    goto oom;
+ 
+  if (!_dbus_string_append (&auxdata, "service="))
+    goto oom;
+
+  if (!_dbus_string_append (&auxdata, service_name))
+    goto oom;
+
+  if (spid)
+    {
+      if (!_dbus_string_append (&auxdata, " spid="))
+	goto oom;
+
+      if (!_dbus_string_append_uint (&auxdata, spid))
+	goto oom;
+    }
+  
+  ret = bus_selinux_check (connection_sid,
+			   service_sid,
+			   SECCLASS_DBUS,
+			   DBUS__ACQUIRE_SVC,
+			   &auxdata);
+
+  _dbus_string_free (&auxdata);
+  return ret;
+
+ oom:
+  _dbus_string_free (&auxdata);
+  BUS_SET_OOM (error);
+  return FALSE;
+
+#else
+  return TRUE;
+#endif /* HAVE_SELINUX */
+}
+
+/**
+ * Check if SELinux security controls allow the message to be sent to a
+ * particular connection based on the security context of the sender and
+ * that of the receiver. The destination connection need not be the
+ * addressed recipient, it could be an "eavesdropper"
+ *
+ * @param sender the sender of the message.
+ * @param proposed_recipient the connection the message is to be sent to.
+ * @returns whether to allow the send
+ */
+dbus_bool_t
+bus_selinux_allows_send (DBusConnection     *sender,
+                         DBusConnection     *proposed_recipient,
+			 const char         *msgtype,
+			 const char         *interface,
+			 const char         *member,
+			 const char         *error_name,
+			 const char         *destination,
+			 DBusError          *error)
+{
+#ifdef HAVE_SELINUX
+  BusSELinuxID *recipient_sid;
+  BusSELinuxID *sender_sid;
+  unsigned long spid, tpid;
+  DBusString auxdata;
+  dbus_bool_t ret;
+  dbus_bool_t string_alloced;
+
+  if (!selinux_enabled)
+    return TRUE;
+
+  if (!sender || !dbus_connection_get_unix_process_id (sender, &spid))
+    spid = 0;
+  if (!proposed_recipient || !dbus_connection_get_unix_process_id (proposed_recipient, &tpid))
+    tpid = 0;
+
+  string_alloced = FALSE;
+  if (!_dbus_string_init (&auxdata))
+    goto oom;
+  string_alloced = TRUE;
+
+  if (!_dbus_string_append (&auxdata, "msgtype="))
+    goto oom;
+
+  if (!_dbus_string_append (&auxdata, msgtype))
+    goto oom;
+
+  if (interface)
+    {
+      if (!_dbus_string_append (&auxdata, " interface="))
+	goto oom;
+      if (!_dbus_string_append (&auxdata, interface))
+	goto oom;
+    }
+
+  if (member)
+    {
+      if (!_dbus_string_append (&auxdata, " member="))
+	goto oom;
+      if (!_dbus_string_append (&auxdata, member))
+	goto oom;
+    }
+
+  if (error_name)
+    {
+      if (!_dbus_string_append (&auxdata, " error_name="))
+	goto oom;
+      if (!_dbus_string_append (&auxdata, error_name))
+	goto oom;
+    }
+
+  if (destination)
+    {
+      if (!_dbus_string_append (&auxdata, " dest="))
+	goto oom;
+      if (!_dbus_string_append (&auxdata, destination))
+	goto oom;
+    }
+
+  if (spid)
+    {
+      if (!_dbus_string_append (&auxdata, " spid="))
+	goto oom;
+
+      if (!_dbus_string_append_uint (&auxdata, spid))
+	goto oom;
+    }
+
+  if (tpid)
+    {
+      if (!_dbus_string_append (&auxdata, " tpid="))
+	goto oom;
+
+      if (!_dbus_string_append_uint (&auxdata, tpid))
+	goto oom;
+    }
+
+  sender_sid = bus_connection_get_selinux_id (sender);
+  /* A NULL proposed_recipient means the bus itself. */
+  if (proposed_recipient)
+    recipient_sid = bus_connection_get_selinux_id (proposed_recipient);
+  else
+    recipient_sid = BUS_SID_FROM_SELINUX (bus_sid);
+
+  ret = bus_selinux_check (sender_sid, 
+			   recipient_sid,
+			   SECCLASS_DBUS, 
+			   DBUS__SEND_MSG,
+			   &auxdata);
+
+  _dbus_string_free (&auxdata);
+
+  return ret;
+
+ oom:
+  if (string_alloced)
+    _dbus_string_free (&auxdata);
+  BUS_SET_OOM (error);
+  return FALSE;
+  
+#else
+  return TRUE;
+#endif /* HAVE_SELINUX */
+}
+
+dbus_bool_t
+bus_selinux_append_context (DBusMessage    *message,
+			    BusSELinuxID   *sid,
+			    DBusError      *error)
+{
+#ifdef HAVE_SELINUX
+  char *context;
+
+  if (avc_sid_to_context (SELINUX_SID_FROM_BUS (sid), &context) < 0)
+    {
+      if (errno == ENOMEM)
+        BUS_SET_OOM (error);
+      else
+        dbus_set_error (error, DBUS_ERROR_FAILED,
+                        "Error getting context from SID: %s\n",
+			_dbus_strerror (errno));
+      return FALSE;
+    }
+  if (!dbus_message_append_args (message,
+				 DBUS_TYPE_ARRAY,
+				 DBUS_TYPE_BYTE,
+				 &context,
+				 strlen (context),
+				 DBUS_TYPE_INVALID))
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+  freecon (context);
+  return TRUE;
+#else
+  return TRUE;
+#endif
+}
+
+/**
+ * Gets the security context of a connection to the bus. It is up to
+ * the caller to freecon() when they are done. 
+ *
+ * @param connection the connection to get the context of.
+ * @param con the location to store the security context.
+ * @returns #TRUE if context is successfully obtained.
+ */
+#ifdef HAVE_SELINUX
+static dbus_bool_t
+bus_connection_read_selinux_context (DBusConnection     *connection,
+                                     char              **con)
+{
+  int fd;
+
+  if (!selinux_enabled)
+    return FALSE;
+
+  _dbus_assert (connection != NULL);
+  
+  if (!dbus_connection_get_unix_fd (connection, &fd))
+    {
+      _dbus_verbose ("Failed to get file descriptor of socket.\n");
+      return FALSE;
+    }
+  
+  if (getpeercon (fd, con) < 0)
+    {
+      _dbus_verbose ("Error getting context of socket peer: %s\n",
+                     _dbus_strerror (errno));
+      return FALSE;
+    }
+  
+  _dbus_verbose ("Successfully read connection context.\n");
+  return TRUE;
+}
+#endif /* HAVE_SELINUX */
+
+/**
+ * Read the SELinux ID from the connection.
+ *
+ * @param connection the connection to read from
+ * @returns the SID if successfully determined, #NULL otherwise.
+ */
+BusSELinuxID*
+bus_selinux_init_connection_id (DBusConnection *connection,
+                                DBusError      *error)
+{
+#ifdef HAVE_SELINUX
+  char *con;
+  security_id_t sid;
+  
+  if (!selinux_enabled)
+    return NULL;
+
+  if (!bus_connection_read_selinux_context (connection, &con))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Failed to read an SELinux context from connection");
+      _dbus_verbose ("Error getting peer context.\n");
+      return NULL;
+    }
+
+  _dbus_verbose ("Converting context to SID to store on connection\n");
+
+  if (avc_context_to_sid (con, &sid) < 0)
+    {
+      if (errno == ENOMEM)
+        BUS_SET_OOM (error);
+      else
+        dbus_set_error (error, DBUS_ERROR_FAILED,
+                        "Error getting SID from context \"%s\": %s\n",
+			con, _dbus_strerror (errno));
+      
+      _dbus_warn ("Error getting SID from context \"%s\": %s\n",
+		  con, _dbus_strerror (errno));
+      
+      freecon (con);
+      return NULL;
+    }
+ 
+  freecon (con); 
+  return BUS_SID_FROM_SELINUX (sid);
+#else
+  return NULL;
+#endif /* HAVE_SELINUX */
+}
+
+
+/**
+ * Function for freeing hash table data.  These SIDs
+ * should no longer be referenced.
+ */
+static void
+bus_selinux_id_table_free_value (BusSELinuxID *sid)
+{
+#ifdef HAVE_SELINUX
+  /* NULL sometimes due to how DBusHashTable works */
+  if (sid)
+    bus_selinux_id_unref (sid);
+#endif /* HAVE_SELINUX */
+}
+
+/**
+ * Creates a new table mapping service names to security ID.
+ * A security ID is a "compiled" security context, a security
+ * context is just a string.
+ *
+ * @returns the new table or #NULL if no memory
+ */
+DBusHashTable*
+bus_selinux_id_table_new (void)
+{
+  return _dbus_hash_table_new (DBUS_HASH_STRING,
+                               (DBusFreeFunction) dbus_free,
+                               (DBusFreeFunction) bus_selinux_id_table_free_value);
+}
+
+/** 
+ * Hashes a service name and service context into the service SID
+ * table as a string and a SID.
+ *
+ * @param service_name is the name of the service.
+ * @param service_context is the context of the service.
+ * @param service_table is the table to hash them into.
+ * @return #FALSE if not enough memory
+ */
+dbus_bool_t
+bus_selinux_id_table_insert (DBusHashTable *service_table,
+                             const char    *service_name,
+                             const char    *service_context)
+{
+#ifdef HAVE_SELINUX
+  dbus_bool_t retval;
+  security_id_t sid;
+  char *key;
+
+  if (!selinux_enabled)
+    return TRUE;
+
+  sid = SECSID_WILD;
+  retval = FALSE;
+
+  key = _dbus_strdup (service_name);
+  if (key == NULL)
+    return retval;
+  
+  if (avc_context_to_sid ((char *) service_context, &sid) < 0)
+    {
+      if (errno == ENOMEM)
+        {
+	  dbus_free (key);
+          return FALSE;
+	}
+
+      _dbus_warn ("Error getting SID from context \"%s\": %s\n",
+		  (char *) service_context,
+                  _dbus_strerror (errno));
+      goto out;
+    }
+
+  if (!_dbus_hash_table_insert_string (service_table,
+                                       key,
+                                       BUS_SID_FROM_SELINUX (sid)))
+    goto out;
+
+  _dbus_verbose ("Parsed \tservice: %s \n\t\tcontext: %s\n",
+                  key, 
+                  sid->ctx);
+
+  /* These are owned by the hash, so clear them to avoid unref */
+  key = NULL;
+  sid = SECSID_WILD;
+
+  retval = TRUE;
+  
+ out:
+  if (sid != SECSID_WILD)
+    sidput (sid);
+
+  if (key)
+    dbus_free (key);
+
+  return retval;
+#else
+  return TRUE;
+#endif /* HAVE_SELINUX */
+}
+
+
+/**
+ * Find the security identifier associated with a particular service
+ * name.  Return a pointer to this SID, or #NULL/SECSID_WILD if the
+ * service is not found in the hash table.  This should be nearly a
+ * constant time operation.  If SELinux support is not available,
+ * always return NULL.
+ *
+ * @param service_table the hash table to check for service name.
+ * @param service_name the name of the service to look for.
+ * @returns the SELinux ID associated with the service
+ */
+BusSELinuxID*
+bus_selinux_id_table_lookup (DBusHashTable    *service_table,
+                             const DBusString *service_name)
+{
+#ifdef HAVE_SELINUX
+  security_id_t sid;
+
+  sid = SECSID_WILD;     /* default context */
+
+  if (!selinux_enabled)
+    return NULL;
+  
+  _dbus_verbose ("Looking up service SID for %s\n",
+                 _dbus_string_get_const_data (service_name));
+
+  sid = _dbus_hash_table_lookup_string (service_table,
+                                        _dbus_string_get_const_data (service_name));
+
+  if (sid == SECSID_WILD)
+    _dbus_verbose ("Service %s not found\n", 
+                   _dbus_string_get_const_data (service_name));
+  else
+    _dbus_verbose ("Service %s found\n", 
+                   _dbus_string_get_const_data (service_name));
+
+  return BUS_SID_FROM_SELINUX (sid);
+#endif /* HAVE_SELINUX */
+  return NULL;
+}
+
+/**
+ * Get the SELinux policy root.  This is used to find the D-Bus
+ * specific config file within the policy.
+ */
+const char *
+bus_selinux_get_policy_root (void)
+{
+#ifdef HAVE_SELINUX
+  return selinux_policy_root ();
+#else
+  return NULL;
+#endif /* HAVE_SELINUX */
+} 
+
+/**
+ * For debugging:  Print out the current hash table of service SIDs.
+ */
+void
+bus_selinux_id_table_print (DBusHashTable *service_table)
+{
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+#ifdef HAVE_SELINUX
+  DBusHashIter iter;
+
+  if (!selinux_enabled)
+    return;
+  
+  _dbus_verbose ("Service SID Table:\n");
+  _dbus_hash_iter_init (service_table, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      const char *key = _dbus_hash_iter_get_string_key (&iter);
+      security_id_t sid = _dbus_hash_iter_get_value (&iter);
+      _dbus_verbose ("The key is %s\n", key);
+      _dbus_verbose ("The context is %s\n", sid->ctx);
+      _dbus_verbose ("The refcount is %d\n", sid->refcnt);
+    }
+#endif /* HAVE_SELINUX */
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+}
+
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+#ifdef HAVE_SELINUX
+/**
+ * Print out some AVC statistics.
+ */
+static void
+bus_avc_print_stats (void)
+{
+  struct avc_cache_stats cstats;
+
+  if (!selinux_enabled)
+    return;
+  
+  _dbus_verbose ("AVC Statistics:\n");
+  avc_cache_stats (&cstats);
+  avc_av_stats ();
+  _dbus_verbose ("AVC Cache Statistics:\n");
+  _dbus_verbose ("Entry lookups: %d\n", cstats.entry_lookups);
+  _dbus_verbose ("Entry hits: %d\n", cstats.entry_hits);
+  _dbus_verbose ("Entry misses %d\n", cstats.entry_misses);
+  _dbus_verbose ("Entry discards: %d\n", cstats.entry_discards);
+  _dbus_verbose ("CAV lookups: %d\n", cstats.cav_lookups);
+  _dbus_verbose ("CAV hits: %d\n", cstats.cav_hits);
+  _dbus_verbose ("CAV probes: %d\n", cstats.cav_probes);
+  _dbus_verbose ("CAV misses: %d\n", cstats.cav_misses);
+}
+#endif /* HAVE_SELINUX */
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+
+
+/**
+ * Destroy the AVC before we terminate.
+ */
+void
+bus_selinux_shutdown (void)
+{
+#ifdef HAVE_SELINUX
+  if (!selinux_enabled)
+    return;
+
+  _dbus_verbose ("AVC shutdown\n");
+
+  if (bus_sid != SECSID_WILD)
+    {
+      sidput (bus_sid);
+      bus_sid = SECSID_WILD;
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+ 
+      if (_dbus_is_verbose()) 
+        bus_avc_print_stats ();
+ 
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+
+      avc_destroy ();
+#ifdef HAVE_LIBAUDIT
+      audit_close (audit_fd);
+#endif /* HAVE_LIBAUDIT */
+    }
+#endif /* HAVE_SELINUX */
+}
+
+/* The !HAVE_LIBAUDIT case lives in dbus-sysdeps-util-unix.c */
+#ifdef HAVE_LIBAUDIT
+/**
+ * Changes the user and group the bus is running as.
+ *
+ * @param user the user to become
+ * @param error return location for errors
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_change_to_daemon_user  (const char    *user,
+                              DBusError     *error)
+{
+  dbus_uid_t uid;
+  dbus_gid_t gid;
+  DBusString u;
+
+  _dbus_string_init_const (&u, user);
+
+  if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "User '%s' does not appear to exist?",
+                      user);
+      return FALSE;
+    }
+
+  /* If we were root */
+  if (_dbus_geteuid () == 0)
+    {
+      int rc;
+
+      capng_clear (CAPNG_SELECT_BOTH);
+      capng_update (CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED,
+                    CAP_AUDIT_WRITE);
+      rc = capng_change_id (uid, gid, CAPNG_DROP_SUPP_GRP);
+      if (rc)
+        {
+          switch (rc) {
+            default:
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Failed to drop capabilities: %s\n",
+                              _dbus_strerror (errno));
+              break;
+            case -4:
+              dbus_set_error (error, _dbus_error_from_errno (errno),
+                              "Failed to set GID to %lu: %s", gid,
+                              _dbus_strerror (errno));
+              break;
+            case -5:
+              _dbus_warn ("Failed to drop supplementary groups: %s\n",
+                          _dbus_strerror (errno));
+              break;
+            case -6:
+              dbus_set_error (error, _dbus_error_from_errno (errno),
+                              "Failed to set UID to %lu: %s", uid,
+                              _dbus_strerror (errno));
+              break;
+            case -7:
+              dbus_set_error (error, _dbus_error_from_errno (errno),
+                              "Failed to unset keep-capabilities: %s\n",
+                              _dbus_strerror (errno));
+              break;
+          }
+          return FALSE;
+        }
+    }
+
+ return TRUE;
+}
+#endif
diff --git a/dbus/bus/selinux.h b/dbus/bus/selinux.h
new file mode 100644
index 0000000..3bab36d
--- /dev/null
+++ b/dbus/bus/selinux.h
@@ -0,0 +1,72 @@
+/* selinux.h  SELinux security check headers for D-BUS
+ *
+ * Author: Matthew Rickard <mjricka@epoch.ncsc.mil>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_SELINUX_H
+#define BUS_SELINUX_H
+
+#include <dbus/dbus-hash.h>
+#include <dbus/dbus-connection.h>
+#include "services.h"
+
+dbus_bool_t bus_selinux_pre_init (void);
+dbus_bool_t bus_selinux_full_init(void);
+void        bus_selinux_shutdown (void);
+
+dbus_bool_t bus_selinux_enabled  (void);
+
+void bus_selinux_id_ref    (BusSELinuxID *sid);
+void bus_selinux_id_unref  (BusSELinuxID *sid);
+
+DBusHashTable* bus_selinux_id_table_new    (void);
+BusSELinuxID*  bus_selinux_id_table_lookup (DBusHashTable    *service_table,
+                                            const DBusString *service_name);
+dbus_bool_t    bus_selinux_id_table_insert (DBusHashTable    *service_table,
+                                            const char       *service_name,
+                                            const char       *service_context);
+void           bus_selinux_id_table_print  (DBusHashTable    *service_table);
+const char*    bus_selinux_get_policy_root (void);
+
+dbus_bool_t    bus_selinux_append_context      (DBusMessage    *message,
+						BusSELinuxID   *context,
+						DBusError      *error);
+
+dbus_bool_t bus_selinux_allows_acquire_service (DBusConnection *connection,
+                                                BusSELinuxID   *service_sid,
+						const char     *service_name,
+						DBusError      *error);
+
+dbus_bool_t bus_selinux_allows_send            (DBusConnection *sender,
+                                                DBusConnection *proposed_recipient,
+						const char     *msgtype, /* Supplementary audit data */
+						const char     *interface,
+						const char     *member,
+						const char     *error_name,
+						const char     *destination,
+						DBusError      *error);
+
+BusSELinuxID* bus_selinux_init_connection_id (DBusConnection *connection,
+                                              DBusError      *error);
+
+
+void bus_selinux_audit_init(void);
+
+#endif /* BUS_SELINUX_H */
diff --git a/dbus/bus/services.c b/dbus/bus/services.c
new file mode 100644
index 0000000..6f380fa
--- /dev/null
+++ b/dbus/bus/services.c
@@ -0,0 +1,1304 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* services.c  Service management
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include <dbus/dbus-hash.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-mempool.h>
+#include <dbus/dbus-marshal-validate.h>
+
+#include "driver.h"
+#include "services.h"
+#include "connection.h"
+#include "utils.h"
+#include "activation.h"
+#include "policy.h"
+#include "bus.h"
+#include "selinux.h"
+
+struct BusService
+{
+  int refcount;
+
+  BusRegistry *registry;
+  char *name;
+  DBusList *owners;
+};
+
+struct BusOwner
+{
+  int refcount;
+
+  BusService *service;
+  DBusConnection *conn;
+
+  unsigned int allow_replacement : 1;
+  unsigned int do_not_queue : 1;
+};
+
+struct BusRegistry
+{
+  int refcount;
+
+  BusContext *context;
+  
+  DBusHashTable *service_hash;
+  DBusMemPool   *service_pool;
+  DBusMemPool   *owner_pool;
+
+  DBusHashTable *service_sid_table;
+};
+
+BusRegistry*
+bus_registry_new (BusContext *context)
+{
+  BusRegistry *registry;
+
+  registry = dbus_new0 (BusRegistry, 1);
+  if (registry == NULL)
+    return NULL;
+
+  registry->refcount = 1;
+  registry->context = context;
+  
+  registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
+                                                 NULL, NULL);
+  if (registry->service_hash == NULL)
+    goto failed;
+  
+  registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
+                                               TRUE);
+
+  if (registry->service_pool == NULL)
+    goto failed;
+
+  registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
+                                             TRUE);
+
+  if (registry->owner_pool == NULL)
+    goto failed;
+
+  registry->service_sid_table = NULL;
+  
+  return registry;
+
+ failed:
+  bus_registry_unref (registry);
+  return NULL;
+}
+
+BusRegistry *
+bus_registry_ref (BusRegistry *registry)
+{
+  _dbus_assert (registry->refcount > 0);
+  registry->refcount += 1;
+
+  return registry;
+}
+
+void
+bus_registry_unref  (BusRegistry *registry)
+{
+  _dbus_assert (registry->refcount > 0);
+  registry->refcount -= 1;
+
+  if (registry->refcount == 0)
+    {
+      if (registry->service_hash)
+        _dbus_hash_table_unref (registry->service_hash);
+      if (registry->service_pool)
+        _dbus_mem_pool_free (registry->service_pool);
+      if (registry->owner_pool)
+        _dbus_mem_pool_free (registry->owner_pool);
+      if (registry->service_sid_table)
+        _dbus_hash_table_unref (registry->service_sid_table);
+      
+      dbus_free (registry);
+    }
+}
+
+BusService*
+bus_registry_lookup (BusRegistry      *registry,
+                     const DBusString *service_name)
+{
+  BusService *service;
+
+  service = _dbus_hash_table_lookup_string (registry->service_hash,
+                                            _dbus_string_get_const_data (service_name));
+
+  return service;
+}
+
+static DBusList *
+_bus_service_find_owner_link (BusService *service,
+                              DBusConnection *connection)
+{
+  DBusList *link;
+  
+  link = _dbus_list_get_first_link (&service->owners);
+
+  while (link != NULL)
+    {
+      BusOwner *bus_owner;
+
+      bus_owner = (BusOwner *) link->data;
+      if (bus_owner->conn == connection) 
+        break;
+
+      link = _dbus_list_get_next_link (&service->owners, link);
+    }
+
+  return link;
+}
+
+static void
+bus_owner_set_flags (BusOwner *owner,
+                     dbus_uint32_t flags)
+{
+   owner->allow_replacement = 
+        (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
+
+   owner->do_not_queue =
+        (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
+}
+
+static BusOwner *
+bus_owner_new (BusService *service, 
+               DBusConnection *conn, 
+	       dbus_uint32_t flags)
+{
+  BusOwner *result;
+
+  result = _dbus_mem_pool_alloc (service->registry->owner_pool);
+  if (result != NULL)
+    {
+      result->refcount = 1;
+      /* don't ref the connection because we don't want
+         to block the connection from going away.
+         transactions take care of reffing the connection
+         but we need to use refcounting on the owner
+         so that the owner does not get freed before
+         we can deref the connection in the transaction
+       */
+      result->conn = conn;
+      result->service = service;
+
+      if (!bus_connection_add_owned_service (conn, service))
+        {
+          _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
+          return NULL;
+        }
+        
+      bus_owner_set_flags (result, flags);
+    }
+  return result;
+}
+
+static BusOwner *
+bus_owner_ref (BusOwner *owner)
+{
+  _dbus_assert (owner->refcount > 0);
+  owner->refcount += 1;
+
+  return owner;
+}
+
+static void
+bus_owner_unref  (BusOwner *owner)
+{
+  _dbus_assert (owner->refcount > 0);
+  owner->refcount -= 1;
+
+  if (owner->refcount == 0)
+    {
+      bus_connection_remove_owned_service (owner->conn, owner->service);
+      _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
+    }
+}
+
+BusService*
+bus_registry_ensure (BusRegistry               *registry,
+                     const DBusString          *service_name,
+                     DBusConnection            *owner_connection_if_created,
+                     dbus_uint32_t              flags,
+                     BusTransaction            *transaction,
+                     DBusError                 *error)
+{
+  BusService *service;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  _dbus_assert (owner_connection_if_created != NULL);
+  _dbus_assert (transaction != NULL);
+
+  service = _dbus_hash_table_lookup_string (registry->service_hash,
+                                            _dbus_string_get_const_data (service_name));
+  if (service != NULL)
+    return service;
+  
+  service = _dbus_mem_pool_alloc (registry->service_pool);
+  if (service == NULL)
+    {
+      BUS_SET_OOM (error);
+      return NULL;
+    }
+
+  service->registry = registry;  
+  service->refcount = 1;
+
+  _dbus_verbose ("copying string %p '%s' to service->name\n",
+                 service_name, _dbus_string_get_const_data (service_name));
+  if (!_dbus_string_copy_data (service_name, &service->name))
+    {
+      _dbus_mem_pool_dealloc (registry->service_pool, service);
+      BUS_SET_OOM (error);
+      return NULL;
+    }
+  _dbus_verbose ("copied string %p '%s' to '%s'\n",
+                 service_name, _dbus_string_get_const_data (service_name),
+                 service->name);
+
+  if (!bus_driver_send_service_owner_changed (service->name, 
+					      NULL,
+					      bus_connection_get_name (owner_connection_if_created),
+					      transaction, error))
+    {
+      bus_service_unref (service);
+      return NULL;
+    }
+
+  if (!bus_activation_service_created (bus_context_get_activation (registry->context),
+				       service->name, transaction, error))
+    {
+      bus_service_unref (service);
+      return NULL;
+    }
+  
+  if (!bus_service_add_owner (service, owner_connection_if_created, flags,
+                                              transaction, error))
+    {
+      bus_service_unref (service);
+      return NULL;
+    }
+  
+  if (!_dbus_hash_table_insert_string (registry->service_hash,
+                                       service->name,
+                                       service))
+    {
+      /* The add_owner gets reverted on transaction cancel */
+      BUS_SET_OOM (error);
+      return NULL;
+    }
+  
+  return service;
+}
+
+void
+bus_registry_foreach (BusRegistry               *registry,
+                      BusServiceForeachFunction  function,
+                      void                      *data)
+{
+  DBusHashIter iter;
+  
+  _dbus_hash_iter_init (registry->service_hash, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      BusService *service = _dbus_hash_iter_get_value (&iter);
+
+      (* function) (service, data);
+    }
+}
+
+dbus_bool_t
+bus_registry_list_services (BusRegistry *registry,
+                            char      ***listp,
+                            int         *array_len)
+{
+  int i, j, len;
+  char **retval;
+  DBusHashIter iter;
+   
+  len = _dbus_hash_table_get_n_entries (registry->service_hash);
+  retval = dbus_new (char *, len + 1);
+
+  if (retval == NULL)
+    return FALSE;
+
+  _dbus_hash_iter_init (registry->service_hash, &iter);
+  i = 0;
+  while (_dbus_hash_iter_next (&iter))
+    {
+      BusService *service = _dbus_hash_iter_get_value (&iter);
+
+      retval[i] = _dbus_strdup (service->name);
+      if (retval[i] == NULL)
+	goto error;
+
+      i++;
+    }
+
+  retval[i] = NULL;
+  
+  if (array_len)
+    *array_len = len;
+  
+  *listp = retval;
+  return TRUE;
+  
+ error:
+  for (j = 0; j < i; j++)
+    dbus_free (retval[i]);
+  dbus_free (retval);
+
+  return FALSE;
+}
+
+dbus_bool_t
+bus_registry_acquire_service (BusRegistry      *registry,
+                              DBusConnection   *connection,
+                              const DBusString *service_name,
+                              dbus_uint32_t     flags,
+                              dbus_uint32_t    *result,
+                              BusTransaction   *transaction,
+                              DBusError        *error)
+{
+  dbus_bool_t retval;
+  DBusConnection *old_owner_conn;
+  BusClientPolicy *policy;
+  BusService *service;
+  BusActivation  *activation;
+  BusSELinuxID *sid;
+  BusOwner *primary_owner;
+ 
+  retval = FALSE;
+
+  if (!_dbus_validate_bus_name (service_name, 0,
+                                _dbus_string_get_length (service_name)))
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Requested bus name \"%s\" is not valid",
+                      _dbus_string_get_const_data (service_name));
+      
+      _dbus_verbose ("Attempt to acquire invalid service name\n");
+      
+      goto out;
+    }
+  
+  if (_dbus_string_get_byte (service_name, 0) == ':')
+    {
+      /* Not allowed; only base services can start with ':' */
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Cannot acquire a service starting with ':' such as \"%s\"",
+                      _dbus_string_get_const_data (service_name));
+      
+      _dbus_verbose ("Attempt to acquire invalid base service name \"%s\"",
+                     _dbus_string_get_const_data (service_name));
+      
+      goto out;
+    }
+
+  if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Connection \"%s\" is not allowed to own the service \"%s\"because "
+                      "it is reserved for D-Bus' use only",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)",
+                      DBUS_SERVICE_DBUS);
+      goto out;
+    }
+
+  policy = bus_connection_get_policy (connection);
+  _dbus_assert (policy != NULL);
+
+  /* Note that if sid is #NULL then the bus's own context gets used
+   * in bus_connection_selinux_allows_acquire_service()
+   */
+  sid = bus_selinux_id_table_lookup (registry->service_sid_table,
+                                     service_name);
+
+  if (!bus_selinux_allows_acquire_service (connection, sid,
+					   _dbus_string_get_const_data (service_name), error))
+    {
+
+      if (dbus_error_is_set (error) &&
+	  dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
+	{
+	  goto out;
+	}
+
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "Connection \"%s\" is not allowed to own the service \"%s\" due "
+                      "to SELinux policy",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)",
+                      _dbus_string_get_const_data (service_name));
+      goto out;
+    }
+  
+  if (!bus_client_policy_check_can_own (policy, service_name))
+    {
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "Connection \"%s\" is not allowed to own the service \"%s\" due "
+                      "to security policies in the configuration file",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)",
+                      _dbus_string_get_const_data (service_name));
+      goto out;
+    }
+
+  if (bus_connection_get_n_services_owned (connection) >=
+      bus_context_get_max_services_per_connection (registry->context))
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                      "Connection \"%s\" is not allowed to own more services "
+                      "(increase limits in configuration file if required)",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)");
+      goto out;
+    }
+  
+  service = bus_registry_lookup (registry, service_name);
+
+  if (service != NULL)
+    {
+      primary_owner = bus_service_get_primary_owner (service);
+      if (primary_owner != NULL)
+        old_owner_conn = primary_owner->conn;
+      else
+        old_owner_conn = NULL;
+    }
+  else
+    old_owner_conn = NULL;
+      
+  if (service == NULL)
+    {
+      service = bus_registry_ensure (registry,
+                                     service_name, connection, flags,
+                                     transaction, error);
+      if (service == NULL)
+        goto out;
+    }
+
+  primary_owner = bus_service_get_primary_owner (service);
+  if (primary_owner == NULL)
+    goto out;
+
+  if (old_owner_conn == NULL)
+    {
+      _dbus_assert (primary_owner->conn == connection);
+
+      *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;      
+    }
+  else if (old_owner_conn == connection)
+    {
+      bus_owner_set_flags (primary_owner, flags);
+      *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
+    }
+  else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
+           !(bus_service_get_allow_replacement (service))) ||
+	   ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
+           !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING))) 
+    {
+      DBusList *link;
+      BusOwner *temp_owner;
+    /* Since we can't be queued if we are already in the queue
+       remove us */
+
+      link = _bus_service_find_owner_link (service, connection);
+      if (link != NULL)
+        {
+          _dbus_list_unlink (&service->owners, link);
+          temp_owner = (BusOwner *)link->data;
+          bus_owner_unref (temp_owner); 
+          _dbus_list_free_link (link);
+        }
+      
+      *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
+    }
+  else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
+           (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
+	    !(bus_service_get_allow_replacement (service))))
+    {
+      /* Queue the connection */
+      if (!bus_service_add_owner (service, connection, 
+                                  flags,
+                                  transaction, error))
+        goto out;
+      
+      *result = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
+    }
+  else
+    {
+      /* Replace the current owner */
+
+      /* We enqueue the new owner and remove the first one because
+       * that will cause NameAcquired and NameLost messages to
+       * be sent.
+       */
+      
+      if (!bus_service_add_owner (service, connection,
+                                  flags,
+                                  transaction, error))
+        goto out;
+
+      if (primary_owner->do_not_queue)
+        {
+          if (!bus_service_remove_owner (service, old_owner_conn,
+                                         transaction, error))
+            goto out;
+        }
+      else
+        {
+          if (!bus_service_swap_owner (service, old_owner_conn,
+                                       transaction, error))
+            goto out;
+        }
+        
+    
+      _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
+      *result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
+    }
+
+  activation = bus_context_get_activation (registry->context);
+  retval = bus_activation_send_pending_auto_activation_messages (activation,
+								 service,
+								 transaction,
+								 error);
+  
+ out:
+  return retval;
+}
+
+dbus_bool_t
+bus_registry_release_service (BusRegistry      *registry,
+                              DBusConnection   *connection,
+                              const DBusString *service_name,
+                              dbus_uint32_t    *result,
+                              BusTransaction   *transaction,
+                              DBusError        *error)
+{
+  dbus_bool_t retval;
+  BusService *service;
+
+  retval = FALSE;
+
+  if (!_dbus_validate_bus_name (service_name, 0,
+                                _dbus_string_get_length (service_name)))
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Given bus name \"%s\" is not valid",
+                      _dbus_string_get_const_data (service_name));
+
+      _dbus_verbose ("Attempt to release invalid service name\n");
+
+      goto out;
+    }
+
+  if (_dbus_string_get_byte (service_name, 0) == ':')
+    {
+      /* Not allowed; the base service name cannot be created or released */
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Cannot release a service starting with ':' such as \"%s\"",
+                      _dbus_string_get_const_data (service_name));
+
+      _dbus_verbose ("Attempt to release invalid base service name \"%s\"",
+                     _dbus_string_get_const_data (service_name));
+
+      goto out;
+    }
+
+   if (_dbus_string_equal_c_str (service_name, DBUS_SERVICE_DBUS))
+    {
+      /* Not allowed; the base service name cannot be created or released */
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Cannot release the %s service because it is owned by the bus",
+                     DBUS_SERVICE_DBUS);
+
+      _dbus_verbose ("Attempt to release service name \"%s\"",
+                     DBUS_SERVICE_DBUS);
+
+      goto out;
+    }
+
+  service = bus_registry_lookup (registry, service_name);
+
+  if (service == NULL)
+    {
+      *result = DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
+    }
+  else if (!bus_service_has_owner (service, connection))
+    {
+      *result = DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
+    }
+  else
+    {
+      if (!bus_service_remove_owner (service, connection,
+                                     transaction, error))
+        goto out;
+
+      _dbus_assert (!bus_service_has_owner (service, connection));
+      *result = DBUS_RELEASE_NAME_REPLY_RELEASED;
+    }
+
+  retval = TRUE;
+
+ out:
+  return retval;
+}
+
+dbus_bool_t
+bus_registry_set_service_context_table (BusRegistry   *registry,
+					DBusHashTable *table)
+{
+  DBusHashTable *new_table;
+  DBusHashIter iter;
+  
+  new_table = bus_selinux_id_table_new ();
+  if (!new_table)
+    return FALSE;
+
+  _dbus_hash_iter_init (table, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      const char *service = _dbus_hash_iter_get_string_key (&iter);
+      const char *context = _dbus_hash_iter_get_value (&iter);
+
+      if (!bus_selinux_id_table_insert (new_table,
+					service,
+					context))
+	return FALSE;
+    }
+  
+  if (registry->service_sid_table)
+    _dbus_hash_table_unref (registry->service_sid_table);
+  registry->service_sid_table = new_table;
+  return TRUE;
+}
+
+static void
+bus_service_unlink_owner (BusService      *service,
+                          BusOwner        *owner)
+{
+  _dbus_list_remove_last (&service->owners, owner);
+  bus_owner_unref (owner);
+}
+
+static void
+bus_service_unlink (BusService *service)
+{
+  _dbus_assert (service->owners == NULL);
+
+  /* the service may not be in the hash, if
+   * the failure causing transaction cancel
+   * was in the right place, but that's OK
+   */
+  _dbus_hash_table_remove_string (service->registry->service_hash,
+                                  service->name);
+  
+  bus_service_unref (service);
+}
+
+static void
+bus_service_relink (BusService           *service,
+                    DBusPreallocatedHash *preallocated)
+{
+  _dbus_assert (service->owners == NULL);
+  _dbus_assert (preallocated != NULL);
+
+  _dbus_hash_table_insert_string_preallocated (service->registry->service_hash,
+                                               preallocated,
+                                               service->name,
+                                               service);
+  
+  bus_service_ref (service);
+}
+
+/**
+ * Data used to represent an ownership cancellation in
+ * a bus transaction.
+ */
+typedef struct
+{
+  BusOwner *owner;            /**< the owner */
+  BusService *service;        /**< service to cancel ownership of */
+} OwnershipCancelData;
+
+static void
+cancel_ownership (void *data)
+{
+  OwnershipCancelData *d = data;
+
+  /* We don't need to send messages notifying of these
+   * changes, since we're reverting something that was
+   * cancelled (effectively never really happened)
+   */
+  bus_service_unlink_owner (d->service, d->owner);
+  
+  if (d->service->owners == NULL)
+    bus_service_unlink (d->service);
+}
+
+static void
+free_ownership_cancel_data (void *data)
+{
+  OwnershipCancelData *d = data;
+
+  dbus_connection_unref (d->owner->conn);
+  bus_owner_unref (d->owner);
+  bus_service_unref (d->service);
+  
+  dbus_free (d);
+}
+
+static dbus_bool_t
+add_cancel_ownership_to_transaction (BusTransaction *transaction,
+                                     BusService     *service,
+                                     BusOwner       *owner)
+{
+  OwnershipCancelData *d;
+
+  d = dbus_new (OwnershipCancelData, 1);
+  if (d == NULL)
+    return FALSE;
+  
+  d->service = service;
+  d->owner = owner;
+
+  if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
+                                        free_ownership_cancel_data))
+    {
+      dbus_free (d);
+      return FALSE;
+    }
+
+  bus_service_ref (d->service);
+  bus_owner_ref (owner);
+  dbus_connection_ref (d->owner->conn);
+ 
+  return TRUE;
+}
+
+/* this function is self-cancelling if you cancel the transaction */
+dbus_bool_t
+bus_service_add_owner (BusService     *service,
+                       DBusConnection *connection,
+                       dbus_uint32_t  flags,
+                       BusTransaction *transaction,
+                       DBusError      *error)
+{
+  BusOwner *bus_owner;
+  DBusList *bus_owner_link;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+ /* Send service acquired message first, OOM will result
+  * in cancelling the transaction
+  */
+  if (service->owners == NULL)
+    {
+      if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
+        return FALSE;
+    }
+  
+  bus_owner_link = _bus_service_find_owner_link (service, connection);
+  
+  if (bus_owner_link == NULL)
+    {
+      bus_owner = bus_owner_new (service, connection, flags);
+      if (bus_owner == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      bus_owner_set_flags (bus_owner, flags);
+      if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
+        {
+          if (!_dbus_list_append (&service->owners,
+                                  bus_owner))
+            {
+              bus_owner_unref (bus_owner);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+        }
+      else
+        {
+          if (!_dbus_list_insert_after (&service->owners,
+                                         _dbus_list_get_first_link (&service->owners),
+                                         bus_owner))
+            {
+              bus_owner_unref (bus_owner);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+        }      
+    } 
+  else 
+    {
+      /* Update the link since we are already in the queue
+       * No need for operations that can produce OOM
+       */
+
+      bus_owner = (BusOwner *) bus_owner_link->data;
+      if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
+        {
+	  DBusList *link;
+          _dbus_list_unlink (&service->owners, bus_owner_link);
+	  link = _dbus_list_get_first_link (&service->owners);
+	  _dbus_assert (link != NULL);
+	  
+          _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
+        }
+      
+      bus_owner_set_flags (bus_owner, flags);
+      return TRUE;
+    }
+
+  if (!add_cancel_ownership_to_transaction (transaction,
+                                            service,
+                                            bus_owner))
+    {
+      bus_service_unlink_owner (service, bus_owner);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+typedef struct
+{
+  BusOwner       *owner;
+  BusService     *service;
+  BusOwner       *before_owner; /* restore to position before this connection in owners list */
+  DBusList       *owner_link;
+  DBusList       *service_link;
+  DBusPreallocatedHash *hash_entry;
+} OwnershipRestoreData;
+
+static void
+restore_ownership (void *data)
+{
+  OwnershipRestoreData *d = data;
+  DBusList *link;
+
+  _dbus_assert (d->service_link != NULL);
+  _dbus_assert (d->owner_link != NULL);
+  
+  if (d->service->owners == NULL)
+    {
+      _dbus_assert (d->hash_entry != NULL);
+      bus_service_relink (d->service, d->hash_entry);
+    }
+  else
+    {
+      _dbus_assert (d->hash_entry == NULL);
+    }
+  
+  /* We don't need to send messages notifying of these
+   * changes, since we're reverting something that was
+   * cancelled (effectively never really happened)
+   */
+  link = _dbus_list_get_first_link (&d->service->owners);
+  while (link != NULL)
+    {
+      if (link->data == d->before_owner)
+        break;
+
+      link = _dbus_list_get_next_link (&d->service->owners, link);
+    }
+  
+  _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
+
+  /* Note that removing then restoring this changes the order in which
+   * ServiceDeleted messages are sent on destruction of the
+   * connection.  This should be OK as the only guarantee there is
+   * that the base service is destroyed last, and we never even
+   * tentatively remove the base service.
+   */
+  bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
+  
+  d->hash_entry = NULL;
+  d->service_link = NULL;
+  d->owner_link = NULL;
+}
+
+static void
+free_ownership_restore_data (void *data)
+{
+  OwnershipRestoreData *d = data;
+
+  if (d->service_link)
+    _dbus_list_free_link (d->service_link);
+  if (d->owner_link)
+    _dbus_list_free_link (d->owner_link);
+  if (d->hash_entry)
+    _dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
+                                              d->hash_entry);
+
+  dbus_connection_unref (d->owner->conn);
+  bus_owner_unref (d->owner);
+  bus_service_unref (d->service);
+  
+  dbus_free (d);
+}
+
+static dbus_bool_t
+add_restore_ownership_to_transaction (BusTransaction *transaction,
+                                      BusService     *service,
+                                      BusOwner       *owner)
+{
+  OwnershipRestoreData *d;
+  DBusList *link;
+
+  d = dbus_new (OwnershipRestoreData, 1);
+  if (d == NULL)
+    return FALSE;
+  
+  d->service = service;
+  d->owner = owner;
+  d->service_link = _dbus_list_alloc_link (service);
+  d->owner_link = _dbus_list_alloc_link (owner);
+  d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
+  
+  bus_service_ref (d->service);
+  bus_owner_ref (d->owner);
+  dbus_connection_ref (d->owner->conn);
+
+  d->before_owner = NULL;
+  link = _dbus_list_get_first_link (&service->owners);
+  while (link != NULL)
+    {
+      if (link->data == owner)
+        {
+          link = _dbus_list_get_next_link (&service->owners, link);
+
+          if (link)
+            d->before_owner = link->data;
+
+          break;
+        }
+      
+      link = _dbus_list_get_next_link (&service->owners, link);
+    }
+  
+  if (d->service_link == NULL ||
+      d->owner_link == NULL ||
+      d->hash_entry == NULL ||
+      !bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
+                                        free_ownership_restore_data))
+    {
+      free_ownership_restore_data (d);
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+dbus_bool_t
+bus_service_swap_owner (BusService     *service,
+                        DBusConnection *connection,
+                        BusTransaction *transaction,
+                        DBusError      *error)
+{
+  DBusList *swap_link;
+  BusOwner *primary_owner;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  /* We send out notifications before we do any work we
+   * might have to undo if the notification-sending failed
+   */
+  
+  /* Send service lost message */
+  primary_owner = bus_service_get_primary_owner (service);
+  if (primary_owner == NULL || primary_owner->conn != connection)
+    _dbus_assert_not_reached ("Tried to swap a non primary owner");
+
+    
+  if (!bus_driver_send_service_lost (connection, service->name,
+                                     transaction, error))
+    return FALSE;
+
+  if (service->owners == NULL)
+    {
+      _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
+    }
+  else if (_dbus_list_length_is_one (&service->owners))
+    {
+      _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
+    }
+  else
+    {
+      DBusList *link;
+      BusOwner *new_owner;
+      DBusConnection *new_owner_conn;
+      link = _dbus_list_get_first_link (&service->owners);
+      _dbus_assert (link != NULL);
+      link = _dbus_list_get_next_link (&service->owners, link);
+      _dbus_assert (link != NULL);
+
+      new_owner = (BusOwner *)link->data;
+      new_owner_conn = new_owner->conn;
+
+      if (!bus_driver_send_service_owner_changed (service->name,
+ 						  bus_connection_get_name (connection),
+ 						  bus_connection_get_name (new_owner_conn),
+ 						  transaction, error))
+        return FALSE;
+
+      /* This will be our new owner */
+      if (!bus_driver_send_service_acquired (new_owner_conn,
+                                             service->name,
+                                             transaction,
+                                             error))
+        return FALSE;
+    }
+
+  if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  /* unlink the primary and make it the second link */
+  swap_link = _dbus_list_get_first_link (&service->owners);
+  _dbus_list_unlink (&service->owners, swap_link);
+
+  _dbus_list_insert_after_link (&service->owners,
+                                _dbus_list_get_first_link (&service->owners),
+				swap_link);
+
+  return TRUE;
+}
+
+/* this function is self-cancelling if you cancel the transaction */
+dbus_bool_t
+bus_service_remove_owner (BusService     *service,
+                          DBusConnection *connection,
+                          BusTransaction *transaction,
+                          DBusError      *error)
+{
+  BusOwner *primary_owner;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  /* We send out notifications before we do any work we
+   * might have to undo if the notification-sending failed
+   */
+  
+  /* Send service lost message */
+  primary_owner = bus_service_get_primary_owner (service);
+  if (primary_owner != NULL && primary_owner->conn == connection)
+    {
+      if (!bus_driver_send_service_lost (connection, service->name,
+                                         transaction, error))
+        return FALSE;
+    }
+  else
+    {
+      /* if we are not the primary owner then just remove us from the queue */
+      DBusList *link;
+      BusOwner *temp_owner;
+
+      link = _bus_service_find_owner_link (service, connection);
+      _dbus_list_unlink (&service->owners, link);
+      temp_owner = (BusOwner *)link->data;
+      bus_owner_unref (temp_owner); 
+      _dbus_list_free_link (link);
+
+      return TRUE; 
+    }
+
+  if (service->owners == NULL)
+    {
+      _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
+    }
+  else if (_dbus_list_length_is_one (&service->owners))
+    {
+      if (!bus_driver_send_service_owner_changed (service->name,
+ 						  bus_connection_get_name (connection),
+ 						  NULL,
+ 						  transaction, error))
+        return FALSE;
+    }
+  else
+    {
+      DBusList *link;
+      BusOwner *new_owner;
+      DBusConnection *new_owner_conn;
+      link = _dbus_list_get_first_link (&service->owners);
+      _dbus_assert (link != NULL);
+      link = _dbus_list_get_next_link (&service->owners, link);
+      _dbus_assert (link != NULL);
+
+      new_owner = (BusOwner *)link->data;
+      new_owner_conn = new_owner->conn;
+
+      if (!bus_driver_send_service_owner_changed (service->name,
+ 						  bus_connection_get_name (connection),
+ 						  bus_connection_get_name (new_owner_conn),
+ 						  transaction, error))
+        return FALSE;
+
+      /* This will be our new owner */
+      if (!bus_driver_send_service_acquired (new_owner_conn,
+                                             service->name,
+                                             transaction,
+                                             error))
+        return FALSE;
+    }
+
+  if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+ 
+  bus_service_unlink_owner (service, primary_owner);
+
+  if (service->owners == NULL)
+    bus_service_unlink (service);
+
+  return TRUE;
+}
+
+BusService *
+bus_service_ref (BusService *service)
+{
+  _dbus_assert (service->refcount > 0);
+  
+  service->refcount += 1;
+
+  return service;
+}
+
+void
+bus_service_unref (BusService *service)
+{
+  _dbus_assert (service->refcount > 0);
+  
+  service->refcount -= 1;
+
+  if (service->refcount == 0)
+    {
+      _dbus_assert (service->owners == NULL);
+      
+      dbus_free (service->name);
+      _dbus_mem_pool_dealloc (service->registry->service_pool, service);
+    }
+}
+
+DBusConnection *
+bus_service_get_primary_owners_connection (BusService *service)
+{
+  BusOwner *owner;
+
+  owner = bus_service_get_primary_owner (service);
+
+  if (owner != NULL)
+    return owner->conn;
+  else
+    return NULL;
+}
+
+BusOwner*
+bus_service_get_primary_owner (BusService *service)
+{
+  return _dbus_list_get_first (&service->owners);
+}
+
+const char*
+bus_service_get_name (BusService *service)
+{
+  return service->name;
+}
+
+dbus_bool_t
+bus_service_get_allow_replacement (BusService *service)
+{
+  BusOwner *owner;
+  DBusList *link;
+ 
+  _dbus_assert (service->owners != NULL);
+
+  link = _dbus_list_get_first_link (&service->owners);
+  owner = (BusOwner *) link->data;
+
+  return owner->allow_replacement;
+}
+
+dbus_bool_t
+bus_service_has_owner (BusService     *service,
+		       DBusConnection *connection)
+{
+  DBusList *link;
+
+  link = _bus_service_find_owner_link (service, connection);
+ 
+  if (link == NULL)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+dbus_bool_t 
+bus_service_list_queued_owners (BusService *service,
+                                DBusList  **return_list,
+                                DBusError  *error)
+{
+  DBusList *link;
+
+  _dbus_assert (*return_list == NULL);
+
+  link = _dbus_list_get_first_link (&service->owners);
+  _dbus_assert (link != NULL);
+  
+  while (link != NULL)
+    {
+      BusOwner *owner;
+      const char *uname;
+
+      owner = (BusOwner *) link->data;
+      uname = bus_connection_get_name (owner->conn);
+
+      if (!_dbus_list_append (return_list, (char *)uname))
+        goto oom;
+
+      link = _dbus_list_get_next_link (&service->owners, link);
+    }
+  
+  return TRUE;
+  
+ oom:
+  _dbus_list_clear (return_list);
+  BUS_SET_OOM (error);
+  return FALSE;
+}
diff --git a/dbus/bus/services.h b/dbus/bus/services.h
new file mode 100644
index 0000000..056dd9f
--- /dev/null
+++ b/dbus/bus/services.h
@@ -0,0 +1,94 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* services.h  Service management
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_SERVICES_H
+#define BUS_SERVICES_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-hash.h>
+#include "connection.h"
+#include "bus.h"
+
+typedef void (* BusServiceForeachFunction) (BusService       *service,
+                                            void             *data);
+
+BusRegistry* bus_registry_new             (BusContext                  *context);
+BusRegistry* bus_registry_ref             (BusRegistry                 *registry);
+void         bus_registry_unref           (BusRegistry                 *registry);
+BusService*  bus_registry_lookup          (BusRegistry                 *registry,
+                                           const DBusString            *service_name);
+BusService*  bus_registry_ensure          (BusRegistry                 *registry,
+                                           const DBusString            *service_name,
+                                           DBusConnection              *owner_connection_if_created,
+					   dbus_uint32_t                flags,
+                                           BusTransaction              *transaction,
+                                           DBusError                   *error);
+void         bus_registry_foreach         (BusRegistry                 *registry,
+                                           BusServiceForeachFunction    function,
+                                           void                        *data);
+dbus_bool_t  bus_registry_list_services   (BusRegistry                 *registry,
+                                           char                      ***listp,
+                                           int                         *array_len);
+dbus_bool_t  bus_registry_acquire_service (BusRegistry                 *registry,
+                                           DBusConnection              *connection,
+                                           const DBusString            *service_name,
+                                           dbus_uint32_t                flags,
+                                           dbus_uint32_t               *result,
+                                           BusTransaction              *transaction,
+                                           DBusError                   *error);
+dbus_bool_t  bus_registry_release_service (BusRegistry                 *registry,
+                                           DBusConnection              *connection,
+                                           const DBusString            *service_name,
+                                           dbus_uint32_t               *result,
+                                           BusTransaction              *transaction,
+                                           DBusError                   *error);
+dbus_bool_t  bus_registry_set_service_context_table (BusRegistry           *registry,
+						     DBusHashTable         *table);
+
+BusService*     bus_service_ref                       (BusService     *service);
+void            bus_service_unref                     (BusService     *service);
+dbus_bool_t     bus_service_add_owner                 (BusService     *service,
+                                                       DBusConnection *connection,
+						       dbus_uint32_t   flags,
+                                                       BusTransaction *transaction,
+                                                       DBusError      *error);
+dbus_bool_t     bus_service_swap_owner                (BusService     *service,
+                                                       DBusConnection *connection,
+                                                       BusTransaction *transaction,
+                                                       DBusError      *error);
+dbus_bool_t     bus_service_remove_owner              (BusService     *service,
+                                                       DBusConnection *connection,
+                                                       BusTransaction *transaction,
+                                                       DBusError      *error);
+dbus_bool_t     bus_service_has_owner                 (BusService     *service,
+                                                       DBusConnection *connection);
+BusOwner*       bus_service_get_primary_owner         (BusService     *service);
+dbus_bool_t     bus_service_get_allow_replacement     (BusService     *service);
+const char*     bus_service_get_name                  (BusService     *service);
+dbus_bool_t     bus_service_list_queued_owners        (BusService *service,
+                                                       DBusList  **return_list,
+                                                       DBusError  *error);
+
+DBusConnection* bus_service_get_primary_owners_connection (BusService     *service);
+#endif /* BUS_SERVICES_H */
diff --git a/dbus/bus/session.conf.in b/dbus/bus/session.conf.in
new file mode 100644
index 0000000..e121ff9
--- /dev/null
+++ b/dbus/bus/session.conf.in
@@ -0,0 +1,63 @@
+<!-- This configuration file controls the per-user-login-session message bus.
+     Add a session-local.conf and edit that rather than changing this 
+     file directly. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <!-- Our well-known bus type, don't change this -->
+  <type>session</type>
+
+  <!-- If we fork, keep the user's original umask to avoid affecting
+       the behavior of child processes. -->
+  <keep_umask/>
+
+  <listen>@DBUS_SESSION_BUS_DEFAULT_ADDRESS@</listen>
+
+  <standard_session_servicedirs />
+
+  <policy context="default">
+    <!-- Allow everything to be sent -->
+    <allow send_destination="*" eavesdrop="true"/>
+    <!-- Allow everything to be received -->
+    <allow eavesdrop="true"/>
+    <!-- Allow anyone to own anything -->
+    <allow own="*"/>
+  </policy>
+
+  <!-- Config files are placed here that among other things, 
+       further restrict the above policy for specific services. -->
+  <includedir>session.d</includedir>
+
+  <!-- This is included last so local configuration can override what's 
+       in this standard file -->
+  <include ignore_missing="yes">session-local.conf</include>
+
+  <include if_selinux_enabled="yes" selinux_root_relative="yes">contexts/dbus_contexts</include>
+
+  <!-- For the session bus, override the default relatively-low limits 
+       with essentially infinite limits, since the bus is just running 
+       as the user anyway, using up bus resources is not something we need 
+       to worry about. In some cases, we do set the limits lower than 
+       "all available memory" if exceeding the limit is almost certainly a bug, 
+       having the bus enforce a limit is nicer than a huge memory leak. But the 
+       intent is that these limits should never be hit. -->
+
+  <!-- the memory limits are 1G instead of say 4G because they can't exceed 32-bit signed int max -->
+  <limit name="max_incoming_bytes">1000000000</limit>
+  <limit name="max_incoming_unix_fds">250000000</limit>
+  <limit name="max_outgoing_bytes">1000000000</limit>
+  <limit name="max_outgoing_unix_fds">250000000</limit>
+  <limit name="max_message_size">1000000000</limit>
+  <limit name="max_message_unix_fds">4096</limit>
+  <limit name="service_start_timeout">120000</limit>  
+  <limit name="auth_timeout">240000</limit>
+  <limit name="max_completed_connections">100000</limit>  
+  <limit name="max_incomplete_connections">10000</limit>
+  <limit name="max_connections_per_user">100000</limit>
+  <limit name="max_pending_service_starts">10000</limit>
+  <limit name="max_names_per_connection">50000</limit>
+  <limit name="max_match_rules_per_connection">50000</limit>
+  <limit name="max_replies_per_connection">50000</limit>
+
+</busconfig>
diff --git a/dbus/bus/signals.c b/dbus/bus/signals.c
new file mode 100644
index 0000000..28506d3
--- /dev/null
+++ b/dbus/bus/signals.c
@@ -0,0 +1,2815 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* signals.c  Bus signal connection implementation
+ *
+ * Copyright (C) 2003, 2005  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "signals.h"
+#include "services.h"
+#include "utils.h"
+#include <dbus/dbus-marshal-validate.h>
+
+struct BusMatchRule
+{
+  int refcount;       /**< reference count */
+
+  DBusConnection *matches_go_to; /**< Owner of the rule */
+
+  unsigned int flags; /**< BusMatchFlags */
+
+  int   message_type;
+  char *interface;
+  char *member;
+  char *sender;
+  char *destination;
+  char *path;
+
+  unsigned int *arg_lens;
+  char **args;
+  int args_len;
+};
+
+#define BUS_MATCH_ARG_NAMESPACE   0x4000000u
+#define BUS_MATCH_ARG_IS_PATH  0x8000000u
+
+#define BUS_MATCH_ARG_FLAGS (BUS_MATCH_ARG_NAMESPACE | BUS_MATCH_ARG_IS_PATH)
+
+BusMatchRule*
+bus_match_rule_new (DBusConnection *matches_go_to)
+{
+  BusMatchRule *rule;
+
+  rule = dbus_new0 (BusMatchRule, 1);
+  if (rule == NULL)
+    return NULL;
+
+  rule->refcount = 1;
+  rule->matches_go_to = matches_go_to;
+
+#ifndef DBUS_BUILD_TESTS
+  _dbus_assert (rule->matches_go_to != NULL);
+#endif
+  
+  return rule;
+}
+
+BusMatchRule *
+bus_match_rule_ref (BusMatchRule *rule)
+{
+  _dbus_assert (rule->refcount > 0);
+
+  rule->refcount += 1;
+
+  return rule;
+}
+
+void
+bus_match_rule_unref (BusMatchRule *rule)
+{
+  _dbus_assert (rule->refcount > 0);
+
+  rule->refcount -= 1;
+  if (rule->refcount == 0)
+    {
+      dbus_free (rule->interface);
+      dbus_free (rule->member);
+      dbus_free (rule->sender);
+      dbus_free (rule->destination);
+      dbus_free (rule->path);
+      dbus_free (rule->arg_lens);
+
+      /* can't use dbus_free_string_array() since there
+       * are embedded NULL
+       */
+      if (rule->args)
+        {
+          int i;
+
+          i = 0;
+          while (i < rule->args_len)
+            {
+              if (rule->args[i])
+                dbus_free (rule->args[i]);
+              ++i;
+            }
+
+          dbus_free (rule->args);
+        }
+      
+      dbus_free (rule);
+    }
+}
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+/* Note this function does not do escaping, so it's only
+ * good for debug spew at the moment
+ */
+static char*
+match_rule_to_string (BusMatchRule *rule)
+{
+  DBusString str;
+  char *ret;
+  
+  if (!_dbus_string_init (&str))
+    {
+      char *s;
+      while ((s = _dbus_strdup ("nomem")) == NULL)
+        ; /* only OK for debug spew... */
+      return s;
+    }
+  
+  if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
+    {
+      if (!_dbus_string_append_printf (&str, "type='%s'",
+            dbus_message_type_to_string (rule->message_type)))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_INTERFACE)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+      
+      if (!_dbus_string_append_printf (&str, "interface='%s'", rule->interface))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_MEMBER)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+      
+      if (!_dbus_string_append_printf (&str, "member='%s'", rule->member))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_PATH)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+      
+      if (!_dbus_string_append_printf (&str, "path='%s'", rule->path))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_PATH_NAMESPACE)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+
+      if (!_dbus_string_append_printf (&str, "path_namespace='%s'", rule->path))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_SENDER)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+      
+      if (!_dbus_string_append_printf (&str, "sender='%s'", rule->sender))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_DESTINATION)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+      
+      if (!_dbus_string_append_printf (&str, "destination='%s'", rule->destination))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+
+      if (!_dbus_string_append_printf (&str, "eavesdrop='%s'",
+            (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) ?
+            "true" : "false"))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_ARGS)
+    {
+      int i;
+      
+      _dbus_assert (rule->args != NULL);
+
+      i = 0;
+      while (i < rule->args_len)
+        {
+          if (rule->args[i] != NULL)
+            {
+              dbus_bool_t is_path, is_namespace;
+
+              if (_dbus_string_get_length (&str) > 0)
+                {
+                  if (!_dbus_string_append (&str, ","))
+                    goto nomem;
+                }
+
+              is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0;
+              is_namespace = (rule->arg_lens[i] & BUS_MATCH_ARG_NAMESPACE) != 0;
+              
+              if (!_dbus_string_append_printf (&str,
+                                               "arg%d%s='%s'",
+                                               i,
+                                               is_path ? "path" :
+                                               is_namespace ? "namespace" : "",
+                                               rule->args[i]))
+                goto nomem;
+            }
+          
+          ++i;
+        }
+    }
+  
+  if (!_dbus_string_steal_data (&str, &ret))
+    goto nomem;
+
+  _dbus_string_free (&str);
+  return ret;
+  
+ nomem:
+  _dbus_string_free (&str);
+  {
+    char *s;
+    while ((s = _dbus_strdup ("nomem")) == NULL)
+      ;  /* only OK for debug spew... */
+    return s;
+  }
+}
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+
+dbus_bool_t
+bus_match_rule_set_message_type (BusMatchRule *rule,
+                                 int           type)
+{
+  rule->flags |= BUS_MATCH_MESSAGE_TYPE;
+
+  rule->message_type = type;
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_match_rule_set_interface (BusMatchRule *rule,
+                              const char   *interface)
+{
+  char *new;
+
+  _dbus_assert (interface != NULL);
+
+  new = _dbus_strdup (interface);
+  if (new == NULL)
+    return FALSE;
+
+  rule->flags |= BUS_MATCH_INTERFACE;
+  dbus_free (rule->interface);
+  rule->interface = new;
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_match_rule_set_member (BusMatchRule *rule,
+                           const char   *member)
+{
+  char *new;
+
+  _dbus_assert (member != NULL);
+
+  new = _dbus_strdup (member);
+  if (new == NULL)
+    return FALSE;
+
+  rule->flags |= BUS_MATCH_MEMBER;
+  dbus_free (rule->member);
+  rule->member = new;
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_match_rule_set_sender (BusMatchRule *rule,
+                           const char   *sender)
+{
+  char *new;
+
+  _dbus_assert (sender != NULL);
+
+  new = _dbus_strdup (sender);
+  if (new == NULL)
+    return FALSE;
+
+  rule->flags |= BUS_MATCH_SENDER;
+  dbus_free (rule->sender);
+  rule->sender = new;
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_match_rule_set_destination (BusMatchRule *rule,
+                                const char   *destination)
+{
+  char *new;
+
+  _dbus_assert (destination != NULL);
+
+  new = _dbus_strdup (destination);
+  if (new == NULL)
+    return FALSE;
+
+  rule->flags |= BUS_MATCH_DESTINATION;
+  dbus_free (rule->destination);
+  rule->destination = new;
+
+  return TRUE;
+}
+
+void
+bus_match_rule_set_client_is_eavesdropping (BusMatchRule *rule,
+                                            dbus_bool_t is_eavesdropping)
+{
+  if (is_eavesdropping)
+    rule->flags |= BUS_MATCH_CLIENT_IS_EAVESDROPPING;
+  else
+    rule->flags &= ~(BUS_MATCH_CLIENT_IS_EAVESDROPPING);
+}
+
+dbus_bool_t
+bus_match_rule_set_path (BusMatchRule *rule,
+                         const char   *path,
+                         dbus_bool_t   is_namespace)
+{
+  char *new;
+
+  _dbus_assert (path != NULL);
+
+  new = _dbus_strdup (path);
+  if (new == NULL)
+    return FALSE;
+
+  rule->flags &= ~(BUS_MATCH_PATH|BUS_MATCH_PATH_NAMESPACE);
+
+  if (is_namespace)
+    rule->flags |= BUS_MATCH_PATH_NAMESPACE;
+  else
+    rule->flags |= BUS_MATCH_PATH;
+
+  dbus_free (rule->path);
+  rule->path = new;
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_match_rule_set_arg (BusMatchRule     *rule,
+                        int                arg,
+                        const DBusString *value,
+                        dbus_bool_t       is_path,
+                        dbus_bool_t       is_namespace)
+{
+  int length;
+  char *new;
+
+  _dbus_assert (value != NULL);
+
+  /* args_len is the number of args not including null termination
+   * in the char**
+   */
+  if (arg >= rule->args_len)
+    {
+      unsigned int *new_arg_lens;
+      char **new_args;
+      int new_args_len;
+      int i;
+
+      new_args_len = arg + 1;
+
+      /* add another + 1 here for null termination */
+      new_args = dbus_realloc (rule->args,
+                               sizeof (char *) * (new_args_len + 1));
+      if (new_args == NULL)
+        return FALSE;
+
+      /* NULL the new slots */
+      i = rule->args_len;
+      while (i <= new_args_len) /* <= for null termination */
+        {
+          new_args[i] = NULL;
+          ++i;
+        }
+      
+      rule->args = new_args;
+
+      /* and now add to the lengths */
+      new_arg_lens = dbus_realloc (rule->arg_lens,
+                                   sizeof (int) * (new_args_len + 1));
+
+      if (new_arg_lens == NULL)
+        return FALSE;
+
+      /* zero the new slots */
+      i = rule->args_len;
+      while (i <= new_args_len) /* <= for null termination */
+        {
+          new_arg_lens[i] = 0;
+          ++i;
+        }
+
+      rule->arg_lens = new_arg_lens;
+      rule->args_len = new_args_len;
+    }
+
+  length = _dbus_string_get_length (value);
+  if (!_dbus_string_copy_data (value, &new))
+    return FALSE;
+
+  rule->flags |= BUS_MATCH_ARGS;
+
+  dbus_free (rule->args[arg]);
+  rule->arg_lens[arg] = length;
+  rule->args[arg] = new;
+
+  if (is_path)
+    rule->arg_lens[arg] |= BUS_MATCH_ARG_IS_PATH;
+
+  if (is_namespace)
+    rule->arg_lens[arg] |= BUS_MATCH_ARG_NAMESPACE;
+
+  /* NULL termination didn't get busted */
+  _dbus_assert (rule->args[rule->args_len] == NULL);
+  _dbus_assert (rule->arg_lens[rule->args_len] == 0);
+
+  return TRUE;
+}
+
+#define ISWHITE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
+
+static dbus_bool_t
+find_key (const DBusString *str,
+          int               start,
+          DBusString       *key,
+          int              *value_pos,
+          DBusError        *error)
+{
+  const char *p;
+  const char *s;
+  const char *key_start;
+  const char *key_end;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  s = _dbus_string_get_const_data (str);
+
+  p = s + start;
+
+  while (*p && ISWHITE (*p))
+    ++p;
+
+  key_start = p;
+
+  while (*p && *p != '=' && !ISWHITE (*p))
+    ++p;
+
+  key_end = p;
+
+  while (*p && ISWHITE (*p))
+    ++p;
+  
+  if (key_start == key_end)
+    {
+      /* Empty match rules or trailing whitespace are OK */
+      *value_pos = p - s;
+      return TRUE;
+    }
+
+  if (*p != '=')
+    {
+      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                      "Match rule has a key with no subsequent '=' character");
+      return FALSE;
+    }
+  ++p;
+  
+  if (!_dbus_string_append_len (key, key_start, key_end - key_start))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  *value_pos = p - s;
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+find_value (const DBusString *str,
+            int               start,
+            const char       *key,
+            DBusString       *value,
+            int              *value_end,
+            DBusError        *error)
+{
+  const char *p;
+  const char *s;
+  char quote_char;
+  int orig_len;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  orig_len = _dbus_string_get_length (value);
+  
+  s = _dbus_string_get_const_data (str);
+
+  p = s + start;
+
+  quote_char = '\0';
+
+  while (*p)
+    {
+      if (quote_char == '\0')
+        {
+          switch (*p)
+            {
+            case '\0':
+              goto done;
+
+            case '\'':
+              quote_char = '\'';
+              goto next;
+              
+            case ',':
+              ++p;
+              goto done;
+
+            case '\\':
+              quote_char = '\\';
+              goto next;
+              
+            default:
+              if (!_dbus_string_append_byte (value, *p))
+                {
+                  BUS_SET_OOM (error);
+                  goto failed;
+                }
+            }
+        }
+      else if (quote_char == '\\')
+        {
+          /* \ only counts as an escape if escaping a quote mark */
+          if (*p != '\'')
+            {
+              if (!_dbus_string_append_byte (value, '\\'))
+                {
+                  BUS_SET_OOM (error);
+                  goto failed;
+                }
+            }
+
+          if (!_dbus_string_append_byte (value, *p))
+            {
+              BUS_SET_OOM (error);
+              goto failed;
+            }
+          
+          quote_char = '\0';
+        }
+      else
+        {
+          _dbus_assert (quote_char == '\'');
+
+          if (*p == '\'')
+            {
+              quote_char = '\0';
+            }
+          else
+            {
+              if (!_dbus_string_append_byte (value, *p))
+                {
+                  BUS_SET_OOM (error);
+                  goto failed;
+                }
+            }
+        }
+
+    next:
+      ++p;
+    }
+
+ done:
+
+  if (quote_char == '\\')
+    {
+      if (!_dbus_string_append_byte (value, '\\'))
+        {
+          BUS_SET_OOM (error);
+          goto failed;
+        }
+    }
+  else if (quote_char == '\'')
+    {
+      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                      "Unbalanced quotation marks in match rule");
+      goto failed;
+    }
+  else
+    _dbus_assert (quote_char == '\0');
+
+  /* Zero-length values are allowed */
+  
+  *value_end = p - s;
+  
+  return TRUE;
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  _dbus_string_set_length (value, orig_len);
+  return FALSE;
+}
+
+/* duplicates aren't allowed so the real legitimate max is only 6 or
+ * so. Leaving extra so we don't have to bother to update it.
+ * FIXME this is sort of busted now with arg matching, but we let
+ * you match on up to 10 args for now
+ */
+#define MAX_RULE_TOKENS 16
+
+/* this is slightly too high level to be termed a "token"
+ * but let's not be pedantic.
+ */
+typedef struct
+{
+  char *key;
+  char *value;
+} RuleToken;
+
+static dbus_bool_t
+tokenize_rule (const DBusString *rule_text,
+               RuleToken         tokens[MAX_RULE_TOKENS],
+               DBusError        *error) 
+{
+  int i;
+  int pos;
+  DBusString key;
+  DBusString value;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+  
+  if (!_dbus_string_init (&key))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&value))
+    {
+      _dbus_string_free (&key);
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  i = 0;
+  pos = 0;
+  while (i < MAX_RULE_TOKENS &&
+         pos < _dbus_string_get_length (rule_text))
+    {
+      _dbus_assert (tokens[i].key == NULL);
+      _dbus_assert (tokens[i].value == NULL);
+
+      if (!find_key (rule_text, pos, &key, &pos, error))
+        goto out;
+
+      if (_dbus_string_get_length (&key) == 0)
+        goto next;
+      
+      if (!_dbus_string_steal_data (&key, &tokens[i].key))
+        {
+          BUS_SET_OOM (error);
+          goto out;
+        }
+
+      if (!find_value (rule_text, pos, tokens[i].key, &value, &pos, error))
+        goto out;
+
+      if (!_dbus_string_steal_data (&value, &tokens[i].value))
+        {
+          BUS_SET_OOM (error);
+          goto out;
+        }
+
+    next:
+      ++i;
+    }
+
+  retval = TRUE;
+  
+ out:
+  if (!retval)
+    {
+      i = 0;
+      while (tokens[i].key || tokens[i].value)
+        {
+          dbus_free (tokens[i].key);
+          dbus_free (tokens[i].value);
+          tokens[i].key = NULL;
+          tokens[i].value = NULL;
+          ++i;
+        }
+    }
+  
+  _dbus_string_free (&key);
+  _dbus_string_free (&value);
+  
+  return retval;
+}
+
+static dbus_bool_t
+bus_match_rule_parse_arg_match (BusMatchRule     *rule,
+                                const char       *key,
+                                const DBusString *value,
+                                DBusError        *error)
+{
+  dbus_bool_t is_path = FALSE;
+  dbus_bool_t is_namespace = FALSE;
+  DBusString key_str;
+  unsigned long arg;
+  int length;
+  int end;
+
+  /* For now, arg0='foo' always implies that 'foo' is a
+   * DBUS_TYPE_STRING. Someday we could add an arg0type='int32' thing
+   * if we wanted, which would specify another type, in which case
+   * arg0='5' would have the 5 parsed as an int rather than string.
+   */
+  
+  /* First we need to parse arg0 = 0, arg27 = 27 */
+
+  _dbus_string_init_const (&key_str, key);
+  length = _dbus_string_get_length (&key_str);
+
+  if (_dbus_string_get_length (&key_str) < 4)
+    {
+      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                      "Key '%s' in match rule starts with 'arg' but lacks an arg number. Should be 'arg0' or 'arg7' for example.\n", key);
+      goto failed;
+    }
+
+  if (!_dbus_string_parse_uint (&key_str, 3, &arg, &end))
+    {
+      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                      "Key '%s' in match rule starts with 'arg' but could not parse arg number. Should be 'arg0' or 'arg7' for example.\n", key);
+      goto failed;
+    }
+
+  if (end != length)
+    {
+      if ((end + strlen ("path")) == length &&
+          _dbus_string_ends_with_c_str (&key_str, "path"))
+        {
+          is_path = TRUE;
+        }
+      else if (_dbus_string_equal_c_str (&key_str, "arg0namespace"))
+        {
+          int value_len = _dbus_string_get_length (value);
+
+          is_namespace = TRUE;
+
+          if (!_dbus_validate_bus_namespace (value, 0, value_len))
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                  "arg0namespace='%s' is not a valid prefix of a bus name",
+                  _dbus_string_get_const_data (value));
+              goto failed;
+            }
+        }
+      else
+        {
+          dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+              "Key '%s' in match rule contains junk after argument number (%u). Only 'arg%upath' (for example) or 'arg0namespace' are valid", key, arg, arg);
+          goto failed;
+        }
+    }
+
+  /* If we didn't check this we could allocate a huge amount of RAM */
+  if (arg > DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER)
+    {
+      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                      "Key '%s' in match rule has arg number %lu but the maximum is %d.\n", key, (unsigned long) arg, DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER);
+      goto failed;
+    }
+  
+  if ((rule->flags & BUS_MATCH_ARGS) &&
+      rule->args_len > (int) arg &&
+      rule->args[arg] != NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                      "Argument %d matched more than once in match rule\n", key);
+      goto failed;
+    }
+  
+  if (!bus_match_rule_set_arg (rule, arg, value, is_path, is_namespace))
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  return TRUE;
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  return FALSE;
+}
+
+/*
+ * The format is comma-separated with strings quoted with single quotes
+ * as for the shell (to escape a literal single quote, use '\'').
+ *
+ * type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',
+ * path='/bar/foo',destination=':452345.34'
+ *
+ */
+BusMatchRule*
+bus_match_rule_parse (DBusConnection   *matches_go_to,
+                      const DBusString *rule_text,
+                      DBusError        *error)
+{
+  BusMatchRule *rule;
+  RuleToken tokens[MAX_RULE_TOKENS+1]; /* NULL termination + 1 */
+  int i;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (_dbus_string_get_length (rule_text) > DBUS_MAXIMUM_MATCH_RULE_LENGTH)
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                      "Match rule text is %d bytes, maximum is %d",
+                      _dbus_string_get_length (rule_text),
+                      DBUS_MAXIMUM_MATCH_RULE_LENGTH);
+      return NULL;
+    }
+  
+  memset (tokens, '\0', sizeof (tokens));
+  
+  rule = bus_match_rule_new (matches_go_to);
+  if (rule == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+  
+  if (!tokenize_rule (rule_text, tokens, error))
+    goto failed;
+  
+  i = 0;
+  while (tokens[i].key != NULL)
+    {
+      DBusString tmp_str;
+      int len;
+      const char *key = tokens[i].key;
+      const char *value = tokens[i].value;
+      
+      _dbus_string_init_const (&tmp_str, value);
+      len = _dbus_string_get_length (&tmp_str);
+
+      if (strcmp (key, "type") == 0)
+        {
+          int t;
+
+          if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Key %s specified twice in match rule\n", key);
+              goto failed;
+            }
+          
+          t = dbus_message_type_from_string (value);
+          
+          if (t == DBUS_MESSAGE_TYPE_INVALID)
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Invalid message type (%s) in match rule\n", value);
+              goto failed;
+            }
+
+          if (!bus_match_rule_set_message_type (rule, t))
+            {
+              BUS_SET_OOM (error);
+              goto failed;
+            }
+        }
+      else if (strcmp (key, "sender") == 0)
+        {
+          if (rule->flags & BUS_MATCH_SENDER)
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Key %s specified twice in match rule\n", key);
+              goto failed;
+            }
+
+          if (!_dbus_validate_bus_name (&tmp_str, 0, len))
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Sender name '%s' is invalid\n", value);
+              goto failed;
+            }
+
+          if (!bus_match_rule_set_sender (rule, value))
+            {
+              BUS_SET_OOM (error);
+              goto failed;
+            }
+        }
+      else if (strcmp (key, "interface") == 0)
+        {
+          if (rule->flags & BUS_MATCH_INTERFACE)
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Key %s specified twice in match rule\n", key);
+              goto failed;
+            }
+
+          if (!_dbus_validate_interface (&tmp_str, 0, len))
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Interface name '%s' is invalid\n", value);
+              goto failed;
+            }
+
+          if (!bus_match_rule_set_interface (rule, value))
+            {
+              BUS_SET_OOM (error);
+              goto failed;
+            }
+        }
+      else if (strcmp (key, "member") == 0)
+        {
+          if (rule->flags & BUS_MATCH_MEMBER)
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Key %s specified twice in match rule\n", key);
+              goto failed;
+            }
+
+          if (!_dbus_validate_member (&tmp_str, 0, len))
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Member name '%s' is invalid\n", value);
+              goto failed;
+            }
+
+          if (!bus_match_rule_set_member (rule, value))
+            {
+              BUS_SET_OOM (error);
+              goto failed;
+            }
+        }
+      else if (strcmp (key, "path") == 0 ||
+          strcmp (key, "path_namespace") == 0)
+        {
+          dbus_bool_t is_namespace = (strcmp (key, "path_namespace") == 0);
+
+          if (rule->flags & (BUS_MATCH_PATH | BUS_MATCH_PATH_NAMESPACE))
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "path or path_namespace specified twice in match rule\n");
+              goto failed;
+            }
+
+          if (!_dbus_validate_path (&tmp_str, 0, len))
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Path '%s' is invalid\n", value);
+              goto failed;
+            }
+
+          if (!bus_match_rule_set_path (rule, value, is_namespace))
+            {
+              BUS_SET_OOM (error);
+              goto failed;
+            }
+        }
+      else if (strcmp (key, "destination") == 0)
+        {
+          if (rule->flags & BUS_MATCH_DESTINATION)
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Key %s specified twice in match rule\n", key);
+              goto failed;
+            }
+
+          if (!_dbus_validate_bus_name (&tmp_str, 0, len))
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "Destination name '%s' is invalid\n", value);
+              goto failed;
+            }
+
+          if (!bus_match_rule_set_destination (rule, value))
+            {
+              BUS_SET_OOM (error);
+              goto failed;
+            }
+        }
+      else if (strcmp (key, "eavesdrop") == 0)
+        {
+          /* do not detect "eavesdrop" being used more than once in rule:
+           * 1) it's not possible, it's only in the flags
+           * 2) it might be used twice to disable eavesdropping when it's
+           * automatically added (eg dbus-monitor/bustle) */
+
+          /* we accept only "true|false" as possible values */
+          if ((strcmp (value, "true") == 0))
+            {
+              bus_match_rule_set_client_is_eavesdropping (rule, TRUE);
+            }
+          else if (strcmp (value, "false") == 0)
+            {
+              bus_match_rule_set_client_is_eavesdropping (rule, FALSE);
+            }
+          else
+            {
+              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                              "eavesdrop='%s' is invalid, "
+                              "it should be 'true' or 'false'\n",
+                              value);
+              goto failed;
+            }
+        }
+      else if (strncmp (key, "arg", 3) == 0)
+        {
+          if (!bus_match_rule_parse_arg_match (rule, key, &tmp_str, error))
+            goto failed;
+        }
+      else
+        {
+          dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+                          "Unknown key \"%s\" in match rule",
+                          key);
+          goto failed;
+        }
+
+      ++i;
+    }
+  
+
+  goto out;
+  
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (rule)
+    {
+      bus_match_rule_unref (rule);
+      rule = NULL;
+    }
+
+ out:
+  
+  i = 0;
+  while (tokens[i].key || tokens[i].value)
+    {
+      _dbus_assert (i < MAX_RULE_TOKENS);
+      dbus_free (tokens[i].key);
+      dbus_free (tokens[i].value);
+      ++i;
+    }
+  
+  return rule;
+}
+
+typedef struct RulePool RulePool;
+struct RulePool
+{
+  /* Maps non-NULL interface names to non-NULL (DBusList **)s */
+  DBusHashTable *rules_by_iface;
+
+  /* List of BusMatchRules which don't specify an interface */
+  DBusList *rules_without_iface;
+};
+
+struct BusMatchmaker
+{
+  int refcount;
+
+  /* Pools of rules, grouped by the type of message they match. 0
+   * (DBUS_MESSAGE_TYPE_INVALID) represents rules that do not specify a message
+   * type.
+   */
+  RulePool rules_by_type[DBUS_NUM_MESSAGE_TYPES];
+};
+
+static void
+rule_list_free (DBusList **rules)
+{
+  while (*rules != NULL)
+    {
+      BusMatchRule *rule;
+
+      rule = (*rules)->data;
+      bus_match_rule_unref (rule);
+      _dbus_list_remove_link (rules, *rules);
+    }
+}
+
+static void
+rule_list_ptr_free (DBusList **list)
+{
+  /* We have to cope with NULL because the hash table frees the "existing"
+   * value (which is NULL) when creating a new table entry...
+   */
+  if (list != NULL)
+    {
+      rule_list_free (list);
+      dbus_free (list);
+    }
+}
+
+BusMatchmaker*
+bus_matchmaker_new (void)
+{
+  BusMatchmaker *matchmaker;
+  int i;
+
+  matchmaker = dbus_new0 (BusMatchmaker, 1);
+  if (matchmaker == NULL)
+    return NULL;
+
+  matchmaker->refcount = 1;
+
+  for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
+    {
+      RulePool *p = matchmaker->rules_by_type + i;
+
+      p->rules_by_iface = _dbus_hash_table_new (DBUS_HASH_STRING,
+          dbus_free, (DBusFreeFunction) rule_list_ptr_free);
+
+      if (p->rules_by_iface == NULL)
+        goto nomem;
+    }
+
+  return matchmaker;
+
+ nomem:
+  for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
+    {
+      RulePool *p = matchmaker->rules_by_type + i;
+
+      if (p->rules_by_iface == NULL)
+        break;
+      else
+        _dbus_hash_table_unref (p->rules_by_iface);
+    }
+  dbus_free (matchmaker);
+
+  return NULL;
+}
+
+static DBusList **
+bus_matchmaker_get_rules (BusMatchmaker *matchmaker,
+                          int            message_type,
+                          const char    *interface,
+                          dbus_bool_t    create)
+{
+  RulePool *p;
+
+  _dbus_assert (message_type >= 0);
+  _dbus_assert (message_type < DBUS_NUM_MESSAGE_TYPES);
+
+  _dbus_verbose ("Looking up rules for message_type %d, interface %s\n",
+                 message_type,
+                 interface != NULL ? interface : "<null>");
+
+  p = matchmaker->rules_by_type + message_type;
+
+  if (interface == NULL)
+    {
+      return &p->rules_without_iface;
+    }
+  else
+    {
+      DBusList **list;
+
+      list = _dbus_hash_table_lookup_string (p->rules_by_iface, interface);
+
+      if (list == NULL && create)
+        {
+          char *dupped_interface;
+
+          list = dbus_new0 (DBusList *, 1);
+          if (list == NULL)
+            return NULL;
+
+          dupped_interface = _dbus_strdup (interface);
+          if (dupped_interface == NULL)
+            {
+              dbus_free (list);
+              return NULL;
+            }
+
+          _dbus_verbose ("Adding list for type %d, iface %s\n", message_type,
+                         interface);
+
+          if (!_dbus_hash_table_insert_string (p->rules_by_iface,
+                                               dupped_interface, list))
+            {
+              dbus_free (list);
+              dbus_free (dupped_interface);
+              return NULL;
+            }
+        }
+
+      return list;
+    }
+}
+
+static void
+bus_matchmaker_gc_rules (BusMatchmaker *matchmaker,
+                         int            message_type,
+                         const char    *interface,
+                         DBusList     **rules)
+{
+  RulePool *p;
+
+  if (interface == NULL)
+    return;
+
+  if (*rules != NULL)
+    return;
+
+  _dbus_verbose ("GCing HT entry for message_type %u, interface %s\n",
+                 message_type, interface);
+
+  p = matchmaker->rules_by_type + message_type;
+
+  _dbus_assert (_dbus_hash_table_lookup_string (p->rules_by_iface, interface)
+      == rules);
+
+  _dbus_hash_table_remove_string (p->rules_by_iface, interface);
+}
+
+BusMatchmaker *
+bus_matchmaker_ref (BusMatchmaker *matchmaker)
+{
+  _dbus_assert (matchmaker->refcount > 0);
+
+  matchmaker->refcount += 1;
+
+  return matchmaker;
+}
+
+void
+bus_matchmaker_unref (BusMatchmaker *matchmaker)
+{
+  _dbus_assert (matchmaker->refcount > 0);
+
+  matchmaker->refcount -= 1;
+  if (matchmaker->refcount == 0)
+    {
+      int i;
+
+      for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
+        {
+          RulePool *p = matchmaker->rules_by_type + i;
+
+          _dbus_hash_table_unref (p->rules_by_iface);
+          rule_list_free (&p->rules_without_iface);
+        }
+
+      dbus_free (matchmaker);
+    }
+}
+
+/* The rule can't be modified after it's added. */
+dbus_bool_t
+bus_matchmaker_add_rule (BusMatchmaker   *matchmaker,
+                         BusMatchRule    *rule)
+{
+  DBusList **rules;
+
+  _dbus_assert (bus_connection_is_active (rule->matches_go_to));
+
+  _dbus_verbose ("Adding rule with message_type %d, interface %s\n",
+                 rule->message_type,
+                 rule->interface != NULL ? rule->interface : "<null>");
+
+  rules = bus_matchmaker_get_rules (matchmaker, rule->message_type,
+                                    rule->interface, TRUE);
+
+  if (rules == NULL)
+    return FALSE;
+
+  if (!_dbus_list_append (rules, rule))
+    return FALSE;
+
+  if (!bus_connection_add_match_rule (rule->matches_go_to, rule))
+    {
+      _dbus_list_remove_last (rules, rule);
+      bus_matchmaker_gc_rules (matchmaker, rule->message_type,
+                               rule->interface, rules);
+      return FALSE;
+    }
+
+  bus_match_rule_ref (rule);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  {
+    char *s = match_rule_to_string (rule);
+
+    _dbus_verbose ("Added match rule %s to connection %p\n",
+                   s, rule->matches_go_to);
+    dbus_free (s);
+  }
+#endif
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+match_rule_equal (BusMatchRule *a,
+                  BusMatchRule *b)
+{
+  if (a->flags != b->flags)
+    return FALSE;
+
+  if (a->matches_go_to != b->matches_go_to)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_MESSAGE_TYPE) &&
+      a->message_type != b->message_type)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_MEMBER) &&
+      strcmp (a->member, b->member) != 0)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_PATH) &&
+      strcmp (a->path, b->path) != 0)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_INTERFACE) &&
+      strcmp (a->interface, b->interface) != 0)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_SENDER) &&
+      strcmp (a->sender, b->sender) != 0)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_DESTINATION) &&
+      strcmp (a->destination, b->destination) != 0)
+    return FALSE;
+
+  /* we already compared the value of flags, and
+   * BUS_MATCH_CLIENT_IS_EAVESDROPPING does not have another struct member */
+
+  if (a->flags & BUS_MATCH_ARGS)
+    {
+      int i;
+      
+      if (a->args_len != b->args_len)
+        return FALSE;
+      
+      i = 0;
+      while (i < a->args_len)
+        {
+          int length;
+
+          if ((a->args[i] != NULL) != (b->args[i] != NULL))
+            return FALSE;
+
+          if (a->arg_lens[i] != b->arg_lens[i])
+            return FALSE;
+
+          length = a->arg_lens[i] & ~BUS_MATCH_ARG_FLAGS;
+
+          if (a->args[i] != NULL)
+            {
+              _dbus_assert (b->args[i] != NULL);
+              if (memcmp (a->args[i], b->args[i], length) != 0)
+                return FALSE;
+            }
+          
+          ++i;
+        }
+    }
+  
+  return TRUE;
+}
+
+static void
+bus_matchmaker_remove_rule_link (DBusList       **rules,
+                                 DBusList        *link)
+{
+  BusMatchRule *rule = link->data;
+  
+  bus_connection_remove_match_rule (rule->matches_go_to, rule);
+  _dbus_list_remove_link (rules, link);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  {
+    char *s = match_rule_to_string (rule);
+
+    _dbus_verbose ("Removed match rule %s for connection %p\n",
+                   s, rule->matches_go_to);
+    dbus_free (s);
+  }
+#endif
+  
+  bus_match_rule_unref (rule);  
+}
+
+void
+bus_matchmaker_remove_rule (BusMatchmaker   *matchmaker,
+                            BusMatchRule    *rule)
+{
+  DBusList **rules;
+
+  _dbus_verbose ("Removing rule with message_type %d, interface %s\n",
+                 rule->message_type,
+                 rule->interface != NULL ? rule->interface : "<null>");
+
+  bus_connection_remove_match_rule (rule->matches_go_to, rule);
+
+  rules = bus_matchmaker_get_rules (matchmaker, rule->message_type,
+                                    rule->interface, FALSE);
+
+  /* We should only be asked to remove a rule by identity right after it was
+   * added, so there should be a list for it.
+   */
+  _dbus_assert (rules != NULL);
+
+  _dbus_list_remove (rules, rule);
+  bus_matchmaker_gc_rules (matchmaker, rule->message_type, rule->interface,
+      rules);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  {
+    char *s = match_rule_to_string (rule);
+
+    _dbus_verbose ("Removed match rule %s for connection %p\n",
+                   s, rule->matches_go_to);
+    dbus_free (s);
+  }
+#endif
+  
+  bus_match_rule_unref (rule);
+}
+
+/* Remove a single rule which is equal to the given rule by value */
+dbus_bool_t
+bus_matchmaker_remove_rule_by_value (BusMatchmaker   *matchmaker,
+                                     BusMatchRule    *value,
+                                     DBusError       *error)
+{
+  DBusList **rules;
+  DBusList *link = NULL;
+
+  _dbus_verbose ("Removing rule by value with message_type %d, interface %s\n",
+                 value->message_type,
+                 value->interface != NULL ? value->interface : "<null>");
+
+  rules = bus_matchmaker_get_rules (matchmaker, value->message_type,
+      value->interface, FALSE);
+
+  if (rules != NULL)
+    {
+      /* we traverse backward because bus_connection_remove_match_rule()
+       * removes the most-recently-added rule
+       */
+      link = _dbus_list_get_last_link (rules);
+      while (link != NULL)
+        {
+          BusMatchRule *rule;
+          DBusList *prev;
+
+          rule = link->data;
+          prev = _dbus_list_get_prev_link (rules, link);
+
+          if (match_rule_equal (rule, value))
+            {
+              bus_matchmaker_remove_rule_link (rules, link);
+              break;
+            }
+
+          link = prev;
+        }
+    }
+
+  if (link == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_NOT_FOUND,
+                      "The given match rule wasn't found and can't be removed");
+      return FALSE;
+    }
+
+  bus_matchmaker_gc_rules (matchmaker, value->message_type, value->interface,
+      rules);
+
+  return TRUE;
+}
+
+static void
+rule_list_remove_by_connection (DBusList       **rules,
+                                DBusConnection  *connection)
+{
+  DBusList *link;
+
+  link = _dbus_list_get_first_link (rules);
+  while (link != NULL)
+    {
+      BusMatchRule *rule;
+      DBusList *next;
+
+      rule = link->data;
+      next = _dbus_list_get_next_link (rules, link);
+
+      if (rule->matches_go_to == connection)
+        {
+          bus_matchmaker_remove_rule_link (rules, link);
+        }
+      else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') ||
+               ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':'))
+        {
+          /* The rule matches to/from a base service, see if it's the
+           * one being disconnected, since we know this service name
+           * will never be recycled.
+           */
+          const char *name;
+
+          name = bus_connection_get_name (connection);
+          _dbus_assert (name != NULL); /* because we're an active connection */
+
+          if (((rule->flags & BUS_MATCH_SENDER) &&
+               strcmp (rule->sender, name) == 0) ||
+              ((rule->flags & BUS_MATCH_DESTINATION) &&
+               strcmp (rule->destination, name) == 0))
+            {
+              bus_matchmaker_remove_rule_link (rules, link);
+            }
+        }
+
+      link = next;
+    }
+}
+
+void
+bus_matchmaker_disconnected (BusMatchmaker   *matchmaker,
+                             DBusConnection  *connection)
+{
+  int i;
+
+  /* FIXME
+   *
+   * This scans all match rules on the bus. We could avoid that
+   * for the rules belonging to the connection, since we keep
+   * a list of those; but for the rules that just refer to
+   * the connection we'd need to do something more elaborate.
+   */
+
+  _dbus_assert (bus_connection_is_active (connection));
+
+  _dbus_verbose ("Removing all rules for connection %p\n", connection);
+
+  for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
+    {
+      RulePool *p = matchmaker->rules_by_type + i;
+      DBusHashIter iter;
+
+      rule_list_remove_by_connection (&p->rules_without_iface, connection);
+
+      _dbus_hash_iter_init (p->rules_by_iface, &iter);
+      while (_dbus_hash_iter_next (&iter))
+        {
+          DBusList **items = _dbus_hash_iter_get_value (&iter);
+
+          rule_list_remove_by_connection (items, connection);
+
+          if (*items == NULL)
+            _dbus_hash_iter_remove_entry (&iter);
+        }
+    }
+}
+
+static dbus_bool_t
+connection_is_primary_owner (DBusConnection *connection,
+                             const char     *service_name)
+{
+  BusService *service;
+  DBusString str;
+  BusRegistry *registry;
+
+  _dbus_assert (connection != NULL);
+  
+  registry = bus_connection_get_registry (connection);
+
+  _dbus_string_init_const (&str, service_name);
+  service = bus_registry_lookup (registry, &str);
+
+  if (service == NULL)
+    return FALSE; /* Service doesn't exist so connection can't own it. */
+
+  return bus_service_get_primary_owners_connection (service) == connection;
+}
+
+static dbus_bool_t
+str_has_prefix (const char *str, const char *prefix)
+{
+  size_t prefix_len;
+  prefix_len = strlen (prefix);
+  if (strncmp (str, prefix, prefix_len) == 0)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+static dbus_bool_t
+match_rule_matches (BusMatchRule    *rule,
+                    DBusConnection  *sender,
+                    DBusConnection  *addressed_recipient,
+                    DBusMessage     *message,
+                    BusMatchFlags    already_matched)
+{
+  dbus_bool_t wants_to_eavesdrop = FALSE;
+  int flags;
+
+  /* All features of the match rule are AND'd together,
+   * so FALSE if any of them don't match.
+   */
+
+  /* sender/addressed_recipient of #NULL may mean bus driver,
+   * or for addressed_recipient may mean a message with no
+   * specific recipient (i.e. a signal)
+   */
+
+  /* Don't bother re-matching features we've already checked implicitly. */
+  flags = rule->flags & (~already_matched);
+
+  if (flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING)
+    wants_to_eavesdrop = TRUE;
+
+  if (flags & BUS_MATCH_MESSAGE_TYPE)
+    {
+      _dbus_assert (rule->message_type != DBUS_MESSAGE_TYPE_INVALID);
+
+      if (rule->message_type != dbus_message_get_type (message))
+        return FALSE;
+    }
+
+  if (flags & BUS_MATCH_INTERFACE)
+    {
+      const char *iface;
+
+      _dbus_assert (rule->interface != NULL);
+
+      iface = dbus_message_get_interface (message);
+      if (iface == NULL)
+        return FALSE;
+
+      if (strcmp (iface, rule->interface) != 0)
+        return FALSE;
+    }
+
+  if (flags & BUS_MATCH_MEMBER)
+    {
+      const char *member;
+
+      _dbus_assert (rule->member != NULL);
+
+      member = dbus_message_get_member (message);
+      if (member == NULL)
+        return FALSE;
+
+      if (strcmp (member, rule->member) != 0)
+        return FALSE;
+    }
+
+  if (flags & BUS_MATCH_SENDER)
+    {
+      _dbus_assert (rule->sender != NULL);
+
+      if (sender == NULL)
+        {
+          if (strcmp (rule->sender,
+                      DBUS_SERVICE_DBUS) != 0)
+            return FALSE;
+        }
+      else
+        {
+          if (!connection_is_primary_owner (sender, rule->sender))
+            return FALSE;
+        }
+    }
+
+  /* Note: this part is relevant for eavesdropper rules:
+   * Two cases:
+   * 1) rule has a destination to be matched
+   *   (flag BUS_MATCH_DESTINATION present). Rule will match if:
+   *   - rule->destination matches the addressed_recipient
+   *   AND
+   *   - wants_to_eavesdrop=TRUE
+   *
+   *   Note: (the case in which addressed_recipient is the actual rule owner
+   *   is handled elsewere in dispatch.c:bus_dispatch_matches().
+   *
+   * 2) rule has no destination. Rule will match if:
+   *    - message has no specified destination (ie broadcasts)
+   *      (Note: this will rule out unicast method calls and unicast signals,
+   *      fixing FDO#269748)
+   *    OR
+   *    - wants_to_eavesdrop=TRUE (destination-catch-all situation)
+   */
+  if (flags & BUS_MATCH_DESTINATION)
+    {
+      const char *destination;
+
+      _dbus_assert (rule->destination != NULL);
+
+      destination = dbus_message_get_destination (message);
+      if (destination == NULL)
+        /* broadcast, but this rule specified a destination: no match */
+        return FALSE;
+
+      /* rule owner does not intend to eavesdrop: we'll deliver only msgs
+       * directed to it, NOT MATCHING */
+      if (!wants_to_eavesdrop)
+        return FALSE;
+
+      if (addressed_recipient == NULL)
+        {          
+          if (strcmp (rule->destination,
+                      DBUS_SERVICE_DBUS) != 0)
+            return FALSE;
+        }
+      else
+        {
+          if (!connection_is_primary_owner (addressed_recipient, rule->destination))
+            return FALSE;
+        }
+    } else { /* no destination in rule */
+        dbus_bool_t msg_is_broadcast;
+
+        _dbus_assert (rule->destination == NULL);
+
+        msg_is_broadcast = (dbus_message_get_destination (message) == NULL);
+
+        if (!wants_to_eavesdrop && !msg_is_broadcast)
+          return FALSE;
+
+        /* if we are here rule owner intends to eavesdrop
+         * OR
+         * message is being broadcasted */
+    }
+
+  if (flags & BUS_MATCH_PATH)
+    {
+      const char *path;
+
+      _dbus_assert (rule->path != NULL);
+
+      path = dbus_message_get_path (message);
+      if (path == NULL)
+        return FALSE;
+
+      if (strcmp (path, rule->path) != 0)
+        return FALSE;
+    }
+
+  if (flags & BUS_MATCH_PATH_NAMESPACE)
+    {
+      const char *path;
+      int len;
+
+      _dbus_assert (rule->path != NULL);
+
+      path = dbus_message_get_path (message);
+      if (path == NULL)
+        return FALSE;
+
+      if (!str_has_prefix (path, rule->path))
+        return FALSE;
+
+      len = strlen (rule->path);
+
+      /* Check that the actual argument is within the expected
+       * namespace, rather than just starting with that string,
+       * by checking that the matched prefix is followed by a '/'
+       * or the end of the path.
+       */
+      if (path[len] != '\0' && path[len] != '/')
+        return FALSE;
+    }
+
+  if (flags & BUS_MATCH_ARGS)
+    {
+      int i;
+      DBusMessageIter iter;
+      
+      _dbus_assert (rule->args != NULL);
+
+      dbus_message_iter_init (message, &iter);
+      
+      i = 0;
+      while (i < rule->args_len)
+        {
+          int current_type;
+          const char *expected_arg;
+          int expected_length;
+          dbus_bool_t is_path, is_namespace;
+
+          expected_arg = rule->args[i];
+          expected_length = rule->arg_lens[i] & ~BUS_MATCH_ARG_FLAGS;
+          is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0;
+          is_namespace = (rule->arg_lens[i] & BUS_MATCH_ARG_NAMESPACE) != 0;
+          
+          current_type = dbus_message_iter_get_arg_type (&iter);
+
+          if (expected_arg != NULL)
+            {
+              const char *actual_arg;
+              int actual_length;
+
+              if (current_type != DBUS_TYPE_STRING &&
+                  (!is_path || current_type != DBUS_TYPE_OBJECT_PATH))
+                return FALSE;
+
+              actual_arg = NULL;
+              dbus_message_iter_get_basic (&iter, &actual_arg);
+              _dbus_assert (actual_arg != NULL);
+
+              actual_length = strlen (actual_arg);
+
+              if (is_path)
+                {
+                  if (actual_length < expected_length &&
+                      actual_arg[actual_length - 1] != '/')
+                    return FALSE;
+
+                  if (expected_length < actual_length &&
+                      expected_arg[expected_length - 1] != '/')
+                    return FALSE;
+
+                  if (memcmp (actual_arg, expected_arg,
+                              MIN (actual_length, expected_length)) != 0)
+                    return FALSE;
+                }
+              else if (is_namespace)
+                {
+                  if (expected_length > actual_length)
+                    return FALSE;
+
+                  /* If the actual argument doesn't start with the expected
+                   * namespace, then we don't match.
+                   */
+                  if (memcmp (expected_arg, actual_arg, expected_length) != 0)
+                    return FALSE;
+
+                  if (expected_length < actual_length)
+                    {
+                      /* Check that the actual argument is within the expected
+                       * namespace, rather than just starting with that string,
+                       * by checking that the matched prefix ends in a '.'.
+                       *
+                       * This doesn't stop "foo.bar." matching "foo.bar..baz"
+                       * which is an invalid namespace, but at some point the
+                       * daemon can't cover up for broken services.
+                       */
+                      if (actual_arg[expected_length] != '.')
+                        return FALSE;
+                    }
+                  /* otherwise we had an exact match. */
+                }
+              else
+                {
+                  if (expected_length != actual_length ||
+                      memcmp (expected_arg, actual_arg, expected_length) != 0)
+                    return FALSE;
+                }
+
+            }
+          
+          if (current_type != DBUS_TYPE_INVALID)
+            dbus_message_iter_next (&iter);
+
+          ++i;
+        }
+    }
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+get_recipients_from_list (DBusList       **rules,
+                          DBusConnection  *sender,
+                          DBusConnection  *addressed_recipient,
+                          DBusMessage     *message,
+                          DBusList       **recipients_p)
+{
+  DBusList *link;
+
+  if (rules == NULL)
+    return TRUE;
+
+  link = _dbus_list_get_first_link (rules);
+  while (link != NULL)
+    {
+      BusMatchRule *rule;
+
+      rule = link->data;
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+      {
+        char *s = match_rule_to_string (rule);
+
+        _dbus_verbose ("Checking whether message matches rule %s for connection %p\n",
+                       s, rule->matches_go_to);
+        dbus_free (s);
+      }
+#endif
+
+      if (match_rule_matches (rule,
+                              sender, addressed_recipient, message,
+                              BUS_MATCH_MESSAGE_TYPE | BUS_MATCH_INTERFACE))
+        {
+          _dbus_verbose ("Rule matched\n");
+
+          /* Append to the list if we haven't already */
+          if (bus_connection_mark_stamp (rule->matches_go_to))
+            {
+              if (!_dbus_list_append (recipients_p, rule->matches_go_to))
+                return FALSE;
+            }
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+          else
+            {
+              _dbus_verbose ("Connection already receiving this message, so not adding again\n");
+            }
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+        }
+
+      link = _dbus_list_get_next_link (rules, link);
+    }
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_matchmaker_get_recipients (BusMatchmaker   *matchmaker,
+                               BusConnections  *connections,
+                               DBusConnection  *sender,
+                               DBusConnection  *addressed_recipient,
+                               DBusMessage     *message,
+                               DBusList       **recipients_p)
+{
+  int type;
+  const char *interface;
+  DBusList **neither, **just_type, **just_iface, **both;
+
+  _dbus_assert (*recipients_p == NULL);
+
+  /* This avoids sending same message to the same connection twice.
+   * Purpose of the stamp instead of a bool is to avoid iterating over
+   * all connections resetting the bool each time.
+   */
+  bus_connections_increment_stamp (connections);
+
+  /* addressed_recipient is already receiving the message, don't add to list.
+   * NULL addressed_recipient means either bus driver, or this is a signal
+   * and thus lacks a specific addressed_recipient.
+   */
+  if (addressed_recipient != NULL)
+    bus_connection_mark_stamp (addressed_recipient);
+
+  type = dbus_message_get_type (message);
+  interface = dbus_message_get_interface (message);
+
+  neither = bus_matchmaker_get_rules (matchmaker, DBUS_MESSAGE_TYPE_INVALID,
+      NULL, FALSE);
+  just_type = just_iface = both = NULL;
+
+  if (interface != NULL)
+    just_iface = bus_matchmaker_get_rules (matchmaker,
+        DBUS_MESSAGE_TYPE_INVALID, interface, FALSE);
+
+  if (type > DBUS_MESSAGE_TYPE_INVALID && type < DBUS_NUM_MESSAGE_TYPES)
+    {
+      just_type = bus_matchmaker_get_rules (matchmaker, type, NULL, FALSE);
+
+      if (interface != NULL)
+        both = bus_matchmaker_get_rules (matchmaker, type, interface, FALSE);
+    }
+
+  if (!(get_recipients_from_list (neither, sender, addressed_recipient,
+                                  message, recipients_p) &&
+        get_recipients_from_list (just_iface, sender, addressed_recipient,
+                                  message, recipients_p) &&
+        get_recipients_from_list (just_type, sender, addressed_recipient,
+                                  message, recipients_p) &&
+        get_recipients_from_list (both, sender, addressed_recipient,
+                                  message, recipients_p)))
+    {
+      _dbus_list_clear (recipients_p);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+#ifdef DBUS_BUILD_TESTS
+#include "test.h"
+#include <stdlib.h>
+
+static BusMatchRule*
+check_parse (dbus_bool_t should_succeed,
+             const char *text)
+{
+  BusMatchRule *rule;
+  DBusString str;
+  DBusError error;
+
+  dbus_error_init (&error);
+
+  _dbus_string_init_const (&str, text);
+  
+  rule = bus_match_rule_parse (NULL, &str, &error);
+  if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+    {
+      dbus_error_free (&error);
+      return NULL;
+    }
+
+  if (should_succeed && rule == NULL)
+    {
+      _dbus_warn ("Failed to parse: %s: %s: \"%s\"\n",
+                  error.name, error.message,
+                  _dbus_string_get_const_data (&str));
+      exit (1);
+    }
+
+  if (!should_succeed && rule != NULL)
+    {
+      _dbus_warn ("Failed to fail to parse: \"%s\"\n",
+                  _dbus_string_get_const_data (&str));
+      exit (1);
+    }
+
+  dbus_error_free (&error);
+
+  return rule;
+}
+
+static void
+assert_large_rule (BusMatchRule *rule)
+{
+  _dbus_assert (rule->flags & BUS_MATCH_MESSAGE_TYPE);
+  _dbus_assert (rule->flags & BUS_MATCH_SENDER);
+  _dbus_assert (rule->flags & BUS_MATCH_INTERFACE);
+  _dbus_assert (rule->flags & BUS_MATCH_MEMBER);
+  _dbus_assert (rule->flags & BUS_MATCH_DESTINATION);
+  _dbus_assert (rule->flags & BUS_MATCH_PATH);
+
+  _dbus_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL);
+  _dbus_assert (rule->interface != NULL);
+  _dbus_assert (rule->member != NULL);
+  _dbus_assert (rule->sender != NULL);
+  _dbus_assert (rule->destination != NULL);
+  _dbus_assert (rule->path != NULL);
+
+  _dbus_assert (strcmp (rule->interface, "org.freedesktop.DBusInterface") == 0);
+  _dbus_assert (strcmp (rule->sender, "org.freedesktop.DBusSender") == 0);
+  _dbus_assert (strcmp (rule->member, "Foo") == 0);
+  _dbus_assert (strcmp (rule->path, "/bar/foo") == 0);
+  _dbus_assert (strcmp (rule->destination, ":452345.34") == 0);
+}
+
+static dbus_bool_t
+test_parsing (void *data)
+{
+  BusMatchRule *rule;
+
+  rule = check_parse (TRUE, "type='signal',sender='org.freedesktop.DBusSender',interface='org.freedesktop.DBusInterface',member='Foo',path='/bar/foo',destination=':452345.34'");
+  if (rule != NULL)
+    {
+      assert_large_rule (rule);
+      bus_match_rule_unref (rule);
+    }
+
+  /* With extra whitespace and useless quotes */
+  rule = check_parse (TRUE, "    type='signal',  \tsender='org.freedes''ktop.DBusSender',   interface='org.freedesktop.DBusInterface''''', \tmember='Foo',path='/bar/foo',destination=':452345.34'''''");
+  if (rule != NULL)
+    {
+      assert_large_rule (rule);
+      bus_match_rule_unref (rule);
+    }
+
+
+  /* A simple signal connection */
+  rule = check_parse (TRUE, "type='signal',path='/foo',interface='org.Bar'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags & BUS_MATCH_MESSAGE_TYPE);
+      _dbus_assert (rule->flags & BUS_MATCH_INTERFACE);
+      _dbus_assert (rule->flags & BUS_MATCH_PATH);
+
+      _dbus_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL);
+      _dbus_assert (rule->interface != NULL);
+      _dbus_assert (rule->path != NULL);
+
+      _dbus_assert (strcmp (rule->interface, "org.Bar") == 0);
+      _dbus_assert (strcmp (rule->path, "/foo") == 0);
+  
+      bus_match_rule_unref (rule);
+    }
+
+  /* argN */
+  rule = check_parse (TRUE, "arg0='foo'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 1);
+      _dbus_assert (rule->args[0] != NULL);
+      _dbus_assert (rule->args[1] == NULL);
+      _dbus_assert (strcmp (rule->args[0], "foo") == 0);
+
+      bus_match_rule_unref (rule);
+    }
+  
+  rule = check_parse (TRUE, "arg1='foo'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 2);
+      _dbus_assert (rule->args[0] == NULL);
+      _dbus_assert (rule->args[1] != NULL);
+      _dbus_assert (rule->args[2] == NULL);
+      _dbus_assert (strcmp (rule->args[1], "foo") == 0);
+
+      bus_match_rule_unref (rule);
+    }
+
+  rule = check_parse (TRUE, "arg2='foo'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 3);
+      _dbus_assert (rule->args[0] == NULL);
+      _dbus_assert (rule->args[1] == NULL);
+      _dbus_assert (rule->args[2] != NULL);
+      _dbus_assert (rule->args[3] == NULL);
+      _dbus_assert (strcmp (rule->args[2], "foo") == 0);
+
+      bus_match_rule_unref (rule);
+    }
+  
+  rule = check_parse (TRUE, "arg40='foo'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 41);
+      _dbus_assert (rule->args[0] == NULL);
+      _dbus_assert (rule->args[1] == NULL);
+      _dbus_assert (rule->args[40] != NULL);
+      _dbus_assert (rule->args[41] == NULL);
+      _dbus_assert (strcmp (rule->args[40], "foo") == 0);
+
+      bus_match_rule_unref (rule);
+    }
+  
+  rule = check_parse (TRUE, "arg63='foo'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 64);
+      _dbus_assert (rule->args[0] == NULL);
+      _dbus_assert (rule->args[1] == NULL);
+      _dbus_assert (rule->args[63] != NULL);
+      _dbus_assert (rule->args[64] == NULL);
+      _dbus_assert (strcmp (rule->args[63], "foo") == 0);
+
+      bus_match_rule_unref (rule);
+    }
+
+  rule = check_parse (TRUE, "arg7path='/foo'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags = BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 8);
+      _dbus_assert (rule->args[7] != NULL);
+      _dbus_assert (rule->args[8] == NULL);
+      _dbus_assert (strcmp (rule->args[7], "/foo") == 0);
+      _dbus_assert ((rule->arg_lens[7] & BUS_MATCH_ARG_IS_PATH)
+          == BUS_MATCH_ARG_IS_PATH);
+
+      bus_match_rule_unref (rule);
+    }
+
+  /* Arg 0 namespace matches */
+  rule = check_parse (TRUE, "arg0namespace='foo'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 1);
+      _dbus_assert (strcmp (rule->args[0], "foo") == 0);
+      _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE)
+          == BUS_MATCH_ARG_NAMESPACE);
+
+      bus_match_rule_unref (rule);
+    }
+
+  rule = check_parse (TRUE, "arg0namespace='foo.bar'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+      _dbus_assert (rule->args != NULL);
+      _dbus_assert (rule->args_len == 1);
+      _dbus_assert (strcmp (rule->args[0], "foo.bar") == 0);
+      _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE)
+          == BUS_MATCH_ARG_NAMESPACE);
+
+      bus_match_rule_unref (rule);
+    }
+
+  /* Only arg0namespace is supported. */
+  rule = check_parse (FALSE, "arg1namespace='foo'");
+  _dbus_assert (rule == NULL);
+
+  /* An empty string isn't a valid namespace prefix (you should just not
+   * specify this key at all).
+   */
+  rule = check_parse (FALSE, "arg0namespace=''");
+  _dbus_assert (rule == NULL);
+
+  /* Trailing periods aren't allowed (earlier versions of the arg0namespace
+   * spec allowed a single trailing period, which altered the semantics) */
+  rule = check_parse (FALSE, "arg0namespace='foo.'");
+  _dbus_assert (rule == NULL);
+
+  rule = check_parse (FALSE, "arg0namespace='foo.bar.'");
+  _dbus_assert (rule == NULL);
+
+  rule = check_parse (FALSE, "arg0namespace='foo..'");
+  _dbus_assert (rule == NULL);
+
+  rule = check_parse (FALSE, "arg0namespace='foo.bar..'");
+  _dbus_assert (rule == NULL);
+
+  /* Too-large argN */
+  rule = check_parse (FALSE, "arg300='foo'");
+  _dbus_assert (rule == NULL);
+  rule = check_parse (FALSE, "arg64='foo'");
+  _dbus_assert (rule == NULL);
+
+  /* No N in argN */
+  rule = check_parse (FALSE, "arg='foo'");
+  _dbus_assert (rule == NULL);
+  rule = check_parse (FALSE, "argv='foo'");
+  _dbus_assert (rule == NULL);
+  rule = check_parse (FALSE, "arg3junk='foo'");
+  _dbus_assert (rule == NULL);
+  rule = check_parse (FALSE, "argument='foo'");
+  _dbus_assert (rule == NULL);
+  
+  /* Reject duplicates */
+  rule = check_parse (FALSE, "type='signal',type='method_call'");
+  _dbus_assert (rule == NULL);
+
+  rule = check_parse (TRUE, "path_namespace='/foo/bar'");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == BUS_MATCH_PATH_NAMESPACE);
+      _dbus_assert (rule->path != NULL);
+      _dbus_assert (strcmp (rule->path, "/foo/bar") == 0);
+
+      bus_match_rule_unref (rule);
+    }
+
+  /* Almost a duplicate */
+  rule = check_parse (FALSE, "path='/foo',path_namespace='/foo'");
+  _dbus_assert (rule == NULL);
+
+  /* Trailing / was supported in the initial proposal, but now isn't */
+  rule = check_parse (FALSE, "path_namespace='/foo/'");
+  _dbus_assert (rule == NULL);
+
+  /* Duplicates with the argN code */
+  rule = check_parse (FALSE, "arg0='foo',arg0='bar'");
+  _dbus_assert (rule == NULL);
+  rule = check_parse (FALSE, "arg3='foo',arg3='bar'");
+  _dbus_assert (rule == NULL);
+  rule = check_parse (FALSE, "arg30='foo',arg30='bar'");
+  _dbus_assert (rule == NULL);
+  
+  /* Reject broken keys */
+  rule = check_parse (FALSE, "blah='signal'");
+  _dbus_assert (rule == NULL);
+
+  /* Reject broken values */
+  rule = check_parse (FALSE, "type='chouin'");
+  _dbus_assert (rule == NULL);
+  rule = check_parse (FALSE, "interface='abc@def++'");
+  _dbus_assert (rule == NULL);
+  rule = check_parse (FALSE, "service='youpi'");
+  _dbus_assert (rule == NULL);
+
+  /* Allow empty rule */
+  rule = check_parse (TRUE, "");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == 0);
+      
+      bus_match_rule_unref (rule);
+    }
+
+  /* All-whitespace rule is the same as empty */
+  rule = check_parse (TRUE, "    \t");
+  if (rule != NULL)
+    {
+      _dbus_assert (rule->flags == 0);
+      
+      bus_match_rule_unref (rule);
+    }
+
+  /* But with non-whitespace chars and no =value, it's not OK */
+  rule = check_parse (FALSE, "type");
+  _dbus_assert (rule == NULL);
+  
+  return TRUE;
+}
+
+static struct {
+  const char *first;
+  const char *second;
+} equality_tests[] = {
+  { "type='signal'", "type='signal'" },
+  { "type='signal',interface='foo.bar'", "interface='foo.bar',type='signal'" },
+  { "type='signal',member='bar'", "member='bar',type='signal'" },
+  { "type='method_call',sender=':1.0'", "sender=':1.0',type='method_call'" },
+  { "type='method_call',destination=':1.0'", "destination=':1.0',type='method_call'" },
+  { "type='method_call',path='/foo/bar'", "path='/foo/bar',type='method_call'" },
+  { "type='method_call',arg0='blah'", "arg0='blah',type='method_call'" },
+  { "type='method_call',arg0='boo'", "arg0='boo',type='method_call'" },
+  { "type='method_call',arg0='blah',arg1='baz'", "arg0='blah',arg1='baz',type='method_call'" },
+  { "type='method_call',arg3='foosh'", "arg3='foosh',type='method_call'" },
+  { "arg3='fool'", "arg3='fool'" },
+  { "arg0namespace='fool'", "arg0namespace='fool'" },
+  { "member='food'", "member='food'" }
+};
+
+static void
+test_equality (void)
+{
+  int i;
+  
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (equality_tests))
+    {
+      BusMatchRule *first;
+      BusMatchRule *second;
+      int j;
+      
+      first = check_parse (TRUE, equality_tests[i].first);
+      _dbus_assert (first != NULL);
+      second = check_parse (TRUE, equality_tests[i].second);
+      _dbus_assert (second != NULL);
+
+      if (!match_rule_equal (first, second))
+        {
+          _dbus_warn ("rule %s and %s should have been equal\n",
+                      equality_tests[i].first,
+                      equality_tests[i].second);
+          exit (1);
+        }
+
+      bus_match_rule_unref (second);
+
+      /* Check that the rule is not equal to any of the
+       * others besides its pair match
+       */
+      j = 0;
+      while (j < _DBUS_N_ELEMENTS (equality_tests))
+        {
+          if (i != j)
+            {
+              second = check_parse (TRUE, equality_tests[j].second);
+
+              if (match_rule_equal (first, second))
+                {
+                  _dbus_warn ("rule %s and %s should not have been equal\n",
+                              equality_tests[i].first,
+                              equality_tests[j].second);
+                  exit (1);
+                }
+              
+              bus_match_rule_unref (second);
+            }
+          
+          ++j;
+        }
+
+      bus_match_rule_unref (first);
+
+      ++i;
+    }
+}
+
+static const char*
+should_match_message_1[] = {
+  "type='signal'",
+  "member='Frobated'",
+  "arg0='foobar'",
+  "type='signal',member='Frobated'",
+  "type='signal',member='Frobated',arg0='foobar'",
+  "member='Frobated',arg0='foobar'",
+  "type='signal',arg0='foobar'",
+  /* The definition of argXpath matches says: "As with normal argument matches,
+   * if the argument is exactly equal to the string given in the match rule
+   * then the rule is satisfied." So this should match (even though the
+   * argument is not a valid path)!
+   */
+  "arg0path='foobar'",
+  "arg0namespace='foobar'",
+  NULL
+};
+
+static const char*
+should_not_match_message_1[] = {
+  "type='method_call'",
+  "type='error'",
+  "type='method_return'",
+  "type='signal',member='Oopsed'",
+  "arg0='blah'",
+  "arg1='foobar'",
+  "arg2='foobar'",
+  "arg3='foobar'",
+  "arg0='3'",
+  "arg1='3'",
+  "arg0='foobar',arg1='abcdef'",
+  "arg0='foobar',arg1='abcdef',arg2='abcdefghi',arg3='abcdefghi',arg4='abcdefghi'",
+  "arg0='foobar',arg1='abcdef',arg4='abcdefghi',arg3='abcdefghi',arg2='abcdefghi'",
+  "arg0path='foo'",
+  "arg0path='foobar/'",
+  "arg1path='3'",
+  "arg0namespace='foo'",
+  "arg0namespace='foo',arg1='abcdef'",
+  "arg0namespace='moo'",
+  NULL
+};
+
+#define EXAMPLE_NAME "com.example.backend.foo"
+
+static const char *
+should_match_message_2[] = {
+  /* EXAMPLE_NAME is in all of these namespaces */
+  "arg0namespace='com.example.backend'",
+  "arg0namespace='com.example'",
+  "arg0namespace='com'",
+
+  /* If the client specifies the name exactly, with no trailing period, then
+   * it should match.
+   */
+  "arg0namespace='com.example.backend.foo'",
+
+  NULL
+};
+
+static const char *
+should_not_match_message_2[] = {
+  /* These are not even prefixes */
+  "arg0namespace='com.example.backend.foo.bar'",
+  "arg0namespace='com.example.backend.foobar'",
+
+  /* These are prefixes, but they're not parent namespaces. */
+  "arg0namespace='com.example.backend.fo'",
+  "arg0namespace='com.example.backen'",
+  "arg0namespace='com.exampl'",
+  "arg0namespace='co'",
+
+  NULL
+};
+
+static void
+check_matches (dbus_bool_t  expected_to_match,
+               int          number,
+               DBusMessage *message,
+               const char  *rule_text)
+{
+  BusMatchRule *rule;
+  dbus_bool_t matched;
+
+  rule = check_parse (TRUE, rule_text);
+  _dbus_assert (rule != NULL);
+
+  /* We can't test sender/destination rules since we pass NULL here */
+  matched = match_rule_matches (rule, NULL, NULL, message, 0);
+
+  if (matched != expected_to_match)
+    {
+      _dbus_warn ("Expected rule %s to %s message %d, failed\n",
+                  rule_text, expected_to_match ?
+                  "match" : "not match", number);
+      exit (1);
+    }
+
+  bus_match_rule_unref (rule);
+}
+
+static void
+check_matching (DBusMessage *message,
+                int          number,
+                const char **should_match,
+                const char **should_not_match)
+{
+  int i;
+
+  i = 0;
+  while (should_match[i] != NULL)
+    {
+      check_matches (TRUE, number, message, should_match[i]);
+      ++i;
+    }
+
+  i = 0;
+  while (should_not_match[i] != NULL)
+    {
+      check_matches (FALSE, number, message, should_not_match[i]);
+      ++i;
+    }
+}
+
+static void
+test_matching (void)
+{
+  DBusMessage *message1, *message2;
+  const char *v_STRING;
+  dbus_int32_t v_INT32;
+
+  message1 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+  _dbus_assert (message1 != NULL);
+  if (!dbus_message_set_member (message1, "Frobated"))
+    _dbus_assert_not_reached ("oom");
+
+  v_STRING = "foobar";
+  v_INT32 = 3;
+  if (!dbus_message_append_args (message1,
+                                 DBUS_TYPE_STRING, &v_STRING,
+                                 DBUS_TYPE_INT32, &v_INT32,
+                                 NULL))
+    _dbus_assert_not_reached ("oom");
+  
+  check_matching (message1, 1,
+                  should_match_message_1,
+                  should_not_match_message_1);
+  
+  dbus_message_unref (message1);
+
+  message2 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+  _dbus_assert (message2 != NULL);
+  if (!dbus_message_set_member (message2, "NameOwnerChanged"))
+    _dbus_assert_not_reached ("oom");
+
+  /* Obviously this isn't really a NameOwnerChanged signal. */
+  v_STRING = EXAMPLE_NAME;
+  if (!dbus_message_append_args (message2,
+                                 DBUS_TYPE_STRING, &v_STRING,
+                                 NULL))
+    _dbus_assert_not_reached ("oom");
+
+  check_matching (message2, 2,
+                  should_match_message_2,
+                  should_not_match_message_2);
+
+  dbus_message_unref (message2);
+}
+
+#define PATH_MATCH_RULE "arg0path='/aa/bb/'"
+
+/* This is a list of paths that should be matched by PATH_MATCH_RULE, taken
+ * from the specification. Notice that not all of them are actually legal D-Bus
+ * paths.
+ *
+ * The author of this test takes no responsibility for the semantics of
+ * this match rule key.
+ */
+static const char *paths_that_should_be_matched[] = {
+    "/aa/",
+    "/aa/bb/",
+    "/aa/bb/cc/",
+#define FIRST_VALID_PATH_WHICH_SHOULD_MATCH 3
+    "/",
+    "/aa/bb/cc",
+    NULL
+};
+
+/* These paths should not be matched by PATH_MATCH_RULE. */
+static const char *paths_that_should_not_be_matched[] = {
+    "/aa/b",
+    "/aa",
+    /* or even... */
+    "/aa/bb",
+    NULL
+};
+
+static void
+test_path_match (int type,
+                 const char   *path,
+                 const char   *rule_text,
+                 BusMatchRule *rule,
+                 dbus_bool_t   should_match)
+{
+  DBusMessage *message = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+  dbus_bool_t matched;
+
+  _dbus_assert (message != NULL);
+  if (!dbus_message_set_member (message, "Foo"))
+    _dbus_assert_not_reached ("oom");
+
+  if (!dbus_message_append_args (message,
+                                 type, &path,
+                                 NULL))
+    _dbus_assert_not_reached ("oom");
+
+  matched = match_rule_matches (rule, NULL, NULL, message, 0);
+
+  if (matched != should_match)
+    {
+      _dbus_warn ("Expected rule %s to %s message "
+                  "with first arg %s of type '%c', failed\n",
+                  rule_text,
+                  should_match ? "match" : "not match",
+                  path,
+                  (char) type);
+      exit (1);
+    }
+
+  dbus_message_unref (message);
+}
+
+static void
+test_path_matching (void)
+{
+  BusMatchRule *rule;
+  const char **s;
+
+  rule = check_parse (TRUE, PATH_MATCH_RULE);
+  _dbus_assert (rule != NULL);
+
+  for (s = paths_that_should_be_matched; *s != NULL; s++)
+    test_path_match (DBUS_TYPE_STRING, *s, PATH_MATCH_RULE, rule, TRUE);
+
+  for (s = paths_that_should_be_matched + FIRST_VALID_PATH_WHICH_SHOULD_MATCH;
+       *s != NULL; s++)
+    test_path_match (DBUS_TYPE_OBJECT_PATH, *s, PATH_MATCH_RULE, rule, TRUE);
+
+  for (s = paths_that_should_not_be_matched; *s != NULL; s++)
+    {
+      test_path_match (DBUS_TYPE_STRING, *s, PATH_MATCH_RULE, rule, FALSE);
+      test_path_match (DBUS_TYPE_OBJECT_PATH, *s, PATH_MATCH_RULE, rule, FALSE);
+    }
+
+  bus_match_rule_unref (rule);
+}
+
+static const char*
+path_namespace_should_match_message_1[] = {
+  "type='signal',path_namespace='/foo'",
+  "type='signal',path_namespace='/foo/TheObjectManager'",
+  NULL
+};
+
+static const char*
+path_namespace_should_not_match_message_1[] = {
+  "type='signal',path_namespace='/bar'",
+  "type='signal',path_namespace='/bar/TheObjectManager'",
+  NULL
+};
+
+static const char*
+path_namespace_should_match_message_2[] = {
+  "type='signal',path_namespace='/foo/TheObjectManager'",
+  NULL
+};
+
+static const char*
+path_namespace_should_not_match_message_2[] = {
+  NULL
+};
+
+static const char*
+path_namespace_should_match_message_3[] = {
+  NULL
+};
+
+static const char*
+path_namespace_should_not_match_message_3[] = {
+  "type='signal',path_namespace='/foo/TheObjectManager'",
+  NULL
+};
+
+static void
+test_matching_path_namespace (void)
+{
+  DBusMessage *message1;
+  DBusMessage *message2;
+  DBusMessage *message3;
+
+  message1 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+  _dbus_assert (message1 != NULL);
+  if (!dbus_message_set_path (message1, "/foo/TheObjectManager"))
+    _dbus_assert_not_reached ("oom");
+
+  message2 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+  _dbus_assert (message2 != NULL);
+  if (!dbus_message_set_path (message2, "/foo/TheObjectManager/child_object"))
+    _dbus_assert_not_reached ("oom");
+
+  message3 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+  _dbus_assert (message3 != NULL);
+  if (!dbus_message_set_path (message3, "/foo/TheObjectManagerOther"))
+    _dbus_assert_not_reached ("oom");
+
+  check_matching (message1, 1,
+                  path_namespace_should_match_message_1,
+                  path_namespace_should_not_match_message_1);
+  check_matching (message2, 2,
+                  path_namespace_should_match_message_2,
+                  path_namespace_should_not_match_message_2);
+  check_matching (message3, 3,
+                  path_namespace_should_match_message_3,
+                  path_namespace_should_not_match_message_3);
+
+  dbus_message_unref (message3);
+  dbus_message_unref (message2);
+  dbus_message_unref (message1);
+}
+
+dbus_bool_t
+bus_signals_test (const DBusString *test_data_dir)
+{
+  BusMatchmaker *matchmaker;
+
+  matchmaker = bus_matchmaker_new ();
+  bus_matchmaker_ref (matchmaker);
+  bus_matchmaker_unref (matchmaker);
+  bus_matchmaker_unref (matchmaker);
+
+  if (!_dbus_test_oom_handling ("parsing match rules", test_parsing, NULL))
+    _dbus_assert_not_reached ("Parsing match rules test failed");
+
+  test_equality ();
+  test_matching ();
+  test_path_matching ();
+  test_matching_path_namespace ();
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
+
diff --git a/dbus/bus/signals.h b/dbus/bus/signals.h
new file mode 100644
index 0000000..a71d2e4
--- /dev/null
+++ b/dbus/bus/signals.h
@@ -0,0 +1,100 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* signals.h  Bus signal connection implementation
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef BUS_SIGNALS_H
+#define BUS_SIGNALS_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-sysdeps.h>
+#include "connection.h"
+
+typedef enum
+{
+  BUS_MATCH_MESSAGE_TYPE            = 1 << 0,
+  BUS_MATCH_INTERFACE               = 1 << 1,
+  BUS_MATCH_MEMBER                  = 1 << 2,
+  BUS_MATCH_SENDER                  = 1 << 3,
+  BUS_MATCH_DESTINATION             = 1 << 4,
+  BUS_MATCH_PATH                    = 1 << 5,
+  BUS_MATCH_ARGS                    = 1 << 6,
+  BUS_MATCH_PATH_NAMESPACE          = 1 << 7,
+  BUS_MATCH_CLIENT_IS_EAVESDROPPING = 1 << 8
+} BusMatchFlags;
+
+BusMatchRule* bus_match_rule_new   (DBusConnection *matches_go_to);
+BusMatchRule* bus_match_rule_ref   (BusMatchRule   *rule);
+void          bus_match_rule_unref (BusMatchRule   *rule);
+
+dbus_bool_t bus_match_rule_set_message_type (BusMatchRule     *rule,
+                                             int               type);
+dbus_bool_t bus_match_rule_set_interface    (BusMatchRule     *rule,
+                                             const char       *interface);
+dbus_bool_t bus_match_rule_set_member       (BusMatchRule     *rule,
+                                             const char       *member);
+dbus_bool_t bus_match_rule_set_sender       (BusMatchRule     *rule,
+                                             const char       *sender);
+dbus_bool_t bus_match_rule_set_destination  (BusMatchRule     *rule,
+                                             const char       *destination);
+dbus_bool_t bus_match_rule_set_path         (BusMatchRule     *rule,
+                                             const char       *path,
+                                             dbus_bool_t       is_namespace);
+dbus_bool_t bus_match_rule_set_arg          (BusMatchRule     *rule,
+                                             int               arg,
+                                             const DBusString *value,
+                                             dbus_bool_t       is_path,
+                                             dbus_bool_t       is_namespace);
+
+/* Calling this methods a client declares that it is creating a rule which
+ * needs to eavesdrop (e.g., dbus-monitor), any other created rules not
+ * setting themselves as eavesdropping won't receive any message not addressed
+ * to them, when eavedrop is enabled in the policy.  On the other hand, when
+ * eavedrop is not enabled in policy, this method won't have any effect */
+void bus_match_rule_set_client_is_eavesdropping (BusMatchRule     *rule,
+                                                 dbus_bool_t is_eavesdropping);
+
+BusMatchRule* bus_match_rule_parse (DBusConnection   *matches_go_to,
+                                    const DBusString *rule_text,
+                                    DBusError        *error);
+
+BusMatchmaker* bus_matchmaker_new   (void);
+BusMatchmaker* bus_matchmaker_ref   (BusMatchmaker *matchmaker);
+void           bus_matchmaker_unref (BusMatchmaker *matchmaker);
+
+dbus_bool_t bus_matchmaker_add_rule             (BusMatchmaker   *matchmaker,
+                                                 BusMatchRule    *rule);
+dbus_bool_t bus_matchmaker_remove_rule_by_value (BusMatchmaker   *matchmaker,
+                                                 BusMatchRule    *value,
+                                                 DBusError       *error);
+void        bus_matchmaker_remove_rule          (BusMatchmaker   *matchmaker,
+                                                 BusMatchRule    *rule);
+void        bus_matchmaker_disconnected         (BusMatchmaker   *matchmaker,
+                                                 DBusConnection  *connection);
+dbus_bool_t bus_matchmaker_get_recipients       (BusMatchmaker   *matchmaker,
+                                                 BusConnections  *connections,
+                                                 DBusConnection  *sender,
+                                                 DBusConnection  *addressed_recipient,
+                                                 DBusMessage     *message,
+                                                 DBusList       **recipients_p);
+
+#endif /* BUS_SIGNALS_H */
diff --git a/dbus/bus/stats.c b/dbus/bus/stats.c
new file mode 100644
index 0000000..28fd49b
--- /dev/null
+++ b/dbus/bus/stats.c
@@ -0,0 +1,352 @@
+/* stats.c - statistics from the bus driver
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ */
+
+#include <config.h>
+#include "stats.h"
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-connection-internal.h>
+
+#include "connection.h"
+#include "services.h"
+#include "utils.h"
+
+#ifdef DBUS_ENABLE_STATS
+
+static DBusMessage *
+new_asv_reply (DBusMessage      *message,
+               DBusMessageIter  *iter,
+               DBusMessageIter  *arr_iter)
+{
+  DBusMessage *reply = dbus_message_new_method_return (message);
+
+  if (reply == NULL)
+    return NULL;
+
+  dbus_message_iter_init_append (reply, iter);
+
+  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{sv}",
+                                         arr_iter))
+    {
+      dbus_message_unref (reply);
+      return NULL;
+    }
+
+  return reply;
+}
+
+static dbus_bool_t
+open_asv_entry (DBusMessageIter *arr_iter,
+                DBusMessageIter *entry_iter,
+                const char      *key,
+                const char      *type,
+                DBusMessageIter *var_iter)
+{
+  if (!dbus_message_iter_open_container (arr_iter, DBUS_TYPE_DICT_ENTRY,
+                                         NULL, entry_iter))
+    return FALSE;
+
+  if (!dbus_message_iter_append_basic (entry_iter, DBUS_TYPE_STRING, &key))
+    {
+      dbus_message_iter_abandon_container (arr_iter, entry_iter);
+      return FALSE;
+    }
+
+  if (!dbus_message_iter_open_container (entry_iter, DBUS_TYPE_VARIANT,
+                                         type, var_iter))
+    {
+      dbus_message_iter_abandon_container (arr_iter, entry_iter);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+close_asv_entry (DBusMessageIter *arr_iter,
+                 DBusMessageIter *entry_iter,
+                 DBusMessageIter *var_iter)
+{
+  if (!dbus_message_iter_close_container (entry_iter, var_iter))
+    {
+      dbus_message_iter_abandon_container (arr_iter, entry_iter);
+      return FALSE;
+    }
+
+  if (!dbus_message_iter_close_container (arr_iter, entry_iter))
+    return FALSE;
+
+  return TRUE;
+}
+
+static dbus_bool_t
+close_asv_reply (DBusMessageIter *iter,
+                 DBusMessageIter *arr_iter)
+{
+  return dbus_message_iter_close_container (iter, arr_iter);
+}
+
+static void
+abandon_asv_entry (DBusMessageIter *arr_iter,
+                   DBusMessageIter *entry_iter,
+                   DBusMessageIter *var_iter)
+{
+  dbus_message_iter_abandon_container (entry_iter, var_iter);
+  dbus_message_iter_abandon_container (arr_iter, entry_iter);
+}
+
+static void
+abandon_asv_reply (DBusMessageIter *iter,
+                 DBusMessageIter *arr_iter)
+{
+  dbus_message_iter_abandon_container (iter, arr_iter);
+}
+
+static dbus_bool_t
+asv_add_uint32 (DBusMessageIter *iter,
+                DBusMessageIter *arr_iter,
+                const char *key,
+                dbus_uint32_t value)
+{
+  DBusMessageIter entry_iter, var_iter;
+
+  if (!open_asv_entry (arr_iter, &entry_iter, key, DBUS_TYPE_UINT32_AS_STRING,
+                       &var_iter))
+    goto oom;
+
+  if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_UINT32,
+                                       &value))
+    {
+      abandon_asv_entry (arr_iter, &entry_iter, &var_iter);
+      goto oom;
+    }
+
+  if (!close_asv_entry (arr_iter, &entry_iter, &var_iter))
+    goto oom;
+
+  return TRUE;
+
+oom:
+  abandon_asv_reply (iter, arr_iter);
+  return FALSE;
+}
+
+static dbus_bool_t
+asv_add_string (DBusMessageIter *iter,
+                DBusMessageIter *arr_iter,
+                const char *key,
+                const char *value)
+{
+  DBusMessageIter entry_iter, var_iter;
+
+  if (!open_asv_entry (arr_iter, &entry_iter, key, DBUS_TYPE_STRING_AS_STRING,
+                       &var_iter))
+    goto oom;
+
+  if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_STRING,
+                                       &value))
+    {
+      abandon_asv_entry (arr_iter, &entry_iter, &var_iter);
+      goto oom;
+    }
+
+  if (!close_asv_entry (arr_iter, &entry_iter, &var_iter))
+    goto oom;
+
+  return TRUE;
+
+oom:
+  abandon_asv_reply (iter, arr_iter);
+  return FALSE;
+}
+
+dbus_bool_t
+bus_stats_handle_get_stats (DBusConnection *connection,
+                            BusTransaction *transaction,
+                            DBusMessage    *message,
+                            DBusError      *error)
+{
+  BusConnections *connections;
+  DBusMessage *reply = NULL;
+  DBusMessageIter iter, arr_iter;
+  static dbus_uint32_t stats_serial = 0;
+  dbus_uint32_t in_use, in_free_list, allocated;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  connections = bus_transaction_get_connections (transaction);
+
+  reply = new_asv_reply (message, &iter, &arr_iter);
+
+  if (reply == NULL)
+    goto oom;
+
+  /* Globals */
+
+  if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++))
+    goto oom;
+
+  _dbus_list_get_stats (&in_use, &in_free_list, &allocated);
+  if (!asv_add_uint32 (&iter, &arr_iter, "ListMemPoolUsedBytes", in_use) ||
+      !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolCachedBytes",
+                       in_free_list) ||
+      !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolAllocatedBytes",
+                       allocated))
+    goto oom;
+
+  /* Connections */
+
+  if (!asv_add_uint32 (&iter, &arr_iter, "ActiveConnections",
+        bus_connections_get_n_active (connections)) ||
+      !asv_add_uint32 (&iter, &arr_iter, "IncompleteConnections",
+        bus_connections_get_n_incomplete (connections)) ||
+      !asv_add_uint32 (&iter, &arr_iter, "MatchRules",
+        bus_connections_get_total_match_rules (connections)) ||
+      !asv_add_uint32 (&iter, &arr_iter, "PeakMatchRules",
+        bus_connections_get_peak_match_rules (connections)) ||
+      !asv_add_uint32 (&iter, &arr_iter, "PeakMatchRulesPerConnection",
+        bus_connections_get_peak_match_rules_per_conn (connections)) ||
+      !asv_add_uint32 (&iter, &arr_iter, "BusNames",
+        bus_connections_get_total_bus_names (connections)) ||
+      !asv_add_uint32 (&iter, &arr_iter, "PeakBusNames",
+        bus_connections_get_peak_bus_names (connections)) ||
+      !asv_add_uint32 (&iter, &arr_iter, "PeakBusNamesPerConnection",
+        bus_connections_get_peak_bus_names_per_conn (connections)))
+    goto oom;
+
+  /* end */
+
+  if (!close_asv_reply (&iter, &arr_iter))
+    goto oom;
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+  return TRUE;
+
+oom:
+  if (reply != NULL)
+    dbus_message_unref (reply);
+
+  BUS_SET_OOM (error);
+  return FALSE;
+}
+
+dbus_bool_t
+bus_stats_handle_get_connection_stats (DBusConnection *caller_connection,
+                                       BusTransaction *transaction,
+                                       DBusMessage    *message,
+                                       DBusError      *error)
+{
+  const char *bus_name = NULL;
+  DBusString bus_name_str;
+  DBusMessage *reply = NULL;
+  DBusMessageIter iter, arr_iter;
+  static dbus_uint32_t stats_serial = 0;
+  dbus_uint32_t in_messages, in_bytes, in_fds, in_peak_bytes, in_peak_fds;
+  dbus_uint32_t out_messages, out_bytes, out_fds, out_peak_bytes, out_peak_fds;
+  BusRegistry *registry;
+  BusService *service;
+  DBusConnection *stats_connection;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  registry = bus_connection_get_registry (caller_connection);
+
+  if (! dbus_message_get_args (message, error,
+                               DBUS_TYPE_STRING, &bus_name,
+                               DBUS_TYPE_INVALID))
+      return FALSE;
+
+  _dbus_string_init_const (&bus_name_str, bus_name);
+  service = bus_registry_lookup (registry, &bus_name_str);
+
+  if (service == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
+                      "Bus name '%s' has no owner", bus_name);
+      return FALSE;
+    }
+
+  stats_connection = bus_service_get_primary_owners_connection (service);
+  _dbus_assert (stats_connection != NULL);
+
+  reply = new_asv_reply (message, &iter, &arr_iter);
+
+  if (reply == NULL)
+    goto oom;
+
+  /* Bus daemon per-connection stats */
+
+  if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++) ||
+      !asv_add_uint32 (&iter, &arr_iter, "MatchRules",
+        bus_connection_get_n_match_rules (stats_connection)) ||
+      !asv_add_uint32 (&iter, &arr_iter, "PeakMatchRules",
+        bus_connection_get_peak_match_rules (stats_connection)) ||
+      !asv_add_uint32 (&iter, &arr_iter, "BusNames",
+        bus_connection_get_n_services_owned (stats_connection)) ||
+      !asv_add_uint32 (&iter, &arr_iter, "PeakBusNames",
+        bus_connection_get_peak_bus_names (stats_connection)) ||
+      !asv_add_string (&iter, &arr_iter, "UniqueName",
+        bus_connection_get_name (stats_connection)))
+    goto oom;
+
+  /* DBusConnection per-connection stats */
+
+  _dbus_connection_get_stats (stats_connection,
+                              &in_messages, &in_bytes, &in_fds,
+                              &in_peak_bytes, &in_peak_fds,
+                              &out_messages, &out_bytes, &out_fds,
+                              &out_peak_bytes, &out_peak_fds);
+
+  if (!asv_add_uint32 (&iter, &arr_iter, "IncomingMessages", in_messages) ||
+      !asv_add_uint32 (&iter, &arr_iter, "IncomingBytes", in_bytes) ||
+      !asv_add_uint32 (&iter, &arr_iter, "IncomingFDs", in_fds) ||
+      !asv_add_uint32 (&iter, &arr_iter, "PeakIncomingBytes", in_peak_bytes) ||
+      !asv_add_uint32 (&iter, &arr_iter, "PeakIncomingFDs", in_peak_fds) ||
+      !asv_add_uint32 (&iter, &arr_iter, "OutgoingMessages", out_messages) ||
+      !asv_add_uint32 (&iter, &arr_iter, "OutgoingBytes", out_bytes) ||
+      !asv_add_uint32 (&iter, &arr_iter, "OutgoingFDs", out_fds) ||
+      !asv_add_uint32 (&iter, &arr_iter, "PeakOutgoingBytes", out_peak_bytes) ||
+      !asv_add_uint32 (&iter, &arr_iter, "PeakOutgoingFDs", out_peak_fds))
+    goto oom;
+
+  /* end */
+
+  if (!close_asv_reply (&iter, &arr_iter))
+    goto oom;
+
+  if (!bus_transaction_send_from_driver (transaction, caller_connection,
+                                         reply))
+    goto oom;
+
+  dbus_message_unref (reply);
+  return TRUE;
+
+oom:
+  if (reply != NULL)
+    dbus_message_unref (reply);
+
+  BUS_SET_OOM (error);
+  return FALSE;
+}
+
+#endif
diff --git a/dbus/bus/stats.h b/dbus/bus/stats.h
new file mode 100644
index 0000000..0f843db
--- /dev/null
+++ b/dbus/bus/stats.h
@@ -0,0 +1,38 @@
+/* stats.h - statistics from the bus driver
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ */
+
+#ifndef BUS_STATS_H
+#define BUS_STATS_H
+
+#include "bus.h"
+
+#define BUS_INTERFACE_STATS "org.freedesktop.DBus.Debug.Stats"
+
+dbus_bool_t bus_stats_handle_get_stats (DBusConnection *connection,
+                                        BusTransaction *transaction,
+                                        DBusMessage    *message,
+                                        DBusError      *error);
+
+dbus_bool_t bus_stats_handle_get_connection_stats (DBusConnection *connection,
+                                                   BusTransaction *transaction,
+                                                   DBusMessage    *message,
+                                                   DBusError      *error);
+
+#endif /* multiple-inclusion guard */
diff --git a/dbus/bus/system.conf.in b/dbus/bus/system.conf.in
new file mode 100644
index 0000000..92f4cc4
--- /dev/null
+++ b/dbus/bus/system.conf.in
@@ -0,0 +1,83 @@
+<!-- This configuration file controls the systemwide message bus.
+     Add a system-local.conf and edit that rather than changing this 
+     file directly. -->
+
+<!-- Note that there are any number of ways you can hose yourself
+     security-wise by screwing up this file; in particular, you
+     probably don't want to listen on any more addresses, add any more
+     auth mechanisms, run as a different user, etc. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+  <!-- Our well-known bus type, do not change this -->
+  <type>system</type>
+
+  <!-- Run as special user -->
+  <user>@DBUS_USER@</user>
+
+  <!-- Fork into daemon mode -->
+  <fork/>
+
+  <!-- We use system service launching using a helper -->
+  <standard_system_servicedirs/>
+
+  <!-- This is a setuid helper that is used to launch system services -->
+  <servicehelper>@DBUS_LIBEXECDIR@/dbus-daemon-launch-helper</servicehelper>
+
+  <!-- Write a pid file -->
+  <pidfile>@DBUS_SYSTEM_PID_FILE@</pidfile>
+
+  <!-- Enable logging to syslog -->
+  <syslog/>
+
+  <!-- Only allow socket-credentials-based authentication -->
+  <auth>EXTERNAL</auth>
+
+  <!-- Only listen on a local socket. (abstract=/path/to/socket 
+       means use abstract namespace, don't really create filesystem 
+       file; only Linux supports this. Use path=/whatever on other 
+       systems.) -->
+  <listen>@DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@</listen>
+
+  <policy context="default">
+    <!-- All users can connect to system bus -->
+    <allow user="*"/>
+
+    <!-- Holes must be punched in service configuration files for
+         name ownership and sending method calls -->
+    <deny own="*"/>
+    <deny send_type="method_call"/>
+
+    <!-- Signals and reply messages (method returns, errors) are allowed
+         by default -->
+    <allow send_type="signal"/>
+    <allow send_requested_reply="true" send_type="method_return"/>
+    <allow send_requested_reply="true" send_type="error"/>
+
+    <!-- All messages may be received by default -->
+    <allow receive_type="method_call"/>
+    <allow receive_type="method_return"/>
+    <allow receive_type="error"/>
+    <allow receive_type="signal"/>
+
+    <!-- Allow anyone to talk to the message bus -->
+    <allow send_destination="org.freedesktop.DBus"/>
+    <!-- But disallow some specific bus services -->
+    <deny send_destination="org.freedesktop.DBus"
+          send_interface="org.freedesktop.DBus"
+          send_member="UpdateActivationEnvironment"/>
+  </policy>
+
+  <!-- Config files are placed here that among other things, punch 
+       holes in the above policy for specific services. -->
+  <includedir>system.d</includedir>
+
+  <!-- This is included last so local configuration can override what's 
+       in this standard file -->
+  <include ignore_missing="yes">system-local.conf</include>
+
+  <include if_selinux_enabled="yes" selinux_root_relative="yes">contexts/dbus_contexts</include>
+
+</busconfig>
diff --git a/dbus/bus/test-launch-helper.c b/dbus/bus/test-launch-helper.c
new file mode 100644
index 0000000..ab36b6e
--- /dev/null
+++ b/dbus/bus/test-launch-helper.c
@@ -0,0 +1,147 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* test-main.c  main() for the OOM check of the launch helper
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "test.h"
+#include "activation-helper.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dbus/dbus-internals.h>
+
+#ifdef DBUS_BUILD_TESTS
+static void
+die (const char *failure)
+{
+  fprintf (stderr, "Unit test failed: %s\n", failure);
+  exit (1);
+}
+
+static void
+check_memleaks (const char *name)
+{
+  dbus_shutdown ();
+  
+  printf ("%s: checking for memleaks\n", name);
+  if (_dbus_get_malloc_blocks_outstanding () != 0)
+    {
+      _dbus_warn ("%d dbus_malloc blocks were not freed\n",
+                  _dbus_get_malloc_blocks_outstanding ());
+      die ("memleaks");
+    }
+}
+
+static void
+test_post_hook (const char *name)
+{
+  check_memleaks (name);
+}
+#endif /* DBUS_BUILD_TESTS */
+
+
+#ifdef ACTIVATION_LAUNCHER_DO_OOM
+
+/* returns true if good things happen, or if we get OOM */
+static dbus_bool_t
+bus_activation_helper_oom_test (void *data)
+{
+  const char *service;
+  DBusError error;
+  dbus_bool_t retval;
+
+  service = (const char *) data;
+  retval = TRUE;
+
+  dbus_error_init (&error);
+  if (!run_launch_helper (service, &error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&error);
+      /* we failed, but a OOM is good */
+      if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+        {
+          _dbus_warn ("FAILED SELF TEST: Error: %s\n", error.message);
+          retval = FALSE;
+        }
+      dbus_error_free (&error);
+    }
+  else
+    {
+      /* we succeeded, yay! */
+      _DBUS_ASSERT_ERROR_IS_CLEAR (&error);
+    }
+  return retval;
+}
+
+#endif
+
+int
+main (int argc, char **argv)
+{
+#ifdef DBUS_BUILD_TESTS
+  const char *dir;
+  DBusString config_file;
+
+  if (argc > 1)
+    dir = argv[1];
+  else
+    dir = _dbus_getenv ("DBUS_TEST_DATA");
+
+  if (dir == NULL)
+    {
+      fprintf (stderr, "Must specify test data directory as argv[1] or in DBUS_TEST_DATA env variable\n");
+      return 1;
+    }
+
+  printf ("%s: Running launch helper OOM checks\n", argv[0]);
+
+  if (!_dbus_string_init (&config_file))
+    return 1;
+  if (!_dbus_string_append (&config_file, dir))
+    return 1;
+  if (!_dbus_string_append (&config_file, "/valid-config-files-system/debug-allow-all-pass.conf"))
+    return 1;
+
+  /* use a config file that will actually work... */
+  _dbus_setenv ("TEST_LAUNCH_HELPER_CONFIG",
+                _dbus_string_get_const_data (&config_file));
+
+  _dbus_string_free (&config_file);
+
+  if (!_dbus_test_oom_handling ("dbus-daemon-launch-helper",
+                                bus_activation_helper_oom_test,
+                                "org.freedesktop.DBus.TestSuiteEchoService"))
+    die ("OOM failed");
+
+  test_post_hook (argv[0]);
+
+  printf ("%s: Success\n", argv[0]);
+
+  return 0;
+#else /* DBUS_BUILD_TESTS */
+
+  printf ("Not compiled with test support\n");
+  
+  return 0;
+#endif
+}
+
diff --git a/dbus/bus/test-main.c b/dbus/bus/test-main.c
new file mode 100644
index 0000000..0f736c7
--- /dev/null
+++ b/dbus/bus/test-main.c
@@ -0,0 +1,190 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* test-main.c  main() for make check
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "test.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-message-internal.h>
+#include "selinux.h"
+
+#ifdef DBUS_BUILD_TESTS
+static void
+die (const char *failure)
+{
+  fprintf (stderr, "Unit test failed: %s\n", failure);
+  exit (1);
+}
+
+static void
+check_memleaks (const char *name)
+{
+  dbus_shutdown ();
+  
+  printf ("%s: checking for memleaks\n", name);
+  if (_dbus_get_malloc_blocks_outstanding () != 0)
+    {
+      _dbus_warn ("%d dbus_malloc blocks were not freed\n",
+                  _dbus_get_malloc_blocks_outstanding ());
+      die ("memleaks");
+    }
+}
+#endif /* DBUS_BUILD_TESTS */
+
+static DBusInitialFDs *initial_fds = NULL;
+
+static void
+test_pre_hook (void)
+{
+  
+  if (_dbus_getenv ("DBUS_TEST_SELINUX")
+      && (!bus_selinux_pre_init ()
+	  || !bus_selinux_full_init ()))
+    die ("could not init selinux support");
+
+  initial_fds = _dbus_check_fdleaks_enter ();
+}
+
+static char *progname = "";
+
+static void
+test_post_hook (void)
+{
+  if (_dbus_getenv ("DBUS_TEST_SELINUX"))
+    bus_selinux_shutdown ();
+  check_memleaks (progname);
+
+  _dbus_check_fdleaks_leave (initial_fds);
+  initial_fds = NULL;
+}
+
+int
+main (int argc, char **argv)
+{
+#ifdef DBUS_BUILD_TESTS
+  const char *dir;
+  const char *only;
+  DBusString test_data_dir;
+
+  progname = argv[0];
+
+  if (argc > 1)
+    dir = argv[1];
+  else
+    dir = _dbus_getenv ("DBUS_TEST_DATA");
+
+  if (argc > 2)
+    only = argv[2];
+  else
+    only = NULL;
+
+  if (dir == NULL)
+    {
+      fprintf (stderr, "Must specify test data directory as argv[1] or in DBUS_TEST_DATA env variable\n");
+      return 1;
+    }
+
+  _dbus_string_init_const (&test_data_dir, dir);
+
+  if (!_dbus_threads_init_debug ())
+    die ("initializing debug threads");
+
+  if (only == NULL || strcmp (only, "expire-list") == 0)
+    {
+      test_pre_hook ();
+      printf ("%s: Running expire list test\n", argv[0]);
+      if (!bus_expire_list_test (&test_data_dir))
+        die ("expire list");
+      test_post_hook ();
+    }
+
+  if (only == NULL || strcmp (only, "config-parser") == 0)
+    {
+      test_pre_hook ();
+      printf ("%s: Running config file parser test\n", argv[0]);
+      if (!bus_config_parser_test (&test_data_dir))
+        die ("parser");
+      test_post_hook ();
+    }
+
+  if (only == NULL || strcmp (only, "signals") == 0)
+    {
+      test_pre_hook ();
+      printf ("%s: Running signals test\n", argv[0]);
+      if (!bus_signals_test (&test_data_dir))
+        die ("signals");
+      test_post_hook ();
+    }
+
+  if (only == NULL || strcmp (only, "dispatch-sha1") == 0)
+    {
+      test_pre_hook ();
+      printf ("%s: Running SHA1 connection test\n", argv[0]);
+      if (!bus_dispatch_sha1_test (&test_data_dir))
+        die ("sha1");
+      test_post_hook ();
+    }
+
+  if (only == NULL || strcmp (only, "dispatch") == 0)
+    {
+      test_pre_hook ();
+      printf ("%s: Running message dispatch test\n", argv[0]);
+      if (!bus_dispatch_test (&test_data_dir)) 
+        die ("dispatch");
+      test_post_hook ();
+    }
+
+  if (only == NULL || strcmp (only, "activation-service-reload") == 0)
+    {
+      test_pre_hook ();
+      printf ("%s: Running service files reloading test\n", argv[0]);
+      if (!bus_activation_service_reload_test (&test_data_dir))
+        die ("service reload");
+      test_post_hook ();
+    }
+
+#ifdef HAVE_UNIX_FD_PASSING
+  if (only == NULL || strcmp (only, "unix-fds-passing") == 0)
+    {
+      test_pre_hook ();
+      printf ("%s: Running unix fd passing test\n", argv[0]);
+      if (!bus_unix_fds_passing_test (&test_data_dir))
+        die ("unix fd passing");
+      test_post_hook ();
+    }
+#endif
+
+  printf ("%s: Success\n", argv[0]);
+
+  
+  return 0;
+#else /* DBUS_BUILD_TESTS */
+
+  printf ("Not compiled with test support\n");
+  
+  return 0;
+#endif
+}
diff --git a/dbus/bus/test-system.c b/dbus/bus/test-system.c
new file mode 100644
index 0000000..56a7d4e
--- /dev/null
+++ b/dbus/bus/test-system.c
@@ -0,0 +1,107 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* test-main.c  main() for make check
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "test.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-internals.h>
+
+#ifdef DBUS_BUILD_TESTS
+static void
+die (const char *failure)
+{
+  fprintf (stderr, "Unit test failed: %s\n", failure);
+  exit (1);
+}
+
+static void
+check_memleaks (const char *name)
+{
+  dbus_shutdown ();
+
+  printf ("%s: checking for memleaks\n", name);
+  if (_dbus_get_malloc_blocks_outstanding () != 0)
+    {
+      _dbus_warn ("%d dbus_malloc blocks were not freed\n",
+                  _dbus_get_malloc_blocks_outstanding ());
+      die ("memleaks");
+    }
+}
+#endif /* DBUS_BUILD_TESTS */
+
+static void
+test_pre_hook (void)
+{
+}
+
+static char *progname = "";
+static void
+test_post_hook (void)
+{
+  check_memleaks (progname);
+}
+
+int
+main (int argc, char **argv)
+{
+#ifdef DBUS_BUILD_TESTS
+  const char *dir;
+  DBusString test_data_dir;
+
+  progname = argv[0];
+
+  if (argc > 1)
+    dir = argv[1];
+  else
+    dir = _dbus_getenv ("DBUS_TEST_DATA");
+
+  if (dir == NULL)
+    {
+      fprintf (stderr, "Must specify test data directory as argv[1] or in DBUS_TEST_DATA env variable\n");
+      return 1;
+    }
+
+  _dbus_string_init_const (&test_data_dir, dir);
+
+  if (!_dbus_threads_init_debug ())
+    die ("initializing debug threads");
+
+  test_pre_hook ();
+  printf ("%s: Running config file parser (trivial) test\n", argv[0]);
+  if (!bus_config_parser_trivial_test (&test_data_dir))
+    die ("parser");
+  test_post_hook ();
+
+  printf ("%s: Success\n", argv[0]);
+
+  return 0;
+#else /* DBUS_BUILD_TESTS */
+
+  printf ("Not compiled with test support\n");
+
+  return 0;
+#endif
+}
diff --git a/dbus/bus/test.c b/dbus/bus/test.c
new file mode 100644
index 0000000..1ca9607
--- /dev/null
+++ b/dbus/bus/test.c
@@ -0,0 +1,315 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* test.c  unit test routines
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#ifdef DBUS_BUILD_TESTS
+#include "test.h"
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-sysdeps.h>
+
+/* The "debug client" watch/timeout handlers don't dispatch messages,
+ * as we manually pull them in order to verify them. This is why they
+ * are different from the real handlers in connection.c
+ */
+static DBusList *clients = NULL;
+static DBusLoop *client_loop = NULL;
+
+static dbus_bool_t
+add_client_watch (DBusWatch      *watch,
+                  void           *data)
+{
+  return _dbus_loop_add_watch (client_loop, watch);
+}
+
+static void
+remove_client_watch (DBusWatch      *watch,
+                     void           *data)
+{
+  _dbus_loop_remove_watch (client_loop, watch);
+}
+
+static void
+toggle_client_watch (DBusWatch      *watch,
+                     void           *data)
+{
+  _dbus_loop_toggle_watch (client_loop, watch);
+}
+
+static dbus_bool_t
+add_client_timeout (DBusTimeout    *timeout,
+                    void           *data)
+{
+  return _dbus_loop_add_timeout (client_loop, timeout);
+}
+
+static void
+remove_client_timeout (DBusTimeout    *timeout,
+                       void           *data)
+{
+  _dbus_loop_remove_timeout (client_loop, timeout);
+}
+
+static DBusHandlerResult
+client_disconnect_filter (DBusConnection     *connection,
+                          DBusMessage        *message,
+                          void               *user_data)
+{
+  if (!dbus_message_is_signal (message,
+                               DBUS_INTERFACE_LOCAL,
+                               "Disconnected"))
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+  _dbus_verbose ("Removing client %p in disconnect handler\n",
+                 connection);
+
+  _dbus_list_remove (&clients, connection);
+
+  dbus_connection_unref (connection);
+
+  if (clients == NULL)
+    {
+      _dbus_loop_unref (client_loop);
+      client_loop = NULL;
+    }
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+dbus_bool_t
+bus_setup_debug_client (DBusConnection *connection)
+{
+  dbus_bool_t retval;
+
+  if (!dbus_connection_add_filter (connection,
+                                   client_disconnect_filter,
+                                   NULL, NULL))
+    return FALSE;
+
+  retval = FALSE;
+
+  if (client_loop == NULL)
+    {
+      client_loop = _dbus_loop_new ();
+      if (client_loop == NULL)
+        goto out;
+    }
+
+  if (!dbus_connection_set_watch_functions (connection,
+                                            add_client_watch,
+                                            remove_client_watch,
+                                            toggle_client_watch,
+                                            connection,
+                                            NULL))
+    goto out;
+
+  if (!dbus_connection_set_timeout_functions (connection,
+                                              add_client_timeout,
+                                              remove_client_timeout,
+                                              NULL,
+                                              connection, NULL))
+    goto out;
+
+  if (!_dbus_list_append (&clients, connection))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  if (!retval)
+    {
+      dbus_connection_remove_filter (connection,
+                                     client_disconnect_filter,
+                                     NULL);
+
+      dbus_connection_set_watch_functions (connection,
+                                           NULL, NULL, NULL, NULL, NULL);
+      dbus_connection_set_timeout_functions (connection,
+                                             NULL, NULL, NULL, NULL, NULL);
+
+      _dbus_list_remove_last (&clients, connection);
+
+      if (clients == NULL)
+        {
+          _dbus_loop_unref (client_loop);
+          client_loop = NULL;
+        }
+    }
+
+  return retval;
+}
+
+void
+bus_test_clients_foreach (BusConnectionForeachFunction  function,
+                          void                         *data)
+{
+  DBusList *link;
+
+  link = _dbus_list_get_first_link (&clients);
+  while (link != NULL)
+    {
+      DBusConnection *connection = link->data;
+      DBusList *next = _dbus_list_get_next_link (&clients, link);
+
+      if (!(* function) (connection, data))
+        break;
+
+      link = next;
+    }
+}
+
+dbus_bool_t
+bus_test_client_listed (DBusConnection *connection)
+{
+  DBusList *link;
+
+  link = _dbus_list_get_first_link (&clients);
+  while (link != NULL)
+    {
+      DBusConnection *c = link->data;
+      DBusList *next = _dbus_list_get_next_link (&clients, link);
+
+      if (c == connection)
+        return TRUE;
+
+      link = next;
+    }
+
+  return FALSE;
+}
+
+void
+bus_test_run_clients_loop (dbus_bool_t block_once)
+{
+  if (client_loop == NULL)
+    return;
+
+  _dbus_verbose ("---> Dispatching on \"client side\"\n");
+
+  /* dispatch before we block so pending dispatches
+   * won't make our block return early
+   */
+  _dbus_loop_dispatch (client_loop);
+
+  /* Do one blocking wait, since we're expecting data */
+  if (block_once)
+    {
+      _dbus_verbose ("---> blocking on \"client side\"\n");
+      _dbus_loop_iterate (client_loop, TRUE);
+    }
+
+  /* Then mop everything up */
+  while (_dbus_loop_iterate (client_loop, FALSE))
+    ;
+
+  _dbus_verbose ("---> Done dispatching on \"client side\"\n");
+}
+
+void
+bus_test_run_bus_loop (BusContext *context,
+                       dbus_bool_t block_once)
+{
+  _dbus_verbose ("---> Dispatching on \"server side\"\n");
+
+  /* dispatch before we block so pending dispatches
+   * won't make our block return early
+   */
+  _dbus_loop_dispatch (bus_context_get_loop (context));
+
+  /* Do one blocking wait, since we're expecting data */
+  if (block_once)
+    {
+      _dbus_verbose ("---> blocking on \"server side\"\n");
+      _dbus_loop_iterate (bus_context_get_loop (context), TRUE);
+    }
+
+  /* Then mop everything up */
+  while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE))
+    ;
+
+  _dbus_verbose ("---> Done dispatching on \"server side\"\n");
+}
+
+void
+bus_test_run_everything (BusContext *context)
+{
+  while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE) ||
+         (client_loop == NULL || _dbus_loop_iterate (client_loop, FALSE)))
+    ;
+}
+
+BusContext*
+bus_context_new_test (const DBusString *test_data_dir,
+                      const char       *filename)
+{
+  DBusError error;
+  DBusString config_file;
+  DBusString relative;
+  BusContext *context;
+
+  if (!_dbus_string_init (&config_file))
+    {
+      _dbus_warn ("No memory\n");
+      return NULL;
+    }
+
+  if (!_dbus_string_copy (test_data_dir, 0,
+                          &config_file, 0))
+    {
+      _dbus_warn ("No memory\n");
+      _dbus_string_free (&config_file);
+      return NULL;
+    }
+
+  _dbus_string_init_const (&relative, filename);
+
+  if (!_dbus_concat_dir_and_file (&config_file, &relative))
+    {
+      _dbus_warn ("No memory\n");
+      _dbus_string_free (&config_file);
+      return NULL;
+    }
+
+  dbus_error_init (&error);
+  context = bus_context_new (&config_file, BUS_CONTEXT_FLAG_NONE, NULL, NULL, NULL, &error);
+  if (context == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&error);
+
+      _dbus_warn ("Failed to create debug bus context from configuration file %s: %s\n",
+                  filename, error.message);
+
+      dbus_error_free (&error);
+
+      _dbus_string_free (&config_file);
+
+      return NULL;
+    }
+
+  _dbus_string_free (&config_file);
+
+  return context;
+}
+
+#endif
diff --git a/dbus/bus/test.h b/dbus/bus/test.h
new file mode 100644
index 0000000..98a2c6b
--- /dev/null
+++ b/dbus/bus/test.h
@@ -0,0 +1,57 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* test.h  unit test routines
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_TEST_H
+#define BUS_TEST_H
+
+#ifdef DBUS_BUILD_TESTS
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-string.h>
+#include "connection.h"
+
+dbus_bool_t bus_dispatch_test         (const DBusString             *test_data_dir);
+dbus_bool_t bus_dispatch_sha1_test    (const DBusString             *test_data_dir);
+dbus_bool_t bus_config_parser_test    (const DBusString             *test_data_dir);
+dbus_bool_t bus_config_parser_trivial_test (const DBusString        *test_data_dir);
+dbus_bool_t bus_signals_test          (const DBusString             *test_data_dir);
+dbus_bool_t bus_expire_list_test      (const DBusString             *test_data_dir);
+dbus_bool_t bus_activation_service_reload_test (const DBusString    *test_data_dir);
+dbus_bool_t bus_setup_debug_client    (DBusConnection               *connection);
+void        bus_test_clients_foreach  (BusConnectionForeachFunction  function,
+                                       void                         *data);
+dbus_bool_t bus_test_client_listed    (DBusConnection               *connection);
+void        bus_test_run_bus_loop     (BusContext                   *context,
+                                       dbus_bool_t                   block);
+void        bus_test_run_clients_loop (dbus_bool_t                   block);
+void        bus_test_run_everything   (BusContext                   *context);
+BusContext* bus_context_new_test      (const DBusString             *test_data_dir,
+                                       const char                   *filename);
+
+#ifdef HAVE_UNIX_FD_PASSING
+dbus_bool_t bus_unix_fds_passing_test (const DBusString             *test_data_dir);
+#endif
+
+#endif
+
+#endif /* BUS_TEST_H */
diff --git a/dbus/bus/utils.c b/dbus/bus/utils.c
new file mode 100644
index 0000000..7d24872
--- /dev/null
+++ b/dbus/bus/utils.c
@@ -0,0 +1,48 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* utils.c  General utility functions
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "utils.h"
+#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-mainloop.h>
+
+const char bus_no_memory_message[] = "Memory allocation failure in message bus";
+
+void
+bus_connection_dispatch_all_messages (DBusConnection *connection)
+{
+  while (bus_connection_dispatch_one_message (connection))
+    ;
+}
+
+dbus_bool_t
+bus_connection_dispatch_one_message  (DBusConnection *connection)
+{
+  DBusDispatchStatus status;
+
+  while ((status = dbus_connection_dispatch (connection)) == DBUS_DISPATCH_NEED_MEMORY)
+    _dbus_wait_for_memory ();
+  
+  return status == DBUS_DISPATCH_DATA_REMAINS;
+}
diff --git a/dbus/bus/utils.h b/dbus/bus/utils.h
new file mode 100644
index 0000000..f533895
--- /dev/null
+++ b/dbus/bus/utils.h
@@ -0,0 +1,36 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* utils.h  General utility functions
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef BUS_UTILS_H
+#define BUS_UTILS_H
+
+#include <dbus/dbus.h>
+
+extern const char bus_no_memory_message[];
+#define BUS_SET_OOM(error) dbus_set_error_const ((error), DBUS_ERROR_NO_MEMORY, bus_no_memory_message)
+
+void        bus_connection_dispatch_all_messages (DBusConnection *connection);
+dbus_bool_t bus_connection_dispatch_one_message  (DBusConnection *connection);
+
+#endif /* BUS_UTILS_H */
diff --git a/dbus/cleanup-man-pages.sh b/dbus/cleanup-man-pages.sh
new file mode 100644
index 0000000..23e98a6
--- /dev/null
+++ b/dbus/cleanup-man-pages.sh
@@ -0,0 +1,86 @@
+#! /bin/sh
+
+## This script cleans up private/internal API from the man pages
+## generated by Doxygen.  This brings the man pages down from 7 megs
+## to 2 megs and avoids namespace-polluting man pages.  It's probably
+## pretty specific to GNU utilities. Patches gladly accepted to make
+## it work without them.
+
+## You would run this after building dbus and after running "doxygen
+## Doxyfile"
+
+die() {
+    echo "$*" 1>&2
+    exit 1
+}
+
+MANDIR=$1
+if test x"$MANDIR" = x ; then
+    MANDIR=doc/api/man/man3dbus
+fi
+
+cd "$MANDIR" || die "Could not cd to $MANDIR"
+
+test -d keep || mkdir keep || die "Could not create $MANDIR/keep directory"
+test -d nuke || mkdir nuke || die "Could not create $MANDIR/nuke directory"
+
+## blacklist
+(find . -maxdepth 1 -name "_*" | xargs -I ITEMS /bin/mv ITEMS nuke) || die "could not move all underscore-prefixed items"
+(find . -maxdepth 1 -name "DBus*Internal*" | xargs -I ITEMS /bin/mv ITEMS nuke) || die "could not move all internal-containing items"
+(find . -maxdepth 1 -name "dbus_*_internal_*" | xargs -I ITEMS /bin/mv ITEMS nuke) || die "could not move all internal-containing items"
+
+## this is kind of unmaintainable, but I guess it's no huge disaster if we miss something.
+## this list should only contain man pages with >1 line, i.e. with real content; the 
+## one-line cross-references get cleaned up next.
+for I in DBusCounter.* DBusCredentials.* DBusDataSlot.* DBusDataSlotAllocator.* DBusDataSlotList.* \
+    DBusDirIter.* DBusFakeMutex.* DBusFreedElement.* DBusGroupInfo.* DBusGUID.* DBusHashEntry.* \
+    DBusHashIter.* DBusHashTable.* DBusHeader.* DBusHeaderField.* DBusKey.* DBusKeyring.* DBusList.* \
+    DBusMarshal.* DBusMD5* DBusMemBlock.* DBusMemPool.* DBusMessageGenerator.* DBusMessageLoader.* \
+    DBusMessageRealIter.* DBusObjectSubtree.* DBusObjectTree.* DBusPollFD.* DBusReal* \
+    DBusResources.* DBusServerDebugPipe.* DBusServerSocket.* DBusServerUnix.* \
+    DBusServerVTable.* DBusSHA.* DBusSHAContext.* DBusSignatureRealIter.* DBusStat.* DBusString.* \
+    DBusSysdeps.* DBusSysdepsUnix.* DBusTimeoutList.* DBusTransport* DBusTypeReader* DBusTypeWriter* \
+    DBusUserInfo.* DBusWatchList.* ; do 
+    if test -f "$I" ; then
+        /bin/mv "$I" nuke || die "could not move $I to $MANDIR/nuke"
+    fi
+done
+
+## many files just contain ".so man3dbus/DBusStringInternals.3dbus" or the like, 
+## if these point to something we nuked, we want to also nuke the pointer.
+for I in * ; do
+    if test -f "$I" ; then
+        LINES=`wc -l "$I" | cut -d ' ' -f 1`
+        if test x"$LINES" = x1 ; then
+            REF_TO=`cat "$I" | sed -e 's/\.so man3dbus\///g'`
+            ## echo "$I points to $REF_TO"
+            if ! test -f "$REF_TO" ; then
+                /bin/mv "$I" nuke || die "could not move $I to $MANDIR/nuke"
+            fi
+        fi
+    fi
+done
+
+## whitelist
+(find . -maxdepth 1 -name "dbus_*" | xargs -I ITEMS /bin/mv ITEMS keep) || die "could not move all dbus-prefixed items"
+(find . -maxdepth 1 -name "DBUS_*" | xargs -I ITEMS /bin/mv ITEMS keep) || die "could not move all DBUS_-prefixed items"
+(find . -maxdepth 1 -name "DBus*" | xargs -I ITEMS /bin/mv ITEMS keep) || die "could not move all DBus-prefixed items"
+
+## everything else is assumed irrelevant, this is mostly struct fields
+## from the public headers
+(find . -maxdepth 1 -type f | xargs -I ITEMS /bin/mv ITEMS nuke) || die "could not move remaining items"
+
+NUKE_COUNT=`find nuke -type f -name "*" | wc -l`
+KEEP_COUNT=`find keep -type f -name "*" | wc -l`
+MISSING_COUNT=`find . -maxdepth 1 -type f -name "*" | wc -l`
+
+echo "$KEEP_COUNT man pages kept and $NUKE_COUNT man pages to remove"
+echo "$MISSING_COUNT not handled"
+
+(find keep -type f -name "*" | xargs -I ITEMS /bin/mv ITEMS .) || die "could not move kept items back"
+
+rmdir keep || die "could not remove $MANDIR/keep"
+
+echo "Man pages to be installed are in $MANDIR and man pages to ignore are in $MANDIR/nuke"
+
+exit 0
diff --git a/dbus/cmake/CMakeLists.txt b/dbus/cmake/CMakeLists.txt
new file mode 100644
index 0000000..000acda
--- /dev/null
+++ b/dbus/cmake/CMakeLists.txt
@@ -0,0 +1,613 @@
+project(dbus)
+
+# we need to be up to date
+CMAKE_MINIMUM_REQUIRED(VERSION 2.4.4 FATAL_ERROR)
+if(COMMAND cmake_policy)
+    cmake_policy(SET CMP0003 NEW)
+endif(COMMAND cmake_policy)
+
+# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
+set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/modules")
+
+# detect version
+include(MacrosAutotools)
+autoversion(../configure.ac dbus)
+# used by file version info
+set (DBUS_PATCH_VERSION "0")
+
+include(Macros)
+TIMESTAMP(DBUS_BUILD_TIMESTAMP)
+
+########### basic vars ###############
+
+
+if (DBUSDIR)
+	set(DBUS_INSTALL_DIR "${DBUSDIR}")
+endif (DBUSDIR)
+if ($ENV{DBUSDIR})
+	set(DBUS_INSTALL_DIR "$ENV{DBUSDIR}")
+endif ($ENV{DBUSDIR})
+
+if (DBUS_INSTALL_DIR)
+	set(CMAKE_INSTALL_PREFIX "${DBUS_INSTALL_DIR}" CACHE PATH "install prefix" FORCE)
+else (DBUS_INSTALL_DIR)
+	set(DBUS_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}")
+endif (DBUS_INSTALL_DIR)
+
+# autotools style
+if (NOT DATAROOTDIR)
+    set (DATAROOTDIR share)
+endif()
+
+if (NOT DATADIR)
+    set (DATADIR ${DATAROOTDIR})
+endif()
+
+if (NOT DOCDIR)
+    SET(DOCDIR ${DATAROOTDIR}/doc/dbus)
+endif()
+
+if (NOT DBUS_DATADIR)
+    SET(DBUS_DATADIR ${DATADIR})
+endif()
+
+set(prefix                   ${DBUS_INSTALL_DIR})
+set(exec_prefix              ${prefix})
+set(EXPANDED_LIBDIR          ${DBUS_INSTALL_DIR}/lib)
+set(EXPANDED_INCLUDEDIR      ${DBUS_INSTALL_DIR}/include)
+set(EXPANDED_BINDIR          ${DBUS_INSTALL_DIR}/bin)
+set(EXPANDED_SYSCONFDIR      ${DBUS_INSTALL_DIR}/etc)
+set(EXPANDED_DATADIR         ${DBUS_INSTALL_DIR}/${DBUS_DATADIR})
+set(DBUS_MACHINE_UUID_FILE   ${DBUS_INSTALL_DIR}/lib/dbus/machine-id)
+set(DBUS_BINDIR              ${EXPANDED_BINDIR})
+set(DBUS_DAEMONDIR 			 ${EXPANDED_BINDIR})
+
+
+#enable building of shared library
+SET(BUILD_SHARED_LIBS ON)
+
+if (CYGWIN)
+   set (WIN32)
+endif (CYGWIN)
+
+# search for required packages
+if (WIN32)
+    # include local header first to avoid using old installed header
+    set (CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} ${CMAKE_SOURCE_DIR}/..)
+	find_package(LibIconv)
+    include(Win32Macros)
+    addExplorerWrapper(${CMAKE_PROJECT_NAME})
+endif (WIN32)
+
+option (DBUS_USE_EXPAT "Use expat (== ON) or libxml2 (==OFF)" ON)
+
+if(NOT WIN32)
+	option (DBUS_ENABLE_ABSTRACT_SOCKETS "enable support for abstract sockets" ON)
+	set (CMAKE_THREAD_PREFER_PTHREAD ON)
+	include (FindThreads)
+endif(NOT WIN32)
+
+#AC_ARG_ENABLE(asserts, AS_HELP_STRING([--enable-asserts],[include assertion checks]),enable_asserts=$enableval,enable_asserts=$USE_MAINTAINER_MODE)
+option (DBUS_DISABLE_ASSERTS "Disable assertion checking" OFF)
+
+option (DBUS_ENABLE_STATS "enable bus daemon usage statistics" OFF)
+
+option (DBUS_ENABLE_STATS "enable bus daemon usage statistics" OFF)
+
+if (DBUS_USE_EXPAT)
+    find_package(LibExpat)
+else ()
+    find_package(LibXml2)
+endif ()
+find_package(X11)
+
+# analogous to AC_USE_SYSTEM_EXTENSIONS in configure.ac
+add_definitions(-D_POSIX_C_SOURCE=199309L -D_GNU_SOURCE)
+
+# do config checks
+INCLUDE(ConfigureChecks.cmake)
+
+# @TODO: how to remove last dir from ${CMAKE_SOURCE_DIR} ?
+SET(DBUS_SOURCE_DIR ${CMAKE_SOURCE_DIR}/..)
+
+# make some more macros available
+include (MacroLibrary)
+
+if(VCS)
+	set(DBUS_VERBOSE_C_S 1 CACHE STRING "verbose mode" FORCE)
+endif(VCS)
+
+if(WIN32)
+	set(CMAKE_DEBUG_POSTFIX "d")
+	if(MSVC)
+		# controll folders in msvc projects
+		include(ProjectSourceGroup)
+		if(NOT GROUP_CODE)
+			#set(GROUP_CODE split) #cmake default
+			set(GROUP_CODE flat)
+		endif(NOT GROUP_CODE)
+		ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
+
+
+		# Use the highest warning level
+		if (WALL)
+			set(WALL 1 CACHE STRING "all warnings"  FORCE)
+			set(CMAKE_CXX_WARNING_LEVEL 4 CACHE STRING "warning level" FORCE)
+
+			if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
+				STRING(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+			else(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
+				SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
+			endif(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
+
+			if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
+				STRING(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
+			else(CMAKE_C_FLAGS MATCHES "/W[0-4]")
+				SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
+			endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
+		else (WALL)
+			set(CMAKE_CXX_WARNING_LEVEL 3 CACHE STRING "warning level" FORCE)
+		endif (WALL)
+
+		SET(MSVC_W_ERROR   " /we4028 /we4013 /we4133 /we4047 /we4031 /we4002 /we4003 /we4114")
+		SET(MSVC_W_DISABLE " /wd4127 /wd4090 /wd4101 /wd4244")
+
+		SET(CMAKE_C_FLAGS_DEBUG   "${CMAKE_C_FLAGS_DEBUG}   /FIconfig.h ${MSVC_W_ERROR} ${MSVC_W_DISABLE}")
+		SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /FIconfig.h ${MSVC_W_ERROR} ${MSVC_W_DISABLE}")
+	endif(MSVC)
+endif(WIN32)
+
+if (UNIX AND NOT DBUS_DISABLE_ASSERTS)
+	# required for backtrace
+	SET(CMAKE_C_FLAGS_DEBUG   "${CMAKE_C_FLAGS_DEBUG}   -Wl,--export-dynamic")
+	SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wl,--export-dynamic")
+	add_definitions(-DDBUS_BUILT_R_DYNAMIC)
+endif (UNIX AND NOT DBUS_DISABLE_ASSERTS)
+
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}  -D_DEBUG")
+
+#########################################################################
+# Windows CE (>= 5.0.0)
+#
+# WinCE support now relies on the presence of platform files, found in cmake/modules/platform
+# Cmake 2.8.0 doesn't include WinCE platform files by default, but working ones can be found
+# on CMake's bugtracker :
+# http://public.kitware.com/Bug/view.php?id=7919
+#
+# for cmake 2.8.0 get the following patch only :
+# http://public.kitware.com/Bug/file_download.php?file_id=2944&type=bug
+#
+# after applying the patch, you can enable the WinCE build by specifying :
+# cmake [...] -DCMAKE_SYSTEM_NAME=WinCE -DCMAKE_SYSTEM_VERSION=X.XX
+# (where X.XX is your actual WinCE version, e.g. 5.02 for Windows Mobile 6)
+#
+# Note that you should have a proper cross-compilation environment set up prior to running
+# cmake, ie. the PATH, INCLUDE and LIB env vars pointing to your CE SDK/toolchain.
+#
+if(WINCE)
+
+MESSAGE("Building for WinCE (${CMAKE_SYSTEM_VERSION})")
+
+endif(WINCE)
+#########################################################################
+
+
+ENABLE_TESTING()
+
+#########################################################################
+# Disallow in-source build
+#macro_ensure_out_of_source_build("dbus requires an out of source build. Please create a separate build directory and run 'cmake path_to_dbus [options]' there.")
+
+# ... and warn in case of an earlier in-source build
+#set(generatedFileInSourceDir EXISTS ${dbus_SOURCE_DIR}/config.h)
+#if(${generatedFileInSourceDir})
+#   message(STATUS "config.h exists in your source directory.")
+#endif(${generatedFileInSourceDir})
+#########################################################################
+
+if (WIN32 OR CYGWIN)
+	set (LIBRARY_OUTPUT_PATH  ${CMAKE_BINARY_DIR}/bin)
+else (WIN32 OR CYGWIN)
+	set (LIBRARY_OUTPUT_PATH  ${CMAKE_BINARY_DIR}/lib)
+endif (WIN32 OR CYGWIN)
+
+set (EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
+
+# for including config.h and for includes like <dir/foo.h>
+include_directories( ${CMAKE_SOURCE_DIR}/.. ${CMAKE_BINARY_DIR} ${CMAKE_INCLUDE_PATH} )
+
+# linker search directories
+link_directories(${DBUS_LIB_DIR} ${LIBRARY_OUTPUT_PATH} )
+include_directories( ${CMAKE_LIBRARY_PATH}  )
+
+set(DBUS_INCLUDES)
+
+ENABLE_TESTING()
+
+########### command line options ###############
+# TODO: take check from configure.in
+
+#AC_ARG_ENABLE(tests, AS_HELP_STRING([--enable-tests],[enable unit test code]),enable_tests=$enableval,enable_tests=$USE_MAINTAINER_MODE)
+option (DBUS_BUILD_TESTS "enable unit test code" ON)
+ 
+if(DBUS_BUILD_TESTS)
+    add_definitions(-DDBUS_BUILD_TESTS -DDBUS_ENABLE_EMBEDDED_TESTS)
+endif(DBUS_BUILD_TESTS)
+
+option (DBUS_USE_OUTPUT_DEBUG_STRING "enable win32 debug port for message output" OFF)
+if(DBUS_USE_OUTPUT_DEBUG_STRING)
+    add_definitions(-DDBUS_USE_OUTPUT_DEBUG_STRING)
+endif(DBUS_USE_OUTPUT_DEBUG_STRING)
+
+if(WIN32)
+	# win32 dbus service support - this support is not complete
+	option (DBUS_SERVICE "enable dbus service installer" OFF)
+endif(WIN32)
+
+#AC_ARG_ENABLE(ansi, AS_HELP_STRING([--enable-ansi],[enable -ansi -pedantic gcc flags]),enable_ansi=$enableval,enable_ansi=no)
+option (DBUS_ENABLE_ANSI "enable -ansi -pedantic gcc flags" OFF)
+if(DBUS_ENABLE_ANSI)
+   if(NOT MSVC)
+        add_definitions(-ansi -D_POSIX_C_SOURCE=199309L -D_BSD_SOURCE -pedantic)
+   else(NOT MSVC)
+        add_definitions(-Za -D_POSIX_C_SOURCE=199309L -D_BSD_SOURCE -W4)
+   endif(NOT MSVC)
+endif(DBUS_ENABLE_ANSI)
+
+#AC_ARG_ENABLE(verbose-mode, AS_HELP_STRING([--enable-verbose-mode],[support verbose debug mode]),enable_verbose_mode=$enableval,enable_verbose_mode=$USE_MAINTAINER_MODE)
+option (DBUS_ENABLE_VERBOSE_MODE "support verbose debug mode" ON)
+
+#AC_ARG_ENABLE(checks, AS_HELP_STRING([--enable-checks],[include sanity checks on public API]),enable_checks=$enableval,enable_checks=yes)
+option (DBUS_DISABLE_CHECKS "Disable public API sanity checking" OFF)
+
+if(NOT MSVC)
+    #AC_ARG_ENABLE(gcov, AS_HELP_STRING([--enable-gcov],[compile with coverage profiling instrumentation (gcc only)]),enable_gcov=$enableval,enable_gcov=no)
+    option (DBUS_GCOV_ENABLED "compile with coverage profiling instrumentation (gcc only)" OFF)
+    if(DBUS_GCOV_ENABLED)
+            add_definitions(-fprofile-arcs -ftest-coverage)
+            # FIXME!!!!
+            ## remove optimization
+    #        CFLAGS=`echo "$CFLAGS" | sed -e 's/-O[0-9]*//g'`
+    endif(DBUS_GCOV_ENABLED)
+endif(NOT MSVC)
+
+#AC_ARG_ENABLE(abstract-sockets, AS_HELP_STRING([--enable-abstract-sockets],[use abstract socket namespace (linux only)]),enable_abstract_sockets=$enableval,enable_abstract_sockets=auto)
+# -> moved before include(ConfigureChecks.cmake)
+
+#AC_ARG_ENABLE(selinux, AS_HELP_STRING([--enable-selinux],[build with SELinux support]),enable_selinux=$enableval,enable_selinux=auto)
+#selinux missing
+
+#AC_ARG_ENABLE(dnotify, AS_HELP_STRING([--enable-dnotify],[build with dnotify support (linux only)]),enable_dnotify=$enableval,enable_dnotify=auto)
+if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
+    option (DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX "build with dnotify support (linux only)" ON) # add a check !
+endif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
+
+#AC_ARG_ENABLE(kqueue, AS_HELP_STRING([--enable-kqueue],[build with kqueue support (FreeBSD only)]),enable_kqueue=$enableval,enable_kqueue=auto)
+#missing
+
+#AC_ARG_ENABLE(console-owner-file, AS_HELP_STRING([--enable-console-owner-file],[enable console owner file]),enable_console_owner_file=$enableval,enable_console_owner_file=auto)
+STRING(TOUPPER ${CMAKE_SYSTEM_NAME} sysname)
+if("${sysname}" MATCHES ".*SOLARIS.*")
+    option (HAVE_CONSOLE_OWNER_FILE "enable console owner file (solaris only)" ON)
+    if(HAVE_CONSOLE_OWNER_FILE)
+        set (DBUS_CONSOLE_OWNER_FILE "/dev/console" CACHE STRING "Directory to check for console ownerhip")
+    endif(HAVE_CONSOLE_OWNER_FILE)
+endif("${sysname}" MATCHES ".*SOLARIS.*")
+
+#AC_ARG_WITH(xml, AS_HELP_STRING([--with-xml=[libxml/expat]],[XML library to use]))
+if(NOT LIBXML2_FOUND AND NOT LIBEXPAT_FOUND)
+    message(FATAL "Neither expat nor libxml2 found!")
+endif(NOT LIBXML2_FOUND AND NOT LIBEXPAT_FOUND)
+
+if(DBUS_USE_EXPAT)
+    SET(XML_LIB "Expat")
+    SET(XML_LIBRARY     ${LIBEXPAT_LIBRARIES})
+    SET(XML_INCLUDE_DIR ${LIBEXPAT_INCLUDE_DIR})
+else(DBUS_USE_EXPAT)
+    SET(XML_LIB "LibXML2")
+    SET(XML_LIBRARY     ${LIBXML2_LIBRARIES})
+    SET(XML_INCLUDE_DIR ${LIBXML2_INCLUDE_DIR})
+endif(DBUS_USE_EXPAT)
+
+
+#AC_ARG_WITH(init-scripts, AS_HELP_STRING([--with-init-scripts=[redhat]],[Style of init scripts to install]))
+#AC_ARG_WITH(session-socket-dir, AS_HELP_STRING([--with-session-socket-dir=[dirname]],[Where to put sockets for the per-login-session message bus]))
+#AC_ARG_WITH(test-socket-dir, AS_HELP_STRING([--with-test-socket-dir=[dirname]],[Where to put sockets for make check]))
+#AC_ARG_WITH(system-pid-file, AS_HELP_STRING([--with-system-pid-file=[pidfile]],[PID file for systemwide daemon]))
+#AC_ARG_WITH(system-socket, AS_HELP_STRING([--with-system-socket=[filename]],[UNIX domain socket for systemwide daemon]))
+#AC_ARG_WITH(console-auth-dir, AS_HELP_STRING([--with-console-auth-dir=[dirname]],[directory to check for console ownerhip]))
+#AC_ARG_WITH(console-owner-file, AS_HELP_STRING([--with-console-owner-file=[filename]],[file whose owner determines current console owner]))
+#AC_ARG_WITH(dbus_user, AS_HELP_STRING([--with-dbus-user=<user>],[User for running the DBUS daemon (messagebus)]))
+#AC_ARG_WITH(dbus_daemondir, AS_HELP_STRING([--with-dbus-daemondir=[dirname]],[Directory for installing the DBUS daemon]))
+# all missing or hardcoded for now
+
+# 'hidden' ones
+set(atomic_int OFF)
+set(atomic_int486 OFF)
+if(CMAKE_COMPILER_IS_GNUCC AND NOT DBUS_ENABLE_ANSI)
+    FIND_PROGRAM(UNAME_EXECUTABLE
+                    NAMES uname
+                    PATHS /bin /usr/bin /usr/local/bin c:/Programme/MSys/bin d:/Programme/MSys/bin)
+
+    if(UNAME_EXECUTABLE)
+        EXECUTE_PROCESS(COMMAND ${UNAME_EXECUTABLE} "-m"
+                        OUTPUT_VARIABLE UNAME_OUTPUT)
+
+        if("UNAME_OUTPUT" MATCHES "^.*i[0123]86.*$")
+            set(atomic_int ON)
+        else("UNAME_OUTPUT" MATCHES "^.*i[0123]86.*$")
+            if("UNAME_OUTPUT" MATCHES "^.*i?86.*$")
+                set(atomic_int ON)
+                set(atomic_int_486 ON)
+            endif("UNAME_OUTPUT" MATCHES "^.*i?86.*$")
+        endif("UNAME_OUTPUT" MATCHES "^.*i[0123]86.*$")
+    endif(UNAME_EXECUTABLE)
+endif(CMAKE_COMPILER_IS_GNUCC AND NOT DBUS_ENABLE_ANSI)
+
+set (DBUS_HAVE_ATOMIC_INT ${atomic_int} CACHE STRING "Some atomic integer implementation present")
+set (DBUS_USE_ATOMIC_INT_486 ${atomic_int_486} CACHE STRING "Use atomic integer implementation for 486")
+
+if(X11_FOUND)
+  option (DBUS_BUILD_X11 "Build with X11 autolaunch support " ON)
+endif(X11_FOUND)
+
+# test binary names
+if (WIN32)
+	# Automake calls this EXEEXT, and CMake doesn't have a standard name
+	# for it; follow Automake's naming convention so we can share .in files
+	set (EXEEXT ".exe")
+endif(WIN32)
+
+if (MSVC_IDE)
+    if(CMAKE_BUILD_TYPE MATCHES Debug)
+		set(IDE_BIN /Debug )
+		message(STATUS)
+		message(STATUS "Visual Studio: test programs will only work with 'Debug' configuration!")
+		message(STATUS "To run tests with 'Release' configuration use -DCMAKE_BUILD_TYPE=Release")
+		message(STATUS "Add '..\\..\\test\\data' to the command line option of the test programs")
+		message(STATUS)
+    else(CMAKE_BUILD_TYPE MATCHES Debug)
+		set(IDE_BIN /Release)
+		message(STATUS)
+		message(STATUS "Visual Studio: test programs will only work with 'Release' configuration!")
+		message(STATUS "To run tests with 'Debug' configuration use -DCMAKE_BUILD_TYPE=Debug")
+		message(STATUS "Add '..\\..\\test\\data' to the command line option of the test programs")
+		message(STATUS)
+    endif(CMAKE_BUILD_TYPE MATCHES Debug)
+	set (TEST_PATH_FORCE FORCE)
+	FILE(REMOVE ${CMAKE_BINARY_DIR}/data/dbus-1/services)
+endif (MSVC_IDE)
+
+#### Find socket directories
+ if (NOT $ENV{TMPDIR} STREQUAL "")
+     set (DBUS_SESSION_SOCKET_DIR $ENV{TMPDIR})
+ else (NOT $ENV{TMPDIR} STREQUAL "")
+     if (NOT $ENV{TEMP} STREQUAL "")
+         set (DBUS_SESSION_SOCKET_DIR $ENV{TEMP})
+     else (NOT $ENV{TEMP} STREQUAL "")
+         if (NOT $ENV{TMP} STREQUAL "")
+             set (DBUS_SESSION_SOCKET_DIR $ENV{TMP})
+         else (NOT $ENV{TMP} STREQUAL "")
+         if (WIN32)
+             #Should never happen, both TMP and TEMP seem always set on Windows
+             message(FATAL "Could not determine a usable temporary directory")
+         else(WIN32)
+            set (DBUS_SESSION_SOCKET_DIR /tmp)
+         endif(WIN32)
+         endif (NOT $ENV{TMP} STREQUAL "")
+     endif (NOT $ENV{TEMP} STREQUAL "")
+ endif (NOT $ENV{TMPDIR} STREQUAL "")
+
+#AC_ARG_WITH(test-socket-dir, AS_HELP_STRING([--with-test-socket-dir=[dirname]],[Where to put sockets for make check]))
+
+#AC_ARG_WITH(system-pid-file, AS_HELP_STRING([--with-system-pid-file=[pidfile]],[PID file for systemwide daemon]))
+
+#if ! test -z "$with_system_pid_file"; then
+#   DBUS_SYSTEM_PID_FILE=$with_system_pid_file
+#elif test x$operating_system = xredhat ; then
+#   DBUS_SYSTEM_PID_FILE=${EXPANDED_LOCALSTATEDIR}/run/messagebus.pid
+#else
+#   DBUS_SYSTEM_PID_FILE=${EXPANDED_LOCALSTATEDIR}/run/dbus/pid
+#fi
+# TODO: fix redhet
+if (WIN32)
+  # bus-test expects a non empty string
+	set (DBUS_SYSTEM_PID_FILE "/dbus-pid")
+else (WIN32)
+	set (DBUS_SYSTEM_PID_FILE ${EXPANDED_LOCALSTATEDIR}/run/dbus/pid)
+endif (WIN32)
+
+#AC_ARG_WITH(system-socket, AS_HELP_STRING([--with-system-socket=[filename]],[UNIX domain socket for systemwide daemon]))
+
+#AC_ARG_WITH(console-auth-dir, AS_HELP_STRING([--with-console-auth-dir=[dirname]],[directory to check for console ownerhip]))
+
+if (WIN32)
+	set (DBUS_CONSOLE_AUTH_DIR "")
+else (WIN32)
+	set (DBUS_CONSOLE_AUTH_DIR "/var/run/console/")
+endif (WIN32)
+
+#AC_ARG_WITH(dbus_user, AS_HELP_STRING([--with-dbus-user=<user>],[User for running the DBUS daemon (messagebus)]))
+
+set (DBUS_USER )
+
+
+if (WIN32)
+  set (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "nonce-tcp:" CACHE STRING "system bus default address")
+  set (DBUS_SESSION_BUS_DEFAULT_ADDRESS "nonce-tcp:" CACHE STRING "session bus default address")
+
+  set (DBUS_SYSTEM_CONFIG_FILE "etc/dbus-1/system.conf")
+  set (DBUS_SESSION_CONFIG_FILE "etc/dbus-1/session.conf")
+  # bus-test expects a non empty string
+  set (DBUS_USER "Administrator")
+else (WIN32)
+  set (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:tmpdir=" CACHE STRING "system bus default address")
+  set (DBUS_SESSION_BUS_DEFAULT_ADDRESS "unix:path=${DBUS_SESSION_SOCKET_DIR}" CACHE STRING "session bus default address")
+  set (sysconfdir "")
+  set (configdir ${sysconfdir}/dbus-1 )
+  set (DBUS_SYSTEM_CONFIG_FILE  ${configdir}/system.conf)
+  set (DBUS_SESSION_CONFIG_FILE ${configdir}/session.conf)
+  set (DBUS_USER "root")
+endif (WIN32)
+
+set (DBUS_DAEMON_NAME "dbus-daemon" CACHE STRING "The name of the dbus daemon executable")
+
+########### create config.h ###############
+
+#include(ConfigureChecks.cmake)
+
+# better use flags for gcc
+if (MINGW)
+	set (HAVE_GNUC_VARARGS 1)
+endif(MINGW)
+
+# compiler definitions
+add_definitions(-DHAVE_CONFIG_H=1)
+add_definitions(${DBUS_BUS_CFLAGS})
+
+
+if (DBUS_BUILD_TESTS)
+    # set variables used for the .in files (substituted by configure_file) in test/data:
+    set(DBUS_TEST_EXEC ${EXECUTABLE_OUTPUT_PATH}${IDE_BIN})
+    set(DBUS_TEST_DATA ${CMAKE_BINARY_DIR}/test/data)
+    set(TEST_SOCKET_DIR ${DBUS_SESSION_SOCKET_DIR} )
+    set(TEST_LAUNCH_HELPER_BINARY ${EXECUTABLE_OUTPUT_PATH}/dbus-daemon-launch-helper-test)
+    if (UNIX)
+        set (TEST_LISTEN "unix:tmpdir=${TEST_SOCKET_DIR}")
+    endif (UNIX)
+    if (WIN32)
+        set (TEST_LISTEN "tcp:host=localhost")
+    endif (WIN32)
+endif  (DBUS_BUILD_TESTS)
+
+set(DBUS_LIBRARIES dbus-1)
+set(DBUS_INTERNAL_LIBRARIES dbus-internal)
+
+# settings for building and using static internal lib
+# important note: DBUS_INTERNAL_xxxxx_DEFINITIONS must *not* be set when building dbus-1 library
+set (DBUS_INTERNAL_ADD_LIBRARY_OPTIONS STATIC)
+set (DBUS_INTERNAL_LIBRARY_DEFINITIONS "-DDBUS_STATIC_BUILD")
+set (DBUS_INTERNAL_CLIENT_DEFINITIONS "-DDBUS_STATIC_BUILD")
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h )
+
+if (WIN32)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dbus-env.bat.cmake ${CMAKE_BINARY_DIR}/bin/dbus-env.bat )
+install_files(/bin FILES ${CMAKE_BINARY_DIR}/bin/dbus-env.bat)
+endif()
+
+add_definitions(-DHAVE_CONFIG_H=1)
+
+########### subdirs ###############
+
+add_subdirectory( dbus )
+add_subdirectory( bus )
+if (DBUS_BUILD_TESTS)
+	add_subdirectory( test )
+endif (DBUS_BUILD_TESTS)
+add_subdirectory( tools )
+add_subdirectory( doc )
+
+
+OPTION(DBUS_INSTALL_SYSTEM_LIBS "install required system libraries" OFF)
+MESSAGE(" ")
+MESSAGE("set -DDBUS_INSTALL_SYSTEM_LIBS=1 to install runtime libraries too")
+MESSAGE("set DBUSDIR (environment or cmake option) to overwrite the default install directory ")
+MESSAGE(" ")
+MESSAGE(" ")
+GET_FILENAME_COMPONENT(C_COMPILER ${CMAKE_C_COMPILER} NAME)
+GET_FILENAME_COMPONENT(CXX_COMPILER ${CMAKE_CXX_COMPILER} NAME)
+
+message("                  D-BUS ${DBUS_VERSION}                               ")
+message("                  ===========                                         ")
+message("                                                                      ")
+message("        install prefix:           ${prefix}                           ")
+message("        install exec_prefix:      ${exec_prefix}                      ")
+message("        install libdir:           ${EXPANDED_LIBDIR}                  ")
+message("        install bindir:           ${EXPANDED_BINDIR}                  ")
+message("        install sysconfdir:       ${EXPANDED_SYSCONFDIR}              ")
+#message("        install localstatedir:    ${EXPANDED_LOCALSTATEDIR}           ")
+message("        install datadir:          ${EXPANDED_DATADIR}                 ")
+message("        source code location:     ${DBUS_SOURCE_DIR}                  ")
+message("        build dir:                ${CMAKE_BINARY_DIR}                 ")
+message("        c compiler:               ${C_COMPILER}                       ")
+message("        cflags:                   ${CMAKE_C_FLAGS}                    ")
+message("        cflags debug:             ${CMAKE_C_FLAGS_DEBUG}              ")
+message("        cflags release:           ${CMAKE_C_FLAGS_RELEASE}            ")
+message("        cxx compiler:             ${CXX_COMPILER}                     ")
+message("        cxxflags:                 ${CMAKE_CXX_FLAGS}                  ")
+message("        cxxflags debug:           ${CMAKE_CXX_FLAGS_DEBUG}            ")
+message("        cxxflags release:         ${CMAKE_CXX_FLAGS_RELEASE}          ")
+message("        64-bit int:               ${DBUS_INT64_TYPE}                  ")
+message("        32-bit int:               ${DBUS_INT32_TYPE}                  ")
+message("        16-bit int:               ${DBUS_INT16_TYPE}                  ")
+message("        Doxygen:                  ${DOXYGEN}                          ")
+message("        Docbook Generator:        ${DOCBOOK_GENERATOR_NAME}           ")
+
+
+#message("        Maintainer mode:          ${USE_MAINTAINER_MODE}              ")
+message("        gcc coverage profiling:   ${DBUS_GCOV_ENABLED}                ")
+message("        Building unit tests:      ${DBUS_BUILD_TESTS}                 ")
+message("        Building verbose mode:    ${DBUS_ENABLE_VERBOSE_MODE}         ")
+message("        Building w/o assertions:  ${DBUS_DISABLE_ASSERTS}             ")
+message("        Building w/o checks:      ${DBUS_DISABLE_CHECKS}              ")
+message("        Building bus stats API:   ${DBUS_ENABLE_STATS}                ")
+message("        installing system libs:   ${DBUS_INSTALL_SYSTEM_LIBS}         ")
+#message("        Building SELinux support: ${have_selinux}                     ")
+#message("        Building dnotify support: ${have_dnotify}                     ")
+message("        Building Doxygen docs:    ${DBUS_ENABLE_DOXYGEN_DOCS}         ")
+message("        Building XML docs:        ${DBUS_ENABLE_XML_DOCS}             ")
+#message("        Gettext libs (empty OK):  ${INTLLIBS}                         ")
+message("        Using XML parser:         ${XML_LIB}                          ")
+message("        Daemon executable name:   ${DBUS_DAEMON_NAME}")
+if (WIN32)
+message("        System bus address:       ${DBUS_SYSTEM_BUS_DEFAULT_ADDRESS}  ")
+message("        Session bus address:      ${DBUS_SESSION_BUS_DEFAULT_ADDRESS} ")
+else (WIN32)
+#message("        Init scripts style:       ${with_init_scripts}                ")
+#message("        Abstract socket names:    ${have_abstract_sockets}            ")
+message("        System bus socket:        ${DBUS_SYSTEM_SOCKET}               ")
+message("        System bus address:       ${DBUS_SYSTEM_BUS_DEFAULT_ADDRESS}  ")
+message("        System bus PID file:      ${DBUS_SYSTEM_PID_FILE}             ")
+message("        Session bus socket dir:   ${DBUS_SESSION_SOCKET_DIR}          ")
+message("        Console auth dir:         ${DBUS_CONSOLE_AUTH_DIR}            ")
+message("        System bus user:          ${DBUS_USER}                        ")
+message("        'make check' socket dir:  ${TEST_SOCKET_DIR}                  ")
+endif (WIN32)
+message("        Test listen address:      ${TEST_LISTEN}                      ")
+if (MSVC)
+message("        build timestamp:          ${DBUS_BUILD_TIMESTAMP}             ")
+endif (MSVC)
+
+MESSAGE(" ")
+if (DBUS_BUILD_TESTS)
+    message("NOTE: building with unit tests increases the size of the installed library and renders it insecure.")
+endif(DBUS_BUILD_TESTS)
+
+if (DBUS_BUILD_TESTS AND DBUS_DISABLE_ASSERTS)
+    message("NOTE: building with unit tests but without assertions means tests may not properly report failures (this configuration is only useful when doing something like profiling the tests)")
+endif(DBUS_BUILD_TESTS AND DBUS_DISABLE_ASSERTS)
+
+if (DBUS_GCOV_ENABLED)
+    message("NOTE: building with coverage profiling is definitely for developers only.")
+endif(DBUS_GCOV_ENABLED)
+
+if (DBUS_ENABLE_VERBOSE_MODE)
+    message("NOTE: building with verbose mode increases library size, may slightly increase security risk, and decreases performance.")
+endif(DBUS_ENABLE_VERBOSE_MODE)
+
+if(NOT DBUS_DISABLE_ASSERTS)
+    message("NOTE: building with assertions increases library size and decreases performance.")
+endif(NOT DBUS_DISABLE_ASSERTS)
+
+if (DBUS_DISABLE_CHECKS)
+    message("NOTE: building without checks for arguments passed to public API makes it harder to debug apps using D-BUS, but will slightly decrease D-BUS library size and _very_ slightly improve performance.")
+endif(DBUS_DISABLE_CHECKS)
+MESSAGE(" ")
+
+INCLUDE(modules/CPackInstallConfig.cmake)
+
+add_custom_target(help-options
+    cmake -LH 
+    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+)
diff --git a/dbus/cmake/ConfigureChecks.cmake b/dbus/cmake/ConfigureChecks.cmake
new file mode 100644
index 0000000..33a9cee
--- /dev/null
+++ b/dbus/cmake/ConfigureChecks.cmake
@@ -0,0 +1,160 @@
+include(CheckIncludeFile)
+include(CheckSymbolExists)
+include(CheckStructMember)
+include(CheckTypeSize)
+
+check_include_file(dirent.h     HAVE_DIRENT_H)  # dbus-sysdeps-util.c
+check_include_file(io.h         HAVE_IO_H)      # internal
+check_include_file(grp.h        HAVE_GRP_H)     # dbus-sysdeps-util-win.c
+check_include_file(sys/poll.h   HAVE_POLL)      # dbus-sysdeps.c, dbus-sysdeps-win.c
+check_include_file(sys/time.h   HAVE_SYS_TIME_H)# dbus-sysdeps-win.c
+check_include_file(sys/wait.h   HAVE_SYS_WAIT_H)# dbus-sysdeps-win.c
+check_include_file(time.h       HAVE_TIME_H)    # dbus-sysdeps-win.c
+check_include_file(ws2tcpip.h   HAVE_WS2TCPIP_H)# dbus-sysdeps-win.c
+check_include_file(wspiapi.h    HAVE_WSPIAPI_H) # dbus-sysdeps-win.c
+check_include_file(unistd.h     HAVE_UNISTD_H)  # dbus-sysdeps-util-win.c
+check_include_file(stdio.h      HAVE_STDIO_H)   # dbus-sysdeps.h
+check_include_file(sys/syslimits.h    HAVE_SYS_SYSLIMITS_H)   # dbus-sysdeps-unix.c
+check_include_file(errno.h     HAVE_ERRNO_H)    # dbus-sysdeps.c
+check_include_file(signal.h     HAVE_SIGNAL_H)
+check_include_file(locale.h     HAVE_LOCALE_H)
+check_include_file(inttypes.h     HAVE_INTTYPES_H)   # dbus-pipe.h
+check_include_file(stdint.h     HAVE_STDINT_H)   # dbus-pipe.h
+
+check_symbol_exists(backtrace    "execinfo.h"       HAVE_BACKTRACE)          #  dbus-sysdeps.c, dbus-sysdeps-win.c
+check_symbol_exists(getgrouplist "grp.h"            HAVE_GETGROUPLIST)       #  dbus-sysdeps.c
+check_symbol_exists(getpeerucred "ucred.h"          HAVE_GETPEERUCRED)       #  dbus-sysdeps.c, dbus-sysdeps-win.c
+check_symbol_exists(nanosleep    "time.h"           HAVE_NANOSLEEP)          #  dbus-sysdeps.c
+check_symbol_exists(getpwnam_r   "errno.h pwd.h"    HAVE_POSIX_GETPWNAM_R)   #  dbus-sysdeps-util-unix.c
+check_symbol_exists(setenv       "stdlib.h"         HAVE_SETENV)             #  dbus-sysdeps.c
+check_symbol_exists(unsetenv     "stdlib.h"         HAVE_UNSETENV)           #  dbus-sysdeps.c
+check_symbol_exists(clearenv     "stdlib.h"         HAVE_CLEARENV)           #  dbus-sysdeps.c
+check_symbol_exists(writev       "sys/uio.h"        HAVE_WRITEV)             #  dbus-sysdeps.c, dbus-sysdeps-win.c
+check_symbol_exists(setrlimit    "sys/resource.h"   HAVE_SETRLIMIT)          #  dbus-sysdeps.c, dbus-sysdeps-win.c, test/test-segfault.c
+check_symbol_exists(socketpair   "sys/socket.h"     HAVE_SOCKETPAIR)         #  dbus-sysdeps.c
+check_symbol_exists(socklen_t    "sys/socket.h"     HAVE_SOCKLEN_T)          #  dbus-sysdeps-unix.c
+check_symbol_exists(setlocale    "locale.h"         HAVE_SETLOCALE)          #  dbus-test-main.c
+check_symbol_exists(localeconv   "locale.h"         HAVE_LOCALECONV)         #  dbus-sysdeps.c
+check_symbol_exists(strtoll      "stdlib.h"         HAVE_STRTOLL)            #  dbus-send.c
+check_symbol_exists(strtoull     "stdlib.h"         HAVE_STRTOULL)           #  dbus-send.c
+
+check_struct_member(cmsgcred cmcred_pid "sys/types.h sys/socket.h" HAVE_CMSGCRED)   #  dbus-sysdeps.c
+
+# missing:
+# HAVE_ABSTRACT_SOCKETS
+# DBUS_HAVE_GCC33_GCOV
+
+check_type_size("short"     SIZEOF_SHORT)
+check_type_size("int"       SIZEOF_INT)
+check_type_size("long"      SIZEOF_LONG)
+check_type_size("long long" SIZEOF_LONG_LONG)
+check_type_size("__int64"   SIZEOF___INT64)
+
+# DBUS_INT64_TYPE
+if(SIZEOF_INT EQUAL 8)
+    set (DBUS_HAVE_INT64 1)
+    set (DBUS_INT64_TYPE "int")
+    set (DBUS_INT64_CONSTANT  "(val)")
+    set (DBUS_UINT64_CONSTANT "(val##U)")
+elseif(SIZEOF_LONG EQUAL 8)
+    set (DBUS_HAVE_INT64 1)
+    set (DBUS_INT64_TYPE "long")
+    set (DBUS_INT64_CONSTANT  "(val##L)")
+    set (DBUS_UINT64_CONSTANT "(val##UL)")
+elseif(SIZEOF_LONG_LONG EQUAL 8)
+    set (DBUS_HAVE_INT64 1)
+    set (DBUS_INT64_TYPE "long long")
+    set (DBUS_INT64_CONSTANT  "(val##LL)")
+    set (DBUS_UINT64_CONSTANT "(val##ULL)")
+elseif(SIZEOF___INT64 EQUAL 8)
+    set (DBUS_HAVE_INT64 1)
+    set (DBUS_INT64_TYPE "__int64")
+    set (DBUS_INT64_CONSTANT  "(val##i64)")
+    set (DBUS_UINT64_CONSTANT "(val##ui64)")
+endif(SIZEOF_INT EQUAL 8)
+
+# DBUS_INT32_TYPE
+if(SIZEOF_INT EQUAL 4)
+    set (DBUS_INT32_TYPE "int")
+elseif(SIZEOF_LONG EQUAL 4)
+    set (DBUS_INT32_TYPE "long")
+elseif(SIZEOF_LONG_LONG EQUAL 4)
+    set (DBUS_INT32_TYPE "long long")
+endif(SIZEOF_INT EQUAL 4)
+
+# DBUS_INT16_TYPE
+if(SIZEOF_INT EQUAL 2)
+    set (DBUS_INT16_TYPE "int")
+elseif(SIZEOF_SHORT EQUAL 2)
+    set (DBUS_INT16_TYPE "short")
+endif(SIZEOF_INT EQUAL 2)
+
+find_program(DOXYGEN doxygen)
+find_program(XMLTO xmlto)
+
+if(MSVC)
+   SET(DBUS_VA_COPY_FUNC "_DBUS_VA_COPY_ASSIGN";)
+else(MSVC)
+write_file("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/cmake_try_compile.c" "#include <stdarg.h>
+	#include <stdlib.h>
+        static void f (int i, ...) {
+	va_list args1, args2;
+	va_start (args1, i);
+	va_copy (args2, args1);
+	if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+	  exit (1);
+	va_end (args1); va_end (args2);
+	}
+	int main() {
+	  f (0, 42);
+	  return 0;
+	}
+")
+try_compile(DBUS_HAVE_VA_COPY
+            ${CMAKE_BINARY_DIR}
+            ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/cmake_try_compile.c)
+
+if(DBUS_HAVE_VA_COPY)
+  SET(DBUS_VA_COPY_FUNC va_copy CACHE STRING "va_copy function")
+else(DBUS_HAVE_VA_COPY)
+  write_file("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/cmake_try_compile.c" "#include <stdarg.h>
+          #include <stdlib.h>
+	  static void f (int i, ...) {
+	  va_list args1, args2;
+	  va_start (args1, i);
+	  __va_copy (args2, args1);
+	  if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+	    exit (1);
+	  va_end (args1); va_end (args2);
+	  }
+	  int main() {
+	    f (0, 42);
+	    return 0;
+	  }
+  ")
+  try_compile(DBUS_HAVE___VA_COPY
+              ${CMAKE_BINARY_DIR}
+              ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/cmake_try_compile.c)
+  if(DBUS_HAVE___VA_COPY)
+    SET(DBUS_VA_COPY_FUNC __va_copy CACHE STRING "va_copy function")
+  else(DBUS_HAVE___VA_COPY)
+    SET(DBUS_VA_COPY_AS_ARRAY "1" CACHE STRING "'va_lists' cannot be copies as values")
+  endif(DBUS_HAVE___VA_COPY)
+endif(DBUS_HAVE_VA_COPY)
+endif(MSVC) # _not_ MSVC
+#### Abstract sockets
+
+if (DBUS_ENABLE_ABSTRACT_SOCKETS)
+
+  try_compile(HAVE_ABSTRACT_SOCKETS
+              ${CMAKE_BINARY_DIR}
+              ${CMAKE_SOURCE_DIR}/modules/CheckForAbstractSockets.c)
+
+endif(DBUS_ENABLE_ABSTRACT_SOCKETS)
+
+if(HAVE_ABSTRACT_SOCKETS)
+  set(DBUS_PATH_OR_ABSTRACT_VALUE abstract)
+else(HAVE_ABSTRACT_SOCKETS)
+  set(DBUS_PATH_OR_ABSTRACT_VALUE path)
+endif(HAVE_ABSTRACT_SOCKETS)
+
diff --git a/dbus/cmake/Doxyfile.cmake b/dbus/cmake/Doxyfile.cmake
new file mode 100644
index 0000000..e00984e
--- /dev/null
+++ b/dbus/cmake/Doxyfile.cmake
@@ -0,0 +1,182 @@
+# Doxyfile 0.1
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = D-Bus
+PROJECT_NUMBER         = @VERSION@
+OUTPUT_DIRECTORY       = api
+OUTPUT_LANGUAGE        = English
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+STRIP_CODE_COMMENTS    = YES
+CASE_SENSE_NAMES       = YES
+SHORT_NAMES            = NO
+HIDE_SCOPE_NAMES       = NO
+VERBATIM_HEADERS       = YES
+SHOW_INCLUDE_FILES     = YES
+JAVADOC_AUTOBRIEF      = YES
+INHERIT_DOCS           = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+ALIASES                = 
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = YES
+SHOW_USED_FILES        = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = YES
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_FORMAT            = 
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = @top_srcdir@/dbus
+FILE_PATTERNS          = *.c *.h
+RECURSIVE              = YES
+#EXCLUDE                = test
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = Makefile.* ChangeLog CHANGES CHANGES.* README \
+                         README.* *.png AUTHORS DESIGN DESIGN.* *.desktop \
+                         DESKTOP* COMMENTS HOWTO magic NOTES TODO THANKS
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = 
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = 
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = 
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = YES
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3dbus
+MAN_LINKS              = YES
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = YES
+EXPAND_ONLY_PREDEF     = YES
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = "DBUS_BEGIN_DECLS=" 			\
+			 "DBUS_END_DECLS=" 			\
+			 "DOXYGEN_SHOULD_SKIP_THIS" 		\
+                         "DBUS_GNUC_DEPRECATED="                \
+			 "_DBUS_DEFINE_GLOBAL_LOCK(name)="	\
+			 "_DBUS_GNUC_PRINTF(from,to)=" \
+			 "DBUS_EXPORT="
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+PERL_PATH              = 
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+TEMPLATE_RELATIONS     = YES
+HIDE_UNDOC_RELATIONS   = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+GRAPHICAL_HIERARCHY    = YES
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 640
+MAX_DOT_GRAPH_HEIGHT   = 1024
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
diff --git a/dbus/cmake/bus-test.bat.cmake b/dbus/cmake/bus-test.bat.cmake
new file mode 100644
index 0000000..0168871
--- /dev/null
+++ b/dbus/cmake/bus-test.bat.cmake
@@ -0,0 +1,14 @@
+:: bus-test wrapper
+@echo off
+
+:: session bus address
+set DBUS_STARTER_BUS=tcp:host=localhost,port=1234
+
+if NOT "%1" == "" (
+	SET DATADIR=%1
+) else (
+	SET DATADIR=test\data
+)
+
+bin\bus-test.exe test\data
+
diff --git a/dbus/cmake/bus/CMakeLists.txt b/dbus/cmake/bus/CMakeLists.txt
new file mode 100644
index 0000000..faf9a8e
--- /dev/null
+++ b/dbus/cmake/bus/CMakeLists.txt
@@ -0,0 +1,187 @@
+project(bus)
+
+add_definitions(-DDBUS_COMPILATION)
+
+SET(EFENCE "")
+SET(BUS_DIR ${CMAKE_SOURCE_DIR}/../bus)
+
+set (config_DATA
+	session.conf				
+	system.conf
+)
+
+# config files for installation 
+CONFIGURE_FILE( "${BUS_DIR}/session.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/session.conf" IMMEDIATE @ONLY)
+CONFIGURE_FILE( "system.conf.cmake" "${CMAKE_CURRENT_BINARY_DIR}/system.conf" IMMEDIATE @ONLY)
+
+# copy services for local daemon start to local service dir data/dbus-1/services
+SET (SERVICE_FILES test/data/valid-service-files)
+FILE(GLOB FILES "${CMAKE_SOURCE_DIR}/../${SERVICE_FILES}/*.service.in" )
+FOREACH(FILE ${FILES})	
+	GET_FILENAME_COMPONENT(FILENAME ${FILE} NAME_WE)
+	SET (TARGET ${CMAKE_BINARY_DIR}/data/dbus-1/services/${FILENAME}.service)
+	IF (CONFIG_VERBOSE)
+		MESSAGE("FROM: ${FILE}\nTO: ${TARGET}\n")
+	ENDIF (CONFIG_VERBOSE)
+	configure_file(${FILE} ${TARGET} )
+ENDFOREACH(FILE)
+
+if(DBUS_USE_EXPAT)
+    SET (XML_SOURCES ${BUS_DIR}/config-loader-expat.c)
+else(DBUS_USE_EXPAT)
+    SET (XML_SOURCES ${BUS_DIR}/config-loader-libxml.c)
+endif (DBUS_USE_EXPAT)
+
+# after next cvs update
+#set (DIR_WATCH_SOURCE ${BUS_DIR}/dir-watch-default.c)
+set (DIR_WATCH_SOURCE )
+
+set (BUS_SOURCES 
+	${BUS_DIR}/activation.c				
+	${BUS_DIR}/activation.h				
+	${BUS_DIR}/bus.c					
+	${BUS_DIR}/bus.h					
+	${BUS_DIR}/config-parser.c				
+	${BUS_DIR}/config-parser.h
+    ${BUS_DIR}/config-parser-common.c
+    ${BUS_DIR}/config-parser-common.h
+#    ${BUS_DIR}/config-parser-trivial.c
+	${BUS_DIR}/connection.c
+	${BUS_DIR}/connection.h				
+	${BUS_DIR}/desktop-file.c				
+	${BUS_DIR}/desktop-file.h				
+	${BUS_DIR}/dir-watch-default.c				
+	${BUS_DIR}/dir-watch.h				
+	${BUS_DIR}/dispatch.c				
+	${BUS_DIR}/dispatch.h				
+	${BUS_DIR}/driver.c				
+	${BUS_DIR}/driver.h				
+	${BUS_DIR}/expirelist.c				
+	${BUS_DIR}/expirelist.h				
+	${BUS_DIR}/policy.c				
+	${BUS_DIR}/policy.h				
+	${BUS_DIR}/selinux.h				
+	${BUS_DIR}/selinux.c				
+	${BUS_DIR}/services.c				
+	${BUS_DIR}/services.h				
+	${BUS_DIR}/signals.c				
+	${BUS_DIR}/signals.h				
+	${BUS_DIR}/test.c					
+	${BUS_DIR}/test.h					
+	${BUS_DIR}/utils.c					
+	${BUS_DIR}/utils.h					
+	${XML_SOURCES}
+	${DIR_WATCH_SOURCE}
+)
+if(DBUS_ENABLE_STATS)
+	list(APPEND BUS_SOURCES
+		${BUS_DIR}/stats.c
+		${BUS_DIR}/stats.h
+	)
+endif()
+
+include_directories(${XML_INCLUDE_DIR})
+
+add_executable(dbus-daemon ${BUS_SOURCES} ${BUS_DIR}/main.c)
+target_link_libraries(dbus-daemon ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY})
+set_target_properties(dbus-daemon PROPERTIES OUTPUT_NAME ${DBUS_DAEMON_NAME})
+set_target_properties(dbus-daemon PROPERTIES COMPILE_FLAGS ${DBUS_INTERNAL_CLIENT_DEFINITIONS})
+
+install_targets(/bin dbus-daemon)
+install_files(/etc/dbus-1 FILES ${config_DATA})
+install(DIRECTORY .  DESTINATION etc/dbus-1/session.d  FILES_MATCHING PATTERN "*.conf")
+
+if (DBUS_SERVICE)
+	set (dbus_service_SOURCES 
+		${BUS_DIR}/bus-service-win.c
+	# TODO: add additional files
+	#	${BUS_DIR}/service-main.c
+	#	${BUS_SOURCES} 
+	)
+
+	add_executable(dbus-service ${dbus_service_SOURCES} )
+	target_link_libraries(dbus-service ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY})
+	set_target_properties(dbus-service PROPERTIES COMPILE_FLAGS ${DBUS_INTERNAL_CLIENT_DEFINITIONS})
+	install_targets(/bin dbus-service )
+endif (DBUS_SERVICE)
+
+if (DBUS_BUILD_TESTS)	
+	add_executable(bus-test ${BUS_SOURCES} ${BUS_DIR}/test-main.c)
+	target_link_libraries(bus-test ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY})
+	set_target_properties(bus-test PROPERTIES COMPILE_FLAGS ${DBUS_INTERNAL_CLIENT_DEFINITIONS})
+	add_test(bus-test ${EXECUTABLE_OUTPUT_PATH}/bus-test ${CMAKE_BINARY_DIR}/test/data)
+endif (DBUS_BUILD_TESTS)
+
+if(MSVC)
+	project_source_group(${GROUP_CODE} bus_test_SOURCES dummy)
+endif(MSVC)
+
+## mop up the gcov files
+#clean-local:
+#	/bin/rm *.bb *.bbg *.da *.gcov || true
+
+#install-data-hook:
+#	$(mkinstalldirs) $(DESTDIR)/$(localstatedir)/run/dbus
+#	$(mkinstalldirs) $(DESTDIR)/$(configdir)/system.d
+#	$(mkinstalldirs) $(DESTDIR)/$(datadir)/dbus-1/services
+
+##install_file(${configdir}/system.d FILE
+
+
+set(LAUNCH_HELPER_SOURCES ${XML_SOURCES}
+    ${BUS_DIR}/config-parser-common.c
+    ${BUS_DIR}/config-parser-trivial.c
+    ${BUS_DIR}/desktop-file.c
+    ${BUS_DIR}/utils.c
+    ${BUS_DIR}/activation-helper.c
+
+)
+
+if(NOT WIN32)
+# TODO PENDING(kdab) fix build on windows (activation-helper.c)
+   add_executable(dbus-daemon-launch-helper ${LAUNCH_HELPER_SOURCES} ${BUS_DIR}/activation-helper-bin.c )
+   target_link_libraries(dbus-daemon-launch-helper ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY} )
+   
+   add_executable(dbus-daemon-launch-helper-test ${LAUNCH_HELPER_SOURCES}     ${BUS_DIR}/activation-helper-bin.c)
+   set_target_properties(dbus-daemon-launch-helper-test PROPERTIES COMPILE_FLAGS "-DACTIVATION_LAUNCHER_TEST")
+   target_link_libraries(dbus-daemon-launch-helper-test ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY} )
+   
+   add_executable(bus-test-launch-helper ${LAUNCH_HELPER_SOURCES}  ${BUS_DIR}/test-launch-helper.c)
+   set_target_properties(bus-test-launch-helper PROPERTIES COMPILE_FLAGS "-DACTIVATION_LAUNCHER_TEST -DACTIVATION_LAUNCHER_DO_OOM")
+   target_link_libraries(bus-test-launch-helper ${DBUS_INTERNAL_LIBRARIES} ${XML_LIBRARY} )
+   add_test(bus-test-launch-helper ${EXECUTABLE_OUTPUT_PATH}/bus-test-launch-helper )
+
+endif(NOT WIN32)
+
+#### Init scripts fun
+#SCRIPT_IN_FILES=messagebus.in
+#		rc.messagebus.in
+
+## Red Hat start
+#if DBUS_INIT_SCRIPTS_RED_HAT
+
+#initddir=$(sysconfdir)/rc.d/init.d
+
+#initd_SCRIPTS= 	
+#	messagebus
+
+#endif
+# ## Red Hat end
+
+## Slackware start
+#if DBUS_INIT_SCRIPTS_SLACKWARE
+
+#initddir=$(sysconfdir)/rc.d/
+
+#initd_SCRIPTS= 	
+#	rc.messagebus
+
+#endif
+## Slackware end
+
+#MAN_IN_FILES=dbus-daemon.1.in
+#man_MANS = dbus-daemon.1
+
+#### Extra dist 
+
+#EXTRA_DIST=$(CONFIG_IN_FILES) $(SCRIPT_IN_FILES) $(man_MANS) $(MAN_IN_FILES)
diff --git a/dbus/cmake/bus/dbus-daemon.xml b/dbus/cmake/bus/dbus-daemon.xml
new file mode 100644
index 0000000..f331699
--- /dev/null
+++ b/dbus/cmake/bus/dbus-daemon.xml
@@ -0,0 +1,752 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<!-- lifted from troff+man by doclifter -->
+<refentry id='dbus-daemon'>
+<!--   -->
+<!--  dbus\-daemon manual page. -->
+<!--  Copyright (C) 2003 Red Hat, Inc. -->
+
+<refmeta>
+<refentrytitle>dbus-daemon</refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+<refnamediv id='name'>
+<refname>dbus-daemon</refname>
+<refpurpose>Message bus daemon</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv id='synopsis'>
+<cmdsynopsis>
+  <command>dbus-daemon</command></cmdsynopsis>
+<cmdsynopsis>
+  <command>dbus-daemon</command>    <arg choice='opt'>--version </arg>
+    <arg choice='opt'>--session </arg>
+    <arg choice='opt'>--system </arg>
+    <arg choice='opt'>--config-file=<replaceable>FILE</replaceable></arg>
+    <arg choice='opt'><arg choice='plain'>--print-address </arg><arg choice='opt'><replaceable>=DESCRIPTOR</replaceable></arg></arg>
+    <arg choice='opt'><arg choice='plain'>--print-pid </arg><arg choice='opt'><replaceable>=DESCRIPTOR</replaceable></arg></arg>
+    <arg choice='opt'>--fork </arg>
+    <sbr/>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1 id='description'><title>DESCRIPTION</title>
+<para><command>dbus-daemon</command> is the D-Bus message bus daemon. See
+<ulink url='http://www.freedesktop.org/software/dbus/'>http://www.freedesktop.org/software/dbus/</ulink> for more information about
+the big picture. D-Bus is first a library that provides one-to-one
+communication between any two applications; <command>dbus-daemon</command> is an
+application that uses this library to implement a message bus
+daemon. Multiple programs connect to the message bus daemon and can
+exchange messages with one another.</para>
+
+
+<para>There are two standard message bus instances: the systemwide message bus 
+(installed on many systems as the "messagebus" init service) and the 
+per-user-login-session message bus (started each time a user logs in).
+<command>dbus-daemon</command> is used for both of these instances, but with 
+a different configuration file.</para>
+
+
+<para>The --session option is equivalent to
+"--config-file=/etc/dbus-1/session.conf" and the --system
+option is equivalent to
+"--config-file=/etc/dbus-1/system.conf". By creating 
+additional configuration files and using the --config-file option,
+additional special-purpose message bus daemons could be created.</para>
+
+
+<para>The systemwide daemon is normally launched by an init script, 
+standardly called simply "messagebus".</para> 
+
+
+<para>The systemwide daemon is largely used for broadcasting system events, 
+such as changes to the printer queue, or adding/removing devices.</para>
+
+
+<para>The per-session daemon is used for various interprocess communication 
+among desktop applications (however, it is not tied to X or the GUI 
+in any way).</para>
+
+
+<para>SIGHUP will cause the D-Bus daemon to PARTIALLY reload its
+configuration file and to flush its user/group information caches. Some
+configuration changes would require kicking all apps off the bus; so they will
+only take effect if you restart the daemon. Policy changes should take effect
+with SIGHUP.</para>
+
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<para>The following options are supported:</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>--config-file=FILE</option></term>
+  <listitem>
+<para>Use the given configuration file.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--fork</option></term>
+  <listitem>
+<para>Force the message bus to fork and become a daemon, even if 
+the configuration file does not specify that it should.
+In most contexts the configuration file already gets this
+right, though.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--print-address[=DESCRIPTOR]</option></term>
+  <listitem>
+<para>Print the address of the message bus to standard output, or 
+to the given file descriptor. This is used by programs that 
+launch the message bus.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--print-pid[=DESCRIPTOR]</option></term>
+  <listitem>
+<para>Print the process ID of the message bus to standard output, or 
+to the given file descriptor. This is used by programs that 
+launch the message bus.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--session</option></term>
+  <listitem>
+<para>Use the standard configuration file for the per-login-session message
+bus.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--system</option></term>
+  <listitem>
+<para>Use the standard configuration file for the systemwide message bus.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--version</option></term>
+  <listitem>
+<para>Print the version of the daemon.</para>
+
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='configuration_file'><title>CONFIGURATION FILE</title>
+<para>A message bus daemon has a configuration file that specializes it
+for a particular application. For example, one configuration 
+file might set up the message bus to be a systemwide message bus, 
+while another might set it up to be a per-user-login-session bus.</para>
+
+
+<para>The configuration file also establishes resource limits, security
+parameters, and so forth.</para>
+
+
+<para>The configuration file is not part of any interoperability
+specification and its backward compatibility is not guaranteed; this
+document is documentation, not specification.</para>
+
+
+<para>The standard systemwide and per-session message bus setups are
+configured in the files "/etc/dbus-1/system.conf" and
+"/etc/dbus-1/session.conf".  These files normally
+&lt;include&gt; a system-local.conf or session-local.conf; you can put local
+overrides in those files to avoid modifying the primary configuration
+files.</para>
+
+
+<para>The configuration file is an XML document. It must have the following
+doctype declaration:</para>
+<literallayout remap='.nf'>
+
+   &lt;!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+    "<ulink url='http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd'>http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd</ulink>"&gt;
+
+</literallayout> <!-- .fi -->
+
+
+<para>The following elements may be present in the configuration file.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;busconfig&gt;</emphasis></term>
+  <listitem>
+<para></para> 
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>Root element.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;type&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>The well-known type of the message bus. Currently known values are
+"system" and "session"; if other values are set, they should be
+either added to the D-Bus specification, or namespaced.  The last
+&lt;type&gt; element "wins" (previous values are ignored).</para>
+
+
+<para>Example: &lt;type&gt;session&lt;/type&gt;</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;include&gt;</emphasis></term>
+  <listitem>
+<para></para> 
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>Include a file &lt;include&gt;filename.conf&lt;/include&gt; at this point.  If the
+filename is relative, it is located relative to the configuration file
+doing the including.</para>
+
+
+<para>&lt;include&gt; has an optional attribute "ignore_missing=(yes|no)"
+which defaults to "no" if not provided. This attribute 
+controls whether it's a fatal error for the included file 
+to be absent.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;includedir&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>Include all files in &lt;includedir&gt;foo.d&lt;/includedir&gt; at this
+point. Files in the directory are included in undefined order.
+Only files ending in ".conf" are included.</para>
+
+
+<para>This is intended to allow extension of the system bus by particular
+packages. For example, if CUPS wants to be able to send out
+notification of printer queue changes, it could install a file to
+/etc/dbus-1/system.d that allowed all apps to receive
+this message and allowed the printer daemon user to send it.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;user&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>The user account the daemon should run as, as either a username or a
+UID. If the daemon cannot change to this UID on startup, it will exit.
+If this element is not present, the daemon will not change or care
+about its UID.</para>
+
+
+<para>The last &lt;user&gt; entry in the file "wins", the others are ignored.</para>
+
+
+<para>The user is changed after the bus has completed initialization.  So
+sockets etc. will be created before changing user, but no data will be
+read from clients before changing user. This means that sockets 
+and PID files can be created in a location that requires root 
+privileges for writing.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;fork&gt;</emphasis></term>
+  <listitem>
+<para></para>    
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>If present, the bus daemon becomes a real daemon (forks 
+into the background, etc.). This is generally used 
+rather than the --fork command line option.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;listen&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>Add an address that the bus should listen on. The 
+address is in the standard D-Bus format that contains 
+a transport name plus possible parameters/options.</para>
+
+
+<para>Example: &lt;listen&gt;unix:path=/tmp/foo&lt;/listen&gt;</para>
+
+
+<para>If there are multiple &lt;listen&gt; elements, then the bus listens 
+on multiple addresses. The bus will pass its address to 
+started services or other interested parties with 
+the last address given in &lt;listen&gt; first. That is, 
+apps will try to connect to the last &lt;listen&gt; address first.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;auth&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>Lists permitted authorization mechanisms. If this element doesn't
+exist, then all known mechanisms are allowed.  If there are multiple
+&lt;auth&gt; elements, all the listed mechanisms are allowed.  The order in
+which mechanisms are listed is not meaningful.</para>
+    
+
+<para>Example: &lt;auth&gt;EXTERNAL&lt;/auth&gt;</para>
+
+
+<para>Example: &lt;auth&gt;DBUS_COOKIE_SHA1&lt;/auth&gt;</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;servicedir&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>Adds a directory to scan for .service files. Directories are
+scanned starting with the last to appear in the config file 
+(the first .service file found that provides a particular 
+service will be used).</para>
+
+
+<para>Service files tell the bus how to automatically start a program.
+They are primarily used with the per-user-session bus, 
+not the systemwide bus.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;standard_session_servicedirs/&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>&lt;standard_session_servicedirs/&gt; is equivalent to specifying a series
+of &lt;servicedir/&gt; elements for each of the data directories in the "XDG
+Base Directory Specification" with the subdirectory "dbus-1/services",
+so for example "/usr/share/dbus-1/services" would be among the
+directories searched.</para>
+
+
+<para>The "XDG Base Directory Specification" can be found at
+<ulink url='http://freedesktop.org/wiki/Standards/basedir-spec'>http://freedesktop.org/wiki/Standards/basedir-spec</ulink> if it hasn't moved,
+otherwise try your favorite search engine.</para>
+
+
+<para>The &lt;standard_session_servicedirs/&gt; option is only relevant to the
+per-user-session bus daemon defined in
+/etc/dbus-1/session.conf. Putting it in any other
+configuration file would probably be nonsense.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;limit&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>&lt;limit&gt; establishes a resource limit. For example:</para>
+<literallayout remap='.nf'>
+  &lt;limit name="max_message_size"&gt;64&lt;/limit&gt;
+  &lt;limit name="max_completed_connections"&gt;512&lt;/limit&gt;
+</literallayout> <!-- .fi -->
+
+
+<para>The name attribute is mandatory.
+Available limit names are:</para>
+<literallayout remap='.nf'>
+      "max_incoming_bytes"         : total size in bytes of messages
+                                     incoming from a single connection
+      "max_outgoing_bytes"         : total size in bytes of messages
+                                     queued up for a single connection
+      "max_message_size"           : max size of a single message in
+                                     bytes
+      "service_start_timeout"      : milliseconds (thousandths) until 
+                                     a started service has to connect
+      "auth_timeout"               : milliseconds (thousandths) a
+                                     connection is given to
+                                     authenticate
+      "max_completed_connections"  : max number of authenticated connections  
+      "max_incomplete_connections" : max number of unauthenticated
+                                     connections
+      "max_connections_per_user"   : max number of completed connections from
+                                     the same user
+      "max_pending_service_starts" : max number of service launches in
+                                     progress at the same time
+      "max_names_per_connection"   : max number of names a single 
+                                     connection can own
+      "max_match_rules_per_connection": max number of match rules for a single 
+                                        connection
+      "max_replies_per_connection" : max number of pending method 
+                                     replies per connection
+                                     (number of calls-in-progress)
+      "reply_timeout"              : milliseconds (thousandths) 
+                                     until a method call times out   
+</literallayout> <!-- .fi -->
+
+
+<para>The max incoming/outgoing queue sizes allow a new message to be queued
+if one byte remains below the max. So you can in fact exceed the max
+by max_message_size.</para>
+
+
+<para>max_completed_connections divided by max_connections_per_user is the
+number of users that can work together to denial-of-service all other users by using
+up all connections on the systemwide bus.</para>
+
+
+<para>Limits are normally only of interest on the systemwide bus, not the user session 
+buses.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;policy&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>The &lt;policy&gt; element defines a security policy to be applied to a particular
+set of connections to the bus. A policy is made up of
+&lt;allow&gt; and &lt;deny&gt; elements. Policies are normally used with the systemwide bus;
+they are analogous to a firewall in that they allow expected traffic 
+and prevent unexpected traffic.</para>
+
+
+<para>The &lt;policy&gt; element has one of three attributes:</para>
+<literallayout remap='.nf'>
+  context="(default|mandatory)"
+  user="username or userid"
+  group="group name or gid"
+</literallayout> <!-- .fi -->
+
+
+<para> 
+Policies are applied to a connection as follows:</para>
+<literallayout remap='.nf'>
+   - all context="default" policies are applied
+   - all group="connection's user's group" policies are applied
+     in undefined order
+   - all user="connection's auth user" policies are applied
+     in undefined order
+   - all context="mandatory" policies are applied
+</literallayout> <!-- .fi -->
+
+
+<para>Policies applied later will override those applied earlier, 
+when the policies overlap. Multiple policies with the same 
+user/group/context are applied in the order they appear 
+in the config file.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;deny&gt;</emphasis></term>
+  <listitem>
+<para><emphasis remap='I'>&lt;allow&gt;</emphasis></para>
+
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>A &lt;deny&gt; element appears below a &lt;policy&gt; element and prohibits some
+action. The &lt;allow&gt; element makes an exception to previous &lt;deny&gt;
+statements, and works just like &lt;deny&gt; but with the inverse meaning.</para>
+
+
+<para>The possible attributes of these elements are:</para>
+<literallayout remap='.nf'>
+   send_interface="interface_name"
+   send_member="method_or_signal_name" 
+   send_error="error_name" 
+   send_destination="name" 
+   send_type="method_call" | "method_return" | "signal" | "error" 
+   send_path="/path/name"
+
+   receive_interface="interface_name"
+   receive_member="method_or_signal_name" 
+   receive_error="error_name" 
+   receive_sender="name" 
+   receive_type="method_call" | "method_return" | "signal" | "error"
+   receive_path="/path/name"
+
+   send_requested_reply="true" | "false"
+   receive_requested_reply="true" | "false"
+
+   eavesdrop="true" | "false"
+
+   own="name"
+   own_prefix="name"
+   user="username"
+   group="groupname"
+</literallayout> <!-- .fi -->
+
+
+<para>Examples:</para>
+<literallayout remap='.nf'>
+   &lt;deny send_interface="org.freedesktop.System" send_member="Reboot"/&gt; 
+   &lt;deny receive_interface="org.freedesktop.System" receive_member="Reboot"/&gt;
+   &lt;deny own="org.freedesktop.System"/&gt;
+   &lt;deny send_destination="org.freedesktop.System"/&gt;
+   &lt;deny receive_sender="org.freedesktop.System"/&gt;
+   &lt;deny user="john"/&gt;
+   &lt;deny group="enemies"/&gt;
+</literallayout> <!-- .fi -->
+
+
+<para>The &lt;deny&gt; element's attributes determine whether the deny "matches" a
+particular action. If it matches, the action is denied (unless later
+rules in the config file allow it).</para>
+
+
+<para>send_destination and receive_sender rules mean that messages may not be
+sent to or received from the *owner* of the given name, not that
+they may not be sent *to that name*. That is, if a connection
+owns services A, B, C, and sending to A is denied, sending to B or C
+will not work either.</para>
+
+
+<para>The other send_* and receive_* attributes are purely textual/by-value
+matches against the given field in the message header.</para>
+
+
+<para>"Eavesdropping" occurs when an application receives a message that
+was explicitly addressed to a name the application does not own.
+Eavesdropping thus only applies to messages that are addressed to
+services (i.e. it does not apply to signals).</para>
+
+
+<para>For &lt;allow&gt;, eavesdrop="true" indicates that the rule matches even 
+when eavesdropping. eavesdrop="false" is the default and means that 
+the rule only allows messages to go to their specified recipient.
+For &lt;deny&gt;, eavesdrop="true" indicates that the rule matches 
+only when eavesdropping. eavesdrop="false" is the default for &lt;deny&gt;
+also, but here it means that the rule applies always, even when 
+not eavesdropping. The eavesdrop attribute can only be combined with
+receive rules (with receive_* attributes).</para>
+
+
+
+<para>The [send|receive]_requested_reply attribute works similarly to the eavesdrop
+attribute. It controls whether the &lt;deny&gt; or &lt;allow&gt; matches a reply
+that is expected (corresponds to a previous method call message).
+This attribute only makes sense for reply messages (errors and method
+returns), and is ignored for other message types.</para>
+
+
+<para>For &lt;allow&gt;, [send|receive]_requested_reply="true" is the default and indicates that
+only requested replies are allowed by the
+rule. [send|receive]_requested_reply="false" means that the rule allows any reply
+even if unexpected.</para>
+
+
+<para>For &lt;deny&gt;, [send|receive]_requested_reply="false" is the default but indicates that
+the rule matches only when the reply was not
+requested. [send|receive]_requested_reply="true" indicates that the rule applies
+always, regardless of pending reply state.</para>
+
+
+<para>user and group denials mean that the given user or group may 
+not connect to the message bus.</para>
+
+
+<para>For "name", "username", "groupname", etc.
+the character "*" can be substituted, meaning "any." Complex globs
+like "foo.bar.*" aren't allowed for now because they'd be work to
+implement and maybe encourage sloppy security anyway.</para>
+
+<para>&lt;allow own_prefix="a.b"/&gt; allows you to own the name "a.b" or any
+name whose first dot-separated elements are "a.b": in particular,
+you can own "a.b.c" or "a.b.c.d", but not "a.bc" or "a.c".
+This is useful when services like Telepathy and ReserveDevice
+define a meaning for subtrees of well-known names, such as
+org.freedesktop.Telepathy.ConnectionManager.(anything)
+and org.freedesktop.ReserveDevice1.(anything).</para>
+
+<para>It does not make sense to deny a user or group inside a &lt;policy&gt;
+for a user or group; user/group denials can only be inside
+context="default" or context="mandatory" policies.</para>
+
+
+<para>A single &lt;deny&gt; rule may specify combinations of attributes such as
+send_destination and send_interface and send_type. In this case, the
+denial applies only if both attributes match the message being denied.
+e.g. &lt;deny send_interface="foo.bar" send_destination="foo.blah"/&gt; would
+deny messages with the given interface AND the given bus name.
+To get an OR effect you specify multiple &lt;deny&gt; rules.</para>
+
+
+<para>You can't include both send_ and receive_ attributes on the same
+rule, since "whether the message can be sent" and "whether it can be
+received" are evaluated separately.</para>
+
+
+<para>Be careful with send_interface/receive_interface, because the 
+interface field in messages is optional.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;selinux&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>The &lt;selinux&gt; element contains settings related to Security Enhanced Linux.
+More details below.</para>
+
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><emphasis remap='I'>&lt;associate&gt;</emphasis></term>
+  <listitem>
+
+<para></para> <!-- FIXME: blank list item -->
+  </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>An &lt;associate&gt; element appears below an &lt;selinux&gt; element and
+creates a mapping. Right now only one kind of association is possible:</para>
+<literallayout remap='.nf'>
+   &lt;associate own="org.freedesktop.Foobar" context="foo_t"/&gt; 
+</literallayout> <!-- .fi -->
+
+
+<para>This means that if a connection asks to own the name
+"org.freedesktop.Foobar" then the source context will be the context
+of the connection and the target context will be "foo_t" - see the 
+short discussion of SELinux below.</para>
+
+
+<para>Note, the context here is the target context when requesting a name,
+NOT the context of the connection owning the name.</para>
+
+
+<para>There's currently no way to set a default for owning any name, if
+we add this syntax it will look like:</para>
+<literallayout remap='.nf'>
+   &lt;associate own="*" context="foo_t"/&gt; 
+</literallayout> <!-- .fi -->
+<para>If you find a reason this is useful, let the developers know.
+Right now the default will be the security context of the bus itself.</para>
+
+
+<para>If two &lt;associate&gt; elements specify the same name, the element
+appearing later in the configuration file will be used.</para>
+
+</refsect1>
+
+<refsect1 id='selinux'><title>SELinux</title>
+<para>See <ulink url='http://www.nsa.gov/selinux/'>http://www.nsa.gov/selinux/</ulink> for full details on SELinux. Some useful excerpts:</para>
+
+
+<para>Every subject (process) and object (e.g. file, socket, IPC object,
+etc) in the system is assigned a collection of security attributes,
+known as a security context. A security context contains all of the
+security attributes associated with a particular subject or object
+that are relevant to the security policy.</para>
+
+
+<para>In order to better encapsulate security contexts and to provide
+greater efficiency, the policy enforcement code of SELinux typically
+handles security identifiers (SIDs) rather than security contexts. A
+SID is an integer that is mapped by the security server to a security
+context at runtime.</para>
+
+
+<para>When a security decision is required, the policy enforcement code
+passes a pair of SIDs (typically the SID of a subject and the SID of
+an object, but sometimes a pair of subject SIDs or a pair of object
+SIDs), and an object security class to the security server. The object
+security class indicates the kind of object, e.g. a process, a regular
+file, a directory, a TCP socket, etc.</para>
+
+
+<para>Access decisions specify whether or not a permission is granted for a
+given pair of SIDs and class. Each object class has a set of
+associated permissions defined to control operations on objects with
+that class.</para>
+
+
+<para>D-Bus performs SELinux security checks in two places.</para>
+
+
+<para>First, any time a message is routed from one connection to another
+connection, the bus daemon will check permissions with the security context of
+the first connection as source, security context of the second connection
+as target, object class "dbus" and requested permission "send_msg".</para>
+
+
+<para>If a security context is not available for a connection 
+(impossible when using UNIX domain sockets), then the target 
+context used is the context of the bus daemon itself.
+There is currently no way to change this default, because we're 
+assuming that only UNIX domain sockets will be used to 
+connect to the systemwide bus. If this changes, we'll 
+probably add a way to set the default connection context.</para>
+
+
+<para>Second, any time a connection asks to own a name, 
+the bus daemon will check permissions with the security 
+context of the connection as source, the security context specified
+for the name in the config file as target, object 
+class "dbus" and requested permission "acquire_svc".</para>
+
+
+<para>The security context for a bus name is specified with the 
+&lt;associate&gt; element described earlier in this document.
+If a name has no security context associated in the 
+configuration file, the security context of the bus daemon 
+itself will be used.</para>
+
+</refsect1>
+
+<refsect1 id='author'><title>AUTHOR</title>
+<para>See <ulink url='http://www.freedesktop.org/software/dbus/doc/AUTHORS'>http://www.freedesktop.org/software/dbus/doc/AUTHORS</ulink></para>
+
+</refsect1>
+
+<refsect1 id='bugs'><title>BUGS</title>
+<para>Please send bug reports to the D-Bus mailing list or bug tracker,
+see <ulink url='http://www.freedesktop.org/software/dbus/'>http://www.freedesktop.org/software/dbus/</ulink></para>
+</refsect1>
+</refentry>
+
diff --git a/dbus/cmake/bus/service.cmake b/dbus/cmake/bus/service.cmake
new file mode 100644
index 0000000..25d17ff
--- /dev/null
+++ b/dbus/cmake/bus/service.cmake
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedektop.DBus.ServiceName
+Exec=notepad
diff --git a/dbus/cmake/bus/system.conf.cmake b/dbus/cmake/bus/system.conf.cmake
new file mode 100644
index 0000000..ee85ecc
--- /dev/null
+++ b/dbus/cmake/bus/system.conf.cmake
@@ -0,0 +1,62 @@
+<!-- This configuration file controls the systemwide message bus.
+     Add a system-local.conf and edit that rather than changing this 
+     file directly. -->
+
+<!-- Note that there are any number of ways you can hose yourself
+     security-wise by screwing up this file; in particular, you
+     probably don't want to listen on any more addresses, add any more
+     auth mechanisms, run as a different user, etc. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+  <!-- Our well-known bus type, do not change this -->
+  <type>system</type>
+
+  <!-- Run as special user -->
+  <user>@DBUS_USER@</user>
+
+  <!-- Fork into daemon mode -->
+  <fork/>
+
+  <!-- Write a pid file -->
+  <pidfile>@DBUS_SYSTEM_PID_FILE@</pidfile>
+
+  <!-- Only allow socket-credentials-based authentication -->
+  <auth>EXTERNAL</auth>
+
+  <!-- Only listen on a local socket. (abstract=/path/to/socket 
+       means use abstract namespace, don't really create filesystem 
+       file; only Linux supports this. Use path=/whatever on other 
+       systems.) -->
+  <listen>@DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@</listen>
+
+  <policy context="default">
+    <!-- Deny everything then punch holes -->
+    <deny send_interface="*"/>
+    <deny receive_interface="*"/>
+    <deny own="*"/>
+    <!-- But allow all users to connect -->
+    <allow user="*"/>
+    <!-- Allow anyone to talk to the message bus -->
+    <!-- FIXME I think currently these allow rules are always implicit 
+         even if they aren't in here -->
+    <allow send_destination="org.freedesktop.DBus"/>
+    <allow receive_sender="org.freedesktop.DBus"/>
+    <!-- valid replies are always allowed -->
+    <allow send_requested_reply="true"/>
+    <allow receive_requested_reply="true"/>
+  </policy>
+
+  <!-- Config files are placed here that among other things, punch 
+       holes in the above policy for specific services. -->
+  <includedir>system.d</includedir>
+
+  <!-- This is included last so local configuration can override what's 
+       in this standard file -->
+  <include ignore_missing="yes">system-local.conf</include>
+
+  <include if_selinux_enabled="yes" selinux_root_relative="yes">contexts/dbus_contexts</include>
+
+</busconfig>
diff --git a/dbus/cmake/config.h.cmake b/dbus/cmake/config.h.cmake
new file mode 100644
index 0000000..6221c19
--- /dev/null
+++ b/dbus/cmake/config.h.cmake
@@ -0,0 +1,252 @@
+/* config.h. Generated by cmake from config.h.cmake */
+
+#ifndef _DBUS_CONFIG_H
+#define _DBUS_CONFIG_H
+/****************************/
+/* indicate that we are building with cmake */
+#define DBUS_CMAKE 1
+
+#cmakedefine HAVE_GNUC_VARARGS 1
+
+#cmakedefine DBUS_CONSOLE_AUTH_DIR "@DBUS_CONSOLE_AUTH_DIR@"
+#cmakedefine DBUS_DATADIR  "@DBUS_DATADIR@"
+#cmakedefine DBUS_BINDIR   "@DBUS_BINDIR@"
+#cmakedefine DBUS_SYSTEM_CONFIG_FILE  "@DBUS_SYSTEM_CONFIG_FILE@"
+#cmakedefine DBUS_SESSION_CONFIG_FILE "@DBUS_SESSION_CONFIG_FILE@"
+#cmakedefine DBUS_DAEMON_NAME "@DBUS_DAEMON_NAME@"
+#cmakedefine DBUS_SYSTEM_BUS_DEFAULT_ADDRESS  "@DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@"
+#cmakedefine DBUS_MACHINE_UUID_FILE "@DBUS_MACHINE_UUID_FILE@"
+#cmakedefine DBUS_SESSION_BUS_DEFAULT_ADDRESS "@DBUS_SESSION_BUS_DEFAULT_ADDRESS@"
+#cmakedefine DBUS_DAEMONDIR "@DBUS_DAEMONDIR@"
+#cmakedefine PACKAGE "@PACKAGE@"
+/* Version number of package */
+#cmakedefine DBUS_MAJOR_VERSION @DBUS_MAJOR_VERSION@
+#cmakedefine DBUS_MINOR_VERSION @DBUS_MINOR_VERSION@
+#cmakedefine DBUS_MICRO_VERSION @DBUS_MICRO_VERSION@
+#cmakedefine DBUS_VERSION ((@DBUS_MAJOR_VERSION@ << 16) | (@DBUS_MINOR_VERSION@ << 8) | (@DBUS_MICRO_VERSION@))
+#cmakedefine DBUS_VERSION_STRING "@DBUS_VERSION_STRING@"
+#cmakedefine DBUS_ENABLE_STATS
+
+#define VERSION DBUS_VERSION_STRING
+
+#define TEST_LISTEN       "@TEST_LISTEN@"
+
+// test binaries
+#define DBUS_TEST_EXEC "@DBUS_TEST_EXEC@"
+#define DBUS_EXEEXT "@EXEEXT@"
+
+/* Full path to test file test/test-exit in builddir */
+#define TEST_BUS_BINARY          "@TEST_BUS_BINARY@"
+
+/* Some dbus features */
+#cmakedefine DBUS_BUILD_TESTS 1
+#cmakedefine DBUS_ENABLE_ANSI 1
+#cmakedefine DBUS_ENABLE_VERBOSE_MODE 1
+#cmakedefine DBUS_DISABLE_ASSERTS 1
+#cmakedefine DBUS_DISABLE_CHECKS 1
+/* xmldocs */
+/* doxygen */
+#cmakedefine DBUS_GCOV_ENABLED 1
+
+/* abstract-sockets */
+
+#cmakedefine HAVE_ABSTRACT_SOCKETS 1
+
+#cmakedefine DBUS_PATH_OR_ABSTRACT_VALUE 1
+
+#if (defined DBUS_PATH_OR_ABSTRACT_VALUE)
+#define DBUS_PATH_OR_ABSTRACT @DBUS_PATH_OR_ABSTRACT_VALUE@
+#endif
+
+#ifdef DBUS_PATH_OR_ABSTRACT_VALUE
+#undef DBUS_PATH_OR_ABSTRACT_VALUE
+#endif
+
+/* selinux */
+#cmakedefine DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX 1
+/* kqueue */
+#cmakedefine HAVE_CONSOLE_OWNER_FILE 1
+#define DBUS_CONSOLE_OWNER_FILE "@DBUS_CONSOLE_OWNER_FILE@"
+
+#cmakedefine DBUS_HAVE_ATOMIC_INT 1
+#cmakedefine DBUS_USE_ATOMIC_INT_486 1
+#if (defined(__i386__) || defined(__x86_64__))
+# define DBUS_HAVE_ATOMIC_INT 1
+# define DBUS_USE_ATOMIC_INT_486 1
+#endif
+
+#cmakedefine DBUS_BUILD_X11 1
+/* For the moment, the cmake build system doesn't have an equivalent of
+ * the autoconf build system's --disable-x11-autolaunch */
+#ifdef DBUS_BUILD_X11
+# define DBUS_ENABLE_X11_AUTOLAUNCH 1
+#endif
+
+#define _DBUS_VA_COPY_ASSIGN(a1,a2) { a1 = a2; }
+
+#cmakedefine DBUS_VA_COPY_FUNC
+#if (defined DBUS_VA_COPY_FUNC)
+# define DBUS_VA_COPY @DBUS_VA_COPY_FUNC@
+#endif
+
+#ifdef DBUS_VA_COPY_FUNC
+#undef DBUS_VA_COPY_FUNC
+#endif
+
+#cmakedefine DBUS_VA_COPY_AS_ARRAY @DBUS_VA_COPY_AS_ARRAY@
+
+// headers
+/* Define to 1 if you have dirent.h */
+#cmakedefine   HAVE_DIRENT_H 1
+
+/* Define to 1 if you have io.h */
+#cmakedefine   HAVE_IO_H 1
+
+/* Define to 1 if you have grp.h */
+#cmakedefine   HAVE_GRP_H 1
+
+/* Define to 1 if you have sys/poll.h */
+#cmakedefine    HAVE_POLL 1
+
+/* Define to 1 if you have sys/time.h */
+#cmakedefine    HAVE_SYS_TIME 1
+
+/* Define to 1 if you have sys/wait.h */
+#cmakedefine    HAVE_SYS_WAIT 1
+
+/* Define to 1 if you have time.h */
+#cmakedefine   HAVE_TIME_H 1
+
+/* Define to 1 if you have ws2tcpip.h */
+#cmakedefine   HAVE_WS2TCPIP_H
+
+/* Define to 1 if you have wspiapi.h */
+#cmakedefine   HAVE_WSPIAPI_H 1
+
+/* Define to 1 if you have unistd.h */
+#cmakedefine   HAVE_UNISTD_H 1
+
+/* Define to 1 if you have stdio.h */
+#cmakedefine   HAVE_STDIO_H 1
+
+/* Define to 1 if you have sys/syslimits.h */
+#cmakedefine   HAVE_SYS_SYSLIMITS_H 1
+
+/* Define to 1 if you have errno.h */
+#cmakedefine   HAVE_ERRNO_H 1
+
+/* Define to 1 if you have signal.h */
+#cmakedefine   HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have locale.h */
+#cmakedefine   HAVE_LOCALE_H 1
+
+/* Define to 1 if you have inttypes.h */
+#cmakedefine   HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have stdint.h */
+#cmakedefine   HAVE_STDINT_H 1
+
+// symbols
+/* Define to 1 if you have backtrace */
+#cmakedefine   HAVE_BACKTRACE 1
+
+/* Define to 1 if you have getgrouplist */
+#cmakedefine   HAVE_GETGROUPLIST 1
+
+/* Define to 1 if you have getpeerucred */
+#cmakedefine   HAVE_GETPEERUCRED 1
+
+/* Define to 1 if you have nanosleep */
+#cmakedefine   HAVE_NANOSLEEP 1
+
+/* Define to 1 if you have getpwnam_r */
+#cmakedefine   HAVE_POSIX_GETPWNAM_R 1
+
+/* Define to 1 if you have socketpair */
+#cmakedefine   HAVE_SOCKETPAIR 1
+
+/* Define to 1 if you have setenv */
+#cmakedefine   HAVE_SETENV 1
+
+/* Define to 1 if you have unsetenv */
+#cmakedefine   HAVE_UNSETENV 1
+
+/* Define to 1 if you have clearenv */
+#cmakedefine   HAVE_CLEARENV 1
+
+/* Define to 1 if you have writev */
+#cmakedefine   HAVE_WRITEV 1
+
+/* Define to 1 if you have socklen_t */
+#cmakedefine   HAVE_SOCKLEN_T 1
+
+/* Define to 1 if you have setlocale */
+#cmakedefine   HAVE_SETLOCALE 1
+
+/* Define to 1 if you have localeconv */
+#cmakedefine   HAVE_LOCALECONV 1
+
+/* Define to 1 if you have strtoll */
+#cmakedefine   HAVE_STRTOLL 1
+
+/* Define to 1 if you have strtoull */
+#cmakedefine   HAVE_STRTOULL 1
+
+// structs
+/* Define to 1 if you have struct cmsgred */
+#cmakedefine    HAVE_CMSGCRED 1
+
+// system type defines
+#if defined(_WIN32) || defined(_WIN64) || defined (_WIN32_WCE)
+# define DBUS_WIN
+# define DBUS_WIN_FIXME 1
+# ifdef _WIN32_WCE
+#  define DBUS_WINCE
+# else
+#  define DBUS_WIN32
+# endif
+#else
+# define DBUS_UNIX
+#endif 
+
+#if defined(_WIN32) || defined(_WIN64)
+// mingw mode_t
+# ifdef HAVE_STDIO_H
+#  include <stdio.h>
+# endif
+# ifndef _MSC_VER
+#  define uid_t int
+#  define gid_t int
+# else
+#  define snprintf _snprintf
+   typedef int mode_t;
+#  if !defined(_WIN32_WCE)
+#    define strtoll _strtoi64
+#    define strtoull _strtoui64
+#    define HAVE_STRTOLL 1
+#    define HAVE_STRTOULL 1
+#  endif
+# endif
+#endif	// defined(_WIN32) || defined(_WIN64)
+
+#ifdef interface
+#undef interface
+#endif
+
+#ifndef SIGHUP
+#define SIGHUP	1
+#endif
+
+#cmakedefine DBUS_VERBOSE_C_S 1
+#ifdef DBUS_VERBOSE_C_S
+#define _dbus_verbose_C_S printf
+#else
+#define _dbus_verbose_C_S _dbus_verbose
+#endif 
+
+# if defined(_MSC_VER) && !defined(inline)
+#define inline __inline
+#endif
+
+#endif  // _DBUS_CONFIG_H
diff --git a/dbus/cmake/cross-compile.sh b/dbus/cmake/cross-compile.sh
new file mode 100755
index 0000000..49e66e5
--- /dev/null
+++ b/dbus/cmake/cross-compile.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+#
+#  cross compile script for cmake
+# 
+# initial written by Fridrich Strba
+# refactored to debian/lenny by Ralf Habacker
+#
+#  reported to work at least on debian/lenny 
+# 
+
+if test -f /usr/bin/i686-pc-mingw32-gcc; then
+    cross_cc=i686-pc-mingw32
+elif test -f /usr/bin/i586-mingw32msvc-gcc; then
+    cross_cc=i586-mingw32msvc
+else
+    echo "could not determine mingw cross compiler"
+    exit 1
+fi
+
+if test -d ~/$cross_cc; then
+    cross_root=~/$cross_cc
+elif test -d /usr/$cross_cc/sys-root/mingw; then
+    cross_root=/usr/$cross_cc/sys-root/mingw
+elif test -d /usr/$cross_cc/lib; then
+    cross_root=/usr/$cross_cc
+else
+    echo "could not determine mingw cross compiler sdk"
+    exit 1
+fi
+
+if ! TEMP=`mktemp --tmpdir -d dbus-cross-compile.XXXXXX`; then
+    echo "mktemp failed, try with coreutils 6.10 or later?" >&2
+    exit 1
+fi
+
+# make cmake happy 
+export TEMP
+
+HOST_CC=gcc; export HOST_CC;
+
+if test -d $cross_root/lib/pkgconfig; then 
+    PKG_CONFIG_PATH="$cross_root/lib/pkgconfig:$cross_root/share/pkgconfig"; export PKG_CONFIG_PATH;
+fi 
+
+if test -d "$MINGW32_CLASSPATH" ||  test -f "$cross_root/share/java/libgcj.jar";  then 
+    CLASSPATH="$CLASSPATH:${MINGW32_CLASSPATH:-$cross_root/share/java/libgcj.jar:$cross_root/share/java/libgcj-tools.jar}"; export CLASSPATH;
+fi
+
+_PREFIX="/usr/bin/$cross_cc-";
+for i in `ls -1 ${_PREFIX}* | grep -v 'gcc-'`; do
+    x=`echo $i|sed "s,${_PREFIX},,"|sed "s,\.awk*,,"|tr "a-z+-" "A-ZX_"`;
+    declare -x $x="$i" ; export $x;
+done;
+unset _PREFIX;
+
+CC="${MINGW32_CC:-$cross_cc-gcc}"; export CC;
+CFLAGS="${MINGW32_CFLAGS:--O2 -g -pipe -Wall -fexceptions -fno-omit-frame-pointer -fno-optimize-sibling-calls --param=ssp-buffer-size=4 -mms-bitfields}"; export CFLAGS;
+LDFLAGS="${MINGW32_LDFLAGS:--Wl,--exclude-libs=libintl.a -Wl,--exclude-libs=libiconv.a}"; export LDFLAGS;
+
+if [ -x "/usr/bin/$cross_cc-g++" ]; then
+    CXX="${MINGW32_CXX:-$cross_cc-g++}"; export CXX;
+    CXXFLAGS="${MINGW32_CXXFLAGS:--O2 -g -pipe -Wall -fexceptions -fno-omit-frame-pointer -fno-optimize-sibling-calls --param=ssp-buffer-size=4 -mms-bitfields}"; export CXXFLAGS;
+else
+    CXX=; export CXX;
+    ac_cv_prog_CXX=no; export ac_cv_prog_CXX;
+    CXXFLAGS=; export CXXFLAGS;
+fi;
+for i in `ls $cross_root/bin/*|grep -- "-config$"` ; do
+    x=`basename $i|tr "a-z+-" "A-ZX_"|sed "s,\.,,"`;
+    declare -x $x="$i" ; export $x;
+done;
+unset x i ;
+
+if ! test -f "$cross_root/lib/libexpat.dll.a"; then
+    (cd $TEMP && wget http://www.winkde.org/pub/kde/ports/win32/repository/win32libs/expat-2.0.1-bin.zip)
+    (cd $TEMP && wget http://www.winkde.org/pub/kde/ports/win32/repository/win32libs/expat-2.0.1-lib.zip)
+    (cd $cross_root && unzip -x $TMP/expat-2.0.1-bin.zip)
+    (cd $cross_root && unzip -x $TMP/expat-2.0.1-lib.zip)
+fi 
+
+if test -f "$cross_root/lib/libexpat.dll.a"; then
+    xml_library=-DDBUS_USE_EXPAT=On -DLIBEXPAT_INCLUDE_DIR:PATH=$cross_root/include -DLIBEXPAT_LIBRARIES:PATH=$cross_root/lib/libexpat.dll.a 
+else
+    echo "could not find a cross compile xml libraray"
+    exit 1
+fi
+
+cmake \
+    -DCMAKE_SYSTEM_NAME="Windows" \
+    -DCMAKE_VERBOSE_MAKEFILE=ON \
+    -DCMAKE_INSTALL_PREFIX:PATH=$cross_root \
+    -DCMAKE_INSTALL_LIBDIR:PATH=$cross_root/lib \
+    -DINCLUDE_INSTALL_DIR:PATH=$cross_root/include \
+    -DLIB_INSTALL_DIR:PATH=$cross_root/lib \
+    -DSYSCONF_INSTALL_DIR:PATH=$cross_root/etc \
+    -DSHARE_INSTALL_PREFIX:PATH=$cross_root/share \
+    -DBUILD_SHARED_LIBS:BOOL=ON \
+    -DCMAKE_C_COMPILER="/usr/bin/$cross_cc-gcc" \
+    -DCMAKE_CXX_COMPILER="/usr/bin/$cross_cc-g++" \
+    -DCMAKE_FIND_ROOT_PATH="$cross_root" \
+    -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
+    -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
+    -DCMAKE_CXX_COMPILER="/usr/bin/$cross_cc-g++" \
+    -DCMAKE_FIND_ROOT_PATH="$cross_root" \
+    -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
+    -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
+    $xml_library \
+    -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
+    $*
+
diff --git a/dbus/cmake/dbus-env.bat.cmake b/dbus/cmake/dbus-env.bat.cmake
new file mode 100644
index 0000000..85f7005
--- /dev/null
+++ b/dbus/cmake/dbus-env.bat.cmake
@@ -0,0 +1,8 @@
+:: environment setting for dbus clients
+@echo off
+
+:: session bus address
+set DBUS_SESSION_BUS_ADDRESS=@DBUS_SESSION_BUS_DEFAULT_ADDRESS@
+
+:: system bus address
+set DBUS_SYSTEM_BUS_DEFAULT_ADDRESS=@DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@ 
\ No newline at end of file
diff --git a/dbus/cmake/dbus/CMakeLists.txt b/dbus/cmake/dbus/CMakeLists.txt
new file mode 100644
index 0000000..d09e63d
--- /dev/null
+++ b/dbus/cmake/dbus/CMakeLists.txt
@@ -0,0 +1,313 @@
+project(dbus-lib)
+
+SET(DBUS_DIR ${CMAKE_SOURCE_DIR}/../dbus)
+
+configure_file(${DBUS_DIR}/dbus-arch-deps.h.in ${CMAKE_CURRENT_BINARY_DIR}/dbus-arch-deps.h )
+
+add_definitions(-DDBUS_COMPILATION)
+
+set (dbusinclude_HEADERS
+	${DBUS_DIR}/dbus.h
+	${DBUS_DIR}/dbus-address.h
+	${DBUS_DIR}/dbus-bus.h
+	${DBUS_DIR}/dbus-connection.h
+	${DBUS_DIR}/dbus-errors.h
+	${DBUS_DIR}/dbus-macros.h
+	${DBUS_DIR}/dbus-memory.h
+	${DBUS_DIR}/dbus-message.h
+	${DBUS_DIR}/dbus-misc.h
+	${DBUS_DIR}/dbus-pending-call.h
+	${DBUS_DIR}/dbus-protocol.h
+	${DBUS_DIR}/dbus-server.h
+	${DBUS_DIR}/dbus-shared.h
+	${DBUS_DIR}/dbus-signature.h
+	${DBUS_DIR}/dbus-syntax.h
+	${DBUS_DIR}/dbus-threads.h
+	${DBUS_DIR}/dbus-types.h
+	dbus-arch-deps.h
+)
+
+### source code that goes in the installed client library
+### and is specific to library functionality
+set (DBUS_LIB_SOURCES
+	${DBUS_DIR}/dbus-address.c
+	${DBUS_DIR}/dbus-auth.c
+	${DBUS_DIR}/dbus-bus.c
+	${DBUS_DIR}/dbus-connection.c
+	${DBUS_DIR}/dbus-credentials.c
+	${DBUS_DIR}/dbus-errors.c
+	${DBUS_DIR}/dbus-keyring.c
+	${DBUS_DIR}/dbus-marshal-header.c
+	${DBUS_DIR}/dbus-marshal-byteswap.c
+	${DBUS_DIR}/dbus-marshal-recursive.c
+	${DBUS_DIR}/dbus-marshal-validate.c
+	${DBUS_DIR}/dbus-message.c
+	${DBUS_DIR}/dbus-misc.c
+	${DBUS_DIR}/dbus-nonce.c
+	${DBUS_DIR}/dbus-object-tree.c
+	${DBUS_DIR}/dbus-pending-call.c
+	${DBUS_DIR}/dbus-resources.c
+	${DBUS_DIR}/dbus-server.c
+	${DBUS_DIR}/dbus-server-socket.c
+	${DBUS_DIR}/dbus-server-debug-pipe.c
+	${DBUS_DIR}/dbus-sha.c
+	${DBUS_DIR}/dbus-signature.c
+	${DBUS_DIR}/dbus-syntax.c
+	${DBUS_DIR}/dbus-timeout.c
+	${DBUS_DIR}/dbus-threads.c
+	${DBUS_DIR}/dbus-transport.c
+	${DBUS_DIR}/dbus-transport-socket.c
+	${DBUS_DIR}/dbus-watch.c
+)
+
+
+if(UNIX)
+	set (DBUS_LIB_SOURCES ${DBUS_LIB_SOURCES} 
+		${DBUS_DIR}/dbus-transport-unix.c
+		${DBUS_DIR}/dbus-server-unix.c
+	)
+else(UNIX)
+	set (DBUS_LIB_SOURCES ${DBUS_LIB_SOURCES} 
+		${DBUS_DIR}/dbus-transport-win.c
+		${DBUS_DIR}/dbus-server-win.c
+	)
+endif(UNIX)
+
+set (DBUS_LIB_HEADERS
+	${DBUS_DIR}/dbus-auth.h
+	${DBUS_DIR}/dbus-connection-internal.h
+	${DBUS_DIR}/dbus-credentials.h
+	${DBUS_DIR}/dbus-keyring.h
+	${DBUS_DIR}/dbus-marshal-header.h
+	${DBUS_DIR}/dbus-marshal-byteswap.h
+	${DBUS_DIR}/dbus-marshal-recursive.h
+	${DBUS_DIR}/dbus-marshal-validate.h
+	${DBUS_DIR}/dbus-message-internal.h
+	${DBUS_DIR}/dbus-message-private.h
+	${DBUS_DIR}/dbus-misc.h
+	${DBUS_DIR}/dbus-object-tree.h
+	${DBUS_DIR}/dbus-protocol.h
+	${DBUS_DIR}/dbus-resources.h
+	${DBUS_DIR}/dbus-server-debug-pipe.h
+	${DBUS_DIR}/dbus-server-protected.h
+	${DBUS_DIR}/dbus-server-unix.h
+	${DBUS_DIR}/dbus-sha.h
+	${DBUS_DIR}/dbus-timeout.h
+	${DBUS_DIR}/dbus-threads.h
+	${DBUS_DIR}/dbus-threads-internal.h
+	${DBUS_DIR}/dbus-transport.h
+	${DBUS_DIR}/dbus-transport-protected.h
+	${DBUS_DIR}/dbus-watch.h
+	${CMAKE_BINARY_DIR}/config.h
+)
+if(UNIX)
+	set (DBUS_LIB_HEADERS ${DBUS_LIB_HEADERS} 
+		${DBUS_DIR}/dbus-transport-unix.h
+	)
+else(UNIX)
+	set (DBUS_LIB_HEADERS ${DBUS_LIB_HEADERS} 
+		${DBUS_DIR}/dbus-transport-win.h
+	)
+endif(UNIX)
+
+
+### source code that goes in the installed client library
+### AND is generic utility functionality used by the 
+### daemon or test programs (all symbols in here should 
+### be underscore-prefixed)
+set (DBUS_SHARED_SOURCES
+	${DBUS_DIR}/dbus-dataslot.c
+	${DBUS_DIR}/dbus-file.c
+	${DBUS_DIR}/dbus-hash.c
+	${DBUS_DIR}/dbus-internals.c
+	${DBUS_DIR}/dbus-list.c
+	${DBUS_DIR}/dbus-marshal-basic.c
+	${DBUS_DIR}/dbus-memory.c
+	${DBUS_DIR}/dbus-mempool.c
+	${DBUS_DIR}/dbus-string.c
+	${DBUS_DIR}/dbus-sysdeps.c
+	${DBUS_DIR}/dbus-pipe.c
+)
+
+set (DBUS_SHARED_HEADERS
+	${DBUS_DIR}/dbus-dataslot.h
+	${DBUS_DIR}/dbus-file.h
+	${DBUS_DIR}/dbus-hash.h
+	${DBUS_DIR}/dbus-internals.h
+	${DBUS_DIR}/dbus-list.h
+	${DBUS_DIR}/dbus-marshal-basic.h
+	${DBUS_DIR}/dbus-mempool.h
+	${DBUS_DIR}/dbus-string.h
+	${DBUS_DIR}/dbus-string-private.h
+	${DBUS_DIR}/dbus-pipe.h
+	${DBUS_DIR}/dbus-sysdeps.h
+)
+
+### source code that is generic utility functionality used
+### by the bus daemon or test apps, but is NOT included
+### in the D-BUS client library (all symbols in here 
+### should be underscore-prefixed but don't really need 
+### to be unless they move to DBUS_SHARED_SOURCES later)
+set (DBUS_UTIL_SOURCES
+	${DBUS_DIR}/dbus-auth-script.c
+	${DBUS_DIR}/dbus-auth-util.c
+	${DBUS_DIR}/dbus-credentials-util.c
+	${DBUS_DIR}/dbus-mainloop.c
+	${DBUS_DIR}/dbus-marshal-byteswap-util.c
+	${DBUS_DIR}/dbus-marshal-recursive-util.c
+	${DBUS_DIR}/dbus-marshal-validate-util.c
+	${DBUS_DIR}/dbus-message-factory.c
+	${DBUS_DIR}/dbus-message-util.c
+	${DBUS_DIR}/dbus-shell.c
+	${DBUS_DIR}/dbus-socket-set.c
+	${DBUS_DIR}/dbus-socket-set-poll.c
+	${DBUS_DIR}/dbus-string-util.c
+	${DBUS_DIR}/dbus-sysdeps-util.c
+)
+
+if (DBUS_BUILD_TESTS)
+	set (DBUS_UTIL_SOURCES 
+		${DBUS_UTIL_SOURCES}
+		${DBUS_DIR}/dbus-test.c
+	)
+endif (DBUS_BUILD_TESTS)
+
+set (DBUS_UTIL_HEADERS
+	${DBUS_DIR}/dbus-auth-script.h
+	${DBUS_DIR}/dbus-mainloop.h
+	${DBUS_DIR}/dbus-message-factory.h
+	${DBUS_DIR}/dbus-shell.h
+	${DBUS_DIR}/dbus-socket-set.h
+	${DBUS_DIR}/dbus-spawn.h
+	${DBUS_DIR}/dbus-test.h
+)
+
+### platform specific settings
+if (WIN32)
+	set (DBUS_SHARED_SOURCES ${DBUS_SHARED_SOURCES} 
+		${DBUS_DIR}/dbus-file-win.c
+		${DBUS_DIR}/dbus-sysdeps-win.c
+		${DBUS_DIR}/dbus-pipe-win.c
+		${DBUS_DIR}/dbus-sysdeps-thread-win.c
+	)
+	set (DBUS_SHARED_HEADERS ${DBUS_SHARED_HEADERS} 
+		${DBUS_DIR}/dbus-sockets-win.h
+		${DBUS_DIR}/dbus-sysdeps-win.h
+	)
+	set (DBUS_UTIL_SOURCES ${DBUS_UTIL_SOURCES}
+		${DBUS_DIR}/dbus-spawn-win.c
+		${DBUS_DIR}/dbus-sysdeps-util-win.c
+	)
+	if(WINCE)
+	set (DBUS_SHARED_SOURCES ${DBUS_SHARED_SOURCES}
+		${DBUS_DIR}/dbus-sysdeps-wince-glue.c
+	)
+	set (DBUS_SHARED_HEADERS ${DBUS_SHARED_HEADERS}
+		${DBUS_DIR}/dbus-sysdeps-wince-glue.h
+	)
+	endif(WINCE)
+else (WIN32)
+	set (DBUS_SHARED_SOURCES ${DBUS_SHARED_SOURCES} 
+		${DBUS_DIR}/dbus-file-unix.c
+		${DBUS_DIR}/dbus-pipe-unix.c
+		${DBUS_DIR}/dbus-sysdeps-unix.c
+		${DBUS_DIR}/dbus-sysdeps-pthread.c
+		${DBUS_DIR}/dbus-userdb.c
+        ${DBUS_DIR}/sd-daemon.c
+	)
+	set (DBUS_SHARED_HEADERS ${DBUS_SHARED_HEADERS} 
+		${DBUS_DIR}/dbus-server-unix.h
+		${DBUS_DIR}/dbus-transport-unix.h
+		${DBUS_DIR}/dbus-sysdeps-unix.h
+		${DBUS_DIR}/dbus-userdb.h
+        ${DBUS_DIR}/sd-daemon.h
+	)
+	set (DBUS_UTIL_SOURCES ${DBUS_UTIL_SOURCES}
+		${DBUS_DIR}/dbus-spawn.c
+		${DBUS_DIR}/dbus-userdb-util.c
+		${DBUS_DIR}/dbus-sysdeps-util-unix.c
+	)
+endif (WIN32)
+
+set(libdbus_SOURCES
+	${DBUS_LIB_SOURCES}
+	${DBUS_SHARED_SOURCES}
+)
+
+set(libdbus_HEADERS 
+	${DBUS_LIB_HEADERS}
+	${DBUS_SHARED_HEADERS}
+)
+if (MSVC)
+    set (BUILD_FILEVERSION ${DBUS_MAJOR_VERSION},${DBUS_MINOR_VERSION},${DBUS_MICRO_VERSION},${DBUS_PATCH_VERSION})
+    set (BUILD_TIMESTAMP ${DBUS_BUILD_TIMESTAMP})
+    
+    configure_file(${DBUS_DIR}/versioninfo.rc.in ${CMAKE_CURRENT_BINARY_DIR}/versioninfo.rc)
+    file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/afxres.h "")
+    list(APPEND libdbus_SOURCES versioninfo.rc)
+    set_source_files_properties(versioninfo.rc COMPILE_FLAGS "-D__LINE__=1")
+endif (MSVC)
+
+if(MSVC_IDE)
+	project_source_group(${GROUP_CODE} DBUS_LIB_SOURCES DBUS_LIB_HEADERS)
+	project_source_group(${GROUP_CODE} DBUS_SHARED_SOURCES DBUS_SHARED_HEADERS)
+	project_source_group(${GROUP_CODE} DBUS_UTIL_SOURCES DBUS_UTIL_SOURCES)
+endif(MSVC_IDE)
+
+### Client library
+
+add_library(dbus-1 SHARED
+			${libdbus_SOURCES}
+			${libdbus_HEADERS}
+)
+if(WIN32)
+    if(WINCE)
+        target_link_libraries(dbus-1 ws2)
+    else(WINCE)
+        target_link_libraries(dbus-1 ws2_32 advapi32 netapi32)
+    endif(WINCE)
+else(WIN32)
+    target_link_libraries(dbus-1 ${CMAKE_THREAD_LIBS_INIT})
+endif(WIN32)
+
+install_targets(/lib dbus-1 )
+install_files(/include/dbus FILES ${dbusinclude_HEADERS})
+
+### Internal library, used for the daemon, tools and tests, compiled statically.
+
+add_library(dbus-internal ${DBUS_INTERNAL_ADD_LIBRARY_OPTIONS}
+			${DBUS_LIB_SOURCES}
+			${DBUS_LIB_HEADERS}
+			${DBUS_SHARED_SOURCES}
+			${DBUS_SHARED_HEADERS}
+			${DBUS_UTIL_SOURCES}
+			${DBUS_UTIL_HEADERS}
+)
+target_link_libraries(dbus-internal)
+set_target_properties(dbus-internal PROPERTIES COMPILE_FLAGS ${DBUS_INTERNAL_LIBRARY_DEFINITIONS})
+if(WIN32)
+    if(WINCE)
+        target_link_libraries(dbus-internal ws2)
+    else(WINCE)
+        target_link_libraries(dbus-internal ws2_32 advapi32 netapi32)
+    endif(WINCE)
+else(WIN32)
+    target_link_libraries(dbus-internal ${CMAKE_THREAD_LIBS_INIT})
+endif(WIN32)
+
+if (DBUS_BUILD_TESTS)
+	set (TESTS_ENVIRONMENT "DBUS_TEST_DATA=${CMAKE_SOURCE_DIR}/test/data DBUS_TEST_HOMEDIR=${CMAKE_BUILD_DIR}/dbus")
+	ADD_EXECUTABLE(dbus-test ${CMAKE_SOURCE_DIR}/../dbus/dbus-test-main.c)
+	target_link_libraries(dbus-test ${DBUS_INTERNAL_LIBRARIES})
+	add_test(dbus-test ${EXECUTABLE_OUTPUT_PATH}/dbus-test ${CMAKE_SOURCE_DIR}/../test/data)
+	set_target_properties(dbus-test PROPERTIES COMPILE_FLAGS ${DBUS_INTERNAL_CLIENT_DEFINITIONS})
+ENDIF (DBUS_BUILD_TESTS)
+
+if (UNIX)
+# set version info
+ENDIF (UNIX)
+
+
+## mop up the gcov files
+#clean-local:
+#/bin/rm *.bb *.bbg *.da *.gcov .libs/*.da .libs/*.bbg || true
diff --git a/dbus/cmake/doc/CMakeLists.txt b/dbus/cmake/doc/CMakeLists.txt
new file mode 100644
index 0000000..df6b587
--- /dev/null
+++ b/dbus/cmake/doc/CMakeLists.txt
@@ -0,0 +1,120 @@
+find_package(Doxygen)
+
+if(DOXYGEN_EXECUTABLE)
+  OPTION(DBUS_ENABLE_DOXYGEN_DOCS "build DOXYGEN documentation (requires Doxygen)" ON)
+endif(DOXYGEN_EXECUTABLE)
+
+if (DBUS_ENABLE_DOXYGEN_DOCS)
+    set (top_srcdir ${CMAKE_SOURCE_DIR}/..)
+    configure_file(${CMAKE_SOURCE_DIR}/Doxyfile.cmake ${CMAKE_BINARY_DIR}/Doxyfile )
+    add_custom_target(doc 
+        COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile
+    )
+endif (DBUS_ENABLE_DOXYGEN_DOCS)
+
+#
+# find docbook generator
+# 
+find_program(MEINPROC4_EXECUTABLE meinproc4)
+
+find_program(XMLTO_EXECUTABLE xmlto)
+
+if (MEINPROC4_EXECUTABLE OR XMLTO_EXECUTABLE)
+  OPTION(DBUS_ENABLE_XML_DOCS "build XML  documentation (requires xmlto or meinproc4)" ON)
+endif (MEINPROC4_EXECUTABLE OR XMLTO_EXECUTABLE)
+
+if (MEINPROC4_EXECUTABLE)
+	set(DOCBOOK_GENERATOR_NAME "meinproc4" PARENT_SCOPE)
+	set(DBUS_XML_DOCS_ENABLED 1)
+	if(WIN32)
+		get_filename_component(_a ${MEINPROC4_EXECUTABLE} PATH)
+		get_filename_component(_meinproc_install_path ${_a} PATH)
+	else(WIN32)
+		set(_meinproc_install_path ${CMAKE_INSTALL_PREFIX})
+	endif(WIN32)
+	set(STYLESHEET "${_meinproc_install_path}/share/apps/ksgmltools2/docbook/xsl/html/docbook.xsl")
+endif (MEINPROC4_EXECUTABLE)
+  
+ 
+if (XMLTO_EXECUTABLE)
+	set (DOCBOOK_GENERATOR_NAME "xmlto" PARENT_SCOPE)
+	set(DBUS_XML_DOCS_ENABLED 1)
+	MESSAGE(STATUS "xmlto docbook generator found")
+endif (XMLTO_EXECUTABLE)
+
+if (DBUS_ENABLE_XML_DOCS)
+
+macro (DOCBOOK _sources _options)
+  get_filename_component(_infile ${_sources} ABSOLUTE)
+  get_filename_component(_basename ${_infile} NAME_WE)
+  set(_outfile ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.html)
+
+  if (EXISTS ${_sources})
+	  if (MEINPROC4_EXECUTABLE)
+		  ADD_CUSTOM_TARGET(${_basename}.html ALL
+			${MEINPROC4_EXECUTABLE} --stylesheet ${STYLESHEET} -o ${_outfile} ${_infile} 
+			DEPENDS ${_infile} 
+			WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+		)
+	  endif ()
+	  if (XMLTO_EXECUTABLE)
+		  ADD_CUSTOM_TARGET(${_basename}.html ALL
+			${XMLTO_EXECUTABLE} -vv ${_options} ${_infile} 
+			DEPENDS ${_infile} 
+			WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+		)
+	  endif ()
+	  install(FILES ${_outfile} DESTINATION share/doc/dbus)
+  else ()
+	  MESSAGE(STATUS "skipping xml doc generating for ${_infile}, file not found")
+  endif ()
+	  
+endmacro (DOCBOOK)
+
+### copy tests to builddir so that generated tests and static tests 
+### are all in one place.
+### todo how to add more filetypes 
+MACRO (COPYDIR _src _type)
+    FOREACH(FILE_TYPE ${_type})
+    	FOREACH(DIR ${_src})
+    		FILE(GLOB FILES "${CMAKE_SOURCE_DIR}/../${DIR}/${FILE_TYPE}" )
+    		FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/${DIR})
+    		FOREACH(FILE ${FILES})
+    			GET_FILENAME_COMPONENT(FILENAME ${FILE} NAME)
+    			SET (TARGET ${CMAKE_BINARY_DIR}/${DIR}/${FILENAME})
+    			configure_file(${FILE} ${TARGET} COPYONLY)
+    			IF (CONFIG_VERBOSE)
+    				MESSAGE("FROM: ${FILE}\nTO: ${TARGET}\n")
+    			ENDIF (CONFIG_VERBOSE)
+    		ENDFOREACH(FILE)
+    	ENDFOREACH(DIR)
+    ENDFOREACH(FILE_TYPE)
+ENDMACRO (COPYDIR)
+
+COPYDIR(doc *.png)
+COPYDIR(doc *.svg)
+
+DOCBOOK(${CMAKE_SOURCE_DIR}/../doc/dbus-test-plan.xml html-nochunks)
+DOCBOOK(${CMAKE_SOURCE_DIR}/../doc/dbus-tutorial.xml html-nochunks)
+DOCBOOK(${CMAKE_SOURCE_DIR}/../doc/dbus-specification.xml html-nochunks)
+DOCBOOK(${CMAKE_SOURCE_DIR}/../doc/dbus-faq.xml html-nochunks)
+DOCBOOK(${CMAKE_SOURCE_DIR}/bus/dbus-daemon.xml html-nochunks)
+DOCBOOK(${CMAKE_SOURCE_DIR}/tools/dbus-monitor.xml html-nochunks)
+DOCBOOK(${CMAKE_SOURCE_DIR}/tools/dbus-send.xml html-nochunks)
+DOCBOOK(${CMAKE_SOURCE_DIR}/tools/dbus-launch.xml html-nochunks)
+
+#
+# handle html index file
+#
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/index.html.cmake ${CMAKE_CURRENT_BINARY_DIR}/index.html )
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/index.html DESTINATION share/doc/dbus)
+
+set (EXTRA_DIST 	
+	${CMAKE_SOURCE_DIR}/../doc/busconfig.dtd			
+	${CMAKE_SOURCE_DIR}/../doc/introspect.dtd			
+	${CMAKE_SOURCE_DIR}/../doc/introspect.xsl
+)
+
+install(FILES ${EXTRA_DIST} DESTINATION share/doc/dbus)
+
+endif(DBUS_ENABLE_XML_DOCS)
diff --git a/dbus/cmake/doc/index.html.cmake b/dbus/cmake/doc/index.html.cmake
new file mode 100644
index 0000000..77dd661
--- /dev/null
+++ b/dbus/cmake/doc/index.html.cmake
@@ -0,0 +1,55 @@
+<html>
+<head>
+<title>D-Bus Documentation Index</title>
+</head>
+<body>
+<h1>D-Bus Documentation Index</h1>
+<p>Version @DBUS_VERSION_STRING@</p>
+
+<table>
+ <tr>
+  <th width=10%>
+  </th>
+  <th width=30% align=left>
+   generic documentation
+  </th>
+  <th width=30% align=left>
+application manuals
+  </th>
+ </tr>
+ <tr>
+  <td valign=top>
+  </td>
+  <td valign=top>
+<a href="http://dbus.freedesktop.org">D-Bus Website</a>
+  <br>
+  <br>
+<a href="dbus-tutorial.html">D-Bus Tutorial</a>
+  <br>
+  <br>
+<a href="dbus-specification.html">D-Bus Specification</a>
+   <br>
+   <br>
+<a href="dbus-faq.html">D-Bus FAQ</a>
+   <br>
+   <br>
+<a href="dbus-test-plan.html">D-Bus Test Plan</a>
+   <br>
+   <br>
+  </td>
+  <td  valign=top>
+<a href="dbus-daemon.html">D-Bus Daemon manual</a>
+   <br>
+   <br>
+<a href="dbus-launch.html">D-Bus launch manual</a>
+   <br>
+   <br>
+<a href="dbus-send.html">D-Bus send tool manual</a>
+   <br>
+   <br>
+<a href="dbus-monitor.html">D-Bus monitor manual</a>
+  </td>
+ </tr>
+</table>
+</body>
+</html>
diff --git a/dbus/cmake/modules/CPackInstallConfig.cmake b/dbus/cmake/modules/CPackInstallConfig.cmake
new file mode 100644
index 0000000..f8073a2
--- /dev/null
+++ b/dbus/cmake/modules/CPackInstallConfig.cmake
@@ -0,0 +1,44 @@
+
+if (DBUS_INSTALL_SYSTEM_LIBS)
+	if (MINGW)
+		if (DBUS_USE_EXPAT)
+			# expat
+			install_files(/bin FILES ${LIBEXPAT_LIBRARIES})	
+		else (DBUS_USE_EXPAT)
+			# xml2
+			install_files(/bin FILES ${LIBXML2_LIBRARIES})	
+			install_files(/bin FILES ${LIBICONV_LIBRARIES})	
+		endif (DBUS_USE_EXPAT)
+	else (MINGW)
+		INCLUDE(InstallRequiredSystemLibraries)
+	endif (MINGW)
+endif (DBUS_INSTALL_SYSTEM_LIBS)
+
+SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "D-BUS For Windows")
+SET(CPACK_PACKAGE_VENDOR "D-BUS Windows Team")
+SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/../README")
+SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/../COPYING")
+# duplicated from VERSION
+SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
+SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
+SET(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
+#SET(CPACK_PACKAGE_INSTALL_DIRECTORY "dbus ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}")
+SET(CPACK_PACKAGE_INSTALL_DIRECTORY "dbus")
+IF(WIN32 AND NOT UNIX)
+  SET(CPACK_GENERATOR NSIS ZIP)     # can be NSIS, STGZ, TBZ2, TGZ, TZ and ZIP
+  SET(CPACK_NSIS_COMPRESSOR "/SOLID lzma")
+  # There is a bug in NSI that does not handle full unix paths properly. Make
+  # sure there is at least one set of four (4) backlasshes.
+# SET(CPACK_PACKAGE_ICON "${CMake_SOURCE_DIR}/Utilities/Release\\\\InstallIcon.bmp")
+  SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\dbus-launch.bat")
+  SET(CPACK_NSIS_DISPLAY_NAME "D-Bus for Windows")
+  SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\sourceforge.net/projects/windbus")
+  SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\sourceforge.net/projects/windbus")
+  SET(CPACK_NSIS_CONTACT "me@my-personal-home-page.com")
+  SET(CPACK_NSIS_MODIFY_PATH ON)
+ELSE(WIN32 AND NOT UNIX)
+  SET(CPACK_STRIP_FILES "bin/MyExecutable")
+  SET(CPACK_SOURCE_STRIP_FILES "")
+ENDIF(WIN32 AND NOT UNIX)
+SET(CPACK_PACKAGE_EXECUTABLES "dbus-launch" "D-Bus Daemon")
+INCLUDE(CPack)
diff --git a/dbus/cmake/modules/CheckForAbstractSockets.c b/dbus/cmake/modules/CheckForAbstractSockets.c
new file mode 100644
index 0000000..062b846
--- /dev/null
+++ b/dbus/cmake/modules/CheckForAbstractSockets.c
@@ -0,0 +1,33 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+
+int main() {
+  int listen_fd;
+  struct sockaddr_un addr;
+
+  listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
+
+  if (listen_fd < 0)
+    {
+      fprintf (stderr, "socket() failed: %s\n", strerror (errno));
+      exit (1);
+    }
+
+  memset (&addr, '\0', sizeof (addr));
+  addr.sun_family = AF_UNIX;
+  strcpy (addr.sun_path, "X/tmp/dbus-fake-socket-path-used-in-configure-test");
+  addr.sun_path[0] = '\0'; /* this is what makes it abstract */
+
+  if (bind (listen_fd, (struct sockaddr*) &addr, SUN_LEN (&addr)) < 0)
+    {
+      fprintf (stderr, "Abstract socket namespace bind() failed: %s\n",
+                strerror (errno));
+      exit (1);
+    }
+  else
+    exit (0);
+}
\ No newline at end of file
diff --git a/dbus/cmake/modules/CheckPrototypeExists.cmake b/dbus/cmake/modules/CheckPrototypeExists.cmake
new file mode 100644
index 0000000..da319f1
--- /dev/null
+++ b/dbus/cmake/modules/CheckPrototypeExists.cmake
@@ -0,0 +1,35 @@
+# - Check if the prototype for a function exists.
+# CHECK_PROTOTYPE_EXISTS (FUNCTION HEADER VARIABLE)
+#
+#  FUNCTION - the name of the function you are looking for
+#  HEADER - the header(s) where the prototype should be declared
+#  VARIABLE - variable to store the result
+#
+# The following variables may be set before calling this macro to
+# modify the way the check is run:
+#
+#  CMAKE_REQUIRED_FLAGS = string of compile command line flags
+#  CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
+#  CMAKE_REQUIRED_INCLUDES = list of include directories
+
+INCLUDE(CheckCXXSourceCompiles)
+
+MACRO (CHECK_PROTOTYPE_EXISTS _SYMBOL _HEADER _RESULT)
+   SET(_INCLUDE_FILES)
+   FOREACH (it ${_HEADER})
+      SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
+   ENDFOREACH (it)
+
+   SET(_CHECK_PROTO_EXISTS_SOURCE_CODE "
+${_INCLUDE_FILES}
+int main()
+{
+#ifndef ${_SYMBOL}
+   int i = sizeof(&${_SYMBOL});
+#endif
+  return 0;
+}
+")
+   CHECK_CXX_SOURCE_COMPILES("${_CHECK_PROTO_EXISTS_SOURCE_CODE}" ${_RESULT})
+ENDMACRO (CHECK_PROTOTYPE_EXISTS _SYMBOL _HEADER _RESULT)
+
diff --git a/dbus/cmake/modules/CheckStructMember.cmake b/dbus/cmake/modules/CheckStructMember.cmake
new file mode 100644
index 0000000..fd5d346
--- /dev/null
+++ b/dbus/cmake/modules/CheckStructMember.cmake
@@ -0,0 +1,36 @@
+# - Check if the given struct or class has the specified member variable
+# CHECK_STRUCT_MEMBER (STRUCT MEMBER HEADER VARIABLE)
+#
+#  STRUCT - the name of the struct or class you are interested in
+#  MEMBER - the member which existence you want to check
+#  HEADER - the header(s) where the prototype should be declared
+#  VARIABLE - variable to store the result
+#
+# The following variables may be set before calling this macro to
+# modify the way the check is run:
+#
+#  CMAKE_REQUIRED_FLAGS = string of compile command line flags
+#  CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
+#  CMAKE_REQUIRED_INCLUDES = list of include directories
+
+INCLUDE(CheckCXXSourceCompiles)
+
+MACRO (CHECK_STRUCT_MEMBER _STRUCT _MEMBER _HEADER _RESULT)
+   SET(_INCLUDE_FILES)
+   FOREACH (it ${_HEADER})
+      SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n")
+   ENDFOREACH (it)
+
+   SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE "
+${_INCLUDE_FILES}
+int main()
+{
+   ${_STRUCT}* tmp;
+   tmp->${_MEMBER};
+  return 0;
+}
+")
+   CHECK_CXX_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT})
+
+ENDMACRO (CHECK_STRUCT_MEMBER)
+
diff --git a/dbus/cmake/modules/FindDoxygen.cmake b/dbus/cmake/modules/FindDoxygen.cmake
new file mode 100644
index 0000000..1767901
--- /dev/null
+++ b/dbus/cmake/modules/FindDoxygen.cmake
@@ -0,0 +1,3 @@
+
+find_program(DOXYGEN_EXECUTABLE NAMES doxygen DOC "doxygen executable")
+mark_as_advanced(DOXYGEN_EXECUTABLE)
diff --git a/dbus/cmake/modules/FindGLIB.cmake b/dbus/cmake/modules/FindGLIB.cmake
new file mode 100644
index 0000000..1fdaee9
--- /dev/null
+++ b/dbus/cmake/modules/FindGLIB.cmake
@@ -0,0 +1,42 @@
+# - Try to find the GLIB library
+# Once done this will define
+#
+#  GLIB_FOUND - system has GLIB
+#  GLIB_INCLUDES - the GLIB include directories
+#  GLIB_LIBRARIES - The libraries needed to use GLIB
+
+if (WIN32)
+
+INCLUDE(MacroGetenvWinPath)
+
+MACRO_GETENV_WIN_PATH(_program_FILES_DIR PROGRAMFILES)
+
+FIND_PATH(GLIB_INCLUDE_DIR glib.h
+   ${_program_FILES_DIR}/glib/include/glib-2.0
+)
+
+
+# search for GLIB in the default install directory for applications (default of (n)make install)
+FIND_LIBRARY(GLIB_LIBRARY NAMES glib-2.0
+   PATHS
+   ${_program_FILES_DIR}/glib/lib
+)
+
+if (GLIB_LIBRARY AND GLIB_INCLUDE_DIR)
+   set(GLIB_FOUND TRUE)
+   set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} ${GLIB_INCLUDES})
+   set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} ${GLIB_LIBRARIES})
+   
+endif (GLIB_LIBRARY AND GLIB_INCLUDE_DIR)
+
+if (GLIB_FOUND)
+   if (NOT GLIB_FIND_QUIETLY)
+      message(STATUS "Found GLIB: ${GLIB_LIBRARY}")
+   endif (NOT GLIB_FIND_QUIETLY)
+else (GLIB_FOUND)
+   if (GLIB_FIND_REQUIRED)
+      message(FATAL_ERROR "Could NOT find GLIB library")
+   endif (GLIB_FIND_REQUIRED)
+endif (GLIB_FOUND)
+
+endif (WIN32)
diff --git a/dbus/cmake/modules/FindLibExpat.cmake b/dbus/cmake/modules/FindLibExpat.cmake
new file mode 100644
index 0000000..a07c8de
--- /dev/null
+++ b/dbus/cmake/modules/FindLibExpat.cmake
@@ -0,0 +1,61 @@
+# - Try to find LIBEXPAT
+# Once done this will define
+#
+#  LIBEXPAT_FOUND - system has LIBEXPAT
+#  LIBEXPAT_INCLUDE_DIR - the LIBEXPAT include directory
+#  LIBEXPAT_LIBRARIES - the libraries needed to use LIBEXPAT
+#  LIBEXPAT_DEFINITIONS - Compiler switches required for using LIBEXPAT
+
+if (LIBEXPAT_INCLUDE_DIR AND LIBEXPAT_LIBRARIES)
+
+    # in cache already
+    SET(LIBEXPAT_FOUND TRUE)
+
+else (LIBEXPAT_INCLUDE_DIR AND LIBEXPAT_LIBRARIES)
+
+    IF (WIN32)
+		file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _progFiles)
+		find_FILE(LIBEXPAT_DIR expat Source/lib/expat.h
+   			PATHS
+   			"${_progFiles}"
+		)
+        if (LIBEXPAT_DIR)
+            set (_LIBEXPATIncDir  ${LIBEXPAT_DIR}/Source/lib)
+            set (_LIBEXPATLinkDir ${LIBEXPAT_DIR}/libs)
+        endif (LIBEXPAT_DIR)
+    ELSE (WIN32)
+        # use pkg-config to get the directories and then use these values
+        # in the FIND_PATH() and FIND_LIBRARY() calls
+        INCLUDE(UsePkgConfig)
+        PKGCONFIG(LIBEXPAT-2.0 _LIBEXPATIncDir _LIBEXPATLinkDir _LIBEXPATLinkFlags _LiIconvCflags)
+        SET(LIBEXPAT_DEFINITIONS ${_LIBEXPATCflags})
+    ENDIF (WIN32)
+
+    FIND_PATH(LIBEXPAT_INCLUDE_DIR expat.h
+      PATHS
+     ${_LIBEXPATIncDir}
+      PATH_SUFFIXES LIBEXPAT
+    )
+
+    FIND_LIBRARY(LIBEXPAT_LIBRARIES NAMES expat libexpat
+      PATHS
+      ${_LIBEXPATLinkDir}
+    )
+
+    if (LIBEXPAT_INCLUDE_DIR AND LIBEXPAT_LIBRARIES)
+       set(LIBEXPAT_FOUND TRUE)
+    endif (LIBEXPAT_INCLUDE_DIR AND LIBEXPAT_LIBRARIES)
+
+    if (LIBEXPAT_FOUND)
+      if (NOT LIBEXPAT_FIND_QUIETLY)
+        message(STATUS "Found libexpat: ${LIBEXPAT_LIBRARIES}")
+      endif (NOT LIBEXPAT_FIND_QUIETLY)
+    else (LIBEXPAT_FOUND)
+      if (LIBEXPAT_FIND_REQUIRED)
+        message(SEND_ERROR "Could NOT find libexpat")
+      endif (LIBEXPAT_FIND_REQUIRED)
+    endif (LIBEXPAT_FOUND)
+
+    MARK_AS_ADVANCED(LIBEXPAT_INCLUDE_DIR LIBEXPAT_LIBRARIES)
+
+endif (LIBEXPAT_INCLUDE_DIR AND LIBEXPAT_LIBRARIES)
diff --git a/dbus/cmake/modules/FindLibIconv.cmake b/dbus/cmake/modules/FindLibIconv.cmake
new file mode 100644
index 0000000..dac6344
--- /dev/null
+++ b/dbus/cmake/modules/FindLibIconv.cmake
@@ -0,0 +1,52 @@
+# - Try to find LibIconv
+# Once done this will define
+#
+#  LIBICONV_FOUND - system has LibIconv
+#  LIBICONV_INCLUDE_DIR - the LibIconv include directory
+#  LIBICONV_LIBRARIES - the libraries needed to use LibIconv
+#  LIBICONV_DEFINITIONS - Compiler switches required for using LibIconv
+
+if (LIBICONV_INCLUDE_DIR AND LIBICONV_LIBRARIES)
+
+    # in cache already
+    SET(LIBICONV_FOUND TRUE)
+
+else (LIBICONV_INCLUDE_DIR AND LIBICONV_LIBRARIES)
+
+    IF (NOT WIN32)
+        MESSAGE(FATAL_ERROR "Please set this to the correct values!")
+        # use pkg-config to get the directories and then use these values
+        # in the FIND_PATH() and FIND_LIBRARY() calls
+        INCLUDE(UsePkgConfig)
+        PKGCONFIG(libiconv-1.9 _LibIconvIncDir _LibIconvLinkDir _LibIconvLinkFlags _LiIconvCflags)
+        SET(LIBICONV_DEFINITIONS ${_LibIconvCflags})
+    ENDIF (NOT WIN32)
+
+    FIND_PATH(LIBICONV_INCLUDE_DIR iconv.h
+      PATHS
+     ${_LibIconvIncDir}
+      PATH_SUFFIXES libiconv
+    )
+
+    FIND_LIBRARY(LIBICONV_LIBRARIES NAMES iconv libiconv
+      PATHS
+      ${_LibIconvLinkDir}
+    )
+
+    if (LIBICONV_INCLUDE_DIR AND LIBICONV_LIBRARIES)
+       set(LIBICONV_FOUND TRUE)
+    endif (LIBICONV_INCLUDE_DIR AND LIBICONV_LIBRARIES)
+
+    if (LIBICONV_FOUND)
+      if (NOT LibIconv_FIND_QUIETLY)
+        message(STATUS "Found LibIconv: ${LIBICONV_LIBRARIES}")
+      endif (NOT LibIconv_FIND_QUIETLY)
+    else (LIBICONV_FOUND)
+      if (LibIconv_FIND_REQUIRED)
+        message(SEND_ERROR "Could NOT find LibIconv")
+      endif (LibIconv_FIND_REQUIRED)
+    endif (LIBICONV_FOUND)
+
+    MARK_AS_ADVANCED(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARIES)
+
+endif (LIBICONV_INCLUDE_DIR AND LIBICONV_LIBRARIES)
diff --git a/dbus/cmake/modules/MacroGetenvWinPath.cmake b/dbus/cmake/modules/MacroGetenvWinPath.cmake
new file mode 100644
index 0000000..b18f7f6
--- /dev/null
+++ b/dbus/cmake/modules/MacroGetenvWinPath.cmake
@@ -0,0 +1,5 @@
+
+MACRO (MACRO_GETENV_WIN_PATH var name)
+   set(${var} $ENV{${name}})
+   STRING(REGEX REPLACE "\\\\" "/" ${var} "${${var}}")
+ENDMACRO (MACRO_GETENV_WIN_PATH var name)
diff --git a/dbus/cmake/modules/MacroLibrary.cmake b/dbus/cmake/modules/MacroLibrary.cmake
new file mode 100644
index 0000000..6523530
--- /dev/null
+++ b/dbus/cmake/modules/MacroLibrary.cmake
@@ -0,0 +1,9 @@
+# - include MacroLibrary offers a collection of macros which extend the built-in cmake commands
+# OPTIONAL_FIND_PACKAGE( <name> [QUIT] )
+
+INCLUDE(MacroOptionalFindPackage)
+#INCLUDE(MacroAdditionalCleanFiles)
+#INCLUDE(MacroAddFileDependencies)
+#INCLUDE(MacroGetenvWinPath)
+#INCLUDE(MacroEnsureOutOfSourceBuild)
+
diff --git a/dbus/cmake/modules/MacroOptionalFindPackage.cmake b/dbus/cmake/modules/MacroOptionalFindPackage.cmake
new file mode 100644
index 0000000..7068131
--- /dev/null
+++ b/dbus/cmake/modules/MacroOptionalFindPackage.cmake
@@ -0,0 +1,22 @@
+# - MACRO_OPTIONAL_FIND_PACKAGE() combines FIND_PACKAGE() with an OPTION()
+# MACRO_OPTIONAL_FIND_PACKAGE( <name> [QUIT] )
+# This macro is a combination of OPTION() and FIND_PACKAGE(), it
+# works like FIND_PACKAGE(), but additionally it automatically creates
+# an option name WITH_<name>, which can be disabled via the cmake GUI.
+# or via -DWITH_<name>=OFF
+# The standard <name>_FOUND variables can be used in the same way
+# as when using the normal FIND_PACKAGE()
+
+MACRO (MACRO_OPTIONAL_FIND_PACKAGE _name )
+   OPTION(WITH_${_name} "Search for ${_name} package" ON)
+   if (WITH_${_name})
+      FIND_PACKAGE(${_name} ${ARGN})
+   else (WITH_${_name})
+      set(${_name}_FOUND)
+      set(${_name}_INCLUDE_DIR)
+      set(${_name}_INCLUDES)
+      set(${_name}_LIBRARY)
+      set(${_name}_LIBRARIES)
+   endif (WITH_${_name})
+ENDMACRO (MACRO_OPTIONAL_FIND_PACKAGE)
+
diff --git a/dbus/cmake/modules/Macros.cmake b/dbus/cmake/modules/Macros.cmake
new file mode 100644
index 0000000..b637156
--- /dev/null
+++ b/dbus/cmake/modules/Macros.cmake
@@ -0,0 +1,15 @@
+
+MACRO(TIMESTAMP RESULT)
+    IF(WIN32)
+        EXECUTE_PROCESS(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE DATE)
+        string(REGEX REPLACE "(..)[/.](..)[/.](....).*" "\\3\\2\\1" DATE ${DATE})
+        EXECUTE_PROCESS(COMMAND "cmd" " /C time /T" OUTPUT_VARIABLE TIME)
+        string(REGEX REPLACE "(..):(..)" "\\1\\2" TIME ${TIME})
+        set (${RESULT} "${DATE}${TIME}")
+    ELSEIF(UNIX)
+        EXECUTE_PROCESS(COMMAND "date" "+%Y%m%d%H%M" OUTPUT_VARIABLE ${RESULT})
+    ELSE()
+        MESSAGE(SEND_ERROR "date not implemented")
+        SET(${RESULT} 000000000000)
+    ENDIF()
+ENDMACRO()
diff --git a/dbus/cmake/modules/MacrosAutotools.cmake b/dbus/cmake/modules/MacrosAutotools.cmake
new file mode 100644
index 0000000..ff30eaf
--- /dev/null
+++ b/dbus/cmake/modules/MacrosAutotools.cmake
@@ -0,0 +1,40 @@
+#
+# @Author Ralf Habacker
+# 
+# extracts version information from autoconf config file
+# and set related cmake variables
+# 
+# returns  
+#   ${prefix}_VERSION
+#   ${prefix}_VERSION_STRING
+#   ${prefix}_MAJOR_VERSION
+#   ${prefix}_MINOR_VERSION
+#   ${prefix}_MICRO_VERSION
+# 
+macro(autoversion config prefix)
+	file (READ ${config} _configure_ac)
+	string(TOUPPER ${prefix} prefix_upper)
+	string (REGEX REPLACE ".*${prefix}_major_version], .([0-9]+).*" "\\1" ${prefix_upper}_MAJOR_VERSION ${_configure_ac})
+	string (REGEX REPLACE ".*${prefix}_minor_version], .([0-9]+).*" "\\1" ${prefix_upper}_MINOR_VERSION ${_configure_ac})
+	string (REGEX REPLACE ".*${prefix}_micro_version], .([0-9]+).*" "\\1" ${prefix_upper}_MICRO_VERSION ${_configure_ac})
+	set (${prefix_upper}_VERSION ${${prefix_upper}_MAJOR_VERSION}.${${prefix_upper}_MINOR_VERSION}.${${prefix_upper}_MICRO_VERSION})
+	set (${prefix_upper}_VERSION_STRING "${${prefix_upper}_VERSION}")
+
+endmacro()
+
+#
+# parses config.h template and create cmake equivalent 
+# not implemented yet
+# 
+macro(autoconfig template output)
+	file(READ ${template} contents)
+	# Convert file contents into a CMake list (where each element in the list
+	# is one line of the file)
+	STRING(REGEX REPLACE ";" "\\\\;" contents "${contents}")
+	STRING(REGEX REPLACE "\n" ";" contents "${contents}")
+	foreach(line contents)
+		message(STATUS ${line})
+		# find #undef lines
+		# append to config.h #define <variable-name> <variable-content>
+	endforeach()
+endmacro()
diff --git a/dbus/cmake/modules/ProjectSourceGroup.cmake b/dbus/cmake/modules/ProjectSourceGroup.cmake
new file mode 100644
index 0000000..713a67a
--- /dev/null
+++ b/dbus/cmake/modules/ProjectSourceGroup.cmake
@@ -0,0 +1,18 @@
+# folders in the msvc projects
+# mode==flat  : headers and ourses in no folders
+# mode==split : standard behavior of cmake, split headers and sources
+# mode== <other values" : code is in this folder
+macro(project_source_group mode sources headers)
+	#message(STATUS ${mode})
+	#message(STATUS ${sources} ${headers})
+	if(${mode} MATCHES "flat")
+		source_group("Source Files" Files)
+		source_group("Header Files" Files)
+		source_group("cmake" FILES CMakeLists.txt)
+	else(${mode} MATCHES "flat")
+		if(NOT ${mode} MATCHES "split")
+			source_group("${mode}" FILES ${${sources}} ${${headers}})
+		endif(NOT ${mode} MATCHES "split")
+	endif(${mode} MATCHES "flat")
+endmacro(project_source_group mode sources headers)
+
diff --git a/dbus/cmake/modules/Win32Macros.cmake b/dbus/cmake/modules/Win32Macros.cmake
new file mode 100644
index 0000000..4385cc9
--- /dev/null
+++ b/dbus/cmake/modules/Win32Macros.cmake
@@ -0,0 +1,44 @@
+#
+# win32 macros 
+# 
+# Copyright (c) 2006-2007, Ralf Habacker
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+#
+
+if (WIN32)
+    #
+    # addExplorerWrapper creates batch files for fast access 
+    # to the build environment from the win32 explorer. 
+    # 
+    # For mingw and nmake projects it's opens a command shell,
+    # for Visual Studio IDE's (at least tested with VS 8 2005) it
+    # opens the related .sln file with paths setting specified at 
+    # configure time. 
+    #
+    MACRO (addExplorerWrapper _projectname)
+        # write explorer wrappers
+        get_filename_component(CMAKE_BIN_PATH ${CMAKE_COMMAND} PATH)
+        set (ADD_PATH "${CMAKE_BIN_PATH}")
+
+        if (QT_QMAKE_EXECUTABLE)
+            get_filename_component(QT_BIN_PATH ${QT_QMAKE_EXECUTABLE} PATH)
+            set (ADD_PATH "${ADD_PATH};${QT_BIN_PATH}")
+        endif (QT_QMAKE_EXECUTABLE)
+        
+        # add here more pathes 
+        
+        if (MINGW)
+            get_filename_component(MINGW_BIN_PATH ${CMAKE_CXX_COMPILER} PATH)
+            set (ADD_PATH "${ADD_PATH};${MINGW_BIN_PATH}")
+            write_file (${CMAKE_BINARY_DIR}/${_projectname}-shell.bat "set PATH=${ADD_PATH};%PATH%\ncmd.exe")
+        else (MINGW)
+            if (CMAKE_BUILD_TOOL STREQUAL  "nmake")
+                get_filename_component(VC_BIN_PATH ${CMAKE_CXX_COMPILER} PATH)
+                write_file (${CMAKE_BINARY_DIR}/${_projectname}-shell.bat "set PATH=${ADD_PATH};%PATH%\ncall \"${VC_BIN_PATH}\\vcvars32.bat\"\ncmd.exe")
+            else (CMAKE_BUILD_TOOL STREQUAL  "nmake")
+                write_file (${CMAKE_BINARY_DIR}/${_projectname}-sln.bat "set PATH=${ADD_PATH};%PATH%\nstart ${_projectname}.sln")
+            endif (CMAKE_BUILD_TOOL STREQUAL  "nmake")
+        endif (MINGW)
+    ENDMACRO (addExplorerWrapper)
+endif(WIN32)
diff --git a/dbus/cmake/test/CMakeLists.txt b/dbus/cmake/test/CMakeLists.txt
new file mode 100644
index 0000000..8657e4c
--- /dev/null
+++ b/dbus/cmake/test/CMakeLists.txt
@@ -0,0 +1,155 @@
+project(test)
+
+add_definitions(${DBUS_INTERNAL_CLIENT_DEFINITIONS})
+
+add_library(dbus-testutils STATIC
+    ${CMAKE_SOURCE_DIR}/../test/test-utils.h
+    ${CMAKE_SOURCE_DIR}/../test/test-utils.c
+)
+target_link_libraries(dbus-testutils ${DBUS_INTERNAL_LIBRARIES})
+
+add_subdirectory( name-test )
+
+set (test-service_SOURCES
+    ${CMAKE_SOURCE_DIR}/../test/test-service.c
+)
+
+set (test-names_SOURCES
+    ${CMAKE_SOURCE_DIR}/../test/test-names.c
+)
+
+set (break_loader_SOURCES
+    ${CMAKE_SOURCE_DIR}/../test/break-loader.c
+)
+
+set (test-shell-service_SOURCES
+    ${CMAKE_SOURCE_DIR}/../test/test-shell-service.c
+)
+
+set (shell-test_SOURCES
+        ${CMAKE_SOURCE_DIR}/../test/shell-test.c
+)
+
+set (spawn-test_SOURCES
+    ${CMAKE_SOURCE_DIR}/../test/spawn-test.c
+)
+
+set (test-exit_SOURCES
+    ${CMAKE_SOURCE_DIR}/../test/test-exit.c
+)
+
+set (test-segfault_SOURCES
+    ${CMAKE_SOURCE_DIR}/../test/test-segfault.c
+)
+
+set (test-sleep-forever_SOURCES
+    ${CMAKE_SOURCE_DIR}/../test/test-sleep-forever.c
+)
+
+add_executable(test-service ${test-service_SOURCES})
+target_link_libraries(test-service dbus-testutils)
+
+add_executable(test-names ${test-names_SOURCES})
+target_link_libraries(test-names dbus-testutils)
+
+add_executable(shell-test ${shell-test_SOURCES})
+target_link_libraries(shell-test ${DBUS_INTERNAL_LIBRARIES})
+ADD_TEST(shell-test ${EXECUTABLE_OUTPUT_PATH}/shell-test${EXEEXT})
+
+add_executable(test-shell-service ${test-shell-service_SOURCES})
+target_link_libraries(test-shell-service dbus-testutils)
+
+add_executable(spawn-test ${spawn-test_SOURCES})
+target_link_libraries(spawn-test ${DBUS_INTERNAL_LIBRARIES})
+
+add_executable(test-exit ${test-exit_SOURCES})
+target_link_libraries(test-exit ${DBUS_INTERNAL_LIBRARIES})
+
+add_executable(test-segfault ${test-segfault_SOURCES})
+target_link_libraries(test-segfault ${DBUS_INTERNAL_LIBRARIES})
+
+add_executable(test-sleep-forever ${test-sleep-forever_SOURCES})
+target_link_libraries(test-sleep-forever ${DBUS_INTERNAL_LIBRARIES})
+
+### keep these in creation order, i.e. uppermost dirs first 
+set (TESTDIRS
+    test/data
+    test/data/valid-messages
+    test/data/invalid-messages
+    test/data/incomplete-messages
+    test/data/auth
+    test/data/sha-1
+    test/data/valid-config-files
+    test/data/valid-config-files/basic.d
+    test/data/valid-config-files/system.d
+    test/data/valid-config-files-system
+    test/data/valid-introspection-files
+    test/data/valid-messages
+    test/data/valid-service-files
+    test/data/valid-service-files-system
+    test/data/invalid-config-files
+    test/data/invalid-config-files-system
+    test/data/invalid-messages
+    test/data/invalid-service-files-system
+    test/data/equiv-config-files
+    test/data/equiv-config-files/basic
+    test/data/equiv-config-files/basic/basic.d
+    test/data/equiv-config-files/entities
+    test/data/equiv-config-files/entities/basic.d
+)
+set (CONFIG_VERBOSE 0)
+
+### copy tests to builddir so that generated tests and static tests 
+### are all in one place.
+MESSAGE(STATUS "Copying test files to test directory")
+FOREACH(FILE_TYPE *.message *.message-raw *.auth-script *.sha1 *.txt *.conf *.service)
+    FOREACH(DIR ${TESTDIRS})
+        FILE(GLOB FILES "${CMAKE_SOURCE_DIR}/../${DIR}/${FILE_TYPE}" )
+        FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/${DIR})
+        FOREACH(FILE ${FILES})
+            GET_FILENAME_COMPONENT(FILENAME ${FILE} NAME)
+            SET (TARGET ${CMAKE_BINARY_DIR}/${DIR}/${FILENAME})
+            configure_file(${FILE} ${TARGET} COPYONLY)
+            IF (CONFIG_VERBOSE)
+                MESSAGE("${FILE}")
+            ENDIF (CONFIG_VERBOSE)
+        ENDFOREACH(FILE)
+    ENDFOREACH(DIR)
+ENDFOREACH(FILE_TYPE)
+
+### generate test files
+MESSAGE(STATUS "Generating test files from templates into test directory")
+
+FOREACH(FILE_TYPE *.conf.in *.service.in)
+  FOREACH(DIR ${TESTDIRS})
+    FILE(GLOB FILES "${CMAKE_SOURCE_DIR}/../${DIR}/${FILE_TYPE}" )
+    FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/${DIR})
+    FOREACH(FILE ${FILES})
+      GET_FILENAME_COMPONENT(FILENAME ${FILE} NAME)
+      STRING(REGEX REPLACE "\\.in$" "" FILENAME ${FILENAME})
+      SET (TARGET ${CMAKE_BINARY_DIR}/${DIR}/${FILENAME})
+      configure_file(${FILE} ${TARGET} @ONLY IMMEDIATE)
+      IF (CONFIG_VERBOSE)
+        MESSAGE("${FILE}")
+      ENDIF (CONFIG_VERBOSE)
+    ENDFOREACH(FILE)
+  ENDFOREACH(DIR)
+ENDFOREACH(FILE_TYPE)
+
+MESSAGE(STATUS "Copying generated bus config files to test directory")
+set (OUTDIR ${CMAKE_BINARY_DIR}/test/data/valid-config-files)
+
+FILE(GLOB FILES "${CMAKE_BINARY_DIR}/bus/*.conf" )
+FILE(MAKE_DIRECTORY ${OUTDIR})
+FOREACH(FILE ${FILES})
+    GET_FILENAME_COMPONENT(FILENAME ${FILE} NAME)
+    SET (TARGET ${OUTDIR}/${FILENAME})
+    configure_file(${FILE} ${TARGET} COPYONLY)
+    IF (CONFIG_VERBOSE)
+        MESSAGE("FROM: ${FILE}\nTO: ${TARGET}\n")
+    ENDIF (CONFIG_VERBOSE)
+ENDFOREACH(FILE)
+
+# todo: for installation the TEST_..._BINARY variables must reflect the 
+#       installation dir or has to be defined relative
+#
diff --git a/dbus/cmake/test/name-test/CMakeLists.txt b/dbus/cmake/test/name-test/CMakeLists.txt
new file mode 100644
index 0000000..80b9908
--- /dev/null
+++ b/dbus/cmake/test/name-test/CMakeLists.txt
@@ -0,0 +1,39 @@
+if (DBUS_BUILD_TESTS)
+
+set (NAMEtest-DIR ../../../test/name-test)
+
+add_definitions(-DDBUS_COMPILATION)
+
+add_executable(test-pending-call-dispatch ${NAMEtest-DIR}/test-pending-call-dispatch.c)
+target_link_libraries(test-pending-call-dispatch ${DBUS_INTERNAL_LIBRARIES})
+ADD_TEST(test-pending-call-dispatch ${EXECUTABLE_OUTPUT_PATH}/test-pending-call-dispatch)
+
+add_executable(test-pending-call-timeout ${NAMEtest-DIR}/test-pending-call-timeout.c)
+target_link_libraries(test-pending-call-timeout ${DBUS_INTERNAL_LIBRARIES})
+ADD_TEST(test-pending-call-timeout ${EXECUTABLE_OUTPUT_PATH}/test-pending-call-timeout)
+
+add_executable(test-thread-init ${NAMEtest-DIR}/test-threads-init.c)
+target_link_libraries(test-thread-init ${DBUS_INTERNAL_LIBRARIES})
+ADD_TEST(test-thread-init ${EXECUTABLE_OUTPUT_PATH}/test-thread-init)
+
+add_executable(test-ids ${NAMEtest-DIR}/test-ids.c)
+target_link_libraries(test-ids ${DBUS_INTERNAL_LIBRARIES})
+ADD_TEST(test-ids ${EXECUTABLE_OUTPUT_PATH}/test-ids)
+
+add_executable(test-shutdown ${NAMEtest-DIR}/test-shutdown.c)
+target_link_libraries(test-shutdown dbus-testutils)
+ADD_TEST(test-shutdown ${EXECUTABLE_OUTPUT_PATH}/test-shutdown)
+
+add_executable(test-privserver ${NAMEtest-DIR}/test-privserver.c)
+target_link_libraries(test-privserver dbus-testutils)
+ADD_TEST(test-privserver ${EXECUTABLE_OUTPUT_PATH}/test-privserver)
+
+add_executable(test-privserver-client ${NAMEtest-DIR}/test-privserver-client.c)
+target_link_libraries(test-privserver-client dbus-testutils)
+ADD_TEST(test-privserver-client ${EXECUTABLE_OUTPUT_PATH}/test-privserver-client)
+
+add_executable(test-autolaunch ${NAMEtest-DIR}/test-autolaunch.c)
+target_link_libraries(test-autolaunch dbus-testutils)
+ADD_TEST(test-autolaunch ${EXECUTABLE_OUTPUT_PATH}/test-autolaunch)
+
+endif (DBUS_BUILD_TESTS)
diff --git a/dbus/cmake/tools/CMakeLists.txt b/dbus/cmake/tools/CMakeLists.txt
new file mode 100644
index 0000000..101c7e6
--- /dev/null
+++ b/dbus/cmake/tools/CMakeLists.txt
@@ -0,0 +1,49 @@
+project(tools)
+
+set (dbus_send_SOURCES
+	../../tools/dbus-print-message.c			
+	../../tools/dbus-print-message.h			
+	../../tools/dbus-send.c
+)
+
+set (dbus_monitor_SOURCES
+	../../tools/dbus-monitor.c				
+	../../tools/dbus-print-message.c			
+	../../tools/dbus-print-message.h
+)
+
+if (WIN32)
+set (dbus_launch_SOURCES
+	../../tools/dbus-launch-win.c
+)
+else (WIN32)
+set (dbus_launch_SOURCES
+	../../tools/dbus-launch.c
+)
+endif (WIN32)
+
+if (DBUS_BUILD_X11)
+set (dbus_launch_SOURCES
+     ${dbus_launch_SOURCES}
+     ../../tools/dbus-launch-x11.c
+)
+endif(DBUS_BUILD_X11)
+
+set (dbus_cleanup_sockets_SOURCES
+	../../tools/dbus-cleanup-sockets.c
+)
+
+add_executable(dbus-send ${dbus_send_SOURCES})
+target_link_libraries(dbus-send ${DBUS_LIBRARIES})
+install_targets(/bin dbus-send )
+
+add_executable(dbus-launch ${dbus_launch_SOURCES})
+target_link_libraries(dbus-launch )
+if (DBUS_BUILD_X11)
+  target_link_libraries(dbus-launch ${X11_LIBRARIES} )
+endif (DBUS_BUILD_X11)
+install_targets(/bin dbus-launch )
+
+add_executable(dbus-monitor ${dbus_monitor_SOURCES})
+target_link_libraries(dbus-monitor ${DBUS_LIBRARIES})
+install_targets(/bin dbus-monitor )
diff --git a/dbus/cmake/tools/dbus-launch.xml b/dbus/cmake/tools/dbus-launch.xml
new file mode 100644
index 0000000..dc34898
--- /dev/null
+++ b/dbus/cmake/tools/dbus-launch.xml
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<!-- lifted from troff+man by doclifter -->
+<refentry id='dbuslaunch1'>
+<!--   -->
+<!--  dbus\-launch manual page. -->
+<!--  Copyright (C) 2003 Red Hat, Inc. -->
+
+<refmeta>
+<refentrytitle>dbus-launch</refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+<refnamediv id='name'>
+<refname>dbus-launch</refname>
+<refpurpose>Utility to start a message bus from a shell script</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv id='synopsis'>
+<cmdsynopsis>
+  <command>dbus-launch</command>    <arg choice='opt'>--version </arg>
+    <arg choice='opt'>--sh-syntax </arg>
+    <arg choice='opt'>--csh-syntax </arg>
+    <arg choice='opt'>--auto-syntax </arg>
+    <arg choice='opt'>--exit-with-session </arg>
+    <arg choice='opt'>--autolaunch=<replaceable>MACHINEID</replaceable></arg>
+    <arg choice='opt'>--config-file=<replaceable>FILENAME</replaceable></arg>
+    <arg choice='opt'><replaceable>PROGRAM</replaceable></arg>
+    <arg choice='opt' rep='repeat'><replaceable>ARGS</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1 id='description'><title>DESCRIPTION</title>
+<para>The <command>dbus-launch</command> command is used to start a session bus 
+instance of <emphasis remap='I'>dbus-daemon</emphasis> from a shell script.
+It would normally be called from a user's login
+scripts. Unlike the daemon itself, <command>dbus-launch</command> exits, so
+backticks or the $() construct can be used to read information from
+<command>dbus-launch</command>.</para>
+
+<para>With no arguments, <command>dbus-launch</command> will launch a session bus
+instance and print the address and pid of that instance to standard
+output.</para>
+
+<para>You may specify a program to be run; in this case, <command>dbus-launch</command>
+will launch a session bus instance, set the appropriate environment
+variables so the specified program can find the bus, and then execute the
+specified program, with the specified arguments.  See below for
+examples.</para>
+
+<para>If you launch a program, <command>dbus-launch</command> will not print the
+information about the new bus to standard output.</para>
+
+<para>When <command>dbus-launch</command> prints bus information to standard output, by
+default it is in a simple key-value pairs format. However, you may 
+request several alternate syntaxes using the --sh-syntax, --csh-syntax,
+--binary-syntax, or
+--auto-syntax options. Several of these cause <command>dbus-launch</command> to emit shell code
+to set up the environment.</para>
+
+<para>With the --auto-syntax option, <command>dbus-launch</command> looks at the value
+of the SHELL environment variable to determine which shell syntax
+should be used.  If SHELL ends in "csh", then csh-compatible code is
+emitted; otherwise Bourne shell code is emitted.  Instead of passing
+--auto-syntax, you may explicity specify a particular one by using
+--sh-syntax for Bourne syntax, or --csh-syntax for csh syntax.
+In scripts, it's more robust to avoid --auto-syntax and you hopefully
+know which shell your script is written in.</para>
+
+
+<para>See <ulink url='http://www.freedesktop.org/software/dbus/'>http://www.freedesktop.org/software/dbus/</ulink> for more information
+about D-Bus. See also the man page for <emphasis remap='I'>dbus-daemon</emphasis>.</para>
+
+
+<para>Here is an example of how to use <command>dbus-launch</command> with an 
+sh-compatible shell to start the per-session bus daemon:</para>
+<literallayout remap='.nf'>
+
+  ## test for an existing bus daemon, just to be safe
+  if test -z "$DBUS_SESSION_BUS_ADDRESS" ; then
+      ## if not found, launch a new one
+      eval `dbus-launch --sh-syntax --exit-with-session`
+      echo "D-Bus per-session daemon address is: $DBUS_SESSION_BUS_ADDRESS"
+  fi
+
+</literallayout> <!-- .fi -->
+<para>You might run something like that in your login scripts.</para>
+
+
+<para>Another way to use <command>dbus-launch</command> is to run your main session
+program, like so:</para>
+<literallayout remap='.nf'>
+
+dbus-launch gnome-session
+
+</literallayout> <!-- .fi -->
+<para>The above would likely be appropriate for ~/.xsession or ~/.Xclients.</para>
+
+</refsect1>
+
+<refsect1 id='automatic_launching'><title>AUTOMATIC LAUNCHING</title>
+<para>If DBUS_SESSION_BUS_ADDRESS is not set for a process that tries to use
+D-Bus, by default the process will attempt to invoke dbus-launch with
+the --autolaunch option to start up a new session bus or find the 
+existing bus address on the X display or in a file in
+~/.dbus/session-bus/</para>
+
+
+<para>Whenever an autolaunch occurs, the application that had to
+start a new bus will be in its own little world; it can effectively
+end up starting a whole new session if it tries to use a lot of 
+bus services. This can be suboptimal or even totally broken, depending
+on the app and what it tries to do.</para>
+
+
+<para>There are two common reasons for autolaunch. One is ssh to a remote
+machine. The ideal fix for that would be forwarding of
+DBUS_SESSION_BUS_ADDRESS in the same way that DISPLAY is forwarded.
+In the meantime, you can edit the session.conf config file to 
+have your session bus listen on TCP, and manually set
+DBUS_SESSION_BUS_ADDRESS, if you like.</para>
+
+
+<para>The second common reason for autolaunch is an su to another user, and
+display of X applications running as the second user on the display
+belonging to the first user. Perhaps the ideal fix in this case
+would be to allow the second user to connect to the session bus of the
+first user, just as they can connect to the first user's display.
+However, a mechanism for that has not been coded.</para>
+
+
+<para>You can always avoid autolaunch by manually setting
+DBUS_SESSION_BUS_ADDRESS. Autolaunch happens because the default
+address if none is set is "autolaunch:", so if any other address is
+set there will be no autolaunch. You can however include autolaunch in
+an explicit session bus address as a fallback, for example
+DBUS_SESSION_BUS_ADDRESS="something:,autolaunch:" - in that case if
+the first address doesn't work, processes will autolaunch. (The bus
+address variable contains a comma-separated list of addresses to try.)</para>
+
+
+<para>The --autolaunch option is considered an internal implementation
+detail of libdbus, and in fact there are plans to change it. There's
+no real reason to use it outside of the libdbus implementation anyhow.</para>
+
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<para>The following options are supported:</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>--auto-syntax</option></term>
+  <listitem>
+<para>Choose --csh-syntax or --sh-syntax based on the SHELL environment variable.</para>
+
+<para><option>--binary-syntax</option>
+Write to stdout a nul-terminated bus address, then the bus PID as a
+binary integer of size sizeof(pid_t), then the bus X window ID as a
+binary integer of size sizeof(long). Integers are in the machine's
+byte order, not network byte order or any other canonical byte order.</para>
+
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--close-stderr</option></term>
+  <listitem>
+<para>Close the standard error output stream before starting the D-Bus
+daemon. This is useful if you want to capture dbus-launch error
+messages but you don't want dbus-daemon to keep the stream open to
+your application.</para>
+
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--config-file=FILENAME</option></term>
+  <listitem>
+<para>Pass --config-file=FILENAME to the bus daemon, instead of passing it 
+the --session argument. See the man page for dbus-daemon</para>
+
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--csh-syntax</option></term>
+  <listitem>
+<para>Emit csh compatible code to set up environment variables.</para>
+
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--exit-with-session</option></term>
+  <listitem>
+<para>If this option is provided, a persistent "babysitter" process will be 
+created that watches stdin for HUP and tries to connect to the X
+server. If this process gets a HUP on stdin or loses its X connection,
+it kills the message bus daemon.</para>
+
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--autolaunch=MACHINEID</option></term>
+  <listitem>
+<para>This option implies that <command>dbus-launch</command> should scan for a
+previously-started session and reuse the values found there. If no
+session is found, it will start a new session. The
+--exit-with-session option is implied if --autolaunch is given.
+This option is for the exclusive use of libdbus, you do not want to
+use it manually. It may change in the future.</para>
+
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--sh-syntax</option></term>
+  <listitem>
+<para>Emit Bourne-shell compatible code to set up environment variables.</para>
+
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--version</option></term>
+  <listitem>
+<para>Print the version of dbus-launch</para>
+
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='author'><title>AUTHOR</title>
+<para>See <ulink url='http://www.freedesktop.org/software/dbus/doc/AUTHORS'>http://www.freedesktop.org/software/dbus/doc/AUTHORS</ulink></para>
+
+</refsect1>
+
+<refsect1 id='bugs'><title>BUGS</title>
+<para>Please send bug reports to the D-Bus mailing list or bug tracker,
+see <ulink url='http://www.freedesktop.org/software/dbus/'>http://www.freedesktop.org/software/dbus/</ulink></para>
+</refsect1>
+</refentry>
+
diff --git a/dbus/cmake/tools/dbus-monitor.xml b/dbus/cmake/tools/dbus-monitor.xml
new file mode 100644
index 0000000..b41cace
--- /dev/null
+++ b/dbus/cmake/tools/dbus-monitor.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<!-- lifted from troff+man by doclifter -->
+<refentry id='dbusmonitor1'>
+<!--   -->
+<!--  dbus\-monitor manual page. -->
+<!--  Copyright (C) 2003 Red Hat, Inc. -->
+
+<refmeta>
+<refentrytitle>dbus-monitor</refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+<refnamediv id='name'>
+<refname>dbus-monitor</refname>
+<refpurpose>debug probe to print message bus messages</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv id='synopsis'>
+<cmdsynopsis>
+  <command>dbus-monitor</command>    
+    <group choice='opt'><arg choice='plain'>--system </arg><arg choice='plain'>--session </arg><arg choice='plain'>--address <replaceable>ADDRESS</replaceable></arg></group>
+    <group choice='opt'><arg choice='plain'>--profile </arg><arg choice='plain'>--monitor </arg></group>
+    <arg choice='opt'><arg choice='plain'><replaceable>watch</replaceable></arg><arg choice='plain'><replaceable>expressions</replaceable></arg></arg>
+    <sbr/>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1 id='description'><title>DESCRIPTION</title>
+<para>The <command>dbus-monitor</command> command is used to monitor messages going
+through a D-Bus message bus.  See
+<ulink url='http://www.freedesktop.org/software/dbus/'>http://www.freedesktop.org/software/dbus/</ulink> for more information about
+the big picture.</para>
+
+
+<para>There are two well-known message buses: the systemwide message bus
+(installed on many systems as the "messagebus" service) and the
+per-user-login-session message bus (started each time a user logs in).
+The --system and --session options direct <command>dbus-monitor</command> to
+monitor the system or session buses respectively.  If neither is
+specified, <command>dbus-monitor</command> monitors the session bus.</para>
+
+
+<para><command>dbus-monitor</command> has two different output modes, the 'classic'-style
+monitoring mode and profiling mode. The profiling format is a compact
+format with a single line per message and microsecond-resolution timing
+information. The --profile and --monitor options select the profiling
+and monitoring output format respectively. If neither is specified,
+<command>dbus-monitor</command> uses the monitoring output format.</para>
+
+
+<para>In order to get <command>dbus-monitor</command> to see the messages you are interested
+in, you should specify a set of watch expressions as you would expect to
+be passed to the <emphasis remap='I'>dbus_bus_add_match</emphasis> function.</para>
+
+
+<para>The message bus configuration may keep <command>dbus-monitor</command> from seeing
+all messages, especially if you run the monitor as a non-root user.</para>
+
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>--system</option></term>
+  <listitem>
+<para>Monitor the system message bus.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--session</option></term>
+  <listitem>
+<para>Monitor the session message bus.  (This is the default.)</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--address ADDRESS</option></term>
+  <listitem>
+<para>Monitor an arbitrary message bus given at ADDRESS.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--profile</option></term>
+  <listitem>
+<para>Use the profiling output format.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--monitor</option></term>
+  <listitem>
+<para>Use the monitoring output format.  (This is the default.)</para>
+
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='example'><title>EXAMPLE</title>
+<para>Here is an example of using dbus-monitor to watch for the gnome typing
+monitor to say things</para>
+<literallayout remap='.nf'>
+
+  dbus-monitor "type='signal',sender='org.gnome.TypingMonitor',interface='org.gnome.TypingMonitor'"
+
+</literallayout> <!-- .fi -->
+
+</refsect1>
+
+<refsect1 id='author'><title>AUTHOR</title>
+<para>dbus-monitor was written by Philip Blundell.
+The profiling output mode was added by Olli Salli.</para>
+
+</refsect1>
+
+<refsect1 id='bugs'><title>BUGS</title>
+<para>Please send bug reports to the D-Bus mailing list or bug tracker,
+see <ulink url='http://www.freedesktop.org/software/dbus/'>http://www.freedesktop.org/software/dbus/</ulink></para>
+</refsect1>
+</refentry>
+
diff --git a/dbus/cmake/tools/dbus-send.xml b/dbus/cmake/tools/dbus-send.xml
new file mode 100644
index 0000000..7fefc03
--- /dev/null
+++ b/dbus/cmake/tools/dbus-send.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+                   "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<!-- lifted from troff+man by doclifter -->
+<refentry id='dbussend1'>
+<!--   -->
+<!--  dbus\-send manual page. -->
+<!--  Copyright (C) 2003 Red Hat, Inc. -->
+
+<refmeta>
+<refentrytitle>dbus-send</refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+<refnamediv id='name'>
+<refname>dbus-send</refname>
+<refpurpose>Send a message to a message bus</refpurpose>
+</refnamediv>
+<!-- body begins here -->
+<refsynopsisdiv id='synopsis'>
+<cmdsynopsis>
+  <command>dbus-send</command>    
+    <group choice='opt'><arg choice='plain'>--system </arg><arg choice='plain'>--session </arg></group>
+    <arg choice='opt'>--dest=<replaceable>NAME</replaceable></arg>
+    <arg choice='opt'>--print-reply </arg>
+    <arg choice='opt'>--type=<replaceable>TYPE</replaceable></arg>
+    <arg choice='plain'><replaceable>&lt;destination</replaceable></arg>
+    <arg choice='plain'><replaceable>object</replaceable></arg>
+    <arg choice='plain'><replaceable>path&gt;</replaceable></arg>
+    <arg choice='plain'><replaceable>&lt;message</replaceable></arg>
+    <arg choice='plain'><replaceable>name&gt;</replaceable></arg>
+    <arg choice='opt' rep='repeat'><replaceable>contents</replaceable></arg>
+    <sbr/>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+
+<refsect1 id='description'><title>DESCRIPTION</title>
+<para>The <command>dbus-send</command> command is used to send a message to a D-Bus message
+bus. See <ulink url='http://www.freedesktop.org/software/dbus/'>http://www.freedesktop.org/software/dbus/</ulink> for more 
+information about the big picture.</para>
+
+
+<para>There are two well-known message buses: the systemwide message bus 
+(installed on many systems as the "messagebus" service) and the 
+per-user-login-session message bus (started each time a user logs in).
+The --system and --session options direct <command>dbus-send</command> to send
+messages to the system or session buses respectively.  If neither is
+specified, <command>dbus-send</command> sends to the session bus.</para>
+
+
+<para>Nearly all uses of <command>dbus-send</command> must provide the --dest argument
+which is the name of a connection on the bus to send the message to. If
+--dest is omitted, no destination is set.</para>
+
+
+<para>The object path and the name of the message to send must always be
+specified. Following arguments, if any, are the message contents
+(message arguments).  These are given as type-specified values and 
+may include containers (arrays, dicts, and variants) as described below.</para>
+
+<literallayout remap='.nf'>
+&lt;contents&gt;   ::= &lt;item&gt; | &lt;container&gt; [ &lt;item&gt; | &lt;container&gt;...]
+&lt;item&gt;       ::= &lt;type&gt;:&lt;value&gt;
+&lt;container&gt;  ::= &lt;array&gt; | &lt;dict&gt; | &lt;variant&gt;
+&lt;array&gt;      ::= array:&lt;type&gt;:&lt;value&gt;[,&lt;value&gt;...] 
+&lt;dict&gt;       ::= dict:&lt;type&gt;:&lt;type&gt;:&lt;key&gt;,&lt;value&gt;[,&lt;key&gt;,&lt;value&gt;...]
+&lt;variant&gt;    ::= variant:&lt;type&gt;:&lt;value&gt;
+&lt;type&gt;       ::= string | int16 | uint 16 | int32 | uint32 | int64 | uint64 | double | byte | boolean | objpath
+</literallayout> <!-- .fi -->
+
+<para>D-Bus supports more types than these, but <command>dbus-send</command> currently
+does not.  Also, <command>dbus-send</command> does not permit empty containers
+or nested containers (e.g. arrays of variants).</para>
+
+
+<para>Here is an example invocation:</para>
+<literallayout remap='.nf'>
+
+  dbus-send --dest=org.freedesktop.ExampleName               \
+            /org/freedesktop/sample/object/name              \
+            org.freedesktop.ExampleInterface.ExampleMethod   \
+            int32:47 string:'hello world' double:65.32       \
+            array:string:"1st item","next item","last item"  \
+            dict:string:int32:"one",1,"two",2,"three",3      \
+            variant:int32:-8                                 \
+            objpath:/org/freedesktop/sample/object/name 
+
+</literallayout> <!-- .fi -->
+
+<para>Note that the interface is separated from a method or signal 
+name by a dot, though in the actual protocol the interface
+and the interface member are separate fields.</para>
+
+</refsect1>
+
+<refsect1 id='options'><title>OPTIONS</title>
+<para>The following options are supported:</para>
+<variablelist remap='TP'>
+  <varlistentry>
+  <term><option>--dest=NAME</option></term>
+  <listitem>
+<para>Specify the name of the connection to receive the message.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--print-reply</option></term>
+  <listitem>
+<para>Block for a reply to the message sent, and print any reply received.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--system</option></term>
+  <listitem>
+<para>Send to the system message bus.</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--session</option></term>
+  <listitem>
+<para>Send to the session message bus.  (This is the default.)</para>
+  </listitem>
+  </varlistentry>
+  <varlistentry>
+  <term><option>--type=TYPE</option></term>
+  <listitem>
+<para>Specify "method_call" or "signal" (defaults to "signal").</para>
+
+  </listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1 id='author'><title>AUTHOR</title>
+<para>dbus-send was written by Philip Blundell.</para>
+
+</refsect1>
+
+<refsect1 id='bugs'><title>BUGS</title>
+<para>Please send bug reports to the D-Bus mailing list or bug tracker,
+see <ulink url='http://www.freedesktop.org/software/dbus/'>http://www.freedesktop.org/software/dbus/</ulink></para>
+</refsect1>
+</refentry>
+
diff --git a/dbus/config.h b/dbus/config.h
new file mode 100644
index 0000000..86707e2
--- /dev/null
+++ b/dbus/config.h
@@ -0,0 +1,303 @@
+/* config.h.in.  Generated from configure.in by autoheader.  */
+#include <cutils/sockets.h>
+
+/* Directory for installing the binaries */
+#define DBUS_BINDIR "/system/bin"
+
+/* Build test code */
+#undef DBUS_BUILD_TESTS
+
+/* Build X11-dependent code */
+#undef DBUS_BUILD_X11
+
+/* whether -export-dynamic was passed to libtool */
+#undef DBUS_BUILT_R_DYNAMIC
+
+/* Use dnotify on Linux */
+#undef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX
+
+/* Use kqueue */
+#undef DBUS_BUS_ENABLE_KQUEUE
+
+/* Directory to check for console ownerhip */
+#define DBUS_CONSOLE_AUTH_DIR "/etc"
+
+/* File to check for console ownerhip */
+#undef DBUS_CONSOLE_OWNER_FILE
+
+/* Directory for installing the DBUS daemon */
+#define DBUS_DAEMONDIR "/system/bin"
+
+/* Directory for installing DBUS data files */
+#define DBUS_DATADIR "/data"
+
+/* Disable assertion checking */
+#undef DBUS_DISABLE_ASSERT
+
+/* Disable public API sanity checking */
+#undef DBUS_DISABLE_CHECKS
+
+/* Support a verbose mode */
+#undef DBUS_ENABLE_VERBOSE_MODE
+
+/* Defined if gcov is enabled to force a rebuild due to config.h changing */
+#undef DBUS_GCOV_ENABLED
+
+/* Some atomic integer implementation present */
+#undef DBUS_HAVE_ATOMIC_INT
+
+
+        #if (defined(__i386__) || defined(__x86_64__))
+        # define DBUS_HAVE_ATOMIC_INT 1
+        #endif
+      
+
+/* Defined if we have gcc 3.3 and thus the new gcov format */
+#undef DBUS_HAVE_GCC33_GCOV
+
+/* Where per-session bus puts its sockets */
+#define DBUS_SESSION_SOCKET_DIR "/data"
+
+/* The default D-Bus address of the system bus */
+#define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path="DBUS_SYSTEM_SOCKET
+
+/* The name of the socket the system bus listens on by default */
+#define DBUS_SYSTEM_SOCKET ANDROID_SOCKET_DIR"/dbus"
+
+/* Where to put test sockets */
+#define DBUS_TEST_SOCKET_DIR "/data"
+
+/* User for running the system BUS daemon */
+#undef DBUS_USER
+
+/* Use atomic integer implementation for 486 */
+#undef DBUS_USE_ATOMIC_INT_486
+
+
+              #if (defined(__i386__) || defined(__x86_64__))
+              # define DBUS_USE_ATOMIC_INT_486 1
+              #endif
+            
+
+/* A 'va_copy' style function */
+#define DBUS_VA_COPY va_copy
+
+/* 'va_lists' cannot be copies as values */
+#undef DBUS_VA_COPY_AS_ARRAY
+
+/* The name of the gettext domain */
+#undef GETTEXT_PACKAGE
+
+/* Disable GLib assertion macros */
+#undef G_DISABLE_ASSERT 
+
+/* Disable GLib public API sanity checking */
+#undef G_DISABLE_CHECKS
+
+/* Have abstract socket namespace */
+#undef HAVE_ABSTRACT_SOCKETS
+
+/* Define to 1 if you have the `backtrace' function. */
+#undef HAVE_BACKTRACE
+
+/* Have cmsgcred structure */
+#undef HAVE_CMSGCRED
+
+/* Have console owner file */
+#undef HAVE_CONSOLE_OWNER_FILE
+
+/* Have the ddfd member of DIR */
+#undef HAVE_DDFD
+
+/* Have dirfd function */
+#undef HAVE_DIRFD
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <execinfo.h> header file. */
+#define HAVE_EXECINFO_H 1
+
+/* Define to 1 if you have the <expat.h> header file. */
+#define HAVE_EXPAT_H 1
+
+/* Define to 1 if you have the `fpathconf' function. */
+#undef HAVE_FPATHCONF
+
+/* Define to 1 if you have the `getgrouplist' function. */
+#define HAVE_GETGROUPLIST 1
+
+/* Define to 1 if you have the `getpeereid' function. */
+#undef HAVE_GETPEEREID
+
+/* Define to 1 if you have the `getpeerucred' function. */
+#undef HAVE_GETPEERUCRED
+
+/* Have GNU-style varargs macros */
+#undef HAVE_GNUC_VARARGS
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Have ISO C99 varargs macros */
+#define HAVE_ISO_VARARGS 1
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `nanosleep' function. */
+#define HAVE_NANOSLEEP 1
+
+/* Have non-POSIX function getpwnam_r */
+#undef HAVE_NONPOSIX_GETPWNAM_R
+
+/* Define to 1 if you have the `poll' function. */
+#define HAVE_POLL 1
+
+/* Have POSIX function getpwnam_r */
+#undef HAVE_POSIX_GETPWNAM_R
+
+/* SELinux support */
+#undef HAVE_SELINUX
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the `socketpair' function. */
+#define HAVE_SOCKETPAIR 1
+
+/* Have socklen_t type */
+#define HAVE_SOCKLEN_T 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/syslimits.h> header file. */
+#undef HAVE_SYS_SYSLIMITS_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+/* actually defined by AndroidConfig.h, commented to get rid of compiler warnings #define HAVE_SYS_UIO_H 1 */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `unsetenv' function. */
+#define HAVE_UNSETENV 1
+
+/* Define to 1 if you have the `usleep' function. */
+#define HAVE_USLEEP 1
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `writev' function. */
+#define HAVE_WRITEV 1
+
+/* Name of package */
+#define PACKAGE "dbus"
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "dbus"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "dbus-0.95"
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.95"
+
+/* The size of a `char', as computed by sizeof. */
+#define SIZEOF_CHAR sizeof(char)
+
+/* The size of a `int', as computed by sizeof. */
+#define SIZEOF_INT sizeof(int)
+
+/* The size of a `long', as computed by sizeof. */
+#define SIZEOF_LONG sizeof(long)
+
+/* The size of a `long long', as computed by sizeof. */
+#define SIZEOF_LONG_LONG sizeof(long long)
+
+/* The size of a `short', as computed by sizeof. */
+#define SIZEOF_SHORT sizeof(short)
+
+/* The size of a `void *', as computed by sizeof. */
+#define SIZEOF_VOID_P sizeof(void *)
+
+/* The size of a `__int64', as computed by sizeof. */
+#define SIZEOF___INT64 sizeof(long long)
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Full path to the daemon in the builddir */
+#define TEST_BUS_BINARY "/system/bin/dbus-test"
+
+/* Full path to test file test/test-exit in builddir */
+#define TEST_EXIT_BINARY "/system/bin/dbus-test-exit"
+
+/* Full path to test file test/test-segfault in builddir */
+#define TEST_SEGFAULT_BINARY "/system/bin/dbus-test-segfault"
+
+/* Full path to test file test/test-service in builddir */
+#define TEST_SERVICE_BINARY "/system/bin/dbus-test-service"
+
+/* Full path to test file test/data/valid-service-files in builddir */
+#define TEST_SERVICE_DIR "/etc/dbus-test-data/valid-service-files"
+
+/* Full path to test file test/test-shell-service in builddir */
+#define TEST_SHELL_SERVICE_BINARY "/system/bin/dbus-shell-service"
+
+/* Full path to test file test/test-sleep-forever in builddir */
+#define TEST_SLEEP_FOREVER_BINARY "/system/bin/dbus-sleep-forever"
+
+/* Version number of package */
+#define VERSION "0.95"
+
+/* 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
+
+
+			/* Use the compiler-provided endianness defines to allow universal compiling. */
+			#if defined(__BIG_ENDIAN__)
+			#define WORDS_BIGENDIAN 1
+			#endif
+		
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#define X_DISPLAY_MISSING 1
+
+#define HAVE_UNIX_FD_PASSING 1
diff --git a/dbus/configure.ac b/dbus/configure.ac
new file mode 100644
index 0000000..24fcc9e
--- /dev/null
+++ b/dbus/configure.ac
@@ -0,0 +1,1841 @@
+dnl -*- mode: m4 -*-
+AC_PREREQ([2.63])
+
+m4_define([dbus_major_version], [1])
+m4_define([dbus_minor_version], [6])
+m4_define([dbus_micro_version], [8])
+m4_define([dbus_version],
+          [dbus_major_version.dbus_minor_version.dbus_micro_version])
+AC_INIT([dbus],[dbus_version],[https://bugs.freedesktop.org/enter_bug.cgi?product=dbus],[dbus])
+
+AC_CANONICAL_HOST
+
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+AM_INIT_AUTOMAKE([1.10 tar-ustar -Wno-portability])
+
+GETTEXT_PACKAGE=dbus-1
+AC_SUBST(GETTEXT_PACKAGE)
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[The name of the gettext domain])
+
+# By default, rebuild autotools files on demand; only use ./missing if the
+# user says --disable-maintainer-mode (some distributions like to do this)
+AM_MAINTAINER_MODE([enable])
+
+m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+
+AC_DEFINE_UNQUOTED(DBUS_DAEMON_NAME,"dbus-daemon",[Name of executable])
+
+# libtool versioning - this applies to libdbus
+#
+# See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details
+#
+
+## increment if the interface has additions, changes, removals.
+LT_CURRENT=10
+
+## increment any time the source changes; set to
+##  0 if you increment CURRENT
+LT_REVISION=2
+
+## increment if any interfaces have been added; set to 0
+## if any interfaces have been changed or removed. removal has
+## precedence over adding, so set to 0 if both happened.
+LT_AGE=7
+
+AC_SUBST(LT_CURRENT)
+AC_SUBST(LT_REVISION)
+AC_SUBST(LT_AGE)
+
+DBUS_MAJOR_VERSION=dbus_major_version
+DBUS_MINOR_VERSION=dbus_minor_version
+DBUS_MICRO_VERSION=dbus_micro_version
+DBUS_VERSION=dbus_major_version.dbus_minor_version.dbus_micro_version
+
+AC_SUBST(DBUS_MAJOR_VERSION)
+AC_SUBST(DBUS_MINOR_VERSION)
+AC_SUBST(DBUS_MICRO_VERSION)
+AC_SUBST(DBUS_VERSION)
+
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_CXX
+AC_USE_SYSTEM_EXTENSIONS
+AC_ISC_POSIX
+AC_HEADER_STDC
+AC_C_INLINE
+AM_PROG_LIBTOOL
+AC_PROG_MKDIR_P
+COMPILER_COVERAGE
+COMPILER_OPTIMISATIONS
+PKG_PROG_PKG_CONFIG
+
+# Initialize libtool
+LT_INIT([win32-dll])
+LT_LANG([Windows Resource])
+
+# Set some internal variables depending on the platform for later use.
+dbus_win=no
+dbus_cygwin=no
+dbus_unix=no
+case "${host}" in
+    *-mingw32ce*)
+        dbus_win=yes
+        dbus_wince=yes
+        ;;
+    *-mingw32*)
+        dbus_win=yes
+        ;;
+    *-cygwin*)
+        dbus_cygwin=yes
+        dbus_unix=yes
+        ;;
+    *)
+        dbus_unix=yes
+       ;;
+esac
+
+# Special defines for certain platforms
+if test "$dbus_win" = yes; then
+    AC_DEFINE(DBUS_WIN,1,[Defined if we run on a W32 API based system])
+    BUILD_TIMESTAMP=`date --iso-8601=minutes`
+    AC_SUBST(BUILD_TIMESTAMP)
+    # Assume DBUS_VERSION is always three numbers
+    BUILD_FILEVERSION=`echo "$DBUS_VERSION" | sed -e 's/\./,/g'`,0
+    AC_SUBST(BUILD_FILEVERSION)
+    AC_CHECK_TOOL(WINDRES, windres, no)
+    if test "$WINDRES" = no; then
+      AC_MSG_ERROR([*** Could not find an implementation of windres in your PATH.])
+    fi
+    if test "$dbus_wince" = yes; then
+      AC_DEFINE(DBUS_WINCE,1,[Defined if we run on a W32 CE API based system])
+      AC_DEFINE(_WIN32_WCE, 0x0502, [Defined to get newer W32 CE APIs])
+    fi
+else
+    AC_DEFINE(DBUS_UNIX,1,[Defined if we run on a Unix-based system])
+fi
+if test "$dbus_cygwin" = yes; then
+    AC_DEFINE(DBUS_CYGWIN,1,[Defined if we run on a cygwin API based system])
+fi
+
+AM_CONDITIONAL(DBUS_WIN, test "$dbus_win" = yes)
+AM_CONDITIONAL(DBUS_WINCE, test "$dbus_wince" = yes)
+AM_CONDITIONAL(DBUS_UNIX, test "$dbus_unix" = yes)
+AM_CONDITIONAL(DBUS_CYGWIN, test "$dbus_cygwin" = yes)
+
+# this must come first: other options use this to set their defaults
+AC_ARG_ENABLE([developer],
+  [AS_HELP_STRING([--enable-developer],
+    [set defaults to be appropriate for a D-Bus developer instead of a distribution/end-user])],
+  [],
+  [enable_developer=no])
+
+DBUS_STATIC_BUILD_CPPFLAGS=
+if test "x$enable_shared" = xno; then
+    # On Windows, linking against the static library requires special effort
+    # to turn off DLL import/export processing. We normally link some things
+    # against the dynamic library, but if we're not building that, we'll
+    # have to link everything statically.
+    DBUS_STATIC_BUILD_CPPFLAGS=-DDBUS_STATIC_BUILD
+fi
+AC_SUBST([DBUS_STATIC_BUILD_CPPFLAGS])
+
+AC_ARG_ENABLE(ansi, AS_HELP_STRING([--enable-ansi],[enable -ansi -pedantic gcc flags]),enable_ansi=$enableval,enable_ansi=no)
+AC_ARG_ENABLE(verbose-mode, AS_HELP_STRING([--enable-verbose-mode],[support verbose debug mode]),enable_verbose_mode=$enableval,enable_verbose_mode=$enable_developer)
+AC_ARG_ENABLE(asserts, AS_HELP_STRING([--enable-asserts],[include assertion checks]),enable_asserts=$enableval,enable_asserts=$enable_developer)
+AC_ARG_ENABLE(checks, AS_HELP_STRING([--enable-checks],[include sanity checks on public API]),enable_checks=$enableval,enable_checks=yes)
+AC_ARG_ENABLE(xml-docs, AS_HELP_STRING([--enable-xml-docs],[build XML documentation (requires xmlto)]),enable_xml_docs=$enableval,enable_xml_docs=auto)
+AC_ARG_ENABLE(doxygen-docs, AS_HELP_STRING([--enable-doxygen-docs],[build DOXYGEN documentation (requires Doxygen)]),enable_doxygen_docs=$enableval,enable_doxygen_docs=auto)
+AC_ARG_ENABLE(abstract-sockets, AS_HELP_STRING([--enable-abstract-sockets],[use abstract socket namespace (linux only)]),enable_abstract_sockets=$enableval,enable_abstract_sockets=auto)
+AC_ARG_ENABLE(selinux, AS_HELP_STRING([--enable-selinux],[build with SELinux support]),enable_selinux=$enableval,enable_selinux=auto)
+AC_ARG_ENABLE(libaudit,AS_HELP_STRING([--enable-libaudit],[build audit daemon support for SELinux]),enable_libaudit=$enableval,enable_libaudit=auto)
+AC_ARG_ENABLE(dnotify, AS_HELP_STRING([--enable-dnotify],[build with dnotify support (linux only)]),enable_dnotify=$enableval,enable_dnotify=auto)
+AC_ARG_ENABLE(inotify, AS_HELP_STRING([--enable-inotify],[build with inotify support (linux only)]),enable_inotify=$enableval,enable_inotify=auto)
+AC_ARG_ENABLE(kqueue, AS_HELP_STRING([--enable-kqueue],[build with kqueue support]),enable_kqueue=$enableval,enable_kqueue=auto)
+AC_ARG_ENABLE(console-owner-file, AS_HELP_STRING([--enable-console-owner-file],[enable console owner file]),enable_console_owner_file=$enableval,enable_console_owner_file=auto)
+AC_ARG_ENABLE(userdb-cache, AS_HELP_STRING([--enable-userdb-cache],[build with userdb-cache support]),enable_userdb_cache=$enableval,enable_userdb_cache=yes)
+AC_ARG_ENABLE(launchd, AS_HELP_STRING([--enable-launchd],[build with launchd auto-launch support]),enable_launchd=$enableval,enable_launchd=auto)
+AC_ARG_ENABLE(systemd, AS_HELP_STRING([--enable-systemd],[build with systemd at_console support]),enable_systemd=$enableval,enable_systemd=auto)
+
+AC_ARG_WITH(xml, AS_HELP_STRING([--with-xml=[libxml/expat]],[XML library to use (libxml may be named libxml2 on some systems)]))
+AC_ARG_WITH(init-scripts, AS_HELP_STRING([--with-init-scripts=[redhat]],[Style of init scripts to install]))
+AC_ARG_WITH(session-socket-dir, AS_HELP_STRING([--with-session-socket-dir=[dirname]],[Where to put sockets for the per-login-session message bus]))
+AC_ARG_WITH(test-socket-dir, AS_HELP_STRING([--with-test-socket-dir=[dirname]],[Where to put sockets for make check]))
+AC_ARG_WITH(system-pid-file, AS_HELP_STRING([--with-system-pid-file=[pidfile]],[PID file for systemwide daemon]))
+AC_ARG_WITH(system-socket, AS_HELP_STRING([--with-system-socket=[filename]],[UNIX domain socket for systemwide daemon]))
+AC_ARG_WITH(console-auth-dir, AS_HELP_STRING([--with-console-auth-dir=[dirname]],[directory to check for console ownerhip]))
+AC_ARG_WITH(console-owner-file, AS_HELP_STRING([--with-console-owner-file=[filename]],[file whose owner determines current console owner]))
+AC_ARG_WITH(launchd-agent-dir, AS_HELP_STRING([--with-launchd-agent-dir=[dirname]],[directory to put the launchd agent (default: /Library/LaunchAgents)]))
+AC_ARG_WITH(dbus_user, AS_HELP_STRING([--with-dbus-user=<user>],[User for running the DBUS daemon (messagebus)]))
+AC_ARG_WITH(dbus_daemondir, AS_HELP_STRING([--with-dbus-daemondir=[dirname]],[Directory for installing the DBUS daemon]))
+AC_ARG_WITH(dbus_session_bus_default_address, AS_HELP_STRING([--with-dbus-session-bus-default-address=[nonce-tcp:/autolaunch:/tcp:host:port]],[Transport Type to be used (default: nonce-tcp:)]),with_dbus_session_bus_default_address=$withval,with_dbus_session_bus_default_address=nonce-tcp:)
+
+AC_ARG_ENABLE([embedded-tests],
+  AS_HELP_STRING([--enable-embedded-tests],
+    [enable unit test code in the library and binaries]),
+  [], [enable_embedded_tests=$enable_developer])
+AC_ARG_ENABLE([modular-tests],
+  AS_HELP_STRING([--enable-modular-tests],
+    [enable modular regression tests (requires GLib)]),
+  [], [enable_modular_tests=auto])
+# --enable-tests overrides both --enable-embedded-tests and
+# --enable-modular-tests
+AC_ARG_ENABLE([tests],
+  AS_HELP_STRING([--enable-tests],
+    [enable/disable all tests, overriding embedded-tests/modular-tests]),
+  [
+  if test "x$enableval" = xyes; then
+    AC_MSG_NOTICE([Full test coverage was requested with --enable-tests=yes])
+    AC_MSG_NOTICE([This has many dependencies (GLib, dbus-glib, Python)])
+  fi
+  enable_embedded_tests=$enableval
+  enable_modular_tests=$enableval
+  ],
+  [])
+
+# DBUS_ENABLE_EMBEDDED_TESTS controls unit tests built in to .c files
+# and also some stuff in the test/ subdir. DBUS_BUILD_TESTS was an older
+# name for this.
+AM_CONDITIONAL([DBUS_BUILD_TESTS], [test "x$enable_embedded_tests" = xyes])
+AM_CONDITIONAL([DBUS_ENABLE_EMBEDDED_TESTS],
+  [test "x$enable_embedded_tests" = xyes])
+if test "x$enable_embedded_tests" = xyes; then
+    AC_DEFINE([DBUS_ENABLE_EMBEDDED_TESTS], [1],
+      [Define to build test code into the library and binaries])
+    AC_DEFINE([DBUS_BUILD_TESTS], [1],
+      [Define to build test code into the library and binaries])
+fi
+
+# DBUS_ENABLE_MODULAR_TESTS controls tests that work based on public API.
+# These use GTest, from GLib, because life's too short. They're enabled by
+# default (unless you don't have GLib), because they don't bloat the library
+# or binaries.
+
+with_glib=yes
+
+if test "x$enable_modular_tests" != xno; then
+  PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.24, gio-2.0 >= 2.24],
+    [],
+    [if test "x$enable_modular_tests" = xyes; then
+      AC_MSG_NOTICE([Full test coverage (--enable-modular-tests=yes or --enable-tests=yes) requires GLib])
+      AC_MSG_ERROR([$GLIB_ERRORS])
+    else # assumed to be "auto"
+      with_glib=no
+    fi])
+  # If dbus-gmain.[ch] returned to libdbus then we wouldn't need this
+  PKG_CHECK_MODULES([DBUS_GLIB], [dbus-glib-1],
+    [],
+    [if test "x$enable_modular_tests" = xyes; then
+      AC_MSG_NOTICE([Full test coverage (--enable-modular-tests=yes or --enable-tests=yes) requires dbus-glib])
+      AC_MSG_ERROR([$DBUS_GLIB_ERRORS])
+    else # assumed to be "auto"
+      with_glib=no
+    fi])
+fi
+if test "x$enable_modular_tests" != xno; then
+  AC_DEFINE([DBUS_ENABLE_MODULAR_TESTS], [1],
+    [Define to build independent test binaries])
+fi
+AM_CONDITIONAL([DBUS_ENABLE_MODULAR_TESTS],
+  [test "x$enable_modular_tests" != xno])
+
+if test "x$with_glib" != xno; then
+  AC_DEFINE([DBUS_WITH_GLIB], [1],
+    [Define if GLib, GObject, GIO are available])
+fi
+AM_CONDITIONAL([DBUS_WITH_GLIB], [test "x$with_glib" != xno])
+
+AC_ARG_ENABLE([installed-tests],
+  AS_HELP_STRING([--enable-installed-tests],
+    [enable unit test code in the library and binaries]),
+  [], [enable_installed_tests=no])
+AM_CONDITIONAL([DBUS_ENABLE_INSTALLED_TESTS],
+  [test "x$enable_installed_tests" = xyes])
+
+if test "x$enable_tests" = xyes; then
+  # full test coverage is required, Python is a hard dependency
+  AC_MSG_NOTICE([Full test coverage (--enable-tests=yes) requires Python, dbus-python, pygobject])
+  AM_PATH_PYTHON([2.6])
+  AC_MSG_CHECKING([for Python modules for full test coverage])
+  if "$PYTHON" -c "import dbus, gobject, dbus.mainloop.glib"; then
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+    AC_MSG_ERROR([cannot import dbus, gobject, dbus.mainloop.glib Python modules])
+  fi
+else
+  # --enable-tests not given: do not abort if Python is missing
+  AM_PATH_PYTHON([2.6], [], [:])
+fi
+
+if test x$enable_verbose_mode = xyes; then
+    AC_DEFINE(DBUS_ENABLE_VERBOSE_MODE,1,[Support a verbose mode])
+fi
+
+if test x$enable_asserts = xno; then
+    AC_DEFINE(DBUS_DISABLE_ASSERT,1,[Disable assertion checking])
+    DISABLE_UNUSED_WARNINGS="unused-label"
+    R_DYNAMIC_LDFLAG=""
+else
+    # -rdynamic is needed for glibc's backtrace_symbols to work.
+    # No clue how much overhead this adds, but it's useful
+    # to do this on any assertion failure,
+    # so for now it's enabled anytime asserts are (currently not
+    # in production builds).
+
+    # To get -rdynamic you pass -export-dynamic to libtool.
+    AC_DEFINE(DBUS_BUILT_R_DYNAMIC,1,[whether -export-dynamic was passed to libtool])
+    R_DYNAMIC_LDFLAG=-export-dynamic
+fi
+AC_SUBST(R_DYNAMIC_LDFLAG)
+
+if test x$enable_checks = xno; then
+    AC_DEFINE(DBUS_DISABLE_CHECKS,1,[Disable public API sanity checking])
+    AC_DEFINE(G_DISABLE_CHECKS,1,[Disable GLib public API sanity checking])
+    DISABLE_UNUSED_WARNINGS="unused-label"
+fi
+
+if test x$enable_userdb_cache = xyes; then
+    AC_DEFINE(DBUS_ENABLE_USERDB_CACHE,1,[Build with caching of user data])
+fi
+
+if test x$enable_compiler_coverage = xyes; then
+     ## so that config.h changes when you toggle gcov support
+     AC_DEFINE_UNQUOTED(DBUS_GCOV_ENABLED, 1, [Defined if gcov is enabled to force a rebuild due to config.h changing])
+fi
+
+# glibc21.m4 serial 3
+dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Test for the GNU C Library, version 2.1 or newer.
+# From Bruno Haible.
+
+AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer,
+  ac_cv_gnu_library_2_1,
+  [AC_EGREP_CPP([Lucky GNU user],
+    [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2)
+  Lucky GNU user
+ #endif
+#endif
+    ],
+    ac_cv_gnu_library_2_1=yes,
+    ac_cv_gnu_library_2_1=no)
+  ]
+)
+
+#### Integer sizes
+
+AC_CHECK_SIZEOF(char)
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(void *)
+AC_CHECK_SIZEOF(long long)
+AC_CHECK_SIZEOF(__int64)
+
+AC_ARG_WITH([64-bit],
+  [AS_HELP_STRING([--without-64-bit],
+    [If you have to use this option, please report it as a bug])],
+  [],
+  [with_64_bit=yes])
+
+### See what our 64 bit type is called
+AC_MSG_CHECKING([64-bit integer type])
+
+case 8 in
+$ac_cv_sizeof_int)
+  dbusint64=int
+  dbusint64_constant='(val)'
+  dbusuint64_constant='(val)'
+  dbusint64_printf_modifier='""'
+  ;;
+$ac_cv_sizeof_long)
+  dbusint64=long
+  dbusint64_constant='(val##L)'
+  dbusuint64_constant='(val##UL)'
+  dbusint64_printf_modifier='"l"'
+  ;;
+$ac_cv_sizeof_long_long)
+  dbusint64='long long'
+  dbusint64_constant='(val##LL)'
+  dbusuint64_constant='(val##ULL)'
+  # Ideally we discover what the format is, but this is
+  # only used in verbose mode, so eh...
+  if test x"$ac_cv_gnu_library_2_1" = xyes; then
+    dbusint64_printf_modifier='"ll"'
+  fi
+  ;;
+$ac_cv_sizeof___int64)
+  dbusint64=__int64
+  dbusint64_constant='(val##i64)'
+  dbusuint64_constant='(val##ui64)'
+  # See above case
+  if test x"$ac_cv_gnu_library_2_1" = xyes; then
+    dbusint64_printf_modifier='"ll"'
+  fi
+  ;;
+esac
+
+AS_IF(
+  [test "x$with_64_bit" = xno],
+  [
+        DBUS_INT64_TYPE="no_int64_type_detected"
+        DBUS_HAVE_INT64=0
+        DBUS_INT64_CONSTANT=
+        DBUS_UINT64_CONSTANT=
+        AC_MSG_RESULT([disabled via --without-64-bit])
+  ],
+  dnl else if
+  [test -z "$dbusint64"],
+  [AC_MSG_RESULT([not found])
+  AC_MSG_ERROR([Could not find a 64-bit integer type.
+
+Please report a bug here with details of your platform and compiler:
+
+    http://bugs.freedesktop.org/enter_bug.cgi?product=DBus&component=core
+
+To compile D-Bus with all 64-bit integer types removed (not recommended), use
+the option "--without-64-bit".
+
+This option is likely to be removed in future, unless you report that your
+platform needs it.])
+  ],
+  dnl else
+  [
+        DBUS_INT64_TYPE="$dbusint64"
+        DBUS_HAVE_INT64=1
+        DBUS_INT64_CONSTANT="$dbusint64_constant"
+        DBUS_UINT64_CONSTANT="$dbusuint64_constant"
+	if test x"$dbusint64_printf_modifier" != x; then
+		AC_DEFINE_UNQUOTED(DBUS_INT64_PRINTF_MODIFIER, [$dbusint64_printf_modifier], [Define to printf modifier for 64 bit integer type])
+	fi
+        AC_MSG_RESULT($DBUS_INT64_TYPE)
+  ])
+
+AC_SUBST(DBUS_INT64_TYPE)
+AC_SUBST(DBUS_INT64_CONSTANT)
+AC_SUBST(DBUS_UINT64_CONSTANT)
+AC_SUBST(DBUS_HAVE_INT64)
+
+### see what 32-bit int is called
+AC_MSG_CHECKING([32-bit integer type])
+
+case 4 in
+$ac_cv_sizeof_short)
+  dbusint32=short
+  ;;
+$ac_cv_sizeof_int)
+  dbusint32=int
+  ;;
+$ac_cv_sizeof_long)
+  dbusint32=long
+  ;;
+esac
+
+if test -z "$dbusint32" ; then
+        DBUS_INT32_TYPE="no_int32_type_detected"
+        AC_MSG_ERROR([No 32-bit integer type found])
+else
+        DBUS_INT32_TYPE="$dbusint32"
+        AC_MSG_RESULT($DBUS_INT32_TYPE)
+fi
+
+AC_SUBST(DBUS_INT32_TYPE)
+
+### see what 16-bit int is called
+AC_MSG_CHECKING([16-bit integer type])
+
+case 2 in
+$ac_cv_sizeof_short)
+  dbusint16=short
+  ;;
+$ac_cv_sizeof_int)
+  dbusint16=int
+  ;;
+esac
+
+if test -z "$dbusint16" ; then
+        DBUS_INT16_TYPE="no_int16_type_detected"
+        AC_MSG_ERROR([No 16-bit integer type found])
+else
+        DBUS_INT16_TYPE="$dbusint16"
+        AC_MSG_RESULT($DBUS_INT16_TYPE)
+fi
+
+AC_SUBST(DBUS_INT16_TYPE)
+
+## byte order
+case $host_os in
+	darwin*)
+		# check at compile-time, so that it is possible to build universal
+		# (with multiple architectures at once on the compile line)
+		AH_VERBATIM([WORDS_BIGENDIAN_DARWIN], [
+			/* Use the compiler-provided endianness defines to allow universal compiling. */
+			#if defined(__BIG_ENDIAN__)
+			#define WORDS_BIGENDIAN 1
+			#endif
+		])
+		;;
+	*)
+		AC_C_BIGENDIAN
+		;;
+esac
+
+dnl **********************************
+dnl *** va_copy checks (from GLib) ***
+dnl **********************************
+dnl we currently check for all three va_copy possibilities, so we get
+dnl all results in config.log for bug reports.
+AC_CACHE_CHECK([for an implementation of va_copy()],dbus_cv_va_copy,[
+	AC_LINK_IFELSE([AC_LANG_SOURCE([#include <stdarg.h>
+#include <stdlib.h>
+	static void f (int i, ...) {
+	va_list args1, args2;
+	va_start (args1, i);
+	va_copy (args2, args1);
+	if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+	  exit (1);
+	va_end (args1); va_end (args2);
+	}
+	int main() {
+	  f (0, 42);
+	  return 0;
+	}])],
+	[dbus_cv_va_copy=yes],
+	[dbus_cv_va_copy=no])
+])
+AC_CACHE_CHECK([for an implementation of __va_copy()],dbus_cv___va_copy,[
+	AC_LINK_IFELSE([AC_LANG_SOURCE([#include <stdarg.h>
+#include <stdlib.h>
+	static void f (int i, ...) {
+	va_list args1, args2;
+	va_start (args1, i);
+	__va_copy (args2, args1);
+	if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+	  exit (1);
+	va_end (args1); va_end (args2);
+	}
+	int main() {
+	  f (0, 42);
+	  return 0;
+	}])],
+	[dbus_cv___va_copy=yes],
+	[dbus_cv___va_copy=no])
+])
+
+if test "x$dbus_cv_va_copy" = "xyes"; then
+  dbus_va_copy_func=va_copy
+else if test "x$dbus_cv___va_copy" = "xyes"; then
+  dbus_va_copy_func=__va_copy
+fi
+fi
+
+if test -n "$dbus_va_copy_func"; then
+  AC_DEFINE_UNQUOTED(DBUS_VA_COPY,$dbus_va_copy_func,[A 'va_copy' style function])
+fi
+
+AC_LANG_PUSH(C)
+AC_CACHE_CHECK([whether va_lists can be copied by value],
+	dbus_cv_va_val_copy,
+	[AC_RUN_IFELSE([AC_LANG_PROGRAM(
+[[
+	#include <stdarg.h>
+	#include <stdlib.h>
+]],
+[[
+	static void f (int i, ...) {
+	va_list args1, args2;
+	va_start (args1, i);
+	args2 = args1;
+	if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+	  exit (1);
+	va_end (args1); va_end (args2);
+	}
+	int main() {
+	  f (0, 42);
+	  return 0;
+	}
+]])],
+	[dbus_cv_va_val_copy=yes],
+	[dbus_cv_va_val_copy=no],
+	[dbus_cv_va_val_copy=yes])
+])
+AC_LANG_POP(C)
+
+if test "x$dbus_cv_va_val_copy" = "xno"; then
+  AC_DEFINE(DBUS_VA_COPY_AS_ARRAY,1, ['va_lists' cannot be copies as values])
+fi
+
+
+#### Atomic integers
+
+AC_CACHE_CHECK([whether $CC knows __sync_sub_and_fetch()],
+  dbus_cv_sync_sub_and_fetch,
+  [AC_LINK_IFELSE([
+     AC_LANG_PROGRAM([[]], [[int a = 4; int b = __sync_sub_and_fetch(&a, 4); exit(b); ]])],
+     [dbus_cv_sync_sub_and_fetch=yes],
+     [dbus_cv_sync_sub_and_fetch=no])
+  ])
+
+if test "x$dbus_cv_sync_sub_and_fetch" = "xyes" ; then
+   have_sync=1
+else
+   have_sync=0
+fi
+
+AC_DEFINE_UNQUOTED([DBUS_USE_SYNC], [$have_sync], [Use the gcc __sync extension])
+
+#### Various functions
+AC_SEARCH_LIBS(socket,[socket network])
+AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)])
+
+AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep setenv clearenv unsetenv socketpair getgrouplist fpathconf setrlimit poll setlocale localeconv strtoll strtoull issetugid getresuid)
+
+AC_CHECK_HEADERS([syslog.h])
+if test "x$ac_cv_header_syslog_h" = "xyes"; then
+  AC_CHECK_DECLS([LOG_PERROR], [], [], [[#include <syslog.h>]])
+fi
+
+#### Check for broken poll; taken from Glib's configure
+
+AC_MSG_CHECKING([for broken poll])
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
+    #include <stdlib.h>
+    #include <fcntl.h>
+    #include <poll.h>
+    #ifdef HAVE_SYS_POLL_H
+    #include <sys/poll.h>
+    #endif
+    int main(void) {
+      struct pollfd fds[1];
+      int fd;
+      fd = open("/dev/null", 1);
+      fds[0].fd = fd;
+      fds[0].events = POLLIN;
+      fds[0].revents = 0;
+      if (poll(fds, 1, 0) < 0 || (fds[0].revents & POLLNVAL) != 0) {
+            exit(1);  /* Does not work for devices -- fail */
+      }
+      exit(0);
+    }]])],
+  [broken_poll=no],
+  [broken_poll=yes
+   AC_DEFINE(BROKEN_POLL,1,[poll doesn't work on devices])],
+  [broken_poll="no (cross compiling)"])
+AC_MSG_RESULT($broken_poll)
+
+AC_MSG_CHECKING(for dirfd)
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <dirent.h>
+]], [[
+DIR *dirp;
+dirp = opendir(".");
+dirfd(dirp);
+closedir(dirp);
+]])],
+[dbus_have_dirfd=yes],
+[dbus_have_dirfd=no])
+AC_MSG_RESULT($dbus_have_dirfd)
+if test "$dbus_have_dirfd" = yes; then
+	AC_DEFINE(HAVE_DIRFD,1,[Have dirfd function])
+else
+	AC_MSG_CHECKING(for DIR *dirp->dd_fd)
+	AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <dirent.h>
+	]], [[
+DIR *dirp;
+int fd;
+dirp = opendir(".");
+fd = dirp->dd_fd;
+closedir(dirp);
+        ]])],
+        [dbus_have_ddfd=yes],
+        [dbus_have_ddfd=no])
+	AC_MSG_RESULT($dbus_have_ddfd)
+	if test "$dbus_have_ddfd" = yes; then
+		AC_DEFINE(HAVE_DDFD,1,[Have the ddfd member of DIR])
+	fi
+fi
+
+AC_CHECK_HEADERS(sys/resource.h)
+
+AC_CHECK_HEADERS(dirent.h)
+
+AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)])
+
+AC_CHECK_HEADERS(errno.h)
+
+AC_CHECK_HEADERS(signal.h)
+
+AC_CHECK_HEADERS(locale.h)
+
+AC_CHECK_HEADERS(byteswap.h)
+
+AC_CHECK_HEADERS(unistd.h)
+
+AC_CHECK_HEADERS(ws2tcpip.h)
+
+AC_CHECK_HEADERS(wspiapi.h)
+
+# Add -D_POSIX_PTHREAD_SEMANTICS if on Solaris
+#
+case $host_os in
+    solaris*)
+       CFLAGS="$CFLAGS -D_POSIX_PTHREAD_SEMANTICS" ;;
+esac
+
+# checking for a posix version of getpwnam_r
+# if we are cross compiling and can not run the test
+# assume getpwnam_r is the posix version
+# it is up to the person cross compiling to change
+# this behavior if desired
+AC_LANG_PUSH(C)
+AC_CACHE_CHECK([for posix getpwnam_r],
+		ac_cv_func_posix_getpwnam_r,
+		[AC_RUN_IFELSE([AC_LANG_PROGRAM(
+[[
+#include <errno.h>
+#include <pwd.h>
+]],
+[[
+    char buffer[10000];
+    struct passwd pwd, *pwptr = &pwd;
+    int error;
+    errno = 0;
+    error = getpwnam_r ("", &pwd, buffer,
+                        sizeof (buffer), &pwptr);
+   return (error < 0 && errno == ENOSYS)
+	   || error == ENOSYS;
+]])],
+	[ac_cv_func_posix_getpwnam_r=yes],
+	[ac_cv_func_posix_getpwnam_r=no],
+        [ac_cv_func_posix_getpwnam_r=yes]
+)])
+AC_LANG_POP(C)
+
+if test "$ac_cv_func_posix_getpwnam_r" = yes; then
+        AC_DEFINE(HAVE_POSIX_GETPWNAM_R,1,
+                [Have POSIX function getpwnam_r])
+else
+        AC_CACHE_CHECK([for nonposix getpwnam_r],
+                ac_cv_func_nonposix_getpwnam_r,
+                [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pwd.h>]], [[char buffer[10000];
+                        struct passwd pwd;
+                        getpwnam_r ("", &pwd, buffer,
+                                        sizeof (buffer));]])],
+                        [ac_cv_func_nonposix_getpwnam_r=yes],
+                        [ac_cv_func_nonposix_getpwnam_r=no])])
+                if test "$ac_cv_func_nonposix_getpwnam_r" = yes; then
+                AC_DEFINE(HAVE_NONPOSIX_GETPWNAM_R,1,
+                        [Have non-POSIX function getpwnam_r])
+        fi
+fi
+
+dnl check for socklen_t
+AC_MSG_CHECKING(whether socklen_t is defined)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+]], [[
+socklen_t foo;
+foo = 1;
+]])],
+[dbus_have_socklen_t=yes],
+[dbus_have_socklen_t=no])
+AC_MSG_RESULT($dbus_have_socklen_t)
+
+if test "x$dbus_have_socklen_t" = "xyes"; then
+    AC_DEFINE(HAVE_SOCKLEN_T,1,[Have socklen_t type])
+fi
+
+dnl check for writev header and writev function so we're
+dnl good to go if HAVE_WRITEV gets defined.
+AC_CHECK_HEADERS(sys/uio.h, [AC_CHECK_FUNCS(writev)])
+
+dnl needed on darwin for NAME_MAX
+AC_CHECK_HEADERS(sys/syslimits.h)
+
+dnl Make it easy to check if we have MSG_NOSIGNAL without actually having to include sys/socket.h
+AC_CHECK_DECLS([MSG_NOSIGNAL], [], [], [[ #include <sys/types.h>
+#include <sys/socket.h> ]])
+
+dnl check for flavours of varargs macros (test from GLib)
+AC_MSG_CHECKING(for ISO C99 varargs macros in C)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+int a(int p1, int p2, int p3);
+#define call_a(...) a(1,__VA_ARGS__)
+call_a(2,3);
+]])],
+[dbus_have_iso_c_varargs=yes],
+[dbus_have_iso_c_varargs=no])
+AC_MSG_RESULT($dbus_have_iso_c_varargs)
+
+AC_MSG_CHECKING(for GNUC varargs macros)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+int a(int p1, int p2, int p3);
+#define call_a(params...) a(1,params)
+call_a(2,3);
+]])],
+[dbus_have_gnuc_varargs=yes],
+[dbus_have_gnuc_varargs=no])
+AC_MSG_RESULT($dbus_have_gnuc_varargs)
+
+dnl Output varargs tests
+if test x$dbus_have_iso_c_varargs = xyes; then
+    AC_DEFINE(HAVE_ISO_VARARGS,1,[Have ISO C99 varargs macros])
+fi
+if test x$dbus_have_gnuc_varargs = xyes; then
+    AC_DEFINE(HAVE_GNUC_VARARGS,1,[Have GNU-style varargs macros])
+fi
+
+dnl Check for various credentials.
+AC_MSG_CHECKING(for struct cmsgcred)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+]], [[
+struct cmsgcred cred;
+
+cred.cmcred_pid = 0;
+]])],
+[dbus_have_struct_cmsgcred=yes],
+[dbus_have_struct_cmsgcred=no])
+AC_MSG_RESULT($dbus_have_struct_cmsgcred)
+
+if test x$dbus_have_struct_cmsgcred = xyes; then
+    AC_DEFINE(HAVE_CMSGCRED,1,[Have cmsgcred structure])
+fi
+
+AC_CHECK_FUNCS(getpeerucred getpeereid)
+
+AC_CHECK_FUNCS(pipe2 accept4)
+
+#### Abstract sockets
+
+if test x$enable_abstract_sockets = xauto; then
+AC_LANG_PUSH(C)
+warn_on_xcompile=no
+AC_CACHE_CHECK([abstract socket namespace],
+		ac_cv_have_abstract_sockets,
+		[AC_RUN_IFELSE([AC_LANG_PROGRAM(
+[[
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+]],
+[[
+  size_t slen;
+  int listen_fd;
+  struct sockaddr_un addr;
+
+  listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
+
+  if (listen_fd < 0)
+    {
+      fprintf (stderr, "socket() failed: %s\n", strerror (errno));
+      exit (1);
+    }
+
+  memset (&addr, '\0', sizeof (addr));
+  addr.sun_family = AF_UNIX;
+  strcpy (addr.sun_path, "X/tmp/dbus-fake-socket-path-used-in-configure-test");
+  /* SUN_LEN uses strlen() so need to calculate it before adding \0 at the
+   * beginning.
+   */
+  slen = SUN_LEN(&addr);
+  addr.sun_path[0] = '\0'; /* this is what makes it abstract */
+
+  if (bind (listen_fd, (struct sockaddr*) &addr, slen) < 0)
+    {
+       fprintf (stderr, "Abstract socket namespace bind() failed: %s\n",
+                strerror (errno));
+       exit (1);
+    }
+  else
+    exit (0);
+]])],
+              [ac_cv_have_abstract_sockets=yes],
+              [ac_cv_have_abstract_sockets=no],
+              [
+                ac_cv_have_abstract_sockets=no
+                warn_on_xcompile=yes
+              ]
+)])
+if test x$warn_on_xcompile = xyes ; then
+  AC_MSG_WARN([Cannot check for abstract sockets when cross-compiling, please use --enable-abstract-sockets])
+fi
+AC_LANG_POP(C)
+fi
+
+if test x$enable_abstract_sockets = xyes; then
+    if test x$ac_cv_have_abstract_sockets = xno; then
+	AC_MSG_ERROR([Abstract sockets explicitly required, and support not detected.])
+    fi
+fi
+
+if test x$enable_abstract_sockets = xno; then
+   ac_cv_have_abstract_sockets=no;
+fi
+
+if test x$ac_cv_have_abstract_sockets = xyes ; then
+   DBUS_PATH_OR_ABSTRACT=abstract
+   AC_DEFINE(HAVE_ABSTRACT_SOCKETS,1,[Have abstract socket namespace])
+else
+   DBUS_PATH_OR_ABSTRACT=path
+fi
+
+# this is used in addresses to prefer abstract, e.g.
+# unix:path=/foo or unix:abstract=/foo
+AC_SUBST(DBUS_PATH_OR_ABSTRACT)
+
+PKG_PROG_PKG_CONFIG
+
+#### Sort out XML library
+
+# see what we have
+AC_CHECK_LIB(expat, XML_ParserCreate_MM,
+             [ AC_CHECK_HEADERS(expat.h, have_expat=true, have_expat=false) ],
+             have_expat=false)
+
+# see what we want to use
+dbus_use_libxml=false
+dbus_use_expat=false
+if test x$with_xml = xexpat; then
+        if ! $have_expat ; then
+           AC_MSG_ERROR([Explicitly requested expat but expat not found])
+        fi
+        dbus_use_expat=true
+elif test x$with_xml = xlibxml; then
+        PKG_CHECK_MODULES(LIBXML, libxml-2.0 >= 2.6.0, have_libxml=true, have_libxml=false)
+        if ! $have_libxml ; then
+           AC_MSG_ERROR([Explicitly requested libxml but libxml not found])
+        fi
+        dbus_use_libxml=true
+else
+        ### expat is the default because libxml can't currently survive
+        ### our brutal OOM-handling unit test setup.
+        ### http://bugzilla.gnome.org/show_bug.cgi?id=109368
+        if test x$have_expat = xfalse; then
+                AC_MSG_ERROR([Could not find expat.h, check config.log for failed attempts])
+        fi
+	### By default, only use Expat since it's tested and known to work.  If you're a
+	### general-purpose OS vendor, please don't enable libxml.  For embedded use
+	### if your OS is built around libxml, that's another case.
+	dbus_use_expat=true
+fi
+
+AM_CONDITIONAL(DBUS_USE_EXPAT, $dbus_use_expat)
+AM_CONDITIONAL(DBUS_USE_LIBXML, $dbus_use_libxml)
+
+if $dbus_use_expat; then
+   XML_LIBS=-lexpat
+   XML_CFLAGS=
+fi
+if $dbus_use_libxml; then
+   XML_LIBS=$LIBXML_LIBS
+   XML_CFLAGS=$LIBXML_CFLAGS
+fi
+AC_SUBST([XML_CFLAGS])
+AC_SUBST([XML_LIBS])
+
+# Thread lib detection
+AC_CHECK_FUNC(pthread_cond_timedwait,[AC_CHECK_LIB(pthread,pthread_cond_timedwait,
+                                                    [THREAD_LIBS="-lpthread"])])
+save_libs="$LIBS"
+LIBS="$LIBS $THREAD_LIBS"
+AC_CHECK_FUNC(pthread_condattr_setclock,have_pthread_condattr_setclock=true,have_pthread_condattr_setclock=false)
+if test x$have_pthread_condattr_setclock = xtrue; then
+    AC_SEARCH_LIBS([clock_getres],[rt],[THREAD_LIBS="$THREAD_LIBS -lrt"])
+    AC_MSG_CHECKING([for CLOCK_MONOTONIC])
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <time.h>
+#include <pthread.h>
+]], [[
+struct timespec monotonic_timer;
+pthread_condattr_t attr;
+pthread_condattr_init (&attr);
+pthread_condattr_setclock (&attr, CLOCK_MONOTONIC);
+clock_getres (CLOCK_MONOTONIC,&monotonic_timer);
+]])],
+[have_clock_monotonic=true],
+[have_clock_monotonic=false])
+if test x$have_clock_monotonic = xtrue; then
+    AC_MSG_RESULT([found])
+    AC_DEFINE(HAVE_MONOTONIC_CLOCK, 1, [Define if we have CLOCK_MONOTONIC])
+else
+    AC_MSG_RESULT([not found])
+fi
+fi
+LIBS="$save_libs"
+
+AC_SUBST([THREAD_LIBS])
+
+# SELinux detection
+if test x$enable_selinux = xno ; then
+    have_selinux=no;
+else
+    # See if we have SELinux library
+    AC_CHECK_LIB(selinux, is_selinux_enabled,
+                 have_selinux=yes, have_selinux=no)
+
+    # see if we have the SELinux header with the new D-Bus stuff in it
+    if test x$have_selinux = xyes ; then
+        AC_MSG_CHECKING([for DBUS Flask permissions in selinux/av_permissions.h])
+        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <selinux/av_permissions.h>]],
+                          [[#ifdef DBUS__ACQUIRE_SVC return 0;
+			    #else
+			    #error DBUS__ACQUIRE_SVC not defined
+			    #endif]])],
+                          [have_selinux=yes],
+                          [have_selinux=no])
+	AC_MSG_RESULT($have_selinux)
+    fi
+
+    if test x$enable_selinux = xauto ; then
+        if test x$have_selinux = xno ; then
+                AC_MSG_WARN([Sufficiently new SELinux library not found])
+        fi
+    else
+        if test x$have_selinux = xno ; then
+                AC_MSG_ERROR([SElinux explicitly required, and SELinux library not found])
+        fi
+    fi
+fi
+
+AM_CONDITIONAL(HAVE_SELINUX, test x$have_selinux = xyes)
+
+if test x$have_selinux = xyes ; then
+    # the selinux code creates threads
+    # which requires libpthread even on linux
+    AC_CHECK_FUNC(pthread_create,,[AC_CHECK_LIB(pthread,pthread_create,
+                                                [SELINUX_THREAD_LIBS="-lpthread"])])
+
+    SELINUX_LIBS="-lselinux $SELINUX_THREAD_LIBS"
+    AC_DEFINE(HAVE_SELINUX,1,[SELinux support])
+else
+    SELINUX_LIBS=
+fi
+
+# inotify checks
+if test x$enable_inotify = xno ; then
+    have_inotify=no;
+else
+    AC_CHECK_HEADERS(sys/inotify.h, have_inotify=yes, have_inotify=no)
+fi
+
+dnl check if inotify backend is enabled
+if test x$have_inotify = xyes; then
+   AC_DEFINE(DBUS_BUS_ENABLE_INOTIFY,1,[Use inotify])
+   AC_CHECK_FUNCS(inotify_init1)
+fi
+
+AM_CONDITIONAL(DBUS_BUS_ENABLE_INOTIFY, test x$have_inotify = xyes)
+
+# dnotify checks
+if test x$enable_dnotify = xno ; then
+    have_dnotify=no;
+else
+    if test x$have_inotify = xno -a x$host_os = xlinux-gnu -o x$host_os = xlinux; then
+        have_dnotify=yes;
+    else
+        have_dnotify=no;
+    fi
+fi
+
+dnl check if dnotify backend is enabled
+if test x$have_dnotify = xyes; then
+   AC_DEFINE(DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX,1,[Use dnotify on Linux])
+fi
+
+AM_CONDITIONAL(DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX, test x$have_dnotify = xyes)
+
+# For simplicity, we require the userland API for epoll_create1 at
+# compile-time (glibc 2.9), but we'll run on kernels that turn out
+# not to have it at runtime.
+AC_ARG_ENABLE([epoll],
+              [AS_HELP_STRING([--enable-epoll],[use epoll(4) on Linux])],
+              [enable_epoll=$enableval], [enable_epoll=auto])
+if test x$enable_epoll = xno; then
+    have_linux_epoll=no
+else
+    AC_MSG_CHECKING([for Linux epoll(4)])
+    AC_LINK_IFELSE([AC_LANG_PROGRAM(
+        [
+        #ifndef __linux__
+        #error This is not Linux
+        #endif
+        #include <sys/epoll.h>
+        ],
+        [epoll_create1 (EPOLL_CLOEXEC);])],
+        [have_linux_epoll=yes],
+        [have_linux_epoll=no])
+    AC_MSG_RESULT([$have_linux_epoll])
+fi
+if test x$enable_epoll,$have_linux_epoll = xyes,no; then
+    AC_MSG_ERROR([epoll support explicitly enabled but not available])
+fi
+if test x$have_linux_epoll = xyes; then
+  AC_DEFINE([DBUS_HAVE_LINUX_EPOLL], 1, [Define to use epoll(4) on Linux])
+fi
+AM_CONDITIONAL([HAVE_LINUX_EPOLL], [test x$have_linux_epoll = xyes])
+
+# kqueue checks
+if test x$enable_kqueue = xno ; then
+    have_kqueue=no
+else
+    have_kqueue=yes
+    AC_CHECK_HEADER(sys/event.h, , have_kqueue=no)
+    AC_CHECK_FUNC(kqueue, , have_kqueue=no)
+
+    if test x$enable_kqueue = xyes -a x$have_kqueue = xno; then
+        AC_MSG_ERROR(kqueue support explicitly enabled but not available)
+    fi
+fi
+
+dnl check if kqueue backend is enabled
+if test x$have_kqueue = xyes; then
+   AC_DEFINE(DBUS_BUS_ENABLE_KQUEUE,1,[Use kqueue])
+fi
+
+AM_CONDITIONAL(DBUS_BUS_ENABLE_KQUEUE, test x$have_kqueue = xyes)
+
+# launchd checks
+if test x$enable_launchd = xno ; then
+    have_launchd=no
+else
+    have_launchd=yes
+    AC_CHECK_HEADER([launch.h], , have_launchd=no)
+    AC_PATH_PROG([LAUNCHCTL], [launchctl])
+    if test "x$LAUNCHCTL" = "x"; then
+        have_launchd=no
+    fi
+
+    if test x$enable_launchd = xyes && test x$have_launchd = xno ; then
+        AC_MSG_ERROR([launchd support explicitly enabled but not available])
+    fi
+fi
+
+dnl check if launchd is enabled
+if test x$have_launchd = xyes; then
+    AC_DEFINE(DBUS_ENABLE_LAUNCHD,1,[Use launchd autolaunch])
+fi
+
+AM_CONDITIONAL(DBUS_ENABLE_LAUNCHD, test x$have_launchd = xyes)
+
+#### Directory to place launchd agent file
+if test "x$with_launchd_agent_dir" = "x"; then
+   LAUNCHD_AGENT_DIR="/Library/LaunchAgents"
+else
+   LAUNCHD_AGENT_DIR="$with_launchd_agent_dir"
+fi
+
+AC_SUBST(LAUNCHD_AGENT_DIR)
+
+dnl console owner file
+if test x$enable_console_owner_file = xno ; then
+    have_console_owner_file=no;
+else
+    case $host_os in
+    solaris*)
+        have_console_owner_file=yes;
+        AC_DEFINE(HAVE_CONSOLE_OWNER_FILE,1,[Have console owner file])
+        ;;
+    *)
+        have_console_owner_file=no;;
+    esac
+fi
+
+AM_CONDITIONAL(HAVE_CONSOLE_OWNER_FILE, test x$have_console_owner_file = xyes)
+
+dnl systemd detection
+if test x$enable_systemd = xno ; then
+    have_systemd=no;
+else
+    PKG_CHECK_MODULES(SYSTEMD,
+        [libsystemd-login >= 32, libsystemd-daemon >= 32],
+        have_systemd=yes,
+        have_systemd=no)
+fi
+
+if test x$have_systemd = xyes; then
+    AC_DEFINE(HAVE_SYSTEMD,1,[Have systemd])
+fi
+
+if test x$enable_systemd = xyes -a x$have_systemd != xyes ; then
+    AC_MSG_ERROR([Explicitly requested systemd support, but systemd not found])
+fi
+
+# libaudit detection
+if test x$enable_libaudit = xno ; then
+    have_libaudit=no;
+else
+    # See if we have audit daemon & capabilities library
+    AC_CHECK_LIB(audit, audit_log_user_avc_message,
+                 have_libaudit=yes, have_libaudit=no)
+    if test x$have_libaudit = xyes ; then
+        AC_CHECK_LIB(cap-ng, capng_clear,
+                 have_libaudit=yes, have_libaudit=no)
+    fi
+fi
+
+AM_CONDITIONAL(HAVE_LIBAUDIT, test x$have_libaudit = xyes)
+
+if test x$have_libaudit = xyes ; then
+    SELINUX_LIBS="$SELINUX_LIBS -laudit -lcap-ng"
+    AC_DEFINE(HAVE_LIBAUDIT,1,[audit daemon SELinux support])
+fi
+
+AC_SUBST([SELINUX_LIBS])
+
+# Check for ADT API (Solaris Basic Security Mode auditing)
+AC_MSG_CHECKING(for ADT API)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <bsm/adt.h>
+adt_user_context = ADT_USER;
+]], [[]])], [ check_adt_audit=yes ], [ check_adt_audit=no ])
+
+if test ${check_adt_audit} = yes
+then
+   AC_DEFINE([HAVE_ADT], [], [Adt audit API])
+   ADT_LIBS="-lbsm"
+   LIBS="-lbsm $LIBS"
+   AC_MSG_RESULT(yes)
+else
+   AC_MSG_RESULT(no)
+fi
+AC_SUBST([ADT_LIBS])
+
+# Check for SCM_RIGHTS
+AC_MSG_CHECKING([for SCM_RIGHTS])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+static int x = SCM_RIGHTS;
+]], [[]])],
+[ AC_MSG_RESULT([supported])
+  AC_DEFINE([HAVE_UNIX_FD_PASSING], [1], [Supports sending UNIX file descriptors]) ],
+[ AC_MSG_RESULT([not supported]) ])
+
+NETWORK_libs=
+if test x$dbus_win = xyes ; then
+  if test x$dbus_wince = xyes ; then
+    NETWORK_libs="-lws2"
+  else
+    NETWORK_libs="-lws2_32"
+  fi
+fi
+
+AC_SUBST([NETWORK_libs])
+
+AC_ARG_WITH([valgrind],
+  [AS_HELP_STRING([--with-valgrind],
+     [Add instrumentation to help valgrind to understand our allocator])],
+  [],
+  [with_valgrind=no])
+
+if test x$with_valgrind != xno; then
+  PKG_CHECK_MODULES([VALGRIND], [valgrind >= 3.6])
+  AC_DEFINE([WITH_VALGRIND], [1], [Define to add Valgrind instrumentation])
+fi
+
+#### Set up final flags
+LIBDBUS_LIBS="$THREAD_LIBS $NETWORK_libs"
+AC_SUBST([LIBDBUS_LIBS])
+
+### X11 detection
+DBUS_X_LIBS=
+DBUS_X_CFLAGS=
+
+AC_ARG_ENABLE([x11-autolaunch],
+  AS_HELP_STRING([--enable-x11-autolaunch], [build with X11 auto-launch support]),
+  [], [enable_x11_autolaunch=auto])
+
+if test "x$dbus_win" = xyes; then
+    if test "x$enable_x11_autolaunch" = xyes; then
+        AC_MSG_ERROR([X11 auto-launch is not supported on Windows])
+    fi
+
+    enable_x11_autolaunch=no
+    have_x11=no
+else
+    AC_PATH_XTRA
+
+    if test "x$no_x" = xyes; then
+        have_x11=no
+    else
+        have_x11=yes
+        DBUS_X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
+        DBUS_X_CFLAGS="$X_CFLAGS"
+    fi
+fi
+
+if test "x$enable_x11_autolaunch,$have_x11" = xyes,no; then
+    AC_MSG_ERROR([X11 auto-launch requires X headers/libraries])
+else
+    # move from "auto" to "yes" or "no" if necessary
+    if test "x$enable_x11_autolaunch" != xno; then
+        enable_x11_autolaunch="$have_x11"
+    fi
+fi
+
+if test "x$have_x11" = xyes ; then
+   AC_DEFINE([DBUS_BUILD_X11], [1], [Define to build X11 functionality])
+fi
+
+if test "x$enable_x11_autolaunch" = xyes ; then
+   AC_DEFINE([DBUS_ENABLE_X11_AUTOLAUNCH], [1], [Define to enable X11 auto-launch])
+fi
+
+AC_SUBST([DBUS_X_CFLAGS])
+AC_SUBST([DBUS_X_LIBS])
+
+#### gcc warning flags
+
+cc_supports_flag() {
+  AC_MSG_CHECKING(whether $CC supports "$*")
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$*"
+  AC_TRY_COMPILE([], [], [rc=yes], [rc=no])
+  CFLAGS="$save_CFLAGS"
+  AC_MSG_RESULT([$rc])
+  test "x$rc" = xyes
+}
+
+TP_COMPILER_WARNINGS([WARNING_CFLAGS],
+  dnl Use -Werror by default if:
+  dnl - we're not on Windows (too many warnings), and
+  dnl - we're in developer mode (a D-Bus developer, not a distro or end-user)
+  dnl Override with --enable-Werror or --disable-Werror
+  [test x$dbus_win != xyes -a x$dbus_cygwin != xyes -a x$enable_developer = xyes],
+
+  dnl Enable these warnings if possible:
+  [all \
+   extra \
+   char-subscripts \
+   missing-declarations \
+   missing-prototypes \
+   nested-externs \
+   pointer-arith \
+   cast-align \
+   no-address \
+   float-equal \
+   declaration-after-statement \
+  ],
+
+  dnl Disable these warnings if possible, make them non-fatal if possible,
+  dnl and don't enable -Werror unless we succeeded.
+  dnl
+  dnl Intentional:
+  dnl - $DISABLE_UNUSED_WARNINGS disables unused-label warnings if not
+  dnl   checking or not asserting
+  dnl - missing field initializers being 0 is a C feature, not a bug
+  dnl - unused-parameter is to make writing callbacks less annoying
+  dnl
+  dnl To be fixed one day:
+  dnl - sign-compare and pointer-sign are workarounds for fd.o #17433
+  dnl - type-limits is probably a bug too, but having the rest of -Wextra
+  dnl   is better than nothing
+  [$DISABLE_UNUSED_WARNINGS \
+   missing-field-initializers \
+   unused-parameter \
+   sign-compare \
+   pointer-sign \
+   type-limits \
+  ])
+
+if test "x$GCC" = "xyes"; then
+  # We're treating -fno-common like a warning: it makes the linker more
+  # strict, because on some systems the linker is *always* this strict
+  TP_ADD_COMPILER_FLAG([WARNING_CFLAGS], [-fno-common])
+
+  # http://bugs.freedesktop.org/show_bug.cgi?id=10599
+  TP_ADD_COMPILER_FLAG([WARNING_CFLAGS], [-fno-strict-aliasing])
+
+  if test "x$enable_ansi" = "xyes"; then
+    TP_ADD_COMPILER_FLAG([WARNING_CFLAGS],
+      [-ansi -D_POSIX_C_SOURCE=199309L -D_BSD_SOURCE -pedantic])
+  fi
+fi
+
+dnl In principle we should put WARNING_CFLAGS in each Makefile.am like
+dnl telepathy-glib does, since CFLAGS is meant to be reserved for the user...
+dnl but prepending to CFLAGS (so the user can override it with later CFLAGS)
+dnl is the next best thing
+CFLAGS="$WARNING_CFLAGS $CFLAGS"
+
+case $host_os in
+    solaris*)
+        # Solaris' C library apparently needs these runes to be threadsafe...
+        CFLAGS="$CFLAGS -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT"
+        # ... this opt-in to get sockaddr_in6 and sockaddr_storage...
+        CFLAGS="$CFLAGS -D__EXTENSIONS__"
+        # ... and this opt-in to get file descriptor passing support
+        CFLAGS="$CFLAGS -D_XOPEN_SOURCE=500"
+        ;;
+esac
+
+### Doxygen Documentation
+
+AC_PATH_PROG(DOXYGEN, doxygen, no)
+
+AC_MSG_CHECKING([whether to build Doxygen documentation])
+
+if test x$DOXYGEN = xno ; then
+    have_doxygen=no
+else
+    have_doxygen=yes
+fi
+
+if test x$enable_doxygen_docs = xauto ; then
+    if test x$have_doxygen = xno ; then
+        enable_doxygen_docs=no
+    else
+        enable_doxygen_docs=yes
+    fi
+fi
+
+if test x$enable_doxygen_docs = xyes; then
+    if test x$have_doxygen = xno; then
+	AC_MSG_ERROR([Building Doxygen docs explicitly required, but Doxygen not found])
+    fi
+fi
+
+AM_CONDITIONAL(DBUS_DOXYGEN_DOCS_ENABLED, test x$enable_doxygen_docs = xyes)
+AC_MSG_RESULT($enable_doxygen_docs)
+
+AC_CHECK_PROGS([XSLTPROC], [xsltproc])
+AM_CONDITIONAL([DBUS_HAVE_XSLTPROC], [test "x$XSLTPROC" != "x"])
+
+### XML Documentation
+
+AC_PATH_PROG(XMLTO, xmlto, no)
+
+AC_MSG_CHECKING([whether to build XML documentation])
+
+if test x$XMLTO = xno ; then
+    have_xmlto=no
+else
+    have_xmlto=yes
+fi
+
+if test x$enable_xml_docs = xauto ; then
+    if test x$have_xmlto = xno ; then
+        enable_xml_docs=no
+    else
+        enable_xml_docs=yes
+    fi
+fi
+
+if test x$enable_xml_docs = xyes; then
+    if test x$have_xmlto = xno; then
+	AC_MSG_ERROR([Building XML docs explicitly required, but xmlto not found])
+    fi
+fi
+
+AM_CONDITIONAL(DBUS_XML_DOCS_ENABLED, test x$enable_xml_docs = xyes)
+AC_MSG_RESULT($enable_xml_docs)
+
+AC_PATH_PROG([MAN2HTML], [man2html])
+AC_ARG_VAR([MAN2HTML], [Path to man2html (optional)])
+AM_CONDITIONAL(DBUS_HAVE_MAN2HTML, test x$MAN2HTML != x)
+
+AM_CONDITIONAL(DBUS_CAN_UPLOAD_DOCS,
+    test x$enable_doxygen_docs = xyes -a x$enable_xml_docs = xyes -a \
+         x$MAN2HTML != x)
+
+#### Have to go $localstatedir->$prefix/var->/usr/local/var
+
+#### find the actual value for $prefix that we'll end up with
+##   (I know this is broken and should be done in the Makefile, but
+##    that's a major pain and almost nobody actually seems to care)
+AS_AC_EXPAND(EXPANDED_PREFIX, "$prefix")
+AS_AC_EXPAND(EXPANDED_LOCALSTATEDIR, "$localstatedir")
+AS_AC_EXPAND(EXPANDED_SYSCONFDIR, "$sysconfdir")
+AS_AC_EXPAND(EXPANDED_BINDIR, "$bindir")
+AS_AC_EXPAND(EXPANDED_LIBDIR, "$libdir")
+AS_AC_EXPAND(EXPANDED_LIBEXECDIR, "$libexecdir")
+AS_AC_EXPAND(EXPANDED_DATADIR, "$datadir")
+
+#### Check our operating system
+operating_system=unknown
+if test -f /etc/redhat-release || test -f $EXPANDED_SYSCONFDIR/redhat-release ; then
+   operating_system=redhat
+fi
+
+if test -f /etc/slackware-version || test -f $EXPANDED_SYSCONFDIR/slackware-version ; then
+   operating_system=slackware
+fi
+
+if test -f /usr/bin/cygwin1.dll || test -f $EXPANDED_BINDIR/cygwin1.dll ; then
+   operating_system=cygwin
+fi
+
+#### Sort out init scripts
+
+if test x$with_init_scripts = x; then
+    case x$operating_system in
+        xredhat)	with_init_scripts=redhat ;;
+        xslackware)	with_init_scripts=slackware ;;
+        xcygwin)	with_init_scripts=cygwin ;;
+        *)			with_init_scripts=none ;;
+    esac
+fi
+
+AM_CONDITIONAL(DBUS_INIT_SCRIPTS_RED_HAT, test x$with_init_scripts = xredhat)
+AM_CONDITIONAL(DBUS_INIT_SCRIPTS_SLACKWARE, test x$with_init_scripts = xslackware)
+AM_CONDITIONAL(DBUS_INIT_SCRIPTS_CYGWIN, test x$with_init_scripts = xcygwin)
+
+##### systemd unit files
+AC_ARG_WITH([systemdsystemunitdir],
+AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
+    [],
+    [
+    PKG_CHECK_EXISTS([systemd],
+      [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)],
+      [with_systemdsystemunitdir=no])
+    ])
+if test "x$with_systemdsystemunitdir" != xno; then
+   AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+fi
+AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
+
+##### Set up location for system bus socket
+if ! test -z "$with_system_socket"; then
+   DBUS_SYSTEM_SOCKET=$with_system_socket
+else
+   DBUS_SYSTEM_SOCKET=${EXPANDED_LOCALSTATEDIR}/run/dbus/system_bus_socket
+fi
+
+AC_SUBST(DBUS_SYSTEM_SOCKET)
+AC_DEFINE_UNQUOTED(DBUS_SYSTEM_SOCKET,"$DBUS_SYSTEM_SOCKET",[The name of the socket the system bus listens on by default])
+
+## system bus only listens on local domain sockets, and never
+## on an abstract socket (so only root can create the socket)
+DBUS_SYSTEM_BUS_DEFAULT_ADDRESS="unix:path=$DBUS_SYSTEM_SOCKET"
+AC_SUBST(DBUS_SYSTEM_BUS_DEFAULT_ADDRESS)
+AC_DEFINE_UNQUOTED(DBUS_SYSTEM_BUS_DEFAULT_ADDRESS, "$DBUS_SYSTEM_BUS_DEFAULT_ADDRESS",[The default D-Bus address of the system bus])
+
+#### Set up the pid file
+if ! test -z "$with_system_pid_file"; then
+   DBUS_SYSTEM_PID_FILE=$with_system_pid_file
+elif test x$with_init_scripts = xredhat ; then
+   DBUS_SYSTEM_PID_FILE=${EXPANDED_LOCALSTATEDIR}/run/messagebus.pid
+else
+   DBUS_SYSTEM_PID_FILE=${EXPANDED_LOCALSTATEDIR}/run/dbus/pid
+fi
+
+AC_SUBST(DBUS_SYSTEM_PID_FILE)
+
+#### Directory to check for console ownership
+if ! test -z "$with_console_auth_dir"; then
+   DBUS_CONSOLE_AUTH_DIR=$with_console_auth_dir
+else
+   DBUS_CONSOLE_AUTH_DIR=/var/run/console/
+fi
+
+AC_SUBST(DBUS_CONSOLE_AUTH_DIR)
+AC_DEFINE_UNQUOTED(DBUS_CONSOLE_AUTH_DIR, "$DBUS_CONSOLE_AUTH_DIR", [Directory to check for console ownerhip])
+
+#### File to check for console ownership
+if test x$have_console_owner_file = xyes; then
+   if ! test -z "$with_console_owner_file"; then
+      DBUS_CONSOLE_OWNER_FILE=$with_console_owner_file
+   else
+      DBUS_CONSOLE_OWNER_FILE=/dev/console
+   fi
+else
+  DBUS_CONSOLE_OWNER_FILE=
+fi
+
+AC_SUBST(DBUS_CONSOLE_OWNER_FILE)
+AC_DEFINE_UNQUOTED(DBUS_CONSOLE_OWNER_FILE, "$DBUS_CONSOLE_OWNER_FILE", [File to check for console ownerhip])
+
+#### User to start the system bus as
+if test -z "$with_dbus_user" ; then
+    DBUS_USER=messagebus
+else
+    DBUS_USER=$with_dbus_user
+fi
+AC_SUBST(DBUS_USER)
+AC_DEFINE_UNQUOTED(DBUS_USER,"$DBUS_USER", [User for running the system BUS daemon])
+
+#### Prefix to install into
+DBUS_PREFIX=$EXPANDED_PREFIX
+AC_SUBST(DBUS_PREFIX)
+AC_DEFINE_UNQUOTED(DBUS_PREFIX,"$DBUS_PREFIX", [Prefix for installing DBUS])
+
+#### Direcotry to install data files into
+DBUS_DATADIR=$EXPANDED_DATADIR
+AC_SUBST(DBUS_DATADIR)
+AC_DEFINE_UNQUOTED(DBUS_DATADIR,"$DBUS_DATADIR", [Directory for installing DBUS data files])
+
+#### Directory to install dbus-daemon
+if test -z "$with_dbus_daemondir" ; then
+    DBUS_DAEMONDIR=$EXPANDED_BINDIR
+else
+    DBUS_DAEMONDIR=$with_dbus_daemondir
+fi
+AC_SUBST(DBUS_DAEMONDIR)
+AC_DEFINE_UNQUOTED(DBUS_DAEMONDIR,"$DBUS_DAEMONDIR", [Directory for installing the DBUS daemon])
+
+#### Directory to install the other binaries
+DBUS_BINDIR="$EXPANDED_BINDIR"
+AC_SUBST(DBUS_BINDIR)
+AC_DEFINE_UNQUOTED(DBUS_BINDIR,"$DBUS_BINDIR", [Directory for installing the binaries])
+
+#### Directory to install the libexec binaries
+DBUS_LIBEXECDIR="$EXPANDED_LIBEXECDIR"
+AC_SUBST(DBUS_LIBEXECDIR)
+AC_DEFINE_UNQUOTED(DBUS_LIBEXECDIR,"$DBUS_LIBEXECDIR", [Directory for installing the libexec binaries])
+
+#### Tell tests where to find certain stuff in builddir
+
+DBUS_PWD=`pwd`
+# Useful in a cross-compilation environment, where the tests are run on the host system.
+AC_ARG_WITH(dbus-test-dir, AS_HELP_STRING([--with-dbus-test-dir=[dirname]],[path where the tests tools are available]),
+			   DBUS_PWD=$withval)
+
+DBUS_TEST_EXEC="$DBUS_PWD/test"
+DBUS_TEST_DATA="$DBUS_PWD/test/data"
+
+AC_SUBST([DBUS_TEST_DATA])
+AC_SUBST([DBUS_TEST_EXEC])
+
+AC_DEFINE_UNQUOTED([DBUS_TEST_EXEC], ["$DBUS_TEST_EXEC"],
+                   [Full path to the daemon in the builddir])
+AC_DEFINE_UNQUOTED([DBUS_EXEEXT], ["$EXEEXT"],
+                   [Extension for executables, typically empty or .exe])
+
+AC_DEFINE_UNQUOTED(TEST_BUS_BINARY, ["$DBUS_PWD/bus/dbus-daemon$EXEEXT"],
+                   [Full path to the daemon in the builddir])
+AC_SUBST(TEST_BUS_BINARY)
+
+## Export the non-setuid external helper
+TEST_LAUNCH_HELPER_BINARY="$DBUS_PWD/bus/dbus-daemon-launch-helper-test$EXEEXT"
+AC_SUBST(TEST_LAUNCH_HELPER_BINARY)
+AC_DEFINE_UNQUOTED(DBUS_TEST_LAUNCH_HELPER_BINARY, "$TEST_LAUNCH_HELPER_BINARY",
+                   [Full path to the launch helper test program in the builddir])
+
+#### Find socket directories
+if ! test -z "$TMPDIR" ; then
+   DEFAULT_SOCKET_DIR=$TMPDIR
+elif ! test -z "$TEMP" ; then
+   DEFAULT_SOCKET_DIR=$TEMP
+elif ! test -z "$TMP" ; then
+   DEFAULT_SOCKET_DIR=$TMP
+else
+   DEFAULT_SOCKET_DIR=/tmp
+fi
+
+DEFAULT_SOCKET_DIR=`echo $DEFAULT_SOCKET_DIR | sed 's/+/%2B/g'`
+
+if ! test -z "$with_test_socket_dir" ; then
+   TEST_SOCKET_DIR="$with_test_socket_dir"
+else
+   TEST_SOCKET_DIR=$DEFAULT_SOCKET_DIR
+fi
+AC_SUBST(TEST_SOCKET_DIR)
+AC_DEFINE_UNQUOTED(DBUS_TEST_SOCKET_DIR, "$TEST_SOCKET_DIR", [Where to put test sockets])
+
+if test "x$dbus_unix" = xyes; then
+  TEST_LISTEN="unix:tmpdir=$TEST_SOCKET_DIR"
+else
+  TEST_LISTEN="tcp:host=localhost"
+fi
+AC_SUBST([TEST_LISTEN])
+AC_DEFINE_UNQUOTED([TEST_LISTEN], ["$TEST_LISTEN"],
+  [Listening address for regression tests])
+
+if ! test -z "$with_session_socket_dir" ; then
+   DBUS_SESSION_SOCKET_DIR="$with_session_socket_dir"
+else
+   DBUS_SESSION_SOCKET_DIR=$DEFAULT_SOCKET_DIR
+fi
+AC_DEFINE_UNQUOTED(DBUS_SESSION_SOCKET_DIR, "$DBUS_SESSION_SOCKET_DIR", [Where per-session bus puts its sockets])
+AC_SUBST(DBUS_SESSION_SOCKET_DIR)
+
+if test x$dbus_win = xyes; then
+        DBUS_SESSION_BUS_DEFAULT_ADDRESS="$with_dbus_session_bus_default_address"
+elif test x$have_launchd = xyes; then
+        DBUS_SESSION_BUS_DEFAULT_ADDRESS="launchd:env=DBUS_LAUNCHD_SESSION_BUS_SOCKET"
+else
+        DBUS_SESSION_BUS_DEFAULT_ADDRESS="unix:tmpdir=$DBUS_SESSION_SOCKET_DIR"
+fi
+AC_SUBST(DBUS_SESSION_BUS_DEFAULT_ADDRESS)
+
+# darwin needs this to initialize the environment
+AC_CHECK_HEADERS(crt_externs.h)
+AC_CHECK_FUNC(_NSGetEnviron, [AC_DEFINE(HAVE_NSGETENVIRON, 1, [Define if your system needs _NSGetEnviron to set up the environment])])
+AH_VERBATIM(_DARWIN_ENVIRON,
+[
+#if defined(HAVE_NSGETENVIRON) && defined(HAVE_CRT_EXTERNS_H)
+# include <sys/time.h>
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+#endif
+])
+
+AC_ARG_ENABLE([stats],
+  [AS_HELP_STRING([--enable-stats],
+    [enable bus daemon usage statistics])],
+  [], [enable_stats=no])
+if test "x$enable_stats" = xyes; then
+  AC_DEFINE([DBUS_ENABLE_STATS], [1],
+    [Define to enable bus daemon usage statistics])
+fi
+
+AC_CONFIG_FILES([
+Doxyfile
+dbus/versioninfo.rc
+dbus/dbus-arch-deps.h
+bus/system.conf
+bus/session.conf
+bus/messagebus
+bus/messagebus-config
+bus/org.freedesktop.dbus-session.plist
+bus/rc.messagebus
+bus/dbus.service
+bus/dbus.socket
+Makefile
+dbus/Makefile
+bus/Makefile
+tools/Makefile
+test/Makefile
+test/name-test/Makefile
+doc/Makefile
+doc/dbus-daemon.1
+dbus-1.pc
+dbus-1-uninstalled.pc
+test/data/valid-config-files/debug-allow-all.conf
+test/data/valid-config-files/debug-allow-all-sha1.conf
+test/data/valid-config-files-system/debug-allow-all-pass.conf
+test/data/valid-config-files-system/debug-allow-all-fail.conf
+test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service
+test/data/valid-service-files/org.freedesktop.DBus.TestSuiteEchoService.service
+test/data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service
+test/data/valid-service-files/org.freedesktop.DBus.TestSuiteSegfaultService.service
+test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service
+test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service
+test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteEchoService.service
+test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteSegfaultService.service
+test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service
+test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service
+test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service
+test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoUser.service
+test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service
+])
+AC_OUTPUT
+
+dnl ==========================================================================
+echo "
+                    D-Bus $VERSION
+                  ==============
+
+	prefix:                   ${EXPANDED_PREFIX}
+	exec_prefix:              ${exec_prefix}
+        libdir:                   ${EXPANDED_LIBDIR}
+        libexecdir:               ${EXPANDED_LIBEXECDIR}
+        bindir:                   ${EXPANDED_BINDIR}
+        sysconfdir:               ${EXPANDED_SYSCONFDIR}
+        localstatedir:            ${EXPANDED_LOCALSTATEDIR}
+	datadir:                  ${EXPANDED_DATADIR}
+	source code location:	  ${srcdir}
+	compiler:		  ${CC}
+	cflags:		          ${CFLAGS}
+	cppflags:		  ${CPPFLAGS}
+	cxxflags:		  ${CXXFLAGS}
+	64-bit int:		  ${DBUS_INT64_TYPE}
+	32-bit int:		  ${DBUS_INT32_TYPE}
+	16-bit int:		  ${DBUS_INT16_TYPE}
+        Doxygen:                  ${DOXYGEN:-not found}
+        xmlto:                    ${XMLTO:-not found}
+        man2html:                 ${MAN2HTML:-not found}"
+
+echo "
+        Rebuilding generated files: ${USE_MAINTAINER_MODE}
+        gcc coverage profiling:   ${enable_compiler_coverage}
+        Building embedded tests:  ${enable_embedded_tests}
+        Building modular tests:   ${enable_modular_tests}
+            - with GLib:          ${with_glib}
+        Building verbose mode:    ${enable_verbose_mode}
+        Building assertions:      ${enable_asserts}
+        Building checks:          ${enable_checks}
+        Building bus stats API:   ${enable_stats}
+        Building SELinux support: ${have_selinux}
+        Building inotify support: ${have_inotify}
+        Building dnotify support: ${have_dnotify}
+        Building kqueue support:  ${have_kqueue}
+        Building systemd support: ${have_systemd}
+        Building X11 code:        ${enable_x11}
+        Building Doxygen docs:    ${enable_doxygen_docs}
+        Building XML docs:        ${enable_xml_docs}
+        Building cache support:   ${enable_userdb_cache}
+        Building launchd support: ${have_launchd}
+        Using XML parser:         ${with_xml}
+        Init scripts style:       ${with_init_scripts}
+        Abstract socket names:    ${ac_cv_have_abstract_sockets}
+        System bus socket:        ${DBUS_SYSTEM_SOCKET}
+        System bus address:       ${DBUS_SYSTEM_BUS_DEFAULT_ADDRESS}
+        System bus PID file:      ${DBUS_SYSTEM_PID_FILE}
+        Session bus address:      ${DBUS_SESSION_BUS_DEFAULT_ADDRESS}
+        Console auth dir:         ${DBUS_CONSOLE_AUTH_DIR}
+        Console owner file:       ${have_console_owner_file}
+        Console owner file path:  ${DBUS_CONSOLE_OWNER_FILE}
+	System bus user:          ${DBUS_USER}
+	Session bus services dir: ${EXPANDED_DATADIR}/dbus-1/services
+        'make check' socket dir:  ${TEST_SOCKET_DIR}
+"
+if test x$have_launchd = xyes; then
+        echo "        launchd agent dir:        ${LAUNCHD_AGENT_DIR}"
+fi
+echo
+
+if test x$enable_embedded_tests = xyes; then
+        echo "NOTE: building with unit tests increases the size of the installed library and renders it insecure."
+fi
+if test x$enable_embedded_tests = xyes -a x$enable_asserts = xno; then
+        echo "NOTE: building with embedded tests but without assertions means tests may not properly report failures (this configuration is only useful when doing something like profiling the tests)"
+fi
+if test x$enable_compiler_coverage = xyes; then
+        echo "NOTE: building with coverage profiling is definitely for developers only."
+fi
+if test x$enable_verbose_mode = xyes; then
+        echo "NOTE: building with verbose mode increases library size, may slightly increase security risk, and decreases performance."
+fi
+if test x$enable_asserts = xyes; then
+        echo "NOTE: building with assertions increases library size and decreases performance."
+fi
+if test x$enable_checks = xno; then
+        echo "NOTE: building without checks for arguments passed to public API makes it harder to debug apps using D-Bus, but will slightly decrease D-Bus library size and _very_ slightly improve performance."
+fi
+if test x$dbus_use_libxml = xtrue; then
+        echo
+	echo "WARNING: You have chosen to use libxml as your xml parser however this code path is not maintained by the D-Bus developers and if it breaks you get to keep the pieces.  If you have selected this option in err please reconfigure with expat (e.g. --with-xml=expat)."
+fi
+
+if test "x$DBUS_HAVE_INT64" = x0; then
+  AC_MSG_WARN([You have disabled 64-bit integers via --without-64-bit.
+
+  This removes parts of the standard D-Bus API and ABI (the 't' and 'x'
+  typecodes, the dbus_int64_t and dbus_uint64_t types, etc.) and should only be
+  used if your compiler lacks support for 64-bit integers. Please report a bug
+  with details of your platform and compiler.
+
+  This option is likely to be removed in future, unless the D-Bus developers
+  receive reports that it is still needed.
+  ])
+fi
diff --git a/dbus/dbus-1-uninstalled.pc.in b/dbus/dbus-1-uninstalled.pc.in
new file mode 100644
index 0000000..038c83e
--- /dev/null
+++ b/dbus/dbus-1-uninstalled.pc.in
@@ -0,0 +1,17 @@
+abs_top_builddir=@abs_top_builddir@
+abs_top_srcdir=@abs_top_srcdir@
+prefix=
+exec_prefix=
+system_bus_default_address=@DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@
+sysconfdir=@EXPANDED_SYSCONFDIR@
+session_bus_services_dir=@EXPANDED_DATADIR@/dbus-1/services
+system_bus_services_dir=@EXPANDED_DATADIR@/dbus-1/system-services
+interfaces_dir=@EXPANDED_DATADIR@/dbus-1/interfaces
+daemondir=@DBUS_DAEMONDIR@
+
+Name: dbus
+Description: Free desktop message bus (uninstalled copy)
+Version: @VERSION@
+Libs: ${abs_top_builddir}/dbus/libdbus-1.la
+Libs.private: @LIBDBUS_LIBS@
+Cflags: -I${abs_top_srcdir} @DBUS_STATIC_BUILD_CPPFLAGS@
diff --git a/dbus/dbus-1.pc.in b/dbus/dbus-1.pc.in
new file mode 100644
index 0000000..25f8bce
--- /dev/null
+++ b/dbus/dbus-1.pc.in
@@ -0,0 +1,17 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+system_bus_default_address=@DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@
+sysconfdir=@EXPANDED_SYSCONFDIR@
+session_bus_services_dir=@EXPANDED_DATADIR@/dbus-1/services
+system_bus_services_dir=@EXPANDED_DATADIR@/dbus-1/system-services
+interfaces_dir=@EXPANDED_DATADIR@/dbus-1/interfaces
+daemondir=@DBUS_DAEMONDIR@
+
+Name: dbus
+Description: Free desktop message bus
+Version: @VERSION@
+Libs: -L${libdir} -ldbus-1
+Libs.private: @LIBDBUS_LIBS@
+Cflags: -I${includedir}/dbus-1.0 -I${libdir}/dbus-1.0/include @DBUS_STATIC_BUILD_CPPFLAGS@
diff --git a/dbus/dbus/Android.bp b/dbus/dbus/Android.bp
new file mode 100644
index 0000000..5d12346
--- /dev/null
+++ b/dbus/dbus/Android.bp
@@ -0,0 +1,86 @@
+cc_library_shared {
+    name: "libdbus",
+
+    srcs: [
+        "dbus-address.c",
+        "dbus-auth.c",
+        "dbus-bus.c",
+        "dbus-connection.c",
+        "dbus-credentials.c",
+        "dbus-dataslot.c",
+        "dbus-errors.c",
+        "dbus-file.c",
+        "dbus-file-unix.c",
+        "dbus-hash.c",
+        "dbus-internals.c",
+        "dbus-keyring.c",
+        "dbus-list.c",
+        "dbus-mainloop.c",
+        "dbus-marshal-basic.c",
+        "dbus-marshal-byteswap.c",
+        "dbus-marshal-header.c",
+        "dbus-marshal-recursive.c",
+        "dbus-marshal-validate.c",
+        "dbus-mempool.c",
+        "dbus-memory.c",
+        "dbus-message.c",
+        "dbus-misc.c",
+        "dbus-nonce.c",
+        "dbus-pending-call.c",
+        "dbus-pipe.c",
+        "dbus-pipe-unix.c",
+        "dbus-resources.c",
+        "dbus-server.c",
+        "dbus-server-socket.c",
+        "dbus-server-unix.c",
+        "dbus-sha.c",
+        "dbus-shell.c",
+        "dbus-signature.c",
+        "dbus-socket-set.c",
+        "dbus-socket-set-poll.c",
+        "dbus-spawn.c",
+        "dbus-string.c",
+        "dbus-string-util.c",
+        "dbus-sysdeps.c",
+        "dbus-sysdeps-pthread.c",
+        "dbus-sysdeps-unix.c",
+        "dbus-sysdeps-util.c",
+        "dbus-sysdeps-util-unix.c",
+        "dbus-timeout.c",
+        "dbus-threads.c",
+        "dbus-transport.c",
+        "dbus-transport-socket.c",
+        "dbus-transport-unix.c",
+        "dbus-object-tree.c",
+        "dbus-userdb.c",
+        "dbus-userdb-util.c",
+        "dbus-watch.c",
+        "sd-daemon.c",
+    ],
+
+    cflags: [
+        "-DDBUS_ANDROID_LOG",
+        "-DDBUS_COMPILATION",
+        "-DANDROID_MANAGED_SOCKET",
+        "-DHAVE_MONOTONIC_CLOCK",
+        "-DDBUS_MACHINE_UUID_FILE=\\\"/etc/machine-id\\\"",
+        "-DDBUS_SYSTEM_CONFIG_FILE=\\\"/system/etc/dbus.conf\\\"",
+        "-DDBUS_SESSION_CONFIG_FILE=\\\"/system/etc/session.conf\\\"",
+        "-Wno-empty-body",
+        "-Wno-missing-field-initializers",
+        "-Wno-pointer-sign",
+        "-Wno-sign-compare",
+        "-Wno-tautological-compare",
+        "-Wno-type-limits",
+        "-Wno-unused-parameter",
+    ],
+    clang: true,
+
+    static_libs: ["libdbus-headers"],
+    export_static_lib_headers: ["libdbus-headers"],
+
+    shared_libs: [
+        "libcutils",
+        "liblog",
+    ],
+}
diff --git a/dbus/dbus/Makefile.am b/dbus/dbus/Makefile.am
new file mode 100644
index 0000000..bb5ccca
--- /dev/null
+++ b/dbus/dbus/Makefile.am
@@ -0,0 +1,312 @@
+
+configdir=$(sysconfdir)/dbus-1
+
+AM_CPPFLAGS = \
+	-I$(top_builddir) \
+	-I$(top_srcdir) \
+	$(SYSTEMD_CFLAGS) \
+	$(VALGRIND_CFLAGS) \
+	-DDBUS_COMPILATION \
+	-DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" \
+	-DDBUS_SYSTEM_CONFIG_FILE=\""$(configdir)/system.conf"\" \
+	-DDBUS_SESSION_CONFIG_FILE=\""$(configdir)/session.conf"\" \
+	$(NULL)
+
+# if assertions are enabled, improve backtraces
+AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
+
+dbusincludedir=$(includedir)/dbus-1.0/dbus
+dbusarchincludedir=$(libdir)/dbus-1.0/include/dbus
+
+lib_LTLIBRARIES=libdbus-1.la
+
+#
+# Deal with W32 .def and version-info.rc stuff
+#
+if DBUS_WIN
+
+SUFFIXES = rc
+
+.rc.o:
+	$(WINDRES) $< -o $@
+
+dbus_res = versioninfo.o
+dbus_res_ldflag = -Wl,$(dbus_res)
+no_undefined = -no-undefined
+export_symbols =
+
+libdbus_1_la_DEPENDENCIES = $(dbus_res)
+intllibs =
+
+else
+dbus_res =
+dbus_res_ldflag =
+no_undefined =
+## don't export symbols that start with "_" (we use this
+## convention for internal symbols)
+export_symbols = -export-symbols-regex "^[^_].*"
+
+intllibs = @LTLIBINTL@
+
+endif
+
+
+#
+# Platform-dependent sources:
+#
+if DBUS_WIN
+DBUS_LIB_arch_sources = 			\
+	dbus-server-win.c 			\
+	dbus-server-win.h
+
+if DBUS_WINCE
+wince_source = dbus-sysdeps-wince-glue.h dbus-sysdeps-wince-glue.c
+else
+wince_source =
+endif
+
+DBUS_SHARED_arch_sources = 			\
+	$(wince_source)				\
+	dbus-file-win.c 			\
+	dbus-pipe-win.c 			\
+	dbus-sockets-win.h			\
+	dbus-sysdeps-win.c 			\
+	dbus-sysdeps-win.h			\
+	dbus-sysdeps-thread-win.c		\
+	dbus-transport-win.c			\
+	dbus-transport-win.h
+
+DBUS_UTIL_arch_sources =			\
+	dbus-sysdeps-util-win.c			\
+	dbus-spawn-win.c
+else
+
+if DBUS_ENABLE_LAUNCHD
+launchd_source = dbus-server-launchd.h dbus-server-launchd.c
+else
+launchd_source =
+endif
+
+DBUS_LIB_arch_sources = 			\
+	dbus-uuidgen.c				\
+	dbus-uuidgen.h				\
+	dbus-server-unix.c 			\
+	dbus-server-unix.h
+
+DBUS_SHARED_arch_sources = 			\
+	$(launchd_source)			\
+	dbus-file-unix.c 			\
+	dbus-pipe-unix.c 			\
+	dbus-sysdeps-unix.c 			\
+	dbus-sysdeps-unix.h			\
+	dbus-sysdeps-pthread.c			\
+	dbus-transport-unix.c			\
+	dbus-transport-unix.h			\
+	dbus-userdb.c				\
+	dbus-userdb.h 				\
+	sd-daemon.c                             \
+	sd-daemon.h
+
+DBUS_UTIL_arch_sources = 			\
+	dbus-sysdeps-util-unix.c		\
+	dbus-userdb-util.c			\
+	dbus-spawn.c
+endif
+
+if HAVE_LINUX_EPOLL
+DBUS_UTIL_arch_sources += dbus-socket-set-epoll.c
+endif
+
+dbusinclude_HEADERS=				\
+	dbus.h					\
+	dbus-address.h				\
+	dbus-bus.h				\
+	dbus-connection.h			\
+	dbus-errors.h				\
+	dbus-macros.h				\
+	dbus-memory.h				\
+	dbus-message.h				\
+	dbus-misc.h				\
+	dbus-pending-call.h			\
+	dbus-protocol.h				\
+	dbus-server.h				\
+	dbus-shared.h				\
+	dbus-signature.h			\
+	dbus-syntax.h				\
+	dbus-threads.h				\
+	dbus-types.h
+
+
+nodist_dbusarchinclude_HEADERS=			\
+	dbus-arch-deps.h
+
+### source code that goes in the installed client library
+### and is specific to library functionality
+DBUS_LIB_SOURCES=				\
+	dbus-address.c				\
+	dbus-auth.c				\
+	dbus-auth.h				\
+	dbus-bus.c				\
+	dbus-connection.c			\
+	dbus-connection-internal.h		\
+	dbus-credentials.c			\
+	dbus-credentials.h			\
+	dbus-errors.c				\
+	dbus-keyring.c				\
+	dbus-keyring.h				\
+	dbus-marshal-header.c			\
+	dbus-marshal-header.h			\
+	dbus-marshal-byteswap.c			\
+	dbus-marshal-byteswap.h			\
+	dbus-marshal-recursive.c		\
+	dbus-marshal-recursive.h		\
+	dbus-marshal-validate.c			\
+	dbus-marshal-validate.h			\
+	dbus-message.c				\
+	dbus-message-internal.h			\
+	dbus-message-private.h			\
+	dbus-misc.c				\
+	dbus-nonce.h				\
+	dbus-nonce.c				\
+	dbus-object-tree.c			\
+	dbus-object-tree.h			\
+	dbus-pending-call.c			\
+	dbus-pending-call-internal.h		\
+	dbus-resources.c			\
+	dbus-resources.h			\
+	dbus-server.c				\
+	dbus-server-debug-pipe.c		\
+	dbus-server-debug-pipe.h		\
+	dbus-server-protected.h			\
+	dbus-server-socket.c			\
+	dbus-server-socket.h			\
+	$(DBUS_LIB_arch_sources)		\
+	dbus-sha.c				\
+	dbus-sha.h				\
+	dbus-signature.c			\
+	dbus-syntax.c				\
+	dbus-timeout.c				\
+	dbus-timeout.h				\
+	dbus-threads-internal.h			\
+	dbus-threads.c				\
+	dbus-transport.c			\
+	dbus-transport.h			\
+	dbus-transport-protected.h		\
+	dbus-transport-socket.c			\
+	dbus-transport-socket.h			\
+	dbus-watch.c				\
+	dbus-watch.h
+
+### source code that goes in the installed client library
+### AND is generic utility functionality used by the
+### daemon or test programs (all symbols in here should
+### be underscore-prefixed)
+DBUS_SHARED_SOURCES=				\
+	dbus-dataslot.c				\
+	dbus-dataslot.h				\
+	dbus-file.c                 \
+	dbus-file.h                 \
+	dbus-hash.c				\
+	dbus-hash.h				\
+	dbus-internals.c			\
+	dbus-internals.h			\
+	dbus-list.c				\
+	dbus-list.h				\
+	dbus-marshal-basic.c			\
+	dbus-marshal-basic.h			\
+	dbus-memory.c				\
+	dbus-mempool.c				\
+	dbus-mempool.h				\
+	dbus-pipe.c                 \
+	dbus-pipe.h                 \
+	dbus-string.c				\
+	dbus-string.h				\
+	dbus-string-private.h			\
+	$(DBUS_SHARED_arch_sources)		\
+	dbus-sysdeps.c				\
+	dbus-sysdeps.h				\
+	dbus-valgrind-internal.h
+
+### source code that is generic utility functionality used
+### by the bus daemon or test apps, but is NOT included
+### in the D-Bus client library (all symbols in here
+### should be underscore-prefixed but don't really need
+### to be unless they move to DBUS_SHARED_SOURCES later)
+DBUS_UTIL_SOURCES=				\
+	dbus-auth-script.c			\
+	dbus-auth-script.h			\
+	dbus-auth-util.c			\
+	dbus-credentials-util.c			\
+	dbus-mainloop.c				\
+	dbus-mainloop.h				\
+	dbus-marshal-byteswap-util.c		\
+	dbus-marshal-recursive-util.c		\
+	dbus-marshal-validate-util.c		\
+	dbus-message-factory.c			\
+	dbus-message-factory.h			\
+	dbus-message-util.c			\
+	dbus-shell.c				\
+	dbus-shell.h				\
+	$(DBUS_UTIL_arch_sources)		\
+	dbus-socket-set.h			\
+	dbus-socket-set.c			\
+	dbus-socket-set-poll.c			\
+	dbus-spawn.h				\
+	dbus-string-util.c			\
+	dbus-sysdeps-util.c			\
+	dbus-test.c				\
+	dbus-test.h
+
+libdbus_1_la_SOURCES=				\
+	$(DBUS_LIB_SOURCES)			\
+	$(DBUS_SHARED_SOURCES)
+
+libdbus_internal_la_SOURCES=			\
+	$(DBUS_LIB_SOURCES)			\
+	$(DBUS_SHARED_SOURCES)			\
+	$(DBUS_UTIL_SOURCES)
+
+BUILT_SOURCES=$(nodist_dbusarchinclude_HEADERS)
+EXTRA_DIST=dbus-arch-deps.h.in
+
+## this library is the same as libdbus, but exports all the symbols
+## and is only used for static linking within the dbus package.
+noinst_LTLIBRARIES=libdbus-internal.la
+
+libdbus_1_la_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	-Ddbus_1_EXPORTS \
+	$(NULL)
+libdbus_1_la_LIBADD= $(LIBDBUS_LIBS)
+libdbus_1_la_LDFLAGS = \
+	$(AM_LDFLAGS) \
+	$(export_symbols) \
+	-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+	-no-undefined \
+	$(NULL)
+
+libdbus_internal_la_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	-DDBUS_STATIC_BUILD \
+	$(NULL)
+libdbus_internal_la_LIBADD=$(LIBDBUS_LIBS) $(SYSTEMD_LIBS)
+
+noinst_PROGRAMS =
+
+if DBUS_BUILD_TESTS
+# We can't actually run this til we've reached test/
+noinst_PROGRAMS += dbus-test
+endif
+
+dbus_test_SOURCES=				\
+	dbus-test-main.c
+
+dbus_test_LDADD = libdbus-internal.la
+
+## mop up the gcov files
+clean-local:
+	/bin/rm *.bb *.bbg *.da *.gcov .libs/*.da .libs/*.bbg || true
+
+update-systemd:
+	curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c > sd-daemon.c
+	curl http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h > sd-daemon.h
diff --git a/dbus/dbus/NOTICE b/dbus/dbus/NOTICE
new file mode 100644
index 0000000..a91ca1d
--- /dev/null
+++ b/dbus/dbus/NOTICE
@@ -0,0 +1,551 @@
+D-Bus is licensed to you under your choice of the Academic Free
+License version 2.1, or the GNU General Public License version 2.
+Both licenses are included here. Some of the standalone binaries are
+under the GPL only; in particular, but not limited to,
+tools/dbus-cleanup-sockets.c and test/decode-gcov.c. Each source code
+file is marked with the proper copyright information - if you find a
+file that isn't marked please bring it to our attention.
+
+
+The Academic Free License
+v. 2.1
+
+This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
+
+Licensed under the Academic Free License version 2.1
+
+1) Grant of Copyright License. Licensor hereby grants You a
+world-wide, royalty-free, non-exclusive, perpetual, sublicenseable
+license to do the following:
+
+a) to reproduce the Original Work in copies;
+
+b) to prepare derivative works ("Derivative Works") based upon the Original Work;
+
+c) to distribute copies of the Original Work and Derivative Works to the public;
+
+d) to perform the Original Work publicly; and
+
+e) to display the Original Work publicly.
+
+2) Grant of Patent License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license, under
+patent claims owned or controlled by the Licensor that are embodied in
+the Original Work as furnished by the Licensor, to make, use, sell and
+offer for sale the Original Work and Derivative Works.
+
+3) Grant of Source Code License. The term "Source Code" means the
+preferred form of the Original Work for making modifications to it and
+all available documentation describing how to modify the Original
+Work. Licensor hereby agrees to provide a machine-readable copy of the
+Source Code of the Original Work along with each copy of the Original
+Work that Licensor distributes. Licensor reserves the right to satisfy
+this obligation by placing a machine-readable copy of the Source Code
+in an information repository reasonably calculated to permit
+inexpensive and convenient access by You for as long as Licensor
+continues to distribute the Original Work, and by publishing the
+address of that information repository in a notice immediately
+following the copyright notice that applies to the Original Work.
+
+4) Exclusions From License Grant. Neither the names of Licensor, nor
+the names of any contributors to the Original Work, nor any of their
+trademarks or service marks, may be used to endorse or promote
+products derived from this Original Work without express prior written
+permission of the Licensor. Nothing in this License shall be deemed to
+grant any rights to trademarks, copyrights, patents, trade secrets or
+any other intellectual property of Licensor except as expressly stated
+herein. No patent license is granted to make, use, sell or offer to
+sell embodiments of any patent claims other than the licensed claims
+defined in Section 2. No right is granted to the trademarks of
+Licensor even if such marks are included in the Original Work. Nothing
+in this License shall be interpreted to prohibit Licensor from
+licensing under different terms from this License any Original Work
+that Licensor otherwise would have a right to license.
+
+5) This section intentionally omitted.
+
+6) Attribution Rights. You must retain, in the Source Code of any
+Derivative Works that You create, all copyright, patent or trademark
+notices from the Source Code of the Original Work, as well as any
+notices of licensing and any descriptive text identified therein as an
+"Attribution Notice." You must cause the Source Code for any
+Derivative Works that You create to carry a prominent Attribution
+Notice reasonably calculated to inform recipients that You have
+modified the Original Work.
+
+7) Warranty of Provenance and Disclaimer of Warranty. Licensor
+warrants that the copyright in and to the Original Work and the patent
+rights granted herein by Licensor are owned by the Licensor or are
+sublicensed to You under the terms of this License with the permission
+of the contributor(s) of those copyrights and patent rights. Except as
+expressly stated in the immediately proceeding sentence, the Original
+Work is provided under this License on an "AS IS" BASIS and WITHOUT
+WARRANTY, either express or implied, including, without limitation,
+the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL
+WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential
+part of this License. No license to Original Work is granted hereunder
+except under this disclaimer.
+
+8) Limitation of Liability. Under no circumstances and under no legal
+theory, whether in tort (including negligence), contract, or
+otherwise, shall the Licensor be liable to any person for any direct,
+indirect, special, incidental, or consequential damages of any
+character arising as a result of this License or the use of the
+Original Work including, without limitation, damages for loss of
+goodwill, work stoppage, computer failure or malfunction, or any and
+all other commercial damages or losses. This limitation of liability
+shall not apply to liability for death or personal injury resulting
+from Licensor's negligence to the extent applicable law prohibits such
+limitation. Some jurisdictions do not allow the exclusion or
+limitation of incidental or consequential damages, so this exclusion
+and limitation may not apply to You.
+
+9) Acceptance and Termination. If You distribute copies of the
+Original Work or a Derivative Work, You must make a reasonable effort
+under the circumstances to obtain the express assent of recipients to
+the terms of this License. Nothing else but this License (or another
+written agreement between Licensor and You) grants You permission to
+create Derivative Works based upon the Original Work or to exercise
+any of the rights granted in Section 1 herein, and any attempt to do
+so except under the terms of this License (or another written
+agreement between Licensor and You) is expressly prohibited by
+U.S. copyright law, the equivalent laws of other countries, and by
+international treaty. Therefore, by exercising any of the rights
+granted to You in Section 1 herein, You indicate Your acceptance of
+this License and all of its terms and conditions.
+
+10) Termination for Patent Action. This License shall terminate
+automatically and You may no longer exercise any of the rights granted
+to You by this License as of the date You commence an action,
+including a cross-claim or counterclaim, against Licensor or any
+licensee alleging that the Original Work infringes a patent. This
+termination provision shall not apply for an action alleging patent
+infringement by combinations of the Original Work with other software
+or hardware.
+
+11) Jurisdiction, Venue and Governing Law. Any action or suit relating
+to this License may be brought only in the courts of a jurisdiction
+wherein the Licensor resides or in which Licensor conducts its primary
+business, and under the laws of that jurisdiction excluding its
+conflict-of-law provisions. The application of the United Nations
+Convention on Contracts for the International Sale of Goods is
+expressly excluded. Any use of the Original Work outside the scope of
+this License or after its termination shall be subject to the
+requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101
+et seq., the equivalent laws of other countries, and international
+treaty. This section shall survive the termination of this License.
+
+12) Attorneys Fees. In any action to enforce the terms of this License
+or seeking damages relating thereto, the prevailing party shall be
+entitled to recover its costs and expenses, including, without
+limitation, reasonable attorneys' fees and costs incurred in
+connection with such action, including any appeal of such action. This
+section shall survive the termination of this License.
+
+13) Miscellaneous. This License represents the complete agreement
+concerning the subject matter hereof. If any provision of this License
+is held to be unenforceable, such provision shall be reformed only to
+the extent necessary to make it enforceable.
+
+14) Definition of "You" in This License. "You" throughout this
+License, whether in upper or lower case, means an individual or a
+legal entity exercising rights under, and complying with all of the
+terms of, this License. For legal entities, "You" includes any entity
+that controls, is controlled by, or is under common control with
+you. For purposes of this definition, "control" means (i) the power,
+direct or indirect, to cause the direction or management of such
+entity, whether by contract or otherwise, or (ii) ownership of fifty
+percent (50%) or more of the outstanding shares, or (iii) beneficial
+ownership of such entity.
+
+15) Right to Use. You may use the Original Work in all ways not
+otherwise restricted or conditioned by this License or by law, and
+Licensor promises not to interfere with or be responsible for such
+uses by You.
+
+This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights
+reserved. Permission is hereby granted to copy and distribute this
+license without modification. This license may not be modified without
+the express written permission of its copyright owner.
+
+
+-- 
+END OF ACADEMIC FREE LICENSE. The following is intended to describe the essential 
+differences between the Academic Free License (AFL) version 1.0 and other 
+open source licenses:
+
+The Academic Free License is similar to the BSD, MIT, UoI/NCSA and Apache 
+licenses in many respects but it is intended to solve a few problems with 
+those licenses.
+    
+* The AFL is written so as to make it clear what software is being 
+licensed (by the inclusion of a statement following the copyright notice 
+in the software). This way, the license functions better than a template 
+license. The BSD, MIT and UoI/NCSA licenses apply to unidentified software.
+    
+* The AFL contains a complete copyright grant to the software. The BSD 
+and Apache licenses are vague and incomplete in that respect.
+    
+* The AFL contains a complete patent grant to the software. The BSD, MIT, 
+UoI/NCSA and Apache licenses rely on an implied patent license and contain 
+no explicit patent grant.
+    
+* The AFL makes it clear that no trademark rights are granted to the 
+licensor's trademarks. The Apache license contains such a provision, but the 
+BSD, MIT and UoI/NCSA licenses do not.
+    
+* The AFL includes the warranty by the licensor that it either owns the 
+copyright or that it is distributing the software under a license. None of 
+the other licenses contain that warranty. All other warranties are disclaimed, 
+as is the case for the other licenses.
+
+* The AFL is itself copyrighted (with the right granted to copy and distribute 
+without modification). This ensures that the owner of the copyright to the 
+license will control changes. The Apache license contains a copyright notice, 
+but the BSD, MIT and UoI/NCSA licenses do not. 
+--
+START OF GNU GENERAL PUBLIC LICENSE
+--
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/dbus/dbus/dbus-address.c b/dbus/dbus/dbus-address.c
new file mode 100644
index 0000000..90484dc
--- /dev/null
+++ b/dbus/dbus/dbus-address.c
@@ -0,0 +1,826 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-address.c  Server address parser.
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2004,2005  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-address.h"
+#include "dbus-internals.h"
+#include "dbus-list.h"
+#include "dbus-string.h"
+#include "dbus-protocol.h"
+
+/**
+ * @defgroup DBusAddressInternals Address parsing
+ * @ingroup  DBusInternals
+ * @brief Implementation of parsing addresses of D-Bus servers.
+ *
+ * @{
+ */
+
+/**
+ * Internals of DBusAddressEntry 
+ */
+struct DBusAddressEntry
+{
+  DBusString method; /**< The address type (unix, tcp, etc.) */
+
+  DBusList *keys;    /**< List of keys */
+  DBusList *values;  /**< List of values */
+};
+
+
+/**
+ *
+ * Sets #DBUS_ERROR_BAD_ADDRESS.
+ * If address_problem_type and address_problem_field are not #NULL,
+ * sets an error message about how the field is no good. Otherwise, sets
+ * address_problem_other as the error message.
+ * 
+ * @param error the error to set
+ * @param address_problem_type the address type of the bad address or #NULL
+ * @param address_problem_field the missing field of the bad address or #NULL
+ * @param address_problem_other any other error message or #NULL
+ */
+void
+_dbus_set_bad_address (DBusError  *error,
+                       const char *address_problem_type,
+                       const char *address_problem_field,
+                       const char *address_problem_other)
+{
+  if (address_problem_type != NULL)
+    dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                    "Server address of type %s was missing argument %s",
+                    address_problem_type, address_problem_field);
+  else
+    dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                    "Could not parse server address: %s",
+                    address_problem_other);
+}
+
+/**
+ * #TRUE if the byte need not be escaped when found in a dbus address.
+ * All other bytes are required to be escaped in a valid address.
+ */
+#define _DBUS_ADDRESS_OPTIONALLY_ESCAPED_BYTE(b)        \
+         (((b) >= 'a' && (b) <= 'z') ||                 \
+          ((b) >= 'A' && (b) <= 'Z') ||                 \
+          ((b) >= '0' && (b) <= '9') ||                 \
+          (b) == '-' ||                                 \
+          (b) == '_' ||                                 \
+          (b) == '/' ||                                 \
+          (b) == '\\' ||                                \
+          (b) == '*' ||                                \
+          (b) == '.')
+
+/**
+ * Appends an escaped version of one string to another string,
+ * using the D-Bus address escaping mechanism
+ *
+ * @param escaped the string to append to
+ * @param unescaped the string to escape
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_address_append_escaped (DBusString       *escaped,
+                              const DBusString *unescaped)
+{
+  const char *p;
+  const char *end;
+  dbus_bool_t ret;
+  int orig_len;
+
+  ret = FALSE;
+
+  orig_len = _dbus_string_get_length (escaped);
+  p = _dbus_string_get_const_data (unescaped);
+  end = p + _dbus_string_get_length (unescaped);
+  while (p != end)
+    {
+      if (_DBUS_ADDRESS_OPTIONALLY_ESCAPED_BYTE (*p))
+        {
+          if (!_dbus_string_append_byte (escaped, *p))
+            goto out;
+        }
+      else
+        {
+          if (!_dbus_string_append_byte (escaped, '%'))
+            goto out;
+          if (!_dbus_string_append_byte_as_hex (escaped, *p))
+            goto out;
+        }
+      
+      ++p;
+    }
+
+  ret = TRUE;
+  
+ out:
+  if (!ret)
+    _dbus_string_set_length (escaped, orig_len);
+  return ret;
+}
+
+/** @} */ /* End of internals */
+
+static void
+dbus_address_entry_free (DBusAddressEntry *entry)
+{
+  DBusList *link;
+  
+  _dbus_string_free (&entry->method);
+
+  link = _dbus_list_get_first_link (&entry->keys);
+  while (link != NULL)
+    {
+      _dbus_string_free (link->data);
+      dbus_free (link->data);
+      
+      link = _dbus_list_get_next_link (&entry->keys, link);
+    }
+  _dbus_list_clear (&entry->keys);
+  
+  link = _dbus_list_get_first_link (&entry->values);
+  while (link != NULL)
+    {
+      _dbus_string_free (link->data);
+      dbus_free (link->data);
+      
+      link = _dbus_list_get_next_link (&entry->values, link);
+    }
+  _dbus_list_clear (&entry->values);
+  
+  dbus_free (entry);
+}
+
+/**
+ * @defgroup DBusAddress Address parsing
+ * @ingroup  DBus
+ * @brief Parsing addresses of D-Bus servers.
+ *
+ * @{
+ */
+
+/**
+ * Frees a #NULL-terminated array of address entries.
+ *
+ * @param entries the array.
+ */
+void
+dbus_address_entries_free (DBusAddressEntry **entries)
+{
+  int i;
+  
+  for (i = 0; entries[i] != NULL; i++)
+    dbus_address_entry_free (entries[i]);
+  dbus_free (entries);
+}
+
+static DBusAddressEntry *
+create_entry (void)
+{
+  DBusAddressEntry *entry;
+
+  entry = dbus_new0 (DBusAddressEntry, 1);
+
+  if (entry == NULL)
+    return NULL;
+
+  if (!_dbus_string_init (&entry->method))
+    {
+      dbus_free (entry);
+      return NULL;
+    }
+
+  return entry;
+}
+
+/**
+ * Returns the method string of an address entry.  For example, given
+ * the address entry "tcp:host=example.com" it would return the string
+ * "tcp"
+ *
+ * @param entry the entry.
+ * @returns a string describing the method. This string
+ * must not be freed.
+ */
+const char *
+dbus_address_entry_get_method (DBusAddressEntry *entry)
+{
+  return _dbus_string_get_const_data (&entry->method);
+}
+
+/**
+ * Returns a value from a key of an entry. For example,
+ * given the address "tcp:host=example.com,port=8073" if you asked
+ * for the key "host" you would get the value "example.com"
+ *
+ * The returned value is already unescaped.
+ * 
+ * @param entry the entry.
+ * @param key the key.
+ * @returns the key value. This string must not be freed.
+ */
+const char *
+dbus_address_entry_get_value (DBusAddressEntry *entry,
+			      const char       *key)
+{
+  DBusList *values, *keys;
+
+  keys = _dbus_list_get_first_link (&entry->keys);
+  values = _dbus_list_get_first_link (&entry->values);
+
+  while (keys != NULL)
+    {
+      _dbus_assert (values != NULL);
+
+      if (_dbus_string_equal_c_str (keys->data, key))
+        return _dbus_string_get_const_data (values->data);
+
+      keys = _dbus_list_get_next_link (&entry->keys, keys);
+      values = _dbus_list_get_next_link (&entry->values, values);
+    }
+  
+  return NULL;
+}
+
+static dbus_bool_t
+append_unescaped_value (DBusString       *unescaped,
+                        const DBusString *escaped,
+                        int               escaped_start,
+                        int               escaped_len,
+                        DBusError        *error)
+{
+  const char *p;
+  const char *end;
+  dbus_bool_t ret;
+  
+  ret = FALSE;
+
+  p = _dbus_string_get_const_data (escaped) + escaped_start;
+  end = p + escaped_len;
+  while (p != end)
+    {
+      if (_DBUS_ADDRESS_OPTIONALLY_ESCAPED_BYTE (*p))
+        {
+          if (!_dbus_string_append_byte (unescaped, *p))
+            goto out;
+        }
+      else if (*p == '%')
+        {
+          /* Efficiency is king */
+          char buf[3];
+          DBusString hex;
+          int hex_end;
+          
+          ++p;
+
+          if ((p + 2) > end)
+            {
+              dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                              "In D-Bus address, percent character was not followed by two hex digits");
+              goto out;
+            }
+            
+          buf[0] = *p;
+          ++p;
+          buf[1] = *p;
+          buf[2] = '\0';
+
+          _dbus_string_init_const (&hex, buf);
+
+          if (!_dbus_string_hex_decode (&hex, 0, &hex_end,
+                                        unescaped,
+                                        _dbus_string_get_length (unescaped)))
+            goto out;
+
+          if (hex_end != 2)
+            {
+              dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                              "In D-Bus address, percent character was followed by characters other than hex digits");
+              goto out;
+            }
+        }
+      else
+        {
+          /* Error, should have been escaped */
+          dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                          "In D-Bus address, character '%c' should have been escaped\n",
+                          *p);
+          goto out;
+        }
+      
+      ++p;
+    }
+
+  ret = TRUE;
+  
+ out:
+  if (!ret && error && !dbus_error_is_set (error))
+    _DBUS_SET_OOM (error);
+
+  _dbus_assert (ret || error == NULL || dbus_error_is_set (error));
+  
+  return ret;
+}
+
+/**
+ * Parses an address string of the form:
+ *
+ * method:key=value,key=value;method:key=value
+ *
+ * See the D-Bus specification for complete docs on the format.
+ *
+ * When connecting to an address, the first address entries
+ * in the semicolon-separated list should be tried first.
+ * 
+ * @param address the address.
+ * @param entry return location to an array of entries.
+ * @param array_len return location for array length.
+ * @param error address where an error can be returned.
+ * @returns #TRUE on success, #FALSE otherwise.
+ */
+dbus_bool_t
+dbus_parse_address (const char         *address,
+		    DBusAddressEntry ***entry,
+		    int                *array_len,
+                    DBusError          *error)
+{
+  DBusString str;
+  int pos, end_pos, len, i;
+  DBusList *entries, *link;
+  DBusAddressEntry **entry_array;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  _dbus_string_init_const (&str, address);
+
+  entries = NULL;
+  pos = 0;
+  len = _dbus_string_get_length (&str);
+
+  if (len == 0)
+  {
+    dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                    "Empty address '%s'", address);
+    goto error;
+  }
+  
+  while (pos < len)
+    {
+      DBusAddressEntry *entry;
+
+      int found_pos;
+
+      entry = create_entry ();
+      if (!entry)
+	{
+	  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+
+	  goto error;
+	}
+      
+      /* Append the entry */
+      if (!_dbus_list_append (&entries, entry))
+	{
+	  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+	  dbus_address_entry_free (entry);
+	  goto error;
+	}
+      
+      /* Look for a semi-colon */
+      if (!_dbus_string_find (&str, pos, ";", &end_pos))
+	end_pos = len;
+      
+      /* Look for the colon : */
+      if (!_dbus_string_find_to (&str, pos, end_pos, ":", &found_pos))
+	{
+	  dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, "Address does not contain a colon");
+	  goto error;
+	}
+
+      if (!_dbus_string_copy_len (&str, pos, found_pos - pos, &entry->method, 0))
+	{
+	  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+	  goto error;
+	}
+	  
+      pos = found_pos + 1;
+
+      while (pos < end_pos)
+	{
+	  int comma_pos, equals_pos;
+
+	  if (!_dbus_string_find_to (&str, pos, end_pos, ",", &comma_pos))
+	    comma_pos = end_pos;
+	  
+	  if (!_dbus_string_find_to (&str, pos, comma_pos, "=", &equals_pos) ||
+	      equals_pos == pos || equals_pos + 1 == comma_pos)
+	    {
+	      dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                              "'=' character not found or has no value following it");
+              goto error;
+	    }
+	  else
+	    {
+	      DBusString *key;
+	      DBusString *value;
+
+	      key = dbus_new0 (DBusString, 1);
+
+	      if (!key)
+		{
+		  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);		  
+		  goto error;
+		}
+
+	      value = dbus_new0 (DBusString, 1);
+	      if (!value)
+		{
+		  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+		  dbus_free (key);
+		  goto error;
+		}
+	      
+	      if (!_dbus_string_init (key))
+		{
+		  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+		  dbus_free (key);
+		  dbus_free (value);
+		  
+		  goto error;
+		}
+	      
+	      if (!_dbus_string_init (value))
+		{
+		  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+		  _dbus_string_free (key);
+
+		  dbus_free (key);
+		  dbus_free (value);		  
+		  goto error;
+		}
+
+	      if (!_dbus_string_copy_len (&str, pos, equals_pos - pos, key, 0))
+		{
+		  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+		  _dbus_string_free (key);
+		  _dbus_string_free (value);
+
+		  dbus_free (key);
+		  dbus_free (value);		  
+		  goto error;
+		}
+
+	      if (!append_unescaped_value (value, &str, equals_pos + 1,
+                                           comma_pos - equals_pos - 1, error))
+		{
+                  _dbus_assert (error == NULL || dbus_error_is_set (error));
+		  _dbus_string_free (key);
+		  _dbus_string_free (value);
+
+		  dbus_free (key);
+		  dbus_free (value);		  
+		  goto error;
+		}
+
+	      if (!_dbus_list_append (&entry->keys, key))
+		{
+		  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);		  
+		  _dbus_string_free (key);
+		  _dbus_string_free (value);
+
+		  dbus_free (key);
+		  dbus_free (value);		  
+		  goto error;
+		}
+
+	      if (!_dbus_list_append (&entry->values, value))
+		{
+		  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);		  
+		  _dbus_string_free (value);
+
+		  dbus_free (value);
+		  goto error;		  
+		}
+	    }
+
+	  pos = comma_pos + 1;
+	}
+
+      pos = end_pos + 1;
+    }
+
+  *array_len = _dbus_list_get_length (&entries);
+  
+  entry_array = dbus_new (DBusAddressEntry *, *array_len + 1);
+
+  if (!entry_array)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      
+      goto error;
+    }
+  
+  entry_array [*array_len] = NULL;
+
+  link = _dbus_list_get_first_link (&entries);
+  i = 0;
+  while (link != NULL)
+    {
+      entry_array[i] = link->data;
+      i++;
+      link = _dbus_list_get_next_link (&entries, link);
+    }
+
+  _dbus_list_clear (&entries);
+  *entry = entry_array;
+
+  return TRUE;
+
+ error:
+  
+  link = _dbus_list_get_first_link (&entries);
+  while (link != NULL)
+    {
+      dbus_address_entry_free (link->data);
+      link = _dbus_list_get_next_link (&entries, link);
+    }
+
+  _dbus_list_clear (&entries);
+  
+  return FALSE;
+  
+}
+
+/**
+ * Escapes the given string as a value in a key=value pair
+ * for a D-Bus address.
+ *
+ * @param value the unescaped value
+ * @returns newly-allocated escaped value or #NULL if no memory
+ */
+char*
+dbus_address_escape_value (const char *value)
+{
+  DBusString escaped;
+  DBusString unescaped;
+  char *ret;
+
+  ret = NULL;
+
+  _dbus_string_init_const (&unescaped, value);
+  
+  if (!_dbus_string_init (&escaped))
+    return NULL;
+
+  if (!_dbus_address_append_escaped (&escaped, &unescaped))
+    goto out;
+  
+  if (!_dbus_string_steal_data (&escaped, &ret))
+    goto out;
+
+ out:
+  _dbus_string_free (&escaped);
+  return ret;
+}
+
+/**
+ * Unescapes the given string as a value in a key=value pair
+ * for a D-Bus address. Note that dbus_address_entry_get_value()
+ * returns an already-unescaped value.
+ *
+ * @param value the escaped value
+ * @param error error to set if the unescaping fails
+ * @returns newly-allocated unescaped value or #NULL if no memory
+ */
+char*
+dbus_address_unescape_value (const char *value,
+                             DBusError  *error)
+{
+  DBusString unescaped;
+  DBusString escaped;
+  char *ret;
+  
+  ret = NULL;
+
+  _dbus_string_init_const (&escaped, value);
+  
+  if (!_dbus_string_init (&unescaped))
+    return NULL;
+
+  if (!append_unescaped_value (&unescaped, &escaped,
+                               0, _dbus_string_get_length (&escaped),
+                               error))
+    goto out;
+  
+  if (!_dbus_string_steal_data (&unescaped, &ret))
+    goto out;
+
+ out:
+  if (ret == NULL && error && !dbus_error_is_set (error))
+    _DBUS_SET_OOM (error);
+
+  _dbus_assert (ret != NULL || error == NULL || dbus_error_is_set (error));
+  
+  _dbus_string_free (&unescaped);
+  return ret;
+}
+
+/** @} */ /* End of public API */
+
+#ifdef DBUS_BUILD_TESTS
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include "dbus-test.h"
+#include <stdlib.h>
+
+typedef struct
+{
+  const char *escaped;
+  const char *unescaped;
+} EscapeTest;
+
+static const EscapeTest escape_tests[] = {
+  { "abcde", "abcde" },
+  { "", "" },
+  { "%20%20", "  " },
+  { "%24", "$" },
+  { "%25", "%" },
+  { "abc%24", "abc$" },
+  { "%24abc", "$abc" },
+  { "abc%24abc", "abc$abc" },
+  { "/", "/" },
+  { "-", "-" },
+  { "_", "_" },
+  { "A", "A" },
+  { "I", "I" },
+  { "Z", "Z" },
+  { "a", "a" },
+  { "i", "i" },
+  { "z", "z" }
+};
+
+static const char* invalid_escaped_values[] = {
+  "%a",
+  "%q",
+  "%az",
+  "%%",
+  "%$$",
+  "abc%a",
+  "%axyz",
+  "%",
+  "$",
+  " ",
+};
+
+dbus_bool_t
+_dbus_address_test (void)
+{
+  DBusAddressEntry **entries;
+  int len;
+  DBusError error = DBUS_ERROR_INIT;
+  int i;
+
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (escape_tests))
+    {
+      const EscapeTest *test = &escape_tests[i];
+      char *escaped;
+      char *unescaped;
+
+      escaped = dbus_address_escape_value (test->unescaped);
+      if (escaped == NULL)
+        _dbus_assert_not_reached ("oom");
+
+      if (strcmp (escaped, test->escaped) != 0)
+        {
+          _dbus_warn ("Escaped '%s' as '%s' should have been '%s'\n",
+                      test->unescaped, escaped, test->escaped);
+          exit (1);
+        }
+      dbus_free (escaped);
+
+      unescaped = dbus_address_unescape_value (test->escaped, &error);
+      if (unescaped == NULL)
+        {
+          _dbus_warn ("Failed to unescape '%s': %s\n",
+                      test->escaped, error.message);
+          dbus_error_free (&error);
+          exit (1);
+        }
+
+      if (strcmp (unescaped, test->unescaped) != 0)
+        {
+          _dbus_warn ("Unescaped '%s' as '%s' should have been '%s'\n",
+                      test->escaped, unescaped, test->unescaped);
+          exit (1);
+        }
+      dbus_free (unescaped);
+      
+      ++i;
+    }
+
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (invalid_escaped_values))
+    {
+      char *unescaped;
+
+      unescaped = dbus_address_unescape_value (invalid_escaped_values[i],
+                                               &error);
+      if (unescaped != NULL)
+        {
+          _dbus_warn ("Should not have successfully unescaped '%s' to '%s'\n",
+                      invalid_escaped_values[i], unescaped);
+          dbus_free (unescaped);
+          exit (1);
+        }
+
+      _dbus_assert (dbus_error_is_set (&error));
+      dbus_error_free (&error);
+
+      ++i;
+    }
+  
+  if (!dbus_parse_address ("unix:path=/tmp/foo;debug:name=test,sliff=sloff;",
+			   &entries, &len, &error))
+    _dbus_assert_not_reached ("could not parse address");
+  _dbus_assert (len == 2);
+  _dbus_assert (strcmp (dbus_address_entry_get_value (entries[0], "path"), "/tmp/foo") == 0);
+  _dbus_assert (strcmp (dbus_address_entry_get_value (entries[1], "name"), "test") == 0);
+  _dbus_assert (strcmp (dbus_address_entry_get_value (entries[1], "sliff"), "sloff") == 0);
+  
+  dbus_address_entries_free (entries);
+
+  /* Different possible errors */
+  if (dbus_parse_address ("", &entries, &len, &error))
+    _dbus_assert_not_reached ("Parsed incorrect address.");
+  else
+    dbus_error_free (&error);
+
+  if (dbus_parse_address ("foo", &entries, &len, &error))
+    _dbus_assert_not_reached ("Parsed incorrect address.");
+  else
+    dbus_error_free (&error);
+  
+  if (dbus_parse_address ("foo:bar", &entries, &len, &error))
+    _dbus_assert_not_reached ("Parsed incorrect address.");
+  else
+    dbus_error_free (&error);
+  
+  if (dbus_parse_address ("foo:bar,baz", &entries, &len, &error))
+    _dbus_assert_not_reached ("Parsed incorrect address.");
+  else
+    dbus_error_free (&error);
+  
+  if (dbus_parse_address ("foo:bar=foo,baz", &entries, &len, &error))
+    _dbus_assert_not_reached ("Parsed incorrect address.");
+  else
+    dbus_error_free (&error);
+  
+  if (dbus_parse_address ("foo:bar=foo;baz", &entries, &len, &error))
+    _dbus_assert_not_reached ("Parsed incorrect address.");
+  else
+    dbus_error_free (&error);
+  
+  if (dbus_parse_address ("foo:=foo", &entries, &len, &error))
+    _dbus_assert_not_reached ("Parsed incorrect address.");
+  else
+    dbus_error_free (&error);
+  
+  if (dbus_parse_address ("foo:foo=", &entries, &len, &error))
+    _dbus_assert_not_reached ("Parsed incorrect address.");
+  else
+    dbus_error_free (&error);
+
+  if (dbus_parse_address ("foo:foo,bar=baz", &entries, &len, &error))
+    _dbus_assert_not_reached ("Parsed incorrect address.");
+  else
+    dbus_error_free (&error);
+
+  return TRUE;
+}
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif
diff --git a/dbus/dbus/dbus-address.h b/dbus/dbus/dbus-address.h
new file mode 100644
index 0000000..e51ef0a
--- /dev/null
+++ b/dbus/dbus/dbus-address.h
@@ -0,0 +1,67 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-address.h  Server address parser.
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_ADDRESS_H
+#define DBUS_ADDRESS_H
+
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusAddress
+ * @{
+ */
+
+/** Opaque type representing one of the semicolon-separated items in an address */
+typedef struct DBusAddressEntry DBusAddressEntry;
+
+DBUS_EXPORT
+dbus_bool_t dbus_parse_address            (const char         *address,
+					   DBusAddressEntry ***entry,
+					   int                *array_len,
+					   DBusError          *error);
+DBUS_EXPORT
+const char *dbus_address_entry_get_value  (DBusAddressEntry   *entry,
+					   const char         *key);
+DBUS_EXPORT
+const char *dbus_address_entry_get_method (DBusAddressEntry   *entry);
+DBUS_EXPORT
+void        dbus_address_entries_free     (DBusAddressEntry  **entries);
+
+DBUS_EXPORT
+char* dbus_address_escape_value   (const char *value);
+DBUS_EXPORT
+char* dbus_address_unescape_value (const char *value,
+                                   DBusError  *error);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_ADDRESS_H */
+
diff --git a/dbus/dbus/dbus-arch-deps.h b/dbus/dbus/dbus-arch-deps.h
new file mode 100644
index 0000000..c8359c8
--- /dev/null
+++ b/dbus/dbus/dbus-arch-deps.h
@@ -0,0 +1,67 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-arch-deps.h Header with architecture/compiler specific information, installed to libdir
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.0
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_ARCH_DEPS_H
+#define DBUS_ARCH_DEPS_H
+
+#include <dbus/dbus-macros.h>
+
+DBUS_BEGIN_DECLS
+
+#if 1
+#define DBUS_HAVE_INT64 1
+_DBUS_GNUC_EXTENSION typedef long long dbus_int64_t;
+_DBUS_GNUC_EXTENSION typedef unsigned long long dbus_uint64_t;
+
+#define DBUS_INT64_CONSTANT(val)  (_DBUS_GNUC_EXTENSION (val##LL))
+#define DBUS_UINT64_CONSTANT(val) (_DBUS_GNUC_EXTENSION (val##ULL))
+
+#else
+#undef DBUS_HAVE_INT64
+#undef DBUS_INT64_CONSTANT
+#undef DBUS_UINT64_CONSTANT
+#endif
+
+typedef int dbus_int32_t;
+typedef unsigned int dbus_uint32_t;
+
+typedef short dbus_int16_t;
+typedef unsigned short dbus_uint16_t;
+
+/* This is not really arch-dependent, but it's not worth
+ * creating an additional generated header just for this
+ */
+#define DBUS_MAJOR_VERSION 1
+#define DBUS_MINOR_VERSION 4
+#define DBUS_MICRO_VERSION 0
+
+#define DBUS_VERSION_STRING "1.4.0"
+
+#define DBUS_VERSION ((1 << 16) | (4 << 8) | (0)) 
+
+DBUS_END_DECLS
+
+#endif /* DBUS_ARCH_DEPS_H */
diff --git a/dbus/dbus/dbus-arch-deps.h.in b/dbus/dbus/dbus-arch-deps.h.in
new file mode 100644
index 0000000..45952cf
--- /dev/null
+++ b/dbus/dbus/dbus-arch-deps.h.in
@@ -0,0 +1,67 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-arch-deps.h Header with architecture/compiler specific information, installed to libdir
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.0
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_ARCH_DEPS_H
+#define DBUS_ARCH_DEPS_H
+
+#include <dbus/dbus-macros.h>
+
+DBUS_BEGIN_DECLS
+
+#if @DBUS_HAVE_INT64@
+#define DBUS_HAVE_INT64 1
+_DBUS_GNUC_EXTENSION typedef @DBUS_INT64_TYPE@ dbus_int64_t;
+_DBUS_GNUC_EXTENSION typedef unsigned @DBUS_INT64_TYPE@ dbus_uint64_t;
+
+#define DBUS_INT64_CONSTANT(val)  (_DBUS_GNUC_EXTENSION @DBUS_INT64_CONSTANT@)
+#define DBUS_UINT64_CONSTANT(val) (_DBUS_GNUC_EXTENSION @DBUS_UINT64_CONSTANT@)
+
+#else
+#undef DBUS_HAVE_INT64
+#undef DBUS_INT64_CONSTANT
+#undef DBUS_UINT64_CONSTANT
+#endif
+
+typedef @DBUS_INT32_TYPE@ dbus_int32_t;
+typedef unsigned @DBUS_INT32_TYPE@ dbus_uint32_t;
+
+typedef @DBUS_INT16_TYPE@ dbus_int16_t;
+typedef unsigned @DBUS_INT16_TYPE@ dbus_uint16_t;
+
+/* This is not really arch-dependent, but it's not worth
+ * creating an additional generated header just for this
+ */
+#define DBUS_MAJOR_VERSION @DBUS_MAJOR_VERSION@
+#define DBUS_MINOR_VERSION @DBUS_MINOR_VERSION@
+#define DBUS_MICRO_VERSION @DBUS_MICRO_VERSION@
+
+#define DBUS_VERSION_STRING "@DBUS_VERSION@"
+
+#define DBUS_VERSION ((@DBUS_MAJOR_VERSION@ << 16) | (@DBUS_MINOR_VERSION@ << 8) | (@DBUS_MICRO_VERSION@)) 
+
+DBUS_END_DECLS
+
+#endif /* DBUS_ARCH_DEPS_H */
diff --git a/dbus/dbus/dbus-auth-script.c b/dbus/dbus/dbus-auth-script.c
new file mode 100644
index 0000000..6285e3b
--- /dev/null
+++ b/dbus/dbus/dbus-auth-script.c
@@ -0,0 +1,803 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-auth-script.c Test DBusAuth using a special script file (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#include <config.h>
+
+#ifdef DBUS_BUILD_TESTS
+
+#include "dbus-auth-script.h"
+#include "dbus-auth.h"
+#include "dbus-string.h"
+#include "dbus-hash.h"
+#include "dbus-credentials.h"
+#include "dbus-internals.h"
+
+/**
+ * @defgroup DBusAuthScript code for running unit test scripts for DBusAuth
+ * @ingroup  DBusInternals
+ * @brief DBusAuth unit test scripting
+ *
+ * The code in here is used for unit testing, it loads
+ * up a script that tests DBusAuth.
+ *
+ * @{
+ */
+
+/* this is slightly different from the other append_quoted_string
+ * in dbus-message-builder.c
+ */
+static dbus_bool_t
+append_quoted_string (DBusString       *dest,
+                      const DBusString *quoted)
+{
+  dbus_bool_t in_quotes = FALSE;
+  dbus_bool_t in_backslash = FALSE;
+  int i;
+
+  i = 0;
+  while (i < _dbus_string_get_length (quoted))
+    {
+      unsigned char b;
+
+      b = _dbus_string_get_byte (quoted, i);
+
+      if (in_backslash)
+        {
+          unsigned char a;
+          
+          if (b == 'r')
+            a = '\r';
+          else if (b == 'n')
+            a = '\n';
+          else if (b == '\\')
+            a = '\\';
+          else
+            {
+              _dbus_warn ("bad backslashed byte %c\n", b);
+              return FALSE;
+            }
+
+          if (!_dbus_string_append_byte (dest, a))
+            return FALSE;
+          
+          in_backslash = FALSE;
+        }
+      else if (b == '\\')
+        {
+          in_backslash = TRUE;
+        }
+      else if (in_quotes)
+        {
+          if (b == '\'')
+            in_quotes = FALSE;
+          else
+            {
+              if (!_dbus_string_append_byte (dest, b))
+                return FALSE;
+            }
+        }
+      else
+        {
+          if (b == '\'')
+            in_quotes = TRUE;
+          else if (b == ' ' || b == '\n' || b == '\t')
+            break; /* end on whitespace if not quoted */
+          else
+            {
+              if (!_dbus_string_append_byte (dest, b))
+                return FALSE;
+            }
+        }
+      
+      ++i;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+same_first_word (const DBusString *a,
+                 const DBusString *b)
+{
+  int first_a_blank, first_b_blank;
+
+  _dbus_string_find_blank (a, 0, &first_a_blank);
+  _dbus_string_find_blank (b, 0, &first_b_blank);
+
+  if (first_a_blank != first_b_blank)
+    return FALSE;
+
+  return _dbus_string_equal_len (a, b, first_a_blank);
+}
+
+static DBusAuthState
+auth_state_from_string (const DBusString *str)
+{ 
+  if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_INPUT"))
+    return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
+  else if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_MEMORY"))
+    return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
+  else if (_dbus_string_starts_with_c_str (str, "HAVE_BYTES_TO_SEND"))
+    return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
+  else if (_dbus_string_starts_with_c_str (str, "NEED_DISCONNECT"))
+    return DBUS_AUTH_STATE_NEED_DISCONNECT;
+  else if (_dbus_string_starts_with_c_str (str, "AUTHENTICATED"))
+    return DBUS_AUTH_STATE_AUTHENTICATED;
+  else
+    return -1;
+}
+
+static const char*
+auth_state_to_string (DBusAuthState state)
+{
+  switch (state)
+    {
+    case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
+      return "WAITING_FOR_INPUT";
+    case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
+      return "WAITING_FOR_MEMORY";
+    case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
+      return "HAVE_BYTES_TO_SEND";
+    case DBUS_AUTH_STATE_NEED_DISCONNECT:
+      return "NEED_DISCONNECT";
+    case DBUS_AUTH_STATE_AUTHENTICATED:
+      return "AUTHENTICATED";
+    }
+
+  return "unknown";
+}
+
+static char **
+split_string (DBusString *str)
+{
+  int i, j, k, count, end;
+  char **array;
+
+  end = _dbus_string_get_length (str);
+
+  i = 0;
+  _dbus_string_skip_blank (str, i, &i);
+  for (count = 0; i < end; count++)
+    {
+      _dbus_string_find_blank (str, i, &i);
+      _dbus_string_skip_blank (str, i, &i);
+    }
+
+  array = dbus_new0 (char *, count + 1);
+  if (array == NULL)
+    return NULL;
+
+  i = 0;
+  _dbus_string_skip_blank (str, i, &i);
+  for (k = 0; k < count; k++)
+    {
+      _dbus_string_find_blank (str, i, &j);
+
+      array[k] = dbus_malloc (j - i + 1);
+      if (array[k] == NULL)
+        {
+          dbus_free_string_array (array);
+          return NULL;
+        }
+      memcpy (array[k],
+              _dbus_string_get_const_data_len (str, i, j - i), j - i);
+      array[k][j - i] = '\0';
+
+      _dbus_string_skip_blank (str, j, &i);
+    }
+  array[k] = NULL;
+
+  return array;
+}
+
+static void
+auth_set_unix_credentials(DBusAuth  *auth,
+                          dbus_uid_t uid,
+                          dbus_pid_t pid)
+{
+  DBusCredentials *credentials;
+
+  credentials = _dbus_credentials_new ();
+  if (credentials == NULL)
+    _dbus_assert_not_reached ("no memory");
+
+  if (uid != DBUS_UID_UNSET)
+    _dbus_credentials_add_unix_uid (credentials, uid);
+  if (pid != DBUS_PID_UNSET)
+    _dbus_credentials_add_unix_pid (credentials, pid);
+
+  _dbus_auth_set_credentials (auth, credentials);
+
+  _dbus_credentials_unref (credentials);
+}
+
+/**
+ * Runs an "auth script" which is a script for testing the
+ * authentication protocol. Scripts send and receive data, and then
+ * include assertions about the state of both ends of the connection
+ * after processing the data. A script succeeds if these assertions
+ * hold.
+ *
+ * @param filename the file containing the script to run
+ * @returns #TRUE if the script succeeds, #FALSE otherwise
+ */
+dbus_bool_t
+_dbus_auth_script_run (const DBusString *filename)
+{
+  DBusString file;
+  DBusError error = DBUS_ERROR_INIT;
+  DBusString line;
+  dbus_bool_t retval;
+  int line_no;
+  DBusAuth *auth;
+  DBusString from_auth;
+  DBusAuthState state;
+  DBusString context;
+  DBusString guid;
+  
+  retval = FALSE;
+  auth = NULL;
+
+  _dbus_string_init_const (&guid, "5fa01f4202cd837709a3274ca0df9d00");
+  _dbus_string_init_const (&context, "org_freedesktop_test");
+  
+  if (!_dbus_string_init (&file))
+    return FALSE;
+
+  if (!_dbus_string_init (&line))
+    {
+      _dbus_string_free (&file);
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&from_auth))
+    {
+      _dbus_string_free (&file);
+      _dbus_string_free (&line);
+      return FALSE;
+    }
+
+  if (!_dbus_file_get_contents (&file, filename, &error))    {
+      _dbus_warn ("Getting contents of %s failed: %s\n",
+                  _dbus_string_get_const_data (filename), error.message);
+      dbus_error_free (&error);
+      goto out;
+    }
+
+  state = DBUS_AUTH_STATE_NEED_DISCONNECT;
+  line_no = 0;
+
+ next_iteration:
+  while (_dbus_string_pop_line (&file, &line))
+    {      
+      line_no += 1;
+
+      /* _dbus_warn ("%s\n", _dbus_string_get_const_data (&line)); */
+      
+      _dbus_string_delete_leading_blanks (&line);
+
+      if (auth != NULL)
+        {
+          while ((state = _dbus_auth_do_work (auth)) ==
+                 DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
+            {
+              const DBusString *tmp;
+              if (_dbus_auth_get_bytes_to_send (auth, &tmp))
+                {
+                  int count = _dbus_string_get_length (tmp);
+
+                  if (_dbus_string_copy (tmp, 0, &from_auth,
+                                         _dbus_string_get_length (&from_auth)))
+                    _dbus_auth_bytes_sent (auth, count);
+                }
+            }
+        }
+      
+      if (_dbus_string_get_length (&line) == 0)
+        {
+          /* empty line */
+          goto next_iteration;
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "#"))
+        {
+          /* Ignore this comment */
+          goto next_iteration;
+        }
+#ifdef DBUS_WIN
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "WIN_ONLY"))
+        {
+          /* Ignore this line */
+          goto next_iteration;
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "UNIX_ONLY"))
+        {
+          /* skip this file */
+          _dbus_warn ("skipping unix only auth script\n");
+          retval = TRUE;
+          goto out;
+        }
+#endif
+#ifdef DBUS_UNIX
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "UNIX_ONLY"))
+        {
+          /* Ignore this line */
+          goto next_iteration;
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "WIN_ONLY"))
+        {
+          /* skip this file */
+          _dbus_warn ("skipping windows only auth script\n");
+          retval = TRUE;
+          goto out;
+        }
+#endif
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "CLIENT"))
+        {
+          DBusCredentials *creds;
+          
+          if (auth != NULL)
+            {
+              _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
+              goto out;
+            }
+
+          auth = _dbus_auth_client_new ();
+          if (auth == NULL)
+            {
+              _dbus_warn ("no memory to create DBusAuth\n");
+              goto out;
+            }
+
+          /* test ref/unref */
+          _dbus_auth_ref (auth);
+          _dbus_auth_unref (auth);
+
+          creds = _dbus_credentials_new_from_current_process ();
+          if (creds == NULL)
+            {
+              _dbus_warn ("no memory for credentials\n");
+              _dbus_auth_unref (auth);
+              auth = NULL;
+              goto out;
+            }
+              
+          if (!_dbus_auth_set_credentials (auth, creds))
+            {
+              _dbus_warn ("no memory for setting credentials\n");
+              _dbus_auth_unref (auth);
+              auth = NULL;
+              _dbus_credentials_unref (creds);
+              goto out;
+            }
+          
+          _dbus_credentials_unref (creds);
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "SERVER"))
+        {
+          DBusCredentials *creds;
+          
+          if (auth != NULL)
+            {
+              _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
+              goto out;
+            }
+
+          auth = _dbus_auth_server_new (&guid);
+          if (auth == NULL)
+            {
+              _dbus_warn ("no memory to create DBusAuth\n");
+              goto out;
+            }
+
+          /* test ref/unref */
+          _dbus_auth_ref (auth);
+          _dbus_auth_unref (auth);
+
+          creds = _dbus_credentials_new_from_current_process ();
+          if (creds == NULL)
+            {
+              _dbus_warn ("no memory for credentials\n");
+              _dbus_auth_unref (auth);
+              auth = NULL;
+              goto out;
+            }
+              
+          if (!_dbus_auth_set_credentials (auth, creds))
+            {
+              _dbus_warn ("no memory for setting credentials\n");
+              _dbus_auth_unref (auth);
+              auth = NULL;
+              _dbus_credentials_unref (creds);
+              goto out;
+            }
+          
+          _dbus_credentials_unref (creds);
+
+          _dbus_auth_set_context (auth, &context);
+        }
+      else if (auth == NULL)
+        {
+          _dbus_warn ("must specify CLIENT or SERVER\n");
+          goto out;
+
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "NO_CREDENTIALS"))
+        {
+          auth_set_unix_credentials (auth, DBUS_UID_UNSET, DBUS_PID_UNSET);
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "ROOT_CREDENTIALS"))
+        {
+          auth_set_unix_credentials (auth, 0, DBUS_PID_UNSET);
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "SILLY_CREDENTIALS"))
+        {
+          auth_set_unix_credentials (auth, 4312, DBUS_PID_UNSET);
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "ALLOWED_MECHS"))
+        {
+          char **mechs;
+
+          _dbus_string_delete_first_word (&line);
+          mechs = split_string (&line);
+          _dbus_auth_set_mechanisms (auth, (const char **) mechs);
+          dbus_free_string_array (mechs);
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "SEND"))
+        {
+          DBusString to_send;
+          
+          _dbus_string_delete_first_word (&line);
+
+          if (!_dbus_string_init (&to_send))
+            {
+              _dbus_warn ("no memory to allocate string\n");
+              goto out;
+            }
+
+          if (!append_quoted_string (&to_send, &line))
+            {
+              _dbus_warn ("failed to append quoted string line %d\n",
+                          line_no);
+              _dbus_string_free (&to_send);
+              goto out;
+            }
+
+          _dbus_verbose ("Sending '%s'\n", _dbus_string_get_const_data (&to_send));
+          
+          if (!_dbus_string_append (&to_send, "\r\n"))
+            {
+              _dbus_warn ("failed to append \r\n from line %d\n",
+                          line_no);
+              _dbus_string_free (&to_send);
+              goto out;
+            }
+
+          /* Replace USERID_HEX with our username in hex */
+          {
+            int where;
+            
+            if (_dbus_string_find (&to_send, 0,
+                                   "USERID_HEX", &where))
+              {
+                DBusString username;
+
+                if (!_dbus_string_init (&username))
+                  {
+                    _dbus_warn ("no memory for userid\n");
+                    _dbus_string_free (&to_send);
+                    goto out;
+                  }
+
+                if (!_dbus_append_user_from_current_process (&username))
+                  {
+                    _dbus_warn ("no memory for userid\n");
+                    _dbus_string_free (&username);
+                    _dbus_string_free (&to_send);
+                    goto out;
+                  }
+
+                _dbus_string_delete (&to_send, where, strlen ("USERID_HEX"));
+                
+                if (!_dbus_string_hex_encode (&username, 0,
+					      &to_send, where))
+                  {
+                    _dbus_warn ("no memory to subst USERID_HEX\n");
+                    _dbus_string_free (&username);
+                    _dbus_string_free (&to_send);
+                    goto out;
+                  }
+
+                _dbus_string_free (&username);
+              }
+            else if (_dbus_string_find (&to_send, 0,
+                                        "USERNAME_HEX", &where))
+              {
+                DBusString username;
+                
+                if (!_dbus_string_init (&username))
+                  {
+                    _dbus_warn ("no memory for username\n");
+                    _dbus_string_free (&to_send);
+                    goto out;
+                  }
+
+                if (!_dbus_append_user_from_current_process (&username))
+                  {
+                    _dbus_warn ("no memory for username\n");
+                    _dbus_string_free (&username);
+                    _dbus_string_free (&to_send);
+                    goto out;
+                  }
+
+                _dbus_string_delete (&to_send, where, strlen ("USERNAME_HEX"));
+                
+                if (!_dbus_string_hex_encode (&username, 0,
+					      &to_send, where))
+                  {
+                    _dbus_warn ("no memory to subst USERNAME_HEX\n");
+                    _dbus_string_free (&username);
+                    _dbus_string_free (&to_send);
+                    goto out;
+                  }
+
+                _dbus_string_free (&username);
+              }
+          }
+
+          {
+            DBusString *buffer;
+
+            _dbus_auth_get_buffer (auth, &buffer);
+            if (!_dbus_string_copy (&to_send, 0,
+                                    buffer, _dbus_string_get_length (buffer)))
+              {
+                _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n");
+                _dbus_string_free (&to_send);
+                _dbus_auth_return_buffer (auth, buffer, 0);
+                goto out;
+              }
+
+            _dbus_auth_return_buffer (auth, buffer, _dbus_string_get_length (&to_send));
+          }
+          
+          _dbus_string_free (&to_send);
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "EXPECT_STATE"))
+        {
+          DBusAuthState expected;
+          
+          _dbus_string_delete_first_word (&line);
+
+          expected = auth_state_from_string (&line);
+          if (expected < 0)
+            {
+              _dbus_warn ("bad auth state given to EXPECT_STATE\n");
+              goto parse_failed;
+            }
+
+          if (expected != state)
+            {
+              _dbus_warn ("expected auth state %s but got %s on line %d\n",
+                          auth_state_to_string (expected),
+                          auth_state_to_string (state),
+                          line_no);
+              goto out;
+            }
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "EXPECT_COMMAND"))
+        {
+          DBusString received;
+          
+          _dbus_string_delete_first_word (&line);
+
+          if (!_dbus_string_init (&received))
+            {
+              _dbus_warn ("no mem to allocate string received\n");
+              goto out;
+            }
+
+          if (!_dbus_string_pop_line (&from_auth, &received))
+            {
+              _dbus_warn ("no line popped from the DBusAuth being tested, expected command %s on line %d\n",
+                          _dbus_string_get_const_data (&line), line_no);
+              _dbus_string_free (&received);
+              goto out;
+            }
+
+          if (!same_first_word (&received, &line))
+            {
+              _dbus_warn ("line %d expected command '%s' and got '%s'\n",
+                          line_no,
+                          _dbus_string_get_const_data (&line),
+                          _dbus_string_get_const_data (&received));
+              _dbus_string_free (&received);
+              goto out;
+            }
+          
+          _dbus_string_free (&received);
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "EXPECT_UNUSED"))
+        {
+          DBusString expected;
+          const DBusString *unused;
+          
+          _dbus_string_delete_first_word (&line);
+
+          if (!_dbus_string_init (&expected))
+            {
+              _dbus_warn ("no mem to allocate string expected\n");
+              goto out;
+            }
+
+          if (!append_quoted_string (&expected, &line))
+            {
+              _dbus_warn ("failed to append quoted string line %d\n",
+                          line_no);
+              _dbus_string_free (&expected);
+              goto out;
+            }
+
+          _dbus_auth_get_unused_bytes (auth, &unused);
+          
+          if (_dbus_string_equal (&expected, unused))
+            {
+              _dbus_auth_delete_unused_bytes (auth);
+              _dbus_string_free (&expected);
+            }
+          else
+            {
+              _dbus_warn ("Expected unused bytes '%s' and have '%s'\n",
+                          _dbus_string_get_const_data (&expected),
+                          _dbus_string_get_const_data (unused));
+              _dbus_string_free (&expected);
+              goto out;
+            }
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "EXPECT_HAVE_NO_CREDENTIALS"))
+        {
+          DBusCredentials *authorized_identity;
+          
+          authorized_identity = _dbus_auth_get_identity (auth);
+          if (!_dbus_credentials_are_anonymous (authorized_identity))
+            {
+              _dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized\n");
+              goto out;
+            }
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "EXPECT_HAVE_SOME_CREDENTIALS"))
+        {
+          DBusCredentials *authorized_identity;
+          
+          authorized_identity = _dbus_auth_get_identity (auth);
+          if (_dbus_credentials_are_anonymous (authorized_identity))
+            {
+              _dbus_warn ("Expected to have some credentials, but we don't\n");
+              goto out;
+            }
+        }
+      else if (_dbus_string_starts_with_c_str (&line,
+                                               "EXPECT"))
+        {
+          DBusString expected;
+          
+          _dbus_string_delete_first_word (&line);
+
+          if (!_dbus_string_init (&expected))
+            {
+              _dbus_warn ("no mem to allocate string expected\n");
+              goto out;
+            }
+
+          if (!append_quoted_string (&expected, &line))
+            {
+              _dbus_warn ("failed to append quoted string line %d\n",
+                          line_no);
+              _dbus_string_free (&expected);
+              goto out;
+            }
+
+          if (_dbus_string_equal_len (&expected, &from_auth,
+                                      _dbus_string_get_length (&expected)))
+            {
+              _dbus_string_delete (&from_auth, 0,
+                                   _dbus_string_get_length (&expected));
+              _dbus_string_free (&expected);
+            }
+          else
+            {
+              _dbus_warn ("Expected exact string '%s' and have '%s'\n",
+                          _dbus_string_get_const_data (&expected),
+                          _dbus_string_get_const_data (&from_auth));
+              _dbus_string_free (&expected);
+              goto out;
+            }
+        }
+      else
+        goto parse_failed;
+
+      goto next_iteration; /* skip parse_failed */
+      
+    parse_failed:
+      {
+        _dbus_warn ("couldn't process line %d \"%s\"\n",
+                    line_no, _dbus_string_get_const_data (&line));
+        goto out;
+      }
+    }
+
+  if (auth == NULL)
+    {
+      _dbus_warn ("Auth script is bogus, did not even have CLIENT or SERVER\n");
+      goto out;
+    }
+  else if (state == DBUS_AUTH_STATE_AUTHENTICATED)
+    {
+      const DBusString *unused;
+
+      _dbus_auth_get_unused_bytes (auth, &unused);
+
+      if (_dbus_string_get_length (unused) > 0)
+        {
+          _dbus_warn ("did not expect unused bytes (scripts must specify explicitly if they are expected)\n");
+          goto out;
+        }
+    }
+
+  if (_dbus_string_get_length (&from_auth) > 0)
+    {
+      _dbus_warn ("script did not have EXPECT_ statements for all the data received from the DBusAuth\n");
+      _dbus_warn ("Leftover data: %s\n", _dbus_string_get_const_data (&from_auth));
+      goto out;
+    }
+  
+  retval = TRUE;
+  
+ out:
+  if (auth)
+    _dbus_auth_unref (auth);
+
+  _dbus_string_free (&file);
+  _dbus_string_free (&line);
+  _dbus_string_free (&from_auth);
+  
+  return retval;
+}
+
+/** @} */
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-auth-script.h b/dbus/dbus/dbus-auth-script.h
new file mode 100644
index 0000000..39e6c7c
--- /dev/null
+++ b/dbus/dbus/dbus-auth-script.h
@@ -0,0 +1,37 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-auth-script.h Test DBusAuth using a special script file (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_AUTH_SCRIPT_H
+#define DBUS_AUTH_SCRIPT_H
+
+#include <dbus/dbus-memory.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-string.h>
+
+DBUS_BEGIN_DECLS
+
+dbus_bool_t _dbus_auth_script_run (const DBusString *filename);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_AUTH_SCRIPT_H */
diff --git a/dbus/dbus/dbus-auth-util.c b/dbus/dbus/dbus-auth-util.c
new file mode 100644
index 0000000..776e8e2
--- /dev/null
+++ b/dbus/dbus/dbus-auth-util.c
@@ -0,0 +1,170 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-auth-util.c Would be in dbus-auth.c, but only used for tests/bus
+ *
+ * Copyright (C) 2002, 2003, 2004 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-test.h"
+#include "dbus-auth.h"
+
+/**
+ * @addtogroup DBusAuth
+ * @{
+ */
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include "dbus-auth-script.h"
+#include <stdio.h>
+
+static dbus_bool_t
+process_test_subdir (const DBusString          *test_base_dir,
+                     const char                *subdir)
+{
+  DBusString test_directory;
+  DBusString filename;
+  DBusDirIter *dir;
+  dbus_bool_t retval;
+  DBusError error = DBUS_ERROR_INIT;
+
+  retval = FALSE;
+  dir = NULL;
+  
+  if (!_dbus_string_init (&test_directory))
+    _dbus_assert_not_reached ("didn't allocate test_directory\n");
+
+  _dbus_string_init_const (&filename, subdir);
+  
+  if (!_dbus_string_copy (test_base_dir, 0,
+                          &test_directory, 0))
+    _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
+  
+  if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
+    _dbus_assert_not_reached ("couldn't allocate full path");
+
+  _dbus_string_free (&filename);
+  if (!_dbus_string_init (&filename))
+    _dbus_assert_not_reached ("didn't allocate filename string\n");
+
+  dir = _dbus_directory_open (&test_directory, &error);
+  if (dir == NULL)
+    {
+      _dbus_warn ("Could not open %s: %s\n",
+                  _dbus_string_get_const_data (&test_directory),
+                  error.message);
+      dbus_error_free (&error);
+      goto failed;
+    }
+
+  printf ("Testing %s:\n", subdir);
+  
+ next:
+  while (_dbus_directory_get_next_file (dir, &filename, &error))
+    {
+      DBusString full_path;
+      
+      if (!_dbus_string_init (&full_path))
+        _dbus_assert_not_reached ("couldn't init string");
+
+      if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
+        _dbus_assert_not_reached ("couldn't copy dir to full_path");
+
+      if (!_dbus_concat_dir_and_file (&full_path, &filename))
+        _dbus_assert_not_reached ("couldn't concat file to dir");
+
+      if (!_dbus_string_ends_with_c_str (&filename, ".auth-script"))
+        {
+          _dbus_verbose ("Skipping non-.auth-script file %s\n",
+                         _dbus_string_get_const_data (&filename));
+	  _dbus_string_free (&full_path);
+          goto next;
+        }
+
+      printf ("    %s\n", _dbus_string_get_const_data (&filename));
+      
+      if (!_dbus_auth_script_run (&full_path))
+        {
+          _dbus_string_free (&full_path);
+          goto failed;
+        }
+      else
+        _dbus_string_free (&full_path);
+    }
+
+  if (dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Could not get next file in %s: %s\n",
+                  _dbus_string_get_const_data (&test_directory), error.message);
+      dbus_error_free (&error);
+      goto failed;
+    }
+    
+  retval = TRUE;
+  
+ failed:
+
+  if (dir)
+    _dbus_directory_close (dir);
+  _dbus_string_free (&test_directory);
+  _dbus_string_free (&filename);
+
+  return retval;
+}
+
+static dbus_bool_t
+process_test_dirs (const char *test_data_dir)
+{
+  DBusString test_directory;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+  
+  _dbus_string_init_const (&test_directory, test_data_dir);
+
+  if (!process_test_subdir (&test_directory, "auth"))
+    goto failed;
+
+  retval = TRUE;
+  
+ failed:
+
+  _dbus_string_free (&test_directory);
+  
+  return retval;
+}
+
+dbus_bool_t
+_dbus_auth_test (const char *test_data_dir)
+{
+  
+  if (test_data_dir == NULL)
+    return TRUE;
+  
+  if (!process_test_dirs (test_data_dir))
+    return FALSE;
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-auth.c b/dbus/dbus/dbus-auth.c
new file mode 100644
index 0000000..d2c37a7
--- /dev/null
+++ b/dbus/dbus/dbus-auth.c
@@ -0,0 +1,2810 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-auth.c Authentication
+ *
+ * Copyright (C) 2002, 2003, 2004 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-auth.h"
+#include "dbus-string.h"
+#include "dbus-list.h"
+#include "dbus-internals.h"
+#include "dbus-keyring.h"
+#include "dbus-sha.h"
+#include "dbus-protocol.h"
+#include "dbus-credentials.h"
+
+/**
+ * @defgroup DBusAuth Authentication
+ * @ingroup  DBusInternals
+ * @brief DBusAuth object
+ *
+ * DBusAuth manages the authentication negotiation when a connection
+ * is first established, and also manage any encryption used over a
+ * connection.
+ *
+ * @todo some SASL profiles require sending the empty string as a
+ * challenge/response, but we don't currently allow that in our
+ * protocol.
+ *
+ * @todo right now sometimes both ends will block waiting for input
+ * from the other end, e.g. if there's an error during
+ * DBUS_COOKIE_SHA1.
+ *
+ * @todo the cookie keyring needs to be cached globally not just
+ * per-auth (which raises threadsafety issues too)
+ * 
+ * @todo grep FIXME in dbus-auth.c
+ */
+
+/**
+ * @defgroup DBusAuthInternals Authentication implementation details
+ * @ingroup  DBusInternals
+ * @brief DBusAuth implementation details
+ *
+ * Private details of authentication code.
+ *
+ * @{
+ */
+
+/**
+ * This function appends an initial client response to the given string
+ */
+typedef dbus_bool_t (* DBusInitialResponseFunction)  (DBusAuth         *auth,
+                                                      DBusString       *response);
+
+/**
+ * This function processes a block of data received from the peer.
+ * i.e. handles a DATA command.
+ */
+typedef dbus_bool_t (* DBusAuthDataFunction)     (DBusAuth         *auth,
+                                                  const DBusString *data);
+
+/**
+ * This function encodes a block of data from the peer.
+ */
+typedef dbus_bool_t (* DBusAuthEncodeFunction)   (DBusAuth         *auth,
+                                                  const DBusString *data,
+                                                  DBusString       *encoded);
+
+/**
+ * This function decodes a block of data from the peer.
+ */
+typedef dbus_bool_t (* DBusAuthDecodeFunction)   (DBusAuth         *auth,
+                                                  const DBusString *data,
+                                                  DBusString       *decoded);
+
+/**
+ * This function is called when the mechanism is abandoned.
+ */
+typedef void        (* DBusAuthShutdownFunction) (DBusAuth       *auth);
+
+/**
+ * Virtual table representing a particular auth mechanism.
+ */
+typedef struct
+{
+  const char *mechanism; /**< Name of the mechanism */
+  DBusAuthDataFunction server_data_func; /**< Function on server side for DATA */
+  DBusAuthEncodeFunction server_encode_func; /**< Function on server side to encode */
+  DBusAuthDecodeFunction server_decode_func; /**< Function on server side to decode */
+  DBusAuthShutdownFunction server_shutdown_func; /**< Function on server side to shut down */
+  DBusInitialResponseFunction client_initial_response_func; /**< Function on client side to handle initial response */
+  DBusAuthDataFunction client_data_func; /**< Function on client side for DATA */
+  DBusAuthEncodeFunction client_encode_func; /**< Function on client side for encode */
+  DBusAuthDecodeFunction client_decode_func; /**< Function on client side for decode */
+  DBusAuthShutdownFunction client_shutdown_func; /**< Function on client side for shutdown */
+} DBusAuthMechanismHandler;
+
+/**
+ * Enumeration for the known authentication commands.
+ */
+typedef enum {
+  DBUS_AUTH_COMMAND_AUTH,
+  DBUS_AUTH_COMMAND_CANCEL,
+  DBUS_AUTH_COMMAND_DATA,
+  DBUS_AUTH_COMMAND_BEGIN,
+  DBUS_AUTH_COMMAND_REJECTED,
+  DBUS_AUTH_COMMAND_OK,
+  DBUS_AUTH_COMMAND_ERROR,
+  DBUS_AUTH_COMMAND_UNKNOWN,
+  DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD,
+  DBUS_AUTH_COMMAND_AGREE_UNIX_FD
+} DBusAuthCommand;
+
+/**
+ * Auth state function, determines the reaction to incoming events for
+ * a particular state. Returns whether we had enough memory to
+ * complete the operation.
+ */
+typedef dbus_bool_t (* DBusAuthStateFunction) (DBusAuth         *auth,
+                                               DBusAuthCommand   command,
+                                               const DBusString *args);
+
+/**
+ * Information about a auth state.
+ */
+typedef struct
+{
+  const char *name;               /**< Name of the state */
+  DBusAuthStateFunction handler;  /**< State function for this state */
+} DBusAuthStateData;
+
+/**
+ * Internal members of DBusAuth.
+ */
+struct DBusAuth
+{
+  int refcount;           /**< reference count */
+  const char *side;       /**< Client or server */
+
+  DBusString incoming;    /**< Incoming data buffer */
+  DBusString outgoing;    /**< Outgoing data buffer */
+  
+  const DBusAuthStateData *state;         /**< Current protocol state */
+
+  const DBusAuthMechanismHandler *mech;   /**< Current auth mechanism */
+
+  DBusString identity;                   /**< Current identity we're authorizing
+                                          *   as.
+                                          */
+  
+  DBusCredentials *credentials;          /**< Credentials read from socket
+                                          */
+
+  DBusCredentials *authorized_identity; /**< Credentials that are authorized */
+
+  DBusCredentials *desired_identity;    /**< Identity client has requested */
+  
+  DBusString context;               /**< Cookie scope */
+  DBusKeyring *keyring;             /**< Keyring for cookie mechanism. */
+  int cookie_id;                    /**< ID of cookie to use */
+  DBusString challenge;             /**< Challenge sent to client */
+
+  char **allowed_mechs;             /**< Mechanisms we're allowed to use,
+                                     * or #NULL if we can use any
+                                     */
+  
+  unsigned int needed_memory : 1;   /**< We needed memory to continue since last
+                                     * successful getting something done
+                                     */
+  unsigned int already_got_mechanisms : 1;       /**< Client already got mech list */
+  unsigned int already_asked_for_initial_response : 1; /**< Already sent a blank challenge to get an initial response */
+  unsigned int buffer_outstanding : 1; /**< Buffer is "checked out" for reading data into */
+
+  unsigned int unix_fd_possible : 1;  /**< This side could do unix fd passing */
+  unsigned int unix_fd_negotiated : 1; /**< Unix fd was successfully negotiated */
+};
+
+/**
+ * "Subclass" of DBusAuth for client side
+ */
+typedef struct
+{
+  DBusAuth base;    /**< Parent class */
+
+  DBusList *mechs_to_try; /**< Mechanisms we got from the server that we're going to try using */
+
+  DBusString guid_from_server; /**< GUID received from server */
+  
+} DBusAuthClient;
+
+/**
+ * "Subclass" of DBusAuth for server side.
+ */
+typedef struct
+{
+  DBusAuth base;    /**< Parent class */
+
+  int failures;     /**< Number of times client has been rejected */
+  int max_failures; /**< Number of times we reject before disconnect */
+
+  DBusString guid;  /**< Our globally unique ID in hex encoding */
+  
+} DBusAuthServer;
+
+static void        goto_state                (DBusAuth                       *auth,
+                                              const DBusAuthStateData        *new_state);
+static dbus_bool_t send_auth                 (DBusAuth *auth,
+                                              const DBusAuthMechanismHandler *mech);
+static dbus_bool_t send_data                 (DBusAuth *auth,
+                                              DBusString *data);
+static dbus_bool_t send_rejected             (DBusAuth *auth);
+static dbus_bool_t send_error                (DBusAuth *auth,
+                                              const char *message);
+static dbus_bool_t send_ok                   (DBusAuth *auth);
+static dbus_bool_t send_begin                (DBusAuth *auth);
+static dbus_bool_t send_cancel               (DBusAuth *auth);
+static dbus_bool_t send_negotiate_unix_fd    (DBusAuth *auth);
+static dbus_bool_t send_agree_unix_fd        (DBusAuth *auth);
+
+/**
+ * Client states
+ */
+ 
+static dbus_bool_t handle_server_state_waiting_for_auth  (DBusAuth         *auth,
+                                                          DBusAuthCommand   command,
+                                                          const DBusString *args);
+static dbus_bool_t handle_server_state_waiting_for_data  (DBusAuth         *auth,
+                                                          DBusAuthCommand   command,
+                                                          const DBusString *args);
+static dbus_bool_t handle_server_state_waiting_for_begin (DBusAuth         *auth,
+                                                          DBusAuthCommand   command,
+                                                          const DBusString *args);
+  
+static const DBusAuthStateData server_state_waiting_for_auth = {
+  "WaitingForAuth", handle_server_state_waiting_for_auth
+};
+static const DBusAuthStateData server_state_waiting_for_data = {
+  "WaitingForData", handle_server_state_waiting_for_data
+};
+static const DBusAuthStateData server_state_waiting_for_begin = {
+  "WaitingForBegin", handle_server_state_waiting_for_begin
+};
+  
+/**
+ * Client states
+ */
+ 
+static dbus_bool_t handle_client_state_waiting_for_data   (DBusAuth         *auth,
+                                                           DBusAuthCommand   command,
+                                                           const DBusString *args);
+static dbus_bool_t handle_client_state_waiting_for_ok     (DBusAuth         *auth,
+                                                           DBusAuthCommand   command,
+                                                           const DBusString *args);
+static dbus_bool_t handle_client_state_waiting_for_reject (DBusAuth         *auth,
+                                                           DBusAuthCommand   command,
+                                                           const DBusString *args);
+static dbus_bool_t handle_client_state_waiting_for_agree_unix_fd (DBusAuth         *auth,
+                                                           DBusAuthCommand   command,
+                                                           const DBusString *args);
+
+static const DBusAuthStateData client_state_need_send_auth = {
+  "NeedSendAuth", NULL
+};
+static const DBusAuthStateData client_state_waiting_for_data = {
+  "WaitingForData", handle_client_state_waiting_for_data
+};
+static const DBusAuthStateData client_state_waiting_for_ok = {
+  "WaitingForOK", handle_client_state_waiting_for_ok
+};
+static const DBusAuthStateData client_state_waiting_for_reject = {
+  "WaitingForReject", handle_client_state_waiting_for_reject
+};
+static const DBusAuthStateData client_state_waiting_for_agree_unix_fd = {
+  "WaitingForAgreeUnixFD", handle_client_state_waiting_for_agree_unix_fd
+};
+
+/**
+ * Common terminal states.  Terminal states have handler == NULL.
+ */
+
+static const DBusAuthStateData common_state_authenticated = {
+  "Authenticated",  NULL
+};
+
+static const DBusAuthStateData common_state_need_disconnect = {
+  "NeedDisconnect",  NULL
+};
+
+static const char auth_side_client[] = "client";
+static const char auth_side_server[] = "server";
+/**
+ * @param auth the auth conversation
+ * @returns #TRUE if the conversation is the server side
+ */
+#define DBUS_AUTH_IS_SERVER(auth) ((auth)->side == auth_side_server)
+/**
+ * @param auth the auth conversation
+ * @returns #TRUE if the conversation is the client side
+ */
+#define DBUS_AUTH_IS_CLIENT(auth) ((auth)->side == auth_side_client)
+/**
+ * @param auth the auth conversation
+ * @returns auth cast to DBusAuthClient
+ */
+#define DBUS_AUTH_CLIENT(auth)    ((DBusAuthClient*)(auth))
+/**
+ * @param auth the auth conversation
+ * @returns auth cast to DBusAuthServer
+ */
+#define DBUS_AUTH_SERVER(auth)    ((DBusAuthServer*)(auth))
+
+/**
+ * The name of the auth ("client" or "server")
+ * @param auth the auth conversation
+ * @returns a string
+ */
+#define DBUS_AUTH_NAME(auth)      ((auth)->side)
+
+static DBusAuth*
+_dbus_auth_new (int size)
+{
+  DBusAuth *auth;
+  
+  auth = dbus_malloc0 (size);
+  if (auth == NULL)
+    return NULL;
+  
+  auth->refcount = 1;
+  
+  auth->keyring = NULL;
+  auth->cookie_id = -1;
+  
+  /* note that we don't use the max string length feature,
+   * because you can't use that feature if you're going to
+   * try to recover from out-of-memory (it creates
+   * what looks like unrecoverable inability to alloc
+   * more space in the string). But we do handle
+   * overlong buffers in _dbus_auth_do_work().
+   */
+  
+  if (!_dbus_string_init (&auth->incoming))
+    goto enomem_0;
+
+  if (!_dbus_string_init (&auth->outgoing))
+    goto enomem_1;
+    
+  if (!_dbus_string_init (&auth->identity))
+    goto enomem_2;
+
+  if (!_dbus_string_init (&auth->context))
+    goto enomem_3;
+
+  if (!_dbus_string_init (&auth->challenge))
+    goto enomem_4;
+
+  /* default context if none is specified */
+  if (!_dbus_string_append (&auth->context, "org_freedesktop_general"))
+    goto enomem_5;
+
+  auth->credentials = _dbus_credentials_new ();
+  if (auth->credentials == NULL)
+    goto enomem_6;
+  
+  auth->authorized_identity = _dbus_credentials_new ();
+  if (auth->authorized_identity == NULL)
+    goto enomem_7;
+
+  auth->desired_identity = _dbus_credentials_new ();
+  if (auth->desired_identity == NULL)
+    goto enomem_8;
+  
+  return auth;
+
+#if 0
+ enomem_9:
+  _dbus_credentials_unref (auth->desired_identity);
+#endif
+ enomem_8:
+  _dbus_credentials_unref (auth->authorized_identity);
+ enomem_7:
+  _dbus_credentials_unref (auth->credentials);
+ enomem_6:
+ /* last alloc was an append to context, which is freed already below */ ;
+ enomem_5:
+  _dbus_string_free (&auth->challenge);
+ enomem_4:
+  _dbus_string_free (&auth->context);
+ enomem_3:
+  _dbus_string_free (&auth->identity);
+ enomem_2:
+  _dbus_string_free (&auth->outgoing);
+ enomem_1:
+  _dbus_string_free (&auth->incoming);
+ enomem_0:
+  dbus_free (auth);
+  return NULL;
+}
+
+static void
+shutdown_mech (DBusAuth *auth)
+{
+  /* Cancel any auth */
+  auth->already_asked_for_initial_response = FALSE;
+  _dbus_string_set_length (&auth->identity, 0);
+
+  _dbus_credentials_clear (auth->authorized_identity);
+  _dbus_credentials_clear (auth->desired_identity);
+  
+  if (auth->mech != NULL)
+    {
+      _dbus_verbose ("%s: Shutting down mechanism %s\n",
+                     DBUS_AUTH_NAME (auth), auth->mech->mechanism);
+      
+      if (DBUS_AUTH_IS_CLIENT (auth))
+        (* auth->mech->client_shutdown_func) (auth);
+      else
+        (* auth->mech->server_shutdown_func) (auth);
+      
+      auth->mech = NULL;
+    }
+}
+
+/*
+ * DBUS_COOKIE_SHA1 mechanism
+ */
+
+/* Returns TRUE but with an empty string hash if the
+ * cookie_id isn't known. As with all this code
+ * TRUE just means we had enough memory.
+ */
+static dbus_bool_t
+sha1_compute_hash (DBusAuth         *auth,
+                   int               cookie_id,
+                   const DBusString *server_challenge,
+                   const DBusString *client_challenge,
+                   DBusString       *hash)
+{
+  DBusString cookie;
+  DBusString to_hash;
+  dbus_bool_t retval;
+  
+  _dbus_assert (auth->keyring != NULL);
+
+  retval = FALSE;
+  
+  if (!_dbus_string_init (&cookie))
+    return FALSE;
+
+  if (!_dbus_keyring_get_hex_key (auth->keyring, cookie_id,
+                                  &cookie))
+    goto out_0;
+
+  if (_dbus_string_get_length (&cookie) == 0)
+    {
+      retval = TRUE;
+      goto out_0;
+    }
+
+  if (!_dbus_string_init (&to_hash))
+    goto out_0;
+  
+  if (!_dbus_string_copy (server_challenge, 0,
+                          &to_hash, _dbus_string_get_length (&to_hash)))
+    goto out_1;
+
+  if (!_dbus_string_append (&to_hash, ":"))
+    goto out_1;
+  
+  if (!_dbus_string_copy (client_challenge, 0,
+                          &to_hash, _dbus_string_get_length (&to_hash)))
+    goto out_1;
+
+  if (!_dbus_string_append (&to_hash, ":"))
+    goto out_1;
+
+  if (!_dbus_string_copy (&cookie, 0,
+                          &to_hash, _dbus_string_get_length (&to_hash)))
+    goto out_1;
+
+  if (!_dbus_sha_compute (&to_hash, hash))
+    goto out_1;
+  
+  retval = TRUE;
+
+ out_1:
+  _dbus_string_zero (&to_hash);
+  _dbus_string_free (&to_hash);
+ out_0:
+  _dbus_string_zero (&cookie);
+  _dbus_string_free (&cookie);
+  return retval;
+}
+
+/** http://www.ietf.org/rfc/rfc2831.txt suggests at least 64 bits of
+ * entropy, we use 128. This is the number of bytes in the random
+ * challenge.
+ */
+#define N_CHALLENGE_BYTES (128/8)
+
+static dbus_bool_t
+sha1_handle_first_client_response (DBusAuth         *auth,
+                                   const DBusString *data)
+{
+  /* We haven't sent a challenge yet, we're expecting a desired
+   * username from the client.
+   */
+  DBusString tmp;
+  DBusString tmp2;
+  dbus_bool_t retval;
+  DBusError error;
+  
+  retval = FALSE;
+
+  _dbus_string_set_length (&auth->challenge, 0);
+  
+  if (_dbus_string_get_length (data) > 0)
+    {
+      if (_dbus_string_get_length (&auth->identity) > 0)
+        {
+          /* Tried to send two auth identities, wtf */
+          _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n",
+                         DBUS_AUTH_NAME (auth));
+          return send_rejected (auth);
+        }
+      else
+        {
+          /* this is our auth identity */
+          if (!_dbus_string_copy (data, 0, &auth->identity, 0))
+            return FALSE;
+        }
+    }
+      
+  if (!_dbus_credentials_add_from_user (auth->desired_identity, data))
+    {
+      _dbus_verbose ("%s: Did not get a valid username from client\n",
+                     DBUS_AUTH_NAME (auth));
+      return send_rejected (auth);
+    }
+      
+  if (!_dbus_string_init (&tmp))
+    return FALSE;
+
+  if (!_dbus_string_init (&tmp2))
+    {
+      _dbus_string_free (&tmp);
+      return FALSE;
+    }
+
+  /* we cache the keyring for speed, so here we drop it if it's the
+   * wrong one. FIXME caching the keyring here is useless since we use
+   * a different DBusAuth for every connection.
+   */
+  if (auth->keyring &&
+      !_dbus_keyring_is_for_credentials (auth->keyring,
+                                         auth->desired_identity))
+    {
+      _dbus_keyring_unref (auth->keyring);
+      auth->keyring = NULL;
+    }
+  
+  if (auth->keyring == NULL)
+    {
+      dbus_error_init (&error);
+      auth->keyring = _dbus_keyring_new_for_credentials (auth->desired_identity,
+                                                         &auth->context,
+                                                         &error);
+
+      if (auth->keyring == NULL)
+        {
+          if (dbus_error_has_name (&error,
+                                   DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_error_free (&error);
+              goto out;
+            }
+          else
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (&error);
+              _dbus_verbose ("%s: Error loading keyring: %s\n",
+                             DBUS_AUTH_NAME (auth), error.message);
+              if (send_rejected (auth))
+                retval = TRUE; /* retval is only about mem */
+              dbus_error_free (&error);
+              goto out;
+            }
+        }
+      else
+        {
+          _dbus_assert (!dbus_error_is_set (&error));
+        }
+    }
+
+  _dbus_assert (auth->keyring != NULL);
+
+  dbus_error_init (&error);
+  auth->cookie_id = _dbus_keyring_get_best_key (auth->keyring, &error);
+  if (auth->cookie_id < 0)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&error);
+      _dbus_verbose ("%s: Could not get a cookie ID to send to client: %s\n",
+                     DBUS_AUTH_NAME (auth), error.message);
+      if (send_rejected (auth))
+        retval = TRUE;
+      dbus_error_free (&error);
+      goto out;
+    }
+  else
+    {
+      _dbus_assert (!dbus_error_is_set (&error));
+    }
+
+  if (!_dbus_string_copy (&auth->context, 0,
+                          &tmp2, _dbus_string_get_length (&tmp2)))
+    goto out;
+
+  if (!_dbus_string_append (&tmp2, " "))
+    goto out;
+
+  if (!_dbus_string_append_int (&tmp2, auth->cookie_id))
+    goto out;
+
+  if (!_dbus_string_append (&tmp2, " "))
+    goto out;  
+  
+  if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES))
+    goto out;
+
+  _dbus_string_set_length (&auth->challenge, 0);
+  if (!_dbus_string_hex_encode (&tmp, 0, &auth->challenge, 0))
+    goto out;
+  
+  if (!_dbus_string_hex_encode (&tmp, 0, &tmp2,
+                                _dbus_string_get_length (&tmp2)))
+    goto out;
+
+  if (!send_data (auth, &tmp2))
+    goto out;
+      
+  goto_state (auth, &server_state_waiting_for_data);
+  retval = TRUE;
+  
+ out:
+  _dbus_string_zero (&tmp);
+  _dbus_string_free (&tmp);
+  _dbus_string_zero (&tmp2);
+  _dbus_string_free (&tmp2);
+
+  return retval;
+}
+
+static dbus_bool_t
+sha1_handle_second_client_response (DBusAuth         *auth,
+                                    const DBusString *data)
+{
+  /* We are expecting a response which is the hex-encoded client
+   * challenge, space, then SHA-1 hash of the concatenation of our
+   * challenge, ":", client challenge, ":", secret key, all
+   * hex-encoded.
+   */
+  int i;
+  DBusString client_challenge;
+  DBusString client_hash;
+  dbus_bool_t retval;
+  DBusString correct_hash;
+  
+  retval = FALSE;
+  
+  if (!_dbus_string_find_blank (data, 0, &i))
+    {
+      _dbus_verbose ("%s: no space separator in client response\n",
+                     DBUS_AUTH_NAME (auth));
+      return send_rejected (auth);
+    }
+  
+  if (!_dbus_string_init (&client_challenge))
+    goto out_0;
+
+  if (!_dbus_string_init (&client_hash))
+    goto out_1;  
+
+  if (!_dbus_string_copy_len (data, 0, i, &client_challenge,
+                              0))
+    goto out_2;
+
+  _dbus_string_skip_blank (data, i, &i);
+  
+  if (!_dbus_string_copy_len (data, i,
+                              _dbus_string_get_length (data) - i,
+                              &client_hash,
+                              0))
+    goto out_2;
+
+  if (_dbus_string_get_length (&client_challenge) == 0 ||
+      _dbus_string_get_length (&client_hash) == 0)
+    {
+      _dbus_verbose ("%s: zero-length client challenge or hash\n",
+                     DBUS_AUTH_NAME (auth));
+      if (send_rejected (auth))
+        retval = TRUE;
+      goto out_2;
+    }
+
+  if (!_dbus_string_init (&correct_hash))
+    goto out_2;
+
+  if (!sha1_compute_hash (auth, auth->cookie_id,
+                          &auth->challenge, 
+                          &client_challenge,
+                          &correct_hash))
+    goto out_3;
+
+  /* if cookie_id was invalid, then we get an empty hash */
+  if (_dbus_string_get_length (&correct_hash) == 0)
+    {
+      if (send_rejected (auth))
+        retval = TRUE;
+      goto out_3;
+    }
+  
+  if (!_dbus_string_equal (&client_hash, &correct_hash))
+    {
+      if (send_rejected (auth))
+        retval = TRUE;
+      goto out_3;
+    }
+
+  if (!_dbus_credentials_add_credentials (auth->authorized_identity,
+                                          auth->desired_identity))
+    goto out_3;
+
+  /* Copy process ID from the socket credentials if it's there
+   */
+  if (!_dbus_credentials_add_credential (auth->authorized_identity,
+                                         DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+                                         auth->credentials))
+    goto out_3;
+  
+  if (!send_ok (auth))
+    goto out_3;
+
+  _dbus_verbose ("%s: authenticated client using DBUS_COOKIE_SHA1\n",
+                 DBUS_AUTH_NAME (auth));
+  
+  retval = TRUE;
+  
+ out_3:
+  _dbus_string_zero (&correct_hash);
+  _dbus_string_free (&correct_hash);
+ out_2:
+  _dbus_string_zero (&client_hash);
+  _dbus_string_free (&client_hash);
+ out_1:
+  _dbus_string_free (&client_challenge);
+ out_0:
+  return retval;
+}
+
+static dbus_bool_t
+handle_server_data_cookie_sha1_mech (DBusAuth         *auth,
+                                     const DBusString *data)
+{
+  if (auth->cookie_id < 0)
+    return sha1_handle_first_client_response (auth, data);
+  else
+    return sha1_handle_second_client_response (auth, data);
+}
+
+static void
+handle_server_shutdown_cookie_sha1_mech (DBusAuth *auth)
+{
+  auth->cookie_id = -1;  
+  _dbus_string_set_length (&auth->challenge, 0);
+}
+
+static dbus_bool_t
+handle_client_initial_response_cookie_sha1_mech (DBusAuth   *auth,
+                                                 DBusString *response)
+{
+  DBusString username;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  if (!_dbus_string_init (&username))
+    return FALSE;
+  
+  if (!_dbus_append_user_from_current_process (&username))
+    goto out_0;
+
+  if (!_dbus_string_hex_encode (&username, 0,
+				response,
+				_dbus_string_get_length (response)))
+    goto out_0;
+
+  retval = TRUE;
+  
+ out_0:
+  _dbus_string_free (&username);
+  
+  return retval;
+}
+
+static dbus_bool_t
+handle_client_data_cookie_sha1_mech (DBusAuth         *auth,
+                                     const DBusString *data)
+{
+  /* The data we get from the server should be the cookie context
+   * name, the cookie ID, and the server challenge, separated by
+   * spaces. We send back our challenge string and the correct hash.
+   */
+  dbus_bool_t retval;
+  DBusString context;
+  DBusString cookie_id_str;
+  DBusString server_challenge;
+  DBusString client_challenge;
+  DBusString correct_hash;
+  DBusString tmp;
+  int i, j;
+  long val;
+  
+  retval = FALSE;                 
+  
+  if (!_dbus_string_find_blank (data, 0, &i))
+    {
+      if (send_error (auth,
+                      "Server did not send context/ID/challenge properly"))
+        retval = TRUE;
+      goto out_0;
+    }
+
+  if (!_dbus_string_init (&context))
+    goto out_0;
+
+  if (!_dbus_string_copy_len (data, 0, i,
+                              &context, 0))
+    goto out_1;
+  
+  _dbus_string_skip_blank (data, i, &i);
+  if (!_dbus_string_find_blank (data, i, &j))
+    {
+      if (send_error (auth,
+                      "Server did not send context/ID/challenge properly"))
+        retval = TRUE;
+      goto out_1;
+    }
+
+  if (!_dbus_string_init (&cookie_id_str))
+    goto out_1;
+  
+  if (!_dbus_string_copy_len (data, i, j - i,
+                              &cookie_id_str, 0))
+    goto out_2;  
+
+  if (!_dbus_string_init (&server_challenge))
+    goto out_2;
+
+  i = j;
+  _dbus_string_skip_blank (data, i, &i);
+  j = _dbus_string_get_length (data);
+
+  if (!_dbus_string_copy_len (data, i, j - i,
+                              &server_challenge, 0))
+    goto out_3;
+
+  if (!_dbus_keyring_validate_context (&context))
+    {
+      if (send_error (auth, "Server sent invalid cookie context"))
+        retval = TRUE;
+      goto out_3;
+    }
+
+  if (!_dbus_string_parse_int (&cookie_id_str, 0, &val, NULL))
+    {
+      if (send_error (auth, "Could not parse cookie ID as an integer"))
+        retval = TRUE;
+      goto out_3;
+    }
+
+  if (_dbus_string_get_length (&server_challenge) == 0)
+    {
+      if (send_error (auth, "Empty server challenge string"))
+        retval = TRUE;
+      goto out_3;
+    }
+
+  if (auth->keyring == NULL)
+    {
+      DBusError error;
+
+      dbus_error_init (&error);
+      auth->keyring = _dbus_keyring_new_for_credentials (NULL,
+                                                         &context,
+                                                         &error);
+
+      if (auth->keyring == NULL)
+        {
+          if (dbus_error_has_name (&error,
+                                   DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_error_free (&error);
+              goto out_3;
+            }
+          else
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (&error);
+
+              _dbus_verbose ("%s: Error loading keyring: %s\n",
+                             DBUS_AUTH_NAME (auth), error.message);
+              
+              if (send_error (auth, "Could not load cookie file"))
+                retval = TRUE; /* retval is only about mem */
+              
+              dbus_error_free (&error);
+              goto out_3;
+            }
+        }
+      else
+        {
+          _dbus_assert (!dbus_error_is_set (&error));
+        }
+    }
+  
+  _dbus_assert (auth->keyring != NULL);
+  
+  if (!_dbus_string_init (&tmp))
+    goto out_3;
+  
+  if (!_dbus_generate_random_bytes (&tmp, N_CHALLENGE_BYTES))
+    goto out_4;
+
+  if (!_dbus_string_init (&client_challenge))
+    goto out_4;
+
+  if (!_dbus_string_hex_encode (&tmp, 0, &client_challenge, 0))
+    goto out_5;
+
+  if (!_dbus_string_init (&correct_hash))
+    goto out_5;
+  
+  if (!sha1_compute_hash (auth, val,
+                          &server_challenge,
+                          &client_challenge,
+                          &correct_hash))
+    goto out_6;
+
+  if (_dbus_string_get_length (&correct_hash) == 0)
+    {
+      /* couldn't find the cookie ID or something */
+      if (send_error (auth, "Don't have the requested cookie ID"))
+        retval = TRUE;
+      goto out_6;
+    }
+  
+  _dbus_string_set_length (&tmp, 0);
+  
+  if (!_dbus_string_copy (&client_challenge, 0, &tmp,
+                          _dbus_string_get_length (&tmp)))
+    goto out_6;
+
+  if (!_dbus_string_append (&tmp, " "))
+    goto out_6;
+
+  if (!_dbus_string_copy (&correct_hash, 0, &tmp,
+                          _dbus_string_get_length (&tmp)))
+    goto out_6;
+
+  if (!send_data (auth, &tmp))
+    goto out_6;
+
+  retval = TRUE;
+
+ out_6:
+  _dbus_string_zero (&correct_hash);
+  _dbus_string_free (&correct_hash);
+ out_5:
+  _dbus_string_free (&client_challenge);
+ out_4:
+  _dbus_string_zero (&tmp);
+  _dbus_string_free (&tmp);
+ out_3:
+  _dbus_string_free (&server_challenge);
+ out_2:
+  _dbus_string_free (&cookie_id_str);
+ out_1:
+  _dbus_string_free (&context);
+ out_0:
+  return retval;
+}
+
+static void
+handle_client_shutdown_cookie_sha1_mech (DBusAuth *auth)
+{
+  auth->cookie_id = -1;  
+  _dbus_string_set_length (&auth->challenge, 0);
+}
+
+/*
+ * EXTERNAL mechanism
+ */
+
+static dbus_bool_t
+handle_server_data_external_mech (DBusAuth         *auth,
+                                  const DBusString *data)
+{
+  if (_dbus_credentials_are_anonymous (auth->credentials))
+    {
+      _dbus_verbose ("%s: no credentials, mechanism EXTERNAL can't authenticate\n",
+                     DBUS_AUTH_NAME (auth));
+      return send_rejected (auth);
+    }
+  
+  if (_dbus_string_get_length (data) > 0)
+    {
+      if (_dbus_string_get_length (&auth->identity) > 0)
+        {
+          /* Tried to send two auth identities, wtf */
+          _dbus_verbose ("%s: client tried to send auth identity, but we already have one\n",
+                         DBUS_AUTH_NAME (auth));
+          return send_rejected (auth);
+        }
+      else
+        {
+          /* this is our auth identity */
+          if (!_dbus_string_copy (data, 0, &auth->identity, 0))
+            return FALSE;
+        }
+    }
+
+  /* Poke client for an auth identity, if none given */
+  if (_dbus_string_get_length (&auth->identity) == 0 &&
+      !auth->already_asked_for_initial_response)
+    {
+      if (send_data (auth, NULL))
+        {
+          _dbus_verbose ("%s: sending empty challenge asking client for auth identity\n",
+                         DBUS_AUTH_NAME (auth));
+          auth->already_asked_for_initial_response = TRUE;
+          goto_state (auth, &server_state_waiting_for_data);
+          return TRUE;
+        }
+      else
+        return FALSE;
+    }
+
+  _dbus_credentials_clear (auth->desired_identity);
+  
+  /* If auth->identity is still empty here, then client
+   * responded with an empty string after we poked it for
+   * an initial response. This means to try to auth the
+   * identity provided in the credentials.
+   */
+  if (_dbus_string_get_length (&auth->identity) == 0)
+    {
+      if (!_dbus_credentials_add_credentials (auth->desired_identity,
+                                              auth->credentials))
+        {
+          return FALSE; /* OOM */
+        }
+    }
+  else
+    {
+      if (!_dbus_credentials_add_from_user (auth->desired_identity,
+                                            &auth->identity))
+        {
+          _dbus_verbose ("%s: could not get credentials from uid string\n",
+                         DBUS_AUTH_NAME (auth));
+          return send_rejected (auth);
+        }
+    }
+
+  if (_dbus_credentials_are_anonymous (auth->desired_identity))
+    {
+      _dbus_verbose ("%s: desired user %s is no good\n",
+                     DBUS_AUTH_NAME (auth),
+                     _dbus_string_get_const_data (&auth->identity));
+      return send_rejected (auth);
+    }
+  
+  if (_dbus_credentials_are_superset (auth->credentials,
+                                      auth->desired_identity))
+    {
+      /* client has authenticated */
+      if (!_dbus_credentials_add_credentials (auth->authorized_identity,
+                                              auth->desired_identity))
+        return FALSE;
+
+      /* also copy process ID from the socket credentials
+       */
+      if (!_dbus_credentials_add_credential (auth->authorized_identity,
+                                             DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+                                             auth->credentials))
+        return FALSE;
+
+      /* also copy audit data from the socket credentials
+       */
+      if (!_dbus_credentials_add_credential (auth->authorized_identity,
+                                             DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID,
+                                             auth->credentials))
+        return FALSE;
+      
+      if (!send_ok (auth))
+        return FALSE;
+
+      _dbus_verbose ("%s: authenticated client based on socket credentials\n",
+                     DBUS_AUTH_NAME (auth));
+
+      return TRUE;
+    }
+  else
+    {
+      _dbus_verbose ("%s: desired identity not found in socket credentials\n",
+                     DBUS_AUTH_NAME (auth));
+      return send_rejected (auth);
+    }
+}
+
+static void
+handle_server_shutdown_external_mech (DBusAuth *auth)
+{
+
+}
+
+static dbus_bool_t
+handle_client_initial_response_external_mech (DBusAuth         *auth,
+                                              DBusString       *response)
+{
+  /* We always append our UID as an initial response, so the server
+   * doesn't have to send back an empty challenge to check whether we
+   * want to specify an identity. i.e. this avoids a round trip that
+   * the spec for the EXTERNAL mechanism otherwise requires.
+   */
+  DBusString plaintext;
+
+  if (!_dbus_string_init (&plaintext))
+    return FALSE;
+
+  if (!_dbus_append_user_from_current_process (&plaintext))
+    goto failed;
+
+  if (!_dbus_string_hex_encode (&plaintext, 0,
+				response,
+				_dbus_string_get_length (response)))
+    goto failed;
+
+  _dbus_string_free (&plaintext);
+  
+  return TRUE;
+
+ failed:
+  _dbus_string_free (&plaintext);
+  return FALSE;  
+}
+
+static dbus_bool_t
+handle_client_data_external_mech (DBusAuth         *auth,
+                                  const DBusString *data)
+{
+  
+  return TRUE;
+}
+
+static void
+handle_client_shutdown_external_mech (DBusAuth *auth)
+{
+
+}
+
+/*
+ * ANONYMOUS mechanism
+ */
+
+static dbus_bool_t
+handle_server_data_anonymous_mech (DBusAuth         *auth,
+                                   const DBusString *data)
+{  
+  if (_dbus_string_get_length (data) > 0)
+    {
+      /* Client is allowed to send "trace" data, the only defined
+       * meaning is that if it contains '@' it is an email address,
+       * and otherwise it is anything else, and it's supposed to be
+       * UTF-8
+       */
+      if (!_dbus_string_validate_utf8 (data, 0, _dbus_string_get_length (data)))
+        {
+          _dbus_verbose ("%s: Received invalid UTF-8 trace data from ANONYMOUS client\n",
+                         DBUS_AUTH_NAME (auth));
+          return send_rejected (auth);
+        }
+      
+      _dbus_verbose ("%s: ANONYMOUS client sent trace string: '%s'\n",
+                     DBUS_AUTH_NAME (auth),
+                     _dbus_string_get_const_data (data));
+    }
+
+  /* We want to be anonymous (clear in case some other protocol got midway through I guess) */
+  _dbus_credentials_clear (auth->desired_identity);
+
+  /* Copy process ID from the socket credentials
+   */
+  if (!_dbus_credentials_add_credential (auth->authorized_identity,
+                                         DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+                                         auth->credentials))
+    return FALSE;
+  
+  /* Anonymous is always allowed */
+  if (!send_ok (auth))
+    return FALSE;
+
+  _dbus_verbose ("%s: authenticated client as anonymous\n",
+                 DBUS_AUTH_NAME (auth));
+
+  return TRUE;
+}
+
+static void
+handle_server_shutdown_anonymous_mech (DBusAuth *auth)
+{
+  
+}
+
+static dbus_bool_t
+handle_client_initial_response_anonymous_mech (DBusAuth         *auth,
+                                               DBusString       *response)
+{
+  /* Our initial response is a "trace" string which must be valid UTF-8
+   * and must be an email address if it contains '@'.
+   * We just send the dbus implementation info, like a user-agent or
+   * something, because... why not. There's nothing guaranteed here
+   * though, we could change it later.
+   */
+  DBusString plaintext;
+
+  if (!_dbus_string_init (&plaintext))
+    return FALSE;
+
+  if (!_dbus_string_append (&plaintext,
+                            "libdbus " DBUS_VERSION_STRING))
+    goto failed;
+
+  if (!_dbus_string_hex_encode (&plaintext, 0,
+				response,
+				_dbus_string_get_length (response)))
+    goto failed;
+
+  _dbus_string_free (&plaintext);
+  
+  return TRUE;
+
+ failed:
+  _dbus_string_free (&plaintext);
+  return FALSE;  
+}
+
+static dbus_bool_t
+handle_client_data_anonymous_mech (DBusAuth         *auth,
+                                  const DBusString *data)
+{
+  
+  return TRUE;
+}
+
+static void
+handle_client_shutdown_anonymous_mech (DBusAuth *auth)
+{
+  
+}
+
+/* Put mechanisms here in order of preference.
+ * Right now we have:
+ *
+ * - EXTERNAL checks socket credentials (or in the future, other info from the OS)
+ * - DBUS_COOKIE_SHA1 uses a cookie in the home directory, like xauth or ICE
+ * - ANONYMOUS checks nothing but doesn't auth the person as a user
+ *
+ * We might ideally add a mechanism to chain to Cyrus SASL so we can
+ * use its mechanisms as well.
+ * 
+ */
+static const DBusAuthMechanismHandler
+all_mechanisms[] = {
+  { "EXTERNAL",
+    handle_server_data_external_mech,
+    NULL, NULL,
+    handle_server_shutdown_external_mech,
+    handle_client_initial_response_external_mech,
+    handle_client_data_external_mech,
+    NULL, NULL,
+    handle_client_shutdown_external_mech },
+  { "DBUS_COOKIE_SHA1",
+    handle_server_data_cookie_sha1_mech,
+    NULL, NULL,
+    handle_server_shutdown_cookie_sha1_mech,
+    handle_client_initial_response_cookie_sha1_mech,
+    handle_client_data_cookie_sha1_mech,
+    NULL, NULL,
+    handle_client_shutdown_cookie_sha1_mech },
+  { "ANONYMOUS",
+    handle_server_data_anonymous_mech,
+    NULL, NULL,
+    handle_server_shutdown_anonymous_mech,
+    handle_client_initial_response_anonymous_mech,
+    handle_client_data_anonymous_mech,
+    NULL, NULL,
+    handle_client_shutdown_anonymous_mech },  
+  { NULL, NULL }
+};
+
+static const DBusAuthMechanismHandler*
+find_mech (const DBusString  *name,
+           char             **allowed_mechs)
+{
+  int i;
+  
+  if (allowed_mechs != NULL &&
+      !_dbus_string_array_contains ((const char**) allowed_mechs,
+                                    _dbus_string_get_const_data (name)))
+    return NULL;
+  
+  i = 0;
+  while (all_mechanisms[i].mechanism != NULL)
+    {      
+      if (_dbus_string_equal_c_str (name,
+                                    all_mechanisms[i].mechanism))
+
+        return &all_mechanisms[i];
+      
+      ++i;
+    }
+  
+  return NULL;
+}
+
+static dbus_bool_t
+send_auth (DBusAuth *auth, const DBusAuthMechanismHandler *mech)
+{
+  DBusString auth_command;
+
+  if (!_dbus_string_init (&auth_command))
+    return FALSE;
+      
+  if (!_dbus_string_append (&auth_command,
+                            "AUTH "))
+    {
+      _dbus_string_free (&auth_command);
+      return FALSE;
+    }  
+  
+  if (!_dbus_string_append (&auth_command,
+                            mech->mechanism))
+    {
+      _dbus_string_free (&auth_command);
+      return FALSE;
+    }
+
+  if (mech->client_initial_response_func != NULL)
+    {
+      if (!_dbus_string_append (&auth_command, " "))
+        {
+          _dbus_string_free (&auth_command);
+          return FALSE;
+        }
+      
+      if (!(* mech->client_initial_response_func) (auth, &auth_command))
+        {
+          _dbus_string_free (&auth_command);
+          return FALSE;
+        }
+    }
+  
+  if (!_dbus_string_append (&auth_command,
+                            "\r\n"))
+    {
+      _dbus_string_free (&auth_command);
+      return FALSE;
+    }
+
+  if (!_dbus_string_copy (&auth_command, 0,
+                          &auth->outgoing,
+                          _dbus_string_get_length (&auth->outgoing)))
+    {
+      _dbus_string_free (&auth_command);
+      return FALSE;
+    }
+
+  _dbus_string_free (&auth_command);
+  shutdown_mech (auth);
+  auth->mech = mech;      
+  goto_state (auth, &client_state_waiting_for_data);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+send_data (DBusAuth *auth, DBusString *data)
+{
+  int old_len;
+
+  if (data == NULL || _dbus_string_get_length (data) == 0)
+    return _dbus_string_append (&auth->outgoing, "DATA\r\n");
+  else
+    {
+      old_len = _dbus_string_get_length (&auth->outgoing);
+      if (!_dbus_string_append (&auth->outgoing, "DATA "))
+        goto out;
+
+      if (!_dbus_string_hex_encode (data, 0, &auth->outgoing,
+                                    _dbus_string_get_length (&auth->outgoing)))
+        goto out;
+
+      if (!_dbus_string_append (&auth->outgoing, "\r\n"))
+        goto out;
+
+      return TRUE;
+
+    out:
+      _dbus_string_set_length (&auth->outgoing, old_len);
+
+      return FALSE;
+    }
+}
+
+static dbus_bool_t
+send_rejected (DBusAuth *auth)
+{
+  DBusString command;
+  DBusAuthServer *server_auth;
+  int i;
+  
+  if (!_dbus_string_init (&command))
+    return FALSE;
+  
+  if (!_dbus_string_append (&command,
+                            "REJECTED"))
+    goto nomem;
+
+  i = 0;
+  while (all_mechanisms[i].mechanism != NULL)
+    {
+      if (!_dbus_string_append (&command,
+                                " "))
+        goto nomem;
+
+      if (!_dbus_string_append (&command,
+                                all_mechanisms[i].mechanism))
+        goto nomem;
+      
+      ++i;
+    }
+  
+  if (!_dbus_string_append (&command, "\r\n"))
+    goto nomem;
+
+  if (!_dbus_string_copy (&command, 0, &auth->outgoing,
+                          _dbus_string_get_length (&auth->outgoing)))
+    goto nomem;
+
+  shutdown_mech (auth);
+  
+  _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
+  server_auth = DBUS_AUTH_SERVER (auth);
+  server_auth->failures += 1;
+
+  if (server_auth->failures >= server_auth->max_failures)
+    goto_state (auth, &common_state_need_disconnect);
+  else
+    goto_state (auth, &server_state_waiting_for_auth);
+
+  _dbus_string_free (&command);
+  
+  return TRUE;
+
+ nomem:
+  _dbus_string_free (&command);
+  return FALSE;
+}
+
+static dbus_bool_t
+send_error (DBusAuth *auth, const char *message)
+{
+  return _dbus_string_append_printf (&auth->outgoing,
+                                     "ERROR \"%s\"\r\n", message);
+}
+
+static dbus_bool_t
+send_ok (DBusAuth *auth)
+{
+  int orig_len;
+
+  orig_len = _dbus_string_get_length (&auth->outgoing);
+  
+  if (_dbus_string_append (&auth->outgoing, "OK ") &&
+      _dbus_string_copy (& DBUS_AUTH_SERVER (auth)->guid,
+                         0,
+                         &auth->outgoing,
+                         _dbus_string_get_length (&auth->outgoing)) &&
+      _dbus_string_append (&auth->outgoing, "\r\n"))
+    {
+      goto_state (auth, &server_state_waiting_for_begin);
+      return TRUE;
+    }
+  else
+    {
+      _dbus_string_set_length (&auth->outgoing, orig_len);
+      return FALSE;
+    }
+}
+
+static dbus_bool_t
+send_begin (DBusAuth         *auth)
+{
+
+  if (!_dbus_string_append (&auth->outgoing,
+                            "BEGIN\r\n"))
+    return FALSE;
+
+  goto_state (auth, &common_state_authenticated);
+  return TRUE;
+}
+
+static dbus_bool_t
+process_ok(DBusAuth *auth,
+          const DBusString *args_from_ok) {
+
+  int end_of_hex;
+  
+  /* "args_from_ok" should be the GUID, whitespace already pulled off the front */
+  _dbus_assert (_dbus_string_get_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server) == 0);
+
+  /* We decode the hex string to binary, using guid_from_server as scratch... */
+  
+  end_of_hex = 0;
+  if (!_dbus_string_hex_decode (args_from_ok, 0, &end_of_hex,
+                                & DBUS_AUTH_CLIENT (auth)->guid_from_server, 0))
+    return FALSE;
+
+  /* now clear out the scratch */
+  _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
+  
+  if (end_of_hex != _dbus_string_get_length (args_from_ok) ||
+      end_of_hex == 0)
+    {
+      _dbus_verbose ("Bad GUID from server, parsed %d bytes and had %d bytes from server\n",
+                     end_of_hex, _dbus_string_get_length (args_from_ok));
+      goto_state (auth, &common_state_need_disconnect);
+      return TRUE;
+    }
+
+  if (!_dbus_string_copy (args_from_ok, 0, &DBUS_AUTH_CLIENT (auth)->guid_from_server, 0)) {
+      _dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
+      return FALSE;
+  }
+
+  _dbus_verbose ("Got GUID '%s' from the server\n",
+                 _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server));
+
+  if (auth->unix_fd_possible)
+    return send_negotiate_unix_fd(auth);
+
+  _dbus_verbose("Not negotiating unix fd passing, since not possible\n");
+  return send_begin (auth);
+}
+
+static dbus_bool_t
+send_cancel (DBusAuth *auth)
+{
+  if (_dbus_string_append (&auth->outgoing, "CANCEL\r\n"))
+    {
+      goto_state (auth, &client_state_waiting_for_reject);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+static dbus_bool_t
+process_data (DBusAuth             *auth,
+              const DBusString     *args,
+              DBusAuthDataFunction  data_func)
+{
+  int end;
+  DBusString decoded;
+
+  if (!_dbus_string_init (&decoded))
+    return FALSE;
+
+  if (!_dbus_string_hex_decode (args, 0, &end, &decoded, 0))
+    {
+      _dbus_string_free (&decoded);
+      return FALSE;
+    }
+
+  if (_dbus_string_get_length (args) != end)
+    {
+      _dbus_string_free (&decoded);
+      if (!send_error (auth, "Invalid hex encoding"))
+        return FALSE;
+
+      return TRUE;
+    }
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  if (_dbus_string_validate_ascii (&decoded, 0,
+                                   _dbus_string_get_length (&decoded)))
+    _dbus_verbose ("%s: data: '%s'\n",
+                   DBUS_AUTH_NAME (auth),
+                   _dbus_string_get_const_data (&decoded));
+#endif
+      
+  if (!(* data_func) (auth, &decoded))
+    {
+      _dbus_string_free (&decoded);
+      return FALSE;
+    }
+
+  _dbus_string_free (&decoded);
+  return TRUE;
+}
+
+static dbus_bool_t
+send_negotiate_unix_fd (DBusAuth *auth)
+{
+  if (!_dbus_string_append (&auth->outgoing,
+                            "NEGOTIATE_UNIX_FD\r\n"))
+    return FALSE;
+
+  goto_state (auth, &client_state_waiting_for_agree_unix_fd);
+  return TRUE;
+}
+
+static dbus_bool_t
+send_agree_unix_fd (DBusAuth *auth)
+{
+  _dbus_assert(auth->unix_fd_possible);
+
+  auth->unix_fd_negotiated = TRUE;
+  _dbus_verbose("Agreed to UNIX FD passing\n");
+
+  if (!_dbus_string_append (&auth->outgoing,
+                            "AGREE_UNIX_FD\r\n"))
+    return FALSE;
+
+  goto_state (auth, &server_state_waiting_for_begin);
+  return TRUE;
+}
+
+static dbus_bool_t
+handle_auth (DBusAuth *auth, const DBusString *args)
+{
+  if (_dbus_string_get_length (args) == 0)
+    {
+      /* No args to the auth, send mechanisms */
+      if (!send_rejected (auth))
+        return FALSE;
+
+      return TRUE;
+    }
+  else
+    {
+      int i;
+      DBusString mech;
+      DBusString hex_response;
+      
+      _dbus_string_find_blank (args, 0, &i);
+
+      if (!_dbus_string_init (&mech))
+        return FALSE;
+
+      if (!_dbus_string_init (&hex_response))
+        {
+          _dbus_string_free (&mech);
+          return FALSE;
+        }
+      
+      if (!_dbus_string_copy_len (args, 0, i, &mech, 0))
+        goto failed;
+
+      _dbus_string_skip_blank (args, i, &i);
+      if (!_dbus_string_copy (args, i, &hex_response, 0))
+        goto failed;
+     
+      auth->mech = find_mech (&mech, auth->allowed_mechs);
+      if (auth->mech != NULL)
+        {
+          _dbus_verbose ("%s: Trying mechanism %s\n",
+                         DBUS_AUTH_NAME (auth),
+                         auth->mech->mechanism);
+          
+          if (!process_data (auth, &hex_response,
+                             auth->mech->server_data_func))
+            goto failed;
+        }
+      else
+        {
+          /* Unsupported mechanism */
+          _dbus_verbose ("%s: Unsupported mechanism %s\n",
+                         DBUS_AUTH_NAME (auth),
+                         _dbus_string_get_const_data (&mech));
+          
+          if (!send_rejected (auth))
+            goto failed;
+        }
+
+      _dbus_string_free (&mech);      
+      _dbus_string_free (&hex_response);
+
+      return TRUE;
+      
+    failed:
+      auth->mech = NULL;
+      _dbus_string_free (&mech);
+      _dbus_string_free (&hex_response);
+      return FALSE;
+    }
+}
+
+static dbus_bool_t
+handle_server_state_waiting_for_auth  (DBusAuth         *auth,
+                                       DBusAuthCommand   command,
+                                       const DBusString *args)
+{
+  switch (command)
+    {
+    case DBUS_AUTH_COMMAND_AUTH:
+      return handle_auth (auth, args);
+
+    case DBUS_AUTH_COMMAND_CANCEL:
+    case DBUS_AUTH_COMMAND_DATA:
+      return send_error (auth, "Not currently in an auth conversation");
+
+    case DBUS_AUTH_COMMAND_BEGIN:
+      goto_state (auth, &common_state_need_disconnect);
+      return TRUE;
+
+    case DBUS_AUTH_COMMAND_ERROR:
+      return send_rejected (auth);
+
+    case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
+      return send_error (auth, "Need to authenticate first");
+
+    case DBUS_AUTH_COMMAND_REJECTED:
+    case DBUS_AUTH_COMMAND_OK:
+    case DBUS_AUTH_COMMAND_UNKNOWN:
+    case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
+    default:
+      return send_error (auth, "Unknown command");
+    }
+}
+
+static dbus_bool_t
+handle_server_state_waiting_for_data  (DBusAuth         *auth,
+                                       DBusAuthCommand   command,
+                                       const DBusString *args)
+{
+  switch (command)
+    {
+    case DBUS_AUTH_COMMAND_AUTH:
+      return send_error (auth, "Sent AUTH while another AUTH in progress");
+
+    case DBUS_AUTH_COMMAND_CANCEL:
+    case DBUS_AUTH_COMMAND_ERROR:
+      return send_rejected (auth);
+
+    case DBUS_AUTH_COMMAND_DATA:
+      return process_data (auth, args, auth->mech->server_data_func);
+
+    case DBUS_AUTH_COMMAND_BEGIN:
+      goto_state (auth, &common_state_need_disconnect);
+      return TRUE;
+
+    case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
+      return send_error (auth, "Need to authenticate first");
+
+    case DBUS_AUTH_COMMAND_REJECTED:
+    case DBUS_AUTH_COMMAND_OK:
+    case DBUS_AUTH_COMMAND_UNKNOWN:
+    case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
+    default:
+      return send_error (auth, "Unknown command");
+    }
+}
+
+static dbus_bool_t
+handle_server_state_waiting_for_begin (DBusAuth         *auth,
+                                       DBusAuthCommand   command,
+                                       const DBusString *args)
+{
+  switch (command)
+    {
+    case DBUS_AUTH_COMMAND_AUTH:
+      return send_error (auth, "Sent AUTH while expecting BEGIN");
+
+    case DBUS_AUTH_COMMAND_DATA:
+      return send_error (auth, "Sent DATA while expecting BEGIN");
+
+    case DBUS_AUTH_COMMAND_BEGIN:
+      goto_state (auth, &common_state_authenticated);
+      return TRUE;
+
+    case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
+      if (auth->unix_fd_possible)
+        return send_agree_unix_fd(auth);
+      else
+        return send_error(auth, "Unix FD passing not supported, not authenticated or otherwise not possible");
+
+    case DBUS_AUTH_COMMAND_REJECTED:
+    case DBUS_AUTH_COMMAND_OK:
+    case DBUS_AUTH_COMMAND_UNKNOWN:
+    case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
+    default:
+      return send_error (auth, "Unknown command");
+
+    case DBUS_AUTH_COMMAND_CANCEL:
+    case DBUS_AUTH_COMMAND_ERROR:
+      return send_rejected (auth);
+    }
+}
+
+/* return FALSE if no memory, TRUE if all OK */
+static dbus_bool_t
+get_word (const DBusString *str,
+          int              *start,
+          DBusString       *word)
+{
+  int i;
+
+  _dbus_string_skip_blank (str, *start, start);
+  _dbus_string_find_blank (str, *start, &i);
+  
+  if (i > *start)
+    {
+      if (!_dbus_string_copy_len (str, *start, i - *start, word, 0))
+        return FALSE;
+      
+      *start = i;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+record_mechanisms (DBusAuth         *auth,
+                   const DBusString *args)
+{
+  int next;
+  int len;
+
+  if (auth->already_got_mechanisms)
+    return TRUE;
+  
+  len = _dbus_string_get_length (args);
+  
+  next = 0;
+  while (next < len)
+    {
+      DBusString m;
+      const DBusAuthMechanismHandler *mech;
+      
+      if (!_dbus_string_init (&m))
+        goto nomem;
+      
+      if (!get_word (args, &next, &m))
+        {
+          _dbus_string_free (&m);
+          goto nomem;
+        }
+
+      mech = find_mech (&m, auth->allowed_mechs);
+
+      if (mech != NULL)
+        {
+          /* FIXME right now we try mechanisms in the order
+           * the server lists them; should we do them in
+           * some more deterministic order?
+           *
+           * Probably in all_mechanisms order, our order of
+           * preference. Of course when the server is us,
+           * it lists things in that order anyhow.
+           */
+
+          if (mech != &all_mechanisms[0])
+            {
+              _dbus_verbose ("%s: Adding mechanism %s to list we will try\n",
+                             DBUS_AUTH_NAME (auth), mech->mechanism);
+          
+              if (!_dbus_list_append (& DBUS_AUTH_CLIENT (auth)->mechs_to_try,
+                                      (void*) mech))
+                {
+                  _dbus_string_free (&m);
+                  goto nomem;
+                }
+            }
+          else
+            {
+              _dbus_verbose ("%s: Already tried mechanism %s; not adding to list we will try\n",
+                             DBUS_AUTH_NAME (auth), mech->mechanism);
+            }
+        }
+      else
+        {
+          _dbus_verbose ("%s: Server offered mechanism \"%s\" that we don't know how to use\n",
+                         DBUS_AUTH_NAME (auth),
+                         _dbus_string_get_const_data (&m));
+        }
+
+      _dbus_string_free (&m);
+    }
+  
+  auth->already_got_mechanisms = TRUE;
+  
+  return TRUE;
+
+ nomem:
+  _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
+  
+  return FALSE;
+}
+
+static dbus_bool_t
+process_rejected (DBusAuth *auth, const DBusString *args)
+{
+  const DBusAuthMechanismHandler *mech;
+  DBusAuthClient *client;
+
+  client = DBUS_AUTH_CLIENT (auth);
+
+  if (!auth->already_got_mechanisms)
+    {
+      if (!record_mechanisms (auth, args))
+        return FALSE;
+    }
+  
+  if (DBUS_AUTH_CLIENT (auth)->mechs_to_try != NULL)
+    {
+      mech = client->mechs_to_try->data;
+
+      if (!send_auth (auth, mech))
+        return FALSE;
+
+      _dbus_list_pop_first (&client->mechs_to_try);
+
+      _dbus_verbose ("%s: Trying mechanism %s\n",
+                     DBUS_AUTH_NAME (auth),
+                     mech->mechanism);
+    }
+  else
+    {
+      /* Give up */
+      _dbus_verbose ("%s: Disconnecting because we are out of mechanisms to try using\n",
+                     DBUS_AUTH_NAME (auth));
+      goto_state (auth, &common_state_need_disconnect);
+    }
+  
+  return TRUE;
+}
+
+
+static dbus_bool_t
+handle_client_state_waiting_for_data (DBusAuth         *auth,
+                                      DBusAuthCommand   command,
+                                      const DBusString *args)
+{
+  _dbus_assert (auth->mech != NULL);
+ 
+  switch (command)
+    {
+    case DBUS_AUTH_COMMAND_DATA:
+      return process_data (auth, args, auth->mech->client_data_func);
+
+    case DBUS_AUTH_COMMAND_REJECTED:
+      return process_rejected (auth, args);
+
+    case DBUS_AUTH_COMMAND_OK:
+      return process_ok(auth, args);
+
+    case DBUS_AUTH_COMMAND_ERROR:
+      return send_cancel (auth);
+
+    case DBUS_AUTH_COMMAND_AUTH:
+    case DBUS_AUTH_COMMAND_CANCEL:
+    case DBUS_AUTH_COMMAND_BEGIN:
+    case DBUS_AUTH_COMMAND_UNKNOWN:
+    case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
+    case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
+    default:
+      return send_error (auth, "Unknown command");
+    }
+}
+
+static dbus_bool_t
+handle_client_state_waiting_for_ok (DBusAuth         *auth,
+                                    DBusAuthCommand   command,
+                                    const DBusString *args)
+{
+  switch (command)
+    {
+    case DBUS_AUTH_COMMAND_REJECTED:
+      return process_rejected (auth, args);
+
+    case DBUS_AUTH_COMMAND_OK:
+      return process_ok(auth, args);
+
+    case DBUS_AUTH_COMMAND_DATA:
+    case DBUS_AUTH_COMMAND_ERROR:
+      return send_cancel (auth);
+
+    case DBUS_AUTH_COMMAND_AUTH:
+    case DBUS_AUTH_COMMAND_CANCEL:
+    case DBUS_AUTH_COMMAND_BEGIN:
+    case DBUS_AUTH_COMMAND_UNKNOWN:
+    case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
+    case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
+    default:
+      return send_error (auth, "Unknown command");
+    }
+}
+
+static dbus_bool_t
+handle_client_state_waiting_for_reject (DBusAuth         *auth,
+                                        DBusAuthCommand   command,
+                                        const DBusString *args)
+{
+  switch (command)
+    {
+    case DBUS_AUTH_COMMAND_REJECTED:
+      return process_rejected (auth, args);
+      
+    case DBUS_AUTH_COMMAND_AUTH:
+    case DBUS_AUTH_COMMAND_CANCEL:
+    case DBUS_AUTH_COMMAND_DATA:
+    case DBUS_AUTH_COMMAND_BEGIN:
+    case DBUS_AUTH_COMMAND_OK:
+    case DBUS_AUTH_COMMAND_ERROR:
+    case DBUS_AUTH_COMMAND_UNKNOWN:
+    case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
+    case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
+    default:
+      goto_state (auth, &common_state_need_disconnect);
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
+handle_client_state_waiting_for_agree_unix_fd(DBusAuth         *auth,
+                                              DBusAuthCommand   command,
+                                              const DBusString *args)
+{
+  switch (command)
+    {
+    case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
+      _dbus_assert(auth->unix_fd_possible);
+      auth->unix_fd_negotiated = TRUE;
+      _dbus_verbose("Successfully negotiated UNIX FD passing\n");
+      return send_begin (auth);
+
+    case DBUS_AUTH_COMMAND_ERROR:
+      _dbus_assert(auth->unix_fd_possible);
+      auth->unix_fd_negotiated = FALSE;
+      _dbus_verbose("Failed to negotiate UNIX FD passing\n");
+      return send_begin (auth);
+
+    case DBUS_AUTH_COMMAND_OK:
+    case DBUS_AUTH_COMMAND_DATA:
+    case DBUS_AUTH_COMMAND_REJECTED:
+    case DBUS_AUTH_COMMAND_AUTH:
+    case DBUS_AUTH_COMMAND_CANCEL:
+    case DBUS_AUTH_COMMAND_BEGIN:
+    case DBUS_AUTH_COMMAND_UNKNOWN:
+    case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
+    default:
+      return send_error (auth, "Unknown command");
+    }
+}
+
+/**
+ * Mapping from command name to enum
+ */
+typedef struct {
+  const char *name;        /**< Name of the command */
+  DBusAuthCommand command; /**< Corresponding enum */
+} DBusAuthCommandName;
+
+static const DBusAuthCommandName auth_command_names[] = {
+  { "AUTH",              DBUS_AUTH_COMMAND_AUTH },
+  { "CANCEL",            DBUS_AUTH_COMMAND_CANCEL },
+  { "DATA",              DBUS_AUTH_COMMAND_DATA },
+  { "BEGIN",             DBUS_AUTH_COMMAND_BEGIN },
+  { "REJECTED",          DBUS_AUTH_COMMAND_REJECTED },
+  { "OK",                DBUS_AUTH_COMMAND_OK },
+  { "ERROR",             DBUS_AUTH_COMMAND_ERROR },
+  { "NEGOTIATE_UNIX_FD", DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD },
+  { "AGREE_UNIX_FD",     DBUS_AUTH_COMMAND_AGREE_UNIX_FD }
+};
+
+static DBusAuthCommand
+lookup_command_from_name (DBusString *command)
+{
+  int i;
+
+  for (i = 0; i < _DBUS_N_ELEMENTS (auth_command_names); i++)
+    {
+      if (_dbus_string_equal_c_str (command,
+                                    auth_command_names[i].name))
+        return auth_command_names[i].command;
+    }
+
+  return DBUS_AUTH_COMMAND_UNKNOWN;
+}
+
+static void
+goto_state (DBusAuth *auth,
+            const DBusAuthStateData *state)
+{
+  _dbus_verbose ("%s: going from state %s to state %s\n",
+                 DBUS_AUTH_NAME (auth),
+                 auth->state->name,
+                 state->name);
+
+  auth->state = state;
+}
+
+/* returns whether to call it again right away */
+static dbus_bool_t
+process_command (DBusAuth *auth)
+{
+  DBusAuthCommand command;
+  DBusString line;
+  DBusString args;
+  int eol;
+  int i, j;
+  dbus_bool_t retval;
+
+  /* _dbus_verbose ("%s:   trying process_command()\n"); */
+  
+  retval = FALSE;
+  
+  eol = 0;
+  if (!_dbus_string_find (&auth->incoming, 0, "\r\n", &eol))
+    return FALSE;
+  
+  if (!_dbus_string_init (&line))
+    {
+      auth->needed_memory = TRUE;
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&args))
+    {
+      _dbus_string_free (&line);
+      auth->needed_memory = TRUE;
+      return FALSE;
+    }
+  
+  if (!_dbus_string_copy_len (&auth->incoming, 0, eol, &line, 0))
+    goto out;
+
+  if (!_dbus_string_validate_ascii (&line, 0,
+                                    _dbus_string_get_length (&line)))
+    {
+      _dbus_verbose ("%s: Command contained non-ASCII chars or embedded nul\n",
+                     DBUS_AUTH_NAME (auth));
+      if (!send_error (auth, "Command contained non-ASCII"))
+        goto out;
+      else
+        goto next_command;
+    }
+  
+  _dbus_verbose ("%s: got command \"%s\"\n",
+                 DBUS_AUTH_NAME (auth),
+                 _dbus_string_get_const_data (&line));
+  
+  _dbus_string_find_blank (&line, 0, &i);
+  _dbus_string_skip_blank (&line, i, &j);
+
+  if (j > i)
+    _dbus_string_delete (&line, i, j - i);
+  
+  if (!_dbus_string_move (&line, i, &args, 0))
+    goto out;
+
+  /* FIXME 1.0 we should probably validate that only the allowed
+   * chars are in the command name
+   */
+  
+  command = lookup_command_from_name (&line);
+  if (!(* auth->state->handler) (auth, command, &args))
+    goto out;
+
+ next_command:
+  
+  /* We've succeeded in processing the whole command so drop it out
+   * of the incoming buffer and return TRUE to try another command.
+   */
+
+  _dbus_string_delete (&auth->incoming, 0, eol);
+  
+  /* kill the \r\n */
+  _dbus_string_delete (&auth->incoming, 0, 2);
+
+  retval = TRUE;
+  
+ out:
+  _dbus_string_free (&args);
+  _dbus_string_free (&line);
+
+  if (!retval)
+    auth->needed_memory = TRUE;
+  else
+    auth->needed_memory = FALSE;
+  
+  return retval;
+}
+
+
+/** @} */
+
+/**
+ * @addtogroup DBusAuth
+ * @{
+ */
+
+/**
+ * Creates a new auth conversation object for the server side.
+ * See doc/dbus-sasl-profile.txt for full details on what
+ * this object does.
+ *
+ * @returns the new object or #NULL if no memory
+ */
+DBusAuth*
+_dbus_auth_server_new (const DBusString *guid)
+{
+  DBusAuth *auth;
+  DBusAuthServer *server_auth;
+  DBusString guid_copy;
+
+  if (!_dbus_string_init (&guid_copy))
+    return NULL;
+
+  if (!_dbus_string_copy (guid, 0, &guid_copy, 0))
+    {
+      _dbus_string_free (&guid_copy);
+      return NULL;
+    }
+
+  auth = _dbus_auth_new (sizeof (DBusAuthServer));
+  if (auth == NULL)
+    {
+      _dbus_string_free (&guid_copy);
+      return NULL;
+    }
+  
+  auth->side = auth_side_server;
+  auth->state = &server_state_waiting_for_auth;
+
+  server_auth = DBUS_AUTH_SERVER (auth);
+
+  server_auth->guid = guid_copy;
+  
+  /* perhaps this should be per-mechanism with a lower
+   * max
+   */
+  server_auth->failures = 0;
+  server_auth->max_failures = 6;
+  
+  return auth;
+}
+
+/**
+ * Creates a new auth conversation object for the client side.
+ * See doc/dbus-sasl-profile.txt for full details on what
+ * this object does.
+ *
+ * @returns the new object or #NULL if no memory
+ */
+DBusAuth*
+_dbus_auth_client_new (void)
+{
+  DBusAuth *auth;
+  DBusString guid_str;
+
+  if (!_dbus_string_init (&guid_str))
+    return NULL;
+
+  auth = _dbus_auth_new (sizeof (DBusAuthClient));
+  if (auth == NULL)
+    {
+      _dbus_string_free (&guid_str);
+      return NULL;
+    }
+
+  DBUS_AUTH_CLIENT (auth)->guid_from_server = guid_str;
+
+  auth->side = auth_side_client;
+  auth->state = &client_state_need_send_auth;
+
+  /* Start the auth conversation by sending AUTH for our default
+   * mechanism */
+  if (!send_auth (auth, &all_mechanisms[0]))
+    {
+      _dbus_auth_unref (auth);
+      return NULL;
+    }
+  
+  return auth;
+}
+
+/**
+ * Increments the refcount of an auth object.
+ *
+ * @param auth the auth conversation
+ * @returns the auth conversation
+ */
+DBusAuth *
+_dbus_auth_ref (DBusAuth *auth)
+{
+  _dbus_assert (auth != NULL);
+  
+  auth->refcount += 1;
+  
+  return auth;
+}
+
+/**
+ * Decrements the refcount of an auth object.
+ *
+ * @param auth the auth conversation
+ */
+void
+_dbus_auth_unref (DBusAuth *auth)
+{
+  _dbus_assert (auth != NULL);
+  _dbus_assert (auth->refcount > 0);
+
+  auth->refcount -= 1;
+  if (auth->refcount == 0)
+    {
+      shutdown_mech (auth);
+
+      if (DBUS_AUTH_IS_CLIENT (auth))
+        {
+          _dbus_string_free (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
+          _dbus_list_clear (& DBUS_AUTH_CLIENT (auth)->mechs_to_try);
+        }
+      else
+        {
+          _dbus_assert (DBUS_AUTH_IS_SERVER (auth));
+
+          _dbus_string_free (& DBUS_AUTH_SERVER (auth)->guid);
+        }
+
+      if (auth->keyring)
+        _dbus_keyring_unref (auth->keyring);
+
+      _dbus_string_free (&auth->context);
+      _dbus_string_free (&auth->challenge);
+      _dbus_string_free (&auth->identity);
+      _dbus_string_free (&auth->incoming);
+      _dbus_string_free (&auth->outgoing);
+
+      dbus_free_string_array (auth->allowed_mechs);
+
+      _dbus_credentials_unref (auth->credentials);
+      _dbus_credentials_unref (auth->authorized_identity);
+      _dbus_credentials_unref (auth->desired_identity);
+      
+      dbus_free (auth);
+    }
+}
+
+/**
+ * Sets an array of authentication mechanism names
+ * that we are willing to use.
+ *
+ * @param auth the auth conversation
+ * @param mechanisms #NULL-terminated array of mechanism names
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_auth_set_mechanisms (DBusAuth    *auth,
+                           const char **mechanisms)
+{
+  char **copy;
+
+  if (mechanisms != NULL)
+    {
+      copy = _dbus_dup_string_array (mechanisms);
+      if (copy == NULL)
+        return FALSE;
+    }
+  else
+    copy = NULL;
+  
+  dbus_free_string_array (auth->allowed_mechs);
+
+  auth->allowed_mechs = copy;
+
+  return TRUE;
+}
+
+/**
+ * @param auth the auth conversation object
+ * @returns #TRUE if we're in a final state
+ */
+#define DBUS_AUTH_IN_END_STATE(auth) ((auth)->state->handler == NULL)
+
+/**
+ * Analyzes buffered input and moves the auth conversation forward,
+ * returning the new state of the auth conversation.
+ *
+ * @param auth the auth conversation
+ * @returns the new state
+ */
+DBusAuthState
+_dbus_auth_do_work (DBusAuth *auth)
+{
+  auth->needed_memory = FALSE;
+
+  /* Max amount we'll buffer up before deciding someone's on crack */
+#define MAX_BUFFER (16 * _DBUS_ONE_KILOBYTE)
+
+  do
+    {
+      if (DBUS_AUTH_IN_END_STATE (auth))
+        break;
+      
+      if (_dbus_string_get_length (&auth->incoming) > MAX_BUFFER ||
+          _dbus_string_get_length (&auth->outgoing) > MAX_BUFFER)
+        {
+          goto_state (auth, &common_state_need_disconnect);
+          _dbus_verbose ("%s: Disconnecting due to excessive data buffered in auth phase\n",
+                         DBUS_AUTH_NAME (auth));
+          break;
+        }
+    }
+  while (process_command (auth));
+
+  if (auth->needed_memory)
+    return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
+  else if (_dbus_string_get_length (&auth->outgoing) > 0)
+    return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
+  else if (auth->state == &common_state_need_disconnect)
+    return DBUS_AUTH_STATE_NEED_DISCONNECT;
+  else if (auth->state == &common_state_authenticated)
+    return DBUS_AUTH_STATE_AUTHENTICATED;
+  else return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
+}
+
+/**
+ * Gets bytes that need to be sent to the peer we're conversing with.
+ * After writing some bytes, _dbus_auth_bytes_sent() must be called
+ * to notify the auth object that they were written.
+ *
+ * @param auth the auth conversation
+ * @param str return location for a ref to the buffer to send
+ * @returns #FALSE if nothing to send
+ */
+dbus_bool_t
+_dbus_auth_get_bytes_to_send (DBusAuth          *auth,
+                              const DBusString **str)
+{
+  _dbus_assert (auth != NULL);
+  _dbus_assert (str != NULL);
+
+  *str = NULL;
+  
+  if (_dbus_string_get_length (&auth->outgoing) == 0)
+    return FALSE;
+
+  *str = &auth->outgoing;
+
+  return TRUE;
+}
+
+/**
+ * Notifies the auth conversation object that
+ * the given number of bytes of the outgoing buffer
+ * have been written out.
+ *
+ * @param auth the auth conversation
+ * @param bytes_sent number of bytes written out
+ */
+void
+_dbus_auth_bytes_sent (DBusAuth *auth,
+                       int       bytes_sent)
+{
+  _dbus_verbose ("%s: Sent %d bytes of: %s\n",
+                 DBUS_AUTH_NAME (auth),
+                 bytes_sent,
+                 _dbus_string_get_const_data (&auth->outgoing));
+  
+  _dbus_string_delete (&auth->outgoing,
+                       0, bytes_sent);
+}
+
+/**
+ * Get a buffer to be used for reading bytes from the peer we're conversing
+ * with. Bytes should be appended to this buffer.
+ *
+ * @param auth the auth conversation
+ * @param buffer return location for buffer to append bytes to
+ */
+void
+_dbus_auth_get_buffer (DBusAuth     *auth,
+                       DBusString **buffer)
+{
+  _dbus_assert (auth != NULL);
+  _dbus_assert (!auth->buffer_outstanding);
+  
+  *buffer = &auth->incoming;
+
+  auth->buffer_outstanding = TRUE;
+}
+
+/**
+ * Returns a buffer with new data read into it.
+ *
+ * @param auth the auth conversation
+ * @param buffer the buffer being returned
+ * @param bytes_read number of new bytes added
+ */
+void
+_dbus_auth_return_buffer (DBusAuth               *auth,
+                          DBusString             *buffer,
+                          int                     bytes_read)
+{
+  _dbus_assert (buffer == &auth->incoming);
+  _dbus_assert (auth->buffer_outstanding);
+
+  auth->buffer_outstanding = FALSE;
+}
+
+/**
+ * Returns leftover bytes that were not used as part of the auth
+ * conversation.  These bytes will be part of the message stream
+ * instead. This function may not be called until authentication has
+ * succeeded.
+ *
+ * @param auth the auth conversation
+ * @param str return location for pointer to string of unused bytes
+ */
+void
+_dbus_auth_get_unused_bytes (DBusAuth           *auth,
+                             const DBusString **str)
+{
+  if (!DBUS_AUTH_IN_END_STATE (auth))
+    return;
+
+  *str = &auth->incoming;
+}
+
+
+/**
+ * Gets rid of unused bytes returned by _dbus_auth_get_unused_bytes()
+ * after we've gotten them and successfully moved them elsewhere.
+ *
+ * @param auth the auth conversation
+ */
+void
+_dbus_auth_delete_unused_bytes (DBusAuth *auth)
+{
+  if (!DBUS_AUTH_IN_END_STATE (auth))
+    return;
+
+  _dbus_string_set_length (&auth->incoming, 0);
+}
+
+/**
+ * Called post-authentication, indicates whether we need to encode
+ * the message stream with _dbus_auth_encode_data() prior to
+ * sending it to the peer.
+ *
+ * @param auth the auth conversation
+ * @returns #TRUE if we need to encode the stream
+ */
+dbus_bool_t
+_dbus_auth_needs_encoding (DBusAuth *auth)
+{
+  if (auth->state != &common_state_authenticated)
+    return FALSE;
+  
+  if (auth->mech != NULL)
+    {
+      if (DBUS_AUTH_IS_CLIENT (auth))
+        return auth->mech->client_encode_func != NULL;
+      else
+        return auth->mech->server_encode_func != NULL;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * Called post-authentication, encodes a block of bytes for sending to
+ * the peer. If no encoding was negotiated, just copies the bytes
+ * (you can avoid this by checking _dbus_auth_needs_encoding()).
+ *
+ * @param auth the auth conversation
+ * @param plaintext the plain text data
+ * @param encoded initialized string to where encoded data is appended
+ * @returns #TRUE if we had enough memory and successfully encoded
+ */
+dbus_bool_t
+_dbus_auth_encode_data (DBusAuth         *auth,
+                        const DBusString *plaintext,
+                        DBusString       *encoded)
+{
+  _dbus_assert (plaintext != encoded);
+  
+  if (auth->state != &common_state_authenticated)
+    return FALSE;
+  
+  if (_dbus_auth_needs_encoding (auth))
+    {
+      if (DBUS_AUTH_IS_CLIENT (auth))
+        return (* auth->mech->client_encode_func) (auth, plaintext, encoded);
+      else
+        return (* auth->mech->server_encode_func) (auth, plaintext, encoded);
+    }
+  else
+    {
+      return _dbus_string_copy (plaintext, 0, encoded,
+                                _dbus_string_get_length (encoded));
+    }
+}
+
+/**
+ * Called post-authentication, indicates whether we need to decode
+ * the message stream with _dbus_auth_decode_data() after
+ * receiving it from the peer.
+ *
+ * @param auth the auth conversation
+ * @returns #TRUE if we need to encode the stream
+ */
+dbus_bool_t
+_dbus_auth_needs_decoding (DBusAuth *auth)
+{
+  if (auth->state != &common_state_authenticated)
+    return FALSE;
+    
+  if (auth->mech != NULL)
+    {
+      if (DBUS_AUTH_IS_CLIENT (auth))
+        return auth->mech->client_decode_func != NULL;
+      else
+        return auth->mech->server_decode_func != NULL;
+    }
+  else
+    return FALSE;
+}
+
+
+/**
+ * Called post-authentication, decodes a block of bytes received from
+ * the peer. If no encoding was negotiated, just copies the bytes (you
+ * can avoid this by checking _dbus_auth_needs_decoding()).
+ *
+ * @todo 1.0? We need to be able to distinguish "out of memory" error
+ * from "the data is hosed" error.
+ *
+ * @param auth the auth conversation
+ * @param encoded the encoded data
+ * @param plaintext initialized string where decoded data is appended
+ * @returns #TRUE if we had enough memory and successfully decoded
+ */
+dbus_bool_t
+_dbus_auth_decode_data (DBusAuth         *auth,
+                        const DBusString *encoded,
+                        DBusString       *plaintext)
+{
+  _dbus_assert (plaintext != encoded);
+  
+  if (auth->state != &common_state_authenticated)
+    return FALSE;
+  
+  if (_dbus_auth_needs_decoding (auth))
+    {
+      if (DBUS_AUTH_IS_CLIENT (auth))
+        return (* auth->mech->client_decode_func) (auth, encoded, plaintext);
+      else
+        return (* auth->mech->server_decode_func) (auth, encoded, plaintext);
+    }
+  else
+    {
+      return _dbus_string_copy (encoded, 0, plaintext,
+                                _dbus_string_get_length (plaintext));
+    }
+}
+
+/**
+ * Sets credentials received via reliable means from the operating
+ * system.
+ *
+ * @param auth the auth conversation
+ * @param credentials the credentials received
+ * @returns #FALSE on OOM
+ */
+dbus_bool_t
+_dbus_auth_set_credentials (DBusAuth               *auth,
+                            DBusCredentials        *credentials)
+{
+  _dbus_credentials_clear (auth->credentials);
+  return _dbus_credentials_add_credentials (auth->credentials,
+                                            credentials);
+}
+
+/**
+ * Gets the identity we authorized the client as.  Apps may have
+ * different policies as to what identities they allow.
+ *
+ * Returned credentials are not a copy and should not be modified
+ *
+ * @param auth the auth conversation
+ * @returns the credentials we've authorized BY REFERENCE do not modify
+ */
+DBusCredentials*
+_dbus_auth_get_identity (DBusAuth               *auth)
+{
+  if (auth->state == &common_state_authenticated)
+    {
+      return auth->authorized_identity;
+    }
+  else
+    {
+      /* FIXME instead of this, keep an empty credential around that
+       * doesn't require allocation or something
+       */
+      /* return empty credentials */
+      _dbus_assert (_dbus_credentials_are_empty (auth->authorized_identity));
+      return auth->authorized_identity;
+    }
+}
+
+/**
+ * Gets the GUID from the server if we've authenticated; gets
+ * #NULL otherwise.
+ * @param auth the auth object
+ * @returns the GUID in ASCII hex format
+ */
+const char*
+_dbus_auth_get_guid_from_server (DBusAuth *auth)
+{
+  _dbus_assert (DBUS_AUTH_IS_CLIENT (auth));
+  
+  if (auth->state == &common_state_authenticated)
+    return _dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server);
+  else
+    return NULL;
+}
+
+/**
+ * Sets the "authentication context" which scopes cookies
+ * with the DBUS_COOKIE_SHA1 auth mechanism for example.
+ *
+ * @param auth the auth conversation
+ * @param context the context
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_auth_set_context (DBusAuth               *auth,
+                        const DBusString       *context)
+{
+  return _dbus_string_replace_len (context, 0, _dbus_string_get_length (context),
+                                   &auth->context, 0, _dbus_string_get_length (context));
+}
+
+/**
+ * Sets whether unix fd passing is potentially on the transport and
+ * hence shall be negotiated.
+ *
+ * @param auth the auth conversation
+ * @param b TRUE when unix fd passing shall be negotiated, otherwise FALSE
+ */
+void
+_dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b)
+{
+  auth->unix_fd_possible = b;
+}
+
+/**
+ * Queries whether unix fd passing was successfully negotiated.
+ *
+ * @param auth the auth conversion
+ * @returns #TRUE when unix fd passing was negotiated.
+ */
+dbus_bool_t
+_dbus_auth_get_unix_fd_negotiated(DBusAuth *auth)
+{
+  return auth->unix_fd_negotiated;
+}
+
+/** @} */
+
+/* tests in dbus-auth-util.c */
diff --git a/dbus/dbus/dbus-auth.h b/dbus/dbus/dbus-auth.h
new file mode 100644
index 0000000..ae3f364
--- /dev/null
+++ b/dbus/dbus/dbus-auth.h
@@ -0,0 +1,83 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-auth.h Authentication
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_AUTH_H
+#define DBUS_AUTH_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-sysdeps.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusAuth DBusAuth;
+
+typedef enum
+{
+  DBUS_AUTH_STATE_WAITING_FOR_INPUT,
+  DBUS_AUTH_STATE_WAITING_FOR_MEMORY,
+  DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND,
+  DBUS_AUTH_STATE_NEED_DISCONNECT,
+  DBUS_AUTH_STATE_AUTHENTICATED
+} DBusAuthState;
+
+DBusAuth*     _dbus_auth_server_new          (const DBusString       *guid);
+DBusAuth*     _dbus_auth_client_new          (void);
+DBusAuth*     _dbus_auth_ref                 (DBusAuth               *auth);
+void          _dbus_auth_unref               (DBusAuth               *auth);
+dbus_bool_t   _dbus_auth_set_mechanisms      (DBusAuth               *auth,
+                                              const char            **mechanisms);
+DBusAuthState _dbus_auth_do_work             (DBusAuth               *auth);
+dbus_bool_t   _dbus_auth_get_bytes_to_send   (DBusAuth               *auth,
+                                              const DBusString      **str);
+void          _dbus_auth_bytes_sent          (DBusAuth               *auth,
+                                              int                     bytes_sent);
+void          _dbus_auth_get_buffer          (DBusAuth               *auth,
+                                              DBusString            **buffer);
+void          _dbus_auth_return_buffer       (DBusAuth               *auth,
+                                              DBusString             *buffer,
+                                              int                     bytes_read);
+void          _dbus_auth_get_unused_bytes    (DBusAuth               *auth,
+                                              const DBusString      **str);
+void          _dbus_auth_delete_unused_bytes (DBusAuth               *auth);
+dbus_bool_t   _dbus_auth_needs_encoding      (DBusAuth               *auth);
+dbus_bool_t   _dbus_auth_encode_data         (DBusAuth               *auth,
+                                              const DBusString       *plaintext,
+                                              DBusString             *encoded);
+dbus_bool_t   _dbus_auth_needs_decoding      (DBusAuth               *auth);
+dbus_bool_t   _dbus_auth_decode_data         (DBusAuth               *auth,
+                                              const DBusString       *encoded,
+                                              DBusString             *plaintext);
+dbus_bool_t   _dbus_auth_set_credentials     (DBusAuth               *auth,
+                                              DBusCredentials        *credentials);
+DBusCredentials* _dbus_auth_get_identity     (DBusAuth               *auth);
+dbus_bool_t   _dbus_auth_set_context         (DBusAuth               *auth,
+                                              const DBusString       *context);
+const char*   _dbus_auth_get_guid_from_server(DBusAuth               *auth);
+
+void          _dbus_auth_set_unix_fd_possible(DBusAuth               *auth, dbus_bool_t b);
+dbus_bool_t   _dbus_auth_get_unix_fd_negotiated(DBusAuth             *auth);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_AUTH_H */
diff --git a/dbus/dbus/dbus-bus.c b/dbus/dbus/dbus-bus.c
new file mode 100644
index 0000000..fadc3a8
--- /dev/null
+++ b/dbus/dbus/dbus-bus.c
@@ -0,0 +1,1590 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-bus.c  Convenience functions for communicating with the bus.
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-bus.h"
+#include "dbus-protocol.h"
+#include "dbus-internals.h"
+#include "dbus-message.h"
+#include "dbus-marshal-validate.h"
+#include "dbus-threads-internal.h"
+#include "dbus-connection-internal.h"
+#include "dbus-string.h"
+
+/**
+ * @defgroup DBusBus Message bus APIs
+ * @ingroup DBus
+ * @brief Functions for communicating with the message bus
+ *
+ * dbus_bus_get() allows all modules and libraries in a given
+ * process to share the same connection to the bus daemon by storing
+ * the connection globally.
+ *
+ * All other functions in this module are just convenience functions;
+ * most of them invoke methods on the bus daemon, by sending method
+ * call messages to #DBUS_SERVICE_DBUS. These convenience functions
+ * often make blocking method calls. If you don't want to block,
+ * you can send the method call messages manually in the same way
+ * you would any other method call message.
+ *
+ * This module is the only one in libdbus that's specific to
+ * communicating with the message bus daemon. The rest of the API can
+ * also be used for connecting to another application directly.
+ * 
+ * @todo right now the default address of the system bus is hardcoded,
+ * so if you change it in the global config file suddenly you have to
+ * set DBUS_SYSTEM_BUS_ADDRESS env variable.  Might be nice if the
+ * client lib somehow read the config file, or if the bus on startup
+ * somehow wrote out its address to a well-known spot, but might also
+ * not be worth it.
+ */
+
+/**
+ * @defgroup DBusBusInternals Message bus APIs internals
+ * @ingroup DBusInternals
+ * @brief Internals of functions for communicating with the message bus
+ *
+ * @{
+ */
+
+/**
+ * Block of message-bus-related data we attach to each
+ * #DBusConnection used with these convenience functions.
+ *
+ */
+typedef struct
+{
+  DBusConnection *connection; /**< Connection we're associated with */
+  char *unique_name; /**< Unique name of this connection */
+
+  unsigned int is_well_known : 1; /**< Is one of the well-known connections in our global array */
+} BusData;
+
+/** The slot we have reserved to store BusData.
+ */
+static dbus_int32_t bus_data_slot = -1;
+
+/** Number of bus types */
+#define N_BUS_TYPES 3
+
+static DBusConnection *bus_connections[N_BUS_TYPES];
+static char *bus_connection_addresses[N_BUS_TYPES] = { NULL, NULL, NULL };
+
+static DBusBusType activation_bus_type = DBUS_BUS_STARTER;
+
+static dbus_bool_t initialized = FALSE;
+
+/**
+ * Lock for globals in this file
+ */
+_DBUS_DEFINE_GLOBAL_LOCK (bus);
+
+/**
+ * Global lock covering all BusData on any connection. The bet is
+ * that some lock contention is better than more memory
+ * for a per-connection lock, but it's tough to imagine it mattering
+ * either way.
+ */
+_DBUS_DEFINE_GLOBAL_LOCK (bus_datas);
+
+static void
+addresses_shutdown_func (void *data)
+{
+  int i;
+
+  i = 0;
+  while (i < N_BUS_TYPES)
+    {
+      if (bus_connections[i] != NULL)
+        _dbus_warn_check_failed ("dbus_shutdown() called but connections were still live. This probably means the application did not drop all its references to bus connections.\n");
+      
+      dbus_free (bus_connection_addresses[i]);
+      bus_connection_addresses[i] = NULL;
+      ++i;
+    }
+
+  activation_bus_type = DBUS_BUS_STARTER;
+
+  initialized = FALSE;
+}
+
+static dbus_bool_t
+get_from_env (char           **connection_p,
+              const char      *env_var)
+{
+  const char *s;
+  
+  _dbus_assert (*connection_p == NULL);
+  
+  s = _dbus_getenv (env_var);
+  if (s == NULL || *s == '\0')
+    return TRUE; /* successfully didn't use the env var */
+  else
+    {
+      *connection_p = _dbus_strdup (s);
+      return *connection_p != NULL;
+    }
+}
+
+static dbus_bool_t
+init_session_address (void)
+{
+  dbus_bool_t retval;
+ 
+  retval = FALSE;
+
+  /* First, look in the environment.  This is the normal case on 
+   * freedesktop.org/Unix systems. */
+  get_from_env (&bus_connection_addresses[DBUS_BUS_SESSION],
+                     "DBUS_SESSION_BUS_ADDRESS");
+  if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
+    {
+      dbus_bool_t supported;
+      DBusString addr;
+      DBusError error = DBUS_ERROR_INIT;
+
+      if (!_dbus_string_init (&addr))
+        return FALSE;
+
+      supported = FALSE;
+      /* So it's not in the environment - let's try a platform-specific method.
+       * On MacOS, this involves asking launchd.  On Windows (not specified yet)
+       * we might do a COM lookup.
+       * Ignore errors - if we failed, fall back to autolaunch. */
+      retval = _dbus_lookup_session_address (&supported, &addr, &error);
+      if (supported && retval)
+        {
+          retval =_dbus_string_steal_data (&addr, &bus_connection_addresses[DBUS_BUS_SESSION]);
+        }
+      else if (supported && !retval)
+        {
+          if (dbus_error_is_set(&error))
+            _dbus_warn ("Dynamic session lookup supported but failed: %s\n", error.message);
+          else
+            _dbus_warn ("Dynamic session lookup supported but failed silently\n");
+        }
+      _dbus_string_free (&addr);
+    }
+  else
+    retval = TRUE;
+
+  if (!retval)
+    return FALSE;
+
+  /* The DBUS_SESSION_BUS_DEFAULT_ADDRESS should have really been named
+   * DBUS_SESSION_BUS_FALLBACK_ADDRESS. 
+   */
+  if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
+    bus_connection_addresses[DBUS_BUS_SESSION] =
+      _dbus_strdup (DBUS_SESSION_BUS_DEFAULT_ADDRESS);
+  if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
+    return FALSE;
+
+  return TRUE;
+}
+
+static dbus_bool_t
+init_connections_unlocked (void)
+{
+  if (!initialized)
+    {
+      const char *s;
+      int i;
+
+      i = 0;
+      while (i < N_BUS_TYPES)
+        {
+          bus_connections[i] = NULL;
+          ++i;
+        }
+
+      /* Don't init these twice, we may run this code twice if
+       * init_connections_unlocked() fails midway through.
+       * In practice, each block below should contain only one
+       * "return FALSE" or running through twice may not
+       * work right.
+       */
+      
+       if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
+         {
+           _dbus_verbose ("Filling in system bus address...\n");
+           
+           if (!get_from_env (&bus_connection_addresses[DBUS_BUS_SYSTEM],
+                              "DBUS_SYSTEM_BUS_ADDRESS"))
+             return FALSE;
+         }
+
+                  
+       if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
+         {
+           /* Use default system bus address if none set in environment */
+           bus_connection_addresses[DBUS_BUS_SYSTEM] =
+             _dbus_strdup (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS);
+
+           if (bus_connection_addresses[DBUS_BUS_SYSTEM] == NULL)
+             return FALSE;
+           
+           _dbus_verbose ("  used default system bus \"%s\"\n",
+                          bus_connection_addresses[DBUS_BUS_SYSTEM]);
+         }
+       else
+         _dbus_verbose ("  used env var system bus \"%s\"\n",
+                        bus_connection_addresses[DBUS_BUS_SYSTEM]);
+          
+      if (bus_connection_addresses[DBUS_BUS_SESSION] == NULL)
+        {
+          _dbus_verbose ("Filling in session bus address...\n");
+          
+          if (!init_session_address ())
+            return FALSE;
+
+          _dbus_verbose ("  \"%s\"\n", bus_connection_addresses[DBUS_BUS_SESSION] ?
+                         bus_connection_addresses[DBUS_BUS_SESSION] : "none set");
+        }
+
+      if (bus_connection_addresses[DBUS_BUS_STARTER] == NULL)
+        {
+          _dbus_verbose ("Filling in activation bus address...\n");
+          
+          if (!get_from_env (&bus_connection_addresses[DBUS_BUS_STARTER],
+                             "DBUS_STARTER_ADDRESS"))
+            return FALSE;
+          
+          _dbus_verbose ("  \"%s\"\n", bus_connection_addresses[DBUS_BUS_STARTER] ?
+                         bus_connection_addresses[DBUS_BUS_STARTER] : "none set");
+        }
+
+
+      if (bus_connection_addresses[DBUS_BUS_STARTER] != NULL)
+        {
+          s = _dbus_getenv ("DBUS_STARTER_BUS_TYPE");
+              
+          if (s != NULL)
+            {
+              _dbus_verbose ("Bus activation type was set to \"%s\"\n", s);
+                  
+              if (strcmp (s, "system") == 0)
+                activation_bus_type = DBUS_BUS_SYSTEM;
+              else if (strcmp (s, "session") == 0)
+                activation_bus_type = DBUS_BUS_SESSION;
+            }
+        }
+      else
+        {
+          /* Default to the session bus instead if available */
+          if (bus_connection_addresses[DBUS_BUS_SESSION] != NULL)
+            {
+              bus_connection_addresses[DBUS_BUS_STARTER] =
+                _dbus_strdup (bus_connection_addresses[DBUS_BUS_SESSION]);
+              if (bus_connection_addresses[DBUS_BUS_STARTER] == NULL)
+                return FALSE;
+            }
+        }
+      
+      /* If we return FALSE we have to be sure that restarting
+       * the above code will work right
+       */
+      
+      if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", NULL))
+        return FALSE;
+
+      if (!_dbus_setenv ("DBUS_ACTIVATION_BUS_TYPE", NULL))
+        return FALSE;
+      
+      if (!_dbus_register_shutdown_func (addresses_shutdown_func,
+                                         NULL))
+        return FALSE;
+      
+      initialized = TRUE;
+    }
+
+  return initialized;
+}
+
+static void
+bus_data_free (void *data)
+{
+  BusData *bd = data;
+  
+  if (bd->is_well_known)
+    {
+      int i;
+      _DBUS_LOCK (bus);
+      /* We may be stored in more than one slot */
+      /* This should now be impossible - these slots are supposed to
+       * be cleared on disconnect, so should not need to be cleared on
+       * finalize
+       */
+      i = 0;
+      while (i < N_BUS_TYPES)
+        {
+          if (bus_connections[i] == bd->connection)
+            bus_connections[i] = NULL;
+          
+          ++i;
+        }
+      _DBUS_UNLOCK (bus);
+    }
+  
+  dbus_free (bd->unique_name);
+  dbus_free (bd);
+
+  dbus_connection_free_data_slot (&bus_data_slot);
+}
+
+static BusData*
+ensure_bus_data (DBusConnection *connection)
+{
+  BusData *bd;
+
+  if (!dbus_connection_allocate_data_slot (&bus_data_slot))
+    return NULL;
+
+  bd = dbus_connection_get_data (connection, bus_data_slot);
+  if (bd == NULL)
+    {      
+      bd = dbus_new0 (BusData, 1);
+      if (bd == NULL)
+        {
+          dbus_connection_free_data_slot (&bus_data_slot);
+          return NULL;
+        }
+
+      bd->connection = connection;
+      
+      if (!dbus_connection_set_data (connection, bus_data_slot, bd,
+                                     bus_data_free))
+        {
+          dbus_free (bd);
+          dbus_connection_free_data_slot (&bus_data_slot);
+          return NULL;
+        }
+
+      /* Data slot refcount now held by the BusData */
+    }
+  else
+    {
+      dbus_connection_free_data_slot (&bus_data_slot);
+    }
+
+  return bd;
+}
+
+/**
+ * Internal function that checks to see if this
+ * is a shared connection owned by the bus and if it is unref it.
+ *
+ * @param connection a connection that has been disconnected.
+ */
+void
+_dbus_bus_notify_shared_connection_disconnected_unlocked (DBusConnection *connection)
+{
+  int i;
+  
+  _DBUS_LOCK (bus);
+
+  /* We are expecting to have the connection saved in only one of these
+   * slots, but someone could in a pathological case set system and session
+   * bus to the same bus or something. Or set one of them to the starter
+   * bus without setting the starter bus type in the env variable.
+   * So we don't break the loop as soon as we find a match.
+   */
+  for (i = 0; i < N_BUS_TYPES; ++i)
+    {
+      if (bus_connections[i] == connection)
+        {
+          bus_connections[i] = NULL;
+        }
+    }
+
+  _DBUS_UNLOCK (bus);
+}
+
+static DBusConnection *
+internal_bus_get (DBusBusType  type,
+                  dbus_bool_t  private,
+                  DBusError   *error)
+{
+  const char *address;
+  DBusConnection *connection;
+  BusData *bd;
+  DBusBusType address_type;
+
+  _dbus_return_val_if_fail (type >= 0 && type < N_BUS_TYPES, NULL);
+  _dbus_return_val_if_error_is_set (error, NULL);
+
+  connection = NULL;
+
+  _DBUS_LOCK (bus);
+
+  if (!init_connections_unlocked ())
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+
+  /* We want to use the activation address even if the
+   * activating bus is the session or system bus,
+   * per the spec.
+   */
+  address_type = type;
+  
+  /* Use the real type of the activation bus for getting its
+   * connection, but only if the real type's address is available. (If
+   * the activating bus isn't a well-known bus then
+   * activation_bus_type == DBUS_BUS_STARTER)
+   */
+  if (type == DBUS_BUS_STARTER &&
+      bus_connection_addresses[activation_bus_type] != NULL)
+    type = activation_bus_type;
+  
+  if (!private && bus_connections[type] != NULL)
+    {
+      connection = bus_connections[type];
+      dbus_connection_ref (connection);
+      goto out;
+    }
+
+  address = bus_connection_addresses[address_type];
+  if (address == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Unable to determine the address of the message bus (try 'man dbus-launch' and 'man dbus-daemon' for help)");
+      goto out;
+    }
+
+  if (private)
+    connection = dbus_connection_open_private (address, error);
+  else
+    connection = dbus_connection_open (address, error);
+  
+  if (!connection)
+    {
+      goto out;
+    }
+
+  if (!dbus_bus_register (connection, error))
+    {
+      _dbus_connection_close_possibly_shared (connection);
+      dbus_connection_unref (connection);
+      connection = NULL;
+      goto out;
+    }
+
+  if (!private)
+    {
+      /* store a weak ref to the connection (dbus-connection.c is
+       * supposed to have a strong ref that it drops on disconnect,
+       * since this is a shared connection)
+       */
+      bus_connections[type] = connection;
+    }
+
+  /* By default we're bound to the lifecycle of
+   * the message bus.
+   */
+  dbus_connection_set_exit_on_disconnect (connection,
+                                          TRUE);
+ 
+  _DBUS_LOCK (bus_datas);
+  bd = ensure_bus_data (connection);
+  _dbus_assert (bd != NULL); /* it should have been created on
+                                register, so OOM not possible */
+  bd->is_well_known = TRUE;
+  _DBUS_UNLOCK (bus_datas);
+
+out:
+  /* Return a reference to the caller, or NULL with error set. */
+  if (connection == NULL)
+    _DBUS_ASSERT_ERROR_IS_SET (error);
+
+  _DBUS_UNLOCK (bus);
+  return connection;
+}
+
+
+/** @} */ /* end of implementation details docs */
+
+/**
+ * @addtogroup DBusBus
+ * @{
+ */
+
+/**
+ * Connects to a bus daemon and registers the client with it.  If a
+ * connection to the bus already exists, then that connection is
+ * returned.  The caller of this function owns a reference to the bus.
+ *
+ * The caller may NOT call dbus_connection_close() on this connection;
+ * see dbus_connection_open() and dbus_connection_close() for details
+ * on that.
+ *
+ * If this function obtains a new connection object never before
+ * returned from dbus_bus_get(), it will call
+ * dbus_connection_set_exit_on_disconnect(), so the application
+ * will exit if the connection closes. You can undo this
+ * by calling dbus_connection_set_exit_on_disconnect() yourself
+ * after you get the connection.
+ *
+ * dbus_bus_get() calls dbus_bus_register() for you.
+ * 
+ * If returning a newly-created connection, this function will block
+ * until authentication and bus registration are complete.
+ * 
+ * @param type bus type
+ * @param error address where an error can be returned.
+ * @returns a #DBusConnection with new ref
+ */
+DBusConnection *
+dbus_bus_get (DBusBusType  type,
+	      DBusError   *error)
+{
+  return internal_bus_get (type, FALSE, error);
+}
+
+/**
+ * Connects to a bus daemon and registers the client with it as with
+ * dbus_bus_register().  Unlike dbus_bus_get(), always creates a new
+ * connection. This connection will not be saved or recycled by
+ * libdbus. Caller owns a reference to the bus and must either close
+ * it or know it to be closed prior to releasing this reference.
+ *
+ * See dbus_connection_open_private() for more details on when to
+ * close and unref this connection.
+ *
+ * This function calls
+ * dbus_connection_set_exit_on_disconnect() on the new connection, so the application
+ * will exit if the connection closes. You can undo this
+ * by calling dbus_connection_set_exit_on_disconnect() yourself
+ * after you get the connection.
+ *
+ * dbus_bus_get_private() calls dbus_bus_register() for you.
+ *
+ * This function will block until authentication and bus registration
+ * are complete.
+ *
+ * @param type bus type
+ * @param error address where an error can be returned.
+ * @returns a DBusConnection with new ref
+ */
+DBusConnection *
+dbus_bus_get_private (DBusBusType  type,
+                      DBusError   *error)
+{
+  return internal_bus_get (type, TRUE, error);
+}
+
+/**
+ * Registers a connection with the bus. This must be the first
+ * thing an application does when connecting to the message bus.
+ * If registration succeeds, the unique name will be set,
+ * and can be obtained using dbus_bus_get_unique_name().
+ *
+ * This function will block until registration is complete.
+ *
+ * If the connection has already registered with the bus
+ * (determined by checking whether dbus_bus_get_unique_name()
+ * returns a non-#NULL value), then this function does nothing.
+ *
+ * If you use dbus_bus_get() or dbus_bus_get_private() this
+ * function will be called for you.
+ * 
+ * @note Just use dbus_bus_get() or dbus_bus_get_private() instead of
+ * dbus_bus_register() and save yourself some pain. Using
+ * dbus_bus_register() manually is only useful if you have your
+ * own custom message bus not found in #DBusBusType.
+ *
+ * If you open a bus connection with dbus_connection_open() or
+ * dbus_connection_open_private() you will have to dbus_bus_register()
+ * yourself, or make the appropriate registration method calls
+ * yourself. If you send the method calls yourself, call
+ * dbus_bus_set_unique_name() with the unique bus name you get from
+ * the bus.
+ *
+ * For shared connections (created with dbus_connection_open()) in a
+ * multithreaded application, you can't really make the registration
+ * calls yourself, because you don't know whether some other thread is
+ * also registering, and the bus will kick you off if you send two
+ * registration messages.
+ *
+ * If you use dbus_bus_register() however, there is a lock that
+ * keeps both apps from registering at the same time.
+ *
+ * The rule in a multithreaded app, then, is that dbus_bus_register()
+ * must be used to register, or you need to have your own locks that
+ * all threads in the app will respect.
+ *
+ * In a single-threaded application you can register by hand instead
+ * of using dbus_bus_register(), as long as you check
+ * dbus_bus_get_unique_name() to see if a unique name has already been
+ * stored by another thread before you send the registration messages.
+ * 
+ * @param connection the connection
+ * @param error place to store errors
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_bus_register (DBusConnection *connection,
+                   DBusError      *error)
+{
+  DBusMessage *message, *reply;
+  char *name;
+  BusData *bd;
+  dbus_bool_t retval;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
+
+  retval = FALSE;
+  message = NULL;
+  reply = NULL;
+
+  _DBUS_LOCK (bus_datas);
+
+  bd = ensure_bus_data (connection);
+  if (bd == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (bd->unique_name != NULL)
+    {
+      _dbus_verbose ("Ignoring attempt to register the same DBusConnection %s with the message bus a second time.\n",
+                     bd->unique_name);
+      /* Success! */
+      retval = TRUE;
+      goto out;
+    }
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "Hello"); 
+
+  if (!message)
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+  
+  reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
+
+  if (reply == NULL)
+    goto out;
+  else if (dbus_set_error_from_message (error, reply))
+    goto out;
+  else if (!dbus_message_get_args (reply, error,
+                                   DBUS_TYPE_STRING, &name,
+                                   DBUS_TYPE_INVALID))
+    goto out;
+  
+  bd->unique_name = _dbus_strdup (name);
+  if (bd->unique_name == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+  
+  retval = TRUE;
+  
+ out:
+  _DBUS_UNLOCK (bus_datas);
+
+  if (message)
+    dbus_message_unref (message);
+
+  if (reply)
+    dbus_message_unref (reply);
+
+  if (!retval)
+    _DBUS_ASSERT_ERROR_IS_SET (error);
+
+  return retval;
+}
+
+
+/**
+ * Sets the unique name of the connection, as assigned by the message
+ * bus.  Can only be used if you registered with the bus manually
+ * (i.e. if you did not call dbus_bus_register()). Can only be called
+ * once per connection.  After the unique name is set, you can get it
+ * with dbus_bus_get_unique_name().
+ *
+ * The only reason to use this function is to re-implement the
+ * equivalent of dbus_bus_register() yourself. One (probably unusual)
+ * reason to do that might be to do the bus registration call
+ * asynchronously instead of synchronously.
+ *
+ * @note Just use dbus_bus_get() or dbus_bus_get_private(), or worst
+ * case dbus_bus_register(), instead of messing with this
+ * function. There's really no point creating pain for yourself by
+ * doing things manually.
+ *
+ * It's hard to use this function safely on shared connections
+ * (created by dbus_connection_open()) in a multithreaded application,
+ * because only one registration attempt can be sent to the bus. If
+ * two threads are both sending the registration message, there is no
+ * mechanism in libdbus itself to avoid sending it twice.
+ *
+ * Thus, you need a way to coordinate which thread sends the
+ * registration attempt; which also means you know which thread
+ * will call dbus_bus_set_unique_name(). If you don't know
+ * about all threads in the app (for example, if some libraries
+ * you're using might start libdbus-using threads), then you
+ * need to avoid using this function on shared connections.
+ *
+ * @param connection the connection
+ * @param unique_name the unique name
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_bus_set_unique_name (DBusConnection *connection,
+                          const char     *unique_name)
+{
+  BusData *bd;
+  dbus_bool_t success = FALSE;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (unique_name != NULL, FALSE);
+
+  _DBUS_LOCK (bus_datas);
+  
+  bd = ensure_bus_data (connection);
+  if (bd == NULL)
+    goto out;
+
+  _dbus_assert (bd->unique_name == NULL);
+  
+  bd->unique_name = _dbus_strdup (unique_name);
+  success = bd->unique_name != NULL;
+
+out:
+  _DBUS_UNLOCK (bus_datas);
+  
+  return success;
+}
+
+/**
+ * Gets the unique name of the connection as assigned by the message
+ * bus. Only possible after the connection has been registered with
+ * the message bus. All connections returned by dbus_bus_get() or
+ * dbus_bus_get_private() have been successfully registered.
+ *
+ * The name remains valid until the connection is freed, and
+ * should not be freed by the caller.
+ *
+ * Other than dbus_bus_get(), there are two ways to set the unique
+ * name; one is dbus_bus_register(), the other is
+ * dbus_bus_set_unique_name().  You are responsible for calling
+ * dbus_bus_set_unique_name() if you register by hand instead of using
+ * dbus_bus_register().
+ * 
+ * @param connection the connection
+ * @returns the unique name or #NULL on error
+ */
+const char*
+dbus_bus_get_unique_name (DBusConnection *connection)
+{
+  BusData *bd;
+  const char *unique_name = NULL;
+
+  _dbus_return_val_if_fail (connection != NULL, NULL);
+
+  _DBUS_LOCK (bus_datas);
+  
+  bd = ensure_bus_data (connection);
+  if (bd == NULL)
+    goto out;
+
+  unique_name = bd->unique_name;
+
+out:
+  _DBUS_UNLOCK (bus_datas);
+
+  return unique_name;
+}
+
+/**
+ * Asks the bus to return the UID the named connection authenticated
+ * as, if any.  Only works on UNIX; only works for connections on the
+ * same machine as the bus. If you are not on the same machine as the
+ * bus, then calling this is probably a bad idea, since the UID will
+ * mean little to your application.
+ *
+ * For the system message bus you're guaranteed to be on the same
+ * machine since it only listens on a UNIX domain socket (at least,
+ * as shipped by default).
+ *
+ * This function only works for connections that authenticated as
+ * a UNIX user, right now that includes all bus connections, but
+ * it's very possible to have connections with no associated UID.
+ * So check for errors and do something sensible if they happen.
+ * 
+ * This function will always return an error on Windows.
+ * 
+ * @param connection the connection
+ * @param name a name owned by the connection
+ * @param error location to store the error
+ * @returns the unix user id, or ((unsigned)-1) if error is set
+ */ 
+unsigned long
+dbus_bus_get_unix_user (DBusConnection *connection,
+                        const char     *name,
+                        DBusError      *error)
+{
+  DBusMessage *message, *reply;
+  dbus_uint32_t uid;
+
+  _dbus_return_val_if_fail (connection != NULL, DBUS_UID_UNSET);
+  _dbus_return_val_if_fail (name != NULL, DBUS_UID_UNSET);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_bus_name (name), DBUS_UID_UNSET);
+  _dbus_return_val_if_error_is_set (error, DBUS_UID_UNSET);
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "GetConnectionUnixUser");
+
+  if (message == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return DBUS_UID_UNSET;
+    }
+ 
+  if (!dbus_message_append_args (message,
+				 DBUS_TYPE_STRING, &name,
+				 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      _DBUS_SET_OOM (error);
+      return DBUS_UID_UNSET;
+    }
+  
+  reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
+                                                     error);
+  
+  dbus_message_unref (message);
+  
+  if (reply == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return DBUS_UID_UNSET;
+    }  
+
+  if (dbus_set_error_from_message (error, reply))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return DBUS_UID_UNSET;
+    }
+  
+  if (!dbus_message_get_args (reply, error,
+                              DBUS_TYPE_UINT32, &uid,
+                              DBUS_TYPE_INVALID))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return DBUS_UID_UNSET;
+    }
+
+  dbus_message_unref (reply);
+  
+  return (unsigned long) uid;
+}
+
+/**
+ * Asks the bus to return its globally unique ID, as described in the
+ * D-Bus specification. For the session bus, this is useful as a way
+ * to uniquely identify each user session. For the system bus,
+ * probably the bus ID is not useful; instead, use the machine ID
+ * since it's accessible without necessarily connecting to the bus and
+ * may be persistent beyond a single bus instance (across reboots for
+ * example). See dbus_get_local_machine_id().
+ *
+ * In addition to an ID for each bus and an ID for each machine, there is
+ * an ID for each address that the bus is listening on; that can
+ * be retrieved with dbus_connection_get_server_id(), though it is
+ * probably not very useful.
+ * 
+ * @param connection the connection
+ * @param error location to store the error
+ * @returns the bus ID or #NULL if error is set
+ */ 
+char*
+dbus_bus_get_id (DBusConnection *connection,
+                 DBusError      *error)
+{
+  DBusMessage *message, *reply;
+  char *id;
+  const char *v_STRING;
+
+  _dbus_return_val_if_fail (connection != NULL, NULL);
+  _dbus_return_val_if_error_is_set (error, NULL);
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "GetId");
+  
+  if (message == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return NULL;
+    }
+  
+  reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
+                                                     error);
+  
+  dbus_message_unref (message);
+  
+  if (reply == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return NULL;
+    }  
+
+  if (dbus_set_error_from_message (error, reply))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return NULL;
+    }
+
+  v_STRING = NULL;
+  if (!dbus_message_get_args (reply, error,
+                              DBUS_TYPE_STRING, &v_STRING,
+                              DBUS_TYPE_INVALID))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return NULL;
+    }
+
+  id = _dbus_strdup (v_STRING); /* may be NULL */
+  
+  dbus_message_unref (reply);
+
+  if (id == NULL)
+    _DBUS_SET_OOM (error);
+
+  /* FIXME it might be nice to cache the ID locally */
+  
+  return id;
+}
+
+/**
+ * Asks the bus to assign the given name to this connection by invoking
+ * the RequestName method on the bus. This method is fully documented
+ * in the D-Bus specification. For quick reference, the flags and
+ * result codes are discussed here, but the specification is the
+ * canonical version of this information.
+ *
+ * First you should know that for each bus name, the bus stores
+ * a queue of connections that would like to own it. Only
+ * one owns it at a time - called the primary owner. If the primary
+ * owner releases the name or disconnects, then the next owner in the
+ * queue atomically takes over.
+ *
+ * So for example if you have an application org.freedesktop.TextEditor
+ * and multiple instances of it can be run, you can have all of them
+ * sitting in the queue. The first one to start up will receive messages
+ * sent to org.freedesktop.TextEditor, but if that one exits another
+ * will become the primary owner and receive messages.
+ *
+ * The queue means you don't need to manually watch for the current owner to
+ * disappear and then request the name again.
+ *
+ * When requesting a name, you can specify several flags.
+ * 
+ * #DBUS_NAME_FLAG_ALLOW_REPLACEMENT and #DBUS_NAME_FLAG_DO_NOT_QUEUE
+ * are properties stored by the bus for this connection with respect to
+ * each requested bus name. These properties are stored even if the
+ * connection is queued and does not become the primary owner.
+ * You can update these flags by calling RequestName again (even if
+ * you already own the name).
+ *
+ * #DBUS_NAME_FLAG_ALLOW_REPLACEMENT means that another requestor of the
+ * name can take it away from you by specifying #DBUS_NAME_FLAG_REPLACE_EXISTING.
+ *
+ * #DBUS_NAME_FLAG_DO_NOT_QUEUE means that if you aren't the primary owner,
+ * you don't want to be queued up - you only care about being the
+ * primary owner.
+ *
+ * Unlike the other two flags, #DBUS_NAME_FLAG_REPLACE_EXISTING is a property
+ * of the individual RequestName call, i.e. the bus does not persistently
+ * associate it with the connection-name pair. If a RequestName call includes
+ * the #DBUS_NAME_FLAG_REPLACE_EXISTING flag, and the current primary
+ * owner has #DBUS_NAME_FLAG_ALLOW_REPLACEMENT set, then the current primary
+ * owner will be kicked off.
+ *
+ * If no flags are given, an application will receive the requested
+ * name only if the name is currently unowned; and it will NOT give
+ * up the name if another application asks to take it over using
+ * #DBUS_NAME_FLAG_REPLACE_EXISTING.
+ *
+ * This function returns a result code. The possible result codes
+ * are as follows.
+ * 
+ * #DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER means that the name had no
+ * existing owner, and the caller is now the primary owner; or that
+ * the name had an owner, and the caller specified
+ * #DBUS_NAME_FLAG_REPLACE_EXISTING, and the current owner
+ * specified #DBUS_NAME_FLAG_ALLOW_REPLACEMENT.
+ *
+ * #DBUS_REQUEST_NAME_REPLY_IN_QUEUE happens only if the caller does NOT
+ * specify #DBUS_NAME_FLAG_DO_NOT_QUEUE and either the current owner
+ * did NOT specify #DBUS_NAME_FLAG_ALLOW_REPLACEMENT or the caller did NOT
+ * specify #DBUS_NAME_FLAG_REPLACE_EXISTING. In this case the caller ends up 
+ * in a queue to own the name after the current owner gives it up.
+ *
+ * #DBUS_REQUEST_NAME_REPLY_EXISTS happens if the name has an owner
+ * already and the caller specifies #DBUS_NAME_FLAG_DO_NOT_QUEUE
+ * and either the current owner has NOT specified 
+ * #DBUS_NAME_FLAG_ALLOW_REPLACEMENT or the caller did NOT specify 
+ * #DBUS_NAME_FLAG_REPLACE_EXISTING.
+ *
+ * #DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER happens if an application
+ * requests a name it already owns. (Re-requesting a name is useful if
+ * you want to change the #DBUS_NAME_FLAG_ALLOW_REPLACEMENT or
+ * #DBUS_NAME_FLAG_DO_NOT_QUEUE settings.)
+ *
+ * When a service represents an application, say "text editor," then
+ * it should specify #DBUS_NAME_FLAG_ALLOW_REPLACEMENT if it wants
+ * the last editor started to be the user's editor vs. the first one
+ * started.  Then any editor that can be the user's editor should
+ * specify #DBUS_NAME_FLAG_REPLACE_EXISTING to either take over
+ * (last-started-wins) or be queued up (first-started-wins) according
+ * to whether #DBUS_NAME_FLAG_ALLOW_REPLACEMENT was given.
+ *
+ * Conventionally, single-instance applications often offer a command
+ * line option called --replace which means to replace the current
+ * instance.  To implement this, always set
+ * #DBUS_NAME_FLAG_ALLOW_REPLACEMENT when you request your
+ * application's bus name.  When you lose ownership of your bus name,
+ * you need to exit.  Look for the signal "NameLost" from
+ * #DBUS_SERVICE_DBUS and #DBUS_INTERFACE_DBUS (the signal's first
+ * argument is the bus name that was lost).  If starting up without
+ * --replace, do not specify #DBUS_NAME_FLAG_REPLACE_EXISTING, and
+ * exit if you fail to become the bus name owner. If --replace is
+ * given, ask to replace the old owner.
+ *
+ * @param connection the connection
+ * @param name the name to request
+ * @param flags flags
+ * @param error location to store the error
+ * @returns a result code, -1 if error is set
+ */ 
+int
+dbus_bus_request_name (DBusConnection *connection,
+                       const char     *name,
+                       unsigned int    flags,
+                       DBusError      *error)
+{
+  DBusMessage *message, *reply;
+  dbus_uint32_t result;
+
+  _dbus_return_val_if_fail (connection != NULL, 0);
+  _dbus_return_val_if_fail (name != NULL, 0);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_bus_name (name), 0);
+  _dbus_return_val_if_error_is_set (error, 0);
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "RequestName");
+
+  if (message == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return -1;
+    }
+ 
+  if (!dbus_message_append_args (message,
+				 DBUS_TYPE_STRING, &name,
+				 DBUS_TYPE_UINT32, &flags,
+				 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      _DBUS_SET_OOM (error);
+      return -1;
+    }
+  
+  reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
+                                                     error);
+  
+  dbus_message_unref (message);
+  
+  if (reply == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return -1;
+    }  
+
+  if (dbus_set_error_from_message (error, reply))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return -1;
+    }
+  
+  if (!dbus_message_get_args (reply, error,
+                              DBUS_TYPE_UINT32, &result,
+                              DBUS_TYPE_INVALID))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return -1;
+    }
+
+  dbus_message_unref (reply);
+  
+  return result;
+}
+
+
+/**
+ * Asks the bus to unassign the given name from this connection by
+ * invoking the ReleaseName method on the bus. The "ReleaseName"
+ * method is canonically documented in the D-Bus specification.
+ *
+ * Possible results are: #DBUS_RELEASE_NAME_REPLY_RELEASED
+ * which means you owned the name or were in the queue to own it,
+ * and and now you don't own it and aren't in the queue.
+ * #DBUS_RELEASE_NAME_REPLY_NOT_OWNER which means someone else
+ * owns the name so you can't release it.
+ * #DBUS_RELEASE_NAME_REPLY_NON_EXISTENT
+ * which means nobody owned the name.
+ * 
+ * @param connection the connection
+ * @param name the name to remove 
+ * @param error location to store the error
+ * @returns a result code, -1 if error is set
+ */ 
+int
+dbus_bus_release_name (DBusConnection *connection,
+                       const char     *name,
+                       DBusError      *error)
+{
+  DBusMessage *message, *reply;
+  dbus_uint32_t result;
+
+  _dbus_return_val_if_fail (connection != NULL, 0);
+  _dbus_return_val_if_fail (name != NULL, 0);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_bus_name (name), 0);
+  _dbus_return_val_if_error_is_set (error, 0);
+
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "ReleaseName");
+
+  if (message == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return -1;
+    }
+
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &name,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      _DBUS_SET_OOM (error);
+      return -1;
+    }
+
+  reply = dbus_connection_send_with_reply_and_block (connection, message, -1,
+                                                     error);
+
+  dbus_message_unref (message);
+
+  if (reply == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return -1;
+    }
+
+  if (dbus_set_error_from_message (error, reply))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return -1;
+    }
+
+  if (!dbus_message_get_args (reply, error,
+                              DBUS_TYPE_UINT32, &result,
+                              DBUS_TYPE_INVALID))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return -1;
+    }
+
+  dbus_message_unref (reply);
+
+  return result;
+}
+
+/**
+ * Asks the bus whether a certain name has an owner.
+ *
+ * Using this can easily result in a race condition,
+ * since an owner can appear or disappear after you
+ * call this.
+ *
+ * If you want to request a name, just request it;
+ * if you want to avoid replacing a current owner,
+ * don't specify #DBUS_NAME_FLAG_REPLACE_EXISTING and
+ * you will get an error if there's already an owner.
+ * 
+ * @param connection the connection
+ * @param name the name
+ * @param error location to store any errors
+ * @returns #TRUE if the name exists, #FALSE if not or on error
+ */
+dbus_bool_t
+dbus_bus_name_has_owner (DBusConnection *connection,
+			 const char     *name,
+                         DBusError      *error)
+{
+  DBusMessage *message, *reply;
+  dbus_bool_t exists;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (name != NULL, FALSE);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_bus_name (name), FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "NameHasOwner");
+  if (message == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!dbus_message_append_args (message,
+				 DBUS_TYPE_STRING, &name,
+				 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
+  dbus_message_unref (message);
+
+  if (reply == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return FALSE;
+    }
+
+  if (!dbus_message_get_args (reply, error,
+                              DBUS_TYPE_BOOLEAN, &exists,
+                              DBUS_TYPE_INVALID))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return FALSE;
+    }
+  
+  dbus_message_unref (reply);
+  return exists;
+}
+
+/**
+ * Starts a service that will request ownership of the given name.
+ * The returned result will be one of be one of
+ * #DBUS_START_REPLY_SUCCESS or #DBUS_START_REPLY_ALREADY_RUNNING if
+ * successful.  Pass #NULL if you don't care about the result.
+ * 
+ * The flags parameter is for future expansion, currently you should
+ * specify 0.
+ *
+ * It's often easier to avoid explicitly starting services, and
+ * just send a method call to the service's bus name instead.
+ * Method calls start a service to handle them by default
+ * unless you call dbus_message_set_auto_start() to disable this
+ * behavior.
+ * 
+ * @param connection the connection
+ * @param name the name we want the new service to request
+ * @param flags the flags (should always be 0 for now)
+ * @param result a place to store the result or #NULL
+ * @param error location to store any errors
+ * @returns #TRUE if the activation succeeded, #FALSE if not
+ */
+dbus_bool_t
+dbus_bus_start_service_by_name (DBusConnection *connection,
+                                const char     *name,
+                                dbus_uint32_t   flags,
+                                dbus_uint32_t  *result,
+                                DBusError      *error)
+{
+  DBusMessage *msg;
+  DBusMessage *reply;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_bus_name (name), FALSE);
+  
+  msg = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                      DBUS_PATH_DBUS,
+                                      DBUS_INTERFACE_DBUS,
+                                      "StartServiceByName");
+
+  if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, &name,
+			  	 DBUS_TYPE_UINT32, &flags, DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (msg);
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  reply = dbus_connection_send_with_reply_and_block (connection, msg,
+                                                     -1, error);
+  dbus_message_unref (msg);
+
+  if (reply == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return FALSE;
+    }
+
+  if (dbus_set_error_from_message (error, reply))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return FALSE;
+    }
+
+  if (result != NULL &&
+      !dbus_message_get_args (reply, error, DBUS_TYPE_UINT32,
+	      		      result, DBUS_TYPE_INVALID))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      dbus_message_unref (reply);
+      return FALSE;
+    }
+  
+  dbus_message_unref (reply);
+  return TRUE;
+}
+
+static void
+send_no_return_values (DBusConnection *connection,
+                       DBusMessage    *msg,
+                       DBusError      *error)
+{
+  if (error)
+    {
+      /* Block to check success codepath */
+      DBusMessage *reply;
+      
+      reply = dbus_connection_send_with_reply_and_block (connection, msg,
+                                                         -1, error);
+      
+      if (reply == NULL)
+        _DBUS_ASSERT_ERROR_IS_SET (error);
+      else
+        dbus_message_unref (reply);
+    }
+  else
+    {
+      /* Silently-fail nonblocking codepath */
+      dbus_message_set_no_reply (msg, TRUE);
+      dbus_connection_send (connection, msg, NULL);
+    }
+}
+
+/**
+ * Adds a match rule to match messages going through the message bus.
+ * The "rule" argument is the string form of a match rule.
+ *
+ * If you pass #NULL for the error, this function will not
+ * block; the match thus won't be added until you flush the
+ * connection, and if there's an error adding the match
+ * you won't find out about it. This is generally acceptable, since the
+ * possible errors (including a lack of resources in the bus, the connection
+ * having exceeded its quota of active match rules, or the match rule being
+ * unparseable) are generally unrecoverable.
+ *
+ * If you pass non-#NULL for the error this function will
+ * block until it gets a reply. This may be useful when using match rule keys
+ * introduced in recent versions of D-Bus, like 'arg0namespace', to allow the
+ * application to fall back to less efficient match rules supported by older
+ * versions of the daemon if the running version is not new enough; or when
+ * using user-supplied rules rather than rules hard-coded at compile time.
+ *
+ * Normal API conventions would have the function return
+ * a boolean value indicating whether the error was set,
+ * but that would require blocking always to determine
+ * the return value.
+ *
+ * The AddMatch method is fully documented in the D-Bus 
+ * specification. For quick reference, the format of the 
+ * match rules is discussed here, but the specification 
+ * is the canonical version of this information.
+ *
+ * Rules are specified as a string of comma separated 
+ * key/value pairs. An example is 
+ * "type='signal',sender='org.freedesktop.DBus',
+ * interface='org.freedesktop.DBus',member='Foo',
+ * path='/bar/foo',destination=':452345.34'"
+ *
+ * Possible keys you can match on are type, sender, 
+ * interface, member, path, destination and numbered
+ * keys to match message args (keys are 'arg0', 'arg1', etc.).
+ * Omitting a key from the rule indicates 
+ * a wildcard match.  For instance omitting
+ * the member from a match rule but adding a sender would
+ * let all messages from that sender through regardless of
+ * the member.
+ *
+ * Matches are inclusive not exclusive so as long as one 
+ * rule matches the message will get through.  It is important
+ * to note this because every time a message is received the 
+ * application will be paged into memory to process it.  This
+ * can cause performance problems such as draining batteries
+ * on embedded platforms.
+ *
+ * If you match message args ('arg0', 'arg1', and so forth)
+ * only string arguments will match. That is, arg0='5' means
+ * match the string "5" not the integer 5.
+ *
+ * Currently there is no way to match against non-string arguments.
+ *
+ * A specialised form of wildcard matching on arguments is
+ * supported for path-like namespaces.  If your argument match has
+ * a 'path' suffix (eg: "arg0path='/some/path/'") then it is
+ * considered a match if the argument exactly matches the given
+ * string or if one of them ends in a '/' and is a prefix of the
+ * other.
+ *
+ * Matching on interface is tricky because method call
+ * messages only optionally specify the interface.
+ * If a message omits the interface, then it will NOT match
+ * if the rule specifies an interface name. This means match
+ * rules on method calls should not usually give an interface.
+ *
+ * However, signal messages are required to include the interface
+ * so when matching signals usually you should specify the interface
+ * in the match rule.
+ * 
+ * For security reasons, you can match arguments only up to
+ * #DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER.
+ *
+ * Match rules have a maximum length of #DBUS_MAXIMUM_MATCH_RULE_LENGTH
+ * bytes.
+ *
+ * Both of these maximums are much higher than you're likely to need,
+ * they only exist because the D-Bus bus daemon has fixed limits on
+ * all resource usage.
+ *
+ * @param connection connection to the message bus
+ * @param rule textual form of match rule
+ * @param error location to store any errors
+ */
+void
+dbus_bus_add_match (DBusConnection *connection,
+                    const char     *rule,
+                    DBusError      *error)
+{
+  DBusMessage *msg;
+
+  _dbus_return_if_fail (rule != NULL);
+
+  msg = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                      DBUS_PATH_DBUS,
+                                      DBUS_INTERFACE_DBUS,
+                                      "AddMatch");
+
+  if (msg == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return;
+    }
+
+  if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, &rule,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (msg);
+      _DBUS_SET_OOM (error);
+      return;
+    }
+
+  send_no_return_values (connection, msg, error);
+
+  dbus_message_unref (msg);
+}
+
+/**
+ * Removes a previously-added match rule "by value" (the most
+ * recently-added identical rule gets removed).  The "rule" argument
+ * is the string form of a match rule.
+ *
+ * The bus compares match rules semantically, not textually, so
+ * whitespace and ordering don't have to be identical to
+ * the rule you passed to dbus_bus_add_match().
+ * 
+ * If you pass #NULL for the error, this function will not
+ * block; otherwise it will. See detailed explanation in
+ * docs for dbus_bus_add_match().
+ * 
+ * @param connection connection to the message bus
+ * @param rule textual form of match rule
+ * @param error location to store any errors
+ */
+void
+dbus_bus_remove_match (DBusConnection *connection,
+                       const char     *rule,
+                       DBusError      *error)
+{
+  DBusMessage *msg;
+
+  _dbus_return_if_fail (rule != NULL);
+  
+  msg = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                      DBUS_PATH_DBUS,
+                                      DBUS_INTERFACE_DBUS,
+                                      "RemoveMatch");
+
+  if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, &rule,
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (msg);
+      _DBUS_SET_OOM (error);
+      return;
+    }
+
+  send_no_return_values (connection, msg, error);
+
+  dbus_message_unref (msg);
+}
+
+/** @} */
diff --git a/dbus/dbus/dbus-bus.h b/dbus/dbus/dbus-bus.h
new file mode 100644
index 0000000..02a9571
--- /dev/null
+++ b/dbus/dbus/dbus-bus.h
@@ -0,0 +1,95 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-bus.h  Convenience functions for communicating with the bus.
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_BUS_H
+#define DBUS_BUS_H
+
+#include <dbus/dbus-connection.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusBus
+ * @{
+ */
+
+DBUS_EXPORT
+DBusConnection *dbus_bus_get              (DBusBusType     type,
+					   DBusError      *error);
+DBUS_EXPORT
+DBusConnection *dbus_bus_get_private      (DBusBusType     type,
+					   DBusError      *error);
+
+DBUS_EXPORT
+dbus_bool_t     dbus_bus_register         (DBusConnection *connection,
+					   DBusError      *error);
+DBUS_EXPORT
+dbus_bool_t     dbus_bus_set_unique_name  (DBusConnection *connection,
+					   const char     *unique_name);
+DBUS_EXPORT
+const char*     dbus_bus_get_unique_name  (DBusConnection *connection);
+DBUS_EXPORT
+unsigned long   dbus_bus_get_unix_user    (DBusConnection *connection,
+			                   const char     *name,
+                                           DBusError      *error);
+DBUS_EXPORT
+char*           dbus_bus_get_id           (DBusConnection *connection,
+                                           DBusError      *error);
+DBUS_EXPORT
+int             dbus_bus_request_name     (DBusConnection *connection,
+					   const char     *name,
+					   unsigned int    flags,
+					   DBusError      *error);
+DBUS_EXPORT
+int             dbus_bus_release_name     (DBusConnection *connection,
+					   const char     *name,
+					   DBusError      *error);
+DBUS_EXPORT
+dbus_bool_t     dbus_bus_name_has_owner   (DBusConnection *connection,
+					   const char     *name,
+					   DBusError      *error);
+
+DBUS_EXPORT
+dbus_bool_t     dbus_bus_start_service_by_name (DBusConnection *connection,
+                                                const char     *name,
+                                                dbus_uint32_t   flags,
+                                                dbus_uint32_t  *reply,
+                                                DBusError      *error);
+
+DBUS_EXPORT
+void            dbus_bus_add_match        (DBusConnection *connection,
+                                           const char     *rule,
+                                           DBusError      *error);
+DBUS_EXPORT
+void            dbus_bus_remove_match     (DBusConnection *connection,
+                                           const char     *rule,
+                                           DBusError      *error);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_BUS_H */
diff --git a/dbus/dbus/dbus-connection-internal.h b/dbus/dbus/dbus-connection-internal.h
new file mode 100644
index 0000000..3d37f18
--- /dev/null
+++ b/dbus/dbus/dbus-connection-internal.h
@@ -0,0 +1,136 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-connection-internal.h DBusConnection internal interfaces
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_CONNECTION_INTERNAL_H
+#define DBUS_CONNECTION_INTERNAL_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-connection.h>
+#include <dbus/dbus-message.h>
+#include <dbus/dbus-transport.h>
+#include <dbus/dbus-resources.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-timeout.h>
+#include <dbus/dbus-dataslot.h>
+
+DBUS_BEGIN_DECLS
+
+typedef enum
+{
+  DBUS_ITERATION_DO_WRITING = 1 << 0, /**< Write messages out. */
+  DBUS_ITERATION_DO_READING = 1 << 1, /**< Read messages in. */
+  DBUS_ITERATION_BLOCK      = 1 << 2  /**< Block if nothing to do. */
+} DBusIterationFlags;
+
+/** default timeout value when waiting for a message reply, 25 seconds */
+#define _DBUS_DEFAULT_TIMEOUT_VALUE (25 * 1000)
+
+void              _dbus_connection_lock                        (DBusConnection     *connection);
+void              _dbus_connection_unlock                      (DBusConnection     *connection);
+DBusConnection *  _dbus_connection_ref_unlocked                (DBusConnection     *connection);
+void              _dbus_connection_unref_unlocked              (DBusConnection     *connection);
+void              _dbus_connection_queue_received_message_link (DBusConnection     *connection,
+                                                                DBusList           *link);
+dbus_bool_t       _dbus_connection_has_messages_to_send_unlocked (DBusConnection     *connection);
+DBusMessage*      _dbus_connection_get_message_to_send         (DBusConnection     *connection);
+void              _dbus_connection_message_sent_unlocked       (DBusConnection     *connection,
+                                                                DBusMessage        *message);
+dbus_bool_t       _dbus_connection_add_watch_unlocked          (DBusConnection     *connection,
+                                                                DBusWatch          *watch);
+void              _dbus_connection_remove_watch_unlocked       (DBusConnection     *connection,
+                                                                DBusWatch          *watch);
+void              _dbus_connection_toggle_watch_unlocked       (DBusConnection     *connection,
+                                                                DBusWatch          *watch,
+                                                                dbus_bool_t         enabled);
+dbus_bool_t       _dbus_connection_handle_watch                (DBusWatch          *watch,
+                                                                unsigned int        condition,
+                                                                void               *data);
+dbus_bool_t       _dbus_connection_add_timeout_unlocked        (DBusConnection     *connection,
+                                                                DBusTimeout        *timeout);
+void              _dbus_connection_remove_timeout_unlocked     (DBusConnection     *connection,
+                                                                DBusTimeout        *timeout);
+void              _dbus_connection_toggle_timeout_unlocked     (DBusConnection     *connection,
+                                                                DBusTimeout        *timeout,
+                                                                dbus_bool_t         enabled);
+DBusConnection*   _dbus_connection_new_for_transport           (DBusTransport      *transport);
+void              _dbus_connection_do_iteration_unlocked       (DBusConnection     *connection,
+                                                                DBusPendingCall    *pending,
+                                                                unsigned int        flags,
+                                                                int                 timeout_milliseconds);
+void              _dbus_connection_close_possibly_shared       (DBusConnection     *connection);
+void              _dbus_connection_close_if_only_one_ref       (DBusConnection     *connection);
+
+DBusPendingCall*  _dbus_pending_call_new                       (DBusConnection     *connection,
+                                                                int                 timeout_milliseconds,
+                                                                DBusTimeoutHandler  timeout_handler);
+void              _dbus_pending_call_notify                    (DBusPendingCall    *pending);
+void              _dbus_connection_remove_pending_call         (DBusConnection     *connection,
+                                                                DBusPendingCall    *pending);
+void              _dbus_connection_block_pending_call          (DBusPendingCall    *pending);
+void              _dbus_pending_call_complete_and_unlock       (DBusPendingCall    *pending,
+                                                                DBusMessage        *message);
+dbus_bool_t       _dbus_connection_send_and_unlock             (DBusConnection     *connection,
+                                                                DBusMessage        *message,
+                                                                dbus_uint32_t      *client_serial);
+
+void              _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
+						                   DBusList *link);
+void              _dbus_connection_test_get_locks                 (DBusConnection *conn,
+                                                                   DBusMutex **mutex_loc,
+                                                                   DBusMutex **dispatch_mutex_loc,
+                                                                   DBusMutex **io_path_mutex_loc,
+                                                                   DBusCondVar **dispatch_cond_loc,
+                                                                   DBusCondVar **io_path_cond_loc);
+
+/* if DBUS_ENABLE_STATS */
+void _dbus_connection_get_stats (DBusConnection *connection,
+                                 dbus_uint32_t  *in_messages,
+                                 dbus_uint32_t  *in_bytes,
+                                 dbus_uint32_t  *in_fds,
+                                 dbus_uint32_t  *in_peak_bytes,
+                                 dbus_uint32_t  *in_peak_fds,
+                                 dbus_uint32_t  *out_messages,
+                                 dbus_uint32_t  *out_bytes,
+                                 dbus_uint32_t  *out_fds,
+                                 dbus_uint32_t  *out_peak_bytes,
+                                 dbus_uint32_t  *out_peak_fds);
+
+
+/* if DBUS_BUILD_TESTS */
+const char* _dbus_connection_get_address (DBusConnection *connection);
+
+/* This _dbus_bus_* stuff doesn't really belong here, but dbus-bus-internal.h seems
+ * silly for one function
+ */
+/**
+ * @addtogroup DBusBusInternals
+ * @{
+ */
+
+void           _dbus_bus_notify_shared_connection_disconnected_unlocked (DBusConnection *connection);
+
+/** @} */
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_CONNECTION_INTERNAL_H */
diff --git a/dbus/dbus/dbus-connection.c b/dbus/dbus/dbus-connection.c
new file mode 100644
index 0000000..0362288
--- /dev/null
+++ b/dbus/dbus/dbus-connection.c
@@ -0,0 +1,6281 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-connection.c DBusConnection object
+ *
+ * Copyright (C) 2002-2006  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include <signal.h>
+#include "dbus-shared.h"
+#include "dbus-connection.h"
+#include "dbus-list.h"
+#include "dbus-timeout.h"
+#include "dbus-transport.h"
+#include "dbus-watch.h"
+#include "dbus-connection-internal.h"
+#include "dbus-pending-call-internal.h"
+#include "dbus-list.h"
+#include "dbus-hash.h"
+#include "dbus-message-internal.h"
+#include "dbus-message-private.h"
+#include "dbus-threads.h"
+#include "dbus-protocol.h"
+#include "dbus-dataslot.h"
+#include "dbus-string.h"
+#include "dbus-signature.h"
+#include "dbus-pending-call.h"
+#include "dbus-object-tree.h"
+#include "dbus-threads-internal.h"
+#include "dbus-bus.h"
+#include "dbus-marshal-basic.h"
+
+#ifdef DBUS_DISABLE_CHECKS
+#define TOOK_LOCK_CHECK(connection)
+#define RELEASING_LOCK_CHECK(connection)
+#define HAVE_LOCK_CHECK(connection)
+#else
+#define TOOK_LOCK_CHECK(connection) do {                \
+    _dbus_assert (!(connection)->have_connection_lock); \
+    (connection)->have_connection_lock = TRUE;          \
+  } while (0)
+#define RELEASING_LOCK_CHECK(connection) do {            \
+    _dbus_assert ((connection)->have_connection_lock);   \
+    (connection)->have_connection_lock = FALSE;          \
+  } while (0)
+#define HAVE_LOCK_CHECK(connection)        _dbus_assert ((connection)->have_connection_lock)
+/* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
+#endif
+
+#define TRACE_LOCKS 0
+
+#define CONNECTION_LOCK(connection)   do {                                      \
+    if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); }   \
+    _dbus_rmutex_lock ((connection)->mutex);                                    \
+    TOOK_LOCK_CHECK (connection);                                               \
+  } while (0)
+
+#define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection)
+
+#define SLOTS_LOCK(connection) do {                     \
+    _dbus_rmutex_lock ((connection)->slot_mutex);       \
+  } while (0)
+
+#define SLOTS_UNLOCK(connection) do {                   \
+    _dbus_rmutex_unlock ((connection)->slot_mutex);     \
+  } while (0)
+
+#define DISPATCH_STATUS_NAME(s)                                            \
+                     ((s) == DBUS_DISPATCH_COMPLETE ? "complete" :         \
+                      (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
+                      (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :   \
+                      "???")
+
+/**
+ * @defgroup DBusConnection DBusConnection
+ * @ingroup  DBus
+ * @brief Connection to another application
+ *
+ * A DBusConnection represents a connection to another
+ * application. Messages can be sent and received via this connection.
+ * The other application may be a message bus; for convenience, the
+ * function dbus_bus_get() is provided to automatically open a
+ * connection to the well-known message buses.
+ * 
+ * In brief a DBusConnection is a message queue associated with some
+ * message transport mechanism such as a socket.  The connection
+ * maintains a queue of incoming messages and a queue of outgoing
+ * messages.
+ *
+ * Several functions use the following terms:
+ * <ul>
+ * <li><b>read</b> means to fill the incoming message queue by reading from the socket</li>
+ * <li><b>write</b> means to drain the outgoing queue by writing to the socket</li>
+ * <li><b>dispatch</b> means to drain the incoming queue by invoking application-provided message handlers</li>
+ * </ul>
+ *
+ * The function dbus_connection_read_write_dispatch() for example does all
+ * three of these things, offering a simple alternative to a main loop.
+ *
+ * In an application with a main loop, the read/write/dispatch
+ * operations are usually separate.
+ *
+ * The connection provides #DBusWatch and #DBusTimeout objects to
+ * the main loop. These are used to know when reading, writing, or
+ * dispatching should be performed.
+ * 
+ * Incoming messages are processed
+ * by calling dbus_connection_dispatch(). dbus_connection_dispatch()
+ * runs any handlers registered for the topmost message in the message
+ * queue, then discards the message, then returns.
+ * 
+ * dbus_connection_get_dispatch_status() indicates whether
+ * messages are currently in the queue that need dispatching.
+ * dbus_connection_set_dispatch_status_function() allows
+ * you to set a function to be used to monitor the dispatch status.
+ * 
+ * If you're using GLib or Qt add-on libraries for D-Bus, there are
+ * special convenience APIs in those libraries that hide
+ * all the details of dispatch and watch/timeout monitoring.
+ * For example, dbus_connection_setup_with_g_main().
+ *
+ * If you aren't using these add-on libraries, but want to process
+ * messages asynchronously, you must manually call
+ * dbus_connection_set_dispatch_status_function(),
+ * dbus_connection_set_watch_functions(),
+ * dbus_connection_set_timeout_functions() providing appropriate
+ * functions to integrate the connection with your application's main
+ * loop. This can be tricky to get right; main loops are not simple.
+ *
+ * If you don't need to be asynchronous, you can ignore #DBusWatch,
+ * #DBusTimeout, and dbus_connection_dispatch().  Instead,
+ * dbus_connection_read_write_dispatch() can be used.
+ *
+ * Or, in <em>very</em> simple applications,
+ * dbus_connection_pop_message() may be all you need, allowing you to
+ * avoid setting up any handler functions (see
+ * dbus_connection_add_filter(),
+ * dbus_connection_register_object_path() for more on handlers).
+ * 
+ * When you use dbus_connection_send() or one of its variants to send
+ * a message, the message is added to the outgoing queue.  It's
+ * actually written to the network later; either in
+ * dbus_watch_handle() invoked by your main loop, or in
+ * dbus_connection_flush() which blocks until it can write out the
+ * entire outgoing queue. The GLib/Qt add-on libraries again
+ * handle the details here for you by setting up watch functions.
+ *
+ * When a connection is disconnected, you are guaranteed to get a
+ * signal "Disconnected" from the interface
+ * #DBUS_INTERFACE_LOCAL, path
+ * #DBUS_PATH_LOCAL.
+ *
+ * You may not drop the last reference to a #DBusConnection
+ * until that connection has been disconnected.
+ *
+ * You may dispatch the unprocessed incoming message queue even if the
+ * connection is disconnected. However, "Disconnected" will always be
+ * the last message in the queue (obviously no messages are received
+ * after disconnection).
+ *
+ * After calling dbus_threads_init(), #DBusConnection has thread
+ * locks and drops them when invoking user callbacks, so in general is
+ * transparently threadsafe. However, #DBusMessage does NOT have
+ * thread locks; you must not send the same message to multiple
+ * #DBusConnection if those connections will be used from different threads,
+ * for example.
+ *
+ * Also, if you dispatch or pop messages from multiple threads, it
+ * may work in the sense that it won't crash, but it's tough to imagine
+ * sane results; it will be completely unpredictable which messages
+ * go to which threads.
+ *
+ * It's recommended to dispatch from a single thread.
+ *
+ * The most useful function to call from multiple threads at once
+ * is dbus_connection_send_with_reply_and_block(). That is,
+ * multiple threads can make method calls at the same time.
+ *
+ * If you aren't using threads, you can use a main loop and
+ * dbus_pending_call_set_notify() to achieve a similar result.
+ */
+
+/**
+ * @defgroup DBusConnectionInternals DBusConnection implementation details
+ * @ingroup  DBusInternals
+ * @brief Implementation details of DBusConnection
+ *
+ * @{
+ */
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+static void
+_dbus_connection_trace_ref (DBusConnection *connection,
+    int old_refcount,
+    int new_refcount,
+    const char *why)
+{
+  static int enabled = -1;
+
+  _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount,
+      why, "DBUS_CONNECTION_TRACE", &enabled);
+}
+#else
+#define _dbus_connection_trace_ref(c,o,n,w) \
+  do \
+  {\
+    (void) (o); \
+    (void) (n); \
+  } while (0)
+#endif
+
+/**
+ * Internal struct representing a message filter function 
+ */
+typedef struct DBusMessageFilter DBusMessageFilter;
+
+/**
+ * Internal struct representing a message filter function 
+ */
+struct DBusMessageFilter
+{
+  DBusAtomic refcount; /**< Reference count */
+  DBusHandleMessageFunction function; /**< Function to call to filter */
+  void *user_data; /**< User data for the function */
+  DBusFreeFunction free_user_data_function; /**< Function to free the user data */
+};
+
+
+/**
+ * Internals of DBusPreallocatedSend
+ */
+struct DBusPreallocatedSend
+{
+  DBusConnection *connection; /**< Connection we'd send the message to */
+  DBusList *queue_link;       /**< Preallocated link in the queue */
+  DBusList *counter_link;     /**< Preallocated link in the resource counter */
+};
+
+#if HAVE_DECL_MSG_NOSIGNAL
+static dbus_bool_t _dbus_modify_sigpipe = FALSE;
+#else
+static dbus_bool_t _dbus_modify_sigpipe = TRUE;
+#endif
+
+/**
+ * Implementation details of DBusConnection. All fields are private.
+ */
+struct DBusConnection
+{
+  DBusAtomic refcount; /**< Reference count. */
+
+  DBusRMutex *mutex; /**< Lock on the entire DBusConnection */
+
+  DBusCMutex *dispatch_mutex;     /**< Protects dispatch_acquired */
+  DBusCondVar *dispatch_cond;    /**< Notify when dispatch_acquired is available */
+  DBusCMutex *io_path_mutex;      /**< Protects io_path_acquired */
+  DBusCondVar *io_path_cond;     /**< Notify when io_path_acquired is available */
+  
+  DBusList *outgoing_messages; /**< Queue of messages we need to send, send the end of the list first. */
+  DBusList *incoming_messages; /**< Queue of messages we have received, end of the list received most recently. */
+  DBusList *expired_messages;  /**< Messages that will be released when we next unlock. */
+
+  DBusMessage *message_borrowed; /**< Filled in if the first incoming message has been borrowed;
+                                  *   dispatch_acquired will be set by the borrower
+                                  */
+  
+  int n_outgoing;              /**< Length of outgoing queue. */
+  int n_incoming;              /**< Length of incoming queue. */
+
+  DBusCounter *outgoing_counter; /**< Counts size of outgoing messages. */
+  
+  DBusTransport *transport;    /**< Object that sends/receives messages over network. */
+  DBusWatchList *watches;      /**< Stores active watches. */
+  DBusTimeoutList *timeouts;   /**< Stores active timeouts. */
+  
+  DBusList *filter_list;        /**< List of filters. */
+
+  DBusRMutex *slot_mutex;        /**< Lock on slot_list so overall connection lock need not be taken */
+  DBusDataSlotList slot_list;   /**< Data stored by allocated integer ID */
+
+  DBusHashTable *pending_replies;  /**< Hash of message serials to #DBusPendingCall. */  
+  
+  dbus_uint32_t client_serial;       /**< Client serial. Increments each time a message is sent  */
+  DBusList *disconnect_message_link; /**< Preallocated list node for queueing the disconnection message */
+
+  DBusWakeupMainFunction wakeup_main_function; /**< Function to wake up the mainloop  */
+  void *wakeup_main_data; /**< Application data for wakeup_main_function */
+  DBusFreeFunction free_wakeup_main_data; /**< free wakeup_main_data */
+
+  DBusDispatchStatusFunction dispatch_status_function; /**< Function on dispatch status changes  */
+  void *dispatch_status_data; /**< Application data for dispatch_status_function */
+  DBusFreeFunction free_dispatch_status_data; /**< free dispatch_status_data */
+
+  DBusDispatchStatus last_dispatch_status; /**< The last dispatch status we reported to the application. */
+
+  DBusObjectTree *objects; /**< Object path handlers registered with this connection */
+
+  char *server_guid; /**< GUID of server if we are in shared_connections, #NULL if server GUID is unknown or connection is private */
+
+  /* These two MUST be bools and not bitfields, because they are protected by a separate lock
+   * from connection->mutex and all bitfields in a word have to be read/written together.
+   * So you can't have a different lock for different bitfields in the same word.
+   */
+  dbus_bool_t dispatch_acquired; /**< Someone has dispatch path (can drain incoming queue) */
+  dbus_bool_t io_path_acquired;  /**< Someone has transport io path (can use the transport to read/write messages) */
+  
+  unsigned int shareable : 1; /**< #TRUE if libdbus owns a reference to the connection and can return it from dbus_connection_open() more than once */
+  
+  unsigned int exit_on_disconnect : 1; /**< If #TRUE, exit after handling disconnect signal */
+
+  unsigned int route_peer_messages : 1; /**< If #TRUE, if org.freedesktop.DBus.Peer messages have a bus name, don't handle them automatically */
+
+  unsigned int disconnected_message_arrived : 1;   /**< We popped or are dispatching the disconnected message.
+                                                    * if the disconnect_message_link is NULL then we queued it, but
+                                                    * this flag is whether it got to the head of the queue.
+                                                    */
+  unsigned int disconnected_message_processed : 1; /**< We did our default handling of the disconnected message,
+                                                    * such as closing the connection.
+                                                    */
+  
+#ifndef DBUS_DISABLE_CHECKS
+  unsigned int have_connection_lock : 1; /**< Used to check locking */
+#endif
+  
+#ifndef DBUS_DISABLE_CHECKS
+  int generation; /**< _dbus_current_generation that should correspond to this connection */
+#endif 
+};
+
+static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked      (DBusConnection     *connection);
+static void               _dbus_connection_update_dispatch_status_and_unlock (DBusConnection     *connection,
+                                                                              DBusDispatchStatus  new_status);
+static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
+static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
+static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
+static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
+static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
+static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
+static dbus_bool_t        _dbus_connection_peek_for_reply_unlocked           (DBusConnection     *connection,
+                                                                              dbus_uint32_t       client_serial);
+
+static DBusMessageFilter *
+_dbus_message_filter_ref (DBusMessageFilter *filter)
+{
+#ifdef DBUS_DISABLE_ASSERT
+  _dbus_atomic_inc (&filter->refcount);
+#else
+  dbus_int32_t old_value;
+
+  old_value = _dbus_atomic_inc (&filter->refcount);
+  _dbus_assert (old_value > 0);
+#endif
+
+  return filter;
+}
+
+static void
+_dbus_message_filter_unref (DBusMessageFilter *filter)
+{
+  dbus_int32_t old_value;
+
+  old_value = _dbus_atomic_dec (&filter->refcount);
+  _dbus_assert (old_value > 0);
+
+  if (old_value == 1)
+    {
+      if (filter->free_user_data_function)
+        (* filter->free_user_data_function) (filter->user_data);
+      
+      dbus_free (filter);
+    }
+}
+
+/**
+ * Acquires the connection lock.
+ *
+ * @param connection the connection.
+ */
+void
+_dbus_connection_lock (DBusConnection *connection)
+{
+  CONNECTION_LOCK (connection);
+}
+
+/**
+ * Releases the connection lock.
+ *
+ * @param connection the connection.
+ */
+void
+_dbus_connection_unlock (DBusConnection *connection)
+{
+  DBusList *expired_messages;
+  DBusList *iter;
+
+  if (TRACE_LOCKS)
+    {
+      _dbus_verbose ("UNLOCK\n");
+    }
+
+  /* If we had messages that expired (fell off the incoming or outgoing
+   * queues) while we were locked, actually release them now */
+  expired_messages = connection->expired_messages;
+  connection->expired_messages = NULL;
+
+  RELEASING_LOCK_CHECK (connection);
+  _dbus_rmutex_unlock (connection->mutex);
+
+  for (iter = _dbus_list_pop_first_link (&expired_messages);
+      iter != NULL;
+      iter = _dbus_list_pop_first_link (&expired_messages))
+    {
+      DBusMessage *message = iter->data;
+
+      dbus_message_unref (message);
+      _dbus_list_free_link (iter);
+    }
+}
+
+/**
+ * Wakes up the main loop if it is sleeping
+ * Needed if we're e.g. queueing outgoing messages
+ * on a thread while the mainloop sleeps.
+ *
+ * @param connection the connection.
+ */
+static void
+_dbus_connection_wakeup_mainloop (DBusConnection *connection)
+{
+  if (connection->wakeup_main_function)
+    (*connection->wakeup_main_function) (connection->wakeup_main_data);
+}
+
+#ifdef DBUS_BUILD_TESTS
+/**
+ * Gets the locks so we can examine them
+ *
+ * @param connection the connection.
+ * @param mutex_loc return for the location of the main mutex pointer
+ * @param dispatch_mutex_loc return location of the dispatch mutex pointer
+ * @param io_path_mutex_loc return location of the io_path mutex pointer
+ * @param dispatch_cond_loc return location of the dispatch conditional 
+ *        variable pointer
+ * @param io_path_cond_loc return location of the io_path conditional 
+ *        variable pointer
+ */ 
+void 
+_dbus_connection_test_get_locks (DBusConnection *connection,
+                                 DBusMutex     **mutex_loc,
+                                 DBusMutex     **dispatch_mutex_loc,
+                                 DBusMutex     **io_path_mutex_loc,
+                                 DBusCondVar   **dispatch_cond_loc,
+                                 DBusCondVar   **io_path_cond_loc)
+{
+  *mutex_loc = (DBusMutex *) connection->mutex;
+  *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex;
+  *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex;
+  *dispatch_cond_loc = connection->dispatch_cond;
+  *io_path_cond_loc = connection->io_path_cond;
+}
+#endif
+
+/**
+ * Adds a message-containing list link to the incoming message queue,
+ * taking ownership of the link and the message's current refcount.
+ * Cannot fail due to lack of memory.
+ *
+ * @param connection the connection.
+ * @param link the message link to queue.
+ */
+void
+_dbus_connection_queue_received_message_link (DBusConnection  *connection,
+                                              DBusList        *link)
+{
+  DBusPendingCall *pending;
+  dbus_uint32_t reply_serial;
+  DBusMessage *message;
+  
+  _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
+  
+  _dbus_list_append_link (&connection->incoming_messages,
+                          link);
+  message = link->data;
+
+  /* If this is a reply we're waiting on, remove timeout for it */
+  reply_serial = dbus_message_get_reply_serial (message);
+  if (reply_serial != 0)
+    {
+      pending = _dbus_hash_table_lookup_int (connection->pending_replies,
+                                             reply_serial);
+      if (pending != NULL)
+	{
+	  if (_dbus_pending_call_is_timeout_added_unlocked (pending))
+            _dbus_connection_remove_timeout_unlocked (connection,
+                                                      _dbus_pending_call_get_timeout_unlocked (pending));
+
+	  _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
+	}
+    }
+  
+  
+
+  connection->n_incoming += 1;
+
+  _dbus_connection_wakeup_mainloop (connection);
+  
+  _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
+                 message,
+                 dbus_message_type_to_string (dbus_message_get_type (message)),
+                 dbus_message_get_path (message) ?
+                 dbus_message_get_path (message) :
+                 "no path",
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) :
+                 "no member",
+                 dbus_message_get_signature (message),
+                 dbus_message_get_reply_serial (message),
+                 connection,
+                 connection->n_incoming);
+
+  _dbus_message_trace_ref (message, -1, -1,
+      "_dbus_conection_queue_received_message_link");
+}
+
+/**
+ * Adds a link + message to the incoming message queue.
+ * Can't fail. Takes ownership of both link and message.
+ *
+ * @param connection the connection.
+ * @param link the list node and message to queue.
+ *
+ */
+void
+_dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
+						 DBusList *link)
+{
+  HAVE_LOCK_CHECK (connection);
+  
+  _dbus_list_append_link (&connection->incoming_messages, link);
+
+  connection->n_incoming += 1;
+
+  _dbus_connection_wakeup_mainloop (connection);
+
+  _dbus_message_trace_ref (link->data, -1, -1,
+      "_dbus_connection_queue_synthesized_message_link");
+
+  _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
+                 link->data, connection, connection->n_incoming);
+}
+
+
+/**
+ * Checks whether there are messages in the outgoing message queue.
+ * Called with connection lock held.
+ *
+ * @param connection the connection.
+ * @returns #TRUE if the outgoing queue is non-empty.
+ */
+dbus_bool_t
+_dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+  return connection->outgoing_messages != NULL;
+}
+
+/**
+ * Checks whether there are messages in the outgoing message queue.
+ * Use dbus_connection_flush() to block until all outgoing
+ * messages have been written to the underlying transport
+ * (such as a socket).
+ * 
+ * @param connection the connection.
+ * @returns #TRUE if the outgoing queue is non-empty.
+ */
+dbus_bool_t
+dbus_connection_has_messages_to_send (DBusConnection *connection)
+{
+  dbus_bool_t v;
+  
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+
+  CONNECTION_LOCK (connection);
+  v = _dbus_connection_has_messages_to_send_unlocked (connection);
+  CONNECTION_UNLOCK (connection);
+
+  return v;
+}
+
+/**
+ * Gets the next outgoing message. The message remains in the
+ * queue, and the caller does not own a reference to it.
+ *
+ * @param connection the connection.
+ * @returns the message to be sent.
+ */ 
+DBusMessage*
+_dbus_connection_get_message_to_send (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+  
+  return _dbus_list_get_last (&connection->outgoing_messages);
+}
+
+/**
+ * Notifies the connection that a message has been sent, so the
+ * message can be removed from the outgoing queue.
+ * Called with the connection lock held.
+ *
+ * @param connection the connection.
+ * @param message the message that was sent.
+ */
+void
+_dbus_connection_message_sent_unlocked (DBusConnection *connection,
+                                        DBusMessage    *message)
+{
+  DBusList *link;
+
+  HAVE_LOCK_CHECK (connection);
+  
+  /* This can be called before we even complete authentication, since
+   * it's called on disconnect to clean up the outgoing queue.
+   * It's also called as we successfully send each message.
+   */
+  
+  link = _dbus_list_get_last_link (&connection->outgoing_messages);
+  _dbus_assert (link != NULL);
+  _dbus_assert (link->data == message);
+
+  _dbus_list_unlink (&connection->outgoing_messages,
+                     link);
+  _dbus_list_prepend_link (&connection->expired_messages, link);
+
+  connection->n_outgoing -= 1;
+
+  _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
+                 message,
+                 dbus_message_type_to_string (dbus_message_get_type (message)),
+                 dbus_message_get_path (message) ?
+                 dbus_message_get_path (message) :
+                 "no path",
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) :
+                 "no member",
+                 dbus_message_get_signature (message),
+                 connection, connection->n_outgoing);
+
+  /* It's OK that in principle we call the notify function, because for the
+   * outgoing limit, there isn't one */
+  _dbus_message_remove_counter (message, connection->outgoing_counter);
+
+  /* The message will actually be unreffed when we unlock */
+}
+
+/** Function to be called in protected_change_watch() with refcount held */
+typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
+                                                  DBusWatch     *watch);
+/** Function to be called in protected_change_watch() with refcount held */
+typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
+                                                  DBusWatch     *watch);
+/** Function to be called in protected_change_watch() with refcount held */
+typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
+                                                  DBusWatch     *watch,
+                                                  dbus_bool_t    enabled);
+
+static dbus_bool_t
+protected_change_watch (DBusConnection         *connection,
+                        DBusWatch              *watch,
+                        DBusWatchAddFunction    add_function,
+                        DBusWatchRemoveFunction remove_function,
+                        DBusWatchToggleFunction toggle_function,
+                        dbus_bool_t             enabled)
+{
+  dbus_bool_t retval;
+
+  HAVE_LOCK_CHECK (connection);
+
+  /* The original purpose of protected_change_watch() was to hold a
+   * ref on the connection while dropping the connection lock, then
+   * calling out to the app.  This was a broken hack that did not
+   * work, since the connection was in a hosed state (no WatchList
+   * field) while calling out.
+   *
+   * So for now we'll just keep the lock while calling out. This means
+   * apps are not allowed to call DBusConnection methods inside a
+   * watch function or they will deadlock.
+   *
+   * The "real fix" is to use the _and_unlock() pattern found
+   * elsewhere in the code, to defer calling out to the app until
+   * we're about to drop locks and return flow of control to the app
+   * anyway.
+   *
+   * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
+   */
+
+  if (connection->watches)
+    {
+      if (add_function)
+        retval = (* add_function) (connection->watches, watch);
+      else if (remove_function)
+        {
+          retval = TRUE;
+          (* remove_function) (connection->watches, watch);
+        }
+      else
+        {
+          retval = TRUE;
+          (* toggle_function) (connection->watches, watch, enabled);
+        }
+      return retval;
+    }
+  else
+    return FALSE;
+}
+     
+
+/**
+ * Adds a watch using the connection's DBusAddWatchFunction if
+ * available. Otherwise records the watch to be added when said
+ * function is available. Also re-adds the watch if the
+ * DBusAddWatchFunction changes. May fail due to lack of memory.
+ * Connection lock should be held when calling this.
+ *
+ * @param connection the connection.
+ * @param watch the watch to add.
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_connection_add_watch_unlocked (DBusConnection *connection,
+                                     DBusWatch      *watch)
+{
+  return protected_change_watch (connection, watch,
+                                 _dbus_watch_list_add_watch,
+                                 NULL, NULL, FALSE);
+}
+
+/**
+ * Removes a watch using the connection's DBusRemoveWatchFunction
+ * if available. It's an error to call this function on a watch
+ * that was not previously added.
+ * Connection lock should be held when calling this.
+ *
+ * @param connection the connection.
+ * @param watch the watch to remove.
+ */
+void
+_dbus_connection_remove_watch_unlocked (DBusConnection *connection,
+                                        DBusWatch      *watch)
+{
+  protected_change_watch (connection, watch,
+                          NULL,
+                          _dbus_watch_list_remove_watch,
+                          NULL, FALSE);
+}
+
+/**
+ * Toggles a watch and notifies app via connection's
+ * DBusWatchToggledFunction if available. It's an error to call this
+ * function on a watch that was not previously added.
+ * Connection lock should be held when calling this.
+ *
+ * @param connection the connection.
+ * @param watch the watch to toggle.
+ * @param enabled whether to enable or disable
+ */
+void
+_dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
+                                        DBusWatch      *watch,
+                                        dbus_bool_t     enabled)
+{
+  _dbus_assert (watch != NULL);
+
+  protected_change_watch (connection, watch,
+                          NULL, NULL,
+                          _dbus_watch_list_toggle_watch,
+                          enabled);
+}
+
+/** Function to be called in protected_change_timeout() with refcount held */
+typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
+                                                   DBusTimeout     *timeout);
+/** Function to be called in protected_change_timeout() with refcount held */
+typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
+                                                   DBusTimeout     *timeout);
+/** Function to be called in protected_change_timeout() with refcount held */
+typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
+                                                   DBusTimeout     *timeout,
+                                                   dbus_bool_t      enabled);
+
+static dbus_bool_t
+protected_change_timeout (DBusConnection           *connection,
+                          DBusTimeout              *timeout,
+                          DBusTimeoutAddFunction    add_function,
+                          DBusTimeoutRemoveFunction remove_function,
+                          DBusTimeoutToggleFunction toggle_function,
+                          dbus_bool_t               enabled)
+{
+  dbus_bool_t retval;
+
+  HAVE_LOCK_CHECK (connection);
+
+  /* The original purpose of protected_change_timeout() was to hold a
+   * ref on the connection while dropping the connection lock, then
+   * calling out to the app.  This was a broken hack that did not
+   * work, since the connection was in a hosed state (no TimeoutList
+   * field) while calling out.
+   *
+   * So for now we'll just keep the lock while calling out. This means
+   * apps are not allowed to call DBusConnection methods inside a
+   * timeout function or they will deadlock.
+   *
+   * The "real fix" is to use the _and_unlock() pattern found
+   * elsewhere in the code, to defer calling out to the app until
+   * we're about to drop locks and return flow of control to the app
+   * anyway.
+   *
+   * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
+   */
+
+  if (connection->timeouts)
+    {
+      if (add_function)
+        retval = (* add_function) (connection->timeouts, timeout);
+      else if (remove_function)
+        {
+          retval = TRUE;
+          (* remove_function) (connection->timeouts, timeout);
+        }
+      else
+        {
+          retval = TRUE;
+          (* toggle_function) (connection->timeouts, timeout, enabled);
+        }
+      return retval;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * Adds a timeout using the connection's DBusAddTimeoutFunction if
+ * available. Otherwise records the timeout to be added when said
+ * function is available. Also re-adds the timeout if the
+ * DBusAddTimeoutFunction changes. May fail due to lack of memory.
+ * The timeout will fire repeatedly until removed.
+ * Connection lock should be held when calling this.
+ *
+ * @param connection the connection.
+ * @param timeout the timeout to add.
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_connection_add_timeout_unlocked (DBusConnection *connection,
+                                       DBusTimeout    *timeout)
+{
+  return protected_change_timeout (connection, timeout,
+                                   _dbus_timeout_list_add_timeout,
+                                   NULL, NULL, FALSE);
+}
+
+/**
+ * Removes a timeout using the connection's DBusRemoveTimeoutFunction
+ * if available. It's an error to call this function on a timeout
+ * that was not previously added.
+ * Connection lock should be held when calling this.
+ *
+ * @param connection the connection.
+ * @param timeout the timeout to remove.
+ */
+void
+_dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
+                                          DBusTimeout    *timeout)
+{
+  protected_change_timeout (connection, timeout,
+                            NULL,
+                            _dbus_timeout_list_remove_timeout,
+                            NULL, FALSE);
+}
+
+/**
+ * Toggles a timeout and notifies app via connection's
+ * DBusTimeoutToggledFunction if available. It's an error to call this
+ * function on a timeout that was not previously added.
+ * Connection lock should be held when calling this.
+ *
+ * @param connection the connection.
+ * @param timeout the timeout to toggle.
+ * @param enabled whether to enable or disable
+ */
+void
+_dbus_connection_toggle_timeout_unlocked (DBusConnection   *connection,
+                                          DBusTimeout      *timeout,
+                                          dbus_bool_t       enabled)
+{
+  protected_change_timeout (connection, timeout,
+                            NULL, NULL,
+                            _dbus_timeout_list_toggle_timeout,
+                            enabled);
+}
+
+static dbus_bool_t
+_dbus_connection_attach_pending_call_unlocked (DBusConnection  *connection,
+                                               DBusPendingCall *pending)
+{
+  dbus_uint32_t reply_serial;
+  DBusTimeout *timeout;
+
+  HAVE_LOCK_CHECK (connection);
+
+  reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
+
+  _dbus_assert (reply_serial != 0);
+
+  timeout = _dbus_pending_call_get_timeout_unlocked (pending);
+
+  if (timeout)
+    {
+      if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
+        return FALSE;
+      
+      if (!_dbus_hash_table_insert_int (connection->pending_replies,
+                                        reply_serial,
+                                        pending))
+        {
+          _dbus_connection_remove_timeout_unlocked (connection, timeout);
+
+          _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
+          HAVE_LOCK_CHECK (connection);
+          return FALSE;
+        }
+      
+      _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
+    }
+  else
+    {
+      if (!_dbus_hash_table_insert_int (connection->pending_replies,
+                                        reply_serial,
+                                        pending))
+        {
+          HAVE_LOCK_CHECK (connection);
+          return FALSE;
+        }
+    }
+
+  _dbus_pending_call_ref_unlocked (pending);
+
+  HAVE_LOCK_CHECK (connection);
+  
+  return TRUE;
+}
+
+static void
+free_pending_call_on_hash_removal (void *data)
+{
+  DBusPendingCall *pending;
+  DBusConnection  *connection;
+  
+  if (data == NULL)
+    return;
+
+  pending = data;
+
+  connection = _dbus_pending_call_get_connection_unlocked (pending);
+
+  HAVE_LOCK_CHECK (connection);
+  
+  if (_dbus_pending_call_is_timeout_added_unlocked (pending))
+    {
+      _dbus_connection_remove_timeout_unlocked (connection,
+                                                _dbus_pending_call_get_timeout_unlocked (pending));
+      
+      _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
+    }
+
+  /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 
+   * here, but the pending call finalizer could in principle call out to 
+   * application code so we pretty much have to... some larger code reorg 
+   * might be needed.
+   */
+  _dbus_connection_ref_unlocked (connection);
+  _dbus_pending_call_unref_and_unlock (pending);
+  CONNECTION_LOCK (connection);
+  _dbus_connection_unref_unlocked (connection);
+}
+
+static void
+_dbus_connection_detach_pending_call_unlocked (DBusConnection  *connection,
+                                               DBusPendingCall *pending)
+{
+  /* This ends up unlocking to call the pending call finalizer, which is unexpected to
+   * say the least.
+   */
+  _dbus_hash_table_remove_int (connection->pending_replies,
+                               _dbus_pending_call_get_reply_serial_unlocked (pending));
+}
+
+static void
+_dbus_connection_detach_pending_call_and_unlock (DBusConnection  *connection,
+                                                 DBusPendingCall *pending)
+{
+  /* The idea here is to avoid finalizing the pending call
+   * with the lock held, since there's a destroy notifier
+   * in pending call that goes out to application code.
+   *
+   * There's an extra unlock inside the hash table
+   * "free pending call" function FIXME...
+   */
+  _dbus_pending_call_ref_unlocked (pending);
+  _dbus_hash_table_remove_int (connection->pending_replies,
+                               _dbus_pending_call_get_reply_serial_unlocked (pending));
+
+  if (_dbus_pending_call_is_timeout_added_unlocked (pending))
+      _dbus_connection_remove_timeout_unlocked (connection,
+              _dbus_pending_call_get_timeout_unlocked (pending));
+
+  _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
+
+  _dbus_pending_call_unref_and_unlock (pending);
+}
+
+/**
+ * Removes a pending call from the connection, such that
+ * the pending reply will be ignored. May drop the last
+ * reference to the pending call.
+ *
+ * @param connection the connection
+ * @param pending the pending call
+ */
+void
+_dbus_connection_remove_pending_call (DBusConnection  *connection,
+                                      DBusPendingCall *pending)
+{
+  CONNECTION_LOCK (connection);
+  _dbus_connection_detach_pending_call_and_unlock (connection, pending);
+}
+
+/**
+ * Acquire the transporter I/O path. This must be done before
+ * doing any I/O in the transporter. May sleep and drop the
+ * IO path mutex while waiting for the I/O path.
+ *
+ * @param connection the connection.
+ * @param timeout_milliseconds maximum blocking time, or -1 for no limit.
+ * @returns TRUE if the I/O path was acquired.
+ */
+static dbus_bool_t
+_dbus_connection_acquire_io_path (DBusConnection *connection,
+				  int             timeout_milliseconds)
+{
+  dbus_bool_t we_acquired;
+  
+  HAVE_LOCK_CHECK (connection);
+
+  /* We don't want the connection to vanish */
+  _dbus_connection_ref_unlocked (connection);
+
+  /* We will only touch io_path_acquired which is protected by our mutex */
+  CONNECTION_UNLOCK (connection);
+  
+  _dbus_verbose ("locking io_path_mutex\n");
+  _dbus_cmutex_lock (connection->io_path_mutex);
+
+  _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
+                 connection->io_path_acquired, timeout_milliseconds);
+
+  we_acquired = FALSE;
+  
+  if (connection->io_path_acquired)
+    {
+      if (timeout_milliseconds != -1)
+        {
+          _dbus_verbose ("waiting %d for IO path to be acquirable\n",
+                         timeout_milliseconds);
+
+          if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
+                                           connection->io_path_mutex,
+                                           timeout_milliseconds))
+            {
+              /* We timed out before anyone signaled. */
+              /* (writing the loop to handle the !timedout case by
+               * waiting longer if needed is a pain since dbus
+               * wraps pthread_cond_timedwait to take a relative
+               * time instead of absolute, something kind of stupid
+               * on our part. for now it doesn't matter, we will just
+               * end up back here eventually.)
+               */
+            }
+        }
+      else
+        {
+          while (connection->io_path_acquired)
+            {
+              _dbus_verbose ("waiting for IO path to be acquirable\n");
+              _dbus_condvar_wait (connection->io_path_cond, 
+                                  connection->io_path_mutex);
+            }
+        }
+    }
+  
+  if (!connection->io_path_acquired)
+    {
+      we_acquired = TRUE;
+      connection->io_path_acquired = TRUE;
+    }
+  
+  _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
+                 connection->io_path_acquired, we_acquired);
+
+  _dbus_verbose ("unlocking io_path_mutex\n");
+  _dbus_cmutex_unlock (connection->io_path_mutex);
+
+  CONNECTION_LOCK (connection);
+  
+  HAVE_LOCK_CHECK (connection);
+
+  _dbus_connection_unref_unlocked (connection);
+  
+  return we_acquired;
+}
+
+/**
+ * Release the I/O path when you're done with it. Only call
+ * after you've acquired the I/O. Wakes up at most one thread
+ * currently waiting to acquire the I/O path.
+ *
+ * @param connection the connection.
+ */
+static void
+_dbus_connection_release_io_path (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+  
+  _dbus_verbose ("locking io_path_mutex\n");
+  _dbus_cmutex_lock (connection->io_path_mutex);
+  
+  _dbus_assert (connection->io_path_acquired);
+
+  _dbus_verbose ("start connection->io_path_acquired = %d\n",
+                 connection->io_path_acquired);
+  
+  connection->io_path_acquired = FALSE;
+  _dbus_condvar_wake_one (connection->io_path_cond);
+
+  _dbus_verbose ("unlocking io_path_mutex\n");
+  _dbus_cmutex_unlock (connection->io_path_mutex);
+}
+
+/**
+ * Queues incoming messages and sends outgoing messages for this
+ * connection, optionally blocking in the process. Each call to
+ * _dbus_connection_do_iteration_unlocked() will call select() or poll() one
+ * time and then read or write data if possible.
+ *
+ * The purpose of this function is to be able to flush outgoing
+ * messages or queue up incoming messages without returning
+ * control to the application and causing reentrancy weirdness.
+ *
+ * The flags parameter allows you to specify whether to
+ * read incoming messages, write outgoing messages, or both,
+ * and whether to block if no immediate action is possible.
+ *
+ * The timeout_milliseconds parameter does nothing unless the
+ * iteration is blocking.
+ *
+ * If there are no outgoing messages and DBUS_ITERATION_DO_READING
+ * wasn't specified, then it's impossible to block, even if
+ * you specify DBUS_ITERATION_BLOCK; in that case the function
+ * returns immediately.
+ *
+ * If pending is not NULL then a check is made if the pending call
+ * is completed after the io path has been required. If the call
+ * has been completed nothing is done. This must be done since
+ * the _dbus_connection_acquire_io_path releases the connection
+ * lock for a while.
+ *
+ * Called with connection lock held.
+ * 
+ * @param connection the connection.
+ * @param pending the pending call that should be checked or NULL
+ * @param flags iteration flags.
+ * @param timeout_milliseconds maximum blocking time, or -1 for no limit.
+ */
+void
+_dbus_connection_do_iteration_unlocked (DBusConnection *connection,
+                                        DBusPendingCall *pending,
+                                        unsigned int    flags,
+                                        int             timeout_milliseconds)
+{
+  _dbus_verbose ("start\n");
+  
+  HAVE_LOCK_CHECK (connection);
+  
+  if (connection->n_outgoing == 0)
+    flags &= ~DBUS_ITERATION_DO_WRITING;
+
+  if (_dbus_connection_acquire_io_path (connection,
+					(flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
+    {
+      HAVE_LOCK_CHECK (connection);
+      
+      if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
+        {
+          _dbus_verbose ("pending call completed while acquiring I/O path");
+        }
+      else if ( (pending != NULL) &&
+                _dbus_connection_peek_for_reply_unlocked (connection,
+                                                          _dbus_pending_call_get_reply_serial_unlocked (pending)))
+        {
+          _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
+        }
+      else
+        {
+          _dbus_transport_do_iteration (connection->transport,
+                                        flags, timeout_milliseconds);
+        }
+
+      _dbus_connection_release_io_path (connection);
+    }
+
+  HAVE_LOCK_CHECK (connection);
+
+  _dbus_verbose ("end\n");
+}
+
+/**
+ * Creates a new connection for the given transport.  A transport
+ * represents a message stream that uses some concrete mechanism, such
+ * as UNIX domain sockets. May return #NULL if insufficient
+ * memory exists to create the connection.
+ *
+ * @param transport the transport.
+ * @returns the new connection, or #NULL on failure.
+ */
+DBusConnection*
+_dbus_connection_new_for_transport (DBusTransport *transport)
+{
+  DBusConnection *connection;
+  DBusWatchList *watch_list;
+  DBusTimeoutList *timeout_list;
+  DBusHashTable *pending_replies;
+  DBusList *disconnect_link;
+  DBusMessage *disconnect_message;
+  DBusCounter *outgoing_counter;
+  DBusObjectTree *objects;
+  
+  watch_list = NULL;
+  connection = NULL;
+  pending_replies = NULL;
+  timeout_list = NULL;
+  disconnect_link = NULL;
+  disconnect_message = NULL;
+  outgoing_counter = NULL;
+  objects = NULL;
+  
+  watch_list = _dbus_watch_list_new ();
+  if (watch_list == NULL)
+    goto error;
+
+  timeout_list = _dbus_timeout_list_new ();
+  if (timeout_list == NULL)
+    goto error;  
+
+  pending_replies =
+    _dbus_hash_table_new (DBUS_HASH_INT,
+			  NULL,
+                          (DBusFreeFunction)free_pending_call_on_hash_removal);
+  if (pending_replies == NULL)
+    goto error;
+  
+  connection = dbus_new0 (DBusConnection, 1);
+  if (connection == NULL)
+    goto error;
+
+  _dbus_rmutex_new_at_location (&connection->mutex);
+  if (connection->mutex == NULL)
+    goto error;
+
+  _dbus_cmutex_new_at_location (&connection->io_path_mutex);
+  if (connection->io_path_mutex == NULL)
+    goto error;
+
+  _dbus_cmutex_new_at_location (&connection->dispatch_mutex);
+  if (connection->dispatch_mutex == NULL)
+    goto error;
+  
+  _dbus_condvar_new_at_location (&connection->dispatch_cond);
+  if (connection->dispatch_cond == NULL)
+    goto error;
+  
+  _dbus_condvar_new_at_location (&connection->io_path_cond);
+  if (connection->io_path_cond == NULL)
+    goto error;
+
+  _dbus_rmutex_new_at_location (&connection->slot_mutex);
+  if (connection->slot_mutex == NULL)
+    goto error;
+
+  disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
+                                                DBUS_INTERFACE_LOCAL,
+                                                "Disconnected");
+  
+  if (disconnect_message == NULL)
+    goto error;
+
+  disconnect_link = _dbus_list_alloc_link (disconnect_message);
+  if (disconnect_link == NULL)
+    goto error;
+
+  outgoing_counter = _dbus_counter_new ();
+  if (outgoing_counter == NULL)
+    goto error;
+
+  objects = _dbus_object_tree_new (connection);
+  if (objects == NULL)
+    goto error;
+  
+  if (_dbus_modify_sigpipe)
+    _dbus_disable_sigpipe ();
+
+  /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
+  _dbus_atomic_inc (&connection->refcount);
+  connection->transport = transport;
+  connection->watches = watch_list;
+  connection->timeouts = timeout_list;
+  connection->pending_replies = pending_replies;
+  connection->outgoing_counter = outgoing_counter;
+  connection->filter_list = NULL;
+  connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
+  connection->objects = objects;
+  connection->exit_on_disconnect = FALSE;
+  connection->shareable = FALSE;
+  connection->route_peer_messages = FALSE;
+  connection->disconnected_message_arrived = FALSE;
+  connection->disconnected_message_processed = FALSE;
+  
+#ifndef DBUS_DISABLE_CHECKS
+  connection->generation = _dbus_current_generation;
+#endif
+  
+  _dbus_data_slot_list_init (&connection->slot_list);
+
+  connection->client_serial = 1;
+
+  connection->disconnect_message_link = disconnect_link;
+
+  CONNECTION_LOCK (connection);
+  
+  if (!_dbus_transport_set_connection (transport, connection))
+    {
+      CONNECTION_UNLOCK (connection);
+
+      goto error;
+    }
+
+  _dbus_transport_ref (transport);
+
+  CONNECTION_UNLOCK (connection);
+
+  _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport");
+  return connection;
+  
+ error:
+  if (disconnect_message != NULL)
+    dbus_message_unref (disconnect_message);
+  
+  if (disconnect_link != NULL)
+    _dbus_list_free_link (disconnect_link);
+  
+  if (connection != NULL)
+    {
+      _dbus_condvar_free_at_location (&connection->io_path_cond);
+      _dbus_condvar_free_at_location (&connection->dispatch_cond);
+      _dbus_rmutex_free_at_location (&connection->mutex);
+      _dbus_cmutex_free_at_location (&connection->io_path_mutex);
+      _dbus_cmutex_free_at_location (&connection->dispatch_mutex);
+      _dbus_rmutex_free_at_location (&connection->slot_mutex);
+      dbus_free (connection);
+    }
+  if (pending_replies)
+    _dbus_hash_table_unref (pending_replies);
+  
+  if (watch_list)
+    _dbus_watch_list_free (watch_list);
+
+  if (timeout_list)
+    _dbus_timeout_list_free (timeout_list);
+
+  if (outgoing_counter)
+    _dbus_counter_unref (outgoing_counter);
+
+  if (objects)
+    _dbus_object_tree_unref (objects);
+  
+  return NULL;
+}
+
+/**
+ * Increments the reference count of a DBusConnection.
+ * Requires that the caller already holds the connection lock.
+ *
+ * @param connection the connection.
+ * @returns the connection.
+ */
+DBusConnection *
+_dbus_connection_ref_unlocked (DBusConnection *connection)
+{
+  dbus_int32_t old_refcount;
+
+  _dbus_assert (connection != NULL);
+  _dbus_assert (connection->generation == _dbus_current_generation);
+
+  HAVE_LOCK_CHECK (connection);
+
+  old_refcount = _dbus_atomic_inc (&connection->refcount);
+  _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
+      "ref_unlocked");
+
+  return connection;
+}
+
+/**
+ * Decrements the reference count of a DBusConnection.
+ * Requires that the caller already holds the connection lock.
+ *
+ * @param connection the connection.
+ */
+void
+_dbus_connection_unref_unlocked (DBusConnection *connection)
+{
+  dbus_int32_t old_refcount;
+
+  HAVE_LOCK_CHECK (connection);
+
+  _dbus_assert (connection != NULL);
+
+  old_refcount = _dbus_atomic_dec (&connection->refcount);
+
+  _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
+      "unref_unlocked");
+
+  if (old_refcount == 1)
+    _dbus_connection_last_unref (connection);
+}
+
+static dbus_uint32_t
+_dbus_connection_get_next_client_serial (DBusConnection *connection)
+{
+  dbus_uint32_t serial;
+
+  serial = connection->client_serial++;
+
+  if (connection->client_serial == 0)
+    connection->client_serial = 1;
+
+  return serial;
+}
+
+/**
+ * A callback for use with dbus_watch_new() to create a DBusWatch.
+ * 
+ * @todo This is basically a hack - we could delete _dbus_transport_handle_watch()
+ * and the virtual handle_watch in DBusTransport if we got rid of it.
+ * The reason this is some work is threading, see the _dbus_connection_handle_watch()
+ * implementation.
+ *
+ * @param watch the watch.
+ * @param condition the current condition of the file descriptors being watched.
+ * @param data must be a pointer to a #DBusConnection
+ * @returns #FALSE if the IO condition may not have been fully handled due to lack of memory
+ */
+dbus_bool_t
+_dbus_connection_handle_watch (DBusWatch                   *watch,
+                               unsigned int                 condition,
+                               void                        *data)
+{
+  DBusConnection *connection;
+  dbus_bool_t retval;
+  DBusDispatchStatus status;
+
+  connection = data;
+
+  _dbus_verbose ("start\n");
+  
+  CONNECTION_LOCK (connection);
+
+  if (!_dbus_connection_acquire_io_path (connection, 1))
+    {
+      /* another thread is handling the message */
+      CONNECTION_UNLOCK (connection);
+      return TRUE;
+    }
+
+  HAVE_LOCK_CHECK (connection);
+  retval = _dbus_transport_handle_watch (connection->transport,
+                                         watch, condition);
+
+  _dbus_connection_release_io_path (connection);
+
+  HAVE_LOCK_CHECK (connection);
+
+  _dbus_verbose ("middle\n");
+  
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+
+  /* this calls out to user code */
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+
+  _dbus_verbose ("end\n");
+  
+  return retval;
+}
+
+_DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
+static DBusHashTable *shared_connections = NULL;
+static DBusList *shared_connections_no_guid = NULL;
+
+static void
+close_connection_on_shutdown (DBusConnection *connection)
+{
+  DBusMessage *message;
+
+  dbus_connection_ref (connection);
+  _dbus_connection_close_possibly_shared (connection);
+
+  /* Churn through to the Disconnected message */
+  while ((message = dbus_connection_pop_message (connection)))
+    {
+      dbus_message_unref (message);
+    }
+  dbus_connection_unref (connection);
+}
+
+static void
+shared_connections_shutdown (void *data)
+{
+  int n_entries;
+  
+  _DBUS_LOCK (shared_connections);
+  
+  /* This is a little bit unpleasant... better ideas? */
+  while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
+    {
+      DBusConnection *connection;
+      DBusHashIter iter;
+      
+      _dbus_hash_iter_init (shared_connections, &iter);
+      _dbus_hash_iter_next (&iter);
+       
+      connection = _dbus_hash_iter_get_value (&iter);
+
+      _DBUS_UNLOCK (shared_connections);
+      close_connection_on_shutdown (connection);
+      _DBUS_LOCK (shared_connections);
+
+      /* The connection should now be dead and not in our hash ... */
+      _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
+    }
+
+  _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
+  
+  _dbus_hash_table_unref (shared_connections);
+  shared_connections = NULL;
+
+  if (shared_connections_no_guid != NULL)
+    {
+      DBusConnection *connection;
+      connection = _dbus_list_pop_first (&shared_connections_no_guid);
+      while (connection != NULL)
+        {
+          _DBUS_UNLOCK (shared_connections);
+          close_connection_on_shutdown (connection);
+          _DBUS_LOCK (shared_connections);
+          connection = _dbus_list_pop_first (&shared_connections_no_guid);
+        }
+    }
+
+  shared_connections_no_guid = NULL;
+  
+  _DBUS_UNLOCK (shared_connections);
+}
+
+static dbus_bool_t
+connection_lookup_shared (DBusAddressEntry  *entry,
+                          DBusConnection   **result)
+{
+  _dbus_verbose ("checking for existing connection\n");
+  
+  *result = NULL;
+  
+  _DBUS_LOCK (shared_connections);
+
+  if (shared_connections == NULL)
+    {
+      _dbus_verbose ("creating shared_connections hash table\n");
+      
+      shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
+                                                 dbus_free,
+                                                 NULL);
+      if (shared_connections == NULL)
+        {
+          _DBUS_UNLOCK (shared_connections);
+          return FALSE;
+        }
+
+      if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
+        {
+          _dbus_hash_table_unref (shared_connections);
+          shared_connections = NULL;
+          _DBUS_UNLOCK (shared_connections);
+          return FALSE;
+        }
+
+      _dbus_verbose ("  successfully created shared_connections\n");
+      
+      _DBUS_UNLOCK (shared_connections);
+      return TRUE; /* no point looking up in the hash we just made */
+    }
+  else
+    {
+      const char *guid;
+
+      guid = dbus_address_entry_get_value (entry, "guid");
+      
+      if (guid != NULL)
+        {
+          DBusConnection *connection;
+          
+          connection = _dbus_hash_table_lookup_string (shared_connections,
+                                                       guid);
+
+          if (connection)
+            {
+              /* The DBusConnection can't be finalized without taking
+               * the shared_connections lock to remove it from the
+               * hash.  So it's safe to ref the connection here.
+               * However, it may be disconnected if the Disconnected
+               * message hasn't been processed yet, in which case we
+               * want to pretend it isn't in the hash and avoid
+               * returning it.
+               *
+               * The idea is to avoid ever returning a disconnected connection
+               * from dbus_connection_open(). We could just synchronously
+               * drop our shared ref to the connection on connection disconnect,
+               * and then assert here that the connection is connected, but
+               * that causes reentrancy headaches.
+               */
+              CONNECTION_LOCK (connection);
+              if (_dbus_connection_get_is_connected_unlocked (connection))
+                {
+                  _dbus_connection_ref_unlocked (connection);
+                  *result = connection;
+                  _dbus_verbose ("looked up existing connection to server guid %s\n",
+                                 guid);
+                }
+              else
+                {
+                  _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
+                                 guid);
+                }
+              CONNECTION_UNLOCK (connection);
+            }
+        }
+      
+      _DBUS_UNLOCK (shared_connections);
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
+connection_record_shared_unlocked (DBusConnection *connection,
+                                   const char     *guid)
+{
+  char *guid_key;
+  char *guid_in_connection;
+
+  HAVE_LOCK_CHECK (connection);
+  _dbus_assert (connection->server_guid == NULL);
+  _dbus_assert (connection->shareable);
+
+  /* get a hard ref on this connection, even if
+   * we won't in fact store it in the hash, we still
+   * need to hold a ref on it until it's disconnected.
+   */
+  _dbus_connection_ref_unlocked (connection);
+
+  if (guid == NULL)
+    {
+      _DBUS_LOCK (shared_connections);
+
+      if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
+        {
+          _DBUS_UNLOCK (shared_connections);
+          return FALSE;
+        }
+
+      _DBUS_UNLOCK (shared_connections);
+      return TRUE; /* don't store in the hash */
+    }
+  
+  /* A separate copy of the key is required in the hash table, because
+   * we don't have a lock on the connection when we are doing a hash
+   * lookup.
+   */
+  
+  guid_key = _dbus_strdup (guid);
+  if (guid_key == NULL)
+    return FALSE;
+
+  guid_in_connection = _dbus_strdup (guid);
+  if (guid_in_connection == NULL)
+    {
+      dbus_free (guid_key);
+      return FALSE;
+    }
+  
+  _DBUS_LOCK (shared_connections);
+  _dbus_assert (shared_connections != NULL);
+  
+  if (!_dbus_hash_table_insert_string (shared_connections,
+                                       guid_key, connection))
+    {
+      dbus_free (guid_key);
+      dbus_free (guid_in_connection);
+      _DBUS_UNLOCK (shared_connections);
+      return FALSE;
+    }
+
+  connection->server_guid = guid_in_connection;
+
+  _dbus_verbose ("stored connection to %s to be shared\n",
+                 connection->server_guid);
+  
+  _DBUS_UNLOCK (shared_connections);
+
+  _dbus_assert (connection->server_guid != NULL);
+  
+  return TRUE;
+}
+
+static void
+connection_forget_shared_unlocked (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+
+  if (!connection->shareable)
+    return;
+  
+  _DBUS_LOCK (shared_connections);
+      
+  if (connection->server_guid != NULL)
+    {
+      _dbus_verbose ("dropping connection to %s out of the shared table\n",
+                     connection->server_guid);
+      
+      if (!_dbus_hash_table_remove_string (shared_connections,
+                                           connection->server_guid))
+        _dbus_assert_not_reached ("connection was not in the shared table");
+      
+      dbus_free (connection->server_guid);
+      connection->server_guid = NULL;
+    }
+  else
+    {
+      _dbus_list_remove (&shared_connections_no_guid, connection);
+    }
+
+  _DBUS_UNLOCK (shared_connections);
+  
+  /* remove our reference held on all shareable connections */
+  _dbus_connection_unref_unlocked (connection);
+}
+
+static DBusConnection*
+connection_try_from_address_entry (DBusAddressEntry *entry,
+                                   DBusError        *error)
+{
+  DBusTransport *transport;
+  DBusConnection *connection;
+
+  transport = _dbus_transport_open (entry, error);
+
+  if (transport == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return NULL;
+    }
+
+  connection = _dbus_connection_new_for_transport (transport);
+
+  _dbus_transport_unref (transport);
+  
+  if (connection == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return NULL;
+    }
+
+#ifndef DBUS_DISABLE_CHECKS
+  _dbus_assert (!connection->have_connection_lock);
+#endif
+  return connection;
+}
+
+/*
+ * If the shared parameter is true, then any existing connection will
+ * be used (and if a new connection is created, it will be available
+ * for use by others). If the shared parameter is false, a new
+ * connection will always be created, and the new connection will
+ * never be returned to other callers.
+ *
+ * @param address the address
+ * @param shared whether the connection is shared or private
+ * @param error error return
+ * @returns the connection or #NULL on error
+ */
+static DBusConnection*
+_dbus_connection_open_internal (const char     *address,
+                                dbus_bool_t     shared,
+                                DBusError      *error)
+{
+  DBusConnection *connection;
+  DBusAddressEntry **entries;
+  DBusError tmp_error = DBUS_ERROR_INIT;
+  DBusError first_error = DBUS_ERROR_INIT;
+  int len, i;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  _dbus_verbose ("opening %s connection to: %s\n",
+                 shared ? "shared" : "private", address);
+  
+  if (!dbus_parse_address (address, &entries, &len, error))
+    return NULL;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  connection = NULL;
+
+  for (i = 0; i < len; i++)
+    {
+      if (shared)
+        {
+          if (!connection_lookup_shared (entries[i], &connection))
+            _DBUS_SET_OOM (&tmp_error);
+        }
+
+      if (connection == NULL)
+        {
+          connection = connection_try_from_address_entry (entries[i],
+                                                          &tmp_error);
+
+          if (connection != NULL && shared)
+            {
+              const char *guid;
+                  
+              connection->shareable = TRUE;
+                  
+              /* guid may be NULL */
+              guid = dbus_address_entry_get_value (entries[i], "guid");
+                  
+              CONNECTION_LOCK (connection);
+          
+              if (!connection_record_shared_unlocked (connection, guid))
+                {
+                  _DBUS_SET_OOM (&tmp_error);
+                  _dbus_connection_close_possibly_shared_and_unlock (connection);
+                  dbus_connection_unref (connection);
+                  connection = NULL;
+                }
+              else
+                CONNECTION_UNLOCK (connection);
+            }
+        }
+      
+      if (connection)
+        break;
+
+      _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+      
+      if (i == 0)
+        dbus_move_error (&tmp_error, &first_error);
+      else
+        dbus_error_free (&tmp_error);
+    }
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+  
+  if (connection == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&first_error);
+      dbus_move_error (&first_error, error);
+    }
+  else
+    dbus_error_free (&first_error);
+  
+  dbus_address_entries_free (entries);
+  return connection;
+}
+
+/**
+ * Closes a shared OR private connection, while dbus_connection_close() can
+ * only be used on private connections. Should only be called by the
+ * dbus code that owns the connection - an owner must be known,
+ * the open/close state is like malloc/free, not like ref/unref.
+ * 
+ * @param connection the connection
+ */
+void
+_dbus_connection_close_possibly_shared (DBusConnection *connection)
+{
+  _dbus_assert (connection != NULL);
+  _dbus_assert (connection->generation == _dbus_current_generation);
+
+  CONNECTION_LOCK (connection);
+  _dbus_connection_close_possibly_shared_and_unlock (connection);
+}
+
+static DBusPreallocatedSend*
+_dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
+{
+  DBusPreallocatedSend *preallocated;
+
+  HAVE_LOCK_CHECK (connection);
+  
+  _dbus_assert (connection != NULL);
+  
+  preallocated = dbus_new (DBusPreallocatedSend, 1);
+  if (preallocated == NULL)
+    return NULL;
+
+  preallocated->queue_link = _dbus_list_alloc_link (NULL);
+  if (preallocated->queue_link == NULL)
+    goto failed_0;
+
+  preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
+  if (preallocated->counter_link == NULL)
+    goto failed_1;
+
+  _dbus_counter_ref (preallocated->counter_link->data);
+
+  preallocated->connection = connection;
+  
+  return preallocated;
+  
+ failed_1:
+  _dbus_list_free_link (preallocated->queue_link);
+ failed_0:
+  dbus_free (preallocated);
+  
+  return NULL;
+}
+
+/* Called with lock held, does not update dispatch status */
+static void
+_dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *connection,
+                                                       DBusPreallocatedSend *preallocated,
+                                                       DBusMessage          *message,
+                                                       dbus_uint32_t        *client_serial)
+{
+  dbus_uint32_t serial;
+
+  preallocated->queue_link->data = message;
+  _dbus_list_prepend_link (&connection->outgoing_messages,
+                           preallocated->queue_link);
+
+  /* It's OK that we'll never call the notify function, because for the
+   * outgoing limit, there isn't one */
+  _dbus_message_add_counter_link (message,
+                                  preallocated->counter_link);
+
+  dbus_free (preallocated);
+  preallocated = NULL;
+  
+  dbus_message_ref (message);
+  
+  connection->n_outgoing += 1;
+
+  _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
+                 message,
+                 dbus_message_type_to_string (dbus_message_get_type (message)),
+                 dbus_message_get_path (message) ?
+                 dbus_message_get_path (message) :
+                 "no path",
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) :
+                 "no member",
+                 dbus_message_get_signature (message),
+                 dbus_message_get_destination (message) ?
+                 dbus_message_get_destination (message) :
+                 "null",
+                 connection,
+                 connection->n_outgoing);
+
+  if (dbus_message_get_serial (message) == 0)
+    {
+      serial = _dbus_connection_get_next_client_serial (connection);
+      dbus_message_set_serial (message, serial);
+      if (client_serial)
+        *client_serial = serial;
+    }
+  else
+    {
+      if (client_serial)
+        *client_serial = dbus_message_get_serial (message);
+    }
+
+  _dbus_verbose ("Message %p serial is %u\n",
+                 message, dbus_message_get_serial (message));
+  
+  dbus_message_lock (message);
+
+  /* Now we need to run an iteration to hopefully just write the messages
+   * out immediately, and otherwise get them queued up
+   */
+  _dbus_connection_do_iteration_unlocked (connection,
+                                          NULL,
+                                          DBUS_ITERATION_DO_WRITING,
+                                          -1);
+
+  /* If stuff is still queued up, be sure we wake up the main loop */
+  if (connection->n_outgoing > 0)
+    _dbus_connection_wakeup_mainloop (connection);
+}
+
+static void
+_dbus_connection_send_preallocated_and_unlock (DBusConnection       *connection,
+					       DBusPreallocatedSend *preallocated,
+					       DBusMessage          *message,
+					       dbus_uint32_t        *client_serial)
+{
+  DBusDispatchStatus status;
+
+  HAVE_LOCK_CHECK (connection);
+  
+  _dbus_connection_send_preallocated_unlocked_no_update (connection,
+                                                         preallocated,
+                                                         message, client_serial);
+
+  _dbus_verbose ("middle\n");
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+
+  /* this calls out to user code */
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+}
+
+/**
+ * Like dbus_connection_send(), but assumes the connection
+ * is already locked on function entry, and unlocks before returning.
+ *
+ * @param connection the connection
+ * @param message the message to send
+ * @param client_serial return location for client serial of sent message
+ * @returns #FALSE on out-of-memory
+ */
+dbus_bool_t
+_dbus_connection_send_and_unlock (DBusConnection *connection,
+				  DBusMessage    *message,
+				  dbus_uint32_t  *client_serial)
+{
+  DBusPreallocatedSend *preallocated;
+
+  _dbus_assert (connection != NULL);
+  _dbus_assert (message != NULL);
+  
+  preallocated = _dbus_connection_preallocate_send_unlocked (connection);
+  if (preallocated == NULL)
+    {
+      CONNECTION_UNLOCK (connection);
+      return FALSE;
+    }
+
+  _dbus_connection_send_preallocated_and_unlock (connection,
+						 preallocated,
+						 message,
+						 client_serial);
+  return TRUE;
+}
+
+/**
+ * Used internally to handle the semantics of dbus_server_set_new_connection_function().
+ * If the new connection function does not ref the connection, we want to close it.
+ *
+ * A bit of a hack, probably the new connection function should have returned a value
+ * for whether to close, or should have had to close the connection itself if it
+ * didn't want it.
+ *
+ * But, this works OK as long as the new connection function doesn't do anything
+ * crazy like keep the connection around without ref'ing it.
+ *
+ * We have to lock the connection across refcount check and close in case
+ * the new connection function spawns a thread that closes and unrefs.
+ * In that case, if the app thread
+ * closes and unrefs first, we'll harmlessly close again; if the app thread
+ * still has the ref, we'll close and then the app will close harmlessly.
+ * If the app unrefs without closing, the app is broken since if the
+ * app refs from the new connection function it is supposed to also close.
+ *
+ * If we didn't atomically check the refcount and close with the lock held
+ * though, we could screw this up.
+ * 
+ * @param connection the connection
+ */
+void
+_dbus_connection_close_if_only_one_ref (DBusConnection *connection)
+{
+  dbus_int32_t refcount;
+
+  CONNECTION_LOCK (connection);
+
+  refcount = _dbus_atomic_get (&connection->refcount);
+  /* The caller should have at least one ref */
+  _dbus_assert (refcount >= 1);
+
+  if (refcount == 1)
+    _dbus_connection_close_possibly_shared_and_unlock (connection);
+  else
+    CONNECTION_UNLOCK (connection);
+}
+
+
+/**
+ * When a function that blocks has been called with a timeout, and we
+ * run out of memory, the time to wait for memory is based on the
+ * timeout. If the caller was willing to block a long time we wait a
+ * relatively long time for memory, if they were only willing to block
+ * briefly then we retry for memory at a rapid rate.
+ *
+ * @timeout_milliseconds the timeout requested for blocking
+ */
+static void
+_dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
+{
+  if (timeout_milliseconds == -1)
+    _dbus_sleep_milliseconds (1000);
+  else if (timeout_milliseconds < 100)
+    ; /* just busy loop */
+  else if (timeout_milliseconds <= 1000)
+    _dbus_sleep_milliseconds (timeout_milliseconds / 3);
+  else
+    _dbus_sleep_milliseconds (1000);
+}
+
+static DBusMessage *
+generate_local_error_message (dbus_uint32_t serial, 
+                              char *error_name, 
+                              char *error_msg)
+{
+  DBusMessage *message;
+  message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
+  if (!message)
+    goto out;
+
+  if (!dbus_message_set_error_name (message, error_name))
+    {
+      dbus_message_unref (message);
+      message = NULL;
+      goto out; 
+    }
+
+  dbus_message_set_no_reply (message, TRUE); 
+
+  if (!dbus_message_set_reply_serial (message,
+                                      serial))
+    {
+      dbus_message_unref (message);
+      message = NULL;
+      goto out;
+    }
+
+  if (error_msg != NULL)
+    {
+      DBusMessageIter iter;
+
+      dbus_message_iter_init_append (message, &iter);
+      if (!dbus_message_iter_append_basic (&iter,
+                                           DBUS_TYPE_STRING,
+                                           &error_msg))
+        {
+          dbus_message_unref (message);
+          message = NULL;
+	  goto out;
+        }
+    }
+
+ out:
+  return message;
+}
+
+/*
+ * Peek the incoming queue to see if we got reply for a specific serial
+ */
+static dbus_bool_t
+_dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
+                                          dbus_uint32_t   client_serial)
+{
+  DBusList *link;
+  HAVE_LOCK_CHECK (connection);
+
+  link = _dbus_list_get_first_link (&connection->incoming_messages);
+
+  while (link != NULL)
+    {
+      DBusMessage *reply = link->data;
+
+      if (dbus_message_get_reply_serial (reply) == client_serial)
+        {
+          _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
+          return TRUE;
+        }
+      link = _dbus_list_get_next_link (&connection->incoming_messages, link);
+    }
+
+  return FALSE;
+}
+
+/* This is slightly strange since we can pop a message here without
+ * the dispatch lock.
+ */
+static DBusMessage*
+check_for_reply_unlocked (DBusConnection *connection,
+                          dbus_uint32_t   client_serial)
+{
+  DBusList *link;
+
+  HAVE_LOCK_CHECK (connection);
+  
+  link = _dbus_list_get_first_link (&connection->incoming_messages);
+
+  while (link != NULL)
+    {
+      DBusMessage *reply = link->data;
+
+      if (dbus_message_get_reply_serial (reply) == client_serial)
+	{
+	  _dbus_list_remove_link (&connection->incoming_messages, link);
+	  connection->n_incoming  -= 1;
+	  return reply;
+	}
+      link = _dbus_list_get_next_link (&connection->incoming_messages, link);
+    }
+
+  return NULL;
+}
+
+static void
+connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
+{
+   /* We can't iterate over the hash in the normal way since we'll be
+    * dropping the lock for each item. So we restart the
+    * iter each time as we drain the hash table.
+    */
+   
+   while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
+    {
+      DBusPendingCall *pending;
+      DBusHashIter iter;
+      
+      _dbus_hash_iter_init (connection->pending_replies, &iter);
+      _dbus_hash_iter_next (&iter);
+       
+      pending = _dbus_hash_iter_get_value (&iter);
+      _dbus_pending_call_ref_unlocked (pending);
+       
+      _dbus_pending_call_queue_timeout_error_unlocked (pending, 
+                                                       connection);
+
+      if (_dbus_pending_call_is_timeout_added_unlocked (pending))
+          _dbus_connection_remove_timeout_unlocked (connection,
+                                                    _dbus_pending_call_get_timeout_unlocked (pending));
+      _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);       
+      _dbus_hash_iter_remove_entry (&iter);
+
+      _dbus_pending_call_unref_and_unlock (pending);
+      CONNECTION_LOCK (connection);
+    }
+  HAVE_LOCK_CHECK (connection);
+}
+
+static void
+complete_pending_call_and_unlock (DBusConnection  *connection,
+                                  DBusPendingCall *pending,
+                                  DBusMessage     *message)
+{
+  _dbus_pending_call_set_reply_unlocked (pending, message);
+  _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
+  _dbus_connection_detach_pending_call_and_unlock (connection, pending);
+ 
+  /* Must be called unlocked since it invokes app callback */
+  _dbus_pending_call_complete (pending);
+  dbus_pending_call_unref (pending);
+}
+
+static dbus_bool_t
+check_for_reply_and_update_dispatch_unlocked (DBusConnection  *connection,
+                                              DBusPendingCall *pending)
+{
+  DBusMessage *reply;
+  DBusDispatchStatus status;
+
+  reply = check_for_reply_unlocked (connection, 
+                                    _dbus_pending_call_get_reply_serial_unlocked (pending));
+  if (reply != NULL)
+    {
+      _dbus_verbose ("checked for reply\n");
+
+      _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
+
+      complete_pending_call_and_unlock (connection, pending, reply);
+      dbus_message_unref (reply);
+
+      CONNECTION_LOCK (connection);
+      status = _dbus_connection_get_dispatch_status_unlocked (connection);
+      _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+      dbus_pending_call_unref (pending);
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/**
+ * Blocks until a pending call times out or gets a reply.
+ *
+ * Does not re-enter the main loop or run filter/path-registered
+ * callbacks. The reply to the message will not be seen by
+ * filter callbacks.
+ *
+ * Returns immediately if pending call already got a reply.
+ * 
+ * @todo could use performance improvements (it keeps scanning
+ * the whole message queue for example)
+ *
+ * @param pending the pending call we block for a reply on
+ */
+void
+_dbus_connection_block_pending_call (DBusPendingCall *pending)
+{
+  long start_tv_sec, start_tv_usec;
+  long tv_sec, tv_usec;
+  DBusDispatchStatus status;
+  DBusConnection *connection;
+  dbus_uint32_t client_serial;
+  DBusTimeout *timeout;
+  int timeout_milliseconds, elapsed_milliseconds;
+
+  _dbus_assert (pending != NULL);
+
+  if (dbus_pending_call_get_completed (pending))
+    return;
+
+  dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
+
+  connection = _dbus_pending_call_get_connection_and_lock (pending);
+  
+  /* Flush message queue - note, can affect dispatch status */
+  _dbus_connection_flush_unlocked (connection);
+
+  client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
+
+  /* note that timeout_milliseconds is limited to a smallish value
+   * in _dbus_pending_call_new() so overflows aren't possible
+   * below
+   */
+  timeout = _dbus_pending_call_get_timeout_unlocked (pending);
+  _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
+  if (timeout)
+    {
+      timeout_milliseconds = dbus_timeout_get_interval (timeout);
+
+      _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
+                     timeout_milliseconds,
+                     client_serial,
+                     start_tv_sec, start_tv_usec);
+    }
+  else
+    {
+      timeout_milliseconds = -1;
+
+      _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
+    }
+
+  /* check to see if we already got the data off the socket */
+  /* from another blocked pending call */
+  if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
+    return;
+
+  /* Now we wait... */
+  /* always block at least once as we know we don't have the reply yet */
+  _dbus_connection_do_iteration_unlocked (connection,
+                                          pending,
+                                          DBUS_ITERATION_DO_READING |
+                                          DBUS_ITERATION_BLOCK,
+                                          timeout_milliseconds);
+
+ recheck_status:
+
+  _dbus_verbose ("top of recheck\n");
+  
+  HAVE_LOCK_CHECK (connection);
+  
+  /* queue messages and get status */
+
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+
+  /* the get_completed() is in case a dispatch() while we were blocking
+   * got the reply instead of us.
+   */
+  if (_dbus_pending_call_get_completed_unlocked (pending))
+    {
+      _dbus_verbose ("Pending call completed by dispatch\n");
+      _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+      dbus_pending_call_unref (pending);
+      return;
+    }
+  
+  if (status == DBUS_DISPATCH_DATA_REMAINS)
+    {
+      if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
+        return;
+    }
+  
+  _dbus_get_monotonic_time (&tv_sec, &tv_usec);
+  elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
+	  (tv_usec - start_tv_usec) / 1000;
+  
+  if (!_dbus_connection_get_is_connected_unlocked (connection))
+    {
+      DBusMessage *error_msg;
+
+      error_msg = generate_local_error_message (client_serial,
+                                                DBUS_ERROR_DISCONNECTED, 
+                                                "Connection was disconnected before a reply was received"); 
+
+      /* on OOM error_msg is set to NULL */
+      complete_pending_call_and_unlock (connection, pending, error_msg);
+      dbus_pending_call_unref (pending);
+      return;
+    }
+  else if (connection->disconnect_message_link == NULL)
+    _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
+  else if (timeout == NULL)
+    {
+       if (status == DBUS_DISPATCH_NEED_MEMORY)
+        {
+          /* Try sleeping a bit, as we aren't sure we need to block for reading,
+           * we may already have a reply in the buffer and just can't process
+           * it.
+           */
+          _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
+
+          _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
+        }
+      else
+        {          
+          /* block again, we don't have the reply buffered yet. */
+          _dbus_connection_do_iteration_unlocked (connection,
+                                                  pending,
+                                                  DBUS_ITERATION_DO_READING |
+                                                  DBUS_ITERATION_BLOCK,
+                                                  timeout_milliseconds - elapsed_milliseconds);
+        }
+
+      goto recheck_status;
+    }
+  else if (tv_sec < start_tv_sec)
+    _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
+  else if (elapsed_milliseconds < timeout_milliseconds)
+    {
+      _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
+      
+      if (status == DBUS_DISPATCH_NEED_MEMORY)
+        {
+          /* Try sleeping a bit, as we aren't sure we need to block for reading,
+           * we may already have a reply in the buffer and just can't process
+           * it.
+           */
+          _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
+
+          _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
+        }
+      else
+        {          
+          /* block again, we don't have the reply buffered yet. */
+          _dbus_connection_do_iteration_unlocked (connection,
+                                                  NULL,
+                                                  DBUS_ITERATION_DO_READING |
+                                                  DBUS_ITERATION_BLOCK,
+                                                  timeout_milliseconds - elapsed_milliseconds);
+        }
+
+      goto recheck_status;
+    }
+
+  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
+                 elapsed_milliseconds);
+
+  _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
+  
+  /* unlock and call user code */
+  complete_pending_call_and_unlock (connection, pending, NULL);
+
+  /* update user code on dispatch status */
+  CONNECTION_LOCK (connection);
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+  dbus_pending_call_unref (pending);
+}
+
+/** @} */
+
+/**
+ * @addtogroup DBusConnection
+ *
+ * @{
+ */
+
+/**
+ * Gets a connection to a remote address. If a connection to the given
+ * address already exists, returns the existing connection with its
+ * reference count incremented.  Otherwise, returns a new connection
+ * and saves the new connection for possible re-use if a future call
+ * to dbus_connection_open() asks to connect to the same server.
+ *
+ * Use dbus_connection_open_private() to get a dedicated connection
+ * not shared with other callers of dbus_connection_open().
+ *
+ * If the open fails, the function returns #NULL, and provides a
+ * reason for the failure in the error parameter. Pass #NULL for the
+ * error parameter if you aren't interested in the reason for
+ * failure.
+ *
+ * Because this connection is shared, no user of the connection
+ * may call dbus_connection_close(). However, when you are done with the
+ * connection you should call dbus_connection_unref().
+ *
+ * @note Prefer dbus_connection_open() to dbus_connection_open_private()
+ * unless you have good reason; connections are expensive enough
+ * that it's wasteful to create lots of connections to the same
+ * server.
+ * 
+ * @param address the address.
+ * @param error address where an error can be returned.
+ * @returns new connection, or #NULL on failure.
+ */
+DBusConnection*
+dbus_connection_open (const char     *address,
+                      DBusError      *error)
+{
+  DBusConnection *connection;
+
+  _dbus_return_val_if_fail (address != NULL, NULL);
+  _dbus_return_val_if_error_is_set (error, NULL);
+
+  connection = _dbus_connection_open_internal (address,
+                                               TRUE,
+                                               error);
+
+  return connection;
+}
+
+/**
+ * Opens a new, dedicated connection to a remote address. Unlike
+ * dbus_connection_open(), always creates a new connection.
+ * This connection will not be saved or recycled by libdbus.
+ *
+ * If the open fails, the function returns #NULL, and provides a
+ * reason for the failure in the error parameter. Pass #NULL for the
+ * error parameter if you aren't interested in the reason for
+ * failure.
+ *
+ * When you are done with this connection, you must
+ * dbus_connection_close() to disconnect it,
+ * and dbus_connection_unref() to free the connection object.
+ * 
+ * (The dbus_connection_close() can be skipped if the
+ * connection is already known to be disconnected, for example
+ * if you are inside a handler for the Disconnected signal.)
+ *
+ * @note Prefer dbus_connection_open() to dbus_connection_open_private()
+ * unless you have good reason; connections are expensive enough
+ * that it's wasteful to create lots of connections to the same
+ * server.
+ *
+ * @param address the address.
+ * @param error address where an error can be returned.
+ * @returns new connection, or #NULL on failure.
+ */
+DBusConnection*
+dbus_connection_open_private (const char     *address,
+                              DBusError      *error)
+{
+  DBusConnection *connection;
+
+  _dbus_return_val_if_fail (address != NULL, NULL);
+  _dbus_return_val_if_error_is_set (error, NULL);
+
+  connection = _dbus_connection_open_internal (address,
+                                               FALSE,
+                                               error);
+
+  return connection;
+}
+
+/**
+ * Increments the reference count of a DBusConnection.
+ *
+ * @param connection the connection.
+ * @returns the connection.
+ */
+DBusConnection *
+dbus_connection_ref (DBusConnection *connection)
+{
+  dbus_int32_t old_refcount;
+
+  _dbus_return_val_if_fail (connection != NULL, NULL);
+  _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
+  old_refcount = _dbus_atomic_inc (&connection->refcount);
+  _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
+      "ref");
+
+  return connection;
+}
+
+static void
+free_outgoing_message (void *element,
+                       void *data)
+{
+  DBusMessage *message = element;
+  DBusConnection *connection = data;
+
+  _dbus_message_remove_counter (message, connection->outgoing_counter);
+  dbus_message_unref (message);
+}
+
+/* This is run without the mutex held, but after the last reference
+ * to the connection has been dropped we should have no thread-related
+ * problems
+ */
+static void
+_dbus_connection_last_unref (DBusConnection *connection)
+{
+  DBusList *link;
+
+  _dbus_verbose ("Finalizing connection %p\n", connection);
+
+  _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
+
+  /* You have to disconnect the connection before unref:ing it. Otherwise
+   * you won't get the disconnected message.
+   */
+  _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
+  _dbus_assert (connection->server_guid == NULL);
+  
+  /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
+  _dbus_object_tree_free_all_unlocked (connection->objects);
+  
+  dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
+  dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
+  dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
+  
+  _dbus_watch_list_free (connection->watches);
+  connection->watches = NULL;
+  
+  _dbus_timeout_list_free (connection->timeouts);
+  connection->timeouts = NULL;
+
+  _dbus_data_slot_list_free (&connection->slot_list);
+  
+  link = _dbus_list_get_first_link (&connection->filter_list);
+  while (link != NULL)
+    {
+      DBusMessageFilter *filter = link->data;
+      DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
+
+      filter->function = NULL;
+      _dbus_message_filter_unref (filter); /* calls app callback */
+      link->data = NULL;
+      
+      link = next;
+    }
+  _dbus_list_clear (&connection->filter_list);
+  
+  /* ---- Done with stuff that invokes application callbacks */
+
+  _dbus_object_tree_unref (connection->objects);  
+
+  _dbus_hash_table_unref (connection->pending_replies);
+  connection->pending_replies = NULL;
+  
+  _dbus_list_clear (&connection->filter_list);
+  
+  _dbus_list_foreach (&connection->outgoing_messages,
+                      free_outgoing_message,
+		      connection);
+  _dbus_list_clear (&connection->outgoing_messages);
+  
+  _dbus_list_foreach (&connection->incoming_messages,
+		      (DBusForeachFunction) dbus_message_unref,
+		      NULL);
+  _dbus_list_clear (&connection->incoming_messages);
+
+  _dbus_counter_unref (connection->outgoing_counter);
+
+  _dbus_transport_unref (connection->transport);
+
+  if (connection->disconnect_message_link)
+    {
+      DBusMessage *message = connection->disconnect_message_link->data;
+      dbus_message_unref (message);
+      _dbus_list_free_link (connection->disconnect_message_link);
+    }
+
+  _dbus_condvar_free_at_location (&connection->dispatch_cond);
+  _dbus_condvar_free_at_location (&connection->io_path_cond);
+
+  _dbus_cmutex_free_at_location (&connection->io_path_mutex);
+  _dbus_cmutex_free_at_location (&connection->dispatch_mutex);
+
+  _dbus_rmutex_free_at_location (&connection->slot_mutex);
+
+  _dbus_rmutex_free_at_location (&connection->mutex);
+  
+  dbus_free (connection);
+}
+
+/**
+ * Decrements the reference count of a DBusConnection, and finalizes
+ * it if the count reaches zero.
+ *
+ * Note: it is a bug to drop the last reference to a connection that
+ * is still connected.
+ *
+ * For shared connections, libdbus will own a reference
+ * as long as the connection is connected, so you can know that either
+ * you don't have the last reference, or it's OK to drop the last reference.
+ * Most connections are shared. dbus_connection_open() and dbus_bus_get()
+ * return shared connections.
+ *
+ * For private connections, the creator of the connection must arrange for
+ * dbus_connection_close() to be called prior to dropping the last reference.
+ * Private connections come from dbus_connection_open_private() or dbus_bus_get_private().
+ *
+ * @param connection the connection.
+ */
+void
+dbus_connection_unref (DBusConnection *connection)
+{
+  dbus_int32_t old_refcount;
+
+  _dbus_return_if_fail (connection != NULL);
+  _dbus_return_if_fail (connection->generation == _dbus_current_generation);
+
+  old_refcount = _dbus_atomic_dec (&connection->refcount);
+
+  _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
+      "unref");
+
+  if (old_refcount == 1)
+    {
+#ifndef DBUS_DISABLE_CHECKS
+      if (_dbus_transport_get_is_connected (connection->transport))
+        {
+          _dbus_warn_check_failed ("The last reference on a connection was dropped without closing the connection. This is a bug in an application. See dbus_connection_unref() documentation for details.\n%s",
+                                   connection->shareable ?
+                                   "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
+                                    "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
+          return;
+        }
+#endif
+      _dbus_connection_last_unref (connection);
+    }
+}
+
+/*
+ * Note that the transport can disconnect itself (other end drops us)
+ * and in that case this function never runs. So this function must
+ * not do anything more than disconnect the transport and update the
+ * dispatch status.
+ * 
+ * If the transport self-disconnects, then we assume someone will
+ * dispatch the connection to cause the dispatch status update.
+ */
+static void
+_dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
+{
+  DBusDispatchStatus status;
+
+  HAVE_LOCK_CHECK (connection);
+  
+  _dbus_verbose ("Disconnecting %p\n", connection);
+
+  /* We need to ref because update_dispatch_status_and_unlock will unref
+   * the connection if it was shared and libdbus was the only remaining
+   * refcount holder.
+   */
+  _dbus_connection_ref_unlocked (connection);
+  
+  _dbus_transport_disconnect (connection->transport);
+
+  /* This has the side effect of queuing the disconnect message link
+   * (unless we don't have enough memory, possibly, so don't assert it).
+   * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
+   * should never again return the newly-disconnected connection.
+   *
+   * However, we only unref the shared connection and exit_on_disconnect when
+   * the disconnect message reaches the head of the message queue,
+   * NOT when it's first queued.
+   */
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+
+  /* This calls out to user code */
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+
+  /* Could also call out to user code */
+  dbus_connection_unref (connection);
+}
+
+/**
+ * Closes a private connection, so no further data can be sent or received.
+ * This disconnects the transport (such as a socket) underlying the
+ * connection.
+ *
+ * Attempts to send messages after closing a connection are safe, but will result in
+ * error replies generated locally in libdbus.
+ * 
+ * This function does not affect the connection's reference count.  It's
+ * safe to close a connection more than once; all calls after the
+ * first do nothing. It's impossible to "reopen" a connection, a
+ * new connection must be created. This function may result in a call
+ * to the DBusDispatchStatusFunction set with
+ * dbus_connection_set_dispatch_status_function(), as the disconnect
+ * message it generates needs to be dispatched.
+ *
+ * If a connection is dropped by the remote application, it will
+ * close itself. 
+ * 
+ * You must close a connection prior to releasing the last reference to
+ * the connection. If you dbus_connection_unref() for the last time
+ * without closing the connection, the results are undefined; it
+ * is a bug in your program and libdbus will try to print a warning.
+ *
+ * You may not close a shared connection. Connections created with
+ * dbus_connection_open() or dbus_bus_get() are shared.
+ * These connections are owned by libdbus, and applications should
+ * only unref them, never close them. Applications can know it is
+ * safe to unref these connections because libdbus will be holding a
+ * reference as long as the connection is open. Thus, either the
+ * connection is closed and it is OK to drop the last reference,
+ * or the connection is open and the app knows it does not have the
+ * last reference.
+ *
+ * Connections created with dbus_connection_open_private() or
+ * dbus_bus_get_private() are not kept track of or referenced by
+ * libdbus. The creator of these connections is responsible for
+ * calling dbus_connection_close() prior to releasing the last
+ * reference, if the connection is not already disconnected.
+ *
+ * @param connection the private (unshared) connection to close
+ */
+void
+dbus_connection_close (DBusConnection *connection)
+{
+  _dbus_return_if_fail (connection != NULL);
+  _dbus_return_if_fail (connection->generation == _dbus_current_generation);
+
+  CONNECTION_LOCK (connection);
+
+#ifndef DBUS_DISABLE_CHECKS
+  if (connection->shareable)
+    {
+      CONNECTION_UNLOCK (connection);
+
+      _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
+      return;
+    }
+#endif
+  
+  _dbus_connection_close_possibly_shared_and_unlock (connection);
+}
+
+static dbus_bool_t
+_dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+  return _dbus_transport_get_is_connected (connection->transport);
+}
+
+/**
+ * Gets whether the connection is currently open.  A connection may
+ * become disconnected when the remote application closes its end, or
+ * exits; a connection may also be disconnected with
+ * dbus_connection_close().
+ * 
+ * There are not separate states for "closed" and "disconnected," the two
+ * terms are synonymous. This function should really be called
+ * get_is_open() but for historical reasons is not.
+ *
+ * @param connection the connection.
+ * @returns #TRUE if the connection is still alive.
+ */
+dbus_bool_t
+dbus_connection_get_is_connected (DBusConnection *connection)
+{
+  dbus_bool_t res;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+  res = _dbus_connection_get_is_connected_unlocked (connection);
+  CONNECTION_UNLOCK (connection);
+  
+  return res;
+}
+
+/**
+ * Gets whether the connection was authenticated. (Note that
+ * if the connection was authenticated then disconnected,
+ * this function still returns #TRUE)
+ *
+ * @param connection the connection
+ * @returns #TRUE if the connection was ever authenticated
+ */
+dbus_bool_t
+dbus_connection_get_is_authenticated (DBusConnection *connection)
+{
+  dbus_bool_t res;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+  res = _dbus_transport_get_is_authenticated (connection->transport);
+  CONNECTION_UNLOCK (connection);
+  
+  return res;
+}
+
+/**
+ * Gets whether the connection is not authenticated as a specific
+ * user.  If the connection is not authenticated, this function
+ * returns #TRUE, and if it is authenticated but as an anonymous user,
+ * it returns #TRUE.  If it is authenticated as a specific user, then
+ * this returns #FALSE. (Note that if the connection was authenticated
+ * as anonymous then disconnected, this function still returns #TRUE.)
+ *
+ * If the connection is not anonymous, you can use
+ * dbus_connection_get_unix_user() and
+ * dbus_connection_get_windows_user() to see who it's authorized as.
+ *
+ * If you want to prevent non-anonymous authorization, use
+ * dbus_server_set_auth_mechanisms() to remove the mechanisms that
+ * allow proving user identity (i.e. only allow the ANONYMOUS
+ * mechanism).
+ * 
+ * @param connection the connection
+ * @returns #TRUE if not authenticated or authenticated as anonymous 
+ */
+dbus_bool_t
+dbus_connection_get_is_anonymous (DBusConnection *connection)
+{
+  dbus_bool_t res;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+  res = _dbus_transport_get_is_anonymous (connection->transport);
+  CONNECTION_UNLOCK (connection);
+  
+  return res;
+}
+
+/**
+ * Gets the ID of the server address we are authenticated to, if this
+ * connection is on the client side. If the connection is on the
+ * server side, this will always return #NULL - use dbus_server_get_id()
+ * to get the ID of your own server, if you are the server side.
+ * 
+ * If a client-side connection is not authenticated yet, the ID may be
+ * available if it was included in the server address, but may not be
+ * available. The only way to be sure the server ID is available
+ * is to wait for authentication to complete.
+ *
+ * In general, each mode of connecting to a given server will have
+ * its own ID. So for example, if the session bus daemon is listening
+ * on UNIX domain sockets and on TCP, then each of those modalities
+ * will have its own server ID.
+ *
+ * If you want an ID that identifies an entire session bus, look at
+ * dbus_bus_get_id() instead (which is just a convenience wrapper
+ * around the org.freedesktop.DBus.GetId method invoked on the bus).
+ *
+ * You can also get a machine ID; see dbus_get_local_machine_id() to
+ * get the machine you are on.  There isn't a convenience wrapper, but
+ * you can invoke org.freedesktop.DBus.Peer.GetMachineId on any peer
+ * to get the machine ID on the other end.
+ * 
+ * The D-Bus specification describes the server ID and other IDs in a
+ * bit more detail.
+ *
+ * @param connection the connection
+ * @returns the server ID or #NULL if no memory or the connection is server-side
+ */
+char*
+dbus_connection_get_server_id (DBusConnection *connection)
+{
+  char *id;
+
+  _dbus_return_val_if_fail (connection != NULL, NULL);
+
+  CONNECTION_LOCK (connection);
+  id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
+  CONNECTION_UNLOCK (connection);
+
+  return id;
+}
+
+/**
+ * Tests whether a certain type can be send via the connection. This
+ * will always return TRUE for all types, with the exception of
+ * DBUS_TYPE_UNIX_FD. The function will return TRUE for
+ * DBUS_TYPE_UNIX_FD only on systems that know Unix file descriptors
+ * and can send them via the chosen transport and when the remote side
+ * supports this.
+ *
+ * This function can be used to do runtime checking for types that
+ * might be unknown to the specific D-Bus client implementation
+ * version, i.e. it will return FALSE for all types this
+ * implementation does not know, including invalid or reserved types.
+ *
+ * @param connection the connection
+ * @param type the type to check
+ * @returns TRUE if the type may be send via the connection
+ */
+dbus_bool_t
+dbus_connection_can_send_type(DBusConnection *connection,
+                                  int type)
+{
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+
+  if (!dbus_type_is_valid (type))
+    return FALSE;
+
+  if (type != DBUS_TYPE_UNIX_FD)
+    return TRUE;
+
+#ifdef HAVE_UNIX_FD_PASSING
+  {
+    dbus_bool_t b;
+
+    CONNECTION_LOCK(connection);
+    b = _dbus_transport_can_pass_unix_fd(connection->transport);
+    CONNECTION_UNLOCK(connection);
+
+    return b;
+  }
+#endif
+
+  return FALSE;
+}
+
+/**
+ * Set whether _exit() should be called when the connection receives a
+ * disconnect signal. The call to _exit() comes after any handlers for
+ * the disconnect signal run; handlers can cancel the exit by calling
+ * this function.
+ *
+ * By default, exit_on_disconnect is #FALSE; but for message bus
+ * connections returned from dbus_bus_get() it will be toggled on
+ * by default.
+ *
+ * @param connection the connection
+ * @param exit_on_disconnect #TRUE if _exit() should be called after a disconnect signal
+ */
+void
+dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
+                                        dbus_bool_t     exit_on_disconnect)
+{
+  _dbus_return_if_fail (connection != NULL);
+
+  CONNECTION_LOCK (connection);
+  connection->exit_on_disconnect = exit_on_disconnect != FALSE;
+  CONNECTION_UNLOCK (connection);
+}
+
+/**
+ * Preallocates resources needed to send a message, allowing the message 
+ * to be sent without the possibility of memory allocation failure.
+ * Allows apps to create a future guarantee that they can send
+ * a message regardless of memory shortages.
+ *
+ * @param connection the connection we're preallocating for.
+ * @returns the preallocated resources, or #NULL
+ */
+DBusPreallocatedSend*
+dbus_connection_preallocate_send (DBusConnection *connection)
+{
+  DBusPreallocatedSend *preallocated;
+
+  _dbus_return_val_if_fail (connection != NULL, NULL);
+
+  CONNECTION_LOCK (connection);
+  
+  preallocated =
+    _dbus_connection_preallocate_send_unlocked (connection);
+
+  CONNECTION_UNLOCK (connection);
+
+  return preallocated;
+}
+
+/**
+ * Frees preallocated message-sending resources from
+ * dbus_connection_preallocate_send(). Should only
+ * be called if the preallocated resources are not used
+ * to send a message.
+ *
+ * @param connection the connection
+ * @param preallocated the resources
+ */
+void
+dbus_connection_free_preallocated_send (DBusConnection       *connection,
+                                        DBusPreallocatedSend *preallocated)
+{
+  _dbus_return_if_fail (connection != NULL);
+  _dbus_return_if_fail (preallocated != NULL);  
+  _dbus_return_if_fail (connection == preallocated->connection);
+
+  _dbus_list_free_link (preallocated->queue_link);
+  _dbus_counter_unref (preallocated->counter_link->data);
+  _dbus_list_free_link (preallocated->counter_link);
+  dbus_free (preallocated);
+}
+
+/**
+ * Sends a message using preallocated resources. This function cannot fail.
+ * It works identically to dbus_connection_send() in other respects.
+ * Preallocated resources comes from dbus_connection_preallocate_send().
+ * This function "consumes" the preallocated resources, they need not
+ * be freed separately.
+ *
+ * @param connection the connection
+ * @param preallocated the preallocated resources
+ * @param message the message to send
+ * @param client_serial return location for client serial assigned to the message
+ */
+void
+dbus_connection_send_preallocated (DBusConnection       *connection,
+                                   DBusPreallocatedSend *preallocated,
+                                   DBusMessage          *message,
+                                   dbus_uint32_t        *client_serial)
+{
+  _dbus_return_if_fail (connection != NULL);
+  _dbus_return_if_fail (preallocated != NULL);
+  _dbus_return_if_fail (message != NULL);
+  _dbus_return_if_fail (preallocated->connection == connection);
+  _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
+                        dbus_message_get_member (message) != NULL);
+  _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
+                        (dbus_message_get_interface (message) != NULL &&
+                         dbus_message_get_member (message) != NULL));
+
+  CONNECTION_LOCK (connection);
+
+#ifdef HAVE_UNIX_FD_PASSING
+
+  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
+      message->n_unix_fds > 0)
+    {
+      /* Refuse to send fds on a connection that cannot handle
+         them. Unfortunately we cannot return a proper error here, so
+         the best we can is just return. */
+      CONNECTION_UNLOCK (connection);
+      return;
+    }
+
+#endif
+
+  _dbus_connection_send_preallocated_and_unlock (connection,
+						 preallocated,
+						 message, client_serial);
+}
+
+static dbus_bool_t
+_dbus_connection_send_unlocked_no_update (DBusConnection *connection,
+                                          DBusMessage    *message,
+                                          dbus_uint32_t  *client_serial)
+{
+  DBusPreallocatedSend *preallocated;
+
+  _dbus_assert (connection != NULL);
+  _dbus_assert (message != NULL);
+  
+  preallocated = _dbus_connection_preallocate_send_unlocked (connection);
+  if (preallocated == NULL)
+    return FALSE;
+
+  _dbus_connection_send_preallocated_unlocked_no_update (connection,
+                                                         preallocated,
+                                                         message,
+                                                         client_serial);
+  return TRUE;
+}
+
+/**
+ * Adds a message to the outgoing message queue. Does not block to
+ * write the message to the network; that happens asynchronously. To
+ * force the message to be written, call dbus_connection_flush() however
+ * it is not necessary to call dbus_connection_flush() by hand; the 
+ * message will be sent the next time the main loop is run. 
+ * dbus_connection_flush() should only be used, for example, if
+ * the application was expected to exit before running the main loop.
+ *
+ * Because this only queues the message, the only reason it can
+ * fail is lack of memory. Even if the connection is disconnected,
+ * no error will be returned. If the function fails due to lack of memory, 
+ * it returns #FALSE. The function will never fail for other reasons; even 
+ * if the connection is disconnected, you can queue an outgoing message,
+ * though obviously it won't be sent.
+ *
+ * The message serial is used by the remote application to send a
+ * reply; see dbus_message_get_serial() or the D-Bus specification.
+ *
+ * dbus_message_unref() can be called as soon as this method returns
+ * as the message queue will hold its own ref until the message is sent.
+ * 
+ * @param connection the connection.
+ * @param message the message to write.
+ * @param serial return location for message serial, or #NULL if you don't care
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+dbus_connection_send (DBusConnection *connection,
+                      DBusMessage    *message,
+                      dbus_uint32_t  *serial)
+{
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+
+  CONNECTION_LOCK (connection);
+
+#ifdef HAVE_UNIX_FD_PASSING
+
+  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
+      message->n_unix_fds > 0)
+    {
+      /* Refuse to send fds on a connection that cannot handle
+         them. Unfortunately we cannot return a proper error here, so
+         the best we can is just return. */
+      CONNECTION_UNLOCK (connection);
+      return FALSE;
+    }
+
+#endif
+
+  return _dbus_connection_send_and_unlock (connection,
+					   message,
+					   serial);
+}
+
+static dbus_bool_t
+reply_handler_timeout (void *data)
+{
+  DBusConnection *connection;
+  DBusDispatchStatus status;
+  DBusPendingCall *pending = data;
+
+  connection = _dbus_pending_call_get_connection_and_lock (pending);
+  _dbus_connection_ref_unlocked (connection);
+
+  _dbus_pending_call_queue_timeout_error_unlocked (pending, 
+                                                   connection);
+  _dbus_connection_remove_timeout_unlocked (connection,
+				            _dbus_pending_call_get_timeout_unlocked (pending));
+  _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
+
+  _dbus_verbose ("middle\n");
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+
+  /* Unlocks, and calls out to user code */
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+  dbus_connection_unref (connection);
+  
+  return TRUE;
+}
+
+/**
+ * Queues a message to send, as with dbus_connection_send(),
+ * but also returns a #DBusPendingCall used to receive a reply to the
+ * message. If no reply is received in the given timeout_milliseconds,
+ * this function expires the pending reply and generates a synthetic
+ * error reply (generated in-process, not by the remote application)
+ * indicating that a timeout occurred.
+ *
+ * A #DBusPendingCall will see a reply message before any filters or
+ * registered object path handlers. See dbus_connection_dispatch() for
+ * details on when handlers are run.
+ *
+ * A #DBusPendingCall will always see exactly one reply message,
+ * unless it's cancelled with dbus_pending_call_cancel().
+ * 
+ * If #NULL is passed for the pending_return, the #DBusPendingCall
+ * will still be generated internally, and used to track
+ * the message reply timeout. This means a timeout error will
+ * occur if no reply arrives, unlike with dbus_connection_send().
+ *
+ * If -1 is passed for the timeout, a sane default timeout is used. -1
+ * is typically the best value for the timeout for this reason, unless
+ * you want a very short or very long timeout.  If #DBUS_TIMEOUT_INFINITE is
+ * passed for the timeout, no timeout will be set and the call will block
+ * forever.
+ *
+ * @warning if the connection is disconnected or you try to send Unix
+ * file descriptors on a connection that does not support them, the
+ * #DBusPendingCall will be set to #NULL, so be careful with this.
+ *
+ * @param connection the connection
+ * @param message the message to send
+ * @param pending_return return location for a #DBusPendingCall
+ * object, or #NULL if connection is disconnected or when you try to
+ * send Unix file descriptors on a connection that does not support
+ * them.
+ * @param timeout_milliseconds timeout in milliseconds, -1 (or
+ *  #DBUS_TIMEOUT_USE_DEFAULT) for default or #DBUS_TIMEOUT_INFINITE for no
+ *  timeout
+ * @returns #FALSE if no memory, #TRUE otherwise.
+ *
+ */
+dbus_bool_t
+dbus_connection_send_with_reply (DBusConnection     *connection,
+                                 DBusMessage        *message,
+                                 DBusPendingCall   **pending_return,
+                                 int                 timeout_milliseconds)
+{
+  DBusPendingCall *pending;
+  dbus_int32_t serial = -1;
+  DBusDispatchStatus status;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
+
+  if (pending_return)
+    *pending_return = NULL;
+
+  CONNECTION_LOCK (connection);
+
+#ifdef HAVE_UNIX_FD_PASSING
+
+  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
+      message->n_unix_fds > 0)
+    {
+      /* Refuse to send fds on a connection that cannot handle
+         them. Unfortunately we cannot return a proper error here, so
+         the best we can do is return TRUE but leave *pending_return
+         as NULL. */
+      CONNECTION_UNLOCK (connection);
+      return TRUE;
+    }
+
+#endif
+
+   if (!_dbus_connection_get_is_connected_unlocked (connection))
+    {
+      CONNECTION_UNLOCK (connection);
+
+      return TRUE;
+    }
+
+  pending = _dbus_pending_call_new_unlocked (connection,
+                                             timeout_milliseconds,
+                                             reply_handler_timeout);
+
+  if (pending == NULL)
+    {
+      CONNECTION_UNLOCK (connection);
+      return FALSE;
+    }
+
+  /* Assign a serial to the message */
+  serial = dbus_message_get_serial (message);
+  if (serial == 0)
+    {
+      serial = _dbus_connection_get_next_client_serial (connection);
+      dbus_message_set_serial (message, serial);
+    }
+
+  if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
+    goto error;
+    
+  /* Insert the serial in the pending replies hash;
+   * hash takes a refcount on DBusPendingCall.
+   * Also, add the timeout.
+   */
+  if (!_dbus_connection_attach_pending_call_unlocked (connection,
+						      pending))
+    goto error;
+ 
+  if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
+    {
+      _dbus_connection_detach_pending_call_and_unlock (connection,
+						       pending);
+      goto error_unlocked;
+    }
+
+  if (pending_return)
+    *pending_return = pending; /* hand off refcount */
+  else
+    {
+      _dbus_connection_detach_pending_call_unlocked (connection, pending);
+      /* we still have a ref to the pending call in this case, we unref
+       * after unlocking, below
+       */
+    }
+
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+
+  /* this calls out to user code */
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+
+  if (pending_return == NULL)
+    dbus_pending_call_unref (pending);
+  
+  return TRUE;
+
+ error:
+  CONNECTION_UNLOCK (connection);
+ error_unlocked:
+  dbus_pending_call_unref (pending);
+  return FALSE;
+}
+
+/**
+ * Sends a message and blocks a certain time period while waiting for
+ * a reply.  This function does not reenter the main loop,
+ * i.e. messages other than the reply are queued up but not
+ * processed. This function is used to invoke method calls on a
+ * remote object.
+ * 
+ * If a normal reply is received, it is returned, and removed from the
+ * incoming message queue. If it is not received, #NULL is returned
+ * and the error is set to #DBUS_ERROR_NO_REPLY.  If an error reply is
+ * received, it is converted to a #DBusError and returned as an error,
+ * then the reply message is deleted and #NULL is returned. If
+ * something else goes wrong, result is set to whatever is
+ * appropriate, such as #DBUS_ERROR_NO_MEMORY or
+ * #DBUS_ERROR_DISCONNECTED.
+ *
+ * @warning While this function blocks the calling thread will not be
+ * processing the incoming message queue. This means you can end up
+ * deadlocked if the application you're talking to needs you to reply
+ * to a method. To solve this, either avoid the situation, block in a
+ * separate thread from the main connection-dispatching thread, or use
+ * dbus_pending_call_set_notify() to avoid blocking.
+ *
+ * @param connection the connection
+ * @param message the message to send
+ * @param timeout_milliseconds timeout in milliseconds, -1 (or
+ *  #DBUS_TIMEOUT_USE_DEFAULT) for default or #DBUS_TIMEOUT_INFINITE for no
+ *  timeout
+ * @param error return location for error message
+ * @returns the message that is the reply or #NULL with an error code if the
+ * function fails.
+ */
+DBusMessage*
+dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
+                                           DBusMessage        *message,
+                                           int                 timeout_milliseconds,
+                                           DBusError          *error)
+{
+  DBusMessage *reply;
+  DBusPendingCall *pending;
+
+  _dbus_return_val_if_fail (connection != NULL, NULL);
+  _dbus_return_val_if_fail (message != NULL, NULL);
+  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
+  _dbus_return_val_if_error_is_set (error, NULL);
+
+#ifdef HAVE_UNIX_FD_PASSING
+
+  CONNECTION_LOCK (connection);
+  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
+      message->n_unix_fds > 0)
+    {
+      CONNECTION_UNLOCK (connection);
+      dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
+      return NULL;
+    }
+  CONNECTION_UNLOCK (connection);
+
+#endif
+
+  if (!dbus_connection_send_with_reply (connection, message,
+                                        &pending, timeout_milliseconds))
+    {
+      _DBUS_SET_OOM (error);
+      return NULL;
+    }
+
+  if (pending == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
+      return NULL;
+    }
+  
+  dbus_pending_call_block (pending);
+
+  reply = dbus_pending_call_steal_reply (pending);
+  dbus_pending_call_unref (pending);
+
+  /* call_complete_and_unlock() called from pending_call_block() should
+   * always fill this in.
+   */
+  _dbus_assert (reply != NULL);
+  
+   if (dbus_set_error_from_message (error, reply))
+    {
+      dbus_message_unref (reply);
+      return NULL;
+    }
+  else
+    return reply;
+}
+
+/**
+ * Blocks until the outgoing message queue is empty.
+ * Assumes connection lock already held.
+ *
+ * If you call this, you MUST call update_dispatch_status afterword...
+ * 
+ * @param connection the connection.
+ */
+static DBusDispatchStatus
+_dbus_connection_flush_unlocked (DBusConnection *connection)
+{
+  /* We have to specify DBUS_ITERATION_DO_READING here because
+   * otherwise we could have two apps deadlock if they are both doing
+   * a flush(), and the kernel buffers fill up. This could change the
+   * dispatch status.
+   */
+  DBusDispatchStatus status;
+
+  HAVE_LOCK_CHECK (connection);
+  
+  while (connection->n_outgoing > 0 &&
+         _dbus_connection_get_is_connected_unlocked (connection))
+    {
+      _dbus_verbose ("doing iteration in\n");
+      HAVE_LOCK_CHECK (connection);
+      _dbus_connection_do_iteration_unlocked (connection,
+                                              NULL,
+                                              DBUS_ITERATION_DO_READING |
+                                              DBUS_ITERATION_DO_WRITING |
+                                              DBUS_ITERATION_BLOCK,
+                                              -1);
+    }
+
+  HAVE_LOCK_CHECK (connection);
+  _dbus_verbose ("middle\n");
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+
+  HAVE_LOCK_CHECK (connection);
+  return status;
+}
+
+/**
+ * Blocks until the outgoing message queue is empty.
+ *
+ * @param connection the connection.
+ */
+void
+dbus_connection_flush (DBusConnection *connection)
+{
+  /* We have to specify DBUS_ITERATION_DO_READING here because
+   * otherwise we could have two apps deadlock if they are both doing
+   * a flush(), and the kernel buffers fill up. This could change the
+   * dispatch status.
+   */
+  DBusDispatchStatus status;
+
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+
+  status = _dbus_connection_flush_unlocked (connection);
+  
+  HAVE_LOCK_CHECK (connection);
+  /* Unlocks and calls out to user code */
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+
+  _dbus_verbose ("end\n");
+}
+
+/**
+ * This function implements dbus_connection_read_write_dispatch() and
+ * dbus_connection_read_write() (they pass a different value for the
+ * dispatch parameter).
+ * 
+ * @param connection the connection
+ * @param timeout_milliseconds max time to block or -1 for infinite
+ * @param dispatch dispatch new messages or leave them on the incoming queue
+ * @returns #TRUE if the disconnect message has not been processed
+ */
+static dbus_bool_t
+_dbus_connection_read_write_dispatch (DBusConnection *connection,
+                                     int             timeout_milliseconds, 
+                                     dbus_bool_t     dispatch)
+{
+  DBusDispatchStatus dstatus;
+  dbus_bool_t progress_possible;
+
+  /* Need to grab a ref here in case we're a private connection and
+   * the user drops the last ref in a handler we call; see bug 
+   * https://bugs.freedesktop.org/show_bug.cgi?id=15635
+   */
+  dbus_connection_ref (connection);
+  dstatus = dbus_connection_get_dispatch_status (connection);
+
+  if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
+    {
+      _dbus_verbose ("doing dispatch\n");
+      dbus_connection_dispatch (connection);
+      CONNECTION_LOCK (connection);
+    }
+  else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
+    {
+      _dbus_verbose ("pausing for memory\n");
+      _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
+      CONNECTION_LOCK (connection);
+    }
+  else
+    {
+      CONNECTION_LOCK (connection);
+      if (_dbus_connection_get_is_connected_unlocked (connection))
+        {
+          _dbus_verbose ("doing iteration\n");
+          _dbus_connection_do_iteration_unlocked (connection,
+                                                  NULL,
+                                                  DBUS_ITERATION_DO_READING |
+                                                  DBUS_ITERATION_DO_WRITING |
+                                                  DBUS_ITERATION_BLOCK,
+                                                  timeout_milliseconds);
+        }
+    }
+  
+  HAVE_LOCK_CHECK (connection);
+  /* If we can dispatch, we can make progress until the Disconnected message
+   * has been processed; if we can only read/write, we can make progress
+   * as long as the transport is open.
+   */
+  if (dispatch)
+    progress_possible = connection->n_incoming != 0 ||
+      connection->disconnect_message_link != NULL;
+  else
+    progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
+
+  CONNECTION_UNLOCK (connection);
+
+  dbus_connection_unref (connection);
+
+  return progress_possible; /* TRUE if we can make more progress */
+}
+
+
+/**
+ * This function is intended for use with applications that don't want
+ * to write a main loop and deal with #DBusWatch and #DBusTimeout. An
+ * example usage would be:
+ * 
+ * @code
+ *   while (dbus_connection_read_write_dispatch (connection, -1))
+ *     ; // empty loop body
+ * @endcode
+ * 
+ * In this usage you would normally have set up a filter function to look
+ * at each message as it is dispatched. The loop terminates when the last
+ * message from the connection (the disconnected signal) is processed.
+ * 
+ * If there are messages to dispatch, this function will
+ * dbus_connection_dispatch() once, and return. If there are no
+ * messages to dispatch, this function will block until it can read or
+ * write, then read or write, then return.
+ *
+ * The way to think of this function is that it either makes some sort
+ * of progress, or it blocks. Note that, while it is blocked on I/O, it
+ * cannot be interrupted (even by other threads), which makes this function
+ * unsuitable for applications that do more than just react to received
+ * messages.
+ *
+ * The return value indicates whether the disconnect message has been
+ * processed, NOT whether the connection is connected. This is
+ * important because even after disconnecting, you want to process any
+ * messages you received prior to the disconnect.
+ *
+ * @param connection the connection
+ * @param timeout_milliseconds max time to block or -1 for infinite
+ * @returns #TRUE if the disconnect message has not been processed
+ */
+dbus_bool_t
+dbus_connection_read_write_dispatch (DBusConnection *connection,
+                                     int             timeout_milliseconds)
+{
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
+   return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
+}
+
+/** 
+ * This function is intended for use with applications that don't want to
+ * write a main loop and deal with #DBusWatch and #DBusTimeout. See also
+ * dbus_connection_read_write_dispatch().
+ * 
+ * As long as the connection is open, this function will block until it can
+ * read or write, then read or write, then return #TRUE.
+ *
+ * If the connection is closed, the function returns #FALSE.
+ *
+ * The return value indicates whether reading or writing is still
+ * possible, i.e. whether the connection is connected.
+ *
+ * Note that even after disconnection, messages may remain in the
+ * incoming queue that need to be
+ * processed. dbus_connection_read_write_dispatch() dispatches
+ * incoming messages for you; with dbus_connection_read_write() you
+ * have to arrange to drain the incoming queue yourself.
+ * 
+ * @param connection the connection 
+ * @param timeout_milliseconds max time to block or -1 for infinite 
+ * @returns #TRUE if still connected
+ */
+dbus_bool_t 
+dbus_connection_read_write (DBusConnection *connection, 
+                            int             timeout_milliseconds) 
+{ 
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
+   return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
+}
+
+/* We need to call this anytime we pop the head of the queue, and then
+ * update_dispatch_status_and_unlock needs to be called afterward
+ * which will "process" the disconnected message and set
+ * disconnected_message_processed.
+ */
+static void
+check_disconnected_message_arrived_unlocked (DBusConnection *connection,
+                                             DBusMessage    *head_of_queue)
+{
+  HAVE_LOCK_CHECK (connection);
+
+  /* checking that the link is NULL is an optimization to avoid the is_signal call */
+  if (connection->disconnect_message_link == NULL &&
+      dbus_message_is_signal (head_of_queue,
+                              DBUS_INTERFACE_LOCAL,
+                              "Disconnected"))
+    {
+      connection->disconnected_message_arrived = TRUE;
+    }
+}
+
+/**
+ * Returns the first-received message from the incoming message queue,
+ * leaving it in the queue. If the queue is empty, returns #NULL.
+ * 
+ * The caller does not own a reference to the returned message, and
+ * must either return it using dbus_connection_return_message() or
+ * keep it after calling dbus_connection_steal_borrowed_message(). No
+ * one can get at the message while its borrowed, so return it as
+ * quickly as possible and don't keep a reference to it after
+ * returning it. If you need to keep the message, make a copy of it.
+ *
+ * dbus_connection_dispatch() will block if called while a borrowed
+ * message is outstanding; only one piece of code can be playing with
+ * the incoming queue at a time. This function will block if called
+ * during a dbus_connection_dispatch().
+ *
+ * @param connection the connection.
+ * @returns next message in the incoming queue.
+ */
+DBusMessage*
+dbus_connection_borrow_message (DBusConnection *connection)
+{
+  DBusDispatchStatus status;
+  DBusMessage *message;
+
+  _dbus_return_val_if_fail (connection != NULL, NULL);
+
+  _dbus_verbose ("start\n");
+  
+  /* this is called for the side effect that it queues
+   * up any messages from the transport
+   */
+  status = dbus_connection_get_dispatch_status (connection);
+  if (status != DBUS_DISPATCH_DATA_REMAINS)
+    return NULL;
+  
+  CONNECTION_LOCK (connection);
+
+  _dbus_connection_acquire_dispatch (connection);
+
+  /* While a message is outstanding, the dispatch lock is held */
+  _dbus_assert (connection->message_borrowed == NULL);
+
+  connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
+  
+  message = connection->message_borrowed;
+
+  check_disconnected_message_arrived_unlocked (connection, message);
+  
+  /* Note that we KEEP the dispatch lock until the message is returned */
+  if (message == NULL)
+    _dbus_connection_release_dispatch (connection);
+
+  CONNECTION_UNLOCK (connection);
+
+  _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message");
+
+  /* We don't update dispatch status until it's returned or stolen */
+  
+  return message;
+}
+
+/**
+ * Used to return a message after peeking at it using
+ * dbus_connection_borrow_message(). Only called if
+ * message from dbus_connection_borrow_message() was non-#NULL.
+ *
+ * @param connection the connection
+ * @param message the message from dbus_connection_borrow_message()
+ */
+void
+dbus_connection_return_message (DBusConnection *connection,
+				DBusMessage    *message)
+{
+  DBusDispatchStatus status;
+  
+  _dbus_return_if_fail (connection != NULL);
+  _dbus_return_if_fail (message != NULL);
+  _dbus_return_if_fail (message == connection->message_borrowed);
+  _dbus_return_if_fail (connection->dispatch_acquired);
+  
+  CONNECTION_LOCK (connection);
+  
+  _dbus_assert (message == connection->message_borrowed);
+  
+  connection->message_borrowed = NULL;
+
+  _dbus_connection_release_dispatch (connection); 
+
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+
+  _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message");
+}
+
+/**
+ * Used to keep a message after peeking at it using
+ * dbus_connection_borrow_message(). Before using this function, see
+ * the caveats/warnings in the documentation for
+ * dbus_connection_pop_message().
+ *
+ * @param connection the connection
+ * @param message the message from dbus_connection_borrow_message()
+ */
+void
+dbus_connection_steal_borrowed_message (DBusConnection *connection,
+					DBusMessage    *message)
+{
+  DBusMessage *pop_message;
+  DBusDispatchStatus status;
+
+  _dbus_return_if_fail (connection != NULL);
+  _dbus_return_if_fail (message != NULL);
+  _dbus_return_if_fail (message == connection->message_borrowed);
+  _dbus_return_if_fail (connection->dispatch_acquired);
+  
+  CONNECTION_LOCK (connection);
+ 
+  _dbus_assert (message == connection->message_borrowed);
+
+  pop_message = _dbus_list_pop_first (&connection->incoming_messages);
+  _dbus_assert (message == pop_message);
+  (void) pop_message; /* unused unless asserting */
+
+  connection->n_incoming -= 1;
+ 
+  _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
+		 message, connection->n_incoming);
+ 
+  connection->message_borrowed = NULL;
+
+  _dbus_connection_release_dispatch (connection);
+
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+  _dbus_message_trace_ref (message, -1, -1,
+      "dbus_connection_steal_borrowed_message");
+}
+
+/* See dbus_connection_pop_message, but requires the caller to own
+ * the lock before calling. May drop the lock while running.
+ */
+static DBusList*
+_dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+  
+  _dbus_assert (connection->message_borrowed == NULL);
+  
+  if (connection->n_incoming > 0)
+    {
+      DBusList *link;
+
+      link = _dbus_list_pop_first_link (&connection->incoming_messages);
+      connection->n_incoming -= 1;
+
+      _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
+                     link->data,
+                     dbus_message_type_to_string (dbus_message_get_type (link->data)),
+                     dbus_message_get_path (link->data) ?
+                     dbus_message_get_path (link->data) :
+                     "no path",
+                     dbus_message_get_interface (link->data) ?
+                     dbus_message_get_interface (link->data) :
+                     "no interface",
+                     dbus_message_get_member (link->data) ?
+                     dbus_message_get_member (link->data) :
+                     "no member",
+                     dbus_message_get_signature (link->data),
+                     connection, connection->n_incoming);
+
+      _dbus_message_trace_ref (link->data, -1, -1,
+          "_dbus_connection_pop_message_link_unlocked");
+
+      check_disconnected_message_arrived_unlocked (connection, link->data);
+      
+      return link;
+    }
+  else
+    return NULL;
+}
+
+/* See dbus_connection_pop_message, but requires the caller to own
+ * the lock before calling. May drop the lock while running.
+ */
+static DBusMessage*
+_dbus_connection_pop_message_unlocked (DBusConnection *connection)
+{
+  DBusList *link;
+
+  HAVE_LOCK_CHECK (connection);
+  
+  link = _dbus_connection_pop_message_link_unlocked (connection);
+
+  if (link != NULL)
+    {
+      DBusMessage *message;
+      
+      message = link->data;
+      
+      _dbus_list_free_link (link);
+      
+      return message;
+    }
+  else
+    return NULL;
+}
+
+static void
+_dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
+                                                DBusList       *message_link)
+{
+  HAVE_LOCK_CHECK (connection);
+  
+  _dbus_assert (message_link != NULL);
+  /* You can't borrow a message while a link is outstanding */
+  _dbus_assert (connection->message_borrowed == NULL);
+  /* We had to have the dispatch lock across the pop/putback */
+  _dbus_assert (connection->dispatch_acquired);
+
+  _dbus_list_prepend_link (&connection->incoming_messages,
+                           message_link);
+  connection->n_incoming += 1;
+
+  _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
+                 message_link->data,
+                 dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
+                 dbus_message_get_interface (message_link->data) ?
+                 dbus_message_get_interface (message_link->data) :
+                 "no interface",
+                 dbus_message_get_member (message_link->data) ?
+                 dbus_message_get_member (message_link->data) :
+                 "no member",
+                 dbus_message_get_signature (message_link->data),
+                 connection, connection->n_incoming);
+
+  _dbus_message_trace_ref (message_link->data, -1, -1,
+      "_dbus_connection_putback_message_link_unlocked");
+}
+
+/**
+ * Returns the first-received message from the incoming message queue,
+ * removing it from the queue. The caller owns a reference to the
+ * returned message. If the queue is empty, returns #NULL.
+ *
+ * This function bypasses any message handlers that are registered,
+ * and so using it is usually wrong. Instead, let the main loop invoke
+ * dbus_connection_dispatch(). Popping messages manually is only
+ * useful in very simple programs that don't share a #DBusConnection
+ * with any libraries or other modules.
+ *
+ * There is a lock that covers all ways of accessing the incoming message
+ * queue, so dbus_connection_dispatch(), dbus_connection_pop_message(),
+ * dbus_connection_borrow_message(), etc. will all block while one of the others
+ * in the group is running.
+ * 
+ * @param connection the connection.
+ * @returns next message in the incoming queue.
+ */
+DBusMessage*
+dbus_connection_pop_message (DBusConnection *connection)
+{
+  DBusMessage *message;
+  DBusDispatchStatus status;
+
+  _dbus_verbose ("start\n");
+  
+  /* this is called for the side effect that it queues
+   * up any messages from the transport
+   */
+  status = dbus_connection_get_dispatch_status (connection);
+  if (status != DBUS_DISPATCH_DATA_REMAINS)
+    return NULL;
+  
+  CONNECTION_LOCK (connection);
+  _dbus_connection_acquire_dispatch (connection);
+  HAVE_LOCK_CHECK (connection);
+  
+  message = _dbus_connection_pop_message_unlocked (connection);
+
+  _dbus_verbose ("Returning popped message %p\n", message);    
+
+  _dbus_connection_release_dispatch (connection);
+
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+  
+  return message;
+}
+
+/**
+ * Acquire the dispatcher. This is a separate lock so the main
+ * connection lock can be dropped to call out to application dispatch
+ * handlers.
+ *
+ * @param connection the connection.
+ */
+static void
+_dbus_connection_acquire_dispatch (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+
+  _dbus_connection_ref_unlocked (connection);
+  CONNECTION_UNLOCK (connection);
+  
+  _dbus_verbose ("locking dispatch_mutex\n");
+  _dbus_cmutex_lock (connection->dispatch_mutex);
+
+  while (connection->dispatch_acquired)
+    {
+      _dbus_verbose ("waiting for dispatch to be acquirable\n");
+      _dbus_condvar_wait (connection->dispatch_cond, 
+                          connection->dispatch_mutex);
+    }
+  
+  _dbus_assert (!connection->dispatch_acquired);
+
+  connection->dispatch_acquired = TRUE;
+
+  _dbus_verbose ("unlocking dispatch_mutex\n");
+  _dbus_cmutex_unlock (connection->dispatch_mutex);
+  
+  CONNECTION_LOCK (connection);
+  _dbus_connection_unref_unlocked (connection);
+}
+
+/**
+ * Release the dispatcher when you're done with it. Only call
+ * after you've acquired the dispatcher. Wakes up at most one
+ * thread currently waiting to acquire the dispatcher.
+ *
+ * @param connection the connection.
+ */
+static void
+_dbus_connection_release_dispatch (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+  
+  _dbus_verbose ("locking dispatch_mutex\n");
+  _dbus_cmutex_lock (connection->dispatch_mutex);
+  
+  _dbus_assert (connection->dispatch_acquired);
+
+  connection->dispatch_acquired = FALSE;
+  _dbus_condvar_wake_one (connection->dispatch_cond);
+
+  _dbus_verbose ("unlocking dispatch_mutex\n");
+  _dbus_cmutex_unlock (connection->dispatch_mutex);
+}
+
+static void
+_dbus_connection_failed_pop (DBusConnection *connection,
+			     DBusList       *message_link)
+{
+  _dbus_list_prepend_link (&connection->incoming_messages,
+			   message_link);
+  connection->n_incoming += 1;
+}
+
+/* Note this may be called multiple times since we don't track whether we already did it */
+static void
+notify_disconnected_unlocked (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+
+  /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
+   * connection from dbus_bus_get(). We make the same guarantee for
+   * dbus_connection_open() but in a different way since we don't want to
+   * unref right here; we instead check for connectedness before returning
+   * the connection from the hash.
+   */
+  _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
+
+  /* Dump the outgoing queue, we aren't going to be able to
+   * send it now, and we'd like accessors like
+   * dbus_connection_get_outgoing_size() to be accurate.
+   */
+  if (connection->n_outgoing > 0)
+    {
+      DBusList *link;
+      
+      _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
+                     connection->n_outgoing);
+      
+      while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
+        {
+          _dbus_connection_message_sent_unlocked (connection, link->data);
+        }
+    } 
+}
+
+/* Note this may be called multiple times since we don't track whether we already did it */
+static DBusDispatchStatus
+notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+  
+  if (connection->disconnect_message_link != NULL)
+    {
+      _dbus_verbose ("Sending disconnect message\n");
+      
+      /* If we have pending calls, queue their timeouts - we want the Disconnected
+       * to be the last message, after these timeouts.
+       */
+      connection_timeout_and_complete_all_pending_calls_unlocked (connection);
+      
+      /* We haven't sent the disconnect message already,
+       * and all real messages have been queued up.
+       */
+      _dbus_connection_queue_synthesized_message_link (connection,
+                                                       connection->disconnect_message_link);
+      connection->disconnect_message_link = NULL;
+
+      return DBUS_DISPATCH_DATA_REMAINS;
+    }
+
+  return DBUS_DISPATCH_COMPLETE;
+}
+
+static DBusDispatchStatus
+_dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
+{
+  HAVE_LOCK_CHECK (connection);
+  
+  if (connection->n_incoming > 0)
+    return DBUS_DISPATCH_DATA_REMAINS;
+  else if (!_dbus_transport_queue_messages (connection->transport))
+    return DBUS_DISPATCH_NEED_MEMORY;
+  else
+    {
+      DBusDispatchStatus status;
+      dbus_bool_t is_connected;
+      
+      status = _dbus_transport_get_dispatch_status (connection->transport);
+      is_connected = _dbus_transport_get_is_connected (connection->transport);
+
+      _dbus_verbose ("dispatch status = %s is_connected = %d\n",
+                     DISPATCH_STATUS_NAME (status), is_connected);
+      
+      if (!is_connected)
+        {
+          /* It's possible this would be better done by having an explicit
+           * notification from _dbus_transport_disconnect() that would
+           * synchronously do this, instead of waiting for the next dispatch
+           * status check. However, probably not good to change until it causes
+           * a problem.
+           */
+          notify_disconnected_unlocked (connection);
+
+          /* I'm not sure this is needed; the idea is that we want to
+           * queue the Disconnected only after we've read all the
+           * messages, but if we're disconnected maybe we are guaranteed
+           * to have read them all ?
+           */
+          if (status == DBUS_DISPATCH_COMPLETE)
+            status = notify_disconnected_and_dispatch_complete_unlocked (connection);
+        }
+      
+      if (status != DBUS_DISPATCH_COMPLETE)
+        return status;
+      else if (connection->n_incoming > 0)
+        return DBUS_DISPATCH_DATA_REMAINS;
+      else
+        return DBUS_DISPATCH_COMPLETE;
+    }
+}
+
+static void
+_dbus_connection_update_dispatch_status_and_unlock (DBusConnection    *connection,
+                                                    DBusDispatchStatus new_status)
+{
+  dbus_bool_t changed;
+  DBusDispatchStatusFunction function;
+  void *data;
+
+  HAVE_LOCK_CHECK (connection);
+
+  _dbus_connection_ref_unlocked (connection);
+
+  changed = new_status != connection->last_dispatch_status;
+
+  connection->last_dispatch_status = new_status;
+
+  function = connection->dispatch_status_function;
+  data = connection->dispatch_status_data;
+
+  if (connection->disconnected_message_arrived &&
+      !connection->disconnected_message_processed)
+    {
+      connection->disconnected_message_processed = TRUE;
+      
+      /* this does an unref, but we have a ref
+       * so we should not run the finalizer here
+       * inside the lock.
+       */
+      connection_forget_shared_unlocked (connection);
+
+      if (connection->exit_on_disconnect)
+        {
+          CONNECTION_UNLOCK (connection);            
+          
+          _dbus_verbose ("Exiting on Disconnected signal\n");
+          if (raise (SIGTERM) != 0)
+            {
+              _dbus_verbose ("Failed to raise a SIGTERM signal. Exiting\n");
+              _dbus_exit (1);
+              _dbus_assert_not_reached ("Call to exit() returned");
+            }
+          return;
+        }
+    }
+  
+  /* We drop the lock */
+  CONNECTION_UNLOCK (connection);
+  
+  if (changed && function)
+    {
+      _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
+                     connection, new_status,
+                     DISPATCH_STATUS_NAME (new_status));
+      (* function) (connection, new_status, data);      
+    }
+  
+  dbus_connection_unref (connection);
+}
+
+/**
+ * Gets the current state of the incoming message queue.
+ * #DBUS_DISPATCH_DATA_REMAINS indicates that the message queue
+ * may contain messages. #DBUS_DISPATCH_COMPLETE indicates that the
+ * incoming queue is empty. #DBUS_DISPATCH_NEED_MEMORY indicates that
+ * there could be data, but we can't know for sure without more
+ * memory.
+ *
+ * To process the incoming message queue, use dbus_connection_dispatch()
+ * or (in rare cases) dbus_connection_pop_message().
+ *
+ * Note, #DBUS_DISPATCH_DATA_REMAINS really means that either we
+ * have messages in the queue, or we have raw bytes buffered up
+ * that need to be parsed. When these bytes are parsed, they
+ * may not add up to an entire message. Thus, it's possible
+ * to see a status of #DBUS_DISPATCH_DATA_REMAINS but not
+ * have a message yet.
+ *
+ * In particular this happens on initial connection, because all sorts
+ * of authentication protocol stuff has to be parsed before the
+ * first message arrives.
+ * 
+ * @param connection the connection.
+ * @returns current dispatch status
+ */
+DBusDispatchStatus
+dbus_connection_get_dispatch_status (DBusConnection *connection)
+{
+  DBusDispatchStatus status;
+
+  _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
+
+  _dbus_verbose ("start\n");
+  
+  CONNECTION_LOCK (connection);
+
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+  
+  CONNECTION_UNLOCK (connection);
+
+  return status;
+}
+
+/**
+ * Filter funtion for handling the Peer standard interface.
+ */
+static DBusHandlerResult
+_dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
+                                                 DBusMessage    *message)
+{
+  dbus_bool_t sent = FALSE;
+  DBusMessage *ret = NULL;
+  DBusList *expire_link;
+
+  if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
+    {
+      /* This means we're letting the bus route this message */
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+  if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
+    {
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+  /* Preallocate a linked-list link, so that if we need to dispose of a
+   * message, we can attach it to the expired list */
+  expire_link = _dbus_list_alloc_link (NULL);
+
+  if (!expire_link)
+    return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+  if (dbus_message_is_method_call (message,
+                                   DBUS_INTERFACE_PEER,
+                                   "Ping"))
+    {
+      ret = dbus_message_new_method_return (message);
+      if (ret == NULL)
+        goto out;
+
+      sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
+    }
+  else if (dbus_message_is_method_call (message,
+                                        DBUS_INTERFACE_PEER,
+                                        "GetMachineId"))
+    {
+      DBusString uuid;
+      
+      ret = dbus_message_new_method_return (message);
+      if (ret == NULL)
+        goto out;
+
+      _dbus_string_init (&uuid);
+      if (_dbus_get_local_machine_uuid_encoded (&uuid))
+        {
+          const char *v_STRING = _dbus_string_get_const_data (&uuid);
+          if (dbus_message_append_args (ret,
+                                        DBUS_TYPE_STRING, &v_STRING,
+                                        DBUS_TYPE_INVALID))
+            {
+              sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
+            }
+        }
+      _dbus_string_free (&uuid);
+    }
+  else
+    {
+      /* We need to bounce anything else with this interface, otherwise apps
+       * could start extending the interface and when we added extensions
+       * here to DBusConnection we'd break those apps.
+       */
+      ret = dbus_message_new_error (message,
+                                    DBUS_ERROR_UNKNOWN_METHOD,
+                                    "Unknown method invoked on org.freedesktop.DBus.Peer interface");
+      if (ret == NULL)
+        goto out;
+
+      sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
+    }
+
+out:
+  if (ret == NULL)
+    {
+      _dbus_list_free_link (expire_link);
+    }
+  else
+    {
+      /* It'll be safe to unref the reply when we unlock */
+      expire_link->data = ret;
+      _dbus_list_prepend_link (&connection->expired_messages, expire_link);
+    }
+
+  if (!sent)
+    return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/**
+* Processes all builtin filter functions
+*
+* If the spec specifies a standard interface
+* they should be processed from this method
+**/
+static DBusHandlerResult
+_dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
+                                                           DBusMessage    *message)
+{
+  /* We just run one filter for now but have the option to run more
+     if the spec calls for it in the future */
+
+  return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
+}
+
+/**
+ * Processes any incoming data.
+ *
+ * If there's incoming raw data that has not yet been parsed, it is
+ * parsed, which may or may not result in adding messages to the
+ * incoming queue.
+ *
+ * The incoming data buffer is filled when the connection reads from
+ * its underlying transport (such as a socket).  Reading usually
+ * happens in dbus_watch_handle() or dbus_connection_read_write().
+ * 
+ * If there are complete messages in the incoming queue,
+ * dbus_connection_dispatch() removes one message from the queue and
+ * processes it. Processing has three steps.
+ *
+ * First, any method replies are passed to #DBusPendingCall or
+ * dbus_connection_send_with_reply_and_block() in order to
+ * complete the pending method call.
+ * 
+ * Second, any filters registered with dbus_connection_add_filter()
+ * are run. If any filter returns #DBUS_HANDLER_RESULT_HANDLED
+ * then processing stops after that filter.
+ *
+ * Third, if the message is a method call it is forwarded to
+ * any registered object path handlers added with
+ * dbus_connection_register_object_path() or
+ * dbus_connection_register_fallback().
+ *
+ * A single call to dbus_connection_dispatch() will process at most
+ * one message; it will not clear the entire message queue.
+ *
+ * Be careful about calling dbus_connection_dispatch() from inside a
+ * message handler, i.e. calling dbus_connection_dispatch()
+ * recursively.  If threads have been initialized with a recursive
+ * mutex function, then this will not deadlock; however, it can
+ * certainly confuse your application.
+ * 
+ * @todo some FIXME in here about handling DBUS_HANDLER_RESULT_NEED_MEMORY
+ * 
+ * @param connection the connection
+ * @returns dispatch status, see dbus_connection_get_dispatch_status()
+ */
+DBusDispatchStatus
+dbus_connection_dispatch (DBusConnection *connection)
+{
+  DBusMessage *message;
+  DBusList *link, *filter_list_copy, *message_link;
+  DBusHandlerResult result;
+  DBusPendingCall *pending;
+  dbus_int32_t reply_serial;
+  DBusDispatchStatus status;
+  dbus_bool_t found_object;
+
+  _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
+
+  _dbus_verbose ("\n");
+  
+  CONNECTION_LOCK (connection);
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+  if (status != DBUS_DISPATCH_DATA_REMAINS)
+    {
+      /* unlocks and calls out to user code */
+      _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+      return status;
+    }
+  
+  /* We need to ref the connection since the callback could potentially
+   * drop the last ref to it
+   */
+  _dbus_connection_ref_unlocked (connection);
+
+  _dbus_connection_acquire_dispatch (connection);
+  HAVE_LOCK_CHECK (connection);
+
+  message_link = _dbus_connection_pop_message_link_unlocked (connection);
+  if (message_link == NULL)
+    {
+      /* another thread dispatched our stuff */
+
+      _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
+      
+      _dbus_connection_release_dispatch (connection);
+
+      status = _dbus_connection_get_dispatch_status_unlocked (connection);
+
+      _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+      
+      dbus_connection_unref (connection);
+      
+      return status;
+    }
+
+  message = message_link->data;
+
+  _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
+                 message,
+                 dbus_message_type_to_string (dbus_message_get_type (message)),
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) :
+                 "no member",
+                 dbus_message_get_signature (message));
+
+  result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  
+  /* Pending call handling must be first, because if you do
+   * dbus_connection_send_with_reply_and_block() or
+   * dbus_pending_call_block() then no handlers/filters will be run on
+   * the reply. We want consistent semantics in the case where we
+   * dbus_connection_dispatch() the reply.
+   */
+  
+  reply_serial = dbus_message_get_reply_serial (message);
+  pending = _dbus_hash_table_lookup_int (connection->pending_replies,
+                                         reply_serial);
+  if (pending)
+    {
+      _dbus_verbose ("Dispatching a pending reply\n");
+      complete_pending_call_and_unlock (connection, pending, message);
+      pending = NULL; /* it's probably unref'd */
+      
+      CONNECTION_LOCK (connection);
+      _dbus_verbose ("pending call completed in dispatch\n");
+      result = DBUS_HANDLER_RESULT_HANDLED;
+      goto out;
+    }
+
+  result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
+  if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
+    goto out;
+ 
+  if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
+    {
+      _dbus_connection_release_dispatch (connection);
+      HAVE_LOCK_CHECK (connection);
+      
+      _dbus_connection_failed_pop (connection, message_link);
+
+      /* unlocks and calls user code */
+      _dbus_connection_update_dispatch_status_and_unlock (connection,
+                                                          DBUS_DISPATCH_NEED_MEMORY);
+      dbus_connection_unref (connection);
+      
+      return DBUS_DISPATCH_NEED_MEMORY;
+    }
+  
+  _dbus_list_foreach (&filter_list_copy,
+		      (DBusForeachFunction)_dbus_message_filter_ref,
+		      NULL);
+
+  /* We're still protected from dispatch() reentrancy here
+   * since we acquired the dispatcher
+   */
+  CONNECTION_UNLOCK (connection);
+  
+  link = _dbus_list_get_first_link (&filter_list_copy);
+  while (link != NULL)
+    {
+      DBusMessageFilter *filter = link->data;
+      DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
+
+      if (filter->function == NULL)
+        {
+          _dbus_verbose ("  filter was removed in a callback function\n");
+          link = next;
+          continue;
+        }
+
+      _dbus_verbose ("  running filter on message %p\n", message);
+      result = (* filter->function) (connection, message, filter->user_data);
+
+      if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
+	break;
+
+      link = next;
+    }
+
+  _dbus_list_foreach (&filter_list_copy,
+		      (DBusForeachFunction)_dbus_message_filter_unref,
+		      NULL);
+  _dbus_list_clear (&filter_list_copy);
+  
+  CONNECTION_LOCK (connection);
+
+  if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
+    {
+      _dbus_verbose ("No memory\n");
+      goto out;
+    }
+  else if (result == DBUS_HANDLER_RESULT_HANDLED)
+    {
+      _dbus_verbose ("filter handled message in dispatch\n");
+      goto out;
+    }
+
+  /* We're still protected from dispatch() reentrancy here
+   * since we acquired the dispatcher
+   */
+  _dbus_verbose ("  running object path dispatch on message %p (%s %s %s '%s')\n",
+                 message,
+                 dbus_message_type_to_string (dbus_message_get_type (message)),
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) :
+                 "no member",
+                 dbus_message_get_signature (message));
+
+  HAVE_LOCK_CHECK (connection);
+  result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
+                                                  message,
+                                                  &found_object);
+  
+  CONNECTION_LOCK (connection);
+
+  if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
+    {
+      _dbus_verbose ("object tree handled message in dispatch\n");
+      goto out;
+    }
+
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
+    {
+      DBusMessage *reply;
+      DBusString str;
+      DBusPreallocatedSend *preallocated;
+      DBusList *expire_link;
+
+      _dbus_verbose ("  sending error %s\n",
+                     DBUS_ERROR_UNKNOWN_METHOD);
+
+      if (!_dbus_string_init (&str))
+        {
+          result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+          _dbus_verbose ("no memory for error string in dispatch\n");
+          goto out;
+        }
+              
+      if (!_dbus_string_append_printf (&str,
+                                       "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
+                                       dbus_message_get_member (message),
+                                       dbus_message_get_signature (message),
+                                       dbus_message_get_interface (message)))
+        {
+          _dbus_string_free (&str);
+          result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+          _dbus_verbose ("no memory for error string in dispatch\n");
+          goto out;
+        }
+      
+      reply = dbus_message_new_error (message,
+                                      found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT,
+                                      _dbus_string_get_const_data (&str));
+      _dbus_string_free (&str);
+
+      if (reply == NULL)
+        {
+          result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+          _dbus_verbose ("no memory for error reply in dispatch\n");
+          goto out;
+        }
+
+      expire_link = _dbus_list_alloc_link (reply);
+
+      if (expire_link == NULL)
+        {
+          dbus_message_unref (reply);
+          result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+          _dbus_verbose ("no memory for error send in dispatch\n");
+          goto out;
+        }
+
+      preallocated = _dbus_connection_preallocate_send_unlocked (connection);
+
+      if (preallocated == NULL)
+        {
+          _dbus_list_free_link (expire_link);
+          /* It's OK that this is finalized, because it hasn't been seen by
+           * anything that could attach user callbacks */
+          dbus_message_unref (reply);
+          result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+          _dbus_verbose ("no memory for error send in dispatch\n");
+          goto out;
+        }
+
+      _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
+                                                             reply, NULL);
+      /* reply will be freed when we release the lock */
+      _dbus_list_prepend_link (&connection->expired_messages, expire_link);
+
+      result = DBUS_HANDLER_RESULT_HANDLED;
+    }
+  
+  _dbus_verbose ("  done dispatching %p (%s %s %s '%s') on connection %p\n", message,
+                 dbus_message_type_to_string (dbus_message_get_type (message)),
+                 dbus_message_get_interface (message) ?
+                 dbus_message_get_interface (message) :
+                 "no interface",
+                 dbus_message_get_member (message) ?
+                 dbus_message_get_member (message) :
+                 "no member",
+                 dbus_message_get_signature (message),
+                 connection);
+  
+ out:
+  if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
+    {
+      _dbus_verbose ("out of memory\n");
+      
+      /* Put message back, and we'll start over.
+       * Yes this means handlers must be idempotent if they
+       * don't return HANDLED; c'est la vie.
+       */
+      _dbus_connection_putback_message_link_unlocked (connection,
+                                                      message_link);
+      /* now we don't want to free them */
+      message_link = NULL;
+      message = NULL;
+    }
+  else
+    {
+      _dbus_verbose (" ... done dispatching\n");
+    }
+
+  _dbus_connection_release_dispatch (connection);
+  HAVE_LOCK_CHECK (connection);
+
+  if (message != NULL)
+    {
+      /* We don't want this message to count in maximum message limits when
+       * computing the dispatch status, below. We have to drop the lock
+       * temporarily, because finalizing a message can trigger callbacks.
+       *
+       * We have a reference to the connection, and we don't use any cached
+       * pointers to the connection's internals below this point, so it should
+       * be safe to drop the lock and take it back. */
+      CONNECTION_UNLOCK (connection);
+      dbus_message_unref (message);
+      CONNECTION_LOCK (connection);
+    }
+
+  if (message_link != NULL)
+    _dbus_list_free_link (message_link);
+
+  _dbus_verbose ("before final status update\n");
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+
+  /* unlocks and calls user code */
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+  
+  dbus_connection_unref (connection);
+  
+  return status;
+}
+
+/**
+ * Sets the watch functions for the connection. These functions are
+ * responsible for making the application's main loop aware of file
+ * descriptors that need to be monitored for events, using select() or
+ * poll(). When using Qt, typically the DBusAddWatchFunction would
+ * create a QSocketNotifier. When using GLib, the DBusAddWatchFunction
+ * could call g_io_add_watch(), or could be used as part of a more
+ * elaborate GSource. Note that when a watch is added, it may
+ * not be enabled.
+ *
+ * The DBusWatchToggledFunction notifies the application that the
+ * watch has been enabled or disabled. Call dbus_watch_get_enabled()
+ * to check this. A disabled watch should have no effect, and enabled
+ * watch should be added to the main loop. This feature is used
+ * instead of simply adding/removing the watch because
+ * enabling/disabling can be done without memory allocation.  The
+ * toggled function may be NULL if a main loop re-queries
+ * dbus_watch_get_enabled() every time anyway.
+ * 
+ * The DBusWatch can be queried for the file descriptor to watch using
+ * dbus_watch_get_unix_fd() or dbus_watch_get_socket(), and for the
+ * events to watch for using dbus_watch_get_flags(). The flags
+ * returned by dbus_watch_get_flags() will only contain
+ * DBUS_WATCH_READABLE and DBUS_WATCH_WRITABLE, never
+ * DBUS_WATCH_HANGUP or DBUS_WATCH_ERROR; all watches implicitly
+ * include a watch for hangups, errors, and other exceptional
+ * conditions.
+ *
+ * Once a file descriptor becomes readable or writable, or an exception
+ * occurs, dbus_watch_handle() should be called to
+ * notify the connection of the file descriptor's condition.
+ *
+ * dbus_watch_handle() cannot be called during the
+ * DBusAddWatchFunction, as the connection will not be ready to handle
+ * that watch yet.
+ * 
+ * It is not allowed to reference a DBusWatch after it has been passed
+ * to remove_function.
+ *
+ * If #FALSE is returned due to lack of memory, the failure may be due
+ * to a #FALSE return from the new add_function. If so, the
+ * add_function may have been called successfully one or more times,
+ * but the remove_function will also have been called to remove any
+ * successful adds. i.e. if #FALSE is returned the net result
+ * should be that dbus_connection_set_watch_functions() has no effect,
+ * but the add_function and remove_function may have been called.
+ *
+ * @note The thread lock on DBusConnection is held while
+ * watch functions are invoked, so inside these functions you
+ * may not invoke any methods on DBusConnection or it will deadlock.
+ * See the comments in the code or http://lists.freedesktop.org/archives/dbus/2007-July/tread.html#8144
+ * if you encounter this issue and want to attempt writing a patch.
+ * 
+ * @param connection the connection.
+ * @param add_function function to begin monitoring a new descriptor.
+ * @param remove_function function to stop monitoring a descriptor.
+ * @param toggled_function function to notify of enable/disable
+ * @param data data to pass to add_function and remove_function.
+ * @param free_data_function function to be called to free the data.
+ * @returns #FALSE on failure (no memory)
+ */
+dbus_bool_t
+dbus_connection_set_watch_functions (DBusConnection              *connection,
+                                     DBusAddWatchFunction         add_function,
+                                     DBusRemoveWatchFunction      remove_function,
+                                     DBusWatchToggledFunction     toggled_function,
+                                     void                        *data,
+                                     DBusFreeFunction             free_data_function)
+{
+  dbus_bool_t retval;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+
+  retval = _dbus_watch_list_set_functions (connection->watches,
+                                           add_function, remove_function,
+                                           toggled_function,
+                                           data, free_data_function);
+
+  CONNECTION_UNLOCK (connection);
+
+  return retval;
+}
+
+/**
+ * Sets the timeout functions for the connection. These functions are
+ * responsible for making the application's main loop aware of timeouts.
+ * When using Qt, typically the DBusAddTimeoutFunction would create a
+ * QTimer. When using GLib, the DBusAddTimeoutFunction would call
+ * g_timeout_add.
+ * 
+ * The DBusTimeoutToggledFunction notifies the application that the
+ * timeout has been enabled or disabled. Call
+ * dbus_timeout_get_enabled() to check this. A disabled timeout should
+ * have no effect, and enabled timeout should be added to the main
+ * loop. This feature is used instead of simply adding/removing the
+ * timeout because enabling/disabling can be done without memory
+ * allocation. With Qt, QTimer::start() and QTimer::stop() can be used
+ * to enable and disable. The toggled function may be NULL if a main
+ * loop re-queries dbus_timeout_get_enabled() every time anyway.
+ * Whenever a timeout is toggled, its interval may change.
+ *
+ * The DBusTimeout can be queried for the timer interval using
+ * dbus_timeout_get_interval(). dbus_timeout_handle() should be called
+ * repeatedly, each time the interval elapses, starting after it has
+ * elapsed once. The timeout stops firing when it is removed with the
+ * given remove_function.  The timer interval may change whenever the
+ * timeout is added, removed, or toggled.
+ *
+ * @note The thread lock on DBusConnection is held while
+ * timeout functions are invoked, so inside these functions you
+ * may not invoke any methods on DBusConnection or it will deadlock.
+ * See the comments in the code or http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
+ * if you encounter this issue and want to attempt writing a patch.
+ *
+ * @param connection the connection.
+ * @param add_function function to add a timeout.
+ * @param remove_function function to remove a timeout.
+ * @param toggled_function function to notify of enable/disable
+ * @param data data to pass to add_function and remove_function.
+ * @param free_data_function function to be called to free the data.
+ * @returns #FALSE on failure (no memory)
+ */
+dbus_bool_t
+dbus_connection_set_timeout_functions   (DBusConnection            *connection,
+					 DBusAddTimeoutFunction     add_function,
+					 DBusRemoveTimeoutFunction  remove_function,
+                                         DBusTimeoutToggledFunction toggled_function,
+					 void                      *data,
+					 DBusFreeFunction           free_data_function)
+{
+  dbus_bool_t retval;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+
+  retval = _dbus_timeout_list_set_functions (connection->timeouts,
+                                             add_function, remove_function,
+                                             toggled_function,
+                                             data, free_data_function);
+
+  CONNECTION_UNLOCK (connection);
+
+  return retval;
+}
+
+/**
+ * Sets the mainloop wakeup function for the connection. This function
+ * is responsible for waking up the main loop (if its sleeping in
+ * another thread) when some some change has happened to the
+ * connection that the mainloop needs to reconsider (e.g. a message
+ * has been queued for writing).  When using Qt, this typically
+ * results in a call to QEventLoop::wakeUp().  When using GLib, it
+ * would call g_main_context_wakeup().
+ *
+ * @param connection the connection.
+ * @param wakeup_main_function function to wake up the mainloop
+ * @param data data to pass wakeup_main_function
+ * @param free_data_function function to be called to free the data.
+ */
+void
+dbus_connection_set_wakeup_main_function (DBusConnection            *connection,
+					  DBusWakeupMainFunction     wakeup_main_function,
+					  void                      *data,
+					  DBusFreeFunction           free_data_function)
+{
+  void *old_data;
+  DBusFreeFunction old_free_data;
+
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+  old_data = connection->wakeup_main_data;
+  old_free_data = connection->free_wakeup_main_data;
+
+  connection->wakeup_main_function = wakeup_main_function;
+  connection->wakeup_main_data = data;
+  connection->free_wakeup_main_data = free_data_function;
+  
+  CONNECTION_UNLOCK (connection);
+
+  /* Callback outside the lock */
+  if (old_free_data)
+    (*old_free_data) (old_data);
+}
+
+/**
+ * Set a function to be invoked when the dispatch status changes.
+ * If the dispatch status is #DBUS_DISPATCH_DATA_REMAINS, then
+ * dbus_connection_dispatch() needs to be called to process incoming
+ * messages. However, dbus_connection_dispatch() MUST NOT BE CALLED
+ * from inside the DBusDispatchStatusFunction. Indeed, almost
+ * any reentrancy in this function is a bad idea. Instead,
+ * the DBusDispatchStatusFunction should simply save an indication
+ * that messages should be dispatched later, when the main loop
+ * is re-entered.
+ *
+ * If you don't set a dispatch status function, you have to be sure to
+ * dispatch on every iteration of your main loop, especially if
+ * dbus_watch_handle() or dbus_timeout_handle() were called.
+ *
+ * @param connection the connection
+ * @param function function to call on dispatch status changes
+ * @param data data for function
+ * @param free_data_function free the function data
+ */
+void
+dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
+                                              DBusDispatchStatusFunction  function,
+                                              void                       *data,
+                                              DBusFreeFunction            free_data_function)
+{
+  void *old_data;
+  DBusFreeFunction old_free_data;
+
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+  old_data = connection->dispatch_status_data;
+  old_free_data = connection->free_dispatch_status_data;
+
+  connection->dispatch_status_function = function;
+  connection->dispatch_status_data = data;
+  connection->free_dispatch_status_data = free_data_function;
+  
+  CONNECTION_UNLOCK (connection);
+
+  /* Callback outside the lock */
+  if (old_free_data)
+    (*old_free_data) (old_data);
+}
+
+/**
+ * Get the UNIX file descriptor of the connection, if any.  This can
+ * be used for SELinux access control checks with getpeercon() for
+ * example. DO NOT read or write to the file descriptor, or try to
+ * select() on it; use DBusWatch for main loop integration. Not all
+ * connections will have a file descriptor. So for adding descriptors
+ * to the main loop, use dbus_watch_get_unix_fd() and so forth.
+ *
+ * If the connection is socket-based, you can also use
+ * dbus_connection_get_socket(), which will work on Windows too.
+ * This function always fails on Windows.
+ *
+ * Right now the returned descriptor is always a socket, but
+ * that is not guaranteed.
+ * 
+ * @param connection the connection
+ * @param fd return location for the file descriptor.
+ * @returns #TRUE if fd is successfully obtained.
+ */
+dbus_bool_t
+dbus_connection_get_unix_fd (DBusConnection *connection,
+                             int            *fd)
+{
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
+
+#ifdef DBUS_WIN
+  /* FIXME do this on a lower level */
+  return FALSE;
+#endif
+  
+  return dbus_connection_get_socket(connection, fd);
+}
+
+/**
+ * Gets the underlying Windows or UNIX socket file descriptor
+ * of the connection, if any. DO NOT read or write to the file descriptor, or try to
+ * select() on it; use DBusWatch for main loop integration. Not all
+ * connections will have a socket. So for adding descriptors
+ * to the main loop, use dbus_watch_get_socket() and so forth.
+ *
+ * If the connection is not socket-based, this function will return FALSE,
+ * even if the connection does have a file descriptor of some kind.
+ * i.e. this function always returns specifically a socket file descriptor.
+ * 
+ * @param connection the connection
+ * @param fd return location for the file descriptor.
+ * @returns #TRUE if fd is successfully obtained.
+ */
+dbus_bool_t
+dbus_connection_get_socket(DBusConnection              *connection,
+                           int                         *fd)
+{
+  dbus_bool_t retval;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+  
+  retval = _dbus_transport_get_socket_fd (connection->transport,
+                                          fd);
+
+  CONNECTION_UNLOCK (connection);
+
+  return retval;
+}
+
+
+/**
+ * Gets the UNIX user ID of the connection if known.  Returns #TRUE if
+ * the uid is filled in.  Always returns #FALSE on non-UNIX platforms
+ * for now, though in theory someone could hook Windows to NIS or
+ * something.  Always returns #FALSE prior to authenticating the
+ * connection.
+ *
+ * The UID is only read by servers from clients; clients can't usually
+ * get the UID of servers, because servers do not authenticate to
+ * clients.  The returned UID is the UID the connection authenticated
+ * as.
+ *
+ * The message bus is a server and the apps connecting to the bus
+ * are clients.
+ *
+ * You can ask the bus to tell you the UID of another connection though
+ * if you like; this is done with dbus_bus_get_unix_user().
+ *
+ * @param connection the connection
+ * @param uid return location for the user ID
+ * @returns #TRUE if uid is filled in with a valid user ID
+ */
+dbus_bool_t
+dbus_connection_get_unix_user (DBusConnection *connection,
+                               unsigned long  *uid)
+{
+  dbus_bool_t result;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (uid != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+
+  if (!_dbus_transport_get_is_authenticated (connection->transport))
+    result = FALSE;
+  else
+    result = _dbus_transport_get_unix_user (connection->transport,
+                                            uid);
+
+#ifdef DBUS_WIN
+  _dbus_assert (!result);
+#endif
+  
+  CONNECTION_UNLOCK (connection);
+
+  return result;
+}
+
+/**
+ * Gets the process ID of the connection if any.
+ * Returns #TRUE if the pid is filled in.
+ * Always returns #FALSE prior to authenticating the
+ * connection.
+ *
+ * @param connection the connection
+ * @param pid return location for the process ID
+ * @returns #TRUE if uid is filled in with a valid process ID
+ */
+dbus_bool_t
+dbus_connection_get_unix_process_id (DBusConnection *connection,
+				     unsigned long  *pid)
+{
+  dbus_bool_t result;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (pid != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+
+  if (!_dbus_transport_get_is_authenticated (connection->transport))
+    result = FALSE;
+  else
+    result = _dbus_transport_get_unix_process_id (connection->transport,
+						  pid);
+
+  CONNECTION_UNLOCK (connection);
+
+  return result;
+}
+
+/**
+ * Gets the ADT audit data of the connection if any.
+ * Returns #TRUE if the structure pointer is returned.
+ * Always returns #FALSE prior to authenticating the
+ * connection.
+ *
+ * @param connection the connection
+ * @param data return location for audit data 
+ * @returns #TRUE if audit data is filled in with a valid ucred pointer
+ */
+dbus_bool_t
+dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
+					    void          **data,
+					    dbus_int32_t   *data_size)
+{
+  dbus_bool_t result;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (data != NULL, FALSE);
+  _dbus_return_val_if_fail (data_size != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+
+  if (!_dbus_transport_get_is_authenticated (connection->transport))
+    result = FALSE;
+  else
+    result = _dbus_transport_get_adt_audit_session_data (connection->transport,
+					    	         data,
+			  			         data_size);
+  CONNECTION_UNLOCK (connection);
+
+  return result;
+}
+
+/**
+ * Sets a predicate function used to determine whether a given user ID
+ * is allowed to connect. When an incoming connection has
+ * authenticated with a particular user ID, this function is called;
+ * if it returns #TRUE, the connection is allowed to proceed,
+ * otherwise the connection is disconnected.
+ *
+ * If the function is set to #NULL (as it is by default), then
+ * only the same UID as the server process will be allowed to
+ * connect. Also, root is always allowed to connect.
+ *
+ * On Windows, the function will be set and its free_data_function will
+ * be invoked when the connection is freed or a new function is set.
+ * However, the function will never be called, because there are
+ * no UNIX user ids to pass to it, or at least none of the existing
+ * auth protocols would allow authenticating as a UNIX user on Windows.
+ * 
+ * @param connection the connection
+ * @param function the predicate
+ * @param data data to pass to the predicate
+ * @param free_data_function function to free the data
+ */
+void
+dbus_connection_set_unix_user_function (DBusConnection             *connection,
+                                        DBusAllowUnixUserFunction   function,
+                                        void                       *data,
+                                        DBusFreeFunction            free_data_function)
+{
+  void *old_data = NULL;
+  DBusFreeFunction old_free_function = NULL;
+
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+  _dbus_transport_set_unix_user_function (connection->transport,
+                                          function, data, free_data_function,
+                                          &old_data, &old_free_function);
+  CONNECTION_UNLOCK (connection);
+
+  if (old_free_function != NULL)
+    (* old_free_function) (old_data);
+}
+
+/**
+ * Gets the Windows user SID of the connection if known.  Returns
+ * #TRUE if the ID is filled in.  Always returns #FALSE on non-Windows
+ * platforms for now, though in theory someone could hook UNIX to
+ * Active Directory or something.  Always returns #FALSE prior to
+ * authenticating the connection.
+ *
+ * The user is only read by servers from clients; clients can't usually
+ * get the user of servers, because servers do not authenticate to
+ * clients. The returned user is the user the connection authenticated
+ * as.
+ *
+ * The message bus is a server and the apps connecting to the bus
+ * are clients.
+ *
+ * The returned user string has to be freed with dbus_free().
+ *
+ * The return value indicates whether the user SID is available;
+ * if it's available but we don't have the memory to copy it,
+ * then the return value is #TRUE and #NULL is given as the SID.
+ * 
+ * @todo We would like to be able to say "You can ask the bus to tell
+ * you the user of another connection though if you like; this is done
+ * with dbus_bus_get_windows_user()." But this has to be implemented
+ * in bus/driver.c and dbus/dbus-bus.c, and is pointless anyway
+ * since on Windows we only use the session bus for now.
+ *
+ * @param connection the connection
+ * @param windows_sid_p return location for an allocated copy of the user ID, or #NULL if no memory
+ * @returns #TRUE if user is available (returned value may be #NULL anyway if no memory)
+ */
+dbus_bool_t
+dbus_connection_get_windows_user (DBusConnection             *connection,
+                                  char                      **windows_sid_p)
+{
+  dbus_bool_t result;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
+  
+  CONNECTION_LOCK (connection);
+
+  if (!_dbus_transport_get_is_authenticated (connection->transport))
+    result = FALSE;
+  else
+    result = _dbus_transport_get_windows_user (connection->transport,
+                                               windows_sid_p);
+
+#ifdef DBUS_UNIX
+  _dbus_assert (!result);
+#endif
+  
+  CONNECTION_UNLOCK (connection);
+
+  return result;
+}
+
+/**
+ * Sets a predicate function used to determine whether a given user ID
+ * is allowed to connect. When an incoming connection has
+ * authenticated with a particular user ID, this function is called;
+ * if it returns #TRUE, the connection is allowed to proceed,
+ * otherwise the connection is disconnected.
+ *
+ * If the function is set to #NULL (as it is by default), then
+ * only the same user owning the server process will be allowed to
+ * connect.
+ *
+ * On UNIX, the function will be set and its free_data_function will
+ * be invoked when the connection is freed or a new function is set.
+ * However, the function will never be called, because there is no
+ * way right now to authenticate as a Windows user on UNIX.
+ * 
+ * @param connection the connection
+ * @param function the predicate
+ * @param data data to pass to the predicate
+ * @param free_data_function function to free the data
+ */
+void
+dbus_connection_set_windows_user_function (DBusConnection              *connection,
+                                           DBusAllowWindowsUserFunction function,
+                                           void                        *data,
+                                           DBusFreeFunction             free_data_function)
+{
+  void *old_data = NULL;
+  DBusFreeFunction old_free_function = NULL;
+
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+  _dbus_transport_set_windows_user_function (connection->transport,
+                                             function, data, free_data_function,
+                                             &old_data, &old_free_function);
+  CONNECTION_UNLOCK (connection);
+
+  if (old_free_function != NULL)
+    (* old_free_function) (old_data);
+}
+
+/**
+ * This function must be called on the server side of a connection when the
+ * connection is first seen in the #DBusNewConnectionFunction. If set to
+ * #TRUE (the default is #FALSE), then the connection can proceed even if
+ * the client does not authenticate as some user identity, i.e. clients
+ * can connect anonymously.
+ * 
+ * This setting interacts with the available authorization mechanisms
+ * (see dbus_server_set_auth_mechanisms()). Namely, an auth mechanism
+ * such as ANONYMOUS that supports anonymous auth must be included in
+ * the list of available mechanisms for anonymous login to work.
+ *
+ * This setting also changes the default rule for connections
+ * authorized as a user; normally, if a connection authorizes as
+ * a user identity, it is permitted if the user identity is
+ * root or the user identity matches the user identity of the server
+ * process. If anonymous connections are allowed, however,
+ * then any user identity is allowed.
+ *
+ * You can override the rules for connections authorized as a
+ * user identity with dbus_connection_set_unix_user_function()
+ * and dbus_connection_set_windows_user_function().
+ * 
+ * @param connection the connection
+ * @param value whether to allow authentication as an anonymous user
+ */
+void
+dbus_connection_set_allow_anonymous (DBusConnection             *connection,
+                                     dbus_bool_t                 value)
+{
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+  _dbus_transport_set_allow_anonymous (connection->transport, value);
+  CONNECTION_UNLOCK (connection);
+}
+
+/**
+ *
+ * Normally #DBusConnection automatically handles all messages to the
+ * org.freedesktop.DBus.Peer interface. However, the message bus wants
+ * to be able to route methods on that interface through the bus and
+ * to other applications. If routing peer messages is enabled, then
+ * messages with the org.freedesktop.DBus.Peer interface that also
+ * have a bus destination name set will not be automatically
+ * handled by the #DBusConnection and instead will be dispatched
+ * normally to the application.
+ *
+ * If a normal application sets this flag, it can break things badly.
+ * So don't set this unless you are the message bus.
+ *
+ * @param connection the connection
+ * @param value #TRUE to pass through org.freedesktop.DBus.Peer messages with a bus name set
+ */
+void
+dbus_connection_set_route_peer_messages (DBusConnection             *connection,
+                                         dbus_bool_t                 value)
+{
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+  connection->route_peer_messages = TRUE;
+  CONNECTION_UNLOCK (connection);
+}
+
+/**
+ * Adds a message filter. Filters are handlers that are run on all
+ * incoming messages, prior to the objects registered with
+ * dbus_connection_register_object_path().  Filters are run in the
+ * order that they were added.  The same handler can be added as a
+ * filter more than once, in which case it will be run more than once.
+ * Filters added during a filter callback won't be run on the message
+ * being processed.
+ *
+ * @todo we don't run filters on messages while blocking without
+ * entering the main loop, since filters are run as part of
+ * dbus_connection_dispatch(). This is probably a feature, as filters
+ * could create arbitrary reentrancy. But kind of sucks if you're
+ * trying to filter METHOD_RETURN for some reason.
+ *
+ * @param connection the connection
+ * @param function function to handle messages
+ * @param user_data user data to pass to the function
+ * @param free_data_function function to use for freeing user data
+ * @returns #TRUE on success, #FALSE if not enough memory.
+ */
+dbus_bool_t
+dbus_connection_add_filter (DBusConnection            *connection,
+                            DBusHandleMessageFunction  function,
+                            void                      *user_data,
+                            DBusFreeFunction           free_data_function)
+{
+  DBusMessageFilter *filter;
+  
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (function != NULL, FALSE);
+
+  filter = dbus_new0 (DBusMessageFilter, 1);
+  if (filter == NULL)
+    return FALSE;
+
+  _dbus_atomic_inc (&filter->refcount);
+
+  CONNECTION_LOCK (connection);
+
+  if (!_dbus_list_append (&connection->filter_list,
+                          filter))
+    {
+      _dbus_message_filter_unref (filter);
+      CONNECTION_UNLOCK (connection);
+      return FALSE;
+    }
+
+  /* Fill in filter after all memory allocated,
+   * so we don't run the free_user_data_function
+   * if the add_filter() fails
+   */
+  
+  filter->function = function;
+  filter->user_data = user_data;
+  filter->free_user_data_function = free_data_function;
+        
+  CONNECTION_UNLOCK (connection);
+  return TRUE;
+}
+
+/**
+ * Removes a previously-added message filter. It is a programming
+ * error to call this function for a handler that has not been added
+ * as a filter. If the given handler was added more than once, only
+ * one instance of it will be removed (the most recently-added
+ * instance).
+ *
+ * @param connection the connection
+ * @param function the handler to remove
+ * @param user_data user data for the handler to remove
+ *
+ */
+void
+dbus_connection_remove_filter (DBusConnection            *connection,
+                               DBusHandleMessageFunction  function,
+                               void                      *user_data)
+{
+  DBusList *link;
+  DBusMessageFilter *filter;
+  
+  _dbus_return_if_fail (connection != NULL);
+  _dbus_return_if_fail (function != NULL);
+  
+  CONNECTION_LOCK (connection);
+
+  filter = NULL;
+  
+  link = _dbus_list_get_last_link (&connection->filter_list);
+  while (link != NULL)
+    {
+      filter = link->data;
+
+      if (filter->function == function &&
+          filter->user_data == user_data)
+        {
+          _dbus_list_remove_link (&connection->filter_list, link);
+          filter->function = NULL;
+          
+          break;
+        }
+        
+      link = _dbus_list_get_prev_link (&connection->filter_list, link);
+      filter = NULL;
+    }
+  
+  CONNECTION_UNLOCK (connection);
+
+#ifndef DBUS_DISABLE_CHECKS
+  if (filter == NULL)
+    {
+      _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
+                               function, user_data);
+      return;
+    }
+#endif
+  
+  /* Call application code */
+  if (filter->free_user_data_function)
+    (* filter->free_user_data_function) (filter->user_data);
+
+  filter->free_user_data_function = NULL;
+  filter->user_data = NULL;
+  
+  _dbus_message_filter_unref (filter);
+}
+
+/**
+ * Registers a handler for a given path or subsection in the object
+ * hierarchy. The given vtable handles messages sent to exactly the
+ * given path or also for paths bellow that, depending on fallback
+ * parameter.
+ *
+ * @param connection the connection
+ * @param fallback whether to handle messages also for "subdirectory"
+ * @param path a '/' delimited string of path elements
+ * @param vtable the virtual table
+ * @param user_data data to pass to functions in the vtable
+ * @param error address where an error can be returned
+ * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
+ *    #DBUS_ERROR_OBJECT_PATH_IN_USE) is reported
+ */
+static dbus_bool_t
+_dbus_connection_register_object_path (DBusConnection              *connection,
+                                       dbus_bool_t                  fallback,
+                                       const char                  *path,
+                                       const DBusObjectPathVTable  *vtable,
+                                       void                        *user_data,
+                                       DBusError                   *error)
+{
+  char **decomposed_path;
+  dbus_bool_t retval;
+
+  if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
+    return FALSE;
+
+  CONNECTION_LOCK (connection);
+
+  retval = _dbus_object_tree_register (connection->objects,
+                                       fallback,
+                                       (const char **) decomposed_path, vtable,
+                                       user_data, error);
+
+  CONNECTION_UNLOCK (connection);
+
+  dbus_free_string_array (decomposed_path);
+
+  return retval;
+}
+
+/**
+ * Registers a handler for a given path in the object hierarchy.
+ * The given vtable handles messages sent to exactly the given path.
+ *
+ * @param connection the connection
+ * @param path a '/' delimited string of path elements
+ * @param vtable the virtual table
+ * @param user_data data to pass to functions in the vtable
+ * @param error address where an error can be returned
+ * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
+ *    #DBUS_ERROR_OBJECT_PATH_IN_USE) is reported
+ */
+dbus_bool_t
+dbus_connection_try_register_object_path (DBusConnection              *connection,
+                                          const char                  *path,
+                                          const DBusObjectPathVTable  *vtable,
+                                          void                        *user_data,
+                                          DBusError                   *error)
+{
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (path != NULL, FALSE);
+  _dbus_return_val_if_fail (path[0] == '/', FALSE);
+  _dbus_return_val_if_fail (vtable != NULL, FALSE);
+
+  return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
+}
+
+/**
+ * Registers a handler for a given path in the object hierarchy.
+ * The given vtable handles messages sent to exactly the given path.
+ *
+ * It is a bug to call this function for object paths which already
+ * have a handler. Use dbus_connection_try_register_object_path() if this
+ * might be the case.
+ *
+ * @param connection the connection
+ * @param path a '/' delimited string of path elements
+ * @param vtable the virtual table
+ * @param user_data data to pass to functions in the vtable
+ * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
+ *    #DBUS_ERROR_OBJECT_PATH_IN_USE) ocurred
+ */
+dbus_bool_t
+dbus_connection_register_object_path (DBusConnection              *connection,
+                                      const char                  *path,
+                                      const DBusObjectPathVTable  *vtable,
+                                      void                        *user_data)
+{
+  dbus_bool_t retval;
+  DBusError error = DBUS_ERROR_INIT;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (path != NULL, FALSE);
+  _dbus_return_val_if_fail (path[0] == '/', FALSE);
+  _dbus_return_val_if_fail (vtable != NULL, FALSE);
+
+  retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
+
+  if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
+    {
+      _dbus_warn ("%s\n", error.message);
+      dbus_error_free (&error);
+      return FALSE;
+    }
+
+  return retval;
+}
+
+/**
+ * Registers a fallback handler for a given subsection of the object
+ * hierarchy.  The given vtable handles messages at or below the given
+ * path. You can use this to establish a default message handling
+ * policy for a whole "subdirectory."
+ *
+ * @param connection the connection
+ * @param path a '/' delimited string of path elements
+ * @param vtable the virtual table
+ * @param user_data data to pass to functions in the vtable
+ * @param error address where an error can be returned
+ * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
+ *    #DBUS_ERROR_OBJECT_PATH_IN_USE) is reported
+ */
+dbus_bool_t
+dbus_connection_try_register_fallback (DBusConnection              *connection,
+                                       const char                  *path,
+                                       const DBusObjectPathVTable  *vtable,
+                                       void                        *user_data,
+                                       DBusError                   *error)
+{
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (path != NULL, FALSE);
+  _dbus_return_val_if_fail (path[0] == '/', FALSE);
+  _dbus_return_val_if_fail (vtable != NULL, FALSE);
+
+  return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
+}
+
+/**
+ * Registers a fallback handler for a given subsection of the object
+ * hierarchy.  The given vtable handles messages at or below the given
+ * path. You can use this to establish a default message handling
+ * policy for a whole "subdirectory."
+ *
+ * It is a bug to call this function for object paths which already
+ * have a handler. Use dbus_connection_try_register_fallback() if this
+ * might be the case.
+ *
+ * @param connection the connection
+ * @param path a '/' delimited string of path elements
+ * @param vtable the virtual table
+ * @param user_data data to pass to functions in the vtable
+ * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
+ *    #DBUS_ERROR_OBJECT_PATH_IN_USE) occured
+ */
+dbus_bool_t
+dbus_connection_register_fallback (DBusConnection              *connection,
+                                   const char                  *path,
+                                   const DBusObjectPathVTable  *vtable,
+                                   void                        *user_data)
+{
+  dbus_bool_t retval;
+  DBusError error = DBUS_ERROR_INIT;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (path != NULL, FALSE);
+  _dbus_return_val_if_fail (path[0] == '/', FALSE);
+  _dbus_return_val_if_fail (vtable != NULL, FALSE);
+
+  retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
+
+  if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
+    {
+      _dbus_warn ("%s\n", error.message);
+      dbus_error_free (&error);
+      return FALSE;
+    }
+
+  return retval;
+}
+
+/**
+ * Unregisters the handler registered with exactly the given path.
+ * It's a bug to call this function for a path that isn't registered.
+ * Can unregister both fallback paths and object paths.
+ *
+ * @param connection the connection
+ * @param path a '/' delimited string of path elements
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_connection_unregister_object_path (DBusConnection              *connection,
+                                        const char                  *path)
+{
+  char **decomposed_path;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (path != NULL, FALSE);
+  _dbus_return_val_if_fail (path[0] == '/', FALSE);
+
+  if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
+      return FALSE;
+
+  CONNECTION_LOCK (connection);
+
+  _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
+
+  dbus_free_string_array (decomposed_path);
+
+  return TRUE;
+}
+
+/**
+ * Gets the user data passed to dbus_connection_register_object_path()
+ * or dbus_connection_register_fallback(). If nothing was registered
+ * at this path, the data is filled in with #NULL.
+ *
+ * @param connection the connection
+ * @param path the path you registered with
+ * @param data_p location to store the user data, or #NULL
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_connection_get_object_path_data (DBusConnection *connection,
+                                      const char     *path,
+                                      void          **data_p)
+{
+  char **decomposed_path;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (path != NULL, FALSE);
+  _dbus_return_val_if_fail (data_p != NULL, FALSE);
+
+  *data_p = NULL;
+  
+  if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
+    return FALSE;
+  
+  CONNECTION_LOCK (connection);
+
+  *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
+
+  CONNECTION_UNLOCK (connection);
+
+  dbus_free_string_array (decomposed_path);
+
+  return TRUE;
+}
+
+/**
+ * Lists the registered fallback handlers and object path handlers at
+ * the given parent_path. The returned array should be freed with
+ * dbus_free_string_array().
+ *
+ * @param connection the connection
+ * @param parent_path the path to list the child handlers of
+ * @param child_entries returns #NULL-terminated array of children
+ * @returns #FALSE if no memory to allocate the child entries
+ */
+dbus_bool_t
+dbus_connection_list_registered (DBusConnection              *connection,
+                                 const char                  *parent_path,
+                                 char                      ***child_entries)
+{
+  char **decomposed_path;
+  dbus_bool_t retval;
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (parent_path != NULL, FALSE);
+  _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
+  _dbus_return_val_if_fail (child_entries != NULL, FALSE);
+
+  if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
+    return FALSE;
+
+  CONNECTION_LOCK (connection);
+
+  retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
+							 (const char **) decomposed_path,
+							 child_entries);
+  dbus_free_string_array (decomposed_path);
+
+  return retval;
+}
+
+static DBusDataSlotAllocator slot_allocator;
+_DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
+
+/**
+ * Allocates an integer ID to be used for storing application-specific
+ * data on any DBusConnection. The allocated ID may then be used
+ * with dbus_connection_set_data() and dbus_connection_get_data().
+ * The passed-in slot must be initialized to -1, and is filled in
+ * with the slot ID. If the passed-in slot is not -1, it's assumed
+ * to be already allocated, and its refcount is incremented.
+ * 
+ * The allocated slot is global, i.e. all DBusConnection objects will
+ * have a slot with the given integer ID reserved.
+ *
+ * @param slot_p address of a global variable storing the slot
+ * @returns #FALSE on failure (no memory)
+ */
+dbus_bool_t
+dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
+{
+  return _dbus_data_slot_allocator_alloc (&slot_allocator,
+                                          &_DBUS_LOCK_NAME (connection_slots),
+                                          slot_p);
+}
+
+/**
+ * Deallocates a global ID for connection data slots.
+ * dbus_connection_get_data() and dbus_connection_set_data() may no
+ * longer be used with this slot.  Existing data stored on existing
+ * DBusConnection objects will be freed when the connection is
+ * finalized, but may not be retrieved (and may only be replaced if
+ * someone else reallocates the slot).  When the refcount on the
+ * passed-in slot reaches 0, it is set to -1.
+ *
+ * @param slot_p address storing the slot to deallocate
+ */
+void
+dbus_connection_free_data_slot (dbus_int32_t *slot_p)
+{
+  _dbus_return_if_fail (*slot_p >= 0);
+  
+  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
+}
+
+/**
+ * Stores a pointer on a DBusConnection, along
+ * with an optional function to be used for freeing
+ * the data when the data is set again, or when
+ * the connection is finalized. The slot number
+ * must have been allocated with dbus_connection_allocate_data_slot().
+ *
+ * @note This function does not take the
+ * main thread lock on DBusConnection, which allows it to be
+ * used from inside watch and timeout functions. (See the
+ * note in docs for dbus_connection_set_watch_functions().)
+ * A side effect of this is that you need to know there's
+ * a reference held on the connection while invoking
+ * dbus_connection_set_data(), or the connection could be
+ * finalized during dbus_connection_set_data().
+ *
+ * @param connection the connection
+ * @param slot the slot number
+ * @param data the data to store
+ * @param free_data_func finalizer function for the data
+ * @returns #TRUE if there was enough memory to store the data
+ */
+dbus_bool_t
+dbus_connection_set_data (DBusConnection   *connection,
+                          dbus_int32_t      slot,
+                          void             *data,
+                          DBusFreeFunction  free_data_func)
+{
+  DBusFreeFunction old_free_func;
+  void *old_data;
+  dbus_bool_t retval;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_fail (slot >= 0, FALSE);
+  
+  SLOTS_LOCK (connection);
+
+  retval = _dbus_data_slot_list_set (&slot_allocator,
+                                     &connection->slot_list,
+                                     slot, data, free_data_func,
+                                     &old_free_func, &old_data);
+  
+  SLOTS_UNLOCK (connection);
+
+  if (retval)
+    {
+      /* Do the actual free outside the connection lock */
+      if (old_free_func)
+        (* old_free_func) (old_data);
+    }
+
+  return retval;
+}
+
+/**
+ * Retrieves data previously set with dbus_connection_set_data().
+ * The slot must still be allocated (must not have been freed).
+ *
+ * @note This function does not take the
+ * main thread lock on DBusConnection, which allows it to be
+ * used from inside watch and timeout functions. (See the
+ * note in docs for dbus_connection_set_watch_functions().)
+ * A side effect of this is that you need to know there's
+ * a reference held on the connection while invoking
+ * dbus_connection_get_data(), or the connection could be
+ * finalized during dbus_connection_get_data().
+ *
+ * @param connection the connection
+ * @param slot the slot to get data from
+ * @returns the data, or #NULL if not found
+ */
+void*
+dbus_connection_get_data (DBusConnection   *connection,
+                          dbus_int32_t      slot)
+{
+  void *res;
+
+  _dbus_return_val_if_fail (connection != NULL, NULL);
+  
+  SLOTS_LOCK (connection);
+
+  res = _dbus_data_slot_list_get (&slot_allocator,
+                                  &connection->slot_list,
+                                  slot);
+  
+  SLOTS_UNLOCK (connection);
+
+  return res;
+}
+
+/**
+ * This function sets a global flag for whether dbus_connection_new()
+ * will set SIGPIPE behavior to SIG_IGN.
+ *
+ * @param will_modify_sigpipe #TRUE to allow sigpipe to be set to SIG_IGN
+ */
+void
+dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
+{  
+  _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
+}
+
+/**
+ * Specifies the maximum size message this connection is allowed to
+ * receive. Larger messages will result in disconnecting the
+ * connection.
+ * 
+ * @param connection a #DBusConnection
+ * @param size maximum message size the connection can receive, in bytes
+ */
+void
+dbus_connection_set_max_message_size (DBusConnection *connection,
+                                      long            size)
+{
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+  _dbus_transport_set_max_message_size (connection->transport,
+                                        size);
+  CONNECTION_UNLOCK (connection);
+}
+
+/**
+ * Gets the value set by dbus_connection_set_max_message_size().
+ *
+ * @param connection the connection
+ * @returns the max size of a single message
+ */
+long
+dbus_connection_get_max_message_size (DBusConnection *connection)
+{
+  long res;
+
+  _dbus_return_val_if_fail (connection != NULL, 0);
+  
+  CONNECTION_LOCK (connection);
+  res = _dbus_transport_get_max_message_size (connection->transport);
+  CONNECTION_UNLOCK (connection);
+  return res;
+}
+
+/**
+ * Specifies the maximum number of unix fds a message on this
+ * connection is allowed to receive. Messages with more unix fds will
+ * result in disconnecting the connection.
+ *
+ * @param connection a #DBusConnection
+ * @param size maximum message unix fds the connection can receive
+ */
+void
+dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
+                                          long            n)
+{
+  _dbus_return_if_fail (connection != NULL);
+
+  CONNECTION_LOCK (connection);
+  _dbus_transport_set_max_message_unix_fds (connection->transport,
+                                            n);
+  CONNECTION_UNLOCK (connection);
+}
+
+/**
+ * Gets the value set by dbus_connection_set_max_message_unix_fds().
+ *
+ * @param connection the connection
+ * @returns the max numer of unix fds of a single message
+ */
+long
+dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
+{
+  long res;
+
+  _dbus_return_val_if_fail (connection != NULL, 0);
+
+  CONNECTION_LOCK (connection);
+  res = _dbus_transport_get_max_message_unix_fds (connection->transport);
+  CONNECTION_UNLOCK (connection);
+  return res;
+}
+
+/**
+ * Sets the maximum total number of bytes that can be used for all messages
+ * received on this connection. Messages count toward the maximum until
+ * they are finalized. When the maximum is reached, the connection will
+ * not read more data until some messages are finalized.
+ *
+ * The semantics of the maximum are: if outstanding messages are
+ * already above the maximum, additional messages will not be read.
+ * The semantics are not: if the next message would cause us to exceed
+ * the maximum, we don't read it. The reason is that we don't know the
+ * size of a message until after we read it.
+ *
+ * Thus, the max live messages size can actually be exceeded
+ * by up to the maximum size of a single message.
+ * 
+ * Also, if we read say 1024 bytes off the wire in a single read(),
+ * and that contains a half-dozen small messages, we may exceed the
+ * size max by that amount. But this should be inconsequential.
+ *
+ * This does imply that we can't call read() with a buffer larger
+ * than we're willing to exceed this limit by.
+ *
+ * @param connection the connection
+ * @param size the maximum size in bytes of all outstanding messages
+ */
+void
+dbus_connection_set_max_received_size (DBusConnection *connection,
+                                       long            size)
+{
+  _dbus_return_if_fail (connection != NULL);
+  
+  CONNECTION_LOCK (connection);
+  _dbus_transport_set_max_received_size (connection->transport,
+                                         size);
+  CONNECTION_UNLOCK (connection);
+}
+
+/**
+ * Gets the value set by dbus_connection_set_max_received_size().
+ *
+ * @param connection the connection
+ * @returns the max size of all live messages
+ */
+long
+dbus_connection_get_max_received_size (DBusConnection *connection)
+{
+  long res;
+
+  _dbus_return_val_if_fail (connection != NULL, 0);
+  
+  CONNECTION_LOCK (connection);
+  res = _dbus_transport_get_max_received_size (connection->transport);
+  CONNECTION_UNLOCK (connection);
+  return res;
+}
+
+/**
+ * Sets the maximum total number of unix fds that can be used for all messages
+ * received on this connection. Messages count toward the maximum until
+ * they are finalized. When the maximum is reached, the connection will
+ * not read more data until some messages are finalized.
+ *
+ * The semantics are analogous to those of dbus_connection_set_max_received_size().
+ *
+ * @param connection the connection
+ * @param size the maximum size in bytes of all outstanding messages
+ */
+void
+dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
+                                           long            n)
+{
+  _dbus_return_if_fail (connection != NULL);
+
+  CONNECTION_LOCK (connection);
+  _dbus_transport_set_max_received_unix_fds (connection->transport,
+                                             n);
+  CONNECTION_UNLOCK (connection);
+}
+
+/**
+ * Gets the value set by dbus_connection_set_max_received_unix_fds().
+ *
+ * @param connection the connection
+ * @returns the max unix fds of all live messages
+ */
+long
+dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
+{
+  long res;
+
+  _dbus_return_val_if_fail (connection != NULL, 0);
+
+  CONNECTION_LOCK (connection);
+  res = _dbus_transport_get_max_received_unix_fds (connection->transport);
+  CONNECTION_UNLOCK (connection);
+  return res;
+}
+
+/**
+ * Gets the approximate size in bytes of all messages in the outgoing
+ * message queue. The size is approximate in that you shouldn't use
+ * it to decide how many bytes to read off the network or anything
+ * of that nature, as optimizations may choose to tell small white lies
+ * to avoid performance overhead.
+ *
+ * @param connection the connection
+ * @returns the number of bytes that have been queued up but not sent
+ */
+long
+dbus_connection_get_outgoing_size (DBusConnection *connection)
+{
+  long res;
+
+  _dbus_return_val_if_fail (connection != NULL, 0);
+
+  CONNECTION_LOCK (connection);
+  res = _dbus_counter_get_size_value (connection->outgoing_counter);
+  CONNECTION_UNLOCK (connection);
+  return res;
+}
+
+#ifdef DBUS_ENABLE_STATS
+void
+_dbus_connection_get_stats (DBusConnection *connection,
+                            dbus_uint32_t  *in_messages,
+                            dbus_uint32_t  *in_bytes,
+                            dbus_uint32_t  *in_fds,
+                            dbus_uint32_t  *in_peak_bytes,
+                            dbus_uint32_t  *in_peak_fds,
+                            dbus_uint32_t  *out_messages,
+                            dbus_uint32_t  *out_bytes,
+                            dbus_uint32_t  *out_fds,
+                            dbus_uint32_t  *out_peak_bytes,
+                            dbus_uint32_t  *out_peak_fds)
+{
+  CONNECTION_LOCK (connection);
+
+  if (in_messages != NULL)
+    *in_messages = connection->n_incoming;
+
+  _dbus_transport_get_stats (connection->transport,
+                             in_bytes, in_fds, in_peak_bytes, in_peak_fds);
+
+  if (out_messages != NULL)
+    *out_messages = connection->n_outgoing;
+
+  if (out_bytes != NULL)
+    *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
+
+  if (out_fds != NULL)
+    *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
+
+  if (out_peak_bytes != NULL)
+    *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
+
+  if (out_peak_fds != NULL)
+    *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
+
+  CONNECTION_UNLOCK (connection);
+}
+#endif /* DBUS_ENABLE_STATS */
+
+/**
+ * Gets the approximate number of uni fds of all messages in the
+ * outgoing message queue.
+ *
+ * @param connection the connection
+ * @returns the number of unix fds that have been queued up but not sent
+ */
+long
+dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
+{
+  long res;
+
+  _dbus_return_val_if_fail (connection != NULL, 0);
+
+  CONNECTION_LOCK (connection);
+  res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
+  CONNECTION_UNLOCK (connection);
+  return res;
+}
+
+#ifdef DBUS_BUILD_TESTS
+/**
+ * Returns the address of the transport object of this connection
+ *
+ * @param connection the connection
+ * @returns the address string
+ */
+const char*
+_dbus_connection_get_address (DBusConnection *connection)
+{
+  return _dbus_transport_get_address (connection->transport);
+}
+#endif
+
+/** @} */
diff --git a/dbus/dbus/dbus-connection.h b/dbus/dbus/dbus-connection.h
new file mode 100644
index 0000000..fe4d04e
--- /dev/null
+++ b/dbus/dbus/dbus-connection.h
@@ -0,0 +1,496 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-connection.h DBusConnection object
+ *
+ * Copyright (C) 2002, 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_CONNECTION_H
+#define DBUS_CONNECTION_H
+
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-memory.h>
+#include <dbus/dbus-message.h>
+#include <dbus/dbus-shared.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusConnection
+ * @{
+ */
+
+/* documented in dbus-watch.c */
+typedef struct DBusWatch DBusWatch;
+/* documented in dbus-timeout.c */
+typedef struct DBusTimeout DBusTimeout;
+/** Opaque type representing preallocated resources so a message can be sent without further memory allocation. */
+typedef struct DBusPreallocatedSend DBusPreallocatedSend;
+/** Opaque type representing a method call that has not yet received a reply. */
+typedef struct DBusPendingCall DBusPendingCall;
+/** Opaque type representing a connection to a remote application and associated incoming/outgoing message queues. */
+typedef struct DBusConnection DBusConnection;
+/** Set of functions that must be implemented to handle messages sent to a particular object path. */
+typedef struct DBusObjectPathVTable DBusObjectPathVTable;
+
+/**
+ * Indicates the status of a #DBusWatch.
+ */
+typedef enum
+{
+  DBUS_WATCH_READABLE = 1 << 0, /**< As in POLLIN */
+  DBUS_WATCH_WRITABLE = 1 << 1, /**< As in POLLOUT */
+  DBUS_WATCH_ERROR    = 1 << 2, /**< As in POLLERR (can't watch for
+                                 *   this, but can be present in
+                                 *   current state passed to
+                                 *   dbus_watch_handle()).
+                                 */
+  DBUS_WATCH_HANGUP   = 1 << 3  /**< As in POLLHUP (can't watch for
+                                 *   it, but can be present in current
+                                 *   state passed to
+                                 *   dbus_watch_handle()).
+                                 */
+  /* Internal to libdbus, there is also _DBUS_WATCH_NVAL in dbus-watch.h */
+} DBusWatchFlags;
+
+/**
+ * Indicates the status of incoming data on a #DBusConnection. This determines whether
+ * dbus_connection_dispatch() needs to be called.
+ */
+typedef enum
+{
+  DBUS_DISPATCH_DATA_REMAINS,  /**< There is more data to potentially convert to messages. */
+  DBUS_DISPATCH_COMPLETE,      /**< All currently available data has been processed. */
+  DBUS_DISPATCH_NEED_MEMORY    /**< More memory is needed to continue. */
+} DBusDispatchStatus;
+
+/** Called when libdbus needs a new watch to be monitored by the main
+ * loop. Returns #FALSE if it lacks enough memory to add the
+ * watch. Set by dbus_connection_set_watch_functions() or
+ * dbus_server_set_watch_functions().
+ */
+typedef dbus_bool_t (* DBusAddWatchFunction)       (DBusWatch      *watch,
+                                                    void           *data);
+/** Called when dbus_watch_get_enabled() may return a different value
+ *  than it did before.  Set by dbus_connection_set_watch_functions()
+ *  or dbus_server_set_watch_functions().
+ */
+typedef void        (* DBusWatchToggledFunction)   (DBusWatch      *watch,
+                                                    void           *data);
+/** Called when libdbus no longer needs a watch to be monitored by the
+ * main loop. Set by dbus_connection_set_watch_functions() or
+ * dbus_server_set_watch_functions().
+ */
+typedef void        (* DBusRemoveWatchFunction)    (DBusWatch      *watch,
+                                                    void           *data);
+/** Called when libdbus needs a new timeout to be monitored by the main
+ * loop. Returns #FALSE if it lacks enough memory to add the
+ * watch. Set by dbus_connection_set_timeout_functions() or
+ * dbus_server_set_timeout_functions().
+ */
+typedef dbus_bool_t (* DBusAddTimeoutFunction)     (DBusTimeout    *timeout,
+                                                    void           *data);
+/** Called when dbus_timeout_get_enabled() may return a different
+ * value than it did before.
+ * Set by dbus_connection_set_timeout_functions() or
+ * dbus_server_set_timeout_functions().
+ */
+typedef void        (* DBusTimeoutToggledFunction) (DBusTimeout    *timeout,
+                                                    void           *data);
+/** Called when libdbus no longer needs a timeout to be monitored by the
+ * main loop. Set by dbus_connection_set_timeout_functions() or
+ * dbus_server_set_timeout_functions().
+ */
+typedef void        (* DBusRemoveTimeoutFunction)  (DBusTimeout    *timeout,
+                                                    void           *data);
+/** Called when the return value of dbus_connection_get_dispatch_status()
+ * may have changed. Set with dbus_connection_set_dispatch_status_function().
+ */
+typedef void        (* DBusDispatchStatusFunction) (DBusConnection *connection,
+                                                    DBusDispatchStatus new_status,
+                                                    void           *data);
+/**
+ * Called when the main loop's thread should be notified that there's now work
+ * to do. Set with dbus_connection_set_wakeup_main_function().
+ */
+typedef void        (* DBusWakeupMainFunction)     (void           *data);
+
+/**
+ * Called during authentication to check whether the given UNIX user
+ * ID is allowed to connect, if the client tried to auth as a UNIX
+ * user ID. Normally on Windows this would never happen. Set with
+ * dbus_connection_set_unix_user_function().
+ */ 
+typedef dbus_bool_t (* DBusAllowUnixUserFunction)  (DBusConnection *connection,
+                                                    unsigned long   uid,
+                                                    void           *data);
+
+/**
+ * Called during authentication to check whether the given Windows user
+ * ID is allowed to connect, if the client tried to auth as a Windows
+ * user ID. Normally on UNIX this would never happen. Set with
+ * dbus_connection_set_windows_user_function().
+ */ 
+typedef dbus_bool_t (* DBusAllowWindowsUserFunction)  (DBusConnection *connection,
+                                                       const char     *user_sid,
+                                                       void           *data);
+
+
+/**
+ * Called when a pending call now has a reply available. Set with
+ * dbus_pending_call_set_notify().
+ */
+typedef void (* DBusPendingCallNotifyFunction) (DBusPendingCall *pending,
+                                                void            *user_data);
+
+/**
+ * Called when a message needs to be handled. The result indicates whether or
+ * not more handlers should be run. Set with dbus_connection_add_filter().
+ */
+typedef DBusHandlerResult (* DBusHandleMessageFunction) (DBusConnection     *connection,
+                                                         DBusMessage        *message,
+                                                         void               *user_data);
+DBUS_EXPORT
+DBusConnection*    dbus_connection_open                         (const char                 *address,
+                                                                 DBusError                  *error);
+DBUS_EXPORT
+DBusConnection*    dbus_connection_open_private                 (const char                 *address,
+                                                                 DBusError                  *error);
+DBUS_EXPORT
+DBusConnection*    dbus_connection_ref                          (DBusConnection             *connection);
+DBUS_EXPORT
+void               dbus_connection_unref                        (DBusConnection             *connection);
+DBUS_EXPORT
+void               dbus_connection_close                        (DBusConnection             *connection);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_get_is_connected             (DBusConnection             *connection);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_get_is_authenticated         (DBusConnection             *connection);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_get_is_anonymous             (DBusConnection             *connection);
+DBUS_EXPORT
+char*              dbus_connection_get_server_id                (DBusConnection             *connection);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_can_send_type                (DBusConnection             *connection,
+                                                                 int                         type);
+
+DBUS_EXPORT
+void               dbus_connection_set_exit_on_disconnect       (DBusConnection             *connection,
+                                                                 dbus_bool_t                 exit_on_disconnect);
+DBUS_EXPORT
+void               dbus_connection_flush                        (DBusConnection             *connection);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_read_write_dispatch          (DBusConnection             *connection,
+                                                                 int                         timeout_milliseconds);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_read_write                   (DBusConnection             *connection,
+                                                                 int                         timeout_milliseconds);
+DBUS_EXPORT
+DBusMessage*       dbus_connection_borrow_message               (DBusConnection             *connection);
+DBUS_EXPORT
+void               dbus_connection_return_message               (DBusConnection             *connection,
+                                                                 DBusMessage                *message);
+DBUS_EXPORT
+void               dbus_connection_steal_borrowed_message       (DBusConnection             *connection,
+                                                                 DBusMessage                *message);
+DBUS_EXPORT
+DBusMessage*       dbus_connection_pop_message                  (DBusConnection             *connection);
+DBUS_EXPORT
+DBusDispatchStatus dbus_connection_get_dispatch_status          (DBusConnection             *connection);
+DBUS_EXPORT
+DBusDispatchStatus dbus_connection_dispatch                     (DBusConnection             *connection);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_has_messages_to_send         (DBusConnection *connection);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_send                         (DBusConnection             *connection,
+                                                                 DBusMessage                *message,
+                                                                 dbus_uint32_t              *client_serial);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_send_with_reply              (DBusConnection             *connection,
+                                                                 DBusMessage                *message,
+                                                                 DBusPendingCall           **pending_return,
+                                                                 int                         timeout_milliseconds);
+DBUS_EXPORT
+DBusMessage *      dbus_connection_send_with_reply_and_block    (DBusConnection             *connection,
+                                                                 DBusMessage                *message,
+                                                                 int                         timeout_milliseconds,
+                                                                 DBusError                  *error);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_set_watch_functions          (DBusConnection             *connection,
+                                                                 DBusAddWatchFunction        add_function,
+                                                                 DBusRemoveWatchFunction     remove_function,
+                                                                 DBusWatchToggledFunction    toggled_function,
+                                                                 void                       *data,
+                                                                 DBusFreeFunction            free_data_function);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_set_timeout_functions        (DBusConnection             *connection,
+                                                                 DBusAddTimeoutFunction      add_function,
+                                                                 DBusRemoveTimeoutFunction   remove_function,
+                                                                 DBusTimeoutToggledFunction  toggled_function,
+                                                                 void                       *data,
+                                                                 DBusFreeFunction            free_data_function);
+DBUS_EXPORT
+void               dbus_connection_set_wakeup_main_function     (DBusConnection             *connection,
+                                                                 DBusWakeupMainFunction      wakeup_main_function,
+                                                                 void                       *data,
+                                                                 DBusFreeFunction            free_data_function);
+DBUS_EXPORT
+void               dbus_connection_set_dispatch_status_function (DBusConnection             *connection,
+                                                                 DBusDispatchStatusFunction  function,
+                                                                 void                       *data,
+                                                                 DBusFreeFunction            free_data_function);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_get_unix_user                (DBusConnection             *connection,
+                                                                 unsigned long              *uid);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_get_unix_process_id          (DBusConnection             *connection,
+                                                                 unsigned long              *pid);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_get_adt_audit_session_data   (DBusConnection             *connection,
+                                                                 void                      **data,
+                                                                 dbus_int32_t               *data_size);
+DBUS_EXPORT
+void               dbus_connection_set_unix_user_function       (DBusConnection             *connection,
+                                                                 DBusAllowUnixUserFunction   function,
+                                                                 void                       *data,
+                                                                 DBusFreeFunction            free_data_function);
+DBUS_EXPORT
+dbus_bool_t        dbus_connection_get_windows_user             (DBusConnection             *connection,
+                                                                 char                      **windows_sid_p); 
+DBUS_EXPORT
+void               dbus_connection_set_windows_user_function    (DBusConnection             *connection,
+                                                                 DBusAllowWindowsUserFunction function,
+                                                                 void                       *data,
+                                                                 DBusFreeFunction            free_data_function);
+DBUS_EXPORT
+void               dbus_connection_set_allow_anonymous          (DBusConnection             *connection,
+                                                                 dbus_bool_t                 value);
+DBUS_EXPORT
+void               dbus_connection_set_route_peer_messages      (DBusConnection             *connection,
+                                                                 dbus_bool_t                 value);
+
+
+/* Filters */
+
+DBUS_EXPORT
+dbus_bool_t dbus_connection_add_filter    (DBusConnection            *connection,
+                                           DBusHandleMessageFunction  function,
+                                           void                      *user_data,
+                                           DBusFreeFunction           free_data_function);
+DBUS_EXPORT
+void        dbus_connection_remove_filter (DBusConnection            *connection,
+                                           DBusHandleMessageFunction  function,
+                                           void                      *user_data);
+
+
+/* Other */
+DBUS_EXPORT
+dbus_bool_t dbus_connection_allocate_data_slot (dbus_int32_t     *slot_p);
+DBUS_EXPORT
+void        dbus_connection_free_data_slot     (dbus_int32_t     *slot_p);
+DBUS_EXPORT
+dbus_bool_t dbus_connection_set_data           (DBusConnection   *connection,
+                                                dbus_int32_t      slot,
+                                                void             *data,
+                                                DBusFreeFunction  free_data_func);
+DBUS_EXPORT
+void*       dbus_connection_get_data           (DBusConnection   *connection,
+                                                dbus_int32_t      slot);
+
+DBUS_EXPORT
+void        dbus_connection_set_change_sigpipe (dbus_bool_t       will_modify_sigpipe); 
+
+DBUS_EXPORT
+void dbus_connection_set_max_message_size  (DBusConnection *connection,
+                                            long            size);
+DBUS_EXPORT
+long dbus_connection_get_max_message_size  (DBusConnection *connection);
+DBUS_EXPORT
+void dbus_connection_set_max_received_size (DBusConnection *connection,
+                                            long            size);
+DBUS_EXPORT
+long dbus_connection_get_max_received_size (DBusConnection *connection);
+
+DBUS_EXPORT
+void dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
+                                               long            n);
+DBUS_EXPORT
+long dbus_connection_get_max_message_unix_fds (DBusConnection *connection);
+DBUS_EXPORT
+void dbus_connection_set_max_received_unix_fds(DBusConnection *connection,
+                                               long            n);
+DBUS_EXPORT
+long dbus_connection_get_max_received_unix_fds(DBusConnection *connection);
+
+DBUS_EXPORT
+long dbus_connection_get_outgoing_size     (DBusConnection *connection);
+DBUS_EXPORT
+long dbus_connection_get_outgoing_unix_fds (DBusConnection *connection);
+
+DBUS_EXPORT
+DBusPreallocatedSend* dbus_connection_preallocate_send       (DBusConnection       *connection);
+DBUS_EXPORT
+void                  dbus_connection_free_preallocated_send (DBusConnection       *connection,
+                                                              DBusPreallocatedSend *preallocated);
+DBUS_EXPORT
+void                  dbus_connection_send_preallocated      (DBusConnection       *connection,
+                                                              DBusPreallocatedSend *preallocated,
+                                                              DBusMessage          *message,
+                                                              dbus_uint32_t        *client_serial);
+
+
+/* Object tree functionality */
+
+/**
+ * Called when a #DBusObjectPathVTable is unregistered (or its connection is freed).
+ * Found in #DBusObjectPathVTable.
+ */
+typedef void              (* DBusObjectPathUnregisterFunction) (DBusConnection  *connection,
+                                                                void            *user_data);
+/**
+ * Called when a message is sent to a registered object path. Found in
+ * #DBusObjectPathVTable which is registered with dbus_connection_register_object_path()
+ * or dbus_connection_register_fallback().
+ */
+typedef DBusHandlerResult (* DBusObjectPathMessageFunction)    (DBusConnection  *connection,
+                                                                DBusMessage     *message,
+                                                                void            *user_data);
+
+/**
+ * Virtual table that must be implemented to handle a portion of the
+ * object path hierarchy. Attach the vtable to a particular path using
+ * dbus_connection_register_object_path() or
+ * dbus_connection_register_fallback().
+ */
+struct DBusObjectPathVTable
+{
+  DBusObjectPathUnregisterFunction   unregister_function; /**< Function to unregister this handler */
+  DBusObjectPathMessageFunction      message_function; /**< Function to handle messages */
+  
+  void (* dbus_internal_pad1) (void *); /**< Reserved for future expansion */
+  void (* dbus_internal_pad2) (void *); /**< Reserved for future expansion */
+  void (* dbus_internal_pad3) (void *); /**< Reserved for future expansion */
+  void (* dbus_internal_pad4) (void *); /**< Reserved for future expansion */
+};
+
+DBUS_EXPORT
+dbus_bool_t dbus_connection_try_register_object_path (DBusConnection              *connection,
+                                                      const char                  *path,
+                                                      const DBusObjectPathVTable  *vtable,
+                                                      void                        *user_data,
+                                                      DBusError                   *error);
+
+DBUS_EXPORT
+dbus_bool_t dbus_connection_register_object_path   (DBusConnection              *connection,
+                                                    const char                  *path,
+                                                    const DBusObjectPathVTable  *vtable,
+                                                    void                        *user_data);
+
+DBUS_EXPORT
+dbus_bool_t dbus_connection_try_register_fallback (DBusConnection              *connection,
+                                                   const char                  *path,
+                                                   const DBusObjectPathVTable  *vtable,
+                                                   void                        *user_data,
+                                                   DBusError                   *error);
+
+DBUS_EXPORT
+dbus_bool_t dbus_connection_register_fallback      (DBusConnection              *connection,
+                                                    const char                  *path,
+                                                    const DBusObjectPathVTable  *vtable,
+                                                    void                        *user_data);
+DBUS_EXPORT
+dbus_bool_t dbus_connection_unregister_object_path (DBusConnection              *connection,
+                                                    const char                  *path);
+
+DBUS_EXPORT
+dbus_bool_t dbus_connection_get_object_path_data   (DBusConnection              *connection,
+                                                    const char                  *path,
+                                                    void                       **data_p);
+
+DBUS_EXPORT
+dbus_bool_t dbus_connection_list_registered        (DBusConnection              *connection,
+                                                    const char                  *parent_path,
+                                                    char                      ***child_entries);
+
+DBUS_EXPORT
+dbus_bool_t dbus_connection_get_unix_fd            (DBusConnection              *connection,
+                                                    int                         *fd);
+DBUS_EXPORT
+dbus_bool_t dbus_connection_get_socket             (DBusConnection              *connection,
+                                                    int                         *fd);
+
+/** @} */
+
+
+/**
+ * @addtogroup DBusWatch
+ * @{
+ */
+
+#ifndef DBUS_DISABLE_DEPRECATED
+DBUS_EXPORT
+DBUS_DEPRECATED int dbus_watch_get_fd      (DBusWatch        *watch);
+#endif
+
+DBUS_EXPORT
+int          dbus_watch_get_unix_fd (DBusWatch        *watch);
+DBUS_EXPORT
+int          dbus_watch_get_socket  (DBusWatch        *watch);
+DBUS_EXPORT
+unsigned int dbus_watch_get_flags   (DBusWatch        *watch);
+DBUS_EXPORT
+void*        dbus_watch_get_data    (DBusWatch        *watch);
+DBUS_EXPORT
+void         dbus_watch_set_data    (DBusWatch        *watch,
+                                     void             *data,
+                                     DBusFreeFunction  free_data_function);
+DBUS_EXPORT
+dbus_bool_t  dbus_watch_handle      (DBusWatch        *watch,
+                                     unsigned int      flags);
+DBUS_EXPORT
+dbus_bool_t  dbus_watch_get_enabled (DBusWatch        *watch);
+
+/** @} */
+
+/**
+ * @addtogroup DBusTimeout
+ * @{
+ */
+
+DBUS_EXPORT
+int         dbus_timeout_get_interval (DBusTimeout      *timeout);
+DBUS_EXPORT
+void*       dbus_timeout_get_data     (DBusTimeout      *timeout);
+DBUS_EXPORT
+void        dbus_timeout_set_data     (DBusTimeout      *timeout,
+                                       void             *data,
+                                       DBusFreeFunction  free_data_function);
+DBUS_EXPORT
+dbus_bool_t dbus_timeout_handle       (DBusTimeout      *timeout);
+DBUS_EXPORT
+dbus_bool_t dbus_timeout_get_enabled  (DBusTimeout      *timeout);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_CONNECTION_H */
diff --git a/dbus/dbus/dbus-credentials-util.c b/dbus/dbus/dbus-credentials-util.c
new file mode 100644
index 0000000..0277196
--- /dev/null
+++ b/dbus/dbus/dbus-credentials-util.c
@@ -0,0 +1,206 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-credentials-util.c Would be in dbus-credentials.c, but only used for tests/bus
+ *
+ * Copyright (C) 2007 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-test.h"
+#include "dbus-credentials.h"
+
+/**
+ * @addtogroup DBusCredentials
+ * @{
+ */
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+#include <string.h>
+
+static DBusCredentials*
+make_credentials(dbus_uid_t  unix_uid,
+                 dbus_pid_t  unix_pid,
+                 const char *windows_sid)
+{
+  DBusCredentials *credentials;
+
+  credentials = _dbus_credentials_new ();
+
+  if (unix_uid != DBUS_UID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_uid (credentials, unix_uid))
+        {
+          _dbus_credentials_unref (credentials);
+          return NULL;
+        }
+    }
+
+  if (unix_pid != DBUS_PID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_pid (credentials, unix_pid))
+        {
+          _dbus_credentials_unref (credentials);
+          return NULL;
+        }
+    }
+
+  if (windows_sid != NULL)
+    {
+      if (!_dbus_credentials_add_windows_sid (credentials, windows_sid))
+        {
+          _dbus_credentials_unref (credentials);
+          return NULL;
+        }
+    }
+
+  return credentials;
+}
+
+#define SAMPLE_SID "whatever a windows sid looks like"
+#define OTHER_SAMPLE_SID "whatever else"
+
+dbus_bool_t
+_dbus_credentials_test (const char *test_data_dir)
+{
+  DBusCredentials *creds;
+  DBusCredentials *creds2;
+  
+  if (test_data_dir == NULL)
+    return TRUE;
+
+  creds = make_credentials (12, 511, SAMPLE_SID);
+  if (creds == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  /* test refcounting */
+  _dbus_credentials_ref (creds);
+  _dbus_credentials_unref (creds);
+  
+  _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_USER_ID));
+  _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_PROCESS_ID));
+  _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_WINDOWS_SID));
+
+  _dbus_assert (_dbus_credentials_get_unix_uid (creds) == 12);
+  _dbus_assert (_dbus_credentials_get_unix_pid (creds) == 511);
+  _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds), SAMPLE_SID) == 0);
+
+  _dbus_assert (!_dbus_credentials_are_empty (creds));
+  _dbus_assert (!_dbus_credentials_are_anonymous (creds));
+
+  /* Test copy */
+  creds2 = _dbus_credentials_copy (creds);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_UNIX_USER_ID));
+  _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_UNIX_PROCESS_ID));
+  _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_WINDOWS_SID));
+
+  _dbus_assert (_dbus_credentials_get_unix_uid (creds2) == 12);
+  _dbus_assert (_dbus_credentials_get_unix_pid (creds2) == 511);
+  _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds2), SAMPLE_SID) == 0);  
+
+  _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+  
+  /* Same user if both unix and windows are the same */
+  creds2 = make_credentials (12, DBUS_PID_UNSET, SAMPLE_SID);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (_dbus_credentials_same_user (creds, creds2));
+
+  _dbus_credentials_unref (creds2);
+
+  /* Not the same user if Windows is missing */
+  creds2 = make_credentials (12, DBUS_PID_UNSET, NULL);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+  _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+
+  /* Not the same user if Windows is different */
+  creds2 = make_credentials (12, DBUS_PID_UNSET, OTHER_SAMPLE_SID);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+  _dbus_assert (!_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+
+  /* Not the same user if Unix is missing */
+  creds2 = make_credentials (DBUS_UID_UNSET, DBUS_PID_UNSET, SAMPLE_SID);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+  _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+
+  /* Not the same user if Unix is different */
+  creds2 = make_credentials (15, DBUS_PID_UNSET, SAMPLE_SID);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+  _dbus_assert (!_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+
+  /* Not the same user if both are missing */
+  creds2 = make_credentials (DBUS_UID_UNSET, DBUS_PID_UNSET, NULL);
+  if (creds2 == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+  _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+  
+  _dbus_credentials_unref (creds2);
+
+  /* Clearing credentials works */
+  _dbus_credentials_clear (creds);
+
+  _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_USER_ID));
+  _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_PROCESS_ID));
+  _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_WINDOWS_SID));
+
+  _dbus_assert (_dbus_credentials_get_unix_uid (creds) == DBUS_UID_UNSET);
+  _dbus_assert (_dbus_credentials_get_unix_pid (creds) == DBUS_PID_UNSET);
+  _dbus_assert (_dbus_credentials_get_windows_sid (creds) == NULL);
+
+  _dbus_assert (_dbus_credentials_are_empty (creds));
+  _dbus_assert (_dbus_credentials_are_anonymous (creds));
+
+  _dbus_credentials_unref (creds);
+  
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-credentials.c b/dbus/dbus/dbus-credentials.c
new file mode 100644
index 0000000..ff69f3b
--- /dev/null
+++ b/dbus/dbus/dbus-credentials.c
@@ -0,0 +1,550 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-credentials.c Credentials provable through authentication
+ *
+ * Copyright (C) 2007 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#include <config.h>
+#include <string.h>
+#include "dbus-credentials.h"
+#include "dbus-internals.h"
+
+/**
+ * @defgroup DBusCredentials Credentials provable through authentication
+ * @ingroup  DBusInternals
+ * @brief DBusCredentials object
+ *
+ * Credentials are what you have to prove you have in order to
+ * authenticate.  The main credentials right now are a unix user
+ * account, a Windows user account, or a UNIX process ID.
+ */
+
+/**
+ * @defgroup DBusCredentialsInternals Credentials implementation details
+ * @ingroup  DBusInternals
+ * @brief DBusCredentials implementation details
+ *
+ * Private details of credentials code.
+ *
+ * @{
+ */
+
+struct DBusCredentials {
+  int refcount;
+  dbus_uid_t unix_uid;
+  dbus_pid_t unix_pid;
+  char *windows_sid;
+  void *adt_audit_data;
+  dbus_int32_t adt_audit_data_size;
+};
+
+/** @} */
+
+/**
+ * @addtogroup DBusCredentials
+ * @{
+ */
+
+/**
+ * Creates a new credentials object.
+ *
+ * @returns the new object or #NULL if no memory
+ */
+DBusCredentials*
+_dbus_credentials_new (void)
+{
+  DBusCredentials *creds;
+
+  creds = dbus_new (DBusCredentials, 1);
+  if (creds == NULL)
+    return NULL;
+  
+  creds->refcount = 1;
+  creds->unix_uid = DBUS_UID_UNSET;
+  creds->unix_pid = DBUS_PID_UNSET;
+  creds->windows_sid = NULL;
+  creds->adt_audit_data = NULL;
+  creds->adt_audit_data_size = 0;
+
+  return creds;
+}
+
+/**
+ * Creates a new object with credentials (user ID and process ID) from the current process.
+ * @returns the new object or #NULL if no memory
+ */
+DBusCredentials*
+_dbus_credentials_new_from_current_process (void)
+{
+  DBusCredentials *creds;
+
+  creds = _dbus_credentials_new ();
+  if (creds == NULL)
+    return NULL;
+
+  if (!_dbus_credentials_add_from_current_process (creds))
+    {
+      _dbus_credentials_unref (creds);
+      return NULL;
+    }
+  
+  return creds;
+}
+
+/**
+ * Increment refcount on credentials.
+ *
+ * @param credentials the object
+ */
+void
+_dbus_credentials_ref (DBusCredentials *credentials)
+{
+  _dbus_assert (credentials->refcount > 0);
+  credentials->refcount += 1;
+}
+
+/**
+ * Decrement refcount on credentials.
+ *
+ * @param credentials the object
+ */
+void
+_dbus_credentials_unref (DBusCredentials    *credentials)
+{
+  _dbus_assert (credentials->refcount > 0);
+
+  credentials->refcount -= 1;
+  if (credentials->refcount == 0)
+    {
+      dbus_free (credentials->windows_sid);
+      dbus_free (credentials->adt_audit_data);
+      dbus_free (credentials);
+    }
+}
+
+/**
+ * Add a UNIX process ID to the credentials.
+ *
+ * @param credentials the object
+ * @param pid the process ID
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_unix_pid (DBusCredentials    *credentials,
+                                dbus_pid_t          pid)
+{
+  credentials->unix_pid = pid;
+  return TRUE;
+}
+
+/**
+ * Add a UNIX user ID to the credentials.
+ *
+ * @param credentials the object
+ * @param uid the user ID
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_unix_uid(DBusCredentials    *credentials,
+                               dbus_uid_t          uid)
+{
+  credentials->unix_uid = uid;
+  return TRUE;
+
+}
+
+/**
+ * Add a Windows user SID to the credentials.
+ *
+ * @param credentials the object
+ * @param windows_sid the user SID
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_windows_sid (DBusCredentials    *credentials,
+                                   const char         *windows_sid)
+{
+  char *copy;
+
+  copy = _dbus_strdup (windows_sid);
+  if (copy == NULL)
+    return FALSE;
+
+  dbus_free (credentials->windows_sid);
+  credentials->windows_sid = copy;
+
+  return TRUE;
+}
+
+/**
+ * Add ADT audit data to the credentials.
+ *
+ * @param credentials the object
+ * @param audit_data the audit data
+ * @param size the length of audit data
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_adt_audit_data (DBusCredentials    *credentials,
+                                      void               *audit_data,
+                                      dbus_int32_t        size)
+{
+  void *copy;
+  copy = _dbus_memdup (audit_data, size);
+  if (copy == NULL)
+    return FALSE;
+
+  dbus_free (credentials->adt_audit_data);
+  credentials->adt_audit_data = copy;
+  credentials->adt_audit_data_size = size;
+
+  return TRUE;
+}
+
+/**
+ * Checks whether the given credential is present.
+ *
+ * @param credentials the object
+ * @param type the credential to check for
+ * @returns #TRUE if the credential is present
+ */
+dbus_bool_t
+_dbus_credentials_include (DBusCredentials    *credentials,
+                           DBusCredentialType  type)
+{
+  switch (type)
+    {
+    case DBUS_CREDENTIAL_UNIX_PROCESS_ID:
+      return credentials->unix_pid != DBUS_PID_UNSET;
+    case DBUS_CREDENTIAL_UNIX_USER_ID:
+      return credentials->unix_uid != DBUS_UID_UNSET;
+    case DBUS_CREDENTIAL_WINDOWS_SID:
+      return credentials->windows_sid != NULL;
+    case DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID:
+      return credentials->adt_audit_data != NULL;
+    }
+
+  _dbus_assert_not_reached ("Unknown credential enum value");
+  return FALSE;
+}
+
+/**
+ * Gets the UNIX process ID in the credentials, or #DBUS_PID_UNSET if
+ * the credentials object doesn't contain a process ID.
+ *
+ * @param credentials the object
+ * @returns UNIX process ID
+ */
+dbus_pid_t
+_dbus_credentials_get_unix_pid (DBusCredentials    *credentials)
+{
+  return credentials->unix_pid;
+}
+
+/**
+ * Gets the UNIX user ID in the credentials, or #DBUS_UID_UNSET if
+ * the credentials object doesn't contain a user ID.
+ *
+ * @param credentials the object
+ * @returns UNIX user ID
+ */
+dbus_uid_t
+_dbus_credentials_get_unix_uid (DBusCredentials    *credentials)
+{
+  return credentials->unix_uid;
+}
+
+/**
+ * Gets the Windows user SID in the credentials, or #NULL if
+ * the credentials object doesn't contain a Windows user SID.
+ *
+ * @param credentials the object
+ * @returns Windows user SID
+ */
+const char*
+_dbus_credentials_get_windows_sid (DBusCredentials    *credentials)
+{
+  return credentials->windows_sid;
+}
+
+/**
+ * Gets the ADT audit data in the credentials, or #NULL if
+ * the credentials object doesn't contain ADT audit data.
+ *
+ * @param credentials the object
+ * @returns Solaris ADT audit data 
+ */
+void *
+_dbus_credentials_get_adt_audit_data (DBusCredentials    *credentials)
+{
+  return credentials->adt_audit_data;
+}
+
+/**
+ * Gets the ADT audit data size in the credentials, or 0 if
+ * the credentials object doesn't contain ADT audit data.
+ *
+ * @param credentials the object
+ * @returns Solaris ADT audit data size
+ */
+dbus_int32_t 
+_dbus_credentials_get_adt_audit_data_size (DBusCredentials    *credentials)
+{
+  return credentials->adt_audit_data_size;
+}
+
+/**
+ * Checks whether the first credentials object contains
+ * all the credentials found in the second credentials object.
+ *
+ * @param credentials the object
+ * @param possible_subset see if credentials in here are also in the first arg
+ * @returns #TRUE if second arg is contained in first
+ */
+dbus_bool_t
+_dbus_credentials_are_superset (DBusCredentials    *credentials,
+                                DBusCredentials    *possible_subset)
+{
+  return
+    (possible_subset->unix_pid == DBUS_PID_UNSET ||
+     possible_subset->unix_pid == credentials->unix_pid) &&
+    (possible_subset->unix_uid == DBUS_UID_UNSET ||
+     possible_subset->unix_uid == credentials->unix_uid) &&
+    (possible_subset->windows_sid == NULL ||
+     (credentials->windows_sid && strcmp (possible_subset->windows_sid,
+                                          credentials->windows_sid) == 0)) &&
+    (possible_subset->adt_audit_data == NULL ||
+     (credentials->adt_audit_data && memcmp (possible_subset->adt_audit_data,
+                                             credentials->adt_audit_data,
+                                             credentials->adt_audit_data_size) == 0));
+}
+
+/**
+ * Checks whether a credentials object contains anything.
+ * 
+ * @param credentials the object
+ * @returns #TRUE if there are no credentials in the object
+ */
+dbus_bool_t
+_dbus_credentials_are_empty (DBusCredentials    *credentials)
+{
+  return
+    credentials->unix_pid == DBUS_PID_UNSET &&
+    credentials->unix_uid == DBUS_UID_UNSET &&
+    credentials->windows_sid == NULL &&
+    credentials->adt_audit_data == NULL;
+}
+
+/**
+ * Checks whether a credentials object contains a user identity.
+ * 
+ * @param credentials the object
+ * @returns #TRUE if there are no user identities in the object
+ */
+dbus_bool_t
+_dbus_credentials_are_anonymous (DBusCredentials    *credentials)
+{
+  return
+    credentials->unix_uid == DBUS_UID_UNSET &&
+    credentials->windows_sid == NULL;
+}
+
+/**
+ * Merge all credentials found in the second object into the first object,
+ * overwriting the first object if there are any overlaps.
+ * 
+ * @param credentials the object
+ * @param other_credentials credentials to merge
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_credentials (DBusCredentials    *credentials,
+                                   DBusCredentials    *other_credentials)
+{
+  return
+    _dbus_credentials_add_credential (credentials,
+                                      DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+                                      other_credentials) &&
+    _dbus_credentials_add_credential (credentials,
+                                      DBUS_CREDENTIAL_UNIX_USER_ID,
+                                      other_credentials) &&
+    _dbus_credentials_add_credential (credentials,
+                                      DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID,
+                                      other_credentials) &&
+    _dbus_credentials_add_credential (credentials,
+                                      DBUS_CREDENTIAL_WINDOWS_SID,
+                                      other_credentials);
+}
+
+/**
+ * Merge the given credential found in the second object into the first object,
+ * overwriting the first object's value for that credential.
+ *
+ * Does nothing if the second object does not contain the specified credential.
+ * i.e., will never delete a credential from the first object.
+ * 
+ * @param credentials the object
+ * @param which the credential to overwrite
+ * @param other_credentials credentials to merge
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_credential (DBusCredentials    *credentials,
+                                  DBusCredentialType  which,
+                                  DBusCredentials    *other_credentials)
+{
+  if (which == DBUS_CREDENTIAL_UNIX_PROCESS_ID &&
+      other_credentials->unix_pid != DBUS_PID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_pid (credentials, other_credentials->unix_pid))
+        return FALSE;
+    }
+  else if (which == DBUS_CREDENTIAL_UNIX_USER_ID &&
+           other_credentials->unix_uid != DBUS_UID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_uid (credentials, other_credentials->unix_uid))
+        return FALSE;
+    }
+  else if (which == DBUS_CREDENTIAL_WINDOWS_SID &&
+           other_credentials->windows_sid != NULL)
+    {
+      if (!_dbus_credentials_add_windows_sid (credentials, other_credentials->windows_sid))
+        return FALSE;
+    } 
+  else if (which == DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID &&
+           other_credentials->adt_audit_data != NULL) 
+    {
+      if (!_dbus_credentials_add_adt_audit_data (credentials, other_credentials->adt_audit_data, other_credentials->adt_audit_data_size))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Clear all credentials in the object.
+ * 
+ * @param credentials the object
+ */
+void
+_dbus_credentials_clear (DBusCredentials    *credentials)
+{
+  credentials->unix_pid = DBUS_PID_UNSET;
+  credentials->unix_uid = DBUS_UID_UNSET;
+  dbus_free (credentials->windows_sid);
+  credentials->windows_sid = NULL;
+  dbus_free (credentials->adt_audit_data);
+  credentials->adt_audit_data = NULL;
+  credentials->adt_audit_data_size = 0;
+}
+
+/**
+ * Copy a credentials object.
+ * 
+ * @param credentials the object
+ * @returns the copy or #NULL
+ */
+DBusCredentials*
+_dbus_credentials_copy (DBusCredentials    *credentials)
+{
+  DBusCredentials *copy;
+
+  copy = _dbus_credentials_new ();
+  if (copy == NULL)
+    return NULL;
+
+  if (!_dbus_credentials_add_credentials (copy, credentials))
+    {
+      _dbus_credentials_unref (copy);
+      return NULL;
+    }
+
+  return copy;
+}
+
+/**
+ * Check whether the user-identifying credentials in two credentials
+ * objects are identical. Credentials that are not related to the
+ * user are ignored, but any kind of user ID credentials must be the
+ * same (UNIX user ID, Windows user SID, etc.) and present in both
+ * objects for the function to return #TRUE.
+ * 
+ * @param credentials the object
+ * @param other_credentials credentials to compare
+ * @returns #TRUE if the two credentials refer to the same user
+ */
+dbus_bool_t
+_dbus_credentials_same_user (DBusCredentials    *credentials,
+                             DBusCredentials    *other_credentials)
+{
+  /* both windows and unix user must be the same (though pretty much
+   * in all conceivable cases, one will be unset)
+   */
+  return credentials->unix_uid == other_credentials->unix_uid &&
+    ((!(credentials->windows_sid || other_credentials->windows_sid)) ||
+     (credentials->windows_sid && other_credentials->windows_sid &&
+      strcmp (credentials->windows_sid, other_credentials->windows_sid) == 0));
+}
+
+/**
+ * Convert the credentials in this object to a human-readable
+ * string format, and append to the given string.
+ *
+ * @param credentials the object
+ * @param string append to this string
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_to_string_append (DBusCredentials    *credentials,
+                                    DBusString         *string)
+{
+  dbus_bool_t join;
+
+  join = FALSE;
+  if (credentials->unix_uid != DBUS_UID_UNSET)
+    {
+      if (!_dbus_string_append_printf (string, "uid=" DBUS_UID_FORMAT, credentials->unix_uid))
+        goto oom;
+      join = TRUE;
+    }
+  if (credentials->unix_pid != DBUS_PID_UNSET)
+    {
+      if (!_dbus_string_append_printf (string, "%spid=" DBUS_PID_FORMAT, join ? " " : "", credentials->unix_pid))
+        goto oom;
+      join = TRUE;
+    }
+  else
+    join = FALSE;
+  if (credentials->windows_sid != NULL)
+    {
+      if (!_dbus_string_append_printf (string, "%ssid=%s", join ? " " : "", credentials->windows_sid))
+        goto oom;
+      join = TRUE;
+    }
+  else
+    join = FALSE;
+
+  return TRUE;
+oom:
+  return FALSE;
+}
+
+/** @} */
+
+/* tests in dbus-credentials-util.c */
diff --git a/dbus/dbus/dbus-credentials.h b/dbus/dbus/dbus-credentials.h
new file mode 100644
index 0000000..ef6124f
--- /dev/null
+++ b/dbus/dbus/dbus-credentials.h
@@ -0,0 +1,79 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-credentials.h Credentials provable through authentication
+ *
+ * Copyright (C) 2007 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_CREDENTIALS_H
+#define DBUS_CREDENTIALS_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-sysdeps.h>
+
+DBUS_BEGIN_DECLS
+
+typedef enum {
+  DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+  DBUS_CREDENTIAL_UNIX_USER_ID,
+  DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID,
+  DBUS_CREDENTIAL_WINDOWS_SID
+} DBusCredentialType;
+
+DBusCredentials* _dbus_credentials_new_from_current_process (void);
+DBusCredentials* _dbus_credentials_new                      (void);
+void             _dbus_credentials_ref                      (DBusCredentials    *credentials);
+void             _dbus_credentials_unref                    (DBusCredentials    *credentials);
+dbus_bool_t      _dbus_credentials_add_unix_pid             (DBusCredentials    *credentials,
+                                                             dbus_pid_t          pid);
+dbus_bool_t      _dbus_credentials_add_unix_uid             (DBusCredentials    *credentials,
+                                                             dbus_uid_t          uid);
+dbus_bool_t      _dbus_credentials_add_windows_sid          (DBusCredentials    *credentials,
+                                                             const char         *windows_sid);
+dbus_bool_t      _dbus_credentials_add_adt_audit_data       (DBusCredentials    *credentials,
+                                                             void               *audit_data,
+                                                             dbus_int32_t        size);
+dbus_bool_t      _dbus_credentials_include                  (DBusCredentials    *credentials,
+                                                             DBusCredentialType  type);
+dbus_pid_t       _dbus_credentials_get_unix_pid             (DBusCredentials    *credentials);
+dbus_uid_t       _dbus_credentials_get_unix_uid             (DBusCredentials    *credentials);
+const char*      _dbus_credentials_get_windows_sid          (DBusCredentials    *credentials);
+void *           _dbus_credentials_get_adt_audit_data       (DBusCredentials    *credentials);
+dbus_int32_t     _dbus_credentials_get_adt_audit_data_size  (DBusCredentials    *credentials);
+dbus_bool_t      _dbus_credentials_are_superset             (DBusCredentials    *credentials,
+                                                             DBusCredentials    *possible_subset);
+dbus_bool_t      _dbus_credentials_are_empty                (DBusCredentials    *credentials);
+dbus_bool_t      _dbus_credentials_are_anonymous            (DBusCredentials    *credentials);
+dbus_bool_t      _dbus_credentials_add_credentials          (DBusCredentials    *credentials,
+                                                             DBusCredentials    *other_credentials);
+/* must silently allow 'which' to not exist */
+dbus_bool_t      _dbus_credentials_add_credential           (DBusCredentials    *credentials,
+                                                             DBusCredentialType  which,
+                                                             DBusCredentials    *other_credentials);
+void             _dbus_credentials_clear                    (DBusCredentials    *credentials);
+DBusCredentials* _dbus_credentials_copy                     (DBusCredentials    *credentials);
+dbus_bool_t      _dbus_credentials_same_user                (DBusCredentials    *credentials,
+                                                             DBusCredentials    *other_credentials);
+dbus_bool_t      _dbus_credentials_to_string_append         (DBusCredentials    *credentials,
+                                                             DBusString         *string);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_CREDENTIALS_H */
diff --git a/dbus/dbus/dbus-dataslot.c b/dbus/dbus/dbus-dataslot.c
new file mode 100644
index 0000000..0369612
--- /dev/null
+++ b/dbus/dbus/dbus-dataslot.c
@@ -0,0 +1,479 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-dataslot.c  storing data on objects
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-dataslot.h"
+#include "dbus-threads-internal.h"
+
+/**
+ * @defgroup DBusDataSlot Data slots
+ * @ingroup  DBusInternals
+ * @brief Storing data by ID
+ *
+ * Types and functions related to storing data by an
+ * allocated ID. This is used for dbus_connection_set_data(),
+ * dbus_server_set_data(), etc. 
+ * @{
+ */
+
+/**
+ * Initializes a data slot allocator object, used to assign
+ * integer IDs for data slots.
+ *
+ * @param allocator the allocator to initialize
+ */
+dbus_bool_t
+_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator)
+{
+  allocator->allocated_slots = NULL;
+  allocator->n_allocated_slots = 0;
+  allocator->n_used_slots = 0;
+  allocator->lock_loc = NULL;
+  
+  return TRUE;
+}
+
+/**
+ * Allocates an integer ID to be used for storing data
+ * in a #DBusDataSlotList. If the value at *slot_id_p is
+ * not -1, this function just increments the refcount for
+ * the existing slot ID. If the value is -1, a new slot ID
+ * is allocated and stored at *slot_id_p.
+ * 
+ * @param allocator the allocator
+ * @param mutex_loc the location lock for this allocator
+ * @param slot_id_p address to fill with the slot ID
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
+                                 DBusRMutex            **mutex_loc,
+                                 dbus_int32_t          *slot_id_p)
+{
+  dbus_int32_t slot;
+
+  _dbus_rmutex_lock (*mutex_loc);
+
+  if (allocator->n_allocated_slots == 0)
+    {
+      _dbus_assert (allocator->lock_loc == NULL);
+      allocator->lock_loc = mutex_loc;
+    }
+  else if (allocator->lock_loc != mutex_loc)
+    {
+      _dbus_warn_check_failed ("D-Bus threads were initialized after first using the D-Bus library. If your application does not directly initialize threads or use D-Bus, keep in mind that some library or plugin may have used D-Bus or initialized threads behind your back. You can often fix this problem by calling dbus_init_threads() or dbus_g_threads_init() early in your main() method, before D-Bus is used.\n");
+      _dbus_assert_not_reached ("exiting");
+    }
+
+  if (*slot_id_p >= 0)
+    {
+      slot = *slot_id_p;
+      
+      _dbus_assert (slot < allocator->n_allocated_slots);
+      _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
+      
+      allocator->allocated_slots[slot].refcount += 1;
+
+      goto out;
+    }
+
+  _dbus_assert (*slot_id_p < 0);
+  
+  if (allocator->n_used_slots < allocator->n_allocated_slots)
+    {
+      slot = 0;
+      while (slot < allocator->n_allocated_slots)
+        {
+          if (allocator->allocated_slots[slot].slot_id < 0)
+            {
+              allocator->allocated_slots[slot].slot_id = slot;
+              allocator->allocated_slots[slot].refcount = 1;
+              allocator->n_used_slots += 1;
+              break;
+            }
+          ++slot;
+        }
+
+      _dbus_assert (slot < allocator->n_allocated_slots);
+    }
+  else
+    {
+      DBusAllocatedSlot *tmp;
+      
+      slot = -1;
+      tmp = dbus_realloc (allocator->allocated_slots,
+                          sizeof (DBusAllocatedSlot) * (allocator->n_allocated_slots + 1));
+      if (tmp == NULL)
+        goto out;
+
+      allocator->allocated_slots = tmp;
+      slot = allocator->n_allocated_slots;
+      allocator->n_allocated_slots += 1;
+      allocator->n_used_slots += 1;
+      allocator->allocated_slots[slot].slot_id = slot;
+      allocator->allocated_slots[slot].refcount = 1;
+    }
+
+  _dbus_assert (slot >= 0);
+  _dbus_assert (slot < allocator->n_allocated_slots);
+  _dbus_assert (*slot_id_p < 0);
+  _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
+  _dbus_assert (allocator->allocated_slots[slot].refcount == 1);
+  
+  *slot_id_p = slot;
+  
+  _dbus_verbose ("Allocated slot %d on allocator %p total %d slots allocated %d used\n",
+                 slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots);
+  
+ out:
+  _dbus_rmutex_unlock (*(allocator->lock_loc));
+  return slot >= 0;
+}
+
+/**
+ * Deallocates an ID previously allocated with
+ * _dbus_data_slot_allocator_alloc().  Existing data stored on
+ * existing #DBusDataSlotList objects with this ID will be freed when the
+ * data list is finalized, but may not be retrieved (and may only be
+ * replaced if someone else reallocates the slot).
+ * The slot value is reset to -1 if this is the last unref.
+ *
+ * @param allocator the allocator
+ * @param slot_id_p address where we store the slot
+ */
+void
+_dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
+                                dbus_int32_t          *slot_id_p)
+{
+  _dbus_rmutex_lock (*(allocator->lock_loc));
+  
+  _dbus_assert (*slot_id_p < allocator->n_allocated_slots);
+  _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p);
+  _dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0);
+
+  allocator->allocated_slots[*slot_id_p].refcount -= 1;
+
+  if (allocator->allocated_slots[*slot_id_p].refcount > 0)
+    {
+      _dbus_rmutex_unlock (*(allocator->lock_loc));
+      return;
+    }
+
+  /* refcount is 0, free the slot */
+  _dbus_verbose ("Freeing slot %d on allocator %p total %d allocated %d used\n",
+                 *slot_id_p, allocator, allocator->n_allocated_slots, allocator->n_used_slots);
+  
+  allocator->allocated_slots[*slot_id_p].slot_id = -1;
+  *slot_id_p = -1;
+  
+  allocator->n_used_slots -= 1;
+  
+  if (allocator->n_used_slots == 0)
+    {
+      DBusRMutex **mutex_loc = allocator->lock_loc;
+      
+      dbus_free (allocator->allocated_slots);
+      allocator->allocated_slots = NULL;
+      allocator->n_allocated_slots = 0;
+      allocator->lock_loc = NULL;
+
+      _dbus_rmutex_unlock (*mutex_loc);
+    }
+  else
+    {
+      _dbus_rmutex_unlock (*(allocator->lock_loc));
+    }
+}
+
+/**
+ * Initializes a slot list.
+ * @param list the list to initialize.
+ */
+void
+_dbus_data_slot_list_init (DBusDataSlotList *list)
+{
+  list->slots = NULL;
+  list->n_slots = 0;
+}
+
+/**
+ * Stores a pointer in the data slot list, along with an optional
+ * function to be used for freeing the data when the data is set
+ * again, or when the slot list is finalized. The slot number must
+ * have been allocated with _dbus_data_slot_allocator_alloc() for the
+ * same allocator passed in here. The same allocator has to be used
+ * with the slot list every time.
+ *
+ * @param allocator the allocator to use
+ * @param list the data slot list
+ * @param slot the slot number
+ * @param data the data to store
+ * @param free_data_func finalizer function for the data
+ * @param old_free_func free function for any previously-existing data
+ * @param old_data previously-existing data, should be freed with old_free_func
+ * @returns #TRUE if there was enough memory to store the data
+ */
+dbus_bool_t
+_dbus_data_slot_list_set  (DBusDataSlotAllocator *allocator,
+                           DBusDataSlotList      *list,
+                           int                    slot,
+                           void                  *data,
+                           DBusFreeFunction       free_data_func,
+                           DBusFreeFunction      *old_free_func,
+                           void                 **old_data)
+{
+#ifndef DBUS_DISABLE_ASSERT
+  /* We need to take the allocator lock here, because the allocator could
+   * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
+   * are disabled, since then the asserts are empty.
+   */
+  _dbus_rmutex_lock (*(allocator->lock_loc));
+  _dbus_assert (slot < allocator->n_allocated_slots);
+  _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
+  _dbus_rmutex_unlock (*(allocator->lock_loc));
+#endif
+  
+  if (slot >= list->n_slots)
+    {
+      DBusDataSlot *tmp;
+      int i;
+      
+      tmp = dbus_realloc (list->slots,
+                          sizeof (DBusDataSlot) * (slot + 1));
+      if (tmp == NULL)
+        return FALSE;
+      
+      list->slots = tmp;
+      i = list->n_slots;
+      list->n_slots = slot + 1;
+      while (i < list->n_slots)
+        {
+          list->slots[i].data = NULL;
+          list->slots[i].free_data_func = NULL;
+          ++i;
+        }
+    }
+
+  _dbus_assert (slot < list->n_slots);
+
+  *old_data = list->slots[slot].data;
+  *old_free_func = list->slots[slot].free_data_func;
+
+  list->slots[slot].data = data;
+  list->slots[slot].free_data_func = free_data_func;
+
+  return TRUE;
+}
+
+/**
+ * Retrieves data previously set with _dbus_data_slot_list_set_data().
+ * The slot must still be allocated (must not have been freed).
+ *
+ * @param allocator the allocator slot was allocated from
+ * @param list the data slot list
+ * @param slot the slot to get data from
+ * @returns the data, or #NULL if not found
+ */
+void*
+_dbus_data_slot_list_get  (DBusDataSlotAllocator *allocator,
+                           DBusDataSlotList      *list,
+                           int                    slot)
+{
+#ifndef DBUS_DISABLE_ASSERT
+  /* We need to take the allocator lock here, because the allocator could
+   * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
+   * are disabled, since then the asserts are empty.
+   */
+  _dbus_rmutex_lock (*(allocator->lock_loc));
+  _dbus_assert (slot >= 0);
+  _dbus_assert (slot < allocator->n_allocated_slots);
+  _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
+  _dbus_rmutex_unlock (*(allocator->lock_loc));
+#endif
+
+  if (slot >= list->n_slots)
+    return NULL;
+  else
+    return list->slots[slot].data;
+}
+
+/**
+ * Frees all data slots contained in the list, calling
+ * application-provided free functions if they exist.
+ *
+ * @param list the list to clear
+ */
+void
+_dbus_data_slot_list_clear (DBusDataSlotList *list)
+{
+  int i;
+
+  i = 0;
+  while (i < list->n_slots)
+    {
+      if (list->slots[i].free_data_func)
+        (* list->slots[i].free_data_func) (list->slots[i].data);
+      list->slots[i].data = NULL;
+      list->slots[i].free_data_func = NULL;
+      ++i;
+    }
+}
+
+/**
+ * Frees the data slot list and all data slots contained
+ * in it, calling application-provided free functions
+ * if they exist.
+ *
+ * @param list the list to free
+ */
+void
+_dbus_data_slot_list_free (DBusDataSlotList *list)
+{
+  _dbus_data_slot_list_clear (list);
+  
+  dbus_free (list->slots);
+  list->slots = NULL;
+  list->n_slots = 0;
+}
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+
+static int free_counter;
+
+static void
+test_free_slot_data_func (void *data)
+{
+  int i = _DBUS_POINTER_TO_INT (data);
+
+  _dbus_assert (free_counter == i);
+  ++free_counter;
+}
+
+/**
+ * Test function for data slots
+ */
+dbus_bool_t
+_dbus_data_slot_test (void)
+{
+  DBusDataSlotAllocator allocator;
+  DBusDataSlotList list;
+  int i;
+  DBusFreeFunction old_free_func;
+  void *old_data;
+  DBusRMutex *mutex;
+  
+  if (!_dbus_data_slot_allocator_init (&allocator))
+    _dbus_assert_not_reached ("no memory for allocator");
+
+  _dbus_data_slot_list_init (&list);
+
+  _dbus_rmutex_new_at_location (&mutex);
+  if (mutex == NULL)
+    _dbus_assert_not_reached ("failed to alloc mutex");
+  
+#define N_SLOTS 100
+
+  i = 0;
+  while (i < N_SLOTS)
+    {
+      /* we don't really want apps to rely on this ordered
+       * allocation, but it simplifies things to rely on it
+       * here.
+       */
+      dbus_int32_t tmp = -1;
+      
+      _dbus_data_slot_allocator_alloc (&allocator, &mutex, &tmp);
+
+      if (tmp != i)
+        _dbus_assert_not_reached ("did not allocate slots in numeric order\n");
+
+      ++i;
+    }
+
+  i = 0;
+  while (i < N_SLOTS)
+    {
+      if (!_dbus_data_slot_list_set (&allocator, &list,
+                                     i,
+                                     _DBUS_INT_TO_POINTER (i), 
+                                     test_free_slot_data_func,
+                                     &old_free_func, &old_data))
+        _dbus_assert_not_reached ("no memory to set data");
+
+      _dbus_assert (old_free_func == NULL);
+      _dbus_assert (old_data == NULL);
+
+      _dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) ==
+                    _DBUS_INT_TO_POINTER (i));
+      
+      ++i;
+    }
+
+  free_counter = 0;
+  i = 0;
+  while (i < N_SLOTS)
+    {
+      if (!_dbus_data_slot_list_set (&allocator, &list,
+                                     i,
+                                     _DBUS_INT_TO_POINTER (i), 
+                                     test_free_slot_data_func,
+                                     &old_free_func, &old_data))
+        _dbus_assert_not_reached ("no memory to set data");
+
+      _dbus_assert (old_free_func == test_free_slot_data_func);
+      _dbus_assert (_DBUS_POINTER_TO_INT (old_data) == i);
+
+      (* old_free_func) (old_data);
+      _dbus_assert (i == (free_counter - 1));
+
+      _dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) ==
+                    _DBUS_INT_TO_POINTER (i));
+      
+      ++i;
+    }
+
+  free_counter = 0;
+  _dbus_data_slot_list_free (&list);
+
+  _dbus_assert (N_SLOTS == free_counter);
+
+  i = 0;
+  while (i < N_SLOTS)
+    {
+      dbus_int32_t tmp = i;
+      
+      _dbus_data_slot_allocator_free (&allocator, &tmp);
+      _dbus_assert (tmp == -1);
+      ++i;
+    }
+
+  _dbus_rmutex_free_at_location (&mutex);
+  
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-dataslot.h b/dbus/dbus/dbus-dataslot.h
new file mode 100644
index 0000000..3d9d5ed
--- /dev/null
+++ b/dbus/dbus/dbus-dataslot.h
@@ -0,0 +1,96 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-dataslot.h  storing data on objects
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_DATASLOT_H
+#define DBUS_DATASLOT_H
+
+#include <dbus/dbus-internals.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusDataSlotAllocator DBusDataSlotAllocator;
+typedef struct DBusDataSlotList DBusDataSlotList;
+
+/** Opaque typedef for DBusDataSlot */
+typedef struct DBusDataSlot DBusDataSlot;
+/** DBusDataSlot is used to store application data on the connection */
+struct DBusDataSlot
+{
+  void *data;                      /**< The application data */
+  DBusFreeFunction free_data_func; /**< Free the application data */
+};
+
+typedef struct DBusAllocatedSlot DBusAllocatedSlot;
+
+/** An allocated slot for storing data
+ */
+struct DBusAllocatedSlot
+{
+  dbus_int32_t slot_id;  /**< ID of this slot */
+  int          refcount; /**< Number of uses of the slot */
+};
+
+/**
+ * An allocator that tracks a set of slot IDs.
+ */
+struct DBusDataSlotAllocator
+{
+  DBusAllocatedSlot *allocated_slots; /**< Allocated slots */
+  int  n_allocated_slots; /**< number of slots malloc'd */
+  int  n_used_slots;      /**< number of slots used */
+  DBusRMutex **lock_loc;  /**< location of thread lock */
+};
+
+/**
+ * Data structure that stores the actual user data set at a given
+ * slot.
+ */
+struct DBusDataSlotList
+{
+  DBusDataSlot *slots;   /**< Data slots */
+  int           n_slots; /**< Slots we have storage for in data_slots */
+};
+
+dbus_bool_t _dbus_data_slot_allocator_init  (DBusDataSlotAllocator  *allocator);
+dbus_bool_t _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator  *allocator,
+                                             DBusRMutex             **mutex_loc,
+                                             int                    *slot_id_p);
+void        _dbus_data_slot_allocator_free  (DBusDataSlotAllocator  *allocator,
+                                             int                    *slot_id_p);
+void        _dbus_data_slot_list_init       (DBusDataSlotList       *list);
+dbus_bool_t _dbus_data_slot_list_set        (DBusDataSlotAllocator  *allocator,
+                                             DBusDataSlotList       *list,
+                                             int                     slot,
+                                             void                   *data,
+                                             DBusFreeFunction        free_data_func,
+                                             DBusFreeFunction       *old_free_func,
+                                             void                  **old_data);
+void*       _dbus_data_slot_list_get        (DBusDataSlotAllocator  *allocator,
+                                             DBusDataSlotList       *list,
+                                             int                     slot);
+void        _dbus_data_slot_list_clear      (DBusDataSlotList       *list);
+void        _dbus_data_slot_list_free       (DBusDataSlotList       *list);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_DATASLOT_H */
diff --git a/dbus/dbus/dbus-errors.c b/dbus/dbus/dbus-errors.c
new file mode 100644
index 0000000..db3305b
--- /dev/null
+++ b/dbus/dbus/dbus-errors.c
@@ -0,0 +1,422 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-errors.c Error reporting
+ *
+ * Copyright (C) 2002, 2004  Red Hat Inc.
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-errors.h"
+#include "dbus-internals.h"
+#include "dbus-string.h"
+#include "dbus-protocol.h"
+#include <stdarg.h>
+#include <string.h>
+
+/**
+ * @defgroup DBusErrorInternals Error reporting internals
+ * @ingroup  DBusInternals
+ * @brief Error reporting internals
+ * @{
+ */
+
+/**
+ * @def DBUS_ERROR_INIT
+ *
+ * Expands to a suitable initializer for a DBusError on the stack.
+ * Declaring a DBusError with:
+ *
+ * @code
+ * DBusError error = DBUS_ERROR_INIT;
+ *
+ * do_things_with (&error);
+ * @endcode
+ *
+ * is a more concise form of:
+ *
+ * @code
+ * DBusError error;
+ *
+ * dbus_error_init (&error);
+ * do_things_with (&error);
+ * @endcode
+ */
+
+/**
+ * Internals of DBusError
+ */
+typedef struct
+{
+  char *name; /**< error name */
+  char *message; /**< error message */
+
+  unsigned int const_message : 1; /**< Message is not owned by DBusError */
+
+  unsigned int dummy2 : 1; /**< placeholder */
+  unsigned int dummy3 : 1; /**< placeholder */
+  unsigned int dummy4 : 1; /**< placeholder */
+  unsigned int dummy5 : 1; /**< placeholder */
+
+  void *padding1; /**< placeholder */
+  
+} DBusRealError;
+
+_DBUS_STATIC_ASSERT (sizeof (DBusRealError) == sizeof (DBusError));
+
+/**
+ * Returns a longer message describing an error name.
+ * If the error name is unknown, returns the name
+ * itself.
+ *
+ * @param error the error to describe
+ * @returns a constant string describing the error.
+ */
+static const char*
+message_from_error (const char *error)
+{
+  if (strcmp (error, DBUS_ERROR_FAILED) == 0)
+    return "Unknown error";
+  else if (strcmp (error, DBUS_ERROR_NO_MEMORY) == 0)
+    return "Not enough memory available";
+  else if (strcmp (error, DBUS_ERROR_IO_ERROR) == 0)
+    return "Error reading or writing data";
+  else if (strcmp (error, DBUS_ERROR_BAD_ADDRESS) == 0)
+    return "Could not parse address";
+  else if (strcmp (error, DBUS_ERROR_NOT_SUPPORTED) == 0)
+    return "Feature not supported";
+  else if (strcmp (error, DBUS_ERROR_LIMITS_EXCEEDED) == 0)
+    return "Resource limits exceeded";
+  else if (strcmp (error, DBUS_ERROR_ACCESS_DENIED) == 0)
+    return "Permission denied";
+  else if (strcmp (error, DBUS_ERROR_AUTH_FAILED) == 0)
+    return "Could not authenticate to server";
+  else if (strcmp (error, DBUS_ERROR_NO_SERVER) == 0)
+    return "No server available at address";
+  else if (strcmp (error, DBUS_ERROR_TIMEOUT) == 0)
+    return "Connection timed out";
+  else if (strcmp (error, DBUS_ERROR_NO_NETWORK) == 0)
+    return "Network unavailable";
+  else if (strcmp (error, DBUS_ERROR_ADDRESS_IN_USE) == 0)
+    return "Address already in use";
+  else if (strcmp (error, DBUS_ERROR_DISCONNECTED) == 0)
+    return "Disconnected.";
+  else if (strcmp (error, DBUS_ERROR_INVALID_ARGS) == 0)
+    return "Invalid arguments.";
+  else if (strcmp (error, DBUS_ERROR_NO_REPLY) == 0)
+    return "Did not get a reply message.";
+  else if (strcmp (error, DBUS_ERROR_FILE_NOT_FOUND) == 0)
+    return "File doesn't exist.";
+  else if (strcmp (error, DBUS_ERROR_OBJECT_PATH_IN_USE) == 0)
+    return "Object path already in use";
+  else
+    return error;
+}
+
+/** @} */ /* End of internals */
+
+/**
+ * @defgroup DBusErrors Error reporting
+ * @ingroup  DBus
+ * @brief Error reporting
+ *
+ * Types and functions related to reporting errors.
+ *
+ *
+ * In essence D-Bus error reporting works as follows:
+ *
+ * @code
+ * DBusError error;
+ * dbus_error_init (&error);
+ * dbus_some_function (arg1, arg2, &error);
+ * if (dbus_error_is_set (&error))
+ *   {
+ *     fprintf (stderr, "an error occurred: %s\n", error.message);
+ *     dbus_error_free (&error);
+ *   }
+ * @endcode
+ *
+ * By convention, all functions allow #NULL instead of a DBusError*,
+ * so callers who don't care about the error can ignore it.
+ * 
+ * There are some rules. An error passed to a D-Bus function must
+ * always be unset; you can't pass in an error that's already set.  If
+ * a function has a return code indicating whether an error occurred,
+ * and also a #DBusError parameter, then the error will always be set
+ * if and only if the return code indicates an error occurred. i.e.
+ * the return code and the error are never going to disagree.
+ *
+ * An error only needs to be freed if it's been set, not if
+ * it's merely been initialized.
+ *
+ * You can check the specific error that occurred using
+ * dbus_error_has_name().
+ * 
+ * Errors will not be set for programming errors, such as passing
+ * invalid arguments to the libdbus API. Instead, libdbus will print
+ * warnings, exit on a failed assertion, or even crash in those cases
+ * (in other words, incorrect use of the API results in undefined
+ * behavior, possibly accompanied by helpful debugging output if
+ * you're lucky).
+ * 
+ * @{
+ */
+
+/**
+ * Initializes a DBusError structure. Does not allocate any memory;
+ * the error only needs to be freed if it is set at some point.
+ *
+ * @param error the DBusError.
+ */
+void
+dbus_error_init (DBusError *error)
+{
+  DBusRealError *real;
+
+  _dbus_return_if_fail (error != NULL);
+
+  _dbus_assert (sizeof (DBusError) == sizeof (DBusRealError));
+
+  real = (DBusRealError *)error;
+  
+  real->name = NULL;  
+  real->message = NULL;
+
+  real->const_message = TRUE;
+}
+
+/**
+ * Frees an error that's been set (or just initialized),
+ * then reinitializes the error as in dbus_error_init().
+ *
+ * @param error memory where the error is stored.
+ */
+void
+dbus_error_free (DBusError *error)
+{
+  DBusRealError *real;
+
+  _dbus_return_if_fail (error != NULL);
+  
+  real = (DBusRealError *)error;
+
+  if (!real->const_message)
+    {
+      dbus_free (real->name);
+      dbus_free (real->message);
+    }
+
+  dbus_error_init (error);
+}
+
+/**
+ * Assigns an error name and message to a DBusError.  Does nothing if
+ * error is #NULL. The message may be #NULL, which means a default
+ * message will be deduced from the name. The default message will be
+ * totally useless, though, so using a #NULL message is not recommended.
+ *
+ * Because this function does not copy the error name or message, you
+ * must ensure the name and message are global data that won't be
+ * freed. You probably want dbus_set_error() instead, in most cases.
+ * 
+ * @param error the error.or #NULL
+ * @param name the error name (not copied!!!)
+ * @param message the error message (not copied!!!)
+ */
+void
+dbus_set_error_const (DBusError  *error,
+		      const char *name,
+		      const char *message)
+{
+  DBusRealError *real;
+
+  _dbus_return_if_error_is_set (error);
+  _dbus_return_if_fail (name != NULL);
+  
+  if (error == NULL)
+    return;
+
+  _dbus_assert (error->name == NULL);
+  _dbus_assert (error->message == NULL);
+
+  if (message == NULL)
+    message = message_from_error (name);
+  
+  real = (DBusRealError *)error;
+  
+  real->name = (char*) name;
+  real->message = (char *)message;
+  real->const_message = TRUE;
+}
+
+/**
+ * Moves an error src into dest, freeing src and
+ * overwriting dest. Both src and dest must be initialized.
+ * src is reinitialized to an empty error. dest may not
+ * contain an existing error. If the destination is
+ * #NULL, just frees and reinits the source error.
+ * 
+ * @param src the source error
+ * @param dest the destination error or #NULL
+ */
+void
+dbus_move_error (DBusError *src,
+                 DBusError *dest)
+{
+  _dbus_return_if_error_is_set (dest);
+
+  if (dest)
+    {
+      dbus_error_free (dest);
+      *dest = *src;
+      dbus_error_init (src);
+    }
+  else
+    dbus_error_free (src);
+}
+
+/**
+ * Checks whether the error is set and has the given
+ * name.
+ * @param error the error
+ * @param name the name
+ * @returns #TRUE if the given named error occurred
+ */
+dbus_bool_t
+dbus_error_has_name (const DBusError *error,
+                     const char      *name)
+{
+  _dbus_return_val_if_fail (error != NULL, FALSE);
+  _dbus_return_val_if_fail (name != NULL, FALSE);
+
+  _dbus_assert ((error->name != NULL && error->message != NULL) ||
+                (error->name == NULL && error->message == NULL));
+  
+  if (error->name != NULL)
+    {
+      DBusString str1, str2;
+      _dbus_string_init_const (&str1, error->name);
+      _dbus_string_init_const (&str2, name);
+      return _dbus_string_equal (&str1, &str2);
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * Checks whether an error occurred (the error is set).
+ *
+ * @param error the error object
+ * @returns #TRUE if an error occurred
+ */
+dbus_bool_t
+dbus_error_is_set (const DBusError *error)
+{
+  _dbus_return_val_if_fail (error != NULL, FALSE);  
+  _dbus_assert ((error->name != NULL && error->message != NULL) ||
+                (error->name == NULL && error->message == NULL));
+  return error->name != NULL;
+}
+
+/**
+ * Assigns an error name and message to a DBusError.
+ * Does nothing if error is #NULL.
+ *
+ * The format may be #NULL, which means a (pretty much useless)
+ * default message will be deduced from the name. This is not a good
+ * idea, just go ahead and provide a useful error message. It won't
+ * hurt you.
+ *
+ * If no memory can be allocated for the error message, 
+ * an out-of-memory error message will be set instead.
+ *
+ * @param error the error.or #NULL
+ * @param name the error name
+ * @param format printf-style format string.
+ */
+void
+dbus_set_error (DBusError  *error,
+		const char *name,
+		const char *format,
+		...)
+{
+  DBusRealError *real;
+  DBusString str;
+  va_list args;
+  
+  if (error == NULL)
+    return;
+
+  /* it's a bug to pile up errors */
+  _dbus_return_if_error_is_set (error);
+  _dbus_return_if_fail (name != NULL);
+  
+  _dbus_assert (error->name == NULL);
+  _dbus_assert (error->message == NULL);
+
+  if (!_dbus_string_init (&str))
+    goto nomem;
+  
+  if (format == NULL)
+    {
+      if (!_dbus_string_append (&str,
+                                message_from_error (name)))
+        {
+          _dbus_string_free (&str);
+          va_end (args);
+          goto nomem;
+        }
+    }
+  else
+    {
+      va_start (args, format);
+      if (!_dbus_string_append_printf_valist (&str, format, args))
+        {
+          _dbus_string_free (&str);
+          va_end (args);
+          goto nomem;
+        }
+      va_end (args);
+    }
+
+  real = (DBusRealError *)error;
+
+  if (!_dbus_string_steal_data (&str, &real->message))
+    {
+      _dbus_string_free (&str);
+      goto nomem;
+    }
+  _dbus_string_free (&str);
+  
+  real->name = _dbus_strdup (name);
+  if (real->name == NULL)
+    {
+      dbus_free (real->message);
+      real->message = NULL;
+      goto nomem;
+    }
+  real->const_message = FALSE;
+
+  return;
+  
+ nomem:
+  _DBUS_SET_OOM (error);
+}
+
+/** @} */ /* End public API */
diff --git a/dbus/dbus/dbus-errors.h b/dbus/dbus/dbus-errors.h
new file mode 100644
index 0000000..e63139a
--- /dev/null
+++ b/dbus/dbus/dbus-errors.h
@@ -0,0 +1,90 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-errors.h Error reporting
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_ERROR_H
+#define DBUS_ERROR_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-protocol.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusErrors
+ * @{
+ */
+
+/** Mostly-opaque type representing an error that occurred */
+typedef struct DBusError DBusError;
+
+/**
+ * Object representing an exception.
+ */
+struct DBusError
+{
+  const char *name;    /**< public error name field */
+  const char *message; /**< public error message field */
+
+  unsigned int dummy1 : 1; /**< placeholder */
+  unsigned int dummy2 : 1; /**< placeholder */
+  unsigned int dummy3 : 1; /**< placeholder */
+  unsigned int dummy4 : 1; /**< placeholder */
+  unsigned int dummy5 : 1; /**< placeholder */
+
+  void *padding1; /**< placeholder */
+};
+
+#define DBUS_ERROR_INIT { NULL, NULL, TRUE, 0, 0, 0, 0, NULL }
+
+DBUS_EXPORT
+void        dbus_error_init      (DBusError       *error);
+DBUS_EXPORT
+void        dbus_error_free      (DBusError       *error);
+DBUS_EXPORT
+void        dbus_set_error       (DBusError       *error,
+                                  const char      *name,
+                                  const char      *message,
+                                  ...);
+DBUS_EXPORT
+void        dbus_set_error_const (DBusError       *error,
+                                  const char      *name,
+                                  const char      *message);
+DBUS_EXPORT
+void        dbus_move_error      (DBusError       *src,
+                                  DBusError       *dest);
+DBUS_EXPORT
+dbus_bool_t dbus_error_has_name  (const DBusError *error,
+                                  const char      *name);
+DBUS_EXPORT
+dbus_bool_t dbus_error_is_set    (const DBusError *error);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_ERROR_H */
diff --git a/dbus/dbus/dbus-file-unix.c b/dbus/dbus/dbus-file-unix.c
new file mode 100644
index 0000000..1975933
--- /dev/null
+++ b/dbus/dbus/dbus-file-unix.c
@@ -0,0 +1,417 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-file-unix.c unix related file implementation (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include "dbus-protocol.h"
+#include "dbus-errors.h"
+#include "dbus-file.h"
+#include "dbus-internals.h"
+#include "dbus-sysdeps.h"
+#include "dbus-sysdeps-unix.h"
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/**
+ * Appends the contents of the given file to the string,
+ * returning error code. At the moment, won't open a file
+ * more than a megabyte in size.
+ *
+ * @param str the string to append to
+ * @param filename filename to load
+ * @param error place to set an error
+ * @returns #FALSE if error was set
+ */
+dbus_bool_t
+_dbus_file_get_contents (DBusString       *str,
+                         const DBusString *filename,
+                         DBusError        *error)
+{
+  int fd;
+  struct stat sb;
+  int orig_len;
+  int total;
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  filename_c = _dbus_string_get_const_data (filename);
+  
+  /* O_BINARY useful on Cygwin */
+  fd = open (filename_c, O_RDONLY | O_BINARY);
+  if (fd < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to open \"%s\": %s",
+                      filename_c,
+                      _dbus_strerror (errno));
+      return FALSE;
+    }
+
+  _dbus_verbose ("file fd %d opened\n", fd);
+  
+  if (fstat (fd, &sb) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to stat \"%s\": %s",
+                      filename_c,
+                      _dbus_strerror (errno));
+
+      _dbus_verbose ("fstat() failed: %s",
+                     _dbus_strerror (errno));
+      
+      _dbus_close (fd, NULL);
+      
+      return FALSE;
+    }
+
+  if (sb.st_size > _DBUS_ONE_MEGABYTE)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "File size %lu of \"%s\" is too large.",
+                      (unsigned long) sb.st_size, filename_c);
+      _dbus_close (fd, NULL);
+      return FALSE;
+    }
+  
+  total = 0;
+  orig_len = _dbus_string_get_length (str);
+  if (sb.st_size > 0 && S_ISREG (sb.st_mode))
+    {
+      int bytes_read;
+
+      while (total < (int) sb.st_size)
+        {
+          bytes_read = _dbus_read (fd, str,
+                                   sb.st_size - total);
+          if (bytes_read <= 0)
+            {
+              dbus_set_error (error, _dbus_error_from_errno (errno),
+                              "Error reading \"%s\": %s",
+                              filename_c,
+                              _dbus_strerror (errno));
+
+              _dbus_verbose ("read() failed: %s",
+                             _dbus_strerror (errno));
+              
+              _dbus_close (fd, NULL);
+              _dbus_string_set_length (str, orig_len);
+              return FALSE;
+            }
+          else
+            total += bytes_read;
+        }
+
+      _dbus_close (fd, NULL);
+      return TRUE;
+    }
+  else if (sb.st_size != 0)
+    {
+      _dbus_verbose ("Can only open regular files at the moment.\n");
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "\"%s\" is not a regular file",
+                      filename_c);
+      _dbus_close (fd, NULL);
+      return FALSE;
+    }
+  else
+    {
+      _dbus_close (fd, NULL);
+      return TRUE;
+    }
+}
+
+/**
+ * Writes a string out to a file. If the file exists,
+ * it will be atomically overwritten by the new data.
+ *
+ * @param str the string to write out
+ * @param filename the file to save string to
+ * @param world_readable If set, ensure the file is world readable
+ * @param error error to be filled in on failure
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_string_save_to_file (const DBusString *str,
+                           const DBusString *filename,
+                           dbus_bool_t      world_readable,
+                           DBusError        *error)
+{
+  int fd;
+  int bytes_to_write;
+  const char *filename_c;
+  DBusString tmp_filename;
+  const char *tmp_filename_c;
+  int total;
+  dbus_bool_t need_unlink;
+  dbus_bool_t retval;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  fd = -1;
+  retval = FALSE;
+  need_unlink = FALSE;
+  
+  if (!_dbus_string_init (&tmp_filename))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+
+  if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&tmp_filename);
+      return FALSE;
+    }
+  
+  if (!_dbus_string_append (&tmp_filename, "."))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&tmp_filename);
+      return FALSE;
+    }
+
+#define N_TMP_FILENAME_RANDOM_BYTES 8
+  if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&tmp_filename);
+      return FALSE;
+    }
+    
+  filename_c = _dbus_string_get_const_data (filename);
+  tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
+
+  fd = open (tmp_filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
+             world_readable ? 0644 : 0600);
+  if (fd < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Could not create %s: %s", tmp_filename_c,
+                      _dbus_strerror (errno));
+      goto out;
+    }
+  if (world_readable)
+    {
+      /* Ensure the file is world readable even in the presence of
+       * possibly restrictive umasks;
+       * see http://lists.freedesktop.org/archives/dbus/2010-September/013367.html
+       */
+      if (fchmod (fd, 0644) < 0)
+        {
+          dbus_set_error (error, _dbus_error_from_errno (errno),
+                          "Could not chmod %s: %s", tmp_filename_c,
+                          _dbus_strerror (errno));
+          goto out;
+        }
+    }
+
+  _dbus_verbose ("tmp file fd %d opened\n", fd);
+  
+  need_unlink = TRUE;
+  
+  total = 0;
+  bytes_to_write = _dbus_string_get_length (str);
+
+  while (total < bytes_to_write)
+    {
+      int bytes_written;
+
+      bytes_written = _dbus_write (fd, str, total,
+                                   bytes_to_write - total);
+
+      if (bytes_written <= 0)
+        {
+          dbus_set_error (error, _dbus_error_from_errno (errno),
+                          "Could not write to %s: %s", tmp_filename_c,
+                          _dbus_strerror (errno));
+          
+          goto out;
+        }
+
+      total += bytes_written;
+    }
+
+  if (fsync(fd))
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Could not synchronize file %s: %s",
+                      tmp_filename_c, _dbus_strerror (errno));
+
+      goto out;
+  }
+
+  if (!_dbus_close (fd, NULL))
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Could not close file %s: %s",
+                      tmp_filename_c, _dbus_strerror (errno));
+
+      goto out;
+    }
+
+  fd = -1;
+  
+  if (rename (tmp_filename_c, filename_c) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Could not rename %s to %s: %s",
+                      tmp_filename_c, filename_c,
+                      _dbus_strerror (errno));
+
+      goto out;
+    }
+
+  need_unlink = FALSE;
+  
+  retval = TRUE;
+  
+ out:
+  /* close first, then unlink, to prevent ".nfs34234235" garbage
+   * files
+   */
+
+  if (fd >= 0)
+    _dbus_close (fd, NULL);
+        
+  if (need_unlink && unlink (tmp_filename_c) < 0)
+    _dbus_verbose ("Failed to unlink temp file %s: %s\n",
+                   tmp_filename_c, _dbus_strerror (errno));
+
+  _dbus_string_free (&tmp_filename);
+
+  if (!retval)
+    _DBUS_ASSERT_ERROR_IS_SET (error);
+  
+  return retval;
+}
+
+/** Makes the file readable by every user in the system.
+ *
+ * @param filename the filename
+ * @param error error location
+ * @returns #TRUE if the file's permissions could be changed.
+ */
+dbus_bool_t
+_dbus_make_file_world_readable(const DBusString *filename,
+                               DBusError *error)
+{
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  filename_c = _dbus_string_get_const_data (filename);
+  if (chmod (filename_c, 0644) == -1)
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_FAILED,
+                      "Could not change permissions of file %s: %s\n",
+                      filename_c,
+                      _dbus_strerror (errno));
+      return FALSE;
+    }
+  return TRUE;
+}
+
+/** Creates the given file, failing if the file already exists.
+ *
+ * @param filename the filename
+ * @param error error location
+ * @returns #TRUE if we created the file and it didn't exist
+ */
+dbus_bool_t
+_dbus_create_file_exclusively (const DBusString *filename,
+                               DBusError        *error)
+{
+  int fd;
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  filename_c = _dbus_string_get_const_data (filename);
+  
+  fd = open (filename_c, O_WRONLY | O_BINARY | O_EXCL | O_CREAT,
+             0600);
+  if (fd < 0)
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_FAILED,
+                      "Could not create file %s: %s\n",
+                      filename_c,
+                      _dbus_strerror (errno));
+      return FALSE;
+    }
+
+  _dbus_verbose ("exclusive file fd %d opened\n", fd);
+  
+  if (!_dbus_close (fd, NULL))
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_FAILED,
+                      "Could not close file %s: %s\n",
+                      filename_c,
+                      _dbus_strerror (errno));
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+/**
+ * Deletes the given file.
+ *
+ * @param filename the filename
+ * @param error error location
+ * 
+ * @returns #TRUE if unlink() succeeded
+ */
+dbus_bool_t
+_dbus_delete_file (const DBusString *filename,
+                   DBusError        *error)
+{
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  filename_c = _dbus_string_get_const_data (filename);
+
+  if (unlink (filename_c) < 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Failed to delete file %s: %s\n",
+                      filename_c, _dbus_strerror (errno));
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
diff --git a/dbus/dbus/dbus-file-win.c b/dbus/dbus/dbus-file-win.c
new file mode 100644
index 0000000..06a8ea1
--- /dev/null
+++ b/dbus/dbus/dbus-file-win.c
@@ -0,0 +1,407 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-file-win.c windows related file implementation (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-protocol.h"
+#include "dbus-string.h"
+#include "dbus-internals.h"
+#include "dbus-sysdeps-win.h"
+#include "dbus-pipe.h"
+
+#include <windows.h>
+
+
+/**
+ * Thin wrapper around the read() system call that appends
+ * the data it reads to the DBusString buffer. It appends
+ * up to the given count.
+ * 
+ * @param hnd the HANDLE to read from
+ * @param buffer the buffer to append data to
+ * @param count the amount of data to read
+ * @param error place to set an error
+ * @returns the number of bytes read or -1
+ */
+static int
+_dbus_file_read (HANDLE            hnd,
+                 DBusString       *buffer,
+                 int               count,
+                 DBusError        *error)
+{
+  BOOL result;
+  DWORD bytes_read;
+  int start;
+  char *data;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  _dbus_assert (count >= 0);
+
+  start = _dbus_string_get_length (buffer);
+
+  if (!_dbus_string_lengthen (buffer, count))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return -1;
+    }
+
+  data = _dbus_string_get_data_len (buffer, start, count);
+
+  result = ReadFile (hnd, data, count, &bytes_read, NULL);
+  if (result == 0)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                      "Failed to read from 0x%x: %s", hnd, emsg);
+      _dbus_win_free_error_string (emsg);
+      return -1;
+    }
+
+  if (bytes_read)
+    {
+      /* put length back (doesn't actually realloc) */
+      _dbus_string_set_length (buffer, start + bytes_read);
+
+#if 0
+      if (bytes_read > 0)
+        _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
+#endif
+    }
+
+  return bytes_read;
+}
+
+
+/**
+ * Appends the contents of the given file to the string,
+ * returning error code. At the moment, won't open a file
+ * more than a megabyte in size.
+ *
+ * @param str the string to append to
+ * @param filename filename to load
+ * @param error place to set an error
+ * @returns #FALSE if error was set
+ */
+dbus_bool_t
+_dbus_file_get_contents (DBusString       *str,
+                         const DBusString *filename,
+                         DBusError        *error)
+{
+  HANDLE hnd;
+  DWORD fsize;
+  DWORD fsize_hi;
+  int orig_len;
+  unsigned int total;
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  filename_c = _dbus_string_get_const_data (filename);
+
+  hnd = CreateFileA (filename_c, GENERIC_READ,
+                    FILE_SHARE_READ | FILE_SHARE_WRITE,
+                    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+  if (hnd == INVALID_HANDLE_VALUE)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                       "Failed to open \"%s\": %s", filename_c, emsg);
+      _dbus_win_free_error_string (emsg);
+      return FALSE;
+    }
+
+  _dbus_verbose ("file %s hnd %p opened\n", filename_c, hnd);
+  
+  fsize = GetFileSize (hnd, &fsize_hi);
+  if (fsize == 0xFFFFFFFF && GetLastError() != NO_ERROR)
+    { 
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                      "Failed to get file size for \"%s\": %s",
+                      filename_c, emsg);
+      _dbus_win_free_error_string (emsg);
+
+      _dbus_verbose ("GetFileSize() failed: %s", emsg);
+
+      CloseHandle (hnd);
+
+      return FALSE;
+    }
+
+  if (fsize_hi != 0 || fsize > _DBUS_ONE_MEGABYTE)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "File size %lu/%lu of \"%s\" is too large.",
+                      (unsigned long) fsize_hi,
+                      (unsigned long) fsize, filename_c);
+      CloseHandle (hnd);
+      return FALSE;
+    }
+
+  total = 0;
+  orig_len = _dbus_string_get_length (str);
+  if (fsize > 0)
+    {
+      int bytes_read;
+
+      while (total < fsize)
+        {
+          bytes_read = _dbus_file_read (hnd, str, fsize - total, error);
+          if (bytes_read <= 0)
+            {
+              if (bytes_read == 0)
+                {
+                  dbus_set_error (error, DBUS_ERROR_FAILED,
+                                  "Premature EOF reading \"%s\"",
+                                  filename_c);
+                }
+              else
+                _DBUS_ASSERT_ERROR_IS_SET (error);
+
+              CloseHandle (hnd);
+              _dbus_string_set_length (str, orig_len);
+              return FALSE;
+            }
+          else
+            total += bytes_read;
+        }
+
+      CloseHandle (hnd);
+      return TRUE;
+    }
+  else
+    {
+      CloseHandle (hnd);
+      return TRUE;
+    }
+}
+
+
+/**
+ * Writes a string out to a file. If the file exists,
+ * it will be atomically overwritten by the new data.
+ *
+ * @param str the string to write out
+ * @param filename the file to save string to
+ * @param world_readable if true, ensure file is world readable
+ * @param error error to be filled in on failure
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_string_save_to_file (const DBusString *str,
+                           const DBusString *filename,
+                           dbus_bool_t       world_readable,
+                           DBusError        *error)
+{
+  HANDLE hnd;
+  int bytes_to_write;
+  const char *filename_c;
+  DBusString tmp_filename;
+  const char *tmp_filename_c;
+  int total;
+  const char *str_c;
+  dbus_bool_t need_unlink;
+  dbus_bool_t retval;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  hnd = INVALID_HANDLE_VALUE;
+  retval = FALSE;
+  need_unlink = FALSE;
+
+  if (!_dbus_string_init (&tmp_filename))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+
+  if (!_dbus_string_copy (filename, 0, &tmp_filename, 0))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&tmp_filename);
+      return FALSE;
+    }
+
+  if (!_dbus_string_append (&tmp_filename, "."))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&tmp_filename);
+      return FALSE;
+    }
+
+#define N_TMP_FILENAME_RANDOM_BYTES 8
+  if (!_dbus_generate_random_ascii (&tmp_filename, N_TMP_FILENAME_RANDOM_BYTES))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&tmp_filename);
+      return FALSE;
+    }
+
+  filename_c = _dbus_string_get_const_data (filename);
+  tmp_filename_c = _dbus_string_get_const_data (&tmp_filename);
+
+  /* TODO - support world-readable in an atomic fashion */
+  hnd = CreateFileA (tmp_filename_c, GENERIC_WRITE,
+                     FILE_SHARE_READ | FILE_SHARE_WRITE,
+                     NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
+                     INVALID_HANDLE_VALUE);
+  if (hnd == INVALID_HANDLE_VALUE)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                       "Could not create \"%s\": %s", filename_c, emsg);
+      _dbus_win_free_error_string (emsg);
+      goto out;
+    }
+  if (world_readable)
+    {
+      if (! _dbus_make_file_world_readable (&tmp_filename, error))
+        goto out;
+    }
+
+  _dbus_verbose ("tmp file %s hnd %p opened\n", tmp_filename_c, hnd);
+
+  need_unlink = TRUE;
+
+  total = 0;
+  bytes_to_write = _dbus_string_get_length (str);
+  str_c = _dbus_string_get_const_data (str);
+
+  while (total < bytes_to_write)
+    {
+      DWORD bytes_written;
+      BOOL res;
+
+      res = WriteFile (hnd, str_c + total, bytes_to_write - total,
+                       &bytes_written, NULL);
+
+      if (res == 0 || bytes_written <= 0)
+        {
+          char *emsg = _dbus_win_error_string (GetLastError ());
+          dbus_set_error (error, _dbus_win_error_from_last_error (),
+                           "Could not write to %s: %s", tmp_filename_c, emsg);
+          _dbus_win_free_error_string (emsg);
+          goto out;
+        }
+
+      total += bytes_written;
+    }
+
+  if (CloseHandle (hnd) == 0)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                       "Could not close file %s: %s", tmp_filename_c, emsg);
+      _dbus_win_free_error_string (emsg);
+      goto out;
+    }
+
+  hnd = INVALID_HANDLE_VALUE;
+
+  /* Unlike rename(), MoveFileEx() can replace existing files */
+  if (!MoveFileExA (tmp_filename_c, filename_c, MOVEFILE_REPLACE_EXISTING))
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                       "Could not rename %s to %s: %s",
+                       tmp_filename_c, filename_c, emsg);
+      _dbus_win_free_error_string (emsg);
+
+      goto out;
+    }
+
+  need_unlink = FALSE;
+
+  retval = TRUE;
+
+ out:
+  /* close first, then unlink */
+
+  if (hnd != INVALID_HANDLE_VALUE)
+    CloseHandle (hnd);
+
+  if (need_unlink && DeleteFileA (tmp_filename_c) == 0)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      _dbus_verbose ("Failed to unlink temp file %s: %s", tmp_filename_c,
+                     emsg);
+      _dbus_win_free_error_string (emsg);
+    }
+
+  _dbus_string_free (&tmp_filename);
+
+  if (!retval)
+    _DBUS_ASSERT_ERROR_IS_SET (error);
+
+  return retval;
+}
+
+
+/** Creates the given file, failing if the file already exists.
+ *
+ * @param filename the filename
+ * @param error error location
+ * @returns #TRUE if we created the file and it didn't exist
+ */
+dbus_bool_t
+_dbus_create_file_exclusively (const DBusString *filename,
+                               DBusError        *error)
+{
+  HANDLE hnd;
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  filename_c = _dbus_string_get_const_data (filename);
+
+  hnd = CreateFileA (filename_c, GENERIC_WRITE,
+                     FILE_SHARE_READ | FILE_SHARE_WRITE,
+                     NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
+                     INVALID_HANDLE_VALUE);
+  if (hnd == INVALID_HANDLE_VALUE)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                       "Could not create file %s: %s",
+                       filename_c, emsg);
+      _dbus_win_free_error_string (emsg);
+      return FALSE;
+    }
+
+  _dbus_verbose ("exclusive file %s hnd %p opened\n", filename_c, hnd);
+
+  if (CloseHandle (hnd) == 0)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                       "Could not close file %s: %s",
+                       filename_c, emsg);
+      _dbus_win_free_error_string (emsg);
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
diff --git a/dbus/dbus/dbus-file.c b/dbus/dbus/dbus-file.c
new file mode 100644
index 0000000..350fbd9
--- /dev/null
+++ b/dbus/dbus/dbus-file.c
@@ -0,0 +1,28 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include "dbus-file.h"
+
diff --git a/dbus/dbus/dbus-file.h b/dbus/dbus/dbus-file.h
new file mode 100644
index 0000000..24837f4
--- /dev/null
+++ b/dbus/dbus/dbus-file.h
@@ -0,0 +1,63 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-file.h dbus file related stuff (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_FILE_H
+#define DBUS_FILE_H
+
+//#include <dbus/dbus-types.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-errors.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusFile
+ * @{
+ */
+
+/**
+ * File interface
+ */
+dbus_bool_t _dbus_file_exists         (const char       *file);
+dbus_bool_t _dbus_file_get_contents   (DBusString       *str,
+                                       const DBusString *filename,
+                                       DBusError        *error);
+dbus_bool_t _dbus_string_save_to_file (const DBusString *str,
+                                       const DBusString *filename,
+                                       dbus_bool_t       world_readable,
+                                       DBusError        *error);
+
+dbus_bool_t _dbus_make_file_world_readable   (const DBusString *filename,
+                                              DBusError *error);
+
+dbus_bool_t    _dbus_create_file_exclusively (const DBusString *filename,
+                                              DBusError        *error);
+dbus_bool_t    _dbus_delete_file             (const DBusString *filename,
+                                              DBusError        *error);
+                                              
+/** @} */
+
+DBUS_END_DECLS
+
+#endif
diff --git a/dbus/dbus/dbus-hash.c b/dbus/dbus/dbus-hash.c
new file mode 100644
index 0000000..c4c6f93
--- /dev/null
+++ b/dbus/dbus/dbus-hash.c
@@ -0,0 +1,1831 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-hash.c Generic hash table utility (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002  Red Hat, Inc.
+ * Copyright (c) 1991-1993 The Regents of the University of California.
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ * 
+ * Hash table implementation based on generic/tclHash.c from the Tcl
+ * source code. The original Tcl license applies to portions of the
+ * code from tclHash.c; the Tcl license follows this standad D-Bus 
+ * license information.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+/* 
+ * The following copyright applies to code from the Tcl distribution.
+ *
+ * Copyright (c) 1991-1993 The Regents of the University of California.
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * This software is copyrighted by the Regents of the University of
+ * California, Sun Microsystems, Inc., Scriptics Corporation, and
+ * other parties.  The following terms apply to all files associated
+ * with the software unless explicitly disclaimed in individual files.
+ * 
+ * The authors hereby grant permission to use, copy, modify,
+ * distribute, and license this software and its documentation for any
+ * purpose, provided that existing copyright notices are retained in
+ * all copies and that this notice is included verbatim in any
+ * distributions. No written agreement, license, or royalty fee is
+ * required for any of the authorized uses.  Modifications to this
+ * software may be copyrighted by their authors and need not follow
+ * the licensing terms described here, provided that the new terms are
+ * clearly indicated on the first page of each file where they apply.
+ * 
+ * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+ * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION,
+ * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
+ * NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
+ * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
+ * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ * 
+ * GOVERNMENT USE: If you are acquiring this software on behalf of the
+ * U.S. government, the Government shall have only "Restricted Rights"
+ * in the software and related documentation as defined in the Federal
+ * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
+ * are acquiring the software on behalf of the Department of Defense,
+ * the software shall be classified as "Commercial Computer Software"
+ * and the Government shall have only "Restricted Rights" as defined
+ * in Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
+ * foregoing, the authors grant the U.S. Government and others acting
+ * in its behalf permission to use and distribute the software in
+ * accordance with the terms specified in this license.
+ */
+
+#include <config.h>
+#include "dbus-hash.h"
+#include "dbus-internals.h"
+#include "dbus-mempool.h"
+
+/**
+ * @defgroup DBusHashTable Hash table
+ * @ingroup  DBusInternals
+ * @brief DBusHashTable data structure
+ *
+ * Types and functions related to DBusHashTable.
+ */
+
+/**
+ * @defgroup DBusHashTableInternals Hash table implementation details
+ * @ingroup  DBusInternals
+ * @brief DBusHashTable implementation details
+ *
+ * The guts of DBusHashTable.
+ *
+ * @{
+ */
+
+/**
+ * When there are this many entries per bucket, on average, rebuild
+ * the hash table to make it larger.
+ */
+#define REBUILD_MULTIPLIER  3
+
+/**
+ * Takes a preliminary integer hash value and produces an index into a
+ * hash tables bucket list.  The idea is to make it so that
+ * preliminary values that are arbitrarily similar will end up in
+ * different buckets.  The hash function was taken from a
+ * random-number generator. (This is used to hash integers.)
+ *
+ * The down_shift drops off the high bits of the hash index, and
+ * decreases as we increase the number of hash buckets (to keep more
+ * range in the hash index). The mask also strips high bits and strips
+ * fewer high bits as the number of hash buckets increases.
+ * I don't understand two things: why is the initial downshift 28
+ * to keep 4 bits when the initial mask is 011 to keep 2 bits,
+ * and why do we have both a mask and a downshift?
+ * 
+ */
+#define RANDOM_INDEX(table, i) \
+    (((((intptr_t) (i))*1103515245) >> (table)->down_shift) & (table)->mask)
+
+/**
+ * Initial number of buckets in hash table (hash table statically
+ * allocates its buckets for this size and below).
+ * The initial mask has to be synced to this.
+ */
+#define DBUS_SMALL_HASH_TABLE 4
+
+/**
+ * Typedef for DBusHashEntry
+ */
+typedef struct DBusHashEntry DBusHashEntry;
+
+/**
+ * @brief Internal representation of a hash entry.
+ * 
+ * A single entry (key-value pair) in the hash table.
+ * Internal to hash table implementation.
+ */
+struct DBusHashEntry
+{
+  DBusHashEntry *next;    /**< Pointer to next entry in this
+                           * hash bucket, or #NULL for end of
+                           * chain.
+                           */
+  void *key;              /**< Hash key */
+  void *value;            /**< Hash value */
+};
+
+/**
+ * Function used to find and optionally create a hash entry.
+ */
+typedef DBusHashEntry* (* DBusFindEntryFunction) (DBusHashTable        *table,
+                                                  void                 *key,
+                                                  dbus_bool_t           create_if_not_found,
+                                                  DBusHashEntry      ***bucket,
+                                                  DBusPreallocatedHash *preallocated);
+
+/**
+ * @brief Internals of DBusHashTable.
+ * 
+ * Hash table internals. Hash tables are opaque objects, they must be
+ * used via accessor functions.
+ */
+struct DBusHashTable {
+  int refcount;                       /**< Reference count */
+  
+  DBusHashEntry **buckets;            /**< Pointer to bucket array.  Each
+                                       * element points to first entry in
+                                       * bucket's hash chain, or #NULL.
+                                       */
+  DBusHashEntry *static_buckets[DBUS_SMALL_HASH_TABLE];
+                                       /**< Bucket array used for small tables
+                                        * (to avoid mallocs and frees).
+                                        */
+  int n_buckets;                       /**< Total number of buckets allocated
+                                        * at **buckets.
+                                        */
+  int n_entries;                       /**< Total number of entries present
+                                        * in table.
+                                        */
+  int hi_rebuild_size;                 /**< Enlarge table when n_entries gets
+                                        * to be this large.
+                                        */
+  int lo_rebuild_size;                 /**< Shrink table when n_entries gets
+                                        * below this.
+                                        */
+  int down_shift;                      /**< Shift count used in hashing
+                                        * function.  Designed to use high-
+                                        * order bits of randomized keys.
+                                        */
+  int mask;                            /**< Mask value used in hashing
+                                        * function.
+                                        */
+  DBusHashType key_type;               /**< Type of keys used in this table */
+
+
+  DBusFindEntryFunction find_function; /**< Function for finding entries */
+
+  DBusFreeFunction free_key_function;   /**< Function to free keys */
+  DBusFreeFunction free_value_function; /**< Function to free values */
+
+  DBusMemPool *entry_pool;              /**< Memory pool for hash entries */
+};
+
+/** 
+ * @brief Internals of DBusHashIter.
+ */
+typedef struct
+{
+  DBusHashTable *table;     /**< Pointer to table containing entry. */
+  DBusHashEntry **bucket;   /**< Pointer to bucket that points to
+                             * first entry in this entry's chain:
+                             * used for deleting the entry.
+                             */
+  DBusHashEntry *entry;      /**< Current hash entry */
+  DBusHashEntry *next_entry; /**< Next entry to be iterated onto in current bucket */
+  int next_bucket;           /**< index of next bucket */
+  int n_entries_on_init;     /**< used to detect table resize since initialization */
+} DBusRealHashIter;
+
+_DBUS_STATIC_ASSERT (sizeof (DBusRealHashIter) == sizeof (DBusHashIter));
+
+static DBusHashEntry* find_direct_function      (DBusHashTable          *table,
+                                                 void                   *key,
+                                                 dbus_bool_t             create_if_not_found,
+                                                 DBusHashEntry        ***bucket,
+                                                 DBusPreallocatedHash   *preallocated);
+static DBusHashEntry* find_string_function      (DBusHashTable          *table,
+                                                 void                   *key,
+                                                 dbus_bool_t             create_if_not_found,
+                                                 DBusHashEntry        ***bucket,
+                                                 DBusPreallocatedHash   *preallocated);
+static unsigned int   string_hash               (const char             *str);
+static void           rebuild_table             (DBusHashTable          *table);
+static DBusHashEntry* alloc_entry               (DBusHashTable          *table);
+static void           remove_entry              (DBusHashTable          *table,
+                                                 DBusHashEntry         **bucket,
+                                                 DBusHashEntry          *entry);
+static void           free_entry                (DBusHashTable          *table,
+                                                 DBusHashEntry          *entry);
+static void           free_entry_data           (DBusHashTable          *table,
+                                                 DBusHashEntry          *entry);
+
+
+/** @} */
+
+/**
+ * @addtogroup DBusHashTable
+ * @{
+ */
+
+/**
+ * @typedef DBusHashIter
+ *
+ * Public opaque hash table iterator object.
+ */
+
+/**
+ * @typedef DBusHashTable
+ *
+ * Public opaque hash table object.
+ */
+
+/**
+ * @typedef DBusHashType
+ *
+ * Indicates the type of a key in the hash table.
+ */
+
+/**
+ * Constructs a new hash table. Should be freed with
+ * _dbus_hash_table_unref(). If memory cannot be
+ * allocated for the hash table, returns #NULL.
+ *
+ * @param type the type of hash key to use.
+ * @param key_free_function function to free hash keys.
+ * @param value_free_function function to free hash values.
+ * @returns a new DBusHashTable or #NULL if no memory.
+ */
+DBusHashTable*
+_dbus_hash_table_new (DBusHashType     type,
+                      DBusFreeFunction key_free_function,
+                      DBusFreeFunction value_free_function)
+{
+  DBusHashTable *table;
+  DBusMemPool *entry_pool;
+  
+  table = dbus_new0 (DBusHashTable, 1);
+  if (table == NULL)
+    return NULL;
+
+  entry_pool = _dbus_mem_pool_new (sizeof (DBusHashEntry), TRUE);
+  if (entry_pool == NULL)
+    {
+      dbus_free (table);
+      return NULL;
+    }
+  
+  table->refcount = 1;
+  table->entry_pool = entry_pool;
+  
+  _dbus_assert (DBUS_SMALL_HASH_TABLE == _DBUS_N_ELEMENTS (table->static_buckets));
+  
+  table->buckets = table->static_buckets;  
+  table->n_buckets = DBUS_SMALL_HASH_TABLE;
+  table->n_entries = 0;
+  table->hi_rebuild_size = DBUS_SMALL_HASH_TABLE * REBUILD_MULTIPLIER;
+  table->lo_rebuild_size = 0;
+  table->down_shift = 28;
+  table->mask = 3;
+  table->key_type = type;
+
+  _dbus_assert (table->mask < table->n_buckets);
+  
+  switch (table->key_type)
+    {
+    case DBUS_HASH_INT:
+    case DBUS_HASH_UINTPTR:
+      table->find_function = find_direct_function;
+      break;
+    case DBUS_HASH_STRING:
+      table->find_function = find_string_function;
+      break;
+    default:
+      _dbus_assert_not_reached ("Unknown hash table type");
+      break;
+    }
+
+  table->free_key_function = key_free_function;
+  table->free_value_function = value_free_function;
+
+  return table;
+}
+
+
+/**
+ * Increments the reference count for a hash table.
+ *
+ * @param table the hash table to add a reference to.
+ * @returns the hash table.
+ */
+DBusHashTable *
+_dbus_hash_table_ref (DBusHashTable *table)
+{
+  table->refcount += 1;
+  
+  return table;
+}
+
+/**
+ * Decrements the reference count for a hash table,
+ * freeing the hash table if the count reaches zero.
+ *
+ * @param table the hash table to remove a reference from.
+ */
+void
+_dbus_hash_table_unref (DBusHashTable *table)
+{
+  table->refcount -= 1;
+
+  if (table->refcount == 0)
+    {
+#if 0
+      DBusHashEntry *entry;
+      DBusHashEntry *next;
+      int i;
+
+      /* Free the entries in the table. */
+      for (i = 0; i < table->n_buckets; i++)
+        {
+          entry = table->buckets[i];
+          while (entry != NULL)
+            {
+              next = entry->next;
+
+              free_entry (table, entry);
+              
+              entry = next;
+            }
+        }
+#else
+      DBusHashEntry *entry;
+      int i;
+
+      /* Free the entries in the table. */
+      for (i = 0; i < table->n_buckets; i++)
+        {
+          entry = table->buckets[i];
+          while (entry != NULL)
+            {
+              free_entry_data (table, entry);
+              
+              entry = entry->next;
+            }
+        }
+      /* We can do this very quickly with memory pools ;-) */
+      _dbus_mem_pool_free (table->entry_pool);
+#endif
+      
+      /* Free the bucket array, if it was dynamically allocated. */
+      if (table->buckets != table->static_buckets)
+        dbus_free (table->buckets);
+
+      dbus_free (table);
+    }
+}
+
+/**
+ * Removed all entries from a hash table.
+ *
+ * @param table the hash table to remove all entries from.
+ */
+void
+_dbus_hash_table_remove_all (DBusHashTable *table)
+{
+  DBusHashIter iter;
+  _dbus_hash_iter_init (table, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      _dbus_hash_iter_remove_entry(&iter);
+    }
+}
+
+static DBusHashEntry*
+alloc_entry (DBusHashTable *table)
+{
+  DBusHashEntry *entry;
+
+  entry = _dbus_mem_pool_alloc (table->entry_pool);
+  
+  return entry;
+}
+
+static void
+free_entry_data (DBusHashTable  *table,
+		 DBusHashEntry  *entry)
+{
+  if (table->free_key_function)
+    (* table->free_key_function) (entry->key);
+  if (table->free_value_function)
+    (* table->free_value_function) (entry->value);
+}
+
+static void
+free_entry (DBusHashTable  *table,
+            DBusHashEntry  *entry)
+{
+  free_entry_data (table, entry);
+  _dbus_mem_pool_dealloc (table->entry_pool, entry);
+}
+
+static void
+remove_entry (DBusHashTable  *table,
+              DBusHashEntry **bucket,
+              DBusHashEntry  *entry)
+{
+  _dbus_assert (table != NULL);
+  _dbus_assert (bucket != NULL);
+  _dbus_assert (*bucket != NULL);  
+  _dbus_assert (entry != NULL);
+  
+  if (*bucket == entry)
+    *bucket = entry->next;
+  else
+    {
+      DBusHashEntry *prev;
+      prev = *bucket;
+
+      while (prev->next != entry)
+        prev = prev->next;      
+      
+      _dbus_assert (prev != NULL);
+
+      prev->next = entry->next;
+    }
+  
+  table->n_entries -= 1;
+  free_entry (table, entry);
+}
+
+/**
+ * Initializes a hash table iterator. To iterate over all entries in a
+ * hash table, use the following code (the printf assumes a hash
+ * from strings to strings obviously):
+ *
+ * @code
+ * DBusHashIter iter;
+ *
+ * _dbus_hash_iter_init (table, &iter);
+ * while (_dbus_hash_iter_next (&iter))
+ *   {
+ *      printf ("The first key is %s and value is %s\n",
+ *              _dbus_hash_iter_get_string_key (&iter),
+ *              _dbus_hash_iter_get_value (&iter));
+ *   }
+ * 
+ * 
+ * @endcode
+ *
+ * The iterator is initialized pointing "one before" the first hash
+ * entry. The first call to _dbus_hash_iter_next() moves it onto
+ * the first valid entry or returns #FALSE if the hash table is
+ * empty. Subsequent calls move to the next valid entry or return
+ * #FALSE if there are no more entries.
+ *
+ * Note that it is guaranteed to be safe to remove a hash entry during
+ * iteration, but it is not safe to add a hash entry.
+ * 
+ * @param table the hash table to iterate over.
+ * @param iter the iterator to initialize.
+ */
+void
+_dbus_hash_iter_init (DBusHashTable *table,
+                      DBusHashIter  *iter)
+{
+  DBusRealHashIter *real;
+  
+  _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter));
+  
+  real = (DBusRealHashIter*) iter;
+
+  real->table = table;
+  real->bucket = NULL;
+  real->entry = NULL;
+  real->next_entry = NULL;
+  real->next_bucket = 0;
+  real->n_entries_on_init = table->n_entries;
+}
+
+/**
+ * Move the hash iterator forward one step, to the next hash entry.
+ * The documentation for _dbus_hash_iter_init() explains in more
+ * detail.
+ *
+ * @param iter the iterator to move forward.
+ * @returns #FALSE if there are no more entries to move to.
+ */
+dbus_bool_t
+_dbus_hash_iter_next (DBusHashIter  *iter)
+{
+  DBusRealHashIter *real;
+  
+  _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter));
+  
+  real = (DBusRealHashIter*) iter;
+
+  /* if this assertion failed someone probably added hash entries
+   * during iteration, which is bad.
+   */
+  _dbus_assert (real->n_entries_on_init >= real->table->n_entries);
+  
+  /* Remember that real->entry may have been deleted */
+  
+  while (real->next_entry == NULL)
+    {
+      if (real->next_bucket >= real->table->n_buckets)
+        {
+          /* invalidate iter and return false */
+          real->entry = NULL;
+          real->table = NULL;
+          real->bucket = NULL;
+          return FALSE;
+        }
+
+      real->bucket = &(real->table->buckets[real->next_bucket]);
+      real->next_entry = *(real->bucket);
+      real->next_bucket += 1;
+    }
+
+  _dbus_assert (real->next_entry != NULL);
+  _dbus_assert (real->bucket != NULL);
+  
+  real->entry = real->next_entry;
+  real->next_entry = real->entry->next;
+  
+  return TRUE;
+}
+
+/**
+ * Removes the current entry from the hash table.
+ * If a key_free_function or value_free_function
+ * was provided to _dbus_hash_table_new(),
+ * frees the key and/or value for this entry.
+ *
+ * @param iter the hash table iterator.
+ */
+void
+_dbus_hash_iter_remove_entry (DBusHashIter *iter)
+{
+  DBusRealHashIter *real;
+
+  real = (DBusRealHashIter*) iter;
+
+  _dbus_assert (real->table != NULL);
+  _dbus_assert (real->entry != NULL);
+  _dbus_assert (real->bucket != NULL);
+  
+  remove_entry (real->table, real->bucket, real->entry);
+
+  real->entry = NULL; /* make it crash if you try to use this entry */
+}
+
+/**
+ * Gets the value of the current entry.
+ *
+ * @param iter the hash table iterator.
+ */
+void*
+_dbus_hash_iter_get_value (DBusHashIter *iter)
+{
+  DBusRealHashIter *real;
+
+  real = (DBusRealHashIter*) iter;
+
+  _dbus_assert (real->table != NULL);
+  _dbus_assert (real->entry != NULL);
+
+  return real->entry->value;
+}
+
+/**
+ * Sets the value of the current entry.
+ * If the hash table has a value_free_function
+ * it will be used to free the previous value.
+ * The hash table will own the passed-in value
+ * (it will not be copied).
+ *
+ * @param iter the hash table iterator.
+ * @param value the new value.
+ */
+void
+_dbus_hash_iter_set_value (DBusHashIter *iter,
+                           void         *value)
+{
+  DBusRealHashIter *real;
+
+  real = (DBusRealHashIter*) iter;
+
+  _dbus_assert (real->table != NULL);
+  _dbus_assert (real->entry != NULL);
+
+  if (real->table->free_value_function && value != real->entry->value)    
+    (* real->table->free_value_function) (real->entry->value);
+  
+  real->entry->value = value;
+}
+
+/**
+ * Gets the key for the current entry.
+ * Only works for hash tables of type #DBUS_HASH_INT.
+ *
+ * @param iter the hash table iterator.
+ */
+int
+_dbus_hash_iter_get_int_key (DBusHashIter *iter)
+{
+  DBusRealHashIter *real;
+
+  real = (DBusRealHashIter*) iter;
+
+  _dbus_assert (real->table != NULL);
+  _dbus_assert (real->entry != NULL);
+
+  return _DBUS_POINTER_TO_INT (real->entry->key);
+}
+
+/**
+ * Gets the key for the current entry.
+ * Only works for hash tables of type #DBUS_HASH_UINTPTR.
+ *
+ * @param iter the hash table iterator.
+ */
+uintptr_t
+_dbus_hash_iter_get_uintptr_key (DBusHashIter *iter)
+{
+  DBusRealHashIter *real;
+
+  real = (DBusRealHashIter*) iter;
+
+  _dbus_assert (real->table != NULL);
+  _dbus_assert (real->entry != NULL);
+
+  return (uintptr_t) real->entry->key;
+}
+
+/**
+ * Gets the key for the current entry.
+ * Only works for hash tables of type #DBUS_HASH_STRING
+ * @param iter the hash table iterator.
+ */
+const char*
+_dbus_hash_iter_get_string_key (DBusHashIter *iter)
+{
+  DBusRealHashIter *real;
+
+  real = (DBusRealHashIter*) iter;
+
+  _dbus_assert (real->table != NULL);
+  _dbus_assert (real->entry != NULL);
+
+  return real->entry->key;
+}
+
+/**
+ * A low-level but efficient interface for manipulating the hash
+ * table.  It's efficient because you can get, set, and optionally
+ * create the hash entry while only running the hash function one
+ * time.
+ *
+ * Note that while calling _dbus_hash_iter_next() on the iterator
+ * filled in by this function may work, it's completely
+ * undefined which entries are after this iter and which
+ * are before it. So it would be silly to iterate using this
+ * iterator.
+ *
+ * If the hash entry is created, its value will be initialized
+ * to all bits zero.
+ *
+ * #FALSE may be returned due to memory allocation failure, or
+ * because create_if_not_found was #FALSE and the entry
+ * did not exist.
+ *
+ * If create_if_not_found is #TRUE and the entry is created, the hash
+ * table takes ownership of the key that's passed in.
+ *
+ * For a hash table of type #DBUS_HASH_INT, cast the int
+ * key to the key parameter using #_DBUS_INT_TO_POINTER().
+ * 
+ * @param table the hash table.
+ * @param key the hash key.
+ * @param create_if_not_found if #TRUE, create the entry if it didn't exist.
+ * @param iter the iterator to initialize.
+ * @returns #TRUE if the hash entry now exists (and the iterator is thus valid).
+ */
+dbus_bool_t
+_dbus_hash_iter_lookup (DBusHashTable *table,
+                        void          *key,
+                        dbus_bool_t    create_if_not_found,
+                        DBusHashIter  *iter)
+{
+  DBusRealHashIter *real;
+  DBusHashEntry *entry;
+  DBusHashEntry **bucket;
+  
+  _dbus_assert (sizeof (DBusHashIter) == sizeof (DBusRealHashIter));
+  
+  real = (DBusRealHashIter*) iter;
+
+  entry = (* table->find_function) (table, key, create_if_not_found, &bucket, NULL);
+
+  if (entry == NULL)
+    return FALSE;
+  
+  real->table = table;
+  real->bucket = bucket;
+  real->entry = entry;
+  real->next_entry = entry->next;
+  real->next_bucket = (bucket - table->buckets) + 1;
+  real->n_entries_on_init = table->n_entries; 
+
+  _dbus_assert (&(table->buckets[real->next_bucket-1]) == real->bucket);
+  
+  return TRUE;
+}
+
+static void
+add_allocated_entry (DBusHashTable   *table,
+                     DBusHashEntry   *entry,
+                     unsigned int     idx,
+                     void            *key,
+                     DBusHashEntry ***bucket)
+{
+  DBusHashEntry **b;  
+  
+  entry->key = key;
+  
+  b = &(table->buckets[idx]);
+  entry->next = *b;
+  *b = entry;
+
+  if (bucket)
+    *bucket = b;
+  
+  table->n_entries += 1;
+
+  /* note we ONLY rebuild when ADDING - because you can iterate over a
+   * table and remove entries safely.
+   */
+  if (table->n_entries >= table->hi_rebuild_size ||
+      table->n_entries < table->lo_rebuild_size)
+    rebuild_table (table);
+}
+
+static DBusHashEntry*
+add_entry (DBusHashTable        *table, 
+           unsigned int          idx,
+           void                 *key,
+           DBusHashEntry      ***bucket,
+           DBusPreallocatedHash *preallocated)
+{
+  DBusHashEntry  *entry;
+
+  if (preallocated == NULL)
+    {
+      entry = alloc_entry (table);
+      if (entry == NULL)
+        {
+          if (bucket)
+            *bucket = NULL;
+          return NULL;
+        }
+    }
+  else
+    {
+      entry = (DBusHashEntry*) preallocated;
+    }
+
+  add_allocated_entry (table, entry, idx, key, bucket);
+
+  return entry;
+}
+
+/* This is g_str_hash from GLib which was
+ * extensively discussed/tested/profiled
+ */
+static unsigned int
+string_hash (const char *str)
+{
+  const char *p = str;
+  unsigned int h = *p;
+
+  if (h)
+    for (p += 1; *p != '\0'; p++)
+      h = (h << 5) - h + *p;
+
+  return h;
+}
+
+/** Key comparison function */
+typedef int (* KeyCompareFunc) (const void *key_a, const void *key_b);
+
+static DBusHashEntry*
+find_generic_function (DBusHashTable        *table,
+                       void                 *key,
+                       unsigned int          idx,
+                       KeyCompareFunc        compare_func,
+                       dbus_bool_t           create_if_not_found,
+                       DBusHashEntry      ***bucket,
+                       DBusPreallocatedHash *preallocated)
+{
+  DBusHashEntry *entry;
+
+  if (bucket)
+    *bucket = NULL;
+
+  /* Search all of the entries in this bucket. */
+  entry = table->buckets[idx];
+  while (entry != NULL)
+    {
+      if ((compare_func == NULL && key == entry->key) ||
+          (compare_func != NULL && (* compare_func) (key, entry->key) == 0))
+        {
+          if (bucket)
+            *bucket = &(table->buckets[idx]);
+
+          if (preallocated)
+            _dbus_hash_table_free_preallocated_entry (table, preallocated);
+          
+          return entry;
+        }
+      
+      entry = entry->next;
+    }
+
+  if (create_if_not_found)
+    entry = add_entry (table, idx, key, bucket, preallocated);
+  else if (preallocated)
+    _dbus_hash_table_free_preallocated_entry (table, preallocated);
+  
+  return entry;
+}
+
+static DBusHashEntry*
+find_string_function (DBusHashTable        *table,
+                      void                 *key,
+                      dbus_bool_t           create_if_not_found,
+                      DBusHashEntry      ***bucket,
+                      DBusPreallocatedHash *preallocated)
+{
+  unsigned int idx;
+  
+  idx = string_hash (key) & table->mask;
+
+  return find_generic_function (table, key, idx,
+                                (KeyCompareFunc) strcmp, create_if_not_found, bucket,
+                                preallocated);
+}
+
+static DBusHashEntry*
+find_direct_function (DBusHashTable        *table,
+                      void                 *key,
+                      dbus_bool_t           create_if_not_found,
+                      DBusHashEntry      ***bucket,
+                      DBusPreallocatedHash *preallocated)
+{
+  unsigned int idx;
+  
+  idx = RANDOM_INDEX (table, key) & table->mask;
+
+
+  return find_generic_function (table, key, idx,
+                                NULL, create_if_not_found, bucket,
+                                preallocated);
+}
+
+static void
+rebuild_table (DBusHashTable *table)
+{
+  int old_size;
+  int new_buckets;
+  DBusHashEntry **old_buckets;
+  DBusHashEntry **old_chain;
+  DBusHashEntry *entry;
+  dbus_bool_t growing;
+  
+  /*
+   * Allocate and initialize the new bucket array, and set up
+   * hashing constants for new array size.
+   */
+
+  growing = table->n_entries >= table->hi_rebuild_size;
+  
+  old_size = table->n_buckets;
+  old_buckets = table->buckets;
+
+  if (growing)
+    {
+      /* overflow paranoia */
+      if (table->n_buckets < _DBUS_INT_MAX / 4 &&
+          table->down_shift >= 0)
+        new_buckets = table->n_buckets * 4;
+      else
+        return; /* can't grow anymore */
+    }
+  else
+    {
+      new_buckets = table->n_buckets / 4;
+      if (new_buckets < DBUS_SMALL_HASH_TABLE)
+        return; /* don't bother shrinking this far */
+    }
+
+  table->buckets = dbus_new0 (DBusHashEntry*, new_buckets);
+  if (table->buckets == NULL)
+    {
+      /* out of memory, yay - just don't reallocate, the table will
+       * still work, albeit more slowly.
+       */
+      table->buckets = old_buckets;
+      return;
+    }
+
+  table->n_buckets = new_buckets;
+  
+  if (growing)
+    {
+      table->lo_rebuild_size = table->hi_rebuild_size;
+      table->hi_rebuild_size *= 4;
+      
+      table->down_shift -= 2;               /* keep 2 more high bits */
+      table->mask = (table->mask << 2) + 3; /* keep 2 more high bits */
+    }
+  else
+    {
+      table->hi_rebuild_size = table->lo_rebuild_size;
+      table->lo_rebuild_size /= 4;
+
+      table->down_shift += 2;         /* keep 2 fewer high bits */
+      table->mask = table->mask >> 2; /* keep 2 fewer high bits */
+    }
+
+#if 0
+  printf ("%s table to lo = %d hi = %d downshift = %d mask = 0x%x\n",
+          growing ? "GROW" : "SHRINK",
+          table->lo_rebuild_size,
+          table->hi_rebuild_size,
+          table->down_shift,
+          table->mask);
+#endif
+  
+  _dbus_assert (table->lo_rebuild_size >= 0);
+  _dbus_assert (table->hi_rebuild_size > table->lo_rebuild_size);
+  _dbus_assert (table->mask != 0);
+  /* the mask is essentially the max index */
+  _dbus_assert (table->mask < table->n_buckets);
+  
+  /*
+   * Rehash all of the existing entries into the new bucket array.
+   */
+
+  for (old_chain = old_buckets; old_size > 0; old_size--, old_chain++)
+    {
+      for (entry = *old_chain; entry != NULL; entry = *old_chain)
+        {
+          unsigned int idx;
+          DBusHashEntry **bucket;
+          
+          *old_chain = entry->next;
+          switch (table->key_type)
+            {
+            case DBUS_HASH_STRING:
+              idx = string_hash (entry->key) & table->mask;
+              break;
+            case DBUS_HASH_INT:
+            case DBUS_HASH_UINTPTR:
+              idx = RANDOM_INDEX (table, entry->key);
+              break;
+            default:
+              idx = 0;
+              _dbus_assert_not_reached ("Unknown hash table type");
+              break;
+            }
+          
+          bucket = &(table->buckets[idx]);
+          entry->next = *bucket;
+          *bucket = entry;
+        }
+    }
+  
+  /* Free the old bucket array, if it was dynamically allocated. */
+
+  if (old_buckets != table->static_buckets)
+    dbus_free (old_buckets);
+}
+
+/**
+ * Looks up the value for a given string in a hash table
+ * of type #DBUS_HASH_STRING. Returns %NULL if the value
+ * is not present. (A not-present entry is indistinguishable
+ * from an entry with a value of %NULL.)
+ * @param table the hash table.
+ * @param key the string to look up.
+ * @returns the value of the hash entry.
+ */
+void*
+_dbus_hash_table_lookup_string (DBusHashTable *table,
+                                const char    *key)
+{
+  DBusHashEntry *entry;
+
+  _dbus_assert (table->key_type == DBUS_HASH_STRING);
+  
+  entry = (* table->find_function) (table, (char*) key, FALSE, NULL, NULL);
+
+  if (entry)
+    return entry->value;
+  else
+    return NULL;
+}
+
+/**
+ * Looks up the value for a given integer in a hash table
+ * of type #DBUS_HASH_INT. Returns %NULL if the value
+ * is not present. (A not-present entry is indistinguishable
+ * from an entry with a value of %NULL.)
+ * @param table the hash table.
+ * @param key the integer to look up.
+ * @returns the value of the hash entry.
+ */
+void*
+_dbus_hash_table_lookup_int (DBusHashTable *table,
+                             int            key)
+{
+  DBusHashEntry *entry;
+
+  _dbus_assert (table->key_type == DBUS_HASH_INT);
+  
+  entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, NULL, NULL);
+
+  if (entry)
+    return entry->value;
+  else
+    return NULL;
+}
+
+/**
+ * Looks up the value for a given integer in a hash table
+ * of type #DBUS_HASH_UINTPTR. Returns %NULL if the value
+ * is not present. (A not-present entry is indistinguishable
+ * from an entry with a value of %NULL.)
+ * @param table the hash table.
+ * @param key the integer to look up.
+ * @returns the value of the hash entry.
+ */
+void*
+_dbus_hash_table_lookup_uintptr (DBusHashTable *table,
+                                 uintptr_t      key)
+{
+  DBusHashEntry *entry;
+
+  _dbus_assert (table->key_type == DBUS_HASH_UINTPTR);
+  
+  entry = (* table->find_function) (table, (void*) key, FALSE, NULL, NULL);
+
+  if (entry)
+    return entry->value;
+  else
+    return NULL;
+}
+
+/**
+ * Removes the hash entry for the given key. If no hash entry
+ * for the key exists, does nothing.
+ *
+ * @param table the hash table.
+ * @param key the hash key.
+ * @returns #TRUE if the entry existed
+ */
+dbus_bool_t
+_dbus_hash_table_remove_string (DBusHashTable *table,
+                                const char    *key)
+{
+  DBusHashEntry *entry;
+  DBusHashEntry **bucket;
+  
+  _dbus_assert (table->key_type == DBUS_HASH_STRING);
+  
+  entry = (* table->find_function) (table, (char*) key, FALSE, &bucket, NULL);
+
+  if (entry)
+    {
+      remove_entry (table, bucket, entry);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * Removes the hash entry for the given key. If no hash entry
+ * for the key exists, does nothing.
+ *
+ * @param table the hash table.
+ * @param key the hash key.
+ * @returns #TRUE if the entry existed
+ */
+dbus_bool_t
+_dbus_hash_table_remove_int (DBusHashTable *table,
+                             int            key)
+{
+  DBusHashEntry *entry;
+  DBusHashEntry **bucket;
+  
+  _dbus_assert (table->key_type == DBUS_HASH_INT);
+  
+  entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), FALSE, &bucket, NULL);
+  
+  if (entry)
+    {
+      remove_entry (table, bucket, entry);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * Removes the hash entry for the given key. If no hash entry
+ * for the key exists, does nothing.
+ *
+ * @param table the hash table.
+ * @param key the hash key.
+ * @returns #TRUE if the entry existed
+ */
+dbus_bool_t
+_dbus_hash_table_remove_uintptr (DBusHashTable *table,
+                                 uintptr_t      key)
+{
+  DBusHashEntry *entry;
+  DBusHashEntry **bucket;
+  
+  _dbus_assert (table->key_type == DBUS_HASH_UINTPTR);
+  
+  entry = (* table->find_function) (table, (void*) key, FALSE, &bucket, NULL);
+  
+  if (entry)
+    {
+      remove_entry (table, bucket, entry);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * Creates a hash entry with the given key and value.
+ * The key and value are not copied; they are stored
+ * in the hash table by reference. If an entry with the
+ * given key already exists, the previous key and value
+ * are overwritten (and freed if the hash table has
+ * a key_free_function and/or value_free_function).
+ *
+ * Returns #FALSE if memory for the new hash entry
+ * can't be allocated.
+ * 
+ * @param table the hash table.
+ * @param key the hash entry key.
+ * @param value the hash entry value.
+ */
+dbus_bool_t
+_dbus_hash_table_insert_string (DBusHashTable *table,
+                                char          *key,
+                                void          *value)
+{
+  DBusPreallocatedHash *preallocated;
+
+  _dbus_assert (table->key_type == DBUS_HASH_STRING);
+
+  preallocated = _dbus_hash_table_preallocate_entry (table);
+  if (preallocated == NULL)
+    return FALSE;
+
+  _dbus_hash_table_insert_string_preallocated (table, preallocated,
+                                               key, value);
+  
+  return TRUE;
+}
+
+/**
+ * Creates a hash entry with the given key and value.
+ * The key and value are not copied; they are stored
+ * in the hash table by reference. If an entry with the
+ * given key already exists, the previous key and value
+ * are overwritten (and freed if the hash table has
+ * a key_free_function and/or value_free_function).
+ *
+ * Returns #FALSE if memory for the new hash entry
+ * can't be allocated.
+ * 
+ * @param table the hash table.
+ * @param key the hash entry key.
+ * @param value the hash entry value.
+ */
+dbus_bool_t
+_dbus_hash_table_insert_int (DBusHashTable *table,
+                             int            key,
+                             void          *value)
+{
+  DBusHashEntry *entry;
+
+  _dbus_assert (table->key_type == DBUS_HASH_INT);
+  
+  entry = (* table->find_function) (table, _DBUS_INT_TO_POINTER (key), TRUE, NULL, NULL);
+
+  if (entry == NULL)
+    return FALSE; /* no memory */
+
+  if (table->free_key_function && entry->key != _DBUS_INT_TO_POINTER (key))
+    (* table->free_key_function) (entry->key);
+  
+  if (table->free_value_function && entry->value != value)
+    (* table->free_value_function) (entry->value);
+  
+  entry->key = _DBUS_INT_TO_POINTER (key);
+  entry->value = value;
+
+  return TRUE;
+}
+
+/**
+ * Creates a hash entry with the given key and value.
+ * The key and value are not copied; they are stored
+ * in the hash table by reference. If an entry with the
+ * given key already exists, the previous key and value
+ * are overwritten (and freed if the hash table has
+ * a key_free_function and/or value_free_function).
+ *
+ * Returns #FALSE if memory for the new hash entry
+ * can't be allocated.
+ * 
+ * @param table the hash table.
+ * @param key the hash entry key.
+ * @param value the hash entry value.
+ */
+dbus_bool_t
+_dbus_hash_table_insert_uintptr (DBusHashTable *table,
+                                 uintptr_t      key,
+                                 void          *value)
+{
+  DBusHashEntry *entry;
+
+  _dbus_assert (table->key_type == DBUS_HASH_UINTPTR);
+  
+  entry = (* table->find_function) (table, (void*) key, TRUE, NULL, NULL);
+
+  if (entry == NULL)
+    return FALSE; /* no memory */
+
+  if (table->free_key_function && entry->key != (void*) key)
+    (* table->free_key_function) (entry->key);
+  
+  if (table->free_value_function && entry->value != value)
+    (* table->free_value_function) (entry->value);
+  
+  entry->key = (void*) key;
+  entry->value = value;
+
+  return TRUE;
+}
+
+/**
+ * Preallocate an opaque data blob that allows us to insert into the
+ * hash table at a later time without allocating any memory.
+ *
+ * @param table the hash table
+ * @returns the preallocated data, or #NULL if no memory
+ */
+DBusPreallocatedHash*
+_dbus_hash_table_preallocate_entry (DBusHashTable *table)
+{
+  DBusHashEntry *entry;
+  
+  entry = alloc_entry (table);
+
+  return (DBusPreallocatedHash*) entry;
+}
+
+/**
+ * Frees an opaque DBusPreallocatedHash that was *not* used
+ * in order to insert into the hash table.
+ *
+ * @param table the hash table
+ * @param preallocated the preallocated data
+ */
+void
+_dbus_hash_table_free_preallocated_entry (DBusHashTable        *table,
+                                          DBusPreallocatedHash *preallocated)
+{
+  DBusHashEntry *entry;
+
+  _dbus_assert (preallocated != NULL);
+  
+  entry = (DBusHashEntry*) preallocated;
+  
+  /* Don't use free_entry(), since this entry has no key/data */
+  _dbus_mem_pool_dealloc (table->entry_pool, entry);
+}
+
+/**
+ * Inserts a string-keyed entry into the hash table, using a
+ * preallocated data block from
+ * _dbus_hash_table_preallocate_entry(). This function cannot fail due
+ * to lack of memory. The DBusPreallocatedHash object is consumed and
+ * should not be reused or freed. Otherwise this function works
+ * just like _dbus_hash_table_insert_string().
+ *
+ * @param table the hash table
+ * @param preallocated the preallocated data
+ * @param key the hash key
+ * @param value the value 
+ */
+void
+_dbus_hash_table_insert_string_preallocated (DBusHashTable        *table,
+                                             DBusPreallocatedHash *preallocated,
+                                             char                 *key,
+                                             void                 *value)
+{
+  DBusHashEntry *entry;
+
+  _dbus_assert (table->key_type == DBUS_HASH_STRING);
+  _dbus_assert (preallocated != NULL);
+  
+  entry = (* table->find_function) (table, key, TRUE, NULL, preallocated);
+
+  _dbus_assert (entry != NULL);
+  
+  if (table->free_key_function && entry->key != key)
+    (* table->free_key_function) (entry->key);
+
+  if (table->free_value_function && entry->value != value)
+    (* table->free_value_function) (entry->value);
+      
+  entry->key = key;
+  entry->value = value;
+}
+
+/**
+ * Gets the number of hash entries in a hash table.
+ *
+ * @param table the hash table.
+ * @returns the number of entries in the table.
+ */
+int
+_dbus_hash_table_get_n_entries (DBusHashTable *table)
+{
+  return table->n_entries;
+}
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+
+/* If you're wondering why the hash table test takes
+ * forever to run, it's because we call this function
+ * in inner loops thus making things quadratic.
+ */
+static int
+count_entries (DBusHashTable *table)
+{
+  DBusHashIter iter;
+  int count;
+
+  count = 0;
+  _dbus_hash_iter_init (table, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    ++count;
+
+  _dbus_assert (count == _dbus_hash_table_get_n_entries (table));
+  
+  return count;
+}
+
+/**
+ * @ingroup DBusHashTableInternals
+ * Unit test for DBusHashTable
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_hash_test (void)
+{
+  int i;
+  DBusHashTable *table1;
+  DBusHashTable *table2;
+  DBusHashTable *table3;
+  DBusHashIter iter;
+#define N_HASH_KEYS 5000
+  char **keys;
+  dbus_bool_t ret = FALSE;
+
+  keys = dbus_new (char *, N_HASH_KEYS);
+  if (keys == NULL)
+    _dbus_assert_not_reached ("no memory");
+
+  for (i = 0; i < N_HASH_KEYS; i++)
+    {
+      keys[i] = dbus_malloc (128);
+
+      if (keys[i] == NULL)
+	_dbus_assert_not_reached ("no memory");
+    }
+
+  printf ("Computing test hash keys...\n");
+  i = 0;
+  while (i < N_HASH_KEYS)
+    {
+      int len;
+
+      len = sprintf (keys[i], "Hash key %d", i);
+      _dbus_assert (*(keys[i] + len) == '\0');
+      ++i;
+    }
+  printf ("... done.\n");
+  
+  table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
+                                 dbus_free, dbus_free);
+  if (table1 == NULL)
+    goto out;
+
+  table2 = _dbus_hash_table_new (DBUS_HASH_INT,
+                                 NULL, dbus_free);
+  if (table2 == NULL)
+    goto out;
+
+  table3 = _dbus_hash_table_new (DBUS_HASH_UINTPTR,
+                                 NULL, dbus_free);
+  if (table3 == NULL)
+    goto out;
+
+  /* Insert and remove a bunch of stuff, counting the table in between
+   * to be sure it's not broken and that iteration works
+   */
+  i = 0;
+  while (i < 3000)
+    {
+      void *value;
+      char *key;
+
+      key = _dbus_strdup (keys[i]);
+      if (key == NULL)
+        goto out;
+      value = _dbus_strdup ("Value!");
+      if (value == NULL)
+        goto out;
+      
+      if (!_dbus_hash_table_insert_string (table1,
+                                           key, value))
+        goto out;
+
+      value = _dbus_strdup (keys[i]);
+      if (value == NULL)
+        goto out;
+      
+      if (!_dbus_hash_table_insert_int (table2,
+                                        i, value))
+        goto out;
+
+      value = _dbus_strdup (keys[i]);
+      if (value == NULL)
+        goto out;
+      
+      if (!_dbus_hash_table_insert_uintptr (table3,
+                                          i, value))
+        goto out;
+
+      _dbus_assert (count_entries (table1) == i + 1);
+      _dbus_assert (count_entries (table2) == i + 1);
+      _dbus_assert (count_entries (table3) == i + 1);
+
+      value = _dbus_hash_table_lookup_string (table1, keys[i]);
+      _dbus_assert (value != NULL);
+      _dbus_assert (strcmp (value, "Value!") == 0);
+
+      value = _dbus_hash_table_lookup_int (table2, i);
+      _dbus_assert (value != NULL);
+      _dbus_assert (strcmp (value, keys[i]) == 0);
+
+      value = _dbus_hash_table_lookup_uintptr (table3, i);
+      _dbus_assert (value != NULL);
+      _dbus_assert (strcmp (value, keys[i]) == 0);
+
+      ++i;
+    }
+
+  --i;
+  while (i >= 0)
+    {
+      _dbus_hash_table_remove_string (table1,
+                                      keys[i]);
+
+      _dbus_hash_table_remove_int (table2, i);
+
+      _dbus_hash_table_remove_uintptr (table3, i);
+
+      _dbus_assert (count_entries (table1) == i);
+      _dbus_assert (count_entries (table2) == i);
+      _dbus_assert (count_entries (table3) == i);
+
+      --i;
+    }
+
+  _dbus_hash_table_ref (table1);
+  _dbus_hash_table_ref (table2);
+  _dbus_hash_table_ref (table3);
+  _dbus_hash_table_unref (table1);
+  _dbus_hash_table_unref (table2);
+  _dbus_hash_table_unref (table3);
+  _dbus_hash_table_unref (table1);
+  _dbus_hash_table_unref (table2);
+  _dbus_hash_table_unref (table3);
+  table3 = NULL;
+
+  /* Insert a bunch of stuff then check
+   * that iteration works correctly (finds the right
+   * values, iter_set_value works, etc.)
+   */
+  table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
+                                 dbus_free, dbus_free);
+  if (table1 == NULL)
+    goto out;
+  
+  table2 = _dbus_hash_table_new (DBUS_HASH_INT,
+                                 NULL, dbus_free);
+  if (table2 == NULL)
+    goto out;
+  
+  i = 0;
+  while (i < 5000)
+    {
+      char *key;
+      void *value;      
+      
+      key = _dbus_strdup (keys[i]);
+      if (key == NULL)
+        goto out;
+      value = _dbus_strdup ("Value!");
+      if (value == NULL)
+        goto out;
+      
+      if (!_dbus_hash_table_insert_string (table1,
+                                           key, value))
+        goto out;
+
+      value = _dbus_strdup (keys[i]);
+      if (value == NULL)
+        goto out;
+      
+      if (!_dbus_hash_table_insert_int (table2,
+                                        i, value))
+        goto out;
+      
+      _dbus_assert (count_entries (table1) == i + 1);
+      _dbus_assert (count_entries (table2) == i + 1);
+      
+      ++i;
+    }
+
+  _dbus_hash_iter_init (table1, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      const char *key;
+      void *value;
+
+      key = _dbus_hash_iter_get_string_key (&iter);
+      value = _dbus_hash_iter_get_value (&iter);
+
+      _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value);
+
+      value = _dbus_strdup ("Different value!");
+      if (value == NULL)
+        goto out;
+      
+      _dbus_hash_iter_set_value (&iter, value);
+
+      _dbus_assert (_dbus_hash_table_lookup_string (table1, key) == value);
+    }
+  
+  _dbus_hash_iter_init (table1, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      _dbus_hash_iter_remove_entry (&iter);
+      _dbus_assert (count_entries (table1) == i - 1);
+      --i;
+    }
+
+  _dbus_hash_iter_init (table2, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      int key;
+      void *value;
+
+      key = _dbus_hash_iter_get_int_key (&iter);
+      value = _dbus_hash_iter_get_value (&iter);
+
+      _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value);
+
+      value = _dbus_strdup ("Different value!");
+      if (value == NULL)
+        goto out;
+      
+      _dbus_hash_iter_set_value (&iter, value);
+
+      _dbus_assert (_dbus_hash_table_lookup_int (table2, key) == value);
+    }
+
+  i = count_entries (table2);
+  _dbus_hash_iter_init (table2, &iter);
+  while (_dbus_hash_iter_next (&iter))
+    {
+      _dbus_hash_iter_remove_entry (&iter);
+      _dbus_assert (count_entries (table2) + 1 == i);
+      --i;
+    }
+
+  /* add/remove interleaved, to check that we grow/shrink the table
+   * appropriately
+   */
+  i = 0;
+  while (i < 1000)
+    {
+      char *key;
+      void *value;
+            
+      key = _dbus_strdup (keys[i]);
+      if (key == NULL)
+        goto out;
+
+      value = _dbus_strdup ("Value!");
+      if (value == NULL)
+        goto out;
+      
+      if (!_dbus_hash_table_insert_string (table1,
+                                           key, value))
+        goto out;
+      
+      ++i;
+    }
+
+  --i;
+  while (i >= 0)
+    {
+      char *key;
+      void *value;      
+      
+      key = _dbus_strdup (keys[i]);
+      if (key == NULL)
+        goto out;
+      value = _dbus_strdup ("Value!");
+      if (value == NULL)
+        goto out;
+
+      if (!_dbus_hash_table_remove_string (table1, keys[i]))
+        goto out;
+      
+      if (!_dbus_hash_table_insert_string (table1,
+                                           key, value))
+        goto out;
+
+      if (!_dbus_hash_table_remove_string (table1, keys[i]))
+        goto out;
+      
+      _dbus_assert (_dbus_hash_table_get_n_entries (table1) == i);
+      
+      --i;
+    }
+
+  /* nuke these tables */
+  _dbus_hash_table_unref (table1);
+  _dbus_hash_table_unref (table2);
+
+
+  /* Now do a bunch of things again using _dbus_hash_iter_lookup() to
+   * be sure that interface works.
+   */
+  table1 = _dbus_hash_table_new (DBUS_HASH_STRING,
+                                 dbus_free, dbus_free);
+  if (table1 == NULL)
+    goto out;
+  
+  table2 = _dbus_hash_table_new (DBUS_HASH_INT,
+                                 NULL, dbus_free);
+  if (table2 == NULL)
+    goto out;
+  
+  i = 0;
+  while (i < 3000)
+    {
+      void *value;
+      char *key;
+
+      key = _dbus_strdup (keys[i]);
+      if (key == NULL)
+        goto out;
+      value = _dbus_strdup ("Value!");
+      if (value == NULL)
+        goto out;
+      
+      if (!_dbus_hash_iter_lookup (table1,
+                                   key, TRUE, &iter))
+        goto out;
+      _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL);
+      _dbus_hash_iter_set_value (&iter, value);
+
+      value = _dbus_strdup (keys[i]);
+      if (value == NULL)
+        goto out;
+
+      if (!_dbus_hash_iter_lookup (table2,
+                                   _DBUS_INT_TO_POINTER (i), TRUE, &iter))
+        goto out;
+      _dbus_assert (_dbus_hash_iter_get_value (&iter) == NULL);
+      _dbus_hash_iter_set_value (&iter, value); 
+      
+      _dbus_assert (count_entries (table1) == i + 1);
+      _dbus_assert (count_entries (table2) == i + 1);
+
+      if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter))
+        goto out;
+      
+      value = _dbus_hash_iter_get_value (&iter);
+      _dbus_assert (value != NULL);
+      _dbus_assert (strcmp (value, "Value!") == 0);
+
+      /* Iterate just to be sure it works, though
+       * it's a stupid thing to do
+       */
+      while (_dbus_hash_iter_next (&iter))
+        ;
+      
+      if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter))
+        goto out;
+
+      value = _dbus_hash_iter_get_value (&iter);
+      _dbus_assert (value != NULL);
+      _dbus_assert (strcmp (value, keys[i]) == 0);
+
+      /* Iterate just to be sure it works, though
+       * it's a stupid thing to do
+       */
+      while (_dbus_hash_iter_next (&iter))
+        ;
+      
+      ++i;
+    }
+
+  --i;
+  while (i >= 0)
+    {
+      if (!_dbus_hash_iter_lookup (table1, keys[i], FALSE, &iter))
+        _dbus_assert_not_reached ("hash entry should have existed");
+      _dbus_hash_iter_remove_entry (&iter);
+      
+      if (!_dbus_hash_iter_lookup (table2, _DBUS_INT_TO_POINTER (i), FALSE, &iter))
+        _dbus_assert_not_reached ("hash entry should have existed");
+      _dbus_hash_iter_remove_entry (&iter);
+
+      _dbus_assert (count_entries (table1) == i);
+      _dbus_assert (count_entries (table2) == i);
+
+      --i;
+    }
+
+  _dbus_hash_table_unref (table1);
+  _dbus_hash_table_unref (table2);
+
+  ret = TRUE;
+
+ out:
+  for (i = 0; i < N_HASH_KEYS; i++)
+    dbus_free (keys[i]);
+
+  dbus_free (keys);
+  
+  return ret;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-hash.h b/dbus/dbus/dbus-hash.h
new file mode 100644
index 0000000..5aa183c
--- /dev/null
+++ b/dbus/dbus/dbus-hash.h
@@ -0,0 +1,134 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-hash.h Generic hash table utility (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_HASH_H
+#define DBUS_HASH_H
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include <dbus/dbus-memory.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-sysdeps.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusHashTable
+ * @{
+ */
+
+/** Hash iterator object. The iterator is on the stack, but its real
+ * fields are hidden privately.
+ */
+struct DBusHashIter
+{
+  void *dummy1; /**< Do not use. */
+  void *dummy2; /**< Do not use. */
+  void *dummy3; /**< Do not use. */
+  void *dummy4; /**< Do not use. */
+  int   dummy5; /**< Do not use. */
+  int   dummy6; /**< Do not use. */
+};
+
+typedef struct DBusHashTable DBusHashTable;
+typedef struct DBusHashIter  DBusHashIter;
+
+/* Allowing an arbitrary function as with GLib
+ * would be nicer for a public API, but for
+ * an internal API this saves typing, we can add
+ * more whenever we feel like it.
+ */
+typedef enum
+{
+  DBUS_HASH_STRING,        /**< Hash keys are strings. */
+  DBUS_HASH_INT,           /**< Hash keys are integers. */
+  DBUS_HASH_UINTPTR        /**< Hash keys are integer capable to hold a pointer. */
+} DBusHashType;
+
+DBusHashTable* _dbus_hash_table_new                (DBusHashType      type,
+                                                    DBusFreeFunction  key_free_function,
+                                                    DBusFreeFunction  value_free_function);
+DBusHashTable* _dbus_hash_table_ref                (DBusHashTable    *table);
+void           _dbus_hash_table_unref              (DBusHashTable    *table);
+void           _dbus_hash_table_remove_all         (DBusHashTable    *table);
+void           _dbus_hash_iter_init                (DBusHashTable    *table,
+                                                    DBusHashIter     *iter);
+dbus_bool_t    _dbus_hash_iter_next                (DBusHashIter     *iter);
+void           _dbus_hash_iter_remove_entry        (DBusHashIter     *iter);
+void*          _dbus_hash_iter_get_value           (DBusHashIter     *iter);
+void           _dbus_hash_iter_set_value           (DBusHashIter     *iter,
+                                                    void             *value);
+int            _dbus_hash_iter_get_int_key         (DBusHashIter     *iter);
+const char*    _dbus_hash_iter_get_string_key      (DBusHashIter     *iter);
+uintptr_t      _dbus_hash_iter_get_uintptr_key     (DBusHashIter     *iter);
+dbus_bool_t    _dbus_hash_iter_lookup              (DBusHashTable    *table,
+                                                    void             *key,
+                                                    dbus_bool_t       create_if_not_found,
+                                                    DBusHashIter     *iter);
+void*          _dbus_hash_table_lookup_string      (DBusHashTable    *table,
+                                                    const char       *key);
+void*          _dbus_hash_table_lookup_int         (DBusHashTable    *table,
+                                                    int               key);
+void*          _dbus_hash_table_lookup_uintptr     (DBusHashTable    *table,
+                                                    uintptr_t         key);
+dbus_bool_t    _dbus_hash_table_remove_string      (DBusHashTable    *table,
+                                                    const char       *key);
+dbus_bool_t    _dbus_hash_table_remove_int         (DBusHashTable    *table,
+                                                    int               key);
+dbus_bool_t    _dbus_hash_table_remove_uintptr     (DBusHashTable    *table,
+                                                    uintptr_t         key);
+dbus_bool_t    _dbus_hash_table_insert_string      (DBusHashTable    *table,
+                                                    char             *key,
+                                                    void             *value);
+dbus_bool_t    _dbus_hash_table_insert_int         (DBusHashTable    *table,
+                                                    int               key,
+                                                    void             *value);
+dbus_bool_t    _dbus_hash_table_insert_uintptr     (DBusHashTable    *table,
+                                                    uintptr_t         key,
+                                                    void             *value);
+int            _dbus_hash_table_get_n_entries      (DBusHashTable    *table);
+
+/* Preallocation */
+
+/** A preallocated hash entry */
+typedef struct DBusPreallocatedHash DBusPreallocatedHash;
+
+DBusPreallocatedHash *_dbus_hash_table_preallocate_entry          (DBusHashTable        *table);
+void                  _dbus_hash_table_free_preallocated_entry    (DBusHashTable        *table,
+                                                                   DBusPreallocatedHash *preallocated);
+void                  _dbus_hash_table_insert_string_preallocated (DBusHashTable        *table,
+                                                                   DBusPreallocatedHash *preallocated,
+                                                                   char                 *key,
+                                                                   void                 *value);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_HASH_H */
diff --git a/dbus/dbus/dbus-internals.c b/dbus/dbus/dbus-internals.c
new file mode 100644
index 0000000..1ec4980
--- /dev/null
+++ b/dbus/dbus/dbus-internals.c
@@ -0,0 +1,1076 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-internals.c  random utility stuff (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-protocol.h"
+#include "dbus-marshal-basic.h"
+#include "dbus-test.h"
+#include "dbus-valgrind-internal.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
+#include <windows.h>
+#include <mbstring.h>
+#endif
+
+#ifdef DBUS_ANDROID_LOG
+#define LOG_TAG "libdbus"
+#include <cutils/log.h>
+#endif /* DBUS_ANDROID_LOG */
+
+/**
+ * @defgroup DBusInternals D-Bus secret internal implementation details
+ * @brief Documentation useful when developing or debugging D-Bus itself.
+ * 
+ */
+
+/**
+ * @defgroup DBusInternalsUtils Utilities and portability
+ * @ingroup DBusInternals
+ * @brief Utility functions (_dbus_assert(), _dbus_warn(), etc.)
+ * @{
+ */
+
+/**
+ * @def _dbus_assert
+ *
+ * Aborts with an error message if the condition is false.
+ * 
+ * @param condition condition which must be true.
+ */
+
+/**
+ * @def _dbus_assert_not_reached
+ *
+ * Aborts with an error message if called.
+ * The given explanation will be printed.
+ * 
+ * @param explanation explanation of what happened if the code was reached.
+ */
+
+/**
+ * @def _DBUS_N_ELEMENTS
+ *
+ * Computes the number of elements in a fixed-size array using
+ * sizeof().
+ *
+ * @param array the array to count elements in.
+ */
+
+/**
+ * @def _DBUS_POINTER_TO_INT
+ *
+ * Safely casts a void* to an integer; should only be used on void*
+ * that actually contain integers, for example one created with
+ * _DBUS_INT_TO_POINTER.  Only guaranteed to preserve 32 bits.
+ * (i.e. it's used to store 32-bit ints in pointers, but
+ * can't be used to store 64-bit pointers in ints.)
+ *
+ * @param pointer pointer to extract an integer from.
+ */
+/**
+ * @def _DBUS_INT_TO_POINTER
+ *
+ * Safely stuffs an integer into a pointer, to be extracted later with
+ * _DBUS_POINTER_TO_INT. Only guaranteed to preserve 32 bits.
+ *
+ * @param integer the integer to stuff into a pointer.
+ */
+/**
+ * @def _DBUS_ZERO
+ *
+ * Sets all bits in an object to zero.
+ *
+ * @param object the object to be zeroed.
+ */
+/**
+ * @def _DBUS_INT16_MIN
+ *
+ * Minimum value of type "int16"
+ */
+/**
+ * @def _DBUS_INT16_MAX
+ *
+ * Maximum value of type "int16"
+ */
+/**
+ * @def _DBUS_UINT16_MAX
+ *
+ * Maximum value of type "uint16"
+ */
+
+/**
+ * @def _DBUS_INT32_MIN
+ *
+ * Minimum value of type "int32"
+ */
+/**
+ * @def _DBUS_INT32_MAX
+ *
+ * Maximum value of type "int32"
+ */
+/**
+ * @def _DBUS_UINT32_MAX
+ *
+ * Maximum value of type "uint32"
+ */
+
+/**
+ * @def _DBUS_INT_MIN
+ *
+ * Minimum value of type "int"
+ */
+/**
+ * @def _DBUS_INT_MAX
+ *
+ * Maximum value of type "int"
+ */
+/**
+ * @def _DBUS_UINT_MAX
+ *
+ * Maximum value of type "uint"
+ */
+
+/**
+ * @typedef DBusForeachFunction
+ * 
+ * Used to iterate over each item in a collection, such as
+ * a DBusList.
+ */
+
+/**
+ * @def _DBUS_LOCK_NAME
+ *
+ * Expands to name of a global lock variable.
+ */
+
+/**
+ * @def _DBUS_DEFINE_GLOBAL_LOCK
+ *
+ * Defines a global lock variable with the given name.
+ * The lock must be added to the list to initialize
+ * in dbus_threads_init().
+ */
+
+/**
+ * @def _DBUS_DECLARE_GLOBAL_LOCK
+ *
+ * Expands to declaration of a global lock defined
+ * with _DBUS_DEFINE_GLOBAL_LOCK.
+ * The lock must be added to the list to initialize
+ * in dbus_threads_init().
+ */
+
+/**
+ * @def _DBUS_LOCK
+ *
+ * Locks a global lock
+ */
+
+/**
+ * @def _DBUS_UNLOCK
+ *
+ * Unlocks a global lock
+ */
+
+/**
+ * Fixed "out of memory" error message, just to avoid
+ * making up a different string every time and wasting
+ * space.
+ */
+const char *_dbus_no_memory_message = "Not enough memory";
+
+static dbus_bool_t warn_initted = FALSE;
+static dbus_bool_t fatal_warnings = FALSE;
+static dbus_bool_t fatal_warnings_on_check_failed = TRUE;
+
+static void
+init_warnings(void)
+{
+  if (!warn_initted)
+    {
+      const char *s;
+      s = _dbus_getenv ("DBUS_FATAL_WARNINGS");
+      if (s && *s)
+        {
+          if (*s == '0')
+            {
+              fatal_warnings = FALSE;
+              fatal_warnings_on_check_failed = FALSE;
+            }
+          else if (*s == '1')
+            {
+              fatal_warnings = TRUE;
+              fatal_warnings_on_check_failed = TRUE;
+            }
+          else
+            {
+              fprintf(stderr, "DBUS_FATAL_WARNINGS should be set to 0 or 1 if set, not '%s'",
+                      s);
+            }
+        }
+
+      warn_initted = TRUE;
+    }
+}
+
+/**
+ * Prints a warning message to stderr. Can optionally be made to exit
+ * fatally by setting DBUS_FATAL_WARNINGS, but this is rarely
+ * used. This function should be considered pretty much equivalent to
+ * fprintf(stderr). _dbus_warn_check_failed() on the other hand is
+ * suitable for use when a programming mistake has been made.
+ *
+ * @param format printf-style format string.
+ */
+void
+_dbus_warn (const char *format,
+            ...)
+{
+  va_list args;
+
+  if (!warn_initted)
+    init_warnings ();
+  
+  va_start (args, format);
+#ifdef DBUS_ANDROID_LOG
+  LOG_PRI_VA(ANDROID_LOG_WARN, LOG_TAG, format, args);
+#else
+  vfprintf (stderr, format, args);
+#endif /* DBUS_ANDROID_LOG */
+  va_end (args);
+
+  if (fatal_warnings)
+    {
+      fflush (stderr);
+      _dbus_abort ();
+    }
+}
+
+/**
+ * Prints a "critical" warning to stderr when an assertion fails;
+ * differs from _dbus_warn primarily in that it prefixes the pid and
+ * defaults to fatal. This should be used only when a programming
+ * error has been detected. (NOT for unavoidable errors that an app
+ * might handle - those should be returned as DBusError.) Calling this
+ * means "there is a bug"
+ */
+void
+_dbus_warn_check_failed(const char *format,
+                        ...)
+{
+  va_list args;
+  
+  if (!warn_initted)
+    init_warnings ();
+
+  fprintf (stderr, "process %lu: ", _dbus_pid_for_log ());
+  
+  va_start (args, format);
+#ifdef DBUS_ANDROID_LOG
+  LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args);
+#else
+  vfprintf (stderr, format, args);
+#endif /* DBUS_ANDROID_LOG */
+  va_end (args);
+
+  if (fatal_warnings_on_check_failed)
+    {
+      fflush (stderr);
+      _dbus_abort ();
+    }
+}
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+
+static dbus_bool_t verbose_initted = FALSE;
+static dbus_bool_t verbose = TRUE;
+
+/** Whether to show the current thread in verbose messages */
+#define PTHREAD_IN_VERBOSE 0
+#if PTHREAD_IN_VERBOSE
+#include <pthread.h>
+#endif
+
+#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
+static char module_name[1024];
+#endif
+
+static inline void
+_dbus_verbose_init (void)
+{
+  if (!verbose_initted)
+    {
+#ifdef DBUS_ANDROID_LOG
+      /* Don't bother checking environment variable - just print the
+         verbose logs (can still be disabled with DBUS_ENABLE_VERBOSE_MODE) */
+      verbose = TRUE;
+#else
+      const char *p = _dbus_getenv ("DBUS_VERBOSE"); 
+      verbose = p != NULL && *p == '1';
+#endif
+      verbose_initted = TRUE;
+#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
+      {
+        char *last_period, *last_slash;
+        GetModuleFileName(0,module_name,sizeof(module_name)-1);
+        last_period = _mbsrchr(module_name,'.');
+        if (last_period)
+          *last_period ='\0';
+        last_slash = _mbsrchr(module_name,'\\');
+        if (last_slash)
+          strcpy(module_name,last_slash+1);
+        strcat(module_name,": ");
+      }
+#endif
+    }
+}
+
+/** @def DBUS_IS_DIR_SEPARATOR(c)
+ * macro for checking if character c is a patch separator
+ * 
+ * @todo move to a header file so that others can use this too
+ */
+#ifdef DBUS_WIN 
+#define DBUS_IS_DIR_SEPARATOR(c) (c == '\\' || c == '/')
+#else
+#define DBUS_IS_DIR_SEPARATOR(c) (c == '/')
+#endif
+
+/** 
+ remove source root from file path 
+ the source root is determined by 
+*/ 
+static char *_dbus_file_path_extract_elements_from_tail(const char *file,int level)
+{
+  static int prefix = -1;
+
+  if (prefix == -1) 
+    {
+      char *p = (char *)file + strlen(file);
+      int i = 0;
+      prefix = 0;
+      for (;p >= file;p--)
+        {
+          if (DBUS_IS_DIR_SEPARATOR(*p))
+            {
+              if (++i >= level) 
+                {
+                  prefix = p-file+1;
+                  break;
+                }
+           }
+        }
+    }
+  return (char *)file+prefix;
+}
+
+/**
+ * Implementation of dbus_is_verbose() macro if built with verbose logging
+ * enabled.
+ * @returns whether verbose logging is active.
+ */
+dbus_bool_t
+_dbus_is_verbose_real (void)
+{
+  _dbus_verbose_init ();
+  return verbose;
+}
+
+/**
+ * Prints a warning message to stderr
+ * if the user has enabled verbose mode.
+ * This is the real function implementation,
+ * use _dbus_verbose() macro in code.
+ *
+ * @param format printf-style format string.
+ */
+void
+_dbus_verbose_real (
+#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
+                    const char *file,
+                    const int line, 
+                    const char *function, 
+#endif
+                    const char *format,
+                    ...)
+{
+  va_list args;
+  static dbus_bool_t need_pid = TRUE;
+  int len;
+  
+  /* things are written a bit oddly here so that
+   * in the non-verbose case we just have the one
+   * conditional and return immediately.
+   */
+  if (!_dbus_is_verbose_real())
+    return;
+
+#ifndef DBUS_USE_OUTPUT_DEBUG_STRING
+  /* Print out pid before the line */
+  if (need_pid)
+    {
+#if PTHREAD_IN_VERBOSE
+      fprintf (stderr, "%lu: 0x%lx: ", _dbus_pid_for_log (), pthread_self ());
+#else
+      fprintf (stderr, "%lu: ", _dbus_pid_for_log ());
+#endif
+    }
+#endif
+
+  /* Only print pid again if the next line is a new line */
+  len = strlen (format);
+  if (format[len-1] == '\n')
+    need_pid = TRUE;
+  else
+    need_pid = FALSE;
+
+  va_start (args, format);
+#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
+  {
+  char buf[1024];
+  strcpy(buf,module_name);
+#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
+  sprintf (buf+strlen(buf), "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function);
+#endif
+  vsprintf (buf+strlen(buf),format, args);
+  va_end (args);
+  OutputDebugStringA(buf);
+  }
+#else
+#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
+  fprintf (stderr, "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function);
+#endif
+
+#ifdef DBUS_ANDROID_LOG
+  LOG_PRI_VA(ANDROID_LOG_DEBUG, LOG_TAG, format, args);
+#else
+  vfprintf (stderr, format, args);
+#endif /* DBUS_ANDROID_LOG */
+  va_end (args);
+
+  fflush (stderr);
+#endif
+}
+
+/**
+ * Reinitializes the verbose logging code, used
+ * as a hack in dbus-spawn.c so that a child
+ * process re-reads its pid
+ *
+ */
+void
+_dbus_verbose_reset_real (void)
+{
+  verbose_initted = FALSE;
+}
+
+void
+_dbus_trace_ref (const char *obj_name,
+                 void       *obj,
+                 int         old_refcount,
+                 int         new_refcount,
+                 const char *why,
+                 const char *env_var,
+                 int        *enabled)
+{
+  _dbus_assert (obj_name != NULL);
+  _dbus_assert (obj != NULL);
+  _dbus_assert (old_refcount >= -1);
+  _dbus_assert (new_refcount >= -1);
+
+  if (old_refcount == -1)
+    {
+      _dbus_assert (new_refcount == -1);
+    }
+  else
+    {
+      _dbus_assert (new_refcount >= 0);
+      _dbus_assert (old_refcount >= 0);
+      _dbus_assert (old_refcount > 0 || new_refcount > 0);
+    }
+
+  _dbus_assert (why != NULL);
+  _dbus_assert (env_var != NULL);
+  _dbus_assert (enabled != NULL);
+
+  if (*enabled < 0)
+    {
+      const char *s = _dbus_getenv (env_var);
+
+      *enabled = FALSE;
+
+      if (s && *s)
+        {
+          if (*s == '0')
+            *enabled = FALSE;
+          else if (*s == '1')
+            *enabled = TRUE;
+          else
+            _dbus_warn ("%s should be 0 or 1 if set, not '%s'", env_var, s);
+        }
+    }
+
+  if (*enabled)
+    {
+      if (old_refcount == -1)
+        {
+          VALGRIND_PRINTF_BACKTRACE ("%s %p ref stolen (%s)",
+                                     obj_name, obj, why);
+          _dbus_verbose ("%s %p ref stolen (%s)",
+                         obj_name, obj, why);
+        }
+      else
+        {
+          VALGRIND_PRINTF_BACKTRACE ("%s %p %d -> %d refs (%s)",
+                                     obj_name, obj,
+                                     old_refcount, new_refcount, why);
+          _dbus_verbose ("%s %p %d -> %d refs (%s)",
+                         obj_name, obj, old_refcount, new_refcount, why);
+        }
+    }
+}
+
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+
+/**
+ * Duplicates a string. Result must be freed with
+ * dbus_free(). Returns #NULL if memory allocation fails.
+ * If the string to be duplicated is #NULL, returns #NULL.
+ * 
+ * @param str string to duplicate.
+ * @returns newly-allocated copy.
+ */
+char*
+_dbus_strdup (const char *str)
+{
+  size_t len;
+  char *copy;
+  
+  if (str == NULL)
+    return NULL;
+  
+  len = strlen (str);
+
+  copy = dbus_malloc (len + 1);
+  if (copy == NULL)
+    return NULL;
+
+  memcpy (copy, str, len + 1);
+  
+  return copy;
+}
+
+/**
+ * Duplicates a block of memory. Returns
+ * #NULL on failure.
+ *
+ * @param mem memory to copy
+ * @param n_bytes number of bytes to copy
+ * @returns the copy
+ */
+void*
+_dbus_memdup (const void  *mem,
+              size_t       n_bytes)
+{
+  void *copy;
+
+  copy = dbus_malloc (n_bytes);
+  if (copy == NULL)
+    return NULL;
+
+  memcpy (copy, mem, n_bytes);
+  
+  return copy;
+}
+
+/**
+ * Duplicates a string array. Result may be freed with
+ * dbus_free_string_array(). Returns #NULL if memory allocation fails.
+ * If the array to be duplicated is #NULL, returns #NULL.
+ * 
+ * @param array array to duplicate.
+ * @returns newly-allocated copy.
+ */
+char**
+_dbus_dup_string_array (const char **array)
+{
+  int len;
+  int i;
+  char **copy;
+  
+  if (array == NULL)
+    return NULL;
+
+  for (len = 0; array[len] != NULL; ++len)
+    ;
+
+  copy = dbus_new0 (char*, len + 1);
+  if (copy == NULL)
+    return NULL;
+
+  i = 0;
+  while (i < len)
+    {
+      copy[i] = _dbus_strdup (array[i]);
+      if (copy[i] == NULL)
+        {
+          dbus_free_string_array (copy);
+          return NULL;
+        }
+
+      ++i;
+    }
+
+  return copy;
+}
+
+/**
+ * Checks whether a string array contains the given string.
+ * 
+ * @param array array to search.
+ * @param str string to look for
+ * @returns #TRUE if array contains string
+ */
+dbus_bool_t
+_dbus_string_array_contains (const char **array,
+                             const char  *str)
+{
+  int i;
+
+  i = 0;
+  while (array[i] != NULL)
+    {
+      if (strcmp (array[i], str) == 0)
+        return TRUE;
+      ++i;
+    }
+
+  return FALSE;
+}
+
+/**
+ * Generates a new UUID. If you change how this is done,
+ * there's some text about it in the spec that should also change.
+ *
+ * @param uuid the uuid to initialize
+ */
+void
+_dbus_generate_uuid (DBusGUID *uuid)
+{
+  long now;
+
+  /* don't use monotonic time because the UUID may be saved to disk, e.g.
+   * it may persist across reboots
+   */
+  _dbus_get_real_time (&now, NULL);
+
+  uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now);
+  
+  _dbus_generate_random_bytes_buffer (uuid->as_bytes, DBUS_UUID_LENGTH_BYTES - 4);
+}
+
+/**
+ * Hex-encode a UUID.
+ *
+ * @param uuid the uuid
+ * @param encoded string to append hex uuid to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_uuid_encode (const DBusGUID *uuid,
+                   DBusString     *encoded)
+{
+  DBusString binary;
+  _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
+  return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded));
+}
+
+static dbus_bool_t
+_dbus_read_uuid_file_without_creating (const DBusString *filename,
+                                       DBusGUID         *uuid,
+                                       DBusError        *error)
+{
+  DBusString contents;
+  DBusString decoded;
+  int end;
+  
+  if (!_dbus_string_init (&contents))
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&decoded))
+    {
+      _dbus_string_free (&contents);
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!_dbus_file_get_contents (&contents, filename, error))
+    goto error;
+
+  _dbus_string_chop_white (&contents);
+
+  if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
+                      "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
+                      _dbus_string_get_const_data (filename),
+                      DBUS_UUID_LENGTH_HEX,
+                      _dbus_string_get_length (&contents));
+      goto error;
+    }
+
+  if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
+    {
+      _DBUS_SET_OOM (error);
+      goto error;
+    }
+
+  if (end == 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
+                      "UUID file '%s' contains invalid hex data",
+                      _dbus_string_get_const_data (filename));
+      goto error;
+    }
+
+  if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
+                      "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
+                      _dbus_string_get_const_data (filename),
+                      _dbus_string_get_length (&decoded),
+                      DBUS_UUID_LENGTH_BYTES);
+      goto error;
+    }
+
+  _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
+
+  _dbus_string_free (&decoded);
+  _dbus_string_free (&contents);
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  return TRUE;
+  
+ error:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  _dbus_string_free (&contents);
+  _dbus_string_free (&decoded);
+  return FALSE;
+}
+
+static dbus_bool_t
+_dbus_create_uuid_file_exclusively (const DBusString *filename,
+                                    DBusGUID         *uuid,
+                                    DBusError        *error)
+{
+  DBusString encoded;
+
+  if (!_dbus_string_init (&encoded))
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  _dbus_generate_uuid (uuid);
+  
+  if (!_dbus_uuid_encode (uuid, &encoded))
+    {
+      _DBUS_SET_OOM (error);
+      goto error;
+    }
+  
+  if (!_dbus_string_append_byte (&encoded, '\n'))
+    {
+      _DBUS_SET_OOM (error);
+      goto error;
+    }
+  
+  if (!_dbus_string_save_to_file (&encoded, filename, TRUE, error))
+    goto error;
+
+  _dbus_string_free (&encoded);
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  return TRUE;
+  
+ error:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  _dbus_string_free (&encoded);
+  return FALSE;        
+}
+
+/**
+ * Reads (and optionally writes) a uuid to a file. Initializes the uuid
+ * unless an error is returned.
+ *
+ * @param filename the name of the file
+ * @param uuid uuid to be initialized with the loaded uuid
+ * @param create_if_not_found #TRUE to create a new uuid and save it if the file doesn't exist
+ * @param error the error return
+ * @returns #FALSE if the error is set
+ */
+dbus_bool_t
+_dbus_read_uuid_file (const DBusString *filename,
+                      DBusGUID         *uuid,
+                      dbus_bool_t       create_if_not_found,
+                      DBusError        *error)
+{
+  DBusError read_error = DBUS_ERROR_INIT;
+
+  if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error))
+    return TRUE;
+
+  if (!create_if_not_found)
+    {
+      dbus_move_error (&read_error, error);
+      return FALSE;
+    }
+
+  /* If the file exists and contains junk, we want to keep that error
+   * message instead of overwriting it with a "file exists" error
+   * message when we try to write
+   */
+  if (dbus_error_has_name (&read_error, DBUS_ERROR_INVALID_FILE_CONTENT))
+    {
+      dbus_move_error (&read_error, error);
+      return FALSE;
+    }
+  else
+    {
+      dbus_error_free (&read_error);
+      return _dbus_create_uuid_file_exclusively (filename, uuid, error);
+    }
+}
+
+_DBUS_DEFINE_GLOBAL_LOCK (machine_uuid);
+static int machine_uuid_initialized_generation = 0;
+static DBusGUID machine_uuid;
+
+/**
+ * Gets the hex-encoded UUID of the machine this function is
+ * executed on. This UUID is guaranteed to be the same for a given
+ * machine at least until it next reboots, though it also
+ * makes some effort to be the same forever, it may change if the
+ * machine is reconfigured or its hardware is modified.
+ * 
+ * @param uuid_str string to append hex-encoded machine uuid to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_get_local_machine_uuid_encoded (DBusString *uuid_str)
+{
+  dbus_bool_t ok;
+  
+  _DBUS_LOCK (machine_uuid);
+  if (machine_uuid_initialized_generation != _dbus_current_generation)
+    {
+      DBusError error = DBUS_ERROR_INIT;
+
+      if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE,
+                                          &error))
+        {          
+#ifndef DBUS_BUILD_TESTS
+          /* For the test suite, we may not be installed so just continue silently
+           * here. But in a production build, we want to be nice and loud about
+           * this.
+           */
+          _dbus_warn_check_failed ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n"
+                                   "See the manual page for dbus-uuidgen to correct this issue.\n",
+                                   error.message);
+#endif
+          
+          dbus_error_free (&error);
+          
+          _dbus_generate_uuid (&machine_uuid);
+        }
+    }
+
+  ok = _dbus_uuid_encode (&machine_uuid, uuid_str);
+
+  _DBUS_UNLOCK (machine_uuid);
+
+  return ok;
+}
+
+#ifndef DBUS_DISABLE_CHECKS
+/** String used in _dbus_return_if_fail macro */
+const char *_dbus_return_if_fail_warning_format =
+"arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
+"This is normally a bug in some application using the D-Bus library.\n";
+#endif
+
+#ifndef DBUS_DISABLE_ASSERT
+/**
+ * Internals of _dbus_assert(); it's a function
+ * rather than a macro with the inline code so
+ * that the assertion failure blocks don't show up
+ * in test suite coverage, and to shrink code size.
+ *
+ * @param condition TRUE if assertion succeeded
+ * @param condition_text condition as a string
+ * @param file file the assertion is in
+ * @param line line the assertion is in
+ * @param func function the assertion is in
+ */
+void
+_dbus_real_assert (dbus_bool_t  condition,
+                   const char  *condition_text,
+                   const char  *file,
+                   int          line,
+                   const char  *func)
+{
+  if (_DBUS_UNLIKELY (!condition))
+    {
+      _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
+                  _dbus_pid_for_log (), condition_text, file, line, func);
+      _dbus_abort ();
+    }
+}
+
+/**
+ * Internals of _dbus_assert_not_reached(); it's a function
+ * rather than a macro with the inline code so
+ * that the assertion failure blocks don't show up
+ * in test suite coverage, and to shrink code size.
+ *
+ * @param explanation what was reached that shouldn't have been
+ * @param file file the assertion is in
+ * @param line line the assertion is in
+ */
+void
+_dbus_real_assert_not_reached (const char *explanation,
+                               const char *file,
+                               int         line)
+{
+  _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
+              file, line, _dbus_pid_for_log (), explanation);
+  _dbus_abort ();
+}
+#endif /* DBUS_DISABLE_ASSERT */
+  
+#ifdef DBUS_BUILD_TESTS
+static dbus_bool_t
+run_failing_each_malloc (int                    n_mallocs,
+                         const char            *description,
+                         DBusTestMemoryFunction func,
+                         void                  *data)
+{
+  n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
+  
+  while (n_mallocs >= 0)
+    {      
+      _dbus_set_fail_alloc_counter (n_mallocs);
+
+      _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
+                     description, n_mallocs,
+                     _dbus_get_fail_alloc_failures ());
+
+      if (!(* func) (data))
+        return FALSE;
+      
+      n_mallocs -= 1;
+    }
+
+  _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
+
+  return TRUE;
+}                        
+
+/**
+ * Tests how well the given function responds to out-of-memory
+ * situations. Calls the function repeatedly, failing a different
+ * call to malloc() each time. If the function ever returns #FALSE,
+ * the test fails. The function should return #TRUE whenever something
+ * valid (such as returning an error, or succeeding) occurs, and #FALSE
+ * if it gets confused in some way.
+ *
+ * @param description description of the test used in verbose output
+ * @param func function to call
+ * @param data data to pass to function
+ * @returns #TRUE if the function never returns FALSE
+ */
+dbus_bool_t
+_dbus_test_oom_handling (const char             *description,
+                         DBusTestMemoryFunction  func,
+                         void                   *data)
+{
+  int approx_mallocs;
+  const char *setting;
+  int max_failures_to_try;
+  int i;
+
+  /* Run once to see about how many mallocs are involved */
+  
+  _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
+
+  _dbus_verbose ("Running once to count mallocs\n");
+  
+  if (!(* func) (data))
+    return FALSE;
+  
+  approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
+
+  _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
+                 description, approx_mallocs);
+
+  setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
+  if (setting != NULL)
+    {
+      DBusString str;
+      long v;
+      _dbus_string_init_const (&str, setting);
+      v = 4;
+      if (!_dbus_string_parse_int (&str, 0, &v, NULL))
+        _dbus_warn ("couldn't parse '%s' as integer\n", setting);
+      max_failures_to_try = v;
+    }
+  else
+    {
+      max_failures_to_try = 4;
+    }
+
+  i = setting ? max_failures_to_try - 1 : 1;
+  while (i < max_failures_to_try)
+    {
+      _dbus_set_fail_alloc_failures (i);
+      if (!run_failing_each_malloc (approx_mallocs, description, func, data))
+        return FALSE;
+      ++i;
+    }
+  
+  _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
+                 description);
+
+  return TRUE;
+}
+#endif /* DBUS_BUILD_TESTS */
+
+/** @} */
diff --git a/dbus/dbus/dbus-internals.h b/dbus/dbus/dbus-internals.h
new file mode 100644
index 0000000..8036a2b
--- /dev/null
+++ b/dbus/dbus/dbus-internals.h
@@ -0,0 +1,379 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-internals.h  random utility stuff (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifdef DBUS_INSIDE_DBUS_H
+#error "You can't include dbus-internals.h in the public header dbus.h"
+#endif
+
+#ifndef DBUS_INTERNALS_H
+#define DBUS_INTERNALS_H
+
+#include <dbus/dbus-memory.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-threads-internal.h>
+
+DBUS_BEGIN_DECLS
+
+#ifndef DBUS_SESSION_BUS_DEFAULT_ADDRESS
+#define DBUS_SESSION_BUS_DEFAULT_ADDRESS	"autolaunch:"
+#endif
+
+void _dbus_warn               (const char *format,
+                               ...) _DBUS_GNUC_PRINTF (1, 2);
+
+void _dbus_warn_check_failed  (const char *format,
+                               ...) _DBUS_GNUC_PRINTF (1, 2);
+
+
+#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#define _DBUS_FUNCTION_NAME __func__
+#elif defined(__GNUC__) || defined(_MSC_VER)
+#define _DBUS_FUNCTION_NAME __FUNCTION__
+#else
+#define _DBUS_FUNCTION_NAME "unknown function"
+#endif
+
+/*
+ * (code from GLib)
+ * 
+ * The _DBUS_LIKELY and _DBUS_UNLIKELY macros let the programmer give hints to 
+ * the compiler about the expected result of an expression. Some compilers
+ * can use this information for optimizations.
+ *
+ * The _DBUS_BOOLEAN_EXPR macro is intended to trigger a gcc warning when
+ * putting assignments in the macro arg
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
+#define _DBUS_BOOLEAN_EXPR(expr)                \
+ __extension__ ({                               \
+   int _dbus_boolean_var_;                      \
+   if (expr)                                    \
+      _dbus_boolean_var_ = 1;                   \
+   else                                         \
+      _dbus_boolean_var_ = 0;                   \
+   _dbus_boolean_var_;                          \
+})
+#define _DBUS_LIKELY(expr) (__builtin_expect (_DBUS_BOOLEAN_EXPR(expr), 1))
+#define _DBUS_UNLIKELY(expr) (__builtin_expect (_DBUS_BOOLEAN_EXPR(expr), 0))
+#else
+#define _DBUS_LIKELY(expr) (expr)
+#define _DBUS_UNLIKELY(expr) (expr)
+#endif
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+
+/*
+ at least gnu cc and msvc compiler are known to 
+ have support for variable macro argument lists
+ add other compilers is required
+*/
+#if defined(__GNUC__) || defined(_MSC_VER) 
+#define DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
+#endif
+
+#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
+void _dbus_verbose_real       (const char *file, const int line, const char *function, 
+                               const char *format,...) _DBUS_GNUC_PRINTF (4, 5);
+#  define _dbus_verbose(fmt,...) _dbus_verbose_real( __FILE__,__LINE__,__FUNCTION__,fmt, ## __VA_ARGS__)
+#else
+void _dbus_verbose_real       (const char *format,
+                               ...) _DBUS_GNUC_PRINTF (1, 2);
+#  define _dbus_verbose _dbus_verbose_real
+#endif
+void _dbus_verbose_reset_real (void);
+dbus_bool_t _dbus_is_verbose_real (void);
+
+#  define _dbus_verbose_reset _dbus_verbose_reset_real
+#  define _dbus_is_verbose _dbus_is_verbose_real
+#else
+#  ifdef HAVE_ISO_VARARGS
+#    define _dbus_verbose(...) do { } while (0)
+#  elif defined (HAVE_GNUC_VARARGS)
+#    define _dbus_verbose(format...) do { } while (0)
+#  else
+static void _dbus_verbose(const char * x,...) {;}
+#  endif
+#  define _dbus_verbose_reset() do { } while (0)
+#  define _dbus_is_verbose() FALSE 
+#endif /* !DBUS_ENABLE_VERBOSE_MODE */
+
+void _dbus_trace_ref (const char *obj_name,
+                      void       *obj,
+                      int         old_refcount,
+                      int         new_refcount,
+                      const char *why,
+                      const char *env_var,
+                      int        *enabled);
+
+const char* _dbus_strerror (int error_number);
+
+#ifdef DBUS_DISABLE_ASSERT
+#define _dbus_assert(condition) do { } while (0)
+#else
+void _dbus_real_assert (dbus_bool_t  condition,
+                        const char  *condition_text,
+                        const char  *file,
+                        int          line,
+                        const char  *func);
+#define _dbus_assert(condition)                                         \
+  _dbus_real_assert ((condition) != 0, #condition, __FILE__, __LINE__, _DBUS_FUNCTION_NAME)
+#endif /* !DBUS_DISABLE_ASSERT */
+
+#ifdef DBUS_DISABLE_ASSERT
+#define _dbus_assert_not_reached(explanation) do { } while (0)
+#else
+void _dbus_real_assert_not_reached (const char *explanation,
+                                    const char *file,
+                                    int         line) _DBUS_GNUC_NORETURN;
+#define _dbus_assert_not_reached(explanation)                                   \
+  _dbus_real_assert_not_reached (explanation, __FILE__, __LINE__)
+#endif /* !DBUS_DISABLE_ASSERT */
+
+#ifdef DBUS_DISABLE_CHECKS
+#define _dbus_return_if_fail(condition)
+#define _dbus_return_val_if_fail(condition, val)
+#else
+
+extern const char *_dbus_return_if_fail_warning_format;
+
+#define _dbus_return_if_fail(condition) do {                                       \
+   _dbus_assert ((*(const char*)_DBUS_FUNCTION_NAME) != '_');                      \
+  if (!(condition)) {                                                              \
+    _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,                  \
+                             _DBUS_FUNCTION_NAME, #condition, __FILE__, __LINE__); \
+    return;                                                                        \
+  } } while (0)
+
+#define _dbus_return_val_if_fail(condition, val) do {                                   \
+   _dbus_assert ((*(const char*)_DBUS_FUNCTION_NAME) != '_');                           \
+  if (!(condition)) {                                                                   \
+    _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,                       \
+                             _DBUS_FUNCTION_NAME, #condition, __FILE__, __LINE__);      \
+    return (val);                                                                       \
+  } } while (0)
+
+#endif /* !DBUS_DISABLE_ASSERT */
+
+#define _DBUS_N_ELEMENTS(array) ((int) (sizeof ((array)) / sizeof ((array)[0])))
+
+#define _DBUS_POINTER_TO_INT(pointer) ((intptr_t)(pointer))
+#define _DBUS_INT_TO_POINTER(integer) ((void*)((intptr_t)(integer)))
+
+#define _DBUS_ZERO(object) (memset (&(object), '\0', sizeof ((object))))
+
+#define _DBUS_STRUCT_OFFSET(struct_type, member)	\
+    ((intptr_t) ((unsigned char*) &((struct_type*) 0)->member))
+
+#ifdef DBUS_DISABLE_CHECKS
+/* this is an assert and not an error, but in the typical --disable-checks case (you're trying
+ * to really minimize code size), disabling these assertions makes sense.
+ */
+#define _DBUS_ASSERT_ERROR_IS_SET(error) do { } while (0)
+#define _DBUS_ASSERT_ERROR_IS_CLEAR(error) do { } while (0)
+#else
+#define _DBUS_ASSERT_ERROR_IS_SET(error)   _dbus_assert ((error) == NULL || dbus_error_is_set ((error)))
+#define _DBUS_ASSERT_ERROR_IS_CLEAR(error) _dbus_assert ((error) == NULL || !dbus_error_is_set ((error)))
+#endif
+
+#define _dbus_return_if_error_is_set(error) _dbus_return_if_fail ((error) == NULL || !dbus_error_is_set ((error)))
+#define _dbus_return_val_if_error_is_set(error, val) _dbus_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), (val))
+
+/* This alignment thing is from ORBit2 */
+/* Align a value upward to a boundary, expressed as a number of bytes.
+ * E.g. align to an 8-byte boundary with argument of 8.
+ */
+
+/*
+ *   (this + boundary - 1)
+ *          &
+ *    ~(boundary - 1)
+ */
+
+#define _DBUS_ALIGN_VALUE(this, boundary) \
+  (( ((uintptr_t)(this)) + (((uintptr_t)(boundary)) -1)) & (~(((uintptr_t)(boundary))-1)))
+
+#define _DBUS_ALIGN_ADDRESS(this, boundary) \
+  ((void*)_DBUS_ALIGN_VALUE(this, boundary))
+
+
+char*       _dbus_strdup                (const char  *str);
+void*       _dbus_memdup                (const void  *mem,
+                                         size_t       n_bytes);
+dbus_bool_t _dbus_string_array_contains (const char **array,
+                                         const char  *str);
+char**      _dbus_dup_string_array      (const char **array);
+
+#define _DBUS_INT16_MIN	 ((dbus_int16_t) 0x8000)
+#define _DBUS_INT16_MAX	 ((dbus_int16_t) 0x7fff)
+#define _DBUS_UINT16_MAX ((dbus_uint16_t)0xffff)
+#define _DBUS_INT32_MIN	 ((dbus_int32_t) 0x80000000)
+#define _DBUS_INT32_MAX	 ((dbus_int32_t) 0x7fffffff)
+#define _DBUS_UINT32_MAX ((dbus_uint32_t)0xffffffff)
+/* using 32-bit here is sort of bogus */
+#define _DBUS_INT_MIN	 _DBUS_INT32_MIN
+#define _DBUS_INT_MAX	 _DBUS_INT32_MAX
+#define _DBUS_UINT_MAX	 _DBUS_UINT32_MAX
+#ifdef DBUS_HAVE_INT64
+#define _DBUS_INT64_MAX	 DBUS_INT64_CONSTANT  (0x7fffffffffffffff)
+#define _DBUS_UINT64_MAX DBUS_UINT64_CONSTANT (0xffffffffffffffff)
+#endif
+#define _DBUS_ONE_KILOBYTE 1024
+#define _DBUS_ONE_MEGABYTE 1024 * _DBUS_ONE_KILOBYTE
+#define _DBUS_ONE_HOUR_IN_MILLISECONDS (1000 * 60 * 60)
+#define _DBUS_USEC_PER_SECOND          (1000000)
+
+#undef	MAX
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
+
+#undef	MIN
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+
+#undef	ABS
+#define ABS(a)	   (((a) < 0) ? -(a) : (a))
+
+#define _DBUS_ISASCII(c) ((c) != '\0' && (((c) & ~0x7f) == 0))
+
+typedef void (* DBusForeachFunction) (void *element,
+                                      void *data);
+
+dbus_bool_t _dbus_set_fd_nonblocking (int             fd,
+                                      DBusError      *error);
+
+void _dbus_verbose_bytes           (const unsigned char *data,
+                                    int                  len,
+                                    int                  offset);
+void _dbus_verbose_bytes_of_string (const DBusString    *str,
+                                    int                  start,
+                                    int                  len);
+
+extern const char *_dbus_no_memory_message;
+#define _DBUS_SET_OOM(error) dbus_set_error_const ((error), DBUS_ERROR_NO_MEMORY, _dbus_no_memory_message)
+
+#ifdef DBUS_BUILD_TESTS
+/* Memory debugging */
+void        _dbus_set_fail_alloc_counter        (int  until_next_fail);
+int         _dbus_get_fail_alloc_counter        (void);
+void        _dbus_set_fail_alloc_failures       (int  failures_per_failure);
+int         _dbus_get_fail_alloc_failures       (void);
+dbus_bool_t _dbus_decrement_fail_alloc_counter  (void);
+dbus_bool_t _dbus_disable_mem_pools             (void);
+int         _dbus_get_malloc_blocks_outstanding (void);
+
+typedef dbus_bool_t (* DBusTestMemoryFunction)  (void *data);
+dbus_bool_t _dbus_test_oom_handling (const char             *description,
+                                     DBusTestMemoryFunction  func,
+                                     void                   *data);
+#else
+#define _dbus_set_fail_alloc_counter(n)
+#define _dbus_get_fail_alloc_counter _DBUS_INT_MAX
+
+/* These are constant expressions so that blocks
+ * they protect should be optimized away
+ */
+#define _dbus_decrement_fail_alloc_counter() (FALSE)
+#define _dbus_disable_mem_pools()            (FALSE)
+#define _dbus_get_malloc_blocks_outstanding  (0)
+#endif /* !DBUS_BUILD_TESTS */
+
+typedef void (* DBusShutdownFunction) (void *data);
+dbus_bool_t _dbus_register_shutdown_func (DBusShutdownFunction  function,
+                                          void                 *data);
+
+extern int _dbus_current_generation;
+
+/* Thread initializers */
+#define _DBUS_LOCK_NAME(name)           _dbus_lock_##name
+#define _DBUS_DECLARE_GLOBAL_LOCK(name) extern DBusRMutex *_dbus_lock_##name
+#define _DBUS_DEFINE_GLOBAL_LOCK(name)  DBusRMutex        *_dbus_lock_##name
+#define _DBUS_LOCK(name)                _dbus_rmutex_lock   (_dbus_lock_##name)
+#define _DBUS_UNLOCK(name)              _dbus_rmutex_unlock (_dbus_lock_##name)
+
+/* 1-5 */
+_DBUS_DECLARE_GLOBAL_LOCK (list);
+_DBUS_DECLARE_GLOBAL_LOCK (connection_slots);
+_DBUS_DECLARE_GLOBAL_LOCK (pending_call_slots);
+_DBUS_DECLARE_GLOBAL_LOCK (server_slots);
+_DBUS_DECLARE_GLOBAL_LOCK (message_slots);
+/* 5-10 */
+_DBUS_DECLARE_GLOBAL_LOCK (bus);
+_DBUS_DECLARE_GLOBAL_LOCK (bus_datas);
+_DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
+_DBUS_DECLARE_GLOBAL_LOCK (system_users);
+_DBUS_DECLARE_GLOBAL_LOCK (message_cache);
+/* 10-14 */
+_DBUS_DECLARE_GLOBAL_LOCK (shared_connections);
+_DBUS_DECLARE_GLOBAL_LOCK (win_fds);
+_DBUS_DECLARE_GLOBAL_LOCK (sid_atom_cache);
+_DBUS_DECLARE_GLOBAL_LOCK (machine_uuid);
+
+#if !DBUS_USE_SYNC
+_DBUS_DECLARE_GLOBAL_LOCK (atomic);
+#define _DBUS_N_GLOBAL_LOCKS (15)
+#else
+#define _DBUS_N_GLOBAL_LOCKS (14)
+#endif
+
+dbus_bool_t _dbus_threads_init_debug (void);
+
+dbus_bool_t   _dbus_address_append_escaped (DBusString       *escaped,
+                                            const DBusString *unescaped);
+
+void          _dbus_set_bad_address        (DBusError         *error,
+                                            const char        *address_problem_type,
+                                            const char        *address_problem_field,
+                                            const char        *address_problem_other);
+
+#define DBUS_UUID_LENGTH_BYTES 16
+#define DBUS_UUID_LENGTH_WORDS (DBUS_UUID_LENGTH_BYTES / 4)
+#define DBUS_UUID_LENGTH_HEX   (DBUS_UUID_LENGTH_BYTES * 2)
+
+/**
+ * A globally unique ID ; we have one for each DBusServer, and also one for each
+ * machine with libdbus installed on it.
+ */
+union DBusGUID
+{
+  dbus_uint32_t as_uint32s[DBUS_UUID_LENGTH_WORDS];     /**< guid as four uint32 values */
+  char as_bytes[DBUS_UUID_LENGTH_BYTES];                /**< guid as 16 single-byte values */
+};
+
+void        _dbus_generate_uuid  (DBusGUID         *uuid);
+dbus_bool_t _dbus_uuid_encode    (const DBusGUID   *uuid,
+                                  DBusString       *encoded);
+dbus_bool_t _dbus_read_uuid_file (const DBusString *filename,
+                                  DBusGUID         *uuid,
+                                  dbus_bool_t       create_if_not_found,
+                                  DBusError        *error);
+
+dbus_bool_t _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str);
+
+#define _DBUS_PASTE2(a, b) a ## b
+#define _DBUS_PASTE(a, b) _DBUS_PASTE2 (a, b)
+#define _DBUS_STATIC_ASSERT(expr) \
+  typedef struct { char _assertion[(expr) ? 1 : -1]; } \
+  _DBUS_PASTE (_DBUS_STATIC_ASSERT_, __LINE__)
+
+DBUS_END_DECLS
+
+#endif /* DBUS_INTERNALS_H */
diff --git a/dbus/dbus/dbus-keyring.c b/dbus/dbus/dbus-keyring.c
new file mode 100644
index 0000000..3b9ce31
--- /dev/null
+++ b/dbus/dbus/dbus-keyring.c
@@ -0,0 +1,1160 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-keyring.c Store secret cookies in your homedir
+ *
+ * Copyright (C) 2003, 2004  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-keyring.h"
+#include "dbus-protocol.h"
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-sysdeps.h>
+
+/**
+ * @defgroup DBusKeyring keyring class
+ * @ingroup  DBusInternals
+ * @brief DBusKeyring data structure
+ *
+ * Types and functions related to DBusKeyring. DBusKeyring is intended
+ * to manage cookies used to authenticate clients to servers.  This is
+ * essentially the "verify that client can read the user's homedir"
+ * authentication mechanism.  Both client and server must have access
+ * to the homedir.
+ *
+ * The secret keys are not kept in locked memory, and are written to a
+ * file in the user's homedir. However they are transient (only used
+ * by a single server instance for a fixed period of time, then
+ * discarded). Also, the keys are not sent over the wire.
+ *
+ * @todo there's a memory leak on some codepath in here, I saw it once
+ * when running make check - probably some specific initial cookies
+ * present in the cookie file, then depending on what we do with them.
+ */
+
+/**
+ * @defgroup DBusKeyringInternals DBusKeyring implementation details
+ * @ingroup  DBusInternals
+ * @brief DBusKeyring implementation details
+ *
+ * The guts of DBusKeyring.
+ *
+ * @{
+ */
+
+/** The maximum age of a key before we create a new key to use in
+ * challenges.  This isn't super-reliably enforced, since system
+ * clocks can change or be wrong, but we make a best effort to only
+ * use keys for a short time.
+ */
+#define NEW_KEY_TIMEOUT_SECONDS     (60*5)
+/**
+ * The time after which we drop a key from the secrets file.
+ * The EXPIRE_KEYS_TIMEOUT_SECONDS - NEW_KEY_TIMEOUT_SECONDS is the minimum
+ * time window a client has to complete authentication.
+ */
+#define EXPIRE_KEYS_TIMEOUT_SECONDS (NEW_KEY_TIMEOUT_SECONDS + (60*2))
+/**
+ * The maximum amount of time a key can be in the future.
+ */
+#define MAX_TIME_TRAVEL_SECONDS (60*5)
+
+/**
+ * Maximum number of keys in the keyring before
+ * we just ignore the rest
+ */
+#ifdef DBUS_BUILD_TESTS
+#define MAX_KEYS_IN_FILE 10
+#else
+#define MAX_KEYS_IN_FILE 256
+#endif
+
+/**
+ * A single key from the cookie file
+ */
+typedef struct
+{
+  dbus_int32_t id; /**< identifier used to refer to the key */
+
+  long creation_time; /**< when the key was generated,
+                       *   as unix timestamp. signed long
+                       *   matches struct timeval.
+                       */
+  
+  DBusString secret; /**< the actual key */
+
+} DBusKey;
+
+/**
+ * @brief Internals of DBusKeyring.
+ * 
+ * DBusKeyring internals. DBusKeyring is an opaque object, it must be
+ * used via accessor functions.
+ */
+struct DBusKeyring
+{
+  int refcount;             /**< Reference count */
+  DBusString directory;     /**< Directory the below two items are inside */
+  DBusString filename;      /**< Keyring filename */
+  DBusString filename_lock; /**< Name of lockfile */
+  DBusKey *keys; /**< Keys loaded from the file */
+  int n_keys;    /**< Number of keys */
+  DBusCredentials *credentials; /**< Credentials containing user the keyring is for */
+};
+
+static DBusKeyring*
+_dbus_keyring_new (void)
+{
+  DBusKeyring *keyring;
+
+  keyring = dbus_new0 (DBusKeyring, 1);
+  if (keyring == NULL)
+    goto out_0;
+  
+  if (!_dbus_string_init (&keyring->directory))
+    goto out_1;
+
+  if (!_dbus_string_init (&keyring->filename))
+    goto out_2;
+
+  if (!_dbus_string_init (&keyring->filename_lock))
+    goto out_3;
+  
+  keyring->refcount = 1;
+  keyring->keys = NULL;
+  keyring->n_keys = 0;
+
+  return keyring;
+
+ out_3:
+  _dbus_string_free (&keyring->filename);
+ out_2:
+  _dbus_string_free (&keyring->directory);
+ out_1:
+  dbus_free (keyring);
+ out_0:
+  return NULL;
+}
+
+static void
+free_keys (DBusKey *keys,
+           int      n_keys)
+{
+  int i;
+
+  /* should be safe for args NULL, 0 */
+  
+  i = 0;
+  while (i < n_keys)
+    {
+      _dbus_string_free (&keys[i].secret);
+      ++i;
+    }
+
+  dbus_free (keys);
+}
+
+/* Our locking scheme is highly unreliable.  However, there is
+ * unfortunately no reliable locking scheme in user home directories;
+ * between bugs in Linux NFS, people using Tru64 or other total crap
+ * NFS, AFS, random-file-system-of-the-week, and so forth, fcntl() in
+ * homedirs simply generates tons of bug reports. This has been
+ * learned through hard experience with GConf, unfortunately.
+ *
+ * This bad hack might work better for the kind of lock we have here,
+ * which we don't expect to hold for any length of time.  Crashing
+ * while we hold it should be unlikely, and timing out such that we
+ * delete a stale lock should also be unlikely except when the
+ * filesystem is running really slowly.  Stuff might break in corner
+ * cases but as long as it's not a security-level breakage it should
+ * be OK.
+ */
+
+/** Maximum number of timeouts waiting for lock before we decide it's stale */
+#define MAX_LOCK_TIMEOUTS 32
+/** Length of each timeout while waiting for a lock */
+#define LOCK_TIMEOUT_MILLISECONDS 250
+
+static dbus_bool_t
+_dbus_keyring_lock (DBusKeyring *keyring)
+{
+  int n_timeouts;
+  
+  n_timeouts = 0;
+  while (n_timeouts < MAX_LOCK_TIMEOUTS)
+    {
+      DBusError error = DBUS_ERROR_INIT;
+
+      if (_dbus_create_file_exclusively (&keyring->filename_lock,
+                                         &error))
+        break;
+
+      _dbus_verbose ("Did not get lock file, sleeping %d milliseconds (%s)\n",
+                     LOCK_TIMEOUT_MILLISECONDS, error.message);
+      dbus_error_free (&error);
+
+      _dbus_sleep_milliseconds (LOCK_TIMEOUT_MILLISECONDS);
+      
+      ++n_timeouts;
+    }
+
+  if (n_timeouts == MAX_LOCK_TIMEOUTS)
+    {
+      DBusError error = DBUS_ERROR_INIT;
+
+      _dbus_verbose ("Lock file timed out %d times, assuming stale\n",
+                     n_timeouts);
+
+      if (!_dbus_delete_file (&keyring->filename_lock, &error))
+        {
+          _dbus_verbose ("Couldn't delete old lock file: %s\n",
+                         error.message);
+          dbus_error_free (&error);
+          return FALSE;
+        }
+
+      if (!_dbus_create_file_exclusively (&keyring->filename_lock,
+                                          &error))
+        {
+          _dbus_verbose ("Couldn't create lock file after deleting stale one: %s\n",
+                         error.message);
+          dbus_error_free (&error);
+          return FALSE;
+        }
+    }
+  
+  return TRUE;
+}
+
+static void
+_dbus_keyring_unlock (DBusKeyring *keyring)
+{
+  DBusError error = DBUS_ERROR_INIT;
+
+  if (!_dbus_delete_file (&keyring->filename_lock, &error))
+    {
+      _dbus_warn ("Failed to delete lock file: %s\n",
+                  error.message);
+      dbus_error_free (&error);
+    }
+}
+
+static DBusKey*
+find_key_by_id (DBusKey *keys,
+                int      n_keys,
+                int      id)
+{
+  int i;
+
+  i = 0;
+  while (i < n_keys)
+    {
+      if (keys[i].id == id)
+        return &keys[i];
+      
+      ++i;
+    }
+
+  return NULL;
+}
+
+static dbus_bool_t
+add_new_key (DBusKey  **keys_p,
+             int       *n_keys_p,
+             DBusError *error)
+{
+  DBusKey *new;
+  DBusString bytes;
+  int id;
+  long timestamp;
+  const unsigned char *s;
+  dbus_bool_t retval;
+  DBusKey *keys;
+  int n_keys;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  if (!_dbus_string_init (&bytes))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+
+  keys = *keys_p;
+  n_keys = *n_keys_p;
+  retval = FALSE;
+      
+  /* Generate an integer ID and then the actual key. */
+ retry:
+      
+  if (!_dbus_generate_random_bytes (&bytes, 4))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto out;
+    }
+
+  s = (const unsigned char*) _dbus_string_get_const_data (&bytes);
+      
+  id = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24);
+  if (id < 0)
+    id = - id;
+  _dbus_assert (id >= 0);
+
+  if (find_key_by_id (keys, n_keys, id) != NULL)
+    {
+      _dbus_string_set_length (&bytes, 0);
+      _dbus_verbose ("Key ID %d already existed, trying another one\n",
+                     id);
+      goto retry;
+    }
+
+  _dbus_verbose ("Creating key with ID %d\n", id);
+      
+#define KEY_LENGTH_BYTES 24
+  _dbus_string_set_length (&bytes, 0);
+  if (!_dbus_generate_random_bytes (&bytes, KEY_LENGTH_BYTES))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto out;
+    }
+
+  new = dbus_realloc (keys, sizeof (DBusKey) * (n_keys + 1));
+  if (new == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto out;
+    }
+
+  keys = new;
+  *keys_p = keys; /* otherwise *keys_p ends up invalid */
+  n_keys += 1;
+
+  if (!_dbus_string_init (&keys[n_keys-1].secret))
+    {
+      n_keys -= 1; /* we don't want to free the one we didn't init */
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto out;
+    }
+
+  _dbus_get_real_time (&timestamp, NULL);
+      
+  keys[n_keys-1].id = id;
+  keys[n_keys-1].creation_time = timestamp;
+  if (!_dbus_string_move (&bytes, 0,
+                          &keys[n_keys-1].secret,
+                          0))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&keys[n_keys-1].secret);
+      n_keys -= 1;
+      goto out;
+    }
+  
+  retval = TRUE;
+  
+ out:
+  *n_keys_p = n_keys;
+  
+  _dbus_string_free (&bytes);
+  return retval;
+}
+
+/**
+ * Reloads the keyring file, optionally adds one new key to the file,
+ * removes all expired keys from the file iff a key was added, then
+ * resaves the file.  Stores the keys from the file in keyring->keys.
+ * Note that the file is only resaved (written to) if a key is added,
+ * this means that only servers ever write to the file and need to
+ * lock it, which avoids a lot of lock contention at login time and
+ * such.
+ *
+ * @param keyring the keyring
+ * @param add_new #TRUE to add a new key to the file, expire keys, and resave
+ * @param error return location for errors
+ * @returns #FALSE on failure
+ */
+static dbus_bool_t
+_dbus_keyring_reload (DBusKeyring *keyring,
+                      dbus_bool_t  add_new,
+                      DBusError   *error)
+{
+  DBusString contents;
+  DBusString line;
+  dbus_bool_t retval;
+  dbus_bool_t have_lock;
+  DBusKey *keys;
+  int n_keys;
+  int i;
+  long now;
+  DBusError tmp_error;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  if (!_dbus_check_dir_is_private_to_user (&keyring->directory, error))
+    return FALSE;
+    
+  if (!_dbus_string_init (&contents))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&line))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&contents);
+      return FALSE;
+    }
+   
+  keys = NULL;
+  n_keys = 0;
+  retval = FALSE;
+  have_lock = FALSE;
+
+  _dbus_get_real_time (&now, NULL);
+  
+  if (add_new)
+    {
+      if (!_dbus_keyring_lock (keyring))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Could not lock keyring file to add to it");
+          goto out;
+        }
+
+      have_lock = TRUE;
+    }
+
+  dbus_error_init (&tmp_error);
+  if (!_dbus_file_get_contents (&contents, 
+                                &keyring->filename,
+                                &tmp_error))
+    {
+      _dbus_verbose ("Failed to load keyring file: %s\n",
+                     tmp_error.message);
+      /* continue with empty keyring file, so we recreate it */
+      dbus_error_free (&tmp_error);
+    }
+
+  if (!_dbus_string_validate_ascii (&contents, 0,
+                                    _dbus_string_get_length (&contents)))
+    {
+      _dbus_warn ("Secret keyring file contains non-ASCII! Ignoring existing contents\n");
+      _dbus_string_set_length (&contents, 0);
+    }
+
+  /* FIXME this is badly inefficient for large keyring files
+   * (not that large keyring files exist outside of test suites)
+   */
+  while (_dbus_string_pop_line (&contents, &line))
+    {
+      int next;
+      long val;
+      int id;
+      long timestamp;
+      int len;
+      int end;
+      DBusKey *new;
+
+      /* Don't load more than the max. */
+      if (n_keys >= (add_new ? MAX_KEYS_IN_FILE - 1 : MAX_KEYS_IN_FILE))
+        break;
+      
+      next = 0;
+      if (!_dbus_string_parse_int (&line, 0, &val, &next))
+        {
+          _dbus_verbose ("could not parse secret key ID at start of line\n");
+          continue;
+        }
+
+      if (val > _DBUS_INT32_MAX || val < 0)
+        {
+          _dbus_verbose ("invalid secret key ID at start of line\n");
+          continue;
+        }
+      
+      id = val;
+
+      _dbus_string_skip_blank (&line, next, &next);
+      
+      if (!_dbus_string_parse_int (&line, next, &timestamp, &next))
+        {
+          _dbus_verbose ("could not parse secret key timestamp\n");
+          continue;
+        }
+
+      if (timestamp < 0 ||
+          (now + MAX_TIME_TRAVEL_SECONDS) < timestamp ||
+          (now - EXPIRE_KEYS_TIMEOUT_SECONDS) > timestamp)
+        {
+          _dbus_verbose ("dropping/ignoring %ld-seconds old key with timestamp %ld as current time is %ld\n",
+                         now - timestamp, timestamp, now);
+          continue;
+        }
+      
+      _dbus_string_skip_blank (&line, next, &next);
+
+      len = _dbus_string_get_length (&line);
+
+      if ((len - next) == 0)
+        {
+          _dbus_verbose ("no secret key after ID and timestamp\n");
+          continue;
+        }
+      
+      /* We have all three parts */
+      new = dbus_realloc (keys, sizeof (DBusKey) * (n_keys + 1));
+      if (new == NULL)
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          goto out;
+        }
+
+      keys = new;
+      n_keys += 1;
+
+      if (!_dbus_string_init (&keys[n_keys-1].secret))
+        {
+          n_keys -= 1; /* we don't want to free the one we didn't init */
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          goto out;
+        }
+      
+      keys[n_keys-1].id = id;
+      keys[n_keys-1].creation_time = timestamp;
+      if (!_dbus_string_hex_decode (&line, next, &end,
+                                    &keys[n_keys-1].secret, 0))
+	{
+	  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+	  goto out;
+	}
+
+      if (_dbus_string_get_length (&line) != end)
+	{
+	  _dbus_verbose ("invalid hex encoding in keyring file\n");
+	  _dbus_string_free (&keys[n_keys - 1].secret);
+	  n_keys -= 1;
+	  continue;
+	}
+    }
+
+  _dbus_verbose ("Successfully loaded %d existing keys\n",
+                 n_keys);
+
+  if (add_new)
+    {
+      if (!add_new_key (&keys, &n_keys, error))
+        {
+          _dbus_verbose ("Failed to generate new key: %s\n",
+                         error ? error->message : "(unknown)");
+          goto out;
+        }
+
+      _dbus_string_set_length (&contents, 0);
+
+      i = 0;
+      while (i < n_keys)
+        {
+          if (!_dbus_string_append_int (&contents,
+                                        keys[i].id))
+            goto nomem;
+
+          if (!_dbus_string_append_byte (&contents, ' '))
+            goto nomem;
+
+          if (!_dbus_string_append_int (&contents,
+                                        keys[i].creation_time))
+            goto nomem;
+
+          if (!_dbus_string_append_byte (&contents, ' '))
+            goto nomem;
+
+          if (!_dbus_string_hex_encode (&keys[i].secret, 0,
+                                        &contents,
+                                        _dbus_string_get_length (&contents)))
+            goto nomem;
+
+          if (!_dbus_string_append_byte (&contents, '\n'))
+            goto nomem;          
+          
+          ++i;
+          continue;
+
+        nomem:
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          goto out;
+        }
+      
+      if (!_dbus_string_save_to_file (&contents, &keyring->filename,
+                                      FALSE, error))
+        goto out;
+    }
+
+  if (keyring->keys)
+    free_keys (keyring->keys, keyring->n_keys);
+  keyring->keys = keys;
+  keyring->n_keys = n_keys;
+  keys = NULL;
+  n_keys = 0;
+  
+  retval = TRUE;  
+  
+ out:
+  if (have_lock)
+    _dbus_keyring_unlock (keyring);
+  
+  if (! ((retval == TRUE && (error == NULL || error->name == NULL)) ||
+         (retval == FALSE && (error == NULL || error->name != NULL))))
+    {
+      if (error && error->name)
+        _dbus_verbose ("error is %s: %s\n", error->name, error->message);
+      _dbus_warn ("returning %d but error pointer %p name %s\n",
+                  retval, error, error->name ? error->name : "(none)");
+      _dbus_assert_not_reached ("didn't handle errors properly");
+    }
+  
+  if (keys != NULL)
+    {
+      i = 0;
+      while (i < n_keys)
+        {
+          _dbus_string_zero (&keys[i].secret);
+          _dbus_string_free (&keys[i].secret);
+          ++i;
+        }
+
+      dbus_free (keys);
+    }
+  
+  _dbus_string_free (&contents);
+  _dbus_string_free (&line);
+
+  return retval;
+}
+
+/** @} */ /* end of internals */
+
+/**
+ * @addtogroup DBusKeyring
+ *
+ * @{
+ */
+
+/**
+ * Increments reference count of the keyring
+ *
+ * @param keyring the keyring
+ * @returns the keyring
+ */
+DBusKeyring *
+_dbus_keyring_ref (DBusKeyring *keyring)
+{
+  keyring->refcount += 1;
+
+  return keyring;
+}
+
+/**
+ * Decrements refcount and finalizes if it reaches
+ * zero.
+ *
+ * @param keyring the keyring
+ */
+void
+_dbus_keyring_unref (DBusKeyring *keyring)
+{
+  keyring->refcount -= 1;
+
+  if (keyring->refcount == 0)
+    {
+      if (keyring->credentials)
+        _dbus_credentials_unref (keyring->credentials);
+
+      _dbus_string_free (&keyring->filename);
+      _dbus_string_free (&keyring->filename_lock);
+      _dbus_string_free (&keyring->directory);
+      free_keys (keyring->keys, keyring->n_keys);
+      dbus_free (keyring);      
+    }
+}
+
+/**
+ * Creates a new keyring that lives in the ~/.dbus-keyrings directory
+ * of the given user credentials. If the credentials are #NULL or
+ * empty, uses those of the current process.
+ *
+ * @param username username to get keyring for, or #NULL
+ * @param context which keyring to get
+ * @param error return location for errors
+ * @returns the keyring or #NULL on error
+ */
+DBusKeyring*
+_dbus_keyring_new_for_credentials (DBusCredentials  *credentials,
+                                   const DBusString *context,
+                                   DBusError        *error)
+{
+  DBusString ringdir;
+  DBusKeyring *keyring;
+  dbus_bool_t error_set;
+  DBusError tmp_error;
+  DBusCredentials *our_credentials;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (_dbus_check_setuid ())
+    {
+      dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
+                            "Unable to create DBus keyring when setuid");
+      return NULL;
+    }
+  
+  keyring = NULL;
+  error_set = FALSE;
+  our_credentials = NULL;
+  
+  if (!_dbus_string_init (&ringdir))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  if (credentials != NULL)
+    {
+      our_credentials = _dbus_credentials_copy (credentials);
+    }
+  else
+    {
+      our_credentials = _dbus_credentials_new_from_current_process ();
+    }
+  
+  if (our_credentials == NULL)
+    goto failed;
+
+  if (_dbus_credentials_are_anonymous (our_credentials))
+    {
+      if (!_dbus_credentials_add_from_current_process (our_credentials))
+        goto failed;
+    }
+  
+  if (!_dbus_append_keyring_directory_for_credentials (&ringdir,
+                                                       our_credentials))
+    goto failed;
+  
+  keyring = _dbus_keyring_new ();
+  if (keyring == NULL)
+    goto failed;
+
+  _dbus_assert (keyring->credentials == NULL);
+  keyring->credentials = our_credentials;
+  our_credentials = NULL; /* so we don't unref it again later */
+  
+  /* should have been validated already, but paranoia check here */
+  if (!_dbus_keyring_validate_context (context))
+    {
+      error_set = TRUE;
+      dbus_set_error_const (error,
+                            DBUS_ERROR_FAILED,
+                            "Invalid context in keyring creation");
+      goto failed;
+    }
+
+  /* Save keyring dir in the keyring object */
+  if (!_dbus_string_copy (&ringdir, 0,
+                          &keyring->directory, 0))
+    goto failed;  
+
+  /* Create keyring->filename based on keyring dir and context */
+  if (!_dbus_string_copy (&keyring->directory, 0,
+                          &keyring->filename, 0))
+    goto failed;
+
+  if (!_dbus_concat_dir_and_file (&keyring->filename,
+                                  context))
+    goto failed;
+
+  /* Create lockfile name */
+  if (!_dbus_string_copy (&keyring->filename, 0,
+                          &keyring->filename_lock, 0))
+    goto failed;
+
+  if (!_dbus_string_append (&keyring->filename_lock, ".lock"))
+    goto failed;
+
+  /* Reload keyring */
+  dbus_error_init (&tmp_error);
+  if (!_dbus_keyring_reload (keyring, FALSE, &tmp_error))
+    {
+      _dbus_verbose ("didn't load an existing keyring: %s\n",
+                     tmp_error.message);
+      dbus_error_free (&tmp_error);
+    }
+  
+  /* We don't fail fatally if we can't create the directory,
+   * but the keyring will probably always be empty
+   * unless someone else manages to create it
+   */
+  dbus_error_init (&tmp_error);
+  if (!_dbus_create_directory (&keyring->directory,
+                               &tmp_error))
+    {
+      _dbus_verbose ("Creating keyring directory: %s\n",
+                     tmp_error.message);
+      dbus_error_free (&tmp_error);
+    }
+
+  _dbus_string_free (&ringdir);
+  
+  return keyring;
+  
+ failed:
+  if (!error_set)
+    dbus_set_error_const (error,
+                          DBUS_ERROR_NO_MEMORY,
+                          NULL);
+  if (our_credentials)
+    _dbus_credentials_unref (our_credentials);
+  if (keyring)
+    _dbus_keyring_unref (keyring);
+  _dbus_string_free (&ringdir);
+  return NULL;
+
+}
+
+/**
+ * Checks whether the context is a valid context.
+ * Contexts that might cause confusion when used
+ * in filenames are not allowed (contexts can't
+ * start with a dot or contain dir separators).
+ *
+ * @todo this is the most inefficient implementation
+ * imaginable.
+ *
+ * @param context the context
+ * @returns #TRUE if valid
+ */
+dbus_bool_t
+_dbus_keyring_validate_context (const DBusString *context)
+{
+  if (_dbus_string_get_length (context) == 0)
+    {
+      _dbus_verbose ("context is zero-length\n");
+      return FALSE;
+    }
+
+  if (!_dbus_string_validate_ascii (context, 0,
+                                    _dbus_string_get_length (context)))
+    {
+      _dbus_verbose ("context not valid ascii\n");
+      return FALSE;
+    }
+  
+  /* no directory separators */  
+  if (_dbus_string_find (context, 0, "/", NULL))
+    {
+      _dbus_verbose ("context contains a slash\n");
+      return FALSE;
+    }
+
+  if (_dbus_string_find (context, 0, "\\", NULL))
+    {
+      _dbus_verbose ("context contains a backslash\n");
+      return FALSE;
+    }
+
+  /* prevent attempts to use dotfiles or ".." or ".lock"
+   * all of which might allow some kind of attack
+   */
+  if (_dbus_string_find (context, 0, ".", NULL))
+    {
+      _dbus_verbose ("context contains a dot\n");
+      return FALSE;
+    }
+
+  /* no spaces/tabs, those are used for separators in the protocol */
+  if (_dbus_string_find_blank (context, 0, NULL))
+    {
+      _dbus_verbose ("context contains a blank\n");
+      return FALSE;
+    }
+
+  if (_dbus_string_find (context, 0, "\n", NULL))
+    {
+      _dbus_verbose ("context contains a newline\n");
+      return FALSE;
+    }
+
+  if (_dbus_string_find (context, 0, "\r", NULL))
+    {
+      _dbus_verbose ("context contains a carriage return\n");
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+static DBusKey*
+find_recent_key (DBusKeyring *keyring)
+{
+  int i;
+  long tv_sec, tv_usec;
+
+  _dbus_get_real_time (&tv_sec, &tv_usec);
+  
+  i = 0;
+  while (i < keyring->n_keys)
+    {
+      DBusKey *key = &keyring->keys[i];
+
+      _dbus_verbose ("Key %d is %ld seconds old\n",
+                     i, tv_sec - key->creation_time);
+      
+      if ((tv_sec - NEW_KEY_TIMEOUT_SECONDS) < key->creation_time)
+        return key;
+      
+      ++i;
+    }
+
+  return NULL;
+}
+
+/**
+ * Gets a recent key to use for authentication.
+ * If no recent key exists, creates one. Returns
+ * the key ID. If a key can't be written to the keyring
+ * file so no recent key can be created, returns -1.
+ * All valid keys are > 0.
+ *
+ * @param keyring the keyring
+ * @param error error on failure
+ * @returns key ID to use for auth, or -1 on failure
+ */
+int
+_dbus_keyring_get_best_key (DBusKeyring  *keyring,
+                            DBusError    *error)
+{
+  DBusKey *key;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  key = find_recent_key (keyring);
+  if (key)
+    return key->id;
+
+  /* All our keys are too old, or we've never loaded the
+   * keyring. Create a new one.
+   */
+  if (!_dbus_keyring_reload (keyring, TRUE,
+                             error))
+    return -1;
+
+  key = find_recent_key (keyring);
+  if (key)
+    return key->id;
+  else
+    {
+      dbus_set_error_const (error,
+                            DBUS_ERROR_FAILED,
+                            "No recent-enough key found in keyring, and unable to create a new key");
+      return -1;
+    }
+}
+
+/**
+ * Checks whether the keyring is for the same user as the given credentials.
+ *
+ * @param keyring the keyring
+ * @param credentials the credentials to check
+ *
+ * @returns #TRUE if the keyring belongs to the given user
+ */
+dbus_bool_t
+_dbus_keyring_is_for_credentials (DBusKeyring           *keyring,
+                                  DBusCredentials       *credentials)
+{
+  return _dbus_credentials_same_user (keyring->credentials,
+                                      credentials);
+}
+
+/**
+ * Gets the hex-encoded secret key for the given ID.
+ * Returns #FALSE if not enough memory. Returns #TRUE
+ * but empty key on any other error such as unknown
+ * key ID.
+ *
+ * @param keyring the keyring
+ * @param key_id the key ID
+ * @param hex_key string to append hex-encoded key to
+ * @returns #TRUE if we had enough memory
+ */
+dbus_bool_t
+_dbus_keyring_get_hex_key (DBusKeyring       *keyring,
+                           int                key_id,
+                           DBusString        *hex_key)
+{
+  DBusKey *key;
+
+  key = find_key_by_id (keyring->keys,
+                        keyring->n_keys,
+                        key_id);
+  if (key == NULL)
+    return TRUE; /* had enough memory, so TRUE */
+
+  return _dbus_string_hex_encode (&key->secret, 0,
+                                  hex_key,
+                                  _dbus_string_get_length (hex_key));
+}
+
+/** @} */ /* end of exposed API */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+
+dbus_bool_t
+_dbus_keyring_test (void)
+{
+  DBusString context;
+  DBusKeyring *ring1;
+  DBusKeyring *ring2;
+  int id;
+  DBusError error;
+  int i;
+
+  ring1 = NULL;
+  ring2 = NULL;
+  
+  /* Context validation */
+  
+  _dbus_string_init_const (&context, "foo");
+  _dbus_assert (_dbus_keyring_validate_context (&context));
+  _dbus_string_init_const (&context, "org_freedesktop_blah");
+  _dbus_assert (_dbus_keyring_validate_context (&context));
+  
+  _dbus_string_init_const (&context, "");
+  _dbus_assert (!_dbus_keyring_validate_context (&context));
+  _dbus_string_init_const (&context, ".foo");
+  _dbus_assert (!_dbus_keyring_validate_context (&context));
+  _dbus_string_init_const (&context, "bar.foo");
+  _dbus_assert (!_dbus_keyring_validate_context (&context));
+  _dbus_string_init_const (&context, "bar/foo");
+  _dbus_assert (!_dbus_keyring_validate_context (&context));
+  _dbus_string_init_const (&context, "bar\\foo");
+  _dbus_assert (!_dbus_keyring_validate_context (&context));
+  _dbus_string_init_const (&context, "foo\xfa\xf0");
+  _dbus_assert (!_dbus_keyring_validate_context (&context));
+  _dbus_string_init_const (&context, "foo\x80");
+  _dbus_assert (!_dbus_keyring_validate_context (&context));
+  _dbus_string_init_const (&context, "foo\x7f");
+  _dbus_assert (_dbus_keyring_validate_context (&context));
+  _dbus_string_init_const (&context, "foo bar");
+  _dbus_assert (!_dbus_keyring_validate_context (&context));
+  
+  if (!_dbus_string_init (&context))
+    _dbus_assert_not_reached ("no memory");
+  if (!_dbus_string_append_byte (&context, '\0'))
+    _dbus_assert_not_reached ("no memory");
+  _dbus_assert (!_dbus_keyring_validate_context (&context));
+  _dbus_string_free (&context);
+
+  /* Now verify that if we create a key in keyring 1,
+   * it is properly loaded in keyring 2
+   */
+
+  _dbus_string_init_const (&context, "org_freedesktop_dbus_testsuite");
+  dbus_error_init (&error);
+  ring1 = _dbus_keyring_new_for_credentials (NULL, &context,
+                                             &error);
+  _dbus_assert (ring1 != NULL);
+  _dbus_assert (error.name == NULL);
+
+  id = _dbus_keyring_get_best_key (ring1, &error);
+  if (id < 0)
+    {
+      fprintf (stderr, "Could not load keyring: %s\n", error.message);
+      dbus_error_free (&error);
+      goto failure;
+    }
+
+  ring2 = _dbus_keyring_new_for_credentials (NULL, &context, &error);
+  _dbus_assert (ring2 != NULL);
+  _dbus_assert (error.name == NULL);
+  
+  if (ring1->n_keys != ring2->n_keys)
+    {
+      fprintf (stderr, "Different number of keys in keyrings\n");
+      goto failure;
+    }
+
+  /* We guarantee we load and save keeping keys in a fixed
+   * order
+   */
+  i = 0;
+  while (i < ring1->n_keys)
+    {
+      if (ring1->keys[i].id != ring2->keys[i].id)
+        {
+          fprintf (stderr, "Keyring 1 has first key ID %d and keyring 2 has %d\n",
+                   ring1->keys[i].id, ring2->keys[i].id);
+          goto failure;
+        }      
+
+      if (ring1->keys[i].creation_time != ring2->keys[i].creation_time)
+        {
+          fprintf (stderr, "Keyring 1 has first key time %ld and keyring 2 has %ld\n",
+                   ring1->keys[i].creation_time, ring2->keys[i].creation_time);
+          goto failure;
+        }
+
+      if (!_dbus_string_equal (&ring1->keys[i].secret,
+                               &ring2->keys[i].secret))
+        {
+          fprintf (stderr, "Keyrings 1 and 2 have different secrets for same ID/timestamp\n");
+          goto failure;
+        }
+      
+      ++i;
+    }
+
+  printf (" %d keys in test\n", ring1->n_keys);
+
+  /* Test ref/unref */
+  _dbus_keyring_ref (ring1);
+  _dbus_keyring_ref (ring2);
+  _dbus_keyring_unref (ring1);
+  _dbus_keyring_unref (ring2);
+
+
+  /* really unref */
+  _dbus_keyring_unref (ring1);
+  _dbus_keyring_unref (ring2);
+  
+  return TRUE;
+
+ failure:
+  if (ring1)
+    _dbus_keyring_unref (ring1);
+  if (ring2)
+    _dbus_keyring_unref (ring2);
+
+  return FALSE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
+     
diff --git a/dbus/dbus/dbus-keyring.h b/dbus/dbus/dbus-keyring.h
new file mode 100644
index 0000000..200e31b
--- /dev/null
+++ b/dbus/dbus/dbus-keyring.h
@@ -0,0 +1,52 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-keyring.h Store secret cookies in your homedir
+ *
+ * Copyright (C) 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_KEYRING_H
+#define DBUS_KEYRING_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-credentials.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusKeyring DBusKeyring;
+
+DBusKeyring* _dbus_keyring_new_for_credentials (DBusCredentials  *credentials,
+                                                const DBusString *context,
+                                                DBusError        *error);
+DBusKeyring* _dbus_keyring_ref                 (DBusKeyring      *keyring);
+void         _dbus_keyring_unref               (DBusKeyring      *keyring);
+dbus_bool_t  _dbus_keyring_validate_context    (const DBusString *context);
+int          _dbus_keyring_get_best_key        (DBusKeyring      *keyring,
+                                                DBusError        *error);
+dbus_bool_t  _dbus_keyring_is_for_credentials  (DBusKeyring      *keyring,
+                                                DBusCredentials  *credentials);
+dbus_bool_t  _dbus_keyring_get_hex_key         (DBusKeyring      *keyring,
+                                                int               key_id,
+                                                DBusString       *hex_key);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_KEYRING_H */
diff --git a/dbus/dbus/dbus-list.c b/dbus/dbus/dbus-list.c
new file mode 100644
index 0000000..7e11cc8
--- /dev/null
+++ b/dbus/dbus/dbus-list.c
@@ -0,0 +1,1339 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-list.c Generic linked list utility (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-list.h"
+#include "dbus-mempool.h"
+#include "dbus-threads-internal.h"
+
+/**
+ * @defgroup DBusList Linked list
+ * @ingroup  DBusInternals
+ * @brief DBusList data structure
+ *
+ * Types and functions related to DBusList.
+ */
+
+static DBusMemPool *list_pool;
+_DBUS_DEFINE_GLOBAL_LOCK (list);
+
+/**
+ * @defgroup DBusListInternals Linked list implementation details
+ * @ingroup  DBusInternals
+ * @brief DBusList implementation details
+ *
+ * The guts of DBusList.
+ *
+ * @{
+ */
+
+/* the mem pool is probably a speed hit, with the thread
+ * lock, though it does still save memory - unknown.
+ */
+static DBusList*
+alloc_link (void *data)
+{
+  DBusList *link;
+
+  _DBUS_LOCK (list);
+
+  if (list_pool == NULL)
+    {      
+      list_pool = _dbus_mem_pool_new (sizeof (DBusList), TRUE);
+
+      if (list_pool == NULL)
+        {
+          _DBUS_UNLOCK (list);
+          return NULL;
+        }
+
+      link = _dbus_mem_pool_alloc (list_pool);
+      if (link == NULL)
+        {
+          _dbus_mem_pool_free (list_pool);
+          list_pool = NULL;
+          _DBUS_UNLOCK (list);
+          return NULL;
+        }
+    }
+  else
+    {
+      link = _dbus_mem_pool_alloc (list_pool);
+    }
+
+  if (link)
+    link->data = data;
+  
+  _DBUS_UNLOCK (list);
+
+  return link;
+}
+
+static void
+free_link (DBusList *link)
+{  
+  _DBUS_LOCK (list);
+  if (_dbus_mem_pool_dealloc (list_pool, link))
+    {
+      _dbus_mem_pool_free (list_pool);
+      list_pool = NULL;
+    }
+  
+  _DBUS_UNLOCK (list);
+}
+
+static void
+link_before (DBusList **list,
+             DBusList  *before_this_link,
+             DBusList  *link)
+{
+  if (*list == NULL)
+    {
+      link->prev = link;
+      link->next = link;
+      *list = link;
+    }
+  else
+    {      
+      link->next = before_this_link;
+      link->prev = before_this_link->prev;
+      before_this_link->prev = link;
+      link->prev->next = link;
+      
+      if (before_this_link == *list)
+        *list = link;
+    }
+}
+
+static void
+link_after (DBusList **list,
+            DBusList  *after_this_link,
+            DBusList  *link)
+{
+  if (*list == NULL)
+    {
+      link->prev = link;
+      link->next = link;
+      *list = link;
+    }
+  else
+    {
+      link->prev = after_this_link;
+      link->next = after_this_link->next;
+      after_this_link->next = link;
+      link->next->prev = link;
+    }
+}
+
+#ifdef DBUS_ENABLE_STATS
+void
+_dbus_list_get_stats     (dbus_uint32_t *in_use_p,
+                          dbus_uint32_t *in_free_list_p,
+                          dbus_uint32_t *allocated_p)
+{
+  _DBUS_LOCK (list);
+  _dbus_mem_pool_get_stats (list_pool, in_use_p, in_free_list_p, allocated_p);
+  _DBUS_UNLOCK (list);
+}
+#endif
+
+/** @} */
+
+/**
+ * @addtogroup DBusList
+ * @{
+ */
+
+/**
+ * @struct DBusList
+ *
+ * A node in a linked list.
+ *
+ * DBusList is a circular list; that is, the tail of the list
+ * points back to the head of the list. The empty list is
+ * represented by a #NULL pointer.
+ */
+
+/**
+ * @def _dbus_list_get_next_link
+ *
+ * Gets the next link in the list, or #NULL if
+ * there are no more links. Used for iteration.
+ *
+ * @code
+ * DBusList *link;
+ * link = _dbus_list_get_first_link (&list);
+ * while (link != NULL)
+ *   {
+ *     printf ("value is %p\n", link->data);
+ *     link = _dbus_list_get_next_link (&link);
+ *   }
+ * @endcode
+ *
+ * @param list address of the list head.
+ * @param link current link.
+ * @returns the next link, or %NULL if none.
+ * 
+ */
+
+/**
+ * @def _dbus_list_get_prev_link
+ *
+ * Gets the previous link in the list, or #NULL if
+ * there are no more links. Used for iteration.
+ *
+ * @code
+ * DBusList *link;
+ * link = _dbus_list_get_last_link (&list);
+ * while (link != NULL)
+ *   {
+ *     printf ("value is %p\n", link->data);
+ *     link = _dbus_list_get_prev_link (&link);
+ *   }
+ * @endcode
+ *
+ * @param list address of the list head.
+ * @param link current link.
+ * @returns the previous link, or %NULL if none.
+ * 
+ */
+
+/**
+ * Allocates a linked list node. Useful for preallocating
+ * nodes and using _dbus_list_append_link() to avoid
+ * allocations.
+ * 
+ * @param data the value to store in the link.
+ * @returns a newly allocated link.
+ */
+DBusList*
+_dbus_list_alloc_link (void *data)
+{
+  return alloc_link (data);
+}
+
+/**
+ * Frees a linked list node allocated with _dbus_list_alloc_link.
+ * Does not free the data in the node.
+ *
+ * @param link the list node
+ */
+void
+_dbus_list_free_link (DBusList *link)
+{
+  free_link (link);
+}
+
+
+/**
+ * Appends a value to the list. May return #FALSE
+ * if insufficient memory exists to add a list link.
+ * This is a constant-time operation.
+ *
+ * @param list address of the list head.
+ * @param data the value to append.
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_list_append (DBusList **list,
+                   void      *data)
+{
+  if (!_dbus_list_prepend (list, data))
+    return FALSE;
+
+  /* Now cycle the list forward one so the prepended node is the tail */
+  *list = (*list)->next;
+
+  return TRUE;
+}
+
+/**
+ * Prepends a value to the list. May return #FALSE
+ * if insufficient memory exists to add a list link.
+ * This is a constant-time operation.
+ *
+ * @param list address of the list head.
+ * @param data the value to prepend.
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_list_prepend (DBusList **list,
+                    void      *data)
+{
+  DBusList *link;
+
+  link = alloc_link (data);
+  if (link == NULL)
+    return FALSE;
+
+  link_before (list, *list, link);
+
+  return TRUE;
+}
+
+/**
+ * Appends a link to the list.
+ * Cannot fail due to out of memory.
+ * This is a constant-time operation.
+ *
+ * @param list address of the list head.
+ * @param link the link to append.
+ */
+void
+_dbus_list_append_link (DBusList **list,
+			DBusList *link)
+{
+  _dbus_list_prepend_link (list, link);
+
+  /* Now cycle the list forward one so the prepended node is the tail */
+  *list = (*list)->next;
+}
+
+/**
+ * Prepends a link to the list. 
+ * Cannot fail due to out of memory.
+ * This is a constant-time operation.
+ *
+ * @param list address of the list head.
+ * @param link the link to prepend.
+ */
+void
+_dbus_list_prepend_link (DBusList **list,
+			 DBusList *link)
+{
+  link_before (list, *list, link);
+}
+
+/**
+ * Inserts data into the list after the given existing link.
+ * 
+ * @param list the list to modify
+ * @param after_this_link existing link to insert after, or #NULL to prepend
+ * @param data the value to insert
+ * @returns #TRUE on success, #FALSE if memory allocation fails
+ */
+dbus_bool_t
+_dbus_list_insert_after (DBusList **list,
+                         DBusList  *after_this_link,
+                         void      *data)
+{
+  DBusList *link;  
+
+  if (after_this_link == NULL)
+    return _dbus_list_prepend (list, data);
+  else
+    {
+      link = alloc_link (data);
+      if (link == NULL)
+        return FALSE;
+  
+      link_after (list, after_this_link, link);
+    }
+  
+  return TRUE;
+}
+
+/**
+ * Inserts a link into the list before the given existing link.
+ * 
+ * @param list the list to modify
+ * @param before_this_link existing link to insert before, or #NULL to append
+ * @param link the link to insert
+ */
+void
+_dbus_list_insert_before_link (DBusList **list,
+                               DBusList  *before_this_link,
+                               DBusList  *link)
+{
+  if (before_this_link == NULL)
+    _dbus_list_append_link (list, link);
+  else
+    link_before (list, before_this_link, link);
+}
+
+/**
+ * Inserts a link into the list after the given existing link.
+ * 
+ * @param list the list to modify
+ * @param after_this_link existing link to insert after, or #NULL to prepend
+ * @param link the link to insert
+ */
+void
+_dbus_list_insert_after_link (DBusList **list,
+                              DBusList  *after_this_link,
+                              DBusList  *link)
+{
+  if (after_this_link == NULL)
+    _dbus_list_prepend_link (list, link);
+  else  
+    link_after (list, after_this_link, link);
+}
+
+/**
+ * Removes a value from the list. Only removes the
+ * first value equal to the given data pointer,
+ * even if multiple values exist which match.
+ * This is a linear-time operation.
+ *
+ * @param list address of the list head.
+ * @param data the value to remove.
+ * @returns #TRUE if a value was found to remove.
+ */
+dbus_bool_t
+_dbus_list_remove (DBusList **list,
+                   void      *data)
+{
+  DBusList *link;
+
+  link = *list;
+  while (link != NULL)
+    {
+      if (link->data == data)
+        {
+          _dbus_list_remove_link (list, link);
+          return TRUE;
+        }
+      
+      link = _dbus_list_get_next_link (list, link);
+    }
+
+  return FALSE;
+}
+
+/**
+ * Removes a value from the list. Only removes the
+ * last value equal to the given data pointer,
+ * even if multiple values exist which match.
+ * This is a linear-time operation.
+ *
+ * @param list address of the list head.
+ * @param data the value to remove.
+ * @returns #TRUE if a value was found to remove.
+ */
+dbus_bool_t
+_dbus_list_remove_last (DBusList **list,
+                        void      *data)
+{
+  DBusList *link;
+
+  link = _dbus_list_find_last (list, data);
+  if (link)
+    {
+      _dbus_list_remove_link (list, link);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * Finds a value in the list. Returns the last link
+ * with value equal to the given data pointer.
+ * This is a linear-time operation.
+ * Returns #NULL if no value found that matches.
+ *
+ * @param list address of the list head.
+ * @param data the value to find.
+ * @returns the link if found
+ */
+DBusList*
+_dbus_list_find_last (DBusList **list,
+                      void      *data)
+{
+  DBusList *link;
+
+  link = _dbus_list_get_last_link (list);
+
+  while (link != NULL)
+    {
+      if (link->data == data)
+        return link;
+      
+      link = _dbus_list_get_prev_link (list, link);
+    }
+
+  return NULL;
+}
+
+/**
+ * Removes the given link from the list, but doesn't
+ * free it. _dbus_list_remove_link() both removes the
+ * link and also frees it.
+ *
+ * @param list the list
+ * @param link the link in the list
+ */
+void
+_dbus_list_unlink (DBusList **list,
+                   DBusList  *link)
+{
+  if (link->next == link)
+    {
+      /* one-element list */
+      *list = NULL;
+    }
+  else
+    {      
+      link->prev->next = link->next;
+      link->next->prev = link->prev;
+      
+      if (*list == link)
+        *list = link->next;
+    }
+
+  link->next = NULL;
+  link->prev = NULL;
+}
+
+/**
+ * Removes a link from the list. This is a constant-time operation.
+ *
+ * @param list address of the list head.
+ * @param link the list link to remove.
+ */
+void
+_dbus_list_remove_link (DBusList **list,
+                        DBusList  *link)
+{
+  _dbus_list_unlink (list, link);
+  free_link (link);
+}
+
+/**
+ * Frees all links in the list and sets the list head to #NULL. Does
+ * not free the data in each link, for obvious reasons. This is a
+ * linear-time operation.
+ *
+ * @param list address of the list head.
+ */
+void
+_dbus_list_clear (DBusList **list)
+{
+  DBusList *link;
+
+  link = *list;
+  while (link != NULL)
+    {
+      DBusList *next = _dbus_list_get_next_link (list, link);
+      
+      free_link (link);
+      
+      link = next;
+    }
+
+  *list = NULL;
+}
+
+/**
+ * Gets the first link in the list.
+ * This is a constant-time operation.
+ *
+ * @param list address of the list head.
+ * @returns the first link, or #NULL for an empty list.
+ */
+DBusList*
+_dbus_list_get_first_link (DBusList **list)
+{
+  return *list;
+}
+
+/**
+ * Gets the last link in the list.
+ * This is a constant-time operation.
+ *
+ * @param list address of the list head.
+ * @returns the last link, or #NULL for an empty list.
+ */
+DBusList*
+_dbus_list_get_last_link (DBusList **list)
+{
+  if (*list == NULL)
+    return NULL;
+  else
+    return (*list)->prev;
+}
+
+/**
+ * Gets the last data in the list.
+ * This is a constant-time operation.
+ *
+ * @param list address of the list head.
+ * @returns the last data in the list, or #NULL for an empty list.
+ */
+void*
+_dbus_list_get_last (DBusList **list)
+{
+  if (*list == NULL)
+    return NULL;
+  else
+    return (*list)->prev->data;
+}
+
+/**
+ * Gets the first data in the list.
+ * This is a constant-time operation.
+ *
+ * @param list address of the list head.
+ * @returns the first data in the list, or #NULL for an empty list.
+ */
+void*
+_dbus_list_get_first (DBusList **list)
+{
+  if (*list == NULL)
+    return NULL;
+  else
+    return (*list)->data;
+}
+
+/**
+ * Removes the first link in the list and returns it.  This is a
+ * constant-time operation.
+ *
+ * @param list address of the list head.
+ * @returns the first link in the list, or #NULL for an empty list.
+ */
+DBusList*
+_dbus_list_pop_first_link (DBusList **list)
+{
+  DBusList *link;
+  
+  link = _dbus_list_get_first_link (list);
+  if (link == NULL)
+    return NULL;
+
+  _dbus_list_unlink (list, link);
+
+  return link;
+}
+
+/**
+ * Removes the first value in the list and returns it.  This is a
+ * constant-time operation.
+ *
+ * @param list address of the list head.
+ * @returns the first data in the list, or #NULL for an empty list.
+ */
+void*
+_dbus_list_pop_first (DBusList **list)
+{
+  DBusList *link;
+  void *data;
+  
+  link = _dbus_list_get_first_link (list);
+  if (link == NULL)
+    return NULL;
+  
+  data = link->data;
+  _dbus_list_remove_link (list, link);
+
+  return data;
+}
+
+/**
+ * Removes the last value in the list and returns it.  This is a
+ * constant-time operation.
+ *
+ * @param list address of the list head.
+ * @returns the last data in the list, or #NULL for an empty list.
+ */
+void*
+_dbus_list_pop_last (DBusList **list)
+{
+  DBusList *link;
+  void *data;
+  
+  link = _dbus_list_get_last_link (list);
+  if (link == NULL)
+    return NULL;
+  
+  data = link->data;
+  _dbus_list_remove_link (list, link);
+
+  return data;
+}
+
+/**
+ * Copies a list. This is a linear-time operation.  If there isn't
+ * enough memory to copy the entire list, the destination list will be
+ * set to #NULL.
+ *
+ * @param list address of the head of the list to copy.
+ * @param dest address where the copied list should be placed.
+ * @returns #TRUE on success, #FALSE if not enough memory.
+ */
+dbus_bool_t
+_dbus_list_copy (DBusList **list,
+                 DBusList **dest)
+{
+  DBusList *link;
+
+  _dbus_assert (list != dest);
+
+  *dest = NULL;
+  
+  link = *list;
+  while (link != NULL)
+    {
+      if (!_dbus_list_append (dest, link->data))
+        {
+          /* free what we have so far */
+          _dbus_list_clear (dest);
+          return FALSE;
+        }
+      
+      link = _dbus_list_get_next_link (list, link);
+    }
+
+  return TRUE;
+}
+
+/**
+ * Gets the length of a list. This is a linear-time
+ * operation.
+ *
+ * @param list address of the head of the list
+ * @returns number of elements in the list.
+ */
+int
+_dbus_list_get_length (DBusList **list)
+{
+  DBusList *link;
+  int length;
+
+  length = 0;
+  
+  link = *list;
+  while (link != NULL)
+    {
+      ++length;
+      
+      link = _dbus_list_get_next_link (list, link);
+    }
+
+  return length;
+}
+
+/**
+ * Calls the given function for each element in the list.  The
+ * function is passed the list element as its first argument, and the
+ * given data as its second argument.
+ *
+ * @param list address of the head of the list.
+ * @param function function to call for each element.
+ * @param data extra data for the function.
+ * 
+ */
+void
+_dbus_list_foreach (DBusList          **list,
+                    DBusForeachFunction function,
+                    void               *data)
+{
+  DBusList *link;
+
+  link = *list;
+  while (link != NULL)
+    {
+      DBusList *next = _dbus_list_get_next_link (list, link);
+      
+      (* function) (link->data, data);
+      
+      link = next;
+    }
+}
+
+/**
+ * Check whether length is exactly one.
+ *
+ * @param list the list
+ * @returns #TRUE if length is exactly one
+ */
+dbus_bool_t
+_dbus_list_length_is_one (DBusList **list)
+{
+  return (*list != NULL &&
+          (*list)->next == *list);
+}
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+
+static void
+verify_list (DBusList **list)
+{
+  DBusList *link;
+  int length;
+  
+  link = *list;
+
+  if (link == NULL)
+    return;
+
+  if (link->next == link)
+    {
+      _dbus_assert (link->prev == link);
+      _dbus_assert (*list == link);
+      return;
+    }
+
+  length = 0;
+  do
+    {
+      length += 1;
+      _dbus_assert (link->prev->next == link);
+      _dbus_assert (link->next->prev == link);
+      link = link->next;
+    }
+  while (link != *list);
+
+  _dbus_assert (length == _dbus_list_get_length (list));
+
+  if (length == 1)
+    _dbus_assert (_dbus_list_length_is_one (list));
+  else
+    _dbus_assert (!_dbus_list_length_is_one (list));
+}
+
+static dbus_bool_t
+is_ascending_sequence (DBusList **list)
+{
+  DBusList *link;
+  int prev;
+
+  prev = _DBUS_INT_MIN;
+  
+  link = _dbus_list_get_first_link (list);
+  while (link != NULL)
+    {
+      int v = _DBUS_POINTER_TO_INT (link->data);
+      
+      if (v <= prev)
+        return FALSE;
+
+      prev = v;
+      
+      link = _dbus_list_get_next_link (list, link);
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+is_descending_sequence (DBusList **list)
+{
+  DBusList *link;
+  int prev;
+
+  prev = _DBUS_INT_MAX;
+  
+  link = _dbus_list_get_first_link (list);
+  while (link != NULL)
+    {
+      int v = _DBUS_POINTER_TO_INT (link->data);
+
+      if (v >= prev)
+        return FALSE;
+
+      prev = v;
+      
+      link = _dbus_list_get_next_link (list, link);
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+all_even_values (DBusList **list)
+{
+  DBusList *link;
+  
+  link = _dbus_list_get_first_link (list);
+  while (link != NULL)
+    {
+      int v = _DBUS_POINTER_TO_INT (link->data);
+
+      if ((v % 2) != 0)
+        return FALSE;
+      
+      link = _dbus_list_get_next_link (list, link);
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+all_odd_values (DBusList **list)
+{
+  DBusList *link;
+  
+  link = _dbus_list_get_first_link (list);
+  while (link != NULL)
+    {
+      int v = _DBUS_POINTER_TO_INT (link->data);
+
+      if ((v % 2) == 0)
+        return FALSE;
+      
+      link = _dbus_list_get_next_link (list, link);
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+lists_equal (DBusList **list1,
+             DBusList **list2)
+{
+  DBusList *link1;
+  DBusList *link2;
+  
+  link1 = _dbus_list_get_first_link (list1);
+  link2 = _dbus_list_get_first_link (list2);
+  while (link1 && link2)
+    {
+      if (link1->data != link2->data)
+        return FALSE;
+      
+      link1 = _dbus_list_get_next_link (list1, link1);
+      link2 = _dbus_list_get_next_link (list2, link2);
+    }
+
+  if (link1 || link2)
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * @ingroup DBusListInternals
+ * Unit test for DBusList
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_list_test (void)
+{
+  DBusList *list1;
+  DBusList *list2;
+  DBusList *link1;
+  DBusList *link2;
+  DBusList *copy1;
+  DBusList *copy2;
+  int i;
+  
+  list1 = NULL;
+  list2 = NULL;
+
+  /* Test append and prepend */
+  
+  i = 0;
+  while (i < 10)
+    {
+      if (!_dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i)))
+        _dbus_assert_not_reached ("could not allocate for append");
+      
+      if (!_dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i)))
+        _dbus_assert_not_reached ("count not allocate for prepend");
+      ++i;
+
+      verify_list (&list1);
+      verify_list (&list2);
+      
+      _dbus_assert (_dbus_list_get_length (&list1) == i);
+      _dbus_assert (_dbus_list_get_length (&list2) == i);
+    }
+
+  _dbus_assert (is_ascending_sequence (&list1));
+  _dbus_assert (is_descending_sequence (&list2));
+
+  /* Test list clear */
+  _dbus_list_clear (&list1);
+  _dbus_list_clear (&list2);
+
+  verify_list (&list1);
+  verify_list (&list2);
+
+  /* Test get_first, get_last, pop_first, pop_last */
+  
+  i = 0;
+  while (i < 10)
+    {
+      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
+      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+      ++i;
+    }
+
+  --i;
+  while (i >= 0)
+    {
+      void *got_data1;
+      void *got_data2;
+      
+      void *data1;
+      void *data2;
+
+      got_data1 = _dbus_list_get_last (&list1);
+      got_data2 = _dbus_list_get_first (&list2);
+      
+      data1 = _dbus_list_pop_last (&list1);
+      data2 = _dbus_list_pop_first (&list2);
+
+      _dbus_assert (got_data1 == data1);
+      _dbus_assert (got_data2 == data2);
+      
+      _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
+      _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);
+
+      verify_list (&list1);
+      verify_list (&list2);
+
+      _dbus_assert (is_ascending_sequence (&list1));
+      _dbus_assert (is_descending_sequence (&list2));
+      
+      --i;
+    }
+
+  _dbus_assert (list1 == NULL);
+  _dbus_assert (list2 == NULL);
+
+  /* Test get_first_link, get_last_link, pop_first_link, pop_last_link */
+  
+  i = 0;
+  while (i < 10)
+    {
+      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
+      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+      ++i;
+    }
+
+  --i;
+  while (i >= 0)
+    {
+      DBusList *got_link1;
+      DBusList *got_link2;
+
+      DBusList *link2;
+      
+      void *data1_indirect;
+      void *data1;
+      void *data2;
+      
+      got_link1 = _dbus_list_get_last_link (&list1);
+      got_link2 = _dbus_list_get_first_link (&list2);
+
+      link2 = _dbus_list_pop_first_link (&list2);
+
+      _dbus_assert (got_link2 == link2);
+
+      data1_indirect = got_link1->data;
+      /* this call makes got_link1 invalid */
+      data1 = _dbus_list_pop_last (&list1);
+      _dbus_assert (data1 == data1_indirect);
+      data2 = link2->data;
+
+      _dbus_list_free_link (link2);
+      
+      _dbus_assert (_DBUS_POINTER_TO_INT (data1) == i);
+      _dbus_assert (_DBUS_POINTER_TO_INT (data2) == i);
+
+      verify_list (&list1);
+      verify_list (&list2);
+
+      _dbus_assert (is_ascending_sequence (&list1));
+      _dbus_assert (is_descending_sequence (&list2));
+      
+      --i;
+    }
+
+  _dbus_assert (list1 == NULL);
+  _dbus_assert (list2 == NULL);
+  
+  /* Test iteration */
+  
+  i = 0;
+  while (i < 10)
+    {
+      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
+      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+      ++i;
+
+      verify_list (&list1);
+      verify_list (&list2);
+      
+      _dbus_assert (_dbus_list_get_length (&list1) == i);
+      _dbus_assert (_dbus_list_get_length (&list2) == i);
+    }
+
+  _dbus_assert (is_ascending_sequence (&list1));
+  _dbus_assert (is_descending_sequence (&list2));
+
+  --i;
+  link2 = _dbus_list_get_first_link (&list2);
+  while (link2 != NULL)
+    {
+      verify_list (&link2); /* pretend this link is the head */
+      
+      _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i);
+      
+      link2 = _dbus_list_get_next_link (&list2, link2);
+      --i;
+    }
+
+  i = 0;
+  link1 = _dbus_list_get_first_link (&list1);
+  while (link1 != NULL)
+    {
+      verify_list (&link1); /* pretend this link is the head */
+      
+      _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
+      
+      link1 = _dbus_list_get_next_link (&list1, link1);
+      ++i;
+    }
+
+  --i;
+  link1 = _dbus_list_get_last_link (&list1);
+  while (link1 != NULL)
+    {
+      verify_list (&link1); /* pretend this link is the head */
+
+      _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
+      
+      link1 = _dbus_list_get_prev_link (&list1, link1);
+      --i;
+    }
+
+  _dbus_list_clear (&list1);
+  _dbus_list_clear (&list2);
+
+  /* Test remove */
+  
+  i = 0;
+  while (i < 10)
+    {
+      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
+      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+      ++i;
+    }
+
+  --i;
+  while (i >= 0)
+    {
+      if ((i % 2) == 0)
+        {
+          if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i)))
+            _dbus_assert_not_reached ("element should have been in list");
+          if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i)))
+            _dbus_assert_not_reached ("element should have been in list");
+
+          verify_list (&list1);
+          verify_list (&list2);
+        }
+      --i;
+    }
+
+  _dbus_assert (all_odd_values (&list1));
+  _dbus_assert (all_odd_values (&list2));
+
+  _dbus_list_clear (&list1);
+  _dbus_list_clear (&list2);
+
+  /* test removing the other half of the elements */
+  
+  i = 0;
+  while (i < 10)
+    {
+      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
+      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+      ++i;
+    }
+
+  --i;
+  while (i >= 0)
+    {
+      if ((i % 2) != 0)
+        {
+          if (!_dbus_list_remove (&list1, _DBUS_INT_TO_POINTER (i)))
+            _dbus_assert_not_reached ("element should have been in list");
+          if (!_dbus_list_remove (&list2, _DBUS_INT_TO_POINTER (i)))
+            _dbus_assert_not_reached ("element should have been in list");
+
+          verify_list (&list1);
+          verify_list (&list2);
+        }
+      --i;
+    }
+
+  _dbus_assert (all_even_values (&list1));
+  _dbus_assert (all_even_values (&list2));
+
+  /* clear list using remove_link */
+  while (list1 != NULL)
+    {
+      _dbus_list_remove_link (&list1, list1);
+      verify_list (&list1);
+    }
+  while (list2 != NULL)
+    {
+      _dbus_list_remove_link (&list2, list2);
+      verify_list (&list2);
+    }
+
+  /* Test remove link more generally */
+  i = 0;
+  while (i < 10)
+    {
+      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
+      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+      ++i;
+    }
+
+  --i;
+  link2 = _dbus_list_get_first_link (&list2);
+  while (link2 != NULL)
+    {
+      DBusList *next = _dbus_list_get_next_link (&list2, link2);
+      
+      _dbus_assert (_DBUS_POINTER_TO_INT (link2->data) == i);
+
+      if ((i % 2) == 0)
+        _dbus_list_remove_link (&list2, link2);
+
+      verify_list (&list2);
+      
+      link2 = next;
+      --i;
+    }
+
+  _dbus_assert (all_odd_values (&list2));  
+  _dbus_list_clear (&list2);
+  
+  i = 0;
+  link1 = _dbus_list_get_first_link (&list1);
+  while (link1 != NULL)
+    {
+      DBusList *next = _dbus_list_get_next_link (&list1, link1);
+
+      _dbus_assert (_DBUS_POINTER_TO_INT (link1->data) == i);
+
+      if ((i % 2) != 0)
+        _dbus_list_remove_link (&list1, link1);
+
+      verify_list (&list1);
+      
+      link1 = next;
+      ++i;
+    }
+
+  _dbus_assert (all_even_values (&list1));
+  _dbus_list_clear (&list1);
+
+  /* Test copying a list */
+  i = 0;
+  while (i < 10)
+    {
+      _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (i));
+      _dbus_list_prepend (&list2, _DBUS_INT_TO_POINTER (i));
+      ++i;
+    }
+
+  /* bad pointers, because they are allowed in the copy dest */
+  copy1 = _DBUS_INT_TO_POINTER (0x342234);
+  copy2 = _DBUS_INT_TO_POINTER (23);
+  
+  _dbus_list_copy (&list1, &copy1);
+  verify_list (&list1);
+  verify_list (&copy1);
+  _dbus_assert (lists_equal (&list1, &copy1));
+  
+  _dbus_list_copy (&list2, &copy2);
+  verify_list (&list2);
+  verify_list (&copy2);
+  _dbus_assert (lists_equal (&list2, &copy2));
+
+  /* Now test copying empty lists */
+  _dbus_list_clear (&list1);
+  _dbus_list_clear (&list2);
+  _dbus_list_clear (&copy1);
+  _dbus_list_clear (&copy2);
+  
+  /* bad pointers, because they are allowed in the copy dest */
+  copy1 = _DBUS_INT_TO_POINTER (0x342234);
+  copy2 = _DBUS_INT_TO_POINTER (23);
+  
+  _dbus_list_copy (&list1, &copy1);
+  verify_list (&list1);
+  verify_list (&copy1);
+  _dbus_assert (lists_equal (&list1, &copy1));
+  
+  _dbus_list_copy (&list2, &copy2);
+  verify_list (&list2);
+  verify_list (&copy2);
+  _dbus_assert (lists_equal (&list2, &copy2));
+
+  _dbus_list_clear (&list1);
+  _dbus_list_clear (&list2);
+
+  /* insert_after on empty list */
+  _dbus_list_insert_after (&list1, NULL,
+                           _DBUS_INT_TO_POINTER (0));
+  verify_list (&list1);
+
+  /* inserting after first element */
+  _dbus_list_insert_after (&list1, list1,
+                           _DBUS_INT_TO_POINTER (1));
+  verify_list (&list1);
+  _dbus_assert (is_ascending_sequence (&list1));
+
+  /* inserting at the end */
+  _dbus_list_insert_after (&list1, list1->next,
+                           _DBUS_INT_TO_POINTER (2));
+  verify_list (&list1);
+  _dbus_assert (is_ascending_sequence (&list1));
+
+  /* using insert_after to prepend */
+  _dbus_list_insert_after (&list1, NULL,
+                           _DBUS_INT_TO_POINTER (-1));
+  verify_list (&list1);
+  _dbus_assert (is_ascending_sequence (&list1));
+  
+  _dbus_list_clear (&list1);
+
+  /* using remove_last */
+  _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (2));
+  _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (1));
+  _dbus_list_append (&list1, _DBUS_INT_TO_POINTER (3));
+
+  _dbus_list_remove_last (&list1, _DBUS_INT_TO_POINTER (2));
+  
+  verify_list (&list1);
+  _dbus_assert (is_ascending_sequence (&list1));
+  
+  _dbus_list_clear (&list1);
+  
+  return TRUE;
+}
+
+#endif
diff --git a/dbus/dbus/dbus-list.h b/dbus/dbus/dbus-list.h
new file mode 100644
index 0000000..910d738
--- /dev/null
+++ b/dbus/dbus/dbus-list.h
@@ -0,0 +1,100 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-list.h Generic linked list utility (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_LIST_H
+#define DBUS_LIST_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-memory.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-sysdeps.h>
+
+DBUS_BEGIN_DECLS
+
+struct DBusList
+{
+  DBusList *prev; /**< Previous list node. */
+  DBusList *next; /**< Next list node. */
+  void     *data; /**< Data stored at this element. */
+};
+dbus_bool_t _dbus_list_append             (DBusList **list,
+                                           void      *data);
+dbus_bool_t _dbus_list_prepend            (DBusList **list,
+                                           void      *data);
+dbus_bool_t _dbus_list_insert_before      (DBusList **list,
+                                           DBusList  *before_this_link,
+                                           void      *data);
+dbus_bool_t _dbus_list_insert_after       (DBusList **list,
+                                           DBusList  *after_this_link,
+                                           void      *data);
+void        _dbus_list_insert_before_link (DBusList **list,
+                                           DBusList  *before_this_link,
+                                           DBusList  *link);
+void        _dbus_list_insert_after_link  (DBusList **list,
+                                           DBusList  *after_this_link,
+                                           DBusList  *link);
+dbus_bool_t _dbus_list_remove             (DBusList **list,
+                                           void      *data);
+dbus_bool_t _dbus_list_remove_last        (DBusList **list,
+                                           void      *data);
+void        _dbus_list_remove_link        (DBusList **list,
+                                           DBusList  *link);
+DBusList*   _dbus_list_find_last          (DBusList **list,
+                                           void      *data);
+void        _dbus_list_clear              (DBusList **list);
+DBusList*   _dbus_list_get_first_link     (DBusList **list);
+DBusList*   _dbus_list_get_last_link      (DBusList **list);
+void*       _dbus_list_get_last           (DBusList **list);
+void*       _dbus_list_get_first          (DBusList **list);
+void*       _dbus_list_pop_first          (DBusList **list);
+void*       _dbus_list_pop_last           (DBusList **list);
+DBusList*   _dbus_list_pop_first_link     (DBusList **list);
+dbus_bool_t _dbus_list_copy               (DBusList **list,
+                                           DBusList **dest);
+int         _dbus_list_get_length         (DBusList **list);
+DBusList*   _dbus_list_alloc_link         (void      *data);
+void        _dbus_list_free_link          (DBusList  *link);
+void        _dbus_list_unlink             (DBusList **list,
+                                           DBusList  *link);
+void        _dbus_list_append_link        (DBusList **list,
+                                           DBusList  *link);
+void        _dbus_list_prepend_link       (DBusList **list,
+                                           DBusList  *link);
+dbus_bool_t _dbus_list_length_is_one      (DBusList **list);
+
+
+void _dbus_list_foreach (DBusList            **list,
+                         DBusForeachFunction   function,
+                         void                 *data);
+
+#define _dbus_list_get_next_link(list, link) ((link)->next == *(list) ? NULL : (link)->next)
+#define _dbus_list_get_prev_link(list, link) ((link) == *(list) ? NULL : (link)->prev)
+
+/* if DBUS_ENABLE_STATS */
+void        _dbus_list_get_stats          (dbus_uint32_t *in_use_p,
+                                           dbus_uint32_t *in_free_list_p,
+                                           dbus_uint32_t *allocated_p);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_LIST_H */
diff --git a/dbus/dbus/dbus-macros.h b/dbus/dbus/dbus-macros.h
new file mode 100644
index 0000000..dcd3eeb
--- /dev/null
+++ b/dbus/dbus/dbus-macros.h
@@ -0,0 +1,188 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-macros.h  generic macros
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_MACROS_H
+#define DBUS_MACROS_H
+
+#ifdef  __cplusplus
+#  define DBUS_BEGIN_DECLS  extern "C" {
+#  define DBUS_END_DECLS    }
+#else
+#  define DBUS_BEGIN_DECLS
+#  define DBUS_END_DECLS
+#endif
+
+#ifndef TRUE
+#  define TRUE 1
+#endif
+#ifndef FALSE
+#  define FALSE 0
+#endif
+
+#ifndef NULL
+#  ifdef __cplusplus
+#    define NULL        (0L)
+#  else /* !__cplusplus */
+#    define NULL        ((void*) 0)
+#  endif /* !__cplusplus */
+#endif
+
+#if  __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+#  define DBUS_DEPRECATED __attribute__ ((__deprecated__))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
+#  define DBUS_DEPRECATED __declspec(deprecated)
+#else
+#  define DBUS_DEPRECATED
+#endif
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
+#  define _DBUS_GNUC_EXTENSION __extension__
+#else
+#  define _DBUS_GNUC_EXTENSION
+#endif
+
+#if     __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+#define _DBUS_GNUC_PRINTF( format_idx, arg_idx )    \
+  __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#define _DBUS_GNUC_NORETURN                         \
+  __attribute__((__noreturn__))
+#else   /* !__GNUC__ */
+#define _DBUS_GNUC_PRINTF( format_idx, arg_idx )
+#define _DBUS_GNUC_NORETURN
+#endif  /* !__GNUC__ */
+
+#if    __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+#define DBUS_MALLOC     __attribute__((__malloc__))
+#else
+#define DBUS_MALLOC
+#endif
+
+#if     (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
+#define DBUS_ALLOC_SIZE(x) __attribute__((__alloc_size__(x)))
+#define DBUS_ALLOC_SIZE2(x,y) __attribute__((__alloc_size__(x,y)))
+#else
+#define DBUS_ALLOC_SIZE(x)
+#define DBUS_ALLOC_SIZE2(x,y)
+#endif
+
+/** @def _DBUS_GNUC_PRINTF
+ * used to tell gcc about printf format strings
+ */
+/** @def _DBUS_GNUC_NORETURN
+ * used to tell gcc about functions that never return, such as _dbus_abort()
+ */
+
+
+/* Normally docs are in .c files, but there isn't a .c file for this. */
+/**
+ * @defgroup DBusMacros Utility macros
+ * @ingroup  DBus
+ * @brief #TRUE, #FALSE, #NULL, and so on
+ *
+ * Utility macros.
+ *
+ * @{
+ */
+
+/**
+ * @def DBUS_BEGIN_DECLS
+ *
+ * Macro used prior to declaring functions in the D-Bus header
+ * files. Expands to "extern "C"" when using a C++ compiler,
+ * and expands to nothing when using a C compiler.
+ *
+ * Please don't use this in your own code, consider it
+ * D-Bus internal.
+ */
+/**
+ * @def DBUS_END_DECLS
+ *
+ * Macro used after declaring functions in the D-Bus header
+ * files. Expands to "}" when using a C++ compiler,
+ * and expands to nothing when using a C compiler.
+ *
+ * Please don't use this in your own code, consider it
+ * D-Bus internal.
+ */
+/**
+ * @def TRUE
+ *
+ * Expands to "1"
+ */
+/**
+ * @def FALSE
+ *
+ * Expands to "0"
+ */
+/**
+ * @def NULL
+ *
+ * A null pointer, defined appropriately for C or C++.
+ */
+/**
+ * @def DBUS_DEPRECATED
+ *
+ * Tells the compiler to warn about a function or type if it's used.
+ * Code marked in this way should also be enclosed in
+ * @code
+ * #ifndef DBUS_DISABLE_DEPRECATED
+ *  deprecated stuff here
+ * #endif
+ * @endcode
+ *
+ * Please don't use this in your own code, consider it
+ * D-Bus internal.
+ */
+/**
+ * @def _DBUS_GNUC_EXTENSION
+ *
+ * Tells gcc not to warn about extensions to the C standard in the
+ * following expression, even if compiling with -pedantic. Do not use
+ * this macro in your own code; please consider it to be internal to libdbus.
+ */
+
+/*
+ * @def DBUS_EXPORT
+ *
+ * Declare the following symbol as public.  This is currently a noop on
+ * platforms other than Windows.
+ */
+
+#if defined(_WIN32)
+#  if defined(DBUS_STATIC_BUILD)
+#  define DBUS_EXPORT
+#  elif defined(dbus_1_EXPORTS)
+#  define DBUS_EXPORT __declspec(dllexport)
+#  else
+#  define DBUS_EXPORT __declspec(dllimport)
+#  endif
+#else
+#define DBUS_EXPORT
+#endif
+
+/** @} */
+
+#endif /* DBUS_MACROS_H */
diff --git a/dbus/dbus/dbus-mainloop.c b/dbus/dbus/dbus-mainloop.c
new file mode 100644
index 0000000..cef676a
--- /dev/null
+++ b/dbus/dbus/dbus-mainloop.c
@@ -0,0 +1,940 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-mainloop.c  Main loop utility
+ *
+ * Copyright © 2003, 2004  Red Hat, Inc.
+ * Copyright © 2011 Nokia Corporation
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-mainloop.h"
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include <dbus/dbus-hash.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-socket-set.h>
+#include <dbus/dbus-watch.h>
+
+#define MAINLOOP_SPEW 0
+
+#if MAINLOOP_SPEW
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+static const char*
+watch_flags_to_string (int flags)
+{
+  const char *watch_type;
+
+  if ((flags & DBUS_WATCH_READABLE) &&
+      (flags & DBUS_WATCH_WRITABLE))
+    watch_type = "readwrite";
+  else if (flags & DBUS_WATCH_READABLE)
+    watch_type = "read";
+  else if (flags & DBUS_WATCH_WRITABLE)
+    watch_type = "write";
+  else
+    watch_type = "not read or write";
+  return watch_type;
+}
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+#endif /* MAINLOOP_SPEW */
+
+struct DBusLoop
+{
+  int refcount;
+  /** fd => dbus_malloc'd DBusList ** of references to DBusWatch */
+  DBusHashTable *watches;
+  DBusSocketSet *socket_set;
+  DBusList *timeouts;
+  int callback_list_serial;
+  int watch_count;
+  int timeout_count;
+  int depth; /**< number of recursive runs */
+  DBusList *need_dispatch;
+  /** TRUE if we will skip a watch next time because it was OOM; becomes
+   * FALSE between polling, and dealing with the results of the poll */
+  unsigned oom_watch_pending : 1;
+};
+
+typedef struct
+{
+  DBusTimeout *timeout;
+  unsigned long last_tv_sec;
+  unsigned long last_tv_usec;
+} TimeoutCallback;
+
+#define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback)
+
+static TimeoutCallback*
+timeout_callback_new (DBusTimeout         *timeout)
+{
+  TimeoutCallback *cb;
+
+  cb = dbus_new (TimeoutCallback, 1);
+  if (cb == NULL)
+    return NULL;
+
+  cb->timeout = timeout;
+  _dbus_get_monotonic_time (&cb->last_tv_sec,
+                            &cb->last_tv_usec);
+  return cb;
+}
+
+static void
+timeout_callback_free (TimeoutCallback *cb)
+{
+  dbus_free (cb);
+}
+
+static void
+free_watch_table_entry (void *data)
+{
+  DBusList **watches = data;
+  DBusWatch *watch;
+
+  /* DBusHashTable sometimes calls free_function(NULL) even if you never
+   * have NULL as a value */
+  if (watches == NULL)
+    return;
+
+  for (watch = _dbus_list_pop_first (watches);
+      watch != NULL;
+      watch = _dbus_list_pop_first (watches))
+    {
+      _dbus_watch_unref (watch);
+    }
+
+  _dbus_assert (*watches == NULL);
+  dbus_free (watches);
+}
+
+DBusLoop*
+_dbus_loop_new (void)
+{
+  DBusLoop *loop;
+
+  loop = dbus_new0 (DBusLoop, 1);
+  if (loop == NULL)
+    return NULL;
+
+  loop->watches = _dbus_hash_table_new (DBUS_HASH_INT, NULL,
+                                        free_watch_table_entry);
+
+  loop->socket_set = _dbus_socket_set_new (0);
+
+  if (loop->watches == NULL || loop->socket_set == NULL)
+    {
+      if (loop->watches != NULL)
+        _dbus_hash_table_unref (loop->watches);
+
+      if (loop->socket_set != NULL)
+        _dbus_socket_set_free (loop->socket_set);
+
+      dbus_free (loop);
+      return NULL;
+    }
+
+  loop->refcount = 1;
+
+  return loop;
+}
+
+DBusLoop *
+_dbus_loop_ref (DBusLoop *loop)
+{
+  _dbus_assert (loop != NULL);
+  _dbus_assert (loop->refcount > 0);
+
+  loop->refcount += 1;
+
+  return loop;
+}
+
+void
+_dbus_loop_unref (DBusLoop *loop)
+{
+  _dbus_assert (loop != NULL);
+  _dbus_assert (loop->refcount > 0);
+
+  loop->refcount -= 1;
+  if (loop->refcount == 0)
+    {
+      while (loop->need_dispatch)
+        {
+          DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch);
+
+          dbus_connection_unref (connection);
+        }
+
+      _dbus_hash_table_unref (loop->watches);
+      _dbus_socket_set_free (loop->socket_set);
+      dbus_free (loop);
+    }
+}
+
+static DBusList **
+ensure_watch_table_entry (DBusLoop *loop,
+                          int       fd)
+{
+  DBusList **watches;
+
+  watches = _dbus_hash_table_lookup_int (loop->watches, fd);
+
+  if (watches == NULL)
+    {
+      watches = dbus_new0 (DBusList *, 1);
+
+      if (watches == NULL)
+        return watches;
+
+      if (!_dbus_hash_table_insert_int (loop->watches, fd, watches))
+        {
+          dbus_free (watches);
+          watches = NULL;
+        }
+    }
+
+  return watches;
+}
+
+static void
+cull_watches_for_invalid_fd (DBusLoop  *loop,
+                             int        fd)
+{
+  DBusList *link;
+  DBusList **watches;
+
+  _dbus_warn ("invalid request, socket fd %d not open\n", fd);
+  watches = _dbus_hash_table_lookup_int (loop->watches, fd);
+
+  if (watches != NULL)
+    {
+      for (link = _dbus_list_get_first_link (watches);
+          link != NULL;
+          link = _dbus_list_get_next_link (watches, link))
+        _dbus_watch_invalidate (link->data);
+    }
+
+  _dbus_hash_table_remove_int (loop->watches, fd);
+}
+
+static dbus_bool_t
+gc_watch_table_entry (DBusLoop  *loop,
+                      DBusList **watches,
+                      int        fd)
+{
+  /* If watches is already NULL we have nothing to do */
+  if (watches == NULL)
+    return FALSE;
+
+  /* We can't GC hash table entries if they're non-empty lists */
+  if (*watches != NULL)
+    return FALSE;
+
+  _dbus_hash_table_remove_int (loop->watches, fd);
+  return TRUE;
+}
+
+static void
+refresh_watches_for_fd (DBusLoop  *loop,
+                        DBusList **watches,
+                        int        fd)
+{
+  DBusList *link;
+  unsigned int flags = 0;
+  dbus_bool_t interested = FALSE;
+
+  _dbus_assert (fd != -1);
+
+  if (watches == NULL)
+    watches = _dbus_hash_table_lookup_int (loop->watches, fd);
+
+  /* we allocated this in the first _dbus_loop_add_watch for the fd, and keep
+   * it until there are none left */
+  _dbus_assert (watches != NULL);
+
+  for (link = _dbus_list_get_first_link (watches);
+      link != NULL;
+      link = _dbus_list_get_next_link (watches, link))
+    {
+      if (dbus_watch_get_enabled (link->data) &&
+          !_dbus_watch_get_oom_last_time (link->data))
+        {
+          flags |= dbus_watch_get_flags (link->data);
+          interested = TRUE;
+        }
+    }
+
+  if (interested)
+    _dbus_socket_set_enable (loop->socket_set, fd, flags);
+  else
+    _dbus_socket_set_disable (loop->socket_set, fd);
+}
+
+dbus_bool_t
+_dbus_loop_add_watch (DBusLoop  *loop,
+                      DBusWatch *watch)
+{
+  int fd;
+  DBusList **watches;
+
+  fd = dbus_watch_get_socket (watch);
+  _dbus_assert (fd != -1);
+
+  watches = ensure_watch_table_entry (loop, fd);
+
+  if (watches == NULL)
+    return FALSE;
+
+  if (!_dbus_list_append (watches, _dbus_watch_ref (watch)))
+    {
+      _dbus_watch_unref (watch);
+      gc_watch_table_entry (loop, watches, fd);
+
+      return FALSE;
+    }
+
+  if (_dbus_list_length_is_one (watches))
+    {
+      if (!_dbus_socket_set_add (loop->socket_set, fd,
+                                 dbus_watch_get_flags (watch),
+                                 dbus_watch_get_enabled (watch)))
+        {
+          _dbus_hash_table_remove_int (loop->watches, fd);
+          return FALSE;
+        }
+    }
+  else
+    {
+      /* we're modifying, not adding, which can't fail with OOM */
+      refresh_watches_for_fd (loop, watches, fd);
+    }
+
+  loop->callback_list_serial += 1;
+  loop->watch_count += 1;
+  return TRUE;
+}
+
+void
+_dbus_loop_toggle_watch (DBusLoop          *loop,
+                         DBusWatch         *watch)
+{
+  refresh_watches_for_fd (loop, NULL, dbus_watch_get_socket (watch));
+}
+
+void
+_dbus_loop_remove_watch (DBusLoop         *loop,
+                         DBusWatch        *watch)
+{
+  DBusList **watches;
+  DBusList *link;
+  int fd;
+
+  /* This relies on people removing watches before they invalidate them,
+   * which has been safe since fd.o #33336 was fixed. Assert about it
+   * so we don't regress. */
+  fd = dbus_watch_get_socket (watch);
+  _dbus_assert (fd != -1);
+
+  watches = _dbus_hash_table_lookup_int (loop->watches, fd);
+
+  if (watches != NULL)
+    {
+      link = _dbus_list_get_first_link (watches);
+      while (link != NULL)
+        {
+          DBusList *next = _dbus_list_get_next_link (watches, link);
+          DBusWatch *this = link->data;
+
+          if (this == watch)
+            {
+              _dbus_list_remove_link (watches, link);
+              loop->callback_list_serial += 1;
+              loop->watch_count -= 1;
+              _dbus_watch_unref (this);
+
+              /* if that was the last watch for that fd, drop the hash table
+               * entry, and stop reserving space for it in the socket set */
+              if (gc_watch_table_entry (loop, watches, fd))
+                {
+                  _dbus_socket_set_remove (loop->socket_set, fd);
+                }
+
+              return;
+            }
+
+          link = next;
+         }
+     }
+
+  _dbus_warn ("could not find watch %p to remove\n", watch);
+}
+
+dbus_bool_t
+_dbus_loop_add_timeout (DBusLoop           *loop,
+                        DBusTimeout        *timeout)
+{
+  TimeoutCallback *tcb;
+
+  tcb = timeout_callback_new (timeout);
+  if (tcb == NULL)
+    return FALSE;
+
+  if (_dbus_list_append (&loop->timeouts, tcb))
+    {
+      loop->callback_list_serial += 1;
+      loop->timeout_count += 1;
+    }
+  else
+    {
+      timeout_callback_free (tcb);
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+void
+_dbus_loop_remove_timeout (DBusLoop           *loop,
+                           DBusTimeout        *timeout)
+{
+  DBusList *link;
+  
+  link = _dbus_list_get_first_link (&loop->timeouts);
+  while (link != NULL)
+    {
+      DBusList *next = _dbus_list_get_next_link (&loop->timeouts, link);
+      TimeoutCallback *this = link->data;
+
+      if (this->timeout == timeout)
+        {
+          _dbus_list_remove_link (&loop->timeouts, link);
+          loop->callback_list_serial += 1;
+          loop->timeout_count -= 1;
+          timeout_callback_free (this);
+
+          return;
+        }
+      
+      link = next;
+    }
+
+  _dbus_warn ("could not find timeout %p to remove\n", timeout);
+}
+
+/* Convolutions from GLib, there really must be a better way
+ * to do this.
+ */
+static dbus_bool_t
+check_timeout (unsigned long    tv_sec,
+               unsigned long    tv_usec,
+               TimeoutCallback *tcb,
+               int             *timeout)
+{
+  long sec_remaining;
+  long msec_remaining;
+  unsigned long expiration_tv_sec;
+  unsigned long expiration_tv_usec;
+  long interval_seconds;
+  long interval_milliseconds;
+  int interval;
+
+  /* I'm pretty sure this function could suck (a lot) less */
+  
+  interval = dbus_timeout_get_interval (tcb->timeout);
+  
+  interval_seconds = interval / 1000L;
+  interval_milliseconds = interval % 1000L;
+  
+  expiration_tv_sec = tcb->last_tv_sec + interval_seconds;
+  expiration_tv_usec = tcb->last_tv_usec + interval_milliseconds * 1000;
+  if (expiration_tv_usec >= 1000000)
+    {
+      expiration_tv_usec -= 1000000;
+      expiration_tv_sec += 1;
+    }
+  
+  sec_remaining = expiration_tv_sec - tv_sec;
+  /* need to force this to be signed, as it is intended to sometimes
+   * produce a negative result
+   */
+  msec_remaining = ((long) expiration_tv_usec - (long) tv_usec) / 1000L;
+
+#if MAINLOOP_SPEW
+  _dbus_verbose ("Interval is %ld seconds %ld msecs\n",
+                 interval_seconds,
+                 interval_milliseconds);
+  _dbus_verbose ("Now is  %lu seconds %lu usecs\n",
+                 tv_sec, tv_usec);
+  _dbus_verbose ("Last is %lu seconds %lu usecs\n",
+                 tcb->last_tv_sec, tcb->last_tv_usec);
+  _dbus_verbose ("Exp is  %lu seconds %lu usecs\n",
+                 expiration_tv_sec, expiration_tv_usec);
+  _dbus_verbose ("Pre-correction, sec_remaining %ld msec_remaining %ld\n",
+                 sec_remaining, msec_remaining);
+#endif
+  
+  /* We do the following in a rather convoluted fashion to deal with
+   * the fact that we don't have an integral type big enough to hold
+   * the difference of two timevals in milliseconds.
+   */
+  if (sec_remaining < 0 || (sec_remaining == 0 && msec_remaining < 0))
+    {
+      *timeout = 0;
+    }
+  else
+    {
+      if (msec_remaining < 0)
+	{
+	  msec_remaining += 1000;
+	  sec_remaining -= 1;
+	}
+
+      if (sec_remaining > (_DBUS_INT_MAX / 1000) ||
+          msec_remaining > _DBUS_INT_MAX)
+        *timeout = _DBUS_INT_MAX;
+      else
+        *timeout = sec_remaining * 1000 + msec_remaining;        
+    }
+
+  if (*timeout > interval)
+    {
+      /* This indicates that the system clock probably moved backward */
+      _dbus_verbose ("System clock set backward! Resetting timeout.\n");
+      
+      tcb->last_tv_sec = tv_sec;
+      tcb->last_tv_usec = tv_usec;
+
+      *timeout = interval;
+    }
+  
+#if MAINLOOP_SPEW
+  _dbus_verbose ("  timeout expires in %d milliseconds\n", *timeout);
+#endif
+  
+  return *timeout == 0;
+}
+
+dbus_bool_t
+_dbus_loop_dispatch (DBusLoop *loop)
+{
+
+#if MAINLOOP_SPEW
+  _dbus_verbose ("  %d connections to dispatch\n", _dbus_list_get_length (&loop->need_dispatch));
+#endif
+  
+  if (loop->need_dispatch == NULL)
+    return FALSE;
+  
+ next:
+  while (loop->need_dispatch != NULL)
+    {
+      DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch);
+      
+      while (TRUE)
+        {
+          DBusDispatchStatus status;
+          
+          status = dbus_connection_dispatch (connection);
+
+          if (status == DBUS_DISPATCH_COMPLETE)
+            {
+              dbus_connection_unref (connection);
+              goto next;
+            }
+          else
+            {
+              if (status == DBUS_DISPATCH_NEED_MEMORY)
+                _dbus_wait_for_memory ();
+            }
+        }
+    }
+
+  return TRUE;
+}
+
+dbus_bool_t
+_dbus_loop_queue_dispatch (DBusLoop       *loop,
+                           DBusConnection *connection)
+{
+  if (_dbus_list_append (&loop->need_dispatch, connection))
+    {
+      dbus_connection_ref (connection);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/* Returns TRUE if we invoked any timeouts or have ready file
+ * descriptors, which is just used in test code as a debug hack
+ */
+
+dbus_bool_t
+_dbus_loop_iterate (DBusLoop     *loop,
+                    dbus_bool_t   block)
+{  
+#define N_STACK_DESCRIPTORS 64
+  dbus_bool_t retval;
+  DBusSocketEvent ready_fds[N_STACK_DESCRIPTORS];
+  int i;
+  DBusList *link;
+  int n_ready;
+  int initial_serial;
+  long timeout;
+  int orig_depth;
+
+  retval = FALSE;      
+
+  orig_depth = loop->depth;
+  
+#if MAINLOOP_SPEW
+  _dbus_verbose ("Iteration block=%d depth=%d timeout_count=%d watch_count=%d\n",
+                 block, loop->depth, loop->timeout_count, loop->watch_count);
+#endif
+
+  if (_dbus_hash_table_get_n_entries (loop->watches) == 0 &&
+      loop->timeouts == NULL)
+    goto next_iteration;
+
+  timeout = -1;
+  if (loop->timeout_count > 0)
+    {
+      unsigned long tv_sec;
+      unsigned long tv_usec;
+      
+      _dbus_get_monotonic_time (&tv_sec, &tv_usec);
+
+      link = _dbus_list_get_first_link (&loop->timeouts);
+      while (link != NULL)
+        {
+          DBusList *next = _dbus_list_get_next_link (&loop->timeouts, link);
+          TimeoutCallback *tcb = link->data;
+
+          if (dbus_timeout_get_enabled (tcb->timeout))
+            {
+              int msecs_remaining;
+
+              check_timeout (tv_sec, tv_usec, tcb, &msecs_remaining);
+
+              if (timeout < 0)
+                timeout = msecs_remaining;
+              else
+                timeout = MIN (msecs_remaining, timeout);
+
+#if MAINLOOP_SPEW
+              _dbus_verbose ("  timeout added, %d remaining, aggregate timeout %ld\n",
+                             msecs_remaining, timeout);
+#endif
+              
+              _dbus_assert (timeout >= 0);
+                  
+              if (timeout == 0)
+                break; /* it's not going to get shorter... */
+            }
+#if MAINLOOP_SPEW
+          else
+            {
+              _dbus_verbose ("  skipping disabled timeout\n");
+            }
+#endif
+          
+          link = next;
+        }
+    }
+
+  /* Never block if we have stuff to dispatch */
+  if (!block || loop->need_dispatch != NULL)
+    {
+      timeout = 0;
+#if MAINLOOP_SPEW
+      _dbus_verbose ("  timeout is 0 as we aren't blocking\n");
+#endif
+    }
+
+  /* if a watch was OOM last time, don't wait longer than the OOM
+   * wait to re-enable it
+   */
+  if (loop->oom_watch_pending)
+    timeout = MIN (timeout, _dbus_get_oom_wait ());
+
+#if MAINLOOP_SPEW
+  _dbus_verbose ("  polling on %d descriptors timeout %ld\n", n_fds, timeout);
+#endif
+
+  n_ready = _dbus_socket_set_poll (loop->socket_set, ready_fds,
+                                   _DBUS_N_ELEMENTS (ready_fds), timeout);
+
+  /* re-enable any watches we skipped this time */
+  if (loop->oom_watch_pending)
+    {
+      DBusHashIter hash_iter;
+
+      loop->oom_watch_pending = FALSE;
+
+      _dbus_hash_iter_init (loop->watches, &hash_iter);
+
+      while (_dbus_hash_iter_next (&hash_iter))
+        {
+          DBusList **watches;
+          int fd;
+          dbus_bool_t changed;
+
+          changed = FALSE;
+          fd = _dbus_hash_iter_get_int_key (&hash_iter);
+          watches = _dbus_hash_iter_get_value (&hash_iter);
+
+          for (link = _dbus_list_get_first_link (watches);
+              link != NULL;
+              link = _dbus_list_get_next_link (watches, link))
+            {
+              DBusWatch *watch = link->data;
+
+              if (_dbus_watch_get_oom_last_time (watch))
+                {
+                  _dbus_watch_set_oom_last_time (watch, FALSE);
+                  changed = TRUE;
+                }
+            }
+
+          if (changed)
+            refresh_watches_for_fd (loop, watches, fd);
+        }
+
+      retval = TRUE; /* return TRUE here to keep the loop going,
+                      * since we don't know the watch was inactive */
+    }
+
+  initial_serial = loop->callback_list_serial;
+
+  if (loop->timeout_count > 0)
+    {
+      unsigned long tv_sec;
+      unsigned long tv_usec;
+
+      _dbus_get_monotonic_time (&tv_sec, &tv_usec);
+
+      /* It'd be nice to avoid this O(n) thingy here */
+      link = _dbus_list_get_first_link (&loop->timeouts);
+      while (link != NULL)
+        {
+          DBusList *next = _dbus_list_get_next_link (&loop->timeouts, link);
+          TimeoutCallback *tcb = link->data;
+
+          if (initial_serial != loop->callback_list_serial)
+            goto next_iteration;
+
+          if (loop->depth != orig_depth)
+            goto next_iteration;
+
+          if (dbus_timeout_get_enabled (tcb->timeout))
+            {
+              int msecs_remaining;
+              
+              if (check_timeout (tv_sec, tv_usec,
+                                 tcb, &msecs_remaining))
+                {
+                  /* Save last callback time and fire this timeout */
+                  tcb->last_tv_sec = tv_sec;
+                  tcb->last_tv_usec = tv_usec;
+
+#if MAINLOOP_SPEW
+                  _dbus_verbose ("  invoking timeout\n");
+#endif
+
+                  /* can theoretically return FALSE on OOM, but we just
+                   * let it fire again later - in practice that's what
+                   * every wrapper callback in dbus-daemon used to do */
+                  dbus_timeout_handle (tcb->timeout);
+
+                  retval = TRUE;
+                }
+              else
+                {
+#if MAINLOOP_SPEW
+                  _dbus_verbose ("  timeout has not expired\n");
+#endif
+                }
+            }
+#if MAINLOOP_SPEW
+          else
+            {
+              _dbus_verbose ("  skipping invocation of disabled timeout\n");
+            }
+#endif
+
+          link = next;
+        }
+    }
+
+  if (n_ready > 0)
+    {
+      for (i = 0; i < n_ready; i++)
+        {
+          DBusList **watches;
+          DBusList *next;
+          unsigned int condition;
+          dbus_bool_t any_oom;
+
+          /* FIXME I think this "restart if we change the watches"
+           * approach could result in starving watches
+           * toward the end of the list.
+           */
+          if (initial_serial != loop->callback_list_serial)
+            goto next_iteration;
+
+          if (loop->depth != orig_depth)
+            goto next_iteration;
+
+          _dbus_assert (ready_fds[i].flags != 0);
+
+          if (_DBUS_UNLIKELY (ready_fds[i].flags & _DBUS_WATCH_NVAL))
+            {
+              cull_watches_for_invalid_fd (loop, ready_fds[i].fd);
+              goto next_iteration;
+            }
+
+          condition = ready_fds[i].flags;
+          _dbus_assert ((condition & _DBUS_WATCH_NVAL) == 0);
+
+          /* condition may still be 0 if we got some
+           * weird POLLFOO thing like POLLWRBAND
+           */
+          if (condition == 0)
+            continue;
+
+          watches = _dbus_hash_table_lookup_int (loop->watches,
+                                                 ready_fds[i].fd);
+
+          if (watches == NULL)
+            continue;
+
+          any_oom = FALSE;
+
+          for (link = _dbus_list_get_first_link (watches);
+              link != NULL;
+              link = next)
+            {
+              DBusWatch *watch = link->data;
+
+              next = _dbus_list_get_next_link (watches, link);
+
+              if (dbus_watch_get_enabled (watch))
+                {
+                  dbus_bool_t oom;
+
+                  oom = !dbus_watch_handle (watch, condition);
+
+                  if (oom)
+                    {
+                      _dbus_watch_set_oom_last_time (watch, TRUE);
+                      loop->oom_watch_pending = TRUE;
+                      any_oom = TRUE;
+                    }
+
+#if MAINLOOP_SPEW
+                  _dbus_verbose ("  Invoked watch, oom = %d\n", oom);
+#endif
+                  retval = TRUE;
+
+                  /* We re-check this every time, in case the callback
+                   * added/removed watches, which might make our position in
+                   * the linked list invalid. See the FIXME above. */
+                  if (initial_serial != loop->callback_list_serial ||
+                      loop->depth != orig_depth)
+                    {
+                      if (any_oom)
+                        refresh_watches_for_fd (loop, NULL, ready_fds[i].fd);
+
+                      goto next_iteration;
+                    }
+                }
+            }
+
+          if (any_oom)
+            refresh_watches_for_fd (loop, watches, ready_fds[i].fd);
+        }
+    }
+      
+ next_iteration:
+#if MAINLOOP_SPEW
+  _dbus_verbose ("  moving to next iteration\n");
+#endif
+
+  if (_dbus_loop_dispatch (loop))
+    retval = TRUE;
+  
+#if MAINLOOP_SPEW
+  _dbus_verbose ("Returning %d\n", retval);
+#endif
+  
+  return retval;
+}
+
+void
+_dbus_loop_run (DBusLoop *loop)
+{
+  int our_exit_depth;
+
+  _dbus_assert (loop->depth >= 0);
+  
+  _dbus_loop_ref (loop);
+  
+  our_exit_depth = loop->depth;
+  loop->depth += 1;
+
+  _dbus_verbose ("Running main loop, depth %d -> %d\n",
+                 loop->depth - 1, loop->depth);
+  
+  while (loop->depth != our_exit_depth)
+    _dbus_loop_iterate (loop, TRUE);
+
+  _dbus_loop_unref (loop);
+}
+
+void
+_dbus_loop_quit (DBusLoop *loop)
+{
+  _dbus_assert (loop->depth > 0);  
+  
+  loop->depth -= 1;
+
+  _dbus_verbose ("Quit main loop, depth %d -> %d\n",
+                 loop->depth + 1, loop->depth);
+}
+
+int
+_dbus_get_oom_wait (void)
+{
+#ifdef DBUS_BUILD_TESTS
+  /* make tests go fast */
+  return 0;
+#else
+  return 500;
+#endif
+}
+
+void
+_dbus_wait_for_memory (void)
+{
+  _dbus_verbose ("Waiting for more memory\n");
+  _dbus_sleep_milliseconds (_dbus_get_oom_wait ());
+}
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
diff --git a/dbus/dbus/dbus-mainloop.h b/dbus/dbus/dbus-mainloop.h
new file mode 100644
index 0000000..a76cb6f
--- /dev/null
+++ b/dbus/dbus/dbus-mainloop.h
@@ -0,0 +1,66 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-mainloop.h  Main loop utility
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_MAINLOOP_H
+#define DBUS_MAINLOOP_H
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include <dbus/dbus.h>
+
+typedef struct DBusLoop DBusLoop;
+
+typedef dbus_bool_t (* DBusWatchFunction)   (DBusWatch     *watch,
+                                             unsigned int   condition,
+                                             void          *data);
+
+DBusLoop*   _dbus_loop_new            (void);
+DBusLoop*   _dbus_loop_ref            (DBusLoop            *loop);
+void        _dbus_loop_unref          (DBusLoop            *loop);
+dbus_bool_t _dbus_loop_add_watch      (DBusLoop            *loop,
+                                       DBusWatch           *watch);
+void        _dbus_loop_remove_watch   (DBusLoop            *loop,
+                                       DBusWatch           *watch);
+void        _dbus_loop_toggle_watch   (DBusLoop            *loop,
+                                       DBusWatch           *watch);
+dbus_bool_t _dbus_loop_add_timeout    (DBusLoop            *loop,
+                                       DBusTimeout         *timeout);
+void        _dbus_loop_remove_timeout (DBusLoop            *loop,
+                                       DBusTimeout         *timeout);
+
+dbus_bool_t _dbus_loop_queue_dispatch (DBusLoop            *loop,
+                                       DBusConnection      *connection);
+
+void        _dbus_loop_run            (DBusLoop            *loop);
+void        _dbus_loop_quit           (DBusLoop            *loop);
+dbus_bool_t _dbus_loop_iterate        (DBusLoop            *loop,
+                                       dbus_bool_t          block);
+dbus_bool_t _dbus_loop_dispatch       (DBusLoop            *loop);
+
+int  _dbus_get_oom_wait    (void);
+void _dbus_wait_for_memory (void);
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif /* DBUS_MAINLOOP_H */
+
diff --git a/dbus/dbus/dbus-marshal-basic.c b/dbus/dbus/dbus-marshal-basic.c
new file mode 100644
index 0000000..88b19f3
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-basic.c
@@ -0,0 +1,1995 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-basic.c  Marshalling routines for basic (primitive) types
+ *
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-marshal-basic.h"
+#include "dbus-signature.h"
+
+#include <string.h>
+
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+# define _DBUS_ASSERT_ALIGNMENT(type, op, val) \
+  _DBUS_STATIC_ASSERT (__extension__ __alignof__ (type) op val)
+#else
+  /* not gcc, so probably no alignof operator: just use a no-op statement
+   * that's valid in the same contexts */
+# define _DBUS_ASSERT_ALIGNMENT(type, op, val) \
+  _DBUS_STATIC_ASSERT (TRUE)
+#endif
+
+/* True by definition, but just for completeness... */
+_DBUS_STATIC_ASSERT (sizeof (char) == 1);
+_DBUS_ASSERT_ALIGNMENT (char, ==, 1);
+
+_DBUS_STATIC_ASSERT (sizeof (dbus_int16_t) == 2);
+_DBUS_ASSERT_ALIGNMENT (dbus_int16_t, <=, 2);
+_DBUS_STATIC_ASSERT (sizeof (dbus_uint16_t) == 2);
+_DBUS_ASSERT_ALIGNMENT (dbus_uint16_t, <=, 2);
+
+_DBUS_STATIC_ASSERT (sizeof (dbus_int32_t) == 4);
+_DBUS_ASSERT_ALIGNMENT (dbus_int32_t, <=, 4);
+_DBUS_STATIC_ASSERT (sizeof (dbus_uint32_t) == 4);
+_DBUS_ASSERT_ALIGNMENT (dbus_uint32_t, <=, 4);
+_DBUS_STATIC_ASSERT (sizeof (dbus_bool_t) == 4);
+_DBUS_ASSERT_ALIGNMENT (dbus_bool_t, <=, 4);
+
+_DBUS_STATIC_ASSERT (sizeof (double) == 8);
+_DBUS_ASSERT_ALIGNMENT (double, <=, 8);
+
+#ifdef DBUS_HAVE_INT64
+_DBUS_STATIC_ASSERT (sizeof (dbus_int64_t) == 8);
+_DBUS_ASSERT_ALIGNMENT (dbus_int64_t, <=, 8);
+_DBUS_STATIC_ASSERT (sizeof (dbus_uint64_t) == 8);
+_DBUS_ASSERT_ALIGNMENT (dbus_uint64_t, <=, 8);
+#endif
+
+_DBUS_STATIC_ASSERT (sizeof (DBusBasicValue) >= 8);
+/* The alignment of a DBusBasicValue might conceivably be > 8 because of the
+ * pointer, so we don't assert about it */
+
+_DBUS_STATIC_ASSERT (sizeof (DBus8ByteStruct) == 8);
+_DBUS_ASSERT_ALIGNMENT (DBus8ByteStruct, <=, 8);
+
+/**
+ * @defgroup DBusMarshal marshaling and unmarshaling
+ * @ingroup  DBusInternals
+ * @brief functions to marshal/unmarshal data from the wire
+ *
+ * Types and functions related to converting primitive data types from
+ * wire format to native machine format, and vice versa.
+ *
+ * A signature is just a string with multiple types one after the other.
+ * for example a type is "i" or "(ii)", a signature is "i(ii)"
+ * where i is int and (ii) is struct { int; int; }
+ *
+ * @{
+ */
+
+static void
+pack_2_octets (dbus_uint16_t   value,
+               int             byte_order,
+               unsigned char  *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
+
+  if ((byte_order) == DBUS_LITTLE_ENDIAN)
+    *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_LE (value);
+  else
+    *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_BE (value);
+}
+
+static void
+pack_4_octets (dbus_uint32_t   value,
+               int             byte_order,
+               unsigned char  *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
+
+  if ((byte_order) == DBUS_LITTLE_ENDIAN)
+    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
+  else
+    *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
+}
+
+static void
+pack_8_octets (DBusBasicValue     value,
+               int                byte_order,
+               unsigned char     *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
+
+#ifdef DBUS_HAVE_INT64
+  if ((byte_order) == DBUS_LITTLE_ENDIAN)
+    *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u64);
+  else
+    *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64);
+#else
+  *(DBus8ByteStruct*)data = value.eight;
+  swap_8_octets ((DBusBasicValue*)data, byte_order);
+#endif
+}
+
+/**
+ * Packs a 32 bit unsigned integer into a data pointer.
+ *
+ * @param value the value
+ * @param byte_order the byte order to use
+ * @param data the data pointer
+ */
+void
+_dbus_pack_uint32 (dbus_uint32_t   value,
+                   int             byte_order,
+                   unsigned char  *data)
+{
+  pack_4_octets (value, byte_order, data);
+}
+
+#ifndef DBUS_HAVE_INT64
+/* from ORBit */
+static void
+swap_bytes (unsigned char *data,
+            unsigned int   len)
+{
+  unsigned char *p1 = data;
+  unsigned char *p2 = data + len - 1;
+
+  while (p1 < p2)
+    {
+      unsigned char tmp = *p1;
+      *p1 = *p2;
+      *p2 = tmp;
+
+      --p2;
+      ++p1;
+    }
+}
+#endif /* !DBUS_HAVE_INT64 */
+
+static void
+swap_8_octets (DBusBasicValue    *value,
+               int                byte_order)
+{
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    {
+#ifdef DBUS_HAVE_INT64
+      value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64);
+#else
+      swap_bytes (&value->bytes, 8);
+#endif
+    }
+}
+
+#if 0
+static DBusBasicValue
+unpack_8_octets (int                  byte_order,
+                 const unsigned char *data)
+{
+  DBusBasicValue r;
+
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
+  _dbus_assert (sizeof (r) == 8);
+
+#ifdef DBUS_HAVE_INT64
+  if (byte_order == DBUS_LITTLE_ENDIAN)
+    r.u64 = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
+  else
+    r.u64 = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
+#else
+  r.eight = *(DBus8ByteStruct*)data;
+  swap_8_octets (&r, byte_order);
+#endif
+
+  return r;
+}
+#endif
+
+#ifndef _dbus_unpack_uint16
+/**
+ * Unpacks a 16 bit unsigned integer from a data pointer
+ *
+ * @param byte_order The byte order to use
+ * @param data the data pointer
+ * @returns the integer
+ */
+dbus_uint16_t
+_dbus_unpack_uint16 (int                  byte_order,
+                     const unsigned char *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
+
+  if (byte_order == DBUS_LITTLE_ENDIAN)
+    return DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)data);
+  else
+    return DBUS_UINT16_FROM_BE (*(dbus_uint16_t*)data);
+}
+#endif /* _dbus_unpack_uint16 */
+
+#ifndef _dbus_unpack_uint32
+/**
+ * Unpacks a 32 bit unsigned integer from a data pointer
+ *
+ * @param byte_order The byte order to use
+ * @param data the data pointer
+ * @returns the integer
+ */
+dbus_uint32_t
+_dbus_unpack_uint32 (int                  byte_order,
+                     const unsigned char *data)
+{
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
+
+  if (byte_order == DBUS_LITTLE_ENDIAN)
+    return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
+  else
+    return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
+}
+#endif /* _dbus_unpack_uint32 */
+
+static void
+set_2_octets (DBusString          *str,
+              int                  offset,
+              dbus_uint16_t        value,
+              int                  byte_order)
+{
+  char *data;
+
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+
+  data = _dbus_string_get_data_len (str, offset, 2);
+
+  pack_2_octets (value, byte_order, data);
+}
+
+static void
+set_4_octets (DBusString          *str,
+              int                  offset,
+              dbus_uint32_t        value,
+              int                  byte_order)
+{
+  char *data;
+
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+
+  data = _dbus_string_get_data_len (str, offset, 4);
+
+  pack_4_octets (value, byte_order, data);
+}
+
+static void
+set_8_octets (DBusString          *str,
+              int                  offset,
+              DBusBasicValue       value,
+              int                  byte_order)
+{
+  char *data;
+
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+
+  data = _dbus_string_get_data_len (str, offset, 8);
+
+  pack_8_octets (value, byte_order, data);
+}
+
+/**
+ * Sets the 4 bytes at the given offset to a marshaled unsigned
+ * integer, replacing anything found there previously.
+ *
+ * @param str the string to write the marshalled int to
+ * @param pos the byte offset where int should be written
+ * @param value the value
+ * @param byte_order the byte order to use
+ *
+ */
+void
+_dbus_marshal_set_uint32 (DBusString          *str,
+                          int                  pos,
+                          dbus_uint32_t        value,
+                          int                  byte_order)
+{
+  set_4_octets (str, pos, value, byte_order);
+}
+
+/**
+ * Sets the existing marshaled string at the given offset with
+ * a new marshaled string. The given offset must point to
+ * an existing string or the wrong length will be deleted
+ * and replaced with the new string.
+ *
+ * Note: no attempt is made by this function to re-align
+ * any data which has been already marshalled after this
+ * string. Use with caution.
+ *
+ * @param str the string to write the marshalled string to
+ * @param pos the position of the marshaled string length
+ * @param value the value
+ * @param byte_order the byte order to use
+ * @param old_end_pos place to store byte after the nul byte of the old value
+ * @param new_end_pos place to store byte after the nul byte of the new value
+ * @returns #TRUE on success, #FALSE if no memory
+ *
+ */
+static dbus_bool_t
+set_string (DBusString          *str,
+            int                  pos,
+            const char          *value,
+            int                  byte_order,
+            int                 *old_end_pos,
+            int                 *new_end_pos)
+{
+  int old_len, new_len;
+  DBusString dstr;
+
+  _dbus_string_init_const (&dstr, value);
+
+  _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos);
+  old_len = _dbus_unpack_uint32 (byte_order,
+                                 _dbus_string_get_const_data_len (str, pos, 4));
+
+  new_len = _dbus_string_get_length (&dstr);
+
+  if (!_dbus_string_replace_len (&dstr, 0, new_len,
+                                 str, pos + 4, old_len))
+    return FALSE;
+
+  _dbus_marshal_set_uint32 (str, pos, new_len, byte_order);
+
+  if (old_end_pos)
+    *old_end_pos = pos + 4 + old_len + 1;
+  if (new_end_pos)
+    *new_end_pos = pos + 4 + new_len + 1;
+
+  return TRUE;
+}
+
+/**
+ * Sets the existing marshaled signature at the given offset to a new
+ * marshaled signature. Same basic ideas as set_string().
+ *
+ * @param str the string to write the marshalled signature to
+ * @param pos the position of the marshaled signature length
+ * @param value the value
+ * @param byte_order the byte order to use
+ * @param old_end_pos place to store byte after the nul byte of the old value
+ * @param new_end_pos place to store byte after the nul byte of the new value
+ * @returns #TRUE on success, #FALSE if no memory
+ *
+ */
+static dbus_bool_t
+set_signature (DBusString          *str,
+               int                  pos,
+               const char          *value,
+               int                  byte_order,
+               int                 *old_end_pos,
+               int                 *new_end_pos)
+{
+  int old_len, new_len;
+  DBusString dstr;
+
+  _dbus_string_init_const (&dstr, value);
+
+  old_len = _dbus_string_get_byte (str, pos);
+  new_len = _dbus_string_get_length (&dstr);
+
+  if (!_dbus_string_replace_len (&dstr, 0, new_len,
+                                 str, pos + 1, old_len))
+    return FALSE;
+
+  _dbus_string_set_byte (str, pos, new_len);
+
+  if (old_end_pos)
+    *old_end_pos = pos + 1 + old_len + 1;
+  if (new_end_pos)
+    *new_end_pos = pos + 1 + new_len + 1;
+
+  return TRUE;
+}
+
+/**
+ * Sets an existing basic type value to a new value.
+ * Arguments work the same way as _dbus_marshal_basic_type().
+ *
+ * @param str the string
+ * @param pos location of the current value
+ * @param type the type of the current and new values
+ * @param value the address of the new value
+ * @param byte_order byte order for marshaling
+ * @param old_end_pos location to store end position of the old value, or #NULL
+ * @param new_end_pos location to store end position of the new value, or #NULL
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_marshal_set_basic (DBusString       *str,
+                         int               pos,
+                         int               type,
+                         const void       *value,
+                         int               byte_order,
+                         int              *old_end_pos,
+                         int              *new_end_pos)
+{
+  const DBusBasicValue *vp;
+
+  vp = value;
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+      _dbus_string_set_byte (str, pos, vp->byt);
+      if (old_end_pos)
+        *old_end_pos = pos + 1;
+      if (new_end_pos)
+        *new_end_pos = pos + 1;
+      return TRUE;
+      break;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      pos = _DBUS_ALIGN_VALUE (pos, 2);
+      set_2_octets (str, pos, vp->u16, byte_order);
+      if (old_end_pos)
+        *old_end_pos = pos + 2;
+      if (new_end_pos)
+        *new_end_pos = pos + 2;
+      return TRUE;
+      break;
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_UNIX_FD:
+      pos = _DBUS_ALIGN_VALUE (pos, 4);
+      set_4_octets (str, pos, vp->u32, byte_order);
+      if (old_end_pos)
+        *old_end_pos = pos + 4;
+      if (new_end_pos)
+        *new_end_pos = pos + 4;
+      return TRUE;
+      break;
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      pos = _DBUS_ALIGN_VALUE (pos, 8);
+      set_8_octets (str, pos, *vp, byte_order);
+      if (old_end_pos)
+        *old_end_pos = pos + 8;
+      if (new_end_pos)
+        *new_end_pos = pos + 8;
+      return TRUE;
+      break;
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+      pos = _DBUS_ALIGN_VALUE (pos, 4);
+      _dbus_assert (vp->str != NULL);
+      return set_string (str, pos, vp->str, byte_order,
+                         old_end_pos, new_end_pos);
+      break;
+    case DBUS_TYPE_SIGNATURE:
+      _dbus_assert (vp->str != NULL);
+      return set_signature (str, pos, vp->str, byte_order,
+                            old_end_pos, new_end_pos);
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      return FALSE;
+      break;
+    }
+}
+
+/**
+ * Convenience function to demarshal a 32 bit unsigned integer.
+ *
+ * @param str the string containing the data
+ * @param byte_order the byte order
+ * @param pos the position in the string
+ * @param new_pos the new position of the string
+ * @returns the demarshaled integer.
+ */
+dbus_uint32_t
+_dbus_marshal_read_uint32  (const DBusString *str,
+                            int               pos,
+                            int               byte_order,
+                            int              *new_pos)
+{
+  pos = _DBUS_ALIGN_VALUE (pos, 4);
+
+  if (new_pos)
+    *new_pos = pos + 4;
+
+  _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
+  
+  return _dbus_unpack_uint32 (byte_order,
+                              _dbus_string_get_const_data (str) + pos);
+}
+
+/**
+ * Demarshals a basic-typed value. The "value" pointer is always
+ * the address of a variable of the basic type. So e.g.
+ * if the basic type is "double" then the pointer is
+ * a double*, and if it's "char*" then the pointer is
+ * a "char**".
+ *
+ * A value of type #DBusBasicValue is guaranteed to be large enough to
+ * hold any of the types that may be returned, which is handy if you
+ * are trying to do things generically. For example you can pass
+ * a DBusBasicValue* in to this function, and then pass the same
+ * DBusBasicValue* in to _dbus_marshal_basic_type() in order to
+ * move a value from one place to another.
+ *
+ * @param str the string containing the data
+ * @param pos position in the string
+ * @param type type of value to demarshal
+ * @param value pointer to return value data
+ * @param byte_order the byte order
+ * @param new_pos pointer to update with new position, or #NULL
+ **/
+void
+_dbus_marshal_read_basic (const DBusString      *str,
+                          int                    pos,
+                          int                    type,
+                          void                  *value,
+                          int                    byte_order,
+                          int                   *new_pos)
+{
+  const char *str_data;
+
+  _dbus_assert (dbus_type_is_basic (type));
+
+  str_data = _dbus_string_get_const_data (str);
+
+  /* Below we volatile types to avoid aliasing issues;
+   * see http://bugs.freedesktop.org/show_bug.cgi?id=20137
+   */
+  
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+      {
+      volatile unsigned char *vp = value;
+      *vp = (unsigned char) _dbus_string_get_byte (str, pos);
+      (pos)++;
+      }
+      break;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      {
+      volatile dbus_uint16_t *vp = value;
+      pos = _DBUS_ALIGN_VALUE (pos, 2);
+      *vp = *(dbus_uint16_t *)(str_data + pos);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+	*vp = DBUS_UINT16_SWAP_LE_BE (*vp);
+      pos += 2;
+      }
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_UNIX_FD:
+      {
+      volatile dbus_uint32_t *vp = value;
+      pos = _DBUS_ALIGN_VALUE (pos, 4);
+      *vp = *(dbus_uint32_t *)(str_data + pos);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+	*vp = DBUS_UINT32_SWAP_LE_BE (*vp);
+      pos += 4;
+      }
+      break;
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      {
+      volatile dbus_uint64_t *vp = value;
+      pos = _DBUS_ALIGN_VALUE (pos, 8);
+#ifdef DBUS_HAVE_INT64
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+        *vp = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
+      else
+        *vp = *(dbus_uint64_t*)(str_data + pos);
+#else
+      *vp = *(DBus8ByteStruct*) (str_data + pos);
+      swap_8_octets (vp, byte_order);
+#endif
+      pos += 8;
+      }
+      break;
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+      {
+        int len;
+        volatile char **vp = value;
+
+        len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
+
+        *vp = (char*) str_data + pos;
+
+        pos += len + 1; /* length plus nul */
+      }
+      break;
+    case DBUS_TYPE_SIGNATURE:
+      {
+        int len;
+        volatile char **vp = value;
+
+        len = _dbus_string_get_byte (str, pos);
+        pos += 1;
+
+        *vp = (char*) str_data + pos;
+
+        pos += len + 1; /* length plus nul */
+      }
+      break;
+    default:
+      _dbus_warn_check_failed ("type %s %d not a basic type\n",
+                               _dbus_type_to_string (type), type);
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+
+  if (new_pos)
+    *new_pos = pos;
+}
+
+static dbus_bool_t
+marshal_2_octets (DBusString   *str,
+                  int           insert_at,
+                  dbus_uint16_t value,
+                  int           byte_order,
+                  int          *pos_after)
+{
+  dbus_bool_t retval;
+  int orig_len;
+
+  _dbus_assert (sizeof (value) == 2);
+
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    value = DBUS_UINT16_SWAP_LE_BE (value);
+
+  orig_len = _dbus_string_get_length (str);
+
+  retval = _dbus_string_insert_2_aligned (str, insert_at,
+                                          (const unsigned char *)&value);
+
+  if (pos_after)
+    {
+      *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
+      _dbus_assert (*pos_after <= _dbus_string_get_length (str));
+    }
+
+  return retval;
+}
+
+static dbus_bool_t
+marshal_4_octets (DBusString   *str,
+                  int           insert_at,
+                  dbus_uint32_t value,
+                  int           byte_order,
+                  int          *pos_after)
+{
+  dbus_bool_t retval;
+  int orig_len;
+
+  _dbus_assert (sizeof (value) == 4);
+
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    value = DBUS_UINT32_SWAP_LE_BE (value);
+
+  orig_len = _dbus_string_get_length (str);
+
+  retval = _dbus_string_insert_4_aligned (str, insert_at,
+                                          (const unsigned char *)&value);
+
+  if (pos_after)
+    {
+      *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
+      _dbus_assert (*pos_after <= _dbus_string_get_length (str));
+    }
+
+  return retval;
+}
+
+static dbus_bool_t
+marshal_8_octets (DBusString    *str,
+                  int            insert_at,
+                  DBusBasicValue value,
+                  int            byte_order,
+                  int           *pos_after)
+{
+  dbus_bool_t retval;
+  int orig_len;
+
+  _dbus_assert (sizeof (value) == 8);
+
+  swap_8_octets (&value, byte_order);
+
+  orig_len = _dbus_string_get_length (str);
+
+  retval = _dbus_string_insert_8_aligned (str, insert_at,
+                                          (const unsigned char *)&value);
+
+  if (pos_after)
+    *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
+
+  return retval;
+}
+
+enum
+  {
+    MARSHAL_AS_STRING,
+    MARSHAL_AS_SIGNATURE,
+    MARSHAL_AS_BYTE_ARRAY
+  };
+
+static dbus_bool_t
+marshal_len_followed_by_bytes (int                  marshal_as,
+                               DBusString          *str,
+                               int                  insert_at,
+                               const unsigned char *value,
+                               int                  data_len, /* doesn't include nul if any */
+                               int                  byte_order,
+                               int                 *pos_after)
+{
+  int pos;
+  DBusString value_str;
+  int value_len;
+
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
+  if (insert_at > _dbus_string_get_length (str))
+    _dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
+                insert_at, _dbus_string_get_length (str), data_len);
+  
+  if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
+    value_len = data_len;
+  else
+    value_len = data_len + 1; /* value has a nul */
+
+  _dbus_string_init_const_len (&value_str, value, value_len);
+
+  pos = insert_at;
+
+  if (marshal_as == MARSHAL_AS_SIGNATURE)
+    {
+      _dbus_assert (data_len <= DBUS_MAXIMUM_SIGNATURE_LENGTH);
+      _dbus_assert (data_len <= 255); /* same as max sig len right now */
+      
+      if (!_dbus_string_insert_byte (str, pos, data_len))
+        goto oom;
+
+      pos += 1;
+    }
+  else
+    {
+      if (!marshal_4_octets (str, pos, data_len,
+                             byte_order, &pos))
+        goto oom;
+    }
+
+  if (!_dbus_string_copy_len (&value_str, 0, value_len,
+                              str, pos))
+    goto oom;
+
+#if 0
+  /* too expensive */
+  _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
+                                              str, pos));
+  _dbus_verbose_bytes_of_string (str, pos, value_len);
+#endif
+
+  pos += value_len;
+
+  if (pos_after)
+    *pos_after = pos;
+
+  return TRUE;
+
+ oom:
+  /* Delete what we've inserted */
+  _dbus_string_delete (str, insert_at, pos - insert_at);
+
+  return FALSE;
+}
+
+static dbus_bool_t
+marshal_string (DBusString    *str,
+                int            insert_at,
+                const char    *value,
+                int            byte_order,
+                int           *pos_after)
+{
+  return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
+                                        str, insert_at, value,
+                                        strlen (value),
+                                        byte_order, pos_after);
+}
+
+static dbus_bool_t
+marshal_signature (DBusString    *str,
+                   int            insert_at,
+                   const char    *value,
+                   int           *pos_after)
+{
+  return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
+                                        str, insert_at, value,
+                                        strlen (value),
+                                        DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
+                                        pos_after);
+}
+
+/**
+ * Marshals a basic-typed value. The "value" pointer is always the
+ * address of a variable containing the basic type value.
+ * So for example for int32 it will be dbus_int32_t*, and
+ * for string it will be const char**. This is for symmetry
+ * with _dbus_marshal_read_basic() and to have a simple
+ * consistent rule.
+ *
+ * @param str string to marshal to
+ * @param insert_at where to insert the value
+ * @param type type of value
+ * @param value pointer to a variable containing the value
+ * @param byte_order byte order
+ * @param pos_after #NULL or the position after the type
+ * @returns #TRUE on success
+ **/
+dbus_bool_t
+_dbus_marshal_write_basic (DBusString *str,
+                           int         insert_at,
+                           int         type,
+                           const void *value,
+                           int         byte_order,
+                           int        *pos_after)
+{
+  const DBusBasicValue *vp;
+
+  _dbus_assert (dbus_type_is_basic (type));
+
+  vp = value;
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+      if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
+        return FALSE;
+      if (pos_after)
+        *pos_after = insert_at + 1;
+      return TRUE;
+      break;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      return marshal_2_octets (str, insert_at, vp->u16,
+                               byte_order, pos_after);
+      break;
+    case DBUS_TYPE_BOOLEAN:
+      return marshal_4_octets (str, insert_at, vp->u32 != FALSE,
+                               byte_order, pos_after);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_UNIX_FD:
+      return marshal_4_octets (str, insert_at, vp->u32,
+                               byte_order, pos_after);
+      break;
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after);
+      break;
+
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+      _dbus_assert (vp->str != NULL);
+      return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
+      break;
+    case DBUS_TYPE_SIGNATURE:
+      _dbus_assert (vp->str != NULL);
+      return marshal_signature (str, insert_at, vp->str, pos_after);
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      return FALSE;
+      break;
+    }
+}
+
+static dbus_bool_t
+marshal_1_octets_array (DBusString          *str,
+                        int                  insert_at,
+                        const unsigned char *value,
+                        int                  n_elements,
+                        int                  byte_order,
+                        int                 *pos_after)
+{
+  int pos;
+  DBusString value_str;
+
+  _dbus_string_init_const_len (&value_str, value, n_elements);
+
+  pos = insert_at;
+
+  if (!_dbus_string_copy_len (&value_str, 0, n_elements,
+                              str, pos))
+    return FALSE;
+
+  pos += n_elements;
+
+  if (pos_after)
+    *pos_after = pos;
+
+  return TRUE;
+}
+
+/**
+ * Swaps the elements of an array to the opposite byte order
+ *
+ * @param data start of array
+ * @param n_elements number of elements
+ * @param alignment size of each element
+ */
+void
+_dbus_swap_array (unsigned char *data,
+                  int            n_elements,
+                  int            alignment)
+{
+  unsigned char *d;
+  unsigned char *end;
+
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data);
+
+  /* we use const_data and cast it off so DBusString can be a const string
+   * for the unit tests. don't ask.
+   */
+  d = data;
+  end = d + (n_elements * alignment);
+  
+  if (alignment == 8)
+    {
+      while (d != end)
+        {
+#ifdef DBUS_HAVE_INT64
+          *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
+#else
+          swap_8_bytes ((DBusBasicValue*) d);
+#endif
+          d += 8;
+        }
+    }
+  else if (alignment == 4)
+    {
+      while (d != end)
+        {
+          *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
+          d += 4;
+        }
+    }
+  else
+    {
+      _dbus_assert (alignment == 2);
+      
+      while (d != end)
+        {
+          *((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d));
+          d += 2;
+        }
+    }
+}
+
+static void
+swap_array (DBusString *str,
+            int         array_start,
+            int         n_elements,
+            int         byte_order,
+            int         alignment)
+{
+  _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
+
+  if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+    {
+      /* we use const_data and cast it off so DBusString can be a const string
+       * for the unit tests. don't ask.
+       */
+      _dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start),
+                        n_elements, alignment);
+    }
+}
+
+static dbus_bool_t
+marshal_fixed_multi (DBusString           *str,
+                     int                   insert_at,
+                     const DBusBasicValue *value,
+                     int                   n_elements,
+                     int                   byte_order,
+                     int                   alignment,
+                     int                  *pos_after)
+{
+  int old_string_len;
+  int array_start;
+  DBusString t;
+  int len_in_bytes;
+
+  _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
+  
+  old_string_len = _dbus_string_get_length (str);
+
+  len_in_bytes = n_elements * alignment;
+  array_start = insert_at;
+  
+  /* Note that we do alignment padding unconditionally
+   * even if the array is empty; this means that
+   * padding + len is always equal to the number of bytes
+   * in the array.
+   */
+
+  if (!_dbus_string_insert_alignment (str, &array_start, alignment))
+    goto error;
+
+  _dbus_string_init_const_len (&t,
+                               (const unsigned char*) value,
+                               len_in_bytes);
+
+  if (!_dbus_string_copy (&t, 0,
+                          str, array_start))
+    goto error;
+
+  swap_array (str, array_start, n_elements, byte_order, alignment);
+
+  if (pos_after)
+    *pos_after = array_start + len_in_bytes;
+  
+  return TRUE;
+
+ error:
+  _dbus_string_delete (str, insert_at,
+                       _dbus_string_get_length (str) - old_string_len);
+
+  return FALSE;
+}
+
+/**
+ * Marshals a block of values of fixed-length type all at once, as an
+ * optimization.  dbus_type_is_fixed() returns #TRUE for fixed-length
+ * types, which are the basic types minus the string-like types.
+ *
+ * The value argument should be the adddress of an
+ * array, so e.g. "const dbus_uint32_t**"
+ *
+ * @param str string to marshal to
+ * @param insert_at where to insert the value
+ * @param element_type type of array elements
+ * @param value address of an array to marshal
+ * @param n_elements number of elements in the array
+ * @param byte_order byte order
+ * @param pos_after #NULL or the position after the type
+ * @returns #TRUE on success
+ **/
+dbus_bool_t
+_dbus_marshal_write_fixed_multi (DBusString *str,
+                                 int         insert_at,
+                                 int         element_type,
+                                 const void *value,
+                                 int         n_elements,
+                                 int         byte_order,
+                                 int        *pos_after)
+{
+  const void* vp = *(const DBusBasicValue**)value;
+  
+  _dbus_assert (dbus_type_is_fixed (element_type));
+  _dbus_assert (n_elements >= 0);
+
+#if 0
+  _dbus_verbose ("writing %d elements of %s\n",
+                 n_elements, _dbus_type_to_string (element_type));
+#endif
+  
+  switch (element_type)
+    {
+    case DBUS_TYPE_BYTE:
+      return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
+      break;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 2, pos_after);
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_UNIX_FD:
+      return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
+      break;
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
+      break;
+
+    default:
+      _dbus_assert_not_reached ("non fixed type in array write");
+      break;
+    }
+
+  return FALSE;
+}
+
+
+/**
+ * Skips over a basic-typed value, reporting the following position.
+ *
+ * @param str the string containing the data
+ * @param type type of value to read
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
+ **/
+void
+_dbus_marshal_skip_basic (const DBusString      *str,
+                          int                    type,
+                          int                    byte_order,
+                          int                   *pos)
+{
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+  
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+      (*pos)++;
+      break;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 2);
+      *pos += 2;
+      break;
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_UNIX_FD:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 4);
+      *pos += 4;
+      break;
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 8);
+      *pos += 8;
+      break;
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+      {
+        int len;
+
+        len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
+        
+        *pos += len + 1; /* length plus nul */
+      }
+      break;
+    case DBUS_TYPE_SIGNATURE:
+      {
+        int len;
+
+        len = _dbus_string_get_byte (str, *pos);
+
+        *pos += len + 2; /* length byte plus length plus nul */
+      }
+      break;
+    default:
+      _dbus_warn ("type %s not a basic type\n",
+                  _dbus_type_to_string (type));
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+}
+
+/**
+ * Skips an array, returning the next position.
+ *
+ * @param str the string containing the data
+ * @param element_type the type of array elements
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
+ */
+void
+_dbus_marshal_skip_array (const DBusString  *str,
+                          int                element_type,
+                          int                byte_order,
+                          int               *pos)
+{
+  dbus_uint32_t array_len;
+  int i;
+  int alignment;
+
+  i = _DBUS_ALIGN_VALUE (*pos, 4);
+
+  array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
+
+  alignment = _dbus_type_get_alignment (element_type);
+
+  i = _DBUS_ALIGN_VALUE (i, alignment);
+
+  *pos = i + array_len;
+}
+
+/**
+ * Gets the alignment requirement for the given type;
+ * will be 1, 4, or 8.
+ *
+ * @param typecode the type
+ * @returns alignment of 1, 4, or 8
+ */
+int
+_dbus_type_get_alignment (int typecode)
+{
+  switch (typecode)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_VARIANT:
+    case DBUS_TYPE_SIGNATURE:
+      return 1;
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+      return 2;
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_UNIX_FD:
+      /* this stuff is 4 since it starts with a length */
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_ARRAY:
+      return 4;
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+      /* struct is 8 since it could contain an 8-aligned item
+       * and it's simpler to just always align structs to 8;
+       * we want the amount of padding in a struct of a given
+       * type to be predictable, not location-dependent.
+       * DICT_ENTRY is always the same as struct.
+       */
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
+      return 8;
+
+    default:
+      _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
+      return 0;
+    }
+}
+
+/**
+ * Returns a string describing the given type.
+ *
+ * @param typecode the type to describe
+ * @returns a constant string describing the type
+ */
+const char *
+_dbus_type_to_string (int typecode)
+{
+  switch (typecode)
+    {
+    case DBUS_TYPE_INVALID:
+      return "invalid";
+    case DBUS_TYPE_BOOLEAN:
+      return "boolean";
+    case DBUS_TYPE_BYTE:
+      return "byte";
+    case DBUS_TYPE_INT16:
+      return "int16";
+    case DBUS_TYPE_UINT16:
+      return "uint16";
+    case DBUS_TYPE_INT32:
+      return "int32";
+    case DBUS_TYPE_UINT32:
+      return "uint32";
+    case DBUS_TYPE_INT64:
+      return "int64";
+    case DBUS_TYPE_UINT64:
+      return "uint64";      
+    case DBUS_TYPE_DOUBLE:
+      return "double";
+    case DBUS_TYPE_STRING:
+      return "string";
+    case DBUS_TYPE_OBJECT_PATH:
+      return "object_path";
+    case DBUS_TYPE_SIGNATURE:
+      return "signature";
+    case DBUS_TYPE_STRUCT:
+      return "struct";
+    case DBUS_TYPE_DICT_ENTRY:
+      return "dict_entry";
+    case DBUS_TYPE_ARRAY:
+      return "array";
+    case DBUS_TYPE_VARIANT:
+      return "variant";
+    case DBUS_STRUCT_BEGIN_CHAR:
+      return "begin_struct";
+    case DBUS_STRUCT_END_CHAR:
+      return "end_struct";
+    case DBUS_DICT_ENTRY_BEGIN_CHAR:
+      return "begin_dict_entry";
+    case DBUS_DICT_ENTRY_END_CHAR:
+      return "end_dict_entry";
+    case DBUS_TYPE_UNIX_FD:
+      return "unix_fd";
+    default:
+      return "unknown";
+    }
+}
+
+/**
+ * If in verbose mode, print a block of binary data.
+ *
+ * @param data the data
+ * @param len the length of the data
+ * @param offset where to start counting for byte indexes
+ */
+void
+_dbus_verbose_bytes (const unsigned char *data,
+                     int                  len,
+                     int                  offset)
+{
+  int i;
+  const unsigned char *aligned;
+
+  _dbus_assert (len >= 0);
+
+  if (!_dbus_is_verbose())
+    return;
+
+  /* Print blanks on first row if appropriate */
+  aligned = _DBUS_ALIGN_ADDRESS (data, 4);
+  if (aligned > data)
+    aligned -= 4;
+  _dbus_assert (aligned <= data);
+
+  if (aligned != data)
+    {
+      _dbus_verbose ("%4ld\t%p: ", - (long)(data - aligned), aligned);
+      while (aligned != data)
+        {
+          _dbus_verbose ("    ");
+          ++aligned;
+        }
+    }
+
+  /* now print the bytes */
+  i = 0;
+  while (i < len)
+    {
+      if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
+        {
+          _dbus_verbose ("%4d\t%p: ",
+                         offset + i, &data[i]);
+        }
+
+      if (data[i] >= 32 &&
+          data[i] <= 126)
+        _dbus_verbose (" '%c' ", data[i]);
+      else
+        _dbus_verbose ("0x%s%x ",
+                       data[i] <= 0xf ? "0" : "", data[i]);
+
+      ++i;
+
+      if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
+        {
+          if (i > 3)
+            _dbus_verbose ("BE: %d LE: %d",
+                           _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
+                           _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
+
+          if (i > 7 &&
+              _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
+            {
+#ifdef DBUS_INT64_PRINTF_MODIFIER
+              _dbus_verbose (" u64: 0x%" DBUS_INT64_PRINTF_MODIFIER "x",
+                             *(dbus_uint64_t*)&data[i-8]);
+#endif
+              _dbus_verbose (" dbl: %g",
+                             *(double*)&data[i-8]);
+            }
+
+          _dbus_verbose ("\n");
+        }
+    }
+
+  _dbus_verbose ("\n");
+}
+
+/**
+ * Dump the given part of the string to verbose log.
+ *
+ * @param str the string
+ * @param start the start of range to dump
+ * @param len length of range
+ */
+void
+_dbus_verbose_bytes_of_string (const DBusString    *str,
+                               int                  start,
+                               int                  len)
+{
+  const char *d;
+  int real_len;
+
+  real_len = _dbus_string_get_length (str);
+
+  _dbus_assert (start >= 0);
+
+  if (start > real_len)
+    {
+      _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
+                     start, len, real_len);
+      return;
+    }
+
+  if ((start + len) > real_len)
+    {
+      _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
+                     start, len, real_len);
+      len = real_len - start;
+    }
+
+  d = _dbus_string_get_const_data_len (str, start, len);
+
+  _dbus_verbose_bytes (d, len, start);
+}
+
+static int
+map_type_char_to_type (int t)
+{
+  if (t == DBUS_STRUCT_BEGIN_CHAR)
+    return DBUS_TYPE_STRUCT;
+  else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
+    return DBUS_TYPE_DICT_ENTRY;
+  else
+    {
+      _dbus_assert (t != DBUS_STRUCT_END_CHAR);
+      _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
+      return t;
+    }
+}
+
+/**
+ * Get the first type in the signature. The difference between this
+ * and just getting the first byte of the signature is that you won't
+ * get DBUS_STRUCT_BEGIN_CHAR, you'll get DBUS_TYPE_STRUCT
+ * instead.
+ *
+ * @param str string containing signature
+ * @param pos where the signature starts
+ * @returns the first type in the signature
+ */
+int
+_dbus_first_type_in_signature (const DBusString *str,
+                               int               pos)
+{
+  return map_type_char_to_type (_dbus_string_get_byte (str, pos));
+}
+
+/**
+ * Similar to #_dbus_first_type_in_signature, but operates
+ * on a C string buffer.
+ *
+ * @param str a C string buffer
+ * @param pos where the signature starts
+ * @returns the first type in the signature
+ */
+int
+_dbus_first_type_in_signature_c_str (const char       *str,
+				     int               pos)
+{
+  return map_type_char_to_type (str[pos]);
+}
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+
+/**
+ * Reads a block of fixed-length basic values, as an optimization
+ * vs. reading each one individually into a new buffer.
+ *
+ * This function returns the data in-place; it does not make a copy,
+ * and it does not swap the bytes.
+ *
+ * If you ask for #DBUS_TYPE_DOUBLE you will get a "const double*" back
+ * and the "value" argument should be a "const double**" and so on.
+ *
+ * @param str the string to read from
+ * @param pos position to read from
+ * @param element_type type of array elements
+ * @param value place to return the array
+ * @param n_elements number of array elements to read
+ * @param byte_order the byte order, used to read the array length
+ * @param new_pos #NULL or location to store a position after the elements
+ */
+void
+_dbus_marshal_read_fixed_multi  (const DBusString *str,
+                                 int               pos,
+                                 int               element_type,
+                                 void             *value,
+                                 int               n_elements,
+                                 int               byte_order,
+                                 int              *new_pos)
+{
+  int array_len;
+  int alignment;
+
+  _dbus_assert (dbus_type_is_fixed (element_type));
+  _dbus_assert (dbus_type_is_basic (element_type));
+
+#if 0
+  _dbus_verbose ("reading %d elements of %s\n",
+                 n_elements, _dbus_type_to_string (element_type));
+#endif
+  
+  alignment = _dbus_type_get_alignment (element_type);
+
+  pos = _DBUS_ALIGN_VALUE (pos, alignment);
+  
+  array_len = n_elements * alignment;
+
+  *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
+  if (new_pos)
+    *new_pos = pos + array_len;
+}
+
+static void
+swap_test_array (void *array,
+                 int   len_bytes,
+                 int   byte_order,
+                 int   alignment)
+{
+  DBusString t;
+
+  if (alignment == 1)
+    return;
+  
+  _dbus_string_init_const_len (&t, array, len_bytes);
+  swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
+}
+
+#define MARSHAL_BASIC(typename, byte_order, literal)                    \
+  do {                                                                  \
+     v_##typename = literal;                                            \
+     if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename,   \
+                                    &v_##typename,                      \
+                                    byte_order, NULL))                  \
+       _dbus_assert_not_reached ("no memory");                          \
+   } while (0)
+
+#define DEMARSHAL_BASIC(typename, byte_order)                                   \
+  do {                                                                          \
+    _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
+                              byte_order, &pos);                                \
+  } while (0)
+
+#define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
+  do {                                                                                  \
+    DEMARSHAL_BASIC (typename, byte_order);                                             \
+    if (literal != v_##typename)                                                        \
+      {                                                                                 \
+        _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
+                                     _dbus_string_get_length (&str) - dump_pos);        \
+        _dbus_assert_not_reached ("demarshaled wrong value");                           \
+      }                                                                                 \
+  } while (0)
+
+#define MARSHAL_TEST(typename, byte_order, literal)             \
+  do {                                                          \
+    MARSHAL_BASIC (typename, byte_order, literal);              \
+    dump_pos = pos;                                             \
+    DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
+  } while (0)
+
+#define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
+  do {                                                                                  \
+    MARSHAL_BASIC (typename, byte_order, literal);                                      \
+    dump_pos = pos;                                                                     \
+    DEMARSHAL_BASIC (typename, byte_order);                                             \
+    if (strcmp (literal, v_##typename) != 0)                                            \
+      {                                                                                 \
+        _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
+                                       _dbus_string_get_length (&str) - dump_pos);      \
+        _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
+        _dbus_assert_not_reached ("demarshaled wrong value");                           \
+      }                                                                                 \
+  } while (0)
+
+#define MARSHAL_FIXED_ARRAY(typename, byte_order, literal)                                      \
+  do {                                                                                          \
+     int next;                                                                                  \
+     v_UINT32 = sizeof(literal);                                                                \
+     if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32,                    \
+                                     byte_order, &next))                                        \
+       _dbus_assert_not_reached ("no memory");                                                  \
+     v_ARRAY_##typename = literal;                                                              \
+     if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename,                    \
+                                           &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal),      \
+                                           byte_order, NULL))                                   \
+       _dbus_assert_not_reached ("no memory");                                                  \
+   } while (0)
+
+#define DEMARSHAL_FIXED_ARRAY(typename, byte_order)                                             \
+  do {                                                                                          \
+    int next;                                                                                   \
+    alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename);                                \
+    v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next);                   \
+    _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, &v_ARRAY_##typename,      \
+                                    v_UINT32/alignment,                                         \
+                                    byte_order, NULL);                                          \
+    swap_test_array (v_ARRAY_##typename, v_UINT32,                                              \
+                     byte_order, alignment);                                                    \
+  } while (0)
+
+#define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal)                  \
+  do {                                                                                  \
+    DEMARSHAL_FIXED_ARRAY (typename, byte_order);                                       \
+    if (memcmp (literal, v_ARRAY_##typename, sizeof (literal) != 0))                    \
+      {                                                                                 \
+        _dbus_verbose ("MARSHALED DATA\n");                                             \
+        _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
+                                      _dbus_string_get_length (&str) - dump_pos);       \
+        _dbus_verbose ("LITERAL DATA\n");                                               \
+        _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0);                      \
+        _dbus_verbose ("READ DATA\n");                                                  \
+        _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0);           \
+        _dbus_assert_not_reached ("demarshaled wrong fixed array value");               \
+      }                                                                                 \
+  } while (0)
+
+#define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal)         \
+  do {                                                                  \
+    MARSHAL_FIXED_ARRAY (typename, byte_order, literal);                \
+    dump_pos = pos;                                                     \
+    DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal);    \
+  } while (0)
+
+dbus_bool_t
+_dbus_marshal_test (void)
+{
+  int alignment;
+  DBusString str;
+  int pos, dump_pos;
+  unsigned char array1[5] = { 3, 4, 0, 1, 9 };
+  dbus_int16_t array2[3] = { 124, 457, 780 };
+  dbus_int32_t array4[3] = { 123, 456, 789 };
+#ifdef DBUS_HAVE_INT64
+  dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
+                             DBUS_INT64_CONSTANT (0x456ffffffff),
+                             DBUS_INT64_CONSTANT (0x789ffffffff) };
+  dbus_int64_t *v_ARRAY_INT64;
+#endif
+  unsigned char *v_ARRAY_BYTE;
+  dbus_int16_t *v_ARRAY_INT16;
+  dbus_uint16_t *v_ARRAY_UINT16;
+  dbus_int32_t *v_ARRAY_INT32;
+  dbus_uint32_t *v_ARRAY_UINT32;
+  DBusString t;
+  double v_DOUBLE;
+  double t_DOUBLE;
+  dbus_int16_t v_INT16;
+  dbus_uint16_t v_UINT16;
+  dbus_int32_t v_INT32;
+  dbus_uint32_t v_UINT32;
+  dbus_int64_t v_INT64;
+  dbus_uint64_t v_UINT64;
+  unsigned char v_BYTE;
+  dbus_bool_t v_BOOLEAN;
+  const char *v_STRING;
+  const char *v_SIGNATURE;
+  const char *v_OBJECT_PATH;
+  int byte_order;
+
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("failed to init string");
+
+  pos = 0;
+
+  /* Marshal doubles */
+  MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
+  DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
+  t_DOUBLE = 3.14;
+  if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
+    _dbus_assert_not_reached ("got wrong double value");
+
+  MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
+  DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
+  t_DOUBLE = 3.14;
+  if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
+    _dbus_assert_not_reached ("got wrong double value");
+
+  /* Marshal signed 16 integers */
+  MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345);
+  MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345);
+
+  /* Marshal unsigned 16 integers */
+  MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234);
+  MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234);
+  
+  /* Marshal signed integers */
+  MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
+  MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
+
+  /* Marshal unsigned integers */
+  MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
+  MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
+
+#ifdef DBUS_HAVE_INT64
+  /* Marshal signed integers */
+  MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
+  MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
+
+  /* Marshal unsigned integers */
+  MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
+  MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
+#endif /* DBUS_HAVE_INT64 */
+
+  /* Marshal byte */
+  MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
+  MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
+
+  /* Marshal all possible bools! */
+  MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
+  MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
+  MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
+  MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
+
+  /* Marshal strings */
+  MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
+  MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
+  MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
+  MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
+
+  /* object paths */
+  MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
+  MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
+
+  /* signatures */
+  MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
+  MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
+  MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
+  MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
+
+  /* Arrays */
+  MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
+  MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
+  MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2);
+  MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2);
+  
+  MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
+  MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
+  MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4);
+  MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4);
+
+  MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
+  MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
+  
+#ifdef DBUS_HAVE_INT64
+  MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
+  MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
+#endif
+
+#if 0
+
+  /*
+   * FIXME restore the set/pack tests
+   */
+
+#ifdef DBUS_HAVE_INT64
+  /* set/pack 64-bit integers */
+  _dbus_string_set_length (&str, 8);
+
+  /* signed little */
+  _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
+                           0, DBUS_INT64_CONSTANT (-0x123456789abc7));
+
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed big */
+  _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
+                           0, DBUS_INT64_CONSTANT (-0x123456789abc7));
+
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed little pack */
+  _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
+                    DBUS_LITTLE_ENDIAN,
+                    _dbus_string_get_data (&str));
+
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed big pack */
+  _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
+                    DBUS_BIG_ENDIAN,
+                    _dbus_string_get_data (&str));
+
+  _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
+                _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* unsigned little */
+  _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
+                            0, DBUS_UINT64_CONSTANT (0x123456789abc7));
+
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+  /* unsigned big */
+  _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
+                            0, DBUS_UINT64_CONSTANT (0x123456789abc7));
+
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+  /* unsigned little pack */
+  _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
+                     DBUS_LITTLE_ENDIAN,
+                     _dbus_string_get_data (&str));
+
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+  /* unsigned big pack */
+  _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
+                     DBUS_BIG_ENDIAN,
+                     _dbus_string_get_data (&str));
+
+  _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
+                _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+#endif /* DBUS_HAVE_INT64 */
+
+  /* set/pack 32-bit integers */
+  _dbus_string_set_length (&str, 4);
+
+  /* signed little */
+  _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
+                           0, -0x123456);
+
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed big */
+  _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
+                           0, -0x123456);
+
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed little pack */
+  _dbus_pack_int32 (-0x123456,
+                    DBUS_LITTLE_ENDIAN,
+                    _dbus_string_get_data (&str));
+
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* signed big pack */
+  _dbus_pack_int32 (-0x123456,
+                    DBUS_BIG_ENDIAN,
+                    _dbus_string_get_data (&str));
+
+  _dbus_assert (-0x123456 ==
+                _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
+                                    _dbus_string_get_const_data (&str)));
+
+  /* unsigned little */
+  _dbus_marshal_set_uint32 (&str,
+                            0, 0x123456,
+                            DBUS_LITTLE_ENDIAN);
+
+  _dbus_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+  /* unsigned big */
+  _dbus_marshal_set_uint32 (&str,
+                            0, 0x123456,
+                            DBUS_BIG_ENDIAN);
+
+  _dbus_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+  /* unsigned little pack */
+  _dbus_pack_uint32 (0x123456,
+                     DBUS_LITTLE_ENDIAN,
+                     _dbus_string_get_data (&str));
+
+  _dbus_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+  /* unsigned big pack */
+  _dbus_pack_uint32 (0x123456,
+                     DBUS_BIG_ENDIAN,
+                     _dbus_string_get_data (&str));
+
+  _dbus_assert (0x123456 ==
+                _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
+                                     _dbus_string_get_const_data (&str)));
+
+#endif /* set/pack tests for integers */
+
+  /* Strings in-place set */
+  byte_order = DBUS_LITTLE_ENDIAN;
+  while (TRUE)
+    {
+      /* Init a string */
+      _dbus_string_set_length (&str, 0);
+
+      /* reset pos for the macros */
+      pos = 0;
+
+      MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
+
+      /* Set it to something longer */
+      _dbus_string_init_const (&t, "Hello world foo");
+
+      v_STRING = _dbus_string_get_const_data (&t);
+      _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
+                               &v_STRING, byte_order, NULL, NULL);
+
+      _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
+                                &v_STRING, byte_order,
+                                NULL);
+      _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
+
+      /* Set it to something shorter */
+      _dbus_string_init_const (&t, "Hello");
+
+      v_STRING = _dbus_string_get_const_data (&t);
+      _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
+                               &v_STRING, byte_order, NULL, NULL);
+      _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
+                                &v_STRING, byte_order,
+                                NULL);
+      _dbus_assert (strcmp (v_STRING, "Hello") == 0);
+
+      /* Do the other byte order */
+      if (byte_order == DBUS_LITTLE_ENDIAN)
+        byte_order = DBUS_BIG_ENDIAN;
+      else
+        break;
+    }
+
+  /* Clean up */
+  _dbus_string_free (&str);
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-marshal-basic.h b/dbus/dbus/dbus-marshal-basic.h
new file mode 100644
index 0000000..034fdab
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-basic.h
@@ -0,0 +1,237 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-basic.h  Marshalling routines for basic (primitive) types
+ *
+ * Copyright (C) 2002  CodeFactory AB
+ * Copyright (C) 2004, 2005  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef DBUS_MARSHAL_BASIC_H
+#define DBUS_MARSHAL_BASIC_H
+
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif
+
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-arch-deps.h>
+#include <dbus/dbus-string.h>
+
+#ifdef WORDS_BIGENDIAN
+#define DBUS_COMPILER_BYTE_ORDER DBUS_BIG_ENDIAN
+#else
+#define DBUS_COMPILER_BYTE_ORDER DBUS_LITTLE_ENDIAN
+#endif
+
+#ifdef HAVE_BYTESWAP_H
+#define DBUS_UINT16_SWAP_LE_BE_CONSTANT(val) bswap_16(val)
+#define DBUS_UINT32_SWAP_LE_BE_CONSTANT(val) bswap_32(val)
+#else /* HAVE_BYTESWAP_H */
+
+#define DBUS_UINT16_SWAP_LE_BE_CONSTANT(val)	((dbus_uint16_t) (      \
+    (dbus_uint16_t) ((dbus_uint16_t) (val) >> 8) |                      \
+    (dbus_uint16_t) ((dbus_uint16_t) (val) << 8)))
+
+#define DBUS_UINT32_SWAP_LE_BE_CONSTANT(val)	((dbus_uint32_t) (      \
+    (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x000000ffU) << 24) |     \
+    (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x0000ff00U) <<  8) |     \
+    (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x00ff0000U) >>  8) |     \
+    (((dbus_uint32_t) (val) & (dbus_uint32_t) 0xff000000U) >> 24)))
+
+#endif /* HAVE_BYTESWAP_H */
+
+#ifdef DBUS_HAVE_INT64
+
+#ifdef HAVE_BYTESWAP_H
+#define DBUS_UINT64_SWAP_LE_BE_CONSTANT(val) bswap_64(val)
+#else /* HAVE_BYTESWAP_H */
+
+#define DBUS_UINT64_SWAP_LE_BE_CONSTANT(val)	((dbus_uint64_t) (              \
+      (((dbus_uint64_t) (val) &                                                 \
+	(dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00000000000000ff)) << 56) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+	(dbus_uint64_t) DBUS_UINT64_CONSTANT (0x000000000000ff00)) << 40) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+	(dbus_uint64_t) DBUS_UINT64_CONSTANT (0x0000000000ff0000)) << 24) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+	(dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00000000ff000000)) <<  8) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+	(dbus_uint64_t) DBUS_UINT64_CONSTANT (0x000000ff00000000)) >>  8) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+	(dbus_uint64_t) DBUS_UINT64_CONSTANT (0x0000ff0000000000)) >> 24) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+	(dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00ff000000000000)) >> 40) |    \
+      (((dbus_uint64_t) (val) &                                                 \
+	(dbus_uint64_t) DBUS_UINT64_CONSTANT (0xff00000000000000)) >> 56)))
+#endif /* DBUS_HAVE_INT64 */
+
+#endif /* HAVE_BYTESWAP_H */
+
+#define DBUS_UINT16_SWAP_LE_BE(val) (DBUS_UINT16_SWAP_LE_BE_CONSTANT (val))
+#define DBUS_INT16_SWAP_LE_BE(val)  ((dbus_int16_t)DBUS_UINT16_SWAP_LE_BE_CONSTANT (val))
+
+#define DBUS_UINT32_SWAP_LE_BE(val) (DBUS_UINT32_SWAP_LE_BE_CONSTANT (val))
+#define DBUS_INT32_SWAP_LE_BE(val)  ((dbus_int32_t)DBUS_UINT32_SWAP_LE_BE_CONSTANT (val))
+
+#ifdef DBUS_HAVE_INT64
+#  define DBUS_UINT64_SWAP_LE_BE(val) (DBUS_UINT64_SWAP_LE_BE_CONSTANT (val))
+#  define DBUS_INT64_SWAP_LE_BE(val)  ((dbus_int64_t)DBUS_UINT64_SWAP_LE_BE_CONSTANT (val))
+#endif /* DBUS_HAVE_INT64 */
+
+#ifdef WORDS_BIGENDIAN
+
+#  define DBUS_INT16_TO_BE(val)	((dbus_int16_t) (val))
+#  define DBUS_UINT16_TO_BE(val)	((dbus_uint16_t) (val))
+#  define DBUS_INT16_TO_LE(val)	(DBUS_INT16_SWAP_LE_BE (val))
+#  define DBUS_UINT16_TO_LE(val)	(DBUS_UINT16_SWAP_LE_BE (val))
+#  define DBUS_INT32_TO_BE(val)	((dbus_int32_t) (val))
+#  define DBUS_UINT32_TO_BE(val)	((dbus_uint32_t) (val))
+#  define DBUS_INT32_TO_LE(val)	(DBUS_INT32_SWAP_LE_BE (val))
+#  define DBUS_UINT32_TO_LE(val)	(DBUS_UINT32_SWAP_LE_BE (val))
+#  ifdef DBUS_HAVE_INT64
+#    define DBUS_INT64_TO_BE(val)	((dbus_int64_t) (val))
+#    define DBUS_UINT64_TO_BE(val)	((dbus_uint64_t) (val))
+#    define DBUS_INT64_TO_LE(val)	(DBUS_INT64_SWAP_LE_BE (val))
+#    define DBUS_UINT64_TO_LE(val)	(DBUS_UINT64_SWAP_LE_BE (val))
+#  endif /* DBUS_HAVE_INT64 */
+
+#else /* WORDS_BIGENDIAN */
+
+#  define DBUS_INT16_TO_LE(val)	((dbus_int16_t) (val))
+#  define DBUS_UINT16_TO_LE(val)	((dbus_uint16_t) (val))
+#  define DBUS_INT16_TO_BE(val)	((dbus_int16_t) DBUS_UINT16_SWAP_LE_BE (val))
+#  define DBUS_UINT16_TO_BE(val)	(DBUS_UINT16_SWAP_LE_BE (val))
+#  define DBUS_INT32_TO_LE(val)	((dbus_int32_t) (val))
+#  define DBUS_UINT32_TO_LE(val)	((dbus_uint32_t) (val))
+#  define DBUS_INT32_TO_BE(val)	((dbus_int32_t) DBUS_UINT32_SWAP_LE_BE (val))
+#  define DBUS_UINT32_TO_BE(val)	(DBUS_UINT32_SWAP_LE_BE (val))
+#  ifdef DBUS_HAVE_INT64
+#    define DBUS_INT64_TO_LE(val)	((dbus_int64_t) (val))
+#    define DBUS_UINT64_TO_LE(val)	((dbus_uint64_t) (val))
+#    define DBUS_INT64_TO_BE(val)	((dbus_int64_t) DBUS_UINT64_SWAP_LE_BE (val))
+#    define DBUS_UINT64_TO_BE(val)	(DBUS_UINT64_SWAP_LE_BE (val))
+#  endif /* DBUS_HAVE_INT64 */
+#endif
+
+/* The transformation is symmetric, so the FROM just maps to the TO. */
+#define DBUS_INT16_FROM_LE(val)	 (DBUS_INT16_TO_LE (val))
+#define DBUS_UINT16_FROM_LE(val) (DBUS_UINT16_TO_LE (val))
+#define DBUS_INT16_FROM_BE(val)	 (DBUS_INT16_TO_BE (val))
+#define DBUS_UINT16_FROM_BE(val) (DBUS_UINT16_TO_BE (val))
+#define DBUS_INT32_FROM_LE(val)	 (DBUS_INT32_TO_LE (val))
+#define DBUS_UINT32_FROM_LE(val) (DBUS_UINT32_TO_LE (val))
+#define DBUS_INT32_FROM_BE(val)	 (DBUS_INT32_TO_BE (val))
+#define DBUS_UINT32_FROM_BE(val) (DBUS_UINT32_TO_BE (val))
+#ifdef DBUS_HAVE_INT64
+#  define DBUS_INT64_FROM_LE(val)	 (DBUS_INT64_TO_LE (val))
+#  define DBUS_UINT64_FROM_LE(val) (DBUS_UINT64_TO_LE (val))
+#  define DBUS_INT64_FROM_BE(val)	 (DBUS_INT64_TO_BE (val))
+#  define DBUS_UINT64_FROM_BE(val) (DBUS_UINT64_TO_BE (val))
+#endif /* DBUS_HAVE_INT64 */
+
+#ifdef DBUS_DISABLE_ASSERT
+#define _dbus_unpack_uint16(byte_order, data)           \
+   (((byte_order) == DBUS_LITTLE_ENDIAN) ?              \
+     DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)(data)) :    \
+     DBUS_UINT16_FROM_BE (*(dbus_uint16_t*)(data)))
+
+#define _dbus_unpack_uint32(byte_order, data)           \
+   (((byte_order) == DBUS_LITTLE_ENDIAN) ?              \
+     DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)(data)) :    \
+     DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)(data)))
+#endif
+
+#ifndef _dbus_unpack_uint16
+dbus_uint16_t _dbus_unpack_uint16 (int                  byte_order,
+                                   const unsigned char *data);
+#endif
+
+void          _dbus_pack_uint32   (dbus_uint32_t        value,
+                                   int                  byte_order,
+                                   unsigned char       *data);
+#ifndef _dbus_unpack_uint32
+dbus_uint32_t _dbus_unpack_uint32 (int                  byte_order,
+                                   const unsigned char *data);
+#endif
+
+dbus_bool_t   _dbus_marshal_set_basic         (DBusString       *str,
+                                               int               pos,
+                                               int               type,
+                                               const void       *value,
+                                               int               byte_order,
+                                               int              *old_end_pos,
+                                               int              *new_end_pos);
+dbus_bool_t   _dbus_marshal_write_basic       (DBusString       *str,
+                                               int               insert_at,
+                                               int               type,
+                                               const void       *value,
+                                               int               byte_order,
+                                               int              *pos_after);
+dbus_bool_t   _dbus_marshal_write_fixed_multi (DBusString       *str,
+                                               int               insert_at,
+                                               int               element_type,
+                                               const void       *value,
+                                               int               n_elements,
+                                               int               byte_order,
+                                               int              *pos_after);
+void          _dbus_marshal_read_basic        (const DBusString *str,
+                                               int               pos,
+                                               int               type,
+                                               void             *value,
+                                               int               byte_order,
+                                               int              *new_pos);
+void          _dbus_marshal_read_fixed_multi  (const DBusString *str,
+                                               int               pos,
+                                               int               element_type,
+                                               void             *value,
+                                               int               n_elements,
+                                               int               byte_order,
+                                               int              *new_pos);
+void          _dbus_marshal_skip_basic        (const DBusString *str,
+                                               int               type,
+                                               int               byte_order,
+                                               int              *pos);
+void          _dbus_marshal_skip_array        (const DBusString *str,
+                                               int               element_type,
+                                               int               byte_order,
+                                               int              *pos);
+void          _dbus_marshal_set_uint32        (DBusString       *str,
+                                               int               pos,
+                                               dbus_uint32_t     value,
+                                               int               byte_order);
+dbus_uint32_t _dbus_marshal_read_uint32       (const DBusString *str,
+                                               int               pos,
+                                               int               byte_order,
+                                               int              *new_pos);
+int           _dbus_type_get_alignment        (int               typecode);
+int           _dbus_type_get_alignment        (int               typecode);
+const char*   _dbus_type_to_string            (int               typecode);
+
+int           _dbus_first_type_in_signature   (const DBusString *str,
+                                               int               pos);
+
+int           _dbus_first_type_in_signature_c_str   (const char       *str,
+						     int               pos);
+
+void _dbus_swap_array (unsigned char *data,
+                       int            n_elements,
+                       int            alignment);
+
+#endif /* DBUS_MARSHAL_BASIC_H */
diff --git a/dbus/dbus/dbus-marshal-byteswap-util.c b/dbus/dbus/dbus-marshal-byteswap-util.c
new file mode 100644
index 0000000..edb74ca
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-byteswap-util.c
@@ -0,0 +1,105 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-byteswap-util.c  Would be in dbus-marshal-byteswap.c but tests/bus only
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#ifdef DBUS_BUILD_TESTS 
+#include "dbus-marshal-byteswap.h"
+#include "dbus-test.h"
+#include <stdio.h>
+
+static void
+do_byteswap_test (int byte_order)
+{
+  int sequence;
+  DBusString signature;
+  DBusString body;
+  int opposite_order;
+
+  if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
+    _dbus_assert_not_reached ("oom");
+
+  opposite_order = byte_order == DBUS_LITTLE_ENDIAN ? DBUS_BIG_ENDIAN : DBUS_LITTLE_ENDIAN;
+  
+  sequence = 0;
+  while (dbus_internal_do_not_use_generate_bodies (sequence,
+                                                   byte_order,
+                                                   &signature, &body))
+    {
+      DBusString copy;
+      DBusTypeReader body_reader;
+      DBusTypeReader copy_reader;
+
+      if (!_dbus_string_init (&copy))
+        _dbus_assert_not_reached ("oom");
+
+      if (!_dbus_string_copy (&body, 0, &copy, 0))
+        _dbus_assert_not_reached ("oom");
+
+      _dbus_marshal_byteswap (&signature, 0,
+                              byte_order,
+                              opposite_order,
+                              &copy, 0);
+
+      _dbus_type_reader_init (&body_reader, byte_order, &signature, 0,
+                              &body, 0);
+      _dbus_type_reader_init (&copy_reader, opposite_order, &signature, 0,
+                              &copy, 0);
+      
+      if (!_dbus_type_reader_equal_values (&body_reader, &copy_reader))
+        {
+          _dbus_verbose_bytes_of_string (&signature, 0,
+                                         _dbus_string_get_length (&signature));
+          _dbus_verbose_bytes_of_string (&body, 0,
+                                         _dbus_string_get_length (&body));
+          _dbus_verbose_bytes_of_string (&copy, 0,
+                                         _dbus_string_get_length (&copy));
+
+          _dbus_warn ("Byte-swapped data did not have same values as original data\n");
+          _dbus_assert_not_reached ("test failed");
+        }
+      
+      _dbus_string_free (&copy);
+      
+      _dbus_string_set_length (&signature, 0);
+      _dbus_string_set_length (&body, 0);
+      ++sequence;
+    }
+
+  _dbus_string_free (&signature);
+  _dbus_string_free (&body);
+
+  printf ("  %d blocks swapped from order '%c' to '%c'\n",
+          sequence, byte_order, opposite_order);
+}
+
+dbus_bool_t
+_dbus_marshal_byteswap_test (void)
+{
+  do_byteswap_test (DBUS_LITTLE_ENDIAN);
+  do_byteswap_test (DBUS_BIG_ENDIAN);
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-marshal-byteswap.c b/dbus/dbus/dbus-marshal-byteswap.c
new file mode 100644
index 0000000..22d7e22
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-byteswap.c
@@ -0,0 +1,252 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-byteswap.c  Swap a block of marshaled data
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-marshal-byteswap.h"
+#include "dbus-marshal-basic.h"
+#include "dbus-signature.h"
+
+/**
+ * @addtogroup DBusMarshal
+ * @{
+ */
+
+static void
+byteswap_body_helper (DBusTypeReader       *reader,
+                      dbus_bool_t           walk_reader_to_end,
+                      int                   old_byte_order,
+                      int                   new_byte_order,
+                      unsigned char        *p,
+                      unsigned char       **new_p)
+{
+  int current_type;
+
+  while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
+    {
+      switch (current_type)
+        {
+        case DBUS_TYPE_BYTE:
+          ++p;
+          break;
+
+        case DBUS_TYPE_INT16:
+        case DBUS_TYPE_UINT16:
+          {
+            p = _DBUS_ALIGN_ADDRESS (p, 2);
+            *((dbus_uint16_t*)p) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)p));
+            p += 2;
+          }
+          break;
+          
+        case DBUS_TYPE_BOOLEAN:
+        case DBUS_TYPE_INT32:
+        case DBUS_TYPE_UINT32:
+          {
+            p = _DBUS_ALIGN_ADDRESS (p, 4);
+            *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p));
+            p += 4;
+          }
+          break;
+          
+        case DBUS_TYPE_INT64:
+        case DBUS_TYPE_UINT64:
+        case DBUS_TYPE_DOUBLE:
+          {
+            p = _DBUS_ALIGN_ADDRESS (p, 8);
+#ifdef DBUS_HAVE_INT64
+            *((dbus_uint64_t*)p) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)p));
+#else
+            _dbus_swap_array (p, 1, 8);
+#endif
+            p += 8;
+          }
+          break;
+
+        case DBUS_TYPE_ARRAY:
+        case DBUS_TYPE_STRING:
+        case DBUS_TYPE_OBJECT_PATH:
+          {
+            dbus_uint32_t array_len;
+            
+            p = _DBUS_ALIGN_ADDRESS (p, 4);
+
+            array_len = _dbus_unpack_uint32 (old_byte_order, p);
+
+            *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p));
+            p += 4;
+
+            if (current_type == DBUS_TYPE_ARRAY)
+              {
+                int elem_type;
+                int alignment;
+
+                elem_type = _dbus_type_reader_get_element_type (reader);
+                alignment = _dbus_type_get_alignment (elem_type);
+
+		_dbus_assert ((array_len / alignment) < DBUS_MAXIMUM_ARRAY_LENGTH);
+
+                p = _DBUS_ALIGN_ADDRESS (p, alignment);
+                
+                if (dbus_type_is_fixed (elem_type))
+                  {
+                    if (alignment > 1)
+		      _dbus_swap_array (p, array_len / alignment, alignment);
+		    p += array_len;
+                  }
+                else
+                  {
+                    DBusTypeReader sub;
+                    const unsigned char *array_end;
+
+                    array_end = p + array_len;
+                    
+                    _dbus_type_reader_recurse (reader, &sub);
+
+                    while (p < array_end)
+                      {
+                        byteswap_body_helper (&sub,
+                                              FALSE,
+                                              old_byte_order,
+                                              new_byte_order,
+                                              p, &p);
+                      }
+                  }
+              }
+            else
+              {
+                _dbus_assert (current_type == DBUS_TYPE_STRING ||
+                              current_type == DBUS_TYPE_OBJECT_PATH);
+                
+                p += (array_len + 1); /* + 1 for nul */
+              }
+          }
+          break;
+
+        case DBUS_TYPE_SIGNATURE:
+          {
+            dbus_uint32_t sig_len;
+
+            sig_len = *p;
+            
+            p += (sig_len + 2); /* +2 for len and nul */
+          }
+          break;
+
+        case DBUS_TYPE_VARIANT:
+          {
+            /* 1 byte sig len, sig typecodes, align to
+             * contained-type-boundary, values.
+             */
+            dbus_uint32_t sig_len;
+            DBusString sig;
+            DBusTypeReader sub;
+            int contained_alignment;
+
+            sig_len = *p;
+            ++p;
+
+            _dbus_string_init_const_len (&sig, p, sig_len);
+
+            p += (sig_len + 1); /* 1 for nul */
+
+            contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (&sig, 0));
+            
+            p = _DBUS_ALIGN_ADDRESS (p, contained_alignment);
+
+            _dbus_type_reader_init_types_only (&sub, &sig, 0);
+
+            byteswap_body_helper (&sub, FALSE, old_byte_order, new_byte_order, p, &p);
+          }
+          break;
+
+        case DBUS_TYPE_STRUCT:
+        case DBUS_TYPE_DICT_ENTRY:
+          {
+            DBusTypeReader sub;
+
+            p = _DBUS_ALIGN_ADDRESS (p, 8);
+            
+            _dbus_type_reader_recurse (reader, &sub);
+            
+            byteswap_body_helper (&sub, TRUE, old_byte_order, new_byte_order, p, &p);
+          }
+          break;
+
+        case DBUS_TYPE_UNIX_FD:
+          /* fds can only be passed on a local machine, so byte order must always match */
+          _dbus_assert_not_reached("attempted to byteswap unix fds which makes no sense");
+          break;
+
+        default:
+          _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
+          break;
+        }
+
+      if (walk_reader_to_end)
+        _dbus_type_reader_next (reader);
+      else
+        break;
+    }
+
+  if (new_p)
+    *new_p = p;
+}
+
+/**
+ * Byteswaps the marshaled data in the given value_str.
+ *
+ * @param signature the types in the value_str
+ * @param signature_start where in signature is the signature
+ * @param old_byte_order the old byte order
+ * @param new_byte_order the new byte order
+ * @param value_str the string containing the body
+ * @param value_pos where the values start
+ */
+void
+_dbus_marshal_byteswap (const DBusString *signature,
+                        int               signature_start,
+                        int               old_byte_order,
+                        int               new_byte_order,
+                        DBusString       *value_str,
+                        int               value_pos)
+{
+  DBusTypeReader reader;
+
+  _dbus_assert (value_pos >= 0);
+  _dbus_assert (value_pos <= _dbus_string_get_length (value_str));
+
+  if (old_byte_order == new_byte_order)
+    return;
+  
+  _dbus_type_reader_init_types_only (&reader,
+                                     signature, signature_start);
+
+  byteswap_body_helper (&reader, TRUE,
+                        old_byte_order, new_byte_order,
+                        _dbus_string_get_data_len (value_str, value_pos, 0),
+                        NULL);
+}
+
+/** @} */
+
+/* Tests in dbus-marshal-byteswap-util.c */
diff --git a/dbus/dbus/dbus-marshal-byteswap.h b/dbus/dbus/dbus-marshal-byteswap.h
new file mode 100644
index 0000000..be2dd75
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-byteswap.h
@@ -0,0 +1,37 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-byteswap.h  Swap a block of marshaled data
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef DBUS_MARSHAL_BYTESWAP_H
+#define DBUS_MARSHAL_BYTESWAP_H
+
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-marshal-recursive.h>
+
+void _dbus_marshal_byteswap (const DBusString *signature,
+                             int               signature_start,
+                             int               old_byte_order,
+                             int               new_byte_order,
+                             DBusString       *value_str,
+                             int               value_pos);
+
+#endif /* DBUS_MARSHAL_BYTESWAP_H */
diff --git a/dbus/dbus/dbus-marshal-header.c b/dbus/dbus/dbus-marshal-header.c
new file mode 100644
index 0000000..88887a8
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-header.c
@@ -0,0 +1,1512 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-header.c  Managing marshaling/demarshaling of message headers
+ *
+ * Copyright (C) 2005  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus/dbus-shared.h"
+#include "dbus-marshal-header.h"
+#include "dbus-marshal-recursive.h"
+#include "dbus-marshal-byteswap.h"
+
+/**
+ * @addtogroup DBusMarshal
+ *
+ * @{
+ */
+
+
+/* Not thread locked, but strictly const/read-only so should be OK
+ */
+/** Static #DBusString containing the signature of a message header */
+_DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE);
+/** Static #DBusString containing the local interface */
+_DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str,  DBUS_INTERFACE_LOCAL);
+/** Static #DBusString containing the local path */
+_DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str,       DBUS_PATH_LOCAL);
+
+/** Offset from start of _dbus_header_signature_str to the signature of the fields array */
+#define FIELDS_ARRAY_SIGNATURE_OFFSET 6
+/** Offset from start of _dbus_header_signature_str to the signature of an element of the fields array */
+#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
+
+
+/** Offset to byte order from start of header */
+#define BYTE_ORDER_OFFSET    0
+/** Offset to type from start of header */
+#define TYPE_OFFSET          1
+/** Offset to flags from start of header */
+#define FLAGS_OFFSET         2
+/** Offset to version from start of header */
+#define VERSION_OFFSET       3
+/** Offset to body length from start of header */
+#define BODY_LENGTH_OFFSET 4
+/** Offset to client serial from start of header */
+#define SERIAL_OFFSET 8
+/** Offset to fields array length from start of header */
+#define FIELDS_ARRAY_LENGTH_OFFSET 12
+/** Offset to first field in header */
+#define FIRST_FIELD_OFFSET 16
+
+typedef struct
+{
+  unsigned char code; /**< the field code */
+  unsigned char type; /**< the value type */
+} HeaderFieldType;
+
+static const HeaderFieldType
+_dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = {
+  { DBUS_HEADER_FIELD_INVALID, DBUS_TYPE_INVALID },
+  { DBUS_HEADER_FIELD_PATH, DBUS_TYPE_OBJECT_PATH },
+  { DBUS_HEADER_FIELD_INTERFACE, DBUS_TYPE_STRING },
+  { DBUS_HEADER_FIELD_MEMBER, DBUS_TYPE_STRING },
+  { DBUS_HEADER_FIELD_ERROR_NAME, DBUS_TYPE_STRING },
+  { DBUS_HEADER_FIELD_REPLY_SERIAL, DBUS_TYPE_UINT32 },
+  { DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING },
+  { DBUS_HEADER_FIELD_SENDER, DBUS_TYPE_STRING },
+  { DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE },
+  { DBUS_HEADER_FIELD_UNIX_FDS, DBUS_TYPE_UINT32 }
+};
+
+/** Macro to look up the correct type for a field */
+#define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
+
+/** The most padding we could ever need for a header */
+#define MAX_POSSIBLE_HEADER_PADDING 7
+static dbus_bool_t
+reserve_header_padding (DBusHeader *header)
+{
+  _dbus_assert (header->padding <= MAX_POSSIBLE_HEADER_PADDING);
+
+  if (!_dbus_string_lengthen (&header->data,
+                              MAX_POSSIBLE_HEADER_PADDING - header->padding))
+    return FALSE;
+  header->padding = MAX_POSSIBLE_HEADER_PADDING;
+  return TRUE;
+}
+
+static void
+correct_header_padding (DBusHeader *header)
+{
+  int unpadded_len;
+
+  _dbus_assert (header->padding == 7);
+
+  _dbus_string_shorten (&header->data, header->padding);
+  unpadded_len = _dbus_string_get_length (&header->data);
+
+  if (!_dbus_string_align_length (&header->data, 8))
+    _dbus_assert_not_reached ("couldn't pad header though enough padding was preallocated");
+
+  header->padding = _dbus_string_get_length (&header->data) - unpadded_len;
+}
+
+/** Compute the end of the header, ignoring padding */
+#define HEADER_END_BEFORE_PADDING(header) \
+  (_dbus_string_get_length (&(header)->data) - (header)->padding)
+
+/**
+ * Invalidates all fields in the cache. This may be used when the
+ * cache is totally uninitialized (contains junk) so should not
+ * look at what's in there now.
+ *
+ * @param header the header
+ */
+static void
+_dbus_header_cache_invalidate_all (DBusHeader *header)
+{
+  int i;
+
+  i = 0;
+  while (i <= DBUS_HEADER_FIELD_LAST)
+    {
+      header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN;
+      ++i;
+    }
+}
+
+/**
+ * Caches one field
+ *
+ * @param header the header
+ * @param field_code the field
+ * @param variant_reader the reader for the variant in the field
+ */
+static void
+_dbus_header_cache_one (DBusHeader     *header,
+                        int             field_code,
+                        DBusTypeReader *variant_reader)
+{
+  header->fields[field_code].value_pos =
+    _dbus_type_reader_get_value_pos (variant_reader);
+
+#if 0
+  _dbus_verbose ("cached value_pos %d for field %d\n",
+                 header->fields[field_code].value_pos, field_code)
+#endif
+}
+
+/**
+ * Returns the header's byte order.
+ *
+ * @param header the header
+ * @returns the byte order
+ */
+char
+_dbus_header_get_byte_order (const DBusHeader *header)
+{
+  _dbus_assert (_dbus_string_get_length (&header->data) > BYTE_ORDER_OFFSET);
+
+  return (char) _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET);
+}
+
+/**
+ * Revalidates the fields cache
+ *
+ * @param header the header
+ */
+static void
+_dbus_header_cache_revalidate (DBusHeader *header)
+{
+  DBusTypeReader array;
+  DBusTypeReader reader;
+  int i;
+
+  i = 0;
+  while (i <= DBUS_HEADER_FIELD_LAST)
+    {
+      header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
+      ++i;
+    }
+
+  _dbus_type_reader_init (&reader,
+                          _dbus_header_get_byte_order (header),
+                          &_dbus_header_signature_str,
+                          FIELDS_ARRAY_SIGNATURE_OFFSET,
+                          &header->data,
+                          FIELDS_ARRAY_LENGTH_OFFSET);
+
+  _dbus_type_reader_recurse (&reader, &array);
+
+  while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
+    {
+      DBusTypeReader sub;
+      DBusTypeReader variant;
+      unsigned char field_code;
+
+      _dbus_type_reader_recurse (&array, &sub);
+
+      _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
+      _dbus_type_reader_read_basic (&sub, &field_code);
+
+      /* Unknown fields should be ignored */
+      if (field_code > DBUS_HEADER_FIELD_LAST)
+        goto next_field;
+
+      _dbus_type_reader_next (&sub);
+
+      _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_VARIANT);
+      _dbus_type_reader_recurse (&sub, &variant);
+
+      _dbus_header_cache_one (header, field_code, &variant);
+
+    next_field:
+      _dbus_type_reader_next (&array);
+    }
+}
+
+/**
+ * Checks for a field, updating the cache if required.
+ *
+ * @param header the header
+ * @param field the field to check
+ * @returns #FALSE if the field doesn't exist
+ */
+static dbus_bool_t
+_dbus_header_cache_check (DBusHeader    *header,
+                          int            field)
+{
+  _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
+
+  if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
+    _dbus_header_cache_revalidate (header);
+
+  if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * Checks whether a field is known not to exist. It may exist
+ * even if it's not known to exist.
+ *
+ * @param header the header
+ * @param field the field to check
+ * @returns #FALSE if the field definitely doesn't exist
+ */
+static dbus_bool_t
+_dbus_header_cache_known_nonexistent (DBusHeader    *header,
+                                      int            field)
+{
+  _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
+
+  return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
+}
+
+/**
+ * Writes a struct of { byte, variant } with the given basic type.
+ *
+ * @param writer the writer (should be ready to write a struct)
+ * @param type the type of the value
+ * @param value the value as for _dbus_marshal_set_basic()
+ * @returns #FALSE if no memory
+ */
+static dbus_bool_t
+write_basic_field (DBusTypeWriter *writer,
+                   int             field,
+                   int             type,
+                   const void     *value)
+{
+  DBusTypeWriter sub;
+  DBusTypeWriter variant;
+  int start;
+  int padding;
+  unsigned char field_byte;
+  DBusString contained_type;
+  char buf[2];
+
+  start = writer->value_pos;
+  padding = _dbus_string_get_length (writer->value_str) - start;
+
+  if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
+                                  NULL, 0, &sub))
+    goto append_failed;
+
+  field_byte = field;
+  if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE,
+                                      &field_byte))
+    goto append_failed;
+
+  buf[0] = type;
+  buf[1] = '\0';
+  _dbus_string_init_const_len (&contained_type, buf, 1);
+
+  if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT,
+                                  &contained_type, 0, &variant))
+    goto append_failed;
+
+  if (!_dbus_type_writer_write_basic (&variant, type, value))
+    goto append_failed;
+
+  if (!_dbus_type_writer_unrecurse (&sub, &variant))
+    goto append_failed;
+
+  if (!_dbus_type_writer_unrecurse (writer, &sub))
+    goto append_failed;
+
+  return TRUE;
+
+ append_failed:
+  _dbus_string_delete (writer->value_str,
+                       start,
+                       _dbus_string_get_length (writer->value_str) - start - padding);
+  return FALSE;
+}
+
+/**
+ * Sets a struct of { byte, variant } with the given basic type.
+ *
+ * @param reader the reader (should be iterating over the array pointing at the field to set)
+ * @param type the type of the value
+ * @param value the value as for _dbus_marshal_set_basic()
+ * @param realign_root where to realign from
+ * @returns #FALSE if no memory
+ */
+static dbus_bool_t
+set_basic_field (DBusTypeReader       *reader,
+                 int                   field,
+                 int                   type,
+                 const void           *value,
+                 const DBusTypeReader *realign_root)
+{
+  DBusTypeReader sub;
+  DBusTypeReader variant;
+
+  _dbus_type_reader_recurse (reader, &sub);
+
+  _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
+#ifndef DBUS_DISABLE_ASSERT
+ {
+   unsigned char v_BYTE;
+   _dbus_type_reader_read_basic (&sub, &v_BYTE);
+   _dbus_assert (((int) v_BYTE) == field);
+ }
+#endif
+
+  if (!_dbus_type_reader_next (&sub))
+    _dbus_assert_not_reached ("no variant field?");
+
+  _dbus_type_reader_recurse (&sub, &variant);
+  _dbus_assert (_dbus_type_reader_get_current_type (&variant) == type);
+
+  if (!_dbus_type_reader_set_basic (&variant, value, realign_root))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * Gets the type of the message.
+ *
+ * @param header the header
+ * @returns the type
+ */
+int
+_dbus_header_get_message_type (DBusHeader *header)
+{
+  int type;
+
+  type = _dbus_string_get_byte (&header->data, TYPE_OFFSET);
+  _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
+
+  return type;
+}
+
+/**
+ * Sets the serial number of a header.  This can only be done once on
+ * a header.
+ *
+ * @param header the header
+ * @param serial the serial
+ */
+void
+_dbus_header_set_serial (DBusHeader    *header,
+                         dbus_uint32_t  serial)
+{
+  /* we use this function to set the serial on outgoing
+   * messages, and to reset the serial in dbus_message_copy;
+   * this assertion should catch a double-set on outgoing.
+   */
+  _dbus_assert (_dbus_header_get_serial (header) == 0 ||
+                serial == 0);
+
+  _dbus_marshal_set_uint32 (&header->data,
+                            SERIAL_OFFSET,
+			    serial,
+                            _dbus_header_get_byte_order (header));
+}
+
+/**
+ * See dbus_message_get_serial()
+ *
+ * @param header the header
+ * @returns the client serial
+ */
+dbus_uint32_t
+_dbus_header_get_serial (DBusHeader *header)
+{
+  return _dbus_marshal_read_uint32 (&header->data,
+                                    SERIAL_OFFSET,
+                                    _dbus_header_get_byte_order (header),
+                                    NULL);
+}
+
+/**
+ * Re-initializes a header that was previously initialized and never
+ * freed.  After this, to make the header valid you have to call
+ * _dbus_header_create().
+ *
+ * @param header header to re-initialize
+ */
+void
+_dbus_header_reinit (DBusHeader *header)
+{
+  _dbus_string_set_length (&header->data, 0);
+
+  header->padding = 0;
+
+  _dbus_header_cache_invalidate_all (header);
+}
+
+/**
+ * Initializes a header, but doesn't prepare it for use;
+ * to make the header valid, you have to call _dbus_header_create().
+ *
+ * @param header header to initialize
+ * @param byte_order byte order of the header
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_header_init (DBusHeader *header)
+{
+  if (!_dbus_string_init_preallocated (&header->data, 32))
+    return FALSE;
+
+  _dbus_header_reinit (header);
+
+  return TRUE;
+}
+
+/**
+ * Frees a header.
+ *
+ * @param header the header
+ */
+void
+_dbus_header_free (DBusHeader *header)
+{
+  _dbus_string_free (&header->data);
+}
+
+/**
+ * Initializes dest with a copy of the given header.
+ * Resets the message serial to 0 on the copy.
+ *
+ * @param header header to copy
+ * @param dest destination for copy
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_header_copy (const DBusHeader *header,
+                   DBusHeader       *dest)
+{
+  *dest = *header;
+
+  if (!_dbus_string_init_preallocated (&dest->data,
+                                       _dbus_string_get_length (&header->data)))
+    return FALSE;
+
+  if (!_dbus_string_copy (&header->data, 0, &dest->data, 0))
+    {
+      _dbus_string_free (&dest->data);
+      return FALSE;
+    }
+
+  /* Reset the serial */
+  _dbus_header_set_serial (dest, 0);
+
+  return TRUE;
+}
+
+/**
+ * Fills in the primary fields of the header, so the header is ready
+ * for use. #NULL may be specified for some or all of the fields to
+ * avoid adding those fields. Some combinations of fields don't make
+ * sense, and passing them in will trigger an assertion failure.
+ *
+ * @param header the header
+ * @param message_type the message type
+ * @param destination destination field or #NULL
+ * @param path path field or #NULL
+ * @param interface interface field or #NULL
+ * @param member member field or #NULL
+ * @param error_name error name or #NULL
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_header_create (DBusHeader  *header,
+                     int          byte_order,
+                     int          message_type,
+                     const char  *destination,
+                     const char  *path,
+                     const char  *interface,
+                     const char  *member,
+                     const char  *error_name)
+{
+  unsigned char v_BYTE;
+  dbus_uint32_t v_UINT32;
+  DBusTypeWriter writer;
+  DBusTypeWriter array;
+
+  _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+                byte_order == DBUS_BIG_ENDIAN);
+  _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
+                (error_name) ||
+                !(interface || member || error_name));
+  _dbus_assert (_dbus_string_get_length (&header->data) == 0);
+
+  if (!reserve_header_padding (header))
+    return FALSE;
+
+  _dbus_type_writer_init_values_only (&writer, byte_order,
+                                      &_dbus_header_signature_str, 0,
+                                      &header->data,
+                                      HEADER_END_BEFORE_PADDING (header));
+
+  v_BYTE = byte_order;
+  if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
+                                      &v_BYTE))
+    goto oom;
+
+  v_BYTE = message_type;
+  if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
+                                      &v_BYTE))
+    goto oom;
+
+  v_BYTE = 0; /* flags */
+  if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
+                                      &v_BYTE))
+    goto oom;
+
+  v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION;
+  if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
+                                      &v_BYTE))
+    goto oom;
+
+  v_UINT32 = 0; /* body length */
+  if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
+                                      &v_UINT32))
+    goto oom;
+
+  v_UINT32 = 0; /* serial */
+  if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
+                                      &v_UINT32))
+    goto oom;
+
+  if (!_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY,
+                                  &_dbus_header_signature_str,
+                                  FIELDS_ARRAY_SIGNATURE_OFFSET,
+                                  &array))
+    goto oom;
+
+  /* Marshal all the fields (Marshall Fields?) */
+
+  if (path != NULL)
+    {
+      if (!write_basic_field (&array,
+                              DBUS_HEADER_FIELD_PATH,
+                              DBUS_TYPE_OBJECT_PATH,
+                              &path))
+        goto oom;
+    }
+
+  if (destination != NULL)
+    {
+      if (!write_basic_field (&array,
+                              DBUS_HEADER_FIELD_DESTINATION,
+                              DBUS_TYPE_STRING,
+                              &destination))
+        goto oom;
+    }
+
+  if (interface != NULL)
+    {
+      if (!write_basic_field (&array,
+                              DBUS_HEADER_FIELD_INTERFACE,
+                              DBUS_TYPE_STRING,
+                              &interface))
+        goto oom;
+    }
+
+  if (member != NULL)
+    {
+      if (!write_basic_field (&array,
+                              DBUS_HEADER_FIELD_MEMBER,
+                              DBUS_TYPE_STRING,
+                              &member))
+        goto oom;
+    }
+
+  if (error_name != NULL)
+    {
+      if (!write_basic_field (&array,
+                              DBUS_HEADER_FIELD_ERROR_NAME,
+                              DBUS_TYPE_STRING,
+                              &error_name))
+        goto oom;
+    }
+
+  if (!_dbus_type_writer_unrecurse (&writer, &array))
+    goto oom;
+
+  correct_header_padding (header);
+
+  return TRUE;
+
+ oom:
+  _dbus_string_delete (&header->data, 0,
+                       _dbus_string_get_length (&header->data) - header->padding);
+  correct_header_padding (header);
+
+  return FALSE;
+}
+
+/**
+ * Given data long enough to contain the length of the message body
+ * and the fields array, check whether the data is long enough to
+ * contain the entire message (assuming the claimed lengths are
+ * accurate). Also checks that the lengths are in sanity parameters.
+ *
+ * @param max_message_length maximum length of a valid message
+ * @param validity return location for why the data is invalid if it is
+ * @param byte_order return location for byte order
+ * @param fields_array_len return location for claimed fields array length
+ * @param header_len return location for claimed header length
+ * @param body_len return location for claimed body length
+ * @param str the data
+ * @param start start of data, 8-aligned
+ * @param len length of data
+ * @returns #TRUE if the data is long enough for the claimed length, and the lengths were valid
+ */
+dbus_bool_t
+_dbus_header_have_message_untrusted (int                max_message_length,
+                                     DBusValidity      *validity,
+                                     int               *byte_order,
+                                     int               *fields_array_len,
+                                     int               *header_len,
+                                     int               *body_len,
+                                     const DBusString  *str,
+                                     int                start,
+                                     int                len)
+
+{
+  dbus_uint32_t header_len_unsigned;
+  dbus_uint32_t fields_array_len_unsigned;
+  dbus_uint32_t body_len_unsigned;
+
+  _dbus_assert (start >= 0);
+  _dbus_assert (start < _DBUS_INT32_MAX / 2);
+  _dbus_assert (len >= 0);
+
+  _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
+
+  *byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET);
+
+  if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN)
+    {
+      *validity = DBUS_INVALID_BAD_BYTE_ORDER;
+      return FALSE;
+    }
+
+  _dbus_assert (FIELDS_ARRAY_LENGTH_OFFSET + 4 <= len);
+  fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET,
+                                                         *byte_order, NULL);
+
+  if (fields_array_len_unsigned > (unsigned) max_message_length)
+    {
+      *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
+      return FALSE;
+    }
+
+  _dbus_assert (BODY_LENGTH_OFFSET + 4 < len);
+  body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET,
+                                                 *byte_order, NULL);
+
+  if (body_len_unsigned > (unsigned) max_message_length)
+    {
+      *validity = DBUS_INVALID_INSANE_BODY_LENGTH;
+      return FALSE;
+    }
+
+  header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned;
+  header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
+
+  /* overflow should be impossible since the lengths aren't allowed to
+   * be huge.
+   */
+  _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2);
+  if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length)
+    {
+      *validity = DBUS_INVALID_MESSAGE_TOO_LONG;
+      return FALSE;
+    }
+
+  _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX);
+  _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX);
+  _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX);
+
+  *body_len = body_len_unsigned;
+  *fields_array_len = fields_array_len_unsigned;
+  *header_len = header_len_unsigned;
+
+  *validity = DBUS_VALID;
+
+  _dbus_verbose ("have %d bytes, need body %u + header %u = %u\n",
+                 len, body_len_unsigned, header_len_unsigned,
+                 body_len_unsigned + header_len_unsigned);
+
+  return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
+}
+
+static DBusValidity
+check_mandatory_fields (DBusHeader *header)
+{
+#define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
+
+  switch (_dbus_header_get_message_type (header))
+    {
+    case DBUS_MESSAGE_TYPE_SIGNAL:
+      REQUIRE_FIELD (INTERFACE);
+      /* FALL THRU - signals also require the path and member */
+    case DBUS_MESSAGE_TYPE_METHOD_CALL:
+      REQUIRE_FIELD (PATH);
+      REQUIRE_FIELD (MEMBER);
+      break;
+    case DBUS_MESSAGE_TYPE_ERROR:
+      REQUIRE_FIELD (ERROR_NAME);
+      REQUIRE_FIELD (REPLY_SERIAL);
+      break;
+    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+      REQUIRE_FIELD (REPLY_SERIAL);
+      break;
+    default:
+      /* other message types allowed but ignored */
+      break;
+    }
+
+  return DBUS_VALID;
+}
+
+static DBusValidity
+load_and_validate_field (DBusHeader     *header,
+                         int             field,
+                         DBusTypeReader *variant_reader)
+{
+  int type;
+  int expected_type;
+  const DBusString *value_str;
+  int value_pos;
+  int str_data_pos;
+  dbus_uint32_t v_UINT32;
+  int bad_string_code;
+  dbus_bool_t (* string_validation_func) (const DBusString *str,
+                                          int start, int len);
+
+  /* Supposed to have been checked already */
+  _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
+  _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
+
+  /* Before we can cache a field, we need to know it has the right type */
+  type = _dbus_type_reader_get_current_type (variant_reader);
+
+  _dbus_assert (_dbus_header_field_types[field].code == field);
+
+  expected_type = EXPECTED_TYPE_OF_FIELD (field);
+  if (type != expected_type)
+    {
+      _dbus_verbose ("Field %d should have type %d but has %d\n",
+                     field, expected_type, type);
+      return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
+    }
+
+  /* If the field was provided twice, we aren't happy */
+  if (header->fields[field].value_pos >= 0)
+    {
+      _dbus_verbose ("Header field %d seen a second time\n", field);
+      return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
+    }
+
+  /* Now we can cache and look at the field content */
+  _dbus_verbose ("initially caching field %d\n", field);
+  _dbus_header_cache_one (header, field, variant_reader);
+
+  string_validation_func = NULL;
+
+  /* make compiler happy that all this is initialized */
+  v_UINT32 = 0;
+  value_str = NULL;
+  value_pos = -1;
+  str_data_pos = -1;
+  bad_string_code = DBUS_VALID;
+
+  if (expected_type == DBUS_TYPE_UINT32)
+    {
+      _dbus_header_get_field_basic (header, field, expected_type,
+                                    &v_UINT32);
+    }
+  else if (expected_type == DBUS_TYPE_STRING ||
+           expected_type == DBUS_TYPE_OBJECT_PATH ||
+           expected_type == DBUS_TYPE_SIGNATURE)
+    {
+      _dbus_header_get_field_raw (header, field,
+                                  &value_str, &value_pos);
+      str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
+    }
+  else
+    {
+      _dbus_assert_not_reached ("none of the known fields should have this type");
+    }
+
+  switch (field)
+    {
+    case DBUS_HEADER_FIELD_DESTINATION:
+      string_validation_func = _dbus_validate_bus_name;
+      bad_string_code = DBUS_INVALID_BAD_DESTINATION;
+      break;
+    case DBUS_HEADER_FIELD_INTERFACE:
+      string_validation_func = _dbus_validate_interface;
+      bad_string_code = DBUS_INVALID_BAD_INTERFACE;
+
+      if (_dbus_string_equal_substring (&_dbus_local_interface_str,
+                                        0,
+                                        _dbus_string_get_length (&_dbus_local_interface_str),
+                                        value_str, str_data_pos))
+        {
+          _dbus_verbose ("Message is on the local interface\n");
+          return DBUS_INVALID_USES_LOCAL_INTERFACE;
+        }
+      break;
+
+    case DBUS_HEADER_FIELD_MEMBER:
+      string_validation_func = _dbus_validate_member;
+      bad_string_code = DBUS_INVALID_BAD_MEMBER;
+      break;
+
+    case DBUS_HEADER_FIELD_ERROR_NAME:
+      string_validation_func = _dbus_validate_error_name;
+      bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
+      break;
+
+    case DBUS_HEADER_FIELD_SENDER:
+      string_validation_func = _dbus_validate_bus_name;
+      bad_string_code = DBUS_INVALID_BAD_SENDER;
+      break;
+
+    case DBUS_HEADER_FIELD_PATH:
+      /* OBJECT_PATH was validated generically due to its type */
+      string_validation_func = NULL;
+
+      if (_dbus_string_equal_substring (&_dbus_local_path_str,
+                                        0,
+                                        _dbus_string_get_length (&_dbus_local_path_str),
+                                        value_str, str_data_pos))
+        {
+          _dbus_verbose ("Message is from the local path\n");
+          return DBUS_INVALID_USES_LOCAL_PATH;
+        }
+      break;
+
+    case DBUS_HEADER_FIELD_REPLY_SERIAL:
+      /* Can't be 0 */
+      if (v_UINT32 == 0)
+        {
+          return DBUS_INVALID_BAD_SERIAL;
+        }
+      break;
+
+    case DBUS_HEADER_FIELD_UNIX_FDS:
+      /* Every value makes sense */
+      break;
+
+    case DBUS_HEADER_FIELD_SIGNATURE:
+      /* SIGNATURE validated generically due to its type */
+      string_validation_func = NULL;
+      break;
+
+    default:
+      _dbus_assert_not_reached ("unknown field shouldn't be seen here");
+      break;
+    }
+
+  if (string_validation_func)
+    {
+      dbus_uint32_t len;
+
+      _dbus_assert (bad_string_code != DBUS_VALID);
+
+      len = _dbus_marshal_read_uint32 (value_str, value_pos,
+                                       _dbus_header_get_byte_order (header),
+                                       NULL);
+
+#if 0
+      _dbus_verbose ("Validating string header field; code %d if fails\n",
+                     bad_string_code);
+#endif
+      if (!(*string_validation_func) (value_str, str_data_pos, len))
+        return bad_string_code;
+    }
+
+  return DBUS_VALID;
+}
+
+/**
+ * Creates a message header from potentially-untrusted data. The
+ * return value is #TRUE if there was enough memory and the data was
+ * valid. If it returns #TRUE, the header will be created. If it
+ * returns #FALSE and *validity == #DBUS_VALIDITY_UNKNOWN_OOM_ERROR, 
+ * then there wasn't enough memory.  If it returns #FALSE 
+ * and *validity != #DBUS_VALIDITY_UNKNOWN_OOM_ERROR then the data was 
+ * invalid.
+ *
+ * The byte_order, fields_array_len, and body_len args should be from
+ * _dbus_header_have_message_untrusted(). Validation performed in
+ * _dbus_header_have_message_untrusted() is assumed to have been
+ * already done.
+ *
+ * @param header the header (must be initialized)
+ * @param mode whether to do validation
+ * @param validity return location for invalidity reason
+ * @param byte_order byte order from header
+ * @param fields_array_len claimed length of fields array
+ * @param body_len claimed length of body
+ * @param header_len claimed length of header
+ * @param str a string
+ * @param start start of header, 8-aligned
+ * @param len length of string to look at
+ * @returns #FALSE if no memory or data was invalid, #TRUE otherwise
+ */
+dbus_bool_t
+_dbus_header_load (DBusHeader        *header,
+                   DBusValidationMode mode,
+                   DBusValidity      *validity,
+                   int                byte_order,
+                   int                fields_array_len,
+                   int                header_len,
+                   int                body_len,
+                   const DBusString  *str,
+                   int                start,
+                   int                len)
+{
+  int leftover;
+  DBusValidity v;
+  DBusTypeReader reader;
+  DBusTypeReader array_reader;
+  unsigned char v_byte;
+  dbus_uint32_t v_uint32;
+  dbus_uint32_t serial;
+  int padding_start;
+  int padding_len;
+  int i;
+
+  _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
+  _dbus_assert (header_len <= len);
+  _dbus_assert (_dbus_string_get_length (&header->data) == 0);
+
+  if (!_dbus_string_copy_len (str, start, header_len, &header->data, 0))
+    {
+      _dbus_verbose ("Failed to copy buffer into new header\n");
+      *validity = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
+      return FALSE;
+    }
+
+  if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
+    {
+      leftover = len - header_len - body_len - start;
+    }
+  else
+    {
+      v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0,
+                                           byte_order,
+                                           &leftover,
+                                           str, start, len);
+      
+      if (v != DBUS_VALID)
+        {
+          *validity = v;
+          goto invalid;
+        }
+    }
+
+  _dbus_assert (leftover < len);
+
+  padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len);
+  padding_start = start + FIRST_FIELD_OFFSET + fields_array_len;
+  _dbus_assert (start + header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8));
+  _dbus_assert (start + header_len == padding_start + padding_len);
+
+  if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
+    {
+      if (!_dbus_string_validate_nul (str, padding_start, padding_len))
+        {
+          *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
+          goto invalid;
+        }
+    }
+
+  header->padding = padding_len;
+
+  if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
+    {
+      *validity = DBUS_VALID;
+      return TRUE;
+    }
+
+  /* We now know the data is well-formed, but we have to check that
+   * it's valid.
+   */
+
+  _dbus_type_reader_init (&reader,
+                          byte_order,
+                          &_dbus_header_signature_str, 0,
+                          str, start);
+
+  /* BYTE ORDER */
+  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
+  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BYTE_ORDER_OFFSET);
+  _dbus_type_reader_read_basic (&reader, &v_byte);
+  _dbus_type_reader_next (&reader);
+
+  _dbus_assert (v_byte == byte_order);
+
+  /* MESSAGE TYPE */
+  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
+  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == TYPE_OFFSET);
+  _dbus_type_reader_read_basic (&reader, &v_byte);
+  _dbus_type_reader_next (&reader);
+
+  /* unknown message types are supposed to be ignored, so only validation here is
+   * that it isn't invalid
+   */
+  if (v_byte == DBUS_MESSAGE_TYPE_INVALID)
+    {
+      *validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
+      goto invalid;
+    }
+
+  /* FLAGS */
+  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
+  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FLAGS_OFFSET);
+  _dbus_type_reader_read_basic (&reader, &v_byte);
+  _dbus_type_reader_next (&reader);
+
+  /* unknown flags should be ignored */
+
+  /* PROTOCOL VERSION */
+  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
+  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == VERSION_OFFSET);
+  _dbus_type_reader_read_basic (&reader, &v_byte);
+  _dbus_type_reader_next (&reader);
+
+  if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION)
+    {
+      *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
+      goto invalid;
+    }
+
+  /* BODY LENGTH */
+  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
+  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BODY_LENGTH_OFFSET);
+  _dbus_type_reader_read_basic (&reader, &v_uint32);
+  _dbus_type_reader_next (&reader);
+
+  _dbus_assert (body_len == (signed) v_uint32);
+
+  /* SERIAL */
+  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
+  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == SERIAL_OFFSET);
+  _dbus_type_reader_read_basic (&reader, &serial);
+  _dbus_type_reader_next (&reader);
+
+  if (serial == 0)
+    {
+      *validity = DBUS_INVALID_BAD_SERIAL;
+      goto invalid;
+    }
+
+  _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_ARRAY);
+  _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FIELDS_ARRAY_LENGTH_OFFSET);
+
+  _dbus_type_reader_recurse (&reader, &array_reader);
+  while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID)
+    {
+      DBusTypeReader struct_reader;
+      DBusTypeReader variant_reader;
+      unsigned char field_code;
+
+      _dbus_assert (_dbus_type_reader_get_current_type (&array_reader) == DBUS_TYPE_STRUCT);
+
+      _dbus_type_reader_recurse (&array_reader, &struct_reader);
+
+      _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_BYTE);
+      _dbus_type_reader_read_basic (&struct_reader, &field_code);
+      _dbus_type_reader_next (&struct_reader);
+
+      if (field_code == DBUS_HEADER_FIELD_INVALID)
+        {
+          _dbus_verbose ("invalid header field code\n");
+          *validity = DBUS_INVALID_HEADER_FIELD_CODE;
+          goto invalid;
+        }
+
+      if (field_code > DBUS_HEADER_FIELD_LAST)
+        {
+          _dbus_verbose ("unknown header field code %d, skipping\n",
+                         field_code);
+          goto next_field;
+        }
+
+      _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_VARIANT);
+      _dbus_type_reader_recurse (&struct_reader, &variant_reader);
+
+      v = load_and_validate_field (header, field_code, &variant_reader);
+      if (v != DBUS_VALID)
+        {
+          _dbus_verbose ("Field %d was invalid\n", field_code);
+          *validity = v;
+          goto invalid;
+        }
+
+    next_field:
+      _dbus_type_reader_next (&array_reader);
+    }
+
+  /* Anything we didn't fill in is now known not to exist */
+  i = 0;
+  while (i <= DBUS_HEADER_FIELD_LAST)
+    {
+      if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
+        header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
+      ++i;
+    }
+
+  v = check_mandatory_fields (header);
+  if (v != DBUS_VALID)
+    {
+      _dbus_verbose ("Mandatory fields were missing, code %d\n", v);
+      *validity = v;
+      goto invalid;
+    }
+
+  *validity = DBUS_VALID;
+  return TRUE;
+
+ invalid:
+  _dbus_string_set_length (&header->data, 0);
+  return FALSE;
+}
+
+/**
+ * Fills in the correct body length.
+ *
+ * @param header the header
+ * @param body_len the length of the body
+ */
+void
+_dbus_header_update_lengths (DBusHeader *header,
+                             int         body_len)
+{
+  _dbus_marshal_set_uint32 (&header->data,
+                            BODY_LENGTH_OFFSET,
+                            body_len,
+                            _dbus_header_get_byte_order (header));
+}
+
+/**
+ * Try to find the given field.
+ *
+ * @param header the header
+ * @param field the field code
+ * @param reader a type reader; on success this is left pointing at the struct
+ *  (uv) for the field, while on failure it is left pointing into empty space
+ *  at the end of the header fields
+ * @param realign_root another type reader; on success or failure it is left
+ *  pointing to the beginning of the array of fields (i.e. the thing that might
+ *  need realigning)
+ * @returns #TRUE on success
+ */
+static dbus_bool_t
+find_field_for_modification (DBusHeader     *header,
+                             int             field,
+                             DBusTypeReader *reader,
+                             DBusTypeReader *realign_root)
+{
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  _dbus_type_reader_init (realign_root,
+                          _dbus_header_get_byte_order (header),
+                          &_dbus_header_signature_str,
+                          FIELDS_ARRAY_SIGNATURE_OFFSET,
+                          &header->data,
+                          FIELDS_ARRAY_LENGTH_OFFSET);
+
+  _dbus_type_reader_recurse (realign_root, reader);
+
+  while (_dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID)
+    {
+      DBusTypeReader sub;
+      unsigned char field_code;
+
+      _dbus_type_reader_recurse (reader, &sub);
+
+      _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
+      _dbus_type_reader_read_basic (&sub, &field_code);
+
+      if (field_code == (unsigned) field)
+        {
+          _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_STRUCT);
+          retval = TRUE;
+          goto done;
+        }
+
+      _dbus_type_reader_next (reader);
+    }
+
+ done:
+  return retval;
+}
+
+/**
+ * Sets the value of a field with basic type. If the value is a string
+ * value, it isn't allowed to be #NULL. If the field doesn't exist,
+ * it will be created.
+ *
+ * @param header the header
+ * @param field the field to set
+ * @param type the type of the value
+ * @param value the value as for _dbus_marshal_set_basic()
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_header_set_field_basic (DBusHeader       *header,
+                              int               field,
+                              int               type,
+                              const void       *value)
+{
+  _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
+
+  if (!reserve_header_padding (header))
+    return FALSE;
+
+  /* If the field exists we set, otherwise we append */
+  if (_dbus_header_cache_check (header, field))
+    {
+      DBusTypeReader reader;
+      DBusTypeReader realign_root;
+
+      if (!find_field_for_modification (header, field,
+                                        &reader, &realign_root))
+        _dbus_assert_not_reached ("field was marked present in cache but wasn't found");
+
+      if (!set_basic_field (&reader, field, type, value, &realign_root))
+        return FALSE;
+    }
+  else
+    {
+      DBusTypeWriter writer;
+      DBusTypeWriter array;
+
+      _dbus_type_writer_init_values_only (&writer,
+                                          _dbus_header_get_byte_order (header),
+                                          &_dbus_header_signature_str,
+                                          FIELDS_ARRAY_SIGNATURE_OFFSET,
+                                          &header->data,
+                                          FIELDS_ARRAY_LENGTH_OFFSET);
+
+      /* recurse into array without creating a new length, and jump to
+       * end of array.
+       */
+      if (!_dbus_type_writer_append_array (&writer,
+                                           &_dbus_header_signature_str,
+                                           FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET,
+                                           &array))
+        _dbus_assert_not_reached ("recurse into ARRAY should not have used memory");
+
+      _dbus_assert (array.u.array.len_pos == FIELDS_ARRAY_LENGTH_OFFSET);
+      _dbus_assert (array.u.array.start_pos == FIRST_FIELD_OFFSET);
+      _dbus_assert (array.value_pos == HEADER_END_BEFORE_PADDING (header));
+
+      if (!write_basic_field (&array,
+                              field, type, value))
+        return FALSE;
+
+      if (!_dbus_type_writer_unrecurse (&writer, &array))
+        _dbus_assert_not_reached ("unrecurse from ARRAY should not have used memory");
+    }
+
+  correct_header_padding (header);
+
+  /* We could be smarter about this (only invalidate fields after the
+   * one we modified, or even only if the one we modified changed
+   * length). But this hack is a start.
+   */
+  _dbus_header_cache_invalidate_all (header);
+
+  return TRUE;
+}
+
+/**
+ * Gets the value of a field with basic type. If the field
+ * doesn't exist, returns #FALSE, otherwise returns #TRUE.
+ *
+ * @param header the header
+ * @param field the field to get
+ * @param type the type of the value
+ * @param value the value as for _dbus_marshal_read_basic()
+ * @returns #FALSE if the field doesn't exist
+ */
+dbus_bool_t
+_dbus_header_get_field_basic (DBusHeader    *header,
+                              int            field,
+                              int            type,
+                              void          *value)
+{
+  _dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
+  _dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
+  _dbus_assert (_dbus_header_field_types[field].code == field);
+  /* in light of this you might ask why the type is passed in;
+   * the only rationale I can think of is so the caller has
+   * to specify its expectation and breaks if we change it
+   */
+  _dbus_assert (type == EXPECTED_TYPE_OF_FIELD (field));
+
+  if (!_dbus_header_cache_check (header, field))
+    return FALSE;
+
+  _dbus_assert (header->fields[field].value_pos >= 0);
+
+  _dbus_marshal_read_basic (&header->data,
+                            header->fields[field].value_pos,
+                            type, value, _dbus_header_get_byte_order (header),
+                            NULL);
+
+  return TRUE;
+}
+
+/**
+ * Gets the raw marshaled data for a field. If the field doesn't
+ * exist, returns #FALSE, otherwise returns #TRUE.  Returns the start
+ * of the marshaled data, i.e. usually the byte where the length
+ * starts (for strings and arrays) or for basic types just the value
+ * itself.
+ *
+ * @param header the header
+ * @param field the field to get
+ * @param str return location for the data string
+ * @param pos return location for start of field value
+ * @returns #FALSE if the field doesn't exist
+ */
+dbus_bool_t
+_dbus_header_get_field_raw (DBusHeader        *header,
+                            int                field,
+                            const DBusString **str,
+                            int               *pos)
+{
+  if (!_dbus_header_cache_check (header, field))
+    return FALSE;
+
+  if (str)
+    *str = &header->data;
+  if (pos)
+    *pos = header->fields[field].value_pos;
+
+  return TRUE;
+}
+
+/**
+ * Deletes a field, if it exists.
+ *
+ * @param header the header
+ * @param field the field to delete
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_header_delete_field (DBusHeader *header,
+                           int         field)
+{
+  DBusTypeReader reader;
+  DBusTypeReader realign_root;
+
+  if (_dbus_header_cache_known_nonexistent (header, field))
+    return TRUE; /* nothing to do */
+
+  /* Scan to the field we want, delete and realign, reappend
+   * padding. Field may turn out not to exist.
+   */
+  if (!find_field_for_modification (header, field,
+                                    &reader, &realign_root))
+    return TRUE; /* nothing to do */
+
+  if (!reserve_header_padding (header))
+    return FALSE;
+
+  if (!_dbus_type_reader_delete (&reader,
+                                 &realign_root))
+    return FALSE;
+
+  correct_header_padding (header);
+
+  _dbus_header_cache_invalidate_all (header);
+
+  _dbus_assert (!_dbus_header_cache_check (header, field)); /* Expensive assertion ... */
+
+  return TRUE;
+}
+
+/**
+ * Toggles a message flag bit, turning on the bit if value = TRUE and
+ * flipping it off if value = FALSE.
+ *
+ * @param header the header
+ * @param flag the message flag to toggle
+ * @param value toggle on or off
+ */
+void
+_dbus_header_toggle_flag (DBusHeader   *header,
+                          dbus_uint32_t flag,
+                          dbus_bool_t   value)
+{
+  unsigned char *flags_p;
+
+  flags_p = _dbus_string_get_data_len (&header->data, FLAGS_OFFSET, 1);
+
+  if (value)
+    *flags_p |= flag;
+  else
+    *flags_p &= ~flag;
+}
+
+/**
+ * Gets a message flag bit, returning TRUE if the bit is set.
+ *
+ * @param header the header
+ * @param flag the message flag to get
+ * @returns #TRUE if the flag is set
+ */
+dbus_bool_t
+_dbus_header_get_flag (DBusHeader   *header,
+                       dbus_uint32_t flag)
+{
+  const unsigned char *flags_p;
+
+  flags_p = _dbus_string_get_const_data_len (&header->data, FLAGS_OFFSET, 1);
+
+  return (*flags_p & flag) != 0;
+}
+
+/**
+ * Swaps the header into the given order if required.
+ *
+ * @param header the header
+ * @param new_order the new byte order
+ */
+void
+_dbus_header_byteswap (DBusHeader *header,
+                       int         new_order)
+{
+  char byte_order;
+
+  byte_order = _dbus_header_get_byte_order (header);
+
+  if (byte_order == new_order)
+    return;
+
+  _dbus_marshal_byteswap (&_dbus_header_signature_str,
+                          0, byte_order,
+                          new_order,
+                          &header->data, 0);
+
+  _dbus_string_set_byte (&header->data, BYTE_ORDER_OFFSET, new_order);
+}
+
+/** @} */
diff --git a/dbus/dbus/dbus-marshal-header.h b/dbus/dbus/dbus-marshal-header.h
new file mode 100644
index 0000000..350fe5c
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-header.h
@@ -0,0 +1,128 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-header.h  Managing marshaling/demarshaling of message headers
+ *
+ * Copyright (C) 2005  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef DBUS_MARSHAL_HEADER_H
+#define DBUS_MARSHAL_HEADER_H
+
+#include <dbus/dbus-marshal-basic.h>
+#include <dbus/dbus-marshal-validate.h>
+
+typedef struct DBusHeader      DBusHeader;
+typedef struct DBusHeaderField DBusHeaderField;
+
+#define _DBUS_HEADER_FIELD_VALUE_UNKNOWN -1
+#define _DBUS_HEADER_FIELD_VALUE_NONEXISTENT -2
+
+/**
+ * Cached information about a header field in the message
+ */
+struct DBusHeaderField
+{
+  int            value_pos; /**< Position of field value, or -1/-2 */
+};
+
+/**
+ * Message header data and some cached details of it.
+ */
+struct DBusHeader
+{
+  DBusString data; /**< Header network data, stored
+                    * separately from body so we can
+                    * independently realloc it.
+                    */
+
+  DBusHeaderField fields[DBUS_HEADER_FIELD_LAST + 1]; /**< Track the location
+                                                       * of each field in header
+                                                       */
+
+  dbus_uint32_t padding : 3;        /**< bytes of alignment in header */
+  dbus_uint32_t byte_order : 8;     /**< byte order of header */
+};
+
+dbus_bool_t   _dbus_header_init                   (DBusHeader        *header);
+void          _dbus_header_free                   (DBusHeader        *header);
+void          _dbus_header_reinit                 (DBusHeader        *header);
+dbus_bool_t   _dbus_header_create                 (DBusHeader        *header,
+                                                   int                byte_order,
+                                                   int                type,
+                                                   const char        *destination,
+                                                   const char        *path,
+                                                   const char        *interface,
+                                                   const char        *member,
+                                                   const char        *error_name);
+dbus_bool_t   _dbus_header_copy                   (const DBusHeader  *header,
+                                                   DBusHeader        *dest);
+int           _dbus_header_get_message_type       (DBusHeader        *header);
+void          _dbus_header_set_serial             (DBusHeader        *header,
+                                                   dbus_uint32_t      serial);
+dbus_uint32_t _dbus_header_get_serial             (DBusHeader        *header);
+void          _dbus_header_update_lengths         (DBusHeader        *header,
+                                                   int                body_len);
+dbus_bool_t   _dbus_header_set_field_basic        (DBusHeader        *header,
+                                                   int                field,
+                                                   int                type,
+                                                   const void        *value);
+dbus_bool_t   _dbus_header_get_field_basic        (DBusHeader        *header,
+                                                   int                field,
+                                                   int                type,
+                                                   void              *value);
+dbus_bool_t   _dbus_header_get_field_raw          (DBusHeader        *header,
+                                                   int                field,
+                                                   const DBusString **str,
+                                                   int               *pos);
+dbus_bool_t   _dbus_header_delete_field           (DBusHeader        *header,
+                                                   int                field);
+void          _dbus_header_toggle_flag            (DBusHeader        *header,
+                                                   dbus_uint32_t      flag,
+                                                   dbus_bool_t        value);
+dbus_bool_t   _dbus_header_get_flag               (DBusHeader        *header,
+                                                   dbus_uint32_t      flag);
+dbus_bool_t   _dbus_header_ensure_signature       (DBusHeader        *header,
+                                                   DBusString       **type_str,
+                                                   int               *type_pos);
+dbus_bool_t   _dbus_header_have_message_untrusted (int                max_message_length,
+                                                   DBusValidity      *validity,
+                                                   int               *byte_order,
+                                                   int               *fields_array_len,
+                                                   int               *header_len,
+                                                   int               *body_len,
+                                                   const DBusString  *str,
+                                                   int                start,
+                                                   int                len);
+dbus_bool_t   _dbus_header_load                   (DBusHeader        *header,
+                                                   DBusValidationMode mode,
+                                                   DBusValidity      *validity,
+                                                   int                byte_order,
+                                                   int                fields_array_len,
+                                                   int                header_len,
+                                                   int                body_len,
+                                                   const DBusString  *str,
+                                                   int                start,
+                                                   int                len);
+void          _dbus_header_byteswap               (DBusHeader        *header,
+                                                   int                new_order);
+char          _dbus_header_get_byte_order         (const DBusHeader  *header);
+
+
+
+#endif /* DBUS_MARSHAL_HEADER_H */
diff --git a/dbus/dbus/dbus-marshal-recursive-util.c b/dbus/dbus/dbus-marshal-recursive-util.c
new file mode 100644
index 0000000..9512414
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-recursive-util.c
@@ -0,0 +1,3577 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-recursive-util.c  Would be in dbus-marshal-recursive.c, but only used in bus/tests
+ *
+ * Copyright (C) 2004, 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#ifdef DBUS_BUILD_TESTS
+
+#include "dbus-marshal-recursive.h"
+#include "dbus-marshal-basic.h"
+#include "dbus-signature.h"
+#include "dbus-internals.h"
+#include <string.h>
+
+static void
+basic_value_zero (DBusBasicValue *value)
+{
+
+#ifdef DBUS_HAVE_INT64
+  value->u64 = 0;
+#else
+  value->eight.first32 = 0;
+  value->eight.second32 = 0;
+#endif
+}
+
+static dbus_bool_t
+basic_value_equal (int             type,
+                   DBusBasicValue *lhs,
+                   DBusBasicValue *rhs)
+{
+  if (type == DBUS_TYPE_STRING ||
+      type == DBUS_TYPE_SIGNATURE ||
+      type == DBUS_TYPE_OBJECT_PATH)
+    {
+      return strcmp (lhs->str, rhs->str) == 0;
+    }
+  else
+    {
+#ifdef DBUS_HAVE_INT64
+      return lhs->u64 == rhs->u64;
+#else
+      return lhs->eight.first32 == rhs->eight.first32 &&
+        lhs->eight.second32 == rhs->eight.second32;
+#endif
+    }
+}
+
+static dbus_bool_t
+equal_values_helper (DBusTypeReader *lhs,
+                     DBusTypeReader *rhs)
+{
+  int lhs_type;
+  int rhs_type;
+
+  lhs_type = _dbus_type_reader_get_current_type (lhs);
+  rhs_type = _dbus_type_reader_get_current_type (rhs);
+
+  if (lhs_type != rhs_type)
+    return FALSE;
+
+  if (lhs_type == DBUS_TYPE_INVALID)
+    return TRUE;
+
+  if (dbus_type_is_basic (lhs_type))
+    {
+      DBusBasicValue lhs_value;
+      DBusBasicValue rhs_value;
+
+      basic_value_zero (&lhs_value);
+      basic_value_zero (&rhs_value);
+      
+      _dbus_type_reader_read_basic (lhs, &lhs_value);
+      _dbus_type_reader_read_basic (rhs, &rhs_value);
+
+      return basic_value_equal (lhs_type, &lhs_value, &rhs_value);
+    }
+  else
+    {
+      DBusTypeReader lhs_sub;
+      DBusTypeReader rhs_sub;
+
+      _dbus_type_reader_recurse (lhs, &lhs_sub);
+      _dbus_type_reader_recurse (rhs, &rhs_sub);
+
+      return equal_values_helper (&lhs_sub, &rhs_sub);
+    }
+}
+
+/**
+ * See whether the two readers point to identical data blocks.
+ *
+ * @param lhs reader 1
+ * @param rhs reader 2
+ * @returns #TRUE if the data blocks have the same values
+ */
+dbus_bool_t
+_dbus_type_reader_equal_values (const DBusTypeReader *lhs,
+                                const DBusTypeReader *rhs)
+{
+  DBusTypeReader copy_lhs = *lhs;
+  DBusTypeReader copy_rhs = *rhs;
+
+  return equal_values_helper (&copy_lhs, &copy_rhs);
+}
+
+/* TESTS */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include "dbus-test.h"
+#include "dbus-list.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Whether to do the OOM stuff (only with other expensive tests) */
+#define TEST_OOM_HANDLING 0
+/* We do start offset 0 through 9, to get various alignment cases. Still this
+ * obviously makes the test suite run 10x as slow.
+ */
+#define MAX_INITIAL_OFFSET 9
+
+/* Largest iteration count to test copying, realignment,
+ * etc. with. i.e. we only test this stuff with some of the smaller
+ * data sets.
+ */
+#define MAX_ITERATIONS_FOR_EXPENSIVE_TESTS 1000
+
+typedef struct
+{
+  int byte_order;
+  int initial_offset;
+  DBusString signature;
+  DBusString body;
+} DataBlock;
+
+typedef struct
+{
+  int saved_sig_len;
+  int saved_body_len;
+} DataBlockState;
+
+#define N_FENCE_BYTES 5
+#define FENCE_BYTES_STR "abcde"
+#define INITIAL_PADDING_BYTE '\0'
+
+static dbus_bool_t
+data_block_init (DataBlock *block,
+                 int        byte_order,
+                 int        initial_offset)
+{
+  if (!_dbus_string_init (&block->signature))
+    return FALSE;
+
+  if (!_dbus_string_init (&block->body))
+    {
+      _dbus_string_free (&block->signature);
+      return FALSE;
+    }
+
+  if (!_dbus_string_insert_bytes (&block->signature, 0, initial_offset,
+                                  INITIAL_PADDING_BYTE) ||
+      !_dbus_string_insert_bytes (&block->body, 0, initial_offset,
+                                  INITIAL_PADDING_BYTE) ||
+      !_dbus_string_append (&block->signature, FENCE_BYTES_STR) ||
+      !_dbus_string_append (&block->body, FENCE_BYTES_STR))
+    {
+      _dbus_string_free (&block->signature);
+      _dbus_string_free (&block->body);
+      return FALSE;
+    }
+
+  block->byte_order = byte_order;
+  block->initial_offset = initial_offset;
+
+  return TRUE;
+}
+
+static void
+data_block_save (DataBlock      *block,
+                 DataBlockState *state)
+{
+  state->saved_sig_len = _dbus_string_get_length (&block->signature) - N_FENCE_BYTES;
+  state->saved_body_len = _dbus_string_get_length (&block->body) - N_FENCE_BYTES;
+}
+
+static void
+data_block_restore (DataBlock      *block,
+                    DataBlockState *state)
+{
+  _dbus_string_delete (&block->signature,
+                       state->saved_sig_len,
+                       _dbus_string_get_length (&block->signature) - state->saved_sig_len - N_FENCE_BYTES);
+  _dbus_string_delete (&block->body,
+                       state->saved_body_len,
+                       _dbus_string_get_length (&block->body) - state->saved_body_len - N_FENCE_BYTES);
+}
+
+static void
+data_block_verify (DataBlock *block)
+{
+  if (!_dbus_string_ends_with_c_str (&block->signature,
+                                     FENCE_BYTES_STR))
+    {
+      int offset;
+
+      offset = _dbus_string_get_length (&block->signature) - N_FENCE_BYTES - 8;
+      if (offset < 0)
+        offset = 0;
+
+      _dbus_verbose_bytes_of_string (&block->signature,
+                                     offset,
+                                     _dbus_string_get_length (&block->signature) - offset);
+      _dbus_assert_not_reached ("block did not verify: bad bytes at end of signature");
+    }
+  if (!_dbus_string_ends_with_c_str (&block->body,
+                                     FENCE_BYTES_STR))
+    {
+      int offset;
+
+      offset = _dbus_string_get_length (&block->body) - N_FENCE_BYTES - 8;
+      if (offset < 0)
+        offset = 0;
+
+      _dbus_verbose_bytes_of_string (&block->body,
+                                     offset,
+                                     _dbus_string_get_length (&block->body) - offset);
+      _dbus_assert_not_reached ("block did not verify: bad bytes at end of body");
+    }
+
+  _dbus_assert (_dbus_string_validate_nul (&block->signature,
+                                           0, block->initial_offset));
+  _dbus_assert (_dbus_string_validate_nul (&block->body,
+                                           0, block->initial_offset));
+}
+
+static void
+data_block_free (DataBlock *block)
+{
+  data_block_verify (block);
+
+  _dbus_string_free (&block->signature);
+  _dbus_string_free (&block->body);
+}
+
+static void
+data_block_reset (DataBlock *block)
+{
+  data_block_verify (block);
+
+  _dbus_string_delete (&block->signature,
+                       block->initial_offset,
+                       _dbus_string_get_length (&block->signature) - N_FENCE_BYTES - block->initial_offset);
+  _dbus_string_delete (&block->body,
+                       block->initial_offset,
+                       _dbus_string_get_length (&block->body) - N_FENCE_BYTES - block->initial_offset);
+
+  data_block_verify (block);
+}
+
+static void
+data_block_init_reader_writer (DataBlock      *block,
+                               DBusTypeReader *reader,
+                               DBusTypeWriter *writer)
+{
+  if (reader)
+    _dbus_type_reader_init (reader,
+                            block->byte_order,
+                            &block->signature,
+                            block->initial_offset,
+                            &block->body,
+                            block->initial_offset);
+
+  if (writer)
+    _dbus_type_writer_init (writer,
+                            block->byte_order,
+                            &block->signature,
+                            _dbus_string_get_length (&block->signature) - N_FENCE_BYTES,
+                            &block->body,
+                            _dbus_string_get_length (&block->body) - N_FENCE_BYTES);
+}
+
+static void
+real_check_expected_type (DBusTypeReader *reader,
+                          int             expected,
+                          const char     *funcname,
+                          int             line)
+{
+  int t;
+
+  t = _dbus_type_reader_get_current_type (reader);
+
+  if (t != expected)
+    {
+      _dbus_warn ("Read type %s while expecting %s at %s line %d\n",
+                  _dbus_type_to_string (t),
+                  _dbus_type_to_string (expected),
+                  funcname, line);
+
+      _dbus_assert_not_reached ("read wrong type");
+    }
+}
+
+#define check_expected_type(reader, expected) real_check_expected_type (reader, expected, _DBUS_FUNCTION_NAME, __LINE__)
+
+#define NEXT_EXPECTING_TRUE(reader)  do { if (!_dbus_type_reader_next (reader))         \
+ {                                                                                      \
+    _dbus_warn ("_dbus_type_reader_next() should have returned TRUE at %s %d\n",        \
+                              _DBUS_FUNCTION_NAME, __LINE__);                           \
+    _dbus_assert_not_reached ("test failed");                                           \
+ }                                                                                      \
+} while (0)
+
+#define NEXT_EXPECTING_FALSE(reader) do { if (_dbus_type_reader_next (reader))          \
+ {                                                                                      \
+    _dbus_warn ("_dbus_type_reader_next() should have returned FALSE at %s %d\n",       \
+                              _DBUS_FUNCTION_NAME, __LINE__);                           \
+    _dbus_assert_not_reached ("test failed");                                           \
+ }                                                                                      \
+ check_expected_type (reader, DBUS_TYPE_INVALID);                                       \
+} while (0)
+
+typedef struct TestTypeNode               TestTypeNode;
+typedef struct TestTypeNodeClass          TestTypeNodeClass;
+typedef struct TestTypeNodeContainer      TestTypeNodeContainer;
+typedef struct TestTypeNodeContainerClass TestTypeNodeContainerClass;
+
+struct TestTypeNode
+{
+  const TestTypeNodeClass *klass;
+};
+
+struct TestTypeNodeContainer
+{
+  TestTypeNode base;
+  DBusList    *children;
+};
+
+struct TestTypeNodeClass
+{
+  int typecode;
+
+  int instance_size;
+
+  int subclass_detail; /* a bad hack to avoid a bunch of subclass casting */
+
+  dbus_bool_t   (* construct)     (TestTypeNode   *node);
+  void          (* destroy)       (TestTypeNode   *node);
+
+  dbus_bool_t (* write_value)     (TestTypeNode   *node,
+                                   DataBlock      *block,
+                                   DBusTypeWriter *writer,
+                                   int             seed);
+  dbus_bool_t (* read_value)      (TestTypeNode   *node,
+                                   DBusTypeReader *reader,
+                                   int             seed);
+  dbus_bool_t (* set_value)       (TestTypeNode   *node,
+                                   DBusTypeReader *reader,
+                                   DBusTypeReader *realign_root,
+                                   int             seed);
+  dbus_bool_t (* build_signature) (TestTypeNode   *node,
+                                   DBusString     *str);
+  dbus_bool_t (* write_multi)     (TestTypeNode   *node,
+                                   DataBlock      *block,
+                                   DBusTypeWriter *writer,
+                                   int             seed,
+                                   int             count);
+  dbus_bool_t (* read_multi)      (TestTypeNode   *node,
+                                   DBusTypeReader *reader,
+                                   int             seed,
+                                   int             count);
+};
+
+struct TestTypeNodeContainerClass
+{
+  TestTypeNodeClass base;
+};
+
+/* FIXME this could be chilled out substantially by unifying
+ * the basic types into basic_write_value/basic_read_value
+ * and by merging read_value and set_value into one function
+ * taking a flag argument.
+ */
+static dbus_bool_t int16_write_value       (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t int16_read_value        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t int16_set_value         (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t int16_write_multi       (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed,
+                                            int             count);
+static dbus_bool_t int16_read_multi        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed,
+                                            int             count);
+static dbus_bool_t int32_write_value       (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t int32_read_value        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t int32_set_value         (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t int32_write_multi       (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed,
+                                            int             count);
+static dbus_bool_t int32_read_multi        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed,
+                                            int             count);
+static dbus_bool_t int64_write_value       (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t int64_read_value        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t int64_set_value         (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t string_write_value      (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t string_read_value       (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t string_set_value        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t bool_write_value        (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t bool_read_value         (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t bool_set_value          (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t byte_write_value        (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t byte_read_value         (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t byte_set_value          (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t double_write_value      (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t double_read_value       (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t double_set_value        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t object_path_write_value (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t object_path_read_value  (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t object_path_set_value   (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t signature_write_value   (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t signature_read_value    (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t signature_set_value     (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t struct_write_value      (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t struct_read_value       (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t struct_set_value        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t struct_build_signature  (TestTypeNode   *node,
+                                            DBusString     *str);
+static dbus_bool_t dict_write_value        (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t dict_read_value         (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t dict_set_value          (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t dict_build_signature    (TestTypeNode   *node,
+                                            DBusString     *str);
+static dbus_bool_t array_write_value       (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t array_read_value        (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t array_set_value         (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static dbus_bool_t array_build_signature   (TestTypeNode   *node,
+                                            DBusString     *str);
+static dbus_bool_t variant_write_value     (TestTypeNode   *node,
+                                            DataBlock      *block,
+                                            DBusTypeWriter *writer,
+                                            int             seed);
+static dbus_bool_t variant_read_value      (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            int             seed);
+static dbus_bool_t variant_set_value       (TestTypeNode   *node,
+                                            DBusTypeReader *reader,
+                                            DBusTypeReader *realign_root,
+                                            int             seed);
+static void        container_destroy       (TestTypeNode   *node);
+
+
+
+static const TestTypeNodeClass int16_class = {
+  DBUS_TYPE_INT16,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  int16_write_value,
+  int16_read_value,
+  int16_set_value,
+  NULL,
+  int16_write_multi,
+  int16_read_multi
+};
+
+static const TestTypeNodeClass uint16_class = {
+  DBUS_TYPE_UINT16,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  int16_write_value, /* recycle from int16 */
+  int16_read_value,  /* recycle from int16 */
+  int16_set_value,   /* recycle from int16 */
+  NULL,
+  int16_write_multi, /* recycle from int16 */
+  int16_read_multi   /* recycle from int16 */
+};
+
+static const TestTypeNodeClass int32_class = {
+  DBUS_TYPE_INT32,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  int32_write_value,
+  int32_read_value,
+  int32_set_value,
+  NULL,
+  int32_write_multi,
+  int32_read_multi
+};
+
+static const TestTypeNodeClass uint32_class = {
+  DBUS_TYPE_UINT32,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  int32_write_value, /* recycle from int32 */
+  int32_read_value,  /* recycle from int32 */
+  int32_set_value,   /* recycle from int32 */
+  NULL,
+  int32_write_multi, /* recycle from int32 */
+  int32_read_multi   /* recycle from int32 */
+};
+
+static const TestTypeNodeClass int64_class = {
+  DBUS_TYPE_INT64,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  int64_write_value,
+  int64_read_value,
+  int64_set_value,
+  NULL,
+  NULL, /* FIXME */
+  NULL  /* FIXME */
+};
+
+static const TestTypeNodeClass uint64_class = {
+  DBUS_TYPE_UINT64,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  int64_write_value, /* recycle from int64 */
+  int64_read_value,  /* recycle from int64 */
+  int64_set_value,   /* recycle from int64 */
+  NULL,
+  NULL, /* FIXME */
+  NULL  /* FIXME */
+};
+
+static const TestTypeNodeClass string_0_class = {
+  DBUS_TYPE_STRING,
+  sizeof (TestTypeNode),
+  0, /* string length */
+  NULL,
+  NULL,
+  string_write_value,
+  string_read_value,
+  string_set_value,
+  NULL,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass string_1_class = {
+  DBUS_TYPE_STRING,
+  sizeof (TestTypeNode),
+  1, /* string length */
+  NULL,
+  NULL,
+  string_write_value,
+  string_read_value,
+  string_set_value,
+  NULL,
+  NULL,
+  NULL
+};
+
+/* with nul, a len 3 string should fill 4 bytes and thus is "special" */
+static const TestTypeNodeClass string_3_class = {
+  DBUS_TYPE_STRING,
+  sizeof (TestTypeNode),
+  3, /* string length */
+  NULL,
+  NULL,
+  string_write_value,
+  string_read_value,
+  string_set_value,
+  NULL,
+  NULL,
+  NULL
+};
+
+/* with nul, a len 8 string should fill 9 bytes and thus is "special" (far-fetched I suppose) */
+static const TestTypeNodeClass string_8_class = {
+  DBUS_TYPE_STRING,
+  sizeof (TestTypeNode),
+  8, /* string length */
+  NULL,
+  NULL,
+  string_write_value,
+  string_read_value,
+  string_set_value,
+  NULL,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass bool_class = {
+  DBUS_TYPE_BOOLEAN,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  bool_write_value,
+  bool_read_value,
+  bool_set_value,
+  NULL,
+  NULL, /* FIXME */
+  NULL  /* FIXME */
+};
+
+static const TestTypeNodeClass byte_class = {
+  DBUS_TYPE_BYTE,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  byte_write_value,
+  byte_read_value,
+  byte_set_value,
+  NULL,
+  NULL, /* FIXME */
+  NULL  /* FIXME */
+};
+
+static const TestTypeNodeClass double_class = {
+  DBUS_TYPE_DOUBLE,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  double_write_value,
+  double_read_value,
+  double_set_value,
+  NULL,
+  NULL, /* FIXME */
+  NULL  /* FIXME */
+};
+
+static const TestTypeNodeClass object_path_class = {
+  DBUS_TYPE_OBJECT_PATH,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  object_path_write_value,
+  object_path_read_value,
+  object_path_set_value,
+  NULL,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass signature_class = {
+  DBUS_TYPE_SIGNATURE,
+  sizeof (TestTypeNode),
+  0,
+  NULL,
+  NULL,
+  signature_write_value,
+  signature_read_value,
+  signature_set_value,
+  NULL,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass struct_1_class = {
+  DBUS_TYPE_STRUCT,
+  sizeof (TestTypeNodeContainer),
+  1, /* number of times children appear as fields */
+  NULL,
+  container_destroy,
+  struct_write_value,
+  struct_read_value,
+  struct_set_value,
+  struct_build_signature,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass struct_2_class = {
+  DBUS_TYPE_STRUCT,
+  sizeof (TestTypeNodeContainer),
+  2, /* number of times children appear as fields */
+  NULL,
+  container_destroy,
+  struct_write_value,
+  struct_read_value,
+  struct_set_value,
+  struct_build_signature,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass dict_1_class = {
+  DBUS_TYPE_ARRAY, /* this is correct, a dict is an array of dict entry */
+  sizeof (TestTypeNodeContainer),
+  1, /* number of entries */
+  NULL,
+  container_destroy,
+  dict_write_value,
+  dict_read_value,
+  dict_set_value,
+  dict_build_signature,
+  NULL,
+  NULL
+};
+
+static dbus_bool_t arrays_write_fixed_in_blocks = FALSE;
+
+static const TestTypeNodeClass array_0_class = {
+  DBUS_TYPE_ARRAY,
+  sizeof (TestTypeNodeContainer),
+  0, /* number of array elements */
+  NULL,
+  container_destroy,
+  array_write_value,
+  array_read_value,
+  array_set_value,
+  array_build_signature,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass array_1_class = {
+  DBUS_TYPE_ARRAY,
+  sizeof (TestTypeNodeContainer),
+  1, /* number of array elements */
+  NULL,
+  container_destroy,
+  array_write_value,
+  array_read_value,
+  array_set_value,
+  array_build_signature,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass array_2_class = {
+  DBUS_TYPE_ARRAY,
+  sizeof (TestTypeNodeContainer),
+  2, /* number of array elements */
+  NULL,
+  container_destroy,
+  array_write_value,
+  array_read_value,
+  array_set_value,
+  array_build_signature,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass array_9_class = {
+  DBUS_TYPE_ARRAY,
+  sizeof (TestTypeNodeContainer),
+  9, /* number of array elements */
+  NULL,
+  container_destroy,
+  array_write_value,
+  array_read_value,
+  array_set_value,
+  array_build_signature,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass variant_class = {
+  DBUS_TYPE_VARIANT,
+  sizeof (TestTypeNodeContainer),
+  0,
+  NULL,
+  container_destroy,
+  variant_write_value,
+  variant_read_value,
+  variant_set_value,
+  NULL,
+  NULL,
+  NULL
+};
+
+static const TestTypeNodeClass* const
+basic_nodes[] = {
+  &int16_class,
+  &uint16_class,
+  &int32_class,
+  &uint32_class,
+  &int64_class,
+  &uint64_class,
+  &bool_class,
+  &byte_class,
+  &double_class,
+  &string_0_class,
+  &string_1_class,
+  &string_3_class,
+  &string_8_class,
+  &object_path_class,
+  &signature_class
+};
+#define N_BASICS (_DBUS_N_ELEMENTS (basic_nodes))
+
+static const TestTypeNodeClass* const
+container_nodes[] = {
+  &struct_1_class,
+  &array_1_class,
+  &struct_2_class,
+  &array_0_class,
+  &array_2_class,
+  &variant_class,
+  &dict_1_class /* last since we want struct and array before it */
+  /* array_9_class is omitted on purpose, it's too slow;
+   * we only use it in one hardcoded test below
+   */
+};
+#define N_CONTAINERS (_DBUS_N_ELEMENTS (container_nodes))
+
+static TestTypeNode*
+node_new (const TestTypeNodeClass *klass)
+{
+  TestTypeNode *node;
+
+  node = dbus_malloc0 (klass->instance_size);
+  if (node == NULL)
+    return NULL;
+
+  node->klass = klass;
+
+  if (klass->construct)
+    {
+      if (!(* klass->construct) (node))
+        {
+          dbus_free (node);
+          return NULL;
+        }
+    }
+
+  return node;
+}
+
+static void
+node_destroy (TestTypeNode *node)
+{
+  if (node->klass->destroy)
+    (* node->klass->destroy) (node);
+  dbus_free (node);
+}
+
+static dbus_bool_t
+node_write_value (TestTypeNode   *node,
+                  DataBlock      *block,
+                  DBusTypeWriter *writer,
+                  int             seed)
+{
+  dbus_bool_t retval;
+
+  retval = (* node->klass->write_value) (node, block, writer, seed);
+
+#if 0
+  /* Handy to see where things break, but too expensive to do all the time */
+  data_block_verify (block);
+#endif
+
+  return retval;
+}
+
+static dbus_bool_t
+node_read_value (TestTypeNode   *node,
+                 DBusTypeReader *reader,
+                 int             seed)
+{
+  /* DBusTypeReader restored; */
+
+  if (!(* node->klass->read_value) (node, reader, seed))
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Warning: if this one fails due to OOM, it has side effects (can
+ * modify only some of the sub-values). OK in a test suite, but we
+ * never do this in real code.
+ */
+static dbus_bool_t
+node_set_value (TestTypeNode   *node,
+                DBusTypeReader *reader,
+                DBusTypeReader *realign_root,
+                int             seed)
+{
+  if (!(* node->klass->set_value) (node, reader, realign_root, seed))
+    return FALSE;
+
+  return TRUE;
+}
+
+static dbus_bool_t
+node_build_signature (TestTypeNode *node,
+                      DBusString   *str)
+{
+  if (node->klass->build_signature)
+    return (* node->klass->build_signature) (node, str);
+  else
+    return _dbus_string_append_byte (str, node->klass->typecode);
+}
+
+static dbus_bool_t
+node_append_child (TestTypeNode *node,
+                   TestTypeNode *child)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+
+  _dbus_assert (node->klass->instance_size >= (int) sizeof (TestTypeNodeContainer));
+
+  if (!_dbus_list_append (&container->children, child))
+    _dbus_assert_not_reached ("no memory"); /* we never check the return value on node_append_child anyhow - it's run from outside the malloc-failure test code */
+
+  return TRUE;
+}
+
+static dbus_bool_t
+node_write_multi (TestTypeNode   *node,
+                  DataBlock      *block,
+                  DBusTypeWriter *writer,
+                  int             seed,
+                  int             n_copies)
+{
+  dbus_bool_t retval;
+
+  _dbus_assert (node->klass->write_multi != NULL);
+  retval = (* node->klass->write_multi) (node, block, writer, seed, n_copies);
+
+#if 0
+  /* Handy to see where things break, but too expensive to do all the time */
+  data_block_verify (block);
+#endif
+
+  return retval;
+}
+
+static dbus_bool_t
+node_read_multi (TestTypeNode   *node,
+                 DBusTypeReader *reader,
+                 int             seed,
+                 int             n_copies)
+{
+  _dbus_assert (node->klass->read_multi != NULL);
+
+  if (!(* node->klass->read_multi) (node, reader, seed, n_copies))
+    return FALSE;
+
+  return TRUE;
+}
+
+static int n_iterations_completed_total = 0;
+static int n_iterations_completed_this_test = 0;
+static int n_iterations_expected_this_test = 0;
+
+typedef struct
+{
+  const DBusString   *signature;
+  DataBlock          *block;
+  int                 type_offset;
+  TestTypeNode      **nodes;
+  int                 n_nodes;
+} NodeIterationData;
+
+static dbus_bool_t
+run_test_copy (NodeIterationData *nid)
+{
+  DataBlock *src;
+  DataBlock dest;
+  dbus_bool_t retval;
+  DBusTypeReader reader;
+  DBusTypeWriter writer;
+
+  _dbus_verbose ("\n");
+
+  src = nid->block;
+
+  retval = FALSE;
+
+  if (!data_block_init (&dest, src->byte_order, src->initial_offset))
+    return FALSE;
+
+  data_block_init_reader_writer (src, &reader, NULL);
+  data_block_init_reader_writer (&dest, NULL, &writer);
+
+  /* DBusTypeWriter assumes it's writing into an existing signature,
+   * so doesn't add nul on its own. We have to do that.
+   */
+  if (!_dbus_string_insert_byte (&dest.signature,
+                                 dest.initial_offset, '\0'))
+    goto out;
+
+  if (!_dbus_type_writer_write_reader (&writer, &reader))
+    goto out;
+
+  /* Data blocks should now be identical */
+  if (!_dbus_string_equal (&src->signature, &dest.signature))
+    {
+      _dbus_verbose ("SOURCE\n");
+      _dbus_verbose_bytes_of_string (&src->signature, 0,
+                                     _dbus_string_get_length (&src->signature));
+      _dbus_verbose ("DEST\n");
+      _dbus_verbose_bytes_of_string (&dest.signature, 0,
+                                     _dbus_string_get_length (&dest.signature));
+      _dbus_assert_not_reached ("signatures did not match");
+    }
+
+  if (!_dbus_string_equal (&src->body, &dest.body))
+    {
+      _dbus_verbose ("SOURCE\n");
+      _dbus_verbose_bytes_of_string (&src->body, 0,
+                                     _dbus_string_get_length (&src->body));
+      _dbus_verbose ("DEST\n");
+      _dbus_verbose_bytes_of_string (&dest.body, 0,
+                                     _dbus_string_get_length (&dest.body));
+      _dbus_assert_not_reached ("bodies did not match");
+    }
+
+  retval = TRUE;
+
+ out:
+
+  data_block_free (&dest);
+
+  return retval;
+}
+
+static dbus_bool_t
+run_test_values_only_write (NodeIterationData *nid)
+{
+  DBusTypeReader reader;
+  DBusTypeWriter writer;
+  int i;
+  dbus_bool_t retval;
+  int sig_len;
+
+  _dbus_verbose ("\n");
+
+  retval = FALSE;
+
+  data_block_reset (nid->block);
+
+  sig_len = _dbus_string_get_length (nid->signature);
+
+  _dbus_type_writer_init_values_only (&writer,
+                                      nid->block->byte_order,
+                                      nid->signature, 0,
+                                      &nid->block->body,
+                                      _dbus_string_get_length (&nid->block->body) - N_FENCE_BYTES);
+  _dbus_type_reader_init (&reader,
+                          nid->block->byte_order,
+                          nid->signature, 0,
+                          &nid->block->body,
+                          nid->block->initial_offset);
+
+  i = 0;
+  while (i < nid->n_nodes)
+    {
+      if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
+        goto out;
+
+      ++i;
+    }
+
+  /* if we wrote any typecodes then this would fail */
+  _dbus_assert (sig_len == _dbus_string_get_length (nid->signature));
+
+  /* But be sure we wrote out the values correctly */
+  i = 0;
+  while (i < nid->n_nodes)
+    {
+      if (!node_read_value (nid->nodes[i], &reader, i))
+        goto out;
+
+      if (i + 1 == nid->n_nodes)
+        NEXT_EXPECTING_FALSE (&reader);
+      else
+        NEXT_EXPECTING_TRUE (&reader);
+
+      ++i;
+    }
+
+  retval = TRUE;
+
+ out:
+  data_block_reset (nid->block);
+  return retval;
+}
+
+/* offset the seed for setting, so we set different numbers than
+ * we originally wrote. Don't offset by a huge number since in
+ * some cases it's value = possibilities[seed % n_possibilities]
+ * and we don't want to wrap around. bool_from_seed
+ * is just seed % 2 even.
+ */
+#define SET_SEED 1
+static dbus_bool_t
+run_test_set_values (NodeIterationData *nid)
+{
+  DBusTypeReader reader;
+  DBusTypeReader realign_root;
+  dbus_bool_t retval;
+  int i;
+
+  _dbus_verbose ("\n");
+
+  retval = FALSE;
+
+  data_block_init_reader_writer (nid->block,
+                                 &reader, NULL);
+
+  realign_root = reader;
+
+  i = 0;
+  while (i < nid->n_nodes)
+    {
+      if (!node_set_value (nid->nodes[i],
+                           &reader, &realign_root,
+                           i + SET_SEED))
+        goto out;
+
+      if (i + 1 == nid->n_nodes)
+        NEXT_EXPECTING_FALSE (&reader);
+      else
+        NEXT_EXPECTING_TRUE (&reader);
+
+      ++i;
+    }
+
+  /* Check that the new values were set */
+
+  reader = realign_root;
+
+  i = 0;
+  while (i < nid->n_nodes)
+    {
+      if (!node_read_value (nid->nodes[i], &reader,
+                            i + SET_SEED))
+        goto out;
+
+      if (i + 1 == nid->n_nodes)
+        NEXT_EXPECTING_FALSE (&reader);
+      else
+        NEXT_EXPECTING_TRUE (&reader);
+
+      ++i;
+    }
+
+  retval = TRUE;
+
+ out:
+  return retval;
+}
+
+static dbus_bool_t
+run_test_delete_values (NodeIterationData *nid)
+{
+  DBusTypeReader reader;
+  dbus_bool_t retval;
+  int t;
+
+  _dbus_verbose ("\n");
+
+  retval = FALSE;
+
+  data_block_init_reader_writer (nid->block,
+                                 &reader, NULL);
+
+  while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID)
+    {
+      /* Right now, deleting only works on array elements.  We delete
+       * all array elements, and then verify that there aren't any
+       * left.
+       */
+      if (t == DBUS_TYPE_ARRAY)
+        {
+          DBusTypeReader array;
+          int n_elements;
+          int elem_type;
+
+          _dbus_type_reader_recurse (&reader, &array);
+          n_elements = 0;
+          while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
+            {
+              n_elements += 1;
+              _dbus_type_reader_next (&array);
+            }
+
+          /* reset to start of array */
+          _dbus_type_reader_recurse (&reader, &array);
+          _dbus_verbose ("recursing into deletion loop reader.value_pos = %d array.value_pos = %d array.u.start_pos = %d\n",
+                         reader.value_pos, array.value_pos, array.u.array.start_pos);
+          while ((elem_type = _dbus_type_reader_get_current_type (&array)) != DBUS_TYPE_INVALID)
+            {
+              /* We don't want to always delete from the same part of the array. */
+              static int cycle = 0;
+              int elem;
+
+              _dbus_assert (n_elements > 0);
+
+              elem = cycle;
+              if (elem == 3 || elem >= n_elements) /* end of array */
+                elem = n_elements - 1;
+
+              _dbus_verbose ("deleting array element %d of %d type %s cycle %d reader pos %d elem pos %d\n",
+                             elem, n_elements, _dbus_type_to_string (elem_type),
+                             cycle, reader.value_pos, array.value_pos);
+              while (elem > 0)
+                {
+                  if (!_dbus_type_reader_next (&array))
+                    _dbus_assert_not_reached ("should have had another element\n");
+                  --elem;
+                }
+
+              if (!_dbus_type_reader_delete (&array, &reader))
+                goto out;
+
+              n_elements -= 1;
+
+              /* reset */
+              _dbus_type_reader_recurse (&reader, &array);
+
+              if (cycle > 2)
+                cycle = 0;
+              else
+                cycle += 1;
+            }
+        }
+      _dbus_type_reader_next (&reader);
+    }
+
+  /* Check that there are no array elements left */
+  data_block_init_reader_writer (nid->block,
+                                 &reader, NULL);
+
+  while ((t = _dbus_type_reader_get_current_type (&reader)) != DBUS_TYPE_INVALID)
+    {
+      _dbus_type_reader_next (&reader);
+    }
+
+  retval = TRUE;
+
+ out:
+  return retval;
+}
+
+static dbus_bool_t
+run_test_nodes_iteration (void *data)
+{
+  NodeIterationData *nid = data;
+  DBusTypeReader reader;
+  DBusTypeWriter writer;
+  int i;
+  dbus_bool_t retval;
+
+  /* Stuff to do:
+   * 1. write the value
+   * 2. strcmp-compare with the signature we built
+   * 3. read the value
+   * 4. type-iterate the signature and the value and see if they are the same type-wise
+   */
+  retval = FALSE;
+
+  data_block_init_reader_writer (nid->block,
+                                 &reader, &writer);
+
+  /* DBusTypeWriter assumes it's writing into an existing signature,
+   * so doesn't add nul on its own. We have to do that.
+   */
+  if (!_dbus_string_insert_byte (&nid->block->signature,
+                                 nid->type_offset, '\0'))
+    goto out;
+
+  i = 0;
+  while (i < nid->n_nodes)
+    {
+      if (!node_write_value (nid->nodes[i], nid->block, &writer, i))
+        goto out;
+
+      ++i;
+    }
+
+  if (!_dbus_string_equal_substring (nid->signature, 0, _dbus_string_get_length (nid->signature),
+                                     &nid->block->signature, nid->type_offset))
+    {
+      _dbus_warn ("Expected signature '%s' and got '%s' with initial offset %d\n",
+                  _dbus_string_get_const_data (nid->signature),
+                  _dbus_string_get_const_data_len (&nid->block->signature, nid->type_offset, 0),
+                  nid->type_offset);
+      _dbus_assert_not_reached ("wrong signature");
+    }
+
+  i = 0;
+  while (i < nid->n_nodes)
+    {
+      if (!node_read_value (nid->nodes[i], &reader, i))
+        goto out;
+
+      if (i + 1 == nid->n_nodes)
+        NEXT_EXPECTING_FALSE (&reader);
+      else
+        NEXT_EXPECTING_TRUE (&reader);
+
+      ++i;
+    }
+
+  if (n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
+    {
+      /* this set values test uses code from copy and
+       * values_only_write so would ideally be last so you get a
+       * simpler test case for problems with copying or values_only
+       * writing; but it also needs an already-written DataBlock so it
+       * has to go first. Comment it out if it breaks, and see if the
+       * later tests also break - debug them first if so.
+       */
+      if (!run_test_set_values (nid))
+        goto out;
+
+      if (!run_test_delete_values (nid))
+        goto out;
+
+      if (!run_test_copy (nid))
+        goto out;
+
+      if (!run_test_values_only_write (nid))
+        goto out;
+    }
+
+  /* FIXME type-iterate both signature and value and compare the resulting
+   * tree to the node tree perhaps
+   */
+
+  retval = TRUE;
+
+ out:
+
+  data_block_reset (nid->block);
+
+  return retval;
+}
+
+static void
+run_test_nodes_in_one_configuration (TestTypeNode    **nodes,
+                                     int               n_nodes,
+                                     const DBusString *signature,
+                                     int               byte_order,
+                                     int               initial_offset)
+{
+  DataBlock block;
+  NodeIterationData nid;
+
+  if (!data_block_init (&block, byte_order, initial_offset))
+    _dbus_assert_not_reached ("no memory");
+
+  nid.signature = signature;
+  nid.block = &block;
+  nid.type_offset = initial_offset;
+  nid.nodes = nodes;
+  nid.n_nodes = n_nodes;
+
+  if (TEST_OOM_HANDLING &&
+      n_iterations_expected_this_test <= MAX_ITERATIONS_FOR_EXPENSIVE_TESTS)
+    {
+      _dbus_test_oom_handling ("running test node",
+                               run_test_nodes_iteration,
+                               &nid);
+    }
+  else
+    {
+      if (!run_test_nodes_iteration (&nid))
+        _dbus_assert_not_reached ("no memory");
+    }
+
+  data_block_free (&block);
+}
+
+static void
+run_test_nodes (TestTypeNode **nodes,
+                int            n_nodes)
+{
+  int i;
+  DBusString signature;
+
+  if (!_dbus_string_init (&signature))
+    _dbus_assert_not_reached ("no memory");
+
+  i = 0;
+  while (i < n_nodes)
+    {
+      if (! node_build_signature (nodes[i], &signature))
+        _dbus_assert_not_reached ("no memory");
+
+      ++i;
+    }
+
+  _dbus_verbose (">>> test nodes with signature '%s'\n",
+                 _dbus_string_get_const_data (&signature));
+
+  i = 0;
+  while (i <= MAX_INITIAL_OFFSET)
+    {
+      run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
+                                           DBUS_LITTLE_ENDIAN, i);
+      run_test_nodes_in_one_configuration (nodes, n_nodes, &signature,
+                                           DBUS_BIG_ENDIAN, i);
+
+      ++i;
+    }
+
+  n_iterations_completed_this_test += 1;
+  n_iterations_completed_total += 1;
+
+  if (n_iterations_completed_this_test == n_iterations_expected_this_test)
+    {
+      fprintf (stderr, " 100%% %d this test (%d cumulative)\n",
+               n_iterations_completed_this_test,
+               n_iterations_completed_total);
+    }
+  /* this happens to turn out well with mod == 1 */
+  else if ((n_iterations_completed_this_test %
+            (int)(n_iterations_expected_this_test / 10.0)) == 1)
+    {
+      fprintf (stderr, " %d%% ", (int) (n_iterations_completed_this_test / (double) n_iterations_expected_this_test * 100));
+    }
+
+  _dbus_string_free (&signature);
+}
+
+#define N_VALUES (N_BASICS * N_CONTAINERS + N_BASICS)
+
+static TestTypeNode*
+value_generator (int *ip)
+{
+  int i = *ip;
+  const TestTypeNodeClass *child_klass;
+  const TestTypeNodeClass *container_klass;
+  TestTypeNode *child;
+  TestTypeNode *node;
+
+  _dbus_assert (i <= N_VALUES);
+
+  if (i == N_VALUES)
+    {
+      return NULL;
+    }
+  else if (i < N_BASICS)
+    {
+      node = node_new (basic_nodes[i]);
+    }
+  else
+    {
+      /* imagine an array:
+       * container 0 of basic 0
+       * container 0 of basic 1
+       * container 0 of basic 2
+       * container 1 of basic 0
+       * container 1 of basic 1
+       * container 1 of basic 2
+       */
+      i -= N_BASICS;
+
+      container_klass = container_nodes[i / N_BASICS];
+      child_klass = basic_nodes[i % N_BASICS];
+
+      node = node_new (container_klass);
+      child = node_new (child_klass);
+
+      node_append_child (node, child);
+    }
+
+  *ip += 1; /* increment the generator */
+
+  return node;
+}
+
+static void
+build_body (TestTypeNode **nodes,
+            int            n_nodes,
+            int            byte_order,
+            DBusString    *signature,
+            DBusString    *body)
+{
+  int i;
+  DataBlock block;
+  DBusTypeReader reader;
+  DBusTypeWriter writer;
+
+  i = 0;
+  while (i < n_nodes)
+    {
+      if (! node_build_signature (nodes[i], signature))
+        _dbus_assert_not_reached ("no memory");
+      
+      ++i;
+    }
+
+  if (!data_block_init (&block, byte_order, 0))
+    _dbus_assert_not_reached ("no memory");
+  
+  data_block_init_reader_writer (&block,
+                                 &reader, &writer);
+  
+  /* DBusTypeWriter assumes it's writing into an existing signature,
+   * so doesn't add nul on its own. We have to do that.
+   */
+  if (!_dbus_string_insert_byte (&block.signature,
+                                 0, '\0'))
+    _dbus_assert_not_reached ("no memory");
+
+  i = 0;
+  while (i < n_nodes)
+    {
+      if (!node_write_value (nodes[i], &block, &writer, i))
+        _dbus_assert_not_reached ("no memory");
+
+      ++i;
+    }
+
+  if (!_dbus_string_copy_len (&block.body, 0,
+                              _dbus_string_get_length (&block.body) - N_FENCE_BYTES,
+                              body, 0))
+    _dbus_assert_not_reached ("oom");
+
+  data_block_free (&block);  
+}
+
+dbus_bool_t
+dbus_internal_do_not_use_generate_bodies (int           sequence,
+                                          int           byte_order,
+                                          DBusString   *signature,
+                                          DBusString   *body)
+{
+  TestTypeNode *nodes[1];
+  int i;
+  int n_nodes;
+
+  nodes[0] = value_generator (&sequence);
+
+  if (nodes[0] == NULL)
+    return FALSE;
+
+  n_nodes = 1;
+  
+  build_body (nodes, n_nodes, byte_order, signature, body);
+
+
+  i = 0;
+  while (i < n_nodes)
+    {
+      node_destroy (nodes[i]);
+      ++i;
+    }
+  
+  return TRUE;
+}
+
+static void
+make_and_run_values_inside_container (const TestTypeNodeClass *container_klass,
+                                      int                      n_nested)
+{
+  TestTypeNode *root;
+  TestTypeNode *container;
+  TestTypeNode *child;
+  int i;
+
+  root = node_new (container_klass);
+  container = root;
+  for (i = 1; i < n_nested; i++)
+    {
+      child = node_new (container_klass);
+      node_append_child (container, child);
+      container = child;
+    }
+
+  /* container should now be the most-nested container */
+
+  i = 0;
+  while ((child = value_generator (&i)))
+    {
+      node_append_child (container, child);
+
+      run_test_nodes (&root, 1);
+
+      _dbus_list_clear (&((TestTypeNodeContainer*)container)->children);
+      node_destroy (child);
+    }
+
+  node_destroy (root);
+}
+
+static void
+start_next_test (const char *format,
+                 int         expected)
+{
+  n_iterations_completed_this_test = 0;
+  n_iterations_expected_this_test = expected;
+
+  fprintf (stderr, ">>> >>> ");
+  fprintf (stderr, format,
+           n_iterations_expected_this_test);
+}
+
+static void
+make_and_run_test_nodes (void)
+{
+  int i, j, k, m;
+
+  /* We try to do this in order of "complicatedness" so that test
+   * failures tend to show up in the simplest test case that
+   * demonstrates the failure.  There are also some tests that run
+   * more than once for this reason, first while going through simple
+   * cases, second while going through a broader range of complex
+   * cases.
+   */
+  /* Each basic node. The basic nodes should include:
+   *
+   * - each fixed-size type (in such a way that it has different values each time,
+   *                         so we can tell if we mix two of them up)
+   * - strings of various lengths
+   * - object path
+   * - signature
+   */
+  /* Each container node. The container nodes should include:
+   *
+   *  struct with 1 and 2 copies of the contained item
+   *  array with 0, 1, 2 copies of the contained item
+   *  variant
+   */
+  /*  Let a "value" be a basic node, or a container containing a single basic node.
+   *  Let n_values be the number of such values i.e. (n_container * n_basic + n_basic)
+   *  When iterating through all values to make combinations, do the basic types
+   *  first and the containers second.
+   */
+  /* Each item is shown with its number of iterations to complete so
+   * we can keep a handle on this unit test
+   */
+
+  /* FIXME test just an empty body, no types at all */
+
+  start_next_test ("Each value by itself %d iterations\n", N_VALUES);
+  {
+    TestTypeNode *node;
+    i = 0;
+    while ((node = value_generator (&i)))
+      {
+        run_test_nodes (&node, 1);
+
+        node_destroy (node);
+      }
+  }
+
+  start_next_test ("Each value by itself with arrays as blocks %d iterations\n", N_VALUES);
+  arrays_write_fixed_in_blocks = TRUE;
+  {
+    TestTypeNode *node;
+    i = 0;
+    while ((node = value_generator (&i)))
+      {
+        run_test_nodes (&node, 1);
+
+        node_destroy (node);
+      }
+  }
+  arrays_write_fixed_in_blocks = FALSE;
+
+  start_next_test ("All values in one big toplevel %d iteration\n", 1);
+  {
+    TestTypeNode *nodes[N_VALUES];
+
+    i = 0;
+    while ((nodes[i] = value_generator (&i)))
+      ;
+
+    run_test_nodes (nodes, N_VALUES);
+
+    for (i = 0; i < N_VALUES; i++)
+      node_destroy (nodes[i]);
+  }
+
+  start_next_test ("Each value,value pair combination as toplevel, in both orders %d iterations\n",
+                   N_VALUES * N_VALUES);
+  {
+    TestTypeNode *nodes[2];
+
+    i = 0;
+    while ((nodes[0] = value_generator (&i)))
+      {
+        j = 0;
+        while ((nodes[1] = value_generator (&j)))
+          {
+            run_test_nodes (nodes, 2);
+
+            node_destroy (nodes[1]);
+          }
+
+        node_destroy (nodes[0]);
+      }
+  }
+
+  start_next_test ("Each container containing each value %d iterations\n",
+                   N_CONTAINERS * N_VALUES);
+  for (i = 0; i < N_CONTAINERS; i++)
+    {
+      const TestTypeNodeClass *container_klass = container_nodes[i];
+
+      make_and_run_values_inside_container (container_klass, 1);
+    }
+
+  start_next_test ("Each container containing each value with arrays as blocks %d iterations\n",
+                   N_CONTAINERS * N_VALUES);
+  arrays_write_fixed_in_blocks = TRUE;
+  for (i = 0; i < N_CONTAINERS; i++)
+    {
+      const TestTypeNodeClass *container_klass = container_nodes[i];
+
+      make_and_run_values_inside_container (container_klass, 1);
+    }
+  arrays_write_fixed_in_blocks = FALSE;
+
+  start_next_test ("Each container of same container of each value %d iterations\n",
+                   N_CONTAINERS * N_VALUES);
+  for (i = 0; i < N_CONTAINERS; i++)
+    {
+      const TestTypeNodeClass *container_klass = container_nodes[i];
+
+      make_and_run_values_inside_container (container_klass, 2);
+    }
+
+  start_next_test ("Each container of same container of same container of each value %d iterations\n",
+                   N_CONTAINERS * N_VALUES);
+  for (i = 0; i < N_CONTAINERS; i++)
+    {
+      const TestTypeNodeClass *container_klass = container_nodes[i];
+
+      make_and_run_values_inside_container (container_klass, 3);
+    }
+
+  start_next_test ("Each value,value pair inside a struct %d iterations\n",
+                   N_VALUES * N_VALUES);
+  {
+    TestTypeNode *val1, *val2;
+    TestTypeNode *node;
+
+    node = node_new (&struct_1_class);
+
+    i = 0;
+    while ((val1 = value_generator (&i)))
+      {
+        j = 0;
+        while ((val2 = value_generator (&j)))
+          {
+            TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+
+            node_append_child (node, val1);
+            node_append_child (node, val2);
+
+            run_test_nodes (&node, 1);
+
+            _dbus_list_clear (&container->children);
+            node_destroy (val2);
+          }
+        node_destroy (val1);
+      }
+    node_destroy (node);
+  }
+
+  start_next_test ("All values in one big struct %d iteration\n",
+                   1);
+  {
+    TestTypeNode *node;
+    TestTypeNode *child;
+
+    node = node_new (&struct_1_class);
+
+    i = 0;
+    while ((child = value_generator (&i)))
+      node_append_child (node, child);
+
+    run_test_nodes (&node, 1);
+
+    node_destroy (node);
+  }
+
+  start_next_test ("Each value in a large array %d iterations\n",
+                   N_VALUES);
+  {
+    TestTypeNode *val;
+    TestTypeNode *node;
+
+    node = node_new (&array_9_class);
+
+    i = 0;
+    while ((val = value_generator (&i)))
+      {
+        TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+
+        node_append_child (node, val);
+
+        run_test_nodes (&node, 1);
+
+        _dbus_list_clear (&container->children);
+        node_destroy (val);
+      }
+
+    node_destroy (node);
+  }
+
+  if (_dbus_getenv ("DBUS_TEST_SLOW") == NULL ||
+      atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 1)
+    {
+      fprintf (stderr, "skipping remaining marshal-recursive tests, "
+          "run with DBUS_TEST_SLOW=1 (or more) to enable\n");
+      goto out;
+    }
+
+  start_next_test ("Each container of each container of each value %d iterations\n",
+                   N_CONTAINERS * N_CONTAINERS * N_VALUES);
+  for (i = 0; i < N_CONTAINERS; i++)
+    {
+      const TestTypeNodeClass *outer_container_klass = container_nodes[i];
+      TestTypeNode *outer_container = node_new (outer_container_klass);
+
+      for (j = 0; j < N_CONTAINERS; j++)
+        {
+          TestTypeNode *child;
+          const TestTypeNodeClass *inner_container_klass = container_nodes[j];
+          TestTypeNode *inner_container = node_new (inner_container_klass);
+
+          node_append_child (outer_container, inner_container);
+
+          m = 0;
+          while ((child = value_generator (&m)))
+            {
+              node_append_child (inner_container, child);
+
+              run_test_nodes (&outer_container, 1);
+
+              _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
+              node_destroy (child);
+            }
+          _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
+          node_destroy (inner_container);
+        }
+      node_destroy (outer_container);
+    }
+
+  start_next_test ("Each container of each container of each container of each value %d iterations\n",
+                   N_CONTAINERS * N_CONTAINERS * N_CONTAINERS * N_VALUES);
+  for (i = 0; i < N_CONTAINERS; i++)
+    {
+      const TestTypeNodeClass *outer_container_klass = container_nodes[i];
+      TestTypeNode *outer_container = node_new (outer_container_klass);
+
+      for (j = 0; j < N_CONTAINERS; j++)
+        {
+          const TestTypeNodeClass *inner_container_klass = container_nodes[j];
+          TestTypeNode *inner_container = node_new (inner_container_klass);
+
+          node_append_child (outer_container, inner_container);
+
+          for (k = 0; k < N_CONTAINERS; k++)
+            {
+              TestTypeNode *child;
+              const TestTypeNodeClass *center_container_klass = container_nodes[k];
+              TestTypeNode *center_container = node_new (center_container_klass);
+
+              node_append_child (inner_container, center_container);
+
+              m = 0;
+              while ((child = value_generator (&m)))
+                {
+                  node_append_child (center_container, child);
+
+                  run_test_nodes (&outer_container, 1);
+
+                  _dbus_list_clear (&((TestTypeNodeContainer*)center_container)->children);
+                  node_destroy (child);
+                }
+              _dbus_list_clear (&((TestTypeNodeContainer*)inner_container)->children);
+              node_destroy (center_container);
+            }
+          _dbus_list_clear (&((TestTypeNodeContainer*)outer_container)->children);
+          node_destroy (inner_container);
+        }
+      node_destroy (outer_container);
+    }
+
+  /* This one takes a really long time (10 minutes on a Core2), so only enable
+   * it if you're really sure */
+  if (atoi (_dbus_getenv ("DBUS_TEST_SLOW")) < 2)
+    {
+      fprintf (stderr, "skipping really slow marshal-recursive test, "
+          "run with DBUS_TEST_SLOW=2 (or more) to enable\n");
+      goto out;
+    }
+
+  start_next_test ("Each value,value,value triplet combination as toplevel, in all orders %d iterations\n",
+                   N_VALUES * N_VALUES * N_VALUES);
+  {
+    TestTypeNode *nodes[3];
+
+    i = 0;
+    while ((nodes[0] = value_generator (&i)))
+      {
+        j = 0;
+        while ((nodes[1] = value_generator (&j)))
+          {
+            k = 0;
+            while ((nodes[2] = value_generator (&k)))
+              {
+                run_test_nodes (nodes, 3);
+
+                node_destroy (nodes[2]);
+              }
+            node_destroy (nodes[1]);
+          }
+        node_destroy (nodes[0]);
+      }
+  }
+
+out:
+  fprintf (stderr, "%d total iterations of recursive marshaling tests\n",
+           n_iterations_completed_total);
+  fprintf (stderr, "each iteration ran at initial offsets 0 through %d in both big and little endian\n",
+           MAX_INITIAL_OFFSET);
+  fprintf (stderr, "out of memory handling %s tested\n",
+           TEST_OOM_HANDLING ? "was" : "was not");
+}
+
+dbus_bool_t
+_dbus_marshal_recursive_test (void)
+{
+  make_and_run_test_nodes ();
+
+  return TRUE;
+}
+
+/*
+ *
+ *
+ *         Implementations of each type node class
+ *
+ *
+ *
+ */
+#define MAX_MULTI_COUNT 5
+
+#define SAMPLE_INT16           1234
+#define SAMPLE_INT16_ALTERNATE 6785
+static dbus_int16_t
+int16_from_seed (int seed)
+{
+  /* Generate an integer value that's predictable from seed.  We could
+   * just use seed itself, but that would only ever touch one byte of
+   * the int so would miss some kinds of bug.
+   */
+  dbus_int16_t v;
+
+  v = 42; /* just to quiet compiler afaik */
+  switch (seed % 5)
+    {
+    case 0:
+      v = SAMPLE_INT16;
+      break;
+    case 1:
+      v = SAMPLE_INT16_ALTERNATE;
+      break;
+    case 2:
+      v = -1;
+      break;
+    case 3:
+      v = _DBUS_INT16_MAX;
+      break;
+    case 4:
+      v = 1;
+      break;
+    }
+
+  if (seed > 1)
+    v *= seed; /* wraps around eventually, which is fine */
+
+  return v;
+}
+
+static dbus_bool_t
+int16_write_value (TestTypeNode   *node,
+                   DataBlock      *block,
+                   DBusTypeWriter *writer,
+                   int             seed)
+{
+  /* also used for uint16 */
+  dbus_int16_t v;
+
+  v = int16_from_seed (seed);
+
+  return _dbus_type_writer_write_basic (writer,
+                                        node->klass->typecode,
+                                        &v);
+}
+
+static dbus_bool_t
+int16_read_value (TestTypeNode   *node,
+                  DBusTypeReader *reader,
+                  int             seed)
+{
+  /* also used for uint16 */
+  dbus_int16_t v;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_basic (reader,
+                                (dbus_int16_t*) &v);
+
+  _dbus_assert (v == int16_from_seed (seed));
+
+  return TRUE;
+}
+
+static dbus_bool_t
+int16_set_value (TestTypeNode   *node,
+                 DBusTypeReader *reader,
+                 DBusTypeReader *realign_root,
+                 int             seed)
+{
+  /* also used for uint16 */
+  dbus_int16_t v;
+
+  v = int16_from_seed (seed);
+
+  return _dbus_type_reader_set_basic (reader,
+                                      &v,
+                                      realign_root);
+}
+
+static dbus_bool_t
+int16_write_multi (TestTypeNode   *node,
+                   DataBlock      *block,
+                   DBusTypeWriter *writer,
+                   int             seed,
+                   int             count)
+{
+  /* also used for uint16 */
+  dbus_int16_t values[MAX_MULTI_COUNT];
+  dbus_int16_t *v_ARRAY_INT16 = values;
+  int i;
+
+  for (i = 0; i < count; ++i)
+    values[i] = int16_from_seed (seed + i);
+
+  return _dbus_type_writer_write_fixed_multi (writer,
+                                              node->klass->typecode,
+                                              &v_ARRAY_INT16, count);
+}
+
+static dbus_bool_t
+int16_read_multi (TestTypeNode   *node,
+                  DBusTypeReader *reader,
+                  int             seed,
+                  int             count)
+{
+  /* also used for uint16 */
+  dbus_int16_t *values;
+  int n_elements;
+  int i;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_fixed_multi (reader,
+                                      &values,
+                                      &n_elements);
+
+  if (n_elements != count)
+    _dbus_warn ("got %d elements expected %d\n", n_elements, count);
+  _dbus_assert (n_elements == count);
+
+  for (i = 0; i < count; i++)
+    _dbus_assert (((dbus_int16_t)_dbus_unpack_uint16 (reader->byte_order,
+                                                      (const unsigned char*)values + (i * 2))) ==
+                  int16_from_seed (seed + i));
+
+  return TRUE;
+}
+
+
+#define SAMPLE_INT32           12345678
+#define SAMPLE_INT32_ALTERNATE 53781429
+static dbus_int32_t
+int32_from_seed (int seed)
+{
+  /* Generate an integer value that's predictable from seed.  We could
+   * just use seed itself, but that would only ever touch one byte of
+   * the int so would miss some kinds of bug.
+   */
+  dbus_int32_t v;
+
+  v = 42; /* just to quiet compiler afaik */
+  switch (seed % 5)
+    {
+    case 0:
+      v = SAMPLE_INT32;
+      break;
+    case 1:
+      v = SAMPLE_INT32_ALTERNATE;
+      break;
+    case 2:
+      v = -1;
+      break;
+    case 3:
+      v = _DBUS_INT_MAX;
+      break;
+    case 4:
+      v = 1;
+      break;
+    }
+
+  if (seed > 1)
+    v *= seed; /* wraps around eventually, which is fine */
+
+  return v;
+}
+
+static dbus_bool_t
+int32_write_value (TestTypeNode   *node,
+                   DataBlock      *block,
+                   DBusTypeWriter *writer,
+                   int             seed)
+{
+  /* also used for uint32 */
+  dbus_int32_t v;
+
+  v = int32_from_seed (seed);
+
+  return _dbus_type_writer_write_basic (writer,
+                                        node->klass->typecode,
+                                        &v);
+}
+
+static dbus_bool_t
+int32_read_value (TestTypeNode   *node,
+                  DBusTypeReader *reader,
+                  int             seed)
+{
+  /* also used for uint32 */
+  dbus_int32_t v;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_basic (reader,
+                                (dbus_int32_t*) &v);
+
+  _dbus_assert (v == int32_from_seed (seed));
+
+  return TRUE;
+}
+
+static dbus_bool_t
+int32_set_value (TestTypeNode   *node,
+                 DBusTypeReader *reader,
+                 DBusTypeReader *realign_root,
+                 int             seed)
+{
+  /* also used for uint32 */
+  dbus_int32_t v;
+
+  v = int32_from_seed (seed);
+
+  return _dbus_type_reader_set_basic (reader,
+                                      &v,
+                                      realign_root);
+}
+
+static dbus_bool_t
+int32_write_multi (TestTypeNode   *node,
+                   DataBlock      *block,
+                   DBusTypeWriter *writer,
+                   int             seed,
+                   int             count)
+{
+  /* also used for uint32 */
+  dbus_int32_t values[MAX_MULTI_COUNT];
+  dbus_int32_t *v_ARRAY_INT32 = values;
+  int i;
+
+  for (i = 0; i < count; ++i)
+    values[i] = int32_from_seed (seed + i);
+
+  return _dbus_type_writer_write_fixed_multi (writer,
+                                              node->klass->typecode,
+                                              &v_ARRAY_INT32, count);
+}
+
+static dbus_bool_t
+int32_read_multi (TestTypeNode   *node,
+                  DBusTypeReader *reader,
+                  int             seed,
+                  int             count)
+{
+  /* also used for uint32 */
+  dbus_int32_t *values;
+  int n_elements;
+  int i;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_fixed_multi (reader,
+                                      &values,
+                                      &n_elements);
+
+  if (n_elements != count)
+    _dbus_warn ("got %d elements expected %d\n", n_elements, count);
+  _dbus_assert (n_elements == count);
+
+  for (i = 0; i < count; i++)
+    _dbus_assert (((int)_dbus_unpack_uint32 (reader->byte_order,
+                                             (const unsigned char*)values + (i * 4))) ==
+                  int32_from_seed (seed + i));
+
+  return TRUE;
+}
+
+#ifdef DBUS_HAVE_INT64
+static dbus_int64_t
+int64_from_seed (int seed)
+{
+  dbus_int32_t v32;
+  dbus_int64_t v;
+
+  v32 = int32_from_seed (seed);
+
+  v = - (dbus_int32_t) ~ v32;
+  v |= (((dbus_int64_t)v32) << 32);
+
+  return v;
+}
+#endif
+
+static dbus_bool_t
+int64_write_value (TestTypeNode   *node,
+                   DataBlock      *block,
+                   DBusTypeWriter *writer,
+                   int             seed)
+{
+#ifdef DBUS_HAVE_INT64
+  /* also used for uint64 */
+  dbus_int64_t v;
+
+  v = int64_from_seed (seed);
+
+  return _dbus_type_writer_write_basic (writer,
+                                        node->klass->typecode,
+                                        &v);
+#else
+  return TRUE;
+#endif
+}
+
+static dbus_bool_t
+int64_read_value (TestTypeNode   *node,
+                  DBusTypeReader *reader,
+                  int             seed)
+{
+#ifdef DBUS_HAVE_INT64
+  /* also used for uint64 */
+  dbus_int64_t v;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_basic (reader,
+                                (dbus_int64_t*) &v);
+
+  _dbus_assert (v == int64_from_seed (seed));
+
+  return TRUE;
+#else
+  return TRUE;
+#endif
+}
+
+static dbus_bool_t
+int64_set_value (TestTypeNode   *node,
+                 DBusTypeReader *reader,
+                 DBusTypeReader *realign_root,
+                 int             seed)
+{
+#ifdef DBUS_HAVE_INT64
+  /* also used for uint64 */
+  dbus_int64_t v;
+
+  v = int64_from_seed (seed);
+
+  return _dbus_type_reader_set_basic (reader,
+                                      &v,
+                                      realign_root);
+#else
+  return TRUE;
+#endif
+}
+
+#define MAX_SAMPLE_STRING_LEN 10
+static void
+string_from_seed (char *buf,
+                  int   len,
+                  int   seed)
+{
+  int i;
+  unsigned char v;
+
+  _dbus_assert (len < MAX_SAMPLE_STRING_LEN);
+
+  /* vary the length slightly, though we also have multiple string
+   * value types for this, varying it here tests the set_value code
+   */
+  switch (seed % 3)
+    {
+    case 1:
+      len += 2;
+      break;
+    case 2:
+      len -= 2;
+      break;
+    }
+  if (len < 0)
+    len = 0;
+
+  v = (unsigned char) ('A' + seed);
+
+  i = 0;
+  while (i < len)
+    {
+      if (v < 'A' || v > 'z')
+        v = 'A';
+
+      buf[i] = v;
+
+      v += 1;
+      ++i;
+    }
+
+  buf[i] = '\0';
+}
+
+static dbus_bool_t
+string_write_value (TestTypeNode   *node,
+                    DataBlock      *block,
+                    DBusTypeWriter *writer,
+                    int             seed)
+{
+  char buf[MAX_SAMPLE_STRING_LEN + 1]="";
+  const char *v_string = buf;
+
+
+  string_from_seed (buf, node->klass->subclass_detail,
+                    seed);
+
+  return _dbus_type_writer_write_basic (writer,
+                                        node->klass->typecode,
+                                        &v_string);
+}
+
+static dbus_bool_t
+string_read_value (TestTypeNode   *node,
+                   DBusTypeReader *reader,
+                   int             seed)
+{
+  const char *v;
+  char buf[MAX_SAMPLE_STRING_LEN + 1];
+  v = buf;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_basic (reader,
+                                (const char **) &v);
+
+  string_from_seed (buf, node->klass->subclass_detail,
+                    seed);
+
+  if (strcmp (buf, v) != 0)
+    {
+      _dbus_warn ("read string '%s' expected '%s'\n",
+                  v, buf);
+      _dbus_assert_not_reached ("test failed");
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+string_set_value (TestTypeNode   *node,
+                  DBusTypeReader *reader,
+                  DBusTypeReader *realign_root,
+                  int             seed)
+{
+  char buf[MAX_SAMPLE_STRING_LEN + 1];
+  const char *v_string = buf;
+
+  string_from_seed (buf, node->klass->subclass_detail,
+                    seed);
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+ {
+   const char *old;
+   _dbus_type_reader_read_basic (reader, &old);
+   _dbus_verbose ("SETTING new string '%s' len %d in place of '%s' len %d\n",
+                  v_string, strlen (v_string), old, strlen (old));
+ }
+#endif
+
+  return _dbus_type_reader_set_basic (reader,
+                                      &v_string,
+                                      realign_root);
+}
+
+#define BOOL_FROM_SEED(seed) ((dbus_bool_t)((seed) % 2))
+
+static dbus_bool_t
+bool_write_value (TestTypeNode   *node,
+                  DataBlock      *block,
+                  DBusTypeWriter *writer,
+                  int             seed)
+{
+  dbus_bool_t v;
+
+  v = BOOL_FROM_SEED (seed);
+
+  return _dbus_type_writer_write_basic (writer,
+                                        node->klass->typecode,
+                                        &v);
+}
+
+static dbus_bool_t
+bool_read_value (TestTypeNode   *node,
+                 DBusTypeReader *reader,
+                 int             seed)
+{
+  dbus_bool_t v;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_basic (reader,
+                                (unsigned char*) &v);
+
+  _dbus_assert (v == BOOL_FROM_SEED (seed));
+
+  return TRUE;
+}
+
+static dbus_bool_t
+bool_set_value (TestTypeNode   *node,
+                DBusTypeReader *reader,
+                DBusTypeReader *realign_root,
+                int             seed)
+{
+  dbus_bool_t v;
+
+  v = BOOL_FROM_SEED (seed);
+
+  return _dbus_type_reader_set_basic (reader,
+                                      &v,
+                                      realign_root);
+}
+
+#define BYTE_FROM_SEED(seed) ((unsigned char) int32_from_seed (seed))
+
+static dbus_bool_t
+byte_write_value (TestTypeNode   *node,
+                  DataBlock      *block,
+                  DBusTypeWriter *writer,
+                  int             seed)
+{
+  unsigned char v;
+
+  v = BYTE_FROM_SEED (seed);
+
+  return _dbus_type_writer_write_basic (writer,
+                                        node->klass->typecode,
+                                        &v);
+}
+
+static dbus_bool_t
+byte_read_value (TestTypeNode   *node,
+                 DBusTypeReader *reader,
+                 int             seed)
+{
+  unsigned char v;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_basic (reader,
+                                (unsigned char*) &v);
+
+  _dbus_assert (v == BYTE_FROM_SEED (seed));
+
+  return TRUE;
+}
+
+
+static dbus_bool_t
+byte_set_value (TestTypeNode   *node,
+                DBusTypeReader *reader,
+                DBusTypeReader *realign_root,
+                int             seed)
+{
+  unsigned char v;
+
+  v = BYTE_FROM_SEED (seed);
+
+  return _dbus_type_reader_set_basic (reader,
+                                      &v,
+                                      realign_root);
+}
+
+static double
+double_from_seed (int seed)
+{
+  return SAMPLE_INT32 * (double) seed + 0.3;
+}
+
+static dbus_bool_t
+double_write_value (TestTypeNode   *node,
+                    DataBlock      *block,
+                    DBusTypeWriter *writer,
+                    int             seed)
+{
+  double v;
+
+  v = double_from_seed (seed);
+
+  return _dbus_type_writer_write_basic (writer,
+                                        node->klass->typecode,
+                                        &v);
+}
+
+static dbus_bool_t
+double_read_value (TestTypeNode   *node,
+                   DBusTypeReader *reader,
+                   int             seed)
+{
+  double v;
+  double expected;
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_basic (reader,
+                                (double*) &v);
+
+  expected = double_from_seed (seed);
+
+  if (!_DBUS_DOUBLES_BITWISE_EQUAL (v, expected))
+    {
+#ifdef DBUS_INT64_PRINTF_MODIFIER
+      _dbus_warn ("Expected double %g got %g\n bits = 0x%" DBUS_INT64_PRINTF_MODIFIER "x vs.\n bits = 0x%" DBUS_INT64_PRINTF_MODIFIER "x)\n",
+                  expected, v,
+                  *(dbus_uint64_t*)(char*)&expected,
+                  *(dbus_uint64_t*)(char*)&v);
+#endif
+      _dbus_assert_not_reached ("test failed");
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+double_set_value (TestTypeNode   *node,
+                DBusTypeReader *reader,
+                DBusTypeReader *realign_root,
+                int             seed)
+{
+  double v;
+
+  v = double_from_seed (seed);
+
+  return _dbus_type_reader_set_basic (reader,
+                                      &v,
+                                      realign_root);
+}
+
+#define MAX_SAMPLE_OBJECT_PATH_LEN 10
+static void
+object_path_from_seed (char *buf,
+                       int   seed)
+{
+  int i;
+  unsigned char v;
+  int len;
+
+  len = seed % 9;
+  _dbus_assert (len < MAX_SAMPLE_OBJECT_PATH_LEN);
+
+  v = (unsigned char) ('A' + seed);
+
+  if (len < 2)
+    {
+      buf[0] = '/';
+      i = 1;
+    }
+  else
+    {
+      i = 0;
+      while (i + 1 < len)
+        {
+          if (v < 'A' || v > 'z')
+            v = 'A';
+
+          buf[i] = '/';
+          ++i;
+          buf[i] = v;
+          ++i;
+          
+          v += 1;
+        }
+    }
+
+  buf[i] = '\0';
+}
+
+static dbus_bool_t
+object_path_write_value (TestTypeNode   *node,
+                         DataBlock      *block,
+                         DBusTypeWriter *writer,
+                         int             seed)
+{
+  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
+  const char *v_string = buf;
+
+  object_path_from_seed (buf, seed);
+
+  return _dbus_type_writer_write_basic (writer,
+                                        node->klass->typecode,
+                                        &v_string);
+}
+
+static dbus_bool_t
+object_path_read_value (TestTypeNode   *node,
+                        DBusTypeReader *reader,
+                        int             seed)
+{
+  const char *v;
+  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_basic (reader,
+                                (const char **) &v);
+
+  object_path_from_seed (buf, seed);
+
+  if (strcmp (buf, v) != 0)
+    {
+      _dbus_warn ("read object path '%s' expected '%s'\n",
+                  v, buf);
+      _dbus_assert_not_reached ("test failed");
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+object_path_set_value (TestTypeNode   *node,
+                       DBusTypeReader *reader,
+                       DBusTypeReader *realign_root,
+                       int             seed)
+{
+  char buf[MAX_SAMPLE_OBJECT_PATH_LEN + 1];
+  const char *v_string = buf;
+
+  object_path_from_seed (buf, seed);
+
+  return _dbus_type_reader_set_basic (reader,
+                                      &v_string,
+                                      realign_root);
+}
+
+#define MAX_SAMPLE_SIGNATURE_LEN 10
+static void
+signature_from_seed (char *buf,
+                     int   seed)
+{
+  /* try to avoid ascending, descending, or alternating length to help find bugs */
+  const char *sample_signatures[] = {
+    "asax"
+    "",
+    "asau(xxxx)",
+    "x",
+    "ai",
+    "a(ii)"
+  };
+
+  strcpy (buf, sample_signatures[seed % _DBUS_N_ELEMENTS(sample_signatures)]);
+}
+
+static dbus_bool_t
+signature_write_value (TestTypeNode   *node,
+                       DataBlock      *block,
+                       DBusTypeWriter *writer,
+                       int             seed)
+{
+  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
+  const char *v_string = buf;
+
+  signature_from_seed (buf, seed);
+
+  return _dbus_type_writer_write_basic (writer,
+                                        node->klass->typecode,
+                                        &v_string);
+}
+
+static dbus_bool_t
+signature_read_value (TestTypeNode   *node,
+                      DBusTypeReader *reader,
+                      int             seed)
+{
+  const char *v;
+  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
+
+  check_expected_type (reader, node->klass->typecode);
+
+  _dbus_type_reader_read_basic (reader,
+                                (const char **) &v);
+
+  signature_from_seed (buf, seed);
+
+  if (strcmp (buf, v) != 0)
+    {
+      _dbus_warn ("read signature value '%s' expected '%s'\n",
+                  v, buf);
+      _dbus_assert_not_reached ("test failed");
+    }
+
+  return TRUE;
+}
+
+
+static dbus_bool_t
+signature_set_value (TestTypeNode   *node,
+                     DBusTypeReader *reader,
+                     DBusTypeReader *realign_root,
+                     int             seed)
+{
+  char buf[MAX_SAMPLE_SIGNATURE_LEN + 1];
+  const char *v_string = buf;
+
+  signature_from_seed (buf, seed);
+
+  return _dbus_type_reader_set_basic (reader,
+                                      &v_string,
+                                      realign_root);
+}
+
+static dbus_bool_t
+struct_write_value (TestTypeNode   *node,
+                    DataBlock      *block,
+                    DBusTypeWriter *writer,
+                    int             seed)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  DataBlockState saved;
+  DBusTypeWriter sub;
+  int i;
+  int n_copies;
+
+  n_copies = node->klass->subclass_detail;
+
+  _dbus_assert (container->children != NULL);
+
+  data_block_save (block, &saved);
+
+  if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
+                                  NULL, 0,
+                                  &sub))
+    return FALSE;
+
+  i = 0;
+  while (i < n_copies)
+    {
+      DBusList *link;
+
+      link = _dbus_list_get_first_link (&container->children);
+      while (link != NULL)
+        {
+          TestTypeNode *child = link->data;
+          DBusList *next = _dbus_list_get_next_link (&container->children, link);
+
+          if (!node_write_value (child, block, &sub, seed + i))
+            {
+              data_block_restore (block, &saved);
+              return FALSE;
+            }
+
+          link = next;
+        }
+
+      ++i;
+    }
+
+  if (!_dbus_type_writer_unrecurse (writer, &sub))
+    {
+      data_block_restore (block, &saved);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+struct_read_or_set_value (TestTypeNode   *node,
+                          DBusTypeReader *reader,
+                          DBusTypeReader *realign_root,
+                          int             seed)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  DBusTypeReader sub;
+  int i;
+  int n_copies;
+
+  n_copies = node->klass->subclass_detail;
+
+  check_expected_type (reader, DBUS_TYPE_STRUCT);
+
+  _dbus_type_reader_recurse (reader, &sub);
+
+  i = 0;
+  while (i < n_copies)
+    {
+      DBusList *link;
+
+      link = _dbus_list_get_first_link (&container->children);
+      while (link != NULL)
+        {
+          TestTypeNode *child = link->data;
+          DBusList *next = _dbus_list_get_next_link (&container->children, link);
+
+          if (realign_root == NULL)
+            {
+              if (!node_read_value (child, &sub, seed + i))
+                return FALSE;
+            }
+          else
+            {
+              if (!node_set_value (child, &sub, realign_root, seed + i))
+                return FALSE;
+            }
+
+          if (i == (n_copies - 1) && next == NULL)
+            NEXT_EXPECTING_FALSE (&sub);
+          else
+            NEXT_EXPECTING_TRUE (&sub);
+
+          link = next;
+        }
+
+      ++i;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+struct_read_value (TestTypeNode   *node,
+                   DBusTypeReader *reader,
+                   int             seed)
+{
+  return struct_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+struct_set_value (TestTypeNode   *node,
+                  DBusTypeReader *reader,
+                  DBusTypeReader *realign_root,
+                  int             seed)
+{
+  return struct_read_or_set_value (node, reader, realign_root, seed);
+}
+
+static dbus_bool_t
+struct_build_signature (TestTypeNode   *node,
+                        DBusString     *str)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  int i;
+  int orig_len;
+  int n_copies;
+
+  n_copies = node->klass->subclass_detail;
+
+  orig_len = _dbus_string_get_length (str);
+
+  if (!_dbus_string_append_byte (str, DBUS_STRUCT_BEGIN_CHAR))
+    goto oom;
+
+  i = 0;
+  while (i < n_copies)
+    {
+      DBusList *link;
+
+      link = _dbus_list_get_first_link (&container->children);
+      while (link != NULL)
+        {
+          TestTypeNode *child = link->data;
+          DBusList *next = _dbus_list_get_next_link (&container->children, link);
+
+          if (!node_build_signature (child, str))
+            goto oom;
+
+          link = next;
+        }
+
+      ++i;
+    }
+
+  if (!_dbus_string_append_byte (str, DBUS_STRUCT_END_CHAR))
+    goto oom;
+
+  return TRUE;
+
+ oom:
+  _dbus_string_set_length (str, orig_len);
+  return FALSE;
+}
+
+static dbus_bool_t
+array_write_value (TestTypeNode   *node,
+                   DataBlock      *block,
+                   DBusTypeWriter *writer,
+                   int             seed)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  DataBlockState saved;
+  DBusTypeWriter sub;
+  DBusString element_signature;
+  int i;
+  int n_copies;
+  int element_type;
+  TestTypeNode *child;
+
+  n_copies = node->klass->subclass_detail;
+
+  _dbus_assert (container->children != NULL);
+
+  data_block_save (block, &saved);
+
+  if (!_dbus_string_init (&element_signature))
+    return FALSE;
+
+  child = _dbus_list_get_first (&container->children);
+
+  if (!node_build_signature (child,
+                             &element_signature))
+    goto oom;
+
+  element_type = _dbus_first_type_in_signature (&element_signature, 0);
+
+  if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
+                                  &element_signature, 0,
+                                  &sub))
+    goto oom;
+
+  if (arrays_write_fixed_in_blocks &&
+      dbus_type_is_fixed (element_type) &&
+      child->klass->write_multi)
+    {
+      if (!node_write_multi (child, block, &sub, seed, n_copies))
+        goto oom;
+    }
+  else
+    {
+      i = 0;
+      while (i < n_copies)
+        {
+          DBusList *link;
+
+          link = _dbus_list_get_first_link (&container->children);
+          while (link != NULL)
+            {
+              TestTypeNode *child = link->data;
+              DBusList *next = _dbus_list_get_next_link (&container->children, link);
+
+              if (!node_write_value (child, block, &sub, seed + i))
+                goto oom;
+
+              link = next;
+            }
+
+          ++i;
+        }
+    }
+
+  if (!_dbus_type_writer_unrecurse (writer, &sub))
+    goto oom;
+
+  _dbus_string_free (&element_signature);
+  return TRUE;
+
+ oom:
+  data_block_restore (block, &saved);
+  _dbus_string_free (&element_signature);
+  return FALSE;
+}
+
+static dbus_bool_t
+array_read_or_set_value (TestTypeNode   *node,
+                         DBusTypeReader *reader,
+                         DBusTypeReader *realign_root,
+                         int             seed)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  DBusTypeReader sub;
+  int i;
+  int n_copies;
+  TestTypeNode *child;
+
+  n_copies = node->klass->subclass_detail;
+
+  check_expected_type (reader, DBUS_TYPE_ARRAY);
+
+  child = _dbus_list_get_first (&container->children);
+
+  if (n_copies > 0)
+    {
+      _dbus_type_reader_recurse (reader, &sub);
+
+      if (realign_root == NULL && arrays_write_fixed_in_blocks &&
+          dbus_type_is_fixed (_dbus_type_reader_get_element_type (reader)) &&
+          child->klass->read_multi)
+        {
+          if (!node_read_multi (child, &sub, seed, n_copies))
+            return FALSE;
+        }
+      else
+        {
+          i = 0;
+          while (i < n_copies)
+            {
+              DBusList *link;
+
+              link = _dbus_list_get_first_link (&container->children);
+              while (link != NULL)
+                {
+                  TestTypeNode *child = link->data;
+                  DBusList *next = _dbus_list_get_next_link (&container->children, link);
+
+                  _dbus_assert (child->klass->typecode ==
+                                _dbus_type_reader_get_element_type (reader));
+
+                  if (realign_root == NULL)
+                    {
+                      if (!node_read_value (child, &sub, seed + i))
+                        return FALSE;
+                    }
+                  else
+                    {
+                      if (!node_set_value (child, &sub, realign_root, seed + i))
+                        return FALSE;
+                    }
+
+                  if (i == (n_copies - 1) && next == NULL)
+                    NEXT_EXPECTING_FALSE (&sub);
+                  else
+                    NEXT_EXPECTING_TRUE (&sub);
+
+                  link = next;
+                }
+
+              ++i;
+            }
+        }
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+array_read_value (TestTypeNode   *node,
+                  DBusTypeReader *reader,
+                  int             seed)
+{
+  return array_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+array_set_value (TestTypeNode   *node,
+                 DBusTypeReader *reader,
+                 DBusTypeReader *realign_root,
+                 int             seed)
+{
+  return array_read_or_set_value (node, reader, realign_root, seed);
+}
+
+static dbus_bool_t
+array_build_signature (TestTypeNode   *node,
+                       DBusString     *str)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  int orig_len;
+
+  orig_len = _dbus_string_get_length (str);
+
+  if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
+    goto oom;
+
+  if (!node_build_signature (_dbus_list_get_first (&container->children),
+                             str))
+    goto oom;
+
+  return TRUE;
+
+ oom:
+  _dbus_string_set_length (str, orig_len);
+  return FALSE;
+}
+
+ /* 10 is random just to add another seed that we use in the suite */
+#define VARIANT_SEED 10
+
+static dbus_bool_t
+variant_write_value (TestTypeNode   *node,
+                     DataBlock      *block,
+                     DBusTypeWriter *writer,
+                     int             seed)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  DataBlockState saved;
+  DBusTypeWriter sub;
+  DBusString content_signature;
+  TestTypeNode *child;
+
+  _dbus_assert (container->children != NULL);
+  _dbus_assert (_dbus_list_length_is_one (&container->children));
+
+  child = _dbus_list_get_first (&container->children);
+
+  data_block_save (block, &saved);
+
+  if (!_dbus_string_init (&content_signature))
+    return FALSE;
+
+  if (!node_build_signature (child,
+                             &content_signature))
+    goto oom;
+
+  if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_VARIANT,
+                                  &content_signature, 0,
+                                  &sub))
+    goto oom;
+
+  if (!node_write_value (child, block, &sub, seed + VARIANT_SEED))
+    goto oom;
+
+  if (!_dbus_type_writer_unrecurse (writer, &sub))
+    goto oom;
+
+  _dbus_string_free (&content_signature);
+  return TRUE;
+
+ oom:
+  data_block_restore (block, &saved);
+  _dbus_string_free (&content_signature);
+  return FALSE;
+}
+
+static dbus_bool_t
+variant_read_or_set_value (TestTypeNode   *node,
+                           DBusTypeReader *reader,
+                           DBusTypeReader *realign_root,
+                           int             seed)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  DBusTypeReader sub;
+  TestTypeNode *child;
+
+  _dbus_assert (container->children != NULL);
+  _dbus_assert (_dbus_list_length_is_one (&container->children));
+
+  child = _dbus_list_get_first (&container->children);
+
+  check_expected_type (reader, DBUS_TYPE_VARIANT);
+
+  _dbus_type_reader_recurse (reader, &sub);
+
+  if (realign_root == NULL)
+    {
+      if (!node_read_value (child, &sub, seed + VARIANT_SEED))
+        return FALSE;
+    }
+  else
+    {
+      if (!node_set_value (child, &sub, realign_root, seed + VARIANT_SEED))
+        return FALSE;
+    }
+
+  NEXT_EXPECTING_FALSE (&sub);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+variant_read_value (TestTypeNode   *node,
+                    DBusTypeReader *reader,
+                    int             seed)
+{
+  return variant_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+variant_set_value (TestTypeNode   *node,
+                   DBusTypeReader *reader,
+                   DBusTypeReader *realign_root,
+                   int             seed)
+{
+  return variant_read_or_set_value (node, reader, realign_root, seed);
+}
+
+static dbus_bool_t
+dict_write_value (TestTypeNode   *node,
+                  DataBlock      *block,
+                  DBusTypeWriter *writer,
+                  int             seed)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  DataBlockState saved;
+  DBusTypeWriter sub;
+  DBusString entry_value_signature;
+  DBusString dict_entry_signature;
+  int i;
+  int n_entries;
+  TestTypeNode *child;
+
+  n_entries = node->klass->subclass_detail;
+
+  _dbus_assert (container->children != NULL);
+
+  data_block_save (block, &saved);
+
+  if (!_dbus_string_init (&entry_value_signature))
+    return FALSE;
+
+  if (!_dbus_string_init (&dict_entry_signature))
+    {
+      _dbus_string_free (&entry_value_signature);
+      return FALSE;
+    }
+  
+  child = _dbus_list_get_first (&container->children);
+
+  if (!node_build_signature (child,
+                             &entry_value_signature))
+    goto oom;
+
+  if (!_dbus_string_append (&dict_entry_signature,
+                            DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                            DBUS_TYPE_INT32_AS_STRING))
+    goto oom;
+
+  if (!_dbus_string_copy (&entry_value_signature, 0,
+                          &dict_entry_signature,
+                          _dbus_string_get_length (&dict_entry_signature)))
+    goto oom;
+
+  if (!_dbus_string_append_byte (&dict_entry_signature,
+                                 DBUS_DICT_ENTRY_END_CHAR))
+    goto oom;
+
+  if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
+                                  &dict_entry_signature, 0,
+                                  &sub))
+    goto oom;
+
+  i = 0;
+  while (i < n_entries)
+    {
+      DBusTypeWriter entry_sub;
+      dbus_int32_t key;
+
+      if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_DICT_ENTRY,
+                                      NULL, 0,
+                                      &entry_sub))
+        goto oom;
+
+      key = int32_from_seed (seed + i);
+
+      if (!_dbus_type_writer_write_basic (&entry_sub,
+                                          DBUS_TYPE_INT32,
+                                          &key))
+        goto oom;
+      
+      if (!node_write_value (child, block, &entry_sub, seed + i))
+        goto oom;
+
+      if (!_dbus_type_writer_unrecurse (&sub, &entry_sub))
+        goto oom;
+      
+      ++i;
+    }
+
+  if (!_dbus_type_writer_unrecurse (writer, &sub))
+    goto oom;
+  
+  _dbus_string_free (&entry_value_signature);
+  _dbus_string_free (&dict_entry_signature);
+  return TRUE;
+
+ oom:
+  data_block_restore (block, &saved);
+  _dbus_string_free (&entry_value_signature);
+  _dbus_string_free (&dict_entry_signature);
+  return FALSE;
+}
+
+static dbus_bool_t
+dict_read_or_set_value (TestTypeNode   *node,
+                        DBusTypeReader *reader,
+                        DBusTypeReader *realign_root,
+                        int             seed)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  DBusTypeReader sub;
+  int i;
+  int n_entries;
+  TestTypeNode *child;
+
+  n_entries = node->klass->subclass_detail;
+
+  check_expected_type (reader, DBUS_TYPE_ARRAY);
+
+  child = _dbus_list_get_first (&container->children);
+
+  if (n_entries > 0)
+    {
+      _dbus_type_reader_recurse (reader, &sub);
+
+      check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
+      
+      i = 0;
+      while (i < n_entries)
+        {
+          DBusTypeReader entry_sub;
+
+          check_expected_type (&sub, DBUS_TYPE_DICT_ENTRY);
+          
+          _dbus_type_reader_recurse (&sub, &entry_sub);
+          
+          if (realign_root == NULL)
+            {
+              dbus_int32_t v;
+              
+              check_expected_type (&entry_sub, DBUS_TYPE_INT32);
+
+              _dbus_type_reader_read_basic (&entry_sub,
+                                            (dbus_int32_t*) &v);
+
+              _dbus_assert (v == int32_from_seed (seed + i));
+
+              NEXT_EXPECTING_TRUE (&entry_sub);
+              
+              if (!node_read_value (child, &entry_sub, seed + i))
+                return FALSE;
+
+              NEXT_EXPECTING_FALSE (&entry_sub);
+            }
+          else
+            {
+              dbus_int32_t v;
+              
+              v = int32_from_seed (seed + i);
+              
+              if (!_dbus_type_reader_set_basic (&entry_sub,
+                                                &v,
+                                                realign_root))
+                return FALSE;
+
+              NEXT_EXPECTING_TRUE (&entry_sub);
+              
+              if (!node_set_value (child, &entry_sub, realign_root, seed + i))
+                return FALSE;
+
+              NEXT_EXPECTING_FALSE (&entry_sub);
+            }
+          
+          if (i == (n_entries - 1))
+            NEXT_EXPECTING_FALSE (&sub);
+          else
+            NEXT_EXPECTING_TRUE (&sub);
+
+          ++i;
+        }
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+dict_read_value (TestTypeNode   *node,
+                 DBusTypeReader *reader,
+                 int             seed)
+{
+  return dict_read_or_set_value (node, reader, NULL, seed);
+}
+
+static dbus_bool_t
+dict_set_value (TestTypeNode   *node,
+                DBusTypeReader *reader,
+                DBusTypeReader *realign_root,
+                int             seed)
+{
+  return dict_read_or_set_value (node, reader, realign_root, seed);
+}
+
+static dbus_bool_t
+dict_build_signature (TestTypeNode   *node,
+                      DBusString     *str)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  int orig_len;
+
+  orig_len = _dbus_string_get_length (str);
+
+  if (!_dbus_string_append_byte (str, DBUS_TYPE_ARRAY))
+    goto oom;
+
+  if (!_dbus_string_append (str, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING))
+    goto oom;
+  
+  if (!node_build_signature (_dbus_list_get_first (&container->children),
+                             str))
+    goto oom;
+
+  if (!_dbus_string_append_byte (str, DBUS_DICT_ENTRY_END_CHAR))
+    goto oom;
+
+  return TRUE;
+
+ oom:
+  _dbus_string_set_length (str, orig_len);
+  return FALSE;
+}
+
+static void
+container_destroy (TestTypeNode *node)
+{
+  TestTypeNodeContainer *container = (TestTypeNodeContainer*) node;
+  DBusList *link;
+
+  link = _dbus_list_get_first_link (&container->children);
+  while (link != NULL)
+    {
+      TestTypeNode *child = link->data;
+      DBusList *next = _dbus_list_get_next_link (&container->children, link);
+
+      node_destroy (child);
+
+      _dbus_list_free_link (link);
+
+      link = next;
+    }
+}
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-marshal-recursive.c b/dbus/dbus/dbus-marshal-recursive.c
new file mode 100644
index 0000000..4adfd2e
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-recursive.c
@@ -0,0 +1,2752 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-recursive.c  Marshalling routines for recursive types
+ *
+ * Copyright (C) 2004, 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-marshal-recursive.h"
+#include "dbus-marshal-basic.h"
+#include "dbus-signature.h"
+#include "dbus-internals.h"
+
+/**
+ * @addtogroup DBusMarshal
+ * @{
+ */
+
+static dbus_bool_t _dbus_type_reader_greater_than              (const DBusTypeReader  *lhs,
+                                                                const DBusTypeReader  *rhs);
+
+static void       _dbus_type_writer_set_enabled           (DBusTypeWriter        *writer,
+                                                           dbus_bool_t            enabled);
+static dbus_bool_t _dbus_type_writer_write_reader_partial (DBusTypeWriter        *writer,
+                                                           DBusTypeReader        *reader,
+                                                           const DBusTypeReader  *start_after,
+                                                           int                    start_after_new_pos,
+                                                           int                    start_after_new_len,
+                                                           DBusList             **fixups);
+
+/** turn this on to get deluged in TypeReader verbose spam */
+#define RECURSIVE_MARSHAL_READ_TRACE  0
+
+/** turn this on to get deluged in TypeWriter verbose spam */
+#define RECURSIVE_MARSHAL_WRITE_TRACE 0
+
+static void
+free_fixups (DBusList **fixups)
+{
+  DBusList *link;
+
+  link = _dbus_list_get_first_link (fixups);
+  while (link != NULL)
+    {
+      DBusList *next;
+
+      next = _dbus_list_get_next_link (fixups, link);
+
+      dbus_free (link->data);
+      _dbus_list_free_link (link);
+
+      link = next;
+    }
+
+  *fixups = NULL;
+}
+
+static void
+apply_and_free_fixups (DBusList      **fixups,
+                       DBusTypeReader *reader)
+{
+  DBusList *link;
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  if (*fixups)
+    _dbus_verbose (" %d FIXUPS to apply\n",
+                   _dbus_list_get_length (fixups));
+#endif
+
+  link = _dbus_list_get_first_link (fixups);
+  while (link != NULL)
+    {
+      DBusList *next;
+
+      next = _dbus_list_get_next_link (fixups, link);
+
+      if (reader)
+        {
+          DBusArrayLenFixup *f;
+
+          f = link->data;
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+          _dbus_verbose (" applying FIXUP to reader %p at pos %d new_len = %d old len %d\n",
+                         reader, f->len_pos_in_reader, f->new_len,
+                         _dbus_marshal_read_uint32 (reader->value_str,
+                                                    f->len_pos_in_reader,
+                                                    reader->byte_order, NULL));
+#endif
+
+          _dbus_marshal_set_uint32 ((DBusString*) reader->value_str,
+                                    f->len_pos_in_reader,
+                                    f->new_len,
+                                    reader->byte_order);
+        }
+
+      dbus_free (link->data);
+      _dbus_list_free_link (link);
+
+      link = next;
+    }
+
+  *fixups = NULL;
+}
+
+/**
+ * Virtual table for a type reader.
+ */
+struct DBusTypeReaderClass
+{
+  const char *name;       /**< name for debugging */
+  int         id;         /**< index in all_reader_classes */
+  dbus_bool_t types_only; /**< only iterates over types, not values */
+  void        (* recurse)          (DBusTypeReader        *sub,
+                                    DBusTypeReader        *parent); /**< recurse with this reader as sub */
+  dbus_bool_t (* check_finished)   (const DBusTypeReader  *reader); /**< check whether reader is at the end */
+  void        (* next)             (DBusTypeReader        *reader,
+                                    int                    current_type); /**< go to the next value */
+};
+
+static int
+element_type_get_alignment (const DBusString *str,
+                            int               pos)
+{
+  return _dbus_type_get_alignment (_dbus_first_type_in_signature (str, pos));
+}
+
+static void
+reader_init (DBusTypeReader    *reader,
+             int                byte_order,
+             const DBusString  *type_str,
+             int                type_pos,
+             const DBusString  *value_str,
+             int                value_pos)
+{
+  reader->byte_order = byte_order;
+  reader->finished = FALSE;
+  reader->type_str = type_str;
+  reader->type_pos = type_pos;
+  reader->value_str = value_str;
+  reader->value_pos = value_pos;
+}
+
+static void
+base_reader_recurse (DBusTypeReader *sub,
+                     DBusTypeReader *parent)
+{
+  /* point subreader at the same place as parent */
+  reader_init (sub,
+               parent->byte_order,
+               parent->type_str,
+               parent->type_pos,
+               parent->value_str,
+               parent->value_pos);
+}
+
+static void
+struct_or_dict_entry_types_only_reader_recurse (DBusTypeReader *sub,
+                                                DBusTypeReader *parent)
+{
+  base_reader_recurse (sub, parent);
+  
+  _dbus_assert (_dbus_string_get_byte (sub->type_str,
+                                       sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR ||
+                _dbus_string_get_byte (sub->type_str,
+                                       sub->type_pos) == DBUS_DICT_ENTRY_BEGIN_CHAR);
+
+  sub->type_pos += 1;
+}
+
+static void
+struct_or_dict_entry_reader_recurse (DBusTypeReader *sub,
+                                     DBusTypeReader *parent)
+{
+  struct_or_dict_entry_types_only_reader_recurse (sub, parent);
+
+  /* struct and dict entry have 8 byte alignment */
+  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
+}
+
+static void
+array_types_only_reader_recurse (DBusTypeReader *sub,
+                                 DBusTypeReader *parent)
+{
+  base_reader_recurse (sub, parent);
+
+  /* point type_pos at the array element type */
+  sub->type_pos += 1;
+
+  /* Init with values likely to crash things if misused */
+  sub->u.array.start_pos = _DBUS_INT_MAX;
+  sub->array_len_offset = 7;
+}
+
+/** compute position of array length given array_len_offset, which is
+    the offset back from start_pos to end of the len */
+#define ARRAY_READER_LEN_POS(reader) \
+  ((reader)->u.array.start_pos - ((int)(reader)->array_len_offset) - 4)
+
+static int
+array_reader_get_array_len (const DBusTypeReader *reader)
+{
+  dbus_uint32_t array_len;
+  int len_pos;
+
+  len_pos = ARRAY_READER_LEN_POS (reader);
+
+  _dbus_assert (_DBUS_ALIGN_VALUE (len_pos, 4) == (unsigned) len_pos);
+  array_len = _dbus_unpack_uint32 (reader->byte_order,
+                                   _dbus_string_get_const_data_len (reader->value_str, len_pos, 4));
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("   reader %p len_pos %d array len %u len_offset %d\n",
+                 reader, len_pos, array_len, reader->array_len_offset);
+#endif
+
+  _dbus_assert (reader->u.array.start_pos - len_pos - 4 < 8);
+
+  return array_len;
+}
+
+static void
+array_reader_recurse (DBusTypeReader *sub,
+                      DBusTypeReader *parent)
+{
+  int alignment;
+  int len_pos;
+
+  array_types_only_reader_recurse (sub, parent);
+
+  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
+
+  len_pos = sub->value_pos;
+
+  sub->value_pos += 4; /* for the length */
+
+  alignment = element_type_get_alignment (sub->type_str,
+                                          sub->type_pos);
+
+  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
+
+  sub->u.array.start_pos = sub->value_pos;
+  _dbus_assert ((sub->u.array.start_pos - (len_pos + 4)) < 8); /* only 3 bits in array_len_offset */
+  sub->array_len_offset = sub->u.array.start_pos - (len_pos + 4);
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("    type reader %p array start = %d len_offset = %d array len = %d array element type = %s\n",
+                 sub,
+                 sub->u.array.start_pos,
+                 sub->array_len_offset,
+                 array_reader_get_array_len (sub),
+                 _dbus_type_to_string (_dbus_first_type_in_signature (sub->type_str,
+                                                                sub->type_pos)));
+#endif
+}
+
+static void
+variant_reader_recurse (DBusTypeReader *sub,
+                        DBusTypeReader *parent)
+{
+  int sig_len;
+  int contained_alignment;
+
+  base_reader_recurse (sub, parent);
+
+  /* Variant is 1 byte sig length (without nul), signature with nul,
+   * padding to 8-boundary, then values
+   */
+
+  sig_len = _dbus_string_get_byte (sub->value_str, sub->value_pos);
+
+  sub->type_str = sub->value_str;
+  sub->type_pos = sub->value_pos + 1;
+
+  sub->value_pos = sub->type_pos + sig_len + 1;
+
+  contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (sub->type_str,
+                                                                           sub->type_pos));
+  
+  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("    type reader %p variant containing '%s'\n",
+                 sub,
+                 _dbus_string_get_const_data_len (sub->type_str,
+                                                  sub->type_pos, 0));
+#endif
+}
+
+static dbus_bool_t
+array_reader_check_finished (const DBusTypeReader *reader)
+{
+  int end_pos;
+
+  /* return the array element type if elements remain, and
+   * TYPE_INVALID otherwise
+   */
+
+  end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
+
+  _dbus_assert (reader->value_pos <= end_pos);
+  _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
+
+  return reader->value_pos == end_pos;
+}
+
+static void
+skip_one_complete_type (const DBusString *type_str,
+                        int              *type_pos)
+{
+  _dbus_type_signature_next (_dbus_string_get_const_data (type_str),
+			     type_pos);
+}
+
+/**
+ * Skips to the next "complete" type inside a type signature.
+ * The signature is read starting at type_pos, and the next
+ * type position is stored in the same variable.
+ *
+ * @param type_str a type signature (must be valid)
+ * @param type_pos an integer position in the type signature (in and out)
+ */
+void
+_dbus_type_signature_next (const char       *type_str,
+			   int              *type_pos)
+{
+  const unsigned char *p;
+  const unsigned char *start;
+
+  _dbus_assert (type_str != NULL);
+  _dbus_assert (type_pos != NULL);
+  
+  start = type_str;
+  p = start + *type_pos;
+
+  _dbus_assert (*p != DBUS_STRUCT_END_CHAR);
+  _dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR);
+  
+  while (*p == DBUS_TYPE_ARRAY)
+    ++p;
+
+  _dbus_assert (*p != DBUS_STRUCT_END_CHAR);
+  _dbus_assert (*p != DBUS_DICT_ENTRY_END_CHAR);
+  
+  if (*p == DBUS_STRUCT_BEGIN_CHAR)
+    {
+      int depth;
+
+      depth = 1;
+
+      while (TRUE)
+        {
+          _dbus_assert (*p != DBUS_TYPE_INVALID);
+
+          ++p;
+
+          _dbus_assert (*p != DBUS_TYPE_INVALID);
+
+          if (*p == DBUS_STRUCT_BEGIN_CHAR)
+            depth += 1;
+          else if (*p == DBUS_STRUCT_END_CHAR)
+            {
+              depth -= 1;
+              if (depth == 0)
+                {
+                  ++p;
+                  break;
+                }
+            }
+        }
+    }
+  else if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR)
+    {
+      int depth;
+
+      depth = 1;
+
+      while (TRUE)
+        {
+          _dbus_assert (*p != DBUS_TYPE_INVALID);
+
+          ++p;
+
+          _dbus_assert (*p != DBUS_TYPE_INVALID);
+
+          if (*p == DBUS_DICT_ENTRY_BEGIN_CHAR)
+            depth += 1;
+          else if (*p == DBUS_DICT_ENTRY_END_CHAR)
+            {
+              depth -= 1;
+              if (depth == 0)
+                {
+                  ++p;
+                  break;
+                }
+            }
+        }
+    }
+  else
+    {
+      ++p;
+    }
+
+  *type_pos = (int) (p - start);
+}
+
+static int
+find_len_of_complete_type (const DBusString *type_str,
+                           int               type_pos)
+{
+  int end;
+
+  end = type_pos;
+
+  skip_one_complete_type (type_str, &end);
+
+  return end - type_pos;
+}
+
+static void
+base_reader_next (DBusTypeReader *reader,
+                  int             current_type)
+{
+  switch (current_type)
+    {
+    case DBUS_TYPE_DICT_ENTRY:
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_VARIANT:
+      /* Scan forward over the entire container contents */
+      {
+        DBusTypeReader sub;
+
+        if (reader->klass->types_only && current_type == DBUS_TYPE_VARIANT)
+          ;
+        else
+          {
+            /* Recurse into the struct or variant */
+            _dbus_type_reader_recurse (reader, &sub);
+
+            /* Skip everything in this subreader */
+            while (_dbus_type_reader_next (&sub))
+              {
+                /* nothing */;
+              }
+          }
+        if (!reader->klass->types_only)
+          reader->value_pos = sub.value_pos;
+
+        /* Now we are at the end of this container; for variants, the
+         * subreader's type_pos is totally inapplicable (it's in the
+         * value string) but we know that we increment by one past the
+         * DBUS_TYPE_VARIANT
+         */
+        if (current_type == DBUS_TYPE_VARIANT)
+          reader->type_pos += 1;
+        else
+          reader->type_pos = sub.type_pos;
+      }
+      break;
+
+    case DBUS_TYPE_ARRAY:
+      {
+        if (!reader->klass->types_only)
+          _dbus_marshal_skip_array (reader->value_str,
+                                    _dbus_first_type_in_signature (reader->type_str,
+                                                                   reader->type_pos + 1),
+                                    reader->byte_order,
+                                    &reader->value_pos);
+
+        skip_one_complete_type (reader->type_str, &reader->type_pos);
+      }
+      break;
+
+    default:
+      if (!reader->klass->types_only)
+        _dbus_marshal_skip_basic (reader->value_str,
+                                  current_type, reader->byte_order,
+                                  &reader->value_pos);
+
+      reader->type_pos += 1;
+      break;
+    }
+}
+
+static void
+struct_reader_next (DBusTypeReader *reader,
+                    int             current_type)
+{
+  int t;
+
+  base_reader_next (reader, current_type);
+
+  /* for STRUCT containers we return FALSE at the end of the struct,
+   * for INVALID we return FALSE at the end of the signature.
+   * In both cases we arrange for get_current_type() to return INVALID
+   * which is defined to happen iff we're at the end (no more next())
+   */
+  t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
+  if (t == DBUS_STRUCT_END_CHAR)
+    {
+      reader->type_pos += 1;
+      reader->finished = TRUE;
+    }
+}
+
+static void
+dict_entry_reader_next (DBusTypeReader *reader,
+                        int             current_type)
+{
+  int t;
+
+  base_reader_next (reader, current_type);
+
+  /* for STRUCT containers we return FALSE at the end of the struct,
+   * for INVALID we return FALSE at the end of the signature.
+   * In both cases we arrange for get_current_type() to return INVALID
+   * which is defined to happen iff we're at the end (no more next())
+   */
+  t = _dbus_string_get_byte (reader->type_str, reader->type_pos);
+  if (t == DBUS_DICT_ENTRY_END_CHAR)
+    {
+      reader->type_pos += 1;
+      reader->finished = TRUE;
+    }
+}
+
+static void
+array_types_only_reader_next (DBusTypeReader *reader,
+                              int             current_type)
+{
+  /* We have one "element" to be iterated over
+   * in each array, which is its element type.
+   * So the finished flag indicates whether we've
+   * iterated over it yet or not.
+   */
+  reader->finished = TRUE;
+}
+
+static void
+array_reader_next (DBusTypeReader *reader,
+                   int             current_type)
+{
+  /* Skip one array element */
+  int end_pos;
+
+  end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("  reader %p array next START start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
+                 reader,
+                 reader->u.array.start_pos,
+                 end_pos, reader->value_pos,
+                 _dbus_type_to_string (current_type));
+#endif
+
+  _dbus_assert (reader->value_pos < end_pos);
+  _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
+
+  switch (_dbus_first_type_in_signature (reader->type_str,
+                                         reader->type_pos))
+    {
+    case DBUS_TYPE_DICT_ENTRY:
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_VARIANT:
+      {
+        DBusTypeReader sub;
+
+        /* Recurse into the struct or variant */
+        _dbus_type_reader_recurse (reader, &sub);
+
+        /* Skip everything in this element */
+        while (_dbus_type_reader_next (&sub))
+          {
+            /* nothing */;
+          }
+
+        /* Now we are at the end of this element */
+        reader->value_pos = sub.value_pos;
+      }
+      break;
+
+    case DBUS_TYPE_ARRAY:
+      {
+        _dbus_marshal_skip_array (reader->value_str,
+                                  _dbus_first_type_in_signature (reader->type_str,
+                                                           reader->type_pos + 1),
+                                  reader->byte_order,
+                                  &reader->value_pos);
+      }
+      break;
+
+    default:
+      {
+        _dbus_marshal_skip_basic (reader->value_str,
+                                  current_type, reader->byte_order,
+                                  &reader->value_pos);
+      }
+      break;
+    }
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("  reader %p array next END start_pos = %d end_pos = %d value_pos = %d current_type = %s\n",
+                 reader,
+                 reader->u.array.start_pos,
+                 end_pos, reader->value_pos,
+                 _dbus_type_to_string (current_type));
+#endif
+
+  _dbus_assert (reader->value_pos <= end_pos);
+
+  if (reader->value_pos == end_pos)
+    {
+      skip_one_complete_type (reader->type_str,
+                              &reader->type_pos);
+    }
+}
+
+static const DBusTypeReaderClass body_reader_class = {
+  "body", 0,
+  FALSE,
+  NULL, /* body is always toplevel, so doesn't get recursed into */
+  NULL,
+  base_reader_next
+};
+
+static const DBusTypeReaderClass body_types_only_reader_class = {
+  "body types", 1,
+  TRUE,
+  NULL, /* body is always toplevel, so doesn't get recursed into */
+  NULL,
+  base_reader_next
+};
+
+static const DBusTypeReaderClass struct_reader_class = {
+  "struct", 2,
+  FALSE,
+  struct_or_dict_entry_reader_recurse,
+  NULL,
+  struct_reader_next
+};
+
+static const DBusTypeReaderClass struct_types_only_reader_class = {
+  "struct types", 3,
+  TRUE,
+  struct_or_dict_entry_types_only_reader_recurse,
+  NULL,
+  struct_reader_next
+};
+
+static const DBusTypeReaderClass dict_entry_reader_class = {
+  "dict_entry", 4,
+  FALSE,
+  struct_or_dict_entry_reader_recurse,
+  NULL,
+  dict_entry_reader_next
+};
+
+static const DBusTypeReaderClass dict_entry_types_only_reader_class = {
+  "dict_entry types", 5,
+  TRUE,
+  struct_or_dict_entry_types_only_reader_recurse,
+  NULL,
+  dict_entry_reader_next
+};
+
+static const DBusTypeReaderClass array_reader_class = {
+  "array", 6,
+  FALSE,
+  array_reader_recurse,
+  array_reader_check_finished,
+  array_reader_next
+};
+
+static const DBusTypeReaderClass array_types_only_reader_class = {
+  "array types", 7,
+  TRUE,
+  array_types_only_reader_recurse,
+  NULL,
+  array_types_only_reader_next
+};
+
+static const DBusTypeReaderClass variant_reader_class = {
+  "variant", 8,
+  FALSE,
+  variant_reader_recurse,
+  NULL,
+  base_reader_next
+};
+
+#ifndef DBUS_DISABLE_ASSERT
+static const DBusTypeReaderClass * const
+all_reader_classes[] = {
+  &body_reader_class,
+  &body_types_only_reader_class,
+  &struct_reader_class,
+  &struct_types_only_reader_class,
+  &dict_entry_reader_class,
+  &dict_entry_types_only_reader_class,
+  &array_reader_class,
+  &array_types_only_reader_class,
+  &variant_reader_class
+};
+#endif
+
+/**
+ * Initializes a type reader.
+ *
+ * @param reader the reader
+ * @param byte_order the byte order of the block to read
+ * @param type_str the signature of the block to read
+ * @param type_pos location of signature
+ * @param value_str the string containing values block
+ * @param value_pos start of values block
+ */
+void
+_dbus_type_reader_init (DBusTypeReader    *reader,
+                        int                byte_order,
+                        const DBusString  *type_str,
+                        int                type_pos,
+                        const DBusString  *value_str,
+                        int                value_pos)
+{
+  reader->klass = &body_reader_class;
+
+  reader_init (reader, byte_order, type_str, type_pos,
+               value_str, value_pos);
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("  type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
+                 reader, reader->type_pos, reader->value_pos,
+                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
+#endif
+}
+
+/**
+ * Like _dbus_type_reader_init() but the iteration is over the
+ * signature, not over values.
+ *
+ * @param reader the reader
+ * @param type_str the signature string
+ * @param type_pos location in the signature string
+ */
+void
+_dbus_type_reader_init_types_only (DBusTypeReader    *reader,
+                                   const DBusString  *type_str,
+                                   int                type_pos)
+{
+  reader->klass = &body_types_only_reader_class;
+
+  reader_init (reader, DBUS_COMPILER_BYTE_ORDER /* irrelevant */,
+               type_str, type_pos, NULL, _DBUS_INT_MAX /* crashes if we screw up */);
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("  type reader %p init types only type_pos = %d remaining sig '%s'\n",
+                 reader, reader->type_pos,
+                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
+#endif
+}
+
+/**
+ * Gets the type of the value the reader is currently pointing to;
+ * or for a types-only reader gets the type it's currently pointing to.
+ * If the reader is at the end of a block or end of a container such
+ * as an array, returns #DBUS_TYPE_INVALID.
+ *
+ * @param reader the reader
+ */
+int
+_dbus_type_reader_get_current_type (const DBusTypeReader *reader)
+{
+  int t;
+
+  if (reader->finished ||
+      (reader->klass->check_finished &&
+       (* reader->klass->check_finished) (reader)))
+    t = DBUS_TYPE_INVALID;
+  else
+    t = _dbus_first_type_in_signature (reader->type_str,
+                                       reader->type_pos);
+
+  _dbus_assert (t != DBUS_STRUCT_END_CHAR);
+  _dbus_assert (t != DBUS_STRUCT_BEGIN_CHAR);
+  _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
+  _dbus_assert (t != DBUS_DICT_ENTRY_BEGIN_CHAR);
+  
+#if 0
+  _dbus_verbose ("  type reader %p current type_pos = %d type = %s\n",
+                 reader, reader->type_pos,
+                 _dbus_type_to_string (t));
+#endif
+
+  return t;
+}
+
+/**
+ * Gets the type of an element of the array the reader is currently
+ * pointing to. It's an error to call this if
+ * _dbus_type_reader_get_current_type() doesn't return #DBUS_TYPE_ARRAY
+ * for this reader.
+ *
+ * @param reader the reader
+ */
+int
+_dbus_type_reader_get_element_type (const DBusTypeReader  *reader)
+{
+  int element_type;
+
+  _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY);
+
+  element_type = _dbus_first_type_in_signature (reader->type_str,
+                                          reader->type_pos + 1);
+
+  return element_type;
+}
+
+/**
+ * Gets the current position in the value block
+ * @param reader the reader
+ */
+int
+_dbus_type_reader_get_value_pos (const DBusTypeReader  *reader)
+{
+  return reader->value_pos;
+}
+
+/**
+ * Get the address of the marshaled value in the data being read.  The
+ * address may not be aligned; you have to align it to the type of the
+ * value you want to read. Most of the demarshal routines do this for
+ * you.
+ *
+ * @param reader the reader
+ * @param value_location the address of the marshaled value
+ */
+void
+_dbus_type_reader_read_raw (const DBusTypeReader  *reader,
+                            const unsigned char  **value_location)
+{
+  _dbus_assert (!reader->klass->types_only);
+
+  *value_location = _dbus_string_get_const_data_len (reader->value_str,
+                                                     reader->value_pos,
+                                                     0);
+}
+
+/**
+ * Reads a basic-typed value, as with _dbus_marshal_read_basic().
+ *
+ * @param reader the reader
+ * @param value the address of the value
+ */
+void
+_dbus_type_reader_read_basic (const DBusTypeReader    *reader,
+                              void                    *value)
+{
+  int t;
+
+  _dbus_assert (!reader->klass->types_only);
+
+  t = _dbus_type_reader_get_current_type (reader);
+
+  _dbus_marshal_read_basic (reader->value_str,
+                            reader->value_pos,
+                            t, value,
+                            reader->byte_order,
+                            NULL);
+
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("  type reader %p read basic type_pos = %d value_pos = %d remaining sig '%s'\n",
+                 reader, reader->type_pos, reader->value_pos,
+                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
+#endif
+}
+
+/**
+ * Returns the number of bytes in the array.
+ *
+ * @param reader the reader to read from
+ * @returns the number of bytes in the array
+ */
+int
+_dbus_type_reader_get_array_length (const DBusTypeReader  *reader)
+{
+  _dbus_assert (!reader->klass->types_only);
+  _dbus_assert (reader->klass == &array_reader_class);
+
+  return array_reader_get_array_len (reader);
+}
+
+/**
+ * Reads a block of fixed-length basic values, from the current point
+ * in an array to the end of the array.  Does not work for arrays of
+ * string or container types.
+ *
+ * This function returns the array in-place; it does not make a copy,
+ * and it does not swap the bytes.
+ *
+ * If you ask for #DBUS_TYPE_DOUBLE you will get a "const double*" back
+ * and the "value" argument should be a "const double**" and so on.
+ *
+ * @param reader the reader to read from
+ * @param value place to return the array values
+ * @param n_elements place to return number of array elements
+ */
+void
+_dbus_type_reader_read_fixed_multi (const DBusTypeReader  *reader,
+                                    void                  *value,
+                                    int                   *n_elements)
+{
+  int element_type;
+  int end_pos;
+  int remaining_len;
+  int alignment;
+  int total_len;
+
+  _dbus_assert (!reader->klass->types_only);
+  _dbus_assert (reader->klass == &array_reader_class);
+
+  element_type = _dbus_first_type_in_signature (reader->type_str,
+                                                reader->type_pos);
+
+  _dbus_assert (element_type != DBUS_TYPE_INVALID); /* why we don't use get_current_type() */
+  _dbus_assert (dbus_type_is_fixed (element_type));
+
+  alignment = _dbus_type_get_alignment (element_type);
+
+  _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
+
+  total_len = array_reader_get_array_len (reader);
+  end_pos = reader->u.array.start_pos + total_len;
+  remaining_len = end_pos - reader->value_pos;
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("end_pos %d total_len %d remaining_len %d value_pos %d\n",
+                 end_pos, total_len, remaining_len, reader->value_pos);
+#endif
+
+  _dbus_assert (remaining_len <= total_len);
+
+  if (remaining_len == 0)
+    *(const DBusBasicValue**) value = NULL;
+  else
+    *(const DBusBasicValue**) value =
+      (void*) _dbus_string_get_const_data_len (reader->value_str,
+                                               reader->value_pos,
+                                               remaining_len);
+
+  *n_elements = remaining_len / alignment;
+  _dbus_assert ((remaining_len % alignment) == 0);
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("  type reader %p read fixed array type_pos = %d value_pos = %d remaining sig '%s'\n",
+                 reader, reader->type_pos, reader->value_pos,
+                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
+#endif
+}
+
+/**
+ * Initialize a new reader pointing to the first type and
+ * corresponding value that's a child of the current container. It's
+ * an error to call this if the current type is a non-container.
+ *
+ * Note that DBusTypeReader traverses values, not types. So if you
+ * have an empty array of array of int, you can't recurse into it. You
+ * can only recurse into each element.
+ *
+ * @param reader the reader
+ * @param sub a reader to init pointing to the first child
+ */
+void
+_dbus_type_reader_recurse (DBusTypeReader *reader,
+                           DBusTypeReader *sub)
+{
+  int t;
+
+  t = _dbus_first_type_in_signature (reader->type_str, reader->type_pos);
+
+  switch (t)
+    {
+    case DBUS_TYPE_STRUCT:
+      if (reader->klass->types_only)
+        sub->klass = &struct_types_only_reader_class;
+      else
+        sub->klass = &struct_reader_class;
+      break;
+    case DBUS_TYPE_DICT_ENTRY:
+      if (reader->klass->types_only)
+        sub->klass = &dict_entry_types_only_reader_class;
+      else
+        sub->klass = &dict_entry_reader_class;
+      break;
+    case DBUS_TYPE_ARRAY:
+      if (reader->klass->types_only)
+        sub->klass = &array_types_only_reader_class;
+      else
+        sub->klass = &array_reader_class;
+      break;
+    case DBUS_TYPE_VARIANT:
+      if (reader->klass->types_only)
+        _dbus_assert_not_reached ("can't recurse into variant typecode");
+      else
+        sub->klass = &variant_reader_class;
+      break;
+    default:
+      _dbus_verbose ("recursing into type %s\n", _dbus_type_to_string (t));
+#ifndef DBUS_DISABLE_CHECKS
+      if (t == DBUS_TYPE_INVALID)
+        _dbus_warn_check_failed ("You can't recurse into an empty array or off the end of a message body\n");
+#endif /* DBUS_DISABLE_CHECKS */
+
+      _dbus_assert_not_reached ("don't yet handle recursing into this type");
+    }
+
+  _dbus_assert (sub->klass == all_reader_classes[sub->klass->id]);
+
+  (* sub->klass->recurse) (sub, reader);
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("  type reader %p RECURSED type_pos = %d value_pos = %d remaining sig '%s'\n",
+                 sub, sub->type_pos, sub->value_pos,
+                 _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0));
+#endif
+}
+
+/**
+ * Skip to the next value on this "level". e.g. the next field in a
+ * struct, the next value in an array. Returns FALSE at the end of the
+ * current container.
+ *
+ * @param reader the reader
+ * @returns FALSE if nothing more to read at or below this level
+ */
+dbus_bool_t
+_dbus_type_reader_next (DBusTypeReader *reader)
+{
+  int t;
+
+  t = _dbus_type_reader_get_current_type (reader);
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("  type reader %p START next() { type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
+                 reader, reader->type_pos, reader->value_pos,
+                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
+                 _dbus_type_to_string (t));
+#endif
+
+  if (t == DBUS_TYPE_INVALID)
+    return FALSE;
+
+  (* reader->klass->next) (reader, t);
+
+#if RECURSIVE_MARSHAL_READ_TRACE
+  _dbus_verbose ("  type reader %p END next() type_pos = %d value_pos = %d remaining sig '%s' current_type = %s\n",
+                 reader, reader->type_pos, reader->value_pos,
+                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
+                 _dbus_type_to_string (_dbus_type_reader_get_current_type (reader)));
+#endif
+
+  return _dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID;
+}
+
+/**
+ * Check whether there's another value on this "level". e.g. the next
+ * field in a struct, the next value in an array. Returns FALSE at the
+ * end of the current container.
+ *
+ * You probably don't want to use this; it makes for an awkward for/while
+ * loop. A nicer one is "while ((current_type = get_current_type()) != INVALID)"
+ *
+ * @param reader the reader
+ * @returns FALSE if nothing more to read at or below this level
+ */
+dbus_bool_t
+_dbus_type_reader_has_next (const DBusTypeReader *reader)
+{
+  /* Not efficient but works for now. */
+  DBusTypeReader copy;
+
+  copy = *reader;
+  return _dbus_type_reader_next (&copy);
+}
+
+/**
+ * Gets the string and range of said string containing the signature
+ * of the current value. Essentially a more complete version of
+ * _dbus_type_reader_get_current_type() (returns the full type
+ * rather than only the outside of the onion).
+ *
+ * Note though that the first byte in a struct signature is
+ * #DBUS_STRUCT_BEGIN_CHAR while the current type will be
+ * #DBUS_TYPE_STRUCT so it isn't true that the first byte of the
+ * signature is always the same as the current type. Another
+ * difference is that this function will still return a signature when
+ * inside an empty array; say you recurse into empty array of int32,
+ * the signature is "i" but the current type will always be
+ * #DBUS_TYPE_INVALID since there are no elements to be currently
+ * pointing to.
+ *
+ * @param reader the reader
+ * @param str_p place to return the string with the type in it
+ * @param start_p place to return start of the type
+ * @param len_p place to return the length of the type
+ */
+void
+_dbus_type_reader_get_signature (const DBusTypeReader  *reader,
+                                 const DBusString     **str_p,
+                                 int                   *start_p,
+                                 int                   *len_p)
+{
+  *str_p = reader->type_str;
+  *start_p = reader->type_pos;
+  *len_p = find_len_of_complete_type (reader->type_str, reader->type_pos);
+}
+
+typedef struct
+{
+  DBusString replacement; /**< Marshaled value including alignment padding */
+  int padding;            /**< How much of the replacement block is padding */
+} ReplacementBlock;
+
+static dbus_bool_t
+replacement_block_init (ReplacementBlock *block,
+                        DBusTypeReader   *reader)
+{
+  if (!_dbus_string_init (&block->replacement))
+    return FALSE;
+
+  /* % 8 is the padding to have the same align properties in
+   * our replacement string as we do at the position being replaced
+   */
+  block->padding = reader->value_pos % 8;
+
+  if (!_dbus_string_lengthen (&block->replacement, block->padding))
+    goto oom;
+
+  return TRUE;
+
+ oom:
+  _dbus_string_free (&block->replacement);
+  return FALSE;
+}
+
+static dbus_bool_t
+replacement_block_replace (ReplacementBlock     *block,
+                           DBusTypeReader       *reader,
+                           const DBusTypeReader *realign_root)
+{
+  DBusTypeWriter writer;
+  DBusTypeReader realign_reader;
+  DBusList *fixups;
+  int orig_len;
+
+  _dbus_assert (realign_root != NULL);
+
+  orig_len = _dbus_string_get_length (&block->replacement);
+
+  realign_reader = *realign_root;
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("INITIALIZING replacement block writer %p at value_pos %d\n",
+                 &writer, _dbus_string_get_length (&block->replacement));
+#endif
+  _dbus_type_writer_init_values_only (&writer,
+                                      realign_reader.byte_order,
+                                      realign_reader.type_str,
+                                      realign_reader.type_pos,
+                                      &block->replacement,
+                                      _dbus_string_get_length (&block->replacement));
+
+  _dbus_assert (realign_reader.value_pos <= reader->value_pos);
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("COPYING from reader at value_pos %d to writer %p starting after value_pos %d\n",
+                 realign_reader.value_pos, &writer, reader->value_pos);
+#endif
+  fixups = NULL;
+  if (!_dbus_type_writer_write_reader_partial (&writer,
+                                               &realign_reader,
+                                               reader,
+                                               block->padding,
+                                               _dbus_string_get_length (&block->replacement) - block->padding,
+                                               &fixups))
+    goto oom;
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("REPLACEMENT at padding %d len %d\n", block->padding,
+                 _dbus_string_get_length (&block->replacement) - block->padding);
+  _dbus_verbose_bytes_of_string (&block->replacement, block->padding,
+                                 _dbus_string_get_length (&block->replacement) - block->padding);
+  _dbus_verbose ("TO BE REPLACED at value_pos = %d (align pad %d) len %d realign_reader.value_pos %d\n",
+                 reader->value_pos, reader->value_pos % 8,
+                 realign_reader.value_pos - reader->value_pos,
+                 realign_reader.value_pos);
+  _dbus_verbose_bytes_of_string (reader->value_str,
+                                 reader->value_pos,
+                                 realign_reader.value_pos - reader->value_pos);
+#endif
+
+  /* Move the replacement into position
+   * (realign_reader should now be at the end of the block to be replaced)
+   */
+  if (!_dbus_string_replace_len (&block->replacement, block->padding,
+                                 _dbus_string_get_length (&block->replacement) - block->padding,
+                                 (DBusString*) reader->value_str,
+                                 reader->value_pos,
+                                 realign_reader.value_pos - reader->value_pos))
+    goto oom;
+
+  /* Process our fixups now that we can't have an OOM error */
+  apply_and_free_fixups (&fixups, reader);
+
+  return TRUE;
+
+ oom:
+  _dbus_string_set_length (&block->replacement, orig_len);
+  free_fixups (&fixups);
+  return FALSE;
+}
+
+static void
+replacement_block_free (ReplacementBlock *block)
+{
+  _dbus_string_free (&block->replacement);
+}
+
+/* In the variable-length case, we have to fix alignment after we insert.
+ * The strategy is as follows:
+ *
+ *  - pad a new string to have the same alignment as the
+ *    start of the current basic value
+ *  - write the new basic value
+ *  - copy from the original reader to the new string,
+ *    which will fix the alignment of types following
+ *    the new value
+ *    - this copy has to start at realign_root,
+ *      but not really write anything until it
+ *      passes the value being set
+ *    - as an optimization, we can stop copying
+ *      when the source and dest values are both
+ *      on an 8-boundary, since we know all following
+ *      padding and alignment will be identical
+ *  - copy the new string back to the original
+ *    string, replacing the relevant part of the
+ *    original string
+ *  - now any arrays in the original string that
+ *    contained the replaced string may have the
+ *    wrong length; so we have to fix that
+ */
+static dbus_bool_t
+reader_set_basic_variable_length (DBusTypeReader       *reader,
+                                  int                   current_type,
+                                  const void           *value,
+                                  const DBusTypeReader *realign_root)
+{
+  dbus_bool_t retval;
+  ReplacementBlock block;
+  DBusTypeWriter writer;
+
+  _dbus_assert (realign_root != NULL);
+
+  retval = FALSE;
+
+  if (!replacement_block_init (&block, reader))
+    return FALSE;
+
+  /* Write the new basic value */
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("INITIALIZING writer %p to write basic value at value_pos %d of replacement string\n",
+                 &writer, _dbus_string_get_length (&block.replacement));
+#endif
+  _dbus_type_writer_init_values_only (&writer,
+                                      reader->byte_order,
+                                      reader->type_str,
+                                      reader->type_pos,
+                                      &block.replacement,
+                                      _dbus_string_get_length (&block.replacement));
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("WRITING basic value to writer %p (replacement string)\n", &writer);
+#endif
+  if (!_dbus_type_writer_write_basic (&writer, current_type, value))
+    goto out;
+
+  if (!replacement_block_replace (&block,
+                                  reader,
+                                  realign_root))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  replacement_block_free (&block);
+  return retval;
+}
+
+static void
+reader_set_basic_fixed_length (DBusTypeReader *reader,
+                               int             current_type,
+                               const void     *value)
+{
+  _dbus_marshal_set_basic ((DBusString*) reader->value_str,
+                           reader->value_pos,
+                           current_type,
+                           value,
+                           reader->byte_order,
+                           NULL, NULL);
+}
+
+/**
+ * Sets a new value for the basic type value pointed to by the reader,
+ * leaving the reader valid to continue reading. Any other readers
+ * will be invalidated if you set a variable-length type such as a
+ * string.
+ *
+ * The provided realign_root is the reader to start from when
+ * realigning the data that follows the newly-set value. The reader
+ * parameter must point to a value below the realign_root parameter.
+ * If the type being set is fixed-length, then realign_root may be
+ * #NULL. Only values reachable from realign_root will be realigned,
+ * so if your string contains other values you will need to deal with
+ * those somehow yourself. It is OK if realign_root is the same
+ * reader as the reader parameter, though if you aren't setting the
+ * root it may not be such a good idea.
+ *
+ * @todo DBusTypeReader currently takes "const" versions of the type
+ * and value strings, and this function modifies those strings by
+ * casting away the const, which is of course bad if we want to get
+ * picky. (To be truly clean you'd have an object which contained the
+ * type and value strings and set_basic would be a method on that
+ * object... this would also make DBusTypeReader the same thing as
+ * DBusTypeMark. But since DBusMessage is effectively that object for
+ * D-Bus it doesn't seem worth creating some random object.)
+ *
+ * @todo optimize this by only rewriting until the old and new values
+ * are at the same alignment. Frequently this should result in only
+ * replacing the value that's immediately at hand.
+ *
+ * @param reader reader indicating where to set a new value
+ * @param value address of the value to set
+ * @param realign_root realign from here
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_type_reader_set_basic (DBusTypeReader       *reader,
+                             const void           *value,
+                             const DBusTypeReader *realign_root)
+{
+  int current_type;
+
+  _dbus_assert (!reader->klass->types_only);
+  _dbus_assert (reader->value_str == realign_root->value_str);
+  _dbus_assert (reader->value_pos >= realign_root->value_pos);
+
+  current_type = _dbus_type_reader_get_current_type (reader);
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("  SET BASIC type reader %p type_pos = %d value_pos = %d remaining sig '%s' realign_root = %p with value_pos %d current_type = %s\n",
+                 reader, reader->type_pos, reader->value_pos,
+                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0),
+                 realign_root,
+                 realign_root ? realign_root->value_pos : -1,
+                 _dbus_type_to_string (current_type));
+  _dbus_verbose_bytes_of_string (realign_root->value_str, realign_root->value_pos,
+                                 _dbus_string_get_length (realign_root->value_str) -
+                                 realign_root->value_pos);
+#endif
+
+  _dbus_assert (dbus_type_is_basic (current_type));
+
+  if (dbus_type_is_fixed (current_type))
+    {
+      reader_set_basic_fixed_length (reader, current_type, value);
+      return TRUE;
+    }
+  else
+    {
+      _dbus_assert (realign_root != NULL);
+      return reader_set_basic_variable_length (reader, current_type,
+                                               value, realign_root);
+    }
+}
+
+/**
+ * Recursively deletes any value pointed to by the reader, leaving the
+ * reader valid to continue reading. Any other readers will be
+ * invalidated.
+ *
+ * The provided realign_root is the reader to start from when
+ * realigning the data that follows the newly-set value.
+ * See _dbus_type_reader_set_basic() for more details on the
+ * realign_root paramter.
+ *
+ * @todo for now this does not delete the typecodes associated with
+ * the value, so this function should only be used for array elements.
+ *
+ * @param reader reader indicating where to delete a value
+ * @param realign_root realign from here
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_type_reader_delete (DBusTypeReader        *reader,
+                          const DBusTypeReader  *realign_root)
+{
+  dbus_bool_t retval;
+  ReplacementBlock block;
+
+  _dbus_assert (realign_root != NULL);
+  _dbus_assert (reader->klass == &array_reader_class);
+
+  retval = FALSE;
+
+  if (!replacement_block_init (&block, reader))
+    return FALSE;
+
+  if (!replacement_block_replace (&block,
+                                  reader,
+                                  realign_root))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  replacement_block_free (&block);
+  return retval;
+}
+
+/*
+ * Compares two readers, which must be iterating over the same value data.
+ * Returns #TRUE if the first parameter is further along than the second parameter.
+ *
+ * @param lhs left-hand-side (first) parameter
+ * @param rhs left-hand-side (first) parameter
+ * @returns whether lhs is greater than rhs
+ */
+static dbus_bool_t
+_dbus_type_reader_greater_than (const DBusTypeReader  *lhs,
+                                const DBusTypeReader  *rhs)
+{
+  _dbus_assert (lhs->value_str == rhs->value_str);
+
+  return lhs->value_pos > rhs->value_pos;
+}
+
+/*
+ *
+ *
+ *         DBusTypeWriter
+ *
+ *
+ *
+ */
+
+/**
+ * Initialize a write iterator, which is used to write out values in
+ * serialized D-Bus format.
+ *
+ * The type_pos passed in is expected to be inside an already-valid,
+ * though potentially empty, type signature. This means that the byte
+ * after type_pos must be either #DBUS_TYPE_INVALID (aka nul) or some
+ * other valid type. #DBusTypeWriter won't enforce that the signature
+ * is already valid (you can append the nul byte at the end if you
+ * like), but just be aware that you need the nul byte eventually and
+ * #DBusTypeWriter isn't going to write it for you.
+ *
+ * @param writer the writer to init
+ * @param byte_order the byte order to marshal into
+ * @param type_str the string to write typecodes into
+ * @param type_pos where to insert typecodes
+ * @param value_str the string to write values into
+ * @param value_pos where to insert values
+ *
+ */
+void
+_dbus_type_writer_init (DBusTypeWriter *writer,
+                        int             byte_order,
+                        DBusString     *type_str,
+                        int             type_pos,
+                        DBusString     *value_str,
+                        int             value_pos)
+{
+  writer->byte_order = byte_order;
+  writer->type_str = type_str;
+  writer->type_pos = type_pos;
+  writer->value_str = value_str;
+  writer->value_pos = value_pos;
+  writer->container_type = DBUS_TYPE_INVALID;
+  writer->type_pos_is_expectation = FALSE;
+  writer->enabled = TRUE;
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("writer %p init remaining sig '%s'\n", writer,
+                 writer->type_str ?
+                 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
+                 "unknown");
+#endif
+}
+
+/**
+ * Initialize a write iterator, with the signature to be provided
+ * later.
+ *
+ * @param writer the writer to init
+ * @param byte_order the byte order to marshal into
+ * @param value_str the string to write values into
+ * @param value_pos where to insert values
+ *
+ */
+void
+_dbus_type_writer_init_types_delayed (DBusTypeWriter *writer,
+                                      int             byte_order,
+                                      DBusString     *value_str,
+                                      int             value_pos)
+{
+  _dbus_type_writer_init (writer, byte_order,
+                          NULL, 0, value_str, value_pos);
+}
+
+/**
+ * Adds type string to the writer, if it had none.
+ *
+ * @param writer the writer to init
+ * @param type_str type string to add
+ * @param type_pos type position
+ *
+ */
+void
+_dbus_type_writer_add_types (DBusTypeWriter *writer,
+                             DBusString     *type_str,
+                             int             type_pos)
+{
+  if (writer->type_str == NULL) /* keeps us from using this as setter */
+    {
+      writer->type_str = type_str;
+      writer->type_pos = type_pos;
+    }
+}
+
+/**
+ * Removes type string from the writer.
+ *
+ * @param writer the writer to remove from
+ */
+void
+_dbus_type_writer_remove_types (DBusTypeWriter *writer)
+{
+  writer->type_str = NULL;
+  writer->type_pos = -1;
+}
+
+/**
+ * Like _dbus_type_writer_init(), except the type string
+ * passed in should correspond to an existing signature that
+ * matches what you're going to write out. The writer will
+ * check what you write vs. this existing signature.
+ *
+ * @param writer the writer to init
+ * @param byte_order the byte order to marshal into
+ * @param type_str the string with signature
+ * @param type_pos start of signature
+ * @param value_str the string to write values into
+ * @param value_pos where to insert values
+ *
+ */
+void
+_dbus_type_writer_init_values_only (DBusTypeWriter   *writer,
+                                    int               byte_order,
+                                    const DBusString *type_str,
+                                    int               type_pos,
+                                    DBusString       *value_str,
+                                    int               value_pos)
+{
+  _dbus_type_writer_init (writer, byte_order,
+                          (DBusString*)type_str, type_pos,
+                          value_str, value_pos);
+
+  writer->type_pos_is_expectation = TRUE;
+}
+
+static dbus_bool_t
+_dbus_type_writer_write_basic_no_typecode (DBusTypeWriter *writer,
+                                           int             type,
+                                           const void     *value)
+{
+  if (writer->enabled)
+    return _dbus_marshal_write_basic (writer->value_str,
+                                      writer->value_pos,
+                                      type,
+                                      value,
+                                      writer->byte_order,
+                                      &writer->value_pos);
+  else
+    return TRUE;
+}
+
+/* If our parent is an array, things are a little bit complicated.
+ *
+ * The parent must have a complete element type, such as
+ * "i" or "aai" or "(ii)" or "a(ii)". There can't be
+ * unclosed parens, or an "a" with no following type.
+ *
+ * To recurse, the only allowed operation is to recurse into the
+ * first type in the element type. So for "i" you can't recurse, for
+ * "ai" you can recurse into the array, for "(ii)" you can recurse
+ * into the struct.
+ *
+ * If you recurse into the array for "ai", then you must specify
+ * "i" for the element type of the array you recurse into.
+ *
+ * While inside an array at any level, we need to avoid writing to
+ * type_str, since the type only appears once for the whole array,
+ * it does not appear for each array element.
+ *
+ * While inside an array type_pos points to the expected next
+ * typecode, rather than the next place we could write a typecode.
+ */
+static void
+writer_recurse_init_and_check (DBusTypeWriter *writer,
+                               int             container_type,
+                               DBusTypeWriter *sub)
+{
+  _dbus_type_writer_init (sub,
+                          writer->byte_order,
+                          writer->type_str,
+                          writer->type_pos,
+                          writer->value_str,
+                          writer->value_pos);
+
+  sub->container_type = container_type;
+
+  if (writer->type_pos_is_expectation ||
+      (sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
+    sub->type_pos_is_expectation = TRUE;
+  else
+    sub->type_pos_is_expectation = FALSE;
+
+  sub->enabled = writer->enabled;
+
+#ifndef DBUS_DISABLE_CHECKS
+  if (writer->type_pos_is_expectation && writer->type_str)
+    {
+      int expected;
+
+      expected = _dbus_first_type_in_signature (writer->type_str, writer->type_pos);
+
+      if (expected != sub->container_type)
+        {
+          if (expected != DBUS_TYPE_INVALID)
+            _dbus_warn_check_failed ("Writing an element of type %s, but the expected type here is %s\n"
+                                     "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+                                     _dbus_type_to_string (sub->container_type),
+                                     _dbus_type_to_string (expected),
+                                     _dbus_string_get_const_data (writer->type_str), writer->type_pos);
+          else
+            _dbus_warn_check_failed ("Writing an element of type %s, but no value is expected here\n"
+                                     "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+                                     _dbus_type_to_string (sub->container_type),
+                                     _dbus_string_get_const_data (writer->type_str), writer->type_pos);
+          
+          _dbus_assert_not_reached ("bad array element or variant content written");
+        }
+    }
+#endif /* DBUS_DISABLE_CHECKS */
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("  type writer %p recurse parent %s type_pos = %d value_pos = %d is_expectation = %d remaining sig '%s' enabled = %d\n",
+                 writer,
+                 _dbus_type_to_string (writer->container_type),
+                 writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
+                 writer->type_str ?
+                 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
+                 "unknown",
+                 writer->enabled);
+  _dbus_verbose ("  type writer %p recurse sub %s   type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
+                 sub,
+                 _dbus_type_to_string (sub->container_type),
+                 sub->type_pos, sub->value_pos,
+                 sub->type_pos_is_expectation,
+                 sub->enabled);
+#endif
+}
+
+static dbus_bool_t
+write_or_verify_typecode (DBusTypeWriter *writer,
+                          int             typecode)
+{
+  /* A subwriter inside an array or variant will have type_pos
+   * pointing to the expected typecode; a writer not inside an array
+   * or variant has type_pos pointing to the next place to insert a
+   * typecode.
+   */
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("  type writer %p write_or_verify start type_pos = %d remaining sig '%s' enabled = %d\n",
+                 writer, writer->type_pos,
+                 writer->type_str ?
+                 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
+                 "unknown",
+                 writer->enabled);
+#endif
+
+  if (writer->type_str == NULL)
+    return TRUE;
+
+  if (writer->type_pos_is_expectation)
+    {
+#ifndef DBUS_DISABLE_CHECKS
+      {
+        int expected;
+
+        expected = _dbus_string_get_byte (writer->type_str, writer->type_pos);
+
+        if (expected != typecode)
+          {
+            if (expected != DBUS_TYPE_INVALID)
+              _dbus_warn_check_failed ("Array or variant type requires that type %s be written, but %s was written.\n"
+                                       "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+                                       _dbus_type_to_string (expected), _dbus_type_to_string (typecode),
+                                       _dbus_string_get_const_data (writer->type_str), writer->type_pos);
+            else
+              _dbus_warn_check_failed ("Array or variant type wasn't expecting any more values to be written into it, but a value %s was written.\n"
+                                       "The overall signature expected here was '%s' and we are on byte %d of that signature.\n",
+                                       _dbus_type_to_string (typecode),
+                                       _dbus_string_get_const_data (writer->type_str), writer->type_pos);
+            _dbus_assert_not_reached ("bad type inserted somewhere inside an array or variant");
+          }
+      }
+#endif /* DBUS_DISABLE_CHECKS */
+
+      /* if immediately inside an array we'd always be appending an element,
+       * so the expected type doesn't change; if inside a struct or something
+       * below an array, we need to move through said struct or something.
+       */
+      if (writer->container_type != DBUS_TYPE_ARRAY)
+        writer->type_pos += 1;
+    }
+  else
+    {
+      if (!_dbus_string_insert_byte (writer->type_str,
+                                     writer->type_pos,
+                                     typecode))
+        return FALSE;
+
+      writer->type_pos += 1;
+    }
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("  type writer %p write_or_verify end type_pos = %d remaining sig '%s'\n",
+                 writer, writer->type_pos,
+                 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0));
+#endif
+
+  return TRUE;
+}
+
+static dbus_bool_t
+writer_recurse_struct_or_dict_entry (DBusTypeWriter   *writer,
+                                     int               begin_char,
+                                     const DBusString *contained_type,
+                                     int               contained_type_start,
+                                     int               contained_type_len,
+                                     DBusTypeWriter   *sub)
+{
+  /* FIXME right now contained_type is ignored; we could probably
+   * almost trivially fix the code so if it's present we
+   * write it out and then set type_pos_is_expectation
+   */
+
+  /* Ensure that we'll be able to add alignment padding and the typecode */
+  if (writer->enabled)
+    {
+      if (!_dbus_string_alloc_space (sub->value_str, 8))
+        return FALSE;
+    }
+
+  if (!write_or_verify_typecode (sub, begin_char))
+    _dbus_assert_not_reached ("failed to insert struct typecode after prealloc");
+
+  if (writer->enabled)
+    {
+      if (!_dbus_string_insert_bytes (sub->value_str,
+                                      sub->value_pos,
+                                      _DBUS_ALIGN_VALUE (sub->value_pos, 8) - sub->value_pos,
+                                      '\0'))
+        _dbus_assert_not_reached ("should not have failed to insert alignment padding for struct");
+      sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
+    }
+
+  return TRUE;
+}
+
+
+static dbus_bool_t
+writer_recurse_array (DBusTypeWriter   *writer,
+                      const DBusString *contained_type,
+                      int               contained_type_start,
+                      int               contained_type_len,
+                      DBusTypeWriter   *sub,
+                      dbus_bool_t       is_array_append)
+{
+  dbus_uint32_t value = 0;
+  int alignment;
+  int aligned;
+
+#ifndef DBUS_DISABLE_CHECKS
+  if (writer->container_type == DBUS_TYPE_ARRAY &&
+      writer->type_str)
+    {
+      if (!_dbus_string_equal_substring (contained_type,
+                                         contained_type_start,
+                                         contained_type_len,
+                                         writer->type_str,
+                                         writer->u.array.element_type_pos + 1))
+        {
+          _dbus_warn_check_failed ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
+                                   _dbus_string_get_const_data_len (contained_type,
+                                                                    contained_type_start,
+                                                                    contained_type_len));
+          _dbus_assert_not_reached ("incompatible type for child array");
+        }
+    }
+#endif /* DBUS_DISABLE_CHECKS */
+
+  if (writer->enabled && !is_array_append)
+    {
+      /* 3 pad + 4 bytes for the array length, and 4 bytes possible padding
+       * before array values
+       */
+      if (!_dbus_string_alloc_space (sub->value_str, 3 + 4 + 4))
+        return FALSE;
+    }
+
+  if (writer->type_str != NULL)
+    {
+      sub->type_pos += 1; /* move to point to the element type, since type_pos
+                           * should be the expected type for further writes
+                           */
+      sub->u.array.element_type_pos = sub->type_pos;
+    }
+
+  if (!writer->type_pos_is_expectation)
+    {
+      /* sub is a toplevel/outermost array so we need to write the type data */
+
+      /* alloc space for array typecode, element signature */
+      if (!_dbus_string_alloc_space (writer->type_str, 1 + contained_type_len))
+        return FALSE;
+
+      if (!_dbus_string_insert_byte (writer->type_str,
+                                     writer->type_pos,
+                                     DBUS_TYPE_ARRAY))
+        _dbus_assert_not_reached ("failed to insert array typecode after prealloc");
+
+      if (!_dbus_string_copy_len (contained_type,
+                                  contained_type_start, contained_type_len,
+                                  sub->type_str,
+                                  sub->u.array.element_type_pos))
+        _dbus_assert_not_reached ("should not have failed to insert array element typecodes");
+    }
+
+  if (writer->type_str != NULL)
+    {
+      /* If the parent is an array, we hold type_pos pointing at the array element type;
+       * otherwise advance it to reflect the array value we just recursed into
+       */
+      if (writer->container_type != DBUS_TYPE_ARRAY)
+        writer->type_pos += 1 + contained_type_len;
+      else
+        _dbus_assert (writer->type_pos_is_expectation); /* because it's an array */
+    }
+
+  if (writer->enabled)
+    {
+      /* Write (or jump over, if is_array_append) the length */
+      sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
+
+      if (is_array_append)
+        {
+          sub->value_pos += 4;
+        }
+      else
+        {
+          if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
+                                                          &value))
+            _dbus_assert_not_reached ("should not have failed to insert array len");
+        }
+
+      _dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
+
+      /* Write alignment padding for array elements
+       * Note that we write the padding *even for empty arrays*
+       * to avoid wonky special cases
+       */
+      alignment = element_type_get_alignment (contained_type, contained_type_start);
+
+      aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
+      if (aligned != sub->value_pos)
+        {
+          if (!is_array_append)
+            {
+              if (!_dbus_string_insert_bytes (sub->value_str,
+                                              sub->value_pos,
+                                              aligned - sub->value_pos,
+                                              '\0'))
+                _dbus_assert_not_reached ("should not have failed to insert alignment padding");
+            }
+
+          sub->value_pos = aligned;
+        }
+
+      sub->u.array.start_pos = sub->value_pos;
+
+      if (is_array_append)
+        {
+          dbus_uint32_t len;
+
+          _dbus_assert (_DBUS_ALIGN_VALUE (sub->u.array.len_pos, 4) ==
+                        (unsigned) sub->u.array.len_pos);
+          len = _dbus_unpack_uint32 (sub->byte_order,
+                                     _dbus_string_get_const_data_len (sub->value_str,
+                                                                      sub->u.array.len_pos,
+                                                                      4));
+
+          sub->value_pos += len;
+        }
+    }
+  else
+    {
+      /* not enabled, so we won't write the len_pos; set it to -1 to so indicate */
+      sub->u.array.len_pos = -1;
+      sub->u.array.start_pos = sub->value_pos;
+    }
+
+  _dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
+  _dbus_assert (is_array_append || sub->u.array.start_pos == sub->value_pos);
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+      _dbus_verbose ("  type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d value_pos = %d\n", sub,
+                     sub->type_str ?
+                     _dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0) :
+                     "unknown",
+                     sub->u.array.start_pos, sub->u.array.len_pos, sub->value_pos);
+#endif
+
+  return TRUE;
+}
+
+/* Variant value will normally have:
+ *   1 byte signature length not including nul
+ *   signature typecodes (nul terminated)
+ *   padding to alignment of contained type
+ *   body according to signature
+ *
+ * The signature string can only have a single type
+ * in it but that type may be complex/recursive.
+ *
+ * So a typical variant type with the integer 3 will have these
+ * octets:
+ *   0x1 'i' '\0' [1 byte padding to alignment boundary] 0x0 0x0 0x0 0x3
+ *
+ * The main world of hurt for writing out a variant is that the type
+ * string is the same string as the value string. Which means
+ * inserting to the type string will move the value_pos; and it means
+ * that inserting to the type string could break type alignment.
+ */
+static dbus_bool_t
+writer_recurse_variant (DBusTypeWriter   *writer,
+                        const DBusString *contained_type,
+                        int               contained_type_start,
+                        int               contained_type_len,
+                        DBusTypeWriter   *sub)
+{
+  int contained_alignment;
+  
+  if (writer->enabled)
+    {
+      /* Allocate space for the worst case, which is 1 byte sig
+       * length, nul byte at end of sig, and 7 bytes padding to
+       * 8-boundary.
+       */
+      if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
+        return FALSE;
+    }
+
+  /* write VARIANT typecode to the parent's type string */
+  if (!write_or_verify_typecode (writer, DBUS_TYPE_VARIANT))
+    return FALSE;
+
+  /* If not enabled, mark that we have no type_str anymore ... */
+
+  if (!writer->enabled)
+    {
+      sub->type_str = NULL;
+      sub->type_pos = -1;
+
+      return TRUE;
+    }
+
+  /* If we're enabled then continue ... */
+
+  if (!_dbus_string_insert_byte (sub->value_str,
+                                 sub->value_pos,
+                                 contained_type_len))
+    _dbus_assert_not_reached ("should not have failed to insert variant type sig len");
+
+  sub->value_pos += 1;
+
+  /* Here we switch over to the expected type sig we're about to write */
+  sub->type_str = sub->value_str;
+  sub->type_pos = sub->value_pos;
+
+  if (!_dbus_string_copy_len (contained_type, contained_type_start, contained_type_len,
+                              sub->value_str, sub->value_pos))
+    _dbus_assert_not_reached ("should not have failed to insert variant type sig");
+
+  sub->value_pos += contained_type_len;
+
+  if (!_dbus_string_insert_byte (sub->value_str,
+                                 sub->value_pos,
+                                 DBUS_TYPE_INVALID))
+    _dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
+
+  sub->value_pos += 1;
+
+  contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (contained_type, contained_type_start));
+  
+  if (!_dbus_string_insert_bytes (sub->value_str,
+                                  sub->value_pos,
+                                  _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment) - sub->value_pos,
+                                  '\0'))
+    _dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
+  sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+_dbus_type_writer_recurse_contained_len (DBusTypeWriter   *writer,
+                                         int               container_type,
+                                         const DBusString *contained_type,
+                                         int               contained_type_start,
+                                         int               contained_type_len,
+                                         DBusTypeWriter   *sub,
+                                         dbus_bool_t       is_array_append)
+{
+  writer_recurse_init_and_check (writer, container_type, sub);
+
+  switch (container_type)
+    {
+    case DBUS_TYPE_STRUCT:
+      return writer_recurse_struct_or_dict_entry (writer,
+                                                  DBUS_STRUCT_BEGIN_CHAR,
+                                                  contained_type,
+                                                  contained_type_start, contained_type_len,
+                                                  sub);
+      break;
+    case DBUS_TYPE_DICT_ENTRY:
+      return writer_recurse_struct_or_dict_entry (writer,
+                                                  DBUS_DICT_ENTRY_BEGIN_CHAR,
+                                                  contained_type,
+                                                  contained_type_start, contained_type_len,
+                                                  sub);
+      break;
+    case DBUS_TYPE_ARRAY:
+      return writer_recurse_array (writer,
+                                   contained_type, contained_type_start, contained_type_len,
+                                   sub, is_array_append);
+      break;
+    case DBUS_TYPE_VARIANT:
+      return writer_recurse_variant (writer,
+                                     contained_type, contained_type_start, contained_type_len,
+                                     sub);
+      break;
+    default:
+      _dbus_assert_not_reached ("tried to recurse into type that doesn't support that");
+      return FALSE;
+      break;
+    }
+}
+
+/**
+ * Opens a new container and writes out the initial information for that container.
+ *
+ * @param writer the writer
+ * @param container_type the type of the container to open
+ * @param contained_type the array element type or variant content type
+ * @param contained_type_start position to look for the type
+ * @param sub the new sub-writer to write container contents
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_type_writer_recurse (DBusTypeWriter   *writer,
+                           int               container_type,
+                           const DBusString *contained_type,
+                           int               contained_type_start,
+                           DBusTypeWriter   *sub)
+{
+  int contained_type_len;
+
+  if (contained_type)
+    contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
+  else
+    contained_type_len = 0;
+
+  return _dbus_type_writer_recurse_contained_len (writer, container_type,
+                                                  contained_type,
+                                                  contained_type_start,
+                                                  contained_type_len,
+                                                  sub,
+                                                  FALSE);
+}
+
+/**
+ * Append to an existing array. Essentially, the writer will read an
+ * existing length at the write location; jump over that length; and
+ * write new fields. On unrecurse(), the existing length will be
+ * updated.
+ *
+ * @param writer the writer
+ * @param contained_type element type
+ * @param contained_type_start position of element type
+ * @param sub the subwriter to init
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_type_writer_append_array (DBusTypeWriter   *writer,
+                                const DBusString *contained_type,
+                                int               contained_type_start,
+                                DBusTypeWriter   *sub)
+{
+  int contained_type_len;
+
+  if (contained_type)
+    contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
+  else
+    contained_type_len = 0;
+
+  return _dbus_type_writer_recurse_contained_len (writer, DBUS_TYPE_ARRAY,
+                                                  contained_type,
+                                                  contained_type_start,
+                                                  contained_type_len,
+                                                  sub,
+                                                  TRUE);
+}
+
+static int
+writer_get_array_len (DBusTypeWriter *writer)
+{
+  _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
+  return writer->value_pos - writer->u.array.start_pos;
+}
+
+/**
+ * Closes a container created by _dbus_type_writer_recurse()
+ * and writes any additional information to the values block.
+ *
+ * @param writer the writer
+ * @param sub the sub-writer created by _dbus_type_writer_recurse()
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_type_writer_unrecurse (DBusTypeWriter *writer,
+                             DBusTypeWriter *sub)
+{
+  /* type_pos_is_expectation never gets unset once set, or we'd get all hosed */
+  _dbus_assert (!writer->type_pos_is_expectation ||
+                (writer->type_pos_is_expectation && sub->type_pos_is_expectation));
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("  type writer %p unrecurse type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
+                 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
+                 _dbus_type_to_string (writer->container_type));
+  _dbus_verbose ("  type writer %p unrecurse sub type_pos = %d value_pos = %d is_expectation = %d container_type = %s\n",
+                 sub, sub->type_pos, sub->value_pos,
+                 sub->type_pos_is_expectation,
+                 _dbus_type_to_string (sub->container_type));
+#endif
+
+  if (sub->container_type == DBUS_TYPE_STRUCT)
+    {
+      if (!write_or_verify_typecode (sub, DBUS_STRUCT_END_CHAR))
+        return FALSE;
+    }
+  else if (sub->container_type == DBUS_TYPE_DICT_ENTRY)
+    {
+      if (!write_or_verify_typecode (sub, DBUS_DICT_ENTRY_END_CHAR))
+        return FALSE;
+    }
+  else if (sub->container_type == DBUS_TYPE_ARRAY)
+    {
+      if (sub->u.array.len_pos >= 0) /* len_pos == -1 if we weren't enabled when we passed it */
+        {
+          dbus_uint32_t len;
+
+          /* Set the array length */
+          len = writer_get_array_len (sub);
+          _dbus_marshal_set_uint32 (sub->value_str,
+                                    sub->u.array.len_pos,
+                                    len,
+                                    sub->byte_order);
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+          _dbus_verbose ("    filled in sub array len to %u at len_pos %d\n",
+                         len, sub->u.array.len_pos);
+#endif
+        }
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+      else
+        {
+          _dbus_verbose ("    not filling in sub array len because we were disabled when we passed the len\n");
+        }
+#endif
+    }
+
+  /* Now get type_pos right for the parent writer. Here are the cases:
+   *
+   * Cases !writer->type_pos_is_expectation:
+   *   (in these cases we want to update to the new insertion point)
+   *
+   * - if we recursed into a STRUCT then we didn't know in advance
+   *   what the types in the struct would be; so we have to fill in
+   *   that information now.
+   *       writer->type_pos = sub->type_pos
+   *
+   * - if we recursed into anything else, we knew the full array
+   *   type, or knew the single typecode marking VARIANT, so
+   *   writer->type_pos is already correct.
+   *       writer->type_pos should remain as-is
+   *
+   * - note that the parent is never an ARRAY or VARIANT, if it were
+   *   then type_pos_is_expectation would be TRUE. The parent
+   *   is thus known to be a toplevel or STRUCT.
+   *
+   * Cases where writer->type_pos_is_expectation:
+   *   (in these cases we want to update to next expected type to write)
+   *
+   * - we recursed from STRUCT into STRUCT and we didn't increment
+   *   type_pos in the parent just to stay consistent with the
+   *   !writer->type_pos_is_expectation case (though we could
+   *   special-case this in recurse_struct instead if we wanted)
+   *       writer->type_pos = sub->type_pos
+   *
+   * - we recursed from STRUCT into ARRAY or VARIANT and type_pos
+   *   for parent should have been incremented already
+   *       writer->type_pos should remain as-is
+   *
+   * - we recursed from ARRAY into a sub-element, so type_pos in the
+   *   parent is the element type and should remain the element type
+   *   for the benefit of the next child element
+   *       writer->type_pos should remain as-is
+   *
+   * - we recursed from VARIANT into its value, so type_pos in the
+   *   parent makes no difference since there's only one value
+   *   and we just finished writing it and won't use type_pos again
+   *       writer->type_pos should remain as-is
+   *
+   *
+   * For all these, DICT_ENTRY is the same as STRUCT
+   */
+  if (writer->type_str != NULL)
+    {
+      if ((sub->container_type == DBUS_TYPE_STRUCT ||
+           sub->container_type == DBUS_TYPE_DICT_ENTRY) &&
+          (writer->container_type == DBUS_TYPE_STRUCT ||
+           writer->container_type == DBUS_TYPE_DICT_ENTRY ||
+           writer->container_type == DBUS_TYPE_INVALID))
+        {
+          /* Advance the parent to the next struct field */
+          writer->type_pos = sub->type_pos;
+        }
+    }
+
+  writer->value_pos = sub->value_pos;
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("  type writer %p unrecursed type_pos = %d value_pos = %d remaining sig '%s'\n",
+                 writer, writer->type_pos, writer->value_pos,
+                 writer->type_str ?
+                 _dbus_string_get_const_data_len (writer->type_str, writer->type_pos, 0) :
+                 "unknown");
+#endif
+
+  return TRUE;
+}
+
+/**
+ * Writes out a basic type.
+ *
+ * @param writer the writer
+ * @param type the type to write
+ * @param value the address of the value to write
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_type_writer_write_basic (DBusTypeWriter *writer,
+                               int             type,
+                               const void     *value)
+{
+  dbus_bool_t retval;
+
+  /* First ensure that our type realloc will succeed */
+  if (!writer->type_pos_is_expectation && writer->type_str != NULL)
+    {
+      if (!_dbus_string_alloc_space (writer->type_str, 1))
+        return FALSE;
+    }
+
+  retval = FALSE;
+
+  if (!_dbus_type_writer_write_basic_no_typecode (writer, type, value))
+    goto out;
+
+  if (!write_or_verify_typecode (writer, type))
+    _dbus_assert_not_reached ("failed to write typecode after prealloc");
+
+  retval = TRUE;
+
+ out:
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("  type writer %p basic type_pos = %d value_pos = %d is_expectation = %d enabled = %d\n",
+                 writer, writer->type_pos, writer->value_pos, writer->type_pos_is_expectation,
+                 writer->enabled);
+#endif
+
+  return retval;
+}
+
+/**
+ * Writes a block of fixed-length basic values, i.e. those that are
+ * both dbus_type_is_fixed() and _dbus_type_is_basic(). The block
+ * must be written inside an array.
+ *
+ * The value parameter should be the address of said array of values,
+ * so e.g. if it's an array of double, pass in "const double**"
+ *
+ * @param writer the writer
+ * @param element_type type of stuff in the array
+ * @param value address of the array
+ * @param n_elements number of elements in the array
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_type_writer_write_fixed_multi (DBusTypeWriter        *writer,
+                                     int                    element_type,
+                                     const void            *value,
+                                     int                    n_elements)
+{
+  _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
+  _dbus_assert (dbus_type_is_fixed (element_type));
+  _dbus_assert (writer->type_pos_is_expectation);
+  _dbus_assert (n_elements >= 0);
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("  type writer %p entering fixed multi type_pos = %d value_pos = %d n_elements %d\n",
+                 writer, writer->type_pos, writer->value_pos, n_elements);
+#endif
+
+  if (!write_or_verify_typecode (writer, element_type))
+    _dbus_assert_not_reached ("OOM should not happen if only verifying typecode");
+
+  if (writer->enabled)
+    {
+      if (!_dbus_marshal_write_fixed_multi (writer->value_str,
+                                            writer->value_pos,
+                                            element_type,
+                                            value,
+                                            n_elements,
+                                            writer->byte_order,
+                                            &writer->value_pos))
+        return FALSE;
+    }
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+  _dbus_verbose ("  type writer %p fixed multi written new type_pos = %d new value_pos = %d n_elements %d\n",
+                 writer, writer->type_pos, writer->value_pos, n_elements);
+#endif
+
+  return TRUE;
+}
+
+static void
+enable_if_after (DBusTypeWriter       *writer,
+                 DBusTypeReader       *reader,
+                 const DBusTypeReader *start_after)
+{
+  if (start_after)
+    {
+      if (!writer->enabled && _dbus_type_reader_greater_than (reader, start_after))
+        {
+          _dbus_type_writer_set_enabled (writer, TRUE);
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+          _dbus_verbose ("ENABLING writer %p at %d because reader at value_pos %d is after reader at value_pos %d\n",
+                         writer, writer->value_pos, reader->value_pos, start_after->value_pos);
+#endif
+        }
+
+      _dbus_assert ((!writer->enabled && !_dbus_type_reader_greater_than (reader, start_after)) ||
+                    (writer->enabled && _dbus_type_reader_greater_than (reader, start_after)));
+    }
+}
+
+static dbus_bool_t
+append_fixup (DBusList               **fixups,
+              const DBusArrayLenFixup *fixup)
+{
+  DBusArrayLenFixup *f;
+
+  f = dbus_new (DBusArrayLenFixup, 1);
+  if (f == NULL)
+    return FALSE;
+
+  *f = *fixup;
+
+  if (!_dbus_list_append (fixups, f))
+    {
+      dbus_free (f);
+      return FALSE;
+    }
+
+  _dbus_assert (f->len_pos_in_reader == fixup->len_pos_in_reader);
+  _dbus_assert (f->new_len == fixup->new_len);
+
+  return TRUE;
+}
+
+/* This loop is trivial if you ignore all the start_after nonsense,
+ * so if you're trying to figure it out, start by ignoring that
+ */
+static dbus_bool_t
+writer_write_reader_helper (DBusTypeWriter       *writer,
+                            DBusTypeReader       *reader,
+                            const DBusTypeReader *start_after,
+                            int                   start_after_new_pos,
+                            int                   start_after_new_len,
+                            DBusList            **fixups,
+                            dbus_bool_t           inside_start_after)
+{
+  int current_type;
+
+  while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
+    {
+      if (dbus_type_is_container (current_type))
+        {
+          DBusTypeReader subreader;
+          DBusTypeWriter subwriter;
+          const DBusString *sig_str;
+          int sig_start;
+          int sig_len;
+          dbus_bool_t enabled_at_recurse;
+          dbus_bool_t past_start_after;
+          int reader_array_len_pos;
+          int reader_array_start_pos;
+          dbus_bool_t this_is_start_after;
+
+          /* type_pos is checked since e.g. in a struct the struct
+           * and its first field have the same value_pos.
+           * type_str will differ in reader/start_after for variants
+           * where type_str is inside the value_str
+           */
+          if (!inside_start_after && start_after &&
+              reader->value_pos == start_after->value_pos &&
+              reader->type_str == start_after->type_str &&
+              reader->type_pos == start_after->type_pos)
+            this_is_start_after = TRUE;
+          else
+            this_is_start_after = FALSE;
+
+          _dbus_type_reader_recurse (reader, &subreader);
+
+          if (current_type == DBUS_TYPE_ARRAY)
+            {
+              reader_array_len_pos = ARRAY_READER_LEN_POS (&subreader);
+              reader_array_start_pos = subreader.u.array.start_pos;
+            }
+          else
+            {
+              /* quiet gcc */
+              reader_array_len_pos = -1;
+              reader_array_start_pos = -1;
+            }
+
+          _dbus_type_reader_get_signature (&subreader, &sig_str,
+                                           &sig_start, &sig_len);
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+          _dbus_verbose ("about to recurse into %s reader at %d subreader at %d writer at %d start_after reader at %d write target len %d inside_start_after = %d this_is_start_after = %d\n",
+                         _dbus_type_to_string (current_type),
+                         reader->value_pos,
+                         subreader.value_pos,
+                         writer->value_pos,
+                         start_after ? start_after->value_pos : -1,
+                         _dbus_string_get_length (writer->value_str),
+                         inside_start_after, this_is_start_after);
+#endif
+
+          if (!inside_start_after && !this_is_start_after)
+            enable_if_after (writer, &subreader, start_after);
+          enabled_at_recurse = writer->enabled;
+          if (!_dbus_type_writer_recurse_contained_len (writer, current_type,
+                                                        sig_str, sig_start, sig_len,
+                                                        &subwriter, FALSE))
+            goto oom;
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+          _dbus_verbose ("recursed into subwriter at %d write target len %d\n",
+                         subwriter.value_pos,
+                         _dbus_string_get_length (subwriter.value_str));
+#endif
+
+          if (!writer_write_reader_helper (&subwriter, &subreader, start_after,
+                                           start_after_new_pos, start_after_new_len,
+                                           fixups,
+                                           inside_start_after ||
+                                           this_is_start_after))
+            goto oom;
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+          _dbus_verbose ("about to unrecurse from %s subreader at %d writer at %d subwriter at %d  write target len %d\n",
+                         _dbus_type_to_string (current_type),
+                         subreader.value_pos,
+                         writer->value_pos,
+                         subwriter.value_pos,
+                         _dbus_string_get_length (writer->value_str));
+#endif
+
+          if (!inside_start_after && !this_is_start_after)
+            enable_if_after (writer, &subreader, start_after);
+          past_start_after = writer->enabled;
+          if (!_dbus_type_writer_unrecurse (writer, &subwriter))
+            goto oom;
+
+          /* If we weren't enabled when we recursed, we didn't
+           * write an array len; if we passed start_after
+           * somewhere inside the array, then we need to generate
+           * a fixup.
+           */
+          if (start_after != NULL &&
+              !enabled_at_recurse && past_start_after &&
+              current_type == DBUS_TYPE_ARRAY &&
+              fixups != NULL)
+            {
+              DBusArrayLenFixup fixup;
+              int bytes_written_after_start_after;
+              int bytes_before_start_after;
+              int old_len;
+
+              /* this subwriter access is moderately unkosher since we
+               * already unrecursed, but it works as long as unrecurse
+               * doesn't break us on purpose
+               */
+              bytes_written_after_start_after = writer_get_array_len (&subwriter);
+
+              bytes_before_start_after =
+                start_after->value_pos - reader_array_start_pos;
+
+              fixup.len_pos_in_reader = reader_array_len_pos;
+              fixup.new_len =
+                bytes_before_start_after +
+                start_after_new_len +
+                bytes_written_after_start_after;
+
+              _dbus_assert (_DBUS_ALIGN_VALUE (fixup.len_pos_in_reader, 4) ==
+                            (unsigned) fixup.len_pos_in_reader);
+
+              old_len = _dbus_unpack_uint32 (reader->byte_order,
+                                             _dbus_string_get_const_data_len (reader->value_str,
+                                                                              fixup.len_pos_in_reader, 4));
+
+              if (old_len != fixup.new_len && !append_fixup (fixups, &fixup))
+                goto oom;
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+              _dbus_verbose ("Generated fixup len_pos_in_reader = %d new_len = %d reader_array_start_pos = %d start_after->value_pos = %d bytes_before_start_after = %d start_after_new_len = %d bytes_written_after_start_after = %d\n",
+                             fixup.len_pos_in_reader,
+                             fixup.new_len,
+                             reader_array_start_pos,
+                             start_after->value_pos,
+                             bytes_before_start_after,
+                             start_after_new_len,
+                             bytes_written_after_start_after);
+#endif
+            }
+        }
+      else
+        {
+          DBusBasicValue val;
+
+          _dbus_assert (dbus_type_is_basic (current_type));
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+          _dbus_verbose ("Reading basic value %s at %d\n",
+                         _dbus_type_to_string (current_type),
+                         reader->value_pos);
+#endif
+
+          _dbus_type_reader_read_basic (reader, &val);
+
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+          _dbus_verbose ("Writing basic value %s at %d write target len %d inside_start_after = %d\n",
+                         _dbus_type_to_string (current_type),
+                         writer->value_pos,
+                         _dbus_string_get_length (writer->value_str),
+                         inside_start_after);
+#endif
+          if (!inside_start_after)
+            enable_if_after (writer, reader, start_after);
+          if (!_dbus_type_writer_write_basic (writer, current_type, &val))
+            goto oom;
+#if RECURSIVE_MARSHAL_WRITE_TRACE
+          _dbus_verbose ("Wrote basic value %s, new value_pos %d write target len %d\n",
+                         _dbus_type_to_string (current_type),
+                         writer->value_pos,
+                         _dbus_string_get_length (writer->value_str));
+#endif
+        }
+
+      _dbus_type_reader_next (reader);
+    }
+
+  return TRUE;
+
+ oom:
+  if (fixups)
+    apply_and_free_fixups (fixups, NULL); /* NULL for reader to apply to */
+
+  return FALSE;
+}
+
+/*
+ * Iterate through all values in the given reader, writing a copy of
+ * each value to the writer.  The reader will be moved forward to its
+ * end position.
+ *
+ * If a reader start_after is provided, it should be a reader for the
+ * same data as the reader to be written. Only values occurring after
+ * the value pointed to by start_after will be written to the writer.
+ *
+ * If start_after is provided, then the copy of the reader will be
+ * partial. This means that array lengths will not have been copied.
+ * The assumption is that you wrote a new version of the value at
+ * start_after to the writer. You have to pass in the start position
+ * and length of the new value. (If you are deleting the value
+ * at start_after, pass in 0 for the length.)
+ *
+ * If the fixups parameter is non-#NULL, then any array length that
+ * was read but not written due to start_after will be provided
+ * as a #DBusArrayLenFixup. The fixup contains the position of the
+ * array length in the source data, and the correct array length
+ * assuming you combine the source data before start_after with
+ * the written data at start_after and beyond.
+ *
+ * @param writer the writer to copy to
+ * @param reader the reader to copy from
+ * @param start_after #NULL or a reader showing where to start
+ * @param start_after_new_pos the position of start_after equivalent in the target data
+ * @param start_after_new_len the length of start_after equivalent in the target data
+ * @param fixups list to append #DBusArrayLenFixup if the write was partial
+ * @returns #FALSE if no memory
+ */
+static dbus_bool_t
+_dbus_type_writer_write_reader_partial (DBusTypeWriter       *writer,
+                                        DBusTypeReader       *reader,
+                                        const DBusTypeReader *start_after,
+                                        int                   start_after_new_pos,
+                                        int                   start_after_new_len,
+                                        DBusList            **fixups)
+{
+  DBusTypeWriter orig;
+  int orig_type_len;
+  int orig_value_len;
+  int new_bytes;
+  int orig_enabled;
+
+  orig = *writer;
+  orig_type_len = _dbus_string_get_length (writer->type_str);
+  orig_value_len = _dbus_string_get_length (writer->value_str);
+  orig_enabled = writer->enabled;
+
+  if (start_after)
+    _dbus_type_writer_set_enabled (writer, FALSE);
+
+  if (!writer_write_reader_helper (writer, reader, start_after,
+                                   start_after_new_pos,
+                                   start_after_new_len,
+                                   fixups, FALSE))
+    goto oom;
+
+  _dbus_type_writer_set_enabled (writer, orig_enabled);
+  return TRUE;
+
+ oom:
+  if (!writer->type_pos_is_expectation)
+    {
+      new_bytes = _dbus_string_get_length (writer->type_str) - orig_type_len;
+      _dbus_string_delete (writer->type_str, orig.type_pos, new_bytes);
+    }
+  new_bytes = _dbus_string_get_length (writer->value_str) - orig_value_len;
+  _dbus_string_delete (writer->value_str, orig.value_pos, new_bytes);
+
+  *writer = orig;
+
+  return FALSE;
+}
+
+/**
+ * Iterate through all values in the given reader, writing a copy of
+ * each value to the writer.  The reader will be moved forward to its
+ * end position.
+ *
+ * @param writer the writer to copy to
+ * @param reader the reader to copy from
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_type_writer_write_reader (DBusTypeWriter       *writer,
+                                DBusTypeReader       *reader)
+{
+  return _dbus_type_writer_write_reader_partial (writer, reader, NULL, 0, 0, NULL);
+}
+
+/*
+ * If disabled, a writer can still be iterated forward and recursed/unrecursed
+ * but won't write any values. Types will still be written unless the
+ * writer is a "values only" writer, because the writer needs access to
+ * a valid signature to be able to iterate.
+ *
+ * @param writer the type writer
+ * @param enabled #TRUE if values should be written
+ */
+static void
+_dbus_type_writer_set_enabled (DBusTypeWriter   *writer,
+                               dbus_bool_t       enabled)
+{
+  writer->enabled = enabled != FALSE;
+}
+
+/** @} */ /* end of DBusMarshal group */
+
+/* tests in dbus-marshal-recursive-util.c */
diff --git a/dbus/dbus/dbus-marshal-recursive.h b/dbus/dbus/dbus-marshal-recursive.h
new file mode 100644
index 0000000..acbfd73
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-recursive.h
@@ -0,0 +1,181 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-recursive.h  Marshalling routines for recursive types
+ *
+ * Copyright (C) 2004, 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef DBUS_MARSHAL_RECURSIVE_H
+#define DBUS_MARSHAL_RECURSIVE_H
+
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-list.h>
+
+typedef struct DBusTypeReader      DBusTypeReader;
+typedef struct DBusTypeWriter      DBusTypeWriter;
+typedef struct DBusTypeReaderClass DBusTypeReaderClass;
+typedef struct DBusArrayLenFixup   DBusArrayLenFixup;
+
+/**
+ * The type reader is an iterator for reading values from a block of
+ * values.
+ */
+struct DBusTypeReader
+{
+  dbus_uint32_t byte_order : 8; /**< byte order of the block */
+
+  dbus_uint32_t finished : 1;   /**< marks we're at end iterator for cases
+                                 * where we don't have another way to tell
+                                 */
+  dbus_uint32_t array_len_offset : 3; /**< bytes back from start_pos that len ends */
+  const DBusString *type_str;   /**< string containing signature of block */
+  int type_pos;                 /**< current position in signature */
+  const DBusString *value_str;  /**< string containing values of block */
+  int value_pos;                /**< current position in values */
+
+  const DBusTypeReaderClass *klass; /**< the vtable for the reader */
+  union
+  {
+    struct {
+      int start_pos;                /**< for array readers, the start of the array values */
+    } array;
+  } u; /**< class-specific data */
+};
+
+/**
+ * The type writer is an iterator for writing to a block of values.
+ */
+struct DBusTypeWriter
+{
+  dbus_uint32_t byte_order : 8;            /**< byte order to write values with */
+
+  dbus_uint32_t container_type : 8;        /**< what are we inside? (e.g. struct, variant, array) */
+
+  dbus_uint32_t type_pos_is_expectation : 1; /**< type_pos can be either an insertion point for or an expected next type */
+
+  dbus_uint32_t enabled : 1; /**< whether to write values */
+
+  DBusString *type_str; /**< where to write typecodes (or read type expectations) */
+  int type_pos;         /**< current pos in type_str */
+  DBusString *value_str; /**< where to write values */
+  int value_pos;         /**< next position to write */
+
+  union
+  {
+    struct {
+      int start_pos; /**< position of first element in the array */
+      int len_pos;   /**< position of length of the array */
+      int element_type_pos; /**< position of array element type in type_str */
+    } array;
+  } u; /**< class-specific data */
+};
+
+/**
+ * When modifying an existing block of values, array lengths may need
+ * to be adjusted; those adjustments are described by this struct.
+ */
+struct DBusArrayLenFixup
+{
+  int len_pos_in_reader; /**< where the length was in the original block */
+  int new_len;           /**< the new value of the length in the written-out block */
+};
+
+void        _dbus_type_reader_init                      (DBusTypeReader        *reader,
+                                                         int                    byte_order,
+                                                         const DBusString      *type_str,
+                                                         int                    type_pos,
+                                                         const DBusString      *value_str,
+                                                         int                    value_pos);
+void        _dbus_type_reader_init_types_only           (DBusTypeReader        *reader,
+                                                         const DBusString      *type_str,
+                                                         int                    type_pos);
+int         _dbus_type_reader_get_current_type          (const DBusTypeReader  *reader);
+int         _dbus_type_reader_get_element_type          (const DBusTypeReader  *reader);
+int         _dbus_type_reader_get_value_pos             (const DBusTypeReader  *reader);
+void        _dbus_type_reader_read_basic                (const DBusTypeReader  *reader,
+                                                         void                  *value);
+int         _dbus_type_reader_get_array_length          (const DBusTypeReader  *reader);
+void        _dbus_type_reader_read_fixed_multi          (const DBusTypeReader  *reader,
+                                                         void                  *value,
+                                                         int                   *n_elements);
+void        _dbus_type_reader_read_raw                  (const DBusTypeReader  *reader,
+                                                         const unsigned char  **value_location);
+void        _dbus_type_reader_recurse                   (DBusTypeReader        *reader,
+                                                         DBusTypeReader        *subreader);
+dbus_bool_t _dbus_type_reader_next                      (DBusTypeReader        *reader);
+dbus_bool_t _dbus_type_reader_has_next                  (const DBusTypeReader  *reader);
+void        _dbus_type_reader_get_signature             (const DBusTypeReader  *reader,
+                                                         const DBusString     **str_p,
+                                                         int                   *start_p,
+                                                         int                   *len_p);
+dbus_bool_t _dbus_type_reader_set_basic                 (DBusTypeReader        *reader,
+                                                         const void            *value,
+                                                         const DBusTypeReader  *realign_root);
+dbus_bool_t _dbus_type_reader_delete                    (DBusTypeReader        *reader,
+                                                         const DBusTypeReader  *realign_root);
+
+dbus_bool_t _dbus_type_reader_equal_values              (const DBusTypeReader *lhs,
+                                                         const DBusTypeReader *rhs);
+
+void        _dbus_type_signature_next                   (const char            *signature,
+							 int                   *type_pos);
+
+void        _dbus_type_writer_init                 (DBusTypeWriter        *writer,
+                                                    int                    byte_order,
+                                                    DBusString            *type_str,
+                                                    int                    type_pos,
+                                                    DBusString            *value_str,
+                                                    int                    value_pos);
+void        _dbus_type_writer_init_types_delayed   (DBusTypeWriter        *writer,
+                                                    int                    byte_order,
+                                                    DBusString            *value_str,
+                                                    int                    value_pos);
+void        _dbus_type_writer_add_types            (DBusTypeWriter        *writer,
+                                                    DBusString            *type_str,
+                                                    int                    type_pos);
+void        _dbus_type_writer_remove_types         (DBusTypeWriter        *writer);
+void        _dbus_type_writer_init_values_only     (DBusTypeWriter        *writer,
+                                                    int                    byte_order,
+                                                    const DBusString      *type_str,
+                                                    int                    type_pos,
+                                                    DBusString            *value_str,
+                                                    int                    value_pos);
+dbus_bool_t _dbus_type_writer_write_basic          (DBusTypeWriter        *writer,
+                                                    int                    type,
+                                                    const void            *value);
+dbus_bool_t _dbus_type_writer_write_fixed_multi    (DBusTypeWriter        *writer,
+                                                    int                    element_type,
+                                                    const void            *value,
+                                                    int                    n_elements);
+dbus_bool_t _dbus_type_writer_recurse              (DBusTypeWriter        *writer,
+                                                    int                    container_type,
+                                                    const DBusString      *contained_type,
+                                                    int                    contained_type_start,
+                                                    DBusTypeWriter        *sub);
+dbus_bool_t _dbus_type_writer_unrecurse            (DBusTypeWriter        *writer,
+                                                    DBusTypeWriter        *sub);
+dbus_bool_t _dbus_type_writer_append_array         (DBusTypeWriter        *writer,
+                                                    const DBusString      *contained_type,
+                                                    int                    contained_type_start,
+                                                    DBusTypeWriter        *sub);
+dbus_bool_t _dbus_type_writer_write_reader         (DBusTypeWriter        *writer,
+                                                    DBusTypeReader        *reader);
+
+
+#endif /* DBUS_MARSHAL_RECURSIVE_H */
diff --git a/dbus/dbus/dbus-marshal-validate-util.c b/dbus/dbus/dbus-marshal-validate-util.c
new file mode 100644
index 0000000..81135bc
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-validate-util.c
@@ -0,0 +1,588 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-validate-util.c Would be in dbus-marshal-validate.c, but only used by tests/bus
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#ifdef DBUS_BUILD_TESTS
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include "dbus-internals.h"
+#include "dbus-marshal-validate.h"
+#include "dbus-marshal-recursive.h"
+
+#include "dbus-test.h"
+#include <stdio.h>
+
+typedef struct
+{
+  const char *data;
+  DBusValidity expected;
+} ValidityTest;
+
+static void
+run_validity_tests (const ValidityTest *tests,
+                    int                 n_tests,
+                    DBusValidity (* func) (const DBusString*,int,int))
+{
+  int i;
+
+  for (i = 0; i < n_tests; i++)
+    {
+      DBusString str;
+      DBusValidity v;
+
+      _dbus_string_init_const (&str, tests[i].data);
+
+      v = (*func) (&str, 0, _dbus_string_get_length (&str));
+
+      if (v != tests[i].expected)
+        {
+          _dbus_warn ("Improper validation result %d for '%s'\n",
+                      v, tests[i].data);
+          _dbus_assert_not_reached ("test failed");
+        }
+
+      ++i;
+    }
+}
+
+static const ValidityTest signature_tests[] = {
+  { "", DBUS_VALID },
+  { "i", DBUS_VALID },
+  { "ai", DBUS_VALID },
+  { "(i)", DBUS_VALID },
+  { "w", DBUS_INVALID_UNKNOWN_TYPECODE },
+  { "a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
+  { "aaaaaa", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
+  { "ii(ii)a", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
+  { "ia", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
+  /* DBUS_INVALID_SIGNATURE_TOO_LONG, */ /* too hard to test this way */
+  { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+    DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION },
+  { "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((ii))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))",
+    DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION },
+  { ")", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
+  { "i)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
+  { "a)", DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED },
+  { "(", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
+  { "(i", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
+  { "(iiiii", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
+  { "(ai", DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED },
+  { "()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
+  { "(())", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
+  { "a()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
+  { "i()", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
+  { "()i", DBUS_INVALID_STRUCT_HAS_NO_FIELDS },
+  { "(a)", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
+  { "a{ia}", DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE },
+  { "a{}", DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS },
+  { "a{aii}", DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE },
+  /* { "a{i}", DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD }, */
+  /* { "{is}", DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY }, */
+  /* { "a{isi}", DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS }, */
+};
+
+dbus_bool_t
+_dbus_marshal_validate_test (void)
+{
+  DBusString str;
+  int i;
+
+  const char *valid_paths[] = {
+    "/",
+    "/foo/bar",
+    "/foo",
+    "/foo/bar/baz"
+  };
+  const char *invalid_paths[] = {
+    "bar",
+    "bar/baz",
+    "/foo/bar/",
+    "/foo/"
+    "foo/",
+    "boo//blah",
+    "//",
+    "///",
+    "foo///blah/",
+    "Hello World",
+    "",
+    "   ",
+    "foo bar"
+  };
+
+  const char *valid_interfaces[] = {
+    "org.freedesktop.Foo",
+    "Bar.Baz",
+    "Blah.Blah.Blah.Blah.Blah",
+    "a.b",
+    "a.b.c.d.e.f.g",
+    "a0.b1.c2.d3.e4.f5.g6",
+    "abc123.foo27"
+  };
+  const char *invalid_interfaces[] = {
+    ".",
+    "",
+    "..",
+    ".Foo.Bar",
+    "..Foo.Bar",
+    "Foo.Bar.",
+    "Foo.Bar..",
+    "Foo",
+    "9foo.bar.baz",
+    "foo.bar..baz",
+    "foo.bar...baz",
+    "foo.bar.b..blah",
+    ":",
+    ":0-1",
+    "10",
+    ":11.34324",
+    "0.0.0",
+    "0..0",
+    "foo.Bar.%",
+    "foo.Bar!!",
+    "!Foo.bar.bz",
+    "foo.$.blah",
+    "",
+    "   ",
+    "foo bar"
+  };
+
+  const char *valid_unique_names[] = {
+    ":0",
+    ":a",
+    ":",
+    ":.a",
+    ":.1",
+    ":0.1",
+    ":000.2222",
+    ":.blah",
+    ":abce.freedesktop.blah"
+  };
+  const char *invalid_unique_names[] = {
+    //":-",
+    ":!",
+    //":0-10",
+    ":blah.",
+    ":blah.",
+    ":blah..org",
+    ":blah.org..",
+    ":..blah.org",
+    "",
+    "   ",
+    "foo bar"
+  };
+
+  const char *valid_members[] = {
+    "Hello",
+    "Bar",
+    "foobar",
+    "_foobar",
+    "foo89"
+  };
+
+  const char *invalid_members[] = {
+    "9Hello",
+    "10",
+    "1",
+    "foo-bar",
+    "blah.org",
+    ".blah",
+    "blah.",
+    "Hello.",
+    "!foo",
+    "",
+    "   ",
+    "foo bar"
+  };
+
+  const char *valid_signatures[] = {
+    "",
+    "sss",
+    "i",
+    "b"
+  };
+
+  const char *invalid_signatures[] = {
+    " ",
+    "not a valid signature",
+    "123",
+    ".",
+    "(",
+    "a{(ii)i}" /* https://bugs.freedesktop.org/show_bug.cgi?id=17803 */
+  };
+
+  /* Signature with reason */
+
+  run_validity_tests (signature_tests, _DBUS_N_ELEMENTS (signature_tests),
+                      _dbus_validate_signature_with_reason);
+
+  /* Path validation */
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
+    {
+      _dbus_string_init_const (&str, valid_paths[i]);
+
+      if (!_dbus_validate_path (&str, 0,
+                                _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
+          _dbus_assert_not_reached ("invalid path");
+        }
+
+      ++i;
+    }
+
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
+    {
+      _dbus_string_init_const (&str, invalid_paths[i]);
+
+      if (_dbus_validate_path (&str, 0,
+                               _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
+          _dbus_assert_not_reached ("valid path");
+        }
+
+      ++i;
+    }
+
+  /* Interface validation */
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
+    {
+      _dbus_string_init_const (&str, valid_interfaces[i]);
+
+      if (!_dbus_validate_interface (&str, 0,
+                                     _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
+          _dbus_assert_not_reached ("invalid interface");
+        }
+
+      ++i;
+    }
+
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
+    {
+      _dbus_string_init_const (&str, invalid_interfaces[i]);
+
+      if (_dbus_validate_interface (&str, 0,
+                                    _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
+          _dbus_assert_not_reached ("valid interface");
+        }
+
+      ++i;
+    }
+
+  /* Bus name validation (check that valid interfaces are valid bus names,
+   * and invalid interfaces are invalid services except if they start with ':')
+   */
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
+    {
+      _dbus_string_init_const (&str, valid_interfaces[i]);
+
+      if (!_dbus_validate_bus_name (&str, 0,
+                                   _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_interfaces[i]);
+          _dbus_assert_not_reached ("invalid bus name");
+        }
+
+      ++i;
+    }
+
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
+    {
+      if (invalid_interfaces[i][0] != ':')
+        {
+          _dbus_string_init_const (&str, invalid_interfaces[i]);
+
+          if (_dbus_validate_bus_name (&str, 0,
+                                       _dbus_string_get_length (&str)))
+            {
+              _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_interfaces[i]);
+              _dbus_assert_not_reached ("valid bus name");
+            }
+        }
+
+      ++i;
+    }
+
+  /* unique name validation */
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (valid_unique_names))
+    {
+      _dbus_string_init_const (&str, valid_unique_names[i]);
+
+      if (!_dbus_validate_bus_name (&str, 0,
+                                    _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Bus name \"%s\" should have been valid\n", valid_unique_names[i]);
+          _dbus_assert_not_reached ("invalid unique name");
+        }
+
+      ++i;
+    }
+
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (invalid_unique_names))
+    {
+      _dbus_string_init_const (&str, invalid_unique_names[i]);
+
+      if (_dbus_validate_bus_name (&str, 0,
+                                   _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Bus name \"%s\" should have been invalid\n", invalid_unique_names[i]);
+          _dbus_assert_not_reached ("valid unique name");
+        }
+
+      ++i;
+    }
+
+
+  /* Error name validation (currently identical to interfaces)
+   */
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
+    {
+      _dbus_string_init_const (&str, valid_interfaces[i]);
+
+      if (!_dbus_validate_error_name (&str, 0,
+                                      _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
+          _dbus_assert_not_reached ("invalid error name");
+        }
+
+      ++i;
+    }
+
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
+    {
+      if (invalid_interfaces[i][0] != ':')
+        {
+          _dbus_string_init_const (&str, invalid_interfaces[i]);
+
+          if (_dbus_validate_error_name (&str, 0,
+                                         _dbus_string_get_length (&str)))
+            {
+              _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
+              _dbus_assert_not_reached ("valid error name");
+            }
+        }
+
+      ++i;
+    }
+
+  /* Member validation */
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (valid_members))
+    {
+      _dbus_string_init_const (&str, valid_members[i]);
+
+      if (!_dbus_validate_member (&str, 0,
+                                  _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
+          _dbus_assert_not_reached ("invalid member");
+        }
+
+      ++i;
+    }
+
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
+    {
+      _dbus_string_init_const (&str, invalid_members[i]);
+
+      if (_dbus_validate_member (&str, 0,
+                                 _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
+          _dbus_assert_not_reached ("valid member");
+        }
+
+      ++i;
+    }
+
+  /* Signature validation */
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (valid_signatures))
+    {
+      _dbus_string_init_const (&str, valid_signatures[i]);
+
+      if (!_dbus_validate_signature (&str, 0,
+                                     _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]);
+          _dbus_assert_not_reached ("invalid signature");
+        }
+
+      ++i;
+    }
+
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures))
+    {
+      _dbus_string_init_const (&str, invalid_signatures[i]);
+
+      if (_dbus_validate_signature (&str, 0,
+                                    _dbus_string_get_length (&str)))
+        {
+          _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]);
+          _dbus_assert_not_reached ("valid signature");
+        }
+
+      ++i;
+    }
+
+  /* Validate claimed length longer than real length */
+  _dbus_string_init_const (&str, "abc.efg");
+  if (_dbus_validate_bus_name (&str, 0, 8))
+    _dbus_assert_not_reached ("validated too-long string");
+  if (_dbus_validate_interface (&str, 0, 8))
+    _dbus_assert_not_reached ("validated too-long string");
+  if (_dbus_validate_error_name (&str, 0, 8))
+    _dbus_assert_not_reached ("validated too-long string");
+
+  _dbus_string_init_const (&str, "abc");
+  if (_dbus_validate_member (&str, 0, 4))
+    _dbus_assert_not_reached ("validated too-long string");
+
+  _dbus_string_init_const (&str, "sss");
+  if (_dbus_validate_signature (&str, 0, 4))
+    _dbus_assert_not_reached ("validated too-long signature");
+
+  /* Validate string exceeding max name length */
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("no memory");
+
+  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
+    if (!_dbus_string_append (&str, "abc.def"))
+      _dbus_assert_not_reached ("no memory");
+
+  if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
+    _dbus_assert_not_reached ("validated overmax string");
+  if (_dbus_validate_interface (&str, 0, _dbus_string_get_length (&str)))
+    _dbus_assert_not_reached ("validated overmax string");
+  if (_dbus_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
+    _dbus_assert_not_reached ("validated overmax string");
+
+  /* overlong member */
+  _dbus_string_set_length (&str, 0);
+  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
+    if (!_dbus_string_append (&str, "abc"))
+      _dbus_assert_not_reached ("no memory");
+
+  if (_dbus_validate_member (&str, 0, _dbus_string_get_length (&str)))
+    _dbus_assert_not_reached ("validated overmax string");
+
+  /* overlong unique name */
+  _dbus_string_set_length (&str, 0);
+  _dbus_string_append (&str, ":");
+  while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
+    if (!_dbus_string_append (&str, "abc"))
+      _dbus_assert_not_reached ("no memory");
+
+  if (_dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str)))
+    _dbus_assert_not_reached ("validated overmax string");
+
+  _dbus_string_free (&str);
+
+  /* Body validation; test basic validation of valid bodies for both endian */
+  
+  {
+    int sequence;
+    DBusString signature;
+    DBusString body;
+
+    if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
+      _dbus_assert_not_reached ("oom");
+
+    sequence = 0;
+    while (dbus_internal_do_not_use_generate_bodies (sequence,
+                                                     DBUS_LITTLE_ENDIAN,
+                                                     &signature, &body))
+      {
+        DBusValidity validity;
+
+        validity = _dbus_validate_body_with_reason (&signature, 0,
+                                                    DBUS_LITTLE_ENDIAN,
+                                                    NULL, &body, 0,
+                                                    _dbus_string_get_length (&body));
+        if (validity != DBUS_VALID)
+          {
+            _dbus_warn ("invalid code %d expected valid on sequence %d little endian\n",
+                        validity, sequence);
+            _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
+            _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
+            _dbus_assert_not_reached ("test failed");
+          }
+
+        _dbus_string_set_length (&signature, 0);
+        _dbus_string_set_length (&body, 0);
+        ++sequence;
+      }
+                                                     
+    sequence = 0;
+    while (dbus_internal_do_not_use_generate_bodies (sequence,
+                                                     DBUS_BIG_ENDIAN,
+                                                     &signature, &body))
+      {
+        DBusValidity validity;
+
+        validity = _dbus_validate_body_with_reason (&signature, 0,
+                                                    DBUS_BIG_ENDIAN,
+                                                    NULL, &body, 0,
+                                                    _dbus_string_get_length (&body));
+        if (validity != DBUS_VALID)
+          {
+            _dbus_warn ("invalid code %d expected valid on sequence %d big endian\n",
+                        validity, sequence);
+            _dbus_verbose_bytes_of_string (&signature, 0, _dbus_string_get_length (&signature));
+            _dbus_verbose_bytes_of_string (&body, 0, _dbus_string_get_length (&body));
+            _dbus_assert_not_reached ("test failed");
+          }
+
+        _dbus_string_set_length (&signature, 0);
+        _dbus_string_set_length (&body, 0);
+        ++sequence;
+      }
+
+    _dbus_string_free (&signature);
+    _dbus_string_free (&body);
+  }
+  
+  return TRUE;
+}
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-marshal-validate.c b/dbus/dbus/dbus-marshal-validate.c
new file mode 100644
index 0000000..9187a3e
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-validate.c
@@ -0,0 +1,1259 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-validate.c Validation routines for marshaled data
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-marshal-validate.h"
+#include "dbus-marshal-recursive.h"
+#include "dbus-marshal-basic.h"
+#include "dbus-signature.h"
+#include "dbus-string.h"
+
+/**
+ * @addtogroup DBusMarshal
+ *
+ * @{
+ */
+
+/**
+ * Verifies that the range of type_str from type_pos to type_end is a
+ * valid signature.  If this function returns #TRUE, it will be safe
+ * to iterate over the signature with a types-only #DBusTypeReader.
+ * The range passed in should NOT include the terminating
+ * nul/DBUS_TYPE_INVALID.
+ *
+ * @param type_str the string
+ * @param type_pos where the typecodes start
+ * @param len length of typecodes
+ * @returns #DBUS_VALID if valid, reason why invalid otherwise
+ */
+DBusValidity
+_dbus_validate_signature_with_reason (const DBusString *type_str,
+                                      int               type_pos,
+                                      int               len)
+{
+  const unsigned char *p;
+  const unsigned char *end;
+  int last;
+  int struct_depth;
+  int array_depth;
+  int dict_entry_depth;
+  DBusValidity result;
+
+  int element_count;
+  DBusList *element_count_stack;
+
+  result = DBUS_VALID;
+  element_count_stack = NULL;
+
+  if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0)))
+    {
+      result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
+      goto out;
+    }
+
+  _dbus_assert (type_str != NULL);
+  _dbus_assert (type_pos < _DBUS_INT32_MAX - len);
+  _dbus_assert (len >= 0);
+  _dbus_assert (type_pos >= 0);
+
+  if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH)
+    {
+      result = DBUS_INVALID_SIGNATURE_TOO_LONG;
+      goto out;
+    }
+
+  p = _dbus_string_get_const_data_len (type_str, type_pos, 0);
+
+  end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0);
+  struct_depth = 0;
+  array_depth = 0;
+  dict_entry_depth = 0;
+  last = DBUS_TYPE_INVALID;
+
+  while (p != end)
+    {
+      switch (*p)
+        {
+        case DBUS_TYPE_BYTE:
+        case DBUS_TYPE_BOOLEAN:
+        case DBUS_TYPE_INT16:
+        case DBUS_TYPE_UINT16:
+        case DBUS_TYPE_INT32:
+        case DBUS_TYPE_UINT32:
+        case DBUS_TYPE_UNIX_FD:
+        case DBUS_TYPE_INT64:
+        case DBUS_TYPE_UINT64:
+        case DBUS_TYPE_DOUBLE:
+        case DBUS_TYPE_STRING:
+        case DBUS_TYPE_OBJECT_PATH:
+        case DBUS_TYPE_SIGNATURE:
+        case DBUS_TYPE_VARIANT:
+          break;
+
+        case DBUS_TYPE_ARRAY:
+          array_depth += 1;
+          if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
+            {
+              result = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
+              goto out;
+            }
+          break;
+
+        case DBUS_STRUCT_BEGIN_CHAR:
+          struct_depth += 1;
+
+          if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
+            {
+              result = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
+              goto out;
+            }
+          
+          if (!_dbus_list_append (&element_count_stack, 
+                             _DBUS_INT_TO_POINTER (0)))
+            {
+              result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
+              goto out;
+            }
+
+          break;
+
+        case DBUS_STRUCT_END_CHAR:
+          if (struct_depth == 0)
+            {
+              result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
+              goto out;
+            }
+
+          if (last == DBUS_STRUCT_BEGIN_CHAR)
+            {
+              result = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
+              goto out;
+            }
+
+          _dbus_list_pop_last (&element_count_stack);
+
+          struct_depth -= 1;
+          break;
+
+        case DBUS_DICT_ENTRY_BEGIN_CHAR:
+          if (last != DBUS_TYPE_ARRAY)
+            {
+              result = DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY;
+              goto out;
+            }
+            
+          dict_entry_depth += 1;
+
+          if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
+            {
+              result = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
+              goto out;
+            }
+
+          if (!_dbus_list_append (&element_count_stack, 
+                             _DBUS_INT_TO_POINTER (0)))
+            {
+              result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
+              goto out;
+            }
+
+          break;
+
+        case DBUS_DICT_ENTRY_END_CHAR:
+          if (dict_entry_depth == 0)
+            {
+              result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
+              goto out;
+            }
+            
+          dict_entry_depth -= 1;
+
+          element_count = 
+            _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack));
+
+          if (element_count != 2)
+            {
+              if (element_count == 0)
+                result = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
+              else if (element_count == 1)
+                result = DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD;
+              else
+                result = DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS;
+              
+              goto out;
+            }
+          break;
+          
+        case DBUS_TYPE_STRUCT:     /* doesn't appear in signatures */
+        case DBUS_TYPE_DICT_ENTRY: /* ditto */
+        default:
+          result = DBUS_INVALID_UNKNOWN_TYPECODE;
+	  goto out;
+        }
+
+      if (*p != DBUS_TYPE_ARRAY && 
+          *p != DBUS_DICT_ENTRY_BEGIN_CHAR && 
+	  *p != DBUS_STRUCT_BEGIN_CHAR) 
+        {
+          element_count = 
+            _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack));
+
+          ++element_count;
+
+          if (!_dbus_list_append (&element_count_stack, 
+                             _DBUS_INT_TO_POINTER (element_count)))
+            {
+              result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
+              goto out;
+            }
+        }
+      
+      if (array_depth > 0)
+        {
+          if (*p == DBUS_TYPE_ARRAY && p != end)
+            {
+	       const char *p1;
+	       p1 = p + 1;
+               if (*p1 == DBUS_STRUCT_END_CHAR ||
+                   *p1 == DBUS_DICT_ENTRY_END_CHAR)
+                 {
+                   result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
+                   goto out;
+                 }
+            }
+          else
+	    {
+              array_depth = 0;
+	    }
+        }
+
+      if (last == DBUS_DICT_ENTRY_BEGIN_CHAR)
+        {
+          if (!(dbus_type_is_valid (*p) && dbus_type_is_basic (*p)))
+            {
+              result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE;
+              goto out;
+            }
+        }
+
+      last = *p;
+      ++p;
+    }
+
+
+  if (array_depth > 0)
+    {
+      result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
+      goto out;
+    }
+    
+  if (struct_depth > 0)
+    {
+       result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
+       goto out;
+    }
+    
+  if (dict_entry_depth > 0)
+    {
+      result =  DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
+      goto out;
+    }
+    
+  _dbus_assert (last != DBUS_TYPE_ARRAY);
+  _dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR);
+  _dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR);
+
+  result = DBUS_VALID;
+
+out:
+  _dbus_list_clear (&element_count_stack);
+  return result;
+}
+
+/* note: this function is also used to validate the header's values,
+ * since the header is a valid body with a particular signature.
+ */
+static DBusValidity
+validate_body_helper (DBusTypeReader       *reader,
+                      int                   byte_order,
+                      dbus_bool_t           walk_reader_to_end,
+                      int                   total_depth,
+                      const unsigned char  *p,
+                      const unsigned char  *end,
+                      const unsigned char **new_p)
+{
+  int current_type;
+
+  /* The spec allows arrays and structs to each nest 32, for total
+   * nesting of 2*32. We want to impose the same limit on "dynamic"
+   * value nesting (not visible in the signature) which is introduced
+   * by DBUS_TYPE_VARIANT.
+   */
+  if (total_depth > (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH * 2))
+    {
+      return DBUS_INVALID_NESTED_TOO_DEEPLY;
+    }
+
+  while ((current_type = _dbus_type_reader_get_current_type (reader)) != DBUS_TYPE_INVALID)
+    {
+      const unsigned char *a;
+      int alignment;
+
+#if 0
+      _dbus_verbose ("   validating value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
+                     _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
+                     (int) (end - p));
+#endif
+
+      /* Guarantee that p has one byte to look at */
+      if (p == end)
+        return DBUS_INVALID_NOT_ENOUGH_DATA;
+
+      switch (current_type)
+        {
+        case DBUS_TYPE_BYTE:
+          ++p;
+          break;
+
+        case DBUS_TYPE_BOOLEAN:
+        case DBUS_TYPE_INT16:
+        case DBUS_TYPE_UINT16:
+        case DBUS_TYPE_INT32:
+        case DBUS_TYPE_UINT32:
+        case DBUS_TYPE_UNIX_FD:
+        case DBUS_TYPE_INT64:
+        case DBUS_TYPE_UINT64:
+        case DBUS_TYPE_DOUBLE:
+          alignment = _dbus_type_get_alignment (current_type);
+          a = _DBUS_ALIGN_ADDRESS (p, alignment);
+          if (a >= end)
+            return DBUS_INVALID_NOT_ENOUGH_DATA;
+          while (p != a)
+            {
+              if (*p != '\0')
+                return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
+              ++p;
+            }
+          
+          if (current_type == DBUS_TYPE_BOOLEAN)
+            {
+              dbus_uint32_t v = _dbus_unpack_uint32 (byte_order,
+                                                     p);
+              if (!(v == 0 || v == 1))
+                return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
+            }
+          
+          p += alignment;
+          break;
+
+        case DBUS_TYPE_ARRAY:
+        case DBUS_TYPE_STRING:
+        case DBUS_TYPE_OBJECT_PATH:
+          {
+            dbus_uint32_t claimed_len;
+
+            a = _DBUS_ALIGN_ADDRESS (p, 4);
+            if (a + 4 > end)
+              return DBUS_INVALID_NOT_ENOUGH_DATA;
+            while (p != a)
+              {
+                if (*p != '\0')
+                  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
+                ++p;
+              }
+
+            claimed_len = _dbus_unpack_uint32 (byte_order, p);
+            p += 4;
+
+            /* p may now be == end */
+            _dbus_assert (p <= end);
+
+            if (current_type == DBUS_TYPE_ARRAY)
+              {
+                int array_elem_type = _dbus_type_reader_get_element_type (reader);
+
+                if (!dbus_type_is_valid (array_elem_type))
+                  {
+                    return DBUS_INVALID_UNKNOWN_TYPECODE;
+                  }
+
+                alignment = _dbus_type_get_alignment (array_elem_type);
+
+                a = _DBUS_ALIGN_ADDRESS (p, alignment);
+
+                /* a may now be == end */
+                if (a > end)
+                  return DBUS_INVALID_NOT_ENOUGH_DATA;
+
+                while (p != a)
+                  {
+                    if (*p != '\0')
+                      return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
+                    ++p;
+                  }
+              }
+
+            if (claimed_len > (unsigned long) (end - p))
+              return DBUS_INVALID_LENGTH_OUT_OF_BOUNDS;
+
+            if (current_type == DBUS_TYPE_OBJECT_PATH)
+              {
+                DBusString str;
+                _dbus_string_init_const_len (&str, p, claimed_len);
+                if (!_dbus_validate_path (&str, 0,
+                                          _dbus_string_get_length (&str)))
+                  return DBUS_INVALID_BAD_PATH;
+
+                p += claimed_len;
+              }
+            else if (current_type == DBUS_TYPE_STRING)
+              {
+                DBusString str;
+                _dbus_string_init_const_len (&str, p, claimed_len);
+                if (!_dbus_string_validate_utf8 (&str, 0,
+                                                 _dbus_string_get_length (&str)))
+                  return DBUS_INVALID_BAD_UTF8_IN_STRING;
+
+                p += claimed_len;
+              }
+            else if (current_type == DBUS_TYPE_ARRAY && claimed_len > 0)
+              {
+                DBusTypeReader sub;
+                DBusValidity validity;
+                const unsigned char *array_end;
+                int array_elem_type;
+
+                if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH)
+                  return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM;
+                
+                /* Remember that the reader is types only, so we can't
+                 * use it to iterate over elements. It stays the same
+                 * for all elements.
+                 */
+                _dbus_type_reader_recurse (reader, &sub);
+
+                array_end = p + claimed_len;
+
+                array_elem_type = _dbus_type_reader_get_element_type (reader);
+
+                /* avoid recursive call to validate_body_helper if this is an array
+                 * of fixed-size elements
+                 */ 
+                if (dbus_type_is_fixed (array_elem_type))
+                  {
+                    /* bools need to be handled differently, because they can
+                     * have an invalid value
+                     */
+                    if (array_elem_type == DBUS_TYPE_BOOLEAN)
+                      {
+                        dbus_uint32_t v;
+                        alignment = _dbus_type_get_alignment (array_elem_type);
+
+                        while (p < array_end)
+                          {
+                            v = _dbus_unpack_uint32 (byte_order, p);
+
+                            if (!(v == 0 || v == 1))
+                              return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
+
+                            p += alignment;
+                          }
+                      }
+
+                    else
+                      {
+                        p = array_end;
+                      }
+                  }
+
+                else
+                  {
+                    while (p < array_end)
+                      {
+                        validity = validate_body_helper (&sub, byte_order, FALSE,
+                                                         total_depth + 1,
+                                                         p, end, &p);
+                        if (validity != DBUS_VALID)
+                          return validity;
+                      }
+                  }
+
+                if (p != array_end)
+                  return DBUS_INVALID_ARRAY_LENGTH_INCORRECT;
+              }
+
+            /* check nul termination */
+            if (current_type != DBUS_TYPE_ARRAY)
+              {
+                if (p == end)
+                  return DBUS_INVALID_NOT_ENOUGH_DATA;
+
+                if (*p != '\0')
+                  return DBUS_INVALID_STRING_MISSING_NUL;
+                ++p;
+              }
+          }
+          break;
+
+        case DBUS_TYPE_SIGNATURE:
+          {
+            dbus_uint32_t claimed_len;
+            DBusString str;
+            DBusValidity validity;
+
+            claimed_len = *p;
+            ++p;
+
+            /* 1 is for nul termination */
+            if (claimed_len + 1 > (unsigned long) (end - p))
+              return DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
+
+            _dbus_string_init_const_len (&str, p, claimed_len);
+            validity =
+              _dbus_validate_signature_with_reason (&str, 0,
+                                                    _dbus_string_get_length (&str));
+
+            if (validity != DBUS_VALID)
+              return validity;
+
+            p += claimed_len;
+
+            _dbus_assert (p < end);
+            if (*p != DBUS_TYPE_INVALID)
+              return DBUS_INVALID_SIGNATURE_MISSING_NUL;
+
+            ++p;
+
+            _dbus_verbose ("p = %p end = %p claimed_len %u\n", p, end, claimed_len);
+          }
+          break;
+
+        case DBUS_TYPE_VARIANT:
+          {
+            /* 1 byte sig len, sig typecodes, align to
+             * contained-type-boundary, values.
+             */
+
+            /* In addition to normal signature validation, we need to be sure
+             * the signature contains only a single (possibly container) type.
+             */
+            dbus_uint32_t claimed_len;
+            DBusString sig;
+            DBusTypeReader sub;
+            DBusValidity validity;
+            int contained_alignment;
+            int contained_type;
+            DBusValidity reason;
+
+            claimed_len = *p;
+            ++p;
+
+            /* + 1 for nul */
+            if (claimed_len + 1 > (unsigned long) (end - p))
+              return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
+
+            _dbus_string_init_const_len (&sig, p, claimed_len);
+            reason = _dbus_validate_signature_with_reason (&sig, 0,
+                                           _dbus_string_get_length (&sig));
+            if (!(reason == DBUS_VALID))
+              {
+                if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
+                  return reason;
+                else 
+                  return DBUS_INVALID_VARIANT_SIGNATURE_BAD;
+              }
+
+            p += claimed_len;
+            
+            if (*p != DBUS_TYPE_INVALID)
+              return DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL;
+            ++p;
+
+            contained_type = _dbus_first_type_in_signature (&sig, 0);
+            if (contained_type == DBUS_TYPE_INVALID)
+              return DBUS_INVALID_VARIANT_SIGNATURE_EMPTY;
+            
+            contained_alignment = _dbus_type_get_alignment (contained_type);
+            
+            a = _DBUS_ALIGN_ADDRESS (p, contained_alignment);
+            if (a > end)
+              return DBUS_INVALID_NOT_ENOUGH_DATA;
+            while (p != a)
+              {
+                if (*p != '\0')
+                  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
+                ++p;
+              }
+
+            _dbus_type_reader_init_types_only (&sub, &sig, 0);
+
+            _dbus_assert (_dbus_type_reader_get_current_type (&sub) != DBUS_TYPE_INVALID);
+
+            validity = validate_body_helper (&sub, byte_order, FALSE,
+                                             total_depth + 1,
+                                             p, end, &p);
+            if (validity != DBUS_VALID)
+              return validity;
+
+            if (_dbus_type_reader_next (&sub))
+              return DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES;
+
+            _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_INVALID);
+          }
+          break;
+
+        case DBUS_TYPE_DICT_ENTRY:
+        case DBUS_TYPE_STRUCT:
+          {
+            DBusTypeReader sub;
+            DBusValidity validity;
+
+            a = _DBUS_ALIGN_ADDRESS (p, 8);
+            if (a > end)
+              return DBUS_INVALID_NOT_ENOUGH_DATA;
+            while (p != a)
+              {
+                if (*p != '\0')
+                  return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
+                ++p;
+              }
+
+            _dbus_type_reader_recurse (reader, &sub);
+
+            validity = validate_body_helper (&sub, byte_order, TRUE,
+                                             total_depth + 1,
+                                             p, end, &p);
+            if (validity != DBUS_VALID)
+              return validity;
+          }
+          break;
+
+        default:
+          _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
+          break;
+        }
+
+#if 0
+      _dbus_verbose ("   validated value of type %s type reader %p type_pos %d p %p end %p %d remain\n",
+                     _dbus_type_to_string (current_type), reader, reader->type_pos, p, end,
+                     (int) (end - p));
+#endif
+
+      if (p > end)
+        {
+          _dbus_verbose ("not enough data!!! p = %p end = %p end-p = %d\n",
+                         p, end, (int) (end - p));
+          return DBUS_INVALID_NOT_ENOUGH_DATA;
+        }
+
+      if (walk_reader_to_end)
+        _dbus_type_reader_next (reader);
+      else
+        break;
+    }
+
+  if (new_p)
+    *new_p = p;
+
+  return DBUS_VALID;
+}
+
+/**
+ * Verifies that the range of value_str from value_pos to value_end is
+ * a legitimate value of type expected_signature.  If this function
+ * returns #TRUE, it will be safe to iterate over the values with
+ * #DBusTypeReader. The signature is assumed to be already valid.
+ *
+ * If bytes_remaining is not #NULL, then leftover bytes will be stored
+ * there and #DBUS_VALID returned. If it is #NULL, then
+ * #DBUS_INVALID_TOO_MUCH_DATA will be returned if bytes are left
+ * over.
+ *
+ * @param expected_signature the expected types in the value_str
+ * @param expected_signature_start where in expected_signature is the signature
+ * @param byte_order the byte order
+ * @param bytes_remaining place to store leftover bytes
+ * @param value_str the string containing the body
+ * @param value_pos where the values start
+ * @param len length of values after value_pos
+ * @returns #DBUS_VALID if valid, reason why invalid otherwise
+ */
+DBusValidity
+_dbus_validate_body_with_reason (const DBusString *expected_signature,
+                                 int               expected_signature_start,
+                                 int               byte_order,
+                                 int              *bytes_remaining,
+                                 const DBusString *value_str,
+                                 int               value_pos,
+                                 int               len)
+{
+  DBusTypeReader reader;
+  const unsigned char *p;
+  const unsigned char *end;
+  DBusValidity validity;
+
+  _dbus_assert (len >= 0);
+  _dbus_assert (value_pos >= 0);
+  _dbus_assert (value_pos <= _dbus_string_get_length (value_str) - len);
+
+  _dbus_verbose ("validating body from pos %d len %d sig '%s'\n",
+                 value_pos, len, _dbus_string_get_const_data_len (expected_signature,
+                                                                  expected_signature_start,
+                                                                  0));
+
+  _dbus_type_reader_init_types_only (&reader,
+                                     expected_signature, expected_signature_start);
+
+  p = _dbus_string_get_const_data_len (value_str, value_pos, len);
+  end = p + len;
+
+  validity = validate_body_helper (&reader, byte_order, TRUE, 0, p, end, &p);
+  if (validity != DBUS_VALID)
+    return validity;
+  
+  if (bytes_remaining)
+    {
+      *bytes_remaining = end - p;
+      return DBUS_VALID;
+    }
+  else if (p < end)
+    return DBUS_INVALID_TOO_MUCH_DATA;
+  else
+    {
+      _dbus_assert (p == end);
+      return DBUS_VALID;
+    }
+}
+
+/**
+ * Determine wether the given character is valid as the first character
+ * in a name.
+ */
+#define VALID_INITIAL_NAME_CHARACTER(c)         \
+  ( ((c) >= 'A' && (c) <= 'Z') ||               \
+    ((c) >= 'a' && (c) <= 'z') ||               \
+    ((c) == '_') )
+
+/**
+ * Determine wether the given character is valid as a second or later
+ * character in a name
+ */
+#define VALID_NAME_CHARACTER(c)                 \
+  ( ((c) >= '0' && (c) <= '9') ||               \
+    ((c) >= 'A' && (c) <= 'Z') ||               \
+    ((c) >= 'a' && (c) <= 'z') ||               \
+    ((c) == '_') )
+
+/**
+ * Checks that the given range of the string is a valid object path
+ * name in the D-Bus protocol. Part of the validation ensures that
+ * the object path contains only ASCII.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @todo change spec to disallow more things, such as spaces in the
+ * path name
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_validate_path (const DBusString  *str,
+                     int                start,
+                     int                len)
+{
+  const unsigned char *s;
+  const unsigned char *end;
+  const unsigned char *last_slash;
+
+  _dbus_assert (start >= 0);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= _dbus_string_get_length (str));
+  
+  if (len > _dbus_string_get_length (str) - start)
+    return FALSE;
+
+  if (len == 0)
+    return FALSE;
+
+  s = _dbus_string_get_const_data (str) + start;
+  end = s + len;
+
+  if (*s != '/')
+    return FALSE;
+  last_slash = s;
+  ++s;
+
+  while (s != end)
+    {
+      if (*s == '/')
+        {
+          if ((s - last_slash) < 2)
+            return FALSE; /* no empty path components allowed */
+
+          last_slash = s;
+        }
+      else
+        {
+          if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
+            return FALSE;
+        }
+
+      ++s;
+    }
+
+  if ((end - last_slash) < 2 &&
+      len > 1)
+    return FALSE; /* trailing slash not allowed unless the string is "/" */
+
+  return TRUE;
+}
+
+const char *
+_dbus_validity_to_error_message (DBusValidity validity)
+{
+  switch (validity)
+    {
+    case DBUS_VALIDITY_UNKNOWN_OOM_ERROR:                          return "Out of memory";
+    case DBUS_INVALID_FOR_UNKNOWN_REASON:                          return "Unknown reason";
+    case DBUS_VALID_BUT_INCOMPLETE:                                return "Valid but incomplete";
+    case DBUS_VALIDITY_UNKNOWN:                                    return "Validity unknown";
+    case DBUS_VALID:                                               return "Valid";
+    case DBUS_INVALID_UNKNOWN_TYPECODE:                            return "Unknown typecode";
+    case DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE:                  return "Missing array element type";
+    case DBUS_INVALID_SIGNATURE_TOO_LONG:                          return "Signature is too long";
+    case DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION:            return "Exceeded maximum array recursion";
+    case DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION:           return "Exceeded maximum struct recursion";
+    case DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED:                return "Struct ended but not started";
+    case DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED:                return "Struct started but not ended";
+    case DBUS_INVALID_STRUCT_HAS_NO_FIELDS:                        return "Struct has no fields";
+    case DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL:                   return "Alignment padding not null";
+    case DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE:                     return "Boolean is not zero or one";
+    case DBUS_INVALID_NOT_ENOUGH_DATA:                             return "Not enough data";
+    case DBUS_INVALID_TOO_MUCH_DATA:                               return "Too much data";
+    case DBUS_INVALID_BAD_BYTE_ORDER:                              return "Bad byte order";
+    case DBUS_INVALID_BAD_PROTOCOL_VERSION:                        return "Bad protocol version";
+    case DBUS_INVALID_BAD_MESSAGE_TYPE:                            return "Bad message type";
+    case DBUS_INVALID_BAD_SERIAL:                                  return "Bad serial";
+    case DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH:                  return "Insane fields array length";
+    case DBUS_INVALID_INSANE_BODY_LENGTH:                          return "Insane body length";
+    case DBUS_INVALID_MESSAGE_TOO_LONG:                            return "Message too long";
+    case DBUS_INVALID_HEADER_FIELD_CODE:                           return "Header field code";
+    case DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE:                 return "Header field has wrong type";
+    case DBUS_INVALID_USES_LOCAL_INTERFACE:                        return "Uses local interface";
+    case DBUS_INVALID_USES_LOCAL_PATH:                             return "Uses local path";
+    case DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE:                  return "Header field appears twice";
+    case DBUS_INVALID_BAD_DESTINATION:                             return "Bad destination";
+    case DBUS_INVALID_BAD_INTERFACE:                               return "Bad interface";
+    case DBUS_INVALID_BAD_MEMBER:                                  return "Bad member";
+    case DBUS_INVALID_BAD_ERROR_NAME:                              return "Bad error name";
+    case DBUS_INVALID_BAD_SENDER:                                  return "Bad sender";
+    case DBUS_INVALID_MISSING_PATH:                                return "Missing path";
+    case DBUS_INVALID_MISSING_INTERFACE:                           return "Missing interface";
+    case DBUS_INVALID_MISSING_MEMBER:                              return "Missing member";
+    case DBUS_INVALID_MISSING_ERROR_NAME:                          return "Missing error name";
+    case DBUS_INVALID_MISSING_REPLY_SERIAL:                        return "Missing reply serial";
+    case DBUS_INVALID_LENGTH_OUT_OF_BOUNDS:                        return "Length out of bounds";
+    case DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM:                return "Array length exceeds maximum";
+    case DBUS_INVALID_BAD_PATH:                                    return "Bad path";
+    case DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS:              return "Signature length out of bounds";
+    case DBUS_INVALID_BAD_UTF8_IN_STRING:                          return "Bad utf8 in string";
+    case DBUS_INVALID_ARRAY_LENGTH_INCORRECT:                      return "Array length incorrect";
+    case DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS:      return "Variant signature length out of bounds";
+    case DBUS_INVALID_VARIANT_SIGNATURE_BAD:                       return "Variant signature bad";
+    case DBUS_INVALID_VARIANT_SIGNATURE_EMPTY:                     return "Variant signature empty";
+    case DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES: return "Variant signature specifies multiple values";
+    case DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL:               return "Variant signature missing nul";
+    case DBUS_INVALID_STRING_MISSING_NUL:                          return "String missing nul";
+    case DBUS_INVALID_SIGNATURE_MISSING_NUL:                       return "Signature missing nul";
+    case DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION:       return "Exceeded maximum dict entry recursion";
+    case DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED:            return "Dict entry ended but not started";
+    case DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED:            return "Dict entry started but not ended";
+    case DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS:                    return "Dict entry has no fields";
+    case DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD:               return "Dict entry has only one field";
+    case DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS:              return "Dict entry has too many fields";
+    case DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY:                 return "Dict entry not inside array";
+    case DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE:                 return "Dict key must be basic type";
+    case DBUS_INVALID_NESTED_TOO_DEEPLY:                           return "Variants cannot be used to create a hugely recursive tree of values";
+    default:
+      return "Invalid";
+    }
+}
+
+/**
+ * Checks that the given range of the string is a valid interface name
+ * in the D-Bus protocol. This includes a length restriction and an
+ * ASCII subset, see the specification.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_validate_interface (const DBusString  *str,
+                          int                start,
+                          int                len)
+{
+  const unsigned char *s;
+  const unsigned char *end;
+  const unsigned char *iface;
+  const unsigned char *last_dot;
+
+  _dbus_assert (start >= 0);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= _dbus_string_get_length (str));
+
+  if (len > _dbus_string_get_length (str) - start)
+    return FALSE;
+
+  if (len > DBUS_MAXIMUM_NAME_LENGTH)
+    return FALSE;
+
+  if (len == 0)
+    return FALSE;
+
+  last_dot = NULL;
+  iface = _dbus_string_get_const_data (str) + start;
+  end = iface + len;
+  s = iface;
+
+  /* check special cases of first char so it doesn't have to be done
+   * in the loop. Note we know len > 0
+   */
+  if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
+    return FALSE;
+  else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
+    return FALSE;
+  else
+    ++s;
+
+  while (s != end)
+    {
+      if (*s == '.')
+        {
+          if (_DBUS_UNLIKELY ((s + 1) == end))
+            return FALSE;
+          else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
+            return FALSE;
+          last_dot = s;
+          ++s; /* we just validated the next char, so skip two */
+        }
+      else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
+        {
+          return FALSE;
+        }
+
+      ++s;
+    }
+
+  if (_DBUS_UNLIKELY (last_dot == NULL))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * Checks that the given range of the string is a valid member name
+ * in the D-Bus protocol. This includes a length restriction, etc.,
+ * see the specification.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_validate_member (const DBusString  *str,
+                       int                start,
+                       int                len)
+{
+  const unsigned char *s;
+  const unsigned char *end;
+  const unsigned char *member;
+
+  _dbus_assert (start >= 0);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= _dbus_string_get_length (str));
+
+  if (len > _dbus_string_get_length (str) - start)
+    return FALSE;
+
+  if (len > DBUS_MAXIMUM_NAME_LENGTH)
+    return FALSE;
+
+  if (len == 0)
+    return FALSE;
+
+  member = _dbus_string_get_const_data (str) + start;
+  end = member + len;
+  s = member;
+
+  /* check special cases of first char so it doesn't have to be done
+   * in the loop. Note we know len > 0
+   */
+
+  if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
+    return FALSE;
+  else
+    ++s;
+
+  while (s != end)
+    {
+      if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
+        {
+          return FALSE;
+        }
+
+      ++s;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Checks that the given range of the string is a valid error name
+ * in the D-Bus protocol. This includes a length restriction, etc.,
+ * see the specification.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_validate_error_name (const DBusString  *str,
+                           int                start,
+                           int                len)
+{
+  /* Same restrictions as interface name at the moment */
+  return _dbus_validate_interface (str, start, len);
+}
+
+/**
+ * Determine wether the given character is valid as the first character
+ * in a bus name.
+ */
+#define VALID_INITIAL_BUS_NAME_CHARACTER(c)         \
+  ( ((c) >= 'A' && (c) <= 'Z') ||               \
+    ((c) >= 'a' && (c) <= 'z') ||               \
+    ((c) == '_') || ((c) == '-'))
+
+/**
+ * Determine wether the given character is valid as a second or later
+ * character in a bus name
+ */
+#define VALID_BUS_NAME_CHARACTER(c)                 \
+  ( ((c) >= '0' && (c) <= '9') ||               \
+    ((c) >= 'A' && (c) <= 'Z') ||               \
+    ((c) >= 'a' && (c) <= 'z') ||               \
+    ((c) == '_') || ((c) == '-'))
+
+static dbus_bool_t
+_dbus_validate_bus_name_full (const DBusString  *str,
+                              int                start,
+                              int                len,
+                              dbus_bool_t        is_namespace)
+{
+  const unsigned char *s;
+  const unsigned char *end;
+  const unsigned char *iface;
+  const unsigned char *last_dot;
+
+  _dbus_assert (start >= 0);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= _dbus_string_get_length (str));
+
+  if (len > _dbus_string_get_length (str) - start)
+    return FALSE;
+
+  if (len > DBUS_MAXIMUM_NAME_LENGTH)
+    return FALSE;
+
+  if (len == 0)
+    return FALSE;
+
+  last_dot = NULL;
+  iface = _dbus_string_get_const_data (str) + start;
+  end = iface + len;
+  s = iface;
+
+  /* check special cases of first char so it doesn't have to be done
+   * in the loop. Note we know len > 0
+   */
+  if (*s == ':')
+  {
+    /* unique name */
+    ++s;
+    while (s != end)
+      {
+        if (*s == '.')
+          {
+            if (_DBUS_UNLIKELY ((s + 1) == end))
+              return FALSE;
+            if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*(s + 1))))
+              return FALSE;
+            ++s; /* we just validated the next char, so skip two */
+          }
+        else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
+          {
+            return FALSE;
+          }
+
+        ++s;
+      }
+
+    return TRUE;
+  }
+  else if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
+    return FALSE;
+  else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*s)))
+    return FALSE;
+  else
+    ++s;
+
+  while (s != end)
+    {
+      if (*s == '.')
+        {
+          if (_DBUS_UNLIKELY ((s + 1) == end))
+            return FALSE;
+          else if (_DBUS_UNLIKELY (!VALID_INITIAL_BUS_NAME_CHARACTER (*(s + 1))))
+            return FALSE;
+          last_dot = s;
+          ++s; /* we just validated the next char, so skip two */
+        }
+      else if (_DBUS_UNLIKELY (!VALID_BUS_NAME_CHARACTER (*s)))
+        {
+          return FALSE;
+        }
+
+      ++s;
+    }
+
+  if (!is_namespace && _DBUS_UNLIKELY (last_dot == NULL))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * Checks that the given range of the string is a valid bus name in
+ * the D-Bus protocol. This includes a length restriction, etc., see
+ * the specification.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_validate_bus_name (const DBusString  *str,
+                         int                start,
+                         int                len)
+{
+  return _dbus_validate_bus_name_full (str, start, len, FALSE);
+}
+
+/**
+ * Checks that the given range of the string is a prefix of a valid bus name in
+ * the D-Bus protocol. Unlike _dbus_validate_bus_name(), this accepts strings
+ * with only one period-separated component.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_validate_bus_namespace (const DBusString  *str,
+                              int                start,
+                              int                len)
+{
+  return _dbus_validate_bus_name_full (str, start, len, TRUE);
+}
+
+/**
+ * Checks that the given range of the string is a valid message type
+ * signature in the D-Bus protocol.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid signature
+ */
+dbus_bool_t
+_dbus_validate_signature (const DBusString  *str,
+                          int                start,
+                          int                len)
+{
+  _dbus_assert (start >= 0);
+  _dbus_assert (start <= _dbus_string_get_length (str));
+  _dbus_assert (len >= 0);
+
+  if (len > _dbus_string_get_length (str) - start)
+    return FALSE;
+
+  return _dbus_validate_signature_with_reason (str, start, len) == DBUS_VALID;
+}
+
+/** define _dbus_check_is_valid_path() */
+DEFINE_DBUS_NAME_CHECK(path)
+/** define _dbus_check_is_valid_interface() */
+DEFINE_DBUS_NAME_CHECK(interface)
+/** define _dbus_check_is_valid_member() */
+DEFINE_DBUS_NAME_CHECK(member)
+/** define _dbus_check_is_valid_error_name() */
+DEFINE_DBUS_NAME_CHECK(error_name)
+/** define _dbus_check_is_valid_bus_name() */
+DEFINE_DBUS_NAME_CHECK(bus_name)
+/** define _dbus_check_is_valid_signature() */
+DEFINE_DBUS_NAME_CHECK(signature)
+/** define _dbus_check_is_valid_utf8() */
+DEFINE_DBUS_NAME_CHECK(utf8)
+
+/** @} */
+
+/* tests in dbus-marshal-validate-util.c */
diff --git a/dbus/dbus/dbus-marshal-validate.h b/dbus/dbus/dbus-marshal-validate.h
new file mode 100644
index 0000000..0643420
--- /dev/null
+++ b/dbus/dbus/dbus-marshal-validate.h
@@ -0,0 +1,206 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-marshal-validate.h  Validation routines for marshaled data
+ *
+ * Copyright (C) 2005  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef DBUS_MARSHAL_VALIDATE_H
+#define DBUS_MARSHAL_VALIDATE_H
+
+/**
+ * @addtogroup DBusMarshal
+ *
+ * @{
+ */
+
+/**
+ * This is used rather than a bool for high visibility
+ */
+typedef enum
+{
+  DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY,
+  DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED
+} DBusValidationMode;
+
+/**
+ * This is primarily used in unit testing, so we can verify that each
+ * invalid message is invalid for the expected reasons. Thus we really
+ * want a distinct enum value for every codepath leaving the validator
+ * functions. Enum values are specified manually for ease of debugging
+ * (so you can see the enum value given a printf)
+ */
+typedef enum
+{
+#define _DBUS_NEGATIVE_VALIDITY_COUNT 4
+  DBUS_VALIDITY_UNKNOWN_OOM_ERROR = -4, /**< can't determine validity due to OOM */
+  DBUS_INVALID_FOR_UNKNOWN_REASON = -3,
+  DBUS_VALID_BUT_INCOMPLETE = -2,
+  DBUS_VALIDITY_UNKNOWN = -1,
+  DBUS_VALID = 0, /**< the data is valid */
+  DBUS_INVALID_UNKNOWN_TYPECODE = 1,
+  DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE = 2,
+  DBUS_INVALID_SIGNATURE_TOO_LONG = 3, /* this one is impossible right now since
+                                        * you can't put a too-long value in a byte
+                                        */
+  DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION = 4,
+  DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION = 5,
+  DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED = 6,
+  DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED = 7,
+  DBUS_INVALID_STRUCT_HAS_NO_FIELDS = 8,
+  DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL = 9,
+  DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE = 10,
+  DBUS_INVALID_NOT_ENOUGH_DATA = 11,
+  DBUS_INVALID_TOO_MUCH_DATA = 12, /**< trailing junk makes it invalid */
+  DBUS_INVALID_BAD_BYTE_ORDER = 13,
+  DBUS_INVALID_BAD_PROTOCOL_VERSION = 14,
+  DBUS_INVALID_BAD_MESSAGE_TYPE = 15,
+  DBUS_INVALID_BAD_SERIAL = 16,
+  DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH = 17,
+  DBUS_INVALID_INSANE_BODY_LENGTH = 18,
+  DBUS_INVALID_MESSAGE_TOO_LONG = 19,
+  DBUS_INVALID_HEADER_FIELD_CODE = 20,
+  DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE = 21,
+  DBUS_INVALID_USES_LOCAL_INTERFACE = 22,
+  DBUS_INVALID_USES_LOCAL_PATH = 23,
+  DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE = 24,
+  DBUS_INVALID_BAD_DESTINATION = 25,
+  DBUS_INVALID_BAD_INTERFACE = 26,
+  DBUS_INVALID_BAD_MEMBER = 27,
+  DBUS_INVALID_BAD_ERROR_NAME = 28,
+  DBUS_INVALID_BAD_SENDER = 29,
+  DBUS_INVALID_MISSING_PATH = 30,
+  DBUS_INVALID_MISSING_INTERFACE = 31,
+  DBUS_INVALID_MISSING_MEMBER = 32,
+  DBUS_INVALID_MISSING_ERROR_NAME = 33,
+  DBUS_INVALID_MISSING_REPLY_SERIAL = 34,
+  DBUS_INVALID_LENGTH_OUT_OF_BOUNDS = 35,
+  DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM = 36,
+  DBUS_INVALID_BAD_PATH = 37,
+  DBUS_INVALID_SIGNATURE_LENGTH_OUT_OF_BOUNDS = 38,
+  DBUS_INVALID_BAD_UTF8_IN_STRING = 39,
+  DBUS_INVALID_ARRAY_LENGTH_INCORRECT = 40,
+  DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS = 41,
+  DBUS_INVALID_VARIANT_SIGNATURE_BAD = 42,
+  DBUS_INVALID_VARIANT_SIGNATURE_EMPTY = 43,
+  DBUS_INVALID_VARIANT_SIGNATURE_SPECIFIES_MULTIPLE_VALUES = 44,
+  DBUS_INVALID_VARIANT_SIGNATURE_MISSING_NUL = 45,
+  DBUS_INVALID_STRING_MISSING_NUL = 46,
+  DBUS_INVALID_SIGNATURE_MISSING_NUL = 47,
+  DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION = 48,
+  DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED = 49,
+  DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED = 50,
+  DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS = 51,
+  DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD = 52,
+  DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS = 53,
+  DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY = 54,
+  DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE = 55,
+  DBUS_INVALID_MISSING_UNIX_FDS = 56,
+  DBUS_INVALID_NESTED_TOO_DEEPLY = 57,
+  DBUS_VALIDITY_LAST
+} DBusValidity;
+
+DBusValidity _dbus_validate_signature_with_reason (const DBusString *type_str,
+                                                   int               type_pos,
+                                                   int               len);
+DBusValidity _dbus_validate_body_with_reason      (const DBusString *expected_signature,
+                                                   int               expected_signature_start,
+                                                   int               byte_order,
+                                                   int              *bytes_remaining,
+                                                   const DBusString *value_str,
+                                                   int               value_pos,
+                                                   int               len);
+
+const char *_dbus_validity_to_error_message (DBusValidity validity);
+
+dbus_bool_t _dbus_validate_path       (const DBusString *str,
+                                       int               start,
+                                       int               len);
+dbus_bool_t _dbus_validate_interface  (const DBusString *str,
+                                       int               start,
+                                       int               len);
+dbus_bool_t _dbus_validate_member     (const DBusString *str,
+                                       int               start,
+                                       int               len);
+dbus_bool_t _dbus_validate_error_name (const DBusString *str,
+                                       int               start,
+                                       int               len);
+dbus_bool_t _dbus_validate_bus_name   (const DBusString *str,
+                                       int               start,
+                                       int               len);
+dbus_bool_t _dbus_validate_bus_namespace (const DBusString  *str,
+                                          int                start,
+                                          int                len);
+dbus_bool_t _dbus_validate_signature  (const DBusString *str,
+                                       int               start,
+                                       int               len);
+/* just to have a name consistent with the above: */
+#define _dbus_validate_utf8(s,b,e) _dbus_string_validate_utf8 (s, b, e)
+
+#ifdef DBUS_DISABLE_CHECKS
+
+/* Be sure they don't exist, since we don't want to use them outside of checks
+ * and so we want the compile failure.
+ */
+#define DECLARE_DBUS_NAME_CHECK(what)
+#define DEFINE_DBUS_NAME_CHECK(what)
+
+#else /* !DBUS_DISABLE_CHECKS */
+
+/** A name check is used in _dbus_return_if_fail(), it's not suitable
+ * for validating untrusted data. use _dbus_validate_whatever for that.
+ */
+#define DECLARE_DBUS_NAME_CHECK(what) \
+dbus_bool_t _dbus_check_is_valid_##what (const char *name)
+
+/** Define a name check to be used in _dbus_return_if_fail() statements.
+ */
+#define DEFINE_DBUS_NAME_CHECK(what)                                    \
+dbus_bool_t                                                             \
+_dbus_check_is_valid_##what (const char *name)                          \
+{                                                                       \
+  DBusString str;                                                       \
+                                                                        \
+  if (name == NULL)                                                     \
+    return FALSE;                                                       \
+                                                                        \
+  _dbus_string_init_const (&str, name);                                 \
+  return _dbus_validate_##what (&str, 0,                                \
+                                _dbus_string_get_length (&str));        \
+}
+#endif /* !DBUS_DISABLE_CHECKS */
+
+/** defines _dbus_check_is_valid_path() */
+DECLARE_DBUS_NAME_CHECK(path);
+/** defines _dbus_check_is_valid_interface() */
+DECLARE_DBUS_NAME_CHECK(interface);
+/** defines _dbus_check_is_valid_member() */
+DECLARE_DBUS_NAME_CHECK(member);
+/** defines _dbus_check_is_valid_error_name() */
+DECLARE_DBUS_NAME_CHECK(error_name);
+/** defines _dbus_check_is_valid_bus_name() */
+DECLARE_DBUS_NAME_CHECK(bus_name);
+/** defines _dbus_check_is_valid_signature() */
+DECLARE_DBUS_NAME_CHECK(signature);
+/** defines _dbus_check_is_valid_utf8() */
+DECLARE_DBUS_NAME_CHECK(utf8);
+
+/** @} */
+
+#endif /* DBUS_MARSHAL_VALIDATE_H */
diff --git a/dbus/dbus/dbus-memory.c b/dbus/dbus/dbus-memory.c
new file mode 100644
index 0000000..a033b54
--- /dev/null
+++ b/dbus/dbus/dbus-memory.c
@@ -0,0 +1,935 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-memory.c  D-Bus memory handling
+ *
+ * Copyright (C) 2002, 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-memory.h"
+#include "dbus-internals.h"
+#include "dbus-sysdeps.h"
+#include "dbus-list.h"
+#include <stdlib.h>
+
+/**
+ * @defgroup DBusMemory Memory Allocation
+ * @ingroup  DBus
+ * @brief dbus_malloc(), dbus_free(), etc.
+ *
+ * Functions and macros related to allocating and releasing
+ * blocks of memory.
+ *
+ */
+
+/**
+ * @defgroup DBusMemoryInternals Memory allocation implementation details
+ * @ingroup  DBusInternals
+ * @brief internals of dbus_malloc() etc.
+ *
+ * Implementation details related to allocating and releasing blocks
+ * of memory.
+ */
+
+/**
+ * @addtogroup DBusMemory
+ *
+ * @{
+ */
+
+/**
+ * @def dbus_new
+ *
+ * Safe macro for using dbus_malloc(). Accepts the type
+ * to allocate and the number of type instances to
+ * allocate as arguments, and returns a memory block
+ * cast to the desired type, instead of as a void*.
+ *
+ * @param type type name to allocate
+ * @param count number of instances in the allocated array
+ * @returns the new memory block or #NULL on failure
+ */
+
+/**
+ * @def dbus_new0
+ *
+ * Safe macro for using dbus_malloc0(). Accepts the type
+ * to allocate and the number of type instances to
+ * allocate as arguments, and returns a memory block
+ * cast to the desired type, instead of as a void*.
+ * The allocated array is initialized to all-bits-zero.
+ *
+ * @param type type name to allocate
+ * @param count number of instances in the allocated array
+ * @returns the new memory block or #NULL on failure
+ */
+
+/**
+ * @typedef DBusFreeFunction
+ *
+ * The type of a function which frees a block of memory.
+ *
+ * @param memory the memory to free
+ */
+
+/** @} */ /* end of public API docs */
+
+/**
+ * @addtogroup DBusMemoryInternals
+ *
+ * @{
+ */
+
+#ifdef DBUS_BUILD_TESTS
+static dbus_bool_t debug_initialized = FALSE;
+static int fail_nth = -1;
+static size_t fail_size = 0;
+static int fail_alloc_counter = _DBUS_INT_MAX;
+static int n_failures_per_failure = 1;
+static int n_failures_this_failure = 0;
+static dbus_bool_t guards = FALSE;
+static dbus_bool_t disable_mem_pools = FALSE;
+static dbus_bool_t backtrace_on_fail_alloc = FALSE;
+static dbus_bool_t malloc_cannot_fail = FALSE;
+static DBusAtomic n_blocks_outstanding = {0};
+
+/** value stored in guard padding for debugging buffer overrun */
+#define GUARD_VALUE 0xdeadbeef
+/** size of the information about the block stored in guard mode */
+#define GUARD_INFO_SIZE 8
+/** size of the GUARD_VALUE-filled padding after the header info  */
+#define GUARD_START_PAD 16
+/** size of the GUARD_VALUE-filled padding at the end of the block */
+#define GUARD_END_PAD 16
+/** size of stuff at start of block */
+#define GUARD_START_OFFSET (GUARD_START_PAD + GUARD_INFO_SIZE)
+/** total extra size over the requested allocation for guard stuff */
+#define GUARD_EXTRA_SIZE (GUARD_START_OFFSET + GUARD_END_PAD)
+
+static void
+_dbus_initialize_malloc_debug (void)
+{
+  if (!debug_initialized)
+    {
+      debug_initialized = TRUE;
+      
+      if (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH") != NULL)
+	{
+	  fail_nth = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_NTH"));
+          fail_alloc_counter = fail_nth;
+          _dbus_verbose ("Will fail dbus_malloc every %d times\n", fail_nth);
+	}
+      
+      if (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN") != NULL)
+        {
+          fail_size = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN"));
+          _dbus_verbose ("Will fail mallocs over %ld bytes\n",
+                         (long) fail_size);
+        }
+
+      if (_dbus_getenv ("DBUS_MALLOC_GUARDS") != NULL)
+        {
+          guards = TRUE;
+          _dbus_verbose ("Will use dbus_malloc guards\n");
+        }
+
+      if (_dbus_getenv ("DBUS_DISABLE_MEM_POOLS") != NULL)
+        {
+          disable_mem_pools = TRUE;
+          _dbus_verbose ("Will disable memory pools\n");
+        }
+
+      if (_dbus_getenv ("DBUS_MALLOC_BACKTRACES") != NULL)
+        {
+          backtrace_on_fail_alloc = TRUE;
+          _dbus_verbose ("Will backtrace on failing a dbus_malloc\n");
+        }
+
+      if (_dbus_getenv ("DBUS_MALLOC_CANNOT_FAIL") != NULL)
+        {
+          malloc_cannot_fail = TRUE;
+          _dbus_verbose ("Will abort if system malloc() and friends fail\n");
+        }
+    }
+}
+
+/**
+ * Whether to turn off mem pools, useful for leak checking.
+ *
+ * @returns #TRUE if mempools should not be used.
+ */
+dbus_bool_t
+_dbus_disable_mem_pools (void)
+{
+  _dbus_initialize_malloc_debug ();
+  return disable_mem_pools;
+}
+
+/**
+ * Sets the number of allocations until we simulate a failed
+ * allocation. If set to 0, the next allocation to run
+ * fails; if set to 1, one succeeds then the next fails; etc.
+ * Set to _DBUS_INT_MAX to not fail anything. 
+ *
+ * @param until_next_fail number of successful allocs before one fails
+ */
+void
+_dbus_set_fail_alloc_counter (int until_next_fail)
+{
+  _dbus_initialize_malloc_debug ();
+
+  fail_alloc_counter = until_next_fail;
+
+#if 0
+  _dbus_verbose ("Set fail alloc counter = %d\n", fail_alloc_counter);
+#endif
+}
+
+/**
+ * Gets the number of successful allocs until we'll simulate
+ * a failed alloc.
+ *
+ * @returns current counter value
+ */
+int
+_dbus_get_fail_alloc_counter (void)
+{
+  _dbus_initialize_malloc_debug ();
+
+  return fail_alloc_counter;
+}
+
+/**
+ * Sets how many mallocs to fail when the fail alloc counter reaches
+ * 0.
+ *
+ * @param failures_per_failure number to fail
+ */
+void
+_dbus_set_fail_alloc_failures (int failures_per_failure)
+{
+  n_failures_per_failure = failures_per_failure;
+}
+
+/**
+ * Gets the number of failures we'll have when the fail malloc
+ * counter reaches 0.
+ *
+ * @returns number of failures planned
+ */
+int
+_dbus_get_fail_alloc_failures (void)
+{
+  return n_failures_per_failure;
+}
+
+#ifdef DBUS_BUILD_TESTS
+/**
+ * Called when about to alloc some memory; if
+ * it returns #TRUE, then the allocation should
+ * fail. If it returns #FALSE, then the allocation
+ * should not fail.
+ *
+ * @returns #TRUE if this alloc should fail
+ */
+dbus_bool_t
+_dbus_decrement_fail_alloc_counter (void)
+{
+  _dbus_initialize_malloc_debug ();
+#ifdef DBUS_WIN_FIXME
+  {
+    static dbus_bool_t called = 0;
+
+    if (!called)
+      {
+        _dbus_verbose("TODO: memory allocation testing errors disabled for now\n");
+        called = 1;
+      }
+    return FALSE;
+  }
+#endif
+
+  if (fail_alloc_counter <= 0)
+    {
+      if (backtrace_on_fail_alloc)
+        _dbus_print_backtrace ();
+
+      _dbus_verbose ("failure %d\n", n_failures_this_failure);
+      
+      n_failures_this_failure += 1;
+      if (n_failures_this_failure >= n_failures_per_failure)
+        {
+          if (fail_nth >= 0)
+            fail_alloc_counter = fail_nth;
+          else
+            fail_alloc_counter = _DBUS_INT_MAX;
+
+          n_failures_this_failure = 0;
+
+          _dbus_verbose ("reset fail alloc counter to %d\n", fail_alloc_counter);
+        }
+      
+      return TRUE;
+    }
+  else
+    {
+      fail_alloc_counter -= 1;
+      return FALSE;
+    }
+}
+#endif /* DBUS_BUILD_TESTS */
+
+/**
+ * Get the number of outstanding malloc()'d blocks.
+ *
+ * @returns number of blocks
+ */
+int
+_dbus_get_malloc_blocks_outstanding (void)
+{
+  return _dbus_atomic_get (&n_blocks_outstanding);
+}
+
+/**
+ * Where the block came from.
+ */
+typedef enum
+{
+  SOURCE_UNKNOWN,
+  SOURCE_MALLOC,
+  SOURCE_REALLOC,
+  SOURCE_MALLOC_ZERO,
+  SOURCE_REALLOC_NULL
+} BlockSource;
+
+static const char*
+source_string (BlockSource source)
+{
+  switch (source)
+    {
+    case SOURCE_UNKNOWN:
+      return "unknown";
+    case SOURCE_MALLOC:
+      return "malloc";
+    case SOURCE_REALLOC:
+      return "realloc";
+    case SOURCE_MALLOC_ZERO:
+      return "malloc0";
+    case SOURCE_REALLOC_NULL:
+      return "realloc(NULL)";
+    }
+  _dbus_assert_not_reached ("Invalid malloc block source ID");
+  return "invalid!";
+}
+
+static void
+check_guards (void       *free_block,
+              dbus_bool_t overwrite)
+{
+  if (free_block != NULL)
+    {
+      unsigned char *block = ((unsigned char*)free_block) - GUARD_START_OFFSET;
+      size_t requested_bytes = *(dbus_uint32_t*)block;
+      BlockSource source = *(dbus_uint32_t*)(block + 4);
+      unsigned int i;
+      dbus_bool_t failed;
+
+      failed = FALSE;
+
+#if 0
+      _dbus_verbose ("Checking %d bytes request from source %s\n",
+                     requested_bytes, source_string (source));
+#endif
+      
+      i = GUARD_INFO_SIZE;
+      while (i < GUARD_START_OFFSET)
+        {
+          dbus_uint32_t value = *(dbus_uint32_t*) &block[i];
+          if (value != GUARD_VALUE)
+            {
+              _dbus_warn ("Block of %lu bytes from %s had start guard value 0x%ux at %d expected 0x%x\n",
+                          (long) requested_bytes, source_string (source),
+                          value, i, GUARD_VALUE);
+              failed = TRUE;
+            }
+          
+          i += 4;
+        }
+
+      i = GUARD_START_OFFSET + requested_bytes;
+      while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD))
+        {
+          dbus_uint32_t value = *(dbus_uint32_t*) &block[i];
+          if (value != GUARD_VALUE)
+            {
+              _dbus_warn ("Block of %lu bytes from %s had end guard value 0x%ux at %d expected 0x%x\n",
+                          (long) requested_bytes, source_string (source),
+                          value, i, GUARD_VALUE);
+              failed = TRUE;
+            }
+          
+          i += 4;
+        }
+
+      /* set memory to anything but nul bytes */
+      if (overwrite)
+        memset (free_block, 'g', requested_bytes);
+      
+      if (failed)
+        _dbus_assert_not_reached ("guard value corruption");
+    }
+}
+
+static void*
+set_guards (void       *real_block,
+            size_t      requested_bytes,
+            BlockSource source)
+{
+  unsigned char *block = real_block;
+  unsigned int i;
+  
+  if (block == NULL)
+    return NULL;
+
+  _dbus_assert (GUARD_START_OFFSET + GUARD_END_PAD == GUARD_EXTRA_SIZE);
+  
+  *((dbus_uint32_t*)block) = requested_bytes;
+  *((dbus_uint32_t*)(block + 4)) = source;
+
+  i = GUARD_INFO_SIZE;
+  while (i < GUARD_START_OFFSET)
+    {
+      (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE;
+      
+      i += 4;
+    }
+
+  i = GUARD_START_OFFSET + requested_bytes;
+  while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD))
+    {
+      (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE;
+      
+      i += 4;
+    }
+  
+  check_guards (block + GUARD_START_OFFSET, FALSE);
+  
+  return block + GUARD_START_OFFSET;
+}
+
+#endif
+
+/** @} */ /* End of internals docs */
+
+
+/**
+ * @addtogroup DBusMemory
+ *
+ * @{
+ */
+
+/**
+ * Allocates the given number of bytes, as with standard
+ * malloc(). Guaranteed to return #NULL if bytes is zero
+ * on all platforms. Returns #NULL if the allocation fails.
+ * The memory must be released with dbus_free().
+ *
+ * dbus_malloc() memory is NOT safe to free with regular free() from
+ * the C library. Free it with dbus_free() only.
+ *
+ * @param bytes number of bytes to allocate
+ * @return allocated memory, or #NULL if the allocation fails.
+ */
+void*
+dbus_malloc (size_t bytes)
+{
+#ifdef DBUS_BUILD_TESTS
+  _dbus_initialize_malloc_debug ();
+  
+  if (_dbus_decrement_fail_alloc_counter ())
+    {
+      _dbus_verbose (" FAILING malloc of %ld bytes\n", (long) bytes);
+      return NULL;
+    }
+#endif
+
+  if (bytes == 0) /* some system mallocs handle this, some don't */
+    return NULL;
+#ifdef DBUS_BUILD_TESTS
+  else if (fail_size != 0 && bytes > fail_size)
+    return NULL;
+  else if (guards)
+    {
+      void *block;
+
+      block = malloc (bytes + GUARD_EXTRA_SIZE);
+      if (block)
+        {
+          _dbus_atomic_inc (&n_blocks_outstanding);
+        }
+      else if (malloc_cannot_fail)
+        {
+          _dbus_warn ("out of memory: malloc (%ld + %ld)\n",
+              (long) bytes, (long) GUARD_EXTRA_SIZE);
+          _dbus_abort ();
+        }
+      
+      return set_guards (block, bytes, SOURCE_MALLOC);
+    }
+#endif
+  else
+    {
+      void *mem;
+      mem = malloc (bytes);
+
+#ifdef DBUS_BUILD_TESTS
+      if (mem)
+        {
+          _dbus_atomic_inc (&n_blocks_outstanding);
+        }
+      else if (malloc_cannot_fail)
+        {
+          _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes);
+          _dbus_abort ();
+        }
+#endif
+
+      return mem;
+    }
+}
+
+/**
+ * Allocates the given number of bytes, as with standard malloc(), but
+ * all bytes are initialized to zero as with calloc(). Guaranteed to
+ * return #NULL if bytes is zero on all platforms. Returns #NULL if the
+ * allocation fails.  The memory must be released with dbus_free().
+ *
+ * dbus_malloc0() memory is NOT safe to free with regular free() from
+ * the C library. Free it with dbus_free() only.
+ *
+ * @param bytes number of bytes to allocate
+ * @return allocated memory, or #NULL if the allocation fails.
+ */
+void*
+dbus_malloc0 (size_t bytes)
+{
+#ifdef DBUS_BUILD_TESTS
+  _dbus_initialize_malloc_debug ();
+  
+  if (_dbus_decrement_fail_alloc_counter ())
+    {
+      _dbus_verbose (" FAILING malloc0 of %ld bytes\n", (long) bytes);
+      
+      return NULL;
+    }
+#endif
+  
+  if (bytes == 0)
+    return NULL;
+#ifdef DBUS_BUILD_TESTS
+  else if (fail_size != 0 && bytes > fail_size)
+    return NULL;
+  else if (guards)
+    {
+      void *block;
+
+      block = calloc (bytes + GUARD_EXTRA_SIZE, 1);
+
+      if (block)
+        {
+          _dbus_atomic_inc (&n_blocks_outstanding);
+        }
+      else if (malloc_cannot_fail)
+        {
+          _dbus_warn ("out of memory: calloc (%ld + %ld, 1)\n",
+              (long) bytes, (long) GUARD_EXTRA_SIZE);
+          _dbus_abort ();
+        }
+
+      return set_guards (block, bytes, SOURCE_MALLOC_ZERO);
+    }
+#endif
+  else
+    {
+      void *mem;
+      mem = calloc (bytes, 1);
+
+#ifdef DBUS_BUILD_TESTS
+      if (mem)
+        {
+          _dbus_atomic_inc (&n_blocks_outstanding);
+        }
+      else if (malloc_cannot_fail)
+        {
+          _dbus_warn ("out of memory: calloc (%ld)\n", (long) bytes);
+          _dbus_abort ();
+        }
+#endif
+
+      return mem;
+    }
+}
+
+/**
+ * Resizes a block of memory previously allocated by dbus_malloc() or
+ * dbus_malloc0(). Guaranteed to free the memory and return #NULL if bytes
+ * is zero on all platforms. Returns #NULL if the resize fails.
+ * If the resize fails, the memory is not freed.
+ *
+ * @param memory block to be resized
+ * @param bytes new size of the memory block
+ * @return allocated memory, or #NULL if the resize fails.
+ */
+void*
+dbus_realloc (void  *memory,
+              size_t bytes)
+{
+#ifdef DBUS_BUILD_TESTS
+  _dbus_initialize_malloc_debug ();
+  
+  if (_dbus_decrement_fail_alloc_counter ())
+    {
+      _dbus_verbose (" FAILING realloc of %ld bytes\n", (long) bytes);
+      
+      return NULL;
+    }
+#endif
+  
+  if (bytes == 0) /* guarantee this is safe */
+    {
+      dbus_free (memory);
+      return NULL;
+    }
+#ifdef DBUS_BUILD_TESTS
+  else if (fail_size != 0 && bytes > fail_size)
+    return NULL;
+  else if (guards)
+    {
+      if (memory)
+        {
+          size_t old_bytes;
+          void *block;
+          
+          check_guards (memory, FALSE);
+          
+          block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET,
+                           bytes + GUARD_EXTRA_SIZE);
+
+          if (block == NULL)
+            {
+              if (malloc_cannot_fail)
+                {
+                  _dbus_warn ("out of memory: realloc (%p, %ld + %ld)\n",
+                      memory, (long) bytes, (long) GUARD_EXTRA_SIZE);
+                  _dbus_abort ();
+                }
+
+              return NULL;
+            }
+
+          old_bytes = *(dbus_uint32_t*)block;
+          if (bytes >= old_bytes)
+            /* old guards shouldn't have moved */
+            check_guards (((unsigned char*)block) + GUARD_START_OFFSET, FALSE);
+          
+          return set_guards (block, bytes, SOURCE_REALLOC);
+        }
+      else
+        {
+          void *block;
+          
+          block = malloc (bytes + GUARD_EXTRA_SIZE);
+
+          if (block)
+            {
+              _dbus_atomic_inc (&n_blocks_outstanding);
+            }
+          else if (malloc_cannot_fail)
+            {
+              _dbus_warn ("out of memory: malloc (%ld + %ld)\n",
+                  (long) bytes, (long) GUARD_EXTRA_SIZE);
+              _dbus_abort ();
+            }
+
+          return set_guards (block, bytes, SOURCE_REALLOC_NULL);   
+        }
+    }
+#endif
+  else
+    {
+      void *mem;
+      mem = realloc (memory, bytes);
+
+#ifdef DBUS_BUILD_TESTS
+      if (mem == NULL && malloc_cannot_fail)
+        {
+          _dbus_warn ("out of memory: malloc (%ld)\n", (long) bytes);
+          _dbus_abort ();
+        }
+
+      if (memory == NULL && mem != NULL)
+	    _dbus_atomic_inc (&n_blocks_outstanding);
+#endif
+      return mem;
+    }
+}
+
+/**
+ * Frees a block of memory previously allocated by dbus_malloc() or
+ * dbus_malloc0(). If passed #NULL, does nothing.
+ * 
+ * @param memory block to be freed
+ */
+void
+dbus_free (void  *memory)
+{
+#ifdef DBUS_BUILD_TESTS
+  if (guards)
+    {
+      check_guards (memory, TRUE);
+      if (memory)
+        {
+#ifdef DBUS_DISABLE_ASSERT
+          _dbus_atomic_dec (&n_blocks_outstanding);
+#else
+          dbus_int32_t old_value;
+
+          old_value = _dbus_atomic_dec (&n_blocks_outstanding);
+          _dbus_assert (old_value >= 1);
+#endif
+
+          free (((unsigned char*)memory) - GUARD_START_OFFSET);
+        }
+      
+      return;
+    }
+#endif
+    
+  if (memory) /* we guarantee it's safe to free (NULL) */
+    {
+#ifdef DBUS_BUILD_TESTS
+#ifdef DBUS_DISABLE_ASSERT
+      _dbus_atomic_dec (&n_blocks_outstanding);
+#else
+      dbus_int32_t old_value;
+
+      old_value = _dbus_atomic_dec (&n_blocks_outstanding);
+      _dbus_assert (old_value >= 1);
+#endif
+#endif
+
+      free (memory);
+    }
+}
+
+/**
+ * Frees a #NULL-terminated array of strings.
+ * If passed #NULL, does nothing.
+ *
+ * @param str_array the array to be freed
+ */
+void
+dbus_free_string_array (char **str_array)
+{
+  if (str_array)
+    {
+      int i;
+
+      i = 0;
+      while (str_array[i])
+	{
+	  dbus_free (str_array[i]);
+	  i++;
+	}
+
+      dbus_free (str_array);
+    }
+}
+
+/** @} */ /* End of public API docs block */
+
+
+/**
+ * @addtogroup DBusMemoryInternals
+ *
+ * @{
+ */
+
+/**
+ * _dbus_current_generation is used to track each
+ * time that dbus_shutdown() is called, so we can
+ * reinit things after it's been called. It is simply
+ * incremented each time we shut down.
+ */
+int _dbus_current_generation = 1;
+
+/**
+ * Represents a function to be called on shutdown.
+ */
+typedef struct ShutdownClosure ShutdownClosure;
+
+/**
+ * This struct represents a function to be called on shutdown.
+ */
+struct ShutdownClosure
+{
+  ShutdownClosure *next;     /**< Next ShutdownClosure */
+  DBusShutdownFunction func; /**< Function to call */
+  void *data;                /**< Data for function */
+};
+
+_DBUS_DEFINE_GLOBAL_LOCK (shutdown_funcs);
+static ShutdownClosure *registered_globals = NULL;
+
+/**
+ * Register a cleanup function to be called exactly once
+ * the next time dbus_shutdown() is called.
+ *
+ * @param func the function
+ * @param data data to pass to the function
+ * @returns #FALSE on not enough memory
+ */
+dbus_bool_t
+_dbus_register_shutdown_func (DBusShutdownFunction  func,
+                              void                 *data)
+{
+  ShutdownClosure *c;
+
+  c = dbus_new (ShutdownClosure, 1);
+
+  if (c == NULL)
+    return FALSE;
+
+  c->func = func;
+  c->data = data;
+
+  _DBUS_LOCK (shutdown_funcs);
+  
+  c->next = registered_globals;
+  registered_globals = c;
+
+  _DBUS_UNLOCK (shutdown_funcs);
+  
+  return TRUE;
+}
+
+/** @} */ /* End of private API docs block */
+
+
+/**
+ * @addtogroup DBusMemory
+ *
+ * @{
+ */
+
+/**
+ * Frees all memory allocated internally by libdbus and
+ * reverses the effects of dbus_threads_init(). libdbus keeps internal
+ * global variables, for example caches and thread locks, and it
+ * can be useful to free these internal data structures.
+ *
+ * dbus_shutdown() does NOT free memory that was returned
+ * to the application. It only returns libdbus-internal
+ * data structures.
+ *
+ * You MUST free all memory and release all reference counts
+ * returned to you by libdbus prior to calling dbus_shutdown().
+ *
+ * You can't continue to use any D-Bus objects, such as connections,
+ * that were allocated prior to dbus_shutdown(). You can, however,
+ * start over; call dbus_threads_init() again, create new connections,
+ * and so forth.
+ *
+ * WARNING: dbus_shutdown() is NOT thread safe, it must be called
+ * while NO other threads are using D-Bus. (Remember, you have to free
+ * all D-Bus objects and memory before you call dbus_shutdown(), so no
+ * thread can be using libdbus.)
+ *
+ * The purpose of dbus_shutdown() is to allow applications to get
+ * clean output from memory leak checkers. dbus_shutdown() may also be
+ * useful if you want to dlopen() libdbus instead of linking to it,
+ * and want to be able to unload the library again.
+ *
+ * There is absolutely no requirement to call dbus_shutdown() - in fact,
+ * most applications won't bother and should not feel guilty.
+ * 
+ * You have to know that nobody is using libdbus in your application's
+ * process before you can call dbus_shutdown(). One implication of this
+ * is that calling dbus_shutdown() from a library is almost certainly
+ * wrong, since you don't know what the rest of the app is up to.
+ * 
+ */
+void
+dbus_shutdown (void)
+{
+  while (registered_globals != NULL)
+    {
+      ShutdownClosure *c;
+
+      c = registered_globals;
+      registered_globals = c->next;
+      
+      (* c->func) (c->data);
+      
+      dbus_free (c);
+    }
+
+  _dbus_current_generation += 1;
+}
+
+/** @} */ /** End of public API docs block */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+
+/**
+ * @ingroup DBusMemoryInternals
+ * Unit test for DBusMemory
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_memory_test (void)
+{
+  dbus_bool_t old_guards;
+  void *p;
+  size_t size;
+
+  old_guards = guards;
+  guards = TRUE;
+  p = dbus_malloc (4);
+  if (p == NULL)
+    _dbus_assert_not_reached ("no memory");
+  for (size = 4; size < 256; size += 4)
+    {
+      p = dbus_realloc (p, size);
+      if (p == NULL)
+	_dbus_assert_not_reached ("no memory");
+    }
+  for (size = 256; size != 0; size -= 4)
+    {
+      p = dbus_realloc (p, size);
+      if (p == NULL)
+	_dbus_assert_not_reached ("no memory");
+    }
+  dbus_free (p);
+  guards = old_guards;
+  return TRUE;
+}
+
+#endif
diff --git a/dbus/dbus/dbus-memory.h b/dbus/dbus/dbus-memory.h
new file mode 100644
index 0000000..4fd56bd
--- /dev/null
+++ b/dbus/dbus/dbus-memory.h
@@ -0,0 +1,73 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-memory.h  D-Bus memory handling
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_MEMORY_H
+#define DBUS_MEMORY_H
+
+#include <dbus/dbus-macros.h>
+#include <stddef.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusMemory
+ * @{
+ */
+
+DBUS_EXPORT
+DBUS_MALLOC
+DBUS_ALLOC_SIZE(1)
+void* dbus_malloc        (size_t bytes);
+
+DBUS_EXPORT
+DBUS_MALLOC
+DBUS_ALLOC_SIZE(1)
+void* dbus_malloc0       (size_t bytes);
+
+DBUS_EXPORT
+DBUS_MALLOC
+DBUS_ALLOC_SIZE(2)
+void* dbus_realloc       (void  *memory,
+                          size_t bytes);
+DBUS_EXPORT
+void  dbus_free          (void  *memory);
+
+#define dbus_new(type, count)  ((type*)dbus_malloc (sizeof (type) * (count)))
+#define dbus_new0(type, count) ((type*)dbus_malloc0 (sizeof (type) * (count)))
+
+DBUS_EXPORT
+void dbus_free_string_array (char **str_array);
+
+typedef void (* DBusFreeFunction) (void *memory);
+
+DBUS_EXPORT
+void dbus_shutdown (void);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_MEMORY_H */
diff --git a/dbus/dbus/dbus-mempool.c b/dbus/dbus/dbus-mempool.c
new file mode 100644
index 0000000..33aabf9
--- /dev/null
+++ b/dbus/dbus/dbus-mempool.c
@@ -0,0 +1,635 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-mempool.h Memory pools
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-mempool.h"
+#include "dbus-internals.h"
+#include "dbus-valgrind-internal.h"
+
+/**
+ * @defgroup DBusMemPool memory pools
+ * @ingroup  DBusInternals
+ * @brief DBusMemPool object
+ *
+ * Types and functions related to DBusMemPool.  A memory pool is used
+ * to decrease memory fragmentation/overhead and increase speed for
+ * blocks of small uniformly-sized objects. The main point is to avoid
+ * the overhead of a malloc block for each small object, speed is
+ * secondary.
+ */
+
+/**
+ * @defgroup DBusMemPoolInternals Memory pool implementation details
+ * @ingroup  DBusInternals
+ * @brief DBusMemPool implementation details
+ *
+ * The guts of DBusMemPool.
+ *
+ * @{
+ */
+
+/**
+ * typedef so DBusFreedElement struct can refer to itself.
+ */
+typedef struct DBusFreedElement DBusFreedElement;
+
+/**
+ * struct representing an element on the free list.
+ * We just cast freed elements to this so we can
+ * make a list out of them.
+ */
+struct DBusFreedElement
+{
+  DBusFreedElement *next; /**< next element of the free list */
+};
+
+/**
+ * The dummy size of the variable-length "elements"
+ * field in DBusMemBlock
+ */
+#define ELEMENT_PADDING 4
+
+/**
+ * Typedef for DBusMemBlock so the struct can recursively
+ * point to itself.
+ */
+typedef struct DBusMemBlock DBusMemBlock;
+
+/**
+ * DBusMemBlock object represents a single malloc()-returned
+ * block that gets chunked up into objects in the memory pool.
+ */
+struct DBusMemBlock
+{
+  DBusMemBlock *next;  /**< next block in the list, which is already used up;
+                        *   only saved so we can free all the blocks
+                        *   when we free the mem pool.
+                        */
+
+  /* this is a long so that "elements" is aligned */
+  long used_so_far;     /**< bytes of this block already allocated as elements. */
+  
+  unsigned char elements[ELEMENT_PADDING]; /**< the block data, actually allocated to required size */
+};
+
+/**
+ * Internals fields of DBusMemPool
+ */
+struct DBusMemPool
+{
+  int element_size;                /**< size of a single object in the pool */
+  int block_size;                  /**< size of most recently allocated block */
+  unsigned int zero_elements : 1;  /**< whether to zero-init allocated elements */
+
+  DBusFreedElement *free_elements; /**< a free list of elements to recycle */
+  DBusMemBlock *blocks;            /**< blocks of memory from malloc() */
+  int allocated_elements;          /**< Count of outstanding allocated elements */
+};
+
+/** @} */
+
+/**
+ * @addtogroup DBusMemPool
+ *
+ * @{
+ */
+
+/**
+ * @typedef DBusMemPool
+ *
+ * Opaque object representing a memory pool. Memory pools allow
+ * avoiding per-malloc-block memory overhead when allocating a lot of
+ * small objects that are all the same size. They are slightly
+ * faster than calling malloc() also.
+ */
+
+/**
+ * Creates a new memory pool, or returns #NULL on failure.  Objects in
+ * the pool must be at least sizeof(void*) bytes each, due to the way
+ * memory pools work. To avoid creating 64 bit problems, this means at
+ * least 8 bytes on all platforms, unless you are 4 bytes on 32-bit
+ * and 8 bytes on 64-bit.
+ *
+ * @param element_size size of an element allocated from the pool.
+ * @param zero_elements whether to zero-initialize elements
+ * @returns the new pool or #NULL
+ */
+DBusMemPool*
+_dbus_mem_pool_new (int element_size,
+                    dbus_bool_t zero_elements)
+{
+  DBusMemPool *pool;
+
+  pool = dbus_new0 (DBusMemPool, 1);
+  if (pool == NULL)
+    return NULL;
+
+  /* Make the element size at least 8 bytes. */
+  if (element_size < 8)
+    element_size = 8;
+  
+  /* these assertions are equivalent but the first is more clear
+   * to programmers that see it fail.
+   */
+  _dbus_assert (element_size >= (int) sizeof (void*));
+  _dbus_assert (element_size >= (int) sizeof (DBusFreedElement));
+
+  /* align the element size to a pointer boundary so we won't get bus
+   * errors under other architectures.  
+   */
+  pool->element_size = _DBUS_ALIGN_VALUE (element_size, sizeof (void *));
+
+  pool->zero_elements = zero_elements != FALSE;
+
+  pool->allocated_elements = 0;
+  
+  /* pick a size for the first block; it increases
+   * for each block we need to allocate. This is
+   * actually half the initial block size
+   * since _dbus_mem_pool_alloc() unconditionally
+   * doubles it prior to creating a new block.  */
+  pool->block_size = pool->element_size * 8;
+
+  _dbus_assert ((pool->block_size %
+                 pool->element_size) == 0);
+
+  VALGRIND_CREATE_MEMPOOL (pool, 0, zero_elements)
+
+  return pool;
+}
+
+/**
+ * Frees a memory pool (and all elements allocated from it).
+ *
+ * @param pool the memory pool.
+ */
+void
+_dbus_mem_pool_free (DBusMemPool *pool)
+{
+  DBusMemBlock *block;
+
+  VALGRIND_DESTROY_MEMPOOL (pool)
+
+  block = pool->blocks;
+  while (block != NULL)
+    {
+      DBusMemBlock *next = block->next;
+
+      dbus_free (block);
+
+      block = next;
+    }
+
+  dbus_free (pool);
+}
+
+/**
+ * Allocates an object from the memory pool.
+ * The object must be freed with _dbus_mem_pool_dealloc().
+ *
+ * @param pool the memory pool
+ * @returns the allocated object or #NULL if no memory.
+ */
+void*
+_dbus_mem_pool_alloc (DBusMemPool *pool)
+{
+#ifdef DBUS_BUILD_TESTS
+  if (_dbus_disable_mem_pools ())
+    {
+      DBusMemBlock *block;
+      int alloc_size;
+      
+      /* This is obviously really silly, but it's
+       * debug-mode-only code that is compiled out
+       * when tests are disabled (_dbus_disable_mem_pools()
+       * is a constant expression FALSE so this block
+       * should vanish)
+       */
+      
+      alloc_size = sizeof (DBusMemBlock) - ELEMENT_PADDING +
+        pool->element_size;
+      
+      if (pool->zero_elements)
+        block = dbus_malloc0 (alloc_size);
+      else
+        block = dbus_malloc (alloc_size);
+
+      if (block != NULL)
+        {
+          block->next = pool->blocks;
+          pool->blocks = block;
+          pool->allocated_elements += 1;
+
+          VALGRIND_MEMPOOL_ALLOC (pool, (void *) &block->elements[0],
+              pool->element_size)
+          return (void*) &block->elements[0];
+        }
+      else
+        return NULL;
+    }
+  else
+#endif
+    {
+      if (_dbus_decrement_fail_alloc_counter ())
+        {
+          _dbus_verbose (" FAILING mempool alloc\n");
+          return NULL;
+        }
+      else if (pool->free_elements)
+        {
+          DBusFreedElement *element = pool->free_elements;
+
+          pool->free_elements = pool->free_elements->next;
+
+          VALGRIND_MEMPOOL_ALLOC (pool, element, pool->element_size)
+
+          if (pool->zero_elements)
+            memset (element, '\0', pool->element_size);
+
+          pool->allocated_elements += 1;
+
+          return element;
+        }
+      else
+        {
+          void *element;
+      
+          if (pool->blocks == NULL ||
+              pool->blocks->used_so_far == pool->block_size)
+            {
+              /* Need a new block */
+              DBusMemBlock *block;
+              int alloc_size;
+#ifdef DBUS_BUILD_TESTS
+              int saved_counter;
+#endif
+          
+              if (pool->block_size <= _DBUS_INT_MAX / 4) /* avoid overflow */
+                {
+                  /* use a larger block size for our next block */
+                  pool->block_size *= 2;
+                  _dbus_assert ((pool->block_size %
+                                 pool->element_size) == 0);
+                }
+
+              alloc_size = sizeof (DBusMemBlock) - ELEMENT_PADDING + pool->block_size;
+
+#ifdef DBUS_BUILD_TESTS
+              /* We save/restore the counter, so that memory pools won't
+               * cause a given function to have different number of
+               * allocations on different invocations. i.e.  when testing
+               * we want consistent alloc patterns. So we skip our
+               * malloc here for purposes of failed alloc simulation.
+               */
+              saved_counter = _dbus_get_fail_alloc_counter ();
+              _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
+#endif
+          
+              if (pool->zero_elements)
+                block = dbus_malloc0 (alloc_size);
+              else
+                block = dbus_malloc (alloc_size);
+
+#ifdef DBUS_BUILD_TESTS
+              _dbus_set_fail_alloc_counter (saved_counter);
+              _dbus_assert (saved_counter == _dbus_get_fail_alloc_counter ());
+#endif
+          
+              if (block == NULL)
+                return NULL;
+
+              block->used_so_far = 0;
+              block->next = pool->blocks;
+              pool->blocks = block;          
+            }
+      
+          element = &pool->blocks->elements[pool->blocks->used_so_far];
+          
+          pool->blocks->used_so_far += pool->element_size;
+
+          pool->allocated_elements += 1;
+
+          VALGRIND_MEMPOOL_ALLOC (pool, element, pool->element_size)
+          return element;
+        }
+    }
+}
+
+/**
+ * Deallocates an object previously created with
+ * _dbus_mem_pool_alloc(). The previous object
+ * must have come from this same pool.
+ * @param pool the memory pool
+ * @param element the element earlier allocated.
+ * @returns #TRUE if there are no remaining allocated elements
+ */
+dbus_bool_t
+_dbus_mem_pool_dealloc (DBusMemPool *pool,
+                        void        *element)
+{
+  VALGRIND_MEMPOOL_FREE (pool, element)
+
+#ifdef DBUS_BUILD_TESTS
+  if (_dbus_disable_mem_pools ())
+    {
+      DBusMemBlock *block;
+      DBusMemBlock *prev;
+
+      /* mmm, fast. ;-) debug-only code, so doesn't matter. */
+      
+      prev = NULL;
+      block = pool->blocks;
+
+      while (block != NULL)
+        {
+          if (block->elements == (unsigned char*) element)
+            {
+              if (prev)
+                prev->next = block->next;
+              else
+                pool->blocks = block->next;
+              
+              dbus_free (block);
+
+              _dbus_assert (pool->allocated_elements > 0);
+              pool->allocated_elements -= 1;
+              
+              if (pool->allocated_elements == 0)
+                _dbus_assert (pool->blocks == NULL);
+              
+              return pool->blocks == NULL;
+            }
+          prev = block;
+          block = block->next;
+        }
+      
+      _dbus_assert_not_reached ("freed nonexistent block");
+      return FALSE;
+    }
+  else
+#endif
+    {
+      DBusFreedElement *freed;
+      
+      freed = element;
+      /* used for internal mempool administration */
+      VALGRIND_MAKE_MEM_UNDEFINED (freed, sizeof (freed));
+
+      freed->next = pool->free_elements;
+      pool->free_elements = freed;
+      
+      _dbus_assert (pool->allocated_elements > 0);
+      pool->allocated_elements -= 1;
+      
+      return pool->allocated_elements == 0;
+    }
+}
+
+#ifdef DBUS_ENABLE_STATS
+void
+_dbus_mem_pool_get_stats (DBusMemPool   *pool,
+                          dbus_uint32_t *in_use_p,
+                          dbus_uint32_t *in_free_list_p,
+                          dbus_uint32_t *allocated_p)
+{
+  DBusMemBlock *block;
+  DBusFreedElement *freed;
+  dbus_uint32_t in_use = 0;
+  dbus_uint32_t in_free_list = 0;
+  dbus_uint32_t allocated = 0;
+
+  if (pool != NULL)
+    {
+      in_use = pool->element_size * pool->allocated_elements;
+
+      for (freed = pool->free_elements; freed != NULL; freed = freed->next)
+        {
+          in_free_list += pool->element_size;
+        }
+
+      for (block = pool->blocks; block != NULL; block = block->next)
+        {
+          if (block == pool->blocks)
+            allocated += pool->block_size;
+          else
+            allocated += block->used_so_far;
+        }
+    }
+
+  if (in_use_p != NULL)
+    *in_use_p = in_use;
+
+  if (in_free_list_p != NULL)
+    *in_free_list_p = in_free_list;
+
+  if (allocated_p != NULL)
+    *allocated_p = allocated;
+}
+#endif /* DBUS_ENABLE_STATS */
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+#include <time.h>
+
+static void
+time_for_size (int size)
+{
+  int i;
+  int j;
+  clock_t start;
+  clock_t end;
+#define FREE_ARRAY_SIZE 512
+#define N_ITERATIONS FREE_ARRAY_SIZE * 512
+  void *to_free[FREE_ARRAY_SIZE];
+  DBusMemPool *pool;
+
+  _dbus_verbose ("Timings for size %d\n", size);
+  
+  _dbus_verbose (" malloc\n");
+  
+  start = clock ();
+  
+  i = 0;
+  j = 0;
+  while (i < N_ITERATIONS)
+    {
+      to_free[j] = dbus_malloc (size);
+      _dbus_assert (to_free[j] != NULL); /* in a real app of course this is wrong */
+
+      ++j;
+
+      if (j == FREE_ARRAY_SIZE)
+        {
+          j = 0;
+          while (j < FREE_ARRAY_SIZE)
+            {
+              dbus_free (to_free[j]);
+              ++j;
+            }
+
+          j = 0;
+        }
+      
+      ++i;
+    }
+
+  end = clock ();
+
+  _dbus_verbose ("  created/destroyed %d elements in %g seconds\n",
+                 N_ITERATIONS, (end - start) / (double) CLOCKS_PER_SEC);
+
+
+
+  _dbus_verbose (" mempools\n");
+  
+  start = clock ();
+
+  pool = _dbus_mem_pool_new (size, FALSE);
+  
+  i = 0;
+  j = 0;
+  while (i < N_ITERATIONS)
+    {
+      to_free[j] = _dbus_mem_pool_alloc (pool); 
+      _dbus_assert (to_free[j] != NULL);  /* in a real app of course this is wrong */
+
+      ++j;
+
+      if (j == FREE_ARRAY_SIZE)
+        {
+          j = 0;
+          while (j < FREE_ARRAY_SIZE)
+            {
+              _dbus_mem_pool_dealloc (pool, to_free[j]);
+              ++j;
+            }
+
+          j = 0;
+        }
+      
+      ++i;
+    }
+
+  _dbus_mem_pool_free (pool);
+  
+  end = clock ();
+
+  _dbus_verbose ("  created/destroyed %d elements in %g seconds\n",
+                 N_ITERATIONS, (end - start) / (double) CLOCKS_PER_SEC);
+
+  _dbus_verbose (" zeroed malloc\n");
+    
+  start = clock ();
+  
+  i = 0;
+  j = 0;
+  while (i < N_ITERATIONS)
+    {
+      to_free[j] = dbus_malloc0 (size);
+      _dbus_assert (to_free[j] != NULL); /* in a real app of course this is wrong */
+
+      ++j;
+
+      if (j == FREE_ARRAY_SIZE)
+        {
+          j = 0;
+          while (j < FREE_ARRAY_SIZE)
+            {
+              dbus_free (to_free[j]);
+              ++j;
+            }
+
+          j = 0;
+        }
+      
+      ++i;
+    }
+
+  end = clock ();
+
+  _dbus_verbose ("  created/destroyed %d elements in %g seconds\n",
+                 N_ITERATIONS, (end - start) / (double) CLOCKS_PER_SEC);
+  
+  _dbus_verbose (" zeroed mempools\n");
+  
+  start = clock ();
+
+  pool = _dbus_mem_pool_new (size, TRUE);
+  
+  i = 0;
+  j = 0;
+  while (i < N_ITERATIONS)
+    {
+      to_free[j] = _dbus_mem_pool_alloc (pool); 
+      _dbus_assert (to_free[j] != NULL);  /* in a real app of course this is wrong */
+
+      ++j;
+
+      if (j == FREE_ARRAY_SIZE)
+        {
+          j = 0;
+          while (j < FREE_ARRAY_SIZE)
+            {
+              _dbus_mem_pool_dealloc (pool, to_free[j]);
+              ++j;
+            }
+
+          j = 0;
+        }
+      
+      ++i;
+    }
+
+  _dbus_mem_pool_free (pool);
+  
+  end = clock ();
+
+  _dbus_verbose ("  created/destroyed %d elements in %g seconds\n",
+                 N_ITERATIONS, (end - start) / (double) CLOCKS_PER_SEC);
+}
+
+/**
+ * @ingroup DBusMemPoolInternals
+ * Unit test for DBusMemPool
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_mem_pool_test (void)
+{
+  int i;
+  int element_sizes[] = { 4, 8, 16, 50, 124 };
+  
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (element_sizes))
+    {
+      time_for_size (element_sizes[i]);
+      ++i;
+    }
+  
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-mempool.h b/dbus/dbus/dbus-mempool.h
new file mode 100644
index 0000000..6693eeb
--- /dev/null
+++ b/dbus/dbus/dbus-mempool.h
@@ -0,0 +1,50 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-mempool.h Memory pools
+ * 
+ * Copyright (C) 2002  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_MEMPOOL_H
+#define DBUS_MEMPOOL_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-memory.h>
+#include <dbus/dbus-types.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusMemPool DBusMemPool;
+
+DBusMemPool* _dbus_mem_pool_new     (int          element_size,
+                                     dbus_bool_t  zero_elements);
+void         _dbus_mem_pool_free    (DBusMemPool *pool);
+void*        _dbus_mem_pool_alloc   (DBusMemPool *pool);
+dbus_bool_t  _dbus_mem_pool_dealloc (DBusMemPool *pool,
+                                     void        *element);
+
+/* if DBUS_ENABLE_STATS */
+void         _dbus_mem_pool_get_stats (DBusMemPool   *pool,
+                                       dbus_uint32_t *in_use_p,
+                                       dbus_uint32_t *in_free_list_p,
+                                       dbus_uint32_t *allocated_p);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_MEMPOOL_H */
diff --git a/dbus/dbus/dbus-message-factory.c b/dbus/dbus/dbus-message-factory.c
new file mode 100644
index 0000000..efa4e02
--- /dev/null
+++ b/dbus/dbus/dbus-message-factory.c
@@ -0,0 +1,1305 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-message-factory.c Generator of valid and invalid message data for test suite
+ *
+ * Copyright (C) 2005 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#include <config.h>
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-message-factory.h"
+#include "dbus-message-private.h"
+#include "dbus-signature.h"
+#include "dbus-test.h"
+#include <stdio.h>
+
+typedef enum
+  {
+    CHANGE_TYPE_ADJUST,
+    CHANGE_TYPE_ABSOLUTE
+  } ChangeType;
+
+#define BYTE_ORDER_OFFSET  0
+#define TYPE_OFFSET        1
+#define BODY_LENGTH_OFFSET 4
+#define FIELDS_ARRAY_LENGTH_OFFSET 12
+
+static void
+iter_recurse (DBusMessageDataIter *iter)
+{
+  iter->depth += 1;
+  _dbus_assert (iter->depth < _DBUS_MESSAGE_DATA_MAX_NESTING);
+  _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
+}
+
+static int
+iter_get_sequence (DBusMessageDataIter *iter)
+{
+  _dbus_assert (iter->sequence_nos[iter->depth] >= 0);
+  return iter->sequence_nos[iter->depth];
+}
+
+static void
+iter_set_sequence (DBusMessageDataIter *iter,
+                   int                  sequence)
+{
+  _dbus_assert (sequence >= 0);
+  iter->sequence_nos[iter->depth] = sequence;
+}
+
+static void
+iter_unrecurse (DBusMessageDataIter *iter)
+{
+  iter->depth -= 1;
+  _dbus_assert (iter->depth >= 0);
+}
+
+static void
+iter_next (DBusMessageDataIter *iter)
+{
+  iter->sequence_nos[iter->depth] += 1;
+}
+
+static dbus_bool_t
+iter_first_in_series (DBusMessageDataIter *iter)
+{
+  int i;
+
+  i = iter->depth;
+  while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
+    {
+      if (iter->sequence_nos[i] != 0)
+        return FALSE;
+      ++i;
+    }
+  return TRUE;
+}
+
+typedef dbus_bool_t (* DBusInnerGeneratorFunc)   (DBusMessageDataIter *iter,
+                                                  DBusMessage        **message_p);
+typedef dbus_bool_t (* DBusMessageGeneratorFunc) (DBusMessageDataIter *iter,
+                                                  DBusString          *data,
+                                                  DBusValidity        *expected_validity);
+
+static void
+set_reply_serial (DBusMessage *message)
+{
+  if (message == NULL)
+    _dbus_assert_not_reached ("oom");
+  if (!dbus_message_set_reply_serial (message, 100))
+    _dbus_assert_not_reached ("oom");
+}
+
+static dbus_bool_t
+generate_trivial_inner (DBusMessageDataIter *iter,
+                        DBusMessage        **message_p)
+{
+  DBusMessage *message;
+
+  switch (iter_get_sequence (iter))
+    {
+    case 0:
+      message = dbus_message_new_method_call ("org.freedesktop.TextEditor",
+                                              "/foo/bar",
+                                              "org.freedesktop.DocumentFactory",
+                                              "Create");
+      break;
+    case 1:
+      message = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
+      set_reply_serial (message);
+      break;
+    case 2:
+      message = dbus_message_new_signal ("/foo/bar",
+                                         "org.freedesktop.DocumentFactory",
+                                         "Created");
+      break;
+    case 3:
+      message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
+
+      if (!dbus_message_set_error_name (message,
+                                        "org.freedesktop.TestErrorName"))
+        _dbus_assert_not_reached ("oom");
+      
+      {
+        DBusMessageIter iter;
+        const char *v_STRING = "This is an error";
+        
+        dbus_message_iter_init_append (message, &iter);
+        if (!dbus_message_iter_append_basic (&iter,
+                                             DBUS_TYPE_STRING,
+                                             &v_STRING))
+          _dbus_assert_not_reached ("oom");
+      }
+      
+      set_reply_serial (message);
+      break;
+    default:
+      return FALSE;
+    }
+  
+  if (message == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  *message_p = message;
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+generate_many_bodies_inner (DBusMessageDataIter *iter,
+                            DBusMessage        **message_p)
+{
+  DBusMessage *message;
+  DBusString signature;
+  DBusString body;
+  char byte_order;
+
+  /* Keeping this small makes things go faster */
+  message = dbus_message_new_method_call ("o.z.F",
+                                          "/",
+                                          "o.z.B",
+                                          "Nah");
+  if (message == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  byte_order = _dbus_header_get_byte_order (&message->header);
+
+  set_reply_serial (message);
+
+  if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
+    _dbus_assert_not_reached ("oom");
+  
+  if (dbus_internal_do_not_use_generate_bodies (iter_get_sequence (iter),
+                                                byte_order,
+                                                &signature, &body))
+    {
+      const char *v_SIGNATURE;
+
+      v_SIGNATURE = _dbus_string_get_const_data (&signature);
+      if (!_dbus_header_set_field_basic (&message->header,
+                                         DBUS_HEADER_FIELD_SIGNATURE,
+                                         DBUS_TYPE_SIGNATURE,
+                                         &v_SIGNATURE))
+        _dbus_assert_not_reached ("oom");
+
+      if (!_dbus_string_move (&body, 0, &message->body, 0))
+        _dbus_assert_not_reached ("oom");
+
+      _dbus_marshal_set_uint32 (&message->header.data, BODY_LENGTH_OFFSET,
+                                _dbus_string_get_length (&message->body),
+                                byte_order);
+      
+      *message_p = message;
+    }
+  else
+    {
+      dbus_message_unref (message);
+      *message_p = NULL;
+    }
+  
+  _dbus_string_free (&signature);
+  _dbus_string_free (&body);
+
+  return *message_p != NULL;
+}
+
+static void
+generate_from_message (DBusString            *data,
+                       DBusValidity          *expected_validity,
+                       DBusMessage           *message)
+{
+  dbus_message_set_serial (message, 1);
+  dbus_message_lock (message);
+
+  *expected_validity = DBUS_VALID;
+  
+  /* move for efficiency, since we'll nuke the message anyway */
+  if (!_dbus_string_move (&message->header.data, 0,
+                          data, 0))
+    _dbus_assert_not_reached ("oom");
+
+  if (!_dbus_string_copy (&message->body, 0,
+                          data, _dbus_string_get_length (data)))
+    _dbus_assert_not_reached ("oom");
+}
+
+static dbus_bool_t
+generate_outer (DBusMessageDataIter   *iter,
+                DBusString            *data,
+                DBusValidity          *expected_validity,
+                DBusInnerGeneratorFunc func)
+{
+  DBusMessage *message;
+
+  message = NULL;
+  if (!(*func)(iter, &message))
+    return FALSE;
+
+  iter_next (iter);
+  
+  _dbus_assert (message != NULL);
+
+  generate_from_message (data, expected_validity, message);
+
+  dbus_message_unref (message);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+generate_trivial (DBusMessageDataIter   *iter,
+                  DBusString            *data,
+                  DBusValidity          *expected_validity)
+{
+  return generate_outer (iter, data, expected_validity,
+                         generate_trivial_inner);
+}
+
+static dbus_bool_t
+generate_many_bodies (DBusMessageDataIter   *iter,
+                      DBusString            *data,
+                      DBusValidity          *expected_validity)
+{
+  return generate_outer (iter, data, expected_validity,
+                         generate_many_bodies_inner);
+}
+
+static DBusMessage*
+simple_method_call (void)
+{
+  DBusMessage *message;
+  /* Keeping this small makes stuff go faster */
+  message = dbus_message_new_method_call ("o.b.Q",
+                                          "/f/b",
+                                          "o.b.Z",
+                                          "Fro");
+  if (message == NULL)
+    _dbus_assert_not_reached ("oom");
+  return message;
+}
+
+static DBusMessage*
+simple_signal (void)
+{
+  DBusMessage *message;
+  message = dbus_message_new_signal ("/f/b",
+                                     "o.b.Z",
+                                     "Fro");
+  if (message == NULL)
+    _dbus_assert_not_reached ("oom");
+  return message;
+}
+
+static DBusMessage*
+simple_method_return (void)
+{
+  DBusMessage *message;
+  message =  dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_RETURN);
+  if (message == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  set_reply_serial (message);
+  
+  return message;
+}
+
+static DBusMessage*
+simple_error (void)
+{
+  DBusMessage *message;
+  message =  dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
+  if (message == NULL)
+    _dbus_assert_not_reached ("oom");
+
+  if (!dbus_message_set_error_name (message, "foo.bar"))
+    _dbus_assert_not_reached ("oom");
+  
+  set_reply_serial (message);
+  
+  return message;
+}
+
+static DBusMessage*
+message_with_nesting_levels (int levels)
+{
+  DBusMessage *message;
+  dbus_int32_t v_INT32;
+  DBusMessageIter *parents;
+  DBusMessageIter *children;
+  int i;
+
+  /* If levels is higher it breaks sig_refcount in DBusMessageRealIter
+   * in dbus-message.c, this assert is just to help you know you need
+   * to fix that if you hit it
+   */
+  _dbus_assert (levels < 256);
+
+  parents = dbus_new(DBusMessageIter, levels + 1);
+  children = dbus_new(DBusMessageIter, levels + 1);
+
+  v_INT32 = 42;
+  message = simple_method_call ();
+
+  i = 0;
+  dbus_message_iter_init_append (message, &parents[i]);
+  while (i < levels)
+    {
+      dbus_message_iter_open_container (&parents[i], DBUS_TYPE_VARIANT,
+                                        i == (levels - 1) ?
+                                        DBUS_TYPE_INT32_AS_STRING :
+                                        DBUS_TYPE_VARIANT_AS_STRING,
+                                        &children[i]);
+      ++i;
+      parents[i] = children[i-1];
+    }
+  --i;
+  dbus_message_iter_append_basic (&children[i], DBUS_TYPE_INT32, &v_INT32);
+  while (i >= 0)
+    {
+      dbus_message_iter_close_container (&parents[i], &children[i]);
+      --i;
+    }
+
+  dbus_free(parents);
+  dbus_free(children);
+
+  return message;
+}
+
+static dbus_bool_t
+generate_special (DBusMessageDataIter   *iter,
+                  DBusString            *data,
+                  DBusValidity          *expected_validity)
+{
+  int item_seq;
+  DBusMessage *message;
+  int pos;
+  dbus_int32_t v_INT32;
+
+  _dbus_assert (_dbus_string_get_length (data) == 0);
+  
+  message = NULL;
+  pos = -1;
+  v_INT32 = 42;
+  item_seq = iter_get_sequence (iter);
+
+  if (item_seq == 0)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      /* set an invalid typecode */
+      _dbus_string_set_byte (data, pos + 1, '$');
+
+      *expected_validity = DBUS_INVALID_UNKNOWN_TYPECODE;
+    }
+  else if (item_seq == 1)
+    {
+      char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH+2];
+      const char *v_STRING;
+      int i;
+      
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+
+      i = 0;
+      while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
+        {
+          long_sig[i] = DBUS_TYPE_ARRAY;
+          ++i;
+        }
+      long_sig[i] = DBUS_TYPE_INVALID;
+
+      v_STRING = long_sig;
+      if (!_dbus_header_set_field_basic (&message->header,
+                                         DBUS_HEADER_FIELD_SIGNATURE,
+                                         DBUS_TYPE_SIGNATURE,
+                                         &v_STRING))
+        _dbus_assert_not_reached ("oom");
+      
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
+    }
+  else if (item_seq == 2)
+    {
+      char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2+4];
+      const char *v_STRING;
+      int i;
+      
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+
+      i = 0;
+      while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH + 1))
+        {
+          long_sig[i] = DBUS_STRUCT_BEGIN_CHAR;
+          ++i;
+        }
+
+      long_sig[i] = DBUS_TYPE_INT32;
+      ++i;
+
+      while (i < (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*2 + 3))
+        {
+          long_sig[i] = DBUS_STRUCT_END_CHAR;
+          ++i;
+        }
+      long_sig[i] = DBUS_TYPE_INVALID;
+      
+      v_STRING = long_sig;
+      if (!_dbus_header_set_field_basic (&message->header,
+                                         DBUS_HEADER_FIELD_SIGNATURE,
+                                         DBUS_TYPE_SIGNATURE,
+                                         &v_STRING))
+        _dbus_assert_not_reached ("oom");
+      
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
+    }
+  else if (item_seq == 3)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
+      
+      *expected_validity = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
+    }
+  else if (item_seq == 4)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_END_CHAR);
+      
+      *expected_validity = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
+    }
+  else if (item_seq == 5)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, pos + 1, DBUS_STRUCT_BEGIN_CHAR);
+      _dbus_string_set_byte (data, pos + 2, DBUS_STRUCT_END_CHAR);
+      
+      *expected_validity = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
+    }
+  else if (item_seq == 6)
+    {
+      message = simple_method_call ();
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, TYPE_OFFSET, DBUS_MESSAGE_TYPE_INVALID);
+      
+      *expected_validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
+    }
+  else if (item_seq == 7)
+    {
+      /* Messages of unknown type are considered valid */
+      message = simple_method_call ();
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, TYPE_OFFSET, 100);
+      
+      *expected_validity = DBUS_VALID;
+    }
+  else if (item_seq == 8)
+    {
+      char byte_order;
+
+      message = simple_method_call ();
+      byte_order = _dbus_header_get_byte_order (&message->header);
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
+                                DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
+                                byte_order);
+      _dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET,
+                                DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
+                                byte_order);
+      *expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG;
+    }
+  else if (item_seq == 9)
+    {
+      const char *v_STRING = "not a valid bus name";
+      message = simple_method_call ();
+
+      if (!_dbus_header_set_field_basic (&message->header,
+                                         DBUS_HEADER_FIELD_SENDER,
+                                         DBUS_TYPE_STRING, &v_STRING))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+
+      *expected_validity = DBUS_INVALID_BAD_SENDER;
+    }
+  else if (item_seq == 10)
+    {
+      message = simple_method_call ();
+
+      if (!dbus_message_set_interface (message, DBUS_INTERFACE_LOCAL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+
+      *expected_validity = DBUS_INVALID_USES_LOCAL_INTERFACE;
+    }
+  else if (item_seq == 11)
+    {
+      message = simple_method_call ();
+
+      if (!dbus_message_set_path (message, DBUS_PATH_LOCAL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+
+      *expected_validity = DBUS_INVALID_USES_LOCAL_PATH;
+    }
+  else if (item_seq == 12)
+    {
+      /* Method calls don't have to have interface */
+      message = simple_method_call ();
+
+      if (!dbus_message_set_interface (message, NULL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_VALID;
+    }
+  else if (item_seq == 13)
+    {
+      /* Signals require an interface */
+      message = simple_signal ();
+
+      if (!dbus_message_set_interface (message, NULL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_INVALID_MISSING_INTERFACE;
+    }
+  else if (item_seq == 14)
+    {
+      message = simple_method_return ();
+
+      if (!_dbus_header_delete_field (&message->header, DBUS_HEADER_FIELD_REPLY_SERIAL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_INVALID_MISSING_REPLY_SERIAL;
+    }
+  else if (item_seq == 15)
+    {
+      message = simple_error ();
+
+      if (!dbus_message_set_error_name (message, NULL))
+        _dbus_assert_not_reached ("oom");
+      
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_INVALID_MISSING_ERROR_NAME;
+    }
+  else if (item_seq == 16)
+    {
+      char long_sig[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*4+10];
+      const char *v_STRING;
+      int i;
+      int n_begins;
+      
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+
+      i = 0;
+      while (i <= (DBUS_MAXIMUM_TYPE_RECURSION_DEPTH*3 + 3))
+        {
+          long_sig[i] = DBUS_TYPE_ARRAY;
+          ++i;
+          long_sig[i] = DBUS_DICT_ENTRY_BEGIN_CHAR;
+          ++i;
+          long_sig[i] = DBUS_TYPE_INT32;
+          ++i;
+        }
+      n_begins = i / 3;
+
+      long_sig[i] = DBUS_TYPE_INT32;
+      ++i;
+      
+      while (n_begins > 0)
+        {
+          long_sig[i] = DBUS_DICT_ENTRY_END_CHAR;
+          ++i;
+          n_begins -= 1;
+        }
+      long_sig[i] = DBUS_TYPE_INVALID;
+      
+      v_STRING = long_sig;
+      if (!_dbus_header_set_field_basic (&message->header,
+                                         DBUS_HEADER_FIELD_SIGNATURE,
+                                         DBUS_TYPE_SIGNATURE,
+                                         &v_STRING))
+        _dbus_assert_not_reached ("oom");
+      
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      *expected_validity = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
+    }
+  else if (item_seq == 17)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+
+      _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
+      _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR);
+      
+      *expected_validity = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
+    }
+  else if (item_seq == 18)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+      
+      _dbus_string_set_byte (data, pos + 1, DBUS_DICT_ENTRY_END_CHAR);
+      
+      *expected_validity = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
+    }
+  else if (item_seq == 19)
+    {
+      message = simple_method_call ();
+      if (!dbus_message_append_args (message,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INT32, &v_INT32,
+                                     DBUS_TYPE_INVALID))
+        _dbus_assert_not_reached ("oom");
+                                     
+      _dbus_header_get_field_raw (&message->header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  NULL, &pos);
+      generate_from_message (data, expected_validity, message);
+
+      _dbus_string_set_byte (data, pos + 1, DBUS_TYPE_ARRAY);
+      _dbus_string_set_byte (data, pos + 2, DBUS_DICT_ENTRY_BEGIN_CHAR);
+      _dbus_string_set_byte (data, pos + 3, DBUS_DICT_ENTRY_END_CHAR);
+      
+      *expected_validity = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
+    }
+  else if (item_seq == 20)
+    {
+      /* 64 levels of nesting is OK */
+      message = message_with_nesting_levels(64);
+
+      generate_from_message (data, expected_validity, message);
+
+      *expected_validity = DBUS_VALID;
+    }
+  else if (item_seq == 21)
+    {
+      /* 65 levels of nesting is not OK */
+      message = message_with_nesting_levels(65);
+
+      generate_from_message (data, expected_validity, message);
+
+      *expected_validity = DBUS_INVALID_NESTED_TOO_DEEPLY;
+    }
+  else
+    {
+      return FALSE;
+    }
+
+  if (message)
+    dbus_message_unref (message);
+
+  iter_next (iter);
+  return TRUE;
+}
+
+static dbus_bool_t
+generate_wrong_length (DBusMessageDataIter *iter,
+                       DBusString          *data,
+                       DBusValidity        *expected_validity)
+{
+  int lengths[] = { -42, -17, -16, -15, -9, -8, -7, -6, -5, -4, -3, -2, -1,
+                    1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 30 };
+  int adjust;
+  int len_seq;
+
+ restart:
+  len_seq = iter_get_sequence (iter);
+  if (len_seq == _DBUS_N_ELEMENTS (lengths))
+    return FALSE;
+
+  _dbus_assert (len_seq < _DBUS_N_ELEMENTS (lengths));
+  
+  iter_recurse (iter);
+  if (!generate_many_bodies (iter, data, expected_validity))
+    {
+      iter_set_sequence (iter, 0); /* reset to first body */
+      iter_unrecurse (iter);
+      iter_next (iter);            /* next length adjustment */
+      goto restart;
+    }
+  iter_unrecurse (iter);
+
+  adjust = lengths[len_seq];
+
+  if (adjust < 0)
+    {
+      if ((_dbus_string_get_length (data) + adjust) < DBUS_MINIMUM_HEADER_SIZE)
+        _dbus_string_set_length (data, DBUS_MINIMUM_HEADER_SIZE);
+      else
+        _dbus_string_shorten (data, - adjust);
+      *expected_validity = DBUS_INVALID_FOR_UNKNOWN_REASON;
+    }
+  else
+    {      
+      if (!_dbus_string_lengthen (data, adjust))
+        _dbus_assert_not_reached ("oom");
+      *expected_validity = DBUS_INVALID_TOO_MUCH_DATA;
+    }
+
+  /* Fixup lengths */
+  {
+    int old_body_len;
+    int new_body_len;
+    int byte_order;
+    
+    _dbus_assert (_dbus_string_get_length (data) >= DBUS_MINIMUM_HEADER_SIZE);
+    
+    byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
+    old_body_len = _dbus_marshal_read_uint32 (data,
+                                              BODY_LENGTH_OFFSET,
+                                              byte_order,
+                                              NULL);
+    _dbus_assert (old_body_len < _dbus_string_get_length (data));
+    new_body_len = old_body_len + adjust;
+    if (new_body_len < 0)
+      {
+        new_body_len = 0;
+        /* we just munged the header, and aren't sure how */
+        *expected_validity = DBUS_VALIDITY_UNKNOWN;
+      }
+
+    _dbus_verbose ("changing body len from %u to %u by adjust %d\n",
+                   old_body_len, new_body_len, adjust);
+    
+    _dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
+                              new_body_len,
+                              byte_order);
+  }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+generate_byte_changed (DBusMessageDataIter *iter,
+                       DBusString          *data,
+                       DBusValidity        *expected_validity)
+{
+  int byte_seq;
+  int v_BYTE;
+
+  /* This is a little convoluted to make the bodies the
+   * outer loop and each byte of each body the inner
+   * loop
+   */
+
+ restart:
+  if (!generate_many_bodies (iter, data, expected_validity))
+    return FALSE;
+
+  iter_recurse (iter);
+  byte_seq = iter_get_sequence (iter);
+  iter_next (iter);
+  iter_unrecurse (iter);
+  
+  if (byte_seq == _dbus_string_get_length (data))
+    {
+      _dbus_string_set_length (data, 0);
+      /* reset byte count */
+      iter_recurse (iter);
+      iter_set_sequence (iter, 0);
+      iter_unrecurse (iter);
+      goto restart;
+    }
+  else
+    {
+      /* Undo the "next" in generate_many_bodies */
+      iter_set_sequence (iter, iter_get_sequence (iter) - 1);
+    }
+
+  _dbus_assert (byte_seq < _dbus_string_get_length (data));
+  v_BYTE = _dbus_string_get_byte (data, byte_seq);
+  v_BYTE += byte_seq; /* arbitrary but deterministic change to the byte */
+  _dbus_string_set_byte (data, byte_seq, v_BYTE);
+  *expected_validity = DBUS_VALIDITY_UNKNOWN;
+
+  return TRUE;
+}
+
+#if 0
+/* This is really expensive and doesn't add too much coverage */
+
+static dbus_bool_t
+find_next_typecode (DBusMessageDataIter *iter,
+                    DBusString          *data,
+                    DBusValidity        *expected_validity)
+{
+  int body_seq;
+  int byte_seq;
+  int base_depth;
+
+  base_depth = iter->depth;
+
+ restart:
+  _dbus_assert (iter->depth == (base_depth + 0));
+  _dbus_string_set_length (data, 0);
+
+  body_seq = iter_get_sequence (iter);
+  
+  if (!generate_many_bodies (iter, data, expected_validity))
+    return FALSE;
+  /* Undo the "next" in generate_many_bodies */
+  iter_set_sequence (iter, body_seq);
+  
+  iter_recurse (iter);
+  while (TRUE)
+    {
+      _dbus_assert (iter->depth == (base_depth + 1));
+      
+      byte_seq = iter_get_sequence (iter);
+
+      _dbus_assert (byte_seq <= _dbus_string_get_length (data));
+      
+      if (byte_seq == _dbus_string_get_length (data))
+        {
+          /* reset byte count */
+          iter_set_sequence (iter, 0);
+          iter_unrecurse (iter);
+          _dbus_assert (iter->depth == (base_depth + 0));
+          iter_next (iter); /* go to the next body */
+          goto restart;
+        }
+
+      _dbus_assert (byte_seq < _dbus_string_get_length (data));
+
+      if (dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
+        break;
+      else
+        iter_next (iter);
+    }
+
+  _dbus_assert (byte_seq == iter_get_sequence (iter));
+  _dbus_assert (byte_seq < _dbus_string_get_length (data));
+
+  iter_unrecurse (iter);
+
+  _dbus_assert (iter->depth == (base_depth + 0));
+  
+  return TRUE;
+}
+
+static const int typecodes[] = {
+  DBUS_TYPE_INVALID,
+  DBUS_TYPE_BYTE,
+  DBUS_TYPE_BOOLEAN,
+  DBUS_TYPE_INT16,
+  DBUS_TYPE_UINT16,
+  DBUS_TYPE_INT32,
+  DBUS_TYPE_UINT32,
+  DBUS_TYPE_INT64,
+  DBUS_TYPE_UINT64,
+  DBUS_TYPE_DOUBLE,
+  DBUS_TYPE_STRING,
+  DBUS_TYPE_OBJECT_PATH,
+  DBUS_TYPE_SIGNATURE,
+  DBUS_TYPE_ARRAY,
+  DBUS_TYPE_VARIANT,
+  DBUS_STRUCT_BEGIN_CHAR,
+  DBUS_STRUCT_END_CHAR,
+  DBUS_DICT_ENTRY_BEGIN_CHAR,
+  DBUS_DICT_ENTRY_END_CHAR,
+  DBUS_TYPE_UNIX_FD,
+  255 /* random invalid typecode */
+};
+
+static dbus_bool_t
+generate_typecode_changed (DBusMessageDataIter *iter,
+                           DBusString          *data,
+                           DBusValidity        *expected_validity)
+{
+  int byte_seq;
+  int typecode_seq;
+  int base_depth;
+
+  base_depth = iter->depth;
+
+ restart:
+  _dbus_assert (iter->depth == (base_depth + 0));
+  _dbus_string_set_length (data, 0);
+  
+  if (!find_next_typecode (iter, data, expected_validity))
+    return FALSE;
+
+  iter_recurse (iter);
+  byte_seq = iter_get_sequence (iter);
+
+  _dbus_assert (byte_seq < _dbus_string_get_length (data));
+  
+  iter_recurse (iter);
+  typecode_seq = iter_get_sequence (iter);
+  iter_next (iter);
+
+  _dbus_assert (typecode_seq <= _DBUS_N_ELEMENTS (typecodes));
+  
+  if (typecode_seq == _DBUS_N_ELEMENTS (typecodes))
+    {
+      _dbus_assert (iter->depth == (base_depth + 2));
+      iter_set_sequence (iter, 0); /* reset typecode sequence */
+      iter_unrecurse (iter);
+      _dbus_assert (iter->depth == (base_depth + 1));
+      iter_next (iter); /* go to the next byte_seq */
+      iter_unrecurse (iter);
+      _dbus_assert (iter->depth == (base_depth + 0));
+      goto restart;
+    }
+
+  _dbus_assert (iter->depth == (base_depth + 2));
+  iter_unrecurse (iter);
+  _dbus_assert (iter->depth == (base_depth + 1));
+  iter_unrecurse (iter);
+  _dbus_assert (iter->depth == (base_depth + 0));
+
+#if 0
+  printf ("Changing byte %d in message %d to %c\n",
+          byte_seq, iter_get_sequence (iter), typecodes[typecode_seq]);
+#endif
+  
+  _dbus_string_set_byte (data, byte_seq, typecodes[typecode_seq]);
+  *expected_validity = DBUS_VALIDITY_UNKNOWN;
+  return TRUE;
+}
+#endif
+
+typedef struct
+{
+  ChangeType type;
+  dbus_uint32_t value; /* cast to signed for adjusts */
+} UIntChange;
+
+static const UIntChange uint32_changes[] = {
+  { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -1 },
+  { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -2 },
+  { CHANGE_TYPE_ADJUST, (dbus_uint32_t) -3 },
+  { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 1 },
+  { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 2 },
+  { CHANGE_TYPE_ADJUST, (dbus_uint32_t) 3 },
+  { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX },
+  { CHANGE_TYPE_ABSOLUTE, 0 },
+  { CHANGE_TYPE_ABSOLUTE, 1 },
+  { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 1 },
+  { CHANGE_TYPE_ABSOLUTE, _DBUS_UINT32_MAX - 5 }
+};
+
+static dbus_bool_t
+generate_uint32_changed (DBusMessageDataIter *iter,
+                         DBusString          *data,
+                         DBusValidity        *expected_validity)
+{
+  int body_seq;
+  int byte_seq;
+  int change_seq;
+  dbus_uint32_t v_UINT32;
+  int byte_order;
+  const UIntChange *change;
+  int base_depth;
+
+  /* Outer loop is each body, next loop is each change,
+   * inner loop is each change location
+   */
+
+  base_depth = iter->depth;
+  
+ next_body:
+  _dbus_assert (iter->depth == (base_depth + 0));
+  _dbus_string_set_length (data, 0);
+  body_seq = iter_get_sequence (iter);
+  
+  if (!generate_many_bodies (iter, data, expected_validity))
+    return FALSE;
+
+  _dbus_assert (iter->depth == (base_depth + 0));
+
+  iter_set_sequence (iter, body_seq); /* undo the "next" from generate_many_bodies */
+  iter_recurse (iter);
+ next_change:
+  _dbus_assert (iter->depth == (base_depth + 1));
+  change_seq = iter_get_sequence (iter);
+  
+  if (change_seq == _DBUS_N_ELEMENTS (uint32_changes))
+    {
+      /* Reset change count */
+      iter_set_sequence (iter, 0);
+      iter_unrecurse (iter);
+      iter_next (iter);
+      goto next_body;
+    }
+
+  _dbus_assert (iter->depth == (base_depth + 1));
+  
+  iter_recurse (iter);
+  _dbus_assert (iter->depth == (base_depth + 2));
+  byte_seq = iter_get_sequence (iter);
+  /* skip 4 bytes at a time */
+  iter_next (iter);
+  iter_next (iter);
+  iter_next (iter);
+  iter_next (iter);
+  iter_unrecurse (iter);
+
+  _dbus_assert (_DBUS_ALIGN_VALUE (byte_seq, 4) == (unsigned) byte_seq);
+  if (byte_seq >= (_dbus_string_get_length (data) - 4))
+    {
+      /* reset byte count */
+      _dbus_assert (iter->depth == (base_depth + 1));
+      iter_recurse (iter);
+      _dbus_assert (iter->depth == (base_depth + 2));
+      iter_set_sequence (iter, 0);
+      iter_unrecurse (iter);
+      _dbus_assert (iter->depth == (base_depth + 1));
+      iter_next (iter);
+      goto next_change;
+    }
+  
+  _dbus_assert (byte_seq <= (_dbus_string_get_length (data) - 4));
+
+  byte_order = _dbus_string_get_byte (data, BYTE_ORDER_OFFSET);
+  
+  v_UINT32 = _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL);
+
+  change = &uint32_changes[change_seq];
+
+  if (change->type == CHANGE_TYPE_ADJUST)
+    {
+      v_UINT32 += (int) change->value;
+    }
+  else
+    {
+      v_UINT32 = change->value;
+    }
+
+#if 0
+  printf ("body %d change %d pos %d ",
+          body_seq, change_seq, byte_seq);
+
+  if (change->type == CHANGE_TYPE_ADJUST)
+    printf ("adjust by %d", (int) change->value);
+  else
+    printf ("set to %u", change->value);
+  
+  printf (" \t%u -> %u\n",
+          _dbus_marshal_read_uint32 (data, byte_seq, byte_order, NULL),
+          v_UINT32);
+#endif
+  
+  _dbus_marshal_set_uint32 (data, byte_seq, v_UINT32, byte_order);
+  *expected_validity = DBUS_VALIDITY_UNKNOWN;
+
+  _dbus_assert (iter->depth == (base_depth + 1));
+  iter_unrecurse (iter);
+  _dbus_assert (iter->depth == (base_depth + 0));
+          
+  return TRUE;
+}
+
+typedef struct
+{
+  const char *name;
+  DBusMessageGeneratorFunc func;  
+} DBusMessageGenerator;
+
+static const DBusMessageGenerator generators[] = {
+  { "trivial example of each message type", generate_trivial },
+  { "assorted arguments", generate_many_bodies },
+  { "assorted special cases", generate_special },
+  { "each uint32 modified", generate_uint32_changed },
+  { "wrong body lengths", generate_wrong_length },
+  { "each byte modified", generate_byte_changed },
+#if 0
+  /* This is really expensive and doesn't add too much coverage */
+  { "change each typecode", generate_typecode_changed }
+#endif
+};
+
+void
+_dbus_message_data_free (DBusMessageData *data)
+{
+  _dbus_string_free (&data->data);
+}
+
+void
+_dbus_message_data_iter_init (DBusMessageDataIter *iter)
+{
+  int i;
+  
+  iter->depth = 0;
+  i = 0;
+  while (i < _DBUS_MESSAGE_DATA_MAX_NESTING)
+    {
+      iter->sequence_nos[i] = 0;
+      ++i;
+    }
+  iter->count = 0;
+}
+
+dbus_bool_t
+_dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter,
+                                      DBusMessageData     *data)
+{
+  DBusMessageGeneratorFunc func;
+  int generator;
+
+ restart:
+  generator = iter_get_sequence (iter);
+  
+  if (generator == _DBUS_N_ELEMENTS (generators))
+    return FALSE;
+
+  iter_recurse (iter);
+  
+  if (iter_first_in_series (iter))
+    {
+      printf (" testing message loading: %s ", generators[generator].name);
+      fflush (stdout);
+    }
+  
+  func = generators[generator].func;
+
+  if (!_dbus_string_init (&data->data))
+    _dbus_assert_not_reached ("oom");
+  
+  if ((*func)(iter, &data->data, &data->expected_validity))
+    ;
+  else
+    {
+      iter_set_sequence (iter, 0);
+      iter_unrecurse (iter);
+      iter_next (iter); /* next generator */
+      _dbus_string_free (&data->data);
+      printf ("%d test loads cumulative\n", iter->count);
+      goto restart;
+    }
+  iter_unrecurse (iter);
+
+  iter->count += 1;
+  return TRUE;
+}
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-message-factory.h b/dbus/dbus/dbus-message-factory.h
new file mode 100644
index 0000000..b074750
--- /dev/null
+++ b/dbus/dbus/dbus-message-factory.h
@@ -0,0 +1,61 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-message-factory.h Generator of valid and invalid message data for test suite
+ *
+ * Copyright (C) 2005 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_MESSAGE_FACTORY_H
+#define DBUS_MESSAGE_FACTORY_H
+
+#ifdef DBUS_BUILD_TESTS
+
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-marshal-basic.h>
+#include <dbus/dbus-marshal-validate.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct
+{
+  DBusValidity expected_validity;
+  
+  DBusString data;
+
+} DBusMessageData;
+
+#define _DBUS_MESSAGE_DATA_MAX_NESTING 10
+typedef struct
+{
+  int sequence_nos[_DBUS_MESSAGE_DATA_MAX_NESTING];
+  int depth;
+  int count;
+} DBusMessageDataIter;
+
+void        _dbus_message_data_free              (DBusMessageData     *data);
+void        _dbus_message_data_iter_init         (DBusMessageDataIter *iter);
+dbus_bool_t _dbus_message_data_iter_get_and_next (DBusMessageDataIter *iter,
+                                                  DBusMessageData     *data);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_BUILD_TESTS */
+
+#endif /* DBUS_MESSAGE_FACTORY_H */
diff --git a/dbus/dbus/dbus-message-internal.h b/dbus/dbus/dbus-message-internal.h
new file mode 100644
index 0000000..c194873
--- /dev/null
+++ b/dbus/dbus/dbus-message-internal.h
@@ -0,0 +1,107 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-message-internal.h DBusMessage object internal interfaces
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_MESSAGE_INTERNAL_H
+#define DBUS_MESSAGE_INTERNAL_H
+
+#include <dbus/dbus-marshal-validate.h>
+#include <dbus/dbus-message.h>
+#include <dbus/dbus-resources.h>
+#include <dbus/dbus-list.h>
+
+DBUS_BEGIN_DECLS
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+void _dbus_message_trace_ref (DBusMessage *message,
+                              int          old_refcount,
+                              int          new_refcount,
+                              const char  *why);
+#else
+/* this bypasses any "unused" warnings for the old and new refcount */
+#define _dbus_message_trace_ref(m, o, n, w) \
+  do \
+  {\
+    (void) (o); \
+    (void) (n); \
+  } while (0)
+#endif
+
+typedef struct DBusMessageLoader DBusMessageLoader;
+
+void _dbus_message_get_network_data  (DBusMessage       *message,
+				      const DBusString **header,
+				      const DBusString **body);
+void _dbus_message_get_unix_fds      (DBusMessage *message,
+                                      const int **fds,
+                                      unsigned *n_fds);
+
+void        _dbus_message_lock                  (DBusMessage  *message);
+void        _dbus_message_unlock                (DBusMessage  *message);
+dbus_bool_t _dbus_message_add_counter           (DBusMessage  *message,
+                                                 DBusCounter  *counter);
+void        _dbus_message_add_counter_link      (DBusMessage  *message,
+                                                 DBusList     *link);
+void        _dbus_message_remove_counter        (DBusMessage  *message,
+                                                 DBusCounter  *counter);
+
+DBusMessageLoader* _dbus_message_loader_new                   (void);
+DBusMessageLoader* _dbus_message_loader_ref                   (DBusMessageLoader  *loader);
+void               _dbus_message_loader_unref                 (DBusMessageLoader  *loader);
+
+void               _dbus_message_loader_get_buffer            (DBusMessageLoader  *loader,
+                                                               DBusString        **buffer);
+void               _dbus_message_loader_return_buffer         (DBusMessageLoader  *loader,
+                                                               DBusString         *buffer,
+                                                               int                 bytes_read);
+
+dbus_bool_t        _dbus_message_loader_get_unix_fds          (DBusMessageLoader  *loader,
+                                                               int               **fds,
+                                                               unsigned           *max_n_fds);
+void               _dbus_message_loader_return_unix_fds       (DBusMessageLoader  *loader,
+                                                               int                *fds,
+                                                               unsigned            n_fds);
+
+dbus_bool_t        _dbus_message_loader_queue_messages        (DBusMessageLoader  *loader);
+DBusMessage*       _dbus_message_loader_peek_message          (DBusMessageLoader  *loader);
+DBusMessage*       _dbus_message_loader_pop_message           (DBusMessageLoader  *loader);
+DBusList*          _dbus_message_loader_pop_message_link      (DBusMessageLoader  *loader);
+void               _dbus_message_loader_putback_message_link  (DBusMessageLoader  *loader,
+                                                               DBusList           *link);
+
+dbus_bool_t        _dbus_message_loader_get_is_corrupted      (DBusMessageLoader  *loader);
+DBusValidity       _dbus_message_loader_get_corruption_reason (DBusMessageLoader  *loader);
+
+void               _dbus_message_loader_set_max_message_size  (DBusMessageLoader  *loader,
+                                                               long                size);
+long               _dbus_message_loader_get_max_message_size  (DBusMessageLoader  *loader);
+
+void               _dbus_message_loader_set_max_message_unix_fds(DBusMessageLoader  *loader,
+                                                                 long                n);
+long               _dbus_message_loader_get_max_message_unix_fds(DBusMessageLoader  *loader);
+
+typedef struct DBusInitialFDs DBusInitialFDs;
+DBusInitialFDs *_dbus_check_fdleaks_enter (void);
+void            _dbus_check_fdleaks_leave (DBusInitialFDs *fds);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_MESSAGE_INTERNAL_H */
diff --git a/dbus/dbus/dbus-message-private.h b/dbus/dbus/dbus-message-private.h
new file mode 100644
index 0000000..e1578ab
--- /dev/null
+++ b/dbus/dbus/dbus-message-private.h
@@ -0,0 +1,143 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-message-private.h header shared between dbus-message.c and dbus-message-util.c
+ *
+ * Copyright (C) 2005  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_MESSAGE_PRIVATE_H
+#define DBUS_MESSAGE_PRIVATE_H
+
+#include <dbus/dbus-message.h>
+#include <dbus/dbus-message-internal.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-dataslot.h>
+#include <dbus/dbus-marshal-header.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusMessageInternals
+ * @{
+ */
+
+/**
+ * @typedef DBusMessageLoader
+ *
+ * The DBusMessageLoader object encapsulates the process of converting
+ * a byte stream into a series of DBusMessage. It buffers the incoming
+ * bytes as efficiently as possible, and generates a queue of
+ * messages. DBusMessageLoader is typically used as part of a
+ * DBusTransport implementation. The DBusTransport then hands off
+ * the loaded messages to a DBusConnection, making the messages
+ * visible to the application.
+ *
+ * @todo write tests for break-loader that a) randomly delete header
+ * fields and b) set string fields to zero-length and other funky
+ * values.
+ *
+ */
+
+/**
+ * Implementation details of DBusMessageLoader.
+ * All members are private.
+ */
+struct DBusMessageLoader
+{
+  int refcount;        /**< Reference count. */
+
+  DBusString data;     /**< Buffered data */
+
+  DBusList *messages;  /**< Complete messages. */
+
+  long max_message_size; /**< Maximum size of a message */
+  long max_message_unix_fds; /**< Maximum unix fds in a message */
+
+  DBusValidity corruption_reason; /**< why we were corrupted */
+
+  unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
+
+  unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
+
+#ifdef HAVE_UNIX_FD_PASSING
+  unsigned int unix_fds_outstanding : 1; /**< Someone is using the unix fd array to read */
+
+  int *unix_fds; /**< File descriptors that have been read from the transport but not yet been handed to any message. Array will be allocated at first use. */
+  unsigned n_unix_fds_allocated; /**< Number of file descriptors this array has space for */
+  unsigned n_unix_fds; /**< Number of valid file descriptors in array */
+#endif
+};
+
+
+/** How many bits are in the changed_stamp used to validate iterators */
+#define CHANGED_STAMP_BITS 21
+
+/**
+ * @brief Internals of DBusMessage
+ *
+ * Object representing a message received from or to be sent to
+ * another application. This is an opaque object, all members
+ * are private.
+ */
+struct DBusMessage
+{
+  DBusAtomic refcount; /**< Reference count */
+
+  DBusHeader header; /**< Header network data and associated cache */
+
+  DBusString body;   /**< Body network data. */
+
+  unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
+
+#ifndef DBUS_DISABLE_CHECKS
+  unsigned int in_cache : 1; /**< Has been "freed" since it's in the cache (this is a debug feature) */
+#endif
+
+  DBusList *counters;   /**< 0-N DBusCounter used to track message size/unix fds. */
+  long size_counter_delta;   /**< Size we incremented the size counters by.   */
+
+  dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; /**< Incremented when iterators are invalidated. */
+
+  DBusDataSlotList slot_list;   /**< Data stored by allocated integer ID */
+
+#ifndef DBUS_DISABLE_CHECKS
+  int generation; /**< _dbus_current_generation when message was created */
+#endif
+
+#ifdef HAVE_UNIX_FD_PASSING
+  int *unix_fds;
+  /**< Unix file descriptors associated with this message. These are
+     closed when the message is destroyed, hence make sure to dup()
+     them when adding or removing them here. */
+  unsigned n_unix_fds; /**< Number of valid fds in the array */
+  unsigned n_unix_fds_allocated; /**< Allocated size of the array */
+
+  long unix_fd_counter_delta; /**< Size we incremented the unix fd counter by */
+#endif
+};
+
+dbus_bool_t _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+                                                DBusError       *error,
+                                                int              first_arg_type,
+                                                va_list          var_args);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_MESSAGE_H */
diff --git a/dbus/dbus/dbus-message-util.c b/dbus/dbus/dbus-message-util.c
new file mode 100644
index 0000000..f785952
--- /dev/null
+++ b/dbus/dbus/dbus-message-util.c
@@ -0,0 +1,1545 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-message-util.c Would be in dbus-message.c, but only used by bus/tests
+ *
+ * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
+ * Copyright (C) 2002, 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-test.h"
+#include "dbus-message-private.h"
+#include "dbus-marshal-recursive.h"
+#include "dbus-string.h"
+#ifdef HAVE_UNIX_FD_PASSING
+#include "dbus-sysdeps-unix.h"
+#endif
+
+#ifdef __linux__
+/* Necessary for the Linux-specific fd leak checking code only */
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <errno.h>
+#endif
+
+/**
+ * @addtogroup DBusMessage
+ * @{
+ */
+
+#ifdef DBUS_BUILD_TESTS
+/**
+ * Reads arguments from a message iterator given a variable argument
+ * list. Only arguments of basic type and arrays of fixed-length
+ * basic type may be read with this function. See
+ * dbus_message_get_args() for more details.
+ *
+ * @param iter the message iterator
+ * @param error error to be filled in on failure
+ * @param first_arg_type the first argument type
+ * @param ... location for first argument value, then list of type-location pairs
+ * @returns #FALSE if the error was set
+ */
+static dbus_bool_t
+dbus_message_iter_get_args (DBusMessageIter *iter,
+			    DBusError       *error,
+			    int              first_arg_type,
+			    ...)
+{
+  dbus_bool_t retval;
+  va_list var_args;
+
+  _dbus_return_val_if_fail (iter != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
+
+  va_start (var_args, first_arg_type);
+  retval = _dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
+  va_end (var_args);
+
+  return retval;
+}
+#endif /* DBUS_BUILD_TESTS */
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include "dbus-message-factory.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+static int validities_seen[DBUS_VALIDITY_LAST + _DBUS_NEGATIVE_VALIDITY_COUNT];
+
+static void
+reset_validities_seen (void)
+{
+  int i;
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (validities_seen))
+    {
+      validities_seen[i] = 0;
+      ++i;
+    }
+}
+
+static void
+record_validity_seen (DBusValidity validity)
+{
+  validities_seen[validity + _DBUS_NEGATIVE_VALIDITY_COUNT] += 1;
+}
+
+static void
+print_validities_seen (dbus_bool_t not_seen)
+{
+  int i;
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (validities_seen))
+    {
+      if ((i - _DBUS_NEGATIVE_VALIDITY_COUNT) == DBUS_VALIDITY_UNKNOWN ||
+          (i - _DBUS_NEGATIVE_VALIDITY_COUNT) == DBUS_INVALID_FOR_UNKNOWN_REASON)
+        ;
+      else if ((not_seen && validities_seen[i] == 0) ||
+               (!not_seen && validities_seen[i] > 0))
+        printf ("validity %3d seen %d times\n",
+                i - _DBUS_NEGATIVE_VALIDITY_COUNT,
+                validities_seen[i]);
+      ++i;
+    }
+}
+
+static void
+check_memleaks (void)
+{
+  dbus_shutdown ();
+
+  if (_dbus_get_malloc_blocks_outstanding () != 0)
+    {
+      _dbus_warn ("%d dbus_malloc blocks were not freed in %s\n",
+                  _dbus_get_malloc_blocks_outstanding (), __FILE__);
+      _dbus_assert_not_reached ("memleaks");
+    }
+}
+
+#ifdef __linux__
+struct DBusInitialFDs {
+    fd_set set;
+};
+#endif
+
+DBusInitialFDs *
+_dbus_check_fdleaks_enter (void)
+{
+#ifdef __linux__
+  DIR *d;
+  DBusInitialFDs *fds;
+
+  /* this is plain malloc so it won't interfere with leak checking */
+  fds = malloc (sizeof (DBusInitialFDs));
+  _dbus_assert (fds != NULL);
+
+  /* This works on Linux only */
+
+  if ((d = opendir ("/proc/self/fd")))
+    {
+      struct dirent *de;
+
+      while ((de = readdir(d)))
+        {
+          long l;
+          char *e = NULL;
+          int fd;
+
+          if (de->d_name[0] == '.')
+            continue;
+
+          errno = 0;
+          l = strtol (de->d_name, &e, 10);
+          _dbus_assert (errno == 0 && e && !*e);
+
+          fd = (int) l;
+
+          if (fd < 3)
+            continue;
+
+          if (fd == dirfd (d))
+            continue;
+
+          FD_SET (fd, &fds->set);
+        }
+
+      closedir (d);
+    }
+
+  return fds;
+#else
+  return NULL;
+#endif
+}
+
+void
+_dbus_check_fdleaks_leave (DBusInitialFDs *fds)
+{
+#ifdef __linux__
+  DIR *d;
+
+  /* This works on Linux only */
+
+  if ((d = opendir ("/proc/self/fd")))
+    {
+      struct dirent *de;
+
+      while ((de = readdir(d)))
+        {
+          long l;
+          char *e = NULL;
+          int fd;
+
+          if (de->d_name[0] == '.')
+            continue;
+
+          errno = 0;
+          l = strtol (de->d_name, &e, 10);
+          _dbus_assert (errno == 0 && e && !*e);
+
+          fd = (int) l;
+
+          if (fd < 3)
+            continue;
+
+          if (fd == dirfd (d))
+            continue;
+
+          if (FD_ISSET (fd, &fds->set))
+            continue;
+
+          _dbus_warn ("file descriptor %i leaked in %s.\n", fd, __FILE__);
+          _dbus_assert_not_reached ("fdleaks");
+        }
+
+      closedir (d);
+    }
+
+  free (fds);
+#else
+  _dbus_assert (fds == NULL);
+#endif
+}
+
+static dbus_bool_t
+check_have_valid_message (DBusMessageLoader *loader)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
+
+  message = NULL;
+  retval = FALSE;
+
+  if (_dbus_message_loader_get_is_corrupted (loader))
+    {
+      _dbus_warn ("loader corrupted on message that was expected to be valid; invalid reason %d\n",
+                  loader->corruption_reason);
+      goto failed;
+    }
+
+  message = _dbus_message_loader_pop_message (loader);
+  if (message == NULL)
+    {
+      _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
+      goto failed;
+    }
+
+  if (_dbus_string_get_length (&loader->data) > 0)
+    {
+      _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
+      goto failed;
+    }
+
+#if 0
+  /* FIXME */
+  /* Verify that we're able to properly deal with the message.
+   * For example, this would detect improper handling of messages
+   * in nonstandard byte order.
+   */
+  if (!check_message_handling (message))
+    goto failed;
+#endif
+
+  record_validity_seen (DBUS_VALID);
+  
+  retval = TRUE;
+
+ failed:
+  if (message)
+    dbus_message_unref (message);
+
+  return retval;
+}
+
+static dbus_bool_t
+check_invalid_message (DBusMessageLoader *loader,
+                       DBusValidity       expected_validity)
+{
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  if (!_dbus_message_loader_get_is_corrupted (loader))
+    {
+      _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
+      goto failed;
+    }
+
+  record_validity_seen (loader->corruption_reason);
+  
+  if (expected_validity != DBUS_INVALID_FOR_UNKNOWN_REASON &&
+      loader->corruption_reason != expected_validity)
+    {
+      _dbus_warn ("expected message to be corrupted for reason %d and was corrupted for %d instead\n",
+                  expected_validity, loader->corruption_reason);
+      goto failed;
+    }
+
+  retval = TRUE;
+
+ failed:
+  return retval;
+}
+
+static dbus_bool_t
+check_incomplete_message (DBusMessageLoader *loader)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
+
+  message = NULL;
+  retval = FALSE;
+
+  if (_dbus_message_loader_get_is_corrupted (loader))
+    {
+      _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete), corruption reason %d\n",
+                  loader->corruption_reason);
+      goto failed;
+    }
+
+  message = _dbus_message_loader_pop_message (loader);
+  if (message != NULL)
+    {
+      _dbus_warn ("loaded message that was expected to be incomplete\n");
+      goto failed;
+    }
+
+  record_validity_seen (DBUS_VALID_BUT_INCOMPLETE);
+  retval = TRUE;
+
+ failed:
+  if (message)
+    dbus_message_unref (message);
+  return retval;
+}
+
+static dbus_bool_t
+check_loader_results (DBusMessageLoader      *loader,
+                      DBusValidity            expected_validity)
+{
+  if (!_dbus_message_loader_queue_messages (loader))
+    _dbus_assert_not_reached ("no memory to queue messages");
+
+  if (expected_validity == DBUS_VALID)
+    return check_have_valid_message (loader);
+  else if (expected_validity == DBUS_VALID_BUT_INCOMPLETE)
+    return check_incomplete_message (loader);
+  else if (expected_validity == DBUS_VALIDITY_UNKNOWN)
+    {
+      /* here we just know we didn't segfault and that was the
+       * only test. Also, we record that we got coverage
+       * for the validity reason.
+       */
+      if (_dbus_message_loader_get_is_corrupted (loader))
+        record_validity_seen (loader->corruption_reason);
+      
+      return TRUE;
+    }
+  else
+    return check_invalid_message (loader, expected_validity);
+}
+
+/**
+ * Loads the message in the given message file.
+ *
+ * @param filename filename to load
+ * @param data string to load message into
+ * @returns #TRUE if the message was loaded
+ */
+dbus_bool_t
+dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
+                                            DBusString          *data)
+{
+  dbus_bool_t retval;
+  DBusError error = DBUS_ERROR_INIT;
+
+  retval = FALSE;
+
+  _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
+  if (!_dbus_file_get_contents (data, filename, &error))
+    {
+      _dbus_warn ("Could not load message file %s: %s\n",
+                  _dbus_string_get_const_data (filename),
+                  error.message);
+      dbus_error_free (&error);
+      goto failed;
+    }
+
+  retval = TRUE;
+
+ failed:
+
+  return retval;
+}
+
+/**
+ * Tries loading the message in the given message file
+ * and verifies that DBusMessageLoader can handle it.
+ *
+ * @param filename filename to load
+ * @param expected_validity what the message has to be like to return #TRUE
+ * @returns #TRUE if the message has the expected validity
+ */
+dbus_bool_t
+dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
+                                           DBusValidity         expected_validity)
+{
+  DBusString data;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  if (!_dbus_string_init (&data))
+    _dbus_assert_not_reached ("could not allocate string\n");
+
+  if (!dbus_internal_do_not_use_load_message_file (filename, &data))
+    goto failed;
+
+  retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
+
+ failed:
+
+  if (!retval)
+    {
+      if (_dbus_string_get_length (&data) > 0)
+        _dbus_verbose_bytes_of_string (&data, 0,
+                                       _dbus_string_get_length (&data));
+
+      _dbus_warn ("Failed message loader test on %s\n",
+                  _dbus_string_get_const_data (filename));
+    }
+
+  _dbus_string_free (&data);
+
+  return retval;
+}
+
+/**
+ * Tries loading the given message data.
+ *
+ *
+ * @param data the message data
+ * @param expected_validity what the message has to be like to return #TRUE
+ * @returns #TRUE if the message has the expected validity
+ */
+dbus_bool_t
+dbus_internal_do_not_use_try_message_data (const DBusString    *data,
+                                           DBusValidity         expected_validity)
+{
+  DBusMessageLoader *loader;
+  dbus_bool_t retval;
+  int len;
+  int i;
+
+  loader = NULL;
+  retval = FALSE;
+
+  /* Write the data one byte at a time */
+
+  loader = _dbus_message_loader_new ();
+
+  /* check some trivial loader functions */
+  _dbus_message_loader_ref (loader);
+  _dbus_message_loader_unref (loader);
+  _dbus_message_loader_get_max_message_size (loader);
+
+  len = _dbus_string_get_length (data);
+  for (i = 0; i < len; i++)
+    {
+      DBusString *buffer;
+
+      _dbus_message_loader_get_buffer (loader, &buffer);
+      _dbus_string_append_byte (buffer,
+                                _dbus_string_get_byte (data, i));
+      _dbus_message_loader_return_buffer (loader, buffer, 1);
+    }
+
+  if (!check_loader_results (loader, expected_validity))
+    goto failed;
+
+  _dbus_message_loader_unref (loader);
+  loader = NULL;
+
+  /* Write the data all at once */
+
+  loader = _dbus_message_loader_new ();
+
+  {
+    DBusString *buffer;
+
+    _dbus_message_loader_get_buffer (loader, &buffer);
+    _dbus_string_copy (data, 0, buffer,
+                       _dbus_string_get_length (buffer));
+    _dbus_message_loader_return_buffer (loader, buffer, 1);
+  }
+
+  if (!check_loader_results (loader, expected_validity))
+    goto failed;
+
+  _dbus_message_loader_unref (loader);
+  loader = NULL;
+
+  /* Write the data 2 bytes at a time */
+
+  loader = _dbus_message_loader_new ();
+
+  len = _dbus_string_get_length (data);
+  for (i = 0; i < len; i += 2)
+    {
+      DBusString *buffer;
+
+      _dbus_message_loader_get_buffer (loader, &buffer);
+      _dbus_string_append_byte (buffer,
+                                _dbus_string_get_byte (data, i));
+      if ((i+1) < len)
+        _dbus_string_append_byte (buffer,
+                                  _dbus_string_get_byte (data, i+1));
+      _dbus_message_loader_return_buffer (loader, buffer, 1);
+    }
+
+  if (!check_loader_results (loader, expected_validity))
+    goto failed;
+
+  _dbus_message_loader_unref (loader);
+  loader = NULL;
+
+  retval = TRUE;
+
+ failed:
+
+  if (loader)
+    _dbus_message_loader_unref (loader);
+
+  return retval;
+}
+
+static dbus_bool_t
+process_test_subdir (const DBusString          *test_base_dir,
+                     const char                *subdir,
+                     DBusValidity               expected_validity,
+                     DBusForeachMessageFileFunc function,
+                     void                      *user_data)
+{
+  DBusString test_directory;
+  DBusString filename;
+  DBusDirIter *dir;
+  dbus_bool_t retval;
+  DBusError error = DBUS_ERROR_INIT;
+
+  retval = FALSE;
+  dir = NULL;
+
+  if (!_dbus_string_init (&test_directory))
+    _dbus_assert_not_reached ("didn't allocate test_directory\n");
+
+  _dbus_string_init_const (&filename, subdir);
+
+  if (!_dbus_string_copy (test_base_dir, 0,
+                          &test_directory, 0))
+    _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
+
+  if (!_dbus_concat_dir_and_file (&test_directory, &filename))
+    _dbus_assert_not_reached ("couldn't allocate full path");
+
+  _dbus_string_free (&filename);
+  if (!_dbus_string_init (&filename))
+    _dbus_assert_not_reached ("didn't allocate filename string\n");
+
+  dir = _dbus_directory_open (&test_directory, &error);
+  if (dir == NULL)
+    {
+      _dbus_warn ("Could not open %s: %s\n",
+                  _dbus_string_get_const_data (&test_directory),
+                  error.message);
+      dbus_error_free (&error);
+      goto failed;
+    }
+
+  printf ("Testing %s:\n", subdir);
+
+ next:
+  while (_dbus_directory_get_next_file (dir, &filename, &error))
+    {
+      DBusString full_path;
+
+      if (!_dbus_string_init (&full_path))
+        _dbus_assert_not_reached ("couldn't init string");
+
+      if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
+        _dbus_assert_not_reached ("couldn't copy dir to full_path");
+
+      if (!_dbus_concat_dir_and_file (&full_path, &filename))
+        _dbus_assert_not_reached ("couldn't concat file to dir");
+
+      if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
+        ;
+      else
+        {
+          if (_dbus_string_ends_with_c_str (&filename, ".message"))
+            {
+              printf ("SKIP: Could not load %s, message builder language no longer supported\n",
+                      _dbus_string_get_const_data (&filename));
+            }
+          
+          _dbus_verbose ("Skipping non-.message file %s\n",
+                         _dbus_string_get_const_data (&filename));
+	  _dbus_string_free (&full_path);
+          goto next;
+        }
+
+      printf ("    %s\n",
+              _dbus_string_get_const_data (&filename));
+
+      if (! (*function) (&full_path,
+                         expected_validity, user_data))
+        {
+          _dbus_string_free (&full_path);
+          goto failed;
+        }
+      else
+        _dbus_string_free (&full_path);
+    }
+
+  if (dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Could not get next file in %s: %s\n",
+                  _dbus_string_get_const_data (&test_directory),
+                  error.message);
+      dbus_error_free (&error);
+      goto failed;
+    }
+
+  retval = TRUE;
+
+ failed:
+
+  if (dir)
+    _dbus_directory_close (dir);
+  _dbus_string_free (&test_directory);
+  _dbus_string_free (&filename);
+
+  return retval;
+}
+
+/**
+ * Runs the given function on every message file in the test suite.
+ * The function should return #FALSE on test failure or fatal error.
+ *
+ * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
+ * @param func the function to run
+ * @param user_data data for function
+ * @returns #FALSE if there's a failure
+ */
+dbus_bool_t
+dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
+                                               DBusForeachMessageFileFunc func,
+                                               void                      *user_data)
+{
+  DBusString test_directory;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+
+  _dbus_string_init_const (&test_directory, test_data_dir);
+  
+  if (!process_test_subdir (&test_directory, "valid-messages",
+                            DBUS_VALID, func, user_data))
+    goto failed;
+
+  check_memleaks ();
+  
+  if (!process_test_subdir (&test_directory, "invalid-messages",
+                            DBUS_INVALID_FOR_UNKNOWN_REASON, func, user_data))
+    goto failed;
+
+  check_memleaks ();
+  
+  if (!process_test_subdir (&test_directory, "incomplete-messages",
+                            DBUS_VALID_BUT_INCOMPLETE, func, user_data))
+    goto failed;
+
+  check_memleaks ();
+  
+  retval = TRUE;
+  
+ failed:
+
+  _dbus_string_free (&test_directory);
+
+  return retval;
+}
+
+#if 0
+#define GET_AND_CHECK(iter, typename, literal)                                  \
+  do {                                                                          \
+    if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename)         \
+      _dbus_assert_not_reached ("got wrong argument type from message iter");   \
+    dbus_message_iter_get_basic (&iter, &v_##typename);                         \
+    if (v_##typename != literal)                                                \
+      _dbus_assert_not_reached ("got wrong value from message iter");           \
+  } while (0)
+
+#define GET_AND_CHECK_STRCMP(iter, typename, literal)                           \
+  do {                                                                          \
+    if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename)         \
+      _dbus_assert_not_reached ("got wrong argument type from message iter");   \
+    dbus_message_iter_get_basic (&iter, &v_##typename);                         \
+    if (strcmp (v_##typename, literal) != 0)                                    \
+      _dbus_assert_not_reached ("got wrong value from message iter");           \
+  } while (0)
+
+#define GET_AND_CHECK_AND_NEXT(iter, typename, literal)         \
+  do {                                                          \
+    GET_AND_CHECK(iter, typename, literal);                     \
+    if (!dbus_message_iter_next (&iter))                        \
+      _dbus_assert_not_reached ("failed to move iter to next"); \
+  } while (0)
+
+#define GET_AND_CHECK_STRCMP_AND_NEXT(iter, typename, literal)  \
+  do {                                                          \
+    GET_AND_CHECK_STRCMP(iter, typename, literal);              \
+    if (!dbus_message_iter_next (&iter))                        \
+      _dbus_assert_not_reached ("failed to move iter to next"); \
+  } while (0)
+
+static void
+message_iter_test (DBusMessage *message)
+{
+  DBusMessageIter iter, array, array2;
+  const char *v_STRING;
+  double v_DOUBLE;
+  dbus_int16_t v_INT16;
+  dbus_uint16_t v_UINT16;
+  dbus_int32_t v_INT32;
+  dbus_uint32_t v_UINT32;
+#ifdef DBUS_HAVE_INT64
+  dbus_int64_t v_INT64;
+  dbus_uint64_t v_UINT64;
+#endif
+  unsigned char v_BYTE;
+  dbus_bool_t v_BOOLEAN;
+
+  const dbus_int32_t *our_int_array;
+  int len;
+
+  dbus_message_iter_init (message, &iter);
+
+  GET_AND_CHECK_STRCMP_AND_NEXT (iter, STRING, "Test string");
+  GET_AND_CHECK_AND_NEXT (iter, INT32, -0x12345678);
+  GET_AND_CHECK_AND_NEXT (iter, UINT32, 0xedd1e);
+  GET_AND_CHECK_AND_NEXT (iter, DOUBLE, 3.14159);
+
+  if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
+    _dbus_assert_not_reached ("Argument type not an array");
+
+  if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_DOUBLE)
+    _dbus_assert_not_reached ("Array type not double");
+
+  dbus_message_iter_recurse (&iter, &array);
+
+  GET_AND_CHECK_AND_NEXT (array, DOUBLE, 1.5);
+  GET_AND_CHECK (array, DOUBLE, 2.5);
+
+  if (dbus_message_iter_next (&array))
+    _dbus_assert_not_reached ("Didn't reach end of array");
+
+  if (!dbus_message_iter_next (&iter))
+    _dbus_assert_not_reached ("Reached end of arguments");
+
+  GET_AND_CHECK_AND_NEXT (iter, BYTE, 0xF0);
+
+  if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
+    _dbus_assert_not_reached ("no array");
+
+  if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_INT32)
+    _dbus_assert_not_reached ("Array type not int32");
+
+  /* Empty array */
+  dbus_message_iter_recurse (&iter, &array);
+
+  if (dbus_message_iter_next (&array))
+    _dbus_assert_not_reached ("Didn't reach end of array");
+
+  if (!dbus_message_iter_next (&iter))
+    _dbus_assert_not_reached ("Reached end of arguments");
+
+  GET_AND_CHECK (iter, BYTE, 0xF0);
+
+  if (dbus_message_iter_next (&iter))
+    _dbus_assert_not_reached ("Didn't reach end of arguments");
+}
+#endif
+
+static void
+verify_test_message (DBusMessage *message)
+{
+  DBusMessageIter iter;
+  DBusError error = DBUS_ERROR_INIT;
+  dbus_int16_t our_int16;
+  dbus_uint16_t our_uint16;
+  dbus_int32_t our_int;
+  dbus_uint32_t our_uint;
+  const char *our_str;
+  double our_double;
+  double v_DOUBLE;
+  dbus_bool_t our_bool;
+  unsigned char our_byte_1, our_byte_2;
+  const dbus_uint32_t *our_uint32_array = (void*)0xdeadbeef;
+  int our_uint32_array_len;
+  dbus_int32_t *our_int32_array = (void*)0xdeadbeef;
+  int our_int32_array_len;
+#ifdef DBUS_HAVE_INT64
+  dbus_int64_t our_int64;
+  dbus_uint64_t our_uint64;
+  dbus_int64_t *our_uint64_array = (void*)0xdeadbeef;
+  int our_uint64_array_len;
+  const dbus_int64_t *our_int64_array = (void*)0xdeadbeef;
+  int our_int64_array_len;
+#endif
+  const double *our_double_array = (void*)0xdeadbeef;
+  int our_double_array_len;
+  const unsigned char *our_byte_array = (void*)0xdeadbeef;
+  int our_byte_array_len;
+  const dbus_bool_t *our_boolean_array = (void*)0xdeadbeef;
+  int our_boolean_array_len;
+  char **our_string_array;
+  int our_string_array_len;
+
+  dbus_message_iter_init (message, &iter);
+
+  if (!dbus_message_iter_get_args (&iter, &error,
+                                   DBUS_TYPE_INT16, &our_int16,
+                                   DBUS_TYPE_UINT16, &our_uint16,
+				   DBUS_TYPE_INT32, &our_int,
+                                   DBUS_TYPE_UINT32, &our_uint,
+#ifdef DBUS_HAVE_INT64
+                                   DBUS_TYPE_INT64, &our_int64,
+                                   DBUS_TYPE_UINT64, &our_uint64,
+#endif
+				   DBUS_TYPE_STRING, &our_str,
+				   DBUS_TYPE_DOUBLE, &our_double,
+				   DBUS_TYPE_BOOLEAN, &our_bool,
+				   DBUS_TYPE_BYTE, &our_byte_1,
+				   DBUS_TYPE_BYTE, &our_byte_2,
+				   DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
+                                   &our_uint32_array, &our_uint32_array_len,
+                                   DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
+                                   &our_int32_array, &our_int32_array_len,
+#ifdef DBUS_HAVE_INT64
+				   DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
+                                   &our_uint64_array, &our_uint64_array_len,
+                                   DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
+                                   &our_int64_array, &our_int64_array_len,
+#endif
+                                   DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
+                                   &our_double_array, &our_double_array_len,
+                                   DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+                                   &our_byte_array, &our_byte_array_len,
+                                   DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
+                                   &our_boolean_array, &our_boolean_array_len,
+                                   DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
+                                   &our_string_array, &our_string_array_len,
+				   0))
+    {
+      _dbus_warn ("error: %s - %s\n", error.name,
+                  (error.message != NULL) ? error.message : "no message");
+      _dbus_assert_not_reached ("Could not get arguments");
+    }
+
+  if (our_int16 != -0x123)
+    _dbus_assert_not_reached ("16-bit integers differ!");
+
+  if (our_uint16 != 0x123)
+    _dbus_assert_not_reached ("16-bit uints differ!");
+  
+  if (our_int != -0x12345678)
+    _dbus_assert_not_reached ("integers differ!");
+
+  if (our_uint != 0x12300042)
+    _dbus_assert_not_reached ("uints differ!");
+
+#ifdef DBUS_HAVE_INT64
+  if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
+    _dbus_assert_not_reached ("64-bit integers differ!");
+  if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
+    _dbus_assert_not_reached ("64-bit unsigned integers differ!");
+#endif
+
+  v_DOUBLE = 3.14159;
+  if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double, v_DOUBLE))
+    _dbus_assert_not_reached ("doubles differ!");
+
+  if (strcmp (our_str, "Test string") != 0)
+    _dbus_assert_not_reached ("strings differ!");
+
+  if (!our_bool)
+    _dbus_assert_not_reached ("booleans differ");
+
+  if (our_byte_1 != 42)
+    _dbus_assert_not_reached ("bytes differ!");
+
+  if (our_byte_2 != 24)
+    _dbus_assert_not_reached ("bytes differ!");
+
+  if (our_uint32_array_len != 4 ||
+      our_uint32_array[0] != 0x12345678 ||
+      our_uint32_array[1] != 0x23456781 ||
+      our_uint32_array[2] != 0x34567812 ||
+      our_uint32_array[3] != 0x45678123)
+    _dbus_assert_not_reached ("uint array differs");
+
+  if (our_int32_array_len != 4 ||
+      our_int32_array[0] != 0x12345678 ||
+      our_int32_array[1] != -0x23456781 ||
+      our_int32_array[2] != 0x34567812 ||
+      our_int32_array[3] != -0x45678123)
+    _dbus_assert_not_reached ("int array differs");
+
+#ifdef DBUS_HAVE_INT64
+  if (our_uint64_array_len != 4 ||
+      our_uint64_array[0] != 0x12345678 ||
+      our_uint64_array[1] != 0x23456781 ||
+      our_uint64_array[2] != 0x34567812 ||
+      our_uint64_array[3] != 0x45678123)
+    _dbus_assert_not_reached ("uint64 array differs");
+
+  if (our_int64_array_len != 4 ||
+      our_int64_array[0] != 0x12345678 ||
+      our_int64_array[1] != -0x23456781 ||
+      our_int64_array[2] != 0x34567812 ||
+      our_int64_array[3] != -0x45678123)
+    _dbus_assert_not_reached ("int64 array differs");
+#endif /* DBUS_HAVE_INT64 */
+
+  if (our_double_array_len != 3)
+    _dbus_assert_not_reached ("double array had wrong length");
+
+  /* On all IEEE machines (i.e. everything sane) exact equality
+   * should be preserved over the wire
+   */
+  v_DOUBLE = 0.1234;
+  if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[0], v_DOUBLE))
+    _dbus_assert_not_reached ("double array had wrong values");
+  v_DOUBLE = 9876.54321;
+  if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[1], v_DOUBLE))
+    _dbus_assert_not_reached ("double array had wrong values");
+  v_DOUBLE = -300.0;
+  if (! _DBUS_DOUBLES_BITWISE_EQUAL (our_double_array[2], v_DOUBLE))
+    _dbus_assert_not_reached ("double array had wrong values");
+
+  if (our_byte_array_len != 4)
+    _dbus_assert_not_reached ("byte array had wrong length");
+
+  if (our_byte_array[0] != 'a' ||
+      our_byte_array[1] != 'b' ||
+      our_byte_array[2] != 'c' ||
+      our_byte_array[3] != 234)
+    _dbus_assert_not_reached ("byte array had wrong values");
+
+  if (our_boolean_array_len != 5)
+    _dbus_assert_not_reached ("bool array had wrong length");
+
+  if (our_boolean_array[0] != TRUE ||
+      our_boolean_array[1] != FALSE ||
+      our_boolean_array[2] != TRUE ||
+      our_boolean_array[3] != TRUE ||
+      our_boolean_array[4] != FALSE)
+    _dbus_assert_not_reached ("bool array had wrong values");
+
+  if (our_string_array_len != 4)
+    _dbus_assert_not_reached ("string array was wrong length");
+
+  if (strcmp (our_string_array[0], "Foo") != 0 ||
+      strcmp (our_string_array[1], "bar") != 0 ||
+      strcmp (our_string_array[2], "") != 0 ||
+      strcmp (our_string_array[3], "woo woo woo woo") != 0)
+    _dbus_assert_not_reached ("string array had wrong values");
+
+  dbus_free_string_array (our_string_array);
+  
+  if (dbus_message_iter_next (&iter))
+    _dbus_assert_not_reached ("Didn't reach end of arguments");
+}
+
+/**
+ * @ingroup DBusMessageInternals
+ * Unit test for DBusMessage.
+ *
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_message_test (const char *test_data_dir)
+{
+  DBusMessage *message, *message_without_unix_fds;
+  DBusMessageLoader *loader;
+  int i;
+  const char *data;
+  DBusMessage *copy;
+  const char *name1;
+  const char *name2;
+  const dbus_uint32_t our_uint32_array[] =
+    { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
+  const dbus_int32_t our_int32_array[] =
+    { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
+  const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array;
+  const dbus_int32_t *v_ARRAY_INT32 = our_int32_array;
+#ifdef DBUS_HAVE_INT64
+  const dbus_uint64_t our_uint64_array[] =
+    { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
+  const dbus_int64_t our_int64_array[] =
+    { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
+  const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array;
+  const dbus_int64_t *v_ARRAY_INT64 = our_int64_array;
+#endif
+  const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
+  const char **v_ARRAY_STRING = our_string_array;
+  const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
+  const double *v_ARRAY_DOUBLE = our_double_array;
+  const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
+  const unsigned char *v_ARRAY_BYTE = our_byte_array;
+  const dbus_bool_t our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
+  const dbus_bool_t *v_ARRAY_BOOLEAN = our_boolean_array;
+  char sig[64];
+  const char *s;
+  const char *v_STRING;
+  double v_DOUBLE;
+  dbus_int16_t v_INT16;
+  dbus_uint16_t v_UINT16;
+  dbus_int32_t v_INT32;
+  dbus_uint32_t v_UINT32;
+#ifdef DBUS_HAVE_INT64
+  dbus_int64_t v_INT64;
+  dbus_uint64_t v_UINT64;
+#endif
+  unsigned char v_BYTE;
+  unsigned char v2_BYTE;
+  dbus_bool_t v_BOOLEAN;
+  DBusMessageIter iter, array_iter, struct_iter;
+#ifdef HAVE_UNIX_FD_PASSING
+  int v_UNIX_FD;
+#endif
+  char **decomposed;
+  DBusInitialFDs *initial_fds;
+
+  initial_fds = _dbus_check_fdleaks_enter ();
+
+  message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
+                                          "/org/freedesktop/TestPath",
+                                          "Foo.TestInterface",
+                                          "TestMethod");
+  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
+  _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
+                                             "TestMethod"));
+  _dbus_assert (strcmp (dbus_message_get_path (message),
+                        "/org/freedesktop/TestPath") == 0);
+  dbus_message_set_serial (message, 1234);
+
+  /* string length including nul byte not a multiple of 4 */
+  if (!dbus_message_set_sender (message, "org.foo.bar1"))
+    _dbus_assert_not_reached ("out of memory");
+
+  _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
+  dbus_message_set_reply_serial (message, 5678);
+
+  _dbus_verbose_bytes_of_string (&message->header.data, 0,
+                                 _dbus_string_get_length (&message->header.data));
+  _dbus_verbose_bytes_of_string (&message->body, 0,
+                                 _dbus_string_get_length (&message->body));
+
+  if (!dbus_message_set_sender (message, NULL))
+    _dbus_assert_not_reached ("out of memory");
+
+
+  _dbus_verbose_bytes_of_string (&message->header.data, 0,
+                                 _dbus_string_get_length (&message->header.data));
+  _dbus_verbose_bytes_of_string (&message->body, 0,
+                                 _dbus_string_get_length (&message->body));
+
+
+  _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
+  _dbus_assert (dbus_message_get_serial (message) == 1234);
+  _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
+  _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
+
+  _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
+  dbus_message_set_no_reply (message, TRUE);
+  _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
+  dbus_message_set_no_reply (message, FALSE);
+  _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
+
+  /* Set/get some header fields */
+
+  if (!dbus_message_set_path (message, "/foo"))
+    _dbus_assert_not_reached ("out of memory");
+  _dbus_assert (strcmp (dbus_message_get_path (message),
+                        "/foo") == 0);
+
+  if (!dbus_message_set_interface (message, "org.Foo"))
+    _dbus_assert_not_reached ("out of memory");
+  _dbus_assert (strcmp (dbus_message_get_interface (message),
+                        "org.Foo") == 0);
+
+  if (!dbus_message_set_member (message, "Bar"))
+    _dbus_assert_not_reached ("out of memory");
+  _dbus_assert (strcmp (dbus_message_get_member (message),
+                        "Bar") == 0);
+
+  /* Set/get them with longer values */
+  if (!dbus_message_set_path (message, "/foo/bar"))
+    _dbus_assert_not_reached ("out of memory");
+  _dbus_assert (strcmp (dbus_message_get_path (message),
+                        "/foo/bar") == 0);
+
+  if (!dbus_message_set_interface (message, "org.Foo.Bar"))
+    _dbus_assert_not_reached ("out of memory");
+  _dbus_assert (strcmp (dbus_message_get_interface (message),
+                        "org.Foo.Bar") == 0);
+
+  if (!dbus_message_set_member (message, "BarFoo"))
+    _dbus_assert_not_reached ("out of memory");
+  _dbus_assert (strcmp (dbus_message_get_member (message),
+                        "BarFoo") == 0);
+
+  /* Realloc shorter again */
+
+  if (!dbus_message_set_path (message, "/foo"))
+    _dbus_assert_not_reached ("out of memory");
+  _dbus_assert (strcmp (dbus_message_get_path (message),
+                        "/foo") == 0);
+
+  if (!dbus_message_set_interface (message, "org.Foo"))
+    _dbus_assert_not_reached ("out of memory");
+  _dbus_assert (strcmp (dbus_message_get_interface (message),
+                        "org.Foo") == 0);
+
+  if (!dbus_message_set_member (message, "Bar"))
+    _dbus_assert_not_reached ("out of memory");
+  _dbus_assert (strcmp (dbus_message_get_member (message),
+                        "Bar") == 0);
+
+  /* Path decomposing */
+  dbus_message_set_path (message, NULL);
+  dbus_message_get_path_decomposed (message, &decomposed);
+  _dbus_assert (decomposed == NULL);
+  dbus_free_string_array (decomposed);
+
+  dbus_message_set_path (message, "/");
+  dbus_message_get_path_decomposed (message, &decomposed);
+  _dbus_assert (decomposed != NULL);
+  _dbus_assert (decomposed[0] == NULL);
+  dbus_free_string_array (decomposed);
+
+  dbus_message_set_path (message, "/a/b");
+  dbus_message_get_path_decomposed (message, &decomposed);
+  _dbus_assert (decomposed != NULL);
+  _dbus_assert (strcmp (decomposed[0], "a") == 0);
+  _dbus_assert (strcmp (decomposed[1], "b") == 0);
+  _dbus_assert (decomposed[2] == NULL);
+  dbus_free_string_array (decomposed);
+
+  dbus_message_set_path (message, "/spam/eggs");
+  dbus_message_get_path_decomposed (message, &decomposed);
+  _dbus_assert (decomposed != NULL);
+  _dbus_assert (strcmp (decomposed[0], "spam") == 0);
+  _dbus_assert (strcmp (decomposed[1], "eggs") == 0);
+  _dbus_assert (decomposed[2] == NULL);
+  dbus_free_string_array (decomposed);
+
+  dbus_message_unref (message);
+
+  /* Test the vararg functions */
+  message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
+                                          "/org/freedesktop/TestPath",
+                                          "Foo.TestInterface",
+                                          "TestMethod");
+  dbus_message_set_serial (message, 1);
+  dbus_message_set_reply_serial (message, 5678);
+
+  v_INT16 = -0x123;
+  v_UINT16 = 0x123;
+  v_INT32 = -0x12345678;
+  v_UINT32 = 0x12300042;
+#ifdef DBUS_HAVE_INT64
+  v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd);
+  v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd);
+#endif
+  v_STRING = "Test string";
+  v_DOUBLE = 3.14159;
+  v_BOOLEAN = TRUE;
+  v_BYTE = 42;
+  v2_BYTE = 24;
+#ifdef HAVE_UNIX_FD_PASSING
+  v_UNIX_FD = 1;
+#endif
+
+  dbus_message_append_args (message,
+                            DBUS_TYPE_INT16, &v_INT16,
+                            DBUS_TYPE_UINT16, &v_UINT16,
+			    DBUS_TYPE_INT32, &v_INT32,
+                            DBUS_TYPE_UINT32, &v_UINT32,
+#ifdef DBUS_HAVE_INT64
+                            DBUS_TYPE_INT64, &v_INT64,
+                            DBUS_TYPE_UINT64, &v_UINT64,
+#endif
+			    DBUS_TYPE_STRING, &v_STRING,
+			    DBUS_TYPE_DOUBLE, &v_DOUBLE,
+			    DBUS_TYPE_BOOLEAN, &v_BOOLEAN,
+			    DBUS_TYPE_BYTE, &v_BYTE,
+			    DBUS_TYPE_BYTE, &v2_BYTE,
+			    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &v_ARRAY_UINT32,
+                            _DBUS_N_ELEMENTS (our_uint32_array),
+                            DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32,
+                            _DBUS_N_ELEMENTS (our_int32_array),
+#ifdef DBUS_HAVE_INT64
+                            DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64,
+                            _DBUS_N_ELEMENTS (our_uint64_array),
+                            DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64,
+                            _DBUS_N_ELEMENTS (our_int64_array),
+#endif
+                            DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE,
+                            _DBUS_N_ELEMENTS (our_double_array),
+                            DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE,
+                            _DBUS_N_ELEMENTS (our_byte_array),
+                            DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &v_ARRAY_BOOLEAN,
+                            _DBUS_N_ELEMENTS (our_boolean_array),
+                            DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v_ARRAY_STRING,
+                            _DBUS_N_ELEMENTS (our_string_array),
+
+			    DBUS_TYPE_INVALID);
+
+  i = 0;
+  sig[i++] = DBUS_TYPE_INT16;
+  sig[i++] = DBUS_TYPE_UINT16;
+  sig[i++] = DBUS_TYPE_INT32;
+  sig[i++] = DBUS_TYPE_UINT32;
+#ifdef DBUS_HAVE_INT64
+  sig[i++] = DBUS_TYPE_INT64;
+  sig[i++] = DBUS_TYPE_UINT64;
+#endif
+  sig[i++] = DBUS_TYPE_STRING;
+  sig[i++] = DBUS_TYPE_DOUBLE;
+  sig[i++] = DBUS_TYPE_BOOLEAN;
+  sig[i++] = DBUS_TYPE_BYTE;
+  sig[i++] = DBUS_TYPE_BYTE;
+  sig[i++] = DBUS_TYPE_ARRAY;
+  sig[i++] = DBUS_TYPE_UINT32;
+  sig[i++] = DBUS_TYPE_ARRAY;
+  sig[i++] = DBUS_TYPE_INT32;
+#ifdef DBUS_HAVE_INT64
+  sig[i++] = DBUS_TYPE_ARRAY;
+  sig[i++] = DBUS_TYPE_UINT64;
+  sig[i++] = DBUS_TYPE_ARRAY;
+  sig[i++] = DBUS_TYPE_INT64;
+#endif
+  sig[i++] = DBUS_TYPE_ARRAY;
+  sig[i++] = DBUS_TYPE_DOUBLE;
+  sig[i++] = DBUS_TYPE_ARRAY;
+  sig[i++] = DBUS_TYPE_BYTE;
+  sig[i++] = DBUS_TYPE_ARRAY;
+  sig[i++] = DBUS_TYPE_BOOLEAN;
+  sig[i++] = DBUS_TYPE_ARRAY;
+  sig[i++] = DBUS_TYPE_STRING;
+
+  message_without_unix_fds = dbus_message_copy(message);
+  _dbus_assert(message_without_unix_fds);
+#ifdef HAVE_UNIX_FD_PASSING
+  dbus_message_append_args (message,
+                            DBUS_TYPE_UNIX_FD, &v_UNIX_FD,
+			    DBUS_TYPE_INVALID);
+  sig[i++] = DBUS_TYPE_UNIX_FD;
+#endif
+  sig[i++] = DBUS_TYPE_INVALID;
+
+  _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
+
+  _dbus_verbose ("HEADER\n");
+  _dbus_verbose_bytes_of_string (&message->header.data, 0,
+                                 _dbus_string_get_length (&message->header.data));
+  _dbus_verbose ("BODY\n");
+  _dbus_verbose_bytes_of_string (&message->body, 0,
+                                 _dbus_string_get_length (&message->body));
+
+  _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
+                 sig, dbus_message_get_signature (message));
+
+  s = dbus_message_get_signature (message);
+
+  _dbus_assert (dbus_message_has_signature (message, sig));
+  _dbus_assert (strcmp (s, sig) == 0);
+
+  verify_test_message (message);
+
+  copy = dbus_message_copy (message);
+
+  _dbus_assert (dbus_message_get_reply_serial (message) ==
+                dbus_message_get_reply_serial (copy));
+  _dbus_assert (message->header.padding == copy->header.padding);
+
+  _dbus_assert (_dbus_string_get_length (&message->header.data) ==
+                _dbus_string_get_length (&copy->header.data));
+
+  _dbus_assert (_dbus_string_get_length (&message->body) ==
+                _dbus_string_get_length (&copy->body));
+
+  verify_test_message (copy);
+
+  name1 = dbus_message_get_interface (message);
+  name2 = dbus_message_get_interface (copy);
+
+  _dbus_assert (strcmp (name1, name2) == 0);
+
+  name1 = dbus_message_get_member (message);
+  name2 = dbus_message_get_member (copy);
+
+  _dbus_assert (strcmp (name1, name2) == 0);
+
+  dbus_message_unref (copy);
+
+  /* Message loader test */
+  dbus_message_lock (message);
+  loader = _dbus_message_loader_new ();
+  
+  /* check ref/unref */
+  _dbus_message_loader_ref (loader);
+  _dbus_message_loader_unref (loader);
+
+  /* Write the header data one byte at a time */
+  data = _dbus_string_get_const_data (&message->header.data);
+  for (i = 0; i < _dbus_string_get_length (&message->header.data); i++)
+    {
+      DBusString *buffer;
+
+      _dbus_message_loader_get_buffer (loader, &buffer);
+      _dbus_string_append_byte (buffer, data[i]);
+      _dbus_message_loader_return_buffer (loader, buffer, 1);
+    }
+
+  /* Write the body data one byte at a time */
+  data = _dbus_string_get_const_data (&message->body);
+  for (i = 0; i < _dbus_string_get_length (&message->body); i++)
+    {
+      DBusString *buffer;
+
+      _dbus_message_loader_get_buffer (loader, &buffer);
+      _dbus_string_append_byte (buffer, data[i]);
+      _dbus_message_loader_return_buffer (loader, buffer, 1);
+    }
+
+#ifdef HAVE_UNIX_FD_PASSING
+  {
+    int *unix_fds;
+    unsigned n_unix_fds;
+    /* Write unix fd */
+    _dbus_message_loader_get_unix_fds(loader, &unix_fds, &n_unix_fds);
+    _dbus_assert(n_unix_fds > 0);
+    _dbus_assert(message->n_unix_fds == 1);
+    unix_fds[0] = _dbus_dup(message->unix_fds[0], NULL);
+    _dbus_assert(unix_fds[0] >= 0);
+    _dbus_message_loader_return_unix_fds(loader, unix_fds, 1);
+  }
+#endif
+
+  dbus_message_unref (message);
+
+  /* Now pop back the message */
+  if (!_dbus_message_loader_queue_messages (loader))
+    _dbus_assert_not_reached ("no memory to queue messages");
+
+  if (_dbus_message_loader_get_is_corrupted (loader))
+    _dbus_assert_not_reached ("message loader corrupted");
+
+  message = _dbus_message_loader_pop_message (loader);
+  if (!message)
+    _dbus_assert_not_reached ("received a NULL message");
+
+  if (dbus_message_get_reply_serial (message) != 5678)
+    _dbus_assert_not_reached ("reply serial fields differ");
+
+  dbus_message_unref (message);
+
+  /* ovveride the serial, since it was reset by dbus_message_copy() */
+  dbus_message_set_serial(message_without_unix_fds, 8901);
+
+  dbus_message_lock (message_without_unix_fds);
+
+  verify_test_message (message_without_unix_fds);
+
+    {
+      /* Marshal and demarshal the message. */
+
+      DBusMessage *message2;
+      DBusError error = DBUS_ERROR_INIT;
+      char *marshalled = NULL;
+      int len = 0;
+      char garbage_header[DBUS_MINIMUM_HEADER_SIZE] = "xxx";
+
+      if (!dbus_message_marshal (message_without_unix_fds, &marshalled, &len))
+        _dbus_assert_not_reached ("failed to marshal message");
+
+      _dbus_assert (len != 0);
+      _dbus_assert (marshalled != NULL);
+
+      _dbus_assert (dbus_message_demarshal_bytes_needed (marshalled, len) == len);
+      message2 = dbus_message_demarshal (marshalled, len, &error);
+
+      _dbus_assert (message2 != NULL);
+      _dbus_assert (!dbus_error_is_set (&error));
+      verify_test_message (message2);
+
+      dbus_message_unref (message2);
+      dbus_free (marshalled);
+
+      /* Demarshal invalid message. */
+
+      message2 = dbus_message_demarshal ("invalid", 7, &error);
+      _dbus_assert (message2 == NULL);
+      _dbus_assert (dbus_error_is_set (&error));
+      dbus_error_free (&error);
+
+      /* Demarshal invalid (empty) message. */
+
+      message2 = dbus_message_demarshal ("", 0, &error);
+      _dbus_assert (message2 == NULL);
+      _dbus_assert (dbus_error_is_set (&error));
+      dbus_error_free (&error);
+
+      /* Bytes needed to demarshal empty message: 0 (more) */
+
+      _dbus_assert (dbus_message_demarshal_bytes_needed ("", 0) == 0);
+      
+      /* Bytes needed to demarshal invalid message: -1 (error). */
+
+      _dbus_assert (dbus_message_demarshal_bytes_needed (garbage_header, DBUS_MINIMUM_HEADER_SIZE) == -1);
+    }
+
+  dbus_message_unref (message_without_unix_fds);
+  _dbus_message_loader_unref (loader);
+
+  check_memleaks ();
+  _dbus_check_fdleaks_leave (initial_fds);
+  initial_fds = _dbus_check_fdleaks_enter ();
+
+  /* Check that we can abandon a container */
+  message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
+		  			  "/org/freedesktop/TestPath",
+					  "Foo.TestInterface",
+					  "Method");
+
+  dbus_message_iter_init_append (message, &iter);
+
+  _dbus_assert (dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+			  			  (DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+						   DBUS_TYPE_STRING_AS_STRING
+						   DBUS_TYPE_STRING_AS_STRING
+						   DBUS_STRUCT_END_CHAR_AS_STRING),
+						  &array_iter));
+  _dbus_assert (dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT,
+			  			  NULL, &struct_iter));
+
+  s = "peaches";
+  _dbus_assert (dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING,
+			  			&s));
+
+  /* uh-oh, error, try and unwind */
+
+  dbus_message_iter_abandon_container (&array_iter, &struct_iter);
+  dbus_message_iter_abandon_container (&array_iter, &iter);
+
+  dbus_message_unref (message);
+
+  /* Load all the sample messages from the message factory */
+  {
+    DBusMessageDataIter diter;
+    DBusMessageData mdata;
+    int count;
+
+    reset_validities_seen ();
+    
+    count = 0;
+    _dbus_message_data_iter_init (&diter);
+    
+    while (_dbus_message_data_iter_get_and_next (&diter,
+                                                 &mdata))
+      {
+        if (!dbus_internal_do_not_use_try_message_data (&mdata.data,
+                                                        mdata.expected_validity))
+          {
+            _dbus_warn ("expected validity %d and did not get it\n",
+                        mdata.expected_validity);
+            _dbus_assert_not_reached ("message data failed");
+          }
+
+        _dbus_message_data_free (&mdata);
+
+        count += 1;
+      }
+
+    printf ("%d sample messages tested\n", count);
+
+    print_validities_seen (FALSE);
+    print_validities_seen (TRUE);
+  }
+
+  check_memleaks ();
+  _dbus_check_fdleaks_leave (initial_fds);
+
+  /* Now load every message in test_data_dir if we have one */
+  if (test_data_dir == NULL)
+    return TRUE;
+
+  initial_fds = _dbus_check_fdleaks_enter ();
+
+  if (!dbus_internal_do_not_use_foreach_message_file (test_data_dir,
+                                                        (DBusForeachMessageFileFunc)
+                                                        dbus_internal_do_not_use_try_message_file,
+                                                        NULL))
+    _dbus_assert_not_reached ("foreach_message_file test failed");
+
+  _dbus_check_fdleaks_leave (initial_fds);
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-message.c b/dbus/dbus/dbus-message.c
new file mode 100644
index 0000000..71bcee6
--- /dev/null
+++ b/dbus/dbus/dbus-message.c
@@ -0,0 +1,4767 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-message.c  DBusMessage object
+ *
+ * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
+ * Copyright (C) 2002, 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-marshal-recursive.h"
+#include "dbus-marshal-validate.h"
+#include "dbus-marshal-byteswap.h"
+#include "dbus-marshal-header.h"
+#include "dbus-signature.h"
+#include "dbus-message-private.h"
+#include "dbus-object-tree.h"
+#include "dbus-memory.h"
+#include "dbus-list.h"
+#include "dbus-threads-internal.h"
+#ifdef HAVE_UNIX_FD_PASSING
+#include "dbus-sysdeps-unix.h"
+#endif
+
+#include <string.h>
+
+#define _DBUS_TYPE_IS_STRINGLIKE(type) \
+  (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
+   type == DBUS_TYPE_OBJECT_PATH)
+
+static void dbus_message_finalize (DBusMessage *message);
+
+/**
+ * @defgroup DBusMessageInternals DBusMessage implementation details
+ * @ingroup DBusInternals
+ * @brief DBusMessage private implementation details.
+ *
+ * The guts of DBusMessage and its methods.
+ *
+ * @{
+ */
+
+#ifdef DBUS_BUILD_TESTS
+static dbus_bool_t
+_dbus_enable_message_cache (void)
+{
+  static int enabled = -1;
+
+  if (enabled < 0)
+    {
+      const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE");
+
+      enabled = TRUE;
+
+      if (s && *s)
+        {
+          if (*s == '0')
+            enabled = FALSE;
+          else if (*s == '1')
+            enabled = TRUE;
+          else
+            _dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'",
+                s);
+        }
+    }
+
+  return enabled;
+}
+#else
+    /* constant expression, should be optimized away */
+#   define _dbus_enable_message_cache() (TRUE)
+#endif
+
+#ifndef _dbus_message_trace_ref
+void
+_dbus_message_trace_ref (DBusMessage *message,
+                         int          old_refcount,
+                         int          new_refcount,
+                         const char  *why)
+{
+  static int enabled = -1;
+
+  _dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why,
+      "DBUS_MESSAGE_TRACE", &enabled);
+}
+#endif
+
+/* Not thread locked, but strictly const/read-only so should be OK
+ */
+/** An static string representing an empty signature */
+_DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
+
+/* these have wacky values to help trap uninitialized iterators;
+ * but has to fit in 3 bits
+ */
+enum {
+  DBUS_MESSAGE_ITER_TYPE_READER = 3,
+  DBUS_MESSAGE_ITER_TYPE_WRITER = 7
+};
+
+/** typedef for internals of message iterator */
+typedef struct DBusMessageRealIter DBusMessageRealIter;
+
+/**
+ * @brief Internals of DBusMessageIter
+ *
+ * Object representing a position in a message. All fields are internal.
+ */
+struct DBusMessageRealIter
+{
+  DBusMessage *message; /**< Message used */
+  dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; /**< stamp to detect invalid iters */
+  dbus_uint32_t iter_type : 3;      /**< whether this is a reader or writer iter */
+  dbus_uint32_t sig_refcount : 8;   /**< depth of open_signature() */
+  union
+  {
+    DBusTypeWriter writer; /**< writer */
+    DBusTypeReader reader; /**< reader */
+  } u; /**< the type writer or reader that does all the work */
+};
+
+static void
+get_const_signature (DBusHeader        *header,
+                     const DBusString **type_str_p,
+                     int               *type_pos_p)
+{
+  if (_dbus_header_get_field_raw (header,
+                                  DBUS_HEADER_FIELD_SIGNATURE,
+                                  type_str_p,
+                                  type_pos_p))
+    {
+      *type_pos_p += 1; /* skip the signature length which is 1 byte */
+    }
+  else
+    {
+      *type_str_p = &_dbus_empty_signature_str;
+      *type_pos_p = 0;
+    }
+}
+
+/**
+ * Swaps the message to compiler byte order if required
+ *
+ * @param message the message
+ */
+static void
+_dbus_message_byteswap (DBusMessage *message)
+{
+  const DBusString *type_str;
+  int type_pos;
+  char byte_order;
+
+  byte_order = _dbus_header_get_byte_order (&message->header);
+
+  if (byte_order == DBUS_COMPILER_BYTE_ORDER)
+    return;
+
+  _dbus_verbose ("Swapping message into compiler byte order\n");
+  
+  get_const_signature (&message->header, &type_str, &type_pos);
+  
+  _dbus_marshal_byteswap (type_str, type_pos,
+                          byte_order,
+                          DBUS_COMPILER_BYTE_ORDER,
+                          &message->body, 0);
+
+  _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
+  _dbus_assert (_dbus_header_get_byte_order (&message->header) ==
+                DBUS_COMPILER_BYTE_ORDER);
+}
+
+/** byte-swap the message if it doesn't match our byte order.
+ *  Called only when we need the message in our own byte order,
+ *  normally when reading arrays of integers or doubles.
+ *  Otherwise should not be called since it would do needless
+ *  work.
+ */
+#define ensure_byte_order(message) _dbus_message_byteswap (message)
+
+/**
+ * Gets the data to be sent over the network for this message.
+ * The header and then the body should be written out.
+ * This function is guaranteed to always return the same
+ * data once a message is locked (with dbus_message_lock()).
+ *
+ * @param message the message.
+ * @param header return location for message header data.
+ * @param body return location for message body data.
+ */
+void
+_dbus_message_get_network_data (DBusMessage          *message,
+                                const DBusString    **header,
+                                const DBusString    **body)
+{
+  _dbus_assert (message->locked);
+
+  *header = &message->header.data;
+  *body = &message->body;
+}
+
+/**
+ * Gets the unix fds to be sent over the network for this message.
+ * This function is guaranteed to always return the same data once a
+ * message is locked (with dbus_message_lock()).
+ *
+ * @param message the message.
+ * @param fds return location of unix fd array
+ * @param n_fds return number of entries in array
+ */
+void _dbus_message_get_unix_fds(DBusMessage *message,
+                                const int  **fds,
+                                unsigned    *n_fds)
+{
+  _dbus_assert (message->locked);
+
+#ifdef HAVE_UNIX_FD_PASSING
+  *fds = message->unix_fds;
+  *n_fds = message->n_unix_fds;
+#else
+  *fds = NULL;
+  *n_fds = 0;
+#endif
+}
+
+/**
+ * Sets the serial number of a message.
+ * This can only be done once on a message.
+ *
+ * DBusConnection will automatically set the serial to an appropriate value 
+ * when the message is sent; this function is only needed when encapsulating 
+ * messages in another protocol, or otherwise bypassing DBusConnection.
+ *
+ * @param message the message
+ * @param serial the serial
+ */
+void 
+dbus_message_set_serial (DBusMessage   *message,
+                         dbus_uint32_t  serial)
+{
+  _dbus_return_if_fail (message != NULL);
+  _dbus_return_if_fail (!message->locked);
+
+  _dbus_header_set_serial (&message->header, serial);
+}
+
+/**
+ * Adds a counter to be incremented immediately with the size/unix fds
+ * of this message, and decremented by the size/unix fds of this
+ * message when this message if finalized.  The link contains a
+ * counter with its refcount already incremented, but the counter
+ * itself not incremented.  Ownership of link and counter refcount is
+ * passed to the message.
+ *
+ * This function may be called with locks held. As a result, the counter's
+ * notify function is not called; the caller is expected to either call
+ * _dbus_counter_notify() on the counter when they are no longer holding
+ * locks, or take the same action that would be taken by the notify function.
+ *
+ * @param message the message
+ * @param link link with counter as data
+ */
+void
+_dbus_message_add_counter_link (DBusMessage  *message,
+                                DBusList     *link)
+{
+  /* right now we don't recompute the delta when message
+   * size changes, and that's OK for current purposes
+   * I think, but could be important to change later.
+   * Do recompute it whenever there are no outstanding counters,
+   * since it's basically free.
+   */
+  if (message->counters == NULL)
+    {
+      message->size_counter_delta =
+        _dbus_string_get_length (&message->header.data) +
+        _dbus_string_get_length (&message->body);
+
+#ifdef HAVE_UNIX_FD_PASSING
+      message->unix_fd_counter_delta = message->n_unix_fds;
+#endif
+
+#if 0
+      _dbus_verbose ("message has size %ld\n",
+                     message->size_counter_delta);
+#endif
+    }
+
+  _dbus_list_append_link (&message->counters, link);
+
+  _dbus_counter_adjust_size (link->data, message->size_counter_delta);
+
+#ifdef HAVE_UNIX_FD_PASSING
+  _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
+#endif
+}
+
+/**
+ * Adds a counter to be incremented immediately with the size/unix fds
+ * of this message, and decremented by the size/unix fds of this
+ * message when this message if finalized.
+ *
+ * This function may be called with locks held. As a result, the counter's
+ * notify function is not called; the caller is expected to either call
+ * _dbus_counter_notify() on the counter when they are no longer holding
+ * locks, or take the same action that would be taken by the notify function.
+ *
+ * @param message the message
+ * @param counter the counter
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_message_add_counter (DBusMessage *message,
+                           DBusCounter *counter)
+{
+  DBusList *link;
+
+  link = _dbus_list_alloc_link (counter);
+  if (link == NULL)
+    return FALSE;
+
+  _dbus_counter_ref (counter);
+  _dbus_message_add_counter_link (message, link);
+
+  return TRUE;
+}
+
+/**
+ * Removes a counter tracking the size/unix fds of this message, and
+ * decrements the counter by the size/unix fds of this message.
+ *
+ * @param message the message
+ * @param counter the counter
+ */
+void
+_dbus_message_remove_counter (DBusMessage  *message,
+                              DBusCounter  *counter)
+{
+  DBusList *link;
+
+  link = _dbus_list_find_last (&message->counters,
+                               counter);
+  _dbus_assert (link != NULL);
+
+  _dbus_list_remove_link (&message->counters, link);
+
+  _dbus_counter_adjust_size (counter, - message->size_counter_delta);
+
+#ifdef HAVE_UNIX_FD_PASSING
+  _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
+#endif
+
+  _dbus_counter_notify (counter);
+  _dbus_counter_unref (counter);
+}
+
+/**
+ * Locks a message. Allows checking that applications don't keep a
+ * reference to a message in the outgoing queue and change it
+ * underneath us. Messages are locked when they enter the outgoing
+ * queue (dbus_connection_send_message()), and the library complains
+ * if the message is modified while locked. This function may also 
+ * called externally, for applications wrapping D-Bus in another protocol.
+ *
+ * @param message the message to lock.
+ */
+void
+dbus_message_lock (DBusMessage  *message)
+{
+  if (!message->locked)
+    {
+      _dbus_header_update_lengths (&message->header,
+                                   _dbus_string_get_length (&message->body));
+
+      /* must have a signature if you have a body */
+      _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
+                    dbus_message_get_signature (message) != NULL);
+
+      message->locked = TRUE;
+    }
+}
+
+static dbus_bool_t
+set_or_delete_string_field (DBusMessage *message,
+                            int          field,
+                            int          typecode,
+                            const char  *value)
+{
+  if (value == NULL)
+    return _dbus_header_delete_field (&message->header, field);
+  else
+    return _dbus_header_set_field_basic (&message->header,
+                                         field,
+                                         typecode,
+                                         &value);
+}
+
+#if 0
+/* Probably we don't need to use this */
+/**
+ * Sets the signature of the message, i.e. the arguments in the
+ * message payload. The signature includes only "in" arguments for
+ * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
+ * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
+ * what you might expect (it does not include the signature of the
+ * entire C++-style method).
+ *
+ * The signature is a string made up of type codes such as
+ * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also
+ * the value of #DBUS_TYPE_INVALID). The macros such as
+ * #DBUS_TYPE_INT32 evaluate to integers; to assemble a signature you
+ * may find it useful to use the string forms, such as
+ * #DBUS_TYPE_INT32_AS_STRING.
+ *
+ * An "unset" or #NULL signature is considered the same as an empty
+ * signature. In fact dbus_message_get_signature() will never return
+ * #NULL.
+ *
+ * @param message the message
+ * @param signature the type signature or #NULL to unset
+ * @returns #FALSE if no memory
+ */
+static dbus_bool_t
+_dbus_message_set_signature (DBusMessage *message,
+                             const char  *signature)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  _dbus_return_val_if_fail (signature == NULL ||
+                            _dbus_check_is_valid_signature (signature));
+  /* can't delete the signature if you have a message body */
+  _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
+                            signature != NULL);
+
+  return set_or_delete_string_field (message,
+                                     DBUS_HEADER_FIELD_SIGNATURE,
+                                     DBUS_TYPE_SIGNATURE,
+                                     signature);
+}
+#endif
+
+/* Message Cache
+ *
+ * We cache some DBusMessage to reduce the overhead of allocating
+ * them.  In my profiling this consistently made about an 8%
+ * difference.  It avoids the malloc for the message, the malloc for
+ * the slot list, the malloc for the header string and body string,
+ * and the associated free() calls. It does introduce another global
+ * lock which could be a performance issue in certain cases.
+ *
+ * For the echo client/server the round trip time goes from around
+ * .000077 to .000069 with the message cache on my laptop. The sysprof
+ * change is as follows (numbers are cumulative percentage):
+ *
+ *  with message cache implemented as array as it is now (0.000069 per):
+ *    new_empty_header           1.46
+ *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
+ *      mutex_unlock             0.25
+ *      self                     0.41
+ *    unref                      2.24
+ *      self                     0.68
+ *      list_clear               0.43
+ *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
+ *      mutex_unlock             0.25
+ *
+ *  with message cache implemented as list (0.000070 per roundtrip):
+ *    new_empty_header           2.72
+ *      list_pop_first           1.88
+ *    unref                      3.3
+ *      list_prepend             1.63
+ *
+ * without cache (0.000077 per roundtrip):
+ *    new_empty_header           6.7
+ *      string_init_preallocated 3.43
+ *        dbus_malloc            2.43
+ *      dbus_malloc0             2.59
+ *
+ *    unref                      4.02
+ *      string_free              1.82
+ *        dbus_free              1.63
+ *      dbus_free                0.71
+ *
+ * If you implement the message_cache with a list, the primary reason
+ * it's slower is that you add another thread lock (on the DBusList
+ * mempool).
+ */
+
+/** Avoid caching huge messages */
+#define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
+
+/** Avoid caching too many messages */
+#define MAX_MESSAGE_CACHE_SIZE    5
+
+_DBUS_DEFINE_GLOBAL_LOCK (message_cache);
+static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
+static int message_cache_count = 0;
+static dbus_bool_t message_cache_shutdown_registered = FALSE;
+
+static void
+dbus_message_cache_shutdown (void *data)
+{
+  int i;
+
+  _DBUS_LOCK (message_cache);
+
+  i = 0;
+  while (i < MAX_MESSAGE_CACHE_SIZE)
+    {
+      if (message_cache[i])
+        dbus_message_finalize (message_cache[i]);
+
+      ++i;
+    }
+
+  message_cache_count = 0;
+  message_cache_shutdown_registered = FALSE;
+
+  _DBUS_UNLOCK (message_cache);
+}
+
+/**
+ * Tries to get a message from the message cache.  The retrieved
+ * message will have junk in it, so it still needs to be cleared out
+ * in dbus_message_new_empty_header()
+ *
+ * @returns the message, or #NULL if none cached
+ */
+static DBusMessage*
+dbus_message_get_cached (void)
+{
+  DBusMessage *message;
+  int i;
+
+  message = NULL;
+
+  _DBUS_LOCK (message_cache);
+
+  _dbus_assert (message_cache_count >= 0);
+
+  if (message_cache_count == 0)
+    {
+      _DBUS_UNLOCK (message_cache);
+      return NULL;
+    }
+
+  /* This is not necessarily true unless count > 0, and
+   * message_cache is uninitialized until the shutdown is
+   * registered
+   */
+  _dbus_assert (message_cache_shutdown_registered);
+
+  i = 0;
+  while (i < MAX_MESSAGE_CACHE_SIZE)
+    {
+      if (message_cache[i])
+        {
+          message = message_cache[i];
+          message_cache[i] = NULL;
+          message_cache_count -= 1;
+          break;
+        }
+      ++i;
+    }
+  _dbus_assert (message_cache_count >= 0);
+  _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
+  _dbus_assert (message != NULL);
+
+  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
+
+  _dbus_assert (message->counters == NULL);
+  
+  _DBUS_UNLOCK (message_cache);
+
+  return message;
+}
+
+#ifdef HAVE_UNIX_FD_PASSING
+static void
+close_unix_fds(int *fds, unsigned *n_fds)
+{
+  DBusError e;
+  int i;
+
+  if (*n_fds <= 0)
+    return;
+
+  dbus_error_init(&e);
+
+  for (i = 0; i < *n_fds; i++)
+    {
+      if (!_dbus_close(fds[i], &e))
+        {
+          _dbus_warn("Failed to close file descriptor: %s\n", e.message);
+          dbus_error_free(&e);
+        }
+    }
+
+  *n_fds = 0;
+
+  /* We don't free the array here, in case we can recycle it later */
+}
+#endif
+
+static void
+free_counter (void *element,
+              void *data)
+{
+  DBusCounter *counter = element;
+  DBusMessage *message = data;
+
+  _dbus_counter_adjust_size (counter, - message->size_counter_delta);
+#ifdef HAVE_UNIX_FD_PASSING
+  _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
+#endif
+
+  _dbus_counter_notify (counter);
+  _dbus_counter_unref (counter);
+}
+
+/**
+ * Tries to cache a message, otherwise finalize it.
+ *
+ * @param message the message
+ */
+static void
+dbus_message_cache_or_finalize (DBusMessage *message)
+{
+  dbus_bool_t was_cached;
+  int i;
+
+  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
+
+  /* This calls application code and has to be done first thing
+   * without holding the lock
+   */
+  _dbus_data_slot_list_clear (&message->slot_list);
+
+  _dbus_list_foreach (&message->counters,
+                      free_counter, message);
+  _dbus_list_clear (&message->counters);
+
+#ifdef HAVE_UNIX_FD_PASSING
+  close_unix_fds(message->unix_fds, &message->n_unix_fds);
+#endif
+
+  was_cached = FALSE;
+
+  _DBUS_LOCK (message_cache);
+
+  if (!message_cache_shutdown_registered)
+    {
+      _dbus_assert (message_cache_count == 0);
+
+      if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
+        goto out;
+
+      i = 0;
+      while (i < MAX_MESSAGE_CACHE_SIZE)
+        {
+          message_cache[i] = NULL;
+          ++i;
+        }
+
+      message_cache_shutdown_registered = TRUE;
+    }
+
+  _dbus_assert (message_cache_count >= 0);
+
+  if (!_dbus_enable_message_cache ())
+    goto out;
+
+  if ((_dbus_string_get_length (&message->header.data) +
+       _dbus_string_get_length (&message->body)) >
+      MAX_MESSAGE_SIZE_TO_CACHE)
+    goto out;
+
+  if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
+    goto out;
+
+  /* Find empty slot */
+  i = 0;
+  while (message_cache[i] != NULL)
+    ++i;
+
+  _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
+
+  _dbus_assert (message_cache[i] == NULL);
+  message_cache[i] = message;
+  message_cache_count += 1;
+  was_cached = TRUE;
+#ifndef DBUS_DISABLE_CHECKS
+  message->in_cache = TRUE;
+#endif
+
+ out:
+  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
+
+  _DBUS_UNLOCK (message_cache);
+  
+  if (!was_cached)
+    dbus_message_finalize (message);
+}
+
+#ifndef DBUS_DISABLE_CHECKS
+static dbus_bool_t
+_dbus_message_iter_check (DBusMessageRealIter *iter)
+{
+  char byte_order;
+
+  if (iter == NULL)
+    {
+      _dbus_warn_check_failed ("dbus message iterator is NULL\n");
+      return FALSE;
+    }
+
+  byte_order = _dbus_header_get_byte_order (&iter->message->header);
+
+  if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
+    {
+      if (iter->u.reader.byte_order != byte_order)
+        {
+          _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
+          return FALSE;
+        }
+      /* because we swap the message into compiler order when you init an iter */
+      _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
+    }
+  else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
+    {
+      if (iter->u.writer.byte_order != byte_order)
+        {
+          _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
+          return FALSE;
+        }
+      /* because we swap the message into compiler order when you init an iter */
+      _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
+    }
+  else
+    {
+      _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
+      return FALSE;
+    }
+
+  if (iter->changed_stamp != iter->message->changed_stamp)
+    {
+      _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+#endif /* DBUS_DISABLE_CHECKS */
+
+/**
+ * Implementation of the varargs arg-getting functions.
+ * dbus_message_get_args() is the place to go for complete
+ * documentation.
+ *
+ * @todo This may leak memory and file descriptors if parsing fails. See #21259
+ *
+ * @see dbus_message_get_args
+ * @param iter the message iter
+ * @param error error to be filled in
+ * @param first_arg_type type of the first argument
+ * @param var_args return location for first argument, followed by list of type/location pairs
+ * @returns #FALSE if error was set
+ */
+dbus_bool_t
+_dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+                                    DBusError       *error,
+                                    int              first_arg_type,
+                                    va_list          var_args)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int spec_type, msg_type, i;
+  dbus_bool_t retval;
+
+  _dbus_assert (_dbus_message_iter_check (real));
+
+  retval = FALSE;
+
+  spec_type = first_arg_type;
+  i = 0;
+
+  while (spec_type != DBUS_TYPE_INVALID)
+    {
+      msg_type = dbus_message_iter_get_arg_type (iter);
+
+      if (msg_type != spec_type)
+	{
+          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                          "Argument %d is specified to be of type \"%s\", but "
+                          "is actually of type \"%s\"\n", i,
+                          _dbus_type_to_string (spec_type),
+                          _dbus_type_to_string (msg_type));
+
+          goto out;
+	}
+
+      if (spec_type == DBUS_TYPE_UNIX_FD)
+        {
+#ifdef HAVE_UNIX_FD_PASSING
+          DBusBasicValue idx;
+          int *pfd, nfd;
+
+          pfd = va_arg (var_args, int*);
+          _dbus_assert(pfd);
+
+          _dbus_type_reader_read_basic(&real->u.reader, &idx);
+
+          if (idx.u32 >= real->message->n_unix_fds)
+            {
+              dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
+                              "Message refers to file descriptor at index %i,"
+                              "but has only %i descriptors attached.\n",
+                              idx.u32,
+                              real->message->n_unix_fds);
+              goto out;
+            }
+
+          if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
+            goto out;
+
+          *pfd = nfd;
+#else
+          dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
+                          "Platform does not support file desciptor passing.\n");
+          goto out;
+#endif
+        }
+      else if (dbus_type_is_basic (spec_type))
+        {
+          DBusBasicValue *ptr;
+
+          ptr = va_arg (var_args, DBusBasicValue*);
+
+          _dbus_assert (ptr != NULL);
+
+          _dbus_type_reader_read_basic (&real->u.reader,
+                                        ptr);
+        }
+      else if (spec_type == DBUS_TYPE_ARRAY)
+        {
+          int element_type;
+          int spec_element_type;
+          const DBusBasicValue **ptr;
+          int *n_elements_p;
+          DBusTypeReader array;
+
+          spec_element_type = va_arg (var_args, int);
+          element_type = _dbus_type_reader_get_element_type (&real->u.reader);
+
+          if (spec_element_type != element_type)
+            {
+              dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                              "Argument %d is specified to be an array of \"%s\", but "
+                              "is actually an array of \"%s\"\n",
+                              i,
+                              _dbus_type_to_string (spec_element_type),
+                              _dbus_type_to_string (element_type));
+
+              goto out;
+            }
+
+          if (dbus_type_is_fixed (spec_element_type) &&
+              element_type != DBUS_TYPE_UNIX_FD)
+            {
+              ptr = va_arg (var_args, const DBusBasicValue**);
+              n_elements_p = va_arg (var_args, int*);
+
+              _dbus_assert (ptr != NULL);
+              _dbus_assert (n_elements_p != NULL);
+
+              _dbus_type_reader_recurse (&real->u.reader, &array);
+
+              _dbus_type_reader_read_fixed_multi (&array,
+                                                  (void *) ptr, n_elements_p);
+            }
+          else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
+            {
+              char ***str_array_p;
+              int n_elements;
+              char **str_array;
+
+              str_array_p = va_arg (var_args, char***);
+              n_elements_p = va_arg (var_args, int*);
+
+              _dbus_assert (str_array_p != NULL);
+              _dbus_assert (n_elements_p != NULL);
+
+              /* Count elements in the array */
+              _dbus_type_reader_recurse (&real->u.reader, &array);
+
+              n_elements = 0;
+              while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
+                {
+                  ++n_elements;
+                  _dbus_type_reader_next (&array);
+                }
+
+              str_array = dbus_new0 (char*, n_elements + 1);
+              if (str_array == NULL)
+                {
+                  _DBUS_SET_OOM (error);
+                  goto out;
+                }
+
+              /* Now go through and dup each string */
+              _dbus_type_reader_recurse (&real->u.reader, &array);
+
+              i = 0;
+              while (i < n_elements)
+                {
+                  const char *s;
+                  _dbus_type_reader_read_basic (&array,
+                                                (void *) &s);
+                  
+                  str_array[i] = _dbus_strdup (s);
+                  if (str_array[i] == NULL)
+                    {
+                      dbus_free_string_array (str_array);
+                      _DBUS_SET_OOM (error);
+                      goto out;
+                    }
+                  
+                  ++i;
+                  
+                  if (!_dbus_type_reader_next (&array))
+                    _dbus_assert (i == n_elements);
+                }
+
+              _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
+              _dbus_assert (i == n_elements);
+              _dbus_assert (str_array[i] == NULL);
+
+              *str_array_p = str_array;
+              *n_elements_p = n_elements;
+            }
+#ifndef DBUS_DISABLE_CHECKS
+          else
+            {
+              _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
+                          _DBUS_FUNCTION_NAME);
+              goto out;
+            }
+#endif
+        }
+#ifndef DBUS_DISABLE_CHECKS
+      else
+        {
+          _dbus_warn ("you can only read arrays and basic types with %s for now\n",
+                      _DBUS_FUNCTION_NAME);
+          goto out;
+        }
+#endif
+
+      spec_type = va_arg (var_args, int);
+      if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
+        {
+          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                          "Message has only %d arguments, but more were expected", i);
+          goto out;
+        }
+
+      i++;
+    }
+
+  retval = TRUE;
+
+ out:
+
+  return retval;
+}
+
+/** @} */
+
+/**
+ * @defgroup DBusMessage DBusMessage
+ * @ingroup  DBus
+ * @brief Message to be sent or received over a #DBusConnection.
+ *
+ * A DBusMessage is the most basic unit of communication over a
+ * DBusConnection. A DBusConnection represents a stream of messages
+ * received from a remote application, and a stream of messages
+ * sent to a remote application.
+ *
+ * A message has a message type, returned from
+ * dbus_message_get_type().  This indicates whether the message is a
+ * method call, a reply to a method call, a signal, or an error reply.
+ *
+ * A message has header fields such as the sender, destination, method
+ * or signal name, and so forth. DBusMessage has accessor functions for
+ * these, such as dbus_message_get_member().
+ *
+ * Convenience functions dbus_message_is_method_call(), dbus_message_is_signal(),
+ * and dbus_message_is_error() check several header fields at once and are
+ * slightly more efficient than checking the header fields with individual
+ * accessor functions.
+ *
+ * Finally, a message has arguments. The number and types of arguments
+ * are in the message's signature header field (accessed with
+ * dbus_message_get_signature()).  Simple argument values are usually
+ * retrieved with dbus_message_get_args() but more complex values such
+ * as structs may require the use of #DBusMessageIter.
+ *
+ * The D-Bus specification goes into some more detail about header fields and
+ * message types.
+ * 
+ * @{
+ */
+
+/**
+ * @typedef DBusMessage
+ *
+ * Opaque data type representing a message received from or to be
+ * sent to another application.
+ */
+
+/**
+ * Returns the serial of a message or 0 if none has been specified.
+ * The message's serial number is provided by the application sending
+ * the message and is used to identify replies to this message.
+ *
+ * All messages received on a connection will have a serial provided
+ * by the remote application.
+ *
+ * For messages you're sending, dbus_connection_send() will assign a
+ * serial and return it to you.
+ *
+ * @param message the message
+ * @returns the serial
+ */
+dbus_uint32_t
+dbus_message_get_serial (DBusMessage *message)
+{
+  _dbus_return_val_if_fail (message != NULL, 0);
+
+  return _dbus_header_get_serial (&message->header);
+}
+
+/**
+ * Sets the reply serial of a message (the serial of the message this
+ * is a reply to).
+ *
+ * @param message the message
+ * @param reply_serial the serial we're replying to
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_reply_serial (DBusMessage   *message,
+                               dbus_uint32_t  reply_serial)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
+
+  return _dbus_header_set_field_basic (&message->header,
+                                       DBUS_HEADER_FIELD_REPLY_SERIAL,
+                                       DBUS_TYPE_UINT32,
+                                       &reply_serial);
+}
+
+/**
+ * Returns the serial that the message is a reply to or 0 if none.
+ *
+ * @param message the message
+ * @returns the reply serial
+ */
+dbus_uint32_t
+dbus_message_get_reply_serial  (DBusMessage *message)
+{
+  dbus_uint32_t v_UINT32;
+
+  _dbus_return_val_if_fail (message != NULL, 0);
+
+  if (_dbus_header_get_field_basic (&message->header,
+                                    DBUS_HEADER_FIELD_REPLY_SERIAL,
+                                    DBUS_TYPE_UINT32,
+                                    &v_UINT32))
+    return v_UINT32;
+  else
+    return 0;
+}
+
+static void
+dbus_message_finalize (DBusMessage *message)
+{
+  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
+
+  /* This calls application callbacks! */
+  _dbus_data_slot_list_free (&message->slot_list);
+
+  _dbus_list_foreach (&message->counters,
+                      free_counter, message);
+  _dbus_list_clear (&message->counters);
+
+  _dbus_header_free (&message->header);
+  _dbus_string_free (&message->body);
+
+#ifdef HAVE_UNIX_FD_PASSING
+  close_unix_fds(message->unix_fds, &message->n_unix_fds);
+  dbus_free(message->unix_fds);
+#endif
+
+  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
+
+  dbus_free (message);
+}
+
+static DBusMessage*
+dbus_message_new_empty_header (void)
+{
+  DBusMessage *message;
+  dbus_bool_t from_cache;
+
+  message = dbus_message_get_cached ();
+
+  if (message != NULL)
+    {
+      from_cache = TRUE;
+    }
+  else
+    {
+      from_cache = FALSE;
+      message = dbus_new0 (DBusMessage, 1);
+      if (message == NULL)
+        return NULL;
+#ifndef DBUS_DISABLE_CHECKS
+      message->generation = _dbus_current_generation;
+#endif
+
+#ifdef HAVE_UNIX_FD_PASSING
+      message->unix_fds = NULL;
+      message->n_unix_fds_allocated = 0;
+#endif
+    }
+
+  _dbus_atomic_inc (&message->refcount);
+
+  _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
+
+  message->locked = FALSE;
+#ifndef DBUS_DISABLE_CHECKS
+  message->in_cache = FALSE;
+#endif
+  message->counters = NULL;
+  message->size_counter_delta = 0;
+  message->changed_stamp = 0;
+
+#ifdef HAVE_UNIX_FD_PASSING
+  message->n_unix_fds = 0;
+  message->n_unix_fds_allocated = 0;
+  message->unix_fd_counter_delta = 0;
+#endif
+
+  if (!from_cache)
+    _dbus_data_slot_list_init (&message->slot_list);
+
+  if (from_cache)
+    {
+      _dbus_header_reinit (&message->header);
+      _dbus_string_set_length (&message->body, 0);
+    }
+  else
+    {
+      if (!_dbus_header_init (&message->header))
+        {
+          dbus_free (message);
+          return NULL;
+        }
+
+      if (!_dbus_string_init_preallocated (&message->body, 32))
+        {
+          _dbus_header_free (&message->header);
+          dbus_free (message);
+          return NULL;
+        }
+    }
+
+  return message;
+}
+
+/**
+ * Constructs a new message of the given message type.
+ * Types include #DBUS_MESSAGE_TYPE_METHOD_CALL,
+ * #DBUS_MESSAGE_TYPE_SIGNAL, and so forth.
+ *
+ * Usually you want to use dbus_message_new_method_call(),
+ * dbus_message_new_method_return(), dbus_message_new_signal(),
+ * or dbus_message_new_error() instead.
+ * 
+ * @param message_type type of message
+ * @returns new message or #NULL if no memory
+ */
+DBusMessage*
+dbus_message_new (int message_type)
+{
+  DBusMessage *message;
+
+  _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
+
+  message = dbus_message_new_empty_header ();
+  if (message == NULL)
+    return NULL;
+
+  if (!_dbus_header_create (&message->header,
+                            DBUS_COMPILER_BYTE_ORDER,
+                            message_type,
+                            NULL, NULL, NULL, NULL, NULL))
+    {
+      dbus_message_unref (message);
+      return NULL;
+    }
+
+  return message;
+}
+
+/**
+ * Constructs a new message to invoke a method on a remote
+ * object. Returns #NULL if memory can't be allocated for the
+ * message. The destination may be #NULL in which case no destination
+ * is set; this is appropriate when using D-Bus in a peer-to-peer
+ * context (no message bus). The interface may be #NULL, which means
+ * that if multiple methods with the given name exist it is undefined
+ * which one will be invoked.
+ *
+ * The path and method names may not be #NULL.
+ *
+ * Destination, path, interface, and method name can't contain
+ * any invalid characters (see the D-Bus specification).
+ * 
+ * @param destination name that the message should be sent to or #NULL
+ * @param path object path the message should be sent to
+ * @param interface interface to invoke method on, or #NULL
+ * @param method method to invoke
+ *
+ * @returns a new DBusMessage, free with dbus_message_unref()
+ */
+DBusMessage*
+dbus_message_new_method_call (const char *destination,
+                              const char *path,
+                              const char *interface,
+                              const char *method)
+{
+  DBusMessage *message;
+
+  _dbus_return_val_if_fail (path != NULL, NULL);
+  _dbus_return_val_if_fail (method != NULL, NULL);
+  _dbus_return_val_if_fail (destination == NULL ||
+                            _dbus_check_is_valid_bus_name (destination), NULL);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
+  _dbus_return_val_if_fail (interface == NULL ||
+                            _dbus_check_is_valid_interface (interface), NULL);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
+
+  message = dbus_message_new_empty_header ();
+  if (message == NULL)
+    return NULL;
+
+  if (!_dbus_header_create (&message->header,
+                            DBUS_COMPILER_BYTE_ORDER,
+                            DBUS_MESSAGE_TYPE_METHOD_CALL,
+                            destination, path, interface, method, NULL))
+    {
+      dbus_message_unref (message);
+      return NULL;
+    }
+
+  return message;
+}
+
+/**
+ * Constructs a message that is a reply to a method call. Returns
+ * #NULL if memory can't be allocated for the message.
+ *
+ * @param method_call the message being replied to
+ * @returns a new DBusMessage, free with dbus_message_unref()
+ */
+DBusMessage*
+dbus_message_new_method_return (DBusMessage *method_call)
+{
+  DBusMessage *message;
+  const char *sender;
+
+  _dbus_return_val_if_fail (method_call != NULL, NULL);
+
+  sender = dbus_message_get_sender (method_call);
+
+  /* sender is allowed to be null here in peer-to-peer case */
+
+  message = dbus_message_new_empty_header ();
+  if (message == NULL)
+    return NULL;
+
+  if (!_dbus_header_create (&message->header,
+                            DBUS_COMPILER_BYTE_ORDER,
+                            DBUS_MESSAGE_TYPE_METHOD_RETURN,
+                            sender, NULL, NULL, NULL, NULL))
+    {
+      dbus_message_unref (message);
+      return NULL;
+    }
+
+  dbus_message_set_no_reply (message, TRUE);
+
+  if (!dbus_message_set_reply_serial (message,
+                                      dbus_message_get_serial (method_call)))
+    {
+      dbus_message_unref (message);
+      return NULL;
+    }
+
+  return message;
+}
+
+/**
+ * Constructs a new message representing a signal emission. Returns
+ * #NULL if memory can't be allocated for the message.  A signal is
+ * identified by its originating object path, interface, and the name
+ * of the signal.
+ *
+ * Path, interface, and signal name must all be valid (the D-Bus
+ * specification defines the syntax of these fields).
+ * 
+ * @param path the path to the object emitting the signal
+ * @param interface the interface the signal is emitted from
+ * @param name name of the signal
+ * @returns a new DBusMessage, free with dbus_message_unref()
+ */
+DBusMessage*
+dbus_message_new_signal (const char *path,
+                         const char *interface,
+                         const char *name)
+{
+  DBusMessage *message;
+
+  _dbus_return_val_if_fail (path != NULL, NULL);
+  _dbus_return_val_if_fail (interface != NULL, NULL);
+  _dbus_return_val_if_fail (name != NULL, NULL);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
+
+  message = dbus_message_new_empty_header ();
+  if (message == NULL)
+    return NULL;
+
+  if (!_dbus_header_create (&message->header,
+                            DBUS_COMPILER_BYTE_ORDER,
+                            DBUS_MESSAGE_TYPE_SIGNAL,
+                            NULL, path, interface, name, NULL))
+    {
+      dbus_message_unref (message);
+      return NULL;
+    }
+
+  dbus_message_set_no_reply (message, TRUE);
+
+  return message;
+}
+
+/**
+ * Creates a new message that is an error reply to another message.
+ * Error replies are most common in response to method calls, but
+ * can be returned in reply to any message.
+ *
+ * The error name must be a valid error name according to the syntax
+ * given in the D-Bus specification. If you don't want to make
+ * up an error name just use #DBUS_ERROR_FAILED.
+ *
+ * @param reply_to the message we're replying to
+ * @param error_name the error name
+ * @param error_message the error message string (or #NULL for none, but please give a message)
+ * @returns a new error message object, free with dbus_message_unref()
+ */
+DBusMessage*
+dbus_message_new_error (DBusMessage *reply_to,
+                        const char  *error_name,
+                        const char  *error_message)
+{
+  DBusMessage *message;
+  const char *sender;
+  DBusMessageIter iter;
+
+  _dbus_return_val_if_fail (reply_to != NULL, NULL);
+  _dbus_return_val_if_fail (error_name != NULL, NULL);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
+
+  sender = dbus_message_get_sender (reply_to);
+
+  /* sender may be NULL for non-message-bus case or
+   * when the message bus is dealing with an unregistered
+   * connection.
+   */
+  message = dbus_message_new_empty_header ();
+  if (message == NULL)
+    return NULL;
+
+  if (!_dbus_header_create (&message->header,
+                            DBUS_COMPILER_BYTE_ORDER,
+                            DBUS_MESSAGE_TYPE_ERROR,
+                            sender, NULL, NULL, NULL, error_name))
+    {
+      dbus_message_unref (message);
+      return NULL;
+    }
+
+  dbus_message_set_no_reply (message, TRUE);
+
+  if (!dbus_message_set_reply_serial (message,
+                                      dbus_message_get_serial (reply_to)))
+    {
+      dbus_message_unref (message);
+      return NULL;
+    }
+
+  if (error_message != NULL)
+    {
+      dbus_message_iter_init_append (message, &iter);
+      if (!dbus_message_iter_append_basic (&iter,
+                                           DBUS_TYPE_STRING,
+                                           &error_message))
+        {
+          dbus_message_unref (message);
+          return NULL;
+        }
+    }
+
+  return message;
+}
+
+/**
+ * Creates a new message that is an error reply to another message, allowing
+ * you to use printf formatting.
+ *
+ * See dbus_message_new_error() for details - this function is the same
+ * aside from the printf formatting.
+ *
+ * @todo add _DBUS_GNUC_PRINTF to this (requires moving _DBUS_GNUC_PRINTF to
+ * public header, see DBUS_DEPRECATED for an example)
+ * 
+ * @param reply_to the original message
+ * @param error_name the error name
+ * @param error_format the error message format as with printf
+ * @param ... format string arguments
+ * @returns a new error message
+ */
+DBusMessage*
+dbus_message_new_error_printf (DBusMessage *reply_to,
+			       const char  *error_name,
+			       const char  *error_format,
+			       ...)
+{
+  va_list args;
+  DBusString str;
+  DBusMessage *message;
+
+  _dbus_return_val_if_fail (reply_to != NULL, NULL);
+  _dbus_return_val_if_fail (error_name != NULL, NULL);
+  _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
+
+  if (!_dbus_string_init (&str))
+    return NULL;
+
+  va_start (args, error_format);
+
+  if (_dbus_string_append_printf_valist (&str, error_format, args))
+    message = dbus_message_new_error (reply_to, error_name,
+				      _dbus_string_get_const_data (&str));
+  else
+    message = NULL;
+
+  _dbus_string_free (&str);
+
+  va_end (args);
+
+  return message;
+}
+
+
+/**
+ * Creates a new message that is an exact replica of the message
+ * specified, except that its refcount is set to 1, its message serial
+ * is reset to 0, and if the original message was "locked" (in the
+ * outgoing message queue and thus not modifiable) the new message
+ * will not be locked.
+ *
+ * @todo This function can't be used in programs that try to recover from OOM errors.
+ *
+ * @param message the message
+ * @returns the new message.or #NULL if not enough memory or Unix file descriptors (in case the message to copy includes Unix file descriptors) can be allocated.
+ */
+DBusMessage *
+dbus_message_copy (const DBusMessage *message)
+{
+  DBusMessage *retval;
+
+  _dbus_return_val_if_fail (message != NULL, NULL);
+
+  retval = dbus_new0 (DBusMessage, 1);
+  if (retval == NULL)
+    return NULL;
+
+  _dbus_atomic_inc (&retval->refcount);
+
+  retval->locked = FALSE;
+#ifndef DBUS_DISABLE_CHECKS
+  retval->generation = message->generation;
+#endif
+
+  if (!_dbus_header_copy (&message->header, &retval->header))
+    {
+      dbus_free (retval);
+      return NULL;
+    }
+
+  if (!_dbus_string_init_preallocated (&retval->body,
+                                       _dbus_string_get_length (&message->body)))
+    {
+      _dbus_header_free (&retval->header);
+      dbus_free (retval);
+      return NULL;
+    }
+
+  if (!_dbus_string_copy (&message->body, 0,
+			  &retval->body, 0))
+    goto failed_copy;
+
+#ifdef HAVE_UNIX_FD_PASSING
+  retval->unix_fds = dbus_new(int, message->n_unix_fds);
+  if (retval->unix_fds == NULL && message->n_unix_fds > 0)
+    goto failed_copy;
+
+  retval->n_unix_fds_allocated = message->n_unix_fds;
+
+  for (retval->n_unix_fds = 0;
+       retval->n_unix_fds < message->n_unix_fds;
+       retval->n_unix_fds++)
+    {
+      retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
+
+      if (retval->unix_fds[retval->n_unix_fds] < 0)
+        goto failed_copy;
+    }
+
+#endif
+
+  _dbus_message_trace_ref (retval, 0, 1, "copy");
+  return retval;
+
+ failed_copy:
+  _dbus_header_free (&retval->header);
+  _dbus_string_free (&retval->body);
+
+#ifdef HAVE_UNIX_FD_PASSING
+  close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
+  dbus_free(retval->unix_fds);
+#endif
+
+  dbus_free (retval);
+
+  return NULL;
+}
+
+
+/**
+ * Increments the reference count of a DBusMessage.
+ *
+ * @param message the message
+ * @returns the message
+ * @see dbus_message_unref
+ */
+DBusMessage *
+dbus_message_ref (DBusMessage *message)
+{
+  dbus_int32_t old_refcount;
+
+  _dbus_return_val_if_fail (message != NULL, NULL);
+  _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
+  _dbus_return_val_if_fail (!message->in_cache, NULL);
+
+  old_refcount = _dbus_atomic_inc (&message->refcount);
+  _dbus_assert (old_refcount >= 1);
+  _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
+
+  return message;
+}
+
+/**
+ * Decrements the reference count of a DBusMessage, freeing the
+ * message if the count reaches 0.
+ *
+ * @param message the message
+ * @see dbus_message_ref
+ */
+void
+dbus_message_unref (DBusMessage *message)
+{
+ dbus_int32_t old_refcount;
+
+  _dbus_return_if_fail (message != NULL);
+  _dbus_return_if_fail (message->generation == _dbus_current_generation);
+  _dbus_return_if_fail (!message->in_cache);
+
+  old_refcount = _dbus_atomic_dec (&message->refcount);
+
+  _dbus_assert (old_refcount >= 1);
+
+  _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
+
+  if (old_refcount == 1)
+    {
+      /* Calls application callbacks! */
+      dbus_message_cache_or_finalize (message);
+    }
+}
+
+/**
+ * Gets the type of a message. Types include
+ * #DBUS_MESSAGE_TYPE_METHOD_CALL, #DBUS_MESSAGE_TYPE_METHOD_RETURN,
+ * #DBUS_MESSAGE_TYPE_ERROR, #DBUS_MESSAGE_TYPE_SIGNAL, but other
+ * types are allowed and all code must silently ignore messages of
+ * unknown type. #DBUS_MESSAGE_TYPE_INVALID will never be returned.
+ *
+ * @param message the message
+ * @returns the type of the message
+ */
+int
+dbus_message_get_type (DBusMessage *message)
+{
+  _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
+
+  return _dbus_header_get_message_type (&message->header);
+}
+
+/**
+ * Appends fields to a message given a variable argument list. The
+ * variable argument list should contain the type of each argument
+ * followed by the value to append. Appendable types are basic types,
+ * and arrays of fixed-length basic types (except arrays of Unix file
+ * descriptors). To append variable-length basic types, or any more
+ * complex value, you have to use an iterator rather than this
+ * function.
+ *
+ * To append a basic type, specify its type code followed by the
+ * address of the value. For example:
+ *
+ * @code
+ *
+ * dbus_int32_t v_INT32 = 42;
+ * const char *v_STRING = "Hello World";
+ * dbus_message_append_args (message,
+ *                           DBUS_TYPE_INT32, &v_INT32,
+ *                           DBUS_TYPE_STRING, &v_STRING,
+ *                           DBUS_TYPE_INVALID);
+ * @endcode
+ *
+ * To append an array of fixed-length basic types (except Unix file
+ * descriptors), pass in the DBUS_TYPE_ARRAY typecode, the element
+ * typecode, the address of the array pointer, and a 32-bit integer
+ * giving the number of elements in the array. So for example: @code
+ * const dbus_int32_t array[] = { 1, 2, 3 }; const dbus_int32_t
+ * *v_ARRAY = array; dbus_message_append_args (message,
+ * DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY, 3, DBUS_TYPE_INVALID);
+ * @endcode
+ *
+ * This function does not support arrays of Unix file descriptors. If
+ * you need those you need to manually recurse into the array.
+ *
+ * For Unix file descriptors this function will internally duplicate
+ * the descriptor you passed in. Hence you may close the descriptor
+ * immediately after this call.
+ *
+ * @warning in C, given "int array[]", "&array == array" (the
+ * comp.lang.c FAQ says otherwise, but gcc and the FAQ don't agree).
+ * So if you're using an array instead of a pointer you have to create
+ * a pointer variable, assign the array to it, then take the address
+ * of the pointer variable. For strings it works to write
+ * const char *array = "Hello" and then use &array though.
+ *
+ * The last argument to this function must be #DBUS_TYPE_INVALID,
+ * marking the end of the argument list. If you don't do this
+ * then libdbus won't know to stop and will read invalid memory.
+ *
+ * String/signature/path arrays should be passed in as "const char***
+ * address_of_array" and "int n_elements"
+ *
+ * @todo support DBUS_TYPE_STRUCT and DBUS_TYPE_VARIANT and complex arrays
+ *
+ * @todo If this fails due to lack of memory, the message is hosed and
+ * you have to start over building the whole message.
+ *
+ * @param message the message
+ * @param first_arg_type type of the first argument
+ * @param ... value of first argument, list of additional type-value pairs
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_append_args (DBusMessage *message,
+			  int          first_arg_type,
+			  ...)
+{
+  dbus_bool_t retval;
+  va_list var_args;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+
+  va_start (var_args, first_arg_type);
+  retval = dbus_message_append_args_valist (message,
+					    first_arg_type,
+					    var_args);
+  va_end (var_args);
+
+  return retval;
+}
+
+/**
+ * Like dbus_message_append_args() but takes a va_list for use by language bindings.
+ *
+ * @todo for now, if this function fails due to OOM it will leave
+ * the message half-written and you have to discard the message
+ * and start over.
+ *
+ * @see dbus_message_append_args.
+ * @param message the message
+ * @param first_arg_type type of first argument
+ * @param var_args value of first argument, then list of type/value pairs
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_append_args_valist (DBusMessage *message,
+				 int          first_arg_type,
+				 va_list      var_args)
+{
+  int type;
+  DBusMessageIter iter;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+
+  type = first_arg_type;
+
+  dbus_message_iter_init_append (message, &iter);
+
+  while (type != DBUS_TYPE_INVALID)
+    {
+      if (dbus_type_is_basic (type))
+        {
+          const DBusBasicValue *value;
+          value = va_arg (var_args, const DBusBasicValue*);
+
+          if (!dbus_message_iter_append_basic (&iter,
+                                               type,
+                                               value))
+            goto failed;
+        }
+      else if (type == DBUS_TYPE_ARRAY)
+        {
+          int element_type;
+          DBusMessageIter array;
+          char buf[2];
+
+          element_type = va_arg (var_args, int);
+              
+          buf[0] = element_type;
+          buf[1] = '\0';
+          if (!dbus_message_iter_open_container (&iter,
+                                                 DBUS_TYPE_ARRAY,
+                                                 buf,
+                                                 &array))
+            goto failed;
+
+          if (dbus_type_is_fixed (element_type) &&
+              element_type != DBUS_TYPE_UNIX_FD)
+            {
+              const DBusBasicValue **value;
+              int n_elements;
+
+              value = va_arg (var_args, const DBusBasicValue**);
+              n_elements = va_arg (var_args, int);
+              
+              if (!dbus_message_iter_append_fixed_array (&array,
+                                                         element_type,
+                                                         value,
+                                                         n_elements)) {
+                dbus_message_iter_abandon_container (&iter, &array);
+                goto failed;
+              }
+            }
+          else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
+            {
+              const char ***value_p;
+              const char **value;
+              int n_elements;
+              int i;
+              
+              value_p = va_arg (var_args, const char***);
+              n_elements = va_arg (var_args, int);
+
+              value = *value_p;
+              
+              i = 0;
+              while (i < n_elements)
+                {
+                  if (!dbus_message_iter_append_basic (&array,
+                                                       element_type,
+                                                       &value[i])) {
+                    dbus_message_iter_abandon_container (&iter, &array);
+                    goto failed;
+                  }
+                  ++i;
+                }
+            }
+          else
+            {
+              _dbus_warn ("arrays of %s can't be appended with %s for now\n",
+                          _dbus_type_to_string (element_type),
+                          _DBUS_FUNCTION_NAME);
+              goto failed;
+            }
+
+          if (!dbus_message_iter_close_container (&iter, &array))
+            goto failed;
+        }
+#ifndef DBUS_DISABLE_CHECKS
+      else
+        {
+          _dbus_warn ("type %s isn't supported yet in %s\n",
+                      _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
+          goto failed;
+        }
+#endif
+
+      type = va_arg (var_args, int);
+    }
+
+  return TRUE;
+
+ failed:
+  return FALSE;
+}
+
+/**
+ * Gets arguments from a message given a variable argument list.  The
+ * supported types include those supported by
+ * dbus_message_append_args(); that is, basic types and arrays of
+ * fixed-length basic types.  The arguments are the same as they would
+ * be for dbus_message_iter_get_basic() or
+ * dbus_message_iter_get_fixed_array().
+ *
+ * In addition to those types, arrays of string, object path, and
+ * signature are supported; but these are returned as allocated memory
+ * and must be freed with dbus_free_string_array(), while the other
+ * types are returned as const references. To get a string array
+ * pass in "char ***array_location" and "int *n_elements".
+ *
+ * Similar to dbus_message_get_fixed_array() this function does not
+ * support arrays of type DBUS_TYPE_UNIX_FD. If you need to parse
+ * messages with arrays of Unix file descriptors you need to recurse
+ * into the array manually.
+ *
+ * Unix file descriptors that are read with this function will have
+ * the FD_CLOEXEC flag set. If you need them without this flag set,
+ * make sure to unset it with fcntl().
+ *
+ * The variable argument list should contain the type of the argument
+ * followed by a pointer to where the value should be stored. The list
+ * is terminated with #DBUS_TYPE_INVALID.
+ *
+ * Except for string arrays, the returned values are constant; do not
+ * free them. They point into the #DBusMessage.
+ *
+ * If the requested arguments are not present, or do not have the
+ * requested types, then an error will be set.
+ *
+ * If more arguments than requested are present, the requested
+ * arguments are returned and the extra arguments are ignored.
+ * 
+ * @todo support DBUS_TYPE_STRUCT and DBUS_TYPE_VARIANT and complex arrays
+ *
+ * @param message the message
+ * @param error error to be filled in on failure
+ * @param first_arg_type the first argument type
+ * @param ... location for first argument value, then list of type-location pairs
+ * @returns #FALSE if the error was set
+ */
+dbus_bool_t
+dbus_message_get_args (DBusMessage     *message,
+                       DBusError       *error,
+		       int              first_arg_type,
+		       ...)
+{
+  dbus_bool_t retval;
+  va_list var_args;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
+
+  va_start (var_args, first_arg_type);
+  retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
+  va_end (var_args);
+
+  return retval;
+}
+
+/**
+ * Like dbus_message_get_args but takes a va_list for use by language bindings.
+ *
+ * @see dbus_message_get_args
+ * @param message the message
+ * @param error error to be filled in
+ * @param first_arg_type type of the first argument
+ * @param var_args return location for first argument, followed by list of type/location pairs
+ * @returns #FALSE if error was set
+ */
+dbus_bool_t
+dbus_message_get_args_valist (DBusMessage     *message,
+                              DBusError       *error,
+			      int              first_arg_type,
+			      va_list          var_args)
+{
+  DBusMessageIter iter;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
+
+  dbus_message_iter_init (message, &iter);
+  return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
+}
+
+static void
+_dbus_message_iter_init_common (DBusMessage         *message,
+                                DBusMessageRealIter *real,
+                                int                  iter_type)
+{
+  _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
+
+  /* Since the iterator will read or write who-knows-what from the
+   * message, we need to get in the right byte order
+   */
+  ensure_byte_order (message);
+  
+  real->message = message;
+  real->changed_stamp = message->changed_stamp;
+  real->iter_type = iter_type;
+  real->sig_refcount = 0;
+}
+
+/**
+ * Initializes a #DBusMessageIter for reading the arguments of the
+ * message passed in.
+ *
+ * When possible, dbus_message_get_args() is much more convenient.
+ * Some types of argument can only be read with #DBusMessageIter
+ * however.
+ *
+ * The easiest way to iterate is like this: 
+ * @code
+ * dbus_message_iter_init (message, &iter);
+ * while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
+ *   dbus_message_iter_next (&iter);
+ * @endcode
+ *
+ * #DBusMessageIter contains no allocated memory; it need not be
+ * freed, and can be copied by assignment or memcpy().
+ * 
+ * @param message the message
+ * @param iter pointer to an iterator to initialize
+ * @returns #FALSE if the message has no arguments
+ */
+dbus_bool_t
+dbus_message_iter_init (DBusMessage     *message,
+			DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  const DBusString *type_str;
+  int type_pos;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (iter != NULL, FALSE);
+
+  get_const_signature (&message->header, &type_str, &type_pos);
+
+  _dbus_message_iter_init_common (message, real,
+                                  DBUS_MESSAGE_ITER_TYPE_READER);
+
+  _dbus_type_reader_init (&real->u.reader,
+                          _dbus_header_get_byte_order (&message->header),
+                          type_str, type_pos,
+                          &message->body,
+                          0);
+
+  return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
+}
+
+/**
+ * Checks if an iterator has any more fields.
+ *
+ * @param iter the message iter
+ * @returns #TRUE if there are more fields following
+ */
+dbus_bool_t
+dbus_message_iter_has_next (DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
+  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
+
+  return _dbus_type_reader_has_next (&real->u.reader);
+}
+
+/**
+ * Moves the iterator to the next field, if any. If there's no next
+ * field, returns #FALSE. If the iterator moves forward, returns
+ * #TRUE.
+ *
+ * @param iter the message iter
+ * @returns #TRUE if the iterator was moved to the next field
+ */
+dbus_bool_t
+dbus_message_iter_next (DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
+  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
+
+  return _dbus_type_reader_next (&real->u.reader);
+}
+
+/**
+ * Returns the argument type of the argument that the message iterator
+ * points to. If the iterator is at the end of the message, returns
+ * #DBUS_TYPE_INVALID. You can thus write a loop as follows:
+ *
+ * @code
+ * dbus_message_iter_init (message, &iter);
+ * while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
+ *   dbus_message_iter_next (&iter);
+ * @endcode
+ *
+ * @param iter the message iter
+ * @returns the argument type
+ */
+int
+dbus_message_iter_get_arg_type (DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
+  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
+
+  return _dbus_type_reader_get_current_type (&real->u.reader);
+}
+
+/**
+ * Returns the element type of the array that the message iterator
+ * points to. Note that you need to check that the iterator points to
+ * an array prior to using this function.
+ *
+ * @param iter the message iter
+ * @returns the array element type
+ */
+int
+dbus_message_iter_get_element_type (DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
+  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
+  _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
+
+  return _dbus_type_reader_get_element_type (&real->u.reader);
+}
+
+/**
+ * Recurses into a container value when reading values from a message,
+ * initializing a sub-iterator to use for traversing the child values
+ * of the container.
+ *
+ * Note that this recurses into a value, not a type, so you can only
+ * recurse if the value exists. The main implication of this is that
+ * if you have for example an empty array of array of int32, you can
+ * recurse into the outermost array, but it will have no values, so
+ * you won't be able to recurse further. There's no array of int32 to
+ * recurse into.
+ *
+ * If a container is an array of fixed-length types (except Unix file
+ * descriptors), it is much more efficient to use
+ * dbus_message_iter_get_fixed_array() to get the whole array in one
+ * shot, rather than individually walking over the array elements.
+ *
+ * Be sure you have somehow checked that
+ * dbus_message_iter_get_arg_type() matches the type you are expecting
+ * to recurse into. Results of this function are undefined if there is
+ * no container to recurse into at the current iterator position.
+ *
+ * @param iter the message iterator
+ * @param sub the sub-iterator to initialize
+ */
+void
+dbus_message_iter_recurse (DBusMessageIter  *iter,
+                           DBusMessageIter  *sub)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
+
+  _dbus_return_if_fail (_dbus_message_iter_check (real));
+  _dbus_return_if_fail (sub != NULL);
+
+  *real_sub = *real;
+  _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
+}
+
+/**
+ * Returns the current signature of a message iterator.  This
+ * is useful primarily for dealing with variants; one can
+ * recurse into a variant and determine the signature of
+ * the variant's value.
+ *
+ * The returned string must be freed with dbus_free().
+ * 
+ * @param iter the message iterator
+ * @returns the contained signature, or NULL if out of memory
+ */
+char *
+dbus_message_iter_get_signature (DBusMessageIter *iter)
+{
+  const DBusString *sig;
+  DBusString retstr;
+  char *ret;
+  int start, len;
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
+
+  if (!_dbus_string_init (&retstr))
+    return NULL;
+
+  _dbus_type_reader_get_signature (&real->u.reader, &sig,
+				   &start, &len);
+  if (!_dbus_string_append_len (&retstr,
+				_dbus_string_get_const_data (sig) + start,
+				len))
+    return NULL;
+  if (!_dbus_string_steal_data (&retstr, &ret))
+    return NULL;
+  _dbus_string_free (&retstr);
+  return ret;
+}
+
+/**
+ * Reads a basic-typed value from the message iterator.
+ * Basic types are the non-containers such as integer and string.
+ *
+ * The value argument should be the address of a location to store
+ * the returned value. So for int32 it should be a "dbus_int32_t*"
+ * and for string a "const char**". The returned value is
+ * by reference and should not be freed.
+ *
+ * This call duplicates Unix file descriptors when reading them. It is
+ * your job to close them when you don't need them anymore.
+ *
+ * Unix file descriptors that are read with this function will have
+ * the FD_CLOEXEC flag set. If you need them without this flag set,
+ * make sure to unset it with fcntl().
+ *
+ * Be sure you have somehow checked that
+ * dbus_message_iter_get_arg_type() matches the type you are
+ * expecting, or you'll crash when you try to use an integer as a
+ * string or something.
+ *
+ * To read any container type (array, struct, dict) you will need to
+ * recurse into the container with dbus_message_iter_recurse().  If
+ * the container is an array of fixed-length values (except Unix file
+ * descriptors), you can get all the array elements at once with
+ * dbus_message_iter_get_fixed_array(). Otherwise, you have to iterate
+ * over the container's contents one value at a time.
+ *
+ * All basic-typed values are guaranteed to fit in a #DBusBasicValue,
+ * so in versions of libdbus that have that type, you can write code like this:
+ *
+ * @code
+ * DBusBasicValue value;
+ * int type;
+ * dbus_message_iter_get_basic (&read_iter, &value);
+ * type = dbus_message_iter_get_arg_type (&read_iter);
+ * dbus_message_iter_append_basic (&write_iter, type, &value);
+ * @endcode
+ *
+ * (All D-Bus basic types are either numeric and 8 bytes or smaller, or
+ * behave like a string; so in older versions of libdbus, DBusBasicValue
+ * can be replaced with union { char *string; unsigned char bytes[8]; },
+ * for instance.)
+ *
+ * @param iter the iterator
+ * @param value location to store the value
+ */
+void
+dbus_message_iter_get_basic (DBusMessageIter  *iter,
+                             void             *value)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_if_fail (_dbus_message_iter_check (real));
+  _dbus_return_if_fail (value != NULL);
+
+  if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
+    {
+#ifdef HAVE_UNIX_FD_PASSING
+      DBusBasicValue idx;
+
+      _dbus_type_reader_read_basic(&real->u.reader, &idx);
+
+      if (idx.u32 >= real->message->n_unix_fds) {
+        /* Hmm, we cannot really signal an error here, so let's make
+           sure to return an invalid fd. */
+        *((int*) value) = -1;
+        return;
+      }
+
+      *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
+#else
+      *((int*) value) = -1;
+#endif
+    }
+  else
+    {
+      _dbus_type_reader_read_basic (&real->u.reader,
+                                    value);
+    }
+}
+
+/**
+ * Returns the number of bytes in the array as marshaled in the wire
+ * protocol. The iterator must currently be inside an array-typed
+ * value.
+ *
+ * This function is deprecated on the grounds that it is stupid.  Why
+ * would you want to know how many bytes are in the array as marshaled
+ * in the wire protocol?  For now, use the n_elements returned from
+ * dbus_message_iter_get_fixed_array() instead, or iterate over the
+ * array values and count them.
+ *
+ * @todo introduce a variant of this get_n_elements that returns
+ * the number of elements, though with a non-fixed array it will not
+ * be very efficient, so maybe it's not good.
+ * 
+ * @param iter the iterator
+ * @returns the number of bytes in the array
+ */
+int
+dbus_message_iter_get_array_len (DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
+
+  return _dbus_type_reader_get_array_length (&real->u.reader);
+}
+
+/**
+ * Reads a block of fixed-length values from the message iterator.
+ * Fixed-length values are those basic types that are not string-like,
+ * such as integers, bool, double. The returned block will be from the
+ * current position in the array until the end of the array.
+ *
+ * There is one exception here: although DBUS_TYPE_UNIX_FD is
+ * considered a 'fixed' type arrays of this type may not be read with
+ * this function.
+ *
+ * The message iter should be "in" the array (that is, you recurse into the
+ * array, and then you call dbus_message_iter_get_fixed_array() on the
+ * "sub-iterator" created by dbus_message_iter_recurse()).
+ *
+ * The value argument should be the address of a location to store the
+ * returned array. So for int32 it should be a "const dbus_int32_t**"
+ * The returned value is by reference and should not be freed.
+ * 
+ * This function should only be used if dbus_type_is_fixed() returns
+ * #TRUE for the element type.
+ *
+ * If an array's elements are not fixed in size, you have to recurse
+ * into the array with dbus_message_iter_recurse() and read the
+ * elements one by one.
+ * 
+ * Because the array is not copied, this function runs in constant
+ * time and is fast; it's much preferred over walking the entire array
+ * with an iterator. (However, you can always use
+ * dbus_message_iter_recurse(), even for fixed-length types;
+ * dbus_message_iter_get_fixed_array() is just an optimization.)
+ * 
+ * @param iter the iterator
+ * @param value location to store the block
+ * @param n_elements number of elements in the block
+ */
+void
+dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
+                                   void             *value,
+                                   int              *n_elements)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+#ifndef DBUS_DISABLE_CHECKS
+  int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
+
+  _dbus_return_if_fail (_dbus_message_iter_check (real));
+  _dbus_return_if_fail (value != NULL);
+  _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
+                        (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
+#endif
+
+  _dbus_type_reader_read_fixed_multi (&real->u.reader,
+                                      value, n_elements);
+}
+
+/**
+ * Initializes a #DBusMessageIter for appending arguments to the end
+ * of a message.
+ *
+ * @todo If appending any of the arguments fails due to lack of
+ * memory, the message is hosed and you have to start over building
+ * the whole message.
+ *
+ * @param message the message
+ * @param iter pointer to an iterator to initialize
+ */
+void
+dbus_message_iter_init_append (DBusMessage     *message,
+			       DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_if_fail (message != NULL);
+  _dbus_return_if_fail (iter != NULL);
+
+  _dbus_message_iter_init_common (message, real,
+                                  DBUS_MESSAGE_ITER_TYPE_WRITER);
+
+  /* We create the signature string and point iterators at it "on demand"
+   * when a value is actually appended. That means that init() never fails
+   * due to OOM.
+   */
+  _dbus_type_writer_init_types_delayed (&real->u.writer,
+                                        _dbus_header_get_byte_order (&message->header),
+                                        &message->body,
+                                        _dbus_string_get_length (&message->body));
+}
+
+/**
+ * Creates a temporary signature string containing the current
+ * signature, stores it in the iterator, and points the iterator to
+ * the end of it. Used any time we write to the message.
+ *
+ * @param real an iterator without a type_str
+ * @returns #FALSE if no memory
+ */
+static dbus_bool_t
+_dbus_message_iter_open_signature (DBusMessageRealIter *real)
+{
+  DBusString *str;
+  const DBusString *current_sig;
+  int current_sig_pos;
+
+  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
+
+  if (real->u.writer.type_str != NULL)
+    {
+      _dbus_assert (real->sig_refcount > 0);
+      real->sig_refcount += 1;
+      return TRUE;
+    }
+
+  str = dbus_new (DBusString, 1);
+  if (str == NULL)
+    return FALSE;
+
+  if (!_dbus_header_get_field_raw (&real->message->header,
+                                   DBUS_HEADER_FIELD_SIGNATURE,
+                                   &current_sig, &current_sig_pos))
+    current_sig = NULL;
+
+  if (current_sig)
+    {
+      int current_len;
+
+      current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
+      current_sig_pos += 1; /* move on to sig data */
+
+      if (!_dbus_string_init_preallocated (str, current_len + 4))
+        {
+          dbus_free (str);
+          return FALSE;
+        }
+
+      if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
+                                  str, 0))
+        {
+          _dbus_string_free (str);
+          dbus_free (str);
+          return FALSE;
+        }
+    }
+  else
+    {
+      if (!_dbus_string_init_preallocated (str, 4))
+        {
+          dbus_free (str);
+          return FALSE;
+        }
+    }
+
+  real->sig_refcount = 1;
+
+  _dbus_type_writer_add_types (&real->u.writer,
+                               str, _dbus_string_get_length (str));
+  return TRUE;
+}
+
+/**
+ * Sets the new signature as the message signature, frees the
+ * signature string, and marks the iterator as not having a type_str
+ * anymore. Frees the signature even if it fails, so you can't
+ * really recover from failure. Kinda busted.
+ *
+ * @param real an iterator without a type_str
+ * @returns #FALSE if no memory
+ */
+static dbus_bool_t
+_dbus_message_iter_close_signature (DBusMessageRealIter *real)
+{
+  DBusString *str;
+  const char *v_STRING;
+  dbus_bool_t retval;
+
+  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
+  _dbus_assert (real->u.writer.type_str != NULL);
+  _dbus_assert (real->sig_refcount > 0);
+
+  real->sig_refcount -= 1;
+
+  if (real->sig_refcount > 0)
+    return TRUE;
+  _dbus_assert (real->sig_refcount == 0);
+
+  retval = TRUE;
+
+  str = real->u.writer.type_str;
+
+  v_STRING = _dbus_string_get_const_data (str);
+  if (!_dbus_header_set_field_basic (&real->message->header,
+                                     DBUS_HEADER_FIELD_SIGNATURE,
+                                     DBUS_TYPE_SIGNATURE,
+                                     &v_STRING))
+    retval = FALSE;
+
+  _dbus_type_writer_remove_types (&real->u.writer);
+  _dbus_string_free (str);
+  dbus_free (str);
+
+  return retval;
+}
+
+/**
+ * Frees the signature string and marks the iterator as not having a
+ * type_str anymore.  Since the new signature is not set, the message
+ * will generally be hosed after this is called.
+ *
+ * @param real an iterator without a type_str
+ */
+static void
+_dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
+{
+  DBusString *str;
+
+  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
+  _dbus_assert (real->u.writer.type_str != NULL);
+  _dbus_assert (real->sig_refcount > 0);
+
+  real->sig_refcount -= 1;
+
+  if (real->sig_refcount > 0)
+    return;
+  _dbus_assert (real->sig_refcount == 0);
+
+  str = real->u.writer.type_str;
+
+  _dbus_type_writer_remove_types (&real->u.writer);
+  _dbus_string_free (str);
+  dbus_free (str);
+}
+
+#ifndef DBUS_DISABLE_CHECKS
+static dbus_bool_t
+_dbus_message_iter_append_check (DBusMessageRealIter *iter)
+{
+  if (!_dbus_message_iter_check (iter))
+    return FALSE;
+
+  if (iter->message->locked)
+    {
+      _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+#endif /* DBUS_DISABLE_CHECKS */
+
+#ifdef HAVE_UNIX_FD_PASSING
+static int *
+expand_fd_array(DBusMessage *m,
+                unsigned     n)
+{
+  _dbus_assert(m);
+
+  /* This makes space for adding n new fds to the array and returns a
+     pointer to the place were the first fd should be put. */
+
+  if (m->n_unix_fds + n > m->n_unix_fds_allocated)
+    {
+      unsigned k;
+      int *p;
+
+      /* Make twice as much space as necessary */
+      k = (m->n_unix_fds + n) * 2;
+
+      /* Allocate at least four */
+      if (k < 4)
+        k = 4;
+
+      p = dbus_realloc(m->unix_fds, k * sizeof(int));
+      if (p == NULL)
+        return NULL;
+
+      m->unix_fds = p;
+      m->n_unix_fds_allocated = k;
+    }
+
+  return m->unix_fds + m->n_unix_fds;
+}
+#endif
+
+/**
+ * Appends a basic-typed value to the message. The basic types are the
+ * non-container types such as integer and string.
+ *
+ * The "value" argument should be the address of a basic-typed value.
+ * So for string, const char**. For integer, dbus_int32_t*.
+ *
+ * For Unix file descriptors this function will internally duplicate
+ * the descriptor you passed in. Hence you may close the descriptor
+ * immediately after this call.
+ *
+ * @todo If this fails due to lack of memory, the message is hosed and
+ * you have to start over building the whole message.
+ *
+ * @param iter the append iterator
+ * @param type the type of the value
+ * @param value the address of the value
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_iter_append_basic (DBusMessageIter *iter,
+                                int              type,
+                                const void      *value)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  dbus_bool_t ret;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
+  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
+  _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
+  _dbus_return_val_if_fail (value != NULL, FALSE);
+
+#ifndef DBUS_DISABLE_CHECKS
+  switch (type)
+    {
+      const char * const *string_p;
+      const dbus_bool_t *bool_p;
+
+      case DBUS_TYPE_STRING:
+        string_p = value;
+        _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
+        break;
+
+      case DBUS_TYPE_OBJECT_PATH:
+        string_p = value;
+        _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
+        break;
+
+      case DBUS_TYPE_SIGNATURE:
+        string_p = value;
+        _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
+        break;
+
+      case DBUS_TYPE_BOOLEAN:
+        bool_p = value;
+        _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
+        break;
+
+      default:
+          {
+            /* nothing to check, all possible values are allowed */
+          }
+    }
+#endif
+
+  if (!_dbus_message_iter_open_signature (real))
+    return FALSE;
+
+  if (type == DBUS_TYPE_UNIX_FD)
+    {
+#ifdef HAVE_UNIX_FD_PASSING
+      int *fds;
+      dbus_uint32_t u;
+
+      /* First step, include the fd in the fd list of this message */
+      if (!(fds = expand_fd_array(real->message, 1)))
+        return FALSE;
+
+      *fds = _dbus_dup(*(int*) value, NULL);
+      if (*fds < 0)
+        return FALSE;
+
+      u = real->message->n_unix_fds;
+
+      /* Second step, write the index to the fd */
+      if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
+        _dbus_close(*fds, NULL);
+        return FALSE;
+      }
+
+      real->message->n_unix_fds += 1;
+      u += 1;
+
+      /* Final step, update the header accordingly */
+      ret = _dbus_header_set_field_basic (&real->message->header,
+                                          DBUS_HEADER_FIELD_UNIX_FDS,
+                                          DBUS_TYPE_UINT32,
+                                          &u);
+
+      /* If any of these operations fail the message is
+         hosed. However, no memory or fds should be leaked since what
+         has been added to message has been added to the message, and
+         can hence be accounted for when the message is being
+         freed. */
+#else
+      ret = FALSE;
+#endif
+    }
+  else
+    {
+      ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
+    }
+
+  if (!_dbus_message_iter_close_signature (real))
+    ret = FALSE;
+
+  return ret;
+}
+
+/**
+ * Appends a block of fixed-length values to an array. The
+ * fixed-length types are all basic types that are not string-like. So
+ * int32, double, bool, etc. (Unix file descriptors however are not
+ * supported.) You must call dbus_message_iter_open_container() to
+ * open an array of values before calling this function. You may call
+ * this function multiple times (and intermixed with calls to
+ * dbus_message_iter_append_basic()) for the same array.
+ *
+ * The "value" argument should be the address of the array.  So for
+ * integer, "dbus_int32_t**" is expected for example.
+ *
+ * @warning in C, given "int array[]", "&array == array" (the
+ * comp.lang.c FAQ says otherwise, but gcc and the FAQ don't agree).
+ * So if you're using an array instead of a pointer you have to create
+ * a pointer variable, assign the array to it, then take the address
+ * of the pointer variable.
+ * @code
+ * const dbus_int32_t array[] = { 1, 2, 3 };
+ * const dbus_int32_t *v_ARRAY = array;
+ * if (!dbus_message_iter_append_fixed_array (&iter, DBUS_TYPE_INT32, &v_ARRAY, 3))
+ *   fprintf (stderr, "No memory!\n");
+ * @endcode
+ * For strings it works to write const char *array = "Hello" and then
+ * use &array though.
+ *
+ * @todo If this fails due to lack of memory, the message is hosed and
+ * you have to start over building the whole message.
+ *
+ * @param iter the append iterator
+ * @param element_type the type of the array elements
+ * @param value the address of the array
+ * @param n_elements the number of elements to append
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
+                                      int              element_type,
+                                      const void      *value,
+                                      int              n_elements)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  dbus_bool_t ret;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
+  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
+  _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
+  _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
+  _dbus_return_val_if_fail (value != NULL, FALSE);
+  _dbus_return_val_if_fail (n_elements >= 0, FALSE);
+  _dbus_return_val_if_fail (n_elements <=
+                            DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
+                            FALSE);
+
+#ifndef DBUS_DISABLE_CHECKS
+  if (element_type == DBUS_TYPE_BOOLEAN)
+    {
+      const dbus_bool_t * const *bools = value;
+      int i;
+
+      for (i = 0; i < n_elements; i++)
+        {
+          _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
+        }
+    }
+#endif
+
+  ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
+
+  return ret;
+}
+
+/**
+ * Appends a container-typed value to the message; you are required to
+ * append the contents of the container using the returned
+ * sub-iterator, and then call
+ * dbus_message_iter_close_container(). Container types are for
+ * example struct, variant, and array. For variants, the
+ * contained_signature should be the type of the single value inside
+ * the variant. For structs and dict entries, contained_signature
+ * should be #NULL; it will be set to whatever types you write into
+ * the struct.  For arrays, contained_signature should be the type of
+ * the array elements.
+ *
+ * @todo If this fails due to lack of memory, the message is hosed and
+ * you have to start over building the whole message.
+ *
+ * @param iter the append iterator
+ * @param type the type of the value
+ * @param contained_signature the type of container contents
+ * @param sub sub-iterator to initialize
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_iter_open_container (DBusMessageIter *iter,
+                                  int              type,
+                                  const char      *contained_signature,
+                                  DBusMessageIter *sub)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
+  DBusString contained_str;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
+  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
+  _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
+  _dbus_return_val_if_fail (sub != NULL, FALSE);
+  _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
+                             contained_signature == NULL) ||
+                            (type == DBUS_TYPE_DICT_ENTRY &&
+                             contained_signature == NULL) ||
+                            (type == DBUS_TYPE_VARIANT &&
+                             contained_signature != NULL) ||
+                            (type == DBUS_TYPE_ARRAY &&
+                             contained_signature != NULL), FALSE);
+  
+  /* this would fail if the contained_signature is a dict entry, since
+   * dict entries are invalid signatures standalone (they must be in
+   * an array)
+   */
+  _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
+                            (contained_signature == NULL ||
+                             _dbus_check_is_valid_signature (contained_signature)),
+                            FALSE);
+
+  if (!_dbus_message_iter_open_signature (real))
+    return FALSE;
+
+  *real_sub = *real;
+
+  if (contained_signature != NULL)
+    {
+      _dbus_string_init_const (&contained_str, contained_signature);
+
+      return _dbus_type_writer_recurse (&real->u.writer,
+                                        type,
+                                        &contained_str, 0,
+                                        &real_sub->u.writer);
+    }
+  else
+    {
+      return _dbus_type_writer_recurse (&real->u.writer,
+                                        type,
+                                        NULL, 0,
+                                        &real_sub->u.writer);
+    } 
+}
+
+
+/**
+ * Closes a container-typed value appended to the message; may write
+ * out more information to the message known only after the entire
+ * container is written, and may free resources created by
+ * dbus_message_iter_open_container().
+ *
+ * @todo If this fails due to lack of memory, the message is hosed and
+ * you have to start over building the whole message.
+ *
+ * @param iter the append iterator
+ * @param sub sub-iterator to close
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_iter_close_container (DBusMessageIter *iter,
+                                   DBusMessageIter *sub)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
+  dbus_bool_t ret;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
+  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
+  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
+  _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
+
+  ret = _dbus_type_writer_unrecurse (&real->u.writer,
+                                     &real_sub->u.writer);
+
+  if (!_dbus_message_iter_close_signature (real))
+    ret = FALSE;
+
+  return ret;
+}
+
+/**
+ * Abandons creation of a contained-typed value and frees resources created
+ * by dbus_message_iter_open_container().  Once this returns, the message
+ * is hosed and you have to start over building the whole message.
+ *
+ * This should only be used to abandon creation of a message when you have
+ * open containers.
+ *
+ * @param iter the append iterator
+ * @param sub sub-iterator to close
+ */
+void
+dbus_message_iter_abandon_container (DBusMessageIter *iter,
+                                     DBusMessageIter *sub)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+#ifndef DBUS_DISABLE_CHECKS
+  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
+
+  _dbus_return_if_fail (_dbus_message_iter_append_check (real));
+  _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
+  _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
+  _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
+#endif
+
+  _dbus_message_iter_abandon_signature (real);
+}
+
+/**
+ * Sets a flag indicating that the message does not want a reply; if
+ * this flag is set, the other end of the connection may (but is not
+ * required to) optimize by not sending method return or error
+ * replies. If this flag is set, there is no way to know whether the
+ * message successfully arrived at the remote end. Normally you know a
+ * message was received when you receive the reply to it.
+ *
+ * The flag is #FALSE by default, that is by default the other end is
+ * required to reply.
+ *
+ * On the protocol level this toggles #DBUS_HEADER_FLAG_NO_REPLY_EXPECTED
+ * 
+ * @param message the message
+ * @param no_reply #TRUE if no reply is desired
+ */
+void
+dbus_message_set_no_reply (DBusMessage *message,
+                           dbus_bool_t  no_reply)
+{
+  _dbus_return_if_fail (message != NULL);
+  _dbus_return_if_fail (!message->locked);
+
+  _dbus_header_toggle_flag (&message->header,
+                            DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
+                            no_reply);
+}
+
+/**
+ * Returns #TRUE if the message does not expect
+ * a reply.
+ *
+ * @param message the message
+ * @returns #TRUE if the message sender isn't waiting for a reply
+ */
+dbus_bool_t
+dbus_message_get_no_reply (DBusMessage *message)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+
+  return _dbus_header_get_flag (&message->header,
+                                DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
+}
+
+/**
+ * Sets a flag indicating that an owner for the destination name will
+ * be automatically started before the message is delivered. When this
+ * flag is set, the message is held until a name owner finishes
+ * starting up, or fails to start up. In case of failure, the reply
+ * will be an error.
+ *
+ * The flag is set to #TRUE by default, i.e. auto starting is the default.
+ *
+ * On the protocol level this toggles #DBUS_HEADER_FLAG_NO_AUTO_START
+ * 
+ * @param message the message
+ * @param auto_start #TRUE if auto-starting is desired
+ */
+void
+dbus_message_set_auto_start (DBusMessage *message,
+                             dbus_bool_t  auto_start)
+{
+  _dbus_return_if_fail (message != NULL);
+  _dbus_return_if_fail (!message->locked);
+
+  _dbus_header_toggle_flag (&message->header,
+                            DBUS_HEADER_FLAG_NO_AUTO_START,
+                            !auto_start);
+}
+
+/**
+ * Returns #TRUE if the message will cause an owner for
+ * destination name to be auto-started.
+ *
+ * @param message the message
+ * @returns #TRUE if the message will use auto-start
+ */
+dbus_bool_t
+dbus_message_get_auto_start (DBusMessage *message)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+
+  return !_dbus_header_get_flag (&message->header,
+                                 DBUS_HEADER_FLAG_NO_AUTO_START);
+}
+
+
+/**
+ * Sets the object path this message is being sent to (for
+ * DBUS_MESSAGE_TYPE_METHOD_CALL) or the one a signal is being
+ * emitted from (for DBUS_MESSAGE_TYPE_SIGNAL).
+ *
+ * The path must contain only valid characters as defined
+ * in the D-Bus specification.
+ *
+ * @param message the message
+ * @param object_path the path or #NULL to unset
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_path (DBusMessage   *message,
+                       const char    *object_path)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  _dbus_return_val_if_fail (object_path == NULL ||
+                            _dbus_check_is_valid_path (object_path),
+                            FALSE);
+
+  return set_or_delete_string_field (message,
+                                     DBUS_HEADER_FIELD_PATH,
+                                     DBUS_TYPE_OBJECT_PATH,
+                                     object_path);
+}
+
+/**
+ * Gets the object path this message is being sent to (for
+ * DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted from (for
+ * DBUS_MESSAGE_TYPE_SIGNAL). Returns #NULL if none.
+ *
+ * See also dbus_message_get_path_decomposed().
+ *
+ * The returned string becomes invalid if the message is
+ * modified, since it points into the wire-marshaled message data.
+ * 
+ * @param message the message
+ * @returns the path (should not be freed) or #NULL
+ */
+const char*
+dbus_message_get_path (DBusMessage   *message)
+{
+  const char *v;
+
+  _dbus_return_val_if_fail (message != NULL, NULL);
+
+  v = NULL; /* in case field doesn't exist */
+  _dbus_header_get_field_basic (&message->header,
+                                DBUS_HEADER_FIELD_PATH,
+                                DBUS_TYPE_OBJECT_PATH,
+                                (void *) &v);
+  return v;
+}
+
+/**
+ * Checks if the message has a particular object path.  The object
+ * path is the destination object for a method call or the emitting
+ * object for a signal.
+ *
+ * @param message the message
+ * @param path the path name
+ * @returns #TRUE if there is a path field in the header
+ */
+dbus_bool_t
+dbus_message_has_path (DBusMessage   *message,
+                       const char    *path)
+{
+  const char *msg_path;
+  msg_path = dbus_message_get_path (message);
+  
+  if (msg_path == NULL)
+    {
+      if (path == NULL)
+        return TRUE;
+      else
+        return FALSE;
+    }
+
+  if (path == NULL)
+    return FALSE;
+   
+  if (strcmp (msg_path, path) == 0)
+    return TRUE;
+
+  return FALSE;
+}
+
+/**
+ * Gets the object path this message is being sent to
+ * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
+ * from (for DBUS_MESSAGE_TYPE_SIGNAL) in a decomposed
+ * format (one array element per path component).
+ * Free the returned array with dbus_free_string_array().
+ *
+ * An empty but non-NULL path array means the path "/".
+ * So the path "/foo/bar" becomes { "foo", "bar", NULL }
+ * and the path "/" becomes { NULL }.
+ *
+ * See also dbus_message_get_path().
+ * 
+ * @todo this could be optimized by using the len from the message
+ * instead of calling strlen() again
+ *
+ * @param message the message
+ * @param path place to store allocated array of path components; #NULL set here if no path field exists
+ * @returns #FALSE if no memory to allocate the array
+ */
+dbus_bool_t
+dbus_message_get_path_decomposed (DBusMessage   *message,
+                                  char        ***path)
+{
+  const char *v;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (path != NULL, FALSE);
+
+  *path = NULL;
+
+  v = dbus_message_get_path (message);
+  if (v != NULL)
+    {
+      if (!_dbus_decompose_path (v, strlen (v),
+                                 path, NULL))
+        return FALSE;
+    }
+  return TRUE;
+}
+
+/**
+ * Sets the interface this message is being sent to
+ * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or
+ * the interface a signal is being emitted from
+ * (for DBUS_MESSAGE_TYPE_SIGNAL).
+ *
+ * The interface name must contain only valid characters as defined
+ * in the D-Bus specification.
+ * 
+ * @param message the message
+ * @param interface the interface or #NULL to unset
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_interface (DBusMessage  *message,
+                            const char   *interface)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  _dbus_return_val_if_fail (interface == NULL ||
+                            _dbus_check_is_valid_interface (interface),
+                            FALSE);
+
+  return set_or_delete_string_field (message,
+                                     DBUS_HEADER_FIELD_INTERFACE,
+                                     DBUS_TYPE_STRING,
+                                     interface);
+}
+
+/**
+ * Gets the interface this message is being sent to
+ * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
+ * from (for DBUS_MESSAGE_TYPE_SIGNAL).
+ * The interface name is fully-qualified (namespaced).
+ * Returns #NULL if none.
+ *
+ * The returned string becomes invalid if the message is
+ * modified, since it points into the wire-marshaled message data.
+ *
+ * @param message the message
+ * @returns the message interface (should not be freed) or #NULL
+ */
+const char*
+dbus_message_get_interface (DBusMessage *message)
+{
+  const char *v;
+
+  _dbus_return_val_if_fail (message != NULL, NULL);
+
+  v = NULL; /* in case field doesn't exist */
+  _dbus_header_get_field_basic (&message->header,
+                                DBUS_HEADER_FIELD_INTERFACE,
+                                DBUS_TYPE_STRING,
+                                (void *) &v);
+  return v;
+}
+
+/**
+ * Checks if the message has an interface
+ *
+ * @param message the message
+ * @param interface the interface name
+ * @returns #TRUE if the interface field in the header matches
+ */
+dbus_bool_t
+dbus_message_has_interface (DBusMessage   *message,
+                            const char    *interface)
+{
+  const char *msg_interface;
+  msg_interface = dbus_message_get_interface (message);
+   
+  if (msg_interface == NULL)
+    {
+      if (interface == NULL)
+        return TRUE;
+      else
+        return FALSE;
+    }
+
+  if (interface == NULL)
+    return FALSE;
+     
+  if (strcmp (msg_interface, interface) == 0)
+    return TRUE;
+
+  return FALSE;
+
+}
+
+/**
+ * Sets the interface member being invoked
+ * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
+ * (DBUS_MESSAGE_TYPE_SIGNAL).
+ *
+ * The member name must contain only valid characters as defined
+ * in the D-Bus specification.
+ *
+ * @param message the message
+ * @param member the member or #NULL to unset
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_member (DBusMessage  *message,
+                         const char   *member)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  _dbus_return_val_if_fail (member == NULL ||
+                            _dbus_check_is_valid_member (member),
+                            FALSE);
+
+  return set_or_delete_string_field (message,
+                                     DBUS_HEADER_FIELD_MEMBER,
+                                     DBUS_TYPE_STRING,
+                                     member);
+}
+
+/**
+ * Gets the interface member being invoked
+ * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
+ * (DBUS_MESSAGE_TYPE_SIGNAL). Returns #NULL if none.
+ *
+ * The returned string becomes invalid if the message is
+ * modified, since it points into the wire-marshaled message data.
+ * 
+ * @param message the message
+ * @returns the member name (should not be freed) or #NULL
+ */
+const char*
+dbus_message_get_member (DBusMessage *message)
+{
+  const char *v;
+
+  _dbus_return_val_if_fail (message != NULL, NULL);
+
+  v = NULL; /* in case field doesn't exist */
+  _dbus_header_get_field_basic (&message->header,
+                                DBUS_HEADER_FIELD_MEMBER,
+                                DBUS_TYPE_STRING,
+                                (void *) &v);
+  return v;
+}
+
+/**
+ * Checks if the message has an interface member
+ *
+ * @param message the message
+ * @param member the member name
+ * @returns #TRUE if there is a member field in the header
+ */
+dbus_bool_t
+dbus_message_has_member (DBusMessage   *message,
+                         const char    *member)
+{
+  const char *msg_member;
+  msg_member = dbus_message_get_member (message);
+ 
+  if (msg_member == NULL)
+    {
+      if (member == NULL)
+        return TRUE;
+      else
+        return FALSE;
+    }
+
+  if (member == NULL)
+    return FALSE;
+    
+  if (strcmp (msg_member, member) == 0)
+    return TRUE;
+
+  return FALSE;
+
+}
+
+/**
+ * Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
+ * The name is fully-qualified (namespaced).
+ *
+ * The error name must contain only valid characters as defined
+ * in the D-Bus specification.
+ *
+ * @param message the message
+ * @param error_name the name or #NULL to unset
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_error_name (DBusMessage  *message,
+                             const char   *error_name)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  _dbus_return_val_if_fail (error_name == NULL ||
+                            _dbus_check_is_valid_error_name (error_name),
+                            FALSE);
+
+  return set_or_delete_string_field (message,
+                                     DBUS_HEADER_FIELD_ERROR_NAME,
+                                     DBUS_TYPE_STRING,
+                                     error_name);
+}
+
+/**
+ * Gets the error name (DBUS_MESSAGE_TYPE_ERROR only)
+ * or #NULL if none.
+ *
+ * The returned string becomes invalid if the message is
+ * modified, since it points into the wire-marshaled message data.
+ * 
+ * @param message the message
+ * @returns the error name (should not be freed) or #NULL
+ */
+const char*
+dbus_message_get_error_name (DBusMessage *message)
+{
+  const char *v;
+
+  _dbus_return_val_if_fail (message != NULL, NULL);
+
+  v = NULL; /* in case field doesn't exist */
+  _dbus_header_get_field_basic (&message->header,
+                                DBUS_HEADER_FIELD_ERROR_NAME,
+                                DBUS_TYPE_STRING,
+                                (void *) &v);
+  return v;
+}
+
+/**
+ * Sets the message's destination. The destination is the name of
+ * another connection on the bus and may be either the unique name
+ * assigned by the bus to each connection, or a well-known name
+ * specified in advance.
+ *
+ * The destination name must contain only valid characters as defined
+ * in the D-Bus specification.
+ * 
+ * @param message the message
+ * @param destination the destination name or #NULL to unset
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_destination (DBusMessage  *message,
+                              const char   *destination)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  _dbus_return_val_if_fail (destination == NULL ||
+                            _dbus_check_is_valid_bus_name (destination),
+                            FALSE);
+
+  return set_or_delete_string_field (message,
+                                     DBUS_HEADER_FIELD_DESTINATION,
+                                     DBUS_TYPE_STRING,
+                                     destination);
+}
+
+/**
+ * Gets the destination of a message or #NULL if there is none set.
+ *
+ * The returned string becomes invalid if the message is
+ * modified, since it points into the wire-marshaled message data.
+ *
+ * @param message the message
+ * @returns the message destination (should not be freed) or #NULL
+ */
+const char*
+dbus_message_get_destination (DBusMessage *message)
+{
+  const char *v;
+
+  _dbus_return_val_if_fail (message != NULL, NULL);
+
+  v = NULL; /* in case field doesn't exist */
+  _dbus_header_get_field_basic (&message->header,
+                                DBUS_HEADER_FIELD_DESTINATION,
+                                DBUS_TYPE_STRING,
+                                (void *) &v);
+  return v;
+}
+
+/**
+ * Sets the message sender.
+ *
+ * The sender must be a valid bus name as defined in the D-Bus
+ * specification.
+ *
+ * Usually you don't want to call this. The message bus daemon will
+ * call it to set the origin of each message. If you aren't implementing
+ * a message bus daemon you shouldn't need to set the sender.
+ *
+ * @param message the message
+ * @param sender the sender or #NULL to unset
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_message_set_sender (DBusMessage  *message,
+                         const char   *sender)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (!message->locked, FALSE);
+  _dbus_return_val_if_fail (sender == NULL ||
+                            _dbus_check_is_valid_bus_name (sender),
+                            FALSE);
+
+  return set_or_delete_string_field (message,
+                                     DBUS_HEADER_FIELD_SENDER,
+                                     DBUS_TYPE_STRING,
+                                     sender);
+}
+
+/**
+ * Gets the unique name of the connection which originated this
+ * message, or #NULL if unknown or inapplicable. The sender is filled
+ * in by the message bus.
+ *
+ * Note, the returned sender is always the unique bus name.
+ * Connections may own multiple other bus names, but those
+ * are not found in the sender field.
+ * 
+ * The returned string becomes invalid if the message is
+ * modified, since it points into the wire-marshaled message data.
+ *
+ * @param message the message
+ * @returns the unique name of the sender or #NULL
+ */
+const char*
+dbus_message_get_sender (DBusMessage *message)
+{
+  const char *v;
+
+  _dbus_return_val_if_fail (message != NULL, NULL);
+
+  v = NULL; /* in case field doesn't exist */
+  _dbus_header_get_field_basic (&message->header,
+                                DBUS_HEADER_FIELD_SENDER,
+                                DBUS_TYPE_STRING,
+                                (void *) &v);
+  return v;
+}
+
+/**
+ * Gets the type signature of the message, i.e. the arguments in the
+ * message payload. The signature includes only "in" arguments for
+ * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
+ * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
+ * what you might expect (that is, it does not include the signature of the
+ * entire C++-style method).
+ *
+ * The signature is a string made up of type codes such as
+ * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also
+ * the value of #DBUS_TYPE_INVALID).
+ *
+ * The returned string becomes invalid if the message is
+ * modified, since it points into the wire-marshaled message data.
+ *
+ * @param message the message
+ * @returns the type signature
+ */
+const char*
+dbus_message_get_signature (DBusMessage *message)
+{
+  const DBusString *type_str;
+  int type_pos;
+
+  _dbus_return_val_if_fail (message != NULL, NULL);
+
+  get_const_signature (&message->header, &type_str, &type_pos);
+
+  return _dbus_string_get_const_data_len (type_str, type_pos, 0);
+}
+
+static dbus_bool_t
+_dbus_message_has_type_interface_member (DBusMessage *message,
+                                         int          type,
+                                         const char  *interface,
+                                         const char  *member)
+{
+  const char *n;
+
+  _dbus_assert (message != NULL);
+  _dbus_assert (interface != NULL);
+  _dbus_assert (member != NULL);
+
+  if (dbus_message_get_type (message) != type)
+    return FALSE;
+
+  /* Optimize by checking the short member name first
+   * instead of the longer interface name
+   */
+
+  n = dbus_message_get_member (message);
+
+  if (n && strcmp (n, member) == 0)
+    {
+      n = dbus_message_get_interface (message);
+
+      if (n == NULL || strcmp (n, interface) == 0)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+/**
+ * Checks whether the message is a method call with the given
+ * interface and member fields.  If the message is not
+ * #DBUS_MESSAGE_TYPE_METHOD_CALL, or has a different interface or
+ * member field, returns #FALSE. If the interface field is missing,
+ * then it will be assumed equal to the provided interface.  The D-Bus
+ * protocol allows method callers to leave out the interface name.
+ *
+ * @param message the message
+ * @param interface the name to check (must not be #NULL)
+ * @param method the name to check (must not be #NULL)
+ *
+ * @returns #TRUE if the message is the specified method call
+ */
+dbus_bool_t
+dbus_message_is_method_call (DBusMessage *message,
+                             const char  *interface,
+                             const char  *method)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (interface != NULL, FALSE);
+  _dbus_return_val_if_fail (method != NULL, FALSE);
+  /* don't check that interface/method are valid since it would be
+   * expensive, and not catch many common errors
+   */
+
+  return _dbus_message_has_type_interface_member (message,
+                                                  DBUS_MESSAGE_TYPE_METHOD_CALL,
+                                                  interface, method);
+}
+
+/**
+ * Checks whether the message is a signal with the given interface and
+ * member fields.  If the message is not #DBUS_MESSAGE_TYPE_SIGNAL, or
+ * has a different interface or member field, returns #FALSE.
+ *
+ * @param message the message
+ * @param interface the name to check (must not be #NULL)
+ * @param signal_name the name to check (must not be #NULL)
+ *
+ * @returns #TRUE if the message is the specified signal
+ */
+dbus_bool_t
+dbus_message_is_signal (DBusMessage *message,
+                        const char  *interface,
+                        const char  *signal_name)
+{
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (interface != NULL, FALSE);
+  _dbus_return_val_if_fail (signal_name != NULL, FALSE);
+  /* don't check that interface/name are valid since it would be
+   * expensive, and not catch many common errors
+   */
+
+  return _dbus_message_has_type_interface_member (message,
+                                                  DBUS_MESSAGE_TYPE_SIGNAL,
+                                                  interface, signal_name);
+}
+
+/**
+ * Checks whether the message is an error reply with the given error
+ * name.  If the message is not #DBUS_MESSAGE_TYPE_ERROR, or has a
+ * different name, returns #FALSE.
+ *
+ * @param message the message
+ * @param error_name the name to check (must not be #NULL)
+ *
+ * @returns #TRUE if the message is the specified error
+ */
+dbus_bool_t
+dbus_message_is_error (DBusMessage *message,
+                       const char  *error_name)
+{
+  const char *n;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (error_name != NULL, FALSE);
+  /* don't check that error_name is valid since it would be expensive,
+   * and not catch many common errors
+   */
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
+    return FALSE;
+
+  n = dbus_message_get_error_name (message);
+
+  if (n && strcmp (n, error_name) == 0)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/**
+ * Checks whether the message was sent to the given name.  If the
+ * message has no destination specified or has a different
+ * destination, returns #FALSE.
+ *
+ * @param message the message
+ * @param name the name to check (must not be #NULL)
+ *
+ * @returns #TRUE if the message has the given destination name
+ */
+dbus_bool_t
+dbus_message_has_destination (DBusMessage  *message,
+                              const char   *name)
+{
+  const char *s;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (name != NULL, FALSE);
+  /* don't check that name is valid since it would be expensive, and
+   * not catch many common errors
+   */
+
+  s = dbus_message_get_destination (message);
+
+  if (s && strcmp (s, name) == 0)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/**
+ * Checks whether the message has the given unique name as its sender.
+ * If the message has no sender specified or has a different sender,
+ * returns #FALSE. Note that a peer application will always have the
+ * unique name of the connection as the sender. So you can't use this
+ * function to see whether a sender owned a well-known name.
+ *
+ * Messages from the bus itself will have #DBUS_SERVICE_DBUS
+ * as the sender.
+ *
+ * @param message the message
+ * @param name the name to check (must not be #NULL)
+ *
+ * @returns #TRUE if the message has the given sender
+ */
+dbus_bool_t
+dbus_message_has_sender (DBusMessage  *message,
+                         const char   *name)
+{
+  const char *s;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (name != NULL, FALSE);
+  /* don't check that name is valid since it would be expensive, and
+   * not catch many common errors
+   */
+
+  s = dbus_message_get_sender (message);
+
+  if (s && strcmp (s, name) == 0)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/**
+ * Checks whether the message has the given signature; see
+ * dbus_message_get_signature() for more details on what the signature
+ * looks like.
+ *
+ * @param message the message
+ * @param signature typecode array
+ * @returns #TRUE if message has the given signature
+*/
+dbus_bool_t
+dbus_message_has_signature (DBusMessage   *message,
+                            const char    *signature)
+{
+  const char *s;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (signature != NULL, FALSE);
+  /* don't check that signature is valid since it would be expensive,
+   * and not catch many common errors
+   */
+
+  s = dbus_message_get_signature (message);
+
+  if (s && strcmp (s, signature) == 0)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/**
+ * Sets a #DBusError based on the contents of the given
+ * message. The error is only set if the message
+ * is an error message, as in #DBUS_MESSAGE_TYPE_ERROR.
+ * The name of the error is set to the name of the message,
+ * and the error message is set to the first argument
+ * if the argument exists and is a string.
+ *
+ * The return value indicates whether the error was set (the error is
+ * set if and only if the message is an error message).  So you can
+ * check for an error reply and convert it to DBusError in one go:
+ * @code
+ *  if (dbus_set_error_from_message (error, reply))
+ *    return error;
+ *  else
+ *    process reply;
+ * @endcode
+ *
+ * @param error the error to set
+ * @param message the message to set it from
+ * @returns #TRUE if the message had type #DBUS_MESSAGE_TYPE_ERROR
+ */
+dbus_bool_t
+dbus_set_error_from_message (DBusError   *error,
+                             DBusMessage *message)
+{
+  const char *str;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
+    return FALSE;
+
+  str = NULL;
+  dbus_message_get_args (message, NULL,
+                         DBUS_TYPE_STRING, &str,
+                         DBUS_TYPE_INVALID);
+
+  dbus_set_error (error, dbus_message_get_error_name (message),
+                  str ? "%s" : NULL, str);
+
+  return TRUE;
+}
+
+/**
+ * Checks whether a message contains unix fds
+ *
+ * @param message the message
+ * @returns #TRUE if the message contains unix fds
+ */
+dbus_bool_t
+dbus_message_contains_unix_fds(DBusMessage *message)
+{
+#ifdef HAVE_UNIX_FD_PASSING
+  _dbus_assert(message);
+
+  return message->n_unix_fds > 0;
+#else
+  return FALSE;
+#endif
+}
+
+/** @} */
+
+/**
+ * @addtogroup DBusMessageInternals
+ *
+ * @{
+ */
+
+/**
+ * The initial buffer size of the message loader.
+ *
+ * @todo this should be based on min header size plus some average
+ * body size, or something. Or rather, the min header size only, if we
+ * want to try to read only the header, store that in a DBusMessage,
+ * then read only the body and store that, etc., depends on
+ * how we optimize _dbus_message_loader_get_buffer() and what
+ * the exact message format is.
+ */
+#define INITIAL_LOADER_DATA_LEN 32
+
+/**
+ * Creates a new message loader. Returns #NULL if memory can't
+ * be allocated.
+ *
+ * @returns new loader, or #NULL.
+ */
+DBusMessageLoader*
+_dbus_message_loader_new (void)
+{
+  DBusMessageLoader *loader;
+
+  loader = dbus_new0 (DBusMessageLoader, 1);
+  if (loader == NULL)
+    return NULL;
+  
+  loader->refcount = 1;
+
+  loader->corrupted = FALSE;
+  loader->corruption_reason = DBUS_VALID;
+
+  /* this can be configured by the app, but defaults to the protocol max */
+  loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
+
+  /* We set a very relatively conservative default here since due to how
+  SCM_RIGHTS works we need to preallocate an fd array of the maximum
+  number of unix fds we want to receive in advance. A
+  try-and-reallocate loop is not possible. */
+  loader->max_message_unix_fds = 1024;
+
+  if (!_dbus_string_init (&loader->data))
+    {
+      dbus_free (loader);
+      return NULL;
+    }
+
+  /* preallocate the buffer for speed, ignore failure */
+  _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
+  _dbus_string_set_length (&loader->data, 0);
+
+#ifdef HAVE_UNIX_FD_PASSING
+  loader->unix_fds = NULL;
+  loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
+  loader->unix_fds_outstanding = FALSE;
+#endif
+
+  return loader;
+}
+
+/**
+ * Increments the reference count of the loader.
+ *
+ * @param loader the loader.
+ * @returns the loader
+ */
+DBusMessageLoader *
+_dbus_message_loader_ref (DBusMessageLoader *loader)
+{
+  loader->refcount += 1;
+
+  return loader;
+}
+
+/**
+ * Decrements the reference count of the loader and finalizes the
+ * loader when the count reaches zero.
+ *
+ * @param loader the loader.
+ */
+void
+_dbus_message_loader_unref (DBusMessageLoader *loader)
+{
+  loader->refcount -= 1;
+  if (loader->refcount == 0)
+    {
+#ifdef HAVE_UNIX_FD_PASSING
+      close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
+      dbus_free(loader->unix_fds);
+#endif
+      _dbus_list_foreach (&loader->messages,
+                          (DBusForeachFunction) dbus_message_unref,
+                          NULL);
+      _dbus_list_clear (&loader->messages);
+      _dbus_string_free (&loader->data);
+      dbus_free (loader);
+    }
+}
+
+/**
+ * Gets the buffer to use for reading data from the network.  Network
+ * data is read directly into an allocated buffer, which is then used
+ * in the DBusMessage, to avoid as many extra memcpy's as possible.
+ * The buffer must always be returned immediately using
+ * _dbus_message_loader_return_buffer(), even if no bytes are
+ * successfully read.
+ *
+ * @todo this function can be a lot more clever. For example
+ * it can probably always return a buffer size to read exactly
+ * the body of the next message, thus avoiding any memory wastage
+ * or reallocs.
+ *
+ * @todo we need to enforce a max length on strings in header fields.
+ *
+ * @param loader the message loader.
+ * @param buffer the buffer
+ */
+void
+_dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
+                                 DBusString        **buffer)
+{
+  _dbus_assert (!loader->buffer_outstanding);
+
+  *buffer = &loader->data;
+
+  loader->buffer_outstanding = TRUE;
+}
+
+/**
+ * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
+ * indicating to the loader how many bytes of the buffer were filled
+ * in. This function must always be called, even if no bytes were
+ * successfully read.
+ *
+ * @param loader the loader.
+ * @param buffer the buffer.
+ * @param bytes_read number of bytes that were read into the buffer.
+ */
+void
+_dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
+                                    DBusString         *buffer,
+                                    int                 bytes_read)
+{
+  _dbus_assert (loader->buffer_outstanding);
+  _dbus_assert (buffer == &loader->data);
+
+  loader->buffer_outstanding = FALSE;
+}
+
+/**
+ * Gets the buffer to use for reading unix fds from the network.
+ *
+ * This works similar to _dbus_message_loader_get_buffer()
+ *
+ * @param loader the message loader.
+ * @param fds the array to read fds into
+ * @param max_n_fds how many fds to read at most
+ * @return TRUE on success, FALSE on OOM
+ */
+dbus_bool_t
+_dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
+                                  int               **fds,
+                                  unsigned           *max_n_fds)
+{
+#ifdef HAVE_UNIX_FD_PASSING
+  _dbus_assert (!loader->unix_fds_outstanding);
+
+  /* Allocate space where we can put the fds we read. We allocate
+     space for max_message_unix_fds since this is an
+     upper limit how many fds can be received within a single
+     message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
+     we are allocating the maximum possible array size right from the
+     beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
+     there is no better way. */
+
+  if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
+    {
+      int *a = dbus_realloc(loader->unix_fds,
+                            loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
+
+      if (!a)
+        return FALSE;
+
+      loader->unix_fds = a;
+      loader->n_unix_fds_allocated = loader->max_message_unix_fds;
+    }
+
+  *fds = loader->unix_fds + loader->n_unix_fds;
+  *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
+
+  loader->unix_fds_outstanding = TRUE;
+  return TRUE;
+#else
+  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
+  return FALSE;
+#endif
+}
+
+/**
+ * Returns a buffer obtained from _dbus_message_loader_get_unix_fds().
+ *
+ * This works similar to _dbus_message_loader_return_buffer()
+ *
+ * @param loader the message loader.
+ * @param fds the array fds were read into
+ * @param max_n_fds how many fds were read
+ */
+
+void
+_dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
+                                     int                *fds,
+                                     unsigned            n_fds)
+{
+#ifdef HAVE_UNIX_FD_PASSING
+  _dbus_assert(loader->unix_fds_outstanding);
+  _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
+  _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
+
+  loader->n_unix_fds += n_fds;
+  loader->unix_fds_outstanding = FALSE;
+#else
+  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
+#endif
+}
+
+/*
+ * FIXME when we move the header out of the buffer, that memmoves all
+ * buffered messages. Kind of crappy.
+ *
+ * Also we copy the header and body, which is kind of crappy.  To
+ * avoid this, we have to allow header and body to be in a single
+ * memory block, which is good for messages we read and bad for
+ * messages we are creating. But we could move_len() the buffer into
+ * this single memory block, and move_len() will just swap the buffers
+ * if you're moving the entire buffer replacing the dest string.
+ *
+ * We could also have the message loader tell the transport how many
+ * bytes to read; so it would first ask for some arbitrary number like
+ * 256, then if the message was incomplete it would use the
+ * header/body len to ask for exactly the size of the message (or
+ * blocks the size of a typical kernel buffer for the socket). That
+ * way we don't get trailing bytes in the buffer that have to be
+ * memmoved. Though I suppose we also don't have a chance of reading a
+ * bunch of small messages at once, so the optimization may be stupid.
+ *
+ * Another approach would be to keep a "start" index into
+ * loader->data and only delete it occasionally, instead of after
+ * each message is loaded.
+ *
+ * load_message() returns FALSE if not enough memory OR the loader was corrupted
+ */
+static dbus_bool_t
+load_message (DBusMessageLoader *loader,
+              DBusMessage       *message,
+              int                byte_order,
+              int                fields_array_len,
+              int                header_len,
+              int                body_len)
+{
+  dbus_bool_t oom;
+  DBusValidity validity;
+  const DBusString *type_str;
+  int type_pos;
+  DBusValidationMode mode;
+  dbus_uint32_t n_unix_fds = 0;
+
+  mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
+  
+  oom = FALSE;
+
+#if 0
+  _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
+#endif
+
+  /* 1. VALIDATE AND COPY OVER HEADER */
+  _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
+  _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
+
+  if (!_dbus_header_load (&message->header,
+                          mode,
+                          &validity,
+                          byte_order,
+                          fields_array_len,
+                          header_len,
+                          body_len,
+                          &loader->data, 0,
+                          _dbus_string_get_length (&loader->data)))
+    {
+      _dbus_verbose ("Failed to load header for new message code %d\n", validity);
+
+      /* assert here so we can catch any code that still uses DBUS_VALID to indicate
+         oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
+      _dbus_assert (validity != DBUS_VALID);
+
+      if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
+        oom = TRUE;
+      else
+        {
+          loader->corrupted = TRUE;
+          loader->corruption_reason = validity;
+        }
+      goto failed;
+    }
+
+  _dbus_assert (validity == DBUS_VALID);
+
+  /* 2. VALIDATE BODY */
+  if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
+    {
+      get_const_signature (&message->header, &type_str, &type_pos);
+      
+      /* Because the bytes_remaining arg is NULL, this validates that the
+       * body is the right length
+       */
+      validity = _dbus_validate_body_with_reason (type_str,
+                                                  type_pos,
+                                                  byte_order,
+                                                  NULL,
+                                                  &loader->data,
+                                                  header_len,
+                                                  body_len);
+      if (validity != DBUS_VALID)
+        {
+          _dbus_verbose ("Failed to validate message body code %d\n", validity);
+
+          loader->corrupted = TRUE;
+          loader->corruption_reason = validity;
+          
+          goto failed;
+        }
+    }
+
+  /* 3. COPY OVER UNIX FDS */
+  _dbus_header_get_field_basic(&message->header,
+                               DBUS_HEADER_FIELD_UNIX_FDS,
+                               DBUS_TYPE_UINT32,
+                               &n_unix_fds);
+
+#ifdef HAVE_UNIX_FD_PASSING
+
+  if (n_unix_fds > loader->n_unix_fds)
+    {
+      _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
+                    n_unix_fds, loader->n_unix_fds);
+
+      loader->corrupted = TRUE;
+      loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
+      goto failed;
+    }
+
+  /* If this was a recycled message there might still be
+     some memory allocated for the fds */
+  dbus_free(message->unix_fds);
+
+  if (n_unix_fds > 0)
+    {
+      message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
+      if (message->unix_fds == NULL)
+        {
+          _dbus_verbose ("Failed to allocate file descriptor array\n");
+          oom = TRUE;
+          goto failed;
+        }
+
+      message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
+      loader->n_unix_fds -= n_unix_fds;
+      memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds);
+    }
+  else
+    message->unix_fds = NULL;
+
+#else
+
+  if (n_unix_fds > 0)
+    {
+      _dbus_verbose ("Hmm, message claims to come with file descriptors "
+                     "but that's not supported on our platform, disconnecting.\n");
+
+      loader->corrupted = TRUE;
+      loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
+      goto failed;
+    }
+
+#endif
+
+  /* 3. COPY OVER BODY AND QUEUE MESSAGE */
+
+  if (!_dbus_list_append (&loader->messages, message))
+    {
+      _dbus_verbose ("Failed to append new message to loader queue\n");
+      oom = TRUE;
+      goto failed;
+    }
+
+  _dbus_assert (_dbus_string_get_length (&message->body) == 0);
+  _dbus_assert (_dbus_string_get_length (&loader->data) >=
+                (header_len + body_len));
+
+  if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
+    {
+      _dbus_verbose ("Failed to move body into new message\n");
+      oom = TRUE;
+      goto failed;
+    }
+
+  _dbus_string_delete (&loader->data, 0, header_len + body_len);
+
+  /* don't waste more than 2k of memory */
+  _dbus_string_compact (&loader->data, 2048);
+
+  _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
+  _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
+
+  _dbus_verbose ("Loaded message %p\n", message);
+
+  _dbus_assert (!oom);
+  _dbus_assert (!loader->corrupted);
+  _dbus_assert (loader->messages != NULL);
+  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
+
+  return TRUE;
+
+ failed:
+
+  /* Clean up */
+
+  /* does nothing if the message isn't in the list */
+  _dbus_list_remove_last (&loader->messages, message);
+  
+  if (oom)
+    _dbus_assert (!loader->corrupted);
+  else
+    _dbus_assert (loader->corrupted);
+
+  _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
+
+  return FALSE;
+}
+
+/**
+ * Converts buffered data into messages, if we have enough data.  If
+ * we don't have enough data, does nothing.
+ *
+ * @todo we need to check that the proper named header fields exist
+ * for each message type.
+ *
+ * @todo If a message has unknown type, we should probably eat it
+ * right here rather than passing it out to applications.  However
+ * it's not an error to see messages of unknown type.
+ *
+ * @param loader the loader.
+ * @returns #TRUE if we had enough memory to finish.
+ */
+dbus_bool_t
+_dbus_message_loader_queue_messages (DBusMessageLoader *loader)
+{
+  while (!loader->corrupted &&
+         _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
+    {
+      DBusValidity validity;
+      int byte_order, fields_array_len, header_len, body_len;
+
+      if (_dbus_header_have_message_untrusted (loader->max_message_size,
+                                               &validity,
+                                               &byte_order,
+                                               &fields_array_len,
+                                               &header_len,
+                                               &body_len,
+                                               &loader->data, 0,
+                                               _dbus_string_get_length (&loader->data)))
+        {
+          DBusMessage *message;
+
+          _dbus_assert (validity == DBUS_VALID);
+
+          message = dbus_message_new_empty_header ();
+          if (message == NULL)
+            return FALSE;
+
+          if (!load_message (loader, message,
+                             byte_order, fields_array_len,
+                             header_len, body_len))
+            {
+              dbus_message_unref (message);
+              /* load_message() returns false if corrupted or OOM; if
+               * corrupted then return TRUE for not OOM
+               */
+              return loader->corrupted;
+            }
+
+          _dbus_assert (loader->messages != NULL);
+          _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
+	}
+      else
+        {
+          _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
+                         validity);
+          if (validity != DBUS_VALID)
+            {
+              loader->corrupted = TRUE;
+              loader->corruption_reason = validity;
+            }
+          return TRUE;
+        }
+    }
+
+  return TRUE;
+}
+
+/**
+ * Peeks at first loaded message, returns #NULL if no messages have
+ * been queued.
+ *
+ * @param loader the loader.
+ * @returns the next message, or #NULL if none.
+ */
+DBusMessage*
+_dbus_message_loader_peek_message (DBusMessageLoader *loader)
+{
+  if (loader->messages)
+    return loader->messages->data;
+  else
+    return NULL;
+}
+
+/**
+ * Pops a loaded message (passing ownership of the message
+ * to the caller). Returns #NULL if no messages have been
+ * queued.
+ *
+ * @param loader the loader.
+ * @returns the next message, or #NULL if none.
+ */
+DBusMessage*
+_dbus_message_loader_pop_message (DBusMessageLoader *loader)
+{
+  return _dbus_list_pop_first (&loader->messages);
+}
+
+/**
+ * Pops a loaded message inside a list link (passing ownership of the
+ * message and link to the caller). Returns #NULL if no messages have
+ * been loaded.
+ *
+ * @param loader the loader.
+ * @returns the next message link, or #NULL if none.
+ */
+DBusList*
+_dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
+{
+  return _dbus_list_pop_first_link (&loader->messages);
+}
+
+/**
+ * Returns a popped message link, used to undo a pop.
+ *
+ * @param loader the loader
+ * @param link the link with a message in it
+ */
+void
+_dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
+                                           DBusList           *link)
+{
+  _dbus_list_prepend_link (&loader->messages, link);
+}
+
+/**
+ * Checks whether the loader is confused due to bad data.
+ * If messages are received that are invalid, the
+ * loader gets confused and gives up permanently.
+ * This state is called "corrupted."
+ *
+ * @param loader the loader
+ * @returns #TRUE if the loader is hosed.
+ */
+dbus_bool_t
+_dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
+{
+  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
+                (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
+  return loader->corrupted;
+}
+
+/**
+ * Checks what kind of bad data confused the loader.
+ *
+ * @param loader the loader
+ * @returns why the loader is hosed, or DBUS_VALID if it isn't.
+ */
+DBusValidity
+_dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
+{
+  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
+                (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
+
+  return loader->corruption_reason;
+}
+
+/**
+ * Sets the maximum size message we allow.
+ *
+ * @param loader the loader
+ * @param size the max message size in bytes
+ */
+void
+_dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
+                                           long                size)
+{
+  if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
+    {
+      _dbus_verbose ("clamping requested max message size %ld to %d\n",
+                     size, DBUS_MAXIMUM_MESSAGE_LENGTH);
+      size = DBUS_MAXIMUM_MESSAGE_LENGTH;
+    }
+  loader->max_message_size = size;
+}
+
+/**
+ * Gets the maximum allowed message size in bytes.
+ *
+ * @param loader the loader
+ * @returns max size in bytes
+ */
+long
+_dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
+{
+  return loader->max_message_size;
+}
+
+/**
+ * Sets the maximum unix fds per message we allow.
+ *
+ * @param loader the loader
+ * @param size the max number of unix fds in a message
+ */
+void
+_dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
+                                               long                n)
+{
+  if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
+    {
+      _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
+                     n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
+      n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
+    }
+  loader->max_message_unix_fds = n;
+}
+
+/**
+ * Gets the maximum allowed number of unix fds per message
+ *
+ * @param loader the loader
+ * @returns max unix fds
+ */
+long
+_dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
+{
+  return loader->max_message_unix_fds;
+}
+
+static DBusDataSlotAllocator slot_allocator;
+_DBUS_DEFINE_GLOBAL_LOCK (message_slots);
+
+/**
+ * Allocates an integer ID to be used for storing application-specific
+ * data on any DBusMessage. The allocated ID may then be used
+ * with dbus_message_set_data() and dbus_message_get_data().
+ * The passed-in slot must be initialized to -1, and is filled in
+ * with the slot ID. If the passed-in slot is not -1, it's assumed
+ * to be already allocated, and its refcount is incremented.
+ *
+ * The allocated slot is global, i.e. all DBusMessage objects will
+ * have a slot with the given integer ID reserved.
+ *
+ * @param slot_p address of a global variable storing the slot
+ * @returns #FALSE on failure (no memory)
+ */
+dbus_bool_t
+dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
+{
+  return _dbus_data_slot_allocator_alloc (&slot_allocator,
+                                          &_DBUS_LOCK_NAME (message_slots),
+                                          slot_p);
+}
+
+/**
+ * Deallocates a global ID for message data slots.
+ * dbus_message_get_data() and dbus_message_set_data() may no
+ * longer be used with this slot.  Existing data stored on existing
+ * DBusMessage objects will be freed when the message is
+ * finalized, but may not be retrieved (and may only be replaced if
+ * someone else reallocates the slot).  When the refcount on the
+ * passed-in slot reaches 0, it is set to -1.
+ *
+ * @param slot_p address storing the slot to deallocate
+ */
+void
+dbus_message_free_data_slot (dbus_int32_t *slot_p)
+{
+  _dbus_return_if_fail (*slot_p >= 0);
+
+  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
+}
+
+/**
+ * Stores a pointer on a DBusMessage, along
+ * with an optional function to be used for freeing
+ * the data when the data is set again, or when
+ * the message is finalized. The slot number
+ * must have been allocated with dbus_message_allocate_data_slot().
+ *
+ * @param message the message
+ * @param slot the slot number
+ * @param data the data to store
+ * @param free_data_func finalizer function for the data
+ * @returns #TRUE if there was enough memory to store the data
+ */
+dbus_bool_t
+dbus_message_set_data (DBusMessage     *message,
+                       dbus_int32_t     slot,
+                       void            *data,
+                       DBusFreeFunction free_data_func)
+{
+  DBusFreeFunction old_free_func;
+  void *old_data;
+  dbus_bool_t retval;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_fail (slot >= 0, FALSE);
+
+  retval = _dbus_data_slot_list_set (&slot_allocator,
+                                     &message->slot_list,
+                                     slot, data, free_data_func,
+                                     &old_free_func, &old_data);
+
+  if (retval)
+    {
+      /* Do the actual free outside the message lock */
+      if (old_free_func)
+        (* old_free_func) (old_data);
+    }
+
+  return retval;
+}
+
+/**
+ * Retrieves data previously set with dbus_message_set_data().
+ * The slot must still be allocated (must not have been freed).
+ *
+ * @param message the message
+ * @param slot the slot to get data from
+ * @returns the data, or #NULL if not found
+ */
+void*
+dbus_message_get_data (DBusMessage   *message,
+                       dbus_int32_t   slot)
+{
+  void *res;
+
+  _dbus_return_val_if_fail (message != NULL, NULL);
+
+  res = _dbus_data_slot_list_get (&slot_allocator,
+                                  &message->slot_list,
+                                  slot);
+
+  return res;
+}
+
+/**
+ * Utility function to convert a machine-readable (not translated)
+ * string into a D-Bus message type.
+ *
+ * @code
+ *   "method_call"    -> DBUS_MESSAGE_TYPE_METHOD_CALL
+ *   "method_return"  -> DBUS_MESSAGE_TYPE_METHOD_RETURN
+ *   "signal"         -> DBUS_MESSAGE_TYPE_SIGNAL
+ *   "error"          -> DBUS_MESSAGE_TYPE_ERROR
+ *   anything else    -> DBUS_MESSAGE_TYPE_INVALID
+ * @endcode
+ *
+ */
+int
+dbus_message_type_from_string (const char *type_str)
+{
+  if (strcmp (type_str, "method_call") == 0)
+    return DBUS_MESSAGE_TYPE_METHOD_CALL;
+  if (strcmp (type_str, "method_return") == 0)
+    return DBUS_MESSAGE_TYPE_METHOD_RETURN;
+  else if (strcmp (type_str, "signal") == 0)
+    return DBUS_MESSAGE_TYPE_SIGNAL;
+  else if (strcmp (type_str, "error") == 0)
+    return DBUS_MESSAGE_TYPE_ERROR;
+  else
+    return DBUS_MESSAGE_TYPE_INVALID;
+}
+
+/**
+ * Utility function to convert a D-Bus message type into a
+ * machine-readable string (not translated).
+ *
+ * @code
+ *   DBUS_MESSAGE_TYPE_METHOD_CALL    -> "method_call"
+ *   DBUS_MESSAGE_TYPE_METHOD_RETURN  -> "method_return"
+ *   DBUS_MESSAGE_TYPE_SIGNAL         -> "signal"
+ *   DBUS_MESSAGE_TYPE_ERROR          -> "error"
+ *   DBUS_MESSAGE_TYPE_INVALID        -> "invalid"
+ * @endcode
+ *
+ */
+const char *
+dbus_message_type_to_string (int type)
+{
+  switch (type)
+    {
+    case DBUS_MESSAGE_TYPE_METHOD_CALL:
+      return "method_call";
+    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+      return "method_return";
+    case DBUS_MESSAGE_TYPE_SIGNAL:
+      return "signal";
+    case DBUS_MESSAGE_TYPE_ERROR:
+      return "error";
+    default:
+      return "invalid";
+    }
+}
+
+/**
+ * Turn a DBusMessage into the marshalled form as described in the D-Bus
+ * specification.
+ *
+ * Generally, this function is only useful for encapsulating D-Bus messages in
+ * a different protocol.
+ *
+ * @param msg the DBusMessage
+ * @param marshalled_data_p the location to save the marshalled form to
+ * @param len_p the location to save the length of the marshalled form to
+ * @returns #FALSE if there was not enough memory
+ */
+dbus_bool_t
+dbus_message_marshal (DBusMessage  *msg,
+                      char        **marshalled_data_p,
+                      int          *len_p)
+{
+  DBusString tmp;
+  dbus_bool_t was_locked;
+
+  _dbus_return_val_if_fail (msg != NULL, FALSE);
+  _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
+  _dbus_return_val_if_fail (len_p != NULL, FALSE);
+  
+  if (!_dbus_string_init (&tmp))
+    return FALSE;
+
+  /* Ensure the message is locked, to ensure the length header is filled in. */
+  was_locked = msg->locked;
+
+  if (!was_locked)
+    dbus_message_lock (msg);
+
+  if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
+    goto fail;
+
+  *len_p = _dbus_string_get_length (&tmp);
+
+  if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
+    goto fail;
+
+  *len_p = _dbus_string_get_length (&tmp);
+
+  if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
+    goto fail;
+
+  _dbus_string_free (&tmp);
+
+  if (!was_locked)
+    msg->locked = FALSE;
+
+  return TRUE;
+
+ fail:
+  _dbus_string_free (&tmp);
+
+  if (!was_locked)
+    msg->locked = FALSE;
+
+  return FALSE;
+}
+
+/**
+ * Demarshal a D-Bus message from the format described in the D-Bus
+ * specification.
+ *
+ * Generally, this function is only useful for encapsulating D-Bus messages in
+ * a different protocol.
+ *
+ * @param str the marshalled DBusMessage
+ * @param len the length of str
+ * @param error the location to save errors to
+ * @returns #NULL if there was an error
+ */
+DBusMessage *
+dbus_message_demarshal (const char *str,
+                        int         len,
+                        DBusError  *error)
+{
+  DBusMessageLoader *loader;
+  DBusString *buffer;
+  DBusMessage *msg;
+
+  _dbus_return_val_if_fail (str != NULL, NULL);
+
+  loader = _dbus_message_loader_new ();
+
+  if (loader == NULL)
+    return NULL;
+
+  _dbus_message_loader_get_buffer (loader, &buffer);
+  _dbus_string_append_len (buffer, str, len);
+  _dbus_message_loader_return_buffer (loader, buffer, len);
+
+  if (!_dbus_message_loader_queue_messages (loader))
+    goto fail_oom;
+
+  if (_dbus_message_loader_get_is_corrupted (loader))
+    goto fail_corrupt;
+
+  msg = _dbus_message_loader_pop_message (loader);
+
+  if (!msg)
+    goto fail_oom;
+
+  _dbus_message_loader_unref (loader);
+  return msg;
+
+ fail_corrupt:
+  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
+                  _dbus_validity_to_error_message (loader->corruption_reason));
+  _dbus_message_loader_unref (loader);
+  return NULL;
+
+ fail_oom:
+  _DBUS_SET_OOM (error);
+  _dbus_message_loader_unref (loader);
+  return NULL;
+}
+
+/**
+ * Returns the number of bytes required to be in the buffer to demarshal a
+ * D-Bus message.
+ *
+ * Generally, this function is only useful for encapsulating D-Bus messages in
+ * a different protocol.
+ *
+ * @param str data to be marshalled
+ * @param len the length of str
+ * @param error the location to save errors to
+ * @returns -1 if there was no valid data to be demarshalled, 0 if there wasn't enough data to determine how much should be demarshalled. Otherwise returns the number of bytes to be demarshalled
+ * 
+ */
+int 
+dbus_message_demarshal_bytes_needed(const char *buf, 
+                                    int         len)
+{
+  DBusString str;
+  int byte_order, fields_array_len, header_len, body_len;
+  DBusValidity validity = DBUS_VALID;
+  int have_message;
+
+  if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
+    return 0;
+
+  if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
+    len = DBUS_MAXIMUM_MESSAGE_LENGTH;
+  _dbus_string_init_const_len (&str, buf, len);
+  
+  validity = DBUS_VALID;
+  have_message
+    = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
+                                          &validity, &byte_order,
+                                          &fields_array_len,
+                                          &header_len,
+                                          &body_len,
+                                          &str, 0,
+                                          len);
+  _dbus_string_free (&str);
+
+  if (validity == DBUS_VALID)
+    {
+      _dbus_assert (have_message || (header_len + body_len) > len);
+      (void) have_message; /* unused unless asserting */
+      return header_len + body_len;
+    }
+  else
+    {
+      return -1; /* broken! */
+    }
+}
+
+/** @} */
+
+/* tests in dbus-message-util.c */
diff --git a/dbus/dbus/dbus-message.h b/dbus/dbus/dbus-message.h
new file mode 100644
index 0000000..5500492
--- /dev/null
+++ b/dbus/dbus/dbus-message.h
@@ -0,0 +1,309 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-message.h DBusMessage object
+ *
+ * Copyright (C) 2002, 2003, 2005 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_MESSAGE_H
+#define DBUS_MESSAGE_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-arch-deps.h>
+#include <dbus/dbus-memory.h>
+#include <dbus/dbus-errors.h>
+#include <stdarg.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusMessage
+ * @{
+ */
+
+typedef struct DBusMessage DBusMessage;
+/** Opaque type representing a message iterator. Can be copied by value, and contains no allocated memory so never needs to be freed and can be allocated on the stack. */
+typedef struct DBusMessageIter DBusMessageIter;
+
+/**
+ * DBusMessageIter struct; contains no public fields. 
+ */
+struct DBusMessageIter
+{ 
+  void *dummy1;         /**< Don't use this */
+  void *dummy2;         /**< Don't use this */
+  dbus_uint32_t dummy3; /**< Don't use this */
+  int dummy4;           /**< Don't use this */
+  int dummy5;           /**< Don't use this */
+  int dummy6;           /**< Don't use this */
+  int dummy7;           /**< Don't use this */
+  int dummy8;           /**< Don't use this */
+  int dummy9;           /**< Don't use this */
+  int dummy10;          /**< Don't use this */
+  int dummy11;          /**< Don't use this */
+  int pad1;             /**< Don't use this */
+  int pad2;             /**< Don't use this */
+  void *pad3;           /**< Don't use this */
+};
+
+DBUS_EXPORT
+DBusMessage* dbus_message_new               (int          message_type);
+DBUS_EXPORT
+DBusMessage* dbus_message_new_method_call   (const char  *bus_name,
+                                             const char  *path,
+                                             const char  *interface,
+                                             const char  *method);
+DBUS_EXPORT
+DBusMessage* dbus_message_new_method_return (DBusMessage *method_call);
+DBUS_EXPORT
+DBusMessage* dbus_message_new_signal        (const char  *path,
+                                             const char  *interface,
+                                             const char  *name);
+DBUS_EXPORT
+DBusMessage* dbus_message_new_error         (DBusMessage *reply_to,
+                                             const char  *error_name,
+                                             const char  *error_message);
+DBUS_EXPORT
+DBusMessage* dbus_message_new_error_printf  (DBusMessage *reply_to,
+                                             const char  *error_name,
+                                             const char  *error_format,
+					     ...);
+
+DBUS_EXPORT
+DBusMessage* dbus_message_copy              (const DBusMessage *message);
+
+DBUS_EXPORT
+DBusMessage*  dbus_message_ref              (DBusMessage   *message);
+DBUS_EXPORT
+void          dbus_message_unref            (DBusMessage   *message);
+DBUS_EXPORT
+int           dbus_message_get_type         (DBusMessage   *message);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_set_path         (DBusMessage   *message,
+                                             const char    *object_path);
+DBUS_EXPORT
+const char*   dbus_message_get_path         (DBusMessage   *message);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_has_path         (DBusMessage   *message, 
+                                             const char    *object_path);  
+DBUS_EXPORT
+dbus_bool_t   dbus_message_set_interface    (DBusMessage   *message,
+                                             const char    *interface);       
+DBUS_EXPORT
+const char*   dbus_message_get_interface    (DBusMessage   *message);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_has_interface    (DBusMessage   *message, 
+                                             const char    *interface);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_set_member       (DBusMessage   *message,
+                                             const char    *member);
+DBUS_EXPORT
+const char*   dbus_message_get_member       (DBusMessage   *message);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_has_member       (DBusMessage   *message, 
+                                             const char    *member);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_set_error_name   (DBusMessage   *message,
+                                             const char    *name);
+DBUS_EXPORT
+const char*   dbus_message_get_error_name   (DBusMessage   *message);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_set_destination  (DBusMessage   *message,
+                                             const char    *destination);
+DBUS_EXPORT
+const char*   dbus_message_get_destination  (DBusMessage   *message);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_set_sender       (DBusMessage   *message,
+                                             const char    *sender);
+DBUS_EXPORT
+const char*   dbus_message_get_sender       (DBusMessage   *message);
+DBUS_EXPORT
+const char*   dbus_message_get_signature    (DBusMessage   *message);
+DBUS_EXPORT
+void          dbus_message_set_no_reply     (DBusMessage   *message,
+                                             dbus_bool_t    no_reply);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_get_no_reply     (DBusMessage   *message);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_is_method_call   (DBusMessage   *message,
+                                             const char    *interface,
+                                             const char    *method);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_is_signal        (DBusMessage   *message,
+                                             const char    *interface,
+                                             const char    *signal_name);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_is_error         (DBusMessage   *message,
+                                             const char    *error_name);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_has_destination  (DBusMessage   *message,
+                                             const char    *bus_name);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_has_sender       (DBusMessage   *message,
+                                             const char    *unique_bus_name);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_has_signature    (DBusMessage   *message,
+                                             const char    *signature);
+DBUS_EXPORT
+dbus_uint32_t dbus_message_get_serial       (DBusMessage   *message);
+DBUS_EXPORT
+void          dbus_message_set_serial       (DBusMessage   *message, 
+                                             dbus_uint32_t  serial);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_set_reply_serial (DBusMessage   *message,
+                                             dbus_uint32_t  reply_serial);
+DBUS_EXPORT
+dbus_uint32_t dbus_message_get_reply_serial (DBusMessage   *message);
+
+DBUS_EXPORT
+void          dbus_message_set_auto_start   (DBusMessage   *message,
+                                             dbus_bool_t    auto_start);
+DBUS_EXPORT
+dbus_bool_t   dbus_message_get_auto_start   (DBusMessage   *message);
+
+DBUS_EXPORT
+dbus_bool_t   dbus_message_get_path_decomposed (DBusMessage   *message,
+                                                char        ***path);
+
+DBUS_EXPORT
+dbus_bool_t dbus_message_append_args          (DBusMessage     *message,
+					       int              first_arg_type,
+					       ...);
+DBUS_EXPORT
+dbus_bool_t dbus_message_append_args_valist   (DBusMessage     *message,
+					       int              first_arg_type,
+					       va_list          var_args);
+DBUS_EXPORT
+dbus_bool_t dbus_message_get_args             (DBusMessage     *message,
+					       DBusError       *error,
+					       int              first_arg_type,
+					       ...);
+DBUS_EXPORT
+dbus_bool_t dbus_message_get_args_valist      (DBusMessage     *message,
+					       DBusError       *error,
+					       int              first_arg_type,
+					       va_list          var_args);
+
+DBUS_EXPORT
+dbus_bool_t dbus_message_contains_unix_fds    (DBusMessage *message);
+
+DBUS_EXPORT
+dbus_bool_t dbus_message_iter_init             (DBusMessage     *message,
+                                                DBusMessageIter *iter);
+DBUS_EXPORT
+dbus_bool_t dbus_message_iter_has_next         (DBusMessageIter *iter);
+DBUS_EXPORT
+dbus_bool_t dbus_message_iter_next             (DBusMessageIter *iter);
+DBUS_EXPORT
+char*       dbus_message_iter_get_signature    (DBusMessageIter *iter);
+DBUS_EXPORT
+int         dbus_message_iter_get_arg_type     (DBusMessageIter *iter);
+DBUS_EXPORT
+int         dbus_message_iter_get_element_type (DBusMessageIter *iter);
+DBUS_EXPORT
+void        dbus_message_iter_recurse          (DBusMessageIter *iter,
+                                                DBusMessageIter *sub);
+DBUS_EXPORT
+void        dbus_message_iter_get_basic        (DBusMessageIter *iter,
+                                                void            *value);
+#ifndef DBUS_DISABLE_DEPRECATED
+/* This function returns the wire protocol size of the array in bytes,
+ * you do not want to know that probably
+ */
+DBUS_EXPORT
+DBUS_DEPRECATED int         dbus_message_iter_get_array_len    (DBusMessageIter *iter);
+#endif
+DBUS_EXPORT
+void        dbus_message_iter_get_fixed_array  (DBusMessageIter *iter,
+                                                void            *value,
+                                                int             *n_elements);
+
+
+DBUS_EXPORT
+void        dbus_message_iter_init_append        (DBusMessage     *message,
+                                                  DBusMessageIter *iter);
+DBUS_EXPORT
+dbus_bool_t dbus_message_iter_append_basic       (DBusMessageIter *iter,
+                                                  int              type,
+                                                  const void      *value);
+DBUS_EXPORT
+dbus_bool_t dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
+                                                  int              element_type,
+                                                  const void      *value,
+                                                  int              n_elements);
+DBUS_EXPORT
+dbus_bool_t dbus_message_iter_open_container     (DBusMessageIter *iter,
+                                                  int              type,
+                                                  const char      *contained_signature,
+                                                  DBusMessageIter *sub);
+DBUS_EXPORT
+dbus_bool_t dbus_message_iter_close_container    (DBusMessageIter *iter,
+                                                  DBusMessageIter *sub);
+DBUS_EXPORT
+void        dbus_message_iter_abandon_container  (DBusMessageIter *iter,
+                                                  DBusMessageIter *sub);
+
+DBUS_EXPORT
+void dbus_message_lock    (DBusMessage  *message);
+
+DBUS_EXPORT
+dbus_bool_t  dbus_set_error_from_message  (DBusError    *error,
+                                           DBusMessage  *message);
+
+
+DBUS_EXPORT
+dbus_bool_t dbus_message_allocate_data_slot (dbus_int32_t     *slot_p);
+DBUS_EXPORT
+void        dbus_message_free_data_slot     (dbus_int32_t     *slot_p);
+DBUS_EXPORT
+dbus_bool_t dbus_message_set_data           (DBusMessage      *message,
+                                             dbus_int32_t      slot,
+                                             void             *data,
+                                             DBusFreeFunction  free_data_func);
+DBUS_EXPORT
+void*       dbus_message_get_data           (DBusMessage      *message,
+                                             dbus_int32_t      slot);
+
+DBUS_EXPORT
+int         dbus_message_type_from_string (const char *type_str);
+DBUS_EXPORT
+const char* dbus_message_type_to_string   (int type);
+
+DBUS_EXPORT
+dbus_bool_t  dbus_message_marshal   (DBusMessage  *msg,
+                                     char        **marshalled_data_p,
+                                     int          *len_p);
+DBUS_EXPORT
+DBusMessage* dbus_message_demarshal (const char *str,
+                                     int         len,
+                                     DBusError  *error);
+
+DBUS_EXPORT
+int          dbus_message_demarshal_bytes_needed (const char *str, 
+                                                  int len);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_MESSAGE_H */
diff --git a/dbus/dbus/dbus-misc.c b/dbus/dbus/dbus-misc.c
new file mode 100644
index 0000000..b161013
--- /dev/null
+++ b/dbus/dbus/dbus-misc.c
@@ -0,0 +1,248 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-misc.c  A few assorted public functions that don't fit elsewhere
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-misc.h"
+#include "dbus-internals.h"
+#include "dbus-string.h"
+
+/**
+ * @defgroup DBusMisc Miscellaneous
+ * @ingroup  DBus
+ * @brief Miscellaneous API that doesn't cleanly fit anywhere else
+ *
+ * @{
+ */
+
+/**
+ * Obtains the machine UUID of the machine this process is running on.
+ *
+ * The returned string must be freed with dbus_free().
+ * 
+ * This UUID is guaranteed to remain the same until the next reboot
+ * (unless the sysadmin foolishly changes it and screws themselves).
+ * It will usually remain the same across reboots also, but hardware
+ * configuration changes or rebuilding the machine could break that.
+ *
+ * The idea is that two processes with the same machine ID should be
+ * able to use shared memory, UNIX domain sockets, process IDs, and other
+ * features of the OS that require both processes to be running
+ * on the same OS kernel instance.
+ *
+ * The machine ID can also be used to create unique per-machine
+ * instances. For example, you could use it in bus names or
+ * X selection names.
+ *
+ * The machine ID is preferred over the machine hostname, because
+ * the hostname is frequently set to "localhost.localdomain" and
+ * may also change at runtime.
+ *
+ * You can get the machine ID of a remote application by invoking the
+ * method GetMachineId from interface org.freedesktop.DBus.Peer.
+ *
+ * If the remote application has the same machine ID as the one
+ * returned by this function, then the remote application is on the
+ * same machine as your application.
+ *
+ * The UUID is not a UUID in the sense of RFC4122; the details
+ * are explained in the D-Bus specification.
+ *
+ * @returns a 32-byte-long hex-encoded UUID string, or #NULL if insufficient memory
+ */
+char*
+dbus_get_local_machine_id (void)
+{
+  DBusString uuid;
+  char *s;
+
+  s = NULL;
+
+  if (!_dbus_string_init (&uuid))
+    return NULL;
+
+  if (!_dbus_get_local_machine_uuid_encoded (&uuid) ||
+      !_dbus_string_steal_data (&uuid, &s))
+    {
+      _dbus_string_free (&uuid);
+      return NULL;
+    }
+  else
+    {
+      _dbus_string_free (&uuid);
+      return s;
+    }
+
+}
+
+/**
+ * @def DBUS_MAJOR_VERSION
+ *
+ * The COMPILE TIME major version of libdbus, that is, the "X" in "X.Y.Z",
+ * as an integer literal. Consider carefully whether to use this or the
+ * runtime version from dbus_get_version().
+ */
+
+/**
+ * @def DBUS_MINOR_VERSION
+ *
+ * The COMPILE TIME minor version of libdbus, that is, the "Y" in "X.Y.Z",
+ * as an integer literal. Consider carefully whether to use this or the
+ * runtime version from dbus_get_version().
+ */
+
+/**
+ * @def DBUS_MICRO_VERSION
+ *
+ * The COMPILE TIME micro version of libdbus, that is, the "Z" in "X.Y.Z",
+ * as an integer literal. Consider carefully whether to use this or the
+ * runtime version from dbus_get_version().
+ */
+
+/**
+ * @def DBUS_VERSION
+ *
+ * The COMPILE TIME version of libdbus, as a single integer that has 0 in the most
+ * significant byte, the major version in the next most significant byte,
+ * the minor version in the third most significant, and the micro version in the
+ * least significant byte. This means two DBUS_VERSION can be compared to see
+ * which is higher.
+ *
+ * Consider carefully whether to use this or the runtime version from
+ * dbus_get_version().
+ */
+
+/**
+ * @def DBUS_VERSION_STRING
+ *
+ * The COMPILE TIME version of libdbus, as a string "X.Y.Z".
+ *
+ * Consider carefully whether to use this or the runtime version from
+ * dbus_get_version().
+ */
+
+/**
+ * Gets the DYNAMICALLY LINKED version of libdbus. Alternatively, there
+ * are macros #DBUS_MAJOR_VERSION, #DBUS_MINOR_VERSION, #DBUS_MICRO_VERSION,
+ * and #DBUS_VERSION which allow you to test the VERSION YOU ARE COMPILED AGAINST.
+ * In other words, you can get either the runtime or the compile-time version.
+ * Think carefully about which of these you want in a given case.
+ *
+ * The libdbus full version number is "MAJOR.MINOR.MICRO" where the
+ * MINOR changes if API is added, and the MICRO changes with each
+ * release of a MAJOR.MINOR series.  The MINOR is an odd number for
+ * development releases and an even number for stable releases.
+ * 
+ * @param major_version_p pointer to return the major version, or #NULL
+ * @param minor_version_p pointer to return the minor version, or #NULL
+ * @param micro_version_p pointer to return the micro version, or #NULL 
+ * 
+ */
+void
+dbus_get_version (int *major_version_p,
+                  int *minor_version_p,
+                  int *micro_version_p)
+{
+  if (major_version_p)
+    *major_version_p = DBUS_MAJOR_VERSION;
+  if (minor_version_p)
+    *minor_version_p = DBUS_MINOR_VERSION;
+  if (micro_version_p)
+    *micro_version_p = DBUS_MICRO_VERSION;
+}
+
+
+/** @} */ /* End of public API */
+
+#ifdef DBUS_BUILD_TESTS
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include "dbus-test.h"
+#include <stdlib.h>
+
+
+dbus_bool_t
+_dbus_misc_test (void)
+{
+  int major, minor, micro;
+  DBusString str;
+
+  /* make sure we don't crash on NULL */
+  dbus_get_version (NULL, NULL, NULL);
+
+  /* Now verify that all the compile-time version stuff
+   * is right and matches the runtime. These tests
+   * are mostly intended to catch various kinds of
+   * typo (mixing up major and minor, that sort of thing).
+   */
+  dbus_get_version (&major, &minor, &micro);
+
+  _dbus_assert (major == DBUS_MAJOR_VERSION);
+  _dbus_assert (minor == DBUS_MINOR_VERSION);
+  _dbus_assert (micro == DBUS_MICRO_VERSION);
+
+#define MAKE_VERSION(x, y, z) (((x) << 16) | ((y) << 8) | (z))
+
+  /* check that MAKE_VERSION works and produces the intended ordering */
+  _dbus_assert (MAKE_VERSION (1, 0, 0) > MAKE_VERSION (0, 0, 0));
+  _dbus_assert (MAKE_VERSION (1, 1, 0) > MAKE_VERSION (1, 0, 0));
+  _dbus_assert (MAKE_VERSION (1, 1, 1) > MAKE_VERSION (1, 1, 0));
+
+  _dbus_assert (MAKE_VERSION (2, 0, 0) > MAKE_VERSION (1, 1, 1));
+  _dbus_assert (MAKE_VERSION (2, 1, 0) > MAKE_VERSION (1, 1, 1));
+  _dbus_assert (MAKE_VERSION (2, 1, 1) > MAKE_VERSION (1, 1, 1));
+
+  /* check DBUS_VERSION */
+  _dbus_assert (MAKE_VERSION (major, minor, micro) == DBUS_VERSION);
+
+  /* check that ordering works with DBUS_VERSION */
+  _dbus_assert (MAKE_VERSION (major - 1, minor, micro) < DBUS_VERSION);
+  _dbus_assert (MAKE_VERSION (major, minor - 1, micro) < DBUS_VERSION);
+  _dbus_assert (MAKE_VERSION (major, minor, micro - 1) < DBUS_VERSION);
+  
+  _dbus_assert (MAKE_VERSION (major + 1, minor, micro) > DBUS_VERSION);
+  _dbus_assert (MAKE_VERSION (major, minor + 1, micro) > DBUS_VERSION);
+  _dbus_assert (MAKE_VERSION (major, minor, micro + 1) > DBUS_VERSION);
+
+  /* Check DBUS_VERSION_STRING */
+
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("no memory");
+
+  if (!(_dbus_string_append_int (&str, major) &&
+        _dbus_string_append_byte (&str, '.') &&
+        _dbus_string_append_int (&str, minor) &&
+        _dbus_string_append_byte (&str, '.') &&
+        _dbus_string_append_int (&str, micro)))
+    _dbus_assert_not_reached ("no memory");
+
+  _dbus_assert (_dbus_string_equal_c_str (&str, DBUS_VERSION_STRING));
+
+  _dbus_string_free (&str);
+   
+  return TRUE;
+}
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif
diff --git a/dbus/dbus/dbus-misc.h b/dbus/dbus/dbus-misc.h
new file mode 100644
index 0000000..3504bca
--- /dev/null
+++ b/dbus/dbus/dbus-misc.h
@@ -0,0 +1,52 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-misc.h  A few assorted public functions that don't fit elsewhere
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_MISC_H
+#define DBUS_MISC_H
+
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusMisc
+ * @{
+ */
+DBUS_EXPORT
+char*       dbus_get_local_machine_id  (void);
+
+DBUS_EXPORT
+void        dbus_get_version           (int *major_version_p,
+                                        int *minor_version_p,
+                                        int *micro_version_p);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_MISC_H */
+
diff --git a/dbus/dbus/dbus-nonce.c b/dbus/dbus/dbus-nonce.c
new file mode 100644
index 0000000..e74c2dd
--- /dev/null
+++ b/dbus/dbus/dbus-nonce.c
@@ -0,0 +1,426 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-nonce.c  Nonce handling functions used by nonce-tcp (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2009 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <config.h>
+// major sections of this file are modified code from libassuan, (C) FSF
+#include "dbus-nonce.h"
+#include "dbus-internals.h"
+#include "dbus-protocol.h"
+#include "dbus-sysdeps.h"
+
+#include <stdio.h>
+
+static dbus_bool_t
+do_check_nonce (int fd, const DBusString *nonce, DBusError *error)
+{
+  DBusString buffer;
+  DBusString p;
+  size_t nleft;
+  dbus_bool_t result;
+  int n;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  nleft = 16;
+
+  if (   !_dbus_string_init (&buffer)
+      || !_dbus_string_init (&p) ) {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        _dbus_string_free (&p);
+        _dbus_string_free (&buffer);
+        return FALSE;
+      }
+
+  while (nleft)
+    {
+      n = _dbus_read_socket (fd, &p, nleft);
+      if (n == -1 && _dbus_get_is_errno_eintr())
+        ;
+      else if (n == -1 && _dbus_get_is_errno_eagain_or_ewouldblock())
+        _dbus_sleep_milliseconds (100);
+      else if (n==-1)
+        {
+          dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%d)", fd );
+          _dbus_string_free (&p);
+          _dbus_string_free (&buffer);
+          return FALSE;
+        }
+      else if (!n)
+        {
+          _dbus_string_free (&p);
+          _dbus_string_free (&buffer);
+          dbus_set_error (error, DBUS_ERROR_IO_ERROR, "Could not read nonce from socket (fd=%d)", fd );
+          return FALSE;
+        }
+      else
+        {
+          _dbus_string_append_len(&buffer, _dbus_string_get_const_data (&p), n);
+          nleft -= n;
+        }
+    }
+
+  result =  _dbus_string_equal_len (&buffer, nonce, 16);
+  if (!result)
+    dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, "Nonces do not match, access denied (fd=%d)", fd );
+
+  _dbus_string_free (&p);
+  _dbus_string_free (&buffer);
+
+  return result;
+}
+
+/**
+ * reads the nonce from the nonce file and stores it in a string
+ *
+ * @param fname the file to read the nonce from
+ * @param nonce returns the nonce. Must be an initialized string, the nonce will be appended.
+ * @param error error object to report possible errors
+ * @return FALSE iff reading the nonce fails (error is set then)
+ */
+dbus_bool_t
+_dbus_read_nonce (const DBusString *fname, DBusString *nonce, DBusError* error)
+{
+  FILE *fp;
+  char buffer[17];
+  size_t nread;
+
+  buffer[sizeof buffer - 1] = '\0';
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  _dbus_verbose ("reading nonce from file: %s\n", _dbus_string_get_const_data (fname));
+
+
+  fp = fopen (_dbus_string_get_const_data (fname), "rb");
+  if (!fp)
+    return FALSE;
+  nread = fread (buffer, 1, sizeof buffer - 1, fp);
+  fclose (fp);
+  if (!nread)
+    {
+      dbus_set_error (error, DBUS_ERROR_FILE_NOT_FOUND, "Could not read nonce from file %s", _dbus_string_get_const_data (fname));
+      return FALSE;
+    }
+
+  if (!_dbus_string_append_len (nonce, buffer, sizeof buffer - 1 ))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+  return TRUE;
+}
+
+int
+_dbus_accept_with_noncefile (int listen_fd, const DBusNonceFile *noncefile)
+{
+  int fd;
+  DBusString nonce;
+
+  _dbus_assert (noncefile != NULL);
+  if (!_dbus_string_init (&nonce))
+    return -1;
+  //PENDING(kdab): set better errors
+  if (_dbus_read_nonce (_dbus_noncefile_get_path(noncefile), &nonce, NULL) != TRUE)
+    return -1;
+  fd = _dbus_accept (listen_fd);
+  if (_dbus_socket_is_invalid (fd))
+    return fd;
+  if (do_check_nonce(fd, &nonce, NULL) != TRUE) {
+    _dbus_verbose ("nonce check failed. Closing socket.\n");
+    _dbus_close_socket(fd, NULL);
+    return -1;
+  }
+
+  return fd;
+}
+
+static dbus_bool_t
+generate_and_write_nonce (const DBusString *filename, DBusError *error)
+{
+  DBusString nonce;
+  dbus_bool_t ret;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (!_dbus_string_init (&nonce))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+
+  if (!_dbus_generate_random_bytes (&nonce, 16))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&nonce);
+      return FALSE;
+    }
+
+  ret = _dbus_string_save_to_file (&nonce, filename, FALSE, error);
+
+  _dbus_string_free (&nonce);
+
+  return ret;
+}
+
+/**
+ * sends the nonce over a given socket. Blocks while doing so.
+ *
+ * @param fd the file descriptor to write the nonce data to (usually a socket)
+ * @param noncefile the noncefile location to read the nonce from
+ * @param error contains error details if FALSE is returned
+ * @return TRUE iff the nonce was successfully sent. Note that this does not
+ * indicate whether the server accepted the nonce.
+ */
+dbus_bool_t
+_dbus_send_nonce (int fd, const DBusString *noncefile, DBusError *error)
+{
+  dbus_bool_t read_result;
+  int send_result;
+  DBusString nonce;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (_dbus_string_get_length (noncefile) == 0)
+    return FALSE;
+
+  if (!_dbus_string_init (&nonce))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+
+  read_result = _dbus_read_nonce (noncefile, &nonce, error);
+  if (!read_result)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      _dbus_string_free (&nonce);
+      return FALSE;
+    }
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  send_result = _dbus_write_socket (fd, &nonce, 0, _dbus_string_get_length (&nonce));
+
+  _dbus_string_free (&nonce);
+
+  if (send_result == -1)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_system_errno (),
+                      "Failed to send nonce (fd=%d): %s",
+                      fd, _dbus_strerror_from_errno ());
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+do_noncefile_create (DBusNonceFile *noncefile,
+                     DBusError *error,
+                     dbus_bool_t use_subdir)
+{
+    DBusString randomStr;
+
+    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+    _dbus_assert (noncefile);
+
+    if (!_dbus_string_init (&randomStr))
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        goto on_error;
+      }
+
+    if (!_dbus_generate_random_ascii (&randomStr, 8))
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        goto on_error;
+      }
+
+    if (!_dbus_string_init (&noncefile->dir)
+        || !_dbus_string_append (&noncefile->dir, _dbus_get_tmpdir()))
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        goto on_error;
+      }
+    if (use_subdir)
+      {
+        if (!_dbus_string_append (&noncefile->dir, "/dbus_nonce-")
+            || !_dbus_string_append (&noncefile->dir, _dbus_string_get_const_data (&randomStr)) )
+          {
+            dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+            goto on_error;
+          }
+        if (!_dbus_string_init (&noncefile->path)
+            || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
+            || !_dbus_string_append (&noncefile->path, "/nonce"))
+          {
+            dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+            goto on_error;
+          }
+        if (!_dbus_create_directory (&noncefile->dir, error))
+          {
+            _DBUS_ASSERT_ERROR_IS_SET (error);
+            goto on_error;
+          }
+        _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+      }
+    else
+      {
+        if (!_dbus_string_init (&noncefile->path)
+            || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0)
+            || !_dbus_string_append (&noncefile->path, "/dbus_nonce-")
+            || !_dbus_string_append (&noncefile->path, _dbus_string_get_const_data (&randomStr)))
+          {
+            dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+            goto on_error;
+          }
+
+      }
+
+    if (!generate_and_write_nonce (&noncefile->path, error))
+      {
+        _DBUS_ASSERT_ERROR_IS_SET (error);
+        if (use_subdir)
+          _dbus_delete_directory (&noncefile->dir, NULL); //we ignore possible errors deleting the dir and return the write error instead
+        goto on_error;
+      }
+    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+    _dbus_string_free (&randomStr);
+
+    return TRUE;
+  on_error:
+    if (use_subdir)
+      _dbus_delete_directory (&noncefile->dir, NULL);
+    _dbus_string_free (&noncefile->dir);
+    _dbus_string_free (&noncefile->path);
+    _dbus_string_free (&randomStr);
+    return FALSE;
+}
+
+#ifdef DBUS_WIN
+/**
+ * creates a nonce file in a user-readable location and writes a generated nonce to it
+ *
+ * @param noncefile returns the nonce file location
+ * @param error error details if creating the nonce file fails
+ * @return TRUE iff the nonce file was successfully created
+ */
+dbus_bool_t
+_dbus_noncefile_create (DBusNonceFile *noncefile,
+                        DBusError *error)
+{
+    return do_noncefile_create (noncefile, error, /*use_subdir=*/FALSE);
+}
+
+/**
+ * deletes the noncefile and frees the DBusNonceFile object.
+ *
+ * @param noncefile the nonce file to delete. Contents will be freed.
+ * @param error error details if the nonce file could not be deleted
+ * @return TRUE
+ */
+dbus_bool_t
+_dbus_noncefile_delete (DBusNonceFile *noncefile,
+                        DBusError *error)
+{
+    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+    _dbus_delete_file (&noncefile->path, error);
+    _dbus_string_free (&noncefile->dir);
+    _dbus_string_free (&noncefile->path);
+    return TRUE;
+}
+
+#else
+/**
+ * creates a nonce file in a user-readable location and writes a generated nonce to it.
+ * Initializes the noncefile object.
+ *
+ * @param noncefile returns the nonce file location
+ * @param error error details if creating the nonce file fails
+ * @return TRUE iff the nonce file was successfully created
+ */
+dbus_bool_t
+_dbus_noncefile_create (DBusNonceFile *noncefile,
+                        DBusError *error)
+{
+    return do_noncefile_create (noncefile, error, /*use_subdir=*/TRUE);
+}
+
+/**
+ * deletes the noncefile and frees the DBusNonceFile object.
+ *
+ * @param noncefile the nonce file to delete. Contents will be freed.
+ * @param error error details if the nonce file could not be deleted
+ * @return TRUE
+ */
+dbus_bool_t
+_dbus_noncefile_delete (DBusNonceFile *noncefile,
+                        DBusError *error)
+{
+    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+    _dbus_delete_directory (&noncefile->dir, error);
+    _dbus_string_free (&noncefile->dir);
+    _dbus_string_free (&noncefile->path);
+    return TRUE;
+}
+#endif
+
+
+/**
+ * returns the absolute file path of the nonce file
+ *
+ * @param noncefile an initialized noncefile object
+ * @return the absolute path of the nonce file
+ */
+const DBusString*
+_dbus_noncefile_get_path (const DBusNonceFile *noncefile)
+{
+    _dbus_assert (noncefile);
+    return &noncefile->path;
+}
+
+/**
+ * reads data from a file descriptor and checks if the received data matches
+ * the data in the given noncefile.
+ *
+ * @param fd the file descriptor to read the nonce from
+ * @param noncefile the nonce file to check the received data against
+ * @param error error details on fail
+ * @return TRUE iff a nonce could be successfully read from the file descriptor
+ * and matches the nonce from the given nonce file
+ */
+dbus_bool_t
+_dbus_noncefile_check_nonce (int fd,
+                             const DBusNonceFile *noncefile,
+                             DBusError* error)
+{
+    return do_check_nonce (fd, _dbus_noncefile_get_path (noncefile), error);
+}
+
+
+/** @} end of nonce */
diff --git a/dbus/dbus/dbus-nonce.h b/dbus/dbus/dbus-nonce.h
new file mode 100644
index 0000000..474ea72
--- /dev/null
+++ b/dbus/dbus/dbus-nonce.h
@@ -0,0 +1,72 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-nonce.h  Nonce handling functions used by nonce-tcp (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2009 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef DBUS_NONCE_H
+#define DBUS_NONCE_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-string.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusNonceFile DBusNonceFile;
+
+struct DBusNonceFile
+{
+  DBusString path;
+  DBusString dir;
+};
+
+// server
+
+dbus_bool_t _dbus_noncefile_create (DBusNonceFile *noncefile,
+                                    DBusError *error);
+
+dbus_bool_t _dbus_noncefile_delete (DBusNonceFile *noncefile,
+                                    DBusError *error);
+
+dbus_bool_t _dbus_noncefile_check_nonce (int fd,
+                                         const DBusNonceFile *noncefile,
+                                         DBusError *error);
+
+const DBusString* _dbus_noncefile_get_path (const DBusNonceFile *noncefile);
+
+int _dbus_accept_with_noncefile (int listen_fd,
+                                 const DBusNonceFile *noncefile);
+
+// shared
+
+dbus_bool_t _dbus_read_nonce (const DBusString *fname,
+                              DBusString *nonce,
+                              DBusError *error);
+
+// client
+
+dbus_bool_t _dbus_send_nonce (int fd,
+                              const DBusString *noncefile,
+                              DBusError *error);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_NONCE_H */
diff --git a/dbus/dbus/dbus-object-tree.c b/dbus/dbus/dbus-object-tree.c
new file mode 100644
index 0000000..172c9d9
--- /dev/null
+++ b/dbus/dbus/dbus-object-tree.c
@@ -0,0 +1,1965 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-object-tree.c  DBusObjectTree (internals of DBusConnection)
+ *
+ * Copyright (C) 2003, 2005  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-object-tree.h"
+#include "dbus-connection-internal.h"
+#include "dbus-internals.h"
+#include "dbus-hash.h"
+#include "dbus-protocol.h"
+#include "dbus-string.h"
+#include <string.h>
+#include <stdlib.h>
+
+/**
+ * @defgroup DBusObjectTree A hierarchy of objects with container-contained relationship
+ * @ingroup  DBusInternals
+ * @brief DBusObjectTree is used by DBusConnection to track the object tree
+ *
+ * Types and functions related to DBusObjectTree. These
+ * are all library-internal.
+ *
+ * @{
+ */
+
+/** Subnode of the object hierarchy */
+typedef struct DBusObjectSubtree DBusObjectSubtree;
+
+static DBusObjectSubtree* _dbus_object_subtree_new   (const char                  *name,
+                                                      const DBusObjectPathVTable  *vtable,
+                                                      void                        *user_data);
+static DBusObjectSubtree* _dbus_object_subtree_ref   (DBusObjectSubtree           *subtree);
+static void               _dbus_object_subtree_unref (DBusObjectSubtree           *subtree);
+
+/**
+ * Internals of DBusObjectTree
+ */
+struct DBusObjectTree
+{
+  int                 refcount;   /**< Reference count */
+  DBusConnection     *connection; /**< Connection this tree belongs to */
+
+  DBusObjectSubtree  *root;       /**< Root of the tree ("/" node) */
+};
+
+/**
+ * Struct representing a single registered subtree handler, or node
+ * that's a parent of a registered subtree handler. If
+ * message_function != NULL there's actually a handler at this node.
+ */
+struct DBusObjectSubtree
+{
+  DBusAtomic                         refcount;            /**< Reference count */
+  DBusObjectSubtree                 *parent;              /**< Parent node */
+  DBusObjectPathUnregisterFunction   unregister_function; /**< Function to call on unregister */
+  DBusObjectPathMessageFunction      message_function;    /**< Function to handle messages */
+  void                              *user_data;           /**< Data for functions */
+  DBusObjectSubtree                **subtrees;            /**< Child nodes */
+  int                                n_subtrees;          /**< Number of child nodes */
+  int                                max_subtrees;        /**< Number of allocated entries in subtrees */
+  unsigned int                       invoke_as_fallback : 1; /**< Whether to invoke message_function when child nodes don't handle the message */
+  char                               name[1]; /**< Allocated as large as necessary */
+};
+
+/**
+ * Creates a new object tree, representing a mapping from paths
+ * to handler vtables.
+ *
+ * @param connection the connection this tree belongs to
+ * @returns the new tree or #NULL if no memory
+ */
+DBusObjectTree*
+_dbus_object_tree_new (DBusConnection *connection)
+{
+  DBusObjectTree *tree;
+
+  /* the connection passed in here isn't fully constructed,
+   * so don't do anything more than store a pointer to
+   * it
+   */
+
+  tree = dbus_new0 (DBusObjectTree, 1);
+  if (tree == NULL)
+    goto oom;
+
+  tree->refcount = 1;
+  tree->connection = connection;
+  tree->root = _dbus_object_subtree_new ("/", NULL, NULL);
+  if (tree->root == NULL)
+    goto oom;
+  tree->root->invoke_as_fallback = TRUE;
+  
+  return tree;
+
+ oom:
+  if (tree)
+    {
+      dbus_free (tree);
+    }
+
+  return NULL;
+}
+
+/**
+ * Increment the reference count
+ * @param tree the object tree
+ * @returns the object tree
+ */
+DBusObjectTree *
+_dbus_object_tree_ref (DBusObjectTree *tree)
+{
+  _dbus_assert (tree->refcount > 0);
+
+  tree->refcount += 1;
+
+  return tree;
+}
+
+/**
+ * Decrement the reference count
+ * @param tree the object tree
+ */
+void
+_dbus_object_tree_unref (DBusObjectTree *tree)
+{
+  _dbus_assert (tree->refcount > 0);
+
+  tree->refcount -= 1;
+
+  if (tree->refcount == 0)
+    {
+      _dbus_object_tree_free_all_unlocked (tree);
+
+      dbus_free (tree);
+    }
+}
+
+/** Set to 1 to get a bunch of debug spew about finding the
+ * subtree nodes
+ */
+#define VERBOSE_FIND 0
+
+static DBusObjectSubtree*
+find_subtree_recurse (DBusObjectSubtree  *subtree,
+                      const char        **path,
+                      dbus_bool_t         create_if_not_found,
+                      int                *index_in_parent,
+                      dbus_bool_t        *exact_match)
+{
+  int i, j;
+  dbus_bool_t return_deepest_match;
+
+  return_deepest_match = exact_match != NULL;
+
+  _dbus_assert (!(return_deepest_match && create_if_not_found));
+
+  if (path[0] == NULL)
+    {
+#if VERBOSE_FIND
+      _dbus_verbose ("  path exhausted, returning %s\n",
+                     subtree->name);
+#endif
+      if (exact_match != NULL)
+	*exact_match = TRUE;
+      return subtree;
+    }
+
+#if VERBOSE_FIND
+  _dbus_verbose ("  searching children of %s for %s\n",
+                 subtree->name, path[0]);
+#endif
+  
+  i = 0;
+  j = subtree->n_subtrees;
+  while (i < j)
+    {
+      int k, v;
+
+      k = (i + j) / 2;
+      v = strcmp (path[0], subtree->subtrees[k]->name);
+
+#if VERBOSE_FIND
+      _dbus_verbose ("  %s cmp %s = %d\n",
+                     path[0], subtree->subtrees[k]->name,
+                     v);
+#endif
+      
+      if (v == 0)
+        {
+          if (index_in_parent)
+            {
+#if VERBOSE_FIND
+              _dbus_verbose ("  storing parent index %d\n", k);
+#endif
+              *index_in_parent = k;
+            }
+
+          if (return_deepest_match)
+            {
+              DBusObjectSubtree *next;
+
+              next = find_subtree_recurse (subtree->subtrees[k],
+                                           &path[1], create_if_not_found, 
+                                           index_in_parent, exact_match);
+              if (next == NULL &&
+                  subtree->invoke_as_fallback)
+                {
+#if VERBOSE_FIND
+                  _dbus_verbose ("  no deeper match found, returning %s\n",
+                                 subtree->name);
+#endif
+		  if (exact_match != NULL)
+		    *exact_match = FALSE;
+                  return subtree;
+                }
+              else
+                return next;
+            }
+          else
+            return find_subtree_recurse (subtree->subtrees[k],
+                                         &path[1], create_if_not_found, 
+                                         index_in_parent, exact_match);
+        }
+      else if (v < 0)
+        {
+          j = k;
+        }
+      else
+        {
+          i = k + 1;
+        }
+    }
+
+#if VERBOSE_FIND
+  _dbus_verbose ("  no match found, current tree %s, create_if_not_found = %d\n",
+                 subtree->name, create_if_not_found);
+#endif
+  
+  if (create_if_not_found)
+    {
+      DBusObjectSubtree* child;
+      int child_pos, new_n_subtrees;
+
+#if VERBOSE_FIND
+      _dbus_verbose ("  creating subtree %s\n",
+                     path[0]);
+#endif
+      
+      child = _dbus_object_subtree_new (path[0],
+                                        NULL, NULL);
+      if (child == NULL)
+        return NULL;
+
+      new_n_subtrees = subtree->n_subtrees + 1;
+      if (new_n_subtrees > subtree->max_subtrees)
+        {
+          int new_max_subtrees;
+          DBusObjectSubtree **new_subtrees;
+
+          new_max_subtrees = subtree->max_subtrees == 0 ? 1 : 2 * subtree->max_subtrees;
+          new_subtrees = dbus_realloc (subtree->subtrees,
+                                       new_max_subtrees * sizeof (DBusObjectSubtree*));
+          if (new_subtrees == NULL)
+            {
+              _dbus_object_subtree_unref (child);
+              return NULL;
+            }
+          subtree->subtrees = new_subtrees;
+          subtree->max_subtrees = new_max_subtrees;
+        }
+
+      /* The binary search failed, so i == j points to the 
+         place the child should be inserted. */
+      child_pos = i;
+      _dbus_assert (child_pos < new_n_subtrees &&
+                    new_n_subtrees <= subtree->max_subtrees);
+      if (child_pos + 1 < new_n_subtrees)
+	{
+	  memmove (&subtree->subtrees[child_pos+1], 
+		   &subtree->subtrees[child_pos], 
+		   (new_n_subtrees - child_pos - 1) * 
+		   sizeof subtree->subtrees[0]);
+	}
+      subtree->subtrees[child_pos] = child;
+
+      if (index_in_parent)
+        *index_in_parent = child_pos;
+      subtree->n_subtrees = new_n_subtrees;
+      child->parent = subtree;
+
+      return find_subtree_recurse (child,
+                                   &path[1], create_if_not_found, 
+                                   index_in_parent, exact_match);
+    }
+  else
+    {
+      if (exact_match != NULL)
+	*exact_match = FALSE;
+      return (return_deepest_match && subtree->invoke_as_fallback) ? subtree : NULL;
+    }
+}
+
+static DBusObjectSubtree*
+find_subtree (DBusObjectTree *tree,
+              const char    **path,
+              int            *index_in_parent)
+{
+  DBusObjectSubtree *subtree;
+
+#if VERBOSE_FIND
+  _dbus_verbose ("Looking for exact registered subtree\n");
+#endif
+  
+  subtree = find_subtree_recurse (tree->root, path, FALSE, index_in_parent, NULL);
+
+  if (subtree && subtree->message_function == NULL)
+    return NULL;
+  else
+    return subtree;
+}
+
+static DBusObjectSubtree*
+lookup_subtree (DBusObjectTree *tree,
+                const char    **path)
+{
+#if VERBOSE_FIND
+  _dbus_verbose ("Looking for subtree\n");
+#endif
+  return find_subtree_recurse (tree->root, path, FALSE, NULL, NULL);
+}
+
+static DBusObjectSubtree*
+find_handler (DBusObjectTree *tree,
+              const char    **path,
+              dbus_bool_t    *exact_match)
+{
+#if VERBOSE_FIND
+  _dbus_verbose ("Looking for deepest handler\n");
+#endif
+  _dbus_assert (exact_match != NULL);
+
+  *exact_match = FALSE; /* ensure always initialized */
+  
+  return find_subtree_recurse (tree->root, path, FALSE, NULL, exact_match);
+}
+
+static DBusObjectSubtree*
+ensure_subtree (DBusObjectTree *tree,
+                const char    **path)
+{
+#if VERBOSE_FIND
+  _dbus_verbose ("Ensuring subtree\n");
+#endif
+  return find_subtree_recurse (tree->root, path, TRUE, NULL, NULL);
+}
+
+static char *flatten_path (const char **path);
+
+/**
+ * Registers a new subtree in the global object tree.
+ *
+ * @param tree the global object tree
+ * @param fallback #TRUE to handle messages to children of this path
+ * @param path NULL-terminated array of path elements giving path to subtree
+ * @param vtable the vtable used to traverse this subtree
+ * @param user_data user data to pass to methods in the vtable
+ * @param error address where an error can be returned
+ * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
+ *    #DBUS_ERROR_OBJECT_PATH_IN_USE) is reported
+ */
+dbus_bool_t
+_dbus_object_tree_register (DBusObjectTree              *tree,
+                            dbus_bool_t                  fallback,
+                            const char                 **path,
+                            const DBusObjectPathVTable  *vtable,
+                            void                        *user_data,
+                            DBusError                   *error)
+{
+  DBusObjectSubtree  *subtree;
+
+  _dbus_assert (tree != NULL);
+  _dbus_assert (vtable->message_function != NULL);
+  _dbus_assert (path != NULL);
+
+  subtree = ensure_subtree (tree, path);
+  if (subtree == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (subtree->message_function != NULL)
+    {
+      if (error != NULL)
+        {
+          char *complete_path = flatten_path (path);
+
+          dbus_set_error (error, DBUS_ERROR_OBJECT_PATH_IN_USE,
+                          "A handler is already registered for %s",
+                          complete_path ? complete_path
+                                        : "(cannot represent path: out of memory!)");
+
+          dbus_free (complete_path);
+        }
+
+      return FALSE;
+    }
+
+  subtree->message_function = vtable->message_function;
+  subtree->unregister_function = vtable->unregister_function;
+  subtree->user_data = user_data;
+  subtree->invoke_as_fallback = fallback != FALSE;
+
+  return TRUE;
+}
+
+/**
+ * Unregisters an object subtree that was registered with the
+ * same path.
+ *
+ * @param tree the global object tree
+ * @param path path to the subtree (same as the one passed to _dbus_object_tree_register())
+ */
+void
+_dbus_object_tree_unregister_and_unlock (DBusObjectTree          *tree,
+                                         const char             **path)
+{
+  int i;
+  DBusObjectSubtree *subtree;
+  DBusObjectPathUnregisterFunction unregister_function;
+  void *user_data;
+  DBusConnection *connection;
+
+  _dbus_assert (path != NULL);
+
+  unregister_function = NULL;
+  user_data = NULL;
+
+  subtree = find_subtree (tree, path, &i);
+
+#ifndef DBUS_DISABLE_CHECKS
+  if (subtree == NULL)
+    {
+      _dbus_warn ("Attempted to unregister path (path[0] = %s path[1] = %s) which isn't registered\n",
+                  path[0] ? path[0] : "null",
+                  path[1] ? path[1] : "null");
+      goto unlock;    
+    }
+#else
+  _dbus_assert (subtree != NULL);
+#endif
+
+  _dbus_assert (subtree->parent == NULL ||
+                (i >= 0 && subtree->parent->subtrees[i] == subtree));
+
+  subtree->message_function = NULL;
+
+  unregister_function = subtree->unregister_function;
+  user_data = subtree->user_data;
+
+  subtree->unregister_function = NULL;
+  subtree->user_data = NULL;
+
+  /* If we have no subtrees of our own, remove from
+   * our parent (FIXME could also be more aggressive
+   * and remove our parent if it becomes empty)
+   */
+  if (subtree->parent && subtree->n_subtrees == 0)
+    {
+      /* assumes a 0-byte memmove is OK */
+      memmove (&subtree->parent->subtrees[i],
+               &subtree->parent->subtrees[i+1],
+               (subtree->parent->n_subtrees - i - 1) *
+               sizeof (subtree->parent->subtrees[0]));
+      subtree->parent->n_subtrees -= 1;
+
+      subtree->parent = NULL;
+
+      _dbus_object_subtree_unref (subtree);
+    }
+  subtree = NULL;
+
+unlock:
+  connection = tree->connection;
+
+  /* Unlock and call application code */
+#ifdef DBUS_BUILD_TESTS
+  if (connection)
+#endif
+    {
+      _dbus_connection_ref_unlocked (connection);
+      _dbus_verbose ("unlock\n");
+      _dbus_connection_unlock (connection);
+    }
+
+  if (unregister_function)
+    (* unregister_function) (connection, user_data);
+
+#ifdef DBUS_BUILD_TESTS
+  if (connection)
+#endif
+    dbus_connection_unref (connection);
+}
+
+static void
+free_subtree_recurse (DBusConnection    *connection,
+                      DBusObjectSubtree *subtree)
+{
+  /* Delete them from the end, for slightly
+   * more robustness against odd reentrancy.
+   */
+  while (subtree->n_subtrees > 0)
+    {
+      DBusObjectSubtree *child;
+
+      child = subtree->subtrees[subtree->n_subtrees - 1];
+      subtree->subtrees[subtree->n_subtrees - 1] = NULL;
+      subtree->n_subtrees -= 1;
+      child->parent = NULL;
+
+      free_subtree_recurse (connection, child);
+    }
+
+  /* Call application code */
+  if (subtree->unregister_function)
+    (* subtree->unregister_function) (connection,
+				      subtree->user_data);
+
+  subtree->message_function = NULL;
+  subtree->unregister_function = NULL;
+  subtree->user_data = NULL;
+
+  /* Now free ourselves */
+  _dbus_object_subtree_unref (subtree);
+}
+
+/**
+ * Free all the handlers in the tree. Lock on tree's connection
+ * must not be held.
+ *
+ * @param tree the object tree
+ */
+void
+_dbus_object_tree_free_all_unlocked (DBusObjectTree *tree)
+{
+  if (tree->root)
+    free_subtree_recurse (tree->connection,
+                          tree->root);
+  tree->root = NULL;
+}
+
+static dbus_bool_t
+_dbus_object_tree_list_registered_unlocked (DBusObjectTree *tree,
+                                            const char    **parent_path,
+                                            char         ***child_entries)
+{
+  DBusObjectSubtree *subtree;
+  char **retval;
+  
+  _dbus_assert (parent_path != NULL);
+  _dbus_assert (child_entries != NULL);
+
+  *child_entries = NULL;
+  
+  subtree = lookup_subtree (tree, parent_path);
+  if (subtree == NULL)
+    {
+      retval = dbus_new0 (char *, 1);
+    }
+  else
+    {
+      int i;
+      retval = dbus_new0 (char*, subtree->n_subtrees + 1);
+      if (retval == NULL)
+        goto out;
+      i = 0;
+      while (i < subtree->n_subtrees)
+        {
+          retval[i] = _dbus_strdup (subtree->subtrees[i]->name);
+          if (retval[i] == NULL)
+            {
+              dbus_free_string_array (retval);
+              retval = NULL;
+              goto out;
+            }
+          ++i;
+        }
+    }
+
+ out:
+    
+  *child_entries = retval;
+  return retval != NULL;
+}
+
+static DBusHandlerResult
+handle_default_introspect_and_unlock (DBusObjectTree          *tree,
+                                      DBusMessage             *message,
+                                      const char             **path)
+{
+  DBusString xml;
+  DBusHandlerResult result;
+  char **children;
+  int i;
+  DBusMessage *reply;
+  DBusMessageIter iter;
+  const char *v_STRING;
+  dbus_bool_t already_unlocked;
+
+  /* We have the connection lock here */
+
+  already_unlocked = FALSE;
+  
+  _dbus_verbose (" considering default Introspect() handler...\n");
+
+  reply = NULL;
+  
+  if (!dbus_message_is_method_call (message,
+                                    DBUS_INTERFACE_INTROSPECTABLE,
+                                    "Introspect"))
+    {
+#ifdef DBUS_BUILD_TESTS
+      if (tree->connection)
+#endif
+        {
+          _dbus_verbose ("unlock\n");
+          _dbus_connection_unlock (tree->connection);
+        }
+      
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+  _dbus_verbose (" using default Introspect() handler!\n");
+  
+  if (!_dbus_string_init (&xml))
+    {
+#ifdef DBUS_BUILD_TESTS
+      if (tree->connection)
+#endif
+        {
+          _dbus_verbose ("unlock\n");
+          _dbus_connection_unlock (tree->connection);
+        }
+
+      return DBUS_HANDLER_RESULT_NEED_MEMORY;
+    }
+
+  result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+  children = NULL;
+  if (!_dbus_object_tree_list_registered_unlocked (tree, path, &children))
+    goto out;
+
+  if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
+    goto out;
+  
+  if (!_dbus_string_append (&xml, "<node>\n"))
+    goto out;
+
+  i = 0;
+  while (children[i] != NULL)
+    {
+      if (!_dbus_string_append_printf (&xml, "  <node name=\"%s\"/>\n",
+                                       children[i]))
+        goto out;
+
+      ++i;
+    }
+
+  if (!_dbus_string_append (&xml, "</node>\n"))
+    goto out;
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    goto out;
+
+  dbus_message_iter_init_append (reply, &iter);
+  v_STRING = _dbus_string_get_const_data (&xml);
+  if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &v_STRING))
+    goto out;
+  
+#ifdef DBUS_BUILD_TESTS
+  if (tree->connection)
+#endif
+    {
+      already_unlocked = TRUE;
+      
+      if (!_dbus_connection_send_and_unlock (tree->connection, reply, NULL))
+        goto out;
+    }
+  
+  result = DBUS_HANDLER_RESULT_HANDLED;
+  
+ out:
+#ifdef DBUS_BUILD_TESTS
+  if (tree->connection)
+#endif
+    {
+      if (!already_unlocked)
+        {
+          _dbus_verbose ("unlock\n");
+          _dbus_connection_unlock (tree->connection);
+        }
+    }
+  
+  _dbus_string_free (&xml);
+  dbus_free_string_array (children);
+  if (reply)
+    dbus_message_unref (reply);
+  
+  return result;
+}
+
+/**
+ * Tries to dispatch a message by directing it to handler for the
+ * object path listed in the message header, if any. Messages are
+ * dispatched first to the registered handler that matches the largest
+ * number of path elements; that is, message to /foo/bar/baz would go
+ * to the handler for /foo/bar before the one for /foo.
+ *
+ * @todo thread problems
+ *
+ * @param tree the global object tree
+ * @param message the message to dispatch
+ * @returns whether message was handled successfully
+ */
+DBusHandlerResult
+_dbus_object_tree_dispatch_and_unlock (DBusObjectTree          *tree,
+                                       DBusMessage             *message,
+                                       dbus_bool_t             *found_object)
+{
+  char **path;
+  dbus_bool_t exact_match;
+  DBusList *list;
+  DBusList *link;
+  DBusHandlerResult result;
+  DBusObjectSubtree *subtree;
+  
+#if 0
+  _dbus_verbose ("Dispatch of message by object path\n");
+#endif
+  
+  path = NULL;
+  if (!dbus_message_get_path_decomposed (message, &path))
+    {
+#ifdef DBUS_BUILD_TESTS
+      if (tree->connection)
+#endif
+        {
+          _dbus_verbose ("unlock\n");
+          _dbus_connection_unlock (tree->connection);
+        }
+      
+      _dbus_verbose ("No memory to get decomposed path\n");
+
+      return DBUS_HANDLER_RESULT_NEED_MEMORY;
+    }
+
+  if (path == NULL)
+    {
+#ifdef DBUS_BUILD_TESTS
+      if (tree->connection)
+#endif
+        {
+          _dbus_verbose ("unlock\n");
+          _dbus_connection_unlock (tree->connection);
+        }
+      
+      _dbus_verbose ("No path field in message\n");
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+  
+  /* Find the deepest path that covers the path in the message */
+  subtree = find_handler (tree, (const char**) path, &exact_match);
+  
+  if (found_object)
+    *found_object = !!subtree;
+
+  /* Build a list of all paths that cover the path in the message */
+
+  list = NULL;
+
+  while (subtree != NULL)
+    {
+      if (subtree->message_function != NULL && (exact_match || subtree->invoke_as_fallback))
+        {
+          _dbus_object_subtree_ref (subtree);
+
+          /* run deepest paths first */
+          if (!_dbus_list_append (&list, subtree))
+            {
+              result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+              _dbus_object_subtree_unref (subtree);
+              goto free_and_return;
+            }
+        }
+
+      exact_match = FALSE;
+      subtree = subtree->parent;
+    }
+
+  _dbus_verbose ("%d handlers in the path tree for this message\n",
+                 _dbus_list_get_length (&list));
+
+  /* Invoke each handler in the list */
+
+  result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+  link = _dbus_list_get_first_link (&list);
+  while (link != NULL)
+    {
+      DBusList *next = _dbus_list_get_next_link (&list, link);
+      subtree = link->data;
+
+      /* message_function is NULL if we're unregistered
+       * due to reentrancy
+       */
+      if (subtree->message_function)
+        {
+          DBusObjectPathMessageFunction message_function;
+          void *user_data;
+
+          message_function = subtree->message_function;
+          user_data = subtree->user_data;
+
+#if 0
+          _dbus_verbose ("  (invoking a handler)\n");
+#endif
+          
+#ifdef DBUS_BUILD_TESTS
+          if (tree->connection)
+#endif
+            {
+              _dbus_verbose ("unlock\n");
+              _dbus_connection_unlock (tree->connection);
+            }
+
+          /* FIXME you could unregister the subtree in another thread
+           * before we invoke the callback, and I can't figure out a
+           * good way to solve this.
+           */
+
+          result = (* message_function) (tree->connection,
+                                         message,
+                                         user_data);
+
+#ifdef DBUS_BUILD_TESTS
+          if (tree->connection)
+#endif
+            _dbus_connection_lock (tree->connection);
+
+          if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
+            goto free_and_return;
+        }
+
+      link = next;
+    }
+
+ free_and_return:
+
+  if (result == DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
+    {
+      /* This hardcoded default handler does a minimal Introspect()
+       */
+      result = handle_default_introspect_and_unlock (tree, message,
+                                                     (const char**) path);
+    }
+  else
+    {
+#ifdef DBUS_BUILD_TESTS
+      if (tree->connection)
+#endif
+        {
+          _dbus_verbose ("unlock\n");
+          _dbus_connection_unlock (tree->connection);
+        }
+    }
+  
+  while (list != NULL)
+    {
+      link = _dbus_list_get_first_link (&list);
+      _dbus_object_subtree_unref (link->data);
+      _dbus_list_remove_link (&list, link);
+    }
+  
+  dbus_free_string_array (path);
+
+  return result;
+}
+
+/**
+ * Looks up the data passed to _dbus_object_tree_register() for a
+ * handler at the given path.
+ *
+ * @param tree the global object tree
+ * @param path NULL-terminated array of path elements giving path to subtree
+ * @returns the object's user_data or #NULL if none found
+ */
+void*
+_dbus_object_tree_get_user_data_unlocked (DBusObjectTree *tree,
+                                          const char    **path)
+{
+  dbus_bool_t exact_match;
+  DBusObjectSubtree *subtree;
+
+  _dbus_assert (tree != NULL);
+  _dbus_assert (path != NULL);
+  
+  /* Find the deepest path that covers the path in the message */
+  subtree = find_handler (tree, (const char**) path, &exact_match);
+
+  if ((subtree == NULL) || !exact_match)
+    {
+      _dbus_verbose ("No object at specified path found\n");
+      return NULL;
+    }
+
+  return subtree->user_data;
+}
+
+/**
+ * Allocates a subtree object.
+ *
+ * @param name name to duplicate.
+ * @returns newly-allocated subtree
+ */
+static DBusObjectSubtree*
+allocate_subtree_object (const char *name)
+{
+  int len;
+  DBusObjectSubtree *subtree;
+  const size_t front_padding = _DBUS_STRUCT_OFFSET (DBusObjectSubtree, name);
+
+  _dbus_assert (name != NULL);
+
+  len = strlen (name);
+
+  subtree = dbus_malloc0 (MAX (front_padding + (len + 1), sizeof (DBusObjectSubtree)));
+
+  if (subtree == NULL)
+    return NULL;
+
+  memcpy (subtree->name, name, len + 1);
+
+  return subtree;
+}
+
+static DBusObjectSubtree*
+_dbus_object_subtree_new (const char                  *name,
+                          const DBusObjectPathVTable  *vtable,
+                          void                        *user_data)
+{
+  DBusObjectSubtree *subtree;
+
+  subtree = allocate_subtree_object (name);
+  if (subtree == NULL)
+    goto oom;
+
+  _dbus_assert (name != NULL);
+
+  subtree->parent = NULL;
+
+  if (vtable)
+    {
+      subtree->message_function = vtable->message_function;
+      subtree->unregister_function = vtable->unregister_function;
+    }
+  else
+    {
+      subtree->message_function = NULL;
+      subtree->unregister_function = NULL;
+    }
+
+  subtree->user_data = user_data;
+  _dbus_atomic_inc (&subtree->refcount);
+  subtree->subtrees = NULL;
+  subtree->n_subtrees = 0;
+  subtree->max_subtrees = 0;
+  subtree->invoke_as_fallback = FALSE;
+
+  return subtree;
+
+ oom:
+  return NULL;
+}
+
+static DBusObjectSubtree *
+_dbus_object_subtree_ref (DBusObjectSubtree *subtree)
+{
+#ifdef DBUS_DISABLE_ASSERT
+  _dbus_atomic_inc (&subtree->refcount);
+#else
+  dbus_int32_t old_value;
+
+  old_value = _dbus_atomic_inc (&subtree->refcount);
+  _dbus_assert (old_value > 0);
+#endif
+
+  return subtree;
+}
+
+static void
+_dbus_object_subtree_unref (DBusObjectSubtree *subtree)
+{
+  dbus_int32_t old_value;
+
+  old_value = _dbus_atomic_dec (&subtree->refcount);
+  _dbus_assert (old_value > 0);
+
+  if (old_value == 1)
+    {
+      _dbus_assert (subtree->unregister_function == NULL);
+      _dbus_assert (subtree->message_function == NULL);
+
+      dbus_free (subtree->subtrees);
+      dbus_free (subtree);
+    }
+}
+
+/**
+ * Lists the registered fallback handlers and object path handlers at
+ * the given parent_path. The returned array should be freed with
+ * dbus_free_string_array().
+ *
+ * @param tree the object tree
+ * @param parent_path the path to list the child handlers of
+ * @param child_entries returns #NULL-terminated array of children
+ * @returns #FALSE if no memory to allocate the child entries
+ */
+dbus_bool_t
+_dbus_object_tree_list_registered_and_unlock (DBusObjectTree *tree,
+                                              const char    **parent_path,
+                                              char         ***child_entries)
+{
+  dbus_bool_t result;
+
+  result = _dbus_object_tree_list_registered_unlocked (tree,
+                                                       parent_path,
+                                                       child_entries);
+  
+#ifdef DBUS_BUILD_TESTS
+  if (tree->connection)
+#endif
+    {
+      _dbus_verbose ("unlock\n");
+      _dbus_connection_unlock (tree->connection);
+    }
+
+  return result;
+}
+
+
+/** Set to 1 to get a bunch of spew about disassembling the path string */
+#define VERBOSE_DECOMPOSE 0
+
+/**
+ * Decompose an object path.  A path of just "/" is
+ * represented as an empty vector of strings.
+ * The path need not be nul terminated.
+ * 
+ * @param data the path data
+ * @param len  the length of the path string
+ * @param path address to store new object path
+ * @param path_len length of stored path
+ */
+dbus_bool_t
+_dbus_decompose_path (const char*     data,
+                      int             len,
+                      char         ***path,
+                      int            *path_len)
+{
+  char **retval;
+  int n_components;
+  int i, j, comp;
+
+  _dbus_assert (data != NULL);
+  _dbus_assert (path != NULL);
+  
+#if VERBOSE_DECOMPOSE
+  _dbus_verbose ("Decomposing path \"%s\"\n",
+                 data);
+#endif
+  
+  n_components = 0;
+  if (len > 1) /* if path is not just "/" */
+    {
+      i = 0;
+      while (i < len)
+        {
+          _dbus_assert (data[i] != '\0');
+          if (data[i] == '/')
+            n_components += 1;
+          ++i;
+        }
+    }
+  
+  retval = dbus_new0 (char*, n_components + 1);
+
+  if (retval == NULL)
+    return FALSE;
+
+  comp = 0;
+  if (n_components == 0)
+    i = 1;
+  else
+    i = 0;
+  while (comp < n_components)
+    {
+      _dbus_assert (i < len);
+      
+      if (data[i] == '/')
+        ++i;
+      j = i;
+
+      while (j < len && data[j] != '/')
+        ++j;
+
+      /* Now [i, j) is the path component */
+      _dbus_assert (i < j);
+      _dbus_assert (data[i] != '/');
+      _dbus_assert (j == len || data[j] == '/');
+
+#if VERBOSE_DECOMPOSE
+      _dbus_verbose ("  (component in [%d,%d))\n",
+                     i, j);
+#endif
+      
+      retval[comp] = _dbus_memdup (&data[i], j - i + 1);
+      if (retval[comp] == NULL)
+        {
+          dbus_free_string_array (retval);
+          return FALSE;
+        }
+      retval[comp][j-i] = '\0';
+#if VERBOSE_DECOMPOSE
+      _dbus_verbose ("  (component %d = \"%s\")\n",
+                     comp, retval[comp]);
+#endif
+
+      ++comp;
+      i = j;
+    }
+  _dbus_assert (i == len);
+  
+  *path = retval;
+  if (path_len)
+    *path_len = n_components;
+  
+  return TRUE;
+}
+
+/** @} */
+
+static char*
+flatten_path (const char **path)
+{
+  DBusString str;
+  char *s;
+
+  if (!_dbus_string_init (&str))
+    return NULL;
+
+  if (path[0] == NULL)
+    {
+      if (!_dbus_string_append_byte (&str, '/'))
+        goto nomem;
+    }
+  else
+    {
+      int i;
+      
+      i = 0;
+      while (path[i])
+        {
+          if (!_dbus_string_append_byte (&str, '/'))
+            goto nomem;
+          
+          if (!_dbus_string_append (&str, path[i]))
+            goto nomem;
+          
+          ++i;
+        }
+    }
+
+  if (!_dbus_string_steal_data (&str, &s))
+    goto nomem;
+
+  _dbus_string_free (&str);
+
+  return s;
+
+ nomem:
+  _dbus_string_free (&str);
+  return NULL;
+}
+
+
+#ifdef DBUS_BUILD_TESTS
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include "dbus-test.h"
+#include <stdio.h>
+
+typedef enum 
+{
+  STR_EQUAL,
+  STR_PREFIX,
+  STR_DIFFERENT
+} StrComparison;
+
+/* Returns TRUE if container is a parent of child
+ */
+static StrComparison
+path_contains (const char **container,
+               const char **child)
+{
+  int i;
+
+  i = 0;
+  while (child[i] != NULL)
+    {
+      int v;
+
+      if (container[i] == NULL)
+        return STR_PREFIX; /* container ran out, child continues;
+                            * thus the container is a parent of the
+                            * child.
+                            */
+
+      _dbus_assert (container[i] != NULL);
+      _dbus_assert (child[i] != NULL);
+
+      v = strcmp (container[i], child[i]);
+
+      if (v != 0)
+        return STR_DIFFERENT; /* they overlap until here and then are different,
+                               * not overlapping
+                               */
+
+      ++i;
+    }
+
+  /* Child ran out; if container also did, they are equal;
+   * otherwise, the child is a parent of the container.
+   */
+  if (container[i] == NULL)
+    return STR_EQUAL;
+  else
+    return STR_DIFFERENT;
+}
+
+#if 0
+static void
+spew_subtree_recurse (DBusObjectSubtree *subtree,
+                      int                indent)
+{
+  int i;
+
+  i = 0;
+  while (i < indent)
+    {
+      _dbus_verbose (" ");
+      ++i;
+    }
+
+  _dbus_verbose ("%s (%d children)\n",
+                 subtree->name, subtree->n_subtrees);
+
+  i = 0;
+  while (i < subtree->n_subtrees)
+    {
+      spew_subtree_recurse (subtree->subtrees[i], indent + 2);
+
+      ++i;
+    }
+}
+
+static void
+spew_tree (DBusObjectTree *tree)
+{
+  spew_subtree_recurse (tree->root, 0);
+}
+#endif
+
+/**
+ * Callback data used in tests
+ */
+typedef struct
+{
+  const char **path; /**< Path */
+  dbus_bool_t handler_fallback; /**< true if the handler may be called as fallback */
+  dbus_bool_t message_handled; /**< Gets set to true if message handler called */
+  dbus_bool_t handler_unregistered; /**< gets set to true if handler is unregistered */
+} TreeTestData;
+
+
+static void
+test_unregister_function (DBusConnection  *connection,
+                          void            *user_data)
+{
+  TreeTestData *ttd = user_data;
+
+  ttd->handler_unregistered = TRUE;
+}
+
+static DBusHandlerResult
+test_message_function (DBusConnection  *connection,
+                       DBusMessage     *message,
+                       void            *user_data)
+{
+  TreeTestData *ttd = user_data;
+
+  ttd->message_handled = TRUE;
+
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static dbus_bool_t
+do_register (DBusObjectTree *tree,
+             const char    **path,
+             dbus_bool_t     fallback,
+             int             i,
+             TreeTestData   *tree_test_data)
+{
+  DBusObjectPathVTable vtable = { test_unregister_function,
+                                  test_message_function, NULL };
+
+  tree_test_data[i].message_handled = FALSE;
+  tree_test_data[i].handler_unregistered = FALSE;
+  tree_test_data[i].handler_fallback = fallback;
+  tree_test_data[i].path = path;
+
+  if (!_dbus_object_tree_register (tree, fallback, path,
+                                   &vtable,
+                                   &tree_test_data[i],
+                                   NULL))
+    return FALSE;
+
+  _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path) ==
+                &tree_test_data[i]);
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+do_test_dispatch (DBusObjectTree *tree,
+                  const char    **path,
+                  int             i,
+                  TreeTestData   *tree_test_data,
+                  int             n_test_data)
+{
+  DBusMessage *message;
+  int j;
+  DBusHandlerResult result;
+  char *flat;
+
+  message = NULL;
+  
+  flat = flatten_path (path);
+  if (flat == NULL)
+    goto oom;
+
+  message = dbus_message_new_method_call (NULL,
+                                          flat,
+                                          "org.freedesktop.TestInterface",
+                                          "Foo");
+  dbus_free (flat);
+  if (message == NULL)
+    goto oom;
+
+  j = 0;
+  while (j < n_test_data)
+    {
+      tree_test_data[j].message_handled = FALSE;
+      ++j;
+    }
+
+  result = _dbus_object_tree_dispatch_and_unlock (tree, message, NULL);
+  if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
+    goto oom;
+
+  _dbus_assert (tree_test_data[i].message_handled);
+
+  j = 0;
+  while (j < n_test_data)
+    {
+      if (tree_test_data[j].message_handled)
+	{
+	  if (tree_test_data[j].handler_fallback)
+	    _dbus_assert (path_contains (tree_test_data[j].path,
+					 path) != STR_DIFFERENT);
+	  else
+	    _dbus_assert (path_contains (tree_test_data[j].path, path) == STR_EQUAL);
+	}
+      else
+	{
+	  if (tree_test_data[j].handler_fallback)
+	    _dbus_assert (path_contains (tree_test_data[j].path,
+					 path) == STR_DIFFERENT);
+	  else
+	    _dbus_assert (path_contains (tree_test_data[j].path, path) != STR_EQUAL);
+	}
+
+      ++j;
+    }
+
+  dbus_message_unref (message);
+
+  return TRUE;
+
+ oom:
+  if (message)
+    dbus_message_unref (message);
+  return FALSE;
+}
+
+static size_t
+string_array_length (const char **array)
+{
+  size_t i;
+  for (i = 0; array[i]; i++) ;
+  return i;
+}
+
+typedef struct
+{
+  const char *path;
+  const char *result[20];
+} DecomposePathTest;
+
+static DecomposePathTest decompose_tests[] = {
+  { "/foo", { "foo", NULL } },
+  { "/foo/bar", { "foo", "bar", NULL } },
+  { "/", { NULL } },
+  { "/a/b", { "a", "b", NULL } },
+  { "/a/b/c", { "a", "b", "c", NULL } },
+  { "/a/b/c/d", { "a", "b", "c", "d", NULL } },
+  { "/foo/bar/q", { "foo", "bar", "q", NULL } },
+  { "/foo/bar/this/is/longer", { "foo", "bar", "this", "is", "longer", NULL } }
+};
+
+static dbus_bool_t
+run_decompose_tests (void)
+{
+  int i;
+
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (decompose_tests))
+    {
+      char **result;
+      int    result_len;
+      int    expected_len;
+
+      if (!_dbus_decompose_path (decompose_tests[i].path,
+                                 strlen (decompose_tests[i].path),
+                                 &result, &result_len))
+        return FALSE;
+
+      expected_len = string_array_length (decompose_tests[i].result);
+      
+      if (result_len != (int) string_array_length ((const char**)result) ||
+          expected_len != result_len ||
+          path_contains (decompose_tests[i].result,
+                         (const char**) result) != STR_EQUAL)
+        {
+          int real_len = string_array_length ((const char**)result);
+          _dbus_warn ("Expected decompose of %s to have len %d, returned %d, appears to have %d\n",
+                      decompose_tests[i].path, expected_len, result_len,
+                      real_len);
+          _dbus_warn ("Decompose resulted in elements: { ");
+          i = 0;
+          while (i < real_len)
+            {
+              _dbus_warn ("\"%s\"%s", result[i],
+                          (i + 1) == real_len ? "" : ", ");
+              ++i;
+            }
+          _dbus_warn ("}\n");
+          _dbus_assert_not_reached ("path decompose failed\n");
+        }
+
+      dbus_free_string_array (result);
+
+      ++i;
+    }
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+object_tree_test_iteration (void *data)
+{
+  const char *path0[] = { NULL };
+  const char *path1[] = { "foo", NULL };
+  const char *path2[] = { "foo", "bar", NULL };
+  const char *path3[] = { "foo", "bar", "baz", NULL };
+  const char *path4[] = { "foo", "bar", "boo", NULL };
+  const char *path5[] = { "blah", NULL };
+  const char *path6[] = { "blah", "boof", NULL };
+  const char *path7[] = { "blah", "boof", "this", "is", "really", "long", NULL };
+  const char *path8[] = { "childless", NULL };
+  DBusObjectTree *tree;
+  TreeTestData tree_test_data[9];
+  int i;
+  dbus_bool_t exact_match;
+
+  if (!run_decompose_tests ())
+    return FALSE;
+  
+  tree = NULL;
+
+  tree = _dbus_object_tree_new (NULL);
+  if (tree == NULL)
+    goto out;
+
+  if (!do_register (tree, path0, TRUE, 0, tree_test_data))
+    goto out;
+
+  _dbus_assert (find_subtree (tree, path0, NULL));
+  _dbus_assert (!find_subtree (tree, path1, NULL));
+  _dbus_assert (!find_subtree (tree, path2, NULL));
+  _dbus_assert (!find_subtree (tree, path3, NULL));
+  _dbus_assert (!find_subtree (tree, path4, NULL));
+  _dbus_assert (!find_subtree (tree, path5, NULL));
+  _dbus_assert (!find_subtree (tree, path6, NULL));
+  _dbus_assert (!find_subtree (tree, path7, NULL));
+  _dbus_assert (!find_subtree (tree, path8, NULL));
+
+  _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match);
+  _dbus_assert (find_handler (tree, path1, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path2, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path3, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path4, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
+  
+  if (!do_register (tree, path1, TRUE, 1, tree_test_data))
+    goto out;
+
+  _dbus_assert (find_subtree (tree, path0, NULL));
+  _dbus_assert (find_subtree (tree, path1, NULL));
+  _dbus_assert (!find_subtree (tree, path2, NULL));
+  _dbus_assert (!find_subtree (tree, path3, NULL));
+  _dbus_assert (!find_subtree (tree, path4, NULL));
+  _dbus_assert (!find_subtree (tree, path5, NULL));
+  _dbus_assert (!find_subtree (tree, path6, NULL));
+  _dbus_assert (!find_subtree (tree, path7, NULL));
+  _dbus_assert (!find_subtree (tree, path8, NULL));
+
+  _dbus_assert (find_handler (tree, path0, &exact_match) &&  exact_match);
+  _dbus_assert (find_handler (tree, path1, &exact_match) &&  exact_match);
+  _dbus_assert (find_handler (tree, path2, &exact_match) && !exact_match);
+  _dbus_assert (find_handler (tree, path3, &exact_match) && !exact_match);
+  _dbus_assert (find_handler (tree, path4, &exact_match) && !exact_match);
+  _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
+
+  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
+    goto out;
+
+  _dbus_assert (find_subtree (tree, path1, NULL));
+  _dbus_assert (find_subtree (tree, path2, NULL));
+  _dbus_assert (!find_subtree (tree, path3, NULL));
+  _dbus_assert (!find_subtree (tree, path4, NULL));
+  _dbus_assert (!find_subtree (tree, path5, NULL));
+  _dbus_assert (!find_subtree (tree, path6, NULL));
+  _dbus_assert (!find_subtree (tree, path7, NULL));
+  _dbus_assert (!find_subtree (tree, path8, NULL));
+
+  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
+    goto out;
+
+  _dbus_assert (find_subtree (tree, path0, NULL));
+  _dbus_assert (find_subtree (tree, path1, NULL));
+  _dbus_assert (find_subtree (tree, path2, NULL));
+  _dbus_assert (find_subtree (tree, path3, NULL));
+  _dbus_assert (!find_subtree (tree, path4, NULL));
+  _dbus_assert (!find_subtree (tree, path5, NULL));
+  _dbus_assert (!find_subtree (tree, path6, NULL));
+  _dbus_assert (!find_subtree (tree, path7, NULL));
+  _dbus_assert (!find_subtree (tree, path8, NULL));
+  
+  if (!do_register (tree, path4, TRUE, 4, tree_test_data))
+    goto out;
+
+  _dbus_assert (find_subtree (tree, path0, NULL));
+  _dbus_assert (find_subtree (tree, path1, NULL));
+  _dbus_assert (find_subtree (tree, path2, NULL));
+  _dbus_assert (find_subtree (tree, path3, NULL));  
+  _dbus_assert (find_subtree (tree, path4, NULL));
+  _dbus_assert (!find_subtree (tree, path5, NULL));
+  _dbus_assert (!find_subtree (tree, path6, NULL));
+  _dbus_assert (!find_subtree (tree, path7, NULL));
+  _dbus_assert (!find_subtree (tree, path8, NULL));
+  
+  if (!do_register (tree, path5, TRUE, 5, tree_test_data))
+    goto out;
+
+  _dbus_assert (find_subtree (tree, path0, NULL));
+  _dbus_assert (find_subtree (tree, path1, NULL));
+  _dbus_assert (find_subtree (tree, path2, NULL));
+  _dbus_assert (find_subtree (tree, path3, NULL));
+  _dbus_assert (find_subtree (tree, path4, NULL));
+  _dbus_assert (find_subtree (tree, path5, NULL));
+  _dbus_assert (!find_subtree (tree, path6, NULL));
+  _dbus_assert (!find_subtree (tree, path7, NULL));
+  _dbus_assert (!find_subtree (tree, path8, NULL));
+
+  _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root &&  exact_match);
+  _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root &&  exact_match);
+  _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root &&  exact_match);
+  _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root &&  exact_match);
+  _dbus_assert (find_handler (tree, path4, &exact_match) != tree->root &&  exact_match);
+  _dbus_assert (find_handler (tree, path5, &exact_match) != tree->root &&  exact_match);
+  _dbus_assert (find_handler (tree, path6, &exact_match) != tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && !exact_match);
+  _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
+
+  if (!do_register (tree, path6, TRUE, 6, tree_test_data))
+    goto out;
+
+  _dbus_assert (find_subtree (tree, path0, NULL));
+  _dbus_assert (find_subtree (tree, path1, NULL));
+  _dbus_assert (find_subtree (tree, path2, NULL));
+  _dbus_assert (find_subtree (tree, path3, NULL));
+  _dbus_assert (find_subtree (tree, path4, NULL));
+  _dbus_assert (find_subtree (tree, path5, NULL));
+  _dbus_assert (find_subtree (tree, path6, NULL));
+  _dbus_assert (!find_subtree (tree, path7, NULL));
+  _dbus_assert (!find_subtree (tree, path8, NULL));
+
+  if (!do_register (tree, path7, TRUE, 7, tree_test_data))
+    goto out;
+
+  _dbus_assert (find_subtree (tree, path0, NULL));
+  _dbus_assert (find_subtree (tree, path1, NULL));
+  _dbus_assert (find_subtree (tree, path2, NULL));
+  _dbus_assert (find_subtree (tree, path3, NULL));
+  _dbus_assert (find_subtree (tree, path4, NULL));
+  _dbus_assert (find_subtree (tree, path5, NULL));
+  _dbus_assert (find_subtree (tree, path6, NULL));
+  _dbus_assert (find_subtree (tree, path7, NULL));
+  _dbus_assert (!find_subtree (tree, path8, NULL));
+
+  if (!do_register (tree, path8, TRUE, 8, tree_test_data))
+    goto out;
+
+  _dbus_assert (find_subtree (tree, path0, NULL));
+  _dbus_assert (find_subtree (tree, path1, NULL));
+  _dbus_assert (find_subtree (tree, path2, NULL));
+  _dbus_assert (find_subtree (tree, path3, NULL));
+  _dbus_assert (find_subtree (tree, path4, NULL));
+  _dbus_assert (find_subtree (tree, path5, NULL));
+  _dbus_assert (find_subtree (tree, path6, NULL));
+  _dbus_assert (find_subtree (tree, path7, NULL));
+  _dbus_assert (find_subtree (tree, path8, NULL));
+
+  _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root &&  exact_match);
+  _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match);
+  _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match);
+  _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match);
+  _dbus_assert (find_handler (tree, path4, &exact_match) != tree->root && exact_match);
+  _dbus_assert (find_handler (tree, path5, &exact_match) != tree->root && exact_match);
+  _dbus_assert (find_handler (tree, path6, &exact_match) != tree->root && exact_match);
+  _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && exact_match);
+  _dbus_assert (find_handler (tree, path8, &exact_match) != tree->root && exact_match);
+  
+  /* test the list_registered function */
+
+  {
+    const char *root[] = { NULL };
+    char **child_entries;
+    int nb;
+
+    _dbus_object_tree_list_registered_unlocked (tree, path1, &child_entries);
+    if (child_entries != NULL)
+      {
+	nb = string_array_length ((const char**)child_entries);
+	_dbus_assert (nb == 1);
+	dbus_free_string_array (child_entries);
+      }
+
+    _dbus_object_tree_list_registered_unlocked (tree, path2, &child_entries);
+    if (child_entries != NULL)
+      {
+	nb = string_array_length ((const char**)child_entries);
+	_dbus_assert (nb == 2);
+	dbus_free_string_array (child_entries);
+      }
+
+    _dbus_object_tree_list_registered_unlocked (tree, path8, &child_entries);
+    if (child_entries != NULL)
+      {
+	nb = string_array_length ((const char**)child_entries);
+	_dbus_assert (nb == 0);
+	dbus_free_string_array (child_entries);
+      }
+
+    _dbus_object_tree_list_registered_unlocked (tree, root, &child_entries);
+    if (child_entries != NULL)
+      {
+	nb = string_array_length ((const char**)child_entries);
+	_dbus_assert (nb == 3);
+	dbus_free_string_array (child_entries);
+      }
+  }
+
+  /* Check that destroying tree calls unregister funcs */
+  _dbus_object_tree_unref (tree);
+
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (tree_test_data))
+    {
+      _dbus_assert (tree_test_data[i].handler_unregistered);
+      _dbus_assert (!tree_test_data[i].message_handled);
+      ++i;
+    }
+
+  /* Now start again and try the individual unregister function */
+  tree = _dbus_object_tree_new (NULL);
+  if (tree == NULL)
+    goto out;
+
+  if (!do_register (tree, path0, TRUE, 0, tree_test_data))
+    goto out;
+  if (!do_register (tree, path1, TRUE, 1, tree_test_data))
+    goto out;
+  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
+    goto out;
+  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
+    goto out;
+  if (!do_register (tree, path4, TRUE, 4, tree_test_data))
+    goto out;
+  if (!do_register (tree, path5, TRUE, 5, tree_test_data))
+    goto out;
+  if (!do_register (tree, path6, TRUE, 6, tree_test_data))
+    goto out;
+  if (!do_register (tree, path7, TRUE, 7, tree_test_data))
+    goto out;
+  if (!do_register (tree, path8, TRUE, 8, tree_test_data))
+    goto out;
+
+  _dbus_object_tree_unregister_and_unlock (tree, path0);
+  _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path0) == NULL);
+
+  _dbus_assert (!find_subtree (tree, path0, NULL));
+  _dbus_assert (find_subtree (tree, path1, NULL));
+  _dbus_assert (find_subtree (tree, path2, NULL));
+  _dbus_assert (find_subtree (tree, path3, NULL));
+  _dbus_assert (find_subtree (tree, path4, NULL));
+  _dbus_assert (find_subtree (tree, path5, NULL));
+  _dbus_assert (find_subtree (tree, path6, NULL));
+  _dbus_assert (find_subtree (tree, path7, NULL));
+  _dbus_assert (find_subtree (tree, path8, NULL));
+  
+  _dbus_object_tree_unregister_and_unlock (tree, path1);
+  _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path1) == NULL);
+
+  _dbus_assert (!find_subtree (tree, path0, NULL));
+  _dbus_assert (!find_subtree (tree, path1, NULL));
+  _dbus_assert (find_subtree (tree, path2, NULL));
+  _dbus_assert (find_subtree (tree, path3, NULL));
+  _dbus_assert (find_subtree (tree, path4, NULL));
+  _dbus_assert (find_subtree (tree, path5, NULL));
+  _dbus_assert (find_subtree (tree, path6, NULL));
+  _dbus_assert (find_subtree (tree, path7, NULL));
+  _dbus_assert (find_subtree (tree, path8, NULL));
+
+  _dbus_object_tree_unregister_and_unlock (tree, path2);
+  _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path2) == NULL);
+
+  _dbus_assert (!find_subtree (tree, path0, NULL));
+  _dbus_assert (!find_subtree (tree, path1, NULL));
+  _dbus_assert (!find_subtree (tree, path2, NULL));
+  _dbus_assert (find_subtree (tree, path3, NULL));
+  _dbus_assert (find_subtree (tree, path4, NULL));
+  _dbus_assert (find_subtree (tree, path5, NULL));
+  _dbus_assert (find_subtree (tree, path6, NULL));
+  _dbus_assert (find_subtree (tree, path7, NULL));
+  _dbus_assert (find_subtree (tree, path8, NULL));
+  
+  _dbus_object_tree_unregister_and_unlock (tree, path3);
+  _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path3) == NULL);
+
+  _dbus_assert (!find_subtree (tree, path0, NULL));
+  _dbus_assert (!find_subtree (tree, path1, NULL));
+  _dbus_assert (!find_subtree (tree, path2, NULL));
+  _dbus_assert (!find_subtree (tree, path3, NULL));
+  _dbus_assert (find_subtree (tree, path4, NULL));
+  _dbus_assert (find_subtree (tree, path5, NULL));
+  _dbus_assert (find_subtree (tree, path6, NULL));
+  _dbus_assert (find_subtree (tree, path7, NULL));
+  _dbus_assert (find_subtree (tree, path8, NULL));
+  
+  _dbus_object_tree_unregister_and_unlock (tree, path4);
+  _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path4) == NULL);
+
+  _dbus_assert (!find_subtree (tree, path0, NULL));
+  _dbus_assert (!find_subtree (tree, path1, NULL));
+  _dbus_assert (!find_subtree (tree, path2, NULL));
+  _dbus_assert (!find_subtree (tree, path3, NULL));
+  _dbus_assert (!find_subtree (tree, path4, NULL));
+  _dbus_assert (find_subtree (tree, path5, NULL));
+  _dbus_assert (find_subtree (tree, path6, NULL));
+  _dbus_assert (find_subtree (tree, path7, NULL));
+  _dbus_assert (find_subtree (tree, path8, NULL));
+  
+  _dbus_object_tree_unregister_and_unlock (tree, path5);
+  _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path5) == NULL);
+
+  _dbus_assert (!find_subtree (tree, path0, NULL));
+  _dbus_assert (!find_subtree (tree, path1, NULL));
+  _dbus_assert (!find_subtree (tree, path2, NULL));
+  _dbus_assert (!find_subtree (tree, path3, NULL));
+  _dbus_assert (!find_subtree (tree, path4, NULL));
+  _dbus_assert (!find_subtree (tree, path5, NULL));
+  _dbus_assert (find_subtree (tree, path6, NULL));
+  _dbus_assert (find_subtree (tree, path7, NULL));
+  _dbus_assert (find_subtree (tree, path8, NULL));
+  
+  _dbus_object_tree_unregister_and_unlock (tree, path6);
+  _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path6) == NULL);
+
+  _dbus_assert (!find_subtree (tree, path0, NULL));
+  _dbus_assert (!find_subtree (tree, path1, NULL));
+  _dbus_assert (!find_subtree (tree, path2, NULL));
+  _dbus_assert (!find_subtree (tree, path3, NULL));
+  _dbus_assert (!find_subtree (tree, path4, NULL));
+  _dbus_assert (!find_subtree (tree, path5, NULL));
+  _dbus_assert (!find_subtree (tree, path6, NULL));
+  _dbus_assert (find_subtree (tree, path7, NULL));
+  _dbus_assert (find_subtree (tree, path8, NULL));
+
+  _dbus_object_tree_unregister_and_unlock (tree, path7);
+  _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path7) == NULL);
+
+  _dbus_assert (!find_subtree (tree, path0, NULL));
+  _dbus_assert (!find_subtree (tree, path1, NULL));
+  _dbus_assert (!find_subtree (tree, path2, NULL));
+  _dbus_assert (!find_subtree (tree, path3, NULL));
+  _dbus_assert (!find_subtree (tree, path4, NULL));
+  _dbus_assert (!find_subtree (tree, path5, NULL));
+  _dbus_assert (!find_subtree (tree, path6, NULL));
+  _dbus_assert (!find_subtree (tree, path7, NULL));
+  _dbus_assert (find_subtree (tree, path8, NULL));
+
+  _dbus_object_tree_unregister_and_unlock (tree, path8);
+  _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path8) == NULL);
+
+  _dbus_assert (!find_subtree (tree, path0, NULL));
+  _dbus_assert (!find_subtree (tree, path1, NULL));
+  _dbus_assert (!find_subtree (tree, path2, NULL));
+  _dbus_assert (!find_subtree (tree, path3, NULL));
+  _dbus_assert (!find_subtree (tree, path4, NULL));
+  _dbus_assert (!find_subtree (tree, path5, NULL));
+  _dbus_assert (!find_subtree (tree, path6, NULL));
+  _dbus_assert (!find_subtree (tree, path7, NULL));
+  _dbus_assert (!find_subtree (tree, path8, NULL));
+  
+  i = 0;
+  while (i < (int) _DBUS_N_ELEMENTS (tree_test_data))
+    {
+      _dbus_assert (tree_test_data[i].handler_unregistered);
+      _dbus_assert (!tree_test_data[i].message_handled);
+      ++i;
+    }
+
+  /* Register it all again, and test dispatch */
+  
+  if (!do_register (tree, path0, TRUE, 0, tree_test_data))
+    goto out;
+  if (!do_register (tree, path1, FALSE, 1, tree_test_data))
+    goto out;
+  if (!do_register (tree, path2, TRUE, 2, tree_test_data))
+    goto out;
+  if (!do_register (tree, path3, TRUE, 3, tree_test_data))
+    goto out;
+  if (!do_register (tree, path4, TRUE, 4, tree_test_data))
+    goto out;
+  if (!do_register (tree, path5, TRUE, 5, tree_test_data))
+    goto out;
+  if (!do_register (tree, path6, FALSE, 6, tree_test_data))
+    goto out;
+  if (!do_register (tree, path7, TRUE, 7, tree_test_data))
+    goto out;
+  if (!do_register (tree, path8, TRUE, 8, tree_test_data))
+    goto out;
+
+#if 0
+  spew_tree (tree);
+#endif
+
+  if (!do_test_dispatch (tree, path0, 0, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+    goto out;
+  if (!do_test_dispatch (tree, path1, 1, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+    goto out;
+  if (!do_test_dispatch (tree, path2, 2, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+    goto out;
+  if (!do_test_dispatch (tree, path3, 3, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+    goto out;
+  if (!do_test_dispatch (tree, path4, 4, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+    goto out;
+  if (!do_test_dispatch (tree, path5, 5, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+    goto out;
+  if (!do_test_dispatch (tree, path6, 6, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+    goto out;
+  if (!do_test_dispatch (tree, path7, 7, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+    goto out;
+  if (!do_test_dispatch (tree, path8, 8, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
+    goto out;
+  
+ out:
+  if (tree)
+    {
+      /* test ref */
+      _dbus_object_tree_ref (tree);
+      _dbus_object_tree_unref (tree);
+      _dbus_object_tree_unref (tree);
+    }
+
+  return TRUE;
+}
+
+/**
+ * @ingroup DBusObjectTree
+ * Unit test for DBusObjectTree
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_object_tree_test (void)
+{
+  _dbus_test_oom_handling ("object tree",
+                           object_tree_test_iteration,
+                           NULL);
+
+  return TRUE;
+}
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-object-tree.h b/dbus/dbus/dbus-object-tree.h
new file mode 100644
index 0000000..5576c25
--- /dev/null
+++ b/dbus/dbus/dbus-object-tree.h
@@ -0,0 +1,63 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-object-tree.h  DBusObjectTree (internals of DBusConnection)
+ *
+ * Copyright (C) 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_OBJECT_TREE_H
+#define DBUS_OBJECT_TREE_H
+
+#include <dbus/dbus-connection.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusObjectTree DBusObjectTree;
+
+DBusObjectTree* _dbus_object_tree_new   (DBusConnection *connection);
+DBusObjectTree* _dbus_object_tree_ref   (DBusObjectTree *tree);
+void            _dbus_object_tree_unref (DBusObjectTree *tree);
+
+dbus_bool_t       _dbus_object_tree_register               (DBusObjectTree              *tree,
+                                                            dbus_bool_t                  fallback,
+                                                            const char                 **path,
+                                                            const DBusObjectPathVTable  *vtable,
+                                                            void                        *user_data,
+                                                            DBusError                   *error);
+void              _dbus_object_tree_unregister_and_unlock  (DBusObjectTree              *tree,
+                                                            const char                 **path);
+DBusHandlerResult _dbus_object_tree_dispatch_and_unlock    (DBusObjectTree              *tree,
+                                                            DBusMessage                 *message,
+                                                            dbus_bool_t                 *found_object);
+void*             _dbus_object_tree_get_user_data_unlocked (DBusObjectTree              *tree,
+                                                            const char                 **path);
+void              _dbus_object_tree_free_all_unlocked      (DBusObjectTree              *tree);
+
+
+dbus_bool_t _dbus_object_tree_list_registered_and_unlock (DBusObjectTree *tree,
+                                                          const char    **parent_path,
+                                                          char         ***child_entries);
+
+dbus_bool_t _dbus_decompose_path (const char   *data,
+                                  int           len,
+                                  char       ***path,
+                                  int          *path_len);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_OBJECT_TREE_H */
diff --git a/dbus/dbus/dbus-pending-call-internal.h b/dbus/dbus/dbus-pending-call-internal.h
new file mode 100644
index 0000000..1875eea
--- /dev/null
+++ b/dbus/dbus/dbus-pending-call-internal.h
@@ -0,0 +1,67 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-pending-call-internal.h DBusPendingCall internal interfaces
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_PENDING_CALL_INTERNAL_H
+#define DBUS_PENDING_CALL_INTERNAL_H
+
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-message.h>
+#include <dbus/dbus-connection.h>
+#include <dbus/dbus-list.h>
+
+DBUS_BEGIN_DECLS
+
+dbus_bool_t      _dbus_pending_call_is_timeout_added_unlocked    (DBusPendingCall    *pending);
+void             _dbus_pending_call_set_timeout_added_unlocked   (DBusPendingCall    *pending,
+                                                                  dbus_bool_t         is_added);
+DBusTimeout    * _dbus_pending_call_get_timeout_unlocked         (DBusPendingCall    *pending);
+dbus_uint32_t    _dbus_pending_call_get_reply_serial_unlocked    (DBusPendingCall    *pending);
+void             _dbus_pending_call_set_reply_serial_unlocked    (DBusPendingCall    *pending,
+                                                                  dbus_uint32_t       serial);
+DBusConnection * _dbus_pending_call_get_connection_and_lock      (DBusPendingCall    *pending);
+DBusConnection * _dbus_pending_call_get_connection_unlocked      (DBusPendingCall    *pending);
+dbus_bool_t      _dbus_pending_call_get_completed_unlocked       (DBusPendingCall    *pending);
+void             _dbus_pending_call_complete                     (DBusPendingCall    *pending);
+void             _dbus_pending_call_set_reply_unlocked           (DBusPendingCall    *pending,
+                                                                  DBusMessage        *message);
+void             _dbus_pending_call_queue_timeout_error_unlocked (DBusPendingCall    *pending,
+                                                                  DBusConnection     *connection);
+void             _dbus_pending_call_set_reply_serial_unlocked    (DBusPendingCall    *pending,
+                                                                  dbus_uint32_t       serial);
+dbus_bool_t      _dbus_pending_call_set_timeout_error_unlocked   (DBusPendingCall    *pending,
+                                                                  DBusMessage        *message,
+                                                                  dbus_uint32_t       serial);
+DBusPendingCall* _dbus_pending_call_new_unlocked                 (DBusConnection     *connection,
+                                                                  int                 timeout_milliseconds,
+                                                                  DBusTimeoutHandler  timeout_handler);
+DBusPendingCall* _dbus_pending_call_ref_unlocked                 (DBusPendingCall    *pending);
+void             _dbus_pending_call_unref_and_unlock             (DBusPendingCall    *pending);
+dbus_bool_t      _dbus_pending_call_set_data_unlocked            (DBusPendingCall    *pending,
+                                                                  dbus_int32_t        slot,
+                                                                  void               *data,
+                                                                  DBusFreeFunction    free_data_func);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_PENDING_CALL_INTERNAL_H */
diff --git a/dbus/dbus/dbus-pending-call.c b/dbus/dbus/dbus-pending-call.c
new file mode 100644
index 0000000..62c6c74
--- /dev/null
+++ b/dbus/dbus/dbus-pending-call.c
@@ -0,0 +1,851 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-pending-call.c Object representing a call in progress.
+ *
+ * Copyright (C) 2002, 2003 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-connection-internal.h"
+#include "dbus-message-internal.h"
+#include "dbus-pending-call-internal.h"
+#include "dbus-pending-call.h"
+#include "dbus-list.h"
+#include "dbus-threads.h"
+#include "dbus-test.h"
+
+/**
+ * @defgroup DBusPendingCallInternals DBusPendingCall implementation details
+ * @ingroup DBusInternals
+ * @brief DBusPendingCall private implementation details.
+ *
+ * The guts of DBusPendingCall and its methods.
+ *
+ * @{
+ */
+
+/**
+ * @brief Internals of DBusPendingCall
+ *
+ * Opaque object representing a reply message that we're waiting for.
+ */
+
+/**
+ * shorter and more visible way to write _dbus_connection_lock()
+ */
+#define CONNECTION_LOCK(connection)   _dbus_connection_lock(connection)
+/**
+ * shorter and more visible way to write _dbus_connection_unlock()
+ */
+#define CONNECTION_UNLOCK(connection) _dbus_connection_unlock(connection)
+
+/**
+ * Implementation details of #DBusPendingCall - all fields are private.
+ */
+struct DBusPendingCall
+{
+  DBusAtomic refcount;                            /**< reference count */
+
+  DBusDataSlotList slot_list;                     /**< Data stored by allocated integer ID */
+  
+  DBusPendingCallNotifyFunction function;         /**< Notifier when reply arrives. */
+
+  DBusConnection *connection;                     /**< Connections we're associated with */
+  DBusMessage *reply;                             /**< Reply (after we've received it) */
+  DBusTimeout *timeout;                           /**< Timeout */
+
+  DBusList *timeout_link;                         /**< Preallocated timeout response */
+  
+  dbus_uint32_t reply_serial;                     /**< Expected serial of reply */
+
+  unsigned int completed : 1;                     /**< TRUE if completed */
+  unsigned int timeout_added : 1;                 /**< Have added the timeout */
+};
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+static void
+_dbus_pending_call_trace_ref (DBusPendingCall *pending_call,
+    int old_refcount,
+    int new_refcount,
+    const char *why)
+{
+  static int enabled = -1;
+
+  _dbus_trace_ref ("DBusPendingCall", pending_call, old_refcount,
+      new_refcount, why, "DBUS_PENDING_CALL_TRACE", &enabled);
+}
+#else
+#define _dbus_pending_call_trace_ref(p, o, n, w) \
+  do \
+  {\
+    (void) (o); \
+    (void) (n); \
+  } while (0)
+#endif
+
+static dbus_int32_t notify_user_data_slot = -1;
+
+/**
+ * Creates a new pending reply object.
+ *
+ * @param connection connection where reply will arrive
+ * @param timeout_milliseconds length of timeout, -1 (or
+ *  #DBUS_TIMEOUT_USE_DEFAULT) for default,
+ *  #DBUS_TIMEOUT_INFINITE for no timeout
+ * @param timeout_handler timeout handler, takes pending call as data
+ * @returns a new #DBusPendingCall or #NULL if no memory.
+ */
+DBusPendingCall*
+_dbus_pending_call_new_unlocked (DBusConnection    *connection,
+                                 int                timeout_milliseconds,
+                                 DBusTimeoutHandler timeout_handler)
+{
+  DBusPendingCall *pending;
+  DBusTimeout *timeout;
+
+  _dbus_assert (timeout_milliseconds >= 0 || timeout_milliseconds == -1);
+ 
+  if (timeout_milliseconds == -1)
+    timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
+
+  if (!dbus_pending_call_allocate_data_slot (&notify_user_data_slot))
+    return NULL;
+  
+  pending = dbus_new0 (DBusPendingCall, 1);
+  
+  if (pending == NULL)
+    {
+      dbus_pending_call_free_data_slot (&notify_user_data_slot);
+      return NULL;
+    }
+
+  if (timeout_milliseconds != DBUS_TIMEOUT_INFINITE)
+    {
+      timeout = _dbus_timeout_new (timeout_milliseconds,
+                                   timeout_handler,
+                                   pending, NULL);  
+
+      if (timeout == NULL)
+        {
+          dbus_pending_call_free_data_slot (&notify_user_data_slot);
+          dbus_free (pending);
+          return NULL;
+        }
+
+      pending->timeout = timeout;
+    }
+  else
+    {
+      pending->timeout = NULL;
+    }
+
+  _dbus_atomic_inc (&pending->refcount);
+  pending->connection = connection;
+  _dbus_connection_ref_unlocked (pending->connection);
+
+  _dbus_data_slot_list_init (&pending->slot_list);
+
+  _dbus_pending_call_trace_ref (pending, 0, 1, "new_unlocked");
+
+  return pending;
+}
+
+/**
+ * Sets the reply of a pending call with the given message,
+ * or if the message is #NULL, by timing out the pending call.
+ * 
+ * @param pending the pending call
+ * @param message the message to complete the call with, or #NULL
+ *  to time out the call
+ */
+void
+_dbus_pending_call_set_reply_unlocked (DBusPendingCall *pending,
+                                       DBusMessage     *message)
+{
+  if (message == NULL)
+    {
+      message = pending->timeout_link->data;
+      _dbus_list_clear (&pending->timeout_link);
+    }
+  else
+    dbus_message_ref (message);
+
+  _dbus_verbose ("  handing message %p (%s) to pending call serial %u\n",
+                 message,
+                 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
+                 "method return" :
+                 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
+                 "error" : "other type",
+                 pending->reply_serial);
+  
+  _dbus_assert (pending->reply == NULL);
+  _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
+  pending->reply = message;
+}
+
+/**
+ * Calls notifier function for the pending call
+ * and sets the call to completed.
+ *
+ * @param pending the pending call
+ * 
+ */
+void
+_dbus_pending_call_complete (DBusPendingCall *pending)
+{
+  _dbus_assert (!pending->completed);
+  
+  pending->completed = TRUE;
+
+  if (pending->function)
+    {
+      void *user_data;
+      user_data = dbus_pending_call_get_data (pending,
+                                              notify_user_data_slot);
+      
+      (* pending->function) (pending, user_data);
+    }
+}
+
+/**
+ * If the pending call hasn't been timed out, add its timeout
+ * error reply to the connection's incoming message queue.
+ *
+ * @param pending the pending call
+ * @param connection the connection the call was sent to
+ */
+void
+_dbus_pending_call_queue_timeout_error_unlocked (DBusPendingCall *pending, 
+                                                 DBusConnection  *connection)
+{
+  _dbus_assert (connection == pending->connection);
+  
+  if (pending->timeout_link)
+    {
+      _dbus_connection_queue_synthesized_message_link (connection,
+						       pending->timeout_link);
+      pending->timeout_link = NULL;
+    }
+}
+
+/**
+ * Checks to see if a timeout has been added
+ *
+ * @param pending the pending_call
+ * @returns #TRUE if there is a timeout or #FALSE if not
+ */
+dbus_bool_t 
+_dbus_pending_call_is_timeout_added_unlocked (DBusPendingCall  *pending)
+{
+  _dbus_assert (pending != NULL);
+
+  return pending->timeout_added;
+}
+
+
+/**
+ * Sets wether the timeout has been added
+ *
+ * @param pending the pending_call
+ * @param is_added whether or not a timeout is added
+ */
+void
+_dbus_pending_call_set_timeout_added_unlocked (DBusPendingCall  *pending,
+                                               dbus_bool_t       is_added)
+{
+  _dbus_assert (pending != NULL);
+
+  pending->timeout_added = is_added;
+}
+
+
+/**
+ * Retrives the timeout
+ *
+ * @param pending the pending_call
+ * @returns a timeout object or NULL if call has no timeout
+ */
+DBusTimeout *
+_dbus_pending_call_get_timeout_unlocked (DBusPendingCall  *pending)
+{
+  _dbus_assert (pending != NULL);
+
+  return pending->timeout;
+}
+
+/**
+ * Gets the reply's serial number
+ *
+ * @param pending the pending_call
+ * @returns a serial number for the reply or 0 
+ */
+dbus_uint32_t 
+_dbus_pending_call_get_reply_serial_unlocked (DBusPendingCall  *pending)
+{
+  _dbus_assert (pending != NULL);
+
+  return pending->reply_serial;
+}
+
+/**
+ * Sets the reply's serial number
+ *
+ * @param pending the pending_call
+ * @param serial the serial number 
+ */
+void
+_dbus_pending_call_set_reply_serial_unlocked  (DBusPendingCall *pending,
+                                               dbus_uint32_t serial)
+{
+  _dbus_assert (pending != NULL);
+  _dbus_assert (pending->reply_serial == 0);
+
+  pending->reply_serial = serial;
+}
+
+/**
+ * Gets the connection associated with this pending call.
+ *
+ * @param pending the pending_call
+ * @returns the connection associated with the pending call
+ */
+DBusConnection *
+_dbus_pending_call_get_connection_and_lock (DBusPendingCall *pending)
+{
+  _dbus_assert (pending != NULL);
+ 
+  CONNECTION_LOCK (pending->connection);
+  return pending->connection;
+}
+
+/**
+ * Gets the connection associated with this pending call.
+ *
+ * @param pending the pending_call
+ * @returns the connection associated with the pending call
+ */
+DBusConnection *
+_dbus_pending_call_get_connection_unlocked (DBusPendingCall *pending)
+{
+  _dbus_assert (pending != NULL);
+ 
+  return pending->connection;
+}
+
+/**
+ * Sets the reply message associated with the pending call to a timeout error
+ *
+ * @param pending the pending_call
+ * @param message the message we are sending the error reply to 
+ * @param serial serial number for the reply
+ * @return #FALSE on OOM
+ */
+dbus_bool_t
+_dbus_pending_call_set_timeout_error_unlocked (DBusPendingCall *pending,
+                                               DBusMessage     *message,
+                                               dbus_uint32_t    serial)
+{ 
+  DBusList *reply_link;
+  DBusMessage *reply;
+
+  reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
+                                  "Did not receive a reply. Possible causes include: "
+                                  "the remote application did not send a reply, "
+                                  "the message bus security policy blocked the reply, "
+                                  "the reply timeout expired, or "
+                                  "the network connection was broken.");
+  if (reply == NULL)
+    return FALSE;
+
+  reply_link = _dbus_list_alloc_link (reply);
+  if (reply_link == NULL)
+    {
+      /* it's OK to unref this, nothing that could have attached a callback
+       * has ever seen it */
+      dbus_message_unref (reply);
+      return FALSE;
+    }
+
+  pending->timeout_link = reply_link;
+
+  _dbus_pending_call_set_reply_serial_unlocked (pending, serial);
+  
+  return TRUE;
+}
+
+/**
+ * Increments the reference count on a pending call,
+ * while the lock on its connection is already held.
+ *
+ * @param pending the pending call object
+ * @returns the pending call object
+ */
+DBusPendingCall *
+_dbus_pending_call_ref_unlocked (DBusPendingCall *pending)
+{
+  dbus_int32_t old_refcount;
+
+  old_refcount = _dbus_atomic_inc (&pending->refcount);
+  _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount + 1,
+      "ref_unlocked");
+
+  return pending;
+}
+
+
+static void
+_dbus_pending_call_last_unref (DBusPendingCall *pending)
+{
+  DBusConnection *connection;
+  
+  /* If we get here, we should be already detached
+   * from the connection, or never attached.
+   */
+  _dbus_assert (!pending->timeout_added);  
+
+  connection = pending->connection;
+
+  /* this assumes we aren't holding connection lock... */
+  _dbus_data_slot_list_free (&pending->slot_list);
+
+  if (pending->timeout != NULL)
+    _dbus_timeout_unref (pending->timeout);
+      
+  if (pending->timeout_link)
+    {
+      dbus_message_unref ((DBusMessage *)pending->timeout_link->data);
+      _dbus_list_free_link (pending->timeout_link);
+      pending->timeout_link = NULL;
+    }
+
+  if (pending->reply)
+    {
+      dbus_message_unref (pending->reply);
+      pending->reply = NULL;
+    }
+      
+  dbus_free (pending);
+
+  dbus_pending_call_free_data_slot (&notify_user_data_slot);
+
+  /* connection lock should not be held. */
+  /* Free the connection last to avoid a weird state while
+   * calling out to application code where the pending exists
+   * but not the connection.
+   */
+  dbus_connection_unref (connection);
+}
+
+/**
+ * Decrements the reference count on a pending call,
+ * freeing it if the count reaches 0. Assumes
+ * connection lock is already held.
+ *
+ * @param pending the pending call object
+ */
+void
+_dbus_pending_call_unref_and_unlock (DBusPendingCall *pending)
+{
+  dbus_int32_t old_refcount;
+
+  old_refcount = _dbus_atomic_dec (&pending->refcount);
+  _dbus_assert (old_refcount > 0);
+  _dbus_pending_call_trace_ref (pending, old_refcount,
+      old_refcount - 1, "unref_and_unlock");
+
+  CONNECTION_UNLOCK (pending->connection);
+
+  if (old_refcount == 1)
+    _dbus_pending_call_last_unref (pending);
+}
+
+/**
+ * Checks whether the pending call has received a reply
+ * yet, or not. Assumes connection lock is held.
+ *
+ * @param pending the pending call
+ * @returns #TRUE if a reply has been received
+ */
+dbus_bool_t
+_dbus_pending_call_get_completed_unlocked (DBusPendingCall    *pending)
+{
+  return pending->completed;
+}
+
+static DBusDataSlotAllocator slot_allocator;
+_DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots);
+
+/**
+ * Stores a pointer on a #DBusPendingCall, along
+ * with an optional function to be used for freeing
+ * the data when the data is set again, or when
+ * the pending call is finalized. The slot number
+ * must have been allocated with dbus_pending_call_allocate_data_slot().
+ *
+ * @param pending the pending_call
+ * @param slot the slot number
+ * @param data the data to store
+ * @param free_data_func finalizer function for the data
+ * @returns #TRUE if there was enough memory to store the data
+ */
+dbus_bool_t
+_dbus_pending_call_set_data_unlocked (DBusPendingCall  *pending,
+                                     dbus_int32_t      slot,
+                                     void             *data,
+                                     DBusFreeFunction  free_data_func)
+{
+  DBusFreeFunction old_free_func;
+  void *old_data;
+  dbus_bool_t retval;
+
+  retval = _dbus_data_slot_list_set (&slot_allocator,
+                                     &pending->slot_list,
+                                     slot, data, free_data_func,
+                                     &old_free_func, &old_data);
+
+  /* Drop locks to call out to app code */
+  CONNECTION_UNLOCK (pending->connection);
+  
+  if (retval)
+    {
+      if (old_free_func)
+        (* old_free_func) (old_data);
+    }
+
+  CONNECTION_LOCK (pending->connection);
+  
+  return retval;
+}
+
+/** @} */
+
+/**
+ * @defgroup DBusPendingCall DBusPendingCall
+ * @ingroup  DBus
+ * @brief Pending reply to a method call message
+ *
+ * A DBusPendingCall is an object representing an
+ * expected reply. A #DBusPendingCall can be created
+ * when you send a message that should have a reply.
+ *
+ * @{
+ */
+
+/**
+ * @def DBUS_TIMEOUT_INFINITE
+ *
+ * An integer constant representing an infinite timeout. This has the
+ * numeric value 0x7fffffff (the largest 32-bit signed integer).
+ *
+ * For source compatibility with D-Bus versions earlier than 1.4.12, use
+ * 0x7fffffff, or INT32_MAX (assuming your platform has it).
+ */
+
+/**
+ * @def DBUS_TIMEOUT_USE_DEFAULT
+ *
+ * An integer constant representing a request to use the default timeout.
+ * This has numeric value -1.
+ *
+ * For source compatibility with D-Bus versions earlier than 1.4.12, use a
+ * literal -1.
+ */
+
+/**
+ * @typedef DBusPendingCall
+ *
+ * Opaque data type representing a message pending.
+ */
+
+/**
+ * Increments the reference count on a pending call.
+ *
+ * @param pending the pending call object
+ * @returns the pending call object
+ */
+DBusPendingCall *
+dbus_pending_call_ref (DBusPendingCall *pending)
+{
+  dbus_int32_t old_refcount;
+
+  _dbus_return_val_if_fail (pending != NULL, NULL);
+
+  old_refcount = _dbus_atomic_inc (&pending->refcount);
+  _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount + 1,
+      "ref");
+
+  return pending;
+}
+
+/**
+ * Decrements the reference count on a pending call,
+ * freeing it if the count reaches 0.
+ *
+ * @param pending the pending call object
+ */
+void
+dbus_pending_call_unref (DBusPendingCall *pending)
+{
+  dbus_int32_t old_refcount;
+
+  _dbus_return_if_fail (pending != NULL);
+
+  old_refcount = _dbus_atomic_dec (&pending->refcount);
+  _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount - 1,
+      "unref");
+
+  if (old_refcount == 1)
+    _dbus_pending_call_last_unref(pending);
+}
+
+/**
+ * Sets a notification function to be called when the reply is
+ * received or the pending call times out.
+ *
+ * @param pending the pending call
+ * @param function notifier function
+ * @param user_data data to pass to notifier function
+ * @param free_user_data function to free the user data
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_pending_call_set_notify (DBusPendingCall              *pending,
+                              DBusPendingCallNotifyFunction function,
+                              void                         *user_data,
+                              DBusFreeFunction              free_user_data)
+{
+  dbus_bool_t ret = FALSE;
+
+  _dbus_return_val_if_fail (pending != NULL, FALSE);
+
+  CONNECTION_LOCK (pending->connection);
+  
+  /* could invoke application code! */
+  if (!_dbus_pending_call_set_data_unlocked (pending, notify_user_data_slot,
+                                             user_data, free_user_data))
+    goto out;
+  
+  pending->function = function;
+  ret = TRUE;
+
+out:
+  CONNECTION_UNLOCK (pending->connection);
+  
+  return ret;
+}
+
+/**
+ * Cancels the pending call, such that any reply or error received
+ * will just be ignored.  Drops the dbus library's internal reference
+ * to the #DBusPendingCall so will free the call if nobody else is
+ * holding a reference. However you usually get a reference from
+ * dbus_connection_send_with_reply() so probably your app owns a ref
+ * also.
+ *
+ * Note that canceling a pending call will <em>not</em> simulate a
+ * timed-out call; if a call times out, then a timeout error reply is
+ * received. If you cancel the call, no reply is received unless the
+ * the reply was already received before you canceled.
+ * 
+ * @param pending the pending call
+ */
+void
+dbus_pending_call_cancel (DBusPendingCall *pending)
+{
+  _dbus_return_if_fail (pending != NULL);
+
+  _dbus_connection_remove_pending_call (pending->connection,
+                                        pending);
+}
+
+/**
+ * Checks whether the pending call has received a reply
+ * yet, or not.
+ *
+ * @param pending the pending call
+ * @returns #TRUE if a reply has been received
+ */
+dbus_bool_t
+dbus_pending_call_get_completed (DBusPendingCall *pending)
+{
+  dbus_bool_t completed;
+  
+  _dbus_return_val_if_fail (pending != NULL, FALSE);
+
+  CONNECTION_LOCK (pending->connection);
+  completed = pending->completed;
+  CONNECTION_UNLOCK (pending->connection);
+
+  return completed;
+}
+
+/**
+ * Gets the reply, or returns #NULL if none has been received
+ * yet. Ownership of the reply message passes to the caller. This
+ * function can only be called once per pending call, since the reply
+ * message is tranferred to the caller.
+ * 
+ * @param pending the pending call
+ * @returns the reply message or #NULL.
+ */
+DBusMessage*
+dbus_pending_call_steal_reply (DBusPendingCall *pending)
+{
+  DBusMessage *message;
+  
+  _dbus_return_val_if_fail (pending != NULL, NULL);
+  _dbus_return_val_if_fail (pending->completed, NULL);
+  _dbus_return_val_if_fail (pending->reply != NULL, NULL);
+
+  CONNECTION_LOCK (pending->connection);
+  
+  message = pending->reply;
+  pending->reply = NULL;
+
+  CONNECTION_UNLOCK (pending->connection);
+
+  _dbus_message_trace_ref (message, -1, -1, "dbus_pending_call_steal_reply");
+  return message;
+}
+
+/**
+ * Block until the pending call is completed.  The blocking is as with
+ * dbus_connection_send_with_reply_and_block(); it does not enter the
+ * main loop or process other messages, it simply waits for the reply
+ * in question.
+ *
+ * If the pending call is already completed, this function returns
+ * immediately.
+ *
+ * @todo when you start blocking, the timeout is reset, but it should
+ * really only use time remaining since the pending call was created.
+ * This requires storing timestamps instead of intervals in the timeout
+ *
+ * @param pending the pending call
+ */
+void
+dbus_pending_call_block (DBusPendingCall *pending)
+{
+  _dbus_return_if_fail (pending != NULL);
+
+  _dbus_connection_block_pending_call (pending);
+}
+
+/**
+ * Allocates an integer ID to be used for storing application-specific
+ * data on any DBusPendingCall. The allocated ID may then be used
+ * with dbus_pending_call_set_data() and dbus_pending_call_get_data().
+ * The passed-in slot must be initialized to -1, and is filled in
+ * with the slot ID. If the passed-in slot is not -1, it's assumed
+ * to be already allocated, and its refcount is incremented.
+ * 
+ * The allocated slot is global, i.e. all DBusPendingCall objects will
+ * have a slot with the given integer ID reserved.
+ *
+ * @param slot_p address of a global variable storing the slot
+ * @returns #FALSE on failure (no memory)
+ */
+dbus_bool_t
+dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p)
+{
+  _dbus_return_val_if_fail (slot_p != NULL, FALSE);
+
+  return _dbus_data_slot_allocator_alloc (&slot_allocator,
+                                          &_DBUS_LOCK_NAME (pending_call_slots),
+                                          slot_p);
+}
+
+/**
+ * Deallocates a global ID for #DBusPendingCall data slots.
+ * dbus_pending_call_get_data() and dbus_pending_call_set_data() may
+ * no longer be used with this slot.  Existing data stored on existing
+ * DBusPendingCall objects will be freed when the #DBusPendingCall is
+ * finalized, but may not be retrieved (and may only be replaced if
+ * someone else reallocates the slot).  When the refcount on the
+ * passed-in slot reaches 0, it is set to -1.
+ *
+ * @param slot_p address storing the slot to deallocate
+ */
+void
+dbus_pending_call_free_data_slot (dbus_int32_t *slot_p)
+{
+  _dbus_return_if_fail (slot_p != NULL);
+  _dbus_return_if_fail (*slot_p >= 0);
+
+  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
+}
+
+/**
+ * Stores a pointer on a #DBusPendingCall, along
+ * with an optional function to be used for freeing
+ * the data when the data is set again, or when
+ * the pending call is finalized. The slot number
+ * must have been allocated with dbus_pending_call_allocate_data_slot().
+ *
+ * @param pending the pending_call
+ * @param slot the slot number
+ * @param data the data to store
+ * @param free_data_func finalizer function for the data
+ * @returns #TRUE if there was enough memory to store the data
+ */
+dbus_bool_t
+dbus_pending_call_set_data (DBusPendingCall  *pending,
+                            dbus_int32_t      slot,
+                            void             *data,
+                            DBusFreeFunction  free_data_func)
+{
+  dbus_bool_t retval;
+  
+  _dbus_return_val_if_fail (pending != NULL, FALSE);
+  _dbus_return_val_if_fail (slot >= 0, FALSE);
+
+  
+  CONNECTION_LOCK (pending->connection);
+  retval = _dbus_pending_call_set_data_unlocked (pending, slot, data, free_data_func);
+  CONNECTION_UNLOCK (pending->connection);
+  return retval;
+}
+
+/**
+ * Retrieves data previously set with dbus_pending_call_set_data().
+ * The slot must still be allocated (must not have been freed).
+ *
+ * @param pending the pending_call
+ * @param slot the slot to get data from
+ * @returns the data, or #NULL if not found
+ */
+void*
+dbus_pending_call_get_data (DBusPendingCall   *pending,
+                            dbus_int32_t       slot)
+{
+  void *res;
+
+  _dbus_return_val_if_fail (pending != NULL, NULL);
+
+  CONNECTION_LOCK (pending->connection);
+  res = _dbus_data_slot_list_get (&slot_allocator,
+                                  &pending->slot_list,
+                                  slot);
+  CONNECTION_UNLOCK (pending->connection);
+
+  return res;
+}
+
+/** @} */
diff --git a/dbus/dbus/dbus-pending-call.h b/dbus/dbus/dbus-pending-call.h
new file mode 100644
index 0000000..8a37ec0
--- /dev/null
+++ b/dbus/dbus/dbus-pending-call.h
@@ -0,0 +1,79 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-pending-call.h Object representing a call in progress.
+ *
+ * Copyright (C) 2002, 2003 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_PENDING_CALL_H
+#define DBUS_PENDING_CALL_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-connection.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusPendingCall
+ * @{
+ */
+
+#define DBUS_TIMEOUT_INFINITE ((int) 0x7fffffff)
+#define DBUS_TIMEOUT_USE_DEFAULT (-1)
+
+DBUS_EXPORT
+DBusPendingCall* dbus_pending_call_ref       (DBusPendingCall               *pending);
+DBUS_EXPORT
+void         dbus_pending_call_unref         (DBusPendingCall               *pending);
+DBUS_EXPORT
+dbus_bool_t  dbus_pending_call_set_notify    (DBusPendingCall               *pending,
+                                              DBusPendingCallNotifyFunction  function,
+                                              void                          *user_data,
+                                              DBusFreeFunction               free_user_data);
+DBUS_EXPORT
+void         dbus_pending_call_cancel        (DBusPendingCall               *pending);
+DBUS_EXPORT
+dbus_bool_t  dbus_pending_call_get_completed (DBusPendingCall               *pending);
+DBUS_EXPORT
+DBusMessage* dbus_pending_call_steal_reply   (DBusPendingCall               *pending);
+DBUS_EXPORT
+void         dbus_pending_call_block         (DBusPendingCall               *pending);
+
+DBUS_EXPORT
+dbus_bool_t dbus_pending_call_allocate_data_slot (dbus_int32_t     *slot_p);
+DBUS_EXPORT
+void        dbus_pending_call_free_data_slot     (dbus_int32_t     *slot_p);
+DBUS_EXPORT
+dbus_bool_t dbus_pending_call_set_data           (DBusPendingCall  *pending,
+                                                  dbus_int32_t      slot,
+                                                  void             *data,
+                                                  DBusFreeFunction  free_data_func);
+DBUS_EXPORT
+void*       dbus_pending_call_get_data           (DBusPendingCall  *pending,
+                                                  dbus_int32_t      slot);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_PENDING_CALL_H */
diff --git a/dbus/dbus/dbus-pipe-unix.c b/dbus/dbus/dbus-pipe-unix.c
new file mode 100644
index 0000000..cfc5704
--- /dev/null
+++ b/dbus/dbus/dbus-pipe-unix.c
@@ -0,0 +1,83 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-pipe-unix.c unix related pipe implementation
+ * 
+ * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-protocol.h"
+#include "dbus-string.h"
+#include "dbus-internals.h"
+#include "dbus-pipe.h"
+#include "dbus-sysdeps-unix.h"
+
+#include <errno.h>
+
+/**
+ * write data to a pipe.
+ *
+ * @param pipe the pipe instance
+ * @param buffer the buffer to write data from
+ * @param start the first byte in the buffer to write
+ * @param len the number of bytes to try to write
+ * @param error error return
+ * @returns the number of bytes written or -1 on error
+ */
+int
+_dbus_pipe_write (DBusPipe         *pipe,
+                  const DBusString *buffer,
+                  int               start,
+                  int               len,
+                  DBusError        *error)
+{
+  int written;
+  
+  written = _dbus_write (pipe->fd, buffer, start, len);
+  if (written < 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Writing to pipe: %s\n",
+                      _dbus_strerror (errno));
+    }
+  return written;
+}
+
+/**
+ * close a pipe.
+ *
+ * @param pipe the pipe instance
+ * @param error return location for an error
+ * @returns -1 if error is set
+ */
+int
+_dbus_pipe_close  (DBusPipe         *pipe,
+                   DBusError        *error)
+{
+  if (!_dbus_close (pipe->fd, error))
+    {
+      return -1;
+    }
+  else
+    {
+      _dbus_pipe_invalidate (pipe);
+      return 0;
+    }
+}
diff --git a/dbus/dbus/dbus-pipe-win.c b/dbus/dbus/dbus-pipe-win.c
new file mode 100644
index 0000000..9c7c257
--- /dev/null
+++ b/dbus/dbus/dbus-pipe-win.c
@@ -0,0 +1,90 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-pipe-win.c windows related pipe implementation
+ * 
+ * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-protocol.h"
+#include "dbus-string.h"
+#include "dbus-internals.h"
+#include "dbus-pipe.h"
+
+#include <windows.h>
+#include <io.h>
+
+/**
+ * write data to a pipe.
+ *
+ * @param pipe the pipe instance
+ * @param buffer the buffer to write data from
+ * @param start the first byte in the buffer to write
+ * @param len the number of bytes to try to write
+ * @param error error return
+ * @returns the number of bytes written or -1 on error
+ */
+int
+_dbus_pipe_write (DBusPipe         *pipe,
+                  const DBusString *buffer,
+                  int               start,
+                  int               len,
+                  DBusError        *error)
+{
+  const char *buffer_c = _dbus_string_get_const_data (buffer);
+  int written;
+
+  written = _write (pipe->fd, buffer_c + start, len);
+
+  if (written >= 0)
+    return written;
+
+  dbus_set_error (error, _dbus_error_from_system_errno (),
+                  "Writing to pipe: %s",
+                  _dbus_strerror_from_errno ());
+  return -1;
+}
+
+/**
+ * close a pipe.
+ *
+ * @param pipe the pipe instance
+ * @param error return location for an error
+ * @returns #FALSE if error is set
+ */
+int
+_dbus_pipe_close  (DBusPipe         *pipe,
+                   DBusError        *error)
+{
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (_close (pipe->fd) != 0)
+    {
+      dbus_set_error (error, _dbus_error_from_system_errno (),
+                      "Could not close pipe fd %d: %s", pipe->fd,
+                      _dbus_strerror_from_errno ());
+      return -1;
+    }
+  else
+    {
+      _dbus_pipe_invalidate (pipe);
+      return 0;
+    }
+}
diff --git a/dbus/dbus/dbus-pipe.c b/dbus/dbus/dbus-pipe.c
new file mode 100644
index 0000000..7b5fe6d
--- /dev/null
+++ b/dbus/dbus/dbus-pipe.c
@@ -0,0 +1,85 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-pipe.c pipe implementation (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-pipe.h"
+
+/*
+ * init a pipe instance.
+ *
+ * @param pipe the pipe
+ * @param fd the file descriptor to init from 
+ */
+void
+_dbus_pipe_init (DBusPipe *pipe,
+                 int       fd)
+{
+  pipe->fd = fd;
+}
+
+/**
+ * init a pipe with stdout
+ *
+ * @param pipe the pipe
+ */
+void
+_dbus_pipe_init_stdout (DBusPipe *pipe)
+{
+  _dbus_pipe_init (pipe, 1);
+}
+
+/**
+ * check if a pipe is valid; pipes can be set invalid, similar to
+ * a -1 file descriptor.
+ *
+ * @param pipe the pipe instance
+ * @returns #FALSE if pipe is not valid
+ */
+dbus_bool_t
+_dbus_pipe_is_valid(DBusPipe *pipe)
+{
+  return pipe->fd >= 0;
+}
+
+/**
+ * Check if a pipe is stdout or stderr.
+ *
+ * @param pipe the pipe instance
+ * @returns #TRUE if pipe is one of the standard out/err channels
+ */
+dbus_bool_t
+_dbus_pipe_is_stdout_or_stderr (DBusPipe *pipe)
+{
+  return pipe->fd == 1 || pipe->fd == 2;
+}
+
+/**
+ * Initializes a pipe to an invalid value.
+ * @param pipe the pipe
+ */
+void
+_dbus_pipe_invalidate (DBusPipe *pipe)
+{
+  pipe->fd = -1;
+}
diff --git a/dbus/dbus/dbus-pipe.h b/dbus/dbus/dbus-pipe.h
new file mode 100644
index 0000000..c2063b5
--- /dev/null
+++ b/dbus/dbus/dbus-pipe.h
@@ -0,0 +1,59 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps.h Wrappers around system/libc features (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_PIPE_H
+#define DBUS_PIPE_H
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-sysdeps.h>
+
+struct DBusPipe {
+  int fd;
+};
+
+void        _dbus_pipe_init                (DBusPipe         *pipe,
+                                            int               fd);
+void        _dbus_pipe_init_stdout         (DBusPipe         *pipe);
+int         _dbus_pipe_write               (DBusPipe         *pipe,
+                                            const DBusString *buffer,
+                                            int               start,
+                                            int               len,
+                                            DBusError        *error);
+int         _dbus_pipe_close               (DBusPipe         *pipe,
+                                            DBusError        *error);
+dbus_bool_t _dbus_pipe_is_valid            (DBusPipe         *pipe);
+void        _dbus_pipe_invalidate          (DBusPipe         *pipe);
+dbus_bool_t _dbus_pipe_is_stdout_or_stderr (DBusPipe         *pipe);
+
+#endif
diff --git a/dbus/dbus/dbus-protocol.h b/dbus/dbus/dbus-protocol.h
new file mode 100644
index 0000000..60605ab
--- /dev/null
+++ b/dbus/dbus/dbus-protocol.h
@@ -0,0 +1,470 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-protocol.h  D-Bus protocol constants
+ *
+ * Copyright (C) 2002, 2003  CodeFactory AB
+ * Copyright (C) 2004, 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef DBUS_PROTOCOL_H
+#define DBUS_PROTOCOL_H
+
+/* Don't include anything in here from anywhere else. It's
+ * intended for use by any random library.
+ */
+
+#ifdef  __cplusplus
+extern "C" {
+#if 0
+} /* avoids confusing emacs indentation */
+#endif
+#endif
+
+/* Normally docs are in .c files, but there isn't a .c file for this. */
+/**
+ * @defgroup DBusProtocol Protocol constants
+ * @ingroup  DBus
+ *
+ * @brief Defines constants which are part of the D-Bus protocol
+ *
+ * This header is intended for use by any library, not only libdbus.
+ *
+ * @{
+ */
+
+
+/* Message byte order */
+#define DBUS_LITTLE_ENDIAN ('l')  /**< Code marking LSB-first byte order in the wire protocol. */
+#define DBUS_BIG_ENDIAN    ('B')  /**< Code marking MSB-first byte order in the wire protocol. */
+
+/** Protocol version. */
+#define DBUS_MAJOR_PROTOCOL_VERSION 1
+
+/** Type code that is never equal to a legitimate type code */
+#define DBUS_TYPE_INVALID       ((int) '\0')
+/** #DBUS_TYPE_INVALID as a string literal instead of a int literal */
+#define DBUS_TYPE_INVALID_AS_STRING        "\0"
+
+/* Primitive types */
+/** Type code marking an 8-bit unsigned integer */
+#define DBUS_TYPE_BYTE          ((int) 'y')
+/** #DBUS_TYPE_BYTE as a string literal instead of a int literal */
+#define DBUS_TYPE_BYTE_AS_STRING           "y"
+/** Type code marking a boolean */
+#define DBUS_TYPE_BOOLEAN       ((int) 'b')
+/** #DBUS_TYPE_BOOLEAN as a string literal instead of a int literal */
+#define DBUS_TYPE_BOOLEAN_AS_STRING        "b"
+/** Type code marking a 16-bit signed integer */
+#define DBUS_TYPE_INT16         ((int) 'n')
+/** #DBUS_TYPE_INT16 as a string literal instead of a int literal */
+#define DBUS_TYPE_INT16_AS_STRING          "n"
+/** Type code marking a 16-bit unsigned integer */
+#define DBUS_TYPE_UINT16        ((int) 'q')
+/** #DBUS_TYPE_UINT16 as a string literal instead of a int literal */
+#define DBUS_TYPE_UINT16_AS_STRING         "q"
+/** Type code marking a 32-bit signed integer */
+#define DBUS_TYPE_INT32         ((int) 'i')
+/** #DBUS_TYPE_INT32 as a string literal instead of a int literal */
+#define DBUS_TYPE_INT32_AS_STRING          "i"
+/** Type code marking a 32-bit unsigned integer */
+#define DBUS_TYPE_UINT32        ((int) 'u')
+/** #DBUS_TYPE_UINT32 as a string literal instead of a int literal */
+#define DBUS_TYPE_UINT32_AS_STRING         "u"
+/** Type code marking a 64-bit signed integer */
+#define DBUS_TYPE_INT64         ((int) 'x')
+/** #DBUS_TYPE_INT64 as a string literal instead of a int literal */
+#define DBUS_TYPE_INT64_AS_STRING          "x"
+/** Type code marking a 64-bit unsigned integer */
+#define DBUS_TYPE_UINT64        ((int) 't')
+/** #DBUS_TYPE_UINT64 as a string literal instead of a int literal */
+#define DBUS_TYPE_UINT64_AS_STRING         "t"
+/** Type code marking an 8-byte double in IEEE 754 format */
+#define DBUS_TYPE_DOUBLE        ((int) 'd')
+/** #DBUS_TYPE_DOUBLE as a string literal instead of a int literal */
+#define DBUS_TYPE_DOUBLE_AS_STRING         "d"
+/** Type code marking a UTF-8 encoded, nul-terminated Unicode string */
+#define DBUS_TYPE_STRING        ((int) 's')
+/** #DBUS_TYPE_STRING as a string literal instead of a int literal */
+#define DBUS_TYPE_STRING_AS_STRING         "s"
+/** Type code marking a D-Bus object path */
+#define DBUS_TYPE_OBJECT_PATH   ((int) 'o')
+/** #DBUS_TYPE_OBJECT_PATH as a string literal instead of a int literal */
+#define DBUS_TYPE_OBJECT_PATH_AS_STRING    "o"
+/** Type code marking a D-Bus type signature */
+#define DBUS_TYPE_SIGNATURE     ((int) 'g')
+/** #DBUS_TYPE_SIGNATURE as a string literal instead of a int literal */
+#define DBUS_TYPE_SIGNATURE_AS_STRING      "g"
+/** Type code marking a unix file descriptor */
+#define DBUS_TYPE_UNIX_FD      ((int) 'h')
+/** #DBUS_TYPE_UNIX_FD as a string literal instead of a int literal */
+#define DBUS_TYPE_UNIX_FD_AS_STRING        "h"
+
+/* Compound types */
+/** Type code marking a D-Bus array type */
+#define DBUS_TYPE_ARRAY         ((int) 'a')
+/** #DBUS_TYPE_ARRAY as a string literal instead of a int literal */
+#define DBUS_TYPE_ARRAY_AS_STRING          "a"
+/** Type code marking a D-Bus variant type */
+#define DBUS_TYPE_VARIANT       ((int) 'v')
+/** #DBUS_TYPE_VARIANT as a string literal instead of a int literal */
+#define DBUS_TYPE_VARIANT_AS_STRING        "v"
+
+/** STRUCT and DICT_ENTRY are sort of special since their codes can't
+ * appear in a type string, instead
+ * DBUS_STRUCT_BEGIN_CHAR/DBUS_DICT_ENTRY_BEGIN_CHAR have to appear
+ */
+/** Type code used to represent a struct; however, this type code does not appear
+ * in type signatures, instead #DBUS_STRUCT_BEGIN_CHAR and #DBUS_STRUCT_END_CHAR will
+ * appear in a signature.
+ */
+#define DBUS_TYPE_STRUCT        ((int) 'r')
+/** #DBUS_TYPE_STRUCT as a string literal instead of a int literal */
+#define DBUS_TYPE_STRUCT_AS_STRING         "r"
+/** Type code used to represent a dict entry; however, this type code does not appear
+ * in type signatures, instead #DBUS_DICT_ENTRY_BEGIN_CHAR and #DBUS_DICT_ENTRY_END_CHAR will
+ * appear in a signature.
+ */
+#define DBUS_TYPE_DICT_ENTRY    ((int) 'e')
+/** #DBUS_TYPE_DICT_ENTRY as a string literal instead of a int literal */
+#define DBUS_TYPE_DICT_ENTRY_AS_STRING     "e"
+
+/** Does not include #DBUS_TYPE_INVALID, #DBUS_STRUCT_BEGIN_CHAR, #DBUS_STRUCT_END_CHAR,
+ * #DBUS_DICT_ENTRY_BEGIN_CHAR, or #DBUS_DICT_ENTRY_END_CHAR - i.e. it is the number of
+ * valid types, not the number of distinct characters that may appear in a type signature.
+ */
+#define DBUS_NUMBER_OF_TYPES    (16)
+
+/* characters other than typecodes that appear in type signatures */
+
+/** Code marking the start of a struct type in a type signature */
+#define DBUS_STRUCT_BEGIN_CHAR   ((int) '(')
+/** #DBUS_STRUCT_BEGIN_CHAR as a string literal instead of a int literal */
+#define DBUS_STRUCT_BEGIN_CHAR_AS_STRING   "("
+/** Code marking the end of a struct type in a type signature */
+#define DBUS_STRUCT_END_CHAR     ((int) ')')
+/** #DBUS_STRUCT_END_CHAR a string literal instead of a int literal */
+#define DBUS_STRUCT_END_CHAR_AS_STRING     ")"
+/** Code marking the start of a dict entry type in a type signature */
+#define DBUS_DICT_ENTRY_BEGIN_CHAR   ((int) '{')
+/** #DBUS_DICT_ENTRY_BEGIN_CHAR as a string literal instead of a int literal */
+#define DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING   "{"
+/** Code marking the end of a dict entry type in a type signature */
+#define DBUS_DICT_ENTRY_END_CHAR     ((int) '}')
+/** #DBUS_DICT_ENTRY_END_CHAR as a string literal instead of a int literal */
+#define DBUS_DICT_ENTRY_END_CHAR_AS_STRING     "}"
+
+/** Max length in bytes of a bus name, interface, or member (not object
+ * path, paths are unlimited). This is limited because lots of stuff
+ * is O(n) in this number, plus it would be obnoxious to type in a
+ * paragraph-long method name so most likely something like that would
+ * be an exploit.
+ */
+#define DBUS_MAXIMUM_NAME_LENGTH 255
+
+/** This one is 255 so it fits in a byte */
+#define DBUS_MAXIMUM_SIGNATURE_LENGTH 255
+
+/** Max length of a match rule string; to keep people from hosing the
+ * daemon with some huge rule
+ */
+#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024
+
+/** Max arg number you can match on in a match rule, e.g.
+ * arg0='hello' is OK, arg3489720987='hello' is not
+ */
+#define DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER 63
+
+/** Max length of a marshaled array in bytes (64M, 2^26) We use signed
+ * int for lengths so must be INT_MAX or less.  We need something a
+ * bit smaller than INT_MAX because the array is inside a message with
+ * header info, etc.  so an INT_MAX array wouldn't allow the message
+ * overhead.  The 64M number is an attempt at a larger number than
+ * we'd reasonably ever use, but small enough that your bus would chew
+ * through it fairly quickly without locking up forever. If you have
+ * data that's likely to be larger than this, you should probably be
+ * sending it in multiple incremental messages anyhow.
+ */
+#define DBUS_MAXIMUM_ARRAY_LENGTH (67108864)
+/** Number of bits you need in an unsigned to store the max array size */
+#define DBUS_MAXIMUM_ARRAY_LENGTH_BITS 26
+
+/** The maximum total message size including header and body; similar
+ * rationale to max array size.
+ */
+#define DBUS_MAXIMUM_MESSAGE_LENGTH (DBUS_MAXIMUM_ARRAY_LENGTH * 2)
+/** Number of bits you need in an unsigned to store the max message size */
+#define DBUS_MAXIMUM_MESSAGE_LENGTH_BITS 27
+
+/** The maximum total number of unix fds in a message. Similar
+ * rationale as DBUS_MAXIMUM_MESSAGE_LENGTH. However we divide by four
+ * given that one fd is an int and hence at least 32 bits.
+ */
+#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS (DBUS_MAXIMUM_MESSAGE_LENGTH/4)
+/** Number of bits you need in an unsigned to store the max message unix fds */
+#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS_BITS (DBUS_MAXIMUM_MESSAGE_LENGTH_BITS-2)
+
+/** Depth of recursion in the type tree. This is automatically limited
+ * to DBUS_MAXIMUM_SIGNATURE_LENGTH since you could only have an array
+ * of array of array of ... that fit in the max signature.  But that's
+ * probably a bit too large.
+ */
+#define DBUS_MAXIMUM_TYPE_RECURSION_DEPTH 32
+
+/* Types of message */
+
+/** This value is never a valid message type, see dbus_message_get_type() */
+#define DBUS_MESSAGE_TYPE_INVALID       0
+/** Message type of a method call message, see dbus_message_get_type() */
+#define DBUS_MESSAGE_TYPE_METHOD_CALL   1
+/** Message type of a method return message, see dbus_message_get_type() */
+#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
+/** Message type of an error reply message, see dbus_message_get_type() */
+#define DBUS_MESSAGE_TYPE_ERROR         3
+/** Message type of a signal message, see dbus_message_get_type() */
+#define DBUS_MESSAGE_TYPE_SIGNAL        4
+
+#define DBUS_NUM_MESSAGE_TYPES          5
+
+/* Header flags */
+
+/** If set, this flag means that the sender of a message does not care about getting
+ * a reply, so the recipient need not send one. See dbus_message_set_no_reply().
+ */
+#define DBUS_HEADER_FLAG_NO_REPLY_EXPECTED 0x1
+/**
+ * If set, this flag means that even if the message bus knows how to start an owner for
+ * the destination bus name (see dbus_message_set_destination()), it should not
+ * do so. If this flag is not set, the bus may launch a program to process the
+ * message.
+ */
+#define DBUS_HEADER_FLAG_NO_AUTO_START     0x2
+
+/* Header fields */
+
+/** Not equal to any valid header field code */
+#define DBUS_HEADER_FIELD_INVALID        0
+/** Header field code for the path - the path is the object emitting a signal or the object receiving a method call.
+ * See dbus_message_set_path().
+ */
+#define DBUS_HEADER_FIELD_PATH           1
+/** Header field code for the interface containing a member (method or signal).
+ * See dbus_message_set_interface().
+ */
+#define DBUS_HEADER_FIELD_INTERFACE      2
+/** Header field code for a member (method or signal). See dbus_message_set_member(). */
+#define DBUS_HEADER_FIELD_MEMBER         3
+/** Header field code for an error name (found in #DBUS_MESSAGE_TYPE_ERROR messages).
+ * See dbus_message_set_error_name().
+ */
+#define DBUS_HEADER_FIELD_ERROR_NAME     4
+/** Header field code for a reply serial, used to match a #DBUS_MESSAGE_TYPE_METHOD_RETURN message with the
+ * message that it's a reply to. See dbus_message_set_reply_serial().
+ */
+#define DBUS_HEADER_FIELD_REPLY_SERIAL   5
+/**
+ * Header field code for the destination bus name of a message. See dbus_message_set_destination().
+ */
+#define DBUS_HEADER_FIELD_DESTINATION    6
+/**
+ * Header field code for the sender of a message; usually initialized by the message bus.
+ * See dbus_message_set_sender().
+ */
+#define DBUS_HEADER_FIELD_SENDER         7
+/**
+ * Header field code for the type signature of a message.
+ */
+#define DBUS_HEADER_FIELD_SIGNATURE      8
+/**
+ * Header field code for the number of unix file descriptors associated
+ * with this message.
+ */
+#define DBUS_HEADER_FIELD_UNIX_FDS       9
+
+
+/**
+ * Value of the highest-numbered header field code, can be used to determine
+ * the size of an array indexed by header field code. Remember though
+ * that unknown codes must be ignored, so check for that before
+ * indexing the array.
+ */
+#define DBUS_HEADER_FIELD_LAST DBUS_HEADER_FIELD_UNIX_FDS
+
+/** Header format is defined as a signature:
+ *   byte                            byte order
+ *   byte                            message type ID
+ *   byte                            flags
+ *   byte                            protocol version
+ *   uint32                          body length
+ *   uint32                          serial
+ *   array of struct (byte,variant)  (field name, value)
+ *
+ * The length of the header can be computed as the
+ * fixed size of the initial data, plus the length of
+ * the array at the end, plus padding to an 8-boundary.
+ */
+#define DBUS_HEADER_SIGNATURE                   \
+     DBUS_TYPE_BYTE_AS_STRING                   \
+     DBUS_TYPE_BYTE_AS_STRING                   \
+     DBUS_TYPE_BYTE_AS_STRING                   \
+     DBUS_TYPE_BYTE_AS_STRING                   \
+     DBUS_TYPE_UINT32_AS_STRING                 \
+     DBUS_TYPE_UINT32_AS_STRING                 \
+     DBUS_TYPE_ARRAY_AS_STRING                  \
+     DBUS_STRUCT_BEGIN_CHAR_AS_STRING           \
+     DBUS_TYPE_BYTE_AS_STRING                   \
+     DBUS_TYPE_VARIANT_AS_STRING                \
+     DBUS_STRUCT_END_CHAR_AS_STRING
+
+
+/**
+ * The smallest header size that can occur.  (It won't be valid due to
+ * missing required header fields.) This is 4 bytes, two uint32, an
+ * array length. This isn't any kind of resource limit, just the
+ * necessary/logical outcome of the header signature.
+ */
+#define DBUS_MINIMUM_HEADER_SIZE 16
+
+/* Errors */
+/* WARNING these get autoconverted to an enum in dbus-glib.h. Thus,
+ * if you change the order it breaks the ABI. Keep them in order.
+ * Also, don't change the formatting since that will break the sed
+ * script.
+ */
+/** A generic error; "something went wrong" - see the error message for more. */
+#define DBUS_ERROR_FAILED                     "org.freedesktop.DBus.Error.Failed"
+/** There was not enough memory to complete an operation. */
+#define DBUS_ERROR_NO_MEMORY                  "org.freedesktop.DBus.Error.NoMemory"
+/** The bus doesn't know how to launch a service to supply the bus name you wanted. */
+#define DBUS_ERROR_SERVICE_UNKNOWN            "org.freedesktop.DBus.Error.ServiceUnknown"
+/** The bus name you referenced doesn't exist (i.e. no application owns it). */
+#define DBUS_ERROR_NAME_HAS_NO_OWNER          "org.freedesktop.DBus.Error.NameHasNoOwner"
+/** No reply to a message expecting one, usually means a timeout occurred. */
+#define DBUS_ERROR_NO_REPLY                   "org.freedesktop.DBus.Error.NoReply"
+/** Something went wrong reading or writing to a socket, for example. */
+#define DBUS_ERROR_IO_ERROR                   "org.freedesktop.DBus.Error.IOError"
+/** A D-Bus bus address was malformed. */
+#define DBUS_ERROR_BAD_ADDRESS                "org.freedesktop.DBus.Error.BadAddress"
+/** Requested operation isn't supported (like ENOSYS on UNIX). */
+#define DBUS_ERROR_NOT_SUPPORTED              "org.freedesktop.DBus.Error.NotSupported"
+/** Some limited resource is exhausted. */
+#define DBUS_ERROR_LIMITS_EXCEEDED            "org.freedesktop.DBus.Error.LimitsExceeded"
+/** Security restrictions don't allow doing what you're trying to do. */
+#define DBUS_ERROR_ACCESS_DENIED              "org.freedesktop.DBus.Error.AccessDenied"
+/** Authentication didn't work. */
+#define DBUS_ERROR_AUTH_FAILED                "org.freedesktop.DBus.Error.AuthFailed"
+/** Unable to connect to server (probably caused by ECONNREFUSED on a socket). */
+#define DBUS_ERROR_NO_SERVER                  "org.freedesktop.DBus.Error.NoServer"
+/** Certain timeout errors, possibly ETIMEDOUT on a socket.
+ * Note that #DBUS_ERROR_NO_REPLY is used for message reply timeouts.
+ * @warning this is confusingly-named given that #DBUS_ERROR_TIMED_OUT also exists. We can't fix
+ * it for compatibility reasons so just be careful.
+ */
+#define DBUS_ERROR_TIMEOUT                    "org.freedesktop.DBus.Error.Timeout"
+/** No network access (probably ENETUNREACH on a socket). */
+#define DBUS_ERROR_NO_NETWORK                 "org.freedesktop.DBus.Error.NoNetwork"
+/** Can't bind a socket since its address is in use (i.e. EADDRINUSE). */
+#define DBUS_ERROR_ADDRESS_IN_USE             "org.freedesktop.DBus.Error.AddressInUse"
+/** The connection is disconnected and you're trying to use it. */
+#define DBUS_ERROR_DISCONNECTED               "org.freedesktop.DBus.Error.Disconnected"
+/** Invalid arguments passed to a method call. */
+#define DBUS_ERROR_INVALID_ARGS               "org.freedesktop.DBus.Error.InvalidArgs"
+/** Missing file. */
+#define DBUS_ERROR_FILE_NOT_FOUND             "org.freedesktop.DBus.Error.FileNotFound"
+/** Existing file and the operation you're using does not silently overwrite. */
+#define DBUS_ERROR_FILE_EXISTS                "org.freedesktop.DBus.Error.FileExists"
+/** Method name you invoked isn't known by the object you invoked it on. */
+#define DBUS_ERROR_UNKNOWN_METHOD             "org.freedesktop.DBus.Error.UnknownMethod"
+/** Object you invoked a method on isn't known. */
+#define DBUS_ERROR_UNKNOWN_OBJECT             "org.freedesktop.DBus.Error.UnknownObject"
+/** Interface you invoked a method on isn't known by the object. */
+#define DBUS_ERROR_UNKNOWN_INTERFACE          "org.freedesktop.DBus.Error.UnknownInterface"
+/** Property you tried to access isn't known by the object. */
+#define DBUS_ERROR_UNKNOWN_PROPERTY           "org.freedesktop.DBus.Error.UnknownProperty"
+/** Property you tried to set is read-only. */
+#define DBUS_ERROR_PROPERTY_READ_ONLY         "org.freedesktop.DBus.Error.PropertyReadOnly"
+/** Certain timeout errors, e.g. while starting a service.
+ * @warning this is confusingly-named given that #DBUS_ERROR_TIMEOUT also exists. We can't fix
+ * it for compatibility reasons so just be careful.
+ */
+#define DBUS_ERROR_TIMED_OUT                  "org.freedesktop.DBus.Error.TimedOut"
+/** Tried to remove or modify a match rule that didn't exist. */
+#define DBUS_ERROR_MATCH_RULE_NOT_FOUND       "org.freedesktop.DBus.Error.MatchRuleNotFound"
+/** The match rule isn't syntactically valid. */
+#define DBUS_ERROR_MATCH_RULE_INVALID         "org.freedesktop.DBus.Error.MatchRuleInvalid"
+/** While starting a new process, the exec() call failed. */
+#define DBUS_ERROR_SPAWN_EXEC_FAILED          "org.freedesktop.DBus.Error.Spawn.ExecFailed"
+/** While starting a new process, the fork() call failed. */
+#define DBUS_ERROR_SPAWN_FORK_FAILED          "org.freedesktop.DBus.Error.Spawn.ForkFailed"
+/** While starting a new process, the child exited with a status code. */
+#define DBUS_ERROR_SPAWN_CHILD_EXITED         "org.freedesktop.DBus.Error.Spawn.ChildExited"
+/** While starting a new process, the child exited on a signal. */
+#define DBUS_ERROR_SPAWN_CHILD_SIGNALED       "org.freedesktop.DBus.Error.Spawn.ChildSignaled"
+/** While starting a new process, something went wrong. */
+#define DBUS_ERROR_SPAWN_FAILED               "org.freedesktop.DBus.Error.Spawn.Failed"
+/** We failed to setup the environment correctly. */
+#define DBUS_ERROR_SPAWN_SETUP_FAILED         "org.freedesktop.DBus.Error.Spawn.FailedToSetup"
+/** We failed to setup the config parser correctly. */
+#define DBUS_ERROR_SPAWN_CONFIG_INVALID       "org.freedesktop.DBus.Error.Spawn.ConfigInvalid"
+/** Bus name was not valid. */
+#define DBUS_ERROR_SPAWN_SERVICE_INVALID      "org.freedesktop.DBus.Error.Spawn.ServiceNotValid"
+/** Service file not found in system-services directory. */
+#define DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND    "org.freedesktop.DBus.Error.Spawn.ServiceNotFound"
+/** Permissions are incorrect on the setuid helper. */
+#define DBUS_ERROR_SPAWN_PERMISSIONS_INVALID  "org.freedesktop.DBus.Error.Spawn.PermissionsInvalid"
+/** Service file invalid (Name, User or Exec missing). */
+#define DBUS_ERROR_SPAWN_FILE_INVALID         "org.freedesktop.DBus.Error.Spawn.FileInvalid"
+/** Tried to get a UNIX process ID and it wasn't available. */
+#define DBUS_ERROR_SPAWN_NO_MEMORY            "org.freedesktop.DBus.Error.Spawn.NoMemory"
+/** Tried to get a UNIX process ID and it wasn't available. */
+#define DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN    "org.freedesktop.DBus.Error.UnixProcessIdUnknown"
+/** A type signature is not valid. */
+#define DBUS_ERROR_INVALID_SIGNATURE          "org.freedesktop.DBus.Error.InvalidSignature"
+/** A file contains invalid syntax or is otherwise broken. */
+#define DBUS_ERROR_INVALID_FILE_CONTENT       "org.freedesktop.DBus.Error.InvalidFileContent"
+/** Asked for SELinux security context and it wasn't available. */
+#define DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN    "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"
+/** Asked for ADT audit data and it wasn't available. */
+#define DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN     "org.freedesktop.DBus.Error.AdtAuditDataUnknown"
+/** There's already an object with the requested object path. */
+#define DBUS_ERROR_OBJECT_PATH_IN_USE         "org.freedesktop.DBus.Error.ObjectPathInUse"
+/** The message meta data does not match the payload. e.g. expected
+    number of file descriptors were not sent over the socket this message was received on. */
+#define DBUS_ERROR_INCONSISTENT_MESSAGE       "org.freedesktop.DBus.Error.InconsistentMessage"
+
+/* XML introspection format */
+
+/** XML namespace of the introspection format version 1.0 */
+#define DBUS_INTROSPECT_1_0_XML_NAMESPACE         "http://www.freedesktop.org/standards/dbus"
+/** XML public identifier of the introspection format version 1.0 */
+#define DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+/** XML system identifier of the introspection format version 1.0 */
+#define DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"
+/** XML document type declaration of the introspection format version 1.0 */
+#define DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<!DOCTYPE node PUBLIC \"" DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "\"\n\"" DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER "\">\n"
+
+/** @} */
+
+#ifdef __cplusplus
+#if 0
+{ /* avoids confusing emacs indentation */
+#endif
+}
+#endif
+
+#endif /* DBUS_PROTOCOL_H */
diff --git a/dbus/dbus/dbus-resources.c b/dbus/dbus/dbus-resources.c
new file mode 100644
index 0000000..80fb55b
--- /dev/null
+++ b/dbus/dbus/dbus-resources.c
@@ -0,0 +1,290 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-resources.c Resource tracking/limits
+ *
+ * Copyright (C) 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include <dbus/dbus-resources.h>
+#include <dbus/dbus-internals.h>
+
+/**
+ * @defgroup DBusResources Resource limits related code
+ * @ingroup  DBusInternals
+ * @brief DBusCounter and other stuff related to resource limits
+ *
+ * Types and functions related to tracking resource limits,
+ * such as the maximum amount of memory/unix fds a connection can use
+ * for messages, etc.
+ */
+
+/**
+ * @defgroup DBusResourcesInternals Resource limits implementation details
+ * @ingroup  DBusInternals
+ * @brief Resource limits implementation details
+ *
+ * Implementation details of resource limits code.
+ *
+ * @{
+ */
+
+/**
+ * @brief Internals of DBusCounter.
+ * 
+ * DBusCounter internals. DBusCounter is an opaque object, it must be
+ * used via accessor functions.
+ */
+struct DBusCounter
+{
+  int refcount;  /**< reference count */
+
+  long size_value;       /**< current size counter value */
+  long unix_fd_value;    /**< current unix fd counter value */
+
+#ifdef DBUS_ENABLE_STATS
+  long peak_size_value;     /**< largest ever size counter value */
+  long peak_unix_fd_value;  /**< largest ever unix fd counter value */
+#endif
+
+  long notify_size_guard_value;    /**< call notify function when crossing this size value */
+  long notify_unix_fd_guard_value; /**< call notify function when crossing this unix fd value */
+
+  DBusCounterNotifyFunction notify_function; /**< notify function */
+  void *notify_data; /**< data for notify function */
+  dbus_bool_t notify_pending : 1; /**< TRUE if the guard value has been crossed */
+};
+
+/** @} */  /* end of resource limits internals docs */
+
+/**
+ * @addtogroup DBusResources
+ * @{
+ */
+
+/**
+ * Creates a new DBusCounter. DBusCounter is used
+ * to count usage of some resource such as memory.
+ *
+ * @returns new counter or #NULL on failure
+ */
+DBusCounter*
+_dbus_counter_new (void)
+{
+  DBusCounter *counter;
+
+  counter = dbus_new0 (DBusCounter, 1);
+  if (counter == NULL)
+    return NULL;
+
+  counter->refcount = 1;
+
+  return counter;
+}
+
+/**
+ * Increments refcount of the counter
+ *
+ * @param counter the counter
+ * @returns the counter
+ */
+DBusCounter *
+_dbus_counter_ref (DBusCounter *counter)
+{
+  _dbus_assert (counter->refcount > 0);
+  
+  counter->refcount += 1;
+
+  return counter;
+}
+
+/**
+ * Decrements refcount of the counter and possibly
+ * finalizes the counter.
+ *
+ * @param counter the counter
+ */
+void
+_dbus_counter_unref (DBusCounter *counter)
+{
+  _dbus_assert (counter->refcount > 0);
+
+  counter->refcount -= 1;
+
+  if (counter->refcount == 0)
+    {
+      
+      dbus_free (counter);
+    }
+}
+
+/**
+ * Adjusts the value of the size counter by the given
+ * delta which may be positive or negative.
+ *
+ * This function may be called with locks held. After calling it, when
+ * any relevant locks are no longer held you must call _dbus_counter_notify().
+ *
+ * @param counter the counter
+ * @param delta value to add to the size counter's current value
+ */
+void
+_dbus_counter_adjust_size (DBusCounter *counter,
+                           long         delta)
+{
+  long old = counter->size_value;
+
+  counter->size_value += delta;
+
+#ifdef DBUS_ENABLE_STATS
+  if (counter->peak_size_value < counter->size_value)
+    counter->peak_size_value = counter->size_value;
+#endif
+
+#if 0
+  _dbus_verbose ("Adjusting counter %ld by %ld = %ld\n",
+                 old, delta, counter->size_value);
+#endif
+
+  if (counter->notify_function != NULL &&
+      ((old < counter->notify_size_guard_value &&
+        counter->size_value >= counter->notify_size_guard_value) ||
+       (old >= counter->notify_size_guard_value &&
+        counter->size_value < counter->notify_size_guard_value)))
+    counter->notify_pending = TRUE;
+}
+
+/**
+ * Calls the notify function from _dbus_counter_set_notify(),
+ * if that function has been specified and the counter has crossed the
+ * guard value (in either direction) since the last call to this function.
+ *
+ * This function must not be called with locks held, since it can call out
+ * to user code.
+ */
+void
+_dbus_counter_notify (DBusCounter *counter)
+{
+  if (counter->notify_pending)
+    {
+      counter->notify_pending = FALSE;
+      (* counter->notify_function) (counter, counter->notify_data);
+    }
+}
+
+/**
+ * Adjusts the value of the unix fd counter by the given
+ * delta which may be positive or negative.
+ *
+ * This function may be called with locks held. After calling it, when
+ * any relevant locks are no longer held you must call _dbus_counter_notify().
+ *
+ * @param counter the counter
+ * @param delta value to add to the unix fds counter's current value
+ */
+void
+_dbus_counter_adjust_unix_fd (DBusCounter *counter,
+                              long         delta)
+{
+  long old = counter->unix_fd_value;
+  
+  counter->unix_fd_value += delta;
+
+#ifdef DBUS_ENABLE_STATS
+  if (counter->peak_unix_fd_value < counter->unix_fd_value)
+    counter->peak_unix_fd_value = counter->unix_fd_value;
+#endif
+
+#if 0
+  _dbus_verbose ("Adjusting counter %ld by %ld = %ld\n",
+                 old, delta, counter->unix_fd_value);
+#endif
+  
+  if (counter->notify_function != NULL &&
+      ((old < counter->notify_unix_fd_guard_value &&
+        counter->unix_fd_value >= counter->notify_unix_fd_guard_value) ||
+       (old >= counter->notify_unix_fd_guard_value &&
+        counter->unix_fd_value < counter->notify_unix_fd_guard_value)))
+    counter->notify_pending = TRUE;
+}
+
+/**
+ * Gets the current value of the size counter.
+ *
+ * @param counter the counter
+ * @returns its current size value
+ */
+long
+_dbus_counter_get_size_value (DBusCounter *counter)
+{
+  return counter->size_value;
+}
+
+/**
+ * Gets the current value of the unix fd counter.
+ *
+ * @param counter the counter
+ * @returns its current unix fd value
+ */
+long
+_dbus_counter_get_unix_fd_value (DBusCounter *counter)
+{
+  return counter->unix_fd_value;
+}
+
+/**
+ * Sets the notify function for this counter; the notify function is
+ * called whenever the counter's values cross the guard values in
+ * either direction (moving up, or moving down).
+ *
+ * @param counter the counter
+ * @param size_guard_value the value we're notified if the size counter crosses
+ * @param unix_fd_guard_value the value we're notified if the unix fd counter crosses
+ * @param function function to call in order to notify
+ * @param user_data data to pass to the function
+ */
+void
+_dbus_counter_set_notify (DBusCounter               *counter,
+                          long                       size_guard_value,
+                          long                       unix_fd_guard_value,
+                          DBusCounterNotifyFunction  function,
+                          void                      *user_data)
+{
+  counter->notify_size_guard_value = size_guard_value;
+  counter->notify_unix_fd_guard_value = unix_fd_guard_value;
+  counter->notify_function = function;
+  counter->notify_data = user_data;
+  counter->notify_pending = FALSE;
+}
+
+#ifdef DBUS_ENABLE_STATS
+long
+_dbus_counter_get_peak_size_value (DBusCounter *counter)
+{
+  return counter->peak_size_value;
+}
+
+long
+_dbus_counter_get_peak_unix_fd_value (DBusCounter *counter)
+{
+  return counter->peak_unix_fd_value;
+}
+#endif
+
+/** @} */  /* end of resource limits exported API */
diff --git a/dbus/dbus/dbus-resources.h b/dbus/dbus/dbus-resources.h
new file mode 100644
index 0000000..781a575
--- /dev/null
+++ b/dbus/dbus/dbus-resources.h
@@ -0,0 +1,61 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-resources.h Resource tracking/limits
+ *
+ * Copyright (C) 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_RESOURCES_H
+#define DBUS_RESOURCES_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-connection.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusCounter DBusCounter;
+
+typedef void (* DBusCounterNotifyFunction) (DBusCounter *counter,
+                                            void        *user_data);
+
+DBusCounter* _dbus_counter_new       (void);
+DBusCounter* _dbus_counter_ref       (DBusCounter *counter);
+void         _dbus_counter_unref     (DBusCounter *counter);
+
+void         _dbus_counter_adjust_size       (DBusCounter *counter,
+                                              long         delta);
+void         _dbus_counter_adjust_unix_fd    (DBusCounter *counter,
+                                              long         delta);
+void         _dbus_counter_notify            (DBusCounter *counter);
+long         _dbus_counter_get_size_value    (DBusCounter *counter);
+long         _dbus_counter_get_unix_fd_value (DBusCounter *counter);
+
+void _dbus_counter_set_notify    (DBusCounter               *counter,
+                                  long                       size_guard_value,
+                                  long                       unix_fd_guard_value,
+                                  DBusCounterNotifyFunction  function,
+                                  void                      *user_data);
+
+/* if DBUS_ENABLE_STATS */
+long _dbus_counter_get_peak_size_value    (DBusCounter *counter);
+long _dbus_counter_get_peak_unix_fd_value (DBusCounter *counter);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_RESOURCES_H */
diff --git a/dbus/dbus/dbus-server-debug-pipe.c b/dbus/dbus/dbus-server-debug-pipe.c
new file mode 100644
index 0000000..419db5c
--- /dev/null
+++ b/dbus/dbus/dbus-server-debug-pipe.c
@@ -0,0 +1,431 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server-debug-pipe.c In-proc debug server implementation 
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2003, 2004  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-server-debug-pipe.h"
+#include "dbus-transport-socket.h"
+#include "dbus-connection-internal.h"
+#include "dbus-hash.h"
+#include "dbus-string.h"
+#include "dbus-protocol.h"
+
+#ifdef DBUS_BUILD_TESTS
+
+/**
+ * @defgroup DBusServerDebugPipe DBusServerDebugPipe
+ * @ingroup  DBusInternals
+ * @brief In-process pipe debug server used in unit tests.
+ *
+ * Types and functions related to DBusServerDebugPipe.
+ * This is used for unit testing.
+ *
+ * @{
+ */
+
+/**
+ * Opaque object representing a debug server implementation.
+ */
+typedef struct DBusServerDebugPipe DBusServerDebugPipe;
+
+/**
+ * Implementation details of DBusServerDebugPipe. All members
+ * are private.
+ */
+struct DBusServerDebugPipe
+{
+  DBusServer base;  /**< Parent class members. */
+
+  char *name; /**< Server name. */
+
+  dbus_bool_t disconnected; /**< TRUE if disconnect has been called */
+};
+
+/* FIXME not threadsafe (right now the test suite doesn't use threads anyhow ) */
+static DBusHashTable *server_pipe_hash;
+static int server_pipe_hash_refcount = 0;
+
+static dbus_bool_t
+pipe_hash_ref (void)
+{
+  if (!server_pipe_hash)
+    {
+      _dbus_assert (server_pipe_hash_refcount == 0);
+      
+      server_pipe_hash = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, NULL);
+
+      if (!server_pipe_hash)
+        return FALSE;
+    }
+
+  server_pipe_hash_refcount = 1;
+
+  return TRUE;
+}
+
+static void
+pipe_hash_unref (void)
+{
+  _dbus_assert (server_pipe_hash != NULL);
+  _dbus_assert (server_pipe_hash_refcount > 0);
+
+  server_pipe_hash_refcount -= 1;
+  if (server_pipe_hash_refcount == 0)
+    {
+      _dbus_hash_table_unref (server_pipe_hash);
+      server_pipe_hash = NULL;
+    }
+}
+
+static void
+debug_finalize (DBusServer *server)
+{
+  DBusServerDebugPipe *debug_server = (DBusServerDebugPipe*) server;
+
+  pipe_hash_unref ();
+  
+  _dbus_server_finalize_base (server);
+
+  dbus_free (debug_server->name);
+  dbus_free (server);
+}
+
+static void
+debug_disconnect (DBusServer *server)
+{
+  ((DBusServerDebugPipe*)server)->disconnected = TRUE;
+}
+
+static DBusServerVTable debug_vtable = {
+  debug_finalize,
+  debug_disconnect
+};
+
+/**
+ * Creates a new debug server using an in-process pipe
+ *
+ * @param server_name the name of the server.
+ * @param error address where an error can be returned.
+ * @returns a new server, or #NULL on failure.
+ */
+DBusServer*
+_dbus_server_debug_pipe_new (const char     *server_name,
+                             DBusError      *error)
+{
+  DBusServerDebugPipe *debug_server;
+  DBusString address;
+  DBusString name_str;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  if (!pipe_hash_ref ())
+    return NULL;
+  
+  if (_dbus_hash_table_lookup_string (server_pipe_hash, server_name) != NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_ADDRESS_IN_USE, NULL);
+      pipe_hash_unref ();
+      return NULL;
+    }
+  
+  debug_server = dbus_new0 (DBusServerDebugPipe, 1);
+  if (debug_server == NULL)
+    goto nomem_0;
+
+  if (!_dbus_string_init (&address))
+    goto nomem_1;
+
+  _dbus_string_init_const (&name_str, server_name);
+  if (!_dbus_string_append (&address, "debug-pipe:name=") ||
+      !_dbus_address_append_escaped (&address, &name_str))
+    goto nomem_2;
+  
+  debug_server->name = _dbus_strdup (server_name);
+  if (debug_server->name == NULL)
+    goto nomem_2;
+  
+  if (!_dbus_server_init_base (&debug_server->base,
+			       &debug_vtable, &address))
+    goto nomem_3;
+
+  if (!_dbus_hash_table_insert_string (server_pipe_hash,
+				       debug_server->name,
+				       debug_server))
+    goto nomem_4;
+
+  _dbus_string_free (&address);
+
+  /* server keeps the pipe hash ref */
+
+  _dbus_server_trace_ref (&debug_server->base, 0, 1, "debug_pipe_new");
+  return (DBusServer *)debug_server;
+
+ nomem_4:
+  _dbus_server_finalize_base (&debug_server->base);
+ nomem_3:
+  dbus_free (debug_server->name);
+ nomem_2:
+  _dbus_string_free (&address);
+ nomem_1:
+  dbus_free (debug_server);
+ nomem_0:
+  pipe_hash_unref ();
+  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+  return NULL;
+}
+
+/**
+ * Creates the client-side transport for
+ * a debug-pipe connection connected to the
+ * given debug-pipe server name.
+ * 
+ * @param server_name name of server to connect to
+ * @param error address where an error can be returned.
+ * @returns #NULL on no memory or transport
+ */
+DBusTransport*
+_dbus_transport_debug_pipe_new (const char     *server_name,
+                                DBusError      *error)
+{
+  DBusTransport *client_transport;
+  DBusTransport *server_transport;
+  DBusConnection *connection;
+  int client_fd, server_fd;
+  DBusServer *server;
+  DBusString address;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (server_pipe_hash == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
+      return NULL;
+    }
+  
+  server = _dbus_hash_table_lookup_string (server_pipe_hash,
+                                           server_name);
+  if (server == NULL ||
+      ((DBusServerDebugPipe*)server)->disconnected)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
+      return NULL;
+    }
+
+  if (!_dbus_string_init (&address))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  if (!_dbus_string_append (&address, "debug-pipe:name=") ||
+      !_dbus_string_append (&address, server_name))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&address);
+      return NULL;
+    }
+  
+  if (!_dbus_full_duplex_pipe (&client_fd, &server_fd, FALSE,
+                               NULL))
+    {
+      _dbus_verbose ("failed to create full duplex pipe\n");
+      dbus_set_error (error, DBUS_ERROR_FAILED, "Could not create full-duplex pipe");
+      _dbus_string_free (&address);
+      return NULL;
+    }
+
+  client_transport = _dbus_transport_new_for_socket (client_fd,
+                                                     NULL, &address);
+  if (client_transport == NULL)
+    {
+      _dbus_close_socket (client_fd, NULL);
+      _dbus_close_socket (server_fd, NULL);
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_string_free (&address);
+      return NULL;
+    }
+
+  _dbus_string_free (&address);
+  
+  client_fd = -1;
+
+  server_transport = _dbus_transport_new_for_socket (server_fd,
+                                                     &server->guid_hex, NULL);
+  if (server_transport == NULL)
+    {
+      _dbus_transport_unref (client_transport);
+      _dbus_close_socket (server_fd, NULL);
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  server_fd = -1;
+
+  if (!_dbus_transport_set_auth_mechanisms (server_transport,
+                                            (const char**) server->auth_mechanisms))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_transport_unref (server_transport);
+      _dbus_transport_unref (client_transport);
+      return NULL;
+    }
+  
+  connection = _dbus_connection_new_for_transport (server_transport);
+  _dbus_transport_unref (server_transport);
+  server_transport = NULL;
+  
+  if (connection == NULL)
+    {
+      _dbus_transport_unref (client_transport);
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  /* See if someone wants to handle this new connection,
+   * self-referencing for paranoia
+   */
+  if (server->new_connection_function)
+    {
+      dbus_server_ref (server);
+      (* server->new_connection_function) (server, connection,
+                                           server->new_connection_data);
+      dbus_server_unref (server);
+    }
+  
+  /* If no one grabbed a reference, the connection will die,
+   * and the client transport will get an immediate disconnect
+   */
+  _dbus_connection_close_if_only_one_ref (connection);
+  dbus_connection_unref (connection);
+
+  return client_transport;
+}
+
+/**
+ * Tries to interpret the address entry as a debug pipe entry.
+ * 
+ * Sets error if the result is not OK.
+ * 
+ * @param entry an address entry
+ * @param server_p location to store a new DBusServer, or #NULL on failure.
+ * @param error location to store rationale for failure on bad address
+ * @returns the outcome
+ * 
+ */
+DBusServerListenResult
+_dbus_server_listen_debug_pipe (DBusAddressEntry *entry,
+                                DBusServer      **server_p,
+                                DBusError        *error)
+{
+  const char *method;
+
+  *server_p = NULL;
+  
+  method = dbus_address_entry_get_method (entry);
+  
+  if (strcmp (method, "debug-pipe") == 0)
+    {
+      const char *name = dbus_address_entry_get_value (entry, "name");
+      
+      if (name == NULL)
+        {
+          _dbus_set_bad_address(error, "debug-pipe", "name",
+                                NULL);
+          return DBUS_SERVER_LISTEN_BAD_ADDRESS;
+        }
+
+      *server_p = _dbus_server_debug_pipe_new (name, error);
+      
+      if (*server_p)
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+          return DBUS_SERVER_LISTEN_OK;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+        }
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+      return DBUS_SERVER_LISTEN_NOT_HANDLED;
+    }
+}
+
+/**
+ * Opens a debug pipe transport, used in the test suite.
+ * 
+ * @param entry the address entry to try opening as debug-pipe
+ * @param transport_p return location for the opened transport
+ * @param error error to be set
+ * @returns result of the attempt
+ */
+DBusTransportOpenResult
+_dbus_transport_open_debug_pipe (DBusAddressEntry  *entry,
+                                 DBusTransport    **transport_p,
+                                 DBusError         *error)
+{
+  const char *method;
+  
+  method = dbus_address_entry_get_method (entry);
+  _dbus_assert (method != NULL);
+
+  if (strcmp (method, "debug-pipe") == 0)
+    {
+      const char *name = dbus_address_entry_get_value (entry, "name");
+
+      if (name == NULL)
+        {
+          _dbus_set_bad_address (error, "debug-pipe", "name",
+                                 NULL);
+          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+        }
+          
+      *transport_p = _dbus_transport_debug_pipe_new (name, error);
+
+      if (*transport_p == NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+          return DBUS_TRANSPORT_OPEN_OK;
+        }      
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+      return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
+    }
+}
+
+
+/** @} */
+
+#endif /* DBUS_BUILD_TESTS */
+
diff --git a/dbus/dbus/dbus-server-debug-pipe.h b/dbus/dbus/dbus-server-debug-pipe.h
new file mode 100644
index 0000000..4574311
--- /dev/null
+++ b/dbus/dbus/dbus-server-debug-pipe.h
@@ -0,0 +1,47 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server-debug-pipe.h In-proc debug server implementation 
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_SERVER_DEBUG_PIPE_H
+#define DBUS_SERVER_DEBUG_PIPE_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-server-protected.h>
+#include <dbus/dbus-transport-protected.h>
+
+DBUS_BEGIN_DECLS
+
+DBusServer*             _dbus_server_debug_pipe_new     (const char        *server_name,
+                                                         DBusError         *error);
+DBusTransport*          _dbus_transport_debug_pipe_new  (const char        *server_name,
+                                                         DBusError         *error);
+DBusServerListenResult  _dbus_server_listen_debug_pipe  (DBusAddressEntry  *entry,
+                                                         DBusServer       **server_p,
+                                                         DBusError         *error);
+DBusTransportOpenResult _dbus_transport_open_debug_pipe (DBusAddressEntry  *entry,
+                                                         DBusTransport    **transport_p,
+                                                         DBusError         *error);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SERVER_DEBUG_PIPE_H */
diff --git a/dbus/dbus/dbus-server-launchd.c b/dbus/dbus/dbus-server-launchd.c
new file mode 100644
index 0000000..db4673c
--- /dev/null
+++ b/dbus/dbus/dbus-server-launchd.c
@@ -0,0 +1,209 @@
+/* dbus-server-launchd.c Server methods for interacting with launchd.
+ * Copyright (C) 2007, Tanner Lovelace <lovelace@wayfarer.org>
+ * Copyright (C) 2008, Colin Walters <walters@verbum.org>
+ * Copyright (C) 2008-2009, Benjamin Reed <rangerrick@befunk.com>
+ * Copyright (C) 2009, Jonas Bähr <jonas.baehr@web.de>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <config.h>
+#include "dbus-server-launchd.h"
+
+/**
+ * @defgroup DBusServerLaunchd DBusServer implementations for Launchd
+ * @ingroup  DBusInternals
+ * @brief Implementation details of DBusServer with Launchd support
+ *
+ * @{
+ */
+
+#ifdef DBUS_ENABLE_LAUNCHD
+#include <launch.h>
+#include <errno.h>
+
+#include "dbus-server-socket.h"
+
+/* put other private launchd functions here */
+
+#endif /* DBUS_ENABLE_LAUNCHD */
+
+/**
+ * @brief Creates a new server from launchd.
+ *
+ * launchd has allocaed a socket for us. We now query launchd for the
+ * file descriptor of this socket and create a server on it.
+ * In addition we inherit launchd's environment which holds a variable
+ * containing the path to the socket. This is used to init the server's
+ * address which is passed to autolaunched services.
+ *
+ * @param launchd_env_var the environment variable which holds the unix path to the socket
+ * @param error location to store reason for failure.
+ * @returns the new server, or #NULL on failure.
+ */
+
+DBusServer *
+_dbus_server_new_for_launchd (const char *launchd_env_var, DBusError * error)
+  {
+#ifdef DBUS_ENABLE_LAUNCHD
+    DBusServer *server;
+    DBusString address;
+    int launchd_fd;
+    launch_data_t sockets_dict, checkin_response;
+    launch_data_t checkin_request;
+    launch_data_t listening_fd_array, listening_fd;
+    launch_data_t environment_dict, environment_param;
+    const char *launchd_socket_path, *display;
+
+    launchd_socket_path = _dbus_getenv (launchd_env_var);
+    display = _dbus_getenv ("DISPLAY");
+
+    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+    if (launchd_socket_path == NULL || *launchd_socket_path == '\0')
+      {
+        dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                        "launchd's environment variable %s is empty, but should contain a socket path.\n", launchd_env_var);
+        return NULL;
+      }
+
+    if (!_dbus_string_init (&address))
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        return NULL;
+      }
+    if (!_dbus_string_append (&address, "unix:path="))
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        goto l_failed_0;
+      }
+    if (!_dbus_string_append (&address, launchd_socket_path))
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        goto l_failed_0;
+      }
+
+    if ((checkin_request = launch_data_new_string (LAUNCH_KEY_CHECKIN)) == NULL)
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                        "launch_data_new_string(\"%s\") Unable to create string.\n",
+                        LAUNCH_KEY_CHECKIN);
+        goto l_failed_0;
+      }
+
+    if ((checkin_response = launch_msg (checkin_request)) == NULL)
+      {
+        dbus_set_error (error, DBUS_ERROR_IO_ERROR,
+                        "launch_msg(\"%s\") IPC failure: %s\n",
+                        LAUNCH_KEY_CHECKIN, strerror (errno));
+        goto l_failed_0;
+      }
+
+    if (LAUNCH_DATA_ERRNO == launch_data_get_type (checkin_response))
+      {
+        dbus_set_error (error, DBUS_ERROR_FAILED, "Check-in failed: %s\n",
+                        strerror (launch_data_get_errno (checkin_response)));
+        goto l_failed_0;
+      }
+
+    sockets_dict =
+      launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_SOCKETS);
+    if (NULL == sockets_dict)
+      {
+        dbus_set_error (error, DBUS_ERROR_IO_ERROR,
+                        "No sockets found to answer requests on!\n");
+        goto l_failed_0;
+      }
+
+    listening_fd_array =
+      launch_data_dict_lookup (sockets_dict, "unix_domain_listener");
+    if (NULL == listening_fd_array)
+      {
+        dbus_set_error (error, DBUS_ERROR_IO_ERROR,
+                        "No known sockets found to answer requests on!\n");
+        goto l_failed_0;
+      }
+
+    if (launch_data_array_get_count (listening_fd_array) != 1)
+      {
+        dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                        "Expected 1 socket from launchd, got %d.\n",
+                        launch_data_array_get_count (listening_fd_array));
+        goto l_failed_0;
+      }
+
+    listening_fd = launch_data_array_get_index (listening_fd_array, 0);
+    launchd_fd = launch_data_get_fd (listening_fd);
+
+    _dbus_fd_set_close_on_exec (launchd_fd);
+
+    if (launchd_fd < 0)
+      {
+        _DBUS_ASSERT_ERROR_IS_SET (error);
+        goto l_failed_0;
+  if (display == NULL || *display == '\0')
+    {
+      environment_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES);
+      if (NULL == environment_dict)
+        {
+          _dbus_warn ("Unable to retrieve user environment from launchd.");
+        }
+      else
+        {
+          environment_param = launch_data_dict_lookup (environment_dict, "DISPLAY");
+          if (NULL == environment_param)
+            {
+              _dbus_warn ("Unable to retrieve DISPLAY from launchd.");
+            }
+          else
+            {
+              display = launch_data_get_string(environment_param);
+              _dbus_setenv ("DISPLAY", display);
+            }
+        }
+    }
+
+      }
+
+    server = _dbus_server_new_for_socket (&launchd_fd, 1, &address, 0);
+    if (server == NULL)
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_SERVER,
+                        "Unable to listen on launchd fd %d.", launchd_fd);
+        goto l_failed_0;
+      }
+
+    _dbus_string_free (&address);
+
+    return server;
+
+  l_failed_0:
+    _dbus_string_free (&address);
+
+    return NULL;
+#else /* DBUS_ENABLE_LAUNCHD */
+    dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                    "address type 'launchd' requested, but launchd support not compiled in");
+    return NULL;
+#endif
+  }
+
+/** @} */
diff --git a/dbus/dbus/dbus-server-launchd.h b/dbus/dbus/dbus-server-launchd.h
new file mode 100644
index 0000000..269b914
--- /dev/null
+++ b/dbus/dbus/dbus-server-launchd.h
@@ -0,0 +1,36 @@
+/* dbus-server-launchd.h Server methods for interacting with launchd.
+* Copyright (C) 2008, Benjamin Reed <rangerrick@befunk.com>
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use, copy,
+* modify, merge, publish, distribute, sublicense, and/or sell copies
+* of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef DBUS_SERVER_LAUNCHD_H
+#define DBUS_SERVER_LAUNCHD_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-server-protected.h>
+
+DBUS_BEGIN_DECLS
+
+DBusServer * _dbus_server_new_for_launchd (const char *launchd_env_var, DBusError * error);
+
+DBUS_END_DECLS
+#endif /* DBUS_SERVER_LAUNCHD_H */
diff --git a/dbus/dbus/dbus-server-protected.h b/dbus/dbus/dbus-server-protected.h
new file mode 100644
index 0000000..dd5234b
--- /dev/null
+++ b/dbus/dbus/dbus-server-protected.h
@@ -0,0 +1,176 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server-protected.h Used by subclasses of DBusServer object (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_SERVER_PROTECTED_H
+#define DBUS_SERVER_PROTECTED_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-threads-internal.h>
+#include <dbus/dbus-server.h>
+#include <dbus/dbus-address.h>
+#include <dbus/dbus-timeout.h>
+#include <dbus/dbus-watch.h>
+#include <dbus/dbus-resources.h>
+#include <dbus/dbus-dataslot.h>
+#include <dbus/dbus-string.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusServerVTable DBusServerVTable;
+
+/**
+ * Virtual table to be implemented by all server "subclasses"
+ */
+struct DBusServerVTable
+{
+  void        (* finalize)      (DBusServer *server);
+  /**< The finalize method must free the server. */
+  
+  void        (* disconnect)    (DBusServer *server);
+  /**< Disconnect this server. */
+};
+
+/**
+ * @ingroup DBusServerInternals
+ * Internals of DBusServer object
+ */
+struct DBusServer
+{
+  DBusAtomic refcount;                        /**< Reference count. */
+  const DBusServerVTable *vtable;             /**< Virtual methods for this instance. */
+  DBusRMutex *mutex;                          /**< Lock on the server object */
+
+  DBusGUID guid;                              /**< Globally unique ID of server */
+
+  DBusString guid_hex;                        /**< Hex-encoded version of GUID */
+  
+  DBusWatchList *watches;                     /**< Our watches */
+  DBusTimeoutList *timeouts;                  /**< Our timeouts */  
+
+  char *address;                              /**< Address this server is listening on. */
+  dbus_bool_t published_address;              /**< flag which indicates that server has published its bus address. */
+
+  int max_connections;                        /**< Max number of connections allowed at once. */
+
+  DBusDataSlotList slot_list;   /**< Data stored by allocated integer ID */
+  
+  DBusNewConnectionFunction  new_connection_function;
+  /**< Callback to invoke when a new connection is created. */
+  void *new_connection_data;
+  /**< Data for new connection callback */
+  DBusFreeFunction new_connection_free_data_function;
+  /**< Callback to invoke to free new_connection_data
+   * when server is finalized or data is replaced.
+   */
+
+  char **auth_mechanisms; /**< Array of allowed authentication mechanisms */
+  
+  unsigned int disconnected : 1;              /**< TRUE if we are disconnected. */
+
+#ifndef DBUS_DISABLE_CHECKS
+  unsigned int have_server_lock : 1; /**< Does someone have the server mutex locked */
+#endif
+};
+
+dbus_bool_t _dbus_server_init_base      (DBusServer             *server,
+                                         const DBusServerVTable *vtable,
+                                         const DBusString       *address);
+void        _dbus_server_finalize_base  (DBusServer             *server);
+dbus_bool_t _dbus_server_add_watch      (DBusServer             *server,
+                                         DBusWatch              *watch);
+void        _dbus_server_remove_watch   (DBusServer             *server,
+                                         DBusWatch              *watch);
+void        _dbus_server_toggle_watch   (DBusServer             *server,
+                                         DBusWatch              *watch,
+                                         dbus_bool_t             enabled);
+dbus_bool_t _dbus_server_add_timeout    (DBusServer             *server,
+                                         DBusTimeout            *timeout);
+void        _dbus_server_remove_timeout (DBusServer             *server,
+                                         DBusTimeout            *timeout);
+void        _dbus_server_toggle_timeout (DBusServer             *server,
+                                         DBusTimeout            *timeout,
+                                         dbus_bool_t             enabled);
+
+void        _dbus_server_ref_unlocked   (DBusServer             *server);
+void        _dbus_server_unref_unlocked (DBusServer             *server);
+
+typedef enum
+{
+  DBUS_SERVER_LISTEN_NOT_HANDLED, /**< we aren't in charge of this address type */
+  DBUS_SERVER_LISTEN_OK,          /**< we set up the listen */
+  DBUS_SERVER_LISTEN_BAD_ADDRESS, /**< malformed address */
+  DBUS_SERVER_LISTEN_DID_NOT_CONNECT, /**< well-formed address but failed to set it up */
+  DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED /**< address is already used */
+} DBusServerListenResult;
+
+DBusServerListenResult _dbus_server_listen_platform_specific (DBusAddressEntry  *entry,
+                                                              DBusServer       **server_p,
+                                                              DBusError         *error);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+void _dbus_server_trace_ref (DBusServer *server,
+    int old_refcount,
+    int new_refcount,
+    const char *why);
+#else
+#define _dbus_server_trace_ref(s,o,n,w) \
+  do \
+  {\
+    (void) (o); \
+    (void) (n); \
+  } while (0)
+#endif
+
+#ifdef DBUS_DISABLE_CHECKS
+#define TOOK_LOCK_CHECK(server)
+#define RELEASING_LOCK_CHECK(server)
+#define HAVE_LOCK_CHECK(server)
+#else
+#define TOOK_LOCK_CHECK(server) do {                \
+    _dbus_assert (!(server)->have_server_lock); \
+    (server)->have_server_lock = TRUE;          \
+  } while (0)
+#define RELEASING_LOCK_CHECK(server) do {            \
+    _dbus_assert ((server)->have_server_lock);   \
+    (server)->have_server_lock = FALSE;          \
+  } while (0)
+#define HAVE_LOCK_CHECK(server)        _dbus_assert ((server)->have_server_lock)
+/* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
+#endif
+
+#define TRACE_LOCKS 0
+
+#define SERVER_LOCK(server)   do {                                              \
+    if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); }   \
+    _dbus_rmutex_lock ((server)->mutex);                                        \
+    TOOK_LOCK_CHECK (server);                                                   \
+  } while (0)
+
+#define SERVER_UNLOCK(server) do {                                                      \
+    if (TRACE_LOCKS) { _dbus_verbose ("UNLOCK\n");  }        \
+    RELEASING_LOCK_CHECK (server);                                                      \
+    _dbus_rmutex_unlock ((server)->mutex);                                              \
+  } while (0)
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SERVER_PROTECTED_H */
diff --git a/dbus/dbus/dbus-server-socket.c b/dbus/dbus/dbus-server-socket.c
new file mode 100644
index 0000000..ae4b602
--- /dev/null
+++ b/dbus/dbus/dbus-server-socket.c
@@ -0,0 +1,586 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server-socket.c Server implementation for sockets
+ *
+ * Copyright (C) 2002, 2003, 2004, 2006  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-server-socket.h"
+#include "dbus-transport-socket.h"
+#include "dbus-connection-internal.h"
+#include "dbus-memory.h"
+#include "dbus-nonce.h"
+#include "dbus-string.h"
+
+/**
+ * @defgroup DBusServerSocket DBusServer implementations for SOCKET
+ * @ingroup  DBusInternals
+ * @brief Implementation details of DBusServer on SOCKET
+ *
+ * @{
+ */
+/**
+ *
+ * Opaque object representing a Socket server implementation.
+ */
+typedef struct DBusServerSocket DBusServerSocket;
+
+/**
+ * Implementation details of DBusServerSocket. All members
+ * are private.
+ */
+struct DBusServerSocket
+{
+  DBusServer base;   /**< Parent class members. */
+  int n_fds;         /**< Number of active file handles */
+  int *fds;          /**< File descriptor or -1 if disconnected. */
+  DBusWatch **watch; /**< File descriptor watch. */
+  char *socket_name; /**< Name of domain socket, to unlink if appropriate */
+  DBusNonceFile *noncefile; /**< Nonce file used to authenticate clients */
+};
+
+static void
+socket_finalize (DBusServer *server)
+{
+  DBusServerSocket *socket_server = (DBusServerSocket*) server;
+  int i;
+
+  _dbus_server_finalize_base (server);
+
+  for (i = 0 ; i < socket_server->n_fds ; i++)
+    if (socket_server->watch[i])
+      {
+        _dbus_watch_unref (socket_server->watch[i]);
+        socket_server->watch[i] = NULL;
+      }
+
+  dbus_free (socket_server->fds);
+  dbus_free (socket_server->watch);
+  dbus_free (socket_server->socket_name);
+  if (socket_server->noncefile)
+	_dbus_noncefile_delete (socket_server->noncefile, NULL);
+  dbus_free (socket_server->noncefile);
+  dbus_free (server);
+}
+
+/* Return value is just for memory, not other failures. */
+static dbus_bool_t
+handle_new_client_fd_and_unlock (DBusServer *server,
+                                 int         client_fd)
+{
+  DBusConnection *connection;
+  DBusTransport *transport;
+  DBusNewConnectionFunction new_connection_function;
+  void *new_connection_data;
+
+  _dbus_verbose ("Creating new client connection with fd %d\n", client_fd);
+
+  HAVE_LOCK_CHECK (server);
+
+  if (!_dbus_set_fd_nonblocking (client_fd, NULL))
+    {
+      SERVER_UNLOCK (server);
+      return TRUE;
+    }
+
+  transport = _dbus_transport_new_for_socket (client_fd, &server->guid_hex, FALSE);
+  if (transport == NULL)
+    {
+      _dbus_close_socket (client_fd, NULL);
+      SERVER_UNLOCK (server);
+      return FALSE;
+    }
+
+  if (!_dbus_transport_set_auth_mechanisms (transport,
+                                            (const char **) server->auth_mechanisms))
+    {
+      _dbus_transport_unref (transport);
+      SERVER_UNLOCK (server);
+      return FALSE;
+    }
+
+  /* note that client_fd is now owned by the transport, and will be
+   * closed on transport disconnection/finalization
+   */
+
+  connection = _dbus_connection_new_for_transport (transport);
+  _dbus_transport_unref (transport);
+  transport = NULL; /* now under the connection lock */
+
+  if (connection == NULL)
+    {
+      SERVER_UNLOCK (server);
+      return FALSE;
+    }
+
+  /* See if someone wants to handle this new connection, self-referencing
+   * for paranoia.
+   */
+  new_connection_function = server->new_connection_function;
+  new_connection_data = server->new_connection_data;
+
+  _dbus_server_ref_unlocked (server);
+  SERVER_UNLOCK (server);
+
+  if (new_connection_function)
+    {
+      (* new_connection_function) (server, connection,
+                                   new_connection_data);
+    }
+  dbus_server_unref (server);
+
+  /* If no one grabbed a reference, the connection will die. */
+  _dbus_connection_close_if_only_one_ref (connection);
+  dbus_connection_unref (connection);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+socket_handle_watch (DBusWatch    *watch,
+                   unsigned int  flags,
+                   void         *data)
+{
+  DBusServer *server = data;
+  DBusServerSocket *socket_server = data;
+
+#ifndef DBUS_DISABLE_ASSERT
+  int i;
+  dbus_bool_t found = FALSE;
+#endif
+
+  SERVER_LOCK (server);
+
+#ifndef DBUS_DISABLE_ASSERT
+  for (i = 0 ; i < socket_server->n_fds ; i++)
+    {
+      if (socket_server->watch[i] == watch)
+        found = TRUE;
+    }
+  _dbus_assert (found);
+#endif
+
+  _dbus_verbose ("Handling client connection, flags 0x%x\n", flags);
+
+  if (flags & DBUS_WATCH_READABLE)
+    {
+      int client_fd;
+      int listen_fd;
+
+      listen_fd = dbus_watch_get_socket (watch);
+
+      if (socket_server->noncefile)
+          client_fd = _dbus_accept_with_noncefile (listen_fd, socket_server->noncefile);
+      else 
+          client_fd = _dbus_accept (listen_fd);
+
+      if (client_fd < 0)
+        {
+          /* EINTR handled for us */
+
+          if (_dbus_get_is_errno_eagain_or_ewouldblock ())
+            _dbus_verbose ("No client available to accept after all\n");
+          else
+            _dbus_verbose ("Failed to accept a client connection: %s\n",
+                           _dbus_strerror_from_errno ());
+
+          SERVER_UNLOCK (server);
+        }
+      else
+        {
+          if (!handle_new_client_fd_and_unlock (server, client_fd))
+            _dbus_verbose ("Rejected client connection due to lack of memory\n");
+        }
+    }
+
+  if (flags & DBUS_WATCH_ERROR)
+    _dbus_verbose ("Error on server listening socket\n");
+
+  if (flags & DBUS_WATCH_HANGUP)
+    _dbus_verbose ("Hangup on server listening socket\n");
+
+  return TRUE;
+}
+
+static void
+socket_disconnect (DBusServer *server)
+{
+  DBusServerSocket *socket_server = (DBusServerSocket*) server;
+  int i;
+
+  HAVE_LOCK_CHECK (server);
+
+  for (i = 0 ; i < socket_server->n_fds ; i++)
+    {
+      if (socket_server->watch[i])
+        {
+          _dbus_server_remove_watch (server,
+                                     socket_server->watch[i]);
+          _dbus_watch_invalidate (socket_server->watch[i]);
+          _dbus_watch_unref (socket_server->watch[i]);
+          socket_server->watch[i] = NULL;
+        }
+
+      _dbus_close_socket (socket_server->fds[i], NULL);
+      socket_server->fds[i] = -1;
+    }
+
+  if (socket_server->socket_name != NULL)
+    {
+      DBusString tmp;
+      _dbus_string_init_const (&tmp, socket_server->socket_name);
+      _dbus_delete_file (&tmp, NULL);
+    }
+
+  if (server->published_address)
+      _dbus_daemon_unpublish_session_bus_address();
+
+  HAVE_LOCK_CHECK (server);
+}
+
+static const DBusServerVTable socket_vtable = {
+  socket_finalize,
+  socket_disconnect
+};
+
+/**
+ * Creates a new server listening on the given file descriptor.  The
+ * file descriptor should be nonblocking (use
+ * _dbus_set_fd_nonblocking() to make it so). The file descriptor
+ * should be listening for connections, that is, listen() should have
+ * been successfully invoked on it. The server will use accept() to
+ * accept new client connections.
+ *
+ * @param fds list of file descriptors.
+ * @param n_fds number of file descriptors
+ * @param address the server's address
+ * @param noncefile to be used for authentication (NULL if not needed)
+ * @returns the new server, or #NULL if no memory.
+ *
+ */
+DBusServer*
+_dbus_server_new_for_socket (int              *fds,
+                             int               n_fds,
+                             const DBusString *address,
+                             DBusNonceFile    *noncefile)
+{
+  DBusServerSocket *socket_server;
+  DBusServer *server;
+  int i;
+
+  socket_server = dbus_new0 (DBusServerSocket, 1);
+  if (socket_server == NULL)
+    return NULL;
+
+  socket_server->noncefile = noncefile;
+
+  socket_server->fds = dbus_new (int, n_fds);
+  if (!socket_server->fds)
+    goto failed_0;
+
+  socket_server->watch = dbus_new0 (DBusWatch *, n_fds);
+  if (!socket_server->watch)
+    goto failed_1;
+
+  for (i = 0 ; i < n_fds ; i++)
+    {
+      DBusWatch *watch;
+
+      watch = _dbus_watch_new (fds[i],
+                               DBUS_WATCH_READABLE,
+                               TRUE,
+                               socket_handle_watch, socket_server,
+                               NULL);
+      if (watch == NULL)
+        goto failed_2;
+
+      socket_server->n_fds++;
+      socket_server->fds[i] = fds[i];
+      socket_server->watch[i] = watch;
+    }
+
+  if (!_dbus_server_init_base (&socket_server->base,
+                               &socket_vtable, address))
+    goto failed_2;
+
+  server = (DBusServer*)socket_server;
+
+  SERVER_LOCK (server);
+
+  for (i = 0 ; i < n_fds ; i++)
+    {
+      if (!_dbus_server_add_watch (&socket_server->base,
+                                   socket_server->watch[i]))
+        {
+          int j;
+          for (j = 0 ; j < i ; j++)
+            _dbus_server_remove_watch (server,
+                                       socket_server->watch[j]);
+
+          SERVER_UNLOCK (server);
+          _dbus_server_finalize_base (&socket_server->base);
+          goto failed_2;
+        }
+    }
+
+  SERVER_UNLOCK (server);
+
+  _dbus_server_trace_ref (&socket_server->base, 0, 1, "new_for_socket");
+  return (DBusServer*) socket_server;
+
+ failed_2:
+  for (i = 0 ; i < n_fds ; i++)
+    {
+      if (socket_server->watch[i] != NULL)
+        {
+          _dbus_watch_unref (socket_server->watch[i]);
+          socket_server->watch[i] = NULL;
+        }
+    }
+  dbus_free (socket_server->watch);
+
+ failed_1:
+  dbus_free (socket_server->fds);
+
+ failed_0:
+  dbus_free (socket_server);
+  return NULL;
+}
+
+/**
+ * Creates a new server listening on TCP.
+ * If host is NULL, it will default to localhost.
+ * If bind is NULL, it will default to the value for the host
+ * parameter, and if that is NULL, then localhost
+ * If bind is a hostname, it will be resolved and will listen
+ * on all returned addresses.
+ * If family is NULL, hostname resolution will try all address
+ * families, otherwise it can be ipv4 or ipv6 to restrict the
+ * addresses considered.
+ *
+ * @param host the hostname to report for the listen address
+ * @param bind the hostname to listen on
+ * @param port the port to listen on or 0 to let the OS choose
+ * @param family
+ * @param error location to store reason for failure.
+ * @param use_nonce whether to use a nonce for low-level authentication (nonce-tcp transport) or not (tcp transport)
+ * @returns the new server, or #NULL on failure.
+ */
+DBusServer*
+_dbus_server_new_for_tcp_socket (const char     *host,
+                                 const char     *bind,
+                                 const char     *port,
+                                 const char     *family,
+                                 DBusError      *error,
+                                 dbus_bool_t    use_nonce)
+{
+  DBusServer *server;
+  int *listen_fds = NULL;
+  int nlisten_fds = 0, i;
+  DBusString address;
+  DBusString host_str;
+  DBusString port_str;
+  DBusNonceFile *noncefile;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  noncefile = NULL;
+
+  if (!_dbus_string_init (&address))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  if (!_dbus_string_init (&port_str))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed_0;
+    }
+
+  if (host == NULL)
+    host = "localhost";
+
+  if (port == NULL)
+    port = "0";
+
+  if (bind == NULL)
+    bind = host;
+  else if (strcmp (bind, "*") == 0)
+    bind = NULL;
+
+  nlisten_fds =_dbus_listen_tcp_socket (bind, port, family,
+                                        &port_str,
+                                        &listen_fds, error);
+  if (nlisten_fds <= 0)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET(error);
+      goto failed_1;
+    }
+
+  _dbus_string_init_const (&host_str, host);
+  if (!_dbus_string_append (&address, use_nonce ? "nonce-tcp:host=" : "tcp:host=") ||
+      !_dbus_address_append_escaped (&address, &host_str) ||
+      !_dbus_string_append (&address, ",port=") ||
+      !_dbus_string_append (&address, _dbus_string_get_const_data(&port_str)))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed_2;
+    }
+  if (family &&
+      (!_dbus_string_append (&address, ",family=") ||
+       !_dbus_string_append (&address, family)))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed_2;
+    }
+
+  if (use_nonce)
+    {
+      noncefile = dbus_new0 (DBusNonceFile, 1);
+      if (noncefile == NULL)
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          goto failed_2;
+        }
+
+      if (!_dbus_noncefile_create (noncefile, error))
+          goto failed_3;
+
+      if (!_dbus_string_append (&address, ",noncefile=") ||
+          !_dbus_address_append_escaped (&address, _dbus_noncefile_get_path (noncefile)))
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          goto failed_4;
+        }
+
+    }
+
+  server = _dbus_server_new_for_socket (listen_fds, nlisten_fds, &address, noncefile);
+  if (server == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed_4;
+    }
+
+  _dbus_string_free (&port_str);
+  _dbus_string_free (&address);
+  dbus_free(listen_fds);
+
+  return server;
+
+ failed_4:
+  _dbus_noncefile_delete (noncefile, NULL);
+
+ failed_3:
+  dbus_free (noncefile);
+
+ failed_2:
+  for (i = 0 ; i < nlisten_fds ; i++)
+    _dbus_close_socket (listen_fds[i], NULL);
+  dbus_free(listen_fds);
+
+ failed_1:
+  _dbus_string_free (&port_str);
+
+ failed_0:
+  _dbus_string_free (&address);
+
+  return NULL;
+}
+
+/**
+ * Tries to interpret the address entry for various socket-related
+ * addresses (well, currently only tcp and nonce-tcp).
+ *
+ * Sets error if the result is not OK.
+ *
+ * @param entry an address entry
+ * @param server_p a new DBusServer, or #NULL on failure.
+ * @param error location to store rationale for failure on bad address
+ * @returns the outcome
+ *
+ */
+DBusServerListenResult
+_dbus_server_listen_socket (DBusAddressEntry *entry,
+                            DBusServer      **server_p,
+                            DBusError        *error)
+{
+  const char *method;
+
+  *server_p = NULL;
+
+  method = dbus_address_entry_get_method (entry);
+
+  if (strcmp (method, "tcp") == 0 || strcmp (method, "nonce-tcp") == 0)
+    {
+      const char *host;
+      const char *port;
+      const char *bind;
+      const char *family;
+
+      host = dbus_address_entry_get_value (entry, "host");
+      bind = dbus_address_entry_get_value (entry, "bind");
+      port = dbus_address_entry_get_value (entry, "port");
+      family = dbus_address_entry_get_value (entry, "family");
+
+      *server_p = _dbus_server_new_for_tcp_socket (host, bind, port,
+                                                   family, error, strcmp (method, "nonce-tcp") == 0 ? TRUE : FALSE);
+
+      if (*server_p)
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+          return DBUS_SERVER_LISTEN_OK;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+        }
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+      return DBUS_SERVER_LISTEN_NOT_HANDLED;
+    }
+}
+
+/**
+ * This is a bad hack since it's really unix domain socket
+ * specific. Also, the function weirdly adopts ownership
+ * of the passed-in string.
+ *
+ * @param server a socket server
+ * @param filename socket filename to report/delete
+ *
+ */
+void
+_dbus_server_socket_own_filename (DBusServer *server,
+                                  char       *filename)
+{
+  DBusServerSocket *socket_server = (DBusServerSocket*) server;
+
+  socket_server->socket_name = filename;
+}
+
+
+/** @} */
+
diff --git a/dbus/dbus/dbus-server-socket.h b/dbus/dbus/dbus-server-socket.h
new file mode 100644
index 0000000..3aec712
--- /dev/null
+++ b/dbus/dbus/dbus-server-socket.h
@@ -0,0 +1,54 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server-socket.h Server implementation for sockets
+ *
+ * Copyright (C) 2002, 2006  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_SERVER_SOCKET_H
+#define DBUS_SERVER_SOCKET_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-server-protected.h>
+#include <dbus/dbus-nonce.h>
+
+DBUS_BEGIN_DECLS
+
+DBusServer* _dbus_server_new_for_socket           (int              *fds,
+                                                   int               n_fds,
+                                                   const DBusString *address,
+                                                   DBusNonceFile    *noncefile);
+DBusServer* _dbus_server_new_for_autolaunch       (const DBusString *address,
+                                                   DBusError        *error);
+DBusServer* _dbus_server_new_for_tcp_socket       (const char       *host,
+                                                   const char       *bind,
+                                                   const char       *port,
+                                                   const char       *family,
+                                                   DBusError        *error,
+                                                   dbus_bool_t      use_nonce);
+DBusServerListenResult _dbus_server_listen_socket (DBusAddressEntry  *entry,
+                                                   DBusServer       **server_p,
+                                                   DBusError         *error);
+
+
+void _dbus_server_socket_own_filename (DBusServer *server,
+                                       char       *filename);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SERVER_SOCKET_H */
diff --git a/dbus/dbus/dbus-server-unix.c b/dbus/dbus/dbus-server-unix.c
new file mode 100644
index 0000000..130f66e
--- /dev/null
+++ b/dbus/dbus/dbus-server-unix.c
@@ -0,0 +1,300 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server-unix.c Server implementation for Unix network protocols.
+ *
+ * Copyright (C) 2002, 2003, 2004  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-server-unix.h"
+#include "dbus-server-socket.h"
+#include "dbus-server-launchd.h"
+#include "dbus-transport-unix.h"
+#include "dbus-connection-internal.h"
+#include "dbus-sysdeps-unix.h"
+#include "dbus-string.h"
+
+/**
+ * @defgroup DBusServerUnix DBusServer implementations for UNIX
+ * @ingroup  DBusInternals
+ * @brief Implementation details of DBusServer on UNIX
+ *
+ * @{
+ */
+
+/**
+ * Tries to interpret the address entry in a platform-specific
+ * way, creating a platform-specific server type if appropriate.
+ * Sets error if the result is not OK.
+ *
+ * @param entry an address entry
+ * @param server_p location to store a new DBusServer, or #NULL on failure.
+ * @param error location to store rationale for failure on bad address
+ * @returns the outcome
+ *
+ */
+DBusServerListenResult
+_dbus_server_listen_platform_specific (DBusAddressEntry *entry,
+                                       DBusServer      **server_p,
+                                       DBusError        *error)
+{
+  const char *method;
+
+  *server_p = NULL;
+
+  method = dbus_address_entry_get_method (entry);
+
+  if (strcmp (method, "unix") == 0)
+    {
+      const char *path = dbus_address_entry_get_value (entry, "path");
+      const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
+      const char *abstract = dbus_address_entry_get_value (entry, "abstract");
+
+      if (path == NULL && tmpdir == NULL && abstract == NULL)
+        {
+          _dbus_set_bad_address(error, "unix",
+                                "path or tmpdir or abstract",
+                                NULL);
+          return DBUS_SERVER_LISTEN_BAD_ADDRESS;
+        }
+
+      if ((path && tmpdir) ||
+          (path && abstract) ||
+          (tmpdir && abstract))
+        {
+          _dbus_set_bad_address(error, NULL, NULL,
+                                "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time");
+          return DBUS_SERVER_LISTEN_BAD_ADDRESS;
+        }
+
+      if (tmpdir != NULL)
+        {
+          DBusString full_path;
+          DBusString filename;
+
+          if (!_dbus_string_init (&full_path))
+            {
+              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+              return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+            }
+
+          if (!_dbus_string_init (&filename))
+            {
+              _dbus_string_free (&full_path);
+              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+              return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+            }
+
+          if (!_dbus_string_append (&filename,
+                                    "dbus-") ||
+              !_dbus_generate_random_ascii (&filename, 10) ||
+              !_dbus_string_append (&full_path, tmpdir) ||
+              !_dbus_concat_dir_and_file (&full_path, &filename))
+            {
+              _dbus_string_free (&full_path);
+              _dbus_string_free (&filename);
+              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+              return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+            }
+
+          /* Always use abstract namespace if possible with tmpdir */
+
+          *server_p =
+            _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
+#ifdef HAVE_ABSTRACT_SOCKETS
+                                                TRUE,
+#else
+                                                FALSE,
+#endif
+                                                error);
+
+          _dbus_string_free (&full_path);
+          _dbus_string_free (&filename);
+        }
+      else
+        {
+          if (path)
+            *server_p = _dbus_server_new_for_domain_socket (path, FALSE, error);
+          else
+            *server_p = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
+        }
+
+      if (*server_p != NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+          return DBUS_SERVER_LISTEN_OK;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+        }
+    }
+  else if (strcmp (method, "systemd") == 0)
+    {
+      int n, *fds;
+      DBusString address;
+
+      n = _dbus_listen_systemd_sockets (&fds, error);
+      if (n < 0)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+        }
+
+      _dbus_string_init_const (&address, "systemd:");
+
+      *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL);
+      if (*server_p == NULL)
+        {
+          int i;
+
+          for (i = 0; i < n; i++)
+            {
+              _dbus_close_socket (fds[i], NULL);
+            }
+          dbus_free (fds);
+
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+        }
+
+      dbus_free (fds);
+
+      return DBUS_SERVER_LISTEN_OK;
+	}
+#ifdef DBUS_ENABLE_LAUNCHD
+  else if (strcmp (method, "launchd") == 0)
+    {
+      const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
+      if (launchd_env_var == NULL)
+        {
+          _dbus_set_bad_address (error, "launchd", "env", NULL);
+          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+        }
+      *server_p = _dbus_server_new_for_launchd (launchd_env_var, error);
+
+      if (*server_p != NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+          return DBUS_SERVER_LISTEN_OK;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+        }
+    }
+#endif
+  else
+    {
+      /* If we don't handle the method, we return NULL with the
+       * error unset
+       */
+      _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+      return DBUS_SERVER_LISTEN_NOT_HANDLED;
+    }
+}
+
+/**
+ * Creates a new server listening on the given Unix domain socket.
+ *
+ * @param path the path for the domain socket.
+ * @param abstract #TRUE to use abstract socket namespace
+ * @param error location to store reason for failure.
+ * @returns the new server, or #NULL on failure.
+ */
+DBusServer*
+_dbus_server_new_for_domain_socket (const char     *path,
+                                    dbus_bool_t     abstract,
+                                    DBusError      *error)
+{
+  DBusServer *server;
+  int listen_fd;
+  DBusString address;
+  char *path_copy;
+  DBusString path_str;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (!_dbus_string_init (&address))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  _dbus_string_init_const (&path_str, path);
+  if ((abstract &&
+       !_dbus_string_append (&address, "unix:abstract=")) ||
+      (!abstract &&
+       !_dbus_string_append (&address, "unix:path=")) ||
+      !_dbus_address_append_escaped (&address, &path_str))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed_0;
+    }
+
+  if (abstract)
+    {
+      path_copy = NULL;
+    }
+  else
+    {
+      path_copy = _dbus_strdup (path);
+      if (path_copy == NULL)
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          goto failed_0;
+        }
+    }
+
+  listen_fd = _dbus_listen_unix_socket (path, abstract, error);
+
+  if (listen_fd < 0)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed_1;
+    }
+
+  server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0);
+  if (server == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed_2;
+    }
+
+  if (path_copy != NULL)
+    _dbus_server_socket_own_filename(server, path_copy);
+
+  _dbus_string_free (&address);
+
+  return server;
+
+ failed_2:
+  _dbus_close_socket (listen_fd, NULL);
+ failed_1:
+  dbus_free (path_copy);
+ failed_0:
+  _dbus_string_free (&address);
+
+  return NULL;
+}
+
+/** @} */
diff --git a/dbus/dbus/dbus-server-unix.h b/dbus/dbus/dbus-server-unix.h
new file mode 100644
index 0000000..92b996c
--- /dev/null
+++ b/dbus/dbus/dbus-server-unix.h
@@ -0,0 +1,37 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server-unix.h Server implementation for Unix network protocols.
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_SERVER_UNIX_H
+#define DBUS_SERVER_UNIX_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-server-protected.h>
+
+DBUS_BEGIN_DECLS
+
+DBusServer* _dbus_server_new_for_domain_socket (const char       *path,
+                                                dbus_bool_t       abstract,
+                                                DBusError        *error);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SERVER_UNIX_H */
diff --git a/dbus/dbus/dbus-server-win.c b/dbus/dbus/dbus-server-win.c
new file mode 100644
index 0000000..bb6da48
--- /dev/null
+++ b/dbus/dbus/dbus-server-win.c
@@ -0,0 +1,96 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server-win.c Server implementation for WIN network protocols.
+ *
+ * Copyright (C) 2002, 2003, 2004  Red Hat Inc.
+ * Copyright (C) 2007 Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-server-win.h"
+#include "dbus-server-socket.h"
+
+/**
+ * @defgroup DBusServerWin DBusServer implementations for Windows
+ * @ingroup  DBusInternals
+ * @brief Implementation details of DBusServer on Windows 
+ *
+ * @{
+ */
+
+/**
+ * Tries to interpret the address entry in a platform-specific
+ * way, creating a platform-specific server type if appropriate.
+ * Sets error if the result is not OK.
+ * 
+ * @param entry an address entry
+ * @param server_p location to store a new DBusServer, or #NULL on failure.
+ * @param error location to store rationale for failure on bad address
+ * @returns the outcome
+ * 
+ */
+DBusServerListenResult
+_dbus_server_listen_platform_specific (DBusAddressEntry *entry,
+                                       DBusServer      **server_p,
+                                       DBusError        *error)
+{
+  const char *method;
+
+  *server_p  = NULL;
+
+  method = dbus_address_entry_get_method (entry);
+
+  if (strcmp (method, "autolaunch") == 0)
+    {
+      const char *host = "localhost";
+      const char *bind = "localhost";
+      const char *port = "0";
+      const char *family = "ipv4";
+      const char *scope = dbus_address_entry_get_value (entry, "scope");
+
+      if (_dbus_daemon_is_session_bus_address_published (scope))
+          return DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED;
+
+      *server_p = _dbus_server_new_for_tcp_socket (host, bind, port,
+                                                   family, error, FALSE);
+      if (*server_p)
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+          (*server_p)->published_address =
+              _dbus_daemon_publish_session_bus_address ((*server_p)->address, scope);
+          return DBUS_SERVER_LISTEN_OK;
+        }
+      else
+        {
+          // make sure no handle is open
+          _dbus_daemon_unpublish_session_bus_address ();
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+        }
+    }
+  else
+    {
+       _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+       return DBUS_SERVER_LISTEN_NOT_HANDLED;
+    }
+}
+
+/** @} */
+
diff --git a/dbus/dbus/dbus-server-win.h b/dbus/dbus/dbus-server-win.h
new file mode 100644
index 0000000..65c2756
--- /dev/null
+++ b/dbus/dbus/dbus-server-win.h
@@ -0,0 +1,36 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server-win.h Server implementation for windows network protocols.
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ * Copyright (C) 2007  Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_SERVER_WIN_H
+#define DBUS_SERVER_WIN_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-server-protected.h>
+
+DBUS_BEGIN_DECLS
+
+/* add definitions here */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SERVER_WIN_H */
diff --git a/dbus/dbus/dbus-server.c b/dbus/dbus/dbus-server.c
new file mode 100644
index 0000000..b62c2b4
--- /dev/null
+++ b/dbus/dbus/dbus-server.c
@@ -0,0 +1,1249 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server.c DBusServer object
+ *
+ * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */ 
+
+#include <config.h>
+#include "dbus-server.h"
+#include "dbus-server-unix.h"
+#include "dbus-server-socket.h"
+#include "dbus-string.h"
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-server-debug-pipe.h"
+#endif
+#include "dbus-address.h"
+#include "dbus-protocol.h"
+
+/**
+ * @defgroup DBusServer DBusServer
+ * @ingroup  DBus
+ * @brief Server that listens for new connections.
+ *
+ * A DBusServer represents a server that other applications
+ * can connect to. Each connection from another application
+ * is represented by a #DBusConnection.
+ *
+ * @todo Thread safety hasn't been tested much for #DBusServer
+ * @todo Need notification to apps of disconnection, may matter for some transports
+ */
+
+/**
+ * @defgroup DBusServerInternals DBusServer implementation details
+ * @ingroup  DBusInternals
+ * @brief Implementation details of DBusServer
+ *
+ * @{
+ */
+
+#ifndef _dbus_server_trace_ref
+void
+_dbus_server_trace_ref (DBusServer *server,
+    int old_refcount,
+    int new_refcount,
+    const char *why)
+{
+  static int enabled = -1;
+
+  _dbus_trace_ref ("DBusServer", server, old_refcount, new_refcount, why,
+      "DBUS_SERVER_TRACE", &enabled);
+}
+#endif
+
+/* this is a little fragile since it assumes the address doesn't
+ * already have a guid, but it shouldn't
+ */
+static char*
+copy_address_with_guid_appended (const DBusString *address,
+                                 const DBusString *guid_hex)
+{
+  DBusString with_guid;
+  char *retval;
+  
+  if (!_dbus_string_init (&with_guid))
+    return NULL;
+
+  if (!_dbus_string_copy (address, 0, &with_guid,
+                          _dbus_string_get_length (&with_guid)) ||
+      !_dbus_string_append (&with_guid, ",guid=") ||
+      !_dbus_string_copy (guid_hex, 0,
+                          &with_guid, _dbus_string_get_length (&with_guid)))
+    {
+      _dbus_string_free (&with_guid);
+      return NULL;
+    }
+
+  retval = NULL;
+  _dbus_string_steal_data (&with_guid, &retval);
+
+  _dbus_string_free (&with_guid);
+      
+  return retval; /* may be NULL if steal_data failed */
+}
+
+/**
+ * Initializes the members of the DBusServer base class.
+ * Chained up to by subclass constructors.
+ *
+ * @param server the server.
+ * @param vtable the vtable for the subclass.
+ * @param address the server's address
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_server_init_base (DBusServer             *server,
+                        const DBusServerVTable *vtable,
+                        const DBusString       *address)
+{
+  server->vtable = vtable;
+
+#ifdef DBUS_DISABLE_ASSERT
+  _dbus_atomic_inc (&server->refcount);
+#else
+    {
+      dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount);
+
+      _dbus_assert (old_refcount == 0);
+    }
+#endif
+
+  server->address = NULL;
+  server->watches = NULL;
+  server->timeouts = NULL;
+  server->published_address = FALSE;
+
+  if (!_dbus_string_init (&server->guid_hex))
+    return FALSE;
+
+  _dbus_generate_uuid (&server->guid);
+
+  if (!_dbus_uuid_encode (&server->guid, &server->guid_hex))
+    goto failed;
+  
+  server->address = copy_address_with_guid_appended (address,
+                                                     &server->guid_hex);
+  if (server->address == NULL)
+    goto failed;
+  
+  _dbus_rmutex_new_at_location (&server->mutex);
+  if (server->mutex == NULL)
+    goto failed;
+  
+  server->watches = _dbus_watch_list_new ();
+  if (server->watches == NULL)
+    goto failed;
+
+  server->timeouts = _dbus_timeout_list_new ();
+  if (server->timeouts == NULL)
+    goto failed;
+
+  _dbus_data_slot_list_init (&server->slot_list);
+
+  _dbus_verbose ("Initialized server on address %s\n", server->address);
+  
+  return TRUE;
+
+ failed:
+  _dbus_rmutex_free_at_location (&server->mutex);
+  server->mutex = NULL;
+  if (server->watches)
+    {
+      _dbus_watch_list_free (server->watches);
+      server->watches = NULL;
+    }
+  if (server->timeouts)
+    {
+      _dbus_timeout_list_free (server->timeouts);
+      server->timeouts = NULL;
+    }
+  if (server->address)
+    {
+      dbus_free (server->address);
+      server->address = NULL;
+    }
+  _dbus_string_free (&server->guid_hex);
+  
+  return FALSE;
+}
+
+/**
+ * Finalizes the members of the DBusServer base class.
+ * Chained up to by subclass finalizers.
+ *
+ * @param server the server.
+ */
+void
+_dbus_server_finalize_base (DBusServer *server)
+{
+  /* We don't have the lock, but nobody should be accessing
+   * concurrently since they don't have a ref
+   */
+#ifndef DBUS_DISABLE_CHECKS
+  _dbus_assert (!server->have_server_lock);
+#endif
+  _dbus_assert (server->disconnected);
+  
+  /* calls out to application code... */
+  _dbus_data_slot_list_free (&server->slot_list);
+
+  dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
+
+  _dbus_watch_list_free (server->watches);
+  _dbus_timeout_list_free (server->timeouts);
+
+  _dbus_rmutex_free_at_location (&server->mutex);
+  
+  dbus_free (server->address);
+
+  dbus_free_string_array (server->auth_mechanisms);
+
+  _dbus_string_free (&server->guid_hex);
+}
+
+
+/** Function to be called in protected_change_watch() with refcount held */
+typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
+                                                  DBusWatch     *watch);
+/** Function to be called in protected_change_watch() with refcount held */
+typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
+                                                  DBusWatch     *watch);
+/** Function to be called in protected_change_watch() with refcount held */
+typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
+                                                  DBusWatch     *watch,
+                                                  dbus_bool_t    enabled);
+
+static dbus_bool_t
+protected_change_watch (DBusServer             *server,
+                        DBusWatch              *watch,
+                        DBusWatchAddFunction    add_function,
+                        DBusWatchRemoveFunction remove_function,
+                        DBusWatchToggleFunction toggle_function,
+                        dbus_bool_t             enabled)
+{
+  DBusWatchList *watches;
+  dbus_bool_t retval;
+  
+  HAVE_LOCK_CHECK (server);
+
+  /* This isn't really safe or reasonable; a better pattern is the "do
+   * everything, then drop lock and call out" one; but it has to be
+   * propagated up through all callers
+   */
+  
+  watches = server->watches;
+  if (watches)
+    {
+      server->watches = NULL;
+      _dbus_server_ref_unlocked (server);
+      SERVER_UNLOCK (server);
+
+      if (add_function)
+        retval = (* add_function) (watches, watch);
+      else if (remove_function)
+        {
+          retval = TRUE;
+          (* remove_function) (watches, watch);
+        }
+      else
+        {
+          retval = TRUE;
+          (* toggle_function) (watches, watch, enabled);
+        }
+      
+      SERVER_LOCK (server);
+      server->watches = watches;
+      _dbus_server_unref_unlocked (server);
+
+      return retval;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * Adds a watch for this server, chaining out to application-provided
+ * watch handlers.
+ *
+ * @param server the server.
+ * @param watch the watch to add.
+ */
+dbus_bool_t
+_dbus_server_add_watch (DBusServer *server,
+                        DBusWatch  *watch)
+{
+  HAVE_LOCK_CHECK (server);
+  return protected_change_watch (server, watch,
+                                 _dbus_watch_list_add_watch,
+                                 NULL, NULL, FALSE);
+}
+
+/**
+ * Removes a watch previously added with _dbus_server_remove_watch().
+ *
+ * @param server the server.
+ * @param watch the watch to remove.
+ */
+void
+_dbus_server_remove_watch  (DBusServer *server,
+                            DBusWatch  *watch)
+{
+  HAVE_LOCK_CHECK (server);
+  protected_change_watch (server, watch,
+                          NULL,
+                          _dbus_watch_list_remove_watch,
+                          NULL, FALSE);
+}
+
+/**
+ * Toggles a watch and notifies app via server's
+ * DBusWatchToggledFunction if available. It's an error to call this
+ * function on a watch that was not previously added.
+ *
+ * @param server the server.
+ * @param watch the watch to toggle.
+ * @param enabled whether to enable or disable
+ */
+void
+_dbus_server_toggle_watch (DBusServer  *server,
+                           DBusWatch   *watch,
+                           dbus_bool_t  enabled)
+{
+  _dbus_assert (watch != NULL);
+
+  HAVE_LOCK_CHECK (server);
+  protected_change_watch (server, watch,
+                          NULL, NULL,
+                          _dbus_watch_list_toggle_watch,
+                          enabled);
+}
+
+/** Function to be called in protected_change_timeout() with refcount held */
+typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
+                                                   DBusTimeout     *timeout);
+/** Function to be called in protected_change_timeout() with refcount held */
+typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
+                                                   DBusTimeout     *timeout);
+/** Function to be called in protected_change_timeout() with refcount held */
+typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
+                                                   DBusTimeout     *timeout,
+                                                   dbus_bool_t      enabled);
+
+
+static dbus_bool_t
+protected_change_timeout (DBusServer               *server,
+                          DBusTimeout              *timeout,
+                          DBusTimeoutAddFunction    add_function,
+                          DBusTimeoutRemoveFunction remove_function,
+                          DBusTimeoutToggleFunction toggle_function,
+                          dbus_bool_t               enabled)
+{
+  DBusTimeoutList *timeouts;
+  dbus_bool_t retval;
+  
+  HAVE_LOCK_CHECK (server);
+
+  /* This isn't really safe or reasonable; a better pattern is the "do everything, then
+   * drop lock and call out" one; but it has to be propagated up through all callers
+   */
+  
+  timeouts = server->timeouts;
+  if (timeouts)
+    {
+      server->timeouts = NULL;
+      _dbus_server_ref_unlocked (server);
+      SERVER_UNLOCK (server);
+
+      if (add_function)
+        retval = (* add_function) (timeouts, timeout);
+      else if (remove_function)
+        {
+          retval = TRUE;
+          (* remove_function) (timeouts, timeout);
+        }
+      else
+        {
+          retval = TRUE;
+          (* toggle_function) (timeouts, timeout, enabled);
+        }
+      
+      SERVER_LOCK (server);
+      server->timeouts = timeouts;
+      _dbus_server_unref_unlocked (server);
+
+      return retval;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * Adds a timeout for this server, chaining out to
+ * application-provided timeout handlers. The timeout should be
+ * repeatedly handled with dbus_timeout_handle() at its given interval
+ * until it is removed.
+ *
+ * @param server the server.
+ * @param timeout the timeout to add.
+ */
+dbus_bool_t
+_dbus_server_add_timeout (DBusServer  *server,
+			  DBusTimeout *timeout)
+{
+  return protected_change_timeout (server, timeout,
+                                   _dbus_timeout_list_add_timeout,
+                                   NULL, NULL, FALSE);
+}
+
+/**
+ * Removes a timeout previously added with _dbus_server_add_timeout().
+ *
+ * @param server the server.
+ * @param timeout the timeout to remove.
+ */
+void
+_dbus_server_remove_timeout (DBusServer  *server,
+			     DBusTimeout *timeout)
+{
+  protected_change_timeout (server, timeout,
+                            NULL,
+                            _dbus_timeout_list_remove_timeout,
+                            NULL, FALSE);
+}
+
+/**
+ * Toggles a timeout and notifies app via server's
+ * DBusTimeoutToggledFunction if available. It's an error to call this
+ * function on a timeout that was not previously added.
+ *
+ * @param server the server.
+ * @param timeout the timeout to toggle.
+ * @param enabled whether to enable or disable
+ */
+void
+_dbus_server_toggle_timeout (DBusServer  *server,
+                             DBusTimeout *timeout,
+                             dbus_bool_t  enabled)
+{
+  protected_change_timeout (server, timeout,
+                            NULL, NULL,
+                            _dbus_timeout_list_toggle_timeout,
+                            enabled);
+}
+
+
+/**
+ * Like dbus_server_ref() but does not acquire the lock (must already be held)
+ *
+ * @param server the server.
+ */
+void
+_dbus_server_ref_unlocked (DBusServer *server)
+{
+  dbus_int32_t old_refcount;
+
+  _dbus_assert (server != NULL);
+  HAVE_LOCK_CHECK (server);
+
+  old_refcount = _dbus_atomic_inc (&server->refcount);
+  _dbus_assert (old_refcount > 0);
+  _dbus_server_trace_ref (server, old_refcount, old_refcount + 1,
+      "ref_unlocked");
+}
+
+/**
+ * Like dbus_server_unref() but does not acquire the lock (must already be held)
+ *
+ * @param server the server.
+ */
+void
+_dbus_server_unref_unlocked (DBusServer *server)
+{
+  dbus_int32_t old_refcount;
+
+  /* Keep this in sync with dbus_server_unref */
+
+  _dbus_assert (server != NULL);
+
+  HAVE_LOCK_CHECK (server);
+
+  old_refcount = _dbus_atomic_dec (&server->refcount);
+  _dbus_assert (old_refcount > 0);
+
+  _dbus_server_trace_ref (server, old_refcount, old_refcount - 1,
+      "unref_unlocked");
+
+  if (old_refcount == 1)
+    {
+      _dbus_assert (server->disconnected);
+      
+      SERVER_UNLOCK (server);
+      
+      _dbus_assert (server->vtable->finalize != NULL);
+      
+      (* server->vtable->finalize) (server);
+    }
+}
+
+/** @} */
+
+/**
+ * @addtogroup DBusServer
+ *
+ * @{
+ */
+
+
+/**
+ * @typedef DBusServer
+ *
+ * An opaque object representing a server that listens for
+ * connections from other applications. Each time a connection
+ * is made, a new DBusConnection is created and made available
+ * via an application-provided DBusNewConnectionFunction.
+ * The DBusNewConnectionFunction is provided with
+ * dbus_server_set_new_connection_function().
+ * 
+ */
+
+static const struct {
+  DBusServerListenResult (* func) (DBusAddressEntry *entry,
+                                   DBusServer      **server_p,
+                                   DBusError        *error);
+} listen_funcs[] = {
+  { _dbus_server_listen_socket }
+  , { _dbus_server_listen_platform_specific }
+#ifdef DBUS_BUILD_TESTS
+  , { _dbus_server_listen_debug_pipe }
+#endif
+};
+
+/**
+ * Listens for new connections on the given address.  If there are
+ * multiple semicolon-separated address entries in the address, tries
+ * each one and listens on the first one that works.
+ * 
+ * Returns #NULL and sets error if listening fails for any reason.
+ * Otherwise returns a new #DBusServer.
+ * dbus_server_set_new_connection_function(),
+ * dbus_server_set_watch_functions(), and
+ * dbus_server_set_timeout_functions() should be called immediately to
+ * render the server fully functional.
+ *
+ * To free the server, applications must call first
+ * dbus_server_disconnect() and then dbus_server_unref().
+ * 
+ * @param address the address of this server.
+ * @param error location to store reason for failure.
+ * @returns a new #DBusServer, or #NULL on failure.
+ * 
+ */
+DBusServer*
+dbus_server_listen (const char     *address,
+                    DBusError      *error)
+{
+  DBusServer *server;
+  DBusAddressEntry **entries;
+  int len, i;
+  DBusError first_connect_error = DBUS_ERROR_INIT;
+  dbus_bool_t handled_once;
+  
+  _dbus_return_val_if_fail (address != NULL, NULL);
+  _dbus_return_val_if_error_is_set (error, NULL);
+  
+  if (!dbus_parse_address (address, &entries, &len, error))
+    return NULL;
+
+  server = NULL;
+  handled_once = FALSE;
+
+  for (i = 0; i < len; i++)
+    {
+      int j;
+
+      for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j)
+        {
+          DBusServerListenResult result;
+          DBusError tmp_error = DBUS_ERROR_INIT;
+
+          result = (* listen_funcs[j].func) (entries[i],
+                                             &server,
+                                             &tmp_error);
+
+          if (result == DBUS_SERVER_LISTEN_OK)
+            {
+              _dbus_assert (server != NULL);
+              _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+              handled_once = TRUE;
+              goto out;
+            }
+          else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED)
+            {
+              _dbus_assert (server == NULL);
+              dbus_set_error (error,
+                       DBUS_ERROR_ADDRESS_IN_USE,
+                       "Address '%s' already used",
+                       dbus_address_entry_get_method (entries[0]));
+              handled_once = TRUE;
+              goto out;
+            }
+          else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS)
+            {
+              _dbus_assert (server == NULL);
+              _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+              dbus_move_error (&tmp_error, error);
+              handled_once = TRUE;
+              goto out;
+            }
+          else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED)
+            {
+              _dbus_assert (server == NULL);
+              _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+
+              /* keep trying addresses */
+            }
+          else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT)
+            {
+              _dbus_assert (server == NULL);
+              _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+              if (!dbus_error_is_set (&first_connect_error))
+                dbus_move_error (&tmp_error, &first_connect_error);
+              else
+                dbus_error_free (&tmp_error);
+
+              handled_once = TRUE;
+              
+              /* keep trying addresses */
+            }
+        }
+
+      _dbus_assert (server == NULL);
+      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+    }
+
+ out:
+
+  if (!handled_once)
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+      if (len > 0)
+        dbus_set_error (error,
+                       DBUS_ERROR_BAD_ADDRESS,
+                       "Unknown address type '%s'",
+                       dbus_address_entry_get_method (entries[0]));
+      else
+        dbus_set_error (error,
+                        DBUS_ERROR_BAD_ADDRESS,
+                        "Empty address '%s'",
+                        address);
+    }
+  
+  dbus_address_entries_free (entries);
+
+  if (server == NULL)
+    {
+      _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) ||
+                   dbus_error_is_set (error));
+      
+      if (error && dbus_error_is_set (error))
+        {
+          /* already set the error */
+        }
+      else
+        {
+          /* didn't set the error but either error should be
+           * NULL or first_connect_error should be set.
+           */
+          _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error));
+          dbus_move_error (&first_connect_error, error);
+        }
+
+      _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+
+      return NULL;
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+      return server;
+    }
+}
+
+/**
+ * Increments the reference count of a DBusServer.
+ *
+ * @param server the server.
+ * @returns the server
+ */
+DBusServer *
+dbus_server_ref (DBusServer *server)
+{
+  dbus_int32_t old_refcount;
+
+  _dbus_return_val_if_fail (server != NULL, NULL);
+
+  /* can't get the refcount without a side-effect */
+  old_refcount = _dbus_atomic_inc (&server->refcount);
+
+#ifndef DBUS_DISABLE_CHECKS
+  if (_DBUS_UNLIKELY (old_refcount <= 0))
+    {
+      /* undo side-effect first */
+      _dbus_atomic_dec (&server->refcount);
+      _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
+                               _DBUS_FUNCTION_NAME, "old_refcount > 0",
+                               __FILE__, __LINE__);
+      return NULL;
+    }
+#endif
+
+  _dbus_server_trace_ref (server, old_refcount, old_refcount + 1, "ref");
+
+  return server;
+}
+
+/**
+ * Decrements the reference count of a DBusServer.  Finalizes the
+ * server if the reference count reaches zero.
+ *
+ * The server must be disconnected before the refcount reaches zero.
+ *
+ * @param server the server.
+ */
+void
+dbus_server_unref (DBusServer *server)
+{
+  dbus_int32_t old_refcount;
+
+  /* keep this in sync with unref_unlocked */
+
+  _dbus_return_if_fail (server != NULL);
+
+  /* can't get the refcount without a side-effect */
+  old_refcount = _dbus_atomic_dec (&server->refcount);
+
+#ifndef DBUS_DISABLE_CHECKS
+  if (_DBUS_UNLIKELY (old_refcount <= 0))
+    {
+      /* undo side-effect first */
+      _dbus_atomic_inc (&server->refcount);
+      _dbus_warn_check_failed (_dbus_return_if_fail_warning_format,
+                               _DBUS_FUNCTION_NAME, "old_refcount > 0",
+                               __FILE__, __LINE__);
+      return;
+    }
+#endif
+
+  _dbus_server_trace_ref (server, old_refcount, old_refcount - 1, "unref");
+
+  if (old_refcount == 1)
+    {
+      /* lock not held! */
+      _dbus_assert (server->disconnected);
+      
+      _dbus_assert (server->vtable->finalize != NULL);
+      
+      (* server->vtable->finalize) (server);
+    }
+}
+
+/**
+ * Releases the server's address and stops listening for
+ * new clients. If called more than once, only the first
+ * call has an effect. Does not modify the server's
+ * reference count.
+ * 
+ * @param server the server.
+ */
+void
+dbus_server_disconnect (DBusServer *server)
+{
+  _dbus_return_if_fail (server != NULL);
+
+#ifdef DBUS_DISABLE_CHECKS
+  _dbus_atomic_inc (&server->refcount);
+#else
+    {
+      dbus_int32_t old_refcount = _dbus_atomic_inc (&server->refcount);
+
+      _dbus_return_if_fail (old_refcount > 0);
+    }
+#endif
+
+  SERVER_LOCK (server);
+
+  _dbus_assert (server->vtable->disconnect != NULL);
+
+  if (!server->disconnected)
+    {
+      /* this has to be first so recursive calls to disconnect don't happen */
+      server->disconnected = TRUE;
+      
+      (* server->vtable->disconnect) (server);
+    }
+
+  SERVER_UNLOCK (server);
+  dbus_server_unref (server);
+}
+
+/**
+ * Returns #TRUE if the server is still listening for new connections.
+ *
+ * @param server the server.
+ */
+dbus_bool_t
+dbus_server_get_is_connected (DBusServer *server)
+{
+  dbus_bool_t retval;
+  
+  _dbus_return_val_if_fail (server != NULL, FALSE);
+
+  SERVER_LOCK (server);
+  retval = !server->disconnected;
+  SERVER_UNLOCK (server);
+
+  return retval;
+}
+
+/**
+ * Returns the address of the server, as a newly-allocated
+ * string which must be freed by the caller.
+ *
+ * @param server the server
+ * @returns the address or #NULL if no memory
+ */
+char*
+dbus_server_get_address (DBusServer *server)
+{
+  char *retval;
+  
+  _dbus_return_val_if_fail (server != NULL, NULL);
+
+  SERVER_LOCK (server);
+  retval = _dbus_strdup (server->address);
+  SERVER_UNLOCK (server);
+
+  return retval;
+}
+
+/**
+ * Returns the unique ID of the server, as a newly-allocated
+ * string which must be freed by the caller. This ID is
+ * normally used by clients to tell when two #DBusConnection
+ * would be equivalent (because the server address passed
+ * to dbus_connection_open() will have the same guid in the
+ * two cases). dbus_connection_open() can re-use an existing
+ * connection with the same ID instead of opening a new
+ * connection.
+ *
+ * This is an ID unique to each #DBusServer. Remember that
+ * a #DBusServer represents only one mode of connecting,
+ * so e.g. a bus daemon can listen on multiple addresses
+ * which will mean it has multiple #DBusServer each with
+ * their own ID.
+ *
+ * The ID is not a UUID in the sense of RFC4122; the details
+ * are explained in the D-Bus specification.
+ *
+ * @param server the server
+ * @returns the id of the server or #NULL if no memory
+ */
+char*
+dbus_server_get_id (DBusServer *server)
+{
+  char *retval;
+  
+  _dbus_return_val_if_fail (server != NULL, NULL);
+
+  SERVER_LOCK (server);
+  retval = NULL;
+  _dbus_string_copy_data (&server->guid_hex, &retval);
+  SERVER_UNLOCK (server);
+
+  return retval;
+}
+
+/**
+ * Sets a function to be used for handling new connections.  The given
+ * function is passed each new connection as the connection is
+ * created. If the new connection function increments the connection's
+ * reference count, the connection will stay alive. Otherwise, the
+ * connection will be unreferenced and closed. The new connection
+ * function may also close the connection itself, which is considered
+ * good form if the connection is not wanted.
+ *
+ * The connection here is private in the sense of
+ * dbus_connection_open_private(), so if the new connection function
+ * keeps a reference it must arrange for the connection to be closed.
+ * i.e. libdbus does not own this connection once the new connection
+ * function takes a reference.
+ *
+ * @param server the server.
+ * @param function a function to handle new connections.
+ * @param data data to pass to the new connection handler.
+ * @param free_data_function function to free the data.
+ */
+void
+dbus_server_set_new_connection_function (DBusServer                *server,
+                                         DBusNewConnectionFunction  function,
+                                         void                      *data,
+                                         DBusFreeFunction           free_data_function)
+{
+  DBusFreeFunction old_free_function;
+  void *old_data;
+  
+  _dbus_return_if_fail (server != NULL);
+
+  SERVER_LOCK (server);
+  old_free_function = server->new_connection_free_data_function;
+  old_data = server->new_connection_data;
+  
+  server->new_connection_function = function;
+  server->new_connection_data = data;
+  server->new_connection_free_data_function = free_data_function;
+  SERVER_UNLOCK (server);
+    
+  if (old_free_function != NULL)
+    (* old_free_function) (old_data);
+}
+
+/**
+ * Sets the watch functions for the server. These functions are
+ * responsible for making the application's main loop aware of file
+ * descriptors that need to be monitored for events.
+ *
+ * This function behaves exactly like dbus_connection_set_watch_functions();
+ * see the documentation for that routine.
+ *
+ * @param server the server.
+ * @param add_function function to begin monitoring a new descriptor.
+ * @param remove_function function to stop monitoring a descriptor.
+ * @param toggled_function function to notify when the watch is enabled/disabled
+ * @param data data to pass to add_function and remove_function.
+ * @param free_data_function function to be called to free the data.
+ * @returns #FALSE on failure (no memory)
+ */
+dbus_bool_t
+dbus_server_set_watch_functions (DBusServer              *server,
+                                 DBusAddWatchFunction     add_function,
+                                 DBusRemoveWatchFunction  remove_function,
+                                 DBusWatchToggledFunction toggled_function,
+                                 void                    *data,
+                                 DBusFreeFunction         free_data_function)
+{
+  dbus_bool_t result;
+  DBusWatchList *watches;
+  
+  _dbus_return_val_if_fail (server != NULL, FALSE);
+
+  SERVER_LOCK (server);
+  watches = server->watches;
+  server->watches = NULL;
+  if (watches)
+    {
+      SERVER_UNLOCK (server);
+      result = _dbus_watch_list_set_functions (watches,
+                                               add_function,
+                                               remove_function,
+                                               toggled_function,
+                                               data,
+                                               free_data_function);
+      SERVER_LOCK (server);
+    }
+  else
+    {
+      _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
+      result = FALSE;
+    }
+  server->watches = watches;
+  SERVER_UNLOCK (server);
+  
+  return result;
+}
+
+/**
+ * Sets the timeout functions for the server. These functions are
+ * responsible for making the application's main loop aware of timeouts.
+ *
+ * This function behaves exactly like dbus_connection_set_timeout_functions();
+ * see the documentation for that routine.
+ *
+ * @param server the server.
+ * @param add_function function to add a timeout.
+ * @param remove_function function to remove a timeout.
+ * @param toggled_function function to notify when the timeout is enabled/disabled
+ * @param data data to pass to add_function and remove_function.
+ * @param free_data_function function to be called to free the data.
+ * @returns #FALSE on failure (no memory)
+ */
+dbus_bool_t
+dbus_server_set_timeout_functions (DBusServer                *server,
+				   DBusAddTimeoutFunction     add_function,
+				   DBusRemoveTimeoutFunction  remove_function,
+                                   DBusTimeoutToggledFunction toggled_function,
+				   void                      *data,
+				   DBusFreeFunction           free_data_function)
+{
+  dbus_bool_t result;
+  DBusTimeoutList *timeouts;
+  
+  _dbus_return_val_if_fail (server != NULL, FALSE);
+
+  SERVER_LOCK (server);
+  timeouts = server->timeouts;
+  server->timeouts = NULL;
+  if (timeouts)
+    {
+      SERVER_UNLOCK (server);
+      result = _dbus_timeout_list_set_functions (timeouts,
+                                                 add_function,
+                                                 remove_function,
+                                                 toggled_function,
+                                                 data,
+                                                 free_data_function);
+      SERVER_LOCK (server);
+    }
+  else
+    {
+      _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
+      result = FALSE;
+    }
+  server->timeouts = timeouts;
+  SERVER_UNLOCK (server);
+  
+  return result;
+}
+
+/**
+ * Sets the authentication mechanisms that this server offers to
+ * clients, as a #NULL-terminated array of mechanism names. This
+ * function only affects connections created <em>after</em> it is
+ * called.  Pass #NULL instead of an array to use all available
+ * mechanisms (this is the default behavior).
+ *
+ * The D-Bus specification describes some of the supported mechanisms.
+ *
+ * @param server the server
+ * @param mechanisms #NULL-terminated array of mechanisms
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+dbus_server_set_auth_mechanisms (DBusServer  *server,
+                                 const char **mechanisms)
+{
+  char **copy;
+
+  _dbus_return_val_if_fail (server != NULL, FALSE);
+
+  SERVER_LOCK (server);
+  
+  if (mechanisms != NULL)
+    {
+      copy = _dbus_dup_string_array (mechanisms);
+      if (copy == NULL)
+        return FALSE;
+    }
+  else
+    copy = NULL;
+
+  dbus_free_string_array (server->auth_mechanisms);
+  server->auth_mechanisms = copy;
+
+  SERVER_UNLOCK (server);
+  
+  return TRUE;
+}
+
+
+static DBusDataSlotAllocator slot_allocator;
+_DBUS_DEFINE_GLOBAL_LOCK (server_slots);
+
+/**
+ * Allocates an integer ID to be used for storing application-specific
+ * data on any DBusServer. The allocated ID may then be used
+ * with dbus_server_set_data() and dbus_server_get_data().
+ * The slot must be initialized with -1. If a nonnegative
+ * slot is passed in, the refcount is incremented on that
+ * slot, rather than creating a new slot.
+ *  
+ * The allocated slot is global, i.e. all DBusServer objects will have
+ * a slot with the given integer ID reserved.
+ *
+ * @param slot_p address of global variable storing the slot ID
+ * @returns #FALSE on no memory
+ */
+dbus_bool_t
+dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
+{
+  return _dbus_data_slot_allocator_alloc (&slot_allocator,
+                                          (DBusRMutex **)&_DBUS_LOCK_NAME (server_slots),
+                                          slot_p);
+}
+
+/**
+ * Deallocates a global ID for server data slots.
+ * dbus_server_get_data() and dbus_server_set_data()
+ * may no longer be used with this slot.
+ * Existing data stored on existing DBusServer objects
+ * will be freed when the server is finalized,
+ * but may not be retrieved (and may only be replaced
+ * if someone else reallocates the slot).
+ *
+ * @param slot_p address of the slot to deallocate
+ */
+void
+dbus_server_free_data_slot (dbus_int32_t *slot_p)
+{
+  _dbus_return_if_fail (*slot_p >= 0);
+  
+  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
+}
+
+/**
+ * Stores a pointer on a DBusServer, along
+ * with an optional function to be used for freeing
+ * the data when the data is set again, or when
+ * the server is finalized. The slot number
+ * must have been allocated with dbus_server_allocate_data_slot().
+ *
+ * @param server the server
+ * @param slot the slot number
+ * @param data the data to store
+ * @param free_data_func finalizer function for the data
+ * @returns #TRUE if there was enough memory to store the data
+ */
+dbus_bool_t
+dbus_server_set_data (DBusServer       *server,
+                      int               slot,
+                      void             *data,
+                      DBusFreeFunction  free_data_func)
+{
+  DBusFreeFunction old_free_func;
+  void *old_data;
+  dbus_bool_t retval;
+
+  _dbus_return_val_if_fail (server != NULL, FALSE);
+
+  SERVER_LOCK (server);
+  
+  retval = _dbus_data_slot_list_set (&slot_allocator,
+                                     &server->slot_list,
+                                     slot, data, free_data_func,
+                                     &old_free_func, &old_data);
+
+
+  SERVER_UNLOCK (server);
+  
+  if (retval)
+    {
+      /* Do the actual free outside the server lock */
+      if (old_free_func)
+        (* old_free_func) (old_data);
+    }
+
+  return retval;
+}
+
+/**
+ * Retrieves data previously set with dbus_server_set_data().
+ * The slot must still be allocated (must not have been freed).
+ *
+ * @param server the server
+ * @param slot the slot to get data from
+ * @returns the data, or #NULL if not found
+ */
+void*
+dbus_server_get_data (DBusServer   *server,
+                      int           slot)
+{
+  void *res;
+
+  _dbus_return_val_if_fail (server != NULL, NULL);
+  
+  SERVER_LOCK (server);
+  
+  res = _dbus_data_slot_list_get (&slot_allocator,
+                                  &server->slot_list,
+                                  slot);
+
+  SERVER_UNLOCK (server);
+  
+  return res;
+}
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <string.h>
+
+dbus_bool_t
+_dbus_server_test (void)
+{
+  const char *valid_addresses[] = {
+    "tcp:port=1234",
+    "tcp:host=localhost,port=1234",
+    "tcp:host=localhost,port=1234;tcp:port=5678",
+#ifdef DBUS_UNIX
+    "unix:path=./boogie",
+    "tcp:port=1234;unix:path=./boogie",
+#endif
+  };
+
+  DBusServer *server;
+  int i;
+  
+  for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
+    {
+      DBusError error = DBUS_ERROR_INIT;
+      char *address;
+      char *id;
+
+      server = dbus_server_listen (valid_addresses[i], &error);
+      if (server == NULL)
+        {
+          _dbus_warn ("server listen error: %s: %s\n", error.name, error.message);
+          dbus_error_free (&error);
+          _dbus_assert_not_reached ("Failed to listen for valid address.");
+        }
+
+      id = dbus_server_get_id (server);
+      _dbus_assert (id != NULL);
+      address = dbus_server_get_address (server);
+      _dbus_assert (address != NULL);
+
+      if (strstr (address, id) == NULL)
+        {
+          _dbus_warn ("server id '%s' is not in the server address '%s'\n",
+                      id, address);
+          _dbus_assert_not_reached ("bad server id or address");
+        }
+
+      dbus_free (id);
+      dbus_free (address);
+      
+      dbus_server_disconnect (server);
+      dbus_server_unref (server);
+    }
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-server.h b/dbus/dbus/dbus-server.h
new file mode 100644
index 0000000..bdbefa0
--- /dev/null
+++ b/dbus/dbus/dbus-server.h
@@ -0,0 +1,106 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-server.h DBusServer object
+ *
+ * Copyright (C) 2002, 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_SERVER_H
+#define DBUS_SERVER_H
+
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-message.h>
+#include <dbus/dbus-connection.h>
+#include <dbus/dbus-protocol.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusServer
+ * @{
+ */
+
+typedef struct DBusServer DBusServer;
+
+/** Called when a new connection to the server is available. Must reference and save the new
+ * connection, or close the new connection. Set with dbus_server_set_new_connection_function().
+ */
+typedef void (* DBusNewConnectionFunction) (DBusServer     *server,
+                                            DBusConnection *new_connection,
+                                            void           *data);
+
+DBUS_EXPORT
+DBusServer* dbus_server_listen           (const char     *address,
+                                          DBusError      *error);
+DBUS_EXPORT
+DBusServer* dbus_server_ref              (DBusServer     *server);
+DBUS_EXPORT
+void        dbus_server_unref            (DBusServer     *server);
+DBUS_EXPORT
+void        dbus_server_disconnect       (DBusServer     *server);
+DBUS_EXPORT
+dbus_bool_t dbus_server_get_is_connected (DBusServer     *server);
+DBUS_EXPORT
+char*       dbus_server_get_address      (DBusServer     *server);
+DBUS_EXPORT
+char*       dbus_server_get_id           (DBusServer     *server);
+DBUS_EXPORT
+void        dbus_server_set_new_connection_function (DBusServer                *server,
+                                                     DBusNewConnectionFunction  function,
+                                                     void                      *data,
+                                                     DBusFreeFunction           free_data_function);
+DBUS_EXPORT
+dbus_bool_t dbus_server_set_watch_functions         (DBusServer                *server,
+                                                     DBusAddWatchFunction       add_function,
+                                                     DBusRemoveWatchFunction    remove_function,
+                                                     DBusWatchToggledFunction   toggled_function,
+                                                     void                      *data,
+                                                     DBusFreeFunction           free_data_function);
+DBUS_EXPORT
+dbus_bool_t dbus_server_set_timeout_functions       (DBusServer                *server,
+                                                     DBusAddTimeoutFunction     add_function,
+                                                     DBusRemoveTimeoutFunction  remove_function,
+                                                     DBusTimeoutToggledFunction toggled_function,
+                                                     void                      *data,
+                                                     DBusFreeFunction           free_data_function);
+DBUS_EXPORT
+dbus_bool_t dbus_server_set_auth_mechanisms         (DBusServer                *server,
+                                                     const char               **mechanisms);
+
+DBUS_EXPORT
+dbus_bool_t dbus_server_allocate_data_slot (dbus_int32_t     *slot_p);
+DBUS_EXPORT
+void        dbus_server_free_data_slot     (dbus_int32_t     *slot_p);
+DBUS_EXPORT
+dbus_bool_t dbus_server_set_data           (DBusServer       *server,
+                                            int               slot,
+                                            void             *data,
+                                            DBusFreeFunction  free_data_func);
+DBUS_EXPORT
+void*       dbus_server_get_data           (DBusServer       *server,
+                                            int               slot);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SERVER_H */
diff --git a/dbus/dbus/dbus-sha.c b/dbus/dbus/dbus-sha.c
new file mode 100644
index 0000000..d182752
--- /dev/null
+++ b/dbus/dbus/dbus-sha.c
@@ -0,0 +1,969 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sha.c SHA-1 implementation
+ *
+ * Copyright (C) 2003 Red Hat Inc.
+ * Copyright (C) 1995 A. M. Kuchling
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-sha.h"
+#include "dbus-marshal-basic.h" /* for byteswap routines */
+#include <string.h>
+
+/* The following comments have the history of where this code
+ * comes from. I actually copied it from GNet in GNOME CVS.
+ * - hp@redhat.com
+ */
+
+/*
+ *  sha.h : Implementation of the Secure Hash Algorithm
+ *
+ * Part of the Python Cryptography Toolkit, version 1.0.0
+ *
+ * Copyright (C) 1995, A.M. Kuchling
+ *
+ * Distribute and use freely; there are no restrictions on further
+ * dissemination and usage except those imposed by the laws of your
+ * country of residence.
+ *
+ */
+
+/* SHA: NIST's Secure Hash Algorithm */
+
+/* Based on SHA code originally posted to sci.crypt by Peter Gutmann
+   in message <30ajo5$oe8@ccu2.auckland.ac.nz>.
+   Modified to test for endianness on creation of SHA objects by AMK.
+   Also, the original specification of SHA was found to have a weakness
+   by NSA/NIST.  This code implements the fixed version of SHA.
+*/
+
+/* Here's the first paragraph of Peter Gutmann's posting:
+
+The following is my SHA (FIPS 180) code updated to allow use of the "fixed"
+SHA, thanks to Jim Gillogly and an anonymous contributor for the information on
+what's changed in the new version.  The fix is a simple change which involves
+adding a single rotate in the initial expansion function.  It is unknown
+whether this is an optimal solution to the problem which was discovered in the
+SHA or whether it's simply a bandaid which fixes the problem with a minimum of
+effort (for example the reengineering of a great many Capstone chips).
+*/
+
+/**
+ * @defgroup DBusSHA SHA implementation
+ * @ingroup  DBusInternals
+ * @brief SHA-1 hash
+ *
+ * Types and functions related to computing SHA-1 hash.
+ */
+
+/**
+ * @defgroup DBusSHAInternals SHA implementation details
+ * @ingroup  DBusInternals
+ * @brief Internals of SHA implementation.
+ *
+ * The implementation of SHA-1 (see http://www.itl.nist.gov/fipspubs/fip180-1.htm).
+ * This SHA implementation was written by A.M. Kuchling
+ *
+ * @{
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/* The SHA block size and message digest sizes, in bytes */
+
+#define SHA_DATASIZE    64
+#define SHA_DIGESTSIZE  20
+
+/* The SHA f()-functions.  The f1 and f3 functions can be optimized to
+   save one boolean operation each - thanks to Rich Schroeppel,
+   rcs@cs.arizona.edu for discovering this */
+
+/*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) )          // Rounds  0-19 */
+#define f1(x,y,z)  ( z ^ ( x & ( y ^ z ) ) )           /* Rounds  0-19 */
+#define f2(x,y,z)  ( x ^ y ^ z )                       /* Rounds 20-39 */
+/*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) )   // Rounds 40-59 */
+#define f3(x,y,z)  ( ( x & y ) | ( z & ( x | y ) ) )   /* Rounds 40-59 */
+#define f4(x,y,z)  ( x ^ y ^ z )                       /* Rounds 60-79 */
+
+/* The SHA Mysterious Constants */
+
+#define K1  0x5A827999L                                 /* Rounds  0-19 */
+#define K2  0x6ED9EBA1L                                 /* Rounds 20-39 */
+#define K3  0x8F1BBCDCL                                 /* Rounds 40-59 */
+#define K4  0xCA62C1D6L                                 /* Rounds 60-79 */
+
+/* SHA initial values */
+
+#define h0init  0x67452301L
+#define h1init  0xEFCDAB89L
+#define h2init  0x98BADCFEL
+#define h3init  0x10325476L
+#define h4init  0xC3D2E1F0L
+
+/* Note that it may be necessary to add parentheses to these macros if they
+   are to be called with expressions as arguments */
+/* 32-bit rotate left - kludged with shifts */
+
+#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
+
+/* The initial expanding function.  The hash function is defined over an
+   80-word expanded input array W, where the first 16 are copies of the input
+   data, and the remaining 64 are defined by
+
+        W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ]
+
+   This implementation generates these values on the fly in a circular
+   buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this
+   optimization.
+
+   The updated SHA changes the expanding function by adding a rotate of 1
+   bit.  Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor
+   for this information */
+
+#define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \
+                                                 W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) )
+
+
+/* The prototype SHA sub-round.  The fundamental sub-round is:
+
+        a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data;
+        b' = a;
+        c' = ROTL( 30, b );
+        d' = c;
+        e' = d;
+
+   but this is implemented by unrolling the loop 5 times and renaming the
+   variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration.
+   This code is then replicated 20 times for each of the 4 functions, using
+   the next 20 values from the W[] array each time */
+
+#define subRound(a, b, c, d, e, f, k, data) \
+   ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
+
+/* Perform the SHA transformation.  Note that this code, like MD5, seems to
+   break some optimizing compilers due to the complexity of the expressions
+   and the size of the basic block.  It may be necessary to split it into
+   sections, e.g. based on the four subrounds
+
+   Note that this corrupts the context->data area */
+
+static void
+SHATransform(dbus_uint32_t *digest, dbus_uint32_t *data)
+{
+  dbus_uint32_t A, B, C, D, E;     /* Local vars */
+  dbus_uint32_t eData[16];       /* Expanded data */
+
+  /* Set up first buffer and local data buffer */
+  A = digest[0];
+  B = digest[1];
+  C = digest[2];
+  D = digest[3];
+  E = digest[4];
+  memmove (eData, data, SHA_DATASIZE);
+
+  /* Heavy mangling, in 4 sub-rounds of 20 interations each. */
+  subRound (A, B, C, D, E, f1, K1, eData[0]);
+  subRound (E, A, B, C, D, f1, K1, eData[1]);
+  subRound (D, E, A, B, C, f1, K1, eData[2]);
+  subRound (C, D, E, A, B, f1, K1, eData[3]);
+  subRound (B, C, D, E, A, f1, K1, eData[4]);
+  subRound (A, B, C, D, E, f1, K1, eData[5]);
+  subRound (E, A, B, C, D, f1, K1, eData[6]);
+  subRound (D, E, A, B, C, f1, K1, eData[7]);
+  subRound (C, D, E, A, B, f1, K1, eData[8]);
+  subRound (B, C, D, E, A, f1, K1, eData[9]);
+  subRound (A, B, C, D, E, f1, K1, eData[10]);
+  subRound (E, A, B, C, D, f1, K1, eData[11]);
+  subRound (D, E, A, B, C, f1, K1, eData[12]);
+  subRound (C, D, E, A, B, f1, K1, eData[13]);
+  subRound (B, C, D, E, A, f1, K1, eData[14]);
+  subRound (A, B, C, D, E, f1, K1, eData[15]);
+  subRound (E, A, B, C, D, f1, K1, expand ( eData, 16) );
+  subRound (D, E, A, B, C, f1, K1, expand ( eData, 17) );
+  subRound (C, D, E, A, B, f1, K1, expand ( eData, 18) );
+  subRound (B, C, D, E, A, f1, K1, expand ( eData, 19) );
+
+  subRound (A, B, C, D, E, f2, K2, expand ( eData, 20) );
+  subRound (E, A, B, C, D, f2, K2, expand ( eData, 21) );
+  subRound (D, E, A, B, C, f2, K2, expand ( eData, 22) );
+  subRound (C, D, E, A, B, f2, K2, expand ( eData, 23) );
+  subRound (B, C, D, E, A, f2, K2, expand ( eData, 24) );
+  subRound (A, B, C, D, E, f2, K2, expand ( eData, 25) );
+  subRound (E, A, B, C, D, f2, K2, expand ( eData, 26) );
+  subRound (D, E, A, B, C, f2, K2, expand ( eData, 27) );
+  subRound (C, D, E, A, B, f2, K2, expand ( eData, 28) );
+  subRound (B, C, D, E, A, f2, K2, expand ( eData, 29) );
+  subRound (A, B, C, D, E, f2, K2, expand ( eData, 30) );
+  subRound (E, A, B, C, D, f2, K2, expand ( eData, 31) );
+  subRound (D, E, A, B, C, f2, K2, expand ( eData, 32) );
+  subRound (C, D, E, A, B, f2, K2, expand ( eData, 33) );
+  subRound (B, C, D, E, A, f2, K2, expand ( eData, 34) );
+  subRound (A, B, C, D, E, f2, K2, expand ( eData, 35) );
+  subRound (E, A, B, C, D, f2, K2, expand ( eData, 36) );
+  subRound (D, E, A, B, C, f2, K2, expand ( eData, 37) );
+  subRound (C, D, E, A, B, f2, K2, expand ( eData, 38) );
+  subRound (B, C, D, E, A, f2, K2, expand ( eData, 39) );
+
+  subRound (A, B, C, D, E, f3, K3, expand ( eData, 40) );
+  subRound (E, A, B, C, D, f3, K3, expand ( eData, 41) );
+  subRound (D, E, A, B, C, f3, K3, expand ( eData, 42) );
+  subRound (C, D, E, A, B, f3, K3, expand ( eData, 43) );
+  subRound (B, C, D, E, A, f3, K3, expand ( eData, 44) );
+  subRound (A, B, C, D, E, f3, K3, expand ( eData, 45) );
+  subRound (E, A, B, C, D, f3, K3, expand ( eData, 46) );
+  subRound (D, E, A, B, C, f3, K3, expand ( eData, 47) );
+  subRound (C, D, E, A, B, f3, K3, expand ( eData, 48) );
+  subRound (B, C, D, E, A, f3, K3, expand ( eData, 49) );
+  subRound (A, B, C, D, E, f3, K3, expand ( eData, 50) );
+  subRound (E, A, B, C, D, f3, K3, expand ( eData, 51) );
+  subRound (D, E, A, B, C, f3, K3, expand ( eData, 52) );
+  subRound (C, D, E, A, B, f3, K3, expand ( eData, 53) );
+  subRound (B, C, D, E, A, f3, K3, expand ( eData, 54) );
+  subRound (A, B, C, D, E, f3, K3, expand ( eData, 55) );
+  subRound (E, A, B, C, D, f3, K3, expand ( eData, 56) );
+  subRound (D, E, A, B, C, f3, K3, expand ( eData, 57) );
+  subRound (C, D, E, A, B, f3, K3, expand ( eData, 58) );
+  subRound (B, C, D, E, A, f3, K3, expand ( eData, 59) );
+
+  subRound (A, B, C, D, E, f4, K4, expand ( eData, 60) );
+  subRound (E, A, B, C, D, f4, K4, expand ( eData, 61) );
+  subRound (D, E, A, B, C, f4, K4, expand ( eData, 62) );
+  subRound (C, D, E, A, B, f4, K4, expand ( eData, 63) );
+  subRound (B, C, D, E, A, f4, K4, expand ( eData, 64) );
+  subRound (A, B, C, D, E, f4, K4, expand ( eData, 65) );
+  subRound (E, A, B, C, D, f4, K4, expand ( eData, 66) );
+  subRound (D, E, A, B, C, f4, K4, expand ( eData, 67) );
+  subRound (C, D, E, A, B, f4, K4, expand ( eData, 68) );
+  subRound (B, C, D, E, A, f4, K4, expand ( eData, 69) );
+  subRound (A, B, C, D, E, f4, K4, expand ( eData, 70) );
+  subRound (E, A, B, C, D, f4, K4, expand ( eData, 71) );
+  subRound (D, E, A, B, C, f4, K4, expand ( eData, 72) );
+  subRound (C, D, E, A, B, f4, K4, expand ( eData, 73) );
+  subRound (B, C, D, E, A, f4, K4, expand ( eData, 74) );
+  subRound (A, B, C, D, E, f4, K4, expand ( eData, 75) );
+  subRound (E, A, B, C, D, f4, K4, expand ( eData, 76) );
+  subRound (D, E, A, B, C, f4, K4, expand ( eData, 77) );
+  subRound (C, D, E, A, B, f4, K4, expand ( eData, 78) );
+  subRound (B, C, D, E, A, f4, K4, expand ( eData, 79) );
+
+  /* Build message digest */
+  digest[0] += A;
+  digest[1] += B;
+  digest[2] += C;
+  digest[3] += D;
+  digest[4] += E;
+}
+
+/* When run on a little-endian CPU we need to perform byte reversal on an
+   array of longwords. */
+
+#ifdef WORDS_BIGENDIAN
+#define swap_words(buffer, byte_count)
+#else
+static void
+swap_words (dbus_uint32_t *buffer,
+            int            byte_count)
+{
+  byte_count /= sizeof (dbus_uint32_t);
+  while (byte_count--)
+    {
+      *buffer = DBUS_UINT32_SWAP_LE_BE (*buffer);
+      ++buffer;
+    }
+}
+#endif
+
+static void
+sha_init (DBusSHAContext *context)
+{
+  /* Set the h-vars to their initial values */
+  context->digest[0] = h0init;
+  context->digest[1] = h1init;
+  context->digest[2] = h2init;
+  context->digest[3] = h3init;
+  context->digest[4] = h4init;
+
+  /* Initialise bit count */
+  context->count_lo = context->count_hi = 0;
+}
+
+static void
+sha_append (DBusSHAContext      *context,
+            const unsigned char *buffer,
+            unsigned int         count)
+{
+  dbus_uint32_t tmp;
+  unsigned int dataCount;
+
+  /* Update bitcount */
+  tmp = context->count_lo;
+  if (( context->count_lo = tmp + ( ( dbus_uint32_t) count << 3) ) < tmp)
+    context->count_hi++;             /* Carry from low to high */
+  context->count_hi += count >> 29;
+
+  /* Get count of bytes already in data */
+  dataCount = (int) (tmp >> 3) & 0x3F;
+
+  /* Handle any leading odd-sized chunks */
+  if (dataCount)
+    {
+      unsigned char *p = (unsigned char *) context->data + dataCount;
+
+      dataCount = SHA_DATASIZE - dataCount;
+      if (count < dataCount)
+        {
+          memmove (p, buffer, count);
+          return;
+        }
+      memmove (p, buffer, dataCount);
+      swap_words (context->data, SHA_DATASIZE);
+      SHATransform (context->digest, context->data);
+      buffer += dataCount;
+      count -= dataCount;
+    }
+
+  /* Process data in SHA_DATASIZE chunks */
+  while (count >= SHA_DATASIZE)
+    {
+      memmove (context->data, buffer, SHA_DATASIZE);
+      swap_words (context->data, SHA_DATASIZE);
+      SHATransform (context->digest, context->data);
+      buffer += SHA_DATASIZE;
+      count -= SHA_DATASIZE;
+    }
+
+  /* Handle any remaining bytes of data. */
+  memmove (context->data, buffer, count);
+}
+
+
+/* Final wrapup - pad to SHA_DATASIZE-byte boundary with the bit pattern
+   1 0* (64-bit count of bits processed, MSB-first) */
+
+static void
+sha_finish (DBusSHAContext *context, unsigned char digest[20])
+{
+  int count;
+  unsigned char *data_p;
+
+  /* Compute number of bytes mod 64 */
+  count = (int) context->count_lo;
+  count = (count >> 3) & 0x3F;
+
+  /* Set the first char of padding to 0x80.  This is safe since there is
+     always at least one byte free */
+  data_p = (unsigned char *) context->data + count;
+  *data_p++ = 0x80;
+
+  /* Bytes of padding needed to make 64 bytes */
+  count = SHA_DATASIZE - 1 - count;
+
+  /* Pad out to 56 mod 64 */
+  if (count < 8)
+    {
+      /* Two lots of padding:  Pad the first block to 64 bytes */
+      memset (data_p, 0, count);
+      swap_words (context->data, SHA_DATASIZE);
+      SHATransform (context->digest, context->data);
+
+      /* Now fill the next block with 56 bytes */
+      memset (context->data, 0, SHA_DATASIZE - 8);
+    }
+  else
+    /* Pad block to 56 bytes */
+    memset (data_p, 0, count - 8);
+
+  /* Append length in bits and transform */
+  context->data[14] = context->count_hi;
+  context->data[15] = context->count_lo;
+
+  swap_words (context->data, SHA_DATASIZE - 8);
+  SHATransform (context->digest, context->data);
+  swap_words (context->digest, SHA_DIGESTSIZE);
+  memmove (digest, context->digest, SHA_DIGESTSIZE);
+}
+
+/** @} */ /* End of internals */
+
+/**
+ * @addtogroup DBusSHA
+ *
+ * @{
+ */
+
+/**
+ * Initializes the SHA context.
+ *
+ * @param context an uninitialized context, typically on the stack.
+ */
+void
+_dbus_sha_init (DBusSHAContext *context)
+{
+  sha_init (context);
+}
+
+/**
+ * Feeds more data into an existing shasum computation.
+ *
+ * @param context the SHA context
+ * @param data the additional data to hash
+ */
+void
+_dbus_sha_update (DBusSHAContext   *context,
+                  const DBusString *data)
+{
+  unsigned int inputLen;
+  const unsigned char *input;
+
+  input = (const unsigned char*) _dbus_string_get_const_data (data);
+  inputLen = _dbus_string_get_length (data);
+
+  sha_append (context, input, inputLen);
+}
+
+/**
+ * SHA finalization. Ends an SHA message-digest operation, writing the
+ * the message digest and zeroing the context.  The results are
+ * returned as a raw 20-byte digest, not as the ascii-hex-digits
+ * string form of the digest.
+ *
+ * @param context the SHA context
+ * @param results string to append the 20-byte SHA digest to
+ * @returns #FALSE if not enough memory to append the digest
+ *
+ */
+dbus_bool_t
+_dbus_sha_final (DBusSHAContext   *context,
+                 DBusString       *results)
+{
+  unsigned char digest[20];
+
+  sha_finish (context, digest);
+
+  if (!_dbus_string_append_len (results, digest, 20))
+    return FALSE;
+
+  /* some kind of security paranoia, though it seems pointless
+   * to me given the nonzeroed stuff flying around
+   */
+  _DBUS_ZERO(*context);
+
+  return TRUE;
+}
+
+/**
+ * Computes the ASCII hex-encoded shasum of the given data and
+ * appends it to the output string.
+ *
+ * @param data input data to be hashed
+ * @param ascii_output string to append ASCII shasum to
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_sha_compute (const DBusString *data,
+                   DBusString       *ascii_output)
+{
+  DBusSHAContext context;
+  DBusString digest;
+
+  _dbus_sha_init (&context);
+
+  _dbus_sha_update (&context, data);
+
+  if (!_dbus_string_init (&digest))
+    return FALSE;
+
+  if (!_dbus_sha_final (&context, &digest))
+    goto error;
+
+  if (!_dbus_string_hex_encode (&digest, 0, ascii_output,
+                                _dbus_string_get_length (ascii_output)))
+    goto error;
+
+  _dbus_string_free (&digest);
+  
+  return TRUE;
+
+ error:
+  _dbus_string_free (&digest);
+  return FALSE;
+}
+
+/** @} */ /* end of exported functions */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+
+static dbus_bool_t
+check_sha_binary (const unsigned char *input,
+                  int                  input_len,
+                  const char          *expected)
+{
+  DBusString input_str;
+  DBusString expected_str;
+  DBusString results;
+
+  _dbus_string_init_const_len (&input_str, input, input_len);
+  _dbus_string_init_const (&expected_str, expected);
+
+  if (!_dbus_string_init (&results))
+    _dbus_assert_not_reached ("no memory for SHA-1 results");
+
+  if (!_dbus_sha_compute (&input_str, &results))
+    _dbus_assert_not_reached ("no memory for SHA-1 results");
+
+  if (!_dbus_string_equal (&expected_str, &results))
+    {
+      _dbus_warn ("Expected hash %s got %s for SHA-1 sum\n",
+                  expected,
+                  _dbus_string_get_const_data (&results));
+      _dbus_string_free (&results);
+      return FALSE;
+    }
+
+  _dbus_string_free (&results);
+  return TRUE;
+}
+
+static dbus_bool_t
+check_sha_str (const char *input,
+               const char *expected)
+{
+  return check_sha_binary (input, strlen (input), expected);
+}
+
+static dbus_bool_t
+decode_compact_string (const DBusString *line,
+                       DBusString       *decoded)
+{
+  int n_bits;
+  dbus_bool_t current_b;
+  int offset;
+  int next;
+  long val;
+  int length_bytes;
+  
+  offset = 0;
+  next = 0;
+
+  if (!_dbus_string_parse_int (line, offset, &val, &next))
+    {
+      fprintf (stderr, "could not parse length at start of compact string: %s\n",
+               _dbus_string_get_const_data (line));
+      return FALSE;
+    }
+
+  _dbus_string_skip_blank (line, next, &next);
+  
+  offset = next;
+  if (!_dbus_string_parse_int (line, offset, &val, &next))
+    {
+      fprintf (stderr, "could not parse start bit 'b' in compact string: %s\n",
+               _dbus_string_get_const_data (line));
+      return FALSE;
+    }
+  
+  if (!(val == 0 || val == 1))
+    {
+      fprintf (stderr, "the value 'b' must be 0 or 1, see sha-1/Readme.txt\n");
+      return FALSE;
+    }
+
+  _dbus_string_skip_blank (line, next, &next);
+  
+  current_b = val;
+  n_bits = 0;
+  
+  while (next < _dbus_string_get_length (line))
+    {
+      int total_bits;
+      
+      offset = next;
+
+      if (_dbus_string_get_byte (line, offset) == '^')
+        break;
+      
+      if (!_dbus_string_parse_int (line, offset, &val, &next))
+        {
+          fprintf (stderr, "could not parse bit count in compact string\n");
+          return FALSE;
+        }
+
+      /* We now append "val" copies of "current_b" bits to the string */
+      total_bits = n_bits + val;
+      while (n_bits < total_bits)
+        {
+          int byte_containing_next_bit = n_bits / 8;
+          int bit_containing_next_bit = 7 - (n_bits % 8);
+          unsigned char old_byte;
+          
+          if (byte_containing_next_bit >= _dbus_string_get_length (decoded))
+            {
+              if (!_dbus_string_set_length (decoded, byte_containing_next_bit + 1))
+                _dbus_assert_not_reached ("no memory to extend to next byte");
+            }
+
+          old_byte = _dbus_string_get_byte (decoded, byte_containing_next_bit);
+          old_byte |= current_b << bit_containing_next_bit;
+
+#if 0
+          printf ("Appending bit %d to byte %d at bit %d resulting in byte 0x%x\n",
+                  current_b, byte_containing_next_bit,
+                  bit_containing_next_bit, old_byte);
+#endif
+          
+          _dbus_string_set_byte (decoded, byte_containing_next_bit, old_byte);
+          
+          ++n_bits;
+        }
+
+      _dbus_string_skip_blank (line, next, &next);
+          
+      current_b = !current_b;
+    }
+
+  length_bytes = (n_bits / 8 + ((n_bits % 8) ? 1 : 0));
+  
+  if (_dbus_string_get_length (decoded) != length_bytes)
+    {
+      fprintf (stderr, "Expected length %d bytes %d bits for compact string, got %d bytes\n",
+               length_bytes, n_bits, _dbus_string_get_length (decoded));
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
+static dbus_bool_t
+get_next_expected_result (DBusString *results,
+                          DBusString *result)
+{
+  DBusString line;
+  dbus_bool_t retval;
+
+  retval = FALSE;
+  
+  if (!_dbus_string_init (&line))
+    _dbus_assert_not_reached ("no memory");
+  
+ next_iteration:
+  while (_dbus_string_pop_line (results, &line))
+    {
+      _dbus_string_delete_leading_blanks (&line);
+
+      if (_dbus_string_get_length (&line) == 0)
+        goto next_iteration;
+      else if (_dbus_string_starts_with_c_str (&line, "#"))
+        goto next_iteration;
+      else if (_dbus_string_starts_with_c_str (&line, "H>"))
+        {
+          /* don't print */
+        }
+      else if (_dbus_string_starts_with_c_str (&line, "D>") ||
+               _dbus_string_starts_with_c_str (&line, "<D"))
+        goto next_iteration;
+      else
+        {
+          int i;
+          
+          if (!_dbus_string_move (&line, 0, result, 0))
+            _dbus_assert_not_reached ("no memory");
+
+          i = 0;
+          while (i < _dbus_string_get_length (result))
+            {
+              switch (_dbus_string_get_byte (result, i))
+                {
+                case 'A':
+                  _dbus_string_set_byte (result, i, 'a');
+                  break;
+                case 'B':
+                  _dbus_string_set_byte (result, i, 'b');
+                  break;
+                case 'C':
+                  _dbus_string_set_byte (result, i, 'c');
+                  break;
+                case 'D':
+                  _dbus_string_set_byte (result, i, 'd');
+                  break;
+                case 'E':
+                  _dbus_string_set_byte (result, i, 'e');
+                  break;
+                case 'F':
+                  _dbus_string_set_byte (result, i, 'f');
+                  break;
+                case '^':
+                case ' ':
+                  _dbus_string_delete (result, i, 1);
+                  --i; /* to offset ++i below */
+                  break;
+                }
+
+              ++i;
+            }
+          
+          break;
+        }
+    }
+  
+  retval = TRUE;
+  
+  /* out: */
+  _dbus_string_free (&line);
+  return retval;
+}
+
+static dbus_bool_t
+process_test_data (const char *test_data_dir)
+{
+  DBusString tests_file;
+  DBusString results_file;
+  DBusString tests;
+  DBusString results;
+  DBusString line;
+  DBusString tmp;
+  int line_no;
+  dbus_bool_t retval;
+  int success_count;
+  DBusError error = DBUS_ERROR_INIT;
+
+  retval = FALSE;
+  
+  if (!_dbus_string_init (&tests_file))
+    _dbus_assert_not_reached ("no memory");
+
+  if (!_dbus_string_init (&results_file))
+    _dbus_assert_not_reached ("no memory");
+
+  if (!_dbus_string_init (&tests))
+    _dbus_assert_not_reached ("no memory");
+
+  if (!_dbus_string_init (&results))
+    _dbus_assert_not_reached ("no memory");
+
+  if (!_dbus_string_init (&line))
+    _dbus_assert_not_reached ("no memory");
+  
+  if (!_dbus_string_append (&tests_file, test_data_dir))
+    _dbus_assert_not_reached ("no memory");
+
+  if (!_dbus_string_append (&results_file, test_data_dir))
+    _dbus_assert_not_reached ("no memory");
+
+  _dbus_string_init_const (&tmp, "sha-1/byte-messages.sha1");
+  if (!_dbus_concat_dir_and_file (&tests_file, &tmp))
+    _dbus_assert_not_reached ("no memory");
+
+  _dbus_string_init_const (&tmp, "sha-1/byte-hashes.sha1");
+  if (!_dbus_concat_dir_and_file (&results_file, &tmp))
+    _dbus_assert_not_reached ("no memory");
+
+  if (!_dbus_file_get_contents (&tests, &tests_file, &error))
+    {
+      fprintf (stderr, "could not load test data file %s: %s\n",
+               _dbus_string_get_const_data (&tests_file),
+               error.message);
+      dbus_error_free (&error);
+      goto out;
+    }
+
+  if (!_dbus_file_get_contents (&results, &results_file, &error))
+    {
+      fprintf (stderr, "could not load results data file %s: %s\n",
+               _dbus_string_get_const_data (&results_file), error.message);
+      dbus_error_free (&error);
+      goto out;
+    }
+
+  success_count = 0;
+  line_no = 0;
+ next_iteration:
+  while (_dbus_string_pop_line (&tests, &line))
+    {
+      line_no += 1;
+
+      _dbus_string_delete_leading_blanks (&line);
+
+      if (_dbus_string_get_length (&line) == 0)
+        goto next_iteration;
+      else if (_dbus_string_starts_with_c_str (&line, "#"))
+        goto next_iteration;
+      else if (_dbus_string_starts_with_c_str (&line, "H>"))
+        {
+          printf ("SHA-1: %s\n", _dbus_string_get_const_data (&line));
+
+          if (_dbus_string_find (&line, 0, "Type 3", NULL))
+            {
+              /* See sha-1/Readme.txt - the "Type 3" tests are
+               * random seeds, rather than data to be hashed.
+               * we'd have to do a little bit more implementation
+               * to use those tests.
+               */
+              
+              printf (" (ending tests due to Type 3 tests seen - this is normal)\n");
+              break;
+            }
+        }
+      else if (_dbus_string_starts_with_c_str (&line, "D>") ||
+               _dbus_string_starts_with_c_str (&line, "<D"))
+        goto next_iteration;
+      else
+        {
+          DBusString test;
+          DBusString result;
+          DBusString next_line;
+          DBusString expected;
+          dbus_bool_t success;
+
+          success = FALSE;
+          
+          if (!_dbus_string_init (&next_line))
+            _dbus_assert_not_reached ("no memory");
+
+          if (!_dbus_string_init (&expected))
+            _dbus_assert_not_reached ("no memory");
+          
+          if (!_dbus_string_init (&test))
+            _dbus_assert_not_reached ("no memory");
+
+          if (!_dbus_string_init (&result))
+            _dbus_assert_not_reached ("no memory");
+
+          /* the "compact strings" are "^"-terminated not
+           * newline-terminated so readahead to find the
+           * "^"
+           */
+          while (!_dbus_string_find (&line, 0, "^", NULL) &&
+                 _dbus_string_pop_line (&tests, &next_line))
+            {
+              if (!_dbus_string_append_byte (&line, ' ') ||
+                  !_dbus_string_move (&next_line, 0, &line,
+                                      _dbus_string_get_length (&line)))
+                _dbus_assert_not_reached ("no memory");
+            }
+          
+          if (!decode_compact_string (&line, &test))
+            {
+              fprintf (stderr, "Failed to decode line %d as a compact string\n",
+                       line_no);
+              goto failure;
+            }
+          
+          if (!_dbus_sha_compute (&test, &result))
+            _dbus_assert_not_reached ("no memory for SHA-1 result");
+
+          if (!get_next_expected_result (&results, &expected))
+            {
+              fprintf (stderr, "Failed to read an expected result\n");
+              goto failure;
+            }
+          
+          if (!_dbus_string_equal (&result, &expected))
+            {              
+              fprintf (stderr, " for line %d got hash %s expected %s\n",
+                       line_no,
+                       _dbus_string_get_const_data (&result),
+                       _dbus_string_get_const_data (&expected));
+              goto failure;
+            }
+          else
+            {
+              success_count += 1;
+            }
+
+          success = TRUE;
+
+        failure:
+          _dbus_string_free (&test);
+          _dbus_string_free (&result);
+          _dbus_string_free (&next_line);
+          _dbus_string_free (&expected);
+
+          if (!success)
+            goto out;
+        }
+    }
+
+  retval = TRUE;
+
+  printf ("Passed the %d SHA-1 tests in the test file\n",
+          success_count);
+  
+ out:
+  _dbus_string_free (&tests_file);
+  _dbus_string_free (&results_file);
+  _dbus_string_free (&tests);
+  _dbus_string_free (&results);
+  _dbus_string_free (&line);
+
+  return retval;
+}
+
+/**
+ * @ingroup DBusSHAInternals
+ * Unit test for SHA computation.
+ *
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_sha_test (const char *test_data_dir)
+{
+  unsigned char all_bytes[256];
+  int i;
+
+  if (test_data_dir != NULL)
+    {
+      if (!process_test_data (test_data_dir))
+        return FALSE;
+    }
+  else
+    printf ("No test data dir\n");
+  
+  i = 0;
+  while (i < 256)
+    {
+      all_bytes[i] = i;
+      ++i;
+    }
+
+  if (!check_sha_binary (all_bytes, 256,
+                         "4916d6bdb7f78e6803698cab32d1586ea457dfc8"))
+    return FALSE;
+
+#define CHECK(input,expected) if (!check_sha_str (input, expected)) return FALSE
+
+  CHECK ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
+  CHECK ("a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
+  CHECK ("abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
+  CHECK ("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3");
+  CHECK ("abcdefghijklmnopqrstuvwxyz", "32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
+  CHECK ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+         "761c457bf73b14d27e9e9265c46f4b4dda11f940");
+  CHECK ("12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+         "50abf5706a150990a08b2c5ea40fa0e585554732");
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-sha.h b/dbus/dbus/dbus-sha.h
new file mode 100644
index 0000000..c48035b
--- /dev/null
+++ b/dbus/dbus/dbus-sha.h
@@ -0,0 +1,55 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sha.h SHA-1 implementation
+ *
+ * Copyright (C) 2003 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+#ifndef DBUS_SHA_H
+#define DBUS_SHA_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-string.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusSHAContext DBusSHAContext;
+
+/**
+ * Struct storing state of the SHA algorithm
+ */
+struct DBusSHAContext
+{
+  dbus_uint32_t  digest[5];         /**< Message digest */
+  dbus_uint32_t  count_lo;          /**< 64-bit bit count */
+  dbus_uint32_t  count_hi;          /**< No clue */
+  dbus_uint32_t  data[16];          /**< SHA data buffer */
+};
+
+void        _dbus_sha_init    (DBusSHAContext   *context);
+void        _dbus_sha_update  (DBusSHAContext   *context,
+                               const DBusString *data);
+dbus_bool_t _dbus_sha_final   (DBusSHAContext   *context,
+                               DBusString       *results);
+dbus_bool_t _dbus_sha_compute (const DBusString *data,
+                               DBusString       *ascii_output);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SHA_H */
diff --git a/dbus/dbus/dbus-shared.h b/dbus/dbus/dbus-shared.h
new file mode 100644
index 0000000..6a57670
--- /dev/null
+++ b/dbus/dbus/dbus-shared.h
@@ -0,0 +1,131 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-shared.h  Stuff used by both dbus/dbus.h low-level and C/C++ binding APIs
+ *
+ * Copyright (C) 2004 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_SHARED_H
+#define DBUS_SHARED_H
+
+/* Don't include anything in here from anywhere else. It's
+ * intended for use by any random library.
+ */
+
+#ifdef  __cplusplus
+extern "C" {
+#if 0
+} /* avoids confusing emacs indentation */
+#endif
+#endif
+
+/* Normally docs are in .c files, but there isn't a .c file for this. */
+/**
+ * @defgroup DBusShared Shared constants 
+ * @ingroup  DBus
+ *
+ * @brief Shared header included by both libdbus and C/C++ bindings such as the GLib bindings.
+ *
+ * Usually a C/C++ binding such as the GLib or Qt binding won't want to include dbus.h in its
+ * public headers. However, a few constants and macros may be useful to include; those are
+ * found here and in dbus-protocol.h
+ *
+ * @{
+ */
+
+
+/**
+ * Well-known bus types. See dbus_bus_get().
+ */
+typedef enum
+{
+  DBUS_BUS_SESSION,    /**< The login session bus */
+  DBUS_BUS_SYSTEM,     /**< The systemwide bus */
+  DBUS_BUS_STARTER     /**< The bus that started us, if any */
+} DBusBusType;
+
+/**
+ * Results that a message handler can return.
+ */
+typedef enum
+{
+  DBUS_HANDLER_RESULT_HANDLED,         /**< Message has had its effect - no need to run more handlers. */ 
+  DBUS_HANDLER_RESULT_NOT_YET_HANDLED, /**< Message has not had any effect - see if other handlers want it. */
+  DBUS_HANDLER_RESULT_NEED_MEMORY      /**< Need more memory in order to return #DBUS_HANDLER_RESULT_HANDLED or #DBUS_HANDLER_RESULT_NOT_YET_HANDLED. Please try again later with more memory. */
+} DBusHandlerResult;
+
+/* Bus names */
+
+/** The bus name used to talk to the bus itself. */
+#define DBUS_SERVICE_DBUS      "org.freedesktop.DBus"
+
+/* Paths */
+/** The object path used to talk to the bus itself. */
+#define DBUS_PATH_DBUS  "/org/freedesktop/DBus"
+/** The object path used in local/in-process-generated messages. */
+#define DBUS_PATH_LOCAL "/org/freedesktop/DBus/Local"
+
+/* Interfaces, these #define don't do much other than
+ * catch typos at compile time
+ */
+/** The interface exported by the object with #DBUS_SERVICE_DBUS and #DBUS_PATH_DBUS */
+#define DBUS_INTERFACE_DBUS           "org.freedesktop.DBus"
+/** The interface supported by introspectable objects */
+#define DBUS_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable"
+/** The interface supported by objects with properties */
+#define DBUS_INTERFACE_PROPERTIES     "org.freedesktop.DBus.Properties"
+/** The interface supported by most dbus peers */
+#define DBUS_INTERFACE_PEER           "org.freedesktop.DBus.Peer"
+
+/** This is a special interface whose methods can only be invoked
+ * by the local implementation (messages from remote apps aren't
+ * allowed to specify this interface).
+ */
+#define DBUS_INTERFACE_LOCAL "org.freedesktop.DBus.Local"
+
+/* Owner flags */
+#define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */
+#define DBUS_NAME_FLAG_REPLACE_EXISTING  0x2 /**< Request to replace the current primary owner */
+#define DBUS_NAME_FLAG_DO_NOT_QUEUE      0x4 /**< If we can not become the primary owner do not place us in the queue */
+
+/* Replies to request for a name */
+#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER  1 /**< Service has become the primary owner of the requested name */
+#define DBUS_REQUEST_NAME_REPLY_IN_QUEUE       2 /**< Service could not become the primary owner and has been placed in the queue */
+#define DBUS_REQUEST_NAME_REPLY_EXISTS         3 /**< Service is already in the queue */
+#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER  4 /**< Service is already the primary owner */
+
+/* Replies to releasing a name */
+#define DBUS_RELEASE_NAME_REPLY_RELEASED        1 /**< Service was released from the given name */
+#define DBUS_RELEASE_NAME_REPLY_NON_EXISTENT    2 /**< The given name does not exist on the bus */
+#define DBUS_RELEASE_NAME_REPLY_NOT_OWNER       3 /**< Service is not an owner of the given name */
+
+/* Replies to service starts */
+#define DBUS_START_REPLY_SUCCESS         1 /**< Service was auto started */
+#define DBUS_START_REPLY_ALREADY_RUNNING 2 /**< Service was already running */
+
+/** @} */
+
+#ifdef __cplusplus
+#if 0
+{ /* avoids confusing emacs indentation */
+#endif
+}
+#endif
+
+#endif /* DBUS_SHARED_H */
diff --git a/dbus/dbus/dbus-shell.c b/dbus/dbus/dbus-shell.c
new file mode 100644
index 0000000..111d39d
--- /dev/null
+++ b/dbus/dbus/dbus-shell.c
@@ -0,0 +1,641 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-shell.c Shell command line utility functions.
+ *
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include <string.h>
+#include "dbus-internals.h"
+#include "dbus-list.h"
+#include "dbus-memory.h"
+#include "dbus-protocol.h"
+#include "dbus-shell.h"
+#include "dbus-string.h"
+
+/* Single quotes preserve the literal string exactly. escape
+ * sequences are not allowed; not even \' - if you want a '
+ * in the quoted text, you have to do something like 'foo'\''bar'
+ *
+ * Double quotes allow $ ` " \ and newline to be escaped with backslash.
+ * Otherwise double quotes preserve things literally.
+ */
+
+static dbus_bool_t
+unquote_string_inplace (char* str, char** end)
+{
+  char* dest;
+  char* s;
+  char quote_char;
+  
+  dest = s = str;
+
+  quote_char = *s;
+  
+  if (!(*s == '"' || *s == '\''))
+    {
+      *end = str;
+      return FALSE;
+    }
+
+  /* Skip the initial quote mark */
+  ++s;
+
+  if (quote_char == '"')
+    {
+      while (*s)
+        {
+          _dbus_assert(s > dest); /* loop invariant */
+      
+          switch (*s)
+            {
+            case '"':
+              /* End of the string, return now */
+              *dest = '\0';
+              ++s;
+              *end = s;
+              return TRUE;
+
+            case '\\':
+              /* Possible escaped quote or \ */
+              ++s;
+              switch (*s)
+                {
+                case '"':
+                case '\\':
+                case '`':
+                case '$':
+                case '\n':
+                  *dest = *s;
+                  ++s;
+                  ++dest;
+                  break;
+
+                default:
+                  /* not an escaped char */
+                  *dest = '\\';
+                  ++dest;
+                  /* ++s already done. */
+                  break;
+                }
+              break;
+
+            default:
+              *dest = *s;
+              ++dest;
+              ++s;
+              break;
+            }
+
+          _dbus_assert(s > dest); /* loop invariant */
+        }
+    }
+  else
+    {
+      while (*s)
+        {
+          _dbus_assert(s > dest); /* loop invariant */
+          
+          if (*s == '\'')
+            {
+              /* End of the string, return now */
+              *dest = '\0';
+              ++s;
+              *end = s;
+              return TRUE;
+            }
+          else
+            {
+              *dest = *s;
+              ++dest;
+              ++s;
+            }
+
+          _dbus_assert(s > dest); /* loop invariant */
+        }
+    }
+  
+  /* If we reach here this means the close quote was never encountered */
+
+  *dest = '\0';
+  
+  *end = s;
+  return FALSE;
+}
+
+/** 
+ * Unquotes a string as the shell (/bin/sh) would. Only handles
+ * quotes; if a string contains file globs, arithmetic operators,
+ * variables, backticks, redirections, or other special-to-the-shell
+ * features, the result will be different from the result a real shell
+ * would produce (the variables, backticks, etc. will be passed
+ * through literally instead of being expanded). This function is
+ * guaranteed to succeed if applied to the result of
+ * _dbus_shell_quote(). If it fails, it returns %NULL.
+ * The @quoted_string need not actually contain quoted or
+ * escaped text; _dbus_shell_unquote() simply goes through the string and
+ * unquotes/unescapes anything that the shell would. Both single and
+ * double quotes are handled, as are escapes including escaped
+ * newlines. The return value must be freed with dbus_free().
+ * 
+ * Shell quoting rules are a bit strange. Single quotes preserve the
+ * literal string exactly. escape sequences are not allowed; not even
+ * \' - if you want a ' in the quoted text, you have to do something
+ * like 'foo'\''bar'.  Double quotes allow $, `, ", \, and newline to
+ * be escaped with backslash. Otherwise double quotes preserve things
+ * literally.
+ *
+ * @quoted_string: shell-quoted string
+ **/
+char*
+_dbus_shell_unquote (const char *quoted_string)
+{
+  char *unquoted;
+  char *end;
+  char *start;
+  char *ret;
+  DBusString retval;
+
+  unquoted = _dbus_strdup (quoted_string);
+  if (unquoted == NULL)
+    return NULL;
+
+  start = unquoted;
+  end = unquoted;
+  if (!_dbus_string_init (&retval))
+    {
+      dbus_free (unquoted);
+      return NULL;
+    }
+
+  /* The loop allows cases such as
+   * "foo"blah blah'bar'woo foo"baz"la la la\'\''foo'
+   */
+  while (*start)
+    {
+      /* Append all non-quoted chars, honoring backslash escape
+       */
+      
+      while (*start && !(*start == '"' || *start == '\''))
+        {
+          if (*start == '\\')
+            {
+              /* all characters can get escaped by backslash,
+               * except newline, which is removed if it follows
+               * a backslash outside of quotes
+               */
+              
+              ++start;
+              if (*start)
+                {
+                  if (*start != '\n')
+		    {
+		      if (!_dbus_string_append_byte (&retval, *start))
+			goto error;
+		    }
+                  ++start;
+                }
+            }
+          else
+            {
+              if (!_dbus_string_append_byte (&retval, *start))
+		goto error;
+              ++start;
+            }
+        }
+
+      if (*start)
+        {
+          if (!unquote_string_inplace (start, &end))
+	    goto error;
+          else
+            {
+              if (!_dbus_string_append (&retval, start))
+		goto error;
+              start = end;
+            }
+        }
+    }
+
+  ret = _dbus_strdup (_dbus_string_get_data (&retval));
+  if (!ret)
+    goto error;
+
+  dbus_free (unquoted);
+  _dbus_string_free (&retval);
+  
+  return ret;
+  
+ error:
+  dbus_free (unquoted);
+  _dbus_string_free (&retval);
+  return NULL;
+}
+
+/* _dbus_shell_parse_argv() does a semi-arbitrary weird subset of the way
+ * the shell parses a command line. We don't do variable expansion,
+ * don't understand that operators are tokens, don't do tilde expansion,
+ * don't do command substitution, no arithmetic expansion, IFS gets ignored,
+ * don't do filename globs, don't remove redirection stuff, etc.
+ *
+ * READ THE UNIX98 SPEC on "Shell Command Language" before changing
+ * the behavior of this code.
+ *
+ * Steps to parsing the argv string:
+ *
+ *  - tokenize the string (but since we ignore operators,
+ *    our tokenization may diverge from what the shell would do)
+ *    note that tokenization ignores the internals of a quoted
+ *    word and it always splits on spaces, not on IFS even
+ *    if we used IFS. We also ignore "end of input indicator"
+ *    (I guess this is control-D?)
+ *
+ *    Tokenization steps, from UNIX98 with operator stuff removed,
+ *    are:
+ * 
+ *    1) "If the current character is backslash, single-quote or
+ *        double-quote (\, ' or ") and it is not quoted, it will affect
+ *        quoting for subsequent characters up to the end of the quoted
+ *        text. The rules for quoting are as described in Quoting
+ *        . During token recognition no substitutions will be actually
+ *        performed, and the result token will contain exactly the
+ *        characters that appear in the input (except for newline
+ *        character joining), unmodified, including any embedded or
+ *        enclosing quotes or substitution operators, between the quote
+ *        mark and the end of the quoted text. The token will not be
+ *        delimited by the end of the quoted field."
+ *
+ *    2) "If the current character is an unquoted newline character,
+ *        the current token will be delimited."
+ *
+ *    3) "If the current character is an unquoted blank character, any
+ *        token containing the previous character is delimited and the
+ *        current character will be discarded."
+ *
+ *    4) "If the previous character was part of a word, the current
+ *        character will be appended to that word."
+ *
+ *    5) "If the current character is a "#", it and all subsequent
+ *        characters up to, but excluding, the next newline character
+ *        will be discarded as a comment. The newline character that
+ *        ends the line is not considered part of the comment. The
+ *        "#" starts a comment only when it is at the beginning of a
+ *        token. Since the search for the end-of-comment does not
+ *        consider an escaped newline character specially, a comment
+ *        cannot be continued to the next line."
+ *
+ *    6) "The current character will be used as the start of a new word."
+ *
+ *
+ *  - for each token (word), perform portions of word expansion, namely
+ *    field splitting (using default whitespace IFS) and quote
+ *    removal.  Field splitting may increase the number of words.
+ *    Quote removal does not increase the number of words.
+ *
+ *   "If the complete expansion appropriate for a word results in an
+ *   empty field, that empty field will be deleted from the list of
+ *   fields that form the completely expanded command, unless the
+ *   original word contained single-quote or double-quote characters."
+ *    - UNIX98 spec
+ *
+ *
+ */
+
+static dbus_bool_t
+delimit_token (DBusString *token,
+               DBusList **retval,
+	       DBusError *error)
+{
+  char *str;
+
+  str = _dbus_strdup (_dbus_string_get_data (token));
+  if (!str)
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!_dbus_list_append (retval, str))
+    {
+      dbus_free (str);
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static DBusList*
+tokenize_command_line (const char *command_line, DBusError *error)
+{
+  char current_quote;
+  const char *p;
+  DBusString current_token;
+  DBusList *retval = NULL;
+  dbus_bool_t quoted;;
+
+  current_quote = '\0';
+  quoted = FALSE;
+  p = command_line;
+
+  if (!_dbus_string_init (&current_token))
+    {
+      _DBUS_SET_OOM (error);
+      return NULL;
+    }
+
+  while (*p)
+    {
+      if (current_quote == '\\')
+        {
+          if (*p == '\n')
+            {
+              /* we append nothing; backslash-newline become nothing */
+            }
+          else
+            {
+	      if (!_dbus_string_append_byte (&current_token, '\\') || 
+	          !_dbus_string_append_byte (&current_token, *p))
+		{
+		  _DBUS_SET_OOM (error);
+		  goto error;
+		}
+            }
+
+          current_quote = '\0';
+        }
+      else if (current_quote == '#')
+        {
+          /* Discard up to and including next newline */
+          while (*p && *p != '\n')
+            ++p;
+
+          current_quote = '\0';
+          
+          if (*p == '\0')
+            break;
+        }
+      else if (current_quote)
+        {
+          if (*p == current_quote &&
+              /* check that it isn't an escaped double quote */
+              !(current_quote == '"' && quoted))
+            {
+              /* close the quote */
+              current_quote = '\0';
+            }
+
+          /* Everything inside quotes, and the close quote,
+           * gets appended literally.
+           */
+
+          if (!_dbus_string_append_byte (&current_token, *p))
+	    {
+	      _DBUS_SET_OOM (error);
+	      goto error;
+	    }
+        }
+      else
+        {
+          switch (*p)
+            {
+            case '\n':
+              if (!delimit_token (&current_token, &retval, error))
+		goto error;
+
+		_dbus_string_free (&current_token);
+
+		if (!_dbus_string_init (&current_token))
+		  {
+		    _DBUS_SET_OOM (error);
+		    goto init_error;
+		  }
+
+              break;
+
+            case ' ':
+            case '\t':
+              /* If the current token contains the previous char, delimit
+               * the current token. A nonzero length
+               * token should always contain the previous char.
+               */
+              if (_dbus_string_get_length (&current_token) > 0)
+                {
+                  if (!delimit_token (&current_token, &retval, error))
+		    goto error;
+
+		  _dbus_string_free (&current_token);
+
+		  if (!_dbus_string_init (&current_token))
+		    {
+		      _DBUS_SET_OOM (error);
+		      goto init_error;
+		    }
+
+                }
+              
+              /* discard all unquoted blanks (don't add them to a token) */
+              break;
+
+
+              /* single/double quotes are appended to the token,
+               * escapes are maybe appended next time through the loop,
+               * comment chars are never appended.
+               */
+              
+            case '\'':
+            case '"':
+              if (!_dbus_string_append_byte (&current_token, *p))
+		{
+		  _DBUS_SET_OOM (error);
+		  goto error;
+		}
+
+              /* FALL THRU */
+              
+            case '#':
+            case '\\':
+              current_quote = *p;
+              break;
+
+            default:
+              /* Combines rules 4) and 6) - if we have a token, append to it,
+               * otherwise create a new token.
+               */
+              if (!_dbus_string_append_byte (&current_token, *p))
+		{
+		  _DBUS_SET_OOM (error);
+		  goto error;
+		}
+              break;
+            }
+        }
+
+      /* We need to count consecutive backslashes mod 2, 
+       * to detect escaped doublequotes.
+       */
+      if (*p != '\\')
+	quoted = FALSE;
+      else
+	quoted = !quoted;
+
+      ++p;
+    }
+
+  if (!delimit_token (&current_token, &retval, error))
+    goto error;
+
+  if (current_quote)
+    {
+      dbus_set_error_const (error, DBUS_ERROR_INVALID_ARGS, "Unclosed quotes in command line");
+      goto error;
+    }
+
+  if (retval == NULL)
+    {
+      dbus_set_error_const (error, DBUS_ERROR_INVALID_ARGS, "No tokens found in command line");
+      goto error;
+    }
+ 
+  _dbus_string_free (&current_token);
+ 
+  return retval;
+
+ error:
+  _dbus_string_free (&current_token);
+
+ init_error:
+  if (retval)
+    {
+      _dbus_list_foreach (&retval, (DBusForeachFunction) dbus_free, NULL);
+      _dbus_list_clear (&retval);
+    }
+
+  return NULL;
+}
+
+/**
+ * _dbus_shell_parse_argv:
+ * 
+ * Parses a command line into an argument vector, in much the same way
+ * the shell would, but without many of the expansions the shell would
+ * perform (variable expansion, globs, operators, filename expansion,
+ * etc. are not supported). The results are defined to be the same as
+ * those you would get from a UNIX98 /bin/sh, as long as the input
+ * contains none of the unsupported shell expansions. If the input
+ * does contain such expansions, they are passed through
+ * literally. Free the returned vector with dbus_free_string_array().
+ * 
+ * @command_line: command line to parse
+ * @argcp: return location for number of args
+ * @argvp: return location for array of args
+ * @error: error information
+ **/
+dbus_bool_t
+_dbus_shell_parse_argv (const char *command_line,
+			int        *argcp,
+			char     ***argvp,
+			DBusError  *error)
+{
+  /* Code based on poptParseArgvString() from libpopt */
+  int argc = 0;
+  char **argv = NULL;
+  DBusList *tokens = NULL;
+  int i;
+  DBusList *tmp_list;
+  
+  if (!command_line)
+    {
+      _dbus_verbose ("Command line is NULL\n");
+      return FALSE;
+    }
+
+  tokens = tokenize_command_line (command_line, error);
+  if (tokens == NULL)
+    {
+      _dbus_verbose ("No tokens for command line '%s'\n", command_line);
+      return FALSE;
+    }
+
+  /* Because we can't have introduced any new blank space into the
+   * tokens (we didn't do any new expansions), we don't need to
+   * perform field splitting. If we were going to honor IFS or do any
+   * expansions, we would have to do field splitting on each word
+   * here. Also, if we were going to do any expansion we would need to
+   * remove any zero-length words that didn't contain quotes
+   * originally; but since there's no expansion we know all words have
+   * nonzero length, unless they contain quotes.
+   * 
+   * So, we simply remove quotes, and don't do any field splitting or
+   * empty word removal, since we know there was no way to introduce
+   * such things.
+   */
+
+  argc = _dbus_list_get_length (&tokens);
+  argv = dbus_new (char *, argc + 1);
+  if (!argv)
+    {
+      _DBUS_SET_OOM (error);
+      goto error;
+    }
+
+  i = 0;
+  tmp_list = tokens;
+  while (tmp_list)
+    {
+      argv[i] = _dbus_shell_unquote (tmp_list->data);
+
+      if (!argv[i])
+        {
+          int j;
+	  for (j = 0; j < i; j++)
+	    dbus_free(argv[j]);
+
+          dbus_free (argv);
+	  _DBUS_SET_OOM (error);
+	  goto error;
+        }
+
+      tmp_list = _dbus_list_get_next_link (&tokens, tmp_list);
+      ++i;
+    }
+  argv[argc] = NULL;
+  
+  _dbus_list_foreach (&tokens, (DBusForeachFunction) dbus_free, NULL);
+  _dbus_list_clear (&tokens);
+  
+  if (argcp)
+    *argcp = argc;
+
+  if (argvp)
+    *argvp = argv;
+  else
+    dbus_free_string_array (argv);
+
+  return TRUE;
+
+ error:
+  _dbus_list_foreach (&tokens, (DBusForeachFunction) dbus_free, NULL);
+  _dbus_list_clear (&tokens);
+
+  return FALSE;
+
+}
diff --git a/dbus/dbus/dbus-shell.h b/dbus/dbus/dbus-shell.h
new file mode 100644
index 0000000..06da274
--- /dev/null
+++ b/dbus/dbus/dbus-shell.h
@@ -0,0 +1,41 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-shell.h Shell command line utility functions.
+ *
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+
+#ifndef DBUS_SHELL_H
+#define DBUS_SHELL_H
+
+DBUS_BEGIN_DECLS
+
+char*       _dbus_shell_unquote    (const char *quoted_string);
+dbus_bool_t _dbus_shell_parse_argv (const char *command_line,
+                                    int        *argcp,
+                                    char       ***argvp,
+				    DBusError  *error);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SHELL_H */
+
+
diff --git a/dbus/dbus/dbus-signature.c b/dbus/dbus/dbus-signature.c
new file mode 100644
index 0000000..c130de5
--- /dev/null
+++ b/dbus/dbus/dbus-signature.c
@@ -0,0 +1,589 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-signature.c  Routines for reading recursive type signatures
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include "dbus-signature.h"
+#include "dbus-marshal-recursive.h"
+#include "dbus-marshal-basic.h"
+#include "dbus-internals.h"
+#include "dbus-test.h"
+
+/**
+ * Implementation details of #DBusSignatureIter, all fields are private
+ */
+typedef struct
+{ 
+  const char *pos;           /**< current position in the signature string */
+  unsigned int finished : 1; /**< true if we are at the end iter */
+  unsigned int in_array : 1; /**< true if we are a subiterator pointing to an array's element type */
+} DBusSignatureRealIter;
+
+/** macro that checks whether a typecode is a container type */
+#define TYPE_IS_CONTAINER(typecode)             \
+    ((typecode) == DBUS_TYPE_STRUCT ||          \
+     (typecode) == DBUS_TYPE_DICT_ENTRY ||      \
+     (typecode) == DBUS_TYPE_VARIANT ||         \
+     (typecode) == DBUS_TYPE_ARRAY)
+
+
+/**
+ * @defgroup DBusSignature Type signature parsing
+ * @ingroup  DBus
+ * @brief Parsing D-Bus type signatures
+ * @{
+ */
+
+/**
+ * Initializes a #DBusSignatureIter for reading a type signature.  This
+ * function is not safe to use on invalid signatures; be sure to
+ * validate potentially invalid signatures with dbus_signature_validate
+ * before using this function.
+ *
+ * @param iter pointer to an iterator to initialize
+ * @param signature the type signature
+ */
+void
+dbus_signature_iter_init (DBusSignatureIter *iter,
+			  const char        *signature)
+{
+  DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
+
+  real_iter->pos = signature;
+  real_iter->finished = FALSE;
+  real_iter->in_array = FALSE;
+}
+
+/**
+ * Returns the current type pointed to by the iterator.
+ * If the iterator is pointing at a type code such as 's', then
+ * it will be returned directly.
+ *
+ * However, when the parser encounters a container type start
+ * character such as '(' for a structure, the corresponding type for
+ * the container will be returned, e.g.  DBUS_TYPE_STRUCT, not '('.
+ * In this case, you should initialize a sub-iterator with
+ * dbus_signature_iter_recurse() to parse the container type.
+ *
+ * @param iter pointer to an iterator 
+ * @returns current type (e.g. #DBUS_TYPE_STRING, #DBUS_TYPE_ARRAY)
+ */
+int
+dbus_signature_iter_get_current_type (const DBusSignatureIter *iter)
+{
+  DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
+
+  return _dbus_first_type_in_signature_c_str (real_iter->pos, 0);
+}
+
+/**
+ * Returns the signature of the single complete type starting at the
+ * given iterator.
+ *
+ * For example, if the iterator is pointing at the start of "(ii)ii"
+ * (which is "a struct of two ints, followed by an int, followed by an
+ * int"), then "(ii)" would be returned. If the iterator is pointing at
+ * one of the "i" then just that "i" would be returned.
+ *
+ * @param iter pointer to an iterator 
+ * @returns current signature; or #NULL if no memory.  Should be freed with dbus_free()
+ */
+char *
+dbus_signature_iter_get_signature (const DBusSignatureIter *iter)
+{
+  DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
+  DBusString str;
+  char *ret;
+  int pos;
+  
+  if (!_dbus_string_init (&str))
+    return NULL;
+
+  pos = 0;
+  _dbus_type_signature_next (real_iter->pos, &pos);
+
+  if (!_dbus_string_append_len (&str, real_iter->pos, pos))
+    return NULL;
+  if (!_dbus_string_steal_data (&str, &ret))
+    ret = NULL;
+  _dbus_string_free (&str);
+
+  return ret; 
+}
+
+/**
+ * Convenience function for returning the element type of an array;
+ * This function allows you to avoid initializing a sub-iterator and
+ * getting its current type.
+ *
+ * Undefined behavior results if you invoke this function when the
+ * current type of the iterator is not #DBUS_TYPE_ARRAY.
+ *
+ * @param iter pointer to an iterator 
+ * @returns current array element type
+ */
+int
+dbus_signature_iter_get_element_type (const DBusSignatureIter *iter)
+{
+  DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
+
+  _dbus_return_val_if_fail (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
+
+  return _dbus_first_type_in_signature_c_str (real_iter->pos, 1);
+}
+
+/**
+ * Skip to the next value on this "level". e.g. the next field in a
+ * struct, the next value in an array. Returns #FALSE at the end of the
+ * current container.
+ *
+ * @param iter the iterator
+ * @returns FALSE if nothing more to read at or below this level
+ */
+dbus_bool_t
+dbus_signature_iter_next (DBusSignatureIter *iter)
+{
+  DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
+
+  if (real_iter->finished)
+    return FALSE;
+  else
+    {
+      int pos;
+
+      if (real_iter->in_array)
+	{
+	  real_iter->finished = TRUE;
+	  return FALSE;
+	}
+
+      pos = 0;
+      _dbus_type_signature_next (real_iter->pos, &pos);
+      real_iter->pos += pos;
+
+      if (*real_iter->pos == DBUS_STRUCT_END_CHAR
+	  || *real_iter->pos == DBUS_DICT_ENTRY_END_CHAR)
+	{
+	  real_iter->finished = TRUE;
+	  return FALSE;
+	}
+
+      return *real_iter->pos != DBUS_TYPE_INVALID;
+    }
+}
+
+/**
+ * Initialize a new iterator pointing to the first type in the current
+ * container.
+ * 
+ * The results are undefined when calling this if the current type is
+ * a non-container (i.e. if dbus_type_is_container() returns #FALSE
+ * for the result of dbus_signature_iter_get_current_type()).
+ *
+ * @param iter the current interator
+ * @param subiter an iterator to initialize pointing to the first child
+ */
+void
+dbus_signature_iter_recurse (const DBusSignatureIter *iter,
+			     DBusSignatureIter       *subiter)
+{
+  DBusSignatureRealIter *real_iter = (DBusSignatureRealIter *) iter;
+  DBusSignatureRealIter *real_sub_iter = (DBusSignatureRealIter *) subiter;
+
+  _dbus_return_if_fail (dbus_type_is_container (dbus_signature_iter_get_current_type (iter)));
+
+  *real_sub_iter = *real_iter;
+  real_sub_iter->in_array = FALSE;
+  real_sub_iter->pos++;
+
+  if (dbus_signature_iter_get_current_type (iter) == DBUS_TYPE_ARRAY)
+    real_sub_iter->in_array = TRUE;
+}
+
+/**
+ * Check a type signature for validity. Remember that #NULL can always
+ * be passed instead of a DBusError*, if you don't care about having
+ * an error name and message.
+ *
+ * @param signature a potentially invalid type signature
+ * @param error error return
+ * @returns #TRUE if signature is valid or #FALSE if an error is set
+ */
+dbus_bool_t
+dbus_signature_validate (const char       *signature,
+			 DBusError        *error)
+			 
+{
+  DBusString str;
+  DBusValidity reason;
+
+  _dbus_string_init_const (&str, signature);
+  reason = _dbus_validate_signature_with_reason (&str, 0, _dbus_string_get_length (&str));
+
+  if (reason == DBUS_VALID)
+    return TRUE;
+  else
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, _dbus_validity_to_error_message (reason));
+      return FALSE;
+    }
+}
+
+/**
+ * Check that a type signature is both valid and contains exactly one
+ * complete type. "One complete type" means a single basic type,
+ * array, struct, or dictionary, though the struct or array may be
+ * arbitrarily recursive and complex. More than one complete type
+ * would mean for example "ii" or two integers in sequence.
+ *
+ * @param signature a potentially invalid type signature
+ * @param error error return
+ * @returns #TRUE if signature is valid and has exactly one complete type
+ */
+dbus_bool_t
+dbus_signature_validate_single (const char       *signature,
+				DBusError        *error)
+{
+  DBusSignatureIter iter;
+
+  if (!dbus_signature_validate (signature, error))
+    return FALSE;
+
+  dbus_signature_iter_init (&iter, signature);
+  if (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID)
+    goto lose;
+  if (!dbus_signature_iter_next (&iter))
+    return TRUE;
+ lose:
+  dbus_set_error (error, DBUS_ERROR_INVALID_SIGNATURE, "Exactly one complete type required in signature");
+  return FALSE;
+}
+
+/**
+ * A "container type" can contain basic types, or nested
+ * container types. #DBUS_TYPE_INVALID is not a container type.
+ *
+ * It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
+ * to this function. The valid type-codes are defined by dbus-protocol.h
+ * and can be checked with dbus_type_is_valid().
+ *
+ * @param typecode either a valid type-code or DBUS_TYPE_INVALID
+ * @returns #TRUE if type is a container
+ */
+dbus_bool_t
+dbus_type_is_container (int typecode)
+{
+  /* only reasonable (non-line-noise) typecodes are allowed */
+  _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
+			    FALSE);
+  return TYPE_IS_CONTAINER (typecode);
+}
+
+/**
+ * A "basic type" is a somewhat arbitrary concept, but the intent is
+ * to include those types that are fully-specified by a single
+ * typecode, with no additional type information or nested values. So
+ * all numbers and strings are basic types and structs, arrays, and
+ * variants are not basic types.  #DBUS_TYPE_INVALID is not a basic
+ * type.
+ *
+ * It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
+ * to this function. The valid type-codes are defined by dbus-protocol.h
+ * and can be checked with dbus_type_is_valid().
+ *
+ * @param typecode either a valid type-code or DBUS_TYPE_INVALID
+ * @returns #TRUE if type is basic
+ */
+dbus_bool_t
+dbus_type_is_basic (int typecode)
+{
+  /* only reasonable (non-line-noise) typecodes are allowed */
+  _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
+			    FALSE);
+
+  /* everything that isn't invalid or a container */
+  return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode));
+}
+
+/**
+ * Tells you whether values of this type can change length if you set
+ * them to some other value. For this purpose, you assume that the
+ * first byte of the old and new value would be in the same location,
+ * so alignment padding is not a factor.
+ *
+ * This function is useful to determine whether
+ * dbus_message_iter_get_fixed_array() may be used.
+ *
+ * Some structs are fixed-size (if they contain only fixed-size types)
+ * but struct is not considered a fixed type for purposes of this
+ * function.
+ *
+ * It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
+ * to this function. The valid type-codes are defined by dbus-protocol.h
+ * and can be checked with dbus_type_is_valid().
+ *
+ * @param typecode either a valid type-code or DBUS_TYPE_INVALID
+ * @returns #FALSE if the type can occupy different lengths
+ */
+dbus_bool_t
+dbus_type_is_fixed (int typecode)
+{
+  /* only reasonable (non-line-noise) typecodes are allowed */
+  _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
+			    FALSE);
+  
+  switch (typecode)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+    case DBUS_TYPE_UNIX_FD:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+/**
+ * Return #TRUE if the argument is a valid typecode.
+ * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and
+ * random unknown bytes aren't either. This function is safe with
+ * untrusted data.
+ *
+ * @param typecode a potential type-code
+ * @returns #TRUE if valid
+ */
+dbus_bool_t
+dbus_type_is_valid (int typecode)
+{
+  switch (typecode)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+    case DBUS_TYPE_INT16:
+    case DBUS_TYPE_UINT16:
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64:
+    case DBUS_TYPE_DOUBLE:
+    case DBUS_TYPE_STRING:
+    case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_SIGNATURE:
+    case DBUS_TYPE_ARRAY:
+    case DBUS_TYPE_STRUCT:
+    case DBUS_TYPE_DICT_ENTRY:
+    case DBUS_TYPE_VARIANT:
+    case DBUS_TYPE_UNIX_FD:
+      return TRUE;
+
+    default:
+      return FALSE;
+    }
+}
+
+/** @} */ /* end of DBusSignature group */
+
+#ifdef DBUS_BUILD_TESTS
+
+/**
+ * @ingroup DBusSignatureInternals
+ * Unit test for DBusSignature.
+ *
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_signature_test (void)
+{
+  DBusSignatureIter iter;
+  DBusSignatureIter subiter;
+  DBusSignatureIter subsubiter;
+  DBusSignatureIter subsubsubiter;
+  const char *sig;
+  dbus_bool_t boolres;
+
+  _dbus_assert (sizeof (DBusSignatureIter) >= sizeof (DBusSignatureRealIter));
+
+  sig = "";
+  _dbus_assert (dbus_signature_validate (sig, NULL));
+  _dbus_assert (!dbus_signature_validate_single (sig, NULL));
+  dbus_signature_iter_init (&iter, sig);
+  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID);
+
+  sig = DBUS_TYPE_STRING_AS_STRING;
+  _dbus_assert (dbus_signature_validate (sig, NULL));
+  _dbus_assert (dbus_signature_validate_single (sig, NULL));
+  dbus_signature_iter_init (&iter, sig);
+  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
+
+  sig = DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
+  _dbus_assert (dbus_signature_validate (sig, NULL));
+  dbus_signature_iter_init (&iter, sig);
+  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
+  boolres = dbus_signature_iter_next (&iter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_BYTE);
+
+  sig = DBUS_TYPE_UINT16_AS_STRING
+    DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+    DBUS_TYPE_STRING_AS_STRING
+    DBUS_TYPE_UINT32_AS_STRING
+    DBUS_TYPE_VARIANT_AS_STRING
+    DBUS_TYPE_DOUBLE_AS_STRING
+    DBUS_STRUCT_END_CHAR_AS_STRING;
+  _dbus_assert (dbus_signature_validate (sig, NULL));
+  dbus_signature_iter_init (&iter, sig);
+  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
+  boolres = dbus_signature_iter_next (&iter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
+  dbus_signature_iter_recurse (&iter, &subiter);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRING);
+  boolres = dbus_signature_iter_next (&subiter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
+  boolres = dbus_signature_iter_next (&subiter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_VARIANT);
+  boolres = dbus_signature_iter_next (&subiter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_DOUBLE);
+
+  sig = DBUS_TYPE_UINT16_AS_STRING
+    DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+    DBUS_TYPE_UINT32_AS_STRING
+    DBUS_TYPE_BYTE_AS_STRING
+    DBUS_TYPE_ARRAY_AS_STRING
+    DBUS_TYPE_ARRAY_AS_STRING
+    DBUS_TYPE_DOUBLE_AS_STRING
+    DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+    DBUS_TYPE_BYTE_AS_STRING
+    DBUS_STRUCT_END_CHAR_AS_STRING
+    DBUS_STRUCT_END_CHAR_AS_STRING;
+  _dbus_assert (dbus_signature_validate (sig, NULL));
+  dbus_signature_iter_init (&iter, sig);
+  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
+  boolres = dbus_signature_iter_next (&iter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
+  dbus_signature_iter_recurse (&iter, &subiter);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
+  boolres = dbus_signature_iter_next (&subiter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_BYTE);
+  boolres = dbus_signature_iter_next (&subiter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_ARRAY);
+  _dbus_assert (dbus_signature_iter_get_element_type (&subiter) == DBUS_TYPE_ARRAY);
+
+  dbus_signature_iter_recurse (&subiter, &subsubiter);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_ARRAY);
+  _dbus_assert (dbus_signature_iter_get_element_type (&subsubiter) == DBUS_TYPE_DOUBLE);
+
+  dbus_signature_iter_recurse (&subsubiter, &subsubsubiter);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subsubsubiter) == DBUS_TYPE_DOUBLE);
+  boolres = dbus_signature_iter_next (&subiter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRUCT);
+  dbus_signature_iter_recurse (&subiter, &subsubiter);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_BYTE);
+
+  sig = DBUS_TYPE_ARRAY_AS_STRING
+    DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+    DBUS_TYPE_INT16_AS_STRING
+    DBUS_TYPE_STRING_AS_STRING
+    DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+    DBUS_TYPE_VARIANT_AS_STRING;
+  _dbus_assert (dbus_signature_validate (sig, NULL));
+  _dbus_assert (!dbus_signature_validate_single (sig, NULL));
+  dbus_signature_iter_init (&iter, sig);
+  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_ARRAY);
+  _dbus_assert (dbus_signature_iter_get_element_type (&iter) == DBUS_TYPE_DICT_ENTRY);
+
+  dbus_signature_iter_recurse (&iter, &subiter);
+  dbus_signature_iter_recurse (&subiter, &subsubiter);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_INT16);
+  boolres = dbus_signature_iter_next (&subsubiter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_STRING);
+  boolres = dbus_signature_iter_next (&subsubiter);
+  _dbus_assert (!boolres);
+
+  boolres = dbus_signature_iter_next (&iter);
+  _dbus_assert (boolres);
+  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_VARIANT);
+  boolres = dbus_signature_iter_next (&iter);
+  _dbus_assert (!boolres);
+
+  sig = DBUS_TYPE_DICT_ENTRY_AS_STRING;
+  _dbus_assert (!dbus_signature_validate (sig, NULL));
+
+  sig = DBUS_TYPE_ARRAY_AS_STRING;
+  _dbus_assert (!dbus_signature_validate (sig, NULL));
+
+  sig = DBUS_TYPE_UINT32_AS_STRING
+    DBUS_TYPE_ARRAY_AS_STRING;
+  _dbus_assert (!dbus_signature_validate (sig, NULL));
+
+  sig = DBUS_TYPE_ARRAY_AS_STRING
+    DBUS_TYPE_DICT_ENTRY_AS_STRING;
+  _dbus_assert (!dbus_signature_validate (sig, NULL));
+
+  sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING;
+  _dbus_assert (!dbus_signature_validate (sig, NULL));
+
+  sig = DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
+  _dbus_assert (!dbus_signature_validate (sig, NULL));
+
+  sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+    DBUS_TYPE_INT32_AS_STRING;
+  _dbus_assert (!dbus_signature_validate (sig, NULL));
+
+  sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+    DBUS_TYPE_INT32_AS_STRING
+    DBUS_TYPE_STRING_AS_STRING;
+  _dbus_assert (!dbus_signature_validate (sig, NULL));
+
+  sig = DBUS_STRUCT_END_CHAR_AS_STRING
+    DBUS_STRUCT_BEGIN_CHAR_AS_STRING;
+  _dbus_assert (!dbus_signature_validate (sig, NULL));
+
+  sig = DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+    DBUS_TYPE_BOOLEAN_AS_STRING;
+  _dbus_assert (!dbus_signature_validate (sig, NULL));
+  return TRUE;
+#if 0
+ oom:
+  _dbus_assert_not_reached ("out of memory");
+  return FALSE;
+#endif
+}
+
+#endif
+
diff --git a/dbus/dbus/dbus-signature.h b/dbus/dbus/dbus-signature.h
new file mode 100644
index 0000000..443941c
--- /dev/null
+++ b/dbus/dbus/dbus-signature.h
@@ -0,0 +1,95 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-signatures.h utility functions for D-Bus types
+ *
+ * Copyright (C) 2005 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_SIGNATURES_H
+#define DBUS_SIGNATURES_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusSignature
+ * @{
+ */
+
+/**
+ * DBusSignatureIter struct; contains no public fields 
+ */
+typedef struct
+{ 
+  void *dummy1;         /**< Don't use this */
+  void *dummy2;         /**< Don't use this */
+  dbus_uint32_t dummy8; /**< Don't use this */
+  int dummy12;           /**< Don't use this */
+  int dummy17;           /**< Don't use this */
+} DBusSignatureIter;
+
+DBUS_EXPORT
+void            dbus_signature_iter_init             (DBusSignatureIter       *iter,
+						      const char              *signature);
+
+DBUS_EXPORT
+int             dbus_signature_iter_get_current_type (const DBusSignatureIter *iter);
+
+DBUS_EXPORT
+char *          dbus_signature_iter_get_signature    (const DBusSignatureIter *iter);
+
+DBUS_EXPORT
+int             dbus_signature_iter_get_element_type (const DBusSignatureIter *iter);
+
+DBUS_EXPORT
+dbus_bool_t     dbus_signature_iter_next             (DBusSignatureIter       *iter);
+
+DBUS_EXPORT
+void            dbus_signature_iter_recurse          (const DBusSignatureIter *iter,
+						      DBusSignatureIter       *subiter);
+
+DBUS_EXPORT
+dbus_bool_t     dbus_signature_validate              (const char       *signature,
+						      DBusError        *error);
+
+DBUS_EXPORT
+dbus_bool_t     dbus_signature_validate_single       (const char       *signature,
+						      DBusError        *error);
+
+DBUS_EXPORT
+dbus_bool_t     dbus_type_is_valid                   (int            typecode);
+
+DBUS_EXPORT
+dbus_bool_t     dbus_type_is_basic                   (int            typecode);
+DBUS_EXPORT
+dbus_bool_t     dbus_type_is_container               (int            typecode);
+DBUS_EXPORT
+dbus_bool_t     dbus_type_is_fixed                   (int            typecode);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SIGNATURE_H */
diff --git a/dbus/dbus/dbus-socket-set-epoll.c b/dbus/dbus/dbus-socket-set-epoll.c
new file mode 100644
index 0000000..4cd9a56
--- /dev/null
+++ b/dbus/dbus/dbus-socket-set-epoll.c
@@ -0,0 +1,371 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-socket-set-epoll.c - a socket set implemented via Linux epoll(4)
+ *
+ * Copyright © 2011 Nokia Corporation
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-socket-set.h"
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-sysdeps.h>
+
+#ifndef __linux__
+# error This file is for Linux epoll(4)
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/epoll.h>
+#include <unistd.h>
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+typedef struct {
+    DBusSocketSet parent;
+    int epfd;
+} DBusSocketSetEpoll;
+
+static inline DBusSocketSetEpoll *
+socket_set_epoll_cast (DBusSocketSet *set)
+{
+  _dbus_assert (set->cls == &_dbus_socket_set_epoll_class);
+  return (DBusSocketSetEpoll *) set;
+}
+
+/* this is safe to call on a partially-allocated socket set */
+static void
+socket_set_epoll_free (DBusSocketSet *set)
+{
+  DBusSocketSetEpoll *self = socket_set_epoll_cast (set);
+
+  if (self == NULL)
+    return;
+
+  if (self->epfd != -1)
+    close (self->epfd);
+
+  dbus_free (self);
+}
+
+DBusSocketSet *
+_dbus_socket_set_epoll_new (void)
+{
+  DBusSocketSetEpoll *self;
+
+  self = dbus_new0 (DBusSocketSetEpoll, 1);
+
+  if (self == NULL)
+    return NULL;
+
+  self->parent.cls = &_dbus_socket_set_epoll_class;
+
+  self->epfd = epoll_create1 (EPOLL_CLOEXEC);
+
+  if (self->epfd == -1)
+    {
+      int flags;
+
+      /* the size hint is ignored unless you have a rather old kernel,
+       * but must be positive on some versions, so just pick something
+       * arbitrary; it's a hint, not a limit */
+      self->epfd = epoll_create (42);
+
+      flags = fcntl (self->epfd, F_GETFD, 0);
+
+      if (flags != -1)
+        fcntl (self->epfd, F_SETFD, flags | FD_CLOEXEC);
+    }
+
+  if (self->epfd == -1)
+    {
+      socket_set_epoll_free ((DBusSocketSet *) self);
+      return NULL;
+    }
+
+  return (DBusSocketSet *) self;
+}
+
+static uint32_t
+watch_flags_to_epoll_events (unsigned int flags)
+{
+  uint32_t events = 0;
+
+  if (flags & DBUS_WATCH_READABLE)
+    events |= EPOLLIN;
+  if (flags & DBUS_WATCH_WRITABLE)
+    events |= EPOLLOUT;
+
+  return events;
+}
+
+static unsigned int
+epoll_events_to_watch_flags (uint32_t events)
+{
+  short flags = 0;
+
+  if (events & EPOLLIN)
+    flags |= DBUS_WATCH_READABLE;
+  if (events & EPOLLOUT)
+    flags |= DBUS_WATCH_WRITABLE;
+  if (events & EPOLLHUP)
+    flags |= DBUS_WATCH_HANGUP;
+  if (events & EPOLLERR)
+    flags |= DBUS_WATCH_ERROR;
+
+  return flags;
+}
+
+static dbus_bool_t
+socket_set_epoll_add (DBusSocketSet  *set,
+                      int             fd,
+                      unsigned int    flags,
+                      dbus_bool_t     enabled)
+{
+  DBusSocketSetEpoll *self = socket_set_epoll_cast (set);
+  struct epoll_event event;
+  int err;
+
+  event.data.fd = fd;
+
+  if (enabled)
+    {
+      event.events = watch_flags_to_epoll_events (flags);
+    }
+  else
+    {
+      /* We need to add *something* to reserve space in the kernel's data
+       * structures: see socket_set_epoll_disable for more details */
+      event.events = EPOLLET;
+    }
+
+  if (epoll_ctl (self->epfd, EPOLL_CTL_ADD, fd, &event) == 0)
+    return TRUE;
+
+  /* Anything except ENOMEM, ENOSPC means we have an internal error. */
+  err = errno;
+  switch (err)
+    {
+      case ENOMEM:
+      case ENOSPC:
+        /* be silent: this is basically OOM, which our callers are expected
+         * to cope with */
+        break;
+
+      case EBADF:
+        _dbus_warn ("Bad fd %d\n", fd);
+        break;
+
+      case EEXIST:
+        _dbus_warn ("fd %d added and then added again\n", fd);
+        break;
+
+      default:
+        _dbus_warn ("Misc error when trying to watch fd %d: %s\n", fd,
+                    strerror (err));
+        break;
+    }
+
+  return FALSE;
+}
+
+static void
+socket_set_epoll_enable (DBusSocketSet  *set,
+                         int             fd,
+                         unsigned int    flags)
+{
+  DBusSocketSetEpoll *self = socket_set_epoll_cast (set);
+  struct epoll_event event;
+  int err;
+
+  event.data.fd = fd;
+  event.events = watch_flags_to_epoll_events (flags);
+
+  if (epoll_ctl (self->epfd, EPOLL_CTL_MOD, fd, &event) == 0)
+    return;
+
+  err = errno;
+
+  /* Enabling a file descriptor isn't allowed to fail, even for OOM, so we
+   * do our best to avoid all of these. */
+  switch (err)
+    {
+      case EBADF:
+        _dbus_warn ("Bad fd %d\n", fd);
+        break;
+
+      case ENOENT:
+        _dbus_warn ("fd %d enabled before it was added\n", fd);
+        break;
+
+      case ENOMEM:
+        _dbus_warn ("Insufficient memory to change watch for fd %d\n", fd);
+        break;
+
+      default:
+        _dbus_warn ("Misc error when trying to watch fd %d: %s\n", fd,
+                    strerror (err));
+        break;
+    }
+}
+
+static void
+socket_set_epoll_disable (DBusSocketSet  *set,
+                          int             fd)
+{
+  DBusSocketSetEpoll *self = socket_set_epoll_cast (set);
+  struct epoll_event event;
+  int err;
+
+  /* The naive thing to do would be EPOLL_CTL_DEL, but that'll probably
+   * free resources in the kernel. When we come to do socket_set_epoll_enable,
+   * there might not be enough resources to bring it back!
+   *
+   * The next idea you might have is to set the flags to 0. However, events
+   * always trigger on EPOLLERR and EPOLLHUP, even if libdbus isn't actually
+   * delivering them to a DBusWatch. Because epoll is level-triggered by
+   * default, we'll busy-loop on an unhandled error or hangup; not good.
+   *
+   * So, let's set it to be edge-triggered: then the worst case is that
+   * we return from poll immediately on one iteration, ignore it because no
+   * watch is enabled, then go back to normal. When we re-enable a watch
+   * we'll switch back to level-triggered and be notified again (verified to
+   * work on 2.6.32). Compile this file with -DTEST_BEHAVIOUR_OF_EPOLLET for
+   * test code.
+   */
+  event.data.fd = fd;
+  event.events = EPOLLET;
+
+  if (epoll_ctl (self->epfd, EPOLL_CTL_MOD, fd, &event) == 0)
+    return;
+
+  err = errno;
+  _dbus_warn ("Error when trying to watch fd %d: %s\n", fd,
+              strerror (err));
+}
+
+static void
+socket_set_epoll_remove (DBusSocketSet  *set,
+                         int             fd)
+{
+  DBusSocketSetEpoll *self = socket_set_epoll_cast (set);
+  int err;
+  /* Kernels < 2.6.9 require a non-NULL struct pointer, even though its
+   * contents are ignored */
+  struct epoll_event dummy = { 0 };
+
+  if (epoll_ctl (self->epfd, EPOLL_CTL_DEL, fd, &dummy) == 0)
+    return;
+
+  err = errno;
+  _dbus_warn ("Error when trying to remove fd %d: %s\n", fd, strerror (err));
+}
+
+/* Optimally, this should be the same as in DBusLoop: we use it to translate
+ * between struct epoll_event and DBusSocketEvent without allocating heap
+ * memory. */
+#define N_STACK_DESCRIPTORS 64
+
+static int
+socket_set_epoll_poll (DBusSocketSet   *set,
+                       DBusSocketEvent *revents,
+                       int              max_events,
+                       int              timeout_ms)
+{
+  DBusSocketSetEpoll *self = socket_set_epoll_cast (set);
+  struct epoll_event events[N_STACK_DESCRIPTORS];
+  int n_ready;
+  int i;
+
+  _dbus_assert (max_events > 0);
+
+  n_ready = epoll_wait (self->epfd, events,
+                        MIN (_DBUS_N_ELEMENTS (events), max_events),
+                        timeout_ms);
+
+  if (n_ready <= 0)
+    return n_ready;
+
+  for (i = 0; i < n_ready; i++)
+    {
+      revents[i].fd = events[i].data.fd;
+      revents[i].flags = epoll_events_to_watch_flags (events[i].events);
+    }
+
+  return n_ready;
+}
+
+DBusSocketSetClass _dbus_socket_set_epoll_class = {
+    socket_set_epoll_free,
+    socket_set_epoll_add,
+    socket_set_epoll_remove,
+    socket_set_epoll_enable,
+    socket_set_epoll_disable,
+    socket_set_epoll_poll
+};
+
+#ifdef TEST_BEHAVIOUR_OF_EPOLLET
+/* usage: cat /dev/null | ./epoll
+ *
+ * desired output:
+ * ctl ADD: 0
+ * wait for HUP, edge-triggered: 1
+ * wait for HUP again: 0
+ * ctl MOD: 0
+ * wait for HUP: 1
+ */
+
+#include <sys/epoll.h>
+
+#include <stdio.h>
+
+int
+main (void)
+{
+  struct epoll_event input;
+  struct epoll_event output;
+  int epfd = epoll_create1 (EPOLL_CLOEXEC);
+  int fd = 0; /* stdin */
+  int ret;
+
+  input.events = EPOLLHUP | EPOLLET;
+  ret = epoll_ctl (epfd, EPOLL_CTL_ADD, fd, &input);
+  printf ("ctl ADD: %d\n", ret);
+
+  ret = epoll_wait (epfd, &output, 1, -1);
+  printf ("wait for HUP, edge-triggered: %d\n", ret);
+
+  ret = epoll_wait (epfd, &output, 1, 1);
+  printf ("wait for HUP again: %d\n", ret);
+
+  input.events = EPOLLHUP;
+  ret = epoll_ctl (epfd, EPOLL_CTL_MOD, fd, &input);
+  printf ("ctl MOD: %d\n", ret);
+
+  ret = epoll_wait (epfd, &output, 1, -1);
+  printf ("wait for HUP: %d\n", ret);
+
+  return 0;
+}
+
+#endif /* TEST_BEHAVIOUR_OF_EPOLLET */
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
diff --git a/dbus/dbus/dbus-socket-set-poll.c b/dbus/dbus/dbus-socket-set-poll.c
new file mode 100644
index 0000000..65a1fd2
--- /dev/null
+++ b/dbus/dbus/dbus-socket-set-poll.c
@@ -0,0 +1,320 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-socket-set-poll.c - a socket set implemented via _dbus_poll
+ *
+ * Copyright © 2011 Nokia Corporation
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-socket-set.h"
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-watch.h>
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+typedef struct {
+    DBusSocketSet      parent;
+    DBusPollFD        *fds;
+    int                n_fds;
+    int                n_reserved;
+    int                n_allocated;
+} DBusSocketSetPoll;
+
+#define REALLOC_INCREMENT 8
+#define MINIMUM_SIZE 8
+
+/* If we're in the regression tests, force reallocation to happen sooner */
+#ifdef DBUS_BUILD_TESTS
+#define DEFAULT_SIZE_HINT 1
+#else
+#define DEFAULT_SIZE_HINT MINIMUM_SIZE
+#endif
+
+static inline DBusSocketSetPoll *
+socket_set_poll_cast (DBusSocketSet *set)
+{
+  _dbus_assert (set->cls == &_dbus_socket_set_poll_class);
+  return (DBusSocketSetPoll *) set;
+}
+
+/* this is safe to call on a partially-allocated socket set */
+static void
+socket_set_poll_free (DBusSocketSet *set)
+{
+  DBusSocketSetPoll *self = socket_set_poll_cast (set);
+
+  dbus_free (self->fds);
+  dbus_free (self);
+  _dbus_verbose ("freed socket set %p\n", self);
+}
+
+DBusSocketSet *
+_dbus_socket_set_poll_new (int size_hint)
+{
+  DBusSocketSetPoll *ret;
+
+  if (size_hint <= 0)
+    size_hint = DEFAULT_SIZE_HINT;
+
+  ret = dbus_new0 (DBusSocketSetPoll, 1);
+
+  if (ret == NULL)
+    return NULL;
+
+  ret->parent.cls = &_dbus_socket_set_poll_class;
+  ret->n_fds = 0;
+  ret->n_allocated = size_hint;
+
+  ret->fds = dbus_new0 (DBusPollFD, size_hint);
+
+  if (ret->fds == NULL)
+    {
+      /* socket_set_poll_free specifically supports half-constructed
+       * socket sets */
+      socket_set_poll_free ((DBusSocketSet *) ret);
+      return NULL;
+    }
+
+  _dbus_verbose ("new socket set at %p\n", ret);
+  return (DBusSocketSet *) ret;
+}
+
+static short
+watch_flags_to_poll_events (unsigned int flags)
+{
+  short events = 0;
+
+  if (flags & DBUS_WATCH_READABLE)
+    events |= _DBUS_POLLIN;
+  if (flags & DBUS_WATCH_WRITABLE)
+    events |= _DBUS_POLLOUT;
+
+  return events;
+}
+
+static dbus_bool_t
+socket_set_poll_add (DBusSocketSet  *set,
+                     int             fd,
+                     unsigned int    flags,
+                     dbus_bool_t     enabled)
+{
+  DBusSocketSetPoll *self = socket_set_poll_cast (set);
+#ifndef DBUS_DISABLE_ASSERT
+  int i;
+
+  for (i = 0; i < self->n_fds; i++)
+    _dbus_assert (self->fds[i].fd != fd);
+#endif
+
+  if (self->n_reserved >= self->n_allocated)
+    {
+      DBusPollFD *new_fds = dbus_realloc (self->fds,
+          sizeof (DBusPollFD) * (self->n_allocated + REALLOC_INCREMENT));
+
+      _dbus_verbose ("inflating set %p from %d en/%d res/%d alloc to %d\n",
+                     self, self->n_fds, self->n_reserved, self->n_allocated,
+                     self->n_allocated + REALLOC_INCREMENT);
+
+      if (new_fds == NULL)
+        return FALSE;
+
+      self->fds = new_fds;
+      self->n_allocated += REALLOC_INCREMENT;
+    }
+
+  _dbus_verbose ("before adding fd %d to %p, %d en/%d res/%d alloc\n",
+                 fd, self, self->n_fds, self->n_reserved, self->n_allocated);
+  _dbus_assert (self->n_reserved >= self->n_fds);
+  _dbus_assert (self->n_allocated > self->n_reserved);
+
+  self->n_reserved++;
+
+  if (enabled)
+    {
+      self->fds[self->n_fds].fd = fd;
+      self->fds[self->n_fds].events = watch_flags_to_poll_events (flags);
+      self->n_fds++;
+    }
+
+  return TRUE;
+}
+
+static void
+socket_set_poll_enable (DBusSocketSet *set,
+                        int            fd,
+                        unsigned int   flags)
+{
+  DBusSocketSetPoll *self = socket_set_poll_cast (set);
+  int i;
+
+  for (i = 0; i < self->n_fds; i++)
+    {
+      if (self->fds[i].fd == fd)
+        {
+          self->fds[i].events = watch_flags_to_poll_events (flags);
+          return;
+        }
+    }
+
+  /* we allocated space when the socket was added */
+  _dbus_assert (self->n_fds < self->n_reserved);
+  _dbus_assert (self->n_reserved <= self->n_allocated);
+
+  self->fds[self->n_fds].fd = fd;
+  self->fds[self->n_fds].events = watch_flags_to_poll_events (flags);
+  self->n_fds++;
+}
+
+static void
+socket_set_poll_disable (DBusSocketSet *set,
+                         int            fd)
+{
+  DBusSocketSetPoll *self = socket_set_poll_cast (set);
+  int i;
+
+  for (i = 0; i < self->n_fds; i++)
+    {
+      if (self->fds[i].fd == fd)
+        {
+          if (i != self->n_fds - 1)
+            {
+              self->fds[i].fd = self->fds[self->n_fds - 1].fd;
+              self->fds[i].events = self->fds[self->n_fds - 1].events;
+            }
+
+          self->n_fds--;
+          return;
+        }
+    }
+}
+
+static void
+socket_set_poll_remove (DBusSocketSet *set,
+                        int            fd)
+{
+  DBusSocketSetPoll *self = socket_set_poll_cast (set);
+
+  socket_set_poll_disable (set, fd);
+  self->n_reserved--;
+
+  _dbus_verbose ("after removing fd %d from %p, %d en/%d res/%d alloc\n",
+                 fd, self, self->n_fds, self->n_reserved, self->n_allocated);
+  _dbus_assert (self->n_fds <= self->n_reserved);
+  _dbus_assert (self->n_reserved <= self->n_allocated);
+
+  if (self->n_reserved + MINIMUM_SIZE < self->n_allocated / 2)
+    {
+      /* Our array is twice as big as it needs to be - deflate it until it's
+       * only slightly larger than the number reserved. */
+      DBusPollFD *new_fds = dbus_realloc (self->fds,
+          sizeof (DBusPollFD) * (self->n_reserved + MINIMUM_SIZE));
+
+      _dbus_verbose ("before deflating %p, %d en/%d res/%d alloc\n",
+                     self, self->n_fds, self->n_reserved, self->n_allocated);
+
+      if (_DBUS_UNLIKELY (new_fds == NULL))
+        {
+          /* Weird. Oh well, never mind, the too-big array is untouched */
+          return;
+        }
+
+      self->fds = new_fds;
+      self->n_allocated = self->n_reserved;
+    }
+}
+
+static unsigned int
+watch_flags_from_poll_revents (short revents)
+{
+  unsigned int condition = 0;
+
+  if (revents & _DBUS_POLLIN)
+    condition |= DBUS_WATCH_READABLE;
+  if (revents & _DBUS_POLLOUT)
+    condition |= DBUS_WATCH_WRITABLE;
+  if (revents & _DBUS_POLLHUP)
+    condition |= DBUS_WATCH_HANGUP;
+  if (revents & _DBUS_POLLERR)
+    condition |= DBUS_WATCH_ERROR;
+
+  if (_DBUS_UNLIKELY (revents & _DBUS_POLLNVAL))
+    condition |= _DBUS_WATCH_NVAL;
+
+  return condition;
+}
+
+/** This is basically Linux's epoll_wait(2) implemented in terms of poll(2);
+ * it returns results into a caller-supplied buffer so we can be reentrant. */
+static int
+socket_set_poll_poll (DBusSocketSet   *set,
+                      DBusSocketEvent *revents,
+                      int              max_events,
+                      int              timeout_ms)
+{
+  DBusSocketSetPoll *self = socket_set_poll_cast (set);
+  int i;
+  int n_events;
+  int n_ready;
+
+  _dbus_assert (max_events > 0);
+
+  for (i = 0; i < self->n_fds; i++)
+    self->fds[i].revents = 0;
+
+  n_ready = _dbus_poll (self->fds, self->n_fds, timeout_ms);
+
+  if (n_ready <= 0)
+    return n_ready;
+
+  n_events = 0;
+
+  for (i = 0; i < self->n_fds; i++)
+    {
+      if (self->fds[i].revents != 0)
+        {
+          revents[n_events].fd = self->fds[i].fd;
+          revents[n_events].flags = watch_flags_from_poll_revents (self->fds[i].revents);
+
+          n_events += 1;
+
+          /* We ignore events beyond max_events because we have nowhere to
+           * put them. _dbus_poll is level-triggered, so we'll just be told
+           * about them next time round the main loop anyway. */
+          if (n_events == max_events)
+            return n_events;
+        }
+    }
+
+  return n_events;
+}
+
+DBusSocketSetClass _dbus_socket_set_poll_class = {
+    socket_set_poll_free,
+    socket_set_poll_add,
+    socket_set_poll_remove,
+    socket_set_poll_enable,
+    socket_set_poll_disable,
+    socket_set_poll_poll
+};
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
diff --git a/dbus/dbus/dbus-socket-set.c b/dbus/dbus/dbus-socket-set.c
new file mode 100644
index 0000000..210d600
--- /dev/null
+++ b/dbus/dbus/dbus-socket-set.c
@@ -0,0 +1,47 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * dbus-socket-set.c - used to bolt file descriptors onto a bus
+ *
+ * Copyright © 2011 Nokia Corporation
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include <dbus/dbus-socket-set.h>
+
+DBusSocketSet *
+_dbus_socket_set_new (int size_hint)
+{
+  DBusSocketSet *ret;
+
+#ifdef DBUS_HAVE_LINUX_EPOLL
+  ret = _dbus_socket_set_epoll_new ();
+
+  if (ret != NULL)
+    return ret;
+#endif
+
+  ret = _dbus_socket_set_poll_new (size_hint);
+
+  if (ret != NULL)
+    return ret;
+
+  return NULL;
+}
diff --git a/dbus/dbus/dbus-socket-set.h b/dbus/dbus/dbus-socket-set.h
new file mode 100644
index 0000000..3b71a92
--- /dev/null
+++ b/dbus/dbus/dbus-socket-set.h
@@ -0,0 +1,122 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * dbus-socket-set.h - used to bolt file descriptors onto a bus
+ *
+ * Copyright © 2011 Nokia Corporation
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef DBUS_SOCKET_SET_H
+#define DBUS_SOCKET_SET_H
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include <dbus/dbus.h>
+
+typedef struct {
+    int fd;
+    unsigned int flags;
+} DBusSocketEvent;
+
+typedef struct DBusSocketSet DBusSocketSet;
+
+typedef struct DBusSocketSetClass DBusSocketSetClass;
+struct DBusSocketSetClass {
+    void            (*free)     (DBusSocketSet   *self);
+    dbus_bool_t     (*add)      (DBusSocketSet   *self,
+                                 int              fd,
+                                 unsigned int     flags,
+                                 dbus_bool_t      enabled);
+    void            (*remove)   (DBusSocketSet   *self,
+                                 int              fd);
+    void            (*enable)   (DBusSocketSet   *self,
+                                 int              fd,
+                                 unsigned int     flags);
+    void            (*disable)  (DBusSocketSet   *self,
+                                 int              fd);
+    int             (*poll)     (DBusSocketSet   *self,
+                                 DBusSocketEvent *revents,
+                                 int              max_events,
+                                 int              timeout_ms);
+};
+
+struct DBusSocketSet {
+    DBusSocketSetClass *cls;
+};
+
+DBusSocketSet *_dbus_socket_set_new           (int               size_hint);
+
+static inline void
+_dbus_socket_set_free (DBusSocketSet *self)
+{
+  (self->cls->free) (self);
+}
+
+static inline dbus_bool_t
+_dbus_socket_set_add (DBusSocketSet *self,
+                      int            fd,
+                      unsigned int   flags,
+                      dbus_bool_t    enabled)
+{
+  return (self->cls->add) (self, fd, flags, enabled);
+}
+
+static inline void
+_dbus_socket_set_remove (DBusSocketSet *self,
+                         int            fd)
+{
+  (self->cls->remove) (self, fd);
+}
+
+static inline void
+_dbus_socket_set_enable (DBusSocketSet *self,
+                         int            fd,
+                         unsigned int   flags)
+{
+  (self->cls->enable) (self, fd, flags);
+}
+
+static inline void
+_dbus_socket_set_disable (DBusSocketSet *self,
+                          int            fd)
+{
+  (self->cls->disable) (self, fd);
+}
+
+
+static inline int
+_dbus_socket_set_poll (DBusSocketSet    *self,
+                       DBusSocketEvent  *revents,
+                       int               max_events,
+                       int               timeout_ms)
+{
+  return (self->cls->poll) (self, revents, max_events, timeout_ms);
+}
+
+/* concrete implementations, not necessarily built on all platforms */
+
+extern DBusSocketSetClass _dbus_socket_set_poll_class;
+extern DBusSocketSetClass _dbus_socket_set_epoll_class;
+
+DBusSocketSet *_dbus_socket_set_poll_new  (int  size_hint);
+DBusSocketSet *_dbus_socket_set_epoll_new (void);
+
+#endif /* !DOXYGEN_SHOULD_SKIP_THIS */
+#endif /* multiple-inclusion guard */
diff --git a/dbus/dbus/dbus-sockets-win.h b/dbus/dbus/dbus-sockets-win.h
new file mode 100644
index 0000000..4e1ab8c
--- /dev/null
+++ b/dbus/dbus/dbus-sockets-win.h
@@ -0,0 +1,66 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sockets.h Wrappers around socket features (internal to D-BUS implementation)
+ * 
+ * Copyright (C) 2005 Novell, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_SOCKETS_H
+#define DBUS_SOCKETS_H
+
+#if defined(DBUS_WIN) || defined(DBUS_WINCE)
+
+
+
+#ifndef STRICT
+#define STRICT
+#include <winsock2.h>
+#undef STRICT
+#endif
+#include <winsock2.h>
+
+#undef interface
+
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#define DBUS_SOCKET_IS_INVALID(s) ((SOCKET)(s) == INVALID_SOCKET)
+#define DBUS_SOCKET_API_RETURNS_ERROR(n) ((n) == SOCKET_ERROR)
+#define DBUS_SOCKET_SET_ERRNO() (_dbus_win_set_errno (WSAGetLastError()))
+
+#define DBUS_CLOSE_SOCKET(s) closesocket(s)
+
+#else
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+
+#define DBUS_SOCKET_IS_INVALID(s) ((s) < 0)
+#define DBUS_SOCKET_API_RETURNS_ERROR(n) ((n) < 0)
+#define DBUS_SOCKET_SET_ERRNO()	/* empty */
+
+#define DBUS_CLOSE_SOCKET(s) close(s)
+
+#endif /* !Win32 */
+
+#endif /* DBUS_SOCKETS_H */
diff --git a/dbus/dbus/dbus-spawn-win.c b/dbus/dbus/dbus-spawn-win.c
new file mode 100644
index 0000000..3dae4f3
--- /dev/null
+++ b/dbus/dbus/dbus-spawn-win.c
@@ -0,0 +1,1035 @@
+#include <config.h>
+
+//#define SPAWN_DEBUG
+
+#if !defined(SPAWN_DEBUG) || defined(_MSC_VER)
+#define PING()
+#else
+#define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); fflush (stderr)
+#endif
+
+#include <stdio.h>
+
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-spawn-win32.c Wrapper around g_spawn
+ * 
+ * Copyright (C) 2002, 2003, 2004  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2005 Novell, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#include "dbus-spawn.h"
+#include "dbus-sysdeps.h"
+#include "dbus-sysdeps-win.h"
+#include "dbus-internals.h"
+#include "dbus-test.h"
+#include "dbus-protocol.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+//#define STRICT
+//#include <windows.h>
+//#undef STRICT
+#include <winsock2.h>
+#undef interface
+
+#include <stdlib.h>
+
+#ifndef DBUS_WINCE
+#include <process.h>
+#endif
+
+/**
+ * Babysitter implementation details
+ */
+struct DBusBabysitter
+  {
+    int refcount;
+
+    HANDLE start_sync_event;
+#ifdef DBUS_BUILD_TESTS
+
+    HANDLE end_sync_event;
+#endif
+
+    char *executable;
+    DBusSpawnChildSetupFunc child_setup;
+    void *user_data;
+
+    int argc;
+    char **argv;
+    char **envp;
+
+    HANDLE child_handle;
+    int socket_to_babysitter;	/* Connection to the babysitter thread */
+    int socket_to_main;
+
+    DBusWatchList *watches;
+    DBusWatch *sitter_watch;
+    DBusBabysitterFinishedFunc finished_cb;
+    void *finished_data;
+
+    dbus_bool_t have_spawn_errno;
+    int spawn_errno;
+    dbus_bool_t have_child_status;
+    int child_status;
+  };
+
+static DBusBabysitter*
+_dbus_babysitter_new (void)
+{
+  DBusBabysitter *sitter;
+
+  sitter = dbus_new0 (DBusBabysitter, 1);
+  if (sitter == NULL)
+    return NULL;
+
+  sitter->refcount = 1;
+
+  sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
+  if (sitter->start_sync_event == NULL)
+    {
+      _dbus_babysitter_unref (sitter);
+      return NULL;
+    }
+
+#ifdef DBUS_BUILD_TESTS
+  sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
+  if (sitter->end_sync_event == NULL)
+    {
+      _dbus_babysitter_unref (sitter);
+      return NULL;
+    }
+#endif
+
+  sitter->child_handle = NULL;
+
+  sitter->socket_to_babysitter = sitter->socket_to_main = -1;
+
+  sitter->argc = 0;
+  sitter->argv = NULL;
+  sitter->envp = NULL;
+
+  sitter->watches = _dbus_watch_list_new ();
+  if (sitter->watches == NULL)
+    {
+      _dbus_babysitter_unref (sitter);
+      return NULL;
+    }
+
+  sitter->have_spawn_errno = FALSE;
+  sitter->have_child_status = FALSE;
+
+  return sitter;
+}
+
+/**
+ * Increment the reference count on the babysitter object.
+ *
+ * @param sitter the babysitter
+ * @returns the babysitter
+ */
+DBusBabysitter *
+_dbus_babysitter_ref (DBusBabysitter *sitter)
+{
+  PING();
+  _dbus_assert (sitter != NULL);
+  _dbus_assert (sitter->refcount > 0);
+
+  sitter->refcount += 1;
+
+  return sitter;
+}
+
+static void
+close_socket_to_babysitter (DBusBabysitter *sitter)
+{
+  _dbus_verbose ("Closing babysitter\n");
+
+  if (sitter->sitter_watch != NULL)
+    {
+      _dbus_assert (sitter->watches != NULL);
+      _dbus_watch_list_remove_watch (sitter->watches,  sitter->sitter_watch);
+      _dbus_watch_invalidate (sitter->sitter_watch);
+      _dbus_watch_unref (sitter->sitter_watch);
+      sitter->sitter_watch = NULL;
+    }
+
+  if (sitter->socket_to_babysitter != -1)
+    {
+      _dbus_close_socket (sitter->socket_to_babysitter, NULL);
+      sitter->socket_to_babysitter = -1;
+    }
+}
+
+/**
+ * Decrement the reference count on the babysitter object.
+ *
+ * @param sitter the babysitter
+ */
+void
+_dbus_babysitter_unref (DBusBabysitter *sitter)
+{
+  int i;
+
+  PING();
+  _dbus_assert (sitter != NULL);
+  _dbus_assert (sitter->refcount > 0);
+
+  sitter->refcount -= 1;
+
+  if (sitter->refcount == 0)
+    {
+      close_socket_to_babysitter (sitter);
+
+      if (sitter->socket_to_main != -1)
+        {
+          _dbus_close_socket (sitter->socket_to_main, NULL);
+          sitter->socket_to_main = -1;
+        }
+
+      PING();
+      if (sitter->argv != NULL)
+        {
+          for (i = 0; i < sitter->argc; i++)
+            if (sitter->argv[i] != NULL)
+              {
+                dbus_free (sitter->argv[i]);
+                sitter->argv[i] = NULL;
+              }
+          dbus_free (sitter->argv);
+          sitter->argv = NULL;
+        }
+
+      if (sitter->envp != NULL)
+        {
+          char **e = sitter->envp;
+
+          while (*e)
+            dbus_free (*e++);
+          dbus_free (sitter->envp);
+          sitter->envp = NULL;
+        }
+
+      if (sitter->child_handle != NULL)
+        {
+          CloseHandle (sitter->child_handle);
+          sitter->child_handle = NULL;
+        }
+
+      if (sitter->sitter_watch)
+        {
+          _dbus_watch_invalidate (sitter->sitter_watch);
+          _dbus_watch_unref (sitter->sitter_watch);
+          sitter->sitter_watch = NULL;
+        }
+
+      if (sitter->watches)
+        _dbus_watch_list_free (sitter->watches);
+
+      if (sitter->start_sync_event != NULL)
+        {
+          PING();
+          CloseHandle (sitter->start_sync_event);
+          sitter->start_sync_event = NULL;
+        }
+
+#ifdef DBUS_BUILD_TESTS
+      if (sitter->end_sync_event != NULL)
+        {
+          CloseHandle (sitter->end_sync_event);
+          sitter->end_sync_event = NULL;
+        }
+#endif
+
+      dbus_free (sitter->executable);
+
+      dbus_free (sitter);
+    }
+}
+
+void
+_dbus_babysitter_kill_child (DBusBabysitter *sitter)
+{
+  PING();
+  if (sitter->child_handle == NULL)
+    return; /* child is already dead, or we're so hosed we'll never recover */
+
+  PING();
+  TerminateProcess (sitter->child_handle, 12345);
+}
+
+/**
+ * Checks whether the child has exited, without blocking.
+ *
+ * @param sitter the babysitter
+ */
+dbus_bool_t
+_dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
+{
+  PING();
+  return (sitter->child_handle == NULL);
+}
+
+/**
+ * Gets the exit status of the child. We do this so implementation specific
+ * detail is not cluttering up dbus, for example the system launcher code.
+ * This can only be called if the child has exited, i.e. call
+ * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
+ * did not return a status code, e.g. because the child was signaled
+ * or we failed to ever launch the child in the first place.
+ *
+ * @param sitter the babysitter
+ * @param status the returned status code
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
+                                        int            *status)
+{
+  if (!_dbus_babysitter_get_child_exited (sitter))
+    _dbus_assert_not_reached ("Child has not exited");
+
+  if (!sitter->have_child_status ||
+      sitter->child_status == STILL_ACTIVE)
+    return FALSE;
+
+  *status = sitter->child_status;
+  return TRUE;
+}
+
+/**
+ * Sets the #DBusError with an explanation of why the spawned
+ * child process exited (on a signal, or whatever). If
+ * the child process has not exited, does nothing (error
+ * will remain unset).
+ *
+ * @param sitter the babysitter
+ * @param error an error to fill in
+ */
+void
+_dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
+                                       DBusError      *error)
+{
+  PING();
+  if (!_dbus_babysitter_get_child_exited (sitter))
+    return;
+
+  PING();
+  if (sitter->have_spawn_errno)
+    {
+      char *emsg = _dbus_win_error_string (sitter->spawn_errno);
+      dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
+                      "Failed to execute program %s: %s",
+                      sitter->executable, emsg);
+      _dbus_win_free_error_string (emsg);
+    }
+  else if (sitter->have_child_status)
+    {
+      PING();
+      dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
+                      "Process %s exited with status %d",
+                      sitter->executable, sitter->child_status);
+    }
+  else
+    {
+      PING();
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Process %s exited, status unknown",
+                      sitter->executable);
+    }
+  PING();
+}
+
+dbus_bool_t
+_dbus_babysitter_set_watch_functions (DBusBabysitter            *sitter,
+                                      DBusAddWatchFunction       add_function,
+                                      DBusRemoveWatchFunction    remove_function,
+                                      DBusWatchToggledFunction   toggled_function,
+                                      void                      *data,
+                                      DBusFreeFunction           free_data_function)
+{
+  PING();
+  return _dbus_watch_list_set_functions (sitter->watches,
+                                         add_function,
+                                         remove_function,
+                                         toggled_function,
+                                         data,
+                                         free_data_function);
+}
+
+static dbus_bool_t
+handle_watch (DBusWatch       *watch,
+              unsigned int     condition,
+              void            *data)
+{
+  DBusBabysitter *sitter = data;
+
+  /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
+   * actually send the exit statuses, error codes and whatnot through
+   * sockets and/or pipes. On Win32, the babysitter is jus a thread,
+   * so it can set the status fields directly in the babysitter struct
+   * just fine. The socket pipe is used just so we can watch it with
+   * select(), as soon as anything is written to it we know that the
+   * babysitter thread has recorded the status in the babysitter
+   * struct.
+   */
+
+  PING();
+  close_socket_to_babysitter (sitter);
+  PING();
+
+  if (_dbus_babysitter_get_child_exited (sitter) &&
+      sitter->finished_cb != NULL)
+    {
+      sitter->finished_cb (sitter, sitter->finished_data);
+      sitter->finished_cb = NULL;
+    }
+
+  return TRUE;
+}
+
+/* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
+static int
+protect_argv (char  **argv,
+              char ***new_argv)
+{
+  int i;
+  int argc = 0;
+
+  while (argv[argc])
+    ++argc;
+  *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
+  if (*new_argv == NULL)
+    return -1;
+
+  for (i = 0; i < argc; i++)
+    (*new_argv)[i] = NULL;
+
+  /* Quote each argv element if necessary, so that it will get
+   * reconstructed correctly in the C runtime startup code.  Note that
+   * the unquoting algorithm in the C runtime is really weird, and
+   * rather different than what Unix shells do. See stdargv.c in the C
+   * runtime sources (in the Platform SDK, in src/crt).
+   *
+   * Note that an new_argv[0] constructed by this function should
+   * *not* be passed as the filename argument to a spawn* or exec*
+   * family function. That argument should be the real file name
+   * without any quoting.
+   */
+  for (i = 0; i < argc; i++)
+    {
+      char *p = argv[i];
+      char *q;
+      int len = 0;
+      int need_dblquotes = FALSE;
+      while (*p)
+        {
+          if (*p == ' ' || *p == '\t')
+            need_dblquotes = TRUE;
+          else if (*p == '"')
+            len++;
+          else if (*p == '\\')
+            {
+              char *pp = p;
+              while (*pp && *pp == '\\')
+                pp++;
+              if (*pp == '"')
+                len++;
+            }
+          len++;
+          p++;
+        }
+
+      q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
+
+      if (q == NULL)
+        return -1;
+
+
+      p = argv[i];
+
+      if (need_dblquotes)
+        *q++ = '"';
+
+      while (*p)
+        {
+          if (*p == '"')
+            *q++ = '\\';
+          else if (*p == '\\')
+            {
+              char *pp = p;
+              while (*pp && *pp == '\\')
+                pp++;
+              if (*pp == '"')
+                *q++ = '\\';
+            }
+          *q++ = *p;
+          p++;
+        }
+
+      if (need_dblquotes)
+        *q++ = '"';
+      *q++ = '\0';
+      /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
+    }
+  (*new_argv)[argc] = NULL;
+
+  return argc;
+}
+
+
+/* From GPGME, relicensed by g10 Code GmbH.  */
+static char *
+compose_string (char **strings, char separator)
+{
+  int i;
+  int n = 0;
+  char *buf;
+  char *p;
+
+  if (!strings || !strings[0])
+    return 0;
+  for (i = 0; strings[i]; i++)
+    n += strlen (strings[i]) + 1;
+  n++;
+
+  buf = p = malloc (n);
+  if (!buf)
+    return NULL;
+  for (i = 0; strings[i]; i++)
+    {
+      strcpy (p, strings[i]);
+      p += strlen (strings[i]);
+      *(p++) = separator;
+    }
+  p--;
+  *(p++) = '\0';
+  *p = '\0';
+
+  return buf;
+}
+
+static char *
+build_commandline (char **argv)
+{
+  return compose_string (argv, ' ');
+}
+
+static char *
+build_env_string (char** envp)
+{
+  return compose_string (envp, '\0');
+}
+
+static HANDLE
+spawn_program (char* name, char** argv, char** envp)
+{
+  PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
+  STARTUPINFOA si;
+  char *arg_string, *env_string;
+  BOOL result;
+
+#ifdef DBUS_WINCE
+  if (argv && argv[0])
+    arg_string = build_commandline (argv + 1);
+  else
+    arg_string = NULL;
+#else
+  arg_string = build_commandline (argv);
+#endif
+  if (!arg_string)
+    return INVALID_HANDLE_VALUE;
+
+  env_string = build_env_string(envp);
+
+  memset (&si, 0, sizeof (si));
+  si.cb = sizeof (si);
+#ifdef DBUS_WINCE
+  result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
+#else
+  result = CreateProcessA (NULL, arg_string, NULL, NULL, FALSE, 0,
+#endif
+			   (LPVOID)env_string, NULL, &si, &pi);
+  free (arg_string);
+  if (env_string)
+    free (env_string);
+
+  if (!result)
+    return INVALID_HANDLE_VALUE;
+
+  CloseHandle (pi.hThread);
+  return pi.hProcess;
+}
+
+
+static DWORD __stdcall
+babysitter (void *parameter)
+{
+  DBusBabysitter *sitter = (DBusBabysitter *) parameter;
+
+  PING();
+  _dbus_babysitter_ref (sitter);
+
+  if (sitter->child_setup)
+    {
+      PING();
+      (*sitter->child_setup) (sitter->user_data);
+    }
+
+  _dbus_verbose ("babysitter: spawning %s\n", sitter->executable);
+
+  PING();
+  sitter->child_handle = spawn_program (sitter->executable,
+					sitter->argv, sitter->envp);
+
+  PING();
+  if (sitter->child_handle == (HANDLE) -1)
+    {
+      sitter->child_handle = NULL;
+      sitter->have_spawn_errno = TRUE;
+      sitter->spawn_errno = GetLastError();
+    }
+  
+  PING();
+  SetEvent (sitter->start_sync_event);
+
+  if (sitter->child_handle != NULL)
+    {
+      int ret;
+      DWORD status;
+
+      PING();
+      WaitForSingleObject (sitter->child_handle, INFINITE);
+
+      PING();
+      ret = GetExitCodeProcess (sitter->child_handle, &status);
+
+      sitter->child_status = status;
+      sitter->have_child_status = TRUE;
+
+      CloseHandle (sitter->child_handle);
+      sitter->child_handle = NULL;
+    }
+
+#ifdef DBUS_BUILD_TESTS
+  SetEvent (sitter->end_sync_event);
+#endif
+
+  PING();
+  send (sitter->socket_to_main, " ", 1, 0);
+
+  _dbus_babysitter_unref (sitter);
+
+  return 0;
+}
+
+dbus_bool_t
+_dbus_spawn_async_with_babysitter (DBusBabysitter           **sitter_p,
+                                   char                     **argv,
+                                   char                     **envp,
+                                   DBusSpawnChildSetupFunc    child_setup,
+                                   void                      *user_data,
+                                   DBusError                 *error)
+{
+  DBusBabysitter *sitter;
+  HANDLE sitter_thread;
+  DWORD sitter_thread_id;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  *sitter_p = NULL;
+
+  PING();
+  sitter = _dbus_babysitter_new ();
+  if (sitter == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  sitter->child_setup = child_setup;
+  sitter->user_data = user_data;
+
+  sitter->executable = _dbus_strdup (argv[0]);
+  if (sitter->executable == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      goto out0;
+    }
+
+  PING();
+  if (!_dbus_full_duplex_pipe (&sitter->socket_to_babysitter,
+                               &sitter->socket_to_main,
+                               FALSE, error))
+    goto out0;
+
+  sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
+                                          DBUS_WATCH_READABLE,
+                                          TRUE, handle_watch, sitter, NULL);
+  PING();
+  if (sitter->sitter_watch == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      goto out0;
+    }
+
+  PING();
+  if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->sitter_watch))
+    {
+      /* we need to free it early so the destructor won't try to remove it
+       * without it having been added, which DBusLoop doesn't allow */
+      _dbus_watch_invalidate (sitter->sitter_watch);
+      _dbus_watch_unref (sitter->sitter_watch);
+      sitter->sitter_watch = NULL;
+
+      _DBUS_SET_OOM (error);
+      goto out0;
+    }
+
+  sitter->argc = protect_argv (argv, &sitter->argv);
+  if (sitter->argc == -1)
+    {
+      _DBUS_SET_OOM (error);
+      goto out0;
+    }
+  sitter->envp = envp;
+
+  PING();
+  sitter_thread = (HANDLE) CreateThread (NULL, 0, babysitter,
+                  sitter, 0, &sitter_thread_id);
+
+  if (sitter_thread == 0)
+    {
+      PING();
+      dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
+                            "Failed to create new thread");
+      goto out0;
+    }
+  CloseHandle (sitter_thread);
+
+  PING();
+  WaitForSingleObject (sitter->start_sync_event, INFINITE);
+
+  PING();
+  if (sitter_p != NULL)
+    *sitter_p = sitter;
+  else
+    _dbus_babysitter_unref (sitter);
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  PING();
+  return TRUE;
+
+out0:
+  _dbus_babysitter_unref (sitter);
+
+  return FALSE;
+}
+
+void
+_dbus_babysitter_set_result_function  (DBusBabysitter             *sitter,
+                                       DBusBabysitterFinishedFunc  finished,
+                                       void                       *user_data)
+{
+  sitter->finished_cb = finished;
+  sitter->finished_data = user_data;
+}
+
+#ifdef DBUS_BUILD_TESTS
+
+static char *
+get_test_exec (const char *exe,
+               DBusString *scratch_space)
+{
+  const char *dbus_test_exec;
+
+  dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
+
+  if (dbus_test_exec == NULL)
+    dbus_test_exec = DBUS_TEST_EXEC;
+
+  if (!_dbus_string_init (scratch_space))
+    return NULL;
+
+  if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
+                                   dbus_test_exec, exe, DBUS_EXEEXT))
+    {
+      _dbus_string_free (scratch_space);
+      return NULL;
+    }
+
+  return _dbus_string_get_data (scratch_space);
+}
+
+#define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
+
+static void
+_dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
+{
+  if (sitter->child_handle == NULL)
+    return;
+
+  WaitForSingleObject (sitter->end_sync_event, INFINITE);
+}
+
+static dbus_bool_t
+check_spawn_nonexistent (void *data)
+{
+  char *argv[4] = { NULL, NULL, NULL, NULL };
+  DBusBabysitter *sitter;
+  DBusError error;
+
+  sitter = NULL;
+
+  dbus_error_init (&error);
+
+  /*** Test launching nonexistent binary */
+
+  argv[0] = "/this/does/not/exist/32542sdgafgafdg";
+  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
+                                         NULL, NULL,
+                                         &error))
+    {
+      _dbus_babysitter_block_for_child_exit (sitter);
+      _dbus_babysitter_set_child_exit_error (sitter, &error);
+    }
+
+  if (sitter)
+    _dbus_babysitter_unref (sitter);
+
+  if (!dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Did not get an error launching nonexistent executable\n");
+      return FALSE;
+    }
+
+  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
+    {
+      _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
+                  error.name, error.message);
+      dbus_error_free (&error);
+      return FALSE;
+    }
+
+  dbus_error_free (&error);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_segfault (void *data)
+{
+  char *argv[4] = { NULL, NULL, NULL, NULL };
+  DBusBabysitter *sitter;
+  DBusError error;
+  DBusString argv0;
+
+  sitter = NULL;
+
+  dbus_error_init (&error);
+
+  /*** Test launching segfault binary */
+
+  argv[0] = get_test_exec ("test-segfault", &argv0);
+
+  if (argv[0] == NULL)
+    {
+      /* OOM was simulated, never mind */
+      return TRUE;
+    }
+
+  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
+                                         NULL, NULL,
+                                         &error))
+    {
+      _dbus_babysitter_block_for_child_exit (sitter);
+      _dbus_babysitter_set_child_exit_error (sitter, &error);
+    }
+
+  _dbus_string_free (&argv0);
+
+  if (sitter)
+    _dbus_babysitter_unref (sitter);
+
+  if (!dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Did not get an error launching segfaulting binary\n");
+      return FALSE;
+    }
+
+  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
+    {
+      _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
+                  error.name, error.message);
+      dbus_error_free (&error);
+      return FALSE;
+    }
+
+  dbus_error_free (&error);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_exit (void *data)
+{
+  char *argv[4] = { NULL, NULL, NULL, NULL };
+  DBusBabysitter *sitter;
+  DBusError error;
+  DBusString argv0;
+
+  sitter = NULL;
+
+  dbus_error_init (&error);
+
+  /*** Test launching exit failure binary */
+
+  argv[0] = get_test_exec ("test-exit", &argv0);
+
+  if (argv[0] == NULL)
+    {
+      /* OOM was simulated, never mind */
+      return TRUE;
+    }
+
+  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
+                                         NULL, NULL,
+                                         &error))
+    {
+      _dbus_babysitter_block_for_child_exit (sitter);
+      _dbus_babysitter_set_child_exit_error (sitter, &error);
+    }
+
+  _dbus_string_free (&argv0);
+
+  if (sitter)
+    _dbus_babysitter_unref (sitter);
+
+  if (!dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
+      return FALSE;
+    }
+
+  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
+    {
+      _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
+                  error.name, error.message);
+      dbus_error_free (&error);
+      return FALSE;
+    }
+
+  dbus_error_free (&error);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_and_kill (void *data)
+{
+  char *argv[4] = { NULL, NULL, NULL, NULL };
+  DBusBabysitter *sitter;
+  DBusError error;
+  DBusString argv0;
+
+  sitter = NULL;
+
+  dbus_error_init (&error);
+
+  /*** Test launching sleeping binary then killing it */
+
+  argv[0] = get_test_exec ("test-sleep-forever", &argv0);
+
+  if (argv[0] == NULL)
+    {
+      /* OOM was simulated, never mind */
+      return TRUE;
+    }
+
+  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
+                                         NULL, NULL,
+                                         &error))
+    {
+      _dbus_babysitter_kill_child (sitter);
+
+      _dbus_babysitter_block_for_child_exit (sitter);
+
+      _dbus_babysitter_set_child_exit_error (sitter, &error);
+    }
+
+  _dbus_string_free (&argv0);
+
+  if (sitter)
+    _dbus_babysitter_unref (sitter);
+
+  if (!dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Did not get an error after killing spawned binary\n");
+      return FALSE;
+    }
+
+  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
+    {
+      _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
+                  error.name, error.message);
+      dbus_error_free (&error);
+      return FALSE;
+    }
+
+  dbus_error_free (&error);
+
+  return TRUE;
+}
+
+dbus_bool_t
+_dbus_spawn_test (const char *test_data_dir)
+{
+  if (!_dbus_test_oom_handling ("spawn_nonexistent",
+                                check_spawn_nonexistent,
+                                NULL))
+    return FALSE;
+
+  /* Don't run the obnoxious segfault test by default,
+   * it's a pain to have to click all those error boxes.
+   */
+  if (getenv ("DO_SEGFAULT_TEST"))
+    if (!_dbus_test_oom_handling ("spawn_segfault",
+                                  check_spawn_segfault,
+                                  NULL))
+      return FALSE;
+
+  if (!_dbus_test_oom_handling ("spawn_exit",
+                                check_spawn_exit,
+                                NULL))
+    return FALSE;
+
+  if (!_dbus_test_oom_handling ("spawn_and_kill",
+                                check_spawn_and_kill,
+                                NULL))
+    return FALSE;
+
+  return TRUE;
+}
+#endif
diff --git a/dbus/dbus/dbus-spawn.c b/dbus/dbus/dbus-spawn.c
new file mode 100644
index 0000000..ef00801
--- /dev/null
+++ b/dbus/dbus/dbus-spawn.c
@@ -0,0 +1,1579 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-spawn.c Wrapper around fork/exec
+ * 
+ * Copyright (C) 2002, 2003, 2004  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include "dbus-spawn.h"
+#include "dbus-sysdeps-unix.h"
+#include "dbus-internals.h"
+#include "dbus-test.h"
+#include "dbus-protocol.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+extern char **environ;
+
+/**
+ * @addtogroup DBusInternalsUtils
+ * @{
+ */
+
+/*
+ * I'm pretty sure this whole spawn file could be made simpler,
+ * if you thought about it a bit.
+ */
+
+/**
+ * Enumeration for status of a read()
+ */
+typedef enum
+{
+  READ_STATUS_OK,    /**< Read succeeded */
+  READ_STATUS_ERROR, /**< Some kind of error */
+  READ_STATUS_EOF    /**< EOF returned */
+} ReadStatus;
+
+static ReadStatus
+read_ints (int        fd,
+	   int       *buf,
+	   int        n_ints_in_buf,
+	   int       *n_ints_read,
+	   DBusError *error)
+{
+  size_t bytes = 0;    
+  ReadStatus retval;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  retval = READ_STATUS_OK;
+  
+  while (TRUE)
+    {
+      ssize_t chunk;
+      size_t to_read;
+
+      to_read = sizeof (int) * n_ints_in_buf - bytes;
+
+      if (to_read == 0)
+        break;
+
+    again:
+      
+      chunk = read (fd,
+                    ((char*)buf) + bytes,
+                    to_read);
+      
+      if (chunk < 0 && errno == EINTR)
+        goto again;
+          
+      if (chunk < 0)
+        {
+          dbus_set_error (error,
+			  DBUS_ERROR_SPAWN_FAILED,
+			  "Failed to read from child pipe (%s)",
+			  _dbus_strerror (errno));
+
+          retval = READ_STATUS_ERROR;
+          break;
+        }
+      else if (chunk == 0)
+        {
+          retval = READ_STATUS_EOF;
+          break; /* EOF */
+        }
+      else /* chunk > 0 */
+	bytes += chunk;
+    }
+
+  *n_ints_read = (int)(bytes / sizeof(int));
+
+  return retval;
+}
+
+static ReadStatus
+read_pid (int        fd,
+          pid_t     *buf,
+          DBusError *error)
+{
+  size_t bytes = 0;    
+  ReadStatus retval;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  retval = READ_STATUS_OK;
+  
+  while (TRUE)
+    {
+      ssize_t chunk;
+      size_t to_read;
+
+      to_read = sizeof (pid_t) - bytes;
+
+      if (to_read == 0)
+        break;
+
+    again:
+      
+      chunk = read (fd,
+                    ((char*)buf) + bytes,
+                    to_read);
+      if (chunk < 0 && errno == EINTR)
+        goto again;
+          
+      if (chunk < 0)
+        {
+          dbus_set_error (error,
+			  DBUS_ERROR_SPAWN_FAILED,
+			  "Failed to read from child pipe (%s)",
+			  _dbus_strerror (errno));
+
+          retval = READ_STATUS_ERROR;
+          break;
+        }
+      else if (chunk == 0)
+        {
+          retval = READ_STATUS_EOF;
+          break; /* EOF */
+        }
+      else /* chunk > 0 */
+	bytes += chunk;
+    }
+
+  return retval;
+}
+
+/* The implementation uses an intermediate child between the main process
+ * and the grandchild. The grandchild is our spawned process. The intermediate
+ * child is a babysitter process; it keeps track of when the grandchild
+ * exits/crashes, and reaps the grandchild.
+ */
+
+/* Messages from children to parents */
+enum
+{
+  CHILD_EXITED,            /* This message is followed by the exit status int */
+  CHILD_FORK_FAILED,       /* Followed by errno */
+  CHILD_EXEC_FAILED,       /* Followed by errno */
+  CHILD_PID                /* Followed by pid_t */
+};
+
+/**
+ * Babysitter implementation details
+ */
+struct DBusBabysitter
+{
+  int refcount; /**< Reference count */
+
+  char *executable; /**< executable name to use in error messages */
+  
+  int socket_to_babysitter; /**< Connection to the babysitter process */
+  int error_pipe_from_child; /**< Connection to the process that does the exec() */
+  
+  pid_t sitter_pid;  /**< PID Of the babysitter */
+  pid_t grandchild_pid; /**< PID of the grandchild */
+
+  DBusWatchList *watches; /**< Watches */
+
+  DBusWatch *error_watch; /**< Error pipe watch */
+  DBusWatch *sitter_watch; /**< Sitter pipe watch */
+
+  DBusBabysitterFinishedFunc finished_cb;
+  void *finished_data;
+
+  int errnum; /**< Error number */
+  int status; /**< Exit status code */
+  unsigned int have_child_status : 1; /**< True if child status has been reaped */
+  unsigned int have_fork_errnum : 1; /**< True if we have an error code from fork() */
+  unsigned int have_exec_errnum : 1; /**< True if we have an error code from exec() */
+};
+
+static DBusBabysitter*
+_dbus_babysitter_new (void)
+{
+  DBusBabysitter *sitter;
+
+  sitter = dbus_new0 (DBusBabysitter, 1);
+  if (sitter == NULL)
+    return NULL;
+
+  sitter->refcount = 1;
+
+  sitter->socket_to_babysitter = -1;
+  sitter->error_pipe_from_child = -1;
+  
+  sitter->sitter_pid = -1;
+  sitter->grandchild_pid = -1;
+
+  sitter->watches = _dbus_watch_list_new ();
+  if (sitter->watches == NULL)
+    goto failed;
+  
+  return sitter;
+
+ failed:
+  _dbus_babysitter_unref (sitter);
+  return NULL;
+}
+
+/**
+ * Increment the reference count on the babysitter object.
+ *
+ * @param sitter the babysitter
+ * @returns the babysitter
+ */
+DBusBabysitter *
+_dbus_babysitter_ref (DBusBabysitter *sitter)
+{
+  _dbus_assert (sitter != NULL);
+  _dbus_assert (sitter->refcount > 0);
+  
+  sitter->refcount += 1;
+
+  return sitter;
+}
+
+static void close_socket_to_babysitter  (DBusBabysitter *sitter);
+static void close_error_pipe_from_child (DBusBabysitter *sitter);
+
+/**
+ * Decrement the reference count on the babysitter object.
+ * When the reference count of the babysitter object reaches
+ * zero, the babysitter is killed and the child that was being
+ * babysat gets emancipated.
+ *
+ * @param sitter the babysitter
+ */
+void
+_dbus_babysitter_unref (DBusBabysitter *sitter)
+{
+  _dbus_assert (sitter != NULL);
+  _dbus_assert (sitter->refcount > 0);
+  
+  sitter->refcount -= 1;
+  if (sitter->refcount == 0)
+    {
+      /* If we haven't forked other babysitters
+       * since this babysitter and socket were
+       * created then this close will cause the
+       * babysitter to wake up from poll with
+       * a hangup and then the babysitter will
+       * quit itself.
+       */
+      close_socket_to_babysitter (sitter);
+
+      close_error_pipe_from_child (sitter);
+
+      if (sitter->sitter_pid > 0)
+        {
+          int status;
+          int ret;
+
+          /* It's possible the babysitter died on its own above 
+           * from the close, or was killed randomly
+           * by some other process, so first try to reap it
+           */
+          ret = waitpid (sitter->sitter_pid, &status, WNOHANG);
+
+          /* If we couldn't reap the child then kill it, and
+           * try again
+           */
+          if (ret == 0)
+            kill (sitter->sitter_pid, SIGKILL);
+
+        again:
+          if (ret == 0)
+            ret = waitpid (sitter->sitter_pid, &status, 0);
+
+          if (ret < 0)
+            {
+              if (errno == EINTR)
+                goto again;
+              else if (errno == ECHILD)
+                _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
+              else
+                _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
+                            errno, _dbus_strerror (errno));
+            }
+          else
+            {
+              _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
+                             (long) ret, (long) sitter->sitter_pid);
+              
+              if (WIFEXITED (sitter->status))
+                _dbus_verbose ("Babysitter exited with status %d\n",
+                               WEXITSTATUS (sitter->status));
+              else if (WIFSIGNALED (sitter->status))
+                _dbus_verbose ("Babysitter received signal %d\n",
+                               WTERMSIG (sitter->status));
+              else
+                _dbus_verbose ("Babysitter exited abnormally\n");
+            }
+
+          sitter->sitter_pid = -1;
+        }
+
+      if (sitter->watches)
+        _dbus_watch_list_free (sitter->watches);
+
+      dbus_free (sitter->executable);
+      
+      dbus_free (sitter);
+    }
+}
+
+static ReadStatus
+read_data (DBusBabysitter *sitter,
+           int             fd)
+{
+  int what;
+  int got;
+  DBusError error = DBUS_ERROR_INIT;
+  ReadStatus r;
+
+  r = read_ints (fd, &what, 1, &got, &error);
+
+  switch (r)
+    {
+    case READ_STATUS_ERROR:
+      _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
+      dbus_error_free (&error);
+      return r;
+
+    case READ_STATUS_EOF:
+      return r;
+
+    case READ_STATUS_OK:
+      break;
+    }
+  
+  if (got == 1)
+    {
+      switch (what)
+        {
+        case CHILD_EXITED:
+        case CHILD_FORK_FAILED:
+        case CHILD_EXEC_FAILED:
+          {
+            int arg;
+            
+            r = read_ints (fd, &arg, 1, &got, &error);
+
+            switch (r)
+              {
+              case READ_STATUS_ERROR:
+                _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
+                dbus_error_free (&error);
+                return r;
+              case READ_STATUS_EOF:
+                return r;
+              case READ_STATUS_OK:
+                break;
+              }
+            
+            if (got == 1)
+              {
+                if (what == CHILD_EXITED)
+                  {
+                    sitter->have_child_status = TRUE;
+                    sitter->status = arg;
+                    sitter->errnum = 0;
+                    _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
+                                   WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
+                                   WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
+                  }
+                else if (what == CHILD_FORK_FAILED)
+                  {
+                    sitter->have_fork_errnum = TRUE;
+                    sitter->errnum = arg;
+                    _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
+                  }
+                else if (what == CHILD_EXEC_FAILED)
+                  {
+                    sitter->have_exec_errnum = TRUE;
+                    sitter->errnum = arg;
+                    _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
+                  }
+              }
+          }
+          break;
+        case CHILD_PID:
+          {
+            pid_t pid = -1;
+
+            r = read_pid (fd, &pid, &error);
+            
+            switch (r)
+              {
+              case READ_STATUS_ERROR:
+                _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
+                dbus_error_free (&error);
+                return r;
+              case READ_STATUS_EOF:
+                return r;
+              case READ_STATUS_OK:
+                break;
+              }
+            
+            sitter->grandchild_pid = pid;
+            
+            _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
+          }
+          break;
+        default:
+          _dbus_warn ("Unknown message received from babysitter process\n");
+          break;
+        }
+    }
+
+  return r;
+}
+
+static void
+close_socket_to_babysitter (DBusBabysitter *sitter)
+{
+  _dbus_verbose ("Closing babysitter\n");
+
+  if (sitter->sitter_watch != NULL)
+    {
+      _dbus_assert (sitter->watches != NULL);
+      _dbus_watch_list_remove_watch (sitter->watches,  sitter->sitter_watch);
+      _dbus_watch_invalidate (sitter->sitter_watch);
+      _dbus_watch_unref (sitter->sitter_watch);
+      sitter->sitter_watch = NULL;
+    }
+
+  if (sitter->socket_to_babysitter >= 0)
+    {
+      _dbus_close_socket (sitter->socket_to_babysitter, NULL);
+      sitter->socket_to_babysitter = -1;
+    }
+}
+
+static void
+close_error_pipe_from_child (DBusBabysitter *sitter)
+{
+  _dbus_verbose ("Closing child error\n");
+
+  if (sitter->error_watch != NULL)
+    {
+      _dbus_assert (sitter->watches != NULL);
+      _dbus_watch_list_remove_watch (sitter->watches,  sitter->error_watch);
+      _dbus_watch_invalidate (sitter->error_watch);
+      _dbus_watch_unref (sitter->error_watch);
+      sitter->error_watch = NULL;
+    }
+
+  if (sitter->error_pipe_from_child >= 0)
+    {
+      _dbus_close_socket (sitter->error_pipe_from_child, NULL);
+      sitter->error_pipe_from_child = -1;
+    }
+}
+
+static void
+handle_babysitter_socket (DBusBabysitter *sitter,
+                          int             revents)
+{
+  /* Even if we have POLLHUP, we want to keep reading
+   * data until POLLIN goes away; so this function only
+   * looks at HUP/ERR if no IN is set.
+   */
+  if (revents & _DBUS_POLLIN)
+    {
+      _dbus_verbose ("Reading data from babysitter\n");
+      if (read_data (sitter, sitter->socket_to_babysitter) != READ_STATUS_OK)
+        close_socket_to_babysitter (sitter);
+    }
+  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
+    {
+      close_socket_to_babysitter (sitter);
+    }
+}
+
+static void
+handle_error_pipe (DBusBabysitter *sitter,
+                   int             revents)
+{
+  if (revents & _DBUS_POLLIN)
+    {
+      _dbus_verbose ("Reading data from child error\n");
+      if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
+        close_error_pipe_from_child (sitter);
+    }
+  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
+    {
+      close_error_pipe_from_child (sitter);
+    }
+}
+
+/* returns whether there were any poll events handled */
+static dbus_bool_t
+babysitter_iteration (DBusBabysitter *sitter,
+                      dbus_bool_t     block)
+{
+  DBusPollFD fds[2];
+  int i;
+  dbus_bool_t descriptors_ready;
+
+  descriptors_ready = FALSE;
+  
+  i = 0;
+
+  if (sitter->error_pipe_from_child >= 0)
+    {
+      fds[i].fd = sitter->error_pipe_from_child;
+      fds[i].events = _DBUS_POLLIN;
+      fds[i].revents = 0;
+      ++i;
+    }
+  
+  if (sitter->socket_to_babysitter >= 0)
+    {
+      fds[i].fd = sitter->socket_to_babysitter;
+      fds[i].events = _DBUS_POLLIN;
+      fds[i].revents = 0;
+      ++i;
+    }
+
+  if (i > 0)
+    {
+      int ret;
+
+      do
+        {
+          ret = _dbus_poll (fds, i, 0);
+        }
+      while (ret < 0 && errno == EINTR);
+
+      if (ret == 0 && block)
+        {
+          do
+            {
+              ret = _dbus_poll (fds, i, -1);
+            }
+          while (ret < 0 && errno == EINTR);
+        }
+
+      if (ret > 0)
+        {
+          descriptors_ready = TRUE;
+          
+          while (i > 0)
+            {
+              --i;
+              if (fds[i].fd == sitter->error_pipe_from_child)
+                handle_error_pipe (sitter, fds[i].revents);
+              else if (fds[i].fd == sitter->socket_to_babysitter)
+                handle_babysitter_socket (sitter, fds[i].revents);
+            }
+        }
+    }
+
+  return descriptors_ready;
+}
+
+/**
+ * Macro returns #TRUE if the babysitter still has live sockets open to the
+ * babysitter child or the grandchild.
+ */
+#define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter >= 0 || (sitter)->error_pipe_from_child >= 0)
+
+/**
+ * Blocks until the babysitter process gives us the PID of the spawned grandchild,
+ * then kills the spawned grandchild.
+ *
+ * @param sitter the babysitter object
+ */
+void
+_dbus_babysitter_kill_child (DBusBabysitter *sitter)
+{
+  /* be sure we have the PID of the child */
+  while (LIVE_CHILDREN (sitter) &&
+         sitter->grandchild_pid == -1)
+    babysitter_iteration (sitter, TRUE);
+
+  _dbus_verbose ("Got child PID %ld for killing\n",
+                 (long) sitter->grandchild_pid);
+  
+  if (sitter->grandchild_pid == -1)
+    return; /* child is already dead, or we're so hosed we'll never recover */
+
+  kill (sitter->grandchild_pid, SIGKILL);
+}
+
+/**
+ * Checks whether the child has exited, without blocking.
+ *
+ * @param sitter the babysitter
+ */
+dbus_bool_t
+_dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
+{
+
+  /* Be sure we're up-to-date */
+  while (LIVE_CHILDREN (sitter) &&
+         babysitter_iteration (sitter, FALSE))
+    ;
+
+  /* We will have exited the babysitter when the child has exited */
+  return sitter->socket_to_babysitter < 0;
+}
+
+/**
+ * Gets the exit status of the child. We do this so implementation specific
+ * detail is not cluttering up dbus, for example the system launcher code.
+ * This can only be called if the child has exited, i.e. call
+ * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
+ * did not return a status code, e.g. because the child was signaled
+ * or we failed to ever launch the child in the first place.
+ *
+ * @param sitter the babysitter
+ * @param status the returned status code
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
+                                        int            *status)
+{
+  if (!_dbus_babysitter_get_child_exited (sitter))
+    _dbus_assert_not_reached ("Child has not exited");
+  
+  if (!sitter->have_child_status ||
+      !(WIFEXITED (sitter->status)))
+    return FALSE;
+
+  *status = WEXITSTATUS (sitter->status);
+  return TRUE;
+}
+
+/**
+ * Sets the #DBusError with an explanation of why the spawned
+ * child process exited (on a signal, or whatever). If
+ * the child process has not exited, does nothing (error
+ * will remain unset).
+ *
+ * @param sitter the babysitter
+ * @param error an error to fill in
+ */
+void
+_dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
+                                       DBusError      *error)
+{
+  if (!_dbus_babysitter_get_child_exited (sitter))
+    return;
+
+  /* Note that if exec fails, we will also get a child status
+   * from the babysitter saying the child exited,
+   * so we need to give priority to the exec error
+   */
+  if (sitter->have_exec_errnum)
+    {
+      dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
+                      "Failed to execute program %s: %s",
+                      sitter->executable, _dbus_strerror (sitter->errnum));
+    }
+  else if (sitter->have_fork_errnum)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                      "Failed to fork a new process %s: %s",
+                      sitter->executable, _dbus_strerror (sitter->errnum));
+    }
+  else if (sitter->have_child_status)
+    {
+      if (WIFEXITED (sitter->status))
+        dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
+                        "Process %s exited with status %d",
+                        sitter->executable, WEXITSTATUS (sitter->status));
+      else if (WIFSIGNALED (sitter->status))
+        dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
+                        "Process %s received signal %d",
+                        sitter->executable, WTERMSIG (sitter->status));
+      else
+        dbus_set_error (error, DBUS_ERROR_FAILED,
+                        "Process %s exited abnormally",
+                        sitter->executable);
+    }
+  else
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Process %s exited, reason unknown",
+                      sitter->executable);
+    }
+}
+
+/**
+ * Sets watch functions to notify us when the
+ * babysitter object needs to read/write file descriptors.
+ *
+ * @param sitter the babysitter
+ * @param add_function function to begin monitoring a new descriptor.
+ * @param remove_function function to stop monitoring a descriptor.
+ * @param toggled_function function to notify when the watch is enabled/disabled
+ * @param data data to pass to add_function and remove_function.
+ * @param free_data_function function to be called to free the data.
+ * @returns #FALSE on failure (no memory)
+ */
+dbus_bool_t
+_dbus_babysitter_set_watch_functions (DBusBabysitter            *sitter,
+                                      DBusAddWatchFunction       add_function,
+                                      DBusRemoveWatchFunction    remove_function,
+                                      DBusWatchToggledFunction   toggled_function,
+                                      void                      *data,
+                                      DBusFreeFunction           free_data_function)
+{
+  return _dbus_watch_list_set_functions (sitter->watches,
+                                         add_function,
+                                         remove_function,
+                                         toggled_function,
+                                         data,
+                                         free_data_function);
+}
+
+static dbus_bool_t
+handle_watch (DBusWatch       *watch,
+              unsigned int     condition,
+              void            *data)
+{
+  DBusBabysitter *sitter = _dbus_babysitter_ref (data);
+  int revents;
+  int fd;
+  
+  revents = 0;
+  if (condition & DBUS_WATCH_READABLE)
+    revents |= _DBUS_POLLIN;
+  if (condition & DBUS_WATCH_ERROR)
+    revents |= _DBUS_POLLERR;
+  if (condition & DBUS_WATCH_HANGUP)
+    revents |= _DBUS_POLLHUP;
+
+  fd = dbus_watch_get_socket (watch);
+
+  if (fd == sitter->error_pipe_from_child)
+    handle_error_pipe (sitter, revents);
+  else if (fd == sitter->socket_to_babysitter)
+    handle_babysitter_socket (sitter, revents);
+
+  while (LIVE_CHILDREN (sitter) &&
+         babysitter_iteration (sitter, FALSE))
+    ;
+
+  /* fd.o #32992: if the handle_* methods closed their sockets, they previously
+   * didn't always remove the watches. Check that we don't regress. */
+  _dbus_assert (sitter->socket_to_babysitter != -1 || sitter->sitter_watch == NULL);
+  _dbus_assert (sitter->error_pipe_from_child != -1 || sitter->error_watch == NULL);
+
+  if (_dbus_babysitter_get_child_exited (sitter) &&
+      sitter->finished_cb != NULL)
+    {
+      sitter->finished_cb (sitter, sitter->finished_data);
+      sitter->finished_cb = NULL;
+    }
+
+  _dbus_babysitter_unref (sitter);
+  return TRUE;
+}
+
+/** Helps remember which end of the pipe is which */
+#define READ_END 0
+/** Helps remember which end of the pipe is which */
+#define WRITE_END 1
+
+
+/* Avoids a danger in threaded situations (calling close()
+ * on a file descriptor twice, and another thread has
+ * re-opened it since the first close)
+ */
+static int
+close_and_invalidate (int *fd)
+{
+  int ret;
+
+  if (*fd < 0)
+    return -1;
+  else
+    {
+      ret = _dbus_close_socket (*fd, NULL);
+      *fd = -1;
+    }
+
+  return ret;
+}
+
+static dbus_bool_t
+make_pipe (int         p[2],
+           DBusError  *error)
+{
+  int retval;
+
+#ifdef HAVE_PIPE2
+  dbus_bool_t cloexec_done;
+
+  retval = pipe2 (p, O_CLOEXEC);
+  cloexec_done = retval >= 0;
+
+  /* Check if kernel seems to be too old to know pipe2(). We assume
+     that if pipe2 is available, O_CLOEXEC is too.  */
+  if (retval < 0 && errno == ENOSYS)
+#endif
+    {
+      retval = pipe(p);
+    }
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (retval < 0)
+    {
+      dbus_set_error (error,
+		      DBUS_ERROR_SPAWN_FAILED,
+		      "Failed to create pipe for communicating with child process (%s)",
+		      _dbus_strerror (errno));
+      return FALSE;
+    }
+
+#ifdef HAVE_PIPE2
+  if (!cloexec_done)
+#endif
+    {
+      _dbus_fd_set_close_on_exec (p[0]);
+      _dbus_fd_set_close_on_exec (p[1]);
+    }
+
+  return TRUE;
+}
+
+static void
+do_write (int fd, const void *buf, size_t count)
+{
+  size_t bytes_written;
+  int ret;
+  
+  bytes_written = 0;
+  
+ again:
+  
+  ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
+
+  if (ret < 0)
+    {
+      if (errno == EINTR)
+        goto again;
+      else
+        {
+          _dbus_warn ("Failed to write data to pipe!\n");
+          exit (1); /* give up, we suck */
+        }
+    }
+  else
+    bytes_written += ret;
+  
+  if (bytes_written < count)
+    goto again;
+}
+
+static void
+write_err_and_exit (int fd, int msg)
+{
+  int en = errno;
+
+  do_write (fd, &msg, sizeof (msg));
+  do_write (fd, &en, sizeof (en));
+  
+  exit (1);
+}
+
+static void
+write_pid (int fd, pid_t pid)
+{
+  int msg = CHILD_PID;
+  
+  do_write (fd, &msg, sizeof (msg));
+  do_write (fd, &pid, sizeof (pid));
+}
+
+static void
+write_status_and_exit (int fd, int status)
+{
+  int msg = CHILD_EXITED;
+  
+  do_write (fd, &msg, sizeof (msg));
+  do_write (fd, &status, sizeof (status));
+  
+  exit (0);
+}
+
+static void
+do_exec (int                       child_err_report_fd,
+	 char                    **argv,
+	 char                    **envp,
+	 DBusSpawnChildSetupFunc   child_setup,
+	 void                     *user_data)
+{
+#ifdef DBUS_BUILD_TESTS
+  int i, max_open;
+#endif
+
+  _dbus_verbose_reset ();
+  _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
+                 _dbus_getpid ());
+  
+  if (child_setup)
+    (* child_setup) (user_data);
+
+#ifdef DBUS_BUILD_TESTS
+  max_open = sysconf (_SC_OPEN_MAX);
+  
+  for (i = 3; i < max_open; i++)
+    {
+      int retval;
+
+      if (i == child_err_report_fd)
+        continue;
+      
+      retval = fcntl (i, F_GETFD);
+
+      if (retval != -1 && !(retval & FD_CLOEXEC))
+	_dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
+    }
+#endif
+
+  if (envp == NULL)
+    {
+      _dbus_assert (environ != NULL);
+
+      envp = environ;
+    }
+  
+  execve (argv[0], argv, envp);
+  
+  /* Exec failed */
+  write_err_and_exit (child_err_report_fd,
+                      CHILD_EXEC_FAILED);
+}
+
+static void
+check_babysit_events (pid_t grandchild_pid,
+                      int   parent_pipe,
+                      int   revents)
+{
+  pid_t ret;
+  int status;
+  
+  do
+    {
+      ret = waitpid (grandchild_pid, &status, WNOHANG);
+      /* The man page says EINTR can't happen with WNOHANG,
+       * but there are reports of it (maybe only with valgrind?)
+       */
+    }
+  while (ret < 0 && errno == EINTR);
+
+  if (ret == 0)
+    {
+      _dbus_verbose ("no child exited\n");
+      
+      ; /* no child exited */
+    }
+  else if (ret < 0)
+    {
+      /* This isn't supposed to happen. */
+      _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n",
+                  _dbus_strerror (errno));
+      exit (1);
+    }
+  else if (ret == grandchild_pid)
+    {
+      /* Child exited */
+      _dbus_verbose ("reaped child pid %ld\n", (long) ret);
+      
+      write_status_and_exit (parent_pipe, status);
+    }
+  else
+    {
+      _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n",
+                  (int) ret);
+      exit (1);
+    }
+
+  if (revents & _DBUS_POLLIN)
+    {
+      _dbus_verbose ("babysitter got POLLIN from parent pipe\n");
+    }
+
+  if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
+    {
+      /* Parent is gone, so we just exit */
+      _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n");
+      exit (0);
+    }
+}
+
+static int babysit_sigchld_pipe = -1;
+
+static void
+babysit_signal_handler (int signo)
+{
+  char b = '\0';
+ again:
+  if (write (babysit_sigchld_pipe, &b, 1) <= 0) 
+    if (errno == EINTR)
+      goto again;
+}
+
+static void
+babysit (pid_t grandchild_pid,
+         int   parent_pipe)
+{
+  int sigchld_pipe[2];
+
+  /* We don't exec, so we keep parent state, such as the pid that
+   * _dbus_verbose() uses. Reset the pid here.
+   */
+  _dbus_verbose_reset ();
+  
+  /* I thought SIGCHLD would just wake up the poll, but
+   * that didn't seem to work, so added this pipe.
+   * Probably the pipe is more likely to work on busted
+   * operating systems anyhow.
+   */
+  if (pipe (sigchld_pipe) < 0)
+    {
+      _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n");
+      exit (1);
+    }
+
+  babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
+
+  _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
+  
+  write_pid (parent_pipe, grandchild_pid);
+
+  check_babysit_events (grandchild_pid, parent_pipe, 0);
+
+  while (TRUE)
+    {
+      DBusPollFD pfds[2];
+      
+      pfds[0].fd = parent_pipe;
+      pfds[0].events = _DBUS_POLLIN;
+      pfds[0].revents = 0;
+
+      pfds[1].fd = sigchld_pipe[READ_END];
+      pfds[1].events = _DBUS_POLLIN;
+      pfds[1].revents = 0;
+      
+      if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR)
+        {
+          _dbus_warn ("_dbus_poll() error: %s\n", strerror (errno));
+          exit (1);
+        }
+
+      if (pfds[0].revents != 0)
+        {
+          check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
+        }
+      else if (pfds[1].revents & _DBUS_POLLIN)
+        {
+          char b;
+          if (read (sigchld_pipe[READ_END], &b, 1) == -1)
+            {
+              /* ignore */
+            }
+          /* do waitpid check */
+          check_babysit_events (grandchild_pid, parent_pipe, 0);
+        }
+    }
+  
+  exit (1);
+}
+
+/**
+ * Spawns a new process. The executable name and argv[0]
+ * are the same, both are provided in argv[0]. The child_setup
+ * function is passed the given user_data and is run in the child
+ * just before calling exec().
+ *
+ * Also creates a "babysitter" which tracks the status of the
+ * child process, advising the parent if the child exits.
+ * If the spawn fails, no babysitter is created.
+ * If sitter_p is #NULL, no babysitter is kept.
+ *
+ * @param sitter_p return location for babysitter or #NULL
+ * @param argv the executable and arguments
+ * @param env the environment (not used on unix yet)
+ * @param child_setup function to call in child pre-exec()
+ * @param user_data user data for setup function
+ * @param error error object to be filled in if function fails
+ * @returns #TRUE on success, #FALSE if error is filled in
+ */
+dbus_bool_t
+_dbus_spawn_async_with_babysitter (DBusBabysitter          **sitter_p,
+                                   char                    **argv,
+                                   char                    **env,
+                                   DBusSpawnChildSetupFunc   child_setup,
+                                   void                     *user_data,
+                                   DBusError                *error)
+{
+  DBusBabysitter *sitter;
+  int child_err_report_pipe[2] = { -1, -1 };
+  int babysitter_pipe[2] = { -1, -1 };
+  pid_t pid;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (sitter_p != NULL)
+    *sitter_p = NULL;
+
+  sitter = NULL;
+
+  sitter = _dbus_babysitter_new ();
+  if (sitter == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+
+  sitter->executable = _dbus_strdup (argv[0]);
+  if (sitter->executable == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto cleanup_and_fail;
+    }
+  
+  if (!make_pipe (child_err_report_pipe, error))
+    goto cleanup_and_fail;
+
+  if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
+    goto cleanup_and_fail;
+
+  /* Setting up the babysitter is only useful in the parent,
+   * but we don't want to run out of memory and fail
+   * after we've already forked, since then we'd leak
+   * child processes everywhere.
+   */
+  sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END],
+                                         DBUS_WATCH_READABLE,
+                                         TRUE, handle_watch, sitter, NULL);
+  if (sitter->error_watch == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto cleanup_and_fail;
+    }
+        
+  if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->error_watch))
+    {
+      /* we need to free it early so the destructor won't try to remove it
+       * without it having been added, which DBusLoop doesn't allow */
+      _dbus_watch_invalidate (sitter->error_watch);
+      _dbus_watch_unref (sitter->error_watch);
+      sitter->error_watch = NULL;
+
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto cleanup_and_fail;
+    }
+      
+  sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0],
+                                          DBUS_WATCH_READABLE,
+                                          TRUE, handle_watch, sitter, NULL);
+  if (sitter->sitter_watch == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto cleanup_and_fail;
+    }
+      
+  if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->sitter_watch))
+    {
+      /* we need to free it early so the destructor won't try to remove it
+       * without it having been added, which DBusLoop doesn't allow */
+      _dbus_watch_invalidate (sitter->sitter_watch);
+      _dbus_watch_unref (sitter->sitter_watch);
+      sitter->sitter_watch = NULL;
+
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto cleanup_and_fail;
+    }
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  pid = fork ();
+  
+  if (pid < 0)
+    {
+      dbus_set_error (error,
+		      DBUS_ERROR_SPAWN_FORK_FAILED,
+		      "Failed to fork (%s)",
+		      _dbus_strerror (errno));
+      goto cleanup_and_fail;
+    }
+  else if (pid == 0)
+    {
+      /* Immediate child, this is the babysitter process. */
+      int grandchild_pid;
+      
+      /* Be sure we crash if the parent exits
+       * and we write to the err_report_pipe
+       */
+      signal (SIGPIPE, SIG_DFL);
+
+      /* Close the parent's end of the pipes. */
+      close_and_invalidate (&child_err_report_pipe[READ_END]);
+      close_and_invalidate (&babysitter_pipe[0]);
+      
+      /* Create the child that will exec () */
+      grandchild_pid = fork ();
+      
+      if (grandchild_pid < 0)
+	{
+	  write_err_and_exit (babysitter_pipe[1],
+			      CHILD_FORK_FAILED);
+          _dbus_assert_not_reached ("Got to code after write_err_and_exit()");
+	}
+      else if (grandchild_pid == 0)
+	{
+	  do_exec (child_err_report_pipe[WRITE_END],
+		   argv,
+		   env,
+		   child_setup, user_data);
+          _dbus_assert_not_reached ("Got to code after exec() - should have exited on error");
+	}
+      else
+	{
+          babysit (grandchild_pid, babysitter_pipe[1]);
+          _dbus_assert_not_reached ("Got to code after babysit()");
+	}
+    }
+  else
+    {      
+      /* Close the uncared-about ends of the pipes */
+      close_and_invalidate (&child_err_report_pipe[WRITE_END]);
+      close_and_invalidate (&babysitter_pipe[1]);
+
+      sitter->socket_to_babysitter = babysitter_pipe[0];
+      babysitter_pipe[0] = -1;
+      
+      sitter->error_pipe_from_child = child_err_report_pipe[READ_END];
+      child_err_report_pipe[READ_END] = -1;
+
+      sitter->sitter_pid = pid;
+
+      if (sitter_p != NULL)
+        *sitter_p = sitter;
+      else
+        _dbus_babysitter_unref (sitter);
+
+      dbus_free_string_array (env);
+
+      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+      
+      return TRUE;
+    }
+
+ cleanup_and_fail:
+
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  
+  close_and_invalidate (&child_err_report_pipe[READ_END]);
+  close_and_invalidate (&child_err_report_pipe[WRITE_END]);
+  close_and_invalidate (&babysitter_pipe[0]);
+  close_and_invalidate (&babysitter_pipe[1]);
+
+  if (sitter != NULL)
+    _dbus_babysitter_unref (sitter);
+  
+  return FALSE;
+}
+
+void
+_dbus_babysitter_set_result_function  (DBusBabysitter             *sitter,
+                                       DBusBabysitterFinishedFunc  finished,
+                                       void                       *user_data)
+{
+  sitter->finished_cb = finished;
+  sitter->finished_data = user_data;
+}
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+
+static char *
+get_test_exec (const char *exe,
+               DBusString *scratch_space)
+{
+  const char *dbus_test_exec;
+
+  dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
+
+  if (dbus_test_exec == NULL)
+    dbus_test_exec = DBUS_TEST_EXEC;
+
+  if (!_dbus_string_init (scratch_space))
+    return NULL;
+
+  if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
+                                   dbus_test_exec, exe, DBUS_EXEEXT))
+    {
+      _dbus_string_free (scratch_space);
+      return NULL;
+    }
+
+  return _dbus_string_get_data (scratch_space);
+}
+
+static void
+_dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
+{
+  while (LIVE_CHILDREN (sitter))
+    babysitter_iteration (sitter, TRUE);
+}
+
+static dbus_bool_t
+check_spawn_nonexistent (void *data)
+{
+  char *argv[4] = { NULL, NULL, NULL, NULL };
+  DBusBabysitter *sitter = NULL;
+  DBusError error = DBUS_ERROR_INIT;
+
+  /*** Test launching nonexistent binary */
+  
+  argv[0] = "/this/does/not/exist/32542sdgafgafdg";
+  if (_dbus_spawn_async_with_babysitter (&sitter, argv,
+                                         NULL, NULL, NULL,
+                                         &error))
+    {
+      _dbus_babysitter_block_for_child_exit (sitter);
+      _dbus_babysitter_set_child_exit_error (sitter, &error);
+    }
+
+  if (sitter)
+    _dbus_babysitter_unref (sitter);
+
+  if (!dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Did not get an error launching nonexistent executable\n");
+      return FALSE;
+    }
+
+  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
+    {
+      _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
+                  error.name, error.message);
+      dbus_error_free (&error);
+      return FALSE;
+    }
+
+  dbus_error_free (&error);
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_segfault (void *data)
+{
+  char *argv[4] = { NULL, NULL, NULL, NULL };
+  DBusBabysitter *sitter = NULL;
+  DBusError error = DBUS_ERROR_INIT;
+  DBusString argv0;
+
+  /*** Test launching segfault binary */
+
+  argv[0] = get_test_exec ("test-segfault", &argv0);
+
+  if (argv[0] == NULL)
+    {
+      /* OOM was simulated, never mind */
+      return TRUE;
+    }
+
+  if (_dbus_spawn_async_with_babysitter (&sitter, argv,
+                                         NULL, NULL, NULL,
+                                         &error))
+    {
+      _dbus_babysitter_block_for_child_exit (sitter);
+      _dbus_babysitter_set_child_exit_error (sitter, &error);
+    }
+
+  _dbus_string_free (&argv0);
+
+  if (sitter)
+    _dbus_babysitter_unref (sitter);
+
+  if (!dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Did not get an error launching segfaulting binary\n");
+      return FALSE;
+    }
+
+  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
+    {
+      _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
+                  error.name, error.message);
+      dbus_error_free (&error);
+      return FALSE;
+    }
+
+  dbus_error_free (&error);
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_exit (void *data)
+{
+  char *argv[4] = { NULL, NULL, NULL, NULL };
+  DBusBabysitter *sitter = NULL;
+  DBusError error = DBUS_ERROR_INIT;
+  DBusString argv0;
+
+  /*** Test launching exit failure binary */
+
+  argv[0] = get_test_exec ("test-exit", &argv0);
+
+  if (argv[0] == NULL)
+    {
+      /* OOM was simulated, never mind */
+      return TRUE;
+    }
+
+  if (_dbus_spawn_async_with_babysitter (&sitter, argv,
+                                         NULL, NULL, NULL,
+                                         &error))
+    {
+      _dbus_babysitter_block_for_child_exit (sitter);
+      _dbus_babysitter_set_child_exit_error (sitter, &error);
+    }
+
+  _dbus_string_free (&argv0);
+
+  if (sitter)
+    _dbus_babysitter_unref (sitter);
+
+  if (!dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
+      return FALSE;
+    }
+
+  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
+    {
+      _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
+                  error.name, error.message);
+      dbus_error_free (&error);
+      return FALSE;
+    }
+
+  dbus_error_free (&error);
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+check_spawn_and_kill (void *data)
+{
+  char *argv[4] = { NULL, NULL, NULL, NULL };
+  DBusBabysitter *sitter = NULL;
+  DBusError error = DBUS_ERROR_INIT;
+  DBusString argv0;
+
+  /*** Test launching sleeping binary then killing it */
+
+  argv[0] = get_test_exec ("test-sleep-forever", &argv0);
+
+  if (argv[0] == NULL)
+    {
+      /* OOM was simulated, never mind */
+      return TRUE;
+    }
+
+  if (_dbus_spawn_async_with_babysitter (&sitter, argv,
+                                         NULL, NULL, NULL,
+                                         &error))
+    {
+      _dbus_babysitter_kill_child (sitter);
+      
+      _dbus_babysitter_block_for_child_exit (sitter);
+      
+      _dbus_babysitter_set_child_exit_error (sitter, &error);
+    }
+
+  _dbus_string_free (&argv0);
+
+  if (sitter)
+    _dbus_babysitter_unref (sitter);
+
+  if (!dbus_error_is_set (&error))
+    {
+      _dbus_warn ("Did not get an error after killing spawned binary\n");
+      return FALSE;
+    }
+
+  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
+        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
+    {
+      _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
+                  error.name, error.message);
+      dbus_error_free (&error);
+      return FALSE;
+    }
+
+  dbus_error_free (&error);
+  
+  return TRUE;
+}
+
+dbus_bool_t
+_dbus_spawn_test (const char *test_data_dir)
+{
+  if (!_dbus_test_oom_handling ("spawn_nonexistent",
+                                check_spawn_nonexistent,
+                                NULL))
+    return FALSE;
+
+  if (!_dbus_test_oom_handling ("spawn_segfault",
+                                check_spawn_segfault,
+                                NULL))
+    return FALSE;
+
+  if (!_dbus_test_oom_handling ("spawn_exit",
+                                check_spawn_exit,
+                                NULL))
+    return FALSE;
+
+  if (!_dbus_test_oom_handling ("spawn_and_kill",
+                                check_spawn_and_kill,
+                                NULL))
+    return FALSE;
+  
+  return TRUE;
+}
+#endif
diff --git a/dbus/dbus/dbus-spawn.h b/dbus/dbus/dbus-spawn.h
new file mode 100644
index 0000000..a8814fb
--- /dev/null
+++ b/dbus/dbus/dbus-spawn.h
@@ -0,0 +1,67 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-spawn.h Wrapper around fork/exec
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_SPAWN_H
+#define DBUS_SPAWN_H
+
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-watch.h>
+
+DBUS_BEGIN_DECLS
+
+typedef void (* DBusSpawnChildSetupFunc) (void *user_data);
+
+typedef struct DBusBabysitter DBusBabysitter;
+
+typedef void (* DBusBabysitterFinishedFunc) (DBusBabysitter *sitter,
+                                             void           *user_data);
+
+dbus_bool_t _dbus_spawn_async_with_babysitter     (DBusBabysitter           **sitter_p,
+                                                   char                     **argv,
+                                                   char                     **env,
+                                                   DBusSpawnChildSetupFunc    child_setup,
+                                                   void                      *user_data,
+                                                   DBusError                 *error);
+void        _dbus_babysitter_set_result_function  (DBusBabysitter            *sitter,
+                                                   DBusBabysitterFinishedFunc finished,
+                                                   void                      *user_data);
+DBusBabysitter* _dbus_babysitter_ref              (DBusBabysitter            *sitter);
+void        _dbus_babysitter_unref                (DBusBabysitter            *sitter);
+void        _dbus_babysitter_kill_child           (DBusBabysitter            *sitter);
+dbus_bool_t _dbus_babysitter_get_child_exited     (DBusBabysitter            *sitter);
+void        _dbus_babysitter_set_child_exit_error (DBusBabysitter            *sitter,
+                                                   DBusError                 *error);
+dbus_bool_t _dbus_babysitter_get_child_exit_status (DBusBabysitter           *sitter,
+                                                    int                      *status);
+dbus_bool_t _dbus_babysitter_set_watch_functions  (DBusBabysitter            *sitter,
+                                                   DBusAddWatchFunction       add_function,
+                                                   DBusRemoveWatchFunction    remove_function,
+                                                   DBusWatchToggledFunction   toggled_function,
+                                                   void                      *data,
+                                                   DBusFreeFunction           free_data_function);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SPAWN_H */
diff --git a/dbus/dbus/dbus-string-private.h b/dbus/dbus/dbus-string-private.h
new file mode 100644
index 0000000..2e6de90
--- /dev/null
+++ b/dbus/dbus/dbus-string-private.h
@@ -0,0 +1,133 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-string-private.h String utility class (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_STRING_PRIVATE_H
+#define DBUS_STRING_PRIVATE_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-memory.h>
+#include <dbus/dbus-types.h>
+
+#ifndef DBUS_CAN_USE_DBUS_STRING_PRIVATE
+#error "Don't go including dbus-string-private.h for no good reason"
+#endif
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @brief Internals of DBusString.
+ * 
+ * DBusString internals. DBusString is an opaque objects, it must be
+ * used via accessor functions.
+ */
+typedef struct
+{
+  unsigned char *str;            /**< String data, plus nul termination */
+  int            len;            /**< Length without nul */
+  int            allocated;      /**< Allocated size of data */
+  unsigned int   constant : 1;   /**< String data is not owned by DBusString */
+  unsigned int   locked : 1;     /**< DBusString has been locked and can't be changed */
+  unsigned int   invalid : 1;    /**< DBusString is invalid (e.g. already freed) */
+  unsigned int   align_offset : 3; /**< str - align_offset is the actual malloc block */
+} DBusRealString;
+
+_DBUS_STATIC_ASSERT (sizeof (DBusRealString) == sizeof (DBusString));
+
+/**
+ * @defgroup DBusStringInternals DBusString implementation details
+ * @ingroup  DBusInternals
+ * @brief DBusString implementation details
+ *
+ * The guts of DBusString.
+ *
+ * @{
+ */
+
+/**
+ * The maximum length of a DBusString
+ */
+#define _DBUS_STRING_MAX_LENGTH (_DBUS_INT32_MAX - _DBUS_STRING_ALLOCATION_PADDING)
+
+/**
+ * Checks a bunch of assertions about a string object
+ *
+ * @param real the DBusRealString
+ */
+#define DBUS_GENERIC_STRING_PREAMBLE(real) \
+  do { \
+      (void) real; /* might be unused unless asserting */ \
+      _dbus_assert ((real) != NULL); \
+      _dbus_assert (!(real)->invalid); \
+      _dbus_assert ((real)->len >= 0); \
+      _dbus_assert ((real)->allocated >= 0); \
+      _dbus_assert ((real)->len <= ((real)->allocated - _DBUS_STRING_ALLOCATION_PADDING)); \
+      _dbus_assert ((real)->len <= _DBUS_STRING_MAX_LENGTH); \
+  } while (0)
+
+/**
+ * Checks assertions about a string object that needs to be
+ * modifiable - may not be locked or const. Also declares
+ * the "real" variable pointing to DBusRealString. 
+ * @param str the string
+ */
+#define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
+  DBUS_GENERIC_STRING_PREAMBLE (real);                                          \
+  _dbus_assert (!(real)->constant);                                             \
+  _dbus_assert (!(real)->locked)
+
+/**
+ * Checks assertions about a string object that may be locked but
+ * can't be const. i.e. a string object that we can free.  Also
+ * declares the "real" variable pointing to DBusRealString.
+ *
+ * @param str the string
+ */
+#define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
+  DBUS_GENERIC_STRING_PREAMBLE (real);                                                 \
+  _dbus_assert (!(real)->constant)
+
+/**
+ * Checks assertions about a string that may be const or locked.  Also
+ * declares the "real" variable pointing to DBusRealString.
+ * @param str the string.
+ */
+#define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
+  DBUS_GENERIC_STRING_PREAMBLE (real)
+
+/**
+ * Checks for ASCII blank byte
+ * @param c the byte
+ */
+#define DBUS_IS_ASCII_BLANK(c) ((c) == ' ' || (c) == '\t')
+
+/**
+ * Checks for ASCII whitespace byte
+ * @param c the byte
+ */
+#define DBUS_IS_ASCII_WHITE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_STRING_PRIVATE_H */
diff --git a/dbus/dbus/dbus-string-util.c b/dbus/dbus/dbus-string-util.c
new file mode 100644
index 0000000..922580d
--- /dev/null
+++ b/dbus/dbus/dbus-string-util.c
@@ -0,0 +1,938 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-string-util.c Would be in dbus-string.c, but not used in libdbus
+ * 
+ * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+ * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-string.h"
+#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
+#include "dbus-string-private.h"
+
+/**
+ * @addtogroup DBusString
+ * @{
+ */
+
+/**
+ * Returns whether a string ends with the given suffix
+ *
+ * @todo memcmp might make this faster.
+ * 
+ * @param a the string
+ * @param c_str the C-style string
+ * @returns #TRUE if the string ends with the suffix
+ */
+dbus_bool_t
+_dbus_string_ends_with_c_str (const DBusString *a,
+                              const char       *c_str)
+{
+  const unsigned char *ap;
+  const unsigned char *bp;
+  const unsigned char *a_end;
+  unsigned long c_str_len;
+  const DBusRealString *real_a = (const DBusRealString*) a;
+  DBUS_GENERIC_STRING_PREAMBLE (real_a);
+  _dbus_assert (c_str != NULL);
+  
+  c_str_len = strlen (c_str);
+  if (((unsigned long)real_a->len) < c_str_len)
+    return FALSE;
+  
+  ap = real_a->str + (real_a->len - c_str_len);
+  bp = (const unsigned char*) c_str;
+  a_end = real_a->str + real_a->len;
+  while (ap != a_end)
+    {
+      if (*ap != *bp)
+        return FALSE;
+      
+      ++ap;
+      ++bp;
+    }
+
+  _dbus_assert (*ap == '\0');
+  _dbus_assert (*bp == '\0');
+  
+  return TRUE;
+}
+
+/**
+ * Find the given byte scanning backward from the given start.
+ * Sets *found to -1 if the byte is not found.
+ *
+ * @param str the string
+ * @param start the place to start scanning (will not find the byte at this point)
+ * @param byte the byte to find
+ * @param found return location for where it was found
+ * @returns #TRUE if found
+ */
+dbus_bool_t
+_dbus_string_find_byte_backward (const DBusString  *str,
+                                 int                start,
+                                 unsigned char      byte,
+                                 int               *found)
+{
+  int i;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (start >= 0);
+  _dbus_assert (found != NULL);
+
+  i = start - 1;
+  while (i >= 0)
+    {
+      if (real->str[i] == byte)
+        break;
+      
+      --i;
+    }
+
+  if (found)
+    *found = i;
+
+  return i >= 0;
+}
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+
+static void
+test_hex_roundtrip (const unsigned char *data,
+                    int                  len)
+{
+  DBusString orig;
+  DBusString encoded;
+  DBusString decoded;
+  int end;
+
+  if (len < 0)
+    len = strlen (data);
+  
+  if (!_dbus_string_init (&orig))
+    _dbus_assert_not_reached ("could not init string");
+
+  if (!_dbus_string_init (&encoded))
+    _dbus_assert_not_reached ("could not init string");
+  
+  if (!_dbus_string_init (&decoded))
+    _dbus_assert_not_reached ("could not init string");
+
+  if (!_dbus_string_append_len (&orig, data, len))
+    _dbus_assert_not_reached ("couldn't append orig data");
+
+  if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
+    _dbus_assert_not_reached ("could not encode");
+
+  if (!_dbus_string_hex_decode (&encoded, 0, &end, &decoded, 0))
+    _dbus_assert_not_reached ("could not decode");
+    
+  _dbus_assert (_dbus_string_get_length (&encoded) == end);
+
+  if (!_dbus_string_equal (&orig, &decoded))
+    {
+      const char *s;
+      
+      printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
+              _dbus_string_get_length (&orig),
+              _dbus_string_get_length (&encoded),
+              _dbus_string_get_length (&decoded));
+      printf ("Original: %s\n", data);
+      s = _dbus_string_get_const_data (&decoded);
+      printf ("Decoded: %s\n", s);
+      _dbus_assert_not_reached ("original string not the same as string decoded from hex");
+    }
+  
+  _dbus_string_free (&orig);
+  _dbus_string_free (&encoded);
+  _dbus_string_free (&decoded);  
+}
+
+typedef void (* TestRoundtripFunc) (const unsigned char *data,
+                                    int                  len);
+static void
+test_roundtrips (TestRoundtripFunc func)
+{
+  (* func) ("Hello this is a string\n", -1);
+  (* func) ("Hello this is a string\n1", -1);
+  (* func) ("Hello this is a string\n12", -1);
+  (* func) ("Hello this is a string\n123", -1);
+  (* func) ("Hello this is a string\n1234", -1);
+  (* func) ("Hello this is a string\n12345", -1);
+  (* func) ("", 0);
+  (* func) ("1", 1);
+  (* func) ("12", 2);
+  (* func) ("123", 3);
+  (* func) ("1234", 4);
+  (* func) ("12345", 5);
+  (* func) ("", 1);
+  (* func) ("1", 2);
+  (* func) ("12", 3);
+  (* func) ("123", 4);
+  (* func) ("1234", 5);
+  (* func) ("12345", 6);
+  {
+    unsigned char buf[512];
+    int i;
+    
+    i = 0;
+    while (i < _DBUS_N_ELEMENTS (buf))
+      {
+        buf[i] = i;
+        ++i;
+      }
+    i = 0;
+    while (i < _DBUS_N_ELEMENTS (buf))
+      {
+        (* func) (buf, i);
+        ++i;
+      }
+  }
+}
+
+/**
+ * @ingroup DBusStringInternals
+ * Unit test for DBusString.
+ *
+ * @todo Need to write tests for _dbus_string_copy() and
+ * _dbus_string_move() moving to/from each of start/middle/end of a
+ * string. Also need tests for _dbus_string_move_len ()
+ * 
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_string_test (void)
+{
+  DBusString str;
+  DBusString other;
+  int i, a, end;
+  long v;
+  int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 };
+  char *s;
+
+  /* Test shortening and setting length */
+  i = 0;
+  while (i < _DBUS_N_ELEMENTS (lens))
+    {
+      int j;
+      
+      if (!_dbus_string_init (&str))
+        _dbus_assert_not_reached ("failed to init string");
+
+      if (!_dbus_string_set_length (&str, lens[i]))
+        _dbus_assert_not_reached ("failed to set string length");
+
+      j = lens[i];
+      while (j > 0)
+        {
+          _dbus_assert (_dbus_string_get_length (&str) == j);
+          if (j > 0)
+            {
+              _dbus_string_shorten (&str, 1);
+              _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
+            }
+          --j;
+        }
+      
+      _dbus_string_free (&str);
+
+      ++i;
+    }
+
+  /* Test equality */
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("oom");
+
+  if (!_dbus_string_append (&str, "Hello World"))
+    _dbus_assert_not_reached ("oom");
+
+  _dbus_string_init_const (&other, "H");
+  _dbus_assert (_dbus_string_equal_substring (&str, 0, 1, &other, 0));
+  _dbus_assert (_dbus_string_equal_substring (&str, 1, 0, &other, 1));
+  _dbus_string_init_const (&other, "Hello");
+  _dbus_assert (_dbus_string_equal_substring (&str, 0, 5, &other, 0));
+  _dbus_assert (_dbus_string_equal_substring (&str, 1, 4, &other, 1));
+  _dbus_assert (_dbus_string_equal_substring (&str, 2, 3, &other, 2));
+  _dbus_assert (_dbus_string_equal_substring (&str, 3, 2, &other, 3));
+  _dbus_assert (_dbus_string_equal_substring (&str, 4, 1, &other, 4));
+  _dbus_assert (_dbus_string_equal_substring (&str, 5, 0, &other, 5));
+
+  _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 0));
+  _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 1));
+  _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 2));
+  _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 3));
+  _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 4));
+  _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 5));
+
+  
+  _dbus_string_init_const (&other, "World");
+  _dbus_assert (_dbus_string_equal_substring (&str, 6,  5, &other, 0));
+  _dbus_assert (_dbus_string_equal_substring (&str, 7,  4, &other, 1));
+  _dbus_assert (_dbus_string_equal_substring (&str, 8,  3, &other, 2));
+  _dbus_assert (_dbus_string_equal_substring (&str, 9,  2, &other, 3));
+  _dbus_assert (_dbus_string_equal_substring (&str, 10, 1, &other, 4));
+  _dbus_assert (_dbus_string_equal_substring (&str, 11, 0, &other, 5));
+
+  _dbus_assert (_dbus_string_equal_substring (&other, 0, 5, &str, 6));
+  _dbus_assert (_dbus_string_equal_substring (&other, 1, 4, &str, 7));
+  _dbus_assert (_dbus_string_equal_substring (&other, 2, 3, &str, 8));
+  _dbus_assert (_dbus_string_equal_substring (&other, 3, 2, &str, 9));
+  _dbus_assert (_dbus_string_equal_substring (&other, 4, 1, &str, 10));
+  _dbus_assert (_dbus_string_equal_substring (&other, 5, 0, &str, 11));
+  
+  _dbus_string_free (&str);
+  
+  /* Test appending data */
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("failed to init string");
+
+  i = 0;
+  while (i < 10)
+    {
+      if (!_dbus_string_append (&str, "a"))
+        _dbus_assert_not_reached ("failed to append string to string\n");
+
+      _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
+
+      if (!_dbus_string_append_byte (&str, 'b'))
+        _dbus_assert_not_reached ("failed to append byte to string\n");
+
+      _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
+                    
+      ++i;
+    }
+
+  _dbus_string_free (&str);
+
+  /* Check steal_data */
+  
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("failed to init string");
+
+  if (!_dbus_string_append (&str, "Hello World"))
+    _dbus_assert_not_reached ("could not append to string");
+
+  i = _dbus_string_get_length (&str);
+  
+  if (!_dbus_string_steal_data (&str, &s))
+    _dbus_assert_not_reached ("failed to steal data");
+
+  _dbus_assert (_dbus_string_get_length (&str) == 0);
+  _dbus_assert (((int)strlen (s)) == i);
+
+  dbus_free (s);
+
+  /* Check move */
+  
+  if (!_dbus_string_append (&str, "Hello World"))
+    _dbus_assert_not_reached ("could not append to string");
+
+  i = _dbus_string_get_length (&str);
+
+  if (!_dbus_string_init (&other))
+    _dbus_assert_not_reached ("could not init string");
+  
+  if (!_dbus_string_move (&str, 0, &other, 0))
+    _dbus_assert_not_reached ("could not move");
+
+  _dbus_assert (_dbus_string_get_length (&str) == 0);
+  _dbus_assert (_dbus_string_get_length (&other) == i);
+
+  if (!_dbus_string_append (&str, "Hello World"))
+    _dbus_assert_not_reached ("could not append to string");
+  
+  if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
+    _dbus_assert_not_reached ("could not move");
+
+  _dbus_assert (_dbus_string_get_length (&str) == 0);
+  _dbus_assert (_dbus_string_get_length (&other) == i * 2);
+
+    if (!_dbus_string_append (&str, "Hello World"))
+    _dbus_assert_not_reached ("could not append to string");
+  
+  if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
+    _dbus_assert_not_reached ("could not move");
+
+  _dbus_assert (_dbus_string_get_length (&str) == 0);
+  _dbus_assert (_dbus_string_get_length (&other) == i * 3);
+  
+  _dbus_string_free (&other);
+
+  /* Check copy */
+  
+  if (!_dbus_string_append (&str, "Hello World"))
+    _dbus_assert_not_reached ("could not append to string");
+
+  i = _dbus_string_get_length (&str);
+  
+  if (!_dbus_string_init (&other))
+    _dbus_assert_not_reached ("could not init string");
+  
+  if (!_dbus_string_copy (&str, 0, &other, 0))
+    _dbus_assert_not_reached ("could not copy");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == i);
+
+  if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
+    _dbus_assert_not_reached ("could not copy");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == i * 2);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "Hello WorldHello World"));
+
+  if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
+    _dbus_assert_not_reached ("could not copy");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == i * 3);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "Hello WorldHello WorldHello World"));
+  
+  _dbus_string_free (&str);
+  _dbus_string_free (&other);
+
+  /* Check replace */
+
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("failed to init string");
+  
+  if (!_dbus_string_append (&str, "Hello World"))
+    _dbus_assert_not_reached ("could not append to string");
+
+  i = _dbus_string_get_length (&str);
+  
+  if (!_dbus_string_init (&other))
+    _dbus_assert_not_reached ("could not init string");
+  
+  if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
+                                 &other, 0, _dbus_string_get_length (&other)))
+    _dbus_assert_not_reached ("could not replace");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == i);
+  _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
+  
+  if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
+                                 &other, 5, 1))
+    _dbus_assert_not_reached ("could not replace center space");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "HelloHello WorldWorld"));
+
+  
+  if (!_dbus_string_replace_len (&str, 1, 1,
+                                 &other,
+                                 _dbus_string_get_length (&other) - 1,
+                                 1))
+    _dbus_assert_not_reached ("could not replace end character");
+  
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "HelloHello WorldWorle"));
+
+  _dbus_string_free (&str);
+  _dbus_string_free (&other);
+
+  /* Different tests are provided because different behaviours are
+   * implemented in _dbus_string_replace_len() in function of replacing and
+   * replaced lengths
+   */
+
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("failed to init string");
+  
+  if (!_dbus_string_append (&str, "Hello World"))
+    _dbus_assert_not_reached ("could not append to string");
+
+  i = _dbus_string_get_length (&str);
+  
+  if (!_dbus_string_init (&other))
+    _dbus_assert_not_reached ("could not init string");
+
+  if (!_dbus_string_append (&other, "Foo String"))
+    _dbus_assert_not_reached ("could not append to string");
+
+  a = _dbus_string_get_length (&other);
+
+  if (!_dbus_string_replace_len (&str, 0, 6,
+                                 &other, 4, 0))
+    _dbus_assert_not_reached ("could not replace 0 length");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 6);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "Foo Hello String"));
+
+  if (!_dbus_string_replace_len (&str, 5, 6,
+                                 &other,
+                                 _dbus_string_get_length (&other),
+                                 0))
+    _dbus_assert_not_reached ("could not replace at the end");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 6 + 6);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "Foo Hello String World"));
+
+  if (!_dbus_string_replace_len (&str, 0, 5,
+                                 &other,
+                                 _dbus_string_get_length (&other) - 5,
+                                 5))
+    _dbus_assert_not_reached ("could not replace same length");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 6 + 6);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "Foo Hello String Hello"));
+
+  if (!_dbus_string_replace_len (&str, 6, 5,
+                                 &other, 4, 12))
+    _dbus_assert_not_reached ("could not replace with shorter string");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 5);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "Foo World Hello"));
+
+  if (!_dbus_string_replace_len (&str, 0, 1,
+                                 &other, 0, 3))
+    _dbus_assert_not_reached ("could not replace at the beginning");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 3);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "H World Hello"));
+
+  if (!_dbus_string_replace_len (&str, 6, 5,
+                                 &other,
+                                 _dbus_string_get_length (&other) - 5,
+                                 5))
+    _dbus_assert_not_reached ("could not replace same length");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 3);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "H World World"));
+
+  _dbus_string_free (&str);
+  _dbus_string_free (&other);
+
+  /* Check insert/set/get byte */
+  
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("failed to init string");
+
+  if (!_dbus_string_append (&str, "Hello"))
+    _dbus_assert_not_reached ("failed to append Hello");
+
+  _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
+  _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
+  _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
+  _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
+  _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
+
+  _dbus_string_set_byte (&str, 1, 'q');
+  _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
+
+  if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
+    _dbus_assert_not_reached ("can't insert byte");
+
+  if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
+    _dbus_assert_not_reached ("can't insert byte");
+
+  if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
+    _dbus_assert_not_reached ("can't insert byte");
+  
+  _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
+  _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
+  _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
+  _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
+  _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
+  _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
+  _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
+  _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
+  _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
+  _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
+  _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
+
+  _dbus_string_free (&str);
+  
+  /* Check append/parse int/double */
+  
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("failed to init string");
+
+  if (!_dbus_string_append_int (&str, 27))
+    _dbus_assert_not_reached ("failed to append int");
+
+  i = _dbus_string_get_length (&str);
+
+  if (!_dbus_string_parse_int (&str, 0, &v, &end))
+    _dbus_assert_not_reached ("failed to parse int");
+
+  _dbus_assert (v == 27);
+  _dbus_assert (end == i);
+
+  _dbus_string_free (&str);
+
+  /* Test find */
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("failed to init string");
+
+  if (!_dbus_string_append (&str, "Hello"))
+    _dbus_assert_not_reached ("couldn't append to string");
+  
+  if (!_dbus_string_find (&str, 0, "He", &i))
+    _dbus_assert_not_reached ("didn't find 'He'");
+  _dbus_assert (i == 0);
+
+  if (!_dbus_string_find (&str, 0, "Hello", &i))
+    _dbus_assert_not_reached ("didn't find 'Hello'");
+  _dbus_assert (i == 0);
+  
+  if (!_dbus_string_find (&str, 0, "ello", &i))
+    _dbus_assert_not_reached ("didn't find 'ello'");
+  _dbus_assert (i == 1);
+
+  if (!_dbus_string_find (&str, 0, "lo", &i))
+    _dbus_assert_not_reached ("didn't find 'lo'");
+  _dbus_assert (i == 3);
+
+  if (!_dbus_string_find (&str, 2, "lo", &i))
+    _dbus_assert_not_reached ("didn't find 'lo'");
+  _dbus_assert (i == 3);
+
+  if (_dbus_string_find (&str, 4, "lo", &i))
+    _dbus_assert_not_reached ("did find 'lo'");
+  
+  if (!_dbus_string_find (&str, 0, "l", &i))
+    _dbus_assert_not_reached ("didn't find 'l'");
+  _dbus_assert (i == 2);
+
+  if (!_dbus_string_find (&str, 0, "H", &i))
+    _dbus_assert_not_reached ("didn't find 'H'");
+  _dbus_assert (i == 0);
+
+  if (!_dbus_string_find (&str, 0, "", &i))
+    _dbus_assert_not_reached ("didn't find ''");
+  _dbus_assert (i == 0);
+  
+  if (_dbus_string_find (&str, 0, "Hello!", NULL))
+    _dbus_assert_not_reached ("Did find 'Hello!'");
+
+  if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
+    _dbus_assert_not_reached ("Did find 'Oh, Hello'");
+  
+  if (_dbus_string_find (&str, 0, "ill", NULL))
+    _dbus_assert_not_reached ("Did find 'ill'");
+
+  if (_dbus_string_find (&str, 0, "q", NULL))
+    _dbus_assert_not_reached ("Did find 'q'");
+
+  if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
+    _dbus_assert_not_reached ("Didn't find 'He'");
+
+  if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
+    _dbus_assert_not_reached ("Did find 'Hello'");
+
+  if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
+    _dbus_assert_not_reached ("Did not find 'H'");
+  _dbus_assert (i == 0);
+
+  if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
+    _dbus_assert_not_reached ("Did not find 'o'");
+  _dbus_assert (i == _dbus_string_get_length (&str) - 1);
+
+  if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
+    _dbus_assert_not_reached ("Did find 'o'");
+  _dbus_assert (i == -1);
+
+  if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
+    _dbus_assert_not_reached ("Did find 'e'");
+  _dbus_assert (i == -1);
+
+  if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
+    _dbus_assert_not_reached ("Didn't find 'e'");
+  _dbus_assert (i == 1);
+  
+  _dbus_string_free (&str);
+
+  /* Hex encoding */
+  _dbus_string_init_const (&str, "cafebabe, this is a bogus hex string");
+  if (!_dbus_string_init (&other))
+    _dbus_assert_not_reached ("could not init string");
+
+  if (!_dbus_string_hex_decode (&str, 0, &end, &other, 0))
+    _dbus_assert_not_reached ("deccoded bogus hex string with no error");
+
+  _dbus_assert (end == 8);
+
+  _dbus_string_free (&other);
+
+  test_roundtrips (test_hex_roundtrip);
+  
+  _dbus_string_free (&str);
+
+  {                                                                                           
+    int found, found_len;  
+
+    _dbus_string_init_const (&str, "012\r\n567\n90");
+    
+    if (!_dbus_string_find_eol (&str, 0, &found, &found_len) || found != 3 || found_len != 2)
+      _dbus_assert_not_reached ("Did not find '\\r\\n'");                                       
+    if (found != 3 || found_len != 2)                                                           
+      _dbus_assert_not_reached ("invalid return values");                                       
+    
+    if (!_dbus_string_find_eol (&str, 5, &found, &found_len))                                    
+      _dbus_assert_not_reached ("Did not find '\\n'");                                          
+    if (found != 8 || found_len != 1)                                                           
+      _dbus_assert_not_reached ("invalid return values");                                       
+    
+    if (_dbus_string_find_eol (&str, 9, &found, &found_len))                                     
+      _dbus_assert_not_reached ("Found not expected '\\n'");                                    
+    else if (found != 11 || found_len != 0)                                                     
+      _dbus_assert_not_reached ("invalid return values '\\n'");                                 
+
+    found = -1;
+    found_len = -1;
+    _dbus_string_init_const (&str, "");
+    if (_dbus_string_find_eol (&str, 0, &found, &found_len))
+      _dbus_assert_not_reached ("found an eol in an empty string");
+    _dbus_assert (found == 0);
+    _dbus_assert (found_len == 0);
+    
+    found = -1;
+    found_len = -1;
+    _dbus_string_init_const (&str, "foobar");
+    if (_dbus_string_find_eol (&str, 0, &found, &found_len))
+      _dbus_assert_not_reached ("found eol in string that lacks one");
+    _dbus_assert (found == 6);
+    _dbus_assert (found_len == 0);
+
+    found = -1;
+    found_len = -1;
+    _dbus_string_init_const (&str, "foobar\n");
+    if (!_dbus_string_find_eol (&str, 0, &found, &found_len))
+      _dbus_assert_not_reached ("did not find eol in string that has one at end");
+    _dbus_assert (found == 6);
+    _dbus_assert (found_len == 1);
+  }
+
+  {
+    DBusString line;
+
+#define FIRST_LINE "this is a line"
+#define SECOND_LINE "this is a second line"
+    /* third line is empty */
+#define THIRD_LINE ""
+#define FOURTH_LINE "this is a fourth line"
+    
+    if (!_dbus_string_init (&str))
+      _dbus_assert_not_reached ("no memory");
+
+    if (!_dbus_string_append (&str, FIRST_LINE "\n" SECOND_LINE "\r\n" THIRD_LINE "\n" FOURTH_LINE))
+      _dbus_assert_not_reached ("no memory");
+    
+    if (!_dbus_string_init (&line))
+      _dbus_assert_not_reached ("no memory");
+    
+    if (!_dbus_string_pop_line (&str, &line))
+      _dbus_assert_not_reached ("failed to pop first line");
+
+    _dbus_assert (_dbus_string_equal_c_str (&line, FIRST_LINE));
+    
+    if (!_dbus_string_pop_line (&str, &line))
+      _dbus_assert_not_reached ("failed to pop second line");
+
+    _dbus_assert (_dbus_string_equal_c_str (&line, SECOND_LINE));
+    
+    if (!_dbus_string_pop_line (&str, &line))
+      _dbus_assert_not_reached ("failed to pop third line");
+
+    _dbus_assert (_dbus_string_equal_c_str (&line, THIRD_LINE));
+    
+    if (!_dbus_string_pop_line (&str, &line))
+      _dbus_assert_not_reached ("failed to pop fourth line");
+
+    _dbus_assert (_dbus_string_equal_c_str (&line, FOURTH_LINE));
+    
+    _dbus_string_free (&str);
+    _dbus_string_free (&line);
+  }
+
+  {
+    if (!_dbus_string_init (&str))
+      _dbus_assert_not_reached ("no memory");
+
+    for (i = 0; i < 10000; i++)
+      if (!_dbus_string_append (&str, "abcdefghijklmnopqrstuvwxyz"))
+        _dbus_assert_not_reached ("no memory");
+
+    if (!_dbus_string_set_length (&str, 10))
+      _dbus_assert_not_reached ("failed to set length");
+
+    /* actually compact */
+    if (!_dbus_string_compact (&str, 2048))
+      _dbus_assert_not_reached ("failed to compact after set_length");
+
+    /* peek inside to make sure it worked */
+    if (((DBusRealString *)&str)->allocated > 30)
+      _dbus_assert_not_reached ("compacting string didn't do anything");
+
+    if (!_dbus_string_equal_c_str (&str, "abcdefghij"))
+      _dbus_assert_not_reached ("unexpected content after compact");
+
+    /* compact nothing */
+    if (!_dbus_string_compact (&str, 2048))
+      _dbus_assert_not_reached ("failed to compact 2nd time");
+
+    if (!_dbus_string_equal_c_str (&str, "abcdefghij"))
+      _dbus_assert_not_reached ("unexpected content after 2nd compact");
+
+    /* and make sure it still works...*/
+    if (!_dbus_string_append (&str, "123456"))
+      _dbus_assert_not_reached ("failed to append after compact");
+
+    if (!_dbus_string_equal_c_str (&str, "abcdefghij123456"))
+      _dbus_assert_not_reached ("unexpected content after append");
+
+    /* after growing automatically, this should do nothing */
+    if (!_dbus_string_compact (&str, 20000))
+      _dbus_assert_not_reached ("failed to compact after grow");
+
+    /* but this one will do something */
+    if (!_dbus_string_compact (&str, 0))
+      _dbus_assert_not_reached ("failed to compact after grow");
+
+    if (!_dbus_string_equal_c_str (&str, "abcdefghij123456"))
+      _dbus_assert_not_reached ("unexpected content");
+
+    if (!_dbus_string_append (&str, "!@#$%"))
+      _dbus_assert_not_reached ("failed to append after compact");
+
+    if (!_dbus_string_equal_c_str (&str, "abcdefghij123456!@#$%"))
+      _dbus_assert_not_reached ("unexpected content");
+
+    _dbus_string_free (&str);
+  }
+
+  {
+    const char two_strings[] = "one\ttwo";
+
+    if (!_dbus_string_init (&str))
+      _dbus_assert_not_reached ("no memory");
+
+    if (!_dbus_string_init (&other))
+      _dbus_assert_not_reached ("no memory");
+
+    if (!_dbus_string_append (&str, two_strings))
+      _dbus_assert_not_reached ("no memory");
+
+    if (!_dbus_string_split_on_byte (&str, '\t', &other))
+      _dbus_assert_not_reached ("no memory or delimiter not found");
+
+    if (strcmp (_dbus_string_get_data (&str), "one") != 0)
+      _dbus_assert_not_reached ("left side after split on tab is wrong");
+
+    if (strcmp (_dbus_string_get_data (&other), "two") != 0)
+      _dbus_assert_not_reached ("right side after split on tab is wrong");
+
+    _dbus_string_free (&str);
+    _dbus_string_free (&other);
+  }
+
+  {
+    const char upper_string[] = "TOUPPERSTRING";
+    const char lower_string[] = "toupperstring";
+    const char lower2_string[] = "toupperSTRING";
+
+    if (!_dbus_string_init (&str))
+      _dbus_assert_not_reached ("no memory");
+
+    if (!_dbus_string_append (&str, upper_string))
+      _dbus_assert_not_reached ("no memory");
+
+    _dbus_string_tolower_ascii (&str, 0, _dbus_string_get_length(&str));
+
+    if (!_dbus_string_equal_c_str (&str, lower_string))
+      _dbus_assert_not_reached ("_dbus_string_tolower_ascii failed");
+
+    _dbus_string_free (&str);
+
+    if (!_dbus_string_init (&str))
+      _dbus_assert_not_reached ("no memory");
+
+    if (!_dbus_string_append (&str, upper_string))
+      _dbus_assert_not_reached ("no memory");
+
+    _dbus_string_tolower_ascii (&str, 0, 7);
+
+    if (!_dbus_string_equal_c_str (&str, lower2_string))
+      _dbus_assert_not_reached ("_dbus_string_tolower_ascii failed in partial conversion");
+
+    _dbus_string_free (&str);
+  }
+
+  {
+    const char lower_string[] = "toupperstring";
+    const char upper_string[] = "TOUPPERSTRING";
+    const char upper2_string[] = "TOUPPERstring";
+
+    if (!_dbus_string_init (&str))
+      _dbus_assert_not_reached ("no memory");
+
+    if (!_dbus_string_append (&str, lower_string))
+      _dbus_assert_not_reached ("no memory");
+
+    _dbus_string_toupper_ascii (&str, 0, _dbus_string_get_length(&str));
+
+    if (!_dbus_string_equal_c_str (&str, upper_string))
+      _dbus_assert_not_reached ("_dbus_string_toupper_ascii failed");
+
+    _dbus_string_free (&str);
+
+    if (!_dbus_string_init (&str))
+      _dbus_assert_not_reached ("no memory");
+
+    if (!_dbus_string_append (&str, lower_string))
+      _dbus_assert_not_reached ("no memory");
+
+    _dbus_string_toupper_ascii (&str, 0, 7);
+
+    if (!_dbus_string_equal_c_str (&str, upper2_string))
+      _dbus_assert_not_reached ("_dbus_string_toupper_ascii failed in partial conversion");
+
+    _dbus_string_free (&str);
+  }
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-string.c b/dbus/dbus/dbus-string.c
new file mode 100644
index 0000000..9accdb1
--- /dev/null
+++ b/dbus/dbus/dbus-string.c
@@ -0,0 +1,2698 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-string.c String utility class (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+ * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-string.h"
+/* we allow a system header here, for speed/convenience */
+#include <string.h>
+/* for vsnprintf */
+#include <stdio.h>
+#define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
+#include "dbus-string-private.h"
+#include "dbus-marshal-basic.h" /* probably should be removed by moving the usage of DBUS_TYPE
+                                 * into the marshaling-related files
+                                 */
+/* for DBUS_VA_COPY */
+#include "dbus-sysdeps.h"
+
+/**
+ * @defgroup DBusString DBusString class
+ * @ingroup  DBusInternals
+ * @brief DBusString data structure for safer string handling
+ *
+ * Types and functions related to DBusString. DBusString is intended
+ * to be a string class that makes it hard to mess up security issues
+ * (and just in general harder to write buggy code).  It should be
+ * used (or extended and then used) rather than the libc stuff in
+ * string.h.  The string class is a bit inconvenient at spots because
+ * it handles out-of-memory failures and tries to be extra-robust.
+ * 
+ * A DBusString has a maximum length set at initialization time; this
+ * can be used to ensure that a buffer doesn't get too big.  The
+ * _dbus_string_lengthen() method checks for overflow, and for max
+ * length being exceeded.
+ * 
+ * Try to avoid conversion to a plain C string, i.e. add methods on
+ * the string object instead, only convert to C string when passing
+ * things out to the public API. In particular, no sprintf, strcpy,
+ * strcat, any of that should be used. The GString feature of
+ * accepting negative numbers for "length of string" is also absent,
+ * because it could keep us from detecting bogus huge lengths. i.e. if
+ * we passed in some bogus huge length it would be taken to mean
+ * "current length of string" instead of "broken crack"
+ *
+ * @todo #DBusString needs a lot of cleaning up; some of the
+ * API is no longer used, and the API is pretty inconsistent.
+ * In particular all the "append" APIs, especially those involving
+ * alignment but probably lots of them, are no longer used by the
+ * marshaling code which always does "inserts" now.
+ */
+
+/**
+ * @addtogroup DBusString
+ * @{
+ */
+
+static void
+fixup_alignment (DBusRealString *real)
+{
+  unsigned char *aligned;
+  unsigned char *real_block;
+  unsigned int old_align_offset;
+
+  /* we have to have extra space in real->allocated for the align offset and nul byte */
+  _dbus_assert (real->len <= real->allocated - _DBUS_STRING_ALLOCATION_PADDING);
+  
+  old_align_offset = real->align_offset;
+  real_block = real->str - old_align_offset;
+  
+  aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
+
+  real->align_offset = aligned - real_block;
+  real->str = aligned;
+  
+  if (old_align_offset != real->align_offset)
+    {
+      /* Here comes the suck */
+      memmove (real_block + real->align_offset,
+               real_block + old_align_offset,
+               real->len + 1);
+    }
+
+  _dbus_assert (real->align_offset < 8);
+  _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
+}
+
+static void
+undo_alignment (DBusRealString *real)
+{
+  if (real->align_offset != 0)
+    {
+      memmove (real->str - real->align_offset,
+               real->str,
+               real->len + 1);
+
+      real->str = real->str - real->align_offset;
+      real->align_offset = 0;
+    }
+}
+
+/**
+ * Initializes a string that can be up to the given allocation size
+ * before it has to realloc. The string starts life with zero length.
+ * The string must eventually be freed with _dbus_string_free().
+ * 
+ * @param str memory to hold the string
+ * @param allocate_size amount to preallocate
+ * @returns #TRUE on success, #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_string_init_preallocated (DBusString *str,
+                                int         allocate_size)
+{
+  DBusRealString *real;
+  
+  _dbus_assert (str != NULL);
+
+  _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
+  
+  real = (DBusRealString*) str;
+
+  /* It's very important not to touch anything
+   * other than real->str if we're going to fail,
+   * since we also use this function to reset
+   * an existing string, e.g. in _dbus_string_steal_data()
+   */
+  
+  real->str = dbus_malloc (_DBUS_STRING_ALLOCATION_PADDING + allocate_size);
+  if (real->str == NULL)
+    return FALSE;  
+  
+  real->allocated = _DBUS_STRING_ALLOCATION_PADDING + allocate_size;
+  real->len = 0;
+  real->str[real->len] = '\0';
+  
+  real->constant = FALSE;
+  real->locked = FALSE;
+  real->invalid = FALSE;
+  real->align_offset = 0;
+  
+  fixup_alignment (real);
+  
+  return TRUE;
+}
+
+/**
+ * Initializes a string. The string starts life with zero length.  The
+ * string must eventually be freed with _dbus_string_free().
+ * 
+ * @param str memory to hold the string
+ * @returns #TRUE on success, #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_string_init (DBusString *str)
+{
+  return _dbus_string_init_preallocated (str, 0);
+}
+
+/**
+ * Initializes a constant string. The value parameter is not copied
+ * (should be static), and the string may never be modified.
+ * It is safe but not necessary to call _dbus_string_free()
+ * on a const string. The string has a length limit of MAXINT - 8.
+ * 
+ * @param str memory to use for the string
+ * @param value a string to be stored in str (not copied!!!)
+ */
+void
+_dbus_string_init_const (DBusString *str,
+                         const char *value)
+{
+  _dbus_assert (value != NULL);
+  
+  _dbus_string_init_const_len (str, value,
+                               strlen (value));
+}
+
+/**
+ * Initializes a constant string with a length. The value parameter is
+ * not copied (should be static), and the string may never be
+ * modified.  It is safe but not necessary to call _dbus_string_free()
+ * on a const string.
+ * 
+ * @param str memory to use for the string
+ * @param value a string to be stored in str (not copied!!!)
+ * @param len the length to use
+ */
+void
+_dbus_string_init_const_len (DBusString *str,
+                             const char *value,
+                             int         len)
+{
+  DBusRealString *real;
+  
+  _dbus_assert (str != NULL);
+  _dbus_assert (len == 0 || value != NULL);
+  _dbus_assert (len <= _DBUS_STRING_MAX_LENGTH);
+  _dbus_assert (len >= 0);
+  
+  real = (DBusRealString*) str;
+  
+  real->str = (unsigned char*) value;
+  real->len = len;
+  real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
+  real->constant = TRUE;
+  real->locked = TRUE;
+  real->invalid = FALSE;
+  real->align_offset = 0;
+
+  /* We don't require const strings to be 8-byte aligned as the
+   * memory is coming from elsewhere.
+   */
+}
+
+/**
+ * Frees a string created by _dbus_string_init().
+ *
+ * @param str memory where the string is stored.
+ */
+void
+_dbus_string_free (DBusString *str)
+{
+  DBusRealString *real = (DBusRealString*) str;
+  DBUS_GENERIC_STRING_PREAMBLE (real);
+  
+  if (real->constant)
+    return;
+  dbus_free (real->str - real->align_offset);
+
+  real->invalid = TRUE;
+}
+
+static dbus_bool_t
+compact (DBusRealString *real,
+         int             max_waste)
+{
+  unsigned char *new_str;
+  int new_allocated;
+  int waste;
+
+  waste = real->allocated - (real->len + _DBUS_STRING_ALLOCATION_PADDING);
+
+  if (waste <= max_waste)
+    return TRUE;
+
+  new_allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING;
+
+  new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
+  if (_DBUS_UNLIKELY (new_str == NULL))
+    return FALSE;
+
+  real->str = new_str + real->align_offset;
+  real->allocated = new_allocated;
+  fixup_alignment (real);
+
+  return TRUE;
+}
+
+#ifdef DBUS_BUILD_TESTS
+/* Not using this feature at the moment,
+ * so marked DBUS_BUILD_TESTS-only
+ */
+/**
+ * Locks a string such that any attempts to change the string will
+ * result in aborting the program. Also, if the string is wasting a
+ * lot of memory (allocation is sufficiently larger than what the
+ * string is really using), _dbus_string_lock() will realloc the
+ * string's data to "compact" it.
+ *
+ * @param str the string to lock.
+ */
+void
+_dbus_string_lock (DBusString *str)
+{  
+  DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
+
+  real->locked = TRUE;
+
+  /* Try to realloc to avoid excess memory usage, since
+   * we know we won't change the string further
+   */
+#define MAX_WASTE 48
+  compact (real, MAX_WASTE);
+}
+#endif /* DBUS_BUILD_TESTS */
+
+static dbus_bool_t
+reallocate_for_length (DBusRealString *real,
+                       int             new_length)
+{
+  int new_allocated;
+  unsigned char *new_str;
+
+  /* at least double our old allocation to avoid O(n), avoiding
+   * overflow
+   */
+  if (real->allocated > (_DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
+    new_allocated = _DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
+  else
+    new_allocated = real->allocated * 2;
+
+  /* if you change the code just above here, run the tests without
+   * the following assert-only hack before you commit
+   */
+  /* This is keyed off asserts in addition to tests so when you
+   * disable asserts to profile, you don't get this destroyer
+   * of profiles.
+   */
+#ifdef DBUS_DISABLE_ASSERT
+#else
+#ifdef DBUS_BUILD_TESTS
+  new_allocated = 0; /* ensure a realloc every time so that we go
+                      * through all malloc failure codepaths
+                      */
+#endif /* DBUS_BUILD_TESTS */
+#endif /* !DBUS_DISABLE_ASSERT */
+
+  /* But be sure we always alloc at least space for the new length */
+  new_allocated = MAX (new_allocated,
+                       new_length + _DBUS_STRING_ALLOCATION_PADDING);
+
+  _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
+  new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
+  if (_DBUS_UNLIKELY (new_str == NULL))
+    return FALSE;
+
+  real->str = new_str + real->align_offset;
+  real->allocated = new_allocated;
+  fixup_alignment (real);
+
+  return TRUE;
+}
+
+/**
+ * Compacts the string to avoid wasted memory.  Wasted memory is
+ * memory that is allocated but not actually required to store the
+ * current length of the string.  The compact is only done if more
+ * than the given amount of memory is being wasted (otherwise the
+ * waste is ignored and the call does nothing).
+ *
+ * @param str the string
+ * @param max_waste the maximum amount of waste to ignore
+ * @returns #FALSE if the compact failed due to realloc failure
+ */
+dbus_bool_t
+_dbus_string_compact (DBusString *str,
+                      int         max_waste)
+{
+  DBUS_STRING_PREAMBLE (str);
+
+  return compact (real, max_waste);
+}
+
+static dbus_bool_t
+set_length (DBusRealString *real,
+            int             new_length)
+{
+  /* Note, we are setting the length not including nul termination */
+
+  /* exceeding max length is the same as failure to allocate memory */
+  if (_DBUS_UNLIKELY (new_length > _DBUS_STRING_MAX_LENGTH))
+    return FALSE;
+  else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
+           _DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
+    return FALSE;
+  else
+    {
+      real->len = new_length;
+      real->str[new_length] = '\0';
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
+open_gap (int             len,
+          DBusRealString *dest,
+          int             insert_at)
+{
+  if (len == 0)
+    return TRUE;
+
+  if (len > _DBUS_STRING_MAX_LENGTH - dest->len)
+    return FALSE; /* detected overflow of dest->len + len below */
+  
+  if (!set_length (dest, dest->len + len))
+    return FALSE;
+
+  memmove (dest->str + insert_at + len, 
+           dest->str + insert_at,
+           dest->len - len - insert_at);
+
+  return TRUE;
+}
+
+#ifndef _dbus_string_get_data
+/**
+ * Gets the raw character buffer from the string.  The returned buffer
+ * will be nul-terminated, but note that strings may contain binary
+ * data so there may be extra nul characters prior to the termination.
+ * This function should be little-used, extend DBusString or add
+ * stuff to dbus-sysdeps.c instead. It's an error to use this
+ * function on a const string.
+ *
+ * @param str the string
+ * @returns the data
+ */
+char*
+_dbus_string_get_data (DBusString *str)
+{
+  DBUS_STRING_PREAMBLE (str);
+  
+  return (char*) real->str;
+}
+#endif /* _dbus_string_get_data */
+
+/* only do the function if we don't have the macro */
+#ifndef _dbus_string_get_const_data
+/**
+ * Gets the raw character buffer from a const string.
+ *
+ * @param str the string
+ * @returns the string data
+ */
+const char*
+_dbus_string_get_const_data (const DBusString  *str)
+{
+  DBUS_CONST_STRING_PREAMBLE (str);
+  
+  return (const char*) real->str;
+}
+#endif /* _dbus_string_get_const_data */
+
+/**
+ * Gets a sub-portion of the raw character buffer from the
+ * string. The "len" field is required simply for error
+ * checking, to be sure you don't try to use more
+ * string than exists. The nul termination of the
+ * returned buffer remains at the end of the entire
+ * string, not at start + len.
+ *
+ * @param str the string
+ * @param start byte offset to return
+ * @param len length of segment to return
+ * @returns the string data
+ */
+char*
+_dbus_string_get_data_len (DBusString *str,
+                           int         start,
+                           int         len)
+{
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (start >= 0);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (len <= real->len - start);
+  
+  return (char*) real->str + start;
+}
+
+/* only do the function if we don't have the macro */
+#ifndef _dbus_string_get_const_data_len
+/**
+ * const version of _dbus_string_get_data_len().
+ *
+ * @param str the string
+ * @param start byte offset to return
+ * @param len length of segment to return
+ * @returns the string data
+ */
+const char*
+_dbus_string_get_const_data_len (const DBusString  *str,
+                                 int                start,
+                                 int                len)
+{
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start >= 0);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (len <= real->len - start);
+  
+  return (const char*) real->str + start;
+}
+#endif /* _dbus_string_get_const_data_len */
+
+/* only do the function if we don't have the macro */
+#ifndef _dbus_string_set_byte
+/**
+ * Sets the value of the byte at the given position.
+ *
+ * @param str the string
+ * @param i the position
+ * @param byte the new value
+ */
+void
+_dbus_string_set_byte (DBusString    *str,
+                       int            i,
+                       unsigned char  byte)
+{
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (i < real->len);
+  _dbus_assert (i >= 0);
+  
+  real->str[i] = byte;
+}
+#endif /* _dbus_string_set_byte */
+
+/* only have the function if we didn't create a macro */
+#ifndef _dbus_string_get_byte
+/**
+ * Gets the byte at the given position. It is
+ * allowed to ask for the nul byte at the end of
+ * the string.
+ *
+ * @param str the string
+ * @param start the position
+ * @returns the byte at that position
+ */
+unsigned char
+_dbus_string_get_byte (const DBusString  *str,
+                       int                start)
+{
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (start >= 0);
+  
+  return real->str[start];
+}
+#endif /* _dbus_string_get_byte */
+
+/**
+ * Inserts a number of bytes of a given value at the
+ * given position.
+ *
+ * @param str the string
+ * @param i the position
+ * @param n_bytes number of bytes
+ * @param byte the value to insert
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_string_insert_bytes (DBusString   *str,
+			   int           i,
+			   int           n_bytes,
+			   unsigned char byte)
+{
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (i <= real->len);
+  _dbus_assert (i >= 0);
+  _dbus_assert (n_bytes >= 0);
+
+  if (n_bytes == 0)
+    return TRUE;
+  
+  if (!open_gap (n_bytes, real, i))
+    return FALSE;
+  
+  memset (real->str + i, byte, n_bytes);
+
+  return TRUE;
+}
+
+/**
+ * Inserts a single byte at the given position.
+ *
+ * @param str the string
+ * @param i the position
+ * @param byte the value to insert
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_string_insert_byte (DBusString   *str,
+			   int           i,
+			   unsigned char byte)
+{
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (i <= real->len);
+  _dbus_assert (i >= 0);
+  
+  if (!open_gap (1, real, i))
+    return FALSE;
+
+  real->str[i] = byte;
+
+  return TRUE;
+}
+
+/**
+ * Like _dbus_string_get_data(), but removes the
+ * gotten data from the original string. The caller
+ * must free the data returned. This function may
+ * fail due to lack of memory, and return #FALSE.
+ *
+ * @param str the string
+ * @param data_return location to return the buffer
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_string_steal_data (DBusString        *str,
+                         char             **data_return)
+{
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (data_return != NULL);
+
+  undo_alignment (real);
+  
+  *data_return = (char*) real->str;
+
+  /* reset the string */
+  if (!_dbus_string_init (str))
+    {
+      /* hrm, put it back then */
+      real->str = (unsigned char*) *data_return;
+      *data_return = NULL;
+      fixup_alignment (real);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Copies the data from the string into a char*
+ *
+ * @param str the string
+ * @param data_return place to return the data
+ * @returns #TRUE on success, #FALSE on no memory
+ */
+dbus_bool_t
+_dbus_string_copy_data (const DBusString  *str,
+                        char             **data_return)
+{
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (data_return != NULL);
+  
+  *data_return = dbus_malloc (real->len + 1);
+  if (*data_return == NULL)
+    return FALSE;
+
+  memcpy (*data_return, real->str, real->len + 1);
+
+  return TRUE;
+}
+
+/**
+ * Copies the contents of a DBusString into a different buffer. It is
+ * a bug if avail_len is too short to hold the string contents. nul
+ * termination is not copied, just the supplied bytes.
+ * 
+ * @param str a string
+ * @param buffer a C buffer to copy data to
+ * @param avail_len maximum length of C buffer
+ */
+void
+_dbus_string_copy_to_buffer (const DBusString  *str,
+			     char              *buffer,
+			     int                avail_len)
+{
+  DBUS_CONST_STRING_PREAMBLE (str);
+
+  _dbus_assert (avail_len >= 0);
+  _dbus_assert (avail_len >= real->len);
+  
+  memcpy (buffer, real->str, real->len);
+}
+
+/**
+ * Copies the contents of a DBusString into a different buffer. It is
+ * a bug if avail_len is too short to hold the string contents plus a
+ * nul byte. 
+ * 
+ * @param str a string
+ * @param buffer a C buffer to copy data to
+ * @param avail_len maximum length of C buffer
+ */
+void
+_dbus_string_copy_to_buffer_with_nul (const DBusString  *str,
+                                      char              *buffer,
+                                      int                avail_len)
+{
+  DBUS_CONST_STRING_PREAMBLE (str);
+
+  _dbus_assert (avail_len >= 0);
+  _dbus_assert (avail_len > real->len);
+  
+  memcpy (buffer, real->str, real->len+1);
+}
+
+/* Only have the function if we don't have the macro */
+#ifndef _dbus_string_get_length
+/**
+ * Gets the length of a string (not including nul termination).
+ *
+ * @returns the length.
+ */
+int
+_dbus_string_get_length (const DBusString  *str)
+{
+  DBUS_CONST_STRING_PREAMBLE (str);
+  
+  return real->len;
+}
+#endif /* !_dbus_string_get_length */
+
+/**
+ * Makes a string longer by the given number of bytes.  Checks whether
+ * adding additional_length to the current length would overflow an
+ * integer, and checks for exceeding a string's max length.
+ * The new bytes are not initialized, other than nul-terminating
+ * the end of the string. The uninitialized bytes may contain
+ * nul bytes or other junk.
+ *
+ * @param str a string
+ * @param additional_length length to add to the string.
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_string_lengthen (DBusString *str,
+                       int         additional_length)
+{
+  DBUS_STRING_PREAMBLE (str);  
+  _dbus_assert (additional_length >= 0);
+
+  if (_DBUS_UNLIKELY (additional_length > _DBUS_STRING_MAX_LENGTH - real->len))
+    return FALSE; /* would overflow */
+  
+  return set_length (real,
+                     real->len + additional_length);
+}
+
+/**
+ * Makes a string shorter by the given number of bytes.
+ *
+ * @param str a string
+ * @param length_to_remove length to remove from the string.
+ */
+void
+_dbus_string_shorten (DBusString *str,
+                      int         length_to_remove)
+{
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (length_to_remove >= 0);
+  _dbus_assert (length_to_remove <= real->len);
+
+  set_length (real,
+              real->len - length_to_remove);
+}
+
+/**
+ * Sets the length of a string. Can be used to truncate or lengthen
+ * the string. If the string is lengthened, the function may fail and
+ * return #FALSE. Newly-added bytes are not initialized, as with
+ * _dbus_string_lengthen().
+ *
+ * @param str a string
+ * @param length new length of the string.
+ * @returns #FALSE on failure.
+ */
+dbus_bool_t
+_dbus_string_set_length (DBusString *str,
+                         int         length)
+{
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (length >= 0);
+
+  return set_length (real, length);
+}
+
+static dbus_bool_t
+align_insert_point_then_open_gap (DBusString *str,
+                                  int        *insert_at_p,
+                                  int         alignment,
+                                  int         gap_size)
+{
+  unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
+  unsigned long gap_pos;
+  int insert_at;
+  int delta;
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (alignment >= 1);
+  _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
+
+  insert_at = *insert_at_p;
+
+  _dbus_assert (insert_at <= real->len);
+  
+  gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
+  new_len = real->len + (gap_pos - insert_at) + gap_size;
+  
+  if (_DBUS_UNLIKELY (new_len > (unsigned long) _DBUS_STRING_MAX_LENGTH))
+    return FALSE;
+  
+  delta = new_len - real->len;
+  _dbus_assert (delta >= 0);
+
+  if (delta == 0) /* only happens if gap_size == 0 and insert_at is aligned already */
+    {
+      _dbus_assert (((unsigned long) *insert_at_p) == gap_pos);
+      return TRUE;
+    }
+
+  if (_DBUS_UNLIKELY (!open_gap (new_len - real->len,
+                                 real, insert_at)))
+    return FALSE;
+
+  /* nul the padding if we had to add any padding */
+  if (gap_size < delta)
+    {
+      memset (&real->str[insert_at], '\0',
+              gap_pos - insert_at);
+    }
+
+  *insert_at_p = gap_pos;
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+align_length_then_lengthen (DBusString *str,
+                            int         alignment,
+                            int         then_lengthen_by)
+{
+  int insert_at;
+
+  insert_at = _dbus_string_get_length (str);
+  
+  return align_insert_point_then_open_gap (str,
+                                           &insert_at,
+                                           alignment, then_lengthen_by);
+}
+
+/**
+ * Align the length of a string to a specific alignment (typically 4 or 8)
+ * by appending nul bytes to the string.
+ *
+ * @param str a string
+ * @param alignment the alignment
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_string_align_length (DBusString *str,
+                           int         alignment)
+{
+  return align_length_then_lengthen (str, alignment, 0);
+}
+
+/**
+ * Preallocate extra_bytes such that a future lengthening of the
+ * string by extra_bytes is guaranteed to succeed without an out of
+ * memory error.
+ *
+ * @param str a string
+ * @param extra_bytes bytes to alloc
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_string_alloc_space (DBusString        *str,
+                          int                extra_bytes)
+{
+  if (!_dbus_string_lengthen (str, extra_bytes))
+    return FALSE;
+  _dbus_string_shorten (str, extra_bytes);
+
+  return TRUE;
+}
+
+static dbus_bool_t
+append (DBusRealString *real,
+        const char     *buffer,
+        int             buffer_len)
+{
+  if (buffer_len == 0)
+    return TRUE;
+
+  if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
+    return FALSE;
+
+  memcpy (real->str + (real->len - buffer_len),
+          buffer,
+          buffer_len);
+
+  return TRUE;
+}
+
+/**
+ * Appends a nul-terminated C-style string to a DBusString.
+ *
+ * @param str the DBusString
+ * @param buffer the nul-terminated characters to append
+ * @returns #FALSE if not enough memory.
+ */
+dbus_bool_t
+_dbus_string_append (DBusString *str,
+                     const char *buffer)
+{
+  unsigned long buffer_len;
+  
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (buffer != NULL);
+  
+  buffer_len = strlen (buffer);
+  if (buffer_len > (unsigned long) _DBUS_STRING_MAX_LENGTH)
+    return FALSE;
+  
+  return append (real, buffer, buffer_len);
+}
+
+/** assign 2 bytes from one string to another */
+#define ASSIGN_2_OCTETS(p, octets) \
+  *((dbus_uint16_t*)(p)) = *((dbus_uint16_t*)(octets));
+
+/** assign 4 bytes from one string to another */
+#define ASSIGN_4_OCTETS(p, octets) \
+  *((dbus_uint32_t*)(p)) = *((dbus_uint32_t*)(octets));
+
+#ifdef DBUS_HAVE_INT64
+/** assign 8 bytes from one string to another */
+#define ASSIGN_8_OCTETS(p, octets) \
+  *((dbus_uint64_t*)(p)) = *((dbus_uint64_t*)(octets));
+#else
+/** assign 8 bytes from one string to another */
+#define ASSIGN_8_OCTETS(p, octets)              \
+do {                                            \
+  unsigned char *b;                             \
+                                                \
+  b = p;                                        \
+                                                \
+  *b++ = octets[0];                             \
+  *b++ = octets[1];                             \
+  *b++ = octets[2];                             \
+  *b++ = octets[3];                             \
+  *b++ = octets[4];                             \
+  *b++ = octets[5];                             \
+  *b++ = octets[6];                             \
+  *b++ = octets[7];                             \
+  _dbus_assert (b == p + 8);                    \
+} while (0)
+#endif /* DBUS_HAVE_INT64 */
+
+/**
+ * Inserts 2 bytes aligned on a 2 byte boundary
+ * with any alignment padding initialized to 0.
+ *
+ * @param str the DBusString
+ * @param insert_at where to insert
+ * @param octets 2 bytes to insert
+ * @returns #FALSE if not enough memory.
+ */
+dbus_bool_t
+_dbus_string_insert_2_aligned (DBusString         *str,
+                               int                 insert_at,
+                               const unsigned char octets[4])
+{
+  DBUS_STRING_PREAMBLE (str);
+  
+  if (!align_insert_point_then_open_gap (str, &insert_at, 2, 2))
+    return FALSE;
+
+  ASSIGN_2_OCTETS (real->str + insert_at, octets);
+
+  return TRUE;
+}
+
+/**
+ * Inserts 4 bytes aligned on a 4 byte boundary
+ * with any alignment padding initialized to 0.
+ *
+ * @param str the DBusString
+ * @param insert_at where to insert
+ * @param octets 4 bytes to insert
+ * @returns #FALSE if not enough memory.
+ */
+dbus_bool_t
+_dbus_string_insert_4_aligned (DBusString         *str,
+                               int                 insert_at,
+                               const unsigned char octets[4])
+{
+  DBUS_STRING_PREAMBLE (str);
+  
+  if (!align_insert_point_then_open_gap (str, &insert_at, 4, 4))
+    return FALSE;
+
+  ASSIGN_4_OCTETS (real->str + insert_at, octets);
+
+  return TRUE;
+}
+
+/**
+ * Inserts 8 bytes aligned on an 8 byte boundary
+ * with any alignment padding initialized to 0.
+ *
+ * @param str the DBusString
+ * @param insert_at where to insert
+ * @param octets 8 bytes to insert
+ * @returns #FALSE if not enough memory.
+ */
+dbus_bool_t
+_dbus_string_insert_8_aligned (DBusString         *str,
+                               int                 insert_at,
+                               const unsigned char octets[8])
+{
+  DBUS_STRING_PREAMBLE (str);
+  
+  if (!align_insert_point_then_open_gap (str, &insert_at, 8, 8))
+    return FALSE;
+
+  _dbus_assert (_DBUS_ALIGN_VALUE (insert_at, 8) == (unsigned) insert_at);
+  
+  ASSIGN_8_OCTETS (real->str + insert_at, octets);
+
+  return TRUE;
+}
+
+
+/**
+ * Inserts padding at *insert_at such to align it to the given
+ * boundary. Initializes the padding to nul bytes. Sets *insert_at
+ * to the aligned position.
+ *
+ * @param str the DBusString
+ * @param insert_at location to be aligned
+ * @param alignment alignment boundary (1, 2, 4, or 8)
+ * @returns #FALSE if not enough memory.
+ */
+dbus_bool_t
+_dbus_string_insert_alignment (DBusString        *str,
+                               int               *insert_at,
+                               int                alignment)
+{
+  DBUS_STRING_PREAMBLE (str);
+  
+  if (!align_insert_point_then_open_gap (str, insert_at, alignment, 0))
+    return FALSE;
+
+  _dbus_assert (_DBUS_ALIGN_VALUE (*insert_at, alignment) == (unsigned) *insert_at);
+
+  return TRUE;
+}
+
+/**
+ * Appends a printf-style formatted string
+ * to the #DBusString.
+ *
+ * @param str the string
+ * @param format printf format
+ * @param args variable argument list
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_string_append_printf_valist  (DBusString        *str,
+                                    const char        *format,
+                                    va_list            args)
+{
+  int len;
+  va_list args_copy;
+
+  DBUS_STRING_PREAMBLE (str);
+
+  DBUS_VA_COPY (args_copy, args);
+
+  /* Measure the message length without terminating nul */
+  len = _dbus_printf_string_upper_bound (format, args);
+
+  if (len < 0)
+    return FALSE;
+
+  if (!_dbus_string_lengthen (str, len))
+    {
+      /* don't leak the copy */
+      va_end (args_copy);
+      return FALSE;
+    }
+  
+  vsprintf ((char*) (real->str + (real->len - len)),
+            format, args_copy);
+
+  va_end (args_copy);
+
+  return TRUE;
+}
+
+/**
+ * Appends a printf-style formatted string
+ * to the #DBusString.
+ *
+ * @param str the string
+ * @param format printf format
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_string_append_printf (DBusString        *str,
+                            const char        *format,
+                            ...)
+{
+  va_list args;
+  dbus_bool_t retval;
+  
+  va_start (args, format);
+  retval = _dbus_string_append_printf_valist (str, format, args);
+  va_end (args);
+
+  return retval;
+}
+
+/**
+ * Appends block of bytes with the given length to a DBusString.
+ *
+ * @param str the DBusString
+ * @param buffer the bytes to append
+ * @param len the number of bytes to append
+ * @returns #FALSE if not enough memory.
+ */
+dbus_bool_t
+_dbus_string_append_len (DBusString *str,
+                         const char *buffer,
+                         int         len)
+{
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (buffer != NULL);
+  _dbus_assert (len >= 0);
+
+  return append (real, buffer, len);
+}
+
+/**
+ * Appends a single byte to the string, returning #FALSE
+ * if not enough memory.
+ *
+ * @param str the string
+ * @param byte the byte to append
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_string_append_byte (DBusString    *str,
+                          unsigned char  byte)
+{
+  DBUS_STRING_PREAMBLE (str);
+
+  if (!set_length (real, real->len + 1))
+    return FALSE;
+
+  real->str[real->len-1] = byte;
+
+  return TRUE;
+}
+
+static void
+delete (DBusRealString *real,
+        int             start,
+        int             len)
+{
+  if (len == 0)
+    return;
+  
+  memmove (real->str + start, real->str + start + len, real->len - (start + len));
+  real->len -= len;
+  real->str[real->len] = '\0';
+}
+
+/**
+ * Deletes a segment of a DBusString with length len starting at
+ * start. (Hint: to clear an entire string, setting length to 0
+ * with _dbus_string_set_length() is easier.)
+ *
+ * @param str the DBusString
+ * @param start where to start deleting
+ * @param len the number of bytes to delete
+ */
+void
+_dbus_string_delete (DBusString       *str,
+                     int               start,
+                     int               len)
+{
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (start >= 0);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (len <= real->len - start);
+  
+  delete (real, start, len);
+}
+
+static dbus_bool_t
+copy (DBusRealString *source,
+      int             start,
+      int             len,
+      DBusRealString *dest,
+      int             insert_at)
+{
+  if (len == 0)
+    return TRUE;
+
+  if (!open_gap (len, dest, insert_at))
+    return FALSE;
+  
+  memmove (dest->str + insert_at,
+           source->str + start,
+           len);
+
+  return TRUE;
+}
+
+/**
+ * Checks assertions for two strings we're copying a segment between,
+ * and declares real_source/real_dest variables.
+ *
+ * @param source the source string
+ * @param start the starting offset
+ * @param dest the dest string
+ * @param insert_at where the copied segment is inserted
+ */
+#define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
+  DBusRealString *real_source = (DBusRealString*) source;               \
+  DBusRealString *real_dest = (DBusRealString*) dest;                   \
+  _dbus_assert ((source) != (dest));                                    \
+  DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
+  DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
+  _dbus_assert (!real_dest->constant);                                  \
+  _dbus_assert (!real_dest->locked);                                    \
+  _dbus_assert ((start) >= 0);                                          \
+  _dbus_assert ((start) <= real_source->len);                           \
+  _dbus_assert ((insert_at) >= 0);                                      \
+  _dbus_assert ((insert_at) <= real_dest->len)
+
+/**
+ * Moves the end of one string into another string. Both strings
+ * must be initialized, valid strings.
+ *
+ * @param source the source string
+ * @param start where to chop off the source string
+ * @param dest the destination string
+ * @param insert_at where to move the chopped-off part of source string
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_string_move (DBusString       *source,
+                   int               start,
+                   DBusString       *dest,
+                   int               insert_at)
+{
+  DBusRealString *real_source = (DBusRealString*) source;
+  _dbus_assert (start <= real_source->len);
+  
+  return _dbus_string_move_len (source, start,
+                                real_source->len - start,
+                                dest, insert_at);
+}
+
+/**
+ * Like _dbus_string_move(), but does not delete the section
+ * of the source string that's copied to the dest string.
+ *
+ * @param source the source string
+ * @param start where to start copying the source string
+ * @param dest the destination string
+ * @param insert_at where to place the copied part of source string
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_string_copy (const DBusString *source,
+                   int               start,
+                   DBusString       *dest,
+                   int               insert_at)
+{
+  DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
+
+  return copy (real_source, start,
+               real_source->len - start,
+               real_dest,
+               insert_at);
+}
+
+/**
+ * Like _dbus_string_move(), but can move a segment from
+ * the middle of the source string.
+ *
+ * @param source the source string
+ * @param start first byte of source string to move
+ * @param len length of segment to move
+ * @param dest the destination string
+ * @param insert_at where to move the bytes from the source string
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_string_move_len (DBusString       *source,
+                       int               start,
+                       int               len,
+                       DBusString       *dest,
+                       int               insert_at)
+
+{
+  DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
+  _dbus_assert (len >= 0);
+  _dbus_assert ((start + len) <= real_source->len);
+
+
+  if (len == 0)
+    {
+      return TRUE;
+    }
+  else if (start == 0 &&
+           len == real_source->len &&
+           real_dest->len == 0)
+    {
+      /* Short-circuit moving an entire existing string to an empty string
+       * by just swapping the buffers.
+       */
+      /* we assume ->constant doesn't matter as you can't have
+       * a constant string involved in a move.
+       */
+#define ASSIGN_DATA(a, b) do {                  \
+        (a)->str = (b)->str;                    \
+        (a)->len = (b)->len;                    \
+        (a)->allocated = (b)->allocated;        \
+        (a)->align_offset = (b)->align_offset;  \
+      } while (0)
+      
+      DBusRealString tmp;
+
+      ASSIGN_DATA (&tmp, real_source);
+      ASSIGN_DATA (real_source, real_dest);
+      ASSIGN_DATA (real_dest, &tmp);
+
+      return TRUE;
+    }
+  else
+    {
+      if (!copy (real_source, start, len,
+                 real_dest,
+                 insert_at))
+        return FALSE;
+      
+      delete (real_source, start,
+              len);
+      
+      return TRUE;
+    }
+}
+
+/**
+ * Like _dbus_string_copy(), but can copy a segment from the middle of
+ * the source string.
+ *
+ * @param source the source string
+ * @param start where to start copying the source string
+ * @param len length of segment to copy
+ * @param dest the destination string
+ * @param insert_at where to place the copied segment of source string
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_string_copy_len (const DBusString *source,
+                       int               start,
+                       int               len,
+                       DBusString       *dest,
+                       int               insert_at)
+{
+  DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= real_source->len);
+  _dbus_assert (len <= real_source->len - start);
+  
+  return copy (real_source, start, len,
+               real_dest,
+               insert_at);
+}
+
+/**
+ * Replaces a segment of dest string with a segment of source string.
+ *
+ * @param source the source string
+ * @param start where to start copying the source string
+ * @param len length of segment to copy
+ * @param dest the destination string
+ * @param replace_at start of segment of dest string to replace
+ * @param replace_len length of segment of dest string to replace
+ * @returns #FALSE if not enough memory
+ *
+ */
+dbus_bool_t
+_dbus_string_replace_len (const DBusString *source,
+                          int               start,
+                          int               len,
+                          DBusString       *dest,
+                          int               replace_at,
+                          int               replace_len)
+{
+  DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= real_source->len);
+  _dbus_assert (len <= real_source->len - start);
+  _dbus_assert (replace_at >= 0);
+  _dbus_assert (replace_at <= real_dest->len);
+  _dbus_assert (replace_len <= real_dest->len - replace_at);
+
+  if (len == replace_len)
+    {
+      memmove (real_dest->str + replace_at,
+               real_source->str + start, len);
+    }
+  else if (len < replace_len)
+    {
+      memmove (real_dest->str + replace_at,
+               real_source->str + start, len);
+      delete (real_dest, replace_at + len,
+              replace_len - len);
+    }
+  else
+    {
+      int diff;
+
+      _dbus_assert (len > replace_len);
+
+      diff = len - replace_len;
+
+      /* First of all we check if destination string can be enlarged as
+       * required, then we overwrite previous bytes
+       */
+
+      if (!copy (real_source, start + replace_len, diff,
+                 real_dest, replace_at + replace_len))
+        return FALSE;
+
+      memmove (real_dest->str + replace_at,
+               real_source->str + start, replace_len);
+    }
+
+  return TRUE;
+}
+
+/**
+ * Looks for the first occurance of a byte, deletes that byte,
+ * and moves everything after the byte to the beginning of a
+ * separate string.  Both strings must be initialized, valid
+ * strings.
+ *
+ * @param source the source string
+ * @param byte the byte to remove and split the string at
+ * @param tail the split off string
+ * @returns #FALSE if not enough memory or if byte could not be found
+ *
+ */
+dbus_bool_t
+_dbus_string_split_on_byte (DBusString        *source,
+                            unsigned char      byte,
+                            DBusString        *tail)
+{
+  int byte_position;
+  char byte_string[2] = "";
+  int head_length;
+  int tail_length;
+
+  byte_string[0] = (char) byte;
+
+  if (!_dbus_string_find (source, 0, byte_string, &byte_position))
+    return FALSE;
+
+  head_length = byte_position;
+  tail_length = _dbus_string_get_length (source) - head_length - 1;
+
+  if (!_dbus_string_move_len (source, byte_position + 1, tail_length,
+                              tail, 0))
+    return FALSE;
+
+  /* remove the trailing delimiter byte from the head now.
+   */
+  if (!_dbus_string_set_length (source, head_length))
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
+ * Pennington, and Tom Tromey are the authors and authorized relicense.
+ */
+
+/** computes length and mask of a unicode character
+ * @param Char the char
+ * @param Mask the mask variable to assign to
+ * @param Len the length variable to assign to
+ */
+#define UTF8_COMPUTE(Char, Mask, Len)					      \
+  if (Char < 128)							      \
+    {									      \
+      Len = 1;								      \
+      Mask = 0x7f;							      \
+    }									      \
+  else if ((Char & 0xe0) == 0xc0)					      \
+    {									      \
+      Len = 2;								      \
+      Mask = 0x1f;							      \
+    }									      \
+  else if ((Char & 0xf0) == 0xe0)					      \
+    {									      \
+      Len = 3;								      \
+      Mask = 0x0f;							      \
+    }									      \
+  else if ((Char & 0xf8) == 0xf0)					      \
+    {									      \
+      Len = 4;								      \
+      Mask = 0x07;							      \
+    }									      \
+  else if ((Char & 0xfc) == 0xf8)					      \
+    {									      \
+      Len = 5;								      \
+      Mask = 0x03;							      \
+    }									      \
+  else if ((Char & 0xfe) == 0xfc)					      \
+    {									      \
+      Len = 6;								      \
+      Mask = 0x01;							      \
+    }									      \
+  else                                                                        \
+    {                                                                         \
+      Len = 0;                                                               \
+      Mask = 0;                                                               \
+    }
+
+/**
+ * computes length of a unicode character in UTF-8
+ * @param Char the char
+ */
+#define UTF8_LENGTH(Char)              \
+  ((Char) < 0x80 ? 1 :                 \
+   ((Char) < 0x800 ? 2 :               \
+    ((Char) < 0x10000 ? 3 :            \
+     ((Char) < 0x200000 ? 4 :          \
+      ((Char) < 0x4000000 ? 5 : 6)))))
+   
+/**
+ * Gets a UTF-8 value.
+ *
+ * @param Result variable for extracted unicode char.
+ * @param Chars the bytes to decode
+ * @param Count counter variable
+ * @param Mask mask for this char
+ * @param Len length for this char in bytes
+ */
+#define UTF8_GET(Result, Chars, Count, Mask, Len)			      \
+  (Result) = (Chars)[0] & (Mask);					      \
+  for ((Count) = 1; (Count) < (Len); ++(Count))				      \
+    {									      \
+      if (((Chars)[(Count)] & 0xc0) != 0x80)				      \
+	{								      \
+	  (Result) = -1;						      \
+	  break;							      \
+	}								      \
+      (Result) <<= 6;							      \
+      (Result) |= ((Chars)[(Count)] & 0x3f);				      \
+    }
+
+/**
+ * Check whether a Unicode (5.2) char is in a valid range.
+ *
+ * The first check comes from the Unicode guarantee to never encode
+ * a point above 0x0010ffff, since UTF-16 couldn't represent it.
+ *
+ * The second check covers surrogate pairs (category Cs).
+ *
+ * The last two checks cover "Noncharacter": defined as:
+ *   "A code point that is permanently reserved for
+ *    internal use, and that should never be interchanged. In
+ *    Unicode 3.1, these consist of the values U+nFFFE and U+nFFFF
+ *    (where n is from 0 to 10_16) and the values U+FDD0..U+FDEF."
+ *
+ * @param Char the character
+ */
+#define UNICODE_VALID(Char)                   \
+    ((Char) < 0x110000 &&                     \
+     (((Char) & 0xFFFFF800) != 0xD800) &&     \
+     ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
+     ((Char) & 0xFFFE) != 0xFFFE)
+
+/**
+ * Finds the given substring in the string,
+ * returning #TRUE and filling in the byte index
+ * where the substring was found, if it was found.
+ * Returns #FALSE if the substring wasn't found.
+ * Sets *start to the length of the string if the substring
+ * is not found.
+ *
+ * @param str the string
+ * @param start where to start looking
+ * @param substr the substring
+ * @param found return location for where it was found, or #NULL
+ * @returns #TRUE if found
+ */
+dbus_bool_t
+_dbus_string_find (const DBusString *str,
+                   int               start,
+                   const char       *substr,
+                   int              *found)
+{
+  return _dbus_string_find_to (str, start,
+                               ((const DBusRealString*)str)->len,
+                               substr, found);
+}
+
+/**
+ * Finds end of line ("\r\n" or "\n") in the string,
+ * returning #TRUE and filling in the byte index
+ * where the eol string was found, if it was found.
+ * Returns #FALSE if eol wasn't found.
+ *
+ * @param str the string
+ * @param start where to start looking
+ * @param found return location for where eol was found or string length otherwise
+ * @param found_len return length of found eol string or zero otherwise
+ * @returns #TRUE if found
+ */
+dbus_bool_t
+_dbus_string_find_eol (const DBusString *str,
+                       int               start,
+                       int              *found,
+                       int              *found_len)
+{
+  int i;
+
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (start >= 0);
+  
+  i = start;
+  while (i < real->len)
+    {
+      if (real->str[i] == '\r') 
+        {
+          if ((i+1) < real->len && real->str[i+1] == '\n') /* "\r\n" */
+            {
+              if (found) 
+                *found = i;
+              if (found_len)
+                *found_len = 2;
+              return TRUE;
+            } 
+          else /* only "\r" */
+            {
+              if (found) 
+                *found = i;
+              if (found_len)
+                *found_len = 1;
+              return TRUE;
+            }
+        } 
+      else if (real->str[i] == '\n')  /* only "\n" */
+        {
+          if (found) 
+            *found = i;
+          if (found_len)
+            *found_len = 1;
+          return TRUE;
+        }
+      ++i;
+    }
+
+  if (found)
+    *found = real->len;
+
+  if (found_len)
+    *found_len = 0;
+  
+  return FALSE;
+}
+
+/**
+ * Finds the given substring in the string,
+ * up to a certain position,
+ * returning #TRUE and filling in the byte index
+ * where the substring was found, if it was found.
+ * Returns #FALSE if the substring wasn't found.
+ * Sets *start to the length of the string if the substring
+ * is not found.
+ *
+ * @param str the string
+ * @param start where to start looking
+ * @param end where to stop looking
+ * @param substr the substring
+ * @param found return location for where it was found, or #NULL
+ * @returns #TRUE if found
+ */
+dbus_bool_t
+_dbus_string_find_to (const DBusString *str,
+		      int               start,
+		      int               end,
+		      const char       *substr,
+		      int              *found)
+{
+  int i;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (substr != NULL);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (start >= 0);
+  _dbus_assert (substr != NULL);
+  _dbus_assert (end <= real->len);
+  _dbus_assert (start <= end);
+
+  /* we always "find" an empty string */
+  if (*substr == '\0')
+    {
+      if (found)
+        *found = start;
+      return TRUE;
+    }
+
+  i = start;
+  while (i < end)
+    {
+      if (real->str[i] == substr[0])
+        {
+          int j = i + 1;
+          
+          while (j < end)
+            {
+              if (substr[j - i] == '\0')
+                break;
+              else if (real->str[j] != substr[j - i])
+                break;
+              
+              ++j;
+            }
+
+          if (substr[j - i] == '\0')
+            {
+              if (found)
+                *found = i;
+              return TRUE;
+            }
+        }
+      
+      ++i;
+    }
+
+  if (found)
+    *found = end;
+  
+  return FALSE;  
+}
+
+/**
+ * Finds a blank (space or tab) in the string. Returns #TRUE
+ * if found, #FALSE otherwise. If a blank is not found sets
+ * *found to the length of the string.
+ *
+ * @param str the string
+ * @param start byte index to start looking
+ * @param found place to store the location of the first blank
+ * @returns #TRUE if a blank was found
+ */
+dbus_bool_t
+_dbus_string_find_blank (const DBusString *str,
+                         int               start,
+                         int              *found)
+{
+  int i;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (start >= 0);
+  
+  i = start;
+  while (i < real->len)
+    {
+      if (real->str[i] == ' ' ||
+          real->str[i] == '\t')
+        {
+          if (found)
+            *found = i;
+          return TRUE;
+        }
+      
+      ++i;
+    }
+
+  if (found)
+    *found = real->len;
+  
+  return FALSE;
+}
+
+/**
+ * Skips blanks from start, storing the first non-blank in *end
+ * (blank is space or tab).
+ *
+ * @param str the string
+ * @param start where to start
+ * @param end where to store the first non-blank byte index
+ */
+void
+_dbus_string_skip_blank (const DBusString *str,
+                         int               start,
+                         int              *end)
+{
+  int i;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (start >= 0);
+  
+  i = start;
+  while (i < real->len)
+    {
+      if (!DBUS_IS_ASCII_BLANK (real->str[i]))
+        break;
+      
+      ++i;
+    }
+
+  _dbus_assert (i == real->len || !DBUS_IS_ASCII_WHITE (real->str[i]));
+  
+  if (end)
+    *end = i;
+}
+
+
+/**
+ * Skips whitespace from start, storing the first non-whitespace in *end.
+ * (whitespace is space, tab, newline, CR).
+ *
+ * @param str the string
+ * @param start where to start
+ * @param end where to store the first non-whitespace byte index
+ */
+void
+_dbus_string_skip_white (const DBusString *str,
+                         int               start,
+                         int              *end)
+{
+  int i;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (start >= 0);
+  
+  i = start;
+  while (i < real->len)
+    {
+      if (!DBUS_IS_ASCII_WHITE (real->str[i]))
+        break;
+      
+      ++i;
+    }
+
+  _dbus_assert (i == real->len || !(DBUS_IS_ASCII_WHITE (real->str[i])));
+  
+  if (end)
+    *end = i;
+}
+
+/**
+ * Skips whitespace from end, storing the start index of the trailing
+ * whitespace in *start. (whitespace is space, tab, newline, CR).
+ *
+ * @param str the string
+ * @param end where to start scanning backward
+ * @param start where to store the start of whitespace chars
+ */
+void
+_dbus_string_skip_white_reverse (const DBusString *str,
+                                 int               end,
+                                 int              *start)
+{
+  int i;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (end <= real->len);
+  _dbus_assert (end >= 0);
+  
+  i = end;
+  while (i > 0)
+    {
+      if (!DBUS_IS_ASCII_WHITE (real->str[i-1]))
+        break;
+      --i;
+    }
+
+  _dbus_assert (i >= 0 && (i == 0 || !(DBUS_IS_ASCII_WHITE (real->str[i-1]))));
+  
+  if (start)
+    *start = i;
+}
+
+/**
+ * Assigns a newline-terminated or \\r\\n-terminated line from the front
+ * of the string to the given dest string. The dest string's previous
+ * contents are deleted. If the source string contains no newline,
+ * moves the entire source string to the dest string.
+ *
+ * @todo owen correctly notes that this is a stupid function (it was
+ * written purely for test code,
+ * e.g. dbus-message-builder.c). Probably should be enforced as test
+ * code only with ifdef DBUS_BUILD_TESTS
+ * 
+ * @param source the source string
+ * @param dest the destination string (contents are replaced)
+ * @returns #FALSE if no memory, or source has length 0
+ */
+dbus_bool_t
+_dbus_string_pop_line (DBusString *source,
+                       DBusString *dest)
+{
+  int eol, eol_len;
+  
+  _dbus_string_set_length (dest, 0);
+  
+  eol = 0;
+  eol_len = 0;
+  if (!_dbus_string_find_eol (source, 0, &eol, &eol_len))
+    {
+      _dbus_assert (eol == _dbus_string_get_length (source));
+      if (eol == 0)
+        {
+          /* If there's no newline and source has zero length, we're done */
+          return FALSE;
+        }
+      /* otherwise, the last line of the file has no eol characters */
+    }
+
+  /* remember eol can be 0 if it's an empty line, but eol_len should not be zero also
+   * since find_eol returned TRUE
+   */
+  
+  if (!_dbus_string_move_len (source, 0, eol + eol_len, dest, 0))
+    return FALSE;
+  
+  /* remove line ending */
+  if (!_dbus_string_set_length (dest, eol))
+    {
+      _dbus_assert_not_reached ("out of memory when shortening a string");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+#ifdef DBUS_BUILD_TESTS
+/**
+ * Deletes up to and including the first blank space
+ * in the string.
+ *
+ * @param str the string
+ */
+void
+_dbus_string_delete_first_word (DBusString *str)
+{
+  int i;
+  
+  if (_dbus_string_find_blank (str, 0, &i))
+    _dbus_string_skip_blank (str, i, &i);
+
+  _dbus_string_delete (str, 0, i);
+}
+#endif
+
+#ifdef DBUS_BUILD_TESTS
+/**
+ * Deletes any leading blanks in the string
+ *
+ * @param str the string
+ */
+void
+_dbus_string_delete_leading_blanks (DBusString *str)
+{
+  int i;
+  
+  _dbus_string_skip_blank (str, 0, &i);
+
+  if (i > 0)
+    _dbus_string_delete (str, 0, i);
+}
+#endif
+
+/**
+ * Deletes leading and trailing whitespace
+ * 
+ * @param str the string
+ */
+void
+_dbus_string_chop_white(DBusString *str)
+{
+  int i;
+  
+  _dbus_string_skip_white (str, 0, &i);
+
+  if (i > 0)
+    _dbus_string_delete (str, 0, i);
+  
+  _dbus_string_skip_white_reverse (str, _dbus_string_get_length (str), &i);
+
+  _dbus_string_set_length (str, i);
+}
+
+/**
+ * Tests two DBusString for equality.
+ *
+ * @todo memcmp is probably faster
+ *
+ * @param a first string
+ * @param b second string
+ * @returns #TRUE if equal
+ */
+dbus_bool_t
+_dbus_string_equal (const DBusString *a,
+                    const DBusString *b)
+{
+  const unsigned char *ap;
+  const unsigned char *bp;
+  const unsigned char *a_end;
+  const DBusRealString *real_a = (const DBusRealString*) a;
+  const DBusRealString *real_b = (const DBusRealString*) b;
+  DBUS_GENERIC_STRING_PREAMBLE (real_a);
+  DBUS_GENERIC_STRING_PREAMBLE (real_b);
+
+  if (real_a->len != real_b->len)
+    return FALSE;
+
+  ap = real_a->str;
+  bp = real_b->str;
+  a_end = real_a->str + real_a->len;
+  while (ap != a_end)
+    {
+      if (*ap != *bp)
+        return FALSE;
+      
+      ++ap;
+      ++bp;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Tests two DBusString for equality up to the given length.
+ * The strings may be shorter than the given length.
+ *
+ * @todo write a unit test
+ *
+ * @todo memcmp is probably faster
+ *
+ * @param a first string
+ * @param b second string
+ * @param len the maximum length to look at
+ * @returns #TRUE if equal for the given number of bytes
+ */
+dbus_bool_t
+_dbus_string_equal_len (const DBusString *a,
+                        const DBusString *b,
+                        int               len)
+{
+  const unsigned char *ap;
+  const unsigned char *bp;
+  const unsigned char *a_end;
+  const DBusRealString *real_a = (const DBusRealString*) a;
+  const DBusRealString *real_b = (const DBusRealString*) b;
+  DBUS_GENERIC_STRING_PREAMBLE (real_a);
+  DBUS_GENERIC_STRING_PREAMBLE (real_b);
+
+  if (real_a->len != real_b->len &&
+      (real_a->len < len || real_b->len < len))
+    return FALSE;
+
+  ap = real_a->str;
+  bp = real_b->str;
+  a_end = real_a->str + MIN (real_a->len, len);
+  while (ap != a_end)
+    {
+      if (*ap != *bp)
+        return FALSE;
+      
+      ++ap;
+      ++bp;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Tests two sub-parts of two DBusString for equality.  The specified
+ * range of the first string must exist; the specified start position
+ * of the second string must exist.
+ *
+ * @todo write a unit test
+ *
+ * @todo memcmp is probably faster
+ *
+ * @param a first string
+ * @param a_start where to start substring in first string
+ * @param a_len length of substring in first string
+ * @param b second string
+ * @param b_start where to start substring in second string
+ * @returns #TRUE if the two substrings are equal
+ */
+dbus_bool_t
+_dbus_string_equal_substring (const DBusString  *a,
+                              int                a_start,
+                              int                a_len,
+                              const DBusString  *b,
+                              int                b_start)
+{
+  const unsigned char *ap;
+  const unsigned char *bp;
+  const unsigned char *a_end;
+  const DBusRealString *real_a = (const DBusRealString*) a;
+  const DBusRealString *real_b = (const DBusRealString*) b;
+  DBUS_GENERIC_STRING_PREAMBLE (real_a);
+  DBUS_GENERIC_STRING_PREAMBLE (real_b);
+  _dbus_assert (a_start >= 0);
+  _dbus_assert (a_len >= 0);
+  _dbus_assert (a_start <= real_a->len);
+  _dbus_assert (a_len <= real_a->len - a_start);
+  _dbus_assert (b_start >= 0);
+  _dbus_assert (b_start <= real_b->len);
+  
+  if (a_len > real_b->len - b_start)
+    return FALSE;
+
+  ap = real_a->str + a_start;
+  bp = real_b->str + b_start;
+  a_end = ap + a_len;
+  while (ap != a_end)
+    {
+      if (*ap != *bp)
+        return FALSE;
+      
+      ++ap;
+      ++bp;
+    }
+
+  _dbus_assert (bp <= (real_b->str + real_b->len));
+  
+  return TRUE;
+}
+
+/**
+ * Checks whether a string is equal to a C string.
+ *
+ * @param a the string
+ * @param c_str the C string
+ * @returns #TRUE if equal
+ */
+dbus_bool_t
+_dbus_string_equal_c_str (const DBusString *a,
+                          const char       *c_str)
+{
+  const unsigned char *ap;
+  const unsigned char *bp;
+  const unsigned char *a_end;
+  const DBusRealString *real_a = (const DBusRealString*) a;
+  DBUS_GENERIC_STRING_PREAMBLE (real_a);
+  _dbus_assert (c_str != NULL);
+  
+  ap = real_a->str;
+  bp = (const unsigned char*) c_str;
+  a_end = real_a->str + real_a->len;
+  while (ap != a_end && *bp)
+    {
+      if (*ap != *bp)
+        return FALSE;
+      
+      ++ap;
+      ++bp;
+    }
+
+  if (ap != a_end || *bp)
+    return FALSE;
+  
+  return TRUE;
+}
+
+/**
+ * Checks whether a string starts with the given C string.
+ *
+ * @param a the string
+ * @param c_str the C string
+ * @returns #TRUE if string starts with it
+ */
+dbus_bool_t
+_dbus_string_starts_with_c_str (const DBusString *a,
+                                const char       *c_str)
+{
+  const unsigned char *ap;
+  const unsigned char *bp;
+  const unsigned char *a_end;
+  const DBusRealString *real_a = (const DBusRealString*) a;
+  DBUS_GENERIC_STRING_PREAMBLE (real_a);
+  _dbus_assert (c_str != NULL);
+  
+  ap = real_a->str;
+  bp = (const unsigned char*) c_str;
+  a_end = real_a->str + real_a->len;
+  while (ap != a_end && *bp)
+    {
+      if (*ap != *bp)
+        return FALSE;
+      
+      ++ap;
+      ++bp;
+    }
+
+  if (*bp == '\0')
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/**
+ * Appends a two-character hex digit to a string, where the hex digit
+ * has the value of the given byte.
+ *
+ * @param str the string
+ * @param byte the byte
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_string_append_byte_as_hex (DBusString *str,
+                                 int         byte)
+{
+  const char hexdigits[16] = {
+    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+    'a', 'b', 'c', 'd', 'e', 'f'
+  };
+
+  if (!_dbus_string_append_byte (str,
+                                 hexdigits[(byte >> 4)]))
+    return FALSE;
+  
+  if (!_dbus_string_append_byte (str,
+                                 hexdigits[(byte & 0x0f)]))
+    {
+      _dbus_string_set_length (str,
+                               _dbus_string_get_length (str) - 1);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Encodes a string in hex, the way MD5 and SHA-1 are usually
+ * encoded. (Each byte is two hex digits.)
+ *
+ * @param source the string to encode
+ * @param start byte index to start encoding
+ * @param dest string where encoded data should be placed
+ * @param insert_at where to place encoded data
+ * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
+ */
+dbus_bool_t
+_dbus_string_hex_encode (const DBusString *source,
+                         int               start,
+                         DBusString       *dest,
+                         int               insert_at)
+{
+  DBusString result;
+  const unsigned char *p;
+  const unsigned char *end;
+  dbus_bool_t retval;
+  
+  _dbus_assert (start <= _dbus_string_get_length (source));
+
+  if (!_dbus_string_init (&result))
+    return FALSE;
+
+  retval = FALSE;
+  
+  p = (const unsigned char*) _dbus_string_get_const_data (source);
+  end = p + _dbus_string_get_length (source);
+  p += start;
+  
+  while (p != end)
+    {
+      if (!_dbus_string_append_byte_as_hex (&result, *p))
+        goto out;
+      
+      ++p;
+    }
+
+  if (!_dbus_string_move (&result, 0, dest, insert_at))
+    goto out;
+
+  retval = TRUE;
+
+ out:
+  _dbus_string_free (&result);
+  return retval;
+}
+
+/**
+ * Decodes a string from hex encoding.
+ *
+ * @param source the string to decode
+ * @param start byte index to start decode
+ * @param end_return return location of the end of the hex data, or #NULL
+ * @param dest string where decoded data should be placed
+ * @param insert_at where to place decoded data
+ * @returns #TRUE if decoding was successful, #FALSE if no memory.
+ */
+dbus_bool_t
+_dbus_string_hex_decode (const DBusString *source,
+                         int               start,
+			 int              *end_return,
+                         DBusString       *dest,
+                         int               insert_at)
+{
+  DBusString result;
+  const unsigned char *p;
+  const unsigned char *end;
+  dbus_bool_t retval;
+  dbus_bool_t high_bits;
+  
+  _dbus_assert (start <= _dbus_string_get_length (source));
+
+  if (!_dbus_string_init (&result))
+    return FALSE;
+
+  retval = FALSE;
+
+  high_bits = TRUE;
+  p = (const unsigned char*) _dbus_string_get_const_data (source);
+  end = p + _dbus_string_get_length (source);
+  p += start;
+  
+  while (p != end)
+    {
+      unsigned int val;
+
+      switch (*p)
+        {
+        case '0':
+          val = 0;
+          break;
+        case '1':
+          val = 1;
+          break;
+        case '2':
+          val = 2;
+          break;
+        case '3':
+          val = 3;
+          break;
+        case '4':
+          val = 4;
+          break;
+        case '5':
+          val = 5;
+          break;
+        case '6':
+          val = 6;
+          break;
+        case '7':
+          val = 7;
+          break;
+        case '8':
+          val = 8;
+          break;
+        case '9':
+          val = 9;
+          break;
+        case 'a':
+        case 'A':
+          val = 10;
+          break;
+        case 'b':
+        case 'B':
+          val = 11;
+          break;
+        case 'c':
+        case 'C':
+          val = 12;
+          break;
+        case 'd':
+        case 'D':
+          val = 13;
+          break;
+        case 'e':
+        case 'E':
+          val = 14;
+          break;
+        case 'f':
+        case 'F':
+          val = 15;
+          break;
+        default:
+          goto done;
+        }
+
+      if (high_bits)
+        {
+          if (!_dbus_string_append_byte (&result,
+                                         val << 4))
+	    goto out;
+        }
+      else
+        {
+          int len;
+          unsigned char b;
+
+          len = _dbus_string_get_length (&result);
+          
+          b = _dbus_string_get_byte (&result, len - 1);
+
+          b |= val;
+
+          _dbus_string_set_byte (&result, len - 1, b);
+        }
+
+      high_bits = !high_bits;
+
+      ++p;
+    }
+
+ done:
+  if (!_dbus_string_move (&result, 0, dest, insert_at))
+    goto out;
+
+  if (end_return)
+    *end_return = p - (const unsigned char*) _dbus_string_get_const_data (source);
+
+  retval = TRUE;
+  
+ out:
+  _dbus_string_free (&result);  
+  return retval;
+}
+
+/**
+ * Checks that the given range of the string is valid ASCII with no
+ * nul bytes. If the given range is not entirely contained in the
+ * string, returns #FALSE.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ * 
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is all valid ASCII
+ */
+dbus_bool_t
+_dbus_string_validate_ascii (const DBusString *str,
+                             int               start,
+                             int               len)
+{
+  const unsigned char *s;
+  const unsigned char *end;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start >= 0);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (len >= 0);
+  
+  if (len > real->len - start)
+    return FALSE;
+  
+  s = real->str + start;
+  end = s + len;
+  while (s != end)
+    {
+      if (_DBUS_UNLIKELY (!_DBUS_ISASCII (*s)))
+        return FALSE;
+        
+      ++s;
+    }
+  
+  return TRUE;
+}
+
+/**
+ * Converts the given range of the string to lower case.
+ *
+ * @param str the string
+ * @param start first byte index to convert
+ * @param len number of bytes to convert
+ */
+void
+_dbus_string_tolower_ascii (const DBusString *str,
+                            int               start,
+                            int               len)
+{
+  unsigned char *s;
+  unsigned char *end;
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (start >= 0);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (len >= 0);
+  _dbus_assert (len <= real->len - start);
+
+  s = real->str + start;
+  end = s + len;
+
+  while (s != end)
+    {
+      if (*s >= 'A' && *s <= 'Z')
+          *s += 'a' - 'A';
+      ++s;
+    }
+}
+
+/**
+ * Converts the given range of the string to upper case.
+ *
+ * @param str the string
+ * @param start first byte index to convert
+ * @param len number of bytes to convert
+ */
+void
+_dbus_string_toupper_ascii (const DBusString *str,
+                            int               start,
+                            int               len)
+{
+  unsigned char *s;
+  unsigned char *end;
+  DBUS_STRING_PREAMBLE (str);
+  _dbus_assert (start >= 0);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (len >= 0);
+  _dbus_assert (len <= real->len - start);
+
+  s = real->str + start;
+  end = s + len;
+
+  while (s != end)
+    {
+      if (*s >= 'a' && *s <= 'z')
+          *s += 'A' - 'a';
+      ++s;
+    }
+}
+
+/**
+ * Checks that the given range of the string is valid UTF-8. If the
+ * given range is not entirely contained in the string, returns
+ * #FALSE. If the string contains any nul bytes in the given range,
+ * returns #FALSE. If the start and start+len are not on character
+ * boundaries, returns #FALSE.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ * 
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is all valid UTF-8
+ */
+dbus_bool_t
+_dbus_string_validate_utf8  (const DBusString *str,
+                             int               start,
+                             int               len)
+{
+  const unsigned char *p;
+  const unsigned char *end;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start >= 0);
+  _dbus_assert (start <= real->len);
+  _dbus_assert (len >= 0);
+
+  /* we are doing _DBUS_UNLIKELY() here which might be
+   * dubious in a generic library like GLib, but in D-Bus
+   * we know we're validating messages and that it would
+   * only be evil/broken apps that would have invalid
+   * UTF-8. Also, this function seems to be a performance
+   * bottleneck in profiles.
+   */
+  
+  if (_DBUS_UNLIKELY (len > real->len - start))
+    return FALSE;
+  
+  p = real->str + start;
+  end = p + len;
+  
+  while (p < end)
+    {
+      int i, mask, char_len;
+      dbus_unichar_t result;
+
+      /* nul bytes considered invalid */
+      if (*p == '\0')
+        break;
+      
+      /* Special-case ASCII; this makes us go a lot faster in
+       * D-Bus profiles where we are typically validating
+       * function names and such. We have to know that
+       * all following checks will pass for ASCII though,
+       * comments follow ...
+       */      
+      if (*p < 128)
+        {
+          ++p;
+          continue;
+        }
+      
+      UTF8_COMPUTE (*p, mask, char_len);
+
+      if (_DBUS_UNLIKELY (char_len == 0))  /* ASCII: char_len == 1 */
+        break;
+
+      /* check that the expected number of bytes exists in the remaining length */
+      if (_DBUS_UNLIKELY ((end - p) < char_len)) /* ASCII: p < end and char_len == 1 */
+        break;
+        
+      UTF8_GET (result, p, i, mask, char_len);
+
+      /* Check for overlong UTF-8 */
+      if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* ASCII: UTF8_LENGTH == 1 */
+        break;
+#if 0
+      /* The UNICODE_VALID check below will catch this */
+      if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1)) /* ASCII: result = ascii value */
+        break;
+#endif
+
+      if (_DBUS_UNLIKELY (!UNICODE_VALID (result))) /* ASCII: always valid */
+        break;
+
+      /* UNICODE_VALID should have caught it */
+      _dbus_assert (result != (dbus_unichar_t)-1);
+      
+      p += char_len;
+    }
+
+  /* See that we covered the entire length if a length was
+   * passed in
+   */
+  if (_DBUS_UNLIKELY (p != end))
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/**
+ * Checks that the given range of the string is all nul bytes. If the
+ * given range is not entirely contained in the string, returns
+ * #FALSE.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ * 
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is all nul bytes
+ */
+dbus_bool_t
+_dbus_string_validate_nul (const DBusString *str,
+                           int               start,
+                           int               len)
+{
+  const unsigned char *s;
+  const unsigned char *end;
+  DBUS_CONST_STRING_PREAMBLE (str);
+  _dbus_assert (start >= 0);
+  _dbus_assert (len >= 0);
+  _dbus_assert (start <= real->len);
+  
+  if (len > real->len - start)
+    return FALSE;
+  
+  s = real->str + start;
+  end = s + len;
+  while (s != end)
+    {
+      if (_DBUS_UNLIKELY (*s != '\0'))
+        return FALSE;
+      ++s;
+    }
+  
+  return TRUE;
+}
+
+/**
+ * Clears all allocated bytes in the string to zero.
+ *
+ * @param str the string
+ */
+void
+_dbus_string_zero (DBusString *str)
+{
+  DBUS_STRING_PREAMBLE (str);
+
+  memset (real->str - real->align_offset, '\0', real->allocated);
+}
+/** @} */
+
+/* tests are in dbus-string-util.c */
diff --git a/dbus/dbus/dbus-string.h b/dbus/dbus/dbus-string.h
new file mode 100644
index 0000000..4ef59db
--- /dev/null
+++ b/dbus/dbus/dbus-string.h
@@ -0,0 +1,314 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-string.h String utility class (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003 Red Hat, Inc.
+ * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_STRING_H
+#define DBUS_STRING_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-memory.h>
+
+#include <stdarg.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * DBusString object
+ */
+
+typedef struct DBusString DBusString;
+
+struct DBusString
+{
+#if defined(DBUS_WIN) && defined(_DEBUG)
+  const char *dummy1; /**< placeholder */
+#else
+  const void *dummy1; /**< placeholder */
+#endif
+  int   dummy2;       /**< placeholder */
+  int   dummy3;       /**< placeholder */
+  unsigned int dummy_bit1 : 1; /**< placeholder */
+  unsigned int dummy_bit2 : 1; /**< placeholder */
+  unsigned int dummy_bit3 : 1; /**< placeholder */
+  unsigned int dummy_bits : 3; /**< placeholder */
+};
+
+#ifdef DBUS_DISABLE_ASSERT
+/* Some simple inlining hacks; the current linker is not smart enough
+ * to inline non-exported symbols across files in the library.
+ * Note that these break type safety (due to the casts)
+ */
+#define _dbus_string_get_data(s) ((char*)(((DBusString*)(s))->dummy1))
+#define _dbus_string_get_length(s) (((DBusString*)(s))->dummy2)
+#define _dbus_string_set_byte(s, i, b) ((((unsigned char*)(((DBusString*)(s))->dummy1))[(i)]) = (unsigned char) (b))
+#define _dbus_string_get_byte(s, i) (((const unsigned char*)(((DBusString*)(s))->dummy1))[(i)])
+#define _dbus_string_get_const_data(s) ((const char*)(((DBusString*)(s))->dummy1))
+#define _dbus_string_get_const_data_len(s,start,len) (((const char*)(((DBusString*)(s))->dummy1)) + (start))
+#endif
+
+dbus_bool_t   _dbus_string_init                  (DBusString        *str);
+void          _dbus_string_init_const            (DBusString        *str,
+                                                  const char        *value);
+void          _dbus_string_init_const_len        (DBusString        *str,
+                                                  const char        *value,
+                                                  int                len);
+dbus_bool_t   _dbus_string_init_preallocated     (DBusString        *str,
+                                                  int                allocate_size);
+void          _dbus_string_free                  (DBusString        *str);
+void          _dbus_string_lock                  (DBusString        *str);
+dbus_bool_t   _dbus_string_compact               (DBusString        *str,
+                                                  int                max_waste);
+#ifndef _dbus_string_get_data
+char*         _dbus_string_get_data              (DBusString        *str);
+#endif /* _dbus_string_get_data */
+#ifndef _dbus_string_get_const_data
+const char*   _dbus_string_get_const_data        (const DBusString  *str);
+#endif /* _dbus_string_get_const_data */
+char*         _dbus_string_get_data_len          (DBusString        *str,
+                                                  int                start,
+                                                  int                len);
+#ifndef _dbus_string_get_const_data_len
+const char*   _dbus_string_get_const_data_len    (const DBusString  *str,
+                                                  int                start,
+                                                  int                len);
+#endif
+#ifndef _dbus_string_set_byte
+void          _dbus_string_set_byte              (DBusString        *str,
+                                                  int                i,
+                                                  unsigned char      byte);
+#endif
+#ifndef _dbus_string_get_byte
+unsigned char _dbus_string_get_byte              (const DBusString  *str,
+                                                  int                start);
+#endif /* _dbus_string_get_byte */
+dbus_bool_t   _dbus_string_insert_bytes          (DBusString        *str,
+                                                  int                i,
+						  int                n_bytes,
+                                                  unsigned char      byte);
+dbus_bool_t   _dbus_string_insert_byte           (DBusString        *str,
+                                                  int                i,
+                                                  unsigned char      byte);
+dbus_bool_t   _dbus_string_steal_data            (DBusString        *str,
+                                                  char             **data_return);
+dbus_bool_t   _dbus_string_steal_data_len        (DBusString        *str,
+                                                  char             **data_return,
+                                                  int                start,
+                                                  int                len);
+dbus_bool_t   _dbus_string_copy_data             (const DBusString  *str,
+                                                  char             **data_return);
+dbus_bool_t   _dbus_string_copy_data_len         (const DBusString  *str,
+                                                  char             **data_return,
+                                                  int                start,
+                                                  int                len);
+void          _dbus_string_copy_to_buffer        (const DBusString  *str,
+                                                  char              *buffer,
+						  int                len);
+void          _dbus_string_copy_to_buffer_with_nul (const DBusString  *str,
+                                                    char              *buffer,
+                                                    int                avail_len);
+#ifndef _dbus_string_get_length
+int           _dbus_string_get_length            (const DBusString  *str);
+#endif /* !_dbus_string_get_length */
+
+dbus_bool_t   _dbus_string_lengthen              (DBusString        *str,
+                                                  int                additional_length);
+void          _dbus_string_shorten               (DBusString        *str,
+                                                  int                length_to_remove);
+dbus_bool_t   _dbus_string_set_length            (DBusString        *str,
+                                                  int                length);
+dbus_bool_t   _dbus_string_align_length          (DBusString        *str,
+                                                  int                alignment);
+dbus_bool_t   _dbus_string_alloc_space           (DBusString        *str,
+                                                  int                extra_bytes);
+dbus_bool_t   _dbus_string_append                (DBusString        *str,
+                                                  const char        *buffer);
+dbus_bool_t   _dbus_string_append_len            (DBusString        *str,
+                                                  const char        *buffer,
+                                                  int                len);
+dbus_bool_t   _dbus_string_append_int            (DBusString        *str,
+                                                  long               value);
+dbus_bool_t   _dbus_string_append_uint           (DBusString        *str,
+                                                  unsigned long      value);
+dbus_bool_t   _dbus_string_append_byte           (DBusString        *str,
+                                                  unsigned char      byte);
+dbus_bool_t   _dbus_string_append_printf         (DBusString        *str,
+                                                  const char        *format,
+                                                  ...) _DBUS_GNUC_PRINTF (2, 3);
+dbus_bool_t   _dbus_string_append_printf_valist  (DBusString        *str,
+                                                  const char        *format,
+                                                  va_list            args);
+dbus_bool_t   _dbus_string_insert_2_aligned      (DBusString        *str,
+                                                  int                insert_at,
+                                                  const unsigned char octets[2]);
+dbus_bool_t   _dbus_string_insert_4_aligned      (DBusString        *str,
+                                                  int                insert_at,
+                                                  const unsigned char octets[4]);
+dbus_bool_t   _dbus_string_insert_8_aligned      (DBusString        *str,
+                                                  int                insert_at,
+                                                  const unsigned char octets[8]);
+dbus_bool_t   _dbus_string_insert_alignment      (DBusString        *str,
+                                                  int               *insert_at,
+                                                  int                alignment);
+void          _dbus_string_delete                (DBusString        *str,
+                                                  int                start,
+                                                  int                len);
+dbus_bool_t   _dbus_string_move                  (DBusString        *source,
+                                                  int                start,
+                                                  DBusString        *dest,
+                                                  int                insert_at);
+dbus_bool_t   _dbus_string_copy                  (const DBusString  *source,
+                                                  int                start,
+                                                  DBusString        *dest,
+                                                  int                insert_at);
+dbus_bool_t   _dbus_string_move_len              (DBusString        *source,
+                                                  int                start,
+                                                  int                len,
+                                                  DBusString        *dest,
+                                                  int                insert_at);
+dbus_bool_t   _dbus_string_copy_len              (const DBusString  *source,
+                                                  int                start,
+                                                  int                len,
+                                                  DBusString        *dest,
+                                                  int                insert_at);
+dbus_bool_t   _dbus_string_replace_len           (const DBusString  *source,
+                                                  int                start,
+                                                  int                len,
+                                                  DBusString        *dest,
+                                                  int                replace_at,
+                                                  int                replace_len);
+dbus_bool_t   _dbus_string_split_on_byte         (DBusString        *source,
+                                                  unsigned char      byte,
+                                                  DBusString        *tail);
+dbus_bool_t   _dbus_string_parse_int             (const DBusString  *str,
+                                                  int                start,
+                                                  long              *value_return,
+                                                  int               *end_return);
+dbus_bool_t   _dbus_string_parse_uint            (const DBusString  *str,
+                                                  int                start,
+                                                  unsigned long     *value_return,
+                                                  int               *end_return);
+dbus_bool_t   _dbus_string_find                  (const DBusString  *str,
+                                                  int                start,
+                                                  const char        *substr,
+                                                  int               *found);
+dbus_bool_t   _dbus_string_find_eol               (const DBusString *str,
+                                                  int               start,
+                                                  int               *found,
+                                                  int               *found_len);
+dbus_bool_t   _dbus_string_find_to               (const DBusString  *str,
+                                                  int                start,
+                                                  int                end,
+                                                  const char        *substr,
+                                                  int               *found);
+dbus_bool_t   _dbus_string_find_byte_backward    (const DBusString  *str,
+                                                  int                start,
+                                                  unsigned char      byte,
+                                                  int               *found);
+dbus_bool_t   _dbus_string_find_blank            (const DBusString  *str,
+                                                  int                start,
+                                                  int               *found);
+void          _dbus_string_skip_blank            (const DBusString  *str,
+                                                  int                start,
+                                                  int               *end);
+void          _dbus_string_skip_white            (const DBusString  *str,
+                                                  int                start,
+                                                  int               *end);
+void          _dbus_string_skip_white_reverse    (const DBusString  *str,
+                                                  int                end,
+                                                  int               *start);
+dbus_bool_t   _dbus_string_equal                 (const DBusString  *a,
+                                                  const DBusString  *b);
+dbus_bool_t   _dbus_string_equal_c_str           (const DBusString  *a,
+                                                  const char        *c_str);
+dbus_bool_t   _dbus_string_equal_len             (const DBusString  *a,
+                                                  const DBusString  *b,
+                                                  int                len);
+dbus_bool_t   _dbus_string_equal_substring       (const DBusString  *a,
+                                                  int                a_start,
+                                                  int                a_len,
+                                                  const DBusString  *b,
+                                                  int                b_start);
+dbus_bool_t   _dbus_string_starts_with_c_str     (const DBusString  *a,
+                                                  const char        *c_str);
+dbus_bool_t   _dbus_string_ends_with_c_str       (const DBusString  *a,
+                                                  const char        *c_str);
+dbus_bool_t   _dbus_string_pop_line              (DBusString        *source,
+                                                  DBusString        *dest);
+void          _dbus_string_delete_first_word     (DBusString        *str);
+void          _dbus_string_delete_leading_blanks (DBusString        *str);
+void          _dbus_string_chop_white            (DBusString        *str); 
+dbus_bool_t   _dbus_string_append_byte_as_hex    (DBusString        *str,
+                                                  int                byte);
+dbus_bool_t   _dbus_string_hex_encode            (const DBusString  *source,
+                                                  int                start,
+                                                  DBusString        *dest,
+                                                  int                insert_at);
+dbus_bool_t   _dbus_string_hex_decode            (const DBusString  *source,
+                                                  int                start,
+						  int               *end_return,
+                                                  DBusString        *dest,
+                                                  int                insert_at);
+void          _dbus_string_tolower_ascii         (const DBusString  *str,
+                                                  int                start,
+                                                  int                len);
+void          _dbus_string_toupper_ascii         (const DBusString  *str,
+                                                  int                start,
+                                                  int                len);
+dbus_bool_t   _dbus_string_validate_ascii        (const DBusString  *str,
+                                                  int                start,
+                                                  int                len);
+dbus_bool_t   _dbus_string_validate_utf8         (const DBusString  *str,
+                                                  int                start,
+                                                  int                len);
+dbus_bool_t   _dbus_string_validate_nul          (const DBusString  *str,
+                                                  int                start,
+                                                  int                len);
+void          _dbus_string_zero                  (DBusString        *str);
+
+
+/**
+ * We allocate 1 byte for nul termination, plus 7 bytes for possible
+ * align_offset, so we always need 8 bytes on top of the string's
+ * length to be in the allocated block.
+ */
+#define _DBUS_STRING_ALLOCATION_PADDING 8
+
+/**
+ * Defines a static const variable with type #DBusString called "name"
+ * containing the given string literal.
+ *
+ * @param name the name of the variable
+ * @param str the string value
+ */
+#define _DBUS_STRING_DEFINE_STATIC(name, str)                           \
+  static const char _dbus_static_string_##name[] = str;                 \
+  static const DBusString name = { _dbus_static_string_##name,          \
+                                   sizeof(_dbus_static_string_##name),  \
+                                   sizeof(_dbus_static_string_##name) + \
+                                   _DBUS_STRING_ALLOCATION_PADDING,     \
+                                   TRUE, TRUE, FALSE, 0 }
+
+DBUS_END_DECLS
+
+#endif /* DBUS_STRING_H */
diff --git a/dbus/dbus/dbus-syntax.c b/dbus/dbus/dbus-syntax.c
new file mode 100644
index 0000000..4792287
--- /dev/null
+++ b/dbus/dbus/dbus-syntax.c
@@ -0,0 +1,309 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-syntax.c - utility functions for strings with special syntax
+ *
+ * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
+ * Copyright © 2011 Nokia Corporation
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-syntax.h"
+
+#include "dbus-internals.h"
+#include "dbus-marshal-validate.h"
+#include "dbus-shared.h"
+
+/**
+ * @defgroup DBusSyntax Utility functions for strings with special syntax
+ * @ingroup  DBus
+ * @brief Parsing D-Bus type signatures
+ * @{
+ */
+
+/**
+ * Check an object path for validity. Remember that #NULL can always
+ * be passed instead of a DBusError *, if you don't care about having
+ * an error name and message.
+ *
+ * This function is suitable for validating C strings, but is not suitable
+ * for validating untrusted data from a network unless the string's length
+ * is also checked, since it assumes that the string ends at the first zero
+ * byte according to normal C conventions.
+ *
+ * @param path a potentially invalid object path, which must not be #NULL
+ * @param error error return
+ * @returns #TRUE if path is valid
+ */
+dbus_bool_t
+dbus_validate_path (const char       *path,
+                    DBusError        *error)
+{
+  DBusString str;
+  int len;
+
+  _dbus_return_val_if_fail (path != NULL, FALSE);
+
+  _dbus_string_init_const (&str, path);
+  len = _dbus_string_get_length (&str);
+
+  /* In general, it ought to be valid... */
+  if (_DBUS_LIKELY (_dbus_validate_path (&str, 0, len)))
+    return TRUE;
+
+  /* slow path: string is invalid, find out why */
+
+  if (!_dbus_string_validate_utf8 (&str, 0, len))
+    {
+      /* don't quote the actual string here, since a DBusError also needs to
+       * be valid UTF-8 */
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Object path was not valid UTF-8");
+      return FALSE;
+    }
+
+  /* FIXME: later, diagnose exactly how it was invalid */
+  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                  "Object path was not valid: '%s'", path);
+  return FALSE;
+}
+
+/**
+ * Check an interface name for validity. Remember that #NULL can always
+ * be passed instead of a DBusError *, if you don't care about having
+ * an error name and message.
+ *
+ * This function is suitable for validating C strings, but is not suitable
+ * for validating untrusted data from a network unless the string's length
+ * is also checked, since it assumes that the string ends at the first zero
+ * byte according to normal C conventions.
+ *
+ * @param path a potentially invalid interface name, which must not be #NULL
+ * @param error error return
+ * @returns #TRUE if name is valid
+ */
+dbus_bool_t
+dbus_validate_interface (const char       *name,
+                         DBusError        *error)
+{
+  DBusString str;
+  int len;
+
+  _dbus_return_val_if_fail (name != NULL, FALSE);
+
+  _dbus_string_init_const (&str, name);
+  len = _dbus_string_get_length (&str);
+
+  /* In general, it ought to be valid... */
+  if (_DBUS_LIKELY (_dbus_validate_interface (&str, 0, len)))
+    return TRUE;
+
+  /* slow path: string is invalid, find out why */
+
+  if (!_dbus_string_validate_utf8 (&str, 0, len))
+    {
+      /* don't quote the actual string here, since a DBusError also needs to
+       * be valid UTF-8 */
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Interface name was not valid UTF-8");
+      return FALSE;
+    }
+
+  /* FIXME: later, diagnose exactly how it was invalid */
+  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                  "Interface name was not valid: '%s'", name);
+  return FALSE;
+}
+
+/**
+ * Check a member (method/signal) name for validity. Remember that #NULL
+ * can always be passed instead of a DBusError *, if you don't care about
+ * having an error name and message.
+ *
+ * This function is suitable for validating C strings, but is not suitable
+ * for validating untrusted data from a network unless the string's length
+ * is also checked, since it assumes that the string ends at the first zero
+ * byte according to normal C conventions.
+ *
+ * @param path a potentially invalid member name, which must not be #NULL
+ * @param error error return
+ * @returns #TRUE if name is valid
+ */
+dbus_bool_t
+dbus_validate_member (const char       *name,
+                      DBusError        *error)
+{
+  DBusString str;
+  int len;
+
+  _dbus_return_val_if_fail (name != NULL, FALSE);
+
+  _dbus_string_init_const (&str, name);
+  len = _dbus_string_get_length (&str);
+
+  /* In general, it ought to be valid... */
+  if (_DBUS_LIKELY (_dbus_validate_member (&str, 0, len)))
+    return TRUE;
+
+  /* slow path: string is invalid, find out why */
+
+  if (!_dbus_string_validate_utf8 (&str, 0, len))
+    {
+      /* don't quote the actual string here, since a DBusError also needs to
+       * be valid UTF-8 */
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Member name was not valid UTF-8");
+      return FALSE;
+    }
+
+  /* FIXME: later, diagnose exactly how it was invalid */
+  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                  "Member name was not valid: '%s'", name);
+  return FALSE;
+}
+
+/**
+ * Check an error name for validity. Remember that #NULL
+ * can always be passed instead of a DBusError *, if you don't care about
+ * having an error name and message.
+ *
+ * This function is suitable for validating C strings, but is not suitable
+ * for validating untrusted data from a network unless the string's length
+ * is also checked, since it assumes that the string ends at the first zero
+ * byte according to normal C conventions.
+ *
+ * @param path a potentially invalid error name, which must not be #NULL
+ * @param error error return
+ * @returns #TRUE if name is valid
+ */
+dbus_bool_t
+dbus_validate_error_name (const char       *name,
+                          DBusError        *error)
+{
+  DBusString str;
+  int len;
+
+  _dbus_return_val_if_fail (name != NULL, FALSE);
+
+  _dbus_string_init_const (&str, name);
+  len = _dbus_string_get_length (&str);
+
+  /* In general, it ought to be valid... */
+  if (_DBUS_LIKELY (_dbus_validate_error_name (&str, 0, len)))
+    return TRUE;
+
+  /* slow path: string is invalid, find out why */
+
+  if (!_dbus_string_validate_utf8 (&str, 0, len))
+    {
+      /* don't quote the actual string here, since a DBusError also needs to
+       * be valid UTF-8 */
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Error name was not valid UTF-8");
+      return FALSE;
+    }
+
+  /* FIXME: later, diagnose exactly how it was invalid */
+  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                  "Error name was not valid: '%s'", name);
+  return FALSE;
+}
+
+/**
+ * Check a bus name for validity. Remember that #NULL
+ * can always be passed instead of a DBusError *, if you don't care about
+ * having an error name and message.
+ *
+ * This function is suitable for validating C strings, but is not suitable
+ * for validating untrusted data from a network unless the string's length
+ * is also checked, since it assumes that the string ends at the first zero
+ * byte according to normal C conventions.
+ *
+ * @param path a potentially invalid bus name, which must not be #NULL
+ * @param error error return
+ * @returns #TRUE if name is valid
+ */
+dbus_bool_t
+dbus_validate_bus_name (const char       *name,
+                        DBusError        *error)
+{
+  DBusString str;
+  int len;
+
+  _dbus_return_val_if_fail (name != NULL, FALSE);
+
+  _dbus_string_init_const (&str, name);
+  len = _dbus_string_get_length (&str);
+
+  /* In general, it ought to be valid... */
+  if (_DBUS_LIKELY (_dbus_validate_bus_name (&str, 0, len)))
+    return TRUE;
+
+  /* slow path: string is invalid, find out why */
+
+  if (!_dbus_string_validate_utf8 (&str, 0, len))
+    {
+      /* don't quote the actual string here, since a DBusError also needs to
+       * be valid UTF-8 */
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                      "Bus name was not valid UTF-8");
+      return FALSE;
+    }
+
+  /* FIXME: later, diagnose exactly how it was invalid */
+  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                  "Bus name was not valid: '%s'", name);
+  return FALSE;
+}
+
+/**
+ * Check a string for validity. Strings on D-Bus must be valid UTF-8.
+ * Remember that #NULL can always be passed instead of a DBusError *,
+ * if you don't care about having an error name and message.
+ *
+ * This function is suitable for validating C strings, but is not suitable
+ * for validating untrusted data from a network unless the string's length
+ * is also checked, since it assumes that the string ends at the first zero
+ * byte according to normal C conventions.
+ *
+ * @param alleged_utf8 a string to be checked, which must not be #NULL
+ * @param error error return
+ * @returns #TRUE if alleged_utf8 is valid UTF-8
+ */
+dbus_bool_t
+dbus_validate_utf8 (const char       *alleged_utf8,
+                    DBusError        *error)
+{
+  DBusString str;
+
+  _dbus_return_val_if_fail (alleged_utf8 != NULL, FALSE);
+
+  _dbus_string_init_const (&str, alleged_utf8);
+
+  if (_DBUS_LIKELY (_dbus_string_validate_utf8 (&str, 0,
+                                                _dbus_string_get_length (&str))))
+    return TRUE;
+
+  /* don't quote the actual string here, since a DBusError also needs to
+   * be valid UTF-8 */
+  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                  "String was not valid UTF-8");
+  return FALSE;
+}
+
+/** @} */ /* end of group */
diff --git a/dbus/dbus/dbus-syntax.h b/dbus/dbus/dbus-syntax.h
new file mode 100644
index 0000000..daf20f0
--- /dev/null
+++ b/dbus/dbus/dbus-syntax.h
@@ -0,0 +1,58 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-syntax.h - utility functions for strings with special syntax
+ *
+ * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
+ * Copyright © 2011 Nokia Corporation
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_SYNTAX_H
+#define DBUS_SYNTAX_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+
+DBUS_BEGIN_DECLS
+
+DBUS_EXPORT
+dbus_bool_t     dbus_validate_path                   (const char *path,
+                                                      DBusError  *error);
+DBUS_EXPORT
+dbus_bool_t     dbus_validate_interface              (const char *name,
+                                                      DBusError  *error);
+DBUS_EXPORT
+dbus_bool_t     dbus_validate_member                 (const char *name,
+                                                      DBusError  *error);
+DBUS_EXPORT
+dbus_bool_t     dbus_validate_error_name             (const char *name,
+                                                      DBusError  *error);
+DBUS_EXPORT
+dbus_bool_t     dbus_validate_bus_name               (const char *name,
+                                                      DBusError  *error);
+DBUS_EXPORT
+dbus_bool_t     dbus_validate_utf8                   (const char *alleged_utf8,
+                                                      DBusError  *error);
+
+DBUS_END_DECLS
+
+#endif /* multiple-inclusion guard */
diff --git a/dbus/dbus/dbus-sysdeps-pthread.c b/dbus/dbus/dbus-sysdeps-pthread.c
new file mode 100644
index 0000000..c60457b
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-pthread.c
@@ -0,0 +1,285 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-pthread.c Implements threads using pthreads (internal to libdbus)
+ * 
+ * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-sysdeps.h"
+#include "dbus-threads.h"
+
+#include <sys/time.h>
+#include <pthread.h>
+#include <string.h>
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <config.h>
+
+/* Whether we have a "monotonic" clock; i.e. a clock not affected by
+ * changes in system time.
+ * This is initialized once in check_monotonic_clock below.
+ * https://bugs.freedesktop.org/show_bug.cgi?id=18121
+ */
+static dbus_bool_t have_monotonic_clock = 0;
+
+struct DBusRMutex {
+  pthread_mutex_t lock; /**< the lock */
+};
+
+struct DBusCMutex {
+  pthread_mutex_t lock; /**< the lock */
+};
+
+struct DBusCondVar {
+  pthread_cond_t cond; /**< the condition */
+};
+
+#define DBUS_MUTEX(m)         ((DBusMutex*) m)
+#define DBUS_MUTEX_PTHREAD(m) ((DBusMutexPThread*) m)
+
+#define DBUS_COND_VAR(c)         ((DBusCondVar*) c)
+#define DBUS_COND_VAR_PTHREAD(c) ((DBusCondVarPThread*) c)
+
+
+#ifdef DBUS_DISABLE_ASSERT
+/* (tmp != 0) is a no-op usage to silence compiler */
+#define PTHREAD_CHECK(func_name, result_or_call)    \
+    do { int tmp = (result_or_call); if (tmp != 0) {;} } while (0)
+#else
+#define PTHREAD_CHECK(func_name, result_or_call) do {                                  \
+    int tmp = (result_or_call);                                                        \
+    if (tmp != 0) {                                                                    \
+      _dbus_warn_check_failed ("pthread function %s failed with %d %s in %s\n",        \
+                               func_name, tmp, strerror(tmp), _DBUS_FUNCTION_NAME);    \
+    }                                                                                  \
+} while (0)
+#endif /* !DBUS_DISABLE_ASSERT */
+
+DBusCMutex *
+_dbus_platform_cmutex_new (void)
+{
+  DBusCMutex *pmutex;
+  int result;
+
+  pmutex = dbus_new (DBusCMutex, 1);
+  if (pmutex == NULL)
+    return NULL;
+
+  result = pthread_mutex_init (&pmutex->lock, NULL);
+
+  if (result == ENOMEM || result == EAGAIN)
+    {
+      dbus_free (pmutex);
+      return NULL;
+    }
+  else
+    {
+      PTHREAD_CHECK ("pthread_mutex_init", result);
+    }
+
+  return pmutex;
+}
+
+DBusRMutex *
+_dbus_platform_rmutex_new (void)
+{
+  DBusRMutex *pmutex;
+  pthread_mutexattr_t mutexattr;
+  int result;
+
+  pmutex = dbus_new (DBusRMutex, 1);
+  if (pmutex == NULL)
+    return NULL;
+
+  pthread_mutexattr_init (&mutexattr);
+  pthread_mutexattr_settype (&mutexattr, PTHREAD_MUTEX_RECURSIVE);
+  result = pthread_mutex_init (&pmutex->lock, &mutexattr);
+  pthread_mutexattr_destroy (&mutexattr);
+
+  if (result == ENOMEM || result == EAGAIN)
+    {
+      dbus_free (pmutex);
+      return NULL;
+    }
+  else
+    {
+      PTHREAD_CHECK ("pthread_mutex_init", result);
+    }
+
+  return pmutex;
+}
+
+void
+_dbus_platform_cmutex_free (DBusCMutex *mutex)
+{
+  PTHREAD_CHECK ("pthread_mutex_destroy", pthread_mutex_destroy (&mutex->lock));
+  dbus_free (mutex);
+}
+
+void
+_dbus_platform_rmutex_free (DBusRMutex *mutex)
+{
+  PTHREAD_CHECK ("pthread_mutex_destroy", pthread_mutex_destroy (&mutex->lock));
+  dbus_free (mutex);
+}
+
+void
+_dbus_platform_cmutex_lock (DBusCMutex *mutex)
+{
+  PTHREAD_CHECK ("pthread_mutex_lock", pthread_mutex_lock (&mutex->lock));
+}
+
+void
+_dbus_platform_rmutex_lock (DBusRMutex *mutex)
+{
+  PTHREAD_CHECK ("pthread_mutex_lock", pthread_mutex_lock (&mutex->lock));
+}
+
+void
+_dbus_platform_cmutex_unlock (DBusCMutex *mutex)
+{
+  PTHREAD_CHECK ("pthread_mutex_unlock", pthread_mutex_unlock (&mutex->lock));
+}
+
+void
+_dbus_platform_rmutex_unlock (DBusRMutex *mutex)
+{
+  PTHREAD_CHECK ("pthread_mutex_unlock", pthread_mutex_unlock (&mutex->lock));
+}
+
+DBusCondVar *
+_dbus_platform_condvar_new (void)
+{
+  DBusCondVar *pcond;
+  pthread_condattr_t attr;
+  int result;
+  
+  pcond = dbus_new (DBusCondVar, 1);
+  if (pcond == NULL)
+    return NULL;
+
+  pthread_condattr_init (&attr);
+#ifdef HAVE_MONOTONIC_CLOCK
+  if (have_monotonic_clock)
+    pthread_condattr_setclock (&attr, CLOCK_MONOTONIC);
+#endif
+
+  result = pthread_cond_init (&pcond->cond, &attr);
+  pthread_condattr_destroy (&attr);
+
+  if (result == EAGAIN || result == ENOMEM)
+    {
+      dbus_free (pcond);
+      return NULL;
+    }
+  else
+    {
+      PTHREAD_CHECK ("pthread_cond_init", result);
+    }
+  
+  return pcond;
+}
+
+void
+_dbus_platform_condvar_free (DBusCondVar *cond)
+{
+  PTHREAD_CHECK ("pthread_cond_destroy", pthread_cond_destroy (&cond->cond));
+  dbus_free (cond);
+}
+
+void
+_dbus_platform_condvar_wait (DBusCondVar *cond,
+                             DBusCMutex  *mutex)
+{
+  PTHREAD_CHECK ("pthread_cond_wait", pthread_cond_wait (&cond->cond, &mutex->lock));
+}
+
+dbus_bool_t
+_dbus_platform_condvar_wait_timeout (DBusCondVar               *cond,
+                                     DBusCMutex                *mutex,
+                                     int                        timeout_milliseconds)
+{
+  struct timeval time_now;
+  struct timespec end_time;
+  int result;
+
+#ifdef HAVE_MONOTONIC_CLOCK
+  if (have_monotonic_clock)
+    {
+      struct timespec monotonic_timer;
+      clock_gettime (CLOCK_MONOTONIC,&monotonic_timer);
+      time_now.tv_sec = monotonic_timer.tv_sec;
+      time_now.tv_usec = monotonic_timer.tv_nsec / 1000;
+    }
+  else
+    /* This else falls through to gettimeofday */
+#endif
+  gettimeofday (&time_now, NULL);
+  
+  end_time.tv_sec = time_now.tv_sec + timeout_milliseconds / 1000;
+  end_time.tv_nsec = (time_now.tv_usec + (timeout_milliseconds % 1000) * 1000) * 1000;
+  if (end_time.tv_nsec > 1000*1000*1000)
+    {
+      end_time.tv_sec += 1;
+      end_time.tv_nsec -= 1000*1000*1000;
+    }
+
+  result = pthread_cond_timedwait (&cond->cond, &mutex->lock, &end_time);
+  
+  if (result != ETIMEDOUT)
+    {
+      PTHREAD_CHECK ("pthread_cond_timedwait", result);
+    }
+
+  /* return true if we did not time out */
+  return result != ETIMEDOUT;
+}
+
+void
+_dbus_platform_condvar_wake_one (DBusCondVar *cond)
+{
+  PTHREAD_CHECK ("pthread_cond_signal", pthread_cond_signal (&cond->cond));
+}
+
+static void
+check_monotonic_clock (void)
+{
+#ifdef HAVE_MONOTONIC_CLOCK
+  struct timespec dummy;
+  if (clock_getres (CLOCK_MONOTONIC, &dummy) == 0)
+    have_monotonic_clock = TRUE;
+#endif
+}
+
+dbus_bool_t
+_dbus_threads_init_platform_specific (void)
+{
+  /* These have static variables, and we need to handle both the case
+   * where dbus_threads_init() has been called and when it hasn't;
+   * so initialize them before any threads are allowed to enter.
+   */
+  check_monotonic_clock ();
+  (void) _dbus_check_setuid ();
+  return dbus_threads_init (NULL);
+}
diff --git a/dbus/dbus/dbus-sysdeps-thread-win.c b/dbus/dbus/dbus-sysdeps-thread-win.c
new file mode 100644
index 0000000..e30e7b8
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-thread-win.c
@@ -0,0 +1,274 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-pthread.c Implements threads using Windows threads (internal to libdbus)
+ * 
+ * Copyright (C) 2006  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-sysdeps.h"
+#include "dbus-sysdeps-win.h"
+#include "dbus-threads.h"
+#include "dbus-list.h"
+
+#include <windows.h>
+
+struct DBusCondVar {
+  DBusList *list;        /**< list thread-local-stored events waiting on the cond variable */
+  CRITICAL_SECTION lock; /**< lock protecting the list */
+};
+
+static DWORD dbus_cond_event_tls = TLS_OUT_OF_INDEXES;
+
+
+static HMODULE dbus_dll_hmodule;
+
+void *
+_dbus_win_get_dll_hmodule (void)
+{
+  return dbus_dll_hmodule;
+}
+
+#ifdef DBUS_WINCE
+#define hinst_t HANDLE
+#else
+#define hinst_t HINSTANCE
+#endif
+
+BOOL WINAPI DllMain (hinst_t, DWORD, LPVOID);
+
+/* We need this to free the TLS events on thread exit */
+BOOL WINAPI
+DllMain (hinst_t hinstDLL,
+	 DWORD     fdwReason,
+	 LPVOID    lpvReserved)
+{
+  HANDLE event;
+  switch (fdwReason) 
+    { 
+    case DLL_PROCESS_ATTACH:
+      dbus_dll_hmodule = hinstDLL;
+      break;
+    case DLL_THREAD_DETACH:
+      if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
+	{
+	  event = TlsGetValue(dbus_cond_event_tls);
+	  CloseHandle (event);
+	  TlsSetValue(dbus_cond_event_tls, NULL);
+	}
+      break;
+    case DLL_PROCESS_DETACH: 
+      if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
+	{
+	  event = TlsGetValue(dbus_cond_event_tls);
+	  CloseHandle (event);
+	  TlsSetValue(dbus_cond_event_tls, NULL);
+
+	  TlsFree(dbus_cond_event_tls); 
+	}
+      break;
+    default: 
+      break; 
+    }
+  return TRUE;
+}
+
+DBusCMutex *
+_dbus_platform_cmutex_new (void)
+{
+  HANDLE handle;
+  handle = CreateMutex (NULL, FALSE, NULL);
+  return (DBusCMutex *) handle;
+}
+
+DBusRMutex *
+_dbus_platform_rmutex_new (void)
+{
+  HANDLE handle;
+  handle = CreateMutex (NULL, FALSE, NULL);
+  return (DBusRMutex *) handle;
+}
+
+void
+_dbus_platform_cmutex_free (DBusCMutex *mutex)
+{
+  CloseHandle ((HANDLE *) mutex);
+}
+
+void
+_dbus_platform_rmutex_free (DBusRMutex *mutex)
+{
+  CloseHandle ((HANDLE *) mutex);
+}
+
+void
+_dbus_platform_cmutex_lock (DBusCMutex *mutex)
+{
+  WaitForSingleObject ((HANDLE *) mutex, INFINITE);
+}
+
+void
+_dbus_platform_rmutex_lock (DBusRMutex *mutex)
+{
+  WaitForSingleObject ((HANDLE *) mutex, INFINITE);
+}
+
+void
+_dbus_platform_cmutex_unlock (DBusCMutex *mutex)
+{
+  ReleaseMutex ((HANDLE *) mutex);
+}
+
+void
+_dbus_platform_rmutex_unlock (DBusRMutex *mutex)
+{
+  ReleaseMutex ((HANDLE *) mutex);
+}
+
+DBusCondVar *
+_dbus_platform_condvar_new (void)
+{
+  DBusCondVar *cond;
+    
+  cond = dbus_new (DBusCondVar, 1);
+  if (cond == NULL)
+    return NULL;
+  
+  cond->list = NULL;
+  
+  InitializeCriticalSection (&cond->lock);
+  return cond;
+}
+
+void
+_dbus_platform_condvar_free (DBusCondVar *cond)
+{
+  DeleteCriticalSection (&cond->lock);
+  _dbus_list_clear (&cond->list);
+  dbus_free (cond);
+}
+
+static dbus_bool_t
+_dbus_condvar_wait_win32 (DBusCondVar *cond,
+			  DBusCMutex *mutex,
+			  int milliseconds)
+{
+  DWORD retval;
+  dbus_bool_t ret;
+  HANDLE event = TlsGetValue (dbus_cond_event_tls);
+
+  if (!event)
+    {
+      event = CreateEvent (0, FALSE, FALSE, NULL);
+      if (event == 0)
+	return FALSE;
+      TlsSetValue (dbus_cond_event_tls, event);
+    }
+
+  EnterCriticalSection (&cond->lock);
+
+  /* The event must not be signaled. Check this */
+  _dbus_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT);
+
+  ret = _dbus_list_append (&cond->list, event);
+  
+  LeaveCriticalSection (&cond->lock);
+  
+  if (!ret)
+    return FALSE; /* Prepend failed */
+
+  _dbus_platform_cmutex_unlock (mutex);
+  retval = WaitForSingleObject (event, milliseconds);
+  _dbus_platform_cmutex_lock (mutex);
+  
+  if (retval == WAIT_TIMEOUT)
+    {
+      EnterCriticalSection (&cond->lock);
+      _dbus_list_remove (&cond->list, event);
+
+      /* In the meantime we could have been signaled, so we must again
+       * wait for the signal, this time with no timeout, to reset
+       * it. retval is set again to honour the late arrival of the
+       * signal */
+      retval = WaitForSingleObject (event, 0);
+
+      LeaveCriticalSection (&cond->lock);
+    }
+
+#ifndef DBUS_DISABLE_ASSERT
+  EnterCriticalSection (&cond->lock);
+
+  /* Now event must not be inside the array, check this */
+  _dbus_assert (_dbus_list_remove (&cond->list, event) == FALSE);
+
+  LeaveCriticalSection (&cond->lock);
+#endif /* !G_DISABLE_ASSERT */
+
+  return retval != WAIT_TIMEOUT;
+}
+
+void
+_dbus_platform_condvar_wait (DBusCondVar *cond,
+                             DBusCMutex  *mutex)
+{
+  _dbus_condvar_wait_win32 (cond, mutex, INFINITE);
+}
+
+dbus_bool_t
+_dbus_platform_condvar_wait_timeout (DBusCondVar               *cond,
+				     DBusCMutex                *mutex,
+				     int                        timeout_milliseconds)
+{
+  return _dbus_condvar_wait_win32 (cond, mutex, timeout_milliseconds);
+}
+
+void
+_dbus_platform_condvar_wake_one (DBusCondVar *cond)
+{
+  EnterCriticalSection (&cond->lock);
+  
+  if (cond->list != NULL)
+    {
+      SetEvent (_dbus_list_pop_first (&cond->list));
+      /* Avoid live lock by pushing the waiter to the mutex lock
+         instruction, which is fair.  If we don't do this, we could
+         acquire the condition variable again before the waiter has a
+         chance itself, leading to starvation.  */
+      Sleep (0);
+    }
+  LeaveCriticalSection (&cond->lock);
+}
+
+dbus_bool_t
+_dbus_threads_init_platform_specific (void)
+{
+  /* We reuse this over several generations, because we can't
+   * free the events once they are in use
+   */
+  if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
+    {
+      dbus_cond_event_tls = TlsAlloc ();
+      if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
+	return FALSE;
+    }
+
+  return dbus_threads_init (NULL);
+}
+
diff --git a/dbus/dbus/dbus-sysdeps-unix.c b/dbus/dbus/dbus-sysdeps-unix.c
new file mode 100644
index 0000000..3f35d99
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-unix.c
@@ -0,0 +1,4191 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include "dbus-internals.h"
+#include "dbus-sysdeps.h"
+#include "dbus-sysdeps-unix.h"
+#include "dbus-threads.h"
+#include "dbus-protocol.h"
+#include "dbus-transport.h"
+#include "dbus-string.h"
+#include "dbus-userdb.h"
+#include "dbus-list.h"
+#include "dbus-credentials.h"
+#include "dbus-nonce.h"
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <dirent.h>
+#include <sys/un.h>
+#include <pwd.h>
+#include <time.h>
+#include <locale.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <grp.h>
+#include <cutils/sockets.h>
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_WRITEV
+#include <sys/uio.h>
+#endif
+#ifdef HAVE_POLL
+#include <sys/poll.h>
+#endif
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+#endif
+#ifdef HAVE_GETPEERUCRED
+#include <ucred.h>
+#endif
+
+#ifdef HAVE_ADT
+#include <bsm/adt.h>
+#endif
+
+#include "sd-daemon.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifndef AI_ADDRCONFIG
+#define AI_ADDRCONFIG 0
+#endif
+
+#ifndef HAVE_SOCKLEN_T
+#define socklen_t int
+#endif
+
+#if defined (__sun) || defined (__sun__)
+/*
+ * CMS_SPACE etc. definitions for Solaris < 10, based on
+ *   http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
+ * via
+ *   http://wiki.opencsw.org/porting-faq#toc10
+ *
+ * These are only redefined for Solaris, for now: if your OS needs these too,
+ * please file a bug. (Or preferably, improve your OS so they're not needed.)
+ */
+
+# ifndef CMSG_ALIGN
+#   ifdef __sun__
+#     define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
+#   else
+      /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
+#     define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
+                              ~(sizeof (long) - 1))
+#   endif
+# endif
+
+# ifndef CMSG_SPACE
+#   define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
+                            CMSG_ALIGN (len))
+# endif
+
+# ifndef CMSG_LEN
+#   define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
+# endif
+
+#endif /* Solaris */
+
+static dbus_bool_t
+_dbus_open_socket (int              *fd_p,
+                   int               domain,
+                   int               type,
+                   int               protocol,
+                   DBusError        *error)
+{
+#ifdef SOCK_CLOEXEC
+  dbus_bool_t cloexec_done;
+
+  *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
+  cloexec_done = *fd_p >= 0;
+
+  /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
+  if (*fd_p < 0 && errno == EINVAL)
+#endif
+    {
+      *fd_p = socket (domain, type, protocol);
+    }
+
+  if (*fd_p >= 0)
+    {
+#ifdef SOCK_CLOEXEC
+      if (!cloexec_done)
+#endif
+        {
+          _dbus_fd_set_close_on_exec(*fd_p);
+        }
+
+      _dbus_verbose ("socket fd %d opened\n", *fd_p);
+      return TRUE;
+    }
+  else
+    {
+      dbus_set_error(error,
+                     _dbus_error_from_errno (errno),
+                     "Failed to open socket: %s",
+                     _dbus_strerror (errno));
+      return FALSE;
+    }
+}
+
+/**
+ * Opens a UNIX domain socket (as in the socket() call).
+ * Does not bind the socket.
+ *
+ * This will set FD_CLOEXEC for the socket returned
+ *
+ * @param fd return location for socket descriptor
+ * @param error return location for an error
+ * @returns #FALSE if error is set
+ */
+static dbus_bool_t
+_dbus_open_unix_socket (int              *fd,
+                        DBusError        *error)
+{
+  return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
+}
+
+/**
+ * Closes a socket. Should not be used on non-socket
+ * file descriptors or handles.
+ *
+ * @param fd the socket
+ * @param error return location for an error
+ * @returns #FALSE if error is set
+ */
+dbus_bool_t
+_dbus_close_socket (int               fd,
+                    DBusError        *error)
+{
+  return _dbus_close (fd, error);
+}
+
+/**
+ * Like _dbus_read(), but only works on sockets so is
+ * available on Windows.
+ *
+ * @param fd the socket
+ * @param buffer string to append data to
+ * @param count max amount of data to read
+ * @returns number of bytes appended to the string
+ */
+int
+_dbus_read_socket (int               fd,
+                   DBusString       *buffer,
+                   int               count)
+{
+  return _dbus_read (fd, buffer, count);
+}
+
+/**
+ * Like _dbus_write(), but only supports sockets
+ * and is thus available on Windows.
+ *
+ * @param fd the file descriptor to write
+ * @param buffer the buffer to write data from
+ * @param start the first byte in the buffer to write
+ * @param len the number of bytes to try to write
+ * @returns the number of bytes written or -1 on error
+ */
+int
+_dbus_write_socket (int               fd,
+                    const DBusString *buffer,
+                    int               start,
+                    int               len)
+{
+#if HAVE_DECL_MSG_NOSIGNAL
+  const char *data;
+  int bytes_written;
+
+  data = _dbus_string_get_const_data_len (buffer, start, len);
+
+ again:
+
+  bytes_written = send (fd, data, len, MSG_NOSIGNAL);
+
+  if (bytes_written < 0 && errno == EINTR)
+    goto again;
+
+  return bytes_written;
+
+#else
+  return _dbus_write (fd, buffer, start, len);
+#endif
+}
+
+/**
+ * Like _dbus_read_socket() but also tries to read unix fds from the
+ * socket. When there are more fds to read than space in the array
+ * passed this function will fail with ENOSPC.
+ *
+ * @param fd the socket
+ * @param buffer string to append data to
+ * @param count max amount of data to read
+ * @param fds array to place read file descriptors in
+ * @param n_fds on input space in fds array, on output how many fds actually got read
+ * @returns number of bytes appended to string
+ */
+int
+_dbus_read_socket_with_unix_fds (int               fd,
+                                 DBusString       *buffer,
+                                 int               count,
+                                 int              *fds,
+                                 int              *n_fds) {
+#ifndef HAVE_UNIX_FD_PASSING
+  int r;
+
+  if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
+    return r;
+
+  *n_fds = 0;
+  return r;
+
+#else
+  int bytes_read;
+  int start;
+  struct msghdr m;
+  struct iovec iov;
+
+  _dbus_assert (count >= 0);
+  _dbus_assert (*n_fds >= 0);
+
+  start = _dbus_string_get_length (buffer);
+
+  if (!_dbus_string_lengthen (buffer, count))
+    {
+      errno = ENOMEM;
+      return -1;
+    }
+
+  _DBUS_ZERO(iov);
+  iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
+  iov.iov_len = count;
+
+  _DBUS_ZERO(m);
+  m.msg_iov = &iov;
+  m.msg_iovlen = 1;
+
+  /* Hmm, we have no clue how long the control data will actually be
+     that is queued for us. The least we can do is assume that the
+     caller knows. Hence let's make space for the number of fds that
+     we shall read at max plus the cmsg header. */
+  m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
+
+  /* It's probably safe to assume that systems with SCM_RIGHTS also
+     know alloca() */
+  m.msg_control = alloca(m.msg_controllen);
+  memset(m.msg_control, 0, m.msg_controllen);
+
+ again:
+
+  bytes_read = recvmsg(fd, &m, 0
+#ifdef MSG_CMSG_CLOEXEC
+                       |MSG_CMSG_CLOEXEC
+#endif
+                       );
+
+  if (bytes_read < 0)
+    {
+      if (errno == EINTR)
+        goto again;
+      else
+        {
+          /* put length back (note that this doesn't actually realloc anything) */
+          _dbus_string_set_length (buffer, start);
+          return -1;
+        }
+    }
+  else
+    {
+      struct cmsghdr *cm;
+      dbus_bool_t found = FALSE;
+
+      if (m.msg_flags & MSG_CTRUNC)
+        {
+          /* Hmm, apparently the control data was truncated. The bad
+             thing is that we might have completely lost a couple of fds
+             without chance to recover them. Hence let's treat this as a
+             serious error. */
+
+          errno = ENOSPC;
+          _dbus_string_set_length (buffer, start);
+          return -1;
+        }
+
+      for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
+        if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
+          {
+            unsigned i;
+
+            _dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int)));
+            *n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+
+            memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int));
+            found = TRUE;
+
+            /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
+               worked, hence we need to go through this list and set
+               CLOEXEC everywhere in any case */
+            for (i = 0; i < *n_fds; i++)
+              _dbus_fd_set_close_on_exec(fds[i]);
+
+            break;
+          }
+
+      if (!found)
+        *n_fds = 0;
+
+      /* put length back (doesn't actually realloc) */
+      _dbus_string_set_length (buffer, start + bytes_read);
+
+#if 0
+      if (bytes_read > 0)
+        _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
+#endif
+
+      return bytes_read;
+    }
+#endif
+}
+
+int
+_dbus_write_socket_with_unix_fds(int               fd,
+                                 const DBusString *buffer,
+                                 int               start,
+                                 int               len,
+                                 const int        *fds,
+                                 int               n_fds) {
+
+#ifndef HAVE_UNIX_FD_PASSING
+
+  if (n_fds > 0) {
+    errno = ENOTSUP;
+    return -1;
+  }
+
+  return _dbus_write_socket(fd, buffer, start, len);
+#else
+  return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
+#endif
+}
+
+int
+_dbus_write_socket_with_unix_fds_two(int               fd,
+                                     const DBusString *buffer1,
+                                     int               start1,
+                                     int               len1,
+                                     const DBusString *buffer2,
+                                     int               start2,
+                                     int               len2,
+                                     const int        *fds,
+                                     int               n_fds) {
+
+#ifndef HAVE_UNIX_FD_PASSING
+
+  if (n_fds > 0) {
+    errno = ENOTSUP;
+    return -1;
+  }
+
+  return _dbus_write_socket_two(fd,
+                                buffer1, start1, len1,
+                                buffer2, start2, len2);
+#else
+
+  struct msghdr m;
+  struct cmsghdr *cm;
+  struct iovec iov[2];
+  int bytes_written;
+
+  _dbus_assert (len1 >= 0);
+  _dbus_assert (len2 >= 0);
+  _dbus_assert (n_fds >= 0);
+
+  _DBUS_ZERO(iov);
+  iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
+  iov[0].iov_len = len1;
+
+  if (buffer2)
+    {
+      iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
+      iov[1].iov_len = len2;
+    }
+
+  _DBUS_ZERO(m);
+  m.msg_iov = iov;
+  m.msg_iovlen = buffer2 ? 2 : 1;
+
+  if (n_fds > 0)
+    {
+      m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
+      m.msg_control = alloca(m.msg_controllen);
+      memset(m.msg_control, 0, m.msg_controllen);
+
+      cm = CMSG_FIRSTHDR(&m);
+      cm->cmsg_level = SOL_SOCKET;
+      cm->cmsg_type = SCM_RIGHTS;
+      cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
+      memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
+    }
+
+ again:
+
+  bytes_written = sendmsg (fd, &m, 0
+#if HAVE_DECL_MSG_NOSIGNAL
+                           |MSG_NOSIGNAL
+#endif
+                           );
+
+  if (bytes_written < 0 && errno == EINTR)
+    goto again;
+
+#if 0
+  if (bytes_written > 0)
+    _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
+#endif
+
+  return bytes_written;
+#endif
+}
+
+/**
+ * Like _dbus_write_two() but only works on sockets and is thus
+ * available on Windows.
+ *
+ * @param fd the file descriptor
+ * @param buffer1 first buffer
+ * @param start1 first byte to write in first buffer
+ * @param len1 number of bytes to write from first buffer
+ * @param buffer2 second buffer, or #NULL
+ * @param start2 first byte to write in second buffer
+ * @param len2 number of bytes to write in second buffer
+ * @returns total bytes written from both buffers, or -1 on error
+ */
+int
+_dbus_write_socket_two (int               fd,
+                        const DBusString *buffer1,
+                        int               start1,
+                        int               len1,
+                        const DBusString *buffer2,
+                        int               start2,
+                        int               len2)
+{
+#if HAVE_DECL_MSG_NOSIGNAL
+  struct iovec vectors[2];
+  const char *data1;
+  const char *data2;
+  int bytes_written;
+  struct msghdr m;
+
+  _dbus_assert (buffer1 != NULL);
+  _dbus_assert (start1 >= 0);
+  _dbus_assert (start2 >= 0);
+  _dbus_assert (len1 >= 0);
+  _dbus_assert (len2 >= 0);
+
+  data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
+
+  if (buffer2 != NULL)
+    data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
+  else
+    {
+      data2 = NULL;
+      start2 = 0;
+      len2 = 0;
+    }
+
+  vectors[0].iov_base = (char*) data1;
+  vectors[0].iov_len = len1;
+  vectors[1].iov_base = (char*) data2;
+  vectors[1].iov_len = len2;
+
+  _DBUS_ZERO(m);
+  m.msg_iov = vectors;
+  m.msg_iovlen = data2 ? 2 : 1;
+
+ again:
+
+  bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
+
+  if (bytes_written < 0 && errno == EINTR)
+    goto again;
+
+  return bytes_written;
+
+#else
+  return _dbus_write_two (fd, buffer1, start1, len1,
+                          buffer2, start2, len2);
+#endif
+}
+
+dbus_bool_t
+_dbus_socket_is_invalid (int fd)
+{
+    return fd < 0 ? TRUE : FALSE;
+}
+
+/**
+ * Thin wrapper around the read() system call that appends
+ * the data it reads to the DBusString buffer. It appends
+ * up to the given count, and returns the same value
+ * and same errno as read(). The only exception is that
+ * _dbus_read() handles EINTR for you. Also, _dbus_read() can
+ * return ENOMEM, even though regular UNIX read doesn't.
+ *
+ * Unlike _dbus_read_socket(), _dbus_read() is not available
+ * on Windows.
+ *
+ * @param fd the file descriptor to read from
+ * @param buffer the buffer to append data to
+ * @param count the amount of data to read
+ * @returns the number of bytes read or -1
+ */
+int
+_dbus_read (int               fd,
+            DBusString       *buffer,
+            int               count)
+{
+  int bytes_read;
+  int start;
+  char *data;
+
+  _dbus_assert (count >= 0);
+
+  start = _dbus_string_get_length (buffer);
+
+  if (!_dbus_string_lengthen (buffer, count))
+    {
+      errno = ENOMEM;
+      return -1;
+    }
+
+  data = _dbus_string_get_data_len (buffer, start, count);
+
+ again:
+
+  bytes_read = read (fd, data, count);
+
+  if (bytes_read < 0)
+    {
+      if (errno == EINTR)
+        goto again;
+      else
+        {
+          /* put length back (note that this doesn't actually realloc anything) */
+          _dbus_string_set_length (buffer, start);
+          return -1;
+        }
+    }
+  else
+    {
+      /* put length back (doesn't actually realloc) */
+      _dbus_string_set_length (buffer, start + bytes_read);
+
+#if 0
+      if (bytes_read > 0)
+        _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
+#endif
+
+      return bytes_read;
+    }
+}
+
+/**
+ * Thin wrapper around the write() system call that writes a part of a
+ * DBusString and handles EINTR for you.
+ *
+ * @param fd the file descriptor to write
+ * @param buffer the buffer to write data from
+ * @param start the first byte in the buffer to write
+ * @param len the number of bytes to try to write
+ * @returns the number of bytes written or -1 on error
+ */
+int
+_dbus_write (int               fd,
+             const DBusString *buffer,
+             int               start,
+             int               len)
+{
+  const char *data;
+  int bytes_written;
+
+  data = _dbus_string_get_const_data_len (buffer, start, len);
+
+ again:
+
+  bytes_written = write (fd, data, len);
+
+  if (bytes_written < 0 && errno == EINTR)
+    goto again;
+
+#if 0
+  if (bytes_written > 0)
+    _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
+#endif
+
+  return bytes_written;
+}
+
+/**
+ * Like _dbus_write() but will use writev() if possible
+ * to write both buffers in sequence. The return value
+ * is the number of bytes written in the first buffer,
+ * plus the number written in the second. If the first
+ * buffer is written successfully and an error occurs
+ * writing the second, the number of bytes in the first
+ * is returned (i.e. the error is ignored), on systems that
+ * don't have writev. Handles EINTR for you.
+ * The second buffer may be #NULL.
+ *
+ * @param fd the file descriptor
+ * @param buffer1 first buffer
+ * @param start1 first byte to write in first buffer
+ * @param len1 number of bytes to write from first buffer
+ * @param buffer2 second buffer, or #NULL
+ * @param start2 first byte to write in second buffer
+ * @param len2 number of bytes to write in second buffer
+ * @returns total bytes written from both buffers, or -1 on error
+ */
+int
+_dbus_write_two (int               fd,
+                 const DBusString *buffer1,
+                 int               start1,
+                 int               len1,
+                 const DBusString *buffer2,
+                 int               start2,
+                 int               len2)
+{
+  _dbus_assert (buffer1 != NULL);
+  _dbus_assert (start1 >= 0);
+  _dbus_assert (start2 >= 0);
+  _dbus_assert (len1 >= 0);
+  _dbus_assert (len2 >= 0);
+
+#ifdef HAVE_WRITEV
+  {
+    struct iovec vectors[2];
+    const char *data1;
+    const char *data2;
+    int bytes_written;
+
+    data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
+
+    if (buffer2 != NULL)
+      data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
+    else
+      {
+        data2 = NULL;
+        start2 = 0;
+        len2 = 0;
+      }
+
+    vectors[0].iov_base = (char*) data1;
+    vectors[0].iov_len = len1;
+    vectors[1].iov_base = (char*) data2;
+    vectors[1].iov_len = len2;
+
+  again:
+
+    bytes_written = writev (fd,
+                            vectors,
+                            data2 ? 2 : 1);
+
+    if (bytes_written < 0 && errno == EINTR)
+      goto again;
+
+    return bytes_written;
+  }
+#else /* HAVE_WRITEV */
+  {
+    int ret1;
+
+    ret1 = _dbus_write (fd, buffer1, start1, len1);
+    if (ret1 == len1 && buffer2 != NULL)
+      {
+        ret2 = _dbus_write (fd, buffer2, start2, len2);
+        if (ret2 < 0)
+          ret2 = 0; /* we can't report an error as the first write was OK */
+
+        return ret1 + ret2;
+      }
+    else
+      return ret1;
+  }
+#endif /* !HAVE_WRITEV */
+}
+
+#define _DBUS_MAX_SUN_PATH_LENGTH 99
+
+/**
+ * @def _DBUS_MAX_SUN_PATH_LENGTH
+ *
+ * Maximum length of the path to a UNIX domain socket,
+ * sockaddr_un::sun_path member. POSIX requires that all systems
+ * support at least 100 bytes here, including the nul termination.
+ * We use 99 for the max value to allow for the nul.
+ *
+ * We could probably also do sizeof (addr.sun_path)
+ * but this way we are the same on all platforms
+ * which is probably a good idea.
+ */
+
+/**
+ * Creates a socket and connects it to the UNIX domain socket at the
+ * given path.  The connection fd is returned, and is set up as
+ * nonblocking.
+ *
+ * Uses abstract sockets instead of filesystem-linked sockets if
+ * requested (it's possible only on Linux; see "man 7 unix" on Linux).
+ * On non-Linux abstract socket usage always fails.
+ *
+ * This will set FD_CLOEXEC for the socket returned.
+ *
+ * @param path the path to UNIX domain socket
+ * @param abstract #TRUE to use abstract namespace
+ * @param error return location for error code
+ * @returns connection file descriptor or -1 on error
+ */
+int
+_dbus_connect_unix_socket (const char     *path,
+                           dbus_bool_t     abstract,
+                           DBusError      *error)
+{
+  int fd;
+  size_t path_len;
+  struct sockaddr_un addr;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
+                 path, abstract);
+
+
+  if (!_dbus_open_unix_socket (&fd, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET(error);
+      return -1;
+    }
+  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+
+  _DBUS_ZERO (addr);
+  addr.sun_family = AF_UNIX;
+  path_len = strlen (path);
+
+  if (abstract)
+    {
+#ifdef HAVE_ABSTRACT_SOCKETS
+      addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
+      path_len++; /* Account for the extra nul byte added to the start of sun_path */
+
+      if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
+        {
+          dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                      "Abstract socket name too long\n");
+          _dbus_close (fd, NULL);
+          return -1;
+	}
+
+      strncpy (&addr.sun_path[1], path, path_len);
+      /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
+#else /* HAVE_ABSTRACT_SOCKETS */
+      dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
+                      "Operating system does not support abstract socket namespace\n");
+      _dbus_close (fd, NULL);
+      return -1;
+#endif /* ! HAVE_ABSTRACT_SOCKETS */
+    }
+  else
+    {
+      if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
+        {
+          dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                      "Socket name too long\n");
+          _dbus_close (fd, NULL);
+          return -1;
+	}
+
+      strncpy (addr.sun_path, path, path_len);
+    }
+
+  if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (errno),
+                      "Failed to connect to socket %s: %s",
+                      path, _dbus_strerror (errno));
+
+      _dbus_close (fd, NULL);
+      return -1;
+    }
+
+  if (!_dbus_set_fd_nonblocking (fd, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+
+      _dbus_close (fd, NULL);
+      return -1;
+    }
+
+  return fd;
+}
+
+/**
+ * Creates a UNIX domain socket and connects it to the specified
+ * process to execute.
+ *
+ * This will set FD_CLOEXEC for the socket returned.
+ *
+ * @param path the path to the executable
+ * @param argv the argument list for the process to execute.
+ * argv[0] typically is identical to the path of the executable
+ * @param error return location for error code
+ * @returns connection file descriptor or -1 on error
+ */
+int
+_dbus_connect_exec (const char     *path,
+                    char *const    argv[],
+                    DBusError      *error)
+{
+  int fds[2];
+  pid_t pid;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  _dbus_verbose ("connecting to process %s\n", path);
+
+  if (socketpair (AF_UNIX, SOCK_STREAM
+#ifdef SOCK_CLOEXEC
+                  |SOCK_CLOEXEC
+#endif
+                  , 0, fds) < 0)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (errno),
+                      "Failed to create socket pair: %s",
+                      _dbus_strerror (errno));
+      return -1;
+    }
+
+  _dbus_fd_set_close_on_exec (fds[0]);
+  _dbus_fd_set_close_on_exec (fds[1]);
+
+  pid = fork ();
+  if (pid < 0)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (errno),
+                      "Failed to fork() to call %s: %s",
+                      path, _dbus_strerror (errno));
+      close (fds[0]);
+      close (fds[1]);
+      return -1;
+    }
+
+  if (pid == 0)
+    {
+      /* child */
+      close (fds[0]);
+
+      dup2 (fds[1], STDIN_FILENO);
+      dup2 (fds[1], STDOUT_FILENO);
+
+      if (fds[1] != STDIN_FILENO &&
+          fds[1] != STDOUT_FILENO)
+        close (fds[1]);
+
+      /* Inherit STDERR and the controlling terminal from the
+         parent */
+
+      _dbus_close_all ();
+
+      execvp (path, argv);
+
+      fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
+
+      _exit(1);
+    }
+
+  /* parent */
+  close (fds[1]);
+
+  if (!_dbus_set_fd_nonblocking (fds[0], error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+
+      close (fds[0]);
+      return -1;
+    }
+
+  return fds[0];
+}
+
+/**
+ * Enables or disables the reception of credentials on the given socket during
+ * the next message transmission.  This is only effective if the #LOCAL_CREDS
+ * system feature exists, in which case the other side of the connection does
+ * not have to do anything special to send the credentials.
+ *
+ * @param fd socket on which to change the #LOCAL_CREDS flag.
+ * @param on whether to enable or disable the #LOCAL_CREDS flag.
+ */
+static dbus_bool_t
+_dbus_set_local_creds (int fd, dbus_bool_t on)
+{
+  dbus_bool_t retval = TRUE;
+
+#if defined(HAVE_CMSGCRED)
+  /* NOOP just to make sure only one codepath is used
+   *      and to prefer CMSGCRED
+   */
+#elif defined(LOCAL_CREDS)
+  int val = on ? 1 : 0;
+  if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
+    {
+      _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
+      retval = FALSE;
+    }
+  else
+    _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
+                   on ? "enabled" : "disabled", fd);
+#endif
+
+  return retval;
+}
+
+/**
+ * Creates a socket and binds it to the given path,
+ * then listens on the socket. The socket is
+ * set to be nonblocking.
+ *
+ * Uses abstract sockets instead of filesystem-linked
+ * sockets if requested (it's possible only on Linux;
+ * see "man 7 unix" on Linux).
+ * On non-Linux abstract socket usage always fails.
+ *
+ * This will set FD_CLOEXEC for the socket returned
+ *
+ * @param path the socket name
+ * @param abstract #TRUE to use abstract namespace
+ * @param error return location for errors
+ * @returns the listening file descriptor or -1 on error
+ */
+int
+_dbus_listen_unix_socket (const char     *path,
+                          dbus_bool_t     abstract,
+                          DBusError      *error)
+{
+  int listen_fd;
+  struct sockaddr_un addr;
+  size_t path_len;
+  unsigned int reuseaddr;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  _dbus_verbose ("listening on unix socket %s abstract=%d\n",
+                 path, abstract);
+#ifdef ANDROID_MANAGED_SOCKET
+  if (strncmp (path, ANDROID_SOCKET_DIR"/", strlen(ANDROID_SOCKET_DIR"/")) == 0)
+    {
+      const char* suffix;
+      /* init has created a socket for us, pick it up from environ */
+      suffix = &path[strlen (ANDROID_SOCKET_DIR"/")];
+      listen_fd = android_get_control_socket (suffix);
+      if (listen_fd == -1)
+        {
+          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                "Could not obtain fd for android socket %s\n", suffix);
+          return -1;
+        }
+
+      _dbus_verbose ("Obtained fd for android socket %s\n", suffix);
+    }
+  else
+    {
+      dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+            "Not an android socket: %s\n", path);
+      return -1;
+    }
+#else
+
+  if (!_dbus_open_unix_socket (&listen_fd, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET(error);
+      return -1;
+    }
+  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+
+  _DBUS_ZERO (addr);
+  addr.sun_family = AF_UNIX;
+  path_len = strlen (path);
+
+  if (abstract)
+    {
+#ifdef HAVE_ABSTRACT_SOCKETS
+      /* remember that abstract names aren't nul-terminated so we rely
+       * on sun_path being filled in with zeroes above.
+       */
+      addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
+      path_len++; /* Account for the extra nul byte added to the start of sun_path */
+
+      if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
+        {
+          dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                      "Abstract socket name too long\n");
+          _dbus_close (listen_fd, NULL);
+          return -1;
+	}
+
+      strncpy (&addr.sun_path[1], path, path_len);
+      /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
+#else /* HAVE_ABSTRACT_SOCKETS */
+      dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
+                      "Operating system does not support abstract socket namespace\n");
+      _dbus_close (listen_fd, NULL);
+      return -1;
+#endif /* ! HAVE_ABSTRACT_SOCKETS */
+    }
+  else
+    {
+      /* Discussed security implications of this with Nalin,
+       * and we couldn't think of where it would kick our ass, but
+       * it still seems a bit sucky. It also has non-security suckage;
+       * really we'd prefer to exit if the socket is already in use.
+       * But there doesn't seem to be a good way to do this.
+       *
+       * Just to be extra careful, I threw in the stat() - clearly
+       * the stat() can't *fix* any security issue, but it at least
+       * avoids inadvertent/accidental data loss.
+       */
+      {
+        struct stat sb;
+
+        if (stat (path, &sb) == 0 &&
+            S_ISSOCK (sb.st_mode))
+          unlink (path);
+      }
+
+      if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
+        {
+          dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                      "Abstract socket name too long\n");
+          _dbus_close (listen_fd, NULL);
+          return -1;
+	}
+
+      strncpy (addr.sun_path, path, path_len);
+    }
+
+  reuseaddr = 1;
+  if (setsockopt  (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
+    {
+      _dbus_warn ("Failed to set socket option\"%s\": %s",
+                  path, _dbus_strerror (errno));
+    }
+
+  if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to bind socket \"%s\": %s",
+                      path, _dbus_strerror (errno));
+      _dbus_close (listen_fd, NULL);
+      return -1;
+    }
+
+#endif  /* android init managed sockets */
+
+  if (listen (listen_fd, 30 /* backlog */) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to listen on socket \"%s\": %s",
+                      path, _dbus_strerror (errno));
+      _dbus_close (listen_fd, NULL);
+      return -1;
+    }
+
+  if (!_dbus_set_local_creds (listen_fd, TRUE))
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to enable LOCAL_CREDS on socket \"%s\": %s",
+                      path, _dbus_strerror (errno));
+      close (listen_fd);
+      return -1;
+    }
+
+  if (!_dbus_set_fd_nonblocking (listen_fd, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      _dbus_close (listen_fd, NULL);
+      return -1;
+    }
+
+#ifndef ANDROID_MANAGED_SOCKET
+  /* Try opening up the permissions, but if we can't, just go ahead
+   * and continue, maybe it will be good enough.
+   */
+  if (!abstract && chmod (path, 0777) < 0)
+    _dbus_warn ("Could not set mode 0777 on socket %s\n",
+                path);
+#endif
+  
+  return listen_fd;
+}
+
+/**
+ * Acquires one or more sockets passed in from systemd. The sockets
+ * are set to be nonblocking.
+ *
+ * This will set FD_CLOEXEC for the sockets returned.
+ *
+ * @oaram fds the file descriptors
+ * @param error return location for errors
+ * @returns the number of file descriptors
+ */
+int
+_dbus_listen_systemd_sockets (int       **fds,
+                              DBusError *error)
+{
+  int r, n;
+  unsigned fd;
+  int *new_fds;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  n = sd_listen_fds (TRUE);
+  if (n < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (-n),
+                      "Failed to acquire systemd socket: %s",
+                      _dbus_strerror (-n));
+      return -1;
+    }
+
+  if (n <= 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                      "No socket received.");
+      return -1;
+    }
+
+  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
+    {
+      r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
+      if (r < 0)
+        {
+          dbus_set_error (error, _dbus_error_from_errno (-r),
+                          "Failed to verify systemd socket type: %s",
+                          _dbus_strerror (-r));
+          return -1;
+        }
+
+      if (!r)
+        {
+          dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
+                          "Passed socket has wrong type.");
+          return -1;
+        }
+    }
+
+  /* OK, the file descriptors are all good, so let's take posession of
+     them then. */
+
+  new_fds = dbus_new (int, n);
+  if (!new_fds)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                      "Failed to allocate file handle array.");
+      goto fail;
+    }
+
+  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
+    {
+      if (!_dbus_set_local_creds (fd, TRUE))
+        {
+          dbus_set_error (error, _dbus_error_from_errno (errno),
+                          "Failed to enable LOCAL_CREDS on systemd socket: %s",
+                          _dbus_strerror (errno));
+          goto fail;
+        }
+
+      if (!_dbus_set_fd_nonblocking (fd, error))
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          goto fail;
+        }
+
+      new_fds[fd - SD_LISTEN_FDS_START] = fd;
+    }
+
+  *fds = new_fds;
+  return n;
+
+ fail:
+
+  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
+    {
+      _dbus_close (fd, NULL);
+    }
+
+  dbus_free (new_fds);
+  return -1;
+}
+
+/**
+ * Creates a socket and connects to a socket at the given host
+ * and port. The connection fd is returned, and is set up as
+ * nonblocking.
+ *
+ * This will set FD_CLOEXEC for the socket returned
+ *
+ * @param host the host name to connect to
+ * @param port the port to connect to
+ * @param family the address family to listen on, NULL for all
+ * @param error return location for error code
+ * @returns connection file descriptor or -1 on error
+ */
+int
+_dbus_connect_tcp_socket (const char     *host,
+                          const char     *port,
+                          const char     *family,
+                          DBusError      *error)
+{
+    return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
+}
+
+int
+_dbus_connect_tcp_socket_with_nonce (const char     *host,
+                                     const char     *port,
+                                     const char     *family,
+                                     const char     *noncefile,
+                                     DBusError      *error)
+{
+  int saved_errno = 0;
+  int fd = -1, res;
+  struct addrinfo hints;
+  struct addrinfo *ai, *tmp;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+
+  _DBUS_ZERO (hints);
+
+  if (!family)
+    hints.ai_family = AF_UNSPEC;
+  else if (!strcmp(family, "ipv4"))
+    hints.ai_family = AF_INET;
+  else if (!strcmp(family, "ipv6"))
+    hints.ai_family = AF_INET6;
+  else
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_BAD_ADDRESS,
+                      "Unknown address family %s", family);
+      return -1;
+    }
+  hints.ai_protocol = IPPROTO_TCP;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_ADDRCONFIG;
+
+  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (errno),
+                      "Failed to lookup host/port: \"%s:%s\": %s (%d)",
+                      host, port, gai_strerror(res), res);
+      return -1;
+    }
+
+  tmp = ai;
+  while (tmp)
+    {
+      if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
+        {
+          freeaddrinfo(ai);
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          return -1;
+        }
+      _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+
+      if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
+        {
+          saved_errno = errno;
+          _dbus_close(fd, NULL);
+          fd = -1;
+          tmp = tmp->ai_next;
+          continue;
+        }
+
+      break;
+    }
+  freeaddrinfo(ai);
+
+  if (fd == -1)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (saved_errno),
+                      "Failed to connect to socket \"%s:%s\" %s",
+                      host, port, _dbus_strerror(saved_errno));
+      return -1;
+    }
+
+  if (noncefile != NULL)
+    {
+      DBusString noncefileStr;
+      dbus_bool_t ret;
+      _dbus_string_init_const (&noncefileStr, noncefile);
+      ret = _dbus_send_nonce (fd, &noncefileStr, error);
+      _dbus_string_free (&noncefileStr);
+
+      if (!ret)
+    {
+      _dbus_close (fd, NULL);
+          return -1;
+        }
+    }
+
+  if (!_dbus_set_fd_nonblocking (fd, error))
+    {
+      _dbus_close (fd, NULL);
+      return -1;
+    }
+
+  return fd;
+}
+
+/**
+ * Creates a socket and binds it to the given path, then listens on
+ * the socket. The socket is set to be nonblocking.  In case of port=0
+ * a random free port is used and returned in the port parameter.
+ * If inaddr_any is specified, the hostname is ignored.
+ *
+ * This will set FD_CLOEXEC for the socket returned
+ *
+ * @param host the host name to listen on
+ * @param port the port to listen on, if zero a free port will be used
+ * @param family the address family to listen on, NULL for all
+ * @param retport string to return the actual port listened on
+ * @param fds_p location to store returned file descriptors
+ * @param error return location for errors
+ * @returns the number of listening file descriptors or -1 on error
+ */
+int
+_dbus_listen_tcp_socket (const char     *host,
+                         const char     *port,
+                         const char     *family,
+                         DBusString     *retport,
+                         int           **fds_p,
+                         DBusError      *error)
+{
+  int saved_errno;
+  int nlisten_fd = 0, *listen_fd = NULL, res, i;
+  struct addrinfo hints;
+  struct addrinfo *ai, *tmp;
+  unsigned int reuseaddr;
+
+  *fds_p = NULL;
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  _DBUS_ZERO (hints);
+
+  if (!family)
+    hints.ai_family = AF_UNSPEC;
+  else if (!strcmp(family, "ipv4"))
+    hints.ai_family = AF_INET;
+  else if (!strcmp(family, "ipv6"))
+    hints.ai_family = AF_INET6;
+  else
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_BAD_ADDRESS,
+                      "Unknown address family %s", family);
+      return -1;
+    }
+
+  hints.ai_protocol = IPPROTO_TCP;
+  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
+
+ redo_lookup_with_port:
+  ai = NULL;
+  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (errno),
+                      "Failed to lookup host/port: \"%s:%s\": %s (%d)",
+                      host ? host : "*", port, gai_strerror(res), res);
+      goto failed;
+    }
+
+  tmp = ai;
+  while (tmp)
+    {
+      int fd = -1, *newlisten_fd;
+      if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
+        {
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          goto failed;
+        }
+      _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+
+      reuseaddr = 1;
+      if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
+        {
+          _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
+                      host ? host : "*", port, _dbus_strerror (errno));
+        }
+
+      if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
+        {
+          saved_errno = errno;
+          _dbus_close(fd, NULL);
+          if (saved_errno == EADDRINUSE)
+            {
+              /* Depending on kernel policy, it may or may not
+                 be neccessary to bind to both IPv4 & 6 addresses
+                 so ignore EADDRINUSE here */
+              tmp = tmp->ai_next;
+              continue;
+            }
+          dbus_set_error (error, _dbus_error_from_errno (saved_errno),
+                          "Failed to bind socket \"%s:%s\": %s",
+                          host ? host : "*", port, _dbus_strerror (saved_errno));
+          goto failed;
+        }
+
+      if (listen (fd, 30 /* backlog */) < 0)
+        {
+          saved_errno = errno;
+          _dbus_close (fd, NULL);
+          dbus_set_error (error, _dbus_error_from_errno (saved_errno),
+                          "Failed to listen on socket \"%s:%s\": %s",
+                          host ? host : "*", port, _dbus_strerror (saved_errno));
+          goto failed;
+        }
+
+      newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
+      if (!newlisten_fd)
+        {
+          saved_errno = errno;
+          _dbus_close (fd, NULL);
+          dbus_set_error (error, _dbus_error_from_errno (saved_errno),
+                          "Failed to allocate file handle array: %s",
+                          _dbus_strerror (saved_errno));
+          goto failed;
+        }
+      listen_fd = newlisten_fd;
+      listen_fd[nlisten_fd] = fd;
+      nlisten_fd++;
+
+      if (!_dbus_string_get_length(retport))
+        {
+          /* If the user didn't specify a port, or used 0, then
+             the kernel chooses a port. After the first address
+             is bound to, we need to force all remaining addresses
+             to use the same port */
+          if (!port || !strcmp(port, "0"))
+            {
+              int result;
+              struct sockaddr_storage addr;
+              socklen_t addrlen;
+              char portbuf[50];
+
+              addrlen = sizeof(addr);
+              result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
+
+              if (result == -1 ||
+                  (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
+                                      portbuf, sizeof(portbuf),
+                                      NI_NUMERICHOST)) != 0)
+                {
+                  dbus_set_error (error, _dbus_error_from_errno (errno),
+                                  "Failed to resolve port \"%s:%s\": %s (%s)",
+                                  host ? host : "*", port, gai_strerror(res), res);
+                  goto failed;
+                }
+              if (!_dbus_string_append(retport, portbuf))
+                {
+                  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+                  goto failed;
+                }
+
+              /* Release current address list & redo lookup */
+              port = _dbus_string_get_const_data(retport);
+              freeaddrinfo(ai);
+              goto redo_lookup_with_port;
+            }
+          else
+            {
+              if (!_dbus_string_append(retport, port))
+                {
+                    dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+                    goto failed;
+                }
+            }
+        }
+
+      tmp = tmp->ai_next;
+    }
+  freeaddrinfo(ai);
+  ai = NULL;
+
+  if (!nlisten_fd)
+    {
+      errno = EADDRINUSE;
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to bind socket \"%s:%s\": %s",
+                      host ? host : "*", port, _dbus_strerror (errno));
+      goto failed;
+    }
+
+  for (i = 0 ; i < nlisten_fd ; i++)
+    {
+      if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
+        {
+          goto failed;
+        }
+    }
+
+  *fds_p = listen_fd;
+
+  return nlisten_fd;
+
+ failed:
+  if (ai)
+    freeaddrinfo(ai);
+  for (i = 0 ; i < nlisten_fd ; i++)
+    _dbus_close(listen_fd[i], NULL);
+  dbus_free(listen_fd);
+  return -1;
+}
+
+static dbus_bool_t
+write_credentials_byte (int             server_fd,
+                        DBusError      *error)
+{
+  int bytes_written;
+  char buf[1] = { '\0' };
+#if defined(HAVE_CMSGCRED)
+  union {
+	  struct cmsghdr hdr;
+	  char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
+  } cmsg;
+  struct iovec iov;
+  struct msghdr msg;
+  iov.iov_base = buf;
+  iov.iov_len = 1;
+
+  _DBUS_ZERO(msg);
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+
+  msg.msg_control = (caddr_t) &cmsg;
+  msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
+  _DBUS_ZERO(cmsg);
+  cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
+  cmsg.hdr.cmsg_level = SOL_SOCKET;
+  cmsg.hdr.cmsg_type = SCM_CREDS;
+#endif
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ again:
+
+#if defined(HAVE_CMSGCRED)
+  bytes_written = sendmsg (server_fd, &msg, 0
+#if HAVE_DECL_MSG_NOSIGNAL
+                           |MSG_NOSIGNAL
+#endif
+                           );
+#else
+  bytes_written = send (server_fd, buf, 1, 0
+#if HAVE_DECL_MSG_NOSIGNAL
+                        |MSG_NOSIGNAL
+#endif
+                        );
+#endif
+
+  if (bytes_written < 0 && errno == EINTR)
+    goto again;
+
+  if (bytes_written < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to write credentials byte: %s",
+                     _dbus_strerror (errno));
+      return FALSE;
+    }
+  else if (bytes_written == 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_IO_ERROR,
+                      "wrote zero bytes writing credentials byte");
+      return FALSE;
+    }
+  else
+    {
+      _dbus_assert (bytes_written == 1);
+      _dbus_verbose ("wrote credentials byte\n");
+      return TRUE;
+    }
+}
+
+/**
+ * Reads a single byte which must be nul (an error occurs otherwise),
+ * and reads unix credentials if available. Clears the credentials
+ * object, then adds pid/uid if available, so any previous credentials
+ * stored in the object are lost.
+ *
+ * Return value indicates whether a byte was read, not whether
+ * we got valid credentials. On some systems, such as Linux,
+ * reading/writing the byte isn't actually required, but we do it
+ * anyway just to avoid multiple codepaths.
+ *
+ * Fails if no byte is available, so you must select() first.
+ *
+ * The point of the byte is that on some systems we have to
+ * use sendmsg()/recvmsg() to transmit credentials.
+ *
+ * @param client_fd the client file descriptor
+ * @param credentials object to add client credentials to
+ * @param error location to store error code
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_read_credentials_socket  (int              client_fd,
+                                DBusCredentials *credentials,
+                                DBusError       *error)
+{
+  struct msghdr msg;
+  struct iovec iov;
+  char buf;
+  dbus_uid_t uid_read;
+  dbus_pid_t pid_read;
+  int bytes_read;
+
+#ifdef HAVE_CMSGCRED
+  union {
+    struct cmsghdr hdr;
+    char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
+  } cmsg;
+
+#elif defined(LOCAL_CREDS)
+  struct {
+    struct cmsghdr hdr;
+    struct sockcred cred;
+  } cmsg;
+#endif
+
+  uid_read = DBUS_UID_UNSET;
+  pid_read = DBUS_PID_UNSET;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  /* The POSIX spec certainly doesn't promise this, but
+   * we need these assertions to fail as soon as we're wrong about
+   * it so we can do the porting fixups
+   */
+  _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
+  _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
+  _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
+
+  _dbus_credentials_clear (credentials);
+
+  /* Systems supporting LOCAL_CREDS are configured to have this feature
+   * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting
+   * the connection.  Therefore, the received message must carry the
+   * credentials information without doing anything special.
+   */
+
+  iov.iov_base = &buf;
+  iov.iov_len = 1;
+
+  _DBUS_ZERO(msg);
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+
+#if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
+  _DBUS_ZERO(cmsg);
+  msg.msg_control = (caddr_t) &cmsg;
+  msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
+#endif
+
+ again:
+  bytes_read = recvmsg (client_fd, &msg, 0);
+
+  if (bytes_read < 0)
+    {
+      if (errno == EINTR)
+	goto again;
+
+      /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
+       * normally only call read_credentials if the socket was ready
+       * for reading
+       */
+
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to read credentials byte: %s",
+                      _dbus_strerror (errno));
+      return FALSE;
+    }
+  else if (bytes_read == 0)
+    {
+      /* this should not happen unless we are using recvmsg wrong,
+       * so is essentially here for paranoia
+       */
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Failed to read credentials byte (zero-length read)");
+      return FALSE;
+    }
+  else if (buf != '\0')
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Credentials byte was not nul");
+      return FALSE;
+    }
+
+#if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
+  if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
+		  || cmsg.hdr.cmsg_type != SCM_CREDS)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Message from recvmsg() was not SCM_CREDS");
+      return FALSE;
+    }
+#endif
+
+  _dbus_verbose ("read credentials byte\n");
+
+  {
+#ifdef SO_PEERCRED
+#ifdef __OpenBSD__
+    struct sockpeercred cr;
+#else
+    struct ucred cr;
+#endif
+    int cr_len = sizeof (cr);
+
+    if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
+	cr_len == sizeof (cr))
+      {
+	pid_read = cr.pid;
+	uid_read = cr.uid;
+      }
+    else
+      {
+	_dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n",
+		       cr_len, (int) sizeof (cr), _dbus_strerror (errno));
+      }
+#elif defined(HAVE_CMSGCRED)
+    struct cmsgcred *cred;
+
+    cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
+    pid_read = cred->cmcred_pid;
+    uid_read = cred->cmcred_euid;
+#elif defined(LOCAL_CREDS)
+    pid_read = DBUS_PID_UNSET;
+    uid_read = cmsg.cred.sc_uid;
+    /* Since we have already got the credentials from this socket, we can
+     * disable its LOCAL_CREDS flag if it was ever set. */
+    _dbus_set_local_creds (client_fd, FALSE);
+#elif defined(HAVE_GETPEEREID)
+    uid_t euid;
+    gid_t egid;
+    if (getpeereid (client_fd, &euid, &egid) == 0)
+      {
+        uid_read = euid;
+      }
+    else
+      {
+        _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
+      }
+#elif defined(HAVE_GETPEERUCRED)
+    ucred_t * ucred = NULL;
+    if (getpeerucred (client_fd, &ucred) == 0)
+      {
+        pid_read = ucred_getpid (ucred);
+        uid_read = ucred_geteuid (ucred);
+#ifdef HAVE_ADT
+        /* generate audit session data based on socket ucred */
+        adt_session_data_t *adth = NULL;
+        adt_export_data_t *data = NULL;
+        size_t size = 0;
+        if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
+          {
+            _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
+          }
+        else
+          {
+            if (adt_set_from_ucred (adth, ucred, ADT_NEW))
+              {
+                _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
+              }
+            else
+              {
+                size = adt_export_session_data (adth, &data);
+                if (size <= 0)
+                  {
+                    _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
+                  }
+                else
+                  {
+                    _dbus_credentials_add_adt_audit_data (credentials, data, size);
+                    free (data);
+                  }
+              }
+            (void) adt_end_session (adth);
+          }
+#endif /* HAVE_ADT */
+      }
+    else
+      {
+        _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
+      }
+    if (ucred != NULL)
+      ucred_free (ucred);
+#else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
+    _dbus_verbose ("Socket credentials not supported on this OS\n");
+#endif
+  }
+
+  _dbus_verbose ("Credentials:"
+                 "  pid "DBUS_PID_FORMAT
+                 "  uid "DBUS_UID_FORMAT
+                 "\n",
+		 pid_read,
+		 uid_read);
+
+  if (pid_read != DBUS_PID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
+        {
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+    }
+
+  if (uid_read != DBUS_UID_UNSET)
+    {
+      if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
+        {
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+    }
+
+  return TRUE;
+}
+
+/**
+ * Sends a single nul byte with our UNIX credentials as ancillary
+ * data.  Returns #TRUE if the data was successfully written.  On
+ * systems that don't support sending credentials, just writes a byte,
+ * doesn't send any credentials.  On some systems, such as Linux,
+ * reading/writing the byte isn't actually required, but we do it
+ * anyway just to avoid multiple codepaths.
+ *
+ * Fails if no byte can be written, so you must select() first.
+ *
+ * The point of the byte is that on some systems we have to
+ * use sendmsg()/recvmsg() to transmit credentials.
+ *
+ * @param server_fd file descriptor for connection to server
+ * @param error return location for error code
+ * @returns #TRUE if the byte was sent
+ */
+dbus_bool_t
+_dbus_send_credentials_socket  (int              server_fd,
+                                DBusError       *error)
+{
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (write_credentials_byte (server_fd, error))
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/**
+ * Accepts a connection on a listening socket.
+ * Handles EINTR for you.
+ *
+ * This will enable FD_CLOEXEC for the returned socket.
+ *
+ * @param listen_fd the listen file descriptor
+ * @returns the connection fd of the client, or -1 on error
+ */
+int
+_dbus_accept  (int listen_fd)
+{
+  int client_fd;
+  struct sockaddr addr;
+  socklen_t addrlen;
+#ifdef HAVE_ACCEPT4
+  dbus_bool_t cloexec_done;
+#endif
+
+  addrlen = sizeof (addr);
+
+ retry:
+
+#ifdef HAVE_ACCEPT4
+  /* We assume that if accept4 is available SOCK_CLOEXEC is too */
+  client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
+  cloexec_done = client_fd >= 0;
+
+  if (client_fd < 0 && errno == ENOSYS)
+#endif
+    {
+      client_fd = accept (listen_fd, &addr, &addrlen);
+    }
+
+  if (client_fd < 0)
+    {
+      if (errno == EINTR)
+        goto retry;
+    }
+
+  _dbus_verbose ("client fd %d accepted\n", client_fd);
+
+#ifdef HAVE_ACCEPT4
+  if (!cloexec_done)
+#endif
+    {
+      _dbus_fd_set_close_on_exec(client_fd);
+    }
+
+  return client_fd;
+}
+
+/**
+ * Checks to make sure the given directory is
+ * private to the user
+ *
+ * @param dir the name of the directory
+ * @param error error return
+ * @returns #FALSE on failure
+ **/
+dbus_bool_t
+_dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
+{
+  const char *directory;
+  struct stat sb;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  directory = _dbus_string_get_const_data (dir);
+
+  if (stat (directory, &sb) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "%s", _dbus_strerror (errno));
+
+      return FALSE;
+    }
+
+  if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
+      (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                     "%s directory is not private to the user", directory);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+fill_user_info_from_passwd (struct passwd *p,
+                            DBusUserInfo  *info,
+                            DBusError     *error)
+{
+  _dbus_assert (p->pw_name != NULL);
+  _dbus_assert (p->pw_dir != NULL);
+
+  info->uid = p->pw_uid;
+  info->primary_gid = p->pw_gid;
+  info->username = _dbus_strdup (p->pw_name);
+  info->homedir = _dbus_strdup (p->pw_dir);
+
+  if (info->username == NULL ||
+      info->homedir == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+fill_user_info (DBusUserInfo       *info,
+                dbus_uid_t          uid,
+                const DBusString   *username,
+                DBusError          *error)
+{
+  const char *username_c;
+
+  /* exactly one of username/uid provided */
+  _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
+  _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
+
+  info->uid = DBUS_UID_UNSET;
+  info->primary_gid = DBUS_GID_UNSET;
+  info->group_ids = NULL;
+  info->n_group_ids = 0;
+  info->username = NULL;
+  info->homedir = NULL;
+
+  if (username != NULL)
+    username_c = _dbus_string_get_const_data (username);
+  else
+    username_c = NULL;
+
+  /* For now assuming that the getpwnam() and getpwuid() flavors
+   * are always symmetrical, if not we have to add more configure
+   * checks
+   */
+
+#if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
+  {
+    struct passwd *p;
+    int result;
+    size_t buflen;
+    char *buf;
+    struct passwd p_str;
+
+    /* retrieve maximum needed size for buf */
+    buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
+
+    /* sysconf actually returns a long, but everything else expects size_t,
+     * so just recast here.
+     * https://bugs.freedesktop.org/show_bug.cgi?id=17061
+     */
+    if ((long) buflen <= 0)
+      buflen = 1024;
+
+    result = -1;
+    while (1)
+      {
+        buf = dbus_malloc (buflen);
+        if (buf == NULL)
+          {
+            dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+            return FALSE;
+          }
+
+        p = NULL;
+#ifdef HAVE_POSIX_GETPWNAM_R
+        if (uid != DBUS_UID_UNSET)
+          result = getpwuid_r (uid, &p_str, buf, buflen,
+                               &p);
+        else
+          result = getpwnam_r (username_c, &p_str, buf, buflen,
+                               &p);
+#else
+        if (uid != DBUS_UID_UNSET)
+          p = getpwuid_r (uid, &p_str, buf, buflen);
+        else
+          p = getpwnam_r (username_c, &p_str, buf, buflen);
+        result = 0;
+#endif /* !HAVE_POSIX_GETPWNAM_R */
+        //Try a bigger buffer if ERANGE was returned
+        if (result == ERANGE && buflen < 512 * 1024)
+          {
+            dbus_free (buf);
+            buflen *= 2;
+          }
+        else
+          {
+            break;
+          }
+      }
+    if (result == 0 && p == &p_str)
+      {
+        if (!fill_user_info_from_passwd (p, info, error))
+          {
+            dbus_free (buf);
+            return FALSE;
+          }
+        dbus_free (buf);
+      }
+    else
+      {
+        dbus_set_error (error, _dbus_error_from_errno (errno),
+                        "User \"%s\" unknown or no memory to allocate password entry\n",
+                        username_c ? username_c : "???");
+        _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
+        dbus_free (buf);
+        return FALSE;
+      }
+  }
+#else /* ! HAVE_GETPWNAM_R */
+  {
+    /* I guess we're screwed on thread safety here */
+    struct passwd *p;
+
+    if (uid != DBUS_UID_UNSET)
+      p = getpwuid (uid);
+    else
+      p = getpwnam (username_c);
+
+    if (p != NULL)
+      {
+        if (!fill_user_info_from_passwd (p, info, error))
+          {
+            return FALSE;
+          }
+      }
+    else
+      {
+        dbus_set_error (error, _dbus_error_from_errno (errno),
+                        "User \"%s\" unknown or no memory to allocate password entry\n",
+                        username_c ? username_c : "???");
+        _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
+        return FALSE;
+      }
+  }
+#endif  /* ! HAVE_GETPWNAM_R */
+
+  /* Fill this in so we can use it to get groups */
+  username_c = info->username;
+
+#ifdef HAVE_GETGROUPLIST
+  {
+    gid_t *buf;
+    int buf_count;
+    int i;
+    int initial_buf_count;
+
+    initial_buf_count = 17;
+    buf_count = initial_buf_count;
+    buf = dbus_new (gid_t, buf_count);
+    if (buf == NULL)
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        goto failed;
+      }
+
+    if (getgrouplist (username_c,
+                      info->primary_gid,
+                      buf, &buf_count) < 0)
+      {
+        gid_t *new;
+        /* Presumed cause of negative return code: buf has insufficient
+           entries to hold the entire group list. The Linux behavior in this
+           case is to pass back the actual number of groups in buf_count, but
+           on Mac OS X 10.5, buf_count is unhelpfully left alone.
+           So as a hack, try to help out a bit by guessing a larger
+           number of groups, within reason.. might still fail, of course,
+           but we can at least print a more informative message.  I looked up
+           the "right way" to do this by downloading Apple's own source code
+           for the "id" command, and it turns out that they use an
+           undocumented library function getgrouplist_2 (!) which is not
+           declared in any header in /usr/include (!!). That did not seem
+           like the way to go here.
+        */
+        if (buf_count == initial_buf_count)
+          {
+            buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
+          }
+        new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
+        if (new == NULL)
+          {
+            dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+            dbus_free (buf);
+            goto failed;
+          }
+
+        buf = new;
+
+        errno = 0;
+        if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
+          {
+            if (errno == 0)
+              {
+                _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
+                            username_c, buf_count, buf_count);
+              }
+            else
+              {
+                dbus_set_error (error,
+                                _dbus_error_from_errno (errno),
+                                "Failed to get groups for username \"%s\" primary GID "
+                                DBUS_GID_FORMAT ": %s\n",
+                                username_c, info->primary_gid,
+                                _dbus_strerror (errno));
+                dbus_free (buf);
+                goto failed;
+              }
+          }
+      }
+
+    info->group_ids = dbus_new (dbus_gid_t, buf_count);
+    if (info->group_ids == NULL)
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        dbus_free (buf);
+        goto failed;
+      }
+
+    for (i = 0; i < buf_count; ++i)
+      info->group_ids[i] = buf[i];
+
+    info->n_group_ids = buf_count;
+
+    dbus_free (buf);
+  }
+#else  /* HAVE_GETGROUPLIST */
+  {
+    /* We just get the one group ID */
+    info->group_ids = dbus_new (dbus_gid_t, 1);
+    if (info->group_ids == NULL)
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        goto failed;
+      }
+
+    info->n_group_ids = 1;
+
+    (info->group_ids)[0] = info->primary_gid;
+  }
+#endif /* HAVE_GETGROUPLIST */
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  return TRUE;
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  return FALSE;
+}
+
+/**
+ * Gets user info for the given username.
+ *
+ * @param info user info object to initialize
+ * @param username the username
+ * @param error error return
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_user_info_fill (DBusUserInfo     *info,
+                      const DBusString *username,
+                      DBusError        *error)
+{
+  return fill_user_info (info, DBUS_UID_UNSET,
+                         username, error);
+}
+
+/**
+ * Gets user info for the given user ID.
+ *
+ * @param info user info object to initialize
+ * @param uid the user ID
+ * @param error error return
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_user_info_fill_uid (DBusUserInfo *info,
+                          dbus_uid_t    uid,
+                          DBusError    *error)
+{
+  return fill_user_info (info, uid,
+                         NULL, error);
+}
+
+/**
+ * Adds the credentials of the current process to the
+ * passed-in credentials object.
+ *
+ * @param credentials credentials to add to
+ * @returns #FALSE if no memory; does not properly roll back on failure, so only some credentials may have been added
+ */
+dbus_bool_t
+_dbus_credentials_add_from_current_process (DBusCredentials *credentials)
+{
+  /* The POSIX spec certainly doesn't promise this, but
+   * we need these assertions to fail as soon as we're wrong about
+   * it so we can do the porting fixups
+   */
+  _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
+  _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
+  _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
+
+  if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
+    return FALSE;
+  if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * Append to the string the identity we would like to have when we
+ * authenticate, on UNIX this is the current process UID and on
+ * Windows something else, probably a Windows SID string.  No escaping
+ * is required, that is done in dbus-auth.c. The username here
+ * need not be anything human-readable, it can be the machine-readable
+ * form i.e. a user id.
+ *
+ * @param str the string to append to
+ * @returns #FALSE on no memory
+ */
+dbus_bool_t
+_dbus_append_user_from_current_process (DBusString *str)
+{
+  return _dbus_string_append_uint (str,
+                                   _dbus_geteuid ());
+}
+
+/**
+ * Gets our process ID
+ * @returns process ID
+ */
+dbus_pid_t
+_dbus_getpid (void)
+{
+  return getpid ();
+}
+
+/** Gets our UID
+ * @returns process UID
+ */
+dbus_uid_t
+_dbus_getuid (void)
+{
+  return getuid ();
+}
+
+/** Gets our effective UID
+ * @returns process effective UID
+ */
+dbus_uid_t
+_dbus_geteuid (void)
+{
+  return geteuid ();
+}
+
+/**
+ * The only reason this is separate from _dbus_getpid() is to allow it
+ * on Windows for logging but not for other purposes.
+ *
+ * @returns process ID to put in log messages
+ */
+unsigned long
+_dbus_pid_for_log (void)
+{
+  return getpid ();
+}
+
+/**
+ * Gets a UID from a UID string.
+ *
+ * @param uid_str the UID in string form
+ * @param uid UID to fill in
+ * @returns #TRUE if successfully filled in UID
+ */
+dbus_bool_t
+_dbus_parse_uid (const DBusString      *uid_str,
+                 dbus_uid_t            *uid)
+{
+  int end;
+  long val;
+
+  if (_dbus_string_get_length (uid_str) == 0)
+    {
+      _dbus_verbose ("UID string was zero length\n");
+      return FALSE;
+    }
+
+  val = -1;
+  end = 0;
+  if (!_dbus_string_parse_int (uid_str, 0, &val,
+                               &end))
+    {
+      _dbus_verbose ("could not parse string as a UID\n");
+      return FALSE;
+    }
+
+  if (end != _dbus_string_get_length (uid_str))
+    {
+      _dbus_verbose ("string contained trailing stuff after UID\n");
+      return FALSE;
+    }
+
+  *uid = val;
+
+  return TRUE;
+}
+
+#if !DBUS_USE_SYNC
+_DBUS_DEFINE_GLOBAL_LOCK (atomic);
+#endif
+
+/**
+ * Atomically increments an integer
+ *
+ * @param atomic pointer to the integer to increment
+ * @returns the value before incrementing
+ */
+dbus_int32_t
+_dbus_atomic_inc (DBusAtomic *atomic)
+{
+#if DBUS_USE_SYNC
+  return __sync_add_and_fetch(&atomic->value, 1)-1;
+#else
+  dbus_int32_t res;
+  _DBUS_LOCK (atomic);
+  res = atomic->value;
+  atomic->value += 1;
+  _DBUS_UNLOCK (atomic);
+  return res;
+#endif
+}
+
+/**
+ * Atomically decrement an integer
+ *
+ * @param atomic pointer to the integer to decrement
+ * @returns the value before decrementing
+ */
+dbus_int32_t
+_dbus_atomic_dec (DBusAtomic *atomic)
+{
+#if DBUS_USE_SYNC
+  return __sync_sub_and_fetch(&atomic->value, 1)+1;
+#else
+  dbus_int32_t res;
+
+  _DBUS_LOCK (atomic);
+  res = atomic->value;
+  atomic->value -= 1;
+  _DBUS_UNLOCK (atomic);
+  return res;
+#endif
+}
+
+/**
+ * Atomically get the value of an integer. It may change at any time
+ * thereafter, so this is mostly only useful for assertions.
+ *
+ * @param atomic pointer to the integer to get
+ * @returns the value at this moment
+ */
+dbus_int32_t
+_dbus_atomic_get (DBusAtomic *atomic)
+{
+#if DBUS_USE_SYNC
+  __sync_synchronize ();
+  return atomic->value;
+#else
+  dbus_int32_t res;
+
+  _DBUS_LOCK (atomic);
+  res = atomic->value;
+  _DBUS_UNLOCK (atomic);
+  return res;
+#endif
+}
+
+/**
+ * Wrapper for poll().
+ *
+ * @param fds the file descriptors to poll
+ * @param n_fds number of descriptors in the array
+ * @param timeout_milliseconds timeout or -1 for infinite
+ * @returns numbers of fds with revents, or <0 on error
+ */
+int
+_dbus_poll (DBusPollFD *fds,
+            int         n_fds,
+            int         timeout_milliseconds)
+{
+#if defined(HAVE_POLL) && !defined(BROKEN_POLL)
+  /* This big thing is a constant expression and should get optimized
+   * out of existence. So it's more robust than a configure check at
+   * no cost.
+   */
+  if (_DBUS_POLLIN == POLLIN &&
+      _DBUS_POLLPRI == POLLPRI &&
+      _DBUS_POLLOUT == POLLOUT &&
+      _DBUS_POLLERR == POLLERR &&
+      _DBUS_POLLHUP == POLLHUP &&
+      _DBUS_POLLNVAL == POLLNVAL &&
+      sizeof (DBusPollFD) == sizeof (struct pollfd) &&
+      _DBUS_STRUCT_OFFSET (DBusPollFD, fd) ==
+      _DBUS_STRUCT_OFFSET (struct pollfd, fd) &&
+      _DBUS_STRUCT_OFFSET (DBusPollFD, events) ==
+      _DBUS_STRUCT_OFFSET (struct pollfd, events) &&
+      _DBUS_STRUCT_OFFSET (DBusPollFD, revents) ==
+      _DBUS_STRUCT_OFFSET (struct pollfd, revents))
+    {
+      return poll ((struct pollfd*) fds,
+                   n_fds,
+                   timeout_milliseconds);
+    }
+  else
+    {
+      /* We have to convert the DBusPollFD to an array of
+       * struct pollfd, poll, and convert back.
+       */
+      _dbus_warn ("didn't implement poll() properly for this system yet\n");
+      return -1;
+    }
+#else /* ! HAVE_POLL */
+
+  fd_set read_set, write_set, err_set;
+  int max_fd = 0;
+  int i;
+  struct timeval tv;
+  int ready;
+
+  FD_ZERO (&read_set);
+  FD_ZERO (&write_set);
+  FD_ZERO (&err_set);
+
+  for (i = 0; i < n_fds; i++)
+    {
+      DBusPollFD *fdp = &fds[i];
+
+      if (fdp->events & _DBUS_POLLIN)
+	FD_SET (fdp->fd, &read_set);
+
+      if (fdp->events & _DBUS_POLLOUT)
+	FD_SET (fdp->fd, &write_set);
+
+      FD_SET (fdp->fd, &err_set);
+
+      max_fd = MAX (max_fd, fdp->fd);
+    }
+
+  tv.tv_sec = timeout_milliseconds / 1000;
+  tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
+
+  ready = select (max_fd + 1, &read_set, &write_set, &err_set,
+                  timeout_milliseconds < 0 ? NULL : &tv);
+
+  if (ready > 0)
+    {
+      for (i = 0; i < n_fds; i++)
+	{
+	  DBusPollFD *fdp = &fds[i];
+
+	  fdp->revents = 0;
+
+	  if (FD_ISSET (fdp->fd, &read_set))
+	    fdp->revents |= _DBUS_POLLIN;
+
+	  if (FD_ISSET (fdp->fd, &write_set))
+	    fdp->revents |= _DBUS_POLLOUT;
+
+	  if (FD_ISSET (fdp->fd, &err_set))
+	    fdp->revents |= _DBUS_POLLERR;
+	}
+    }
+
+  return ready;
+#endif
+}
+
+/**
+ * Get current time, as in gettimeofday(). Use the monotonic clock if
+ * available, to avoid problems when the system time changes.
+ *
+ * @param tv_sec return location for number of seconds
+ * @param tv_usec return location for number of microseconds
+ */
+void
+_dbus_get_monotonic_time (long *tv_sec,
+                          long *tv_usec)
+{
+#ifdef HAVE_MONOTONIC_CLOCK
+  struct timespec ts;
+  clock_gettime (CLOCK_MONOTONIC, &ts);
+
+  if (tv_sec)
+    *tv_sec = ts.tv_sec;
+  if (tv_usec)
+    *tv_usec = ts.tv_nsec / 1000;
+#else
+  struct timeval t;
+
+  gettimeofday (&t, NULL);
+
+  if (tv_sec)
+    *tv_sec = t.tv_sec;
+  if (tv_usec)
+    *tv_usec = t.tv_usec;
+#endif
+}
+
+/**
+ * Get current time, as in gettimeofday(). Never uses the monotonic
+ * clock.
+ *
+ * @param tv_sec return location for number of seconds
+ * @param tv_usec return location for number of microseconds
+ */
+void
+_dbus_get_real_time (long *tv_sec,
+                     long *tv_usec)
+{
+  struct timeval t;
+
+  gettimeofday (&t, NULL);
+
+  if (tv_sec)
+    *tv_sec = t.tv_sec;
+  if (tv_usec)
+    *tv_usec = t.tv_usec;
+}
+
+/**
+ * Creates a directory; succeeds if the directory
+ * is created or already existed.
+ *
+ * @param filename directory filename
+ * @param error initialized error object
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_create_directory (const DBusString *filename,
+                        DBusError        *error)
+{
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  filename_c = _dbus_string_get_const_data (filename);
+
+  if (mkdir (filename_c, 0700) < 0)
+    {
+      if (errno == EEXIST)
+        return TRUE;
+
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Failed to create directory %s: %s\n",
+                      filename_c, _dbus_strerror (errno));
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
+/**
+ * Appends the given filename to the given directory.
+ *
+ * @todo it might be cute to collapse multiple '/' such as "foo//"
+ * concat "//bar"
+ *
+ * @param dir the directory name
+ * @param next_component the filename
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_concat_dir_and_file (DBusString       *dir,
+                           const DBusString *next_component)
+{
+  dbus_bool_t dir_ends_in_slash;
+  dbus_bool_t file_starts_with_slash;
+
+  if (_dbus_string_get_length (dir) == 0 ||
+      _dbus_string_get_length (next_component) == 0)
+    return TRUE;
+
+  dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
+                                                    _dbus_string_get_length (dir) - 1);
+
+  file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
+
+  if (dir_ends_in_slash && file_starts_with_slash)
+    {
+      _dbus_string_shorten (dir, 1);
+    }
+  else if (!(dir_ends_in_slash || file_starts_with_slash))
+    {
+      if (!_dbus_string_append_byte (dir, '/'))
+        return FALSE;
+    }
+
+  return _dbus_string_copy (next_component, 0, dir,
+                            _dbus_string_get_length (dir));
+}
+
+/** nanoseconds in a second */
+#define NANOSECONDS_PER_SECOND       1000000000
+/** microseconds in a second */
+#define MICROSECONDS_PER_SECOND      1000000
+/** milliseconds in a second */
+#define MILLISECONDS_PER_SECOND      1000
+/** nanoseconds in a millisecond */
+#define NANOSECONDS_PER_MILLISECOND  1000000
+/** microseconds in a millisecond */
+#define MICROSECONDS_PER_MILLISECOND 1000
+
+/**
+ * Sleeps the given number of milliseconds.
+ * @param milliseconds number of milliseconds
+ */
+void
+_dbus_sleep_milliseconds (int milliseconds)
+{
+#ifdef HAVE_NANOSLEEP
+  struct timespec req;
+  struct timespec rem;
+
+  req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
+  req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
+  rem.tv_sec = 0;
+  rem.tv_nsec = 0;
+
+  while (nanosleep (&req, &rem) < 0 && errno == EINTR)
+    req = rem;
+#elif defined (HAVE_USLEEP)
+  usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
+#else /* ! HAVE_USLEEP */
+  sleep (MAX (milliseconds / 1000, 1));
+#endif
+}
+
+static dbus_bool_t
+_dbus_generate_pseudorandom_bytes (DBusString *str,
+                                   int         n_bytes)
+{
+  int old_len;
+  char *p;
+
+  old_len = _dbus_string_get_length (str);
+
+  if (!_dbus_string_lengthen (str, n_bytes))
+    return FALSE;
+
+  p = _dbus_string_get_data_len (str, old_len, n_bytes);
+
+  _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes);
+
+  return TRUE;
+}
+
+/**
+ * Generates the given number of random bytes,
+ * using the best mechanism we can come up with.
+ *
+ * @param str the string
+ * @param n_bytes the number of random bytes to append to string
+ * @returns #TRUE on success, #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_generate_random_bytes (DBusString *str,
+                             int         n_bytes)
+{
+  int old_len;
+  int fd;
+
+  /* FALSE return means "no memory", if it could
+   * mean something else then we'd need to return
+   * a DBusError. So we always fall back to pseudorandom
+   * if the I/O fails.
+   */
+
+  old_len = _dbus_string_get_length (str);
+  fd = -1;
+
+  /* note, urandom on linux will fall back to pseudorandom */
+  fd = open ("/dev/urandom", O_RDONLY);
+  if (fd < 0)
+    return _dbus_generate_pseudorandom_bytes (str, n_bytes);
+
+  _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
+
+  if (_dbus_read (fd, str, n_bytes) != n_bytes)
+    {
+      _dbus_close (fd, NULL);
+      _dbus_string_set_length (str, old_len);
+      return _dbus_generate_pseudorandom_bytes (str, n_bytes);
+    }
+
+  _dbus_verbose ("Read %d bytes from /dev/urandom\n",
+                 n_bytes);
+
+  _dbus_close (fd, NULL);
+
+  return TRUE;
+}
+
+/**
+ * Exit the process, returning the given value.
+ *
+ * @param code the exit code
+ */
+void
+_dbus_exit (int code)
+{
+  _exit (code);
+}
+
+/**
+ * A wrapper around strerror() because some platforms
+ * may be lame and not have strerror(). Also, never
+ * returns NULL.
+ *
+ * @param error_number errno.
+ * @returns error description.
+ */
+const char*
+_dbus_strerror (int error_number)
+{
+  const char *msg;
+
+  msg = strerror (error_number);
+  if (msg == NULL)
+    msg = "unknown";
+
+  return msg;
+}
+
+/**
+ * signal (SIGPIPE, SIG_IGN);
+ */
+void
+_dbus_disable_sigpipe (void)
+{
+  signal (SIGPIPE, SIG_IGN);
+}
+
+/**
+ * Sets the file descriptor to be close
+ * on exec. Should be called for all file
+ * descriptors in D-Bus code.
+ *
+ * @param fd the file descriptor
+ */
+void
+_dbus_fd_set_close_on_exec (intptr_t fd)
+{
+  int val;
+
+  val = fcntl (fd, F_GETFD, 0);
+
+  if (val < 0)
+    return;
+
+  val |= FD_CLOEXEC;
+
+  fcntl (fd, F_SETFD, val);
+}
+
+/**
+ * Closes a file descriptor.
+ *
+ * @param fd the file descriptor
+ * @param error error object
+ * @returns #FALSE if error set
+ */
+dbus_bool_t
+_dbus_close (int        fd,
+             DBusError *error)
+{
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ again:
+  if (close (fd) < 0)
+    {
+      if (errno == EINTR)
+        goto again;
+
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Could not close fd %d", fd);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Duplicates a file descriptor. Makes sure the fd returned is >= 3
+ * (i.e. avoids stdin/stdout/stderr). Sets O_CLOEXEC.
+ *
+ * @param fd the file descriptor to duplicate
+ * @returns duplicated file descriptor
+ * */
+int
+_dbus_dup(int        fd,
+          DBusError *error)
+{
+  int new_fd;
+
+#ifdef F_DUPFD_CLOEXEC
+  dbus_bool_t cloexec_done;
+
+  new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
+  cloexec_done = new_fd >= 0;
+
+  if (new_fd < 0 && errno == EINVAL)
+#endif
+    {
+      new_fd = fcntl(fd, F_DUPFD, 3);
+    }
+
+  if (new_fd < 0) {
+
+    dbus_set_error (error, _dbus_error_from_errno (errno),
+                    "Could not duplicate fd %d", fd);
+    return -1;
+  }
+
+#ifdef F_DUPFD_CLOEXEC
+  if (!cloexec_done)
+#endif
+    {
+      _dbus_fd_set_close_on_exec(new_fd);
+    }
+
+  return new_fd;
+}
+
+/**
+ * Sets a file descriptor to be nonblocking.
+ *
+ * @param fd the file descriptor.
+ * @param error address of error location.
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_set_fd_nonblocking (int             fd,
+                          DBusError      *error)
+{
+  int val;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  val = fcntl (fd, F_GETFL, 0);
+  if (val < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to get flags from file descriptor %d: %s",
+                      fd, _dbus_strerror (errno));
+      _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
+                     _dbus_strerror (errno));
+      return FALSE;
+    }
+
+  if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to set nonblocking flag of file descriptor %d: %s",
+                      fd, _dbus_strerror (errno));
+      _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
+                     fd, _dbus_strerror (errno));
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * On GNU libc systems, print a crude backtrace to stderr.  On other
+ * systems, print "no backtrace support" and block for possible gdb
+ * attachment if an appropriate environment variable is set.
+ */
+void
+_dbus_print_backtrace (void)
+{
+#if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
+  void *bt[500];
+  int bt_size;
+  int i;
+  char **syms;
+
+  bt_size = backtrace (bt, 500);
+
+  syms = backtrace_symbols (bt, bt_size);
+
+  i = 0;
+  while (i < bt_size)
+    {
+      /* don't use dbus_warn since it can _dbus_abort() */
+      fprintf (stderr, "  %s\n", syms[i]);
+      ++i;
+    }
+  fflush (stderr);
+
+  free (syms);
+#elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
+  fprintf (stderr, "  D-Bus not built with -rdynamic so unable to print a backtrace\n");
+#else
+  fprintf (stderr, "  D-Bus not compiled with backtrace support so unable to print a backtrace\n");
+#endif
+}
+
+/**
+ * Creates a full-duplex pipe (as in socketpair()).
+ * Sets both ends of the pipe nonblocking.
+ *
+ * Marks both file descriptors as close-on-exec
+ *
+ * @param fd1 return location for one end
+ * @param fd2 return location for the other end
+ * @param blocking #TRUE if pipe should be blocking
+ * @param error error return
+ * @returns #FALSE on failure (if error is set)
+ */
+dbus_bool_t
+_dbus_full_duplex_pipe (int        *fd1,
+                        int        *fd2,
+                        dbus_bool_t blocking,
+                        DBusError  *error)
+{
+#ifdef HAVE_SOCKETPAIR
+  int fds[2];
+  int retval;
+
+#ifdef SOCK_CLOEXEC
+  dbus_bool_t cloexec_done;
+
+  retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
+  cloexec_done = retval >= 0;
+
+  if (retval < 0 && errno == EINVAL)
+#endif
+    {
+      retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
+    }
+
+  if (retval < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Could not create full-duplex pipe");
+      return FALSE;
+    }
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+#ifdef SOCK_CLOEXEC
+  if (!cloexec_done)
+#endif
+    {
+      _dbus_fd_set_close_on_exec (fds[0]);
+      _dbus_fd_set_close_on_exec (fds[1]);
+    }
+
+  if (!blocking &&
+      (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
+       !_dbus_set_fd_nonblocking (fds[1], NULL)))
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Could not set full-duplex pipe nonblocking");
+
+      _dbus_close (fds[0], NULL);
+      _dbus_close (fds[1], NULL);
+
+      return FALSE;
+    }
+
+  *fd1 = fds[0];
+  *fd2 = fds[1];
+
+  _dbus_verbose ("full-duplex pipe %d <-> %d\n",
+                 *fd1, *fd2);
+
+  return TRUE;
+#else
+  _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n");
+  dbus_set_error (error, DBUS_ERROR_FAILED,
+                  "_dbus_full_duplex_pipe() not implemented on this OS");
+  return FALSE;
+#endif
+}
+
+/**
+ * Measure the length of the given format string and arguments,
+ * not including the terminating nul.
+ *
+ * @param format a printf-style format string
+ * @param args arguments for the format string
+ * @returns length of the given format string and args, or -1 if no memory
+ */
+int
+_dbus_printf_string_upper_bound (const char *format,
+                                 va_list     args)
+{
+  char static_buf[1024];
+  int bufsize = sizeof (static_buf);
+  int len;
+
+  len = vsnprintf (static_buf, bufsize, format, args);
+
+  /* If vsnprintf() returned non-negative, then either the string fits in
+   * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
+   * returns the number of characters that were needed, or this OS returns the
+   * truncated length.
+   *
+   * We ignore the possibility that snprintf might just ignore the length and
+   * overrun the buffer (64-bit Solaris 7), because that's pathological.
+   * If your libc is really that bad, come back when you have a better one. */
+  if (len == bufsize)
+    {
+      /* This could be the truncated length (Tru64 and IRIX have this bug),
+       * or the real length could be coincidentally the same. Which is it?
+       * If vsnprintf returns the truncated length, we'll go to the slow
+       * path. */
+      if (vsnprintf (static_buf, 1, format, args) == 1)
+        len = -1;
+    }
+
+  /* If vsnprintf() returned negative, we have to do more work.
+   * HP-UX returns negative. */
+  while (len < 0)
+    {
+      char *buf;
+
+      bufsize *= 2;
+
+      buf = dbus_malloc (bufsize);
+
+      if (buf == NULL)
+        return -1;
+
+      len = vsnprintf (buf, bufsize, format, args);
+      dbus_free (buf);
+
+      /* If the reported length is exactly the buffer size, round up to the
+       * next size, in case vsnprintf has been returning the truncated
+       * length */
+      if (len == bufsize)
+        len = -1;
+    }
+
+  return len;
+}
+
+/**
+ * Gets the temporary files directory by inspecting the environment variables
+ * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
+ *
+ * @returns location of temp directory
+ */
+const char*
+_dbus_get_tmpdir(void)
+{
+  static const char* tmpdir = NULL;
+
+  if (tmpdir == NULL)
+    {
+      /* TMPDIR is what glibc uses, then
+       * glibc falls back to the P_tmpdir macro which
+       * just expands to "/tmp"
+       */
+      if (tmpdir == NULL)
+        tmpdir = getenv("TMPDIR");
+
+      /* These two env variables are probably
+       * broken, but maybe some OS uses them?
+       */
+      if (tmpdir == NULL)
+        tmpdir = getenv("TMP");
+      if (tmpdir == NULL)
+        tmpdir = getenv("TEMP");
+
+      /* And this is the sane fallback. */
+      if (tmpdir == NULL)
+        tmpdir = "/tmp";
+    }
+
+  _dbus_assert(tmpdir != NULL);
+
+  return tmpdir;
+}
+
+/**
+ * Execute a subprocess, returning up to 1024 bytes of output
+ * into @p result.
+ *
+ * If successful, returns #TRUE and appends the output to @p
+ * result. If a failure happens, returns #FALSE and
+ * sets an error in @p error.
+ *
+ * @note It's not an error if the subprocess terminates normally
+ * without writing any data to stdout. Verify the @p result length
+ * before and after this function call to cover this case.
+ *
+ * @param progname initial path to exec (may or may not be absolute)
+ * @param path_fallback if %TRUE, search PATH for executable
+ * @param argv NULL-terminated list of arguments
+ * @param result a DBusString where the output can be append
+ * @param error a DBusError to store the error in case of failure
+ * @returns #TRUE on success, #FALSE if an error happened
+ */
+static dbus_bool_t
+_read_subprocess_line_argv (const char *progpath,
+                            dbus_bool_t path_fallback,
+                            char       * const *argv,
+                            DBusString *result,
+                            DBusError  *error)
+{
+  int result_pipe[2] = { -1, -1 };
+  int errors_pipe[2] = { -1, -1 };
+  pid_t pid;
+  int ret;
+  int status;
+  int orig_len;
+
+  dbus_bool_t retval;
+  sigset_t new_set, old_set;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  retval = FALSE;
+
+  /* We need to block any existing handlers for SIGCHLD temporarily; they
+   * will cause waitpid() below to fail.
+   * https://bugs.freedesktop.org/show_bug.cgi?id=21347
+   */
+  sigemptyset (&new_set);
+  sigaddset (&new_set, SIGCHLD);
+  sigprocmask (SIG_BLOCK, &new_set, &old_set);
+
+  orig_len = _dbus_string_get_length (result);
+
+#define READ_END        0
+#define WRITE_END       1
+  if (pipe (result_pipe) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to create a pipe to call %s: %s",
+                      progpath, _dbus_strerror (errno));
+      _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
+                     progpath, _dbus_strerror (errno));
+      goto out;
+    }
+  if (pipe (errors_pipe) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to create a pipe to call %s: %s",
+                      progpath, _dbus_strerror (errno));
+      _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
+                     progpath, _dbus_strerror (errno));
+      goto out;
+    }
+
+  pid = fork ();
+  if (pid < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to fork() to call %s: %s",
+                      progpath, _dbus_strerror (errno));
+      _dbus_verbose ("Failed to fork() to call %s: %s\n",
+                     progpath, _dbus_strerror (errno));
+      goto out;
+    }
+
+  if (pid == 0)
+    {
+      /* child process */
+      int fd;
+
+      fd = open ("/dev/null", O_RDWR);
+      if (fd == -1)
+        /* huh?! can't open /dev/null? */
+        _exit (1);
+
+      _dbus_verbose ("/dev/null fd %d opened\n", fd);
+
+      /* set-up stdXXX */
+      close (result_pipe[READ_END]);
+      close (errors_pipe[READ_END]);
+      close (0);                /* close stdin */
+      close (1);                /* close stdout */
+      close (2);                /* close stderr */
+
+      if (dup2 (fd, 0) == -1)
+        _exit (1);
+      if (dup2 (result_pipe[WRITE_END], 1) == -1)
+        _exit (1);
+      if (dup2 (errors_pipe[WRITE_END], 2) == -1)
+        _exit (1);
+
+      _dbus_close_all ();
+
+      sigprocmask (SIG_SETMASK, &old_set, NULL);
+
+      /* If it looks fully-qualified, try execv first */
+      if (progpath[0] == '/')
+        {
+          execv (progpath, argv);
+          /* Ok, that failed.  Now if path_fallback is given, let's
+           * try unqualified.  This is mostly a hack to work
+           * around systems which ship dbus-launch in /usr/bin
+           * but everything else in /bin (because dbus-launch
+           * depends on X11).
+           */
+          if (path_fallback)
+            /* We must have a slash, because we checked above */
+            execvp (strrchr (progpath, '/')+1, argv);
+        }
+      else
+        execvp (progpath, argv);
+
+      /* still nothing, we failed */
+      _exit (1);
+    }
+
+  /* parent process */
+  close (result_pipe[WRITE_END]);
+  close (errors_pipe[WRITE_END]);
+  result_pipe[WRITE_END] = -1;
+  errors_pipe[WRITE_END] = -1;
+
+  ret = 0;
+  do
+    {
+      ret = _dbus_read (result_pipe[READ_END], result, 1024);
+    }
+  while (ret > 0);
+
+  /* reap the child process to avoid it lingering as zombie */
+  do
+    {
+      ret = waitpid (pid, &status, 0);
+    }
+  while (ret == -1 && errno == EINTR);
+
+  /* We succeeded if the process exited with status 0 and
+     anything was read */
+  if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
+    {
+      /* The process ended with error */
+      DBusString error_message;
+      if (!_dbus_string_init (&error_message))
+        {
+          _DBUS_SET_OOM (error);
+          goto out;
+        }
+
+      ret = 0;
+      do
+        {
+          ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
+        }
+      while (ret > 0);
+
+      _dbus_string_set_length (result, orig_len);
+      if (_dbus_string_get_length (&error_message) > 0)
+        dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
+                        "%s terminated abnormally with the following error: %s",
+                        progpath, _dbus_string_get_data (&error_message));
+      else
+        dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
+                        "%s terminated abnormally without any error message",
+                        progpath);
+      goto out;
+    }
+
+  retval = TRUE;
+
+ out:
+  sigprocmask (SIG_SETMASK, &old_set, NULL);
+
+  if (retval)
+    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  else
+    _DBUS_ASSERT_ERROR_IS_SET (error);
+
+  if (result_pipe[0] != -1)
+    close (result_pipe[0]);
+  if (result_pipe[1] != -1)
+    close (result_pipe[1]);
+  if (errors_pipe[0] != -1)
+    close (errors_pipe[0]);
+  if (errors_pipe[1] != -1)
+    close (errors_pipe[1]);
+
+  return retval;
+}
+
+/**
+ * Returns the address of a new session bus.
+ *
+ * If successful, returns #TRUE and appends the address to @p
+ * address. If a failure happens, returns #FALSE and
+ * sets an error in @p error.
+ *
+ * @param address a DBusString where the address can be stored
+ * @param error a DBusError to store the error in case of failure
+ * @returns #TRUE on success, #FALSE if an error happened
+ */
+dbus_bool_t
+_dbus_get_autolaunch_address (const char *scope,
+                              DBusString *address,
+                              DBusError  *error)
+{
+#ifdef DBUS_ENABLE_X11_AUTOLAUNCH
+  /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
+   * but that's done elsewhere, and if it worked, this function wouldn't
+   * be called.) */
+  const char *display;
+  static char *argv[6];
+  int i;
+  DBusString uuid;
+  dbus_bool_t retval;
+
+  if (_dbus_check_setuid ())
+    {
+      dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
+                            "Unable to autolaunch when setuid");
+      return FALSE;
+    }
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  retval = FALSE;
+
+  /* fd.o #19997: if $DISPLAY isn't set to something useful, then
+   * dbus-launch-x11 is just going to fail. Rather than trying to
+   * run it, we might as well bail out early with a nice error. */
+  display = _dbus_getenv ("DISPLAY");
+
+  if (display == NULL || display[0] == '\0')
+    {
+      dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
+          "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&uuid))
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!_dbus_get_local_machine_uuid_encoded (&uuid))
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+
+  i = 0;
+  argv[i] = "dbus-launch";
+  ++i;
+  argv[i] = "--autolaunch";
+  ++i;
+  argv[i] = _dbus_string_get_data (&uuid);
+  ++i;
+  argv[i] = "--binary-syntax";
+  ++i;
+  argv[i] = "--close-stderr";
+  ++i;
+  argv[i] = NULL;
+  ++i;
+
+  _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
+
+  retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch",
+                                       TRUE,
+                                       argv, address, error);
+
+ out:
+  _dbus_string_free (&uuid);
+  return retval;
+#else
+  dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
+      "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
+      "set your DBUS_SESSION_BUS_ADDRESS instead");
+  return FALSE;
+#endif
+}
+
+/**
+ * Reads the uuid of the machine we're running on from
+ * the dbus configuration. Optionally try to create it
+ * (only root can do this usually).
+ *
+ * On UNIX, reads a file that gets created by dbus-uuidgen
+ * in a post-install script. On Windows, if there's a standard
+ * machine uuid we could just use that, but I can't find one
+ * with the right properties (the hardware profile guid can change
+ * without rebooting I believe). If there's no standard one
+ * we might want to use the registry instead of a file for
+ * this, and I'm not sure how we'd ensure the uuid gets created.
+ *
+ * @param machine_id guid to init with the machine's uuid
+ * @param create_if_not_found try to create the uuid if it doesn't exist
+ * @param error the error return
+ * @returns #FALSE if the error is set
+ */
+dbus_bool_t
+_dbus_read_local_machine_uuid (DBusGUID   *machine_id,
+                               dbus_bool_t create_if_not_found,
+                               DBusError  *error)
+{
+  DBusString filename;
+  dbus_bool_t b;
+
+  _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
+
+  b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error);
+  if (b)
+    return TRUE;
+
+  dbus_error_free (error);
+
+  /* Fallback to the system machine ID */
+  _dbus_string_init_const (&filename, "/etc/machine-id");
+  return _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
+}
+
+#define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
+#define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
+
+/**
+ * quries launchd for a specific env var which holds the socket path.
+ * @param launchd_env_var the env var to look up
+ * @param error a DBusError to store the error in case of failure
+ * @return the value of the env var
+ */
+dbus_bool_t
+_dbus_lookup_launchd_socket (DBusString *socket_path,
+                             const char *launchd_env_var,
+                             DBusError  *error)
+{
+#ifdef DBUS_ENABLE_LAUNCHD
+  char *argv[4];
+  int i;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (_dbus_check_setuid ())
+    {
+      dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
+                            "Unable to find launchd socket when setuid");
+      return FALSE;
+    }
+
+  i = 0;
+  argv[i] = "launchctl";
+  ++i;
+  argv[i] = "getenv";
+  ++i;
+  argv[i] = (char*)launchd_env_var;
+  ++i;
+  argv[i] = NULL;
+  ++i;
+
+  _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
+
+  if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
+    {
+      return FALSE;
+    }
+
+  /* no error, but no result either */
+  if (_dbus_string_get_length(socket_path) == 0)
+    {
+      return FALSE;
+    }
+
+  /* strip the carriage-return */
+  _dbus_string_shorten(socket_path, 1);
+  return TRUE;
+#else /* DBUS_ENABLE_LAUNCHD */
+  dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
+                "can't lookup socket from launchd; launchd support not compiled in");
+  return FALSE;
+#endif
+}
+
+#ifdef DBUS_ENABLE_LAUNCHD
+static dbus_bool_t
+_dbus_lookup_session_address_launchd (DBusString *address, DBusError  *error)
+{
+  dbus_bool_t valid_socket;
+  DBusString socket_path;
+
+  if (_dbus_check_setuid ())
+    {
+      dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
+                            "Unable to find launchd socket when setuid");
+      return FALSE;
+    }
+
+  if (!_dbus_string_init (&socket_path))
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
+
+  if (dbus_error_is_set(error))
+    {
+      _dbus_string_free(&socket_path);
+      return FALSE;
+    }
+
+  if (!valid_socket)
+    {
+      dbus_set_error(error, "no socket path",
+                "launchd did not provide a socket path, "
+                "verify that org.freedesktop.dbus-session.plist is loaded!");
+      _dbus_string_free(&socket_path);
+      return FALSE;
+    }
+  if (!_dbus_string_append (address, "unix:path="))
+    {
+      _DBUS_SET_OOM (error);
+      _dbus_string_free(&socket_path);
+      return FALSE;
+    }
+  if (!_dbus_string_copy (&socket_path, 0, address,
+                          _dbus_string_get_length (address)))
+    {
+      _DBUS_SET_OOM (error);
+      _dbus_string_free(&socket_path);
+      return FALSE;
+    }
+
+  _dbus_string_free(&socket_path);
+  return TRUE;
+}
+#endif
+
+/**
+ * Determines the address of the session bus by querying a
+ * platform-specific method.
+ *
+ * The first parameter will be a boolean specifying whether
+ * or not a dynamic session lookup is supported on this platform.
+ *
+ * If supported is TRUE and the return value is #TRUE, the
+ * address will be  appended to @p address.
+ * If a failure happens, returns #FALSE and sets an error in
+ * @p error.
+ *
+ * If supported is FALSE, ignore the return value.
+ *
+ * @param supported returns whether this method is supported
+ * @param address a DBusString where the address can be stored
+ * @param error a DBusError to store the error in case of failure
+ * @returns #TRUE on success, #FALSE if an error happened
+ */
+dbus_bool_t
+_dbus_lookup_session_address (dbus_bool_t *supported,
+                              DBusString  *address,
+                              DBusError   *error)
+{
+#ifdef DBUS_ENABLE_LAUNCHD
+  *supported = TRUE;
+  return _dbus_lookup_session_address_launchd (address, error);
+#else
+  /* On non-Mac Unix platforms, if the session address isn't already
+   * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and
+   * fall back to the autolaunch: global default; see
+   * init_session_address in dbus/dbus-bus.c. */
+  *supported = FALSE;
+  return TRUE;
+#endif
+}
+
+/**
+ * Returns the standard directories for a session bus to look for service
+ * activation files
+ *
+ * On UNIX this should be the standard xdg freedesktop.org data directories:
+ *
+ * XDG_DATA_HOME=${XDG_DATA_HOME-$HOME/.local/share}
+ * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
+ *
+ * and
+ *
+ * DBUS_DATADIR
+ *
+ * @param dirs the directory list we are returning
+ * @returns #FALSE on OOM
+ */
+
+dbus_bool_t
+_dbus_get_standard_session_servicedirs (DBusList **dirs)
+{
+  const char *xdg_data_home;
+  const char *xdg_data_dirs;
+  DBusString servicedir_path;
+
+  if (!_dbus_string_init (&servicedir_path))
+    return FALSE;
+
+  xdg_data_home = _dbus_getenv ("XDG_DATA_HOME");
+  xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS");
+
+  if (xdg_data_home != NULL)
+    {
+      if (!_dbus_string_append (&servicedir_path, xdg_data_home))
+        goto oom;
+    }
+  else
+    {
+      const DBusString *homedir;
+      DBusString local_share;
+
+      if (!_dbus_homedir_from_current_process (&homedir))
+        goto oom;
+
+      if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir)))
+        goto oom;
+
+      _dbus_string_init_const (&local_share, "/.local/share");
+      if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share))
+        goto oom;
+    }
+
+  if (!_dbus_string_append (&servicedir_path, ":"))
+    goto oom;
+
+  if (xdg_data_dirs != NULL)
+    {
+      if (!_dbus_string_append (&servicedir_path, xdg_data_dirs))
+        goto oom;
+
+      if (!_dbus_string_append (&servicedir_path, ":"))
+        goto oom;
+    }
+  else
+    {
+      if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:"))
+        goto oom;
+    }
+
+  /*
+   * add configured datadir to defaults
+   * this may be the same as an xdg dir
+   * however the config parser should take
+   * care of duplicates
+   */
+  if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR))
+    goto oom;
+
+  if (!_dbus_split_paths_and_append (&servicedir_path,
+                                     DBUS_UNIX_STANDARD_SESSION_SERVICEDIR,
+                                     dirs))
+    goto oom;
+
+  _dbus_string_free (&servicedir_path);
+  return TRUE;
+
+ oom:
+  _dbus_string_free (&servicedir_path);
+  return FALSE;
+}
+
+
+/**
+ * Returns the standard directories for a system bus to look for service
+ * activation files
+ *
+ * On UNIX this should be the standard xdg freedesktop.org data directories:
+ *
+ * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
+ *
+ * and
+ *
+ * DBUS_DATADIR
+ *
+ * On Windows there is no system bus and this function can return nothing.
+ *
+ * @param dirs the directory list we are returning
+ * @returns #FALSE on OOM
+ */
+
+dbus_bool_t
+_dbus_get_standard_system_servicedirs (DBusList **dirs)
+{
+  /*
+   * DBUS_DATADIR may be the same as one of the standard directories. However,
+   * the config parser should take care of the duplicates.
+   *
+   * Also, append /lib as counterpart of /usr/share on the root
+   * directory (the root directory does not know /share), in order to
+   * facilitate early boot system bus activation where /usr might not
+   * be available.
+   */
+  static const char standard_search_path[] =
+    "/usr/local/share:"
+    "/usr/share:"
+    DBUS_DATADIR ":"
+    "/lib";
+  DBusString servicedir_path;
+
+  _dbus_string_init_const (&servicedir_path, standard_search_path);
+
+  return _dbus_split_paths_and_append (&servicedir_path,
+                                       DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR,
+                                       dirs);
+}
+
+/**
+ * Append the absolute path of the system.conf file
+ * (there is no system bus on Windows so this can just
+ * return FALSE and print a warning or something)
+ *
+ * @param str the string to append to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_append_system_config_file (DBusString *str)
+{
+  return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE);
+}
+
+/**
+ * Append the absolute path of the session.conf file.
+ *
+ * @param str the string to append to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_append_session_config_file (DBusString *str)
+{
+  return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE);
+}
+
+/**
+ * Called when the bus daemon is signaled to reload its configuration; any
+ * caches should be nuked. Of course any caches that need explicit reload
+ * are probably broken, but c'est la vie.
+ *
+ *
+ */
+void
+_dbus_flush_caches (void)
+{
+  _dbus_user_database_flush_system ();
+}
+
+/**
+ * Appends the directory in which a keyring for the given credentials
+ * should be stored.  The credentials should have either a Windows or
+ * UNIX user in them.  The directory should be an absolute path.
+ *
+ * On UNIX the directory is ~/.dbus-keyrings while on Windows it should probably
+ * be something else, since the dotfile convention is not normal on Windows.
+ *
+ * @param directory string to append directory to
+ * @param credentials credentials the directory should be for
+ *
+ * @returns #FALSE on no memory
+ */
+dbus_bool_t
+_dbus_append_keyring_directory_for_credentials (DBusString      *directory,
+                                                DBusCredentials *credentials)
+{
+  DBusString homedir;
+  DBusString dotdir;
+  dbus_uid_t uid;
+
+  _dbus_assert (credentials != NULL);
+  _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
+
+  if (!_dbus_string_init (&homedir))
+    return FALSE;
+
+  uid = _dbus_credentials_get_unix_uid (credentials);
+  _dbus_assert (uid != DBUS_UID_UNSET);
+
+  if (!_dbus_homedir_from_uid (uid, &homedir))
+    goto failed;
+
+#ifdef DBUS_BUILD_TESTS
+  {
+    const char *override;
+
+    override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
+    if (override != NULL && *override != '\0')
+      {
+        _dbus_string_set_length (&homedir, 0);
+        if (!_dbus_string_append (&homedir, override))
+          goto failed;
+
+        _dbus_verbose ("Using fake homedir for testing: %s\n",
+                       _dbus_string_get_const_data (&homedir));
+      }
+    else
+      {
+        static dbus_bool_t already_warned = FALSE;
+        if (!already_warned)
+          {
+            _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
+            already_warned = TRUE;
+          }
+      }
+  }
+#endif
+
+  _dbus_string_init_const (&dotdir, ".dbus-keyrings");
+  if (!_dbus_concat_dir_and_file (&homedir,
+                                  &dotdir))
+    goto failed;
+
+  if (!_dbus_string_copy (&homedir, 0,
+                          directory, _dbus_string_get_length (directory))) {
+    goto failed;
+  }
+
+  _dbus_string_free (&homedir);
+  return TRUE;
+
+ failed:
+  _dbus_string_free (&homedir);
+  return FALSE;
+}
+
+//PENDING(kdab) docs
+dbus_bool_t
+_dbus_daemon_publish_session_bus_address (const char* addr,
+                                          const char *scope)
+{
+  return TRUE;
+}
+
+//PENDING(kdab) docs
+void
+_dbus_daemon_unpublish_session_bus_address (void)
+{
+
+}
+
+/**
+ * See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently
+ * for Winsock so is abstracted)
+ *
+ * @returns #TRUE if errno == EAGAIN or errno == EWOULDBLOCK
+ */
+dbus_bool_t
+_dbus_get_is_errno_eagain_or_ewouldblock (void)
+{
+  return errno == EAGAIN || errno == EWOULDBLOCK;
+}
+
+/**
+ * Removes a directory; Directory must be empty
+ *
+ * @param filename directory filename
+ * @param error initialized error object
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_delete_directory (const DBusString *filename,
+                        DBusError        *error)
+{
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  filename_c = _dbus_string_get_const_data (filename);
+
+  if (rmdir (filename_c) != 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Failed to remove directory %s: %s\n",
+                      filename_c, _dbus_strerror (errno));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ *  Checks whether file descriptors may be passed via the socket
+ *
+ *  @param fd the socket
+ *  @return TRUE when fd passing over this socket is supported
+ *
+ */
+dbus_bool_t
+_dbus_socket_can_pass_unix_fd(int fd) {
+
+#ifdef SCM_RIGHTS
+  union {
+    struct sockaddr sa;
+    struct sockaddr_storage storage;
+    struct sockaddr_un un;
+  } sa_buf;
+
+  socklen_t sa_len = sizeof(sa_buf);
+
+  _DBUS_ZERO(sa_buf);
+
+  if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
+    return FALSE;
+
+  return sa_buf.sa.sa_family == AF_UNIX;
+
+#else
+  return FALSE;
+
+#endif
+}
+
+
+/*
+ * replaces the term DBUS_PREFIX in configure_time_path by the
+ * current dbus installation directory. On unix this function is a noop
+ *
+ * @param configure_time_path
+ * @return real path
+ */
+const char *
+_dbus_replace_install_prefix (const char *configure_time_path)
+{
+  return configure_time_path;
+}
+
+/**
+ * Closes all file descriptors except the first three (i.e. stdin,
+ * stdout, stderr).
+ */
+void
+_dbus_close_all (void)
+{
+  int maxfds, i;
+
+#ifdef __linux__
+  DIR *d;
+
+  /* On Linux we can optimize this a bit if /proc is available. If it
+     isn't available, fall back to the brute force way. */
+
+  d = opendir ("/proc/self/fd");
+  if (d)
+    {
+      for (;;)
+        {
+          struct dirent buf, *de;
+          int k, fd;
+          long l;
+          char *e = NULL;
+
+          k = readdir_r (d, &buf, &de);
+          if (k != 0 || !de)
+            break;
+
+          if (de->d_name[0] == '.')
+            continue;
+
+          errno = 0;
+          l = strtol (de->d_name, &e, 10);
+          if (errno != 0 || e == NULL || *e != '\0')
+            continue;
+
+          fd = (int) l;
+          if (fd < 3)
+            continue;
+
+          if (fd == dirfd (d))
+            continue;
+
+          close (fd);
+        }
+
+      closedir (d);
+      return;
+    }
+#endif
+
+  maxfds = sysconf (_SC_OPEN_MAX);
+
+  /* Pick something reasonable if for some reason sysconf says
+   * unlimited.
+   */
+  if (maxfds < 0)
+    maxfds = 1024;
+
+  /* close all inherited fds */
+  for (i = 3; i < maxfds; i++)
+    close (i);
+}
+
+/**
+ * **NOTE**: If you modify this function, please also consider making
+ * the corresponding change in GLib.  See
+ * glib/gutils.c:g_check_setuid().
+ *
+ * Returns TRUE if the current process was executed as setuid (or an
+ * equivalent __libc_enable_secure is available).  See:
+ * http://osdir.com/ml/linux.lfs.hardened/2007-04/msg00032.html
+ */
+dbus_bool_t
+_dbus_check_setuid (void)
+{
+  /* TODO: get __libc_enable_secure exported from glibc.
+   * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
+   */
+#if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
+  {
+    /* See glibc/include/unistd.h */
+    extern int __libc_enable_secure;
+    return __libc_enable_secure;
+  }
+#elif defined(HAVE_ISSETUGID)
+  /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
+  return issetugid ();
+#else
+  uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
+  gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
+
+  static dbus_bool_t check_setuid_initialised;
+  static dbus_bool_t is_setuid;
+
+  if (_DBUS_UNLIKELY (!check_setuid_initialised))
+    {
+#ifdef HAVE_GETRESUID
+      if (getresuid (&ruid, &euid, &suid) != 0 ||
+          getresgid (&rgid, &egid, &sgid) != 0)
+#endif /* HAVE_GETRESUID */
+        {
+          suid = ruid = getuid ();
+          sgid = rgid = getgid ();
+          euid = geteuid ();
+          egid = getegid ();
+        }
+
+      check_setuid_initialised = TRUE;
+      is_setuid = (ruid != euid || ruid != suid ||
+                   rgid != egid || rgid != sgid);
+
+    }
+  return is_setuid;
+#endif
+}
+
+/* tests in dbus-sysdeps-util.c */
diff --git a/dbus/dbus/dbus-sysdeps-unix.h b/dbus/dbus/dbus-sysdeps-unix.h
new file mode 100644
index 0000000..9b70896
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-unix.h
@@ -0,0 +1,145 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-unix.h UNIX-specific wrappers around system/libc features (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef DBUS_SYSDEPS_UNIX_H
+#define DBUS_SYSDEPS_UNIX_H
+
+#include <dbus/dbus-sysdeps.h>
+
+#ifdef DBUS_WIN
+#error "Don't include this on Windows"
+#endif
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @defgroup DBusSysdepsUnix UNIX-specific internal API
+ * @ingroup DBusInternals
+ * @brief Internal system-dependent API available on UNIX only
+ * @{
+ */
+
+dbus_bool_t
+_dbus_close     (int               fd,
+                 DBusError        *error);
+int _dbus_dup   (int               fd,
+                 DBusError        *error);
+int
+_dbus_read      (int               fd,
+                 DBusString       *buffer,
+                 int               count);
+int
+_dbus_write     (int               fd,
+                 const DBusString *buffer,
+                 int               start,
+                 int               len);
+int
+_dbus_write_two (int               fd,
+                 const DBusString *buffer1,
+                 int               start1,
+                 int               len1,
+                 const DBusString *buffer2,
+                 int               start2,
+                 int               len2);
+
+int _dbus_connect_unix_socket (const char     *path,
+                               dbus_bool_t     abstract,
+                               DBusError      *error);
+int _dbus_listen_unix_socket  (const char     *path,
+                               dbus_bool_t     abstract,
+                               DBusError      *error);
+
+int _dbus_connect_exec (const char     *path,
+                        char *const    argv[],
+                        DBusError      *error);
+
+int _dbus_listen_systemd_sockets (int       **fd,
+                                 DBusError *error);
+
+dbus_bool_t _dbus_read_credentials (int               client_fd,
+                                    DBusCredentials  *credentials,
+                                    DBusError        *error);
+dbus_bool_t _dbus_send_credentials (int              server_fd,
+                                    DBusError       *error);
+
+dbus_bool_t _dbus_lookup_launchd_socket (DBusString *socket_path,
+                                         const char *launchd_env_var,
+                                         DBusError  *error);
+
+/** Information about a UNIX user */
+typedef struct DBusUserInfo  DBusUserInfo;
+/** Information about a UNIX group */
+typedef struct DBusGroupInfo DBusGroupInfo;
+
+/**
+ * Information about a UNIX user
+ */
+struct DBusUserInfo
+{
+  dbus_uid_t  uid;            /**< UID */
+  dbus_gid_t  primary_gid;    /**< GID */
+  dbus_gid_t *group_ids;      /**< Groups IDs, *including* above primary group */
+  int         n_group_ids;    /**< Size of group IDs array */
+  char       *username;       /**< Username */
+  char       *homedir;        /**< Home directory */
+};
+
+/**
+ * Information about a UNIX group
+ */
+struct DBusGroupInfo
+{
+  dbus_gid_t  gid;            /**< GID */
+  char       *groupname;      /**< Group name */
+};
+
+dbus_bool_t _dbus_user_info_fill     (DBusUserInfo     *info,
+                                      const DBusString *username,
+                                      DBusError        *error);
+dbus_bool_t _dbus_user_info_fill_uid (DBusUserInfo     *info,
+                                      dbus_uid_t        uid,
+                                      DBusError        *error);
+void        _dbus_user_info_free     (DBusUserInfo     *info);
+
+dbus_bool_t _dbus_group_info_fill     (DBusGroupInfo    *info,
+                                       const DBusString *groupname,
+                                       DBusError        *error);
+dbus_bool_t _dbus_group_info_fill_gid (DBusGroupInfo    *info,
+                                       dbus_gid_t        gid,
+                                       DBusError        *error);
+void        _dbus_group_info_free     (DBusGroupInfo    *info);
+
+dbus_uid_t    _dbus_getuid (void);
+dbus_uid_t    _dbus_geteuid (void);
+
+dbus_bool_t _dbus_parse_uid (const DBusString  *uid_str,
+                             dbus_uid_t        *uid);
+
+void _dbus_close_all (void);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SYSDEPS_UNIX_H */
diff --git a/dbus/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus/dbus-sysdeps-util-unix.c
new file mode 100644
index 0000000..76423ab
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-util-unix.c
@@ -0,0 +1,1166 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-util-unix.c Would be in dbus-sysdeps-unix.c, but not used in libdbus
+ * 
+ * Copyright (C) 2002, 2003, 2004, 2005  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-sysdeps.h"
+#include "dbus-sysdeps-unix.h"
+#include "dbus-internals.h"
+#include "dbus-pipe.h"
+#include "dbus-protocol.h"
+#include "dbus-string.h"
+#define DBUS_USERDB_INCLUDES_PRIVATE 1
+#include "dbus-userdb.h"
+#include "dbus-test.h"
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#include <grp.h>
+#include <sys/socket.h>
+#include <dirent.h>
+#include <sys/un.h>
+#include <syslog.h>
+
+#ifdef HAVE_SYS_SYSLIMITS_H
+#include <sys/syslimits.h>
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/**
+ * @addtogroup DBusInternalsUtils
+ * @{
+ */
+
+
+/**
+ * Does the chdir, fork, setsid, etc. to become a daemon process.
+ *
+ * @param pidfile #NULL, or pidfile to create
+ * @param print_pid_pipe pipe to print daemon's pid to, or -1 for none
+ * @param error return location for errors
+ * @param keep_umask #TRUE to keep the original umask
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_become_daemon (const DBusString *pidfile,
+                     DBusPipe         *print_pid_pipe,
+                     DBusError        *error,
+                     dbus_bool_t       keep_umask)
+{
+  const char *s;
+  pid_t child_pid;
+  int dev_null_fd;
+
+  _dbus_verbose ("Becoming a daemon...\n");
+
+  _dbus_verbose ("chdir to /\n");
+  if (chdir ("/") < 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Could not chdir() to root directory");
+      return FALSE;
+    }
+
+  _dbus_verbose ("forking...\n");
+  switch ((child_pid = fork ()))
+    {
+    case -1:
+      _dbus_verbose ("fork failed\n");
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to fork daemon: %s", _dbus_strerror (errno));
+      return FALSE;
+      break;
+
+    case 0:
+      _dbus_verbose ("in child, closing std file descriptors\n");
+
+      /* silently ignore failures here, if someone
+       * doesn't have /dev/null we may as well try
+       * to continue anyhow
+       */
+      
+      dev_null_fd = open ("/dev/null", O_RDWR);
+      if (dev_null_fd >= 0)
+        {
+          dup2 (dev_null_fd, 0);
+          dup2 (dev_null_fd, 1);
+          
+          s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
+          if (s == NULL || *s == '\0')
+            dup2 (dev_null_fd, 2);
+          else
+            _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n");
+        }
+
+      if (!keep_umask)
+        {
+          /* Get a predictable umask */
+          _dbus_verbose ("setting umask\n");
+          umask (022);
+        }
+
+      _dbus_verbose ("calling setsid()\n");
+      if (setsid () == -1)
+        _dbus_assert_not_reached ("setsid() failed");
+      
+      break;
+
+    default:
+      if (!_dbus_write_pid_to_file_and_pipe (pidfile, print_pid_pipe,
+                                             child_pid, error))
+        {
+          _dbus_verbose ("pid file or pipe write failed: %s\n",
+                         error->message);
+          kill (child_pid, SIGTERM);
+          return FALSE;
+        }
+
+      _dbus_verbose ("parent exiting\n");
+      _exit (0);
+      break;
+    }
+  
+  return TRUE;
+}
+
+
+/**
+ * Creates a file containing the process ID.
+ *
+ * @param filename the filename to write to
+ * @param pid our process ID
+ * @param error return location for errors
+ * @returns #FALSE on failure
+ */
+static dbus_bool_t
+_dbus_write_pid_file (const DBusString *filename,
+                      unsigned long     pid,
+		      DBusError        *error)
+{
+  const char *cfilename;
+  int fd;
+  FILE *f;
+
+  cfilename = _dbus_string_get_const_data (filename);
+  
+  fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
+  
+  if (fd < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to open \"%s\": %s", cfilename,
+                      _dbus_strerror (errno));
+      return FALSE;
+    }
+
+  if ((f = fdopen (fd, "w")) == NULL)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
+      _dbus_close (fd, NULL);
+      return FALSE;
+    }
+  
+  if (fprintf (f, "%lu\n", pid) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to write to \"%s\": %s", cfilename,
+                      _dbus_strerror (errno));
+      
+      fclose (f);
+      return FALSE;
+    }
+
+  if (fclose (f) == EOF)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to close \"%s\": %s", cfilename,
+                      _dbus_strerror (errno));
+      return FALSE;
+    }
+  
+  return TRUE;
+}
+
+/**
+ * Writes the given pid_to_write to a pidfile (if non-NULL) and/or to a
+ * pipe (if non-NULL). Does nothing if pidfile and print_pid_pipe are both
+ * NULL.
+ *
+ * @param pidfile the file to write to or #NULL
+ * @param print_pid_pipe the pipe to write to or #NULL
+ * @param pid_to_write the pid to write out
+ * @param error error on failure
+ * @returns FALSE if error is set
+ */
+dbus_bool_t
+_dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
+                                  DBusPipe         *print_pid_pipe,
+                                  dbus_pid_t        pid_to_write,
+                                  DBusError        *error)
+{
+  if (pidfile)
+    {
+      _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
+      if (!_dbus_write_pid_file (pidfile,
+                                 pid_to_write,
+                                 error))
+        {
+          _dbus_verbose ("pid file write failed\n");
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          return FALSE;
+        }
+    }
+  else
+    {
+      _dbus_verbose ("No pid file requested\n");
+    }
+
+  if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
+    {
+      DBusString pid;
+      int bytes;
+
+      _dbus_verbose ("writing our pid to pipe %d\n",
+                     print_pid_pipe->fd);
+      
+      if (!_dbus_string_init (&pid))
+        {
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+	  
+      if (!_dbus_string_append_int (&pid, pid_to_write) ||
+          !_dbus_string_append (&pid, "\n"))
+        {
+          _dbus_string_free (&pid);
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+	  
+      bytes = _dbus_string_get_length (&pid);
+      if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
+        {
+          /* _dbus_pipe_write sets error only on failure, not short write */
+          if (error != NULL && !dbus_error_is_set(error))
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Printing message bus PID: did not write enough bytes\n");
+            }
+          _dbus_string_free (&pid);
+          return FALSE;
+        }
+	  
+      _dbus_string_free (&pid);
+    }
+  else
+    {
+      _dbus_verbose ("No pid pipe to write to\n");
+    }
+
+  return TRUE;
+}
+
+/**
+ * Verify that after the fork we can successfully change to this user.
+ *
+ * @param user the username given in the daemon configuration
+ * @returns #TRUE if username is valid
+ */
+dbus_bool_t
+_dbus_verify_daemon_user (const char *user)
+{
+  DBusString u;
+
+  _dbus_string_init_const (&u, user);
+
+  return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
+}
+
+
+/* The HAVE_LIBAUDIT case lives in selinux.c */
+#ifndef HAVE_LIBAUDIT
+/**
+ * Changes the user and group the bus is running as.
+ *
+ * @param user the user to become
+ * @param error return location for errors
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_change_to_daemon_user  (const char    *user,
+                              DBusError     *error)
+{
+  dbus_uid_t uid;
+  dbus_gid_t gid;
+  DBusString u;
+
+  _dbus_string_init_const (&u, user);
+
+  if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "User '%s' does not appear to exist?",
+                      user);
+      return FALSE;
+    }
+
+  /* setgroups() only works if we are a privileged process,
+   * so we don't return error on failure; the only possible
+   * failure is that we don't have perms to do it.
+   *
+   * not sure this is right, maybe if setuid()
+   * is going to work then setgroups() should also work.
+   */
+  if (setgroups (0, NULL) < 0)
+    _dbus_warn ("Failed to drop supplementary groups: %s\n",
+                _dbus_strerror (errno));
+
+  /* Set GID first, or the setuid may remove our permission
+   * to change the GID
+   */
+  if (setgid (gid) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to set GID to %lu: %s", gid,
+                      _dbus_strerror (errno));
+      return FALSE;
+    }
+
+  if (setuid (uid) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to set UID to %lu: %s", uid,
+                      _dbus_strerror (errno));
+      return FALSE;
+    }
+
+  return TRUE;
+}
+#endif /* !HAVE_LIBAUDIT */
+
+
+/**
+ * Attempt to ensure that the current process can open
+ * at least @limit file descriptors.
+ *
+ * If @limit is lower than the current, it will not be
+ * lowered.  No error is returned if the request can
+ * not be satisfied.
+ *
+ * @limit Number of file descriptors
+ */
+void
+_dbus_request_file_descriptor_limit (unsigned int limit)
+{
+#ifdef HAVE_SETRLIMIT
+  struct rlimit lim;
+  struct rlimit target_lim;
+
+  /* No point to doing this practically speaking
+   * if we're not uid 0.  We expect the system
+   * bus to use this before we change UID, and
+   * the session bus takes the Linux default
+   * of 1024 for both cur and max.
+   */
+  if (getuid () != 0)
+    return;
+
+  if (getrlimit (RLIMIT_NOFILE, &lim) < 0)
+    return;
+
+  if (lim.rlim_cur >= limit)
+    return;
+
+  /* Ignore "maximum limit", assume we have the "superuser"
+   * privileges.  On Linux this is CAP_SYS_RESOURCE.
+   */
+  target_lim.rlim_cur = target_lim.rlim_max = limit;
+  /* Also ignore errors; if we fail, we will at least work
+   * up to whatever limit we had, which seems better than
+   * just outright aborting.
+   *
+   * However, in the future we should probably log this so OS builders
+   * have a chance to notice any misconfiguration like dbus-daemon
+   * being started without CAP_SYS_RESOURCE.
+   */
+  setrlimit (RLIMIT_NOFILE, &target_lim);
+#endif
+}
+
+void
+_dbus_init_system_log (void)
+{
+#if HAVE_DECL_LOG_PERROR
+  openlog ("dbus", LOG_PID | LOG_PERROR, LOG_DAEMON);
+#else
+  openlog ("dbus", LOG_PID, LOG_DAEMON);
+#endif
+}
+
+/**
+ * Log a message to the system log file (e.g. syslog on Unix).
+ *
+ * @param severity a severity value
+ * @param msg a printf-style format string
+ * @param args arguments for the format string
+ *
+ */
+void
+_dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...)
+{
+  va_list args;
+
+  va_start (args, msg);
+
+  _dbus_system_logv (severity, msg, args);
+
+  va_end (args);
+}
+
+/**
+ * Log a message to the system log file (e.g. syslog on Unix).
+ *
+ * @param severity a severity value
+ * @param msg a printf-style format string
+ * @param args arguments for the format string
+ *
+ * If the FATAL severity is given, this function will terminate the program
+ * with an error code.
+ */
+void
+_dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args)
+{
+  int flags;
+  switch (severity)
+    {
+      case DBUS_SYSTEM_LOG_INFO:
+        flags =  LOG_DAEMON | LOG_NOTICE;
+        break;
+      case DBUS_SYSTEM_LOG_SECURITY:
+        flags = LOG_AUTH | LOG_NOTICE;
+        break;
+      case DBUS_SYSTEM_LOG_FATAL:
+        flags = LOG_DAEMON|LOG_CRIT;
+        break;
+      default:
+        return;
+    }
+
+#ifndef HAVE_DECL_LOG_PERROR
+    {
+      /* vsyslog() won't write to stderr, so we'd better do it */
+      va_list tmp;
+
+      DBUS_VA_COPY (tmp, args);
+      fprintf (stderr, "dbus[" DBUS_PID_FORMAT "]: ", _dbus_getpid ());
+      vfprintf (stderr, msg, tmp);
+      fputc ('\n', stderr);
+      va_end (tmp);
+    }
+#endif
+
+  vsyslog (flags, msg, args);
+
+  if (severity == DBUS_SYSTEM_LOG_FATAL)
+    exit (1);
+}
+
+/** Installs a UNIX signal handler
+ *
+ * @param sig the signal to handle
+ * @param handler the handler
+ */
+void
+_dbus_set_signal_handler (int               sig,
+                          DBusSignalHandler handler)
+{
+  struct sigaction act;
+  sigset_t empty_mask;
+  
+  sigemptyset (&empty_mask);
+  act.sa_handler = handler;
+  act.sa_mask    = empty_mask;
+  act.sa_flags   = 0;
+  sigaction (sig,  &act, NULL);
+}
+
+/** Checks if a file exists
+*
+* @param file full path to the file
+* @returns #TRUE if file exists
+*/
+dbus_bool_t 
+_dbus_file_exists (const char *file)
+{
+  return (access (file, F_OK) == 0);
+}
+
+/** Checks if user is at the console
+*
+* @param username user to check
+* @param error return location for errors
+* @returns #TRUE is the user is at the consolei and there are no errors
+*/
+dbus_bool_t 
+_dbus_user_at_console (const char *username,
+                       DBusError  *error)
+{
+
+  DBusString u, f;
+  dbus_bool_t result;
+
+  result = FALSE;
+  if (!_dbus_string_init (&f))
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR))
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+
+  _dbus_string_init_const (&u, username);
+
+  if (!_dbus_concat_dir_and_file (&f, &u))
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+
+  result = _dbus_file_exists (_dbus_string_get_const_data (&f));
+
+ out:
+  _dbus_string_free (&f);
+
+  return result;
+}
+
+
+/**
+ * Checks whether the filename is an absolute path
+ *
+ * @param filename the filename
+ * @returns #TRUE if an absolute path
+ */
+dbus_bool_t
+_dbus_path_is_absolute (const DBusString *filename)
+{
+  if (_dbus_string_get_length (filename) > 0)
+    return _dbus_string_get_byte (filename, 0) == '/';
+  else
+    return FALSE;
+}
+
+/**
+ * stat() wrapper.
+ *
+ * @param filename the filename to stat
+ * @param statbuf the stat info to fill in
+ * @param error return location for error
+ * @returns #FALSE if error was set
+ */
+dbus_bool_t
+_dbus_stat (const DBusString *filename,
+            DBusStat         *statbuf,
+            DBusError        *error)
+{
+  const char *filename_c;
+  struct stat sb;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  filename_c = _dbus_string_get_const_data (filename);
+
+  if (stat (filename_c, &sb) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "%s", _dbus_strerror (errno));
+      return FALSE;
+    }
+
+  statbuf->mode = sb.st_mode;
+  statbuf->nlink = sb.st_nlink;
+  statbuf->uid = sb.st_uid;
+  statbuf->gid = sb.st_gid;
+  statbuf->size = sb.st_size;
+  statbuf->atime = sb.st_atime;
+  statbuf->mtime = sb.st_mtime;
+  statbuf->ctime = sb.st_ctime;
+
+  return TRUE;
+}
+
+
+/**
+ * Internals of directory iterator
+ */
+struct DBusDirIter
+{
+  DIR *d; /**< The DIR* from opendir() */
+  
+};
+
+/**
+ * Open a directory to iterate over.
+ *
+ * @param filename the directory name
+ * @param error exception return object or #NULL
+ * @returns new iterator, or #NULL on error
+ */
+DBusDirIter*
+_dbus_directory_open (const DBusString *filename,
+                      DBusError        *error)
+{
+  DIR *d;
+  DBusDirIter *iter;
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  filename_c = _dbus_string_get_const_data (filename);
+
+  d = opendir (filename_c);
+  if (d == NULL)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to read directory \"%s\": %s",
+                      filename_c,
+                      _dbus_strerror (errno));
+      return NULL;
+    }
+  iter = dbus_new0 (DBusDirIter, 1);
+  if (iter == NULL)
+    {
+      closedir (d);
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                      "Could not allocate memory for directory iterator");
+      return NULL;
+    }
+
+  iter->d = d;
+
+  return iter;
+}
+
+/**
+ * Get next file in the directory. Will not return "." or ".."  on
+ * UNIX. If an error occurs, the contents of "filename" are
+ * undefined. The error is never set if the function succeeds.
+ *
+ * This function is not re-entrant, and not necessarily thread-safe.
+ * Only use it for test code or single-threaded utilities.
+ *
+ * @param iter the iterator
+ * @param filename string to be set to the next file in the dir
+ * @param error return location for error
+ * @returns #TRUE if filename was filled in with a new filename
+ */
+dbus_bool_t
+_dbus_directory_get_next_file (DBusDirIter      *iter,
+                               DBusString       *filename,
+                               DBusError        *error)
+{
+  struct dirent *ent;
+  int err;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ again:
+  errno = 0;
+  ent = readdir (iter->d);
+
+  if (!ent)
+    {
+      err = errno;
+
+      if (err != 0)
+        dbus_set_error (error,
+                        _dbus_error_from_errno (err),
+                        "%s", _dbus_strerror (err));
+
+      return FALSE;
+    }
+  else if (ent->d_name[0] == '.' &&
+           (ent->d_name[1] == '\0' ||
+            (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
+    goto again;
+  else
+    {
+      _dbus_string_set_length (filename, 0);
+      if (!_dbus_string_append (filename, ent->d_name))
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                          "No memory to read directory entry");
+          return FALSE;
+        }
+      else
+        {
+          return TRUE;
+        }
+    }
+}
+
+/**
+ * Closes a directory iteration.
+ */
+void
+_dbus_directory_close (DBusDirIter *iter)
+{
+  closedir (iter->d);
+  dbus_free (iter);
+}
+
+static dbus_bool_t
+fill_user_info_from_group (struct group  *g,
+                           DBusGroupInfo *info,
+                           DBusError     *error)
+{
+  _dbus_assert (g->gr_name != NULL);
+  
+  info->gid = g->gr_gid;
+  info->groupname = _dbus_strdup (g->gr_name);
+
+  /* info->members = dbus_strdupv (g->gr_mem) */
+  
+  if (info->groupname == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+fill_group_info (DBusGroupInfo    *info,
+                 dbus_gid_t        gid,
+                 const DBusString *groupname,
+                 DBusError        *error)
+{
+  const char *group_c_str;
+
+  _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
+  _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
+
+  if (groupname)
+    group_c_str = _dbus_string_get_const_data (groupname);
+  else
+    group_c_str = NULL;
+  
+  /* For now assuming that the getgrnam() and getgrgid() flavors
+   * always correspond to the pwnam flavors, if not we have
+   * to add more configure checks.
+   */
+  
+#if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
+  {
+    struct group *g;
+    int result;
+    size_t buflen;
+    char *buf;
+    struct group g_str;
+    dbus_bool_t b;
+
+    /* retrieve maximum needed size for buf */
+    buflen = sysconf (_SC_GETGR_R_SIZE_MAX);
+
+    /* sysconf actually returns a long, but everything else expects size_t,
+     * so just recast here.
+     * https://bugs.freedesktop.org/show_bug.cgi?id=17061
+     */
+    if ((long) buflen <= 0)
+      buflen = 1024;
+
+    result = -1;
+    while (1)
+      {
+        buf = dbus_malloc (buflen);
+        if (buf == NULL)
+          {
+            dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+            return FALSE;
+          }
+
+        g = NULL;
+#ifdef HAVE_POSIX_GETPWNAM_R
+        if (group_c_str)
+          result = getgrnam_r (group_c_str, &g_str, buf, buflen,
+                               &g);
+        else
+          result = getgrgid_r (gid, &g_str, buf, buflen,
+                               &g);
+#else
+        g = getgrnam_r (group_c_str, &g_str, buf, buflen);
+        result = 0;
+#endif /* !HAVE_POSIX_GETPWNAM_R */
+        /* Try a bigger buffer if ERANGE was returned:
+           https://bugs.freedesktop.org/show_bug.cgi?id=16727
+        */
+        if (result == ERANGE && buflen < 512 * 1024)
+          {
+            dbus_free (buf);
+            buflen *= 2;
+          }
+        else
+          {
+            break;
+          }
+      }
+
+    if (result == 0 && g == &g_str)
+      {
+        b = fill_user_info_from_group (g, info, error);
+        dbus_free (buf);
+        return b;
+      }
+    else
+      {
+        dbus_set_error (error, _dbus_error_from_errno (errno),
+                        "Group %s unknown or failed to look it up\n",
+                        group_c_str ? group_c_str : "???");
+        dbus_free (buf);
+        return FALSE;
+      }
+  }
+#else /* ! HAVE_GETPWNAM_R */
+  {
+    /* I guess we're screwed on thread safety here */
+    struct group *g;
+
+    g = getgrnam (group_c_str);
+
+    if (g != NULL)
+      {
+        return fill_user_info_from_group (g, info, error);
+      }
+    else
+      {
+        dbus_set_error (error, _dbus_error_from_errno (errno),
+                        "Group %s unknown or failed to look it up\n",
+                        group_c_str ? group_c_str : "???");
+        return FALSE;
+      }
+  }
+#endif  /* ! HAVE_GETPWNAM_R */
+}
+
+/**
+ * Initializes the given DBusGroupInfo struct
+ * with information about the given group name.
+ *
+ * @param info the group info struct
+ * @param groupname name of group
+ * @param error the error return
+ * @returns #FALSE if error is set
+ */
+dbus_bool_t
+_dbus_group_info_fill (DBusGroupInfo    *info,
+                       const DBusString *groupname,
+                       DBusError        *error)
+{
+  return fill_group_info (info, DBUS_GID_UNSET,
+                          groupname, error);
+
+}
+
+/**
+ * Initializes the given DBusGroupInfo struct
+ * with information about the given group ID.
+ *
+ * @param info the group info struct
+ * @param gid group ID
+ * @param error the error return
+ * @returns #FALSE if error is set
+ */
+dbus_bool_t
+_dbus_group_info_fill_gid (DBusGroupInfo *info,
+                           dbus_gid_t     gid,
+                           DBusError     *error)
+{
+  return fill_group_info (info, gid, NULL, error);
+}
+
+/**
+ * Parse a UNIX user from the bus config file. On Windows, this should
+ * simply always fail (just return #FALSE).
+ *
+ * @param username the username text
+ * @param uid_p place to return the uid
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_parse_unix_user_from_config (const DBusString  *username,
+                                   dbus_uid_t        *uid_p)
+{
+  return _dbus_get_user_id (username, uid_p);
+
+}
+
+/**
+ * Parse a UNIX group from the bus config file. On Windows, this should
+ * simply always fail (just return #FALSE).
+ *
+ * @param groupname the groupname text
+ * @param gid_p place to return the gid
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_parse_unix_group_from_config (const DBusString  *groupname,
+                                    dbus_gid_t        *gid_p)
+{
+  return _dbus_get_group_id (groupname, gid_p);
+}
+
+/**
+ * Gets all groups corresponding to the given UNIX user ID. On UNIX,
+ * just calls _dbus_groups_from_uid(). On Windows, should always
+ * fail since we don't know any UNIX groups.
+ *
+ * @param uid the UID
+ * @param group_ids return location for array of group IDs
+ * @param n_group_ids return location for length of returned array
+ * @returns #TRUE if the UID existed and we got some credentials
+ */
+dbus_bool_t
+_dbus_unix_groups_from_uid (dbus_uid_t            uid,
+                            dbus_gid_t          **group_ids,
+                            int                  *n_group_ids)
+{
+  return _dbus_groups_from_uid (uid, group_ids, n_group_ids);
+}
+
+/**
+ * Checks to see if the UNIX user ID is at the console.
+ * Should always fail on Windows (set the error to
+ * #DBUS_ERROR_NOT_SUPPORTED).
+ *
+ * @param uid UID of person to check 
+ * @param error return location for errors
+ * @returns #TRUE if the UID is the same as the console user and there are no errors
+ */
+dbus_bool_t
+_dbus_unix_user_is_at_console (dbus_uid_t         uid,
+                               DBusError         *error)
+{
+  return _dbus_is_console_user (uid, error);
+
+}
+
+/**
+ * Checks to see if the UNIX user ID matches the UID of
+ * the process. Should always return #FALSE on Windows.
+ *
+ * @param uid the UNIX user ID
+ * @returns #TRUE if this uid owns the process.
+ */
+dbus_bool_t
+_dbus_unix_user_is_process_owner (dbus_uid_t uid)
+{
+  return uid == _dbus_geteuid ();
+}
+
+/**
+ * Checks to see if the Windows user SID matches the owner of
+ * the process. Should always return #FALSE on UNIX.
+ *
+ * @param windows_sid the Windows user SID
+ * @returns #TRUE if this user owns the process.
+ */
+dbus_bool_t
+_dbus_windows_user_is_process_owner (const char *windows_sid)
+{
+  return FALSE;
+}
+
+/** @} */ /* End of DBusInternalsUtils functions */
+
+/**
+ * @addtogroup DBusString
+ *
+ * @{
+ */
+/**
+ * Get the directory name from a complete filename
+ * @param filename the filename
+ * @param dirname string to append directory name to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_string_get_dirname  (const DBusString *filename,
+                           DBusString       *dirname)
+{
+  int sep;
+  
+  _dbus_assert (filename != dirname);
+  _dbus_assert (filename != NULL);
+  _dbus_assert (dirname != NULL);
+
+  /* Ignore any separators on the end */
+  sep = _dbus_string_get_length (filename);
+  if (sep == 0)
+    return _dbus_string_append (dirname, "."); /* empty string passed in */
+    
+  while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
+    --sep;
+
+  _dbus_assert (sep >= 0);
+  
+  if (sep == 0)
+    return _dbus_string_append (dirname, "/");
+  
+  /* Now find the previous separator */
+  _dbus_string_find_byte_backward (filename, sep, '/', &sep);
+  if (sep < 0)
+    return _dbus_string_append (dirname, ".");
+  
+  /* skip multiple separators */
+  while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/')
+    --sep;
+
+  _dbus_assert (sep >= 0);
+  
+  if (sep == 0 &&
+      _dbus_string_get_byte (filename, 0) == '/')
+    return _dbus_string_append (dirname, "/");
+  else
+    return _dbus_string_copy_len (filename, 0, sep - 0,
+                                  dirname, _dbus_string_get_length (dirname));
+}
+/** @} */ /* DBusString stuff */
+
+static void
+string_squash_nonprintable (DBusString *str)
+{
+  unsigned char *buf;
+  int i, len; 
+  
+  buf = _dbus_string_get_data (str);
+  len = _dbus_string_get_length (str);
+  
+  for (i = 0; i < len; i++)
+    {
+      unsigned char c = (unsigned char) buf[i];
+      if (c == '\0')
+        buf[i] = ' ';
+      else if (c < 0x20 || c > 127)
+        buf[i] = '?';
+    }
+}
+
+/**
+ * Get a printable string describing the command used to execute
+ * the process with pid.  This string should only be used for
+ * informative purposes such as logging; it may not be trusted.
+ * 
+ * The command is guaranteed to be printable ASCII and no longer
+ * than max_len.
+ * 
+ * @param pid Process id
+ * @param str Append command to this string
+ * @param max_len Maximum length of returned command
+ * @param error return location for errors
+ * @returns #FALSE on error
+ */
+dbus_bool_t 
+_dbus_command_for_pid (unsigned long  pid,
+                       DBusString    *str,
+                       int            max_len,
+                       DBusError     *error)
+{
+  /* This is all Linux-specific for now */
+  DBusString path;
+  DBusString cmdline;
+  int fd;
+  
+  if (!_dbus_string_init (&path)) 
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+  
+  if (!_dbus_string_init (&cmdline))
+    {
+      _DBUS_SET_OOM (error);
+      _dbus_string_free (&path);
+      return FALSE;
+    }
+  
+  if (!_dbus_string_append_printf (&path, "/proc/%ld/cmdline", pid))
+    goto oom;
+  
+  fd = open (_dbus_string_get_const_data (&path), O_RDONLY);
+  if (fd < 0) 
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (errno),
+                      "Failed to open \"%s\": %s",
+                      _dbus_string_get_const_data (&path),
+                      _dbus_strerror (errno));
+      goto fail;
+    }
+  
+  if (!_dbus_read (fd, &cmdline, max_len))
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (errno),
+                      "Failed to read from \"%s\": %s",
+                      _dbus_string_get_const_data (&path),
+                      _dbus_strerror (errno));      
+      goto fail;
+    }
+  
+  if (!_dbus_close (fd, error))
+    goto fail;
+  
+  string_squash_nonprintable (&cmdline);  
+
+  if (!_dbus_string_copy (&cmdline, 0, str, _dbus_string_get_length (str)))
+    goto oom;
+
+  _dbus_string_free (&cmdline);  
+  _dbus_string_free (&path);
+  return TRUE;
+oom:
+  _DBUS_SET_OOM (error);
+fail:
+  _dbus_string_free (&cmdline);
+  _dbus_string_free (&path);
+  return FALSE;
+}
diff --git a/dbus/dbus/dbus-sysdeps-util-win.c b/dbus/dbus/dbus-sysdeps-util-win.c
new file mode 100644
index 0000000..111db9e
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-util-win.c
@@ -0,0 +1,1532 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-util.c Would be in dbus-sysdeps.c, but not used in libdbus
+ * 
+ * Copyright (C) 2002, 2003, 2004, 2005  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#define STRSAFE_NO_DEPRECATE
+
+#include "dbus-sysdeps.h"
+#include "dbus-internals.h"
+#include "dbus-protocol.h"
+#include "dbus-string.h"
+#include "dbus-sysdeps.h"
+#include "dbus-sysdeps-win.h"
+#include "dbus-sockets-win.h"
+#include "dbus-memory.h"
+#include "dbus-pipe.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <winsock2.h>   // WSA error codes
+
+#ifndef DBUS_WINCE
+#include <io.h>
+#include <lm.h>
+#include <sys/stat.h>
+#endif
+
+
+/**
+ * Does the chdir, fork, setsid, etc. to become a daemon process.
+ *
+ * @param pidfile #NULL, or pidfile to create
+ * @param print_pid_fd file descriptor to print daemon's pid to, or -1 for none
+ * @param error return location for errors
+ * @param keep_umask #TRUE to keep the original umask
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_become_daemon (const DBusString *pidfile,
+                     DBusPipe         *print_pid_pipe,
+                     DBusError        *error,
+                     dbus_bool_t       keep_umask)
+{
+  return TRUE;
+}
+
+/**
+ * Creates a file containing the process ID.
+ *
+ * @param filename the filename to write to
+ * @param pid our process ID
+ * @param error return location for errors
+ * @returns #FALSE on failure
+ */
+static dbus_bool_t
+_dbus_write_pid_file (const DBusString *filename,
+                      unsigned long     pid,
+                      DBusError        *error)
+{
+  const char *cfilename;
+  HANDLE hnd;
+  char pidstr[20];
+  int total;
+  int bytes_to_write;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  cfilename = _dbus_string_get_const_data (filename);
+
+  hnd = CreateFileA (cfilename, GENERIC_WRITE,
+                     FILE_SHARE_READ | FILE_SHARE_WRITE,
+                     NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
+                     INVALID_HANDLE_VALUE);
+  if (hnd == INVALID_HANDLE_VALUE)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                      "Could not create PID file %s: %s",
+                      cfilename, emsg);
+      _dbus_win_free_error_string (emsg);
+      return FALSE;
+    }
+
+  if (snprintf (pidstr, sizeof (pidstr), "%lu\n", pid) < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_system_errno (),
+                      "Failed to format PID for \"%s\": %s", cfilename,
+                      _dbus_strerror_from_errno ());
+      CloseHandle (hnd);
+      return FALSE;
+    }
+
+  total = 0;
+  bytes_to_write = strlen (pidstr);;
+
+  while (total < bytes_to_write)
+    {
+      DWORD bytes_written;
+      BOOL res;
+
+      res = WriteFile (hnd, pidstr + total, bytes_to_write - total,
+                       &bytes_written, NULL);
+
+      if (res == 0 || bytes_written <= 0)
+        {
+          char *emsg = _dbus_win_error_string (GetLastError ());
+          dbus_set_error (error, _dbus_win_error_from_last_error (),
+                           "Could not write to %s: %s", cfilename, emsg);
+          _dbus_win_free_error_string (emsg);
+          CloseHandle (hnd);
+          return FALSE;
+        }
+
+      total += bytes_written;
+    }
+
+  if (CloseHandle (hnd) == 0)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                       "Could not close file %s: %s",
+                      cfilename, emsg);
+      _dbus_win_free_error_string (emsg);
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Writes the given pid_to_write to a pidfile (if non-NULL) and/or to a
+ * pipe (if non-NULL). Does nothing if pidfile and print_pid_pipe are both
+ * NULL.
+ *
+ * @param pidfile the file to write to or #NULL
+ * @param print_pid_pipe the pipe to write to or #NULL
+ * @param pid_to_write the pid to write out
+ * @param error error on failure
+ * @returns FALSE if error is set
+ */
+dbus_bool_t
+_dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
+                                  DBusPipe         *print_pid_pipe,
+                                  dbus_pid_t        pid_to_write,
+                                  DBusError        *error)
+{
+  if (pidfile)
+    {
+      _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
+      if (!_dbus_write_pid_file (pidfile,
+                                 pid_to_write,
+                                 error))
+        {
+          _dbus_verbose ("pid file write failed\n");
+          _DBUS_ASSERT_ERROR_IS_SET(error);
+          return FALSE;
+        }
+    }
+  else
+    {
+      _dbus_verbose ("No pid file requested\n");
+    }
+
+  if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
+    {
+      DBusString pid;
+      int bytes;
+
+      _dbus_verbose ("writing our pid to pipe %d\n", print_pid_pipe->fd);
+
+      if (!_dbus_string_init (&pid))
+        {
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      if (!_dbus_string_append_int (&pid, pid_to_write) ||
+          !_dbus_string_append (&pid, "\n"))
+        {
+          _dbus_string_free (&pid);
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      bytes = _dbus_string_get_length (&pid);
+      if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
+        {
+          /* _dbus_pipe_write sets error only on failure, not short write */
+          if (error != NULL && !dbus_error_is_set(error))
+            {
+              dbus_set_error (error, DBUS_ERROR_FAILED,
+                              "Printing message bus PID: did not write enough bytes\n");
+            }
+          _dbus_string_free (&pid);
+          return FALSE;
+        }
+
+      _dbus_string_free (&pid);
+    }
+  else
+    {
+      _dbus_verbose ("No pid pipe to write to\n");
+    }
+
+  return TRUE;
+}
+
+/**
+ * Verify that after the fork we can successfully change to this user.
+ *
+ * @param user the username given in the daemon configuration
+ * @returns #TRUE if username is valid
+ */
+dbus_bool_t
+_dbus_verify_daemon_user (const char *user)
+{
+  return TRUE;
+}
+
+/**
+ * Changes the user and group the bus is running as.
+ *
+ * @param user the user to become
+ * @param error return location for errors
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_change_to_daemon_user  (const char    *user,
+                              DBusError     *error)
+{
+  return TRUE;
+}
+
+void
+_dbus_request_file_descriptor_limit (unsigned int limit)
+{
+}
+
+void
+_dbus_init_system_log (void)
+{
+  /* OutputDebugStringA doesn't need any special initialization, do nothing */
+}
+
+/**
+ * Log a message to the system log file (e.g. syslog on Unix).
+ *
+ * @param severity a severity value
+ * @param msg a printf-style format string
+ * @param args arguments for the format string
+ *
+ */
+void
+_dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...)
+{
+  va_list args;
+
+  va_start (args, msg);
+
+  _dbus_system_logv (severity, msg, args);
+
+  va_end (args);
+}
+
+/**
+ * Log a message to the system log file (e.g. syslog on Unix).
+ *
+ * @param severity a severity value
+ * @param msg a printf-style format string
+ * @param args arguments for the format string
+ *
+ * If the FATAL severity is given, this function will terminate the program
+ * with an error code.
+ */
+void
+_dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args)
+{
+  char *s = "";
+  char buf[1024];
+  
+  switch(severity) 
+   {
+     case DBUS_SYSTEM_LOG_INFO: s = "info"; break;
+     case DBUS_SYSTEM_LOG_SECURITY: s = "security"; break;
+     case DBUS_SYSTEM_LOG_FATAL: s = "fatal"; break;
+   }
+   
+  sprintf(buf,"%s%s",s,msg);
+  vsprintf(buf,buf,args);
+  OutputDebugStringA(buf);
+  
+  if (severity == DBUS_SYSTEM_LOG_FATAL)
+    exit (1);
+}
+
+/** Installs a signal handler
+ *
+ * @param sig the signal to handle
+ * @param handler the handler
+ */
+void
+_dbus_set_signal_handler (int               sig,
+                          DBusSignalHandler handler)
+{
+  _dbus_verbose ("_dbus_set_signal_handler() has to be implemented\n");
+}
+
+/**
+ * stat() wrapper.
+ *
+ * @param filename the filename to stat
+ * @param statbuf the stat info to fill in
+ * @param error return location for error
+ * @returns #FALSE if error was set
+ */
+dbus_bool_t
+_dbus_stat(const DBusString *filename,
+           DBusStat         *statbuf,
+           DBusError        *error)
+{
+  const char *filename_c;
+  WIN32_FILE_ATTRIBUTE_DATA wfad;
+  char *lastdot;
+  DWORD rc;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  filename_c = _dbus_string_get_const_data (filename);
+
+  if (!GetFileAttributesExA (filename_c, GetFileExInfoStandard, &wfad))
+    {
+      _dbus_win_set_error_from_win_error (error, GetLastError ());
+      return FALSE;
+    }
+
+  if (wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+    statbuf->mode = _S_IFDIR;
+  else
+    statbuf->mode = _S_IFREG;
+
+  statbuf->mode |= _S_IREAD;
+  if (wfad.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+    statbuf->mode |= _S_IWRITE;
+
+  lastdot = strrchr (filename_c, '.');
+  if (lastdot && stricmp (lastdot, ".exe") == 0)
+    statbuf->mode |= _S_IEXEC;
+
+  statbuf->mode |= (statbuf->mode & 0700) >> 3;
+  statbuf->mode |= (statbuf->mode & 0700) >> 6;
+
+  statbuf->nlink = 1;
+
+#ifdef ENABLE_UID_TO_SID
+  {
+    PSID owner_sid, group_sid;
+    PSECURITY_DESCRIPTOR sd;
+
+    sd = NULL;
+    rc = GetNamedSecurityInfo ((char *) filename_c, SE_FILE_OBJECT,
+                               OWNER_SECURITY_INFORMATION |
+                               GROUP_SECURITY_INFORMATION,
+                               &owner_sid, &group_sid,
+                               NULL, NULL,
+                               &sd);
+    if (rc != ERROR_SUCCESS)
+      {
+        _dbus_win_set_error_from_win_error (error, rc);
+        if (sd != NULL)
+          LocalFree (sd);
+        return FALSE;
+      }
+    
+    /* FIXME */
+    statbuf->uid = _dbus_win_sid_to_uid_t (owner_sid);
+    statbuf->gid = _dbus_win_sid_to_uid_t (group_sid);
+
+    LocalFree (sd);
+  }
+#else
+  statbuf->uid = DBUS_UID_UNSET;
+  statbuf->gid = DBUS_GID_UNSET;
+#endif
+
+  statbuf->size = ((dbus_int64_t) wfad.nFileSizeHigh << 32) + wfad.nFileSizeLow;
+
+  statbuf->atime =
+    (((dbus_int64_t) wfad.ftLastAccessTime.dwHighDateTime << 32) +
+     wfad.ftLastAccessTime.dwLowDateTime) / 10000000 - DBUS_INT64_CONSTANT (116444736000000000);
+
+  statbuf->mtime =
+    (((dbus_int64_t) wfad.ftLastWriteTime.dwHighDateTime << 32) +
+     wfad.ftLastWriteTime.dwLowDateTime) / 10000000 - DBUS_INT64_CONSTANT (116444736000000000);
+
+  statbuf->ctime =
+    (((dbus_int64_t) wfad.ftCreationTime.dwHighDateTime << 32) +
+     wfad.ftCreationTime.dwLowDateTime) / 10000000 - DBUS_INT64_CONSTANT (116444736000000000);
+
+  return TRUE;
+}
+
+
+/* This file is part of the KDE project
+Copyright (C) 2000 Werner Almesberger
+
+libc/sys/linux/sys/dirent.h - Directory entry as returned by readdir
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this program; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
+*/
+#define HAVE_NO_D_NAMLEN	/* no struct dirent->d_namlen */
+#define HAVE_DD_LOCK  		/* have locking mechanism */
+
+#define MAXNAMLEN 255		/* sizeof(struct dirent.d_name)-1 */
+
+#define __dirfd(dir) (dir)->dd_fd
+
+/* struct dirent - same as Unix */
+struct dirent
+  {
+    long d_ino;                    /* inode (always 1 in WIN32) */
+    off_t d_off;                /* offset to this dirent */
+    unsigned short d_reclen;    /* length of d_name */
+    char d_name[_MAX_FNAME+1];    /* filename (null terminated) */
+  };
+
+/* typedef DIR - not the same as Unix */
+typedef struct
+  {
+    HANDLE handle;              /* FindFirst/FindNext handle */
+    short offset;               /* offset into directory */
+    short finished;             /* 1 if there are not more files */
+    WIN32_FIND_DATAA fileinfo;  /* from FindFirst/FindNext */
+    char *dir;                  /* the dir we are reading */
+    struct dirent dent;         /* the dirent to return */
+  }
+DIR;
+
+/**********************************************************************
+* Implement dirent-style opendir/readdir/closedir on Window 95/NT
+*
+* Functions defined are opendir(), readdir() and closedir() with the
+* same prototypes as the normal dirent.h implementation.
+*
+* Does not implement telldir(), seekdir(), rewinddir() or scandir().
+* The dirent struct is compatible with Unix, except that d_ino is
+* always 1 and d_off is made up as we go along.
+*
+* Error codes are not available with errno but GetLastError.
+*
+* The DIR typedef is not compatible with Unix.
+**********************************************************************/
+
+static DIR * _dbus_opendir(const char *dir)
+{
+  DIR *dp;
+  char *filespec;
+  HANDLE handle;
+  int index;
+
+  filespec = malloc(strlen(dir) + 2 + 1);
+  strcpy(filespec, dir);
+  index = strlen(filespec) - 1;
+  if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
+    filespec[index] = '\0';
+  strcat(filespec, "\\*");
+
+  dp = (DIR *)malloc(sizeof(DIR));
+  dp->offset = 0;
+  dp->finished = 0;
+  dp->dir = strdup(dir);
+
+  handle = FindFirstFileA(filespec, &(dp->fileinfo));
+  if (handle == INVALID_HANDLE_VALUE)
+    {
+      if (GetLastError() == ERROR_NO_MORE_FILES)
+        dp->finished = 1;
+      else
+        return NULL;
+    }
+
+  dp->handle = handle;
+  free(filespec);
+
+  return dp;
+}
+
+static struct dirent * _dbus_readdir(DIR *dp)
+{
+  int saved_err = GetLastError();
+
+  if (!dp || dp->finished)
+    return NULL;
+
+  if (dp->offset != 0)
+    {
+      if (FindNextFileA(dp->handle, &(dp->fileinfo)) == 0)
+        {
+          if (GetLastError() == ERROR_NO_MORE_FILES)
+            {
+              SetLastError(saved_err);
+              dp->finished = 1;
+            }
+          return NULL;
+        }
+    }
+  dp->offset++;
+  
+  strncpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME);
+  dp->dent.d_ino = 1;
+  dp->dent.d_reclen = strlen(dp->dent.d_name);
+  dp->dent.d_off = dp->offset;
+  
+  return &(dp->dent);
+}
+
+
+static int _dbus_closedir(DIR *dp)
+{
+  if (!dp)
+    return 0;
+  FindClose(dp->handle);
+  if (dp->dir)
+    free(dp->dir);
+  if (dp)
+    free(dp);
+
+  return 0;
+}
+
+
+/**
+ * Internals of directory iterator
+ */
+struct DBusDirIter
+  {
+    DIR *d; /**< The DIR* from opendir() */
+
+  };
+
+/**
+ * Open a directory to iterate over.
+ *
+ * @param filename the directory name
+ * @param error exception return object or #NULL
+ * @returns new iterator, or #NULL on error
+ */
+DBusDirIter*
+_dbus_directory_open (const DBusString *filename,
+                      DBusError        *error)
+{
+  DIR *d;
+  DBusDirIter *iter;
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  filename_c = _dbus_string_get_const_data (filename);
+
+  d = _dbus_opendir (filename_c);
+  if (d == NULL)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                      "Failed to read directory \"%s\": %s",
+                      filename_c, emsg);
+      _dbus_win_free_error_string (emsg);
+      return NULL;
+    }
+  iter = dbus_new0 (DBusDirIter, 1);
+  if (iter == NULL)
+    {
+      _dbus_closedir (d);
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                      "Could not allocate memory for directory iterator");
+      return NULL;
+    }
+
+  iter->d = d;
+
+  return iter;
+}
+
+/**
+ * Get next file in the directory. Will not return "." or ".."  on
+ * UNIX. If an error occurs, the contents of "filename" are
+ * undefined. The error is never set if the function succeeds.
+ *
+ * @todo for thread safety, I think we have to use
+ * readdir_r(). (GLib has the same issue, should file a bug.)
+ *
+ * @param iter the iterator
+ * @param filename string to be set to the next file in the dir
+ * @param error return location for error
+ * @returns #TRUE if filename was filled in with a new filename
+ */
+dbus_bool_t
+_dbus_directory_get_next_file (DBusDirIter      *iter,
+                               DBusString       *filename,
+                               DBusError        *error)
+{
+  struct dirent *ent;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+again:
+  SetLastError (0);
+  ent = _dbus_readdir (iter->d);
+  if (ent == NULL)
+    {
+      if (GetLastError() != 0)
+        {
+          char *emsg = _dbus_win_error_string (GetLastError ());
+          dbus_set_error (error, _dbus_win_error_from_last_error (),
+                          "Failed to get next in directory: %s", emsg);
+          _dbus_win_free_error_string (emsg);
+        }
+      return FALSE;
+    }
+  else if (ent->d_name[0] == '.' &&
+           (ent->d_name[1] == '\0' ||
+            (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
+    goto again;
+  else
+    {
+      _dbus_string_set_length (filename, 0);
+      if (!_dbus_string_append (filename, ent->d_name))
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                          "No memory to read directory entry");
+          return FALSE;
+        }
+      else
+        return TRUE;
+    }
+}
+
+/**
+ * Closes a directory iteration.
+ */
+void
+_dbus_directory_close (DBusDirIter *iter)
+{
+  _dbus_closedir (iter->d);
+  dbus_free (iter);
+}
+
+/** @} */ /* End of DBusInternalsUtils functions */
+
+/**
+ * @addtogroup DBusString
+ *
+ * @{
+ */
+/**
+ * Get the directory name from a complete filename
+ * @param filename the filename
+ * @param dirname string to append directory name to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_string_get_dirname(const DBusString *filename,
+                         DBusString       *dirname)
+{
+  int sep;
+
+  _dbus_assert (filename != dirname);
+  _dbus_assert (filename != NULL);
+  _dbus_assert (dirname != NULL);
+
+  /* Ignore any separators on the end */
+  sep = _dbus_string_get_length (filename);
+  if (sep == 0)
+    return _dbus_string_append (dirname, "."); /* empty string passed in */
+
+  while (sep > 0 &&
+         (_dbus_string_get_byte (filename, sep - 1) == '/' ||
+          _dbus_string_get_byte (filename, sep - 1) == '\\'))
+    --sep;
+
+  _dbus_assert (sep >= 0);
+
+  if (sep == 0 ||
+      (sep == 2 &&
+       _dbus_string_get_byte (filename, 1) == ':' &&
+       isalpha (_dbus_string_get_byte (filename, 0))))
+    return _dbus_string_copy_len (filename, 0, sep + 1,
+                                  dirname, _dbus_string_get_length (dirname));
+
+  {
+    int sep1, sep2;
+    _dbus_string_find_byte_backward (filename, sep, '/', &sep1);
+    _dbus_string_find_byte_backward (filename, sep, '\\', &sep2);
+
+    sep = MAX (sep1, sep2);
+  }
+  if (sep < 0)
+    return _dbus_string_append (dirname, ".");
+
+  while (sep > 0 &&
+         (_dbus_string_get_byte (filename, sep - 1) == '/' ||
+          _dbus_string_get_byte (filename, sep - 1) == '\\'))
+    --sep;
+
+  _dbus_assert (sep >= 0);
+
+  if ((sep == 0 ||
+       (sep == 2 &&
+        _dbus_string_get_byte (filename, 1) == ':' &&
+        isalpha (_dbus_string_get_byte (filename, 0))))
+      &&
+      (_dbus_string_get_byte (filename, sep) == '/' ||
+       _dbus_string_get_byte (filename, sep) == '\\'))
+    return _dbus_string_copy_len (filename, 0, sep + 1,
+                                  dirname, _dbus_string_get_length (dirname));
+  else
+    return _dbus_string_copy_len (filename, 0, sep - 0,
+                                  dirname, _dbus_string_get_length (dirname));
+}
+
+
+/**
+ * Checks to see if the UNIX user ID matches the UID of
+ * the process. Should always return #FALSE on Windows.
+ *
+ * @param uid the UNIX user ID
+ * @returns #TRUE if this uid owns the process.
+ */
+dbus_bool_t
+_dbus_unix_user_is_process_owner (dbus_uid_t uid)
+{
+  return FALSE;
+}
+
+dbus_bool_t _dbus_windows_user_is_process_owner (const char *windows_sid)
+{
+  return TRUE;
+}
+
+/*=====================================================================
+  unix emulation functions - should be removed sometime in the future
+ =====================================================================*/
+
+/**
+ * Checks to see if the UNIX user ID is at the console.
+ * Should always fail on Windows (set the error to
+ * #DBUS_ERROR_NOT_SUPPORTED).
+ *
+ * @param uid UID of person to check 
+ * @param error return location for errors
+ * @returns #TRUE if the UID is the same as the console user and there are no errors
+ */
+dbus_bool_t
+_dbus_unix_user_is_at_console (dbus_uid_t         uid,
+                               DBusError         *error)
+{
+  dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
+                  "UNIX user IDs not supported on Windows\n");
+  return FALSE;
+}
+
+
+/**
+ * Parse a UNIX group from the bus config file. On Windows, this should
+ * simply always fail (just return #FALSE).
+ *
+ * @param groupname the groupname text
+ * @param gid_p place to return the gid
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_parse_unix_group_from_config (const DBusString  *groupname,
+                                    dbus_gid_t        *gid_p)
+{
+  return FALSE;
+}
+
+/**
+ * Parse a UNIX user from the bus config file. On Windows, this should
+ * simply always fail (just return #FALSE).
+ *
+ * @param username the username text
+ * @param uid_p place to return the uid
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_parse_unix_user_from_config (const DBusString  *username,
+                                   dbus_uid_t        *uid_p)
+{
+  return FALSE;
+}
+
+
+/**
+ * Gets all groups corresponding to the given UNIX user ID. On UNIX,
+ * just calls _dbus_groups_from_uid(). On Windows, should always
+ * fail since we don't know any UNIX groups.
+ *
+ * @param uid the UID
+ * @param group_ids return location for array of group IDs
+ * @param n_group_ids return location for length of returned array
+ * @returns #TRUE if the UID existed and we got some credentials
+ */
+dbus_bool_t
+_dbus_unix_groups_from_uid (dbus_uid_t            uid,
+                            dbus_gid_t          **group_ids,
+                            int                  *n_group_ids)
+{
+  return FALSE;
+}
+
+
+
+/** @} */ /* DBusString stuff */
+
+/************************************************************************
+ 
+ error handling
+ 
+ ************************************************************************/
+
+
+
+
+
+/* lan manager error codes */
+const char*
+_dbus_lm_strerror(int error_number)
+{
+#ifdef DBUS_WINCE
+  // TODO
+  return "unknown";
+#else
+  const char *msg;
+  switch (error_number)
+    {
+    case NERR_NetNotStarted:
+      return "The workstation driver is not installed.";
+    case NERR_UnknownServer:
+      return "The server could not be located.";
+    case NERR_ShareMem:
+      return "An internal error occurred. The network cannot access a shared memory segment.";
+    case NERR_NoNetworkResource:
+      return "A network resource shortage occurred.";
+    case NERR_RemoteOnly:
+      return "This operation is not supported on workstations.";
+    case NERR_DevNotRedirected:
+      return "The device is not connected.";
+    case NERR_ServerNotStarted:
+      return "The Server service is not started.";
+    case NERR_ItemNotFound:
+      return "The queue is empty.";
+    case NERR_UnknownDevDir:
+      return "The device or directory does not exist.";
+    case NERR_RedirectedPath:
+      return "The operation is invalid on a redirected resource.";
+    case NERR_DuplicateShare:
+      return "The name has already been shared.";
+    case NERR_NoRoom:
+      return "The server is currently out of the requested resource.";
+    case NERR_TooManyItems:
+      return "Requested addition of items exceeds the maximum allowed.";
+    case NERR_InvalidMaxUsers:
+      return "The Peer service supports only two simultaneous users.";
+    case NERR_BufTooSmall:
+      return "The API return buffer is too small.";
+    case NERR_RemoteErr:
+      return "A remote API error occurred.";
+    case NERR_LanmanIniError:
+      return "An error occurred when opening or reading the configuration file.";
+    case NERR_NetworkError:
+      return "A general network error occurred.";
+    case NERR_WkstaInconsistentState:
+      return "The Workstation service is in an inconsistent state. Restart the computer before restarting the Workstation service.";
+    case NERR_WkstaNotStarted:
+      return "The Workstation service has not been started.";
+    case NERR_BrowserNotStarted:
+      return "The requested information is not available.";
+    case NERR_InternalError:
+      return "An internal error occurred.";
+    case NERR_BadTransactConfig:
+      return "The server is not configured for transactions.";
+    case NERR_InvalidAPI:
+      return "The requested API is not supported on the remote server.";
+    case NERR_BadEventName:
+      return "The event name is invalid.";
+    case NERR_DupNameReboot:
+      return "The computer name already exists on the network. Change it and restart the computer.";
+    case NERR_CfgCompNotFound:
+      return "The specified component could not be found in the configuration information.";
+    case NERR_CfgParamNotFound:
+      return "The specified parameter could not be found in the configuration information.";
+    case NERR_LineTooLong:
+      return "A line in the configuration file is too long.";
+    case NERR_QNotFound:
+      return "The printer does not exist.";
+    case NERR_JobNotFound:
+      return "The print job does not exist.";
+    case NERR_DestNotFound:
+      return "The printer destination cannot be found.";
+    case NERR_DestExists:
+      return "The printer destination already exists.";
+    case NERR_QExists:
+      return "The printer queue already exists.";
+    case NERR_QNoRoom:
+      return "No more printers can be added.";
+    case NERR_JobNoRoom:
+      return "No more print jobs can be added.";
+    case NERR_DestNoRoom:
+      return "No more printer destinations can be added.";
+    case NERR_DestIdle:
+      return "This printer destination is idle and cannot accept control operations.";
+    case NERR_DestInvalidOp:
+      return "This printer destination request contains an invalid control function.";
+    case NERR_ProcNoRespond:
+      return "The print processor is not responding.";
+    case NERR_SpoolerNotLoaded:
+      return "The spooler is not running.";
+    case NERR_DestInvalidState:
+      return "This operation cannot be performed on the print destination in its current state.";
+    case NERR_QInvalidState:
+      return "This operation cannot be performed on the printer queue in its current state.";
+    case NERR_JobInvalidState:
+      return "This operation cannot be performed on the print job in its current state.";
+    case NERR_SpoolNoMemory:
+      return "A spooler memory allocation failure occurred.";
+    case NERR_DriverNotFound:
+      return "The device driver does not exist.";
+    case NERR_DataTypeInvalid:
+      return "The data type is not supported by the print processor.";
+    case NERR_ProcNotFound:
+      return "The print processor is not installed.";
+    case NERR_ServiceTableLocked:
+      return "The service database is locked.";
+    case NERR_ServiceTableFull:
+      return "The service table is full.";
+    case NERR_ServiceInstalled:
+      return "The requested service has already been started.";
+    case NERR_ServiceEntryLocked:
+      return "The service does not respond to control actions.";
+    case NERR_ServiceNotInstalled:
+      return "The service has not been started.";
+    case NERR_BadServiceName:
+      return "The service name is invalid.";
+    case NERR_ServiceCtlTimeout:
+      return "The service is not responding to the control function.";
+    case NERR_ServiceCtlBusy:
+      return "The service control is busy.";
+    case NERR_BadServiceProgName:
+      return "The configuration file contains an invalid service program name.";
+    case NERR_ServiceNotCtrl:
+      return "The service could not be controlled in its present state.";
+    case NERR_ServiceKillProc:
+      return "The service ended abnormally.";
+    case NERR_ServiceCtlNotValid:
+      return "The requested pause or stop is not valid for this service.";
+    case NERR_NotInDispatchTbl:
+      return "The service control dispatcher could not find the service name in the dispatch table.";
+    case NERR_BadControlRecv:
+      return "The service control dispatcher pipe read failed.";
+    case NERR_ServiceNotStarting:
+      return "A thread for the new service could not be created.";
+    case NERR_AlreadyLoggedOn:
+      return "This workstation is already logged on to the local-area network.";
+    case NERR_NotLoggedOn:
+      return "The workstation is not logged on to the local-area network.";
+    case NERR_BadUsername:
+      return "The user name or group name parameter is invalid.";
+    case NERR_BadPassword:
+      return "The password parameter is invalid.";
+    case NERR_UnableToAddName_W:
+      return "@W The logon processor did not add the message alias.";
+    case NERR_UnableToAddName_F:
+      return "The logon processor did not add the message alias.";
+    case NERR_UnableToDelName_W:
+      return "@W The logoff processor did not delete the message alias.";
+    case NERR_UnableToDelName_F:
+      return "The logoff processor did not delete the message alias.";
+    case NERR_LogonsPaused:
+      return "Network logons are paused.";
+    case NERR_LogonServerConflict:
+      return "A centralized logon-server conflict occurred.";
+    case NERR_LogonNoUserPath:
+      return "The server is configured without a valid user path.";
+    case NERR_LogonScriptError:
+      return "An error occurred while loading or running the logon script.";
+    case NERR_StandaloneLogon:
+      return "The logon server was not specified. Your computer will be logged on as STANDALONE.";
+    case NERR_LogonServerNotFound:
+      return "The logon server could not be found.";
+    case NERR_LogonDomainExists:
+      return "There is already a logon domain for this computer.";
+    case NERR_NonValidatedLogon:
+      return "The logon server could not validate the logon.";
+    case NERR_ACFNotFound:
+      return "The security database could not be found.";
+    case NERR_GroupNotFound:
+      return "The group name could not be found.";
+    case NERR_UserNotFound:
+      return "The user name could not be found.";
+    case NERR_ResourceNotFound:
+      return "The resource name could not be found.";
+    case NERR_GroupExists:
+      return "The group already exists.";
+    case NERR_UserExists:
+      return "The user account already exists.";
+    case NERR_ResourceExists:
+      return "The resource permission list already exists.";
+    case NERR_NotPrimary:
+      return "This operation is only allowed on the primary domain controller of the domain.";
+    case NERR_ACFNotLoaded:
+      return "The security database has not been started.";
+    case NERR_ACFNoRoom:
+      return "There are too many names in the user accounts database.";
+    case NERR_ACFFileIOFail:
+      return "A disk I/O failure occurred.";
+    case NERR_ACFTooManyLists:
+      return "The limit of 64 entries per resource was exceeded.";
+    case NERR_UserLogon:
+      return "Deleting a user with a session is not allowed.";
+    case NERR_ACFNoParent:
+      return "The parent directory could not be located.";
+    case NERR_CanNotGrowSegment:
+      return "Unable to add to the security database session cache segment.";
+    case NERR_SpeGroupOp:
+      return "This operation is not allowed on this special group.";
+    case NERR_NotInCache:
+      return "This user is not cached in user accounts database session cache.";
+    case NERR_UserInGroup:
+      return "The user already belongs to this group.";
+    case NERR_UserNotInGroup:
+      return "The user does not belong to this group.";
+    case NERR_AccountUndefined:
+      return "This user account is undefined.";
+    case NERR_AccountExpired:
+      return "This user account has expired.";
+    case NERR_InvalidWorkstation:
+      return "The user is not allowed to log on from this workstation.";
+    case NERR_InvalidLogonHours:
+      return "The user is not allowed to log on at this time.";
+    case NERR_PasswordExpired:
+      return "The password of this user has expired.";
+    case NERR_PasswordCantChange:
+      return "The password of this user cannot change.";
+    case NERR_PasswordHistConflict:
+      return "This password cannot be used now.";
+    case NERR_PasswordTooShort:
+      return "The password does not meet the password policy requirements. Check the minimum password length, password complexity and password history requirements.";
+    case NERR_PasswordTooRecent:
+      return "The password of this user is too recent to change.";
+    case NERR_InvalidDatabase:
+      return "The security database is corrupted.";
+    case NERR_DatabaseUpToDate:
+      return "No updates are necessary to this replicant network/local security database.";
+    case NERR_SyncRequired:
+      return "This replicant database is outdated; synchronization is required.";
+    case NERR_UseNotFound:
+      return "The network connection could not be found.";
+    case NERR_BadAsgType:
+      return "This asg_type is invalid.";
+    case NERR_DeviceIsShared:
+      return "This device is currently being shared.";
+    case NERR_NoComputerName:
+      return "The computer name could not be added as a message alias. The name may already exist on the network.";
+    case NERR_MsgAlreadyStarted:
+      return "The Messenger service is already started.";
+    case NERR_MsgInitFailed:
+      return "The Messenger service failed to start.";
+    case NERR_NameNotFound:
+      return "The message alias could not be found on the network.";
+    case NERR_AlreadyForwarded:
+      return "This message alias has already been forwarded.";
+    case NERR_AddForwarded:
+      return "This message alias has been added but is still forwarded.";
+    case NERR_AlreadyExists:
+      return "This message alias already exists locally.";
+    case NERR_TooManyNames:
+      return "The maximum number of added message aliases has been exceeded.";
+    case NERR_DelComputerName:
+      return "The computer name could not be deleted.";
+    case NERR_LocalForward:
+      return "Messages cannot be forwarded back to the same workstation.";
+    case NERR_GrpMsgProcessor:
+      return "An error occurred in the domain message processor.";
+    case NERR_PausedRemote:
+      return "The message was sent, but the recipient has paused the Messenger service.";
+    case NERR_BadReceive:
+      return "The message was sent but not received.";
+    case NERR_NameInUse:
+      return "The message alias is currently in use. Try again later.";
+    case NERR_MsgNotStarted:
+      return "The Messenger service has not been started.";
+    case NERR_NotLocalName:
+      return "The name is not on the local computer.";
+    case NERR_NoForwardName:
+      return "The forwarded message alias could not be found on the network.";
+    case NERR_RemoteFull:
+      return "The message alias table on the remote station is full.";
+    case NERR_NameNotForwarded:
+      return "Messages for this alias are not currently being forwarded.";
+    case NERR_TruncatedBroadcast:
+      return "The broadcast message was truncated.";
+    case NERR_InvalidDevice:
+      return "This is an invalid device name.";
+    case NERR_WriteFault:
+      return "A write fault occurred.";
+    case NERR_DuplicateName:
+      return "A duplicate message alias exists on the network.";
+    case NERR_DeleteLater:
+      return "@W This message alias will be deleted later.";
+    case NERR_IncompleteDel:
+      return "The message alias was not successfully deleted from all networks.";
+    case NERR_MultipleNets:
+      return "This operation is not supported on computers with multiple networks.";
+    case NERR_NetNameNotFound:
+      return "This shared resource does not exist.";
+    case NERR_DeviceNotShared:
+      return "This device is not shared.";
+    case NERR_ClientNameNotFound:
+      return "A session does not exist with that computer name.";
+    case NERR_FileIdNotFound:
+      return "There is not an open file with that identification number.";
+    case NERR_ExecFailure:
+      return "A failure occurred when executing a remote administration command.";
+    case NERR_TmpFile:
+      return "A failure occurred when opening a remote temporary file.";
+    case NERR_TooMuchData:
+      return "The data returned from a remote administration command has been truncated to 64K.";
+    case NERR_DeviceShareConflict:
+      return "This device cannot be shared as both a spooled and a non-spooled resource.";
+    case NERR_BrowserTableIncomplete:
+      return "The information in the list of servers may be incorrect.";
+    case NERR_NotLocalDomain:
+      return "The computer is not active in this domain.";
+#ifdef NERR_IsDfsShare
+
+    case NERR_IsDfsShare:
+      return "The share must be removed from the Distributed File System before it can be deleted.";
+#endif
+
+    case NERR_DevInvalidOpCode:
+      return "The operation is invalid for this device.";
+    case NERR_DevNotFound:
+      return "This device cannot be shared.";
+    case NERR_DevNotOpen:
+      return "This device was not open.";
+    case NERR_BadQueueDevString:
+      return "This device name list is invalid.";
+    case NERR_BadQueuePriority:
+      return "The queue priority is invalid.";
+    case NERR_NoCommDevs:
+      return "There are no shared communication devices.";
+    case NERR_QueueNotFound:
+      return "The queue you specified does not exist.";
+    case NERR_BadDevString:
+      return "This list of devices is invalid.";
+    case NERR_BadDev:
+      return "The requested device is invalid.";
+    case NERR_InUseBySpooler:
+      return "This device is already in use by the spooler.";
+    case NERR_CommDevInUse:
+      return "This device is already in use as a communication device.";
+    case NERR_InvalidComputer:
+      return "This computer name is invalid.";
+    case NERR_MaxLenExceeded:
+      return "The string and prefix specified are too long.";
+    case NERR_BadComponent:
+      return "This path component is invalid.";
+    case NERR_CantType:
+      return "Could not determine the type of input.";
+    case NERR_TooManyEntries:
+      return "The buffer for types is not big enough.";
+    case NERR_ProfileFileTooBig:
+      return "Profile files cannot exceed 64K.";
+    case NERR_ProfileOffset:
+      return "The start offset is out of range.";
+    case NERR_ProfileCleanup:
+      return "The system cannot delete current connections to network resources.";
+    case NERR_ProfileUnknownCmd:
+      return "The system was unable to parse the command line in this file.";
+    case NERR_ProfileLoadErr:
+      return "An error occurred while loading the profile file.";
+    case NERR_ProfileSaveErr:
+      return "@W Errors occurred while saving the profile file. The profile was partially saved.";
+    case NERR_LogOverflow:
+      return "Log file %1 is full.";
+    case NERR_LogFileChanged:
+      return "This log file has changed between reads.";
+    case NERR_LogFileCorrupt:
+      return "Log file %1 is corrupt.";
+    case NERR_SourceIsDir:
+      return "The source path cannot be a directory.";
+    case NERR_BadSource:
+      return "The source path is illegal.";
+    case NERR_BadDest:
+      return "The destination path is illegal.";
+    case NERR_DifferentServers:
+      return "The source and destination paths are on different servers.";
+    case NERR_RunSrvPaused:
+      return "The Run server you requested is paused.";
+    case NERR_ErrCommRunSrv:
+      return "An error occurred when communicating with a Run server.";
+    case NERR_ErrorExecingGhost:
+      return "An error occurred when starting a background process.";
+    case NERR_ShareNotFound:
+      return "The shared resource you are connected to could not be found.";
+    case NERR_InvalidLana:
+      return "The LAN adapter number is invalid.";
+    case NERR_OpenFiles:
+      return "There are open files on the connection.";
+    case NERR_ActiveConns:
+      return "Active connections still exist.";
+    case NERR_BadPasswordCore:
+      return "This share name or password is invalid.";
+    case NERR_DevInUse:
+      return "The device is being accessed by an active process.";
+    case NERR_LocalDrive:
+      return "The drive letter is in use locally.";
+    case NERR_AlertExists:
+      return "The specified client is already registered for the specified event.";
+    case NERR_TooManyAlerts:
+      return "The alert table is full.";
+    case NERR_NoSuchAlert:
+      return "An invalid or nonexistent alert name was raised.";
+    case NERR_BadRecipient:
+      return "The alert recipient is invalid.";
+    case NERR_AcctLimitExceeded:
+      return "A user's session with this server has been deleted.";
+    case NERR_InvalidLogSeek:
+      return "The log file does not contain the requested record number.";
+    case NERR_BadUasConfig:
+      return "The user accounts database is not configured correctly.";
+    case NERR_InvalidUASOp:
+      return "This operation is not permitted when the Netlogon service is running.";
+    case NERR_LastAdmin:
+      return "This operation is not allowed on the last administrative account.";
+    case NERR_DCNotFound:
+      return "Could not find domain controller for this domain.";
+    case NERR_LogonTrackingError:
+      return "Could not set logon information for this user.";
+    case NERR_NetlogonNotStarted:
+      return "The Netlogon service has not been started.";
+    case NERR_CanNotGrowUASFile:
+      return "Unable to add to the user accounts database.";
+    case NERR_TimeDiffAtDC:
+      return "This server's clock is not synchronized with the primary domain controller's clock.";
+    case NERR_PasswordMismatch:
+      return "A password mismatch has been detected.";
+    case NERR_NoSuchServer:
+      return "The server identification does not specify a valid server.";
+    case NERR_NoSuchSession:
+      return "The session identification does not specify a valid session.";
+    case NERR_NoSuchConnection:
+      return "The connection identification does not specify a valid connection.";
+    case NERR_TooManyServers:
+      return "There is no space for another entry in the table of available servers.";
+    case NERR_TooManySessions:
+      return "The server has reached the maximum number of sessions it supports.";
+    case NERR_TooManyConnections:
+      return "The server has reached the maximum number of connections it supports.";
+    case NERR_TooManyFiles:
+      return "The server cannot open more files because it has reached its maximum number.";
+    case NERR_NoAlternateServers:
+      return "There are no alternate servers registered on this server.";
+    case NERR_TryDownLevel:
+      return "Try down-level (remote admin protocol) version of API instead.";
+    case NERR_UPSDriverNotStarted:
+      return "The UPS driver could not be accessed by the UPS service.";
+    case NERR_UPSInvalidConfig:
+      return "The UPS service is not configured correctly.";
+    case NERR_UPSInvalidCommPort:
+      return "The UPS service could not access the specified Comm Port.";
+    case NERR_UPSSignalAsserted:
+      return "The UPS indicated a line fail or low battery situation. Service not started.";
+    case NERR_UPSShutdownFailed:
+      return "The UPS service failed to perform a system shut down.";
+    case NERR_BadDosRetCode:
+      return "The program below returned an MS-DOS error code:";
+    case NERR_ProgNeedsExtraMem:
+      return "The program below needs more memory:";
+    case NERR_BadDosFunction:
+      return "The program below called an unsupported MS-DOS function:";
+    case NERR_RemoteBootFailed:
+      return "The workstation failed to boot.";
+    case NERR_BadFileCheckSum:
+      return "The file below is corrupt.";
+    case NERR_NoRplBootSystem:
+      return "No loader is specified in the boot-block definition file.";
+    case NERR_RplLoadrNetBiosErr:
+      return "NetBIOS returned an error:      The NCB and SMB are dumped above.";
+    case NERR_RplLoadrDiskErr:
+      return "A disk I/O error occurred.";
+    case NERR_ImageParamErr:
+      return "Image parameter substitution failed.";
+    case NERR_TooManyImageParams:
+      return "Too many image parameters cross disk sector boundaries.";
+    case NERR_NonDosFloppyUsed:
+      return "The image was not generated from an MS-DOS diskette formatted with /S.";
+    case NERR_RplBootRestart:
+      return "Remote boot will be restarted later.";
+    case NERR_RplSrvrCallFailed:
+      return "The call to the Remoteboot server failed.";
+    case NERR_CantConnectRplSrvr:
+      return "Cannot connect to the Remoteboot server.";
+    case NERR_CantOpenImageFile:
+      return "Cannot open image file on the Remoteboot server.";
+    case NERR_CallingRplSrvr:
+      return "Connecting to the Remoteboot server...";
+    case NERR_StartingRplBoot:
+      return "Connecting to the Remoteboot server...";
+    case NERR_RplBootServiceTerm:
+      return "Remote boot service was stopped; check the error log for the cause of the problem.";
+    case NERR_RplBootStartFailed:
+      return "Remote boot startup failed; check the error log for the cause of the problem.";
+    case NERR_RPL_CONNECTED:
+      return "A second connection to a Remoteboot resource is not allowed.";
+    case NERR_BrowserConfiguredToNotRun:
+      return "The browser service was configured with MaintainServerList=No.";
+    case NERR_RplNoAdaptersStarted:
+      return "Service failed to start since none of the network adapters started with this service.";
+    case NERR_RplBadRegistry:
+      return "Service failed to start due to bad startup information in the registry.";
+    case NERR_RplBadDatabase:
+      return "Service failed to start because its database is absent or corrupt.";
+    case NERR_RplRplfilesShare:
+      return "Service failed to start because RPLFILES share is absent.";
+    case NERR_RplNotRplServer:
+      return "Service failed to start because RPLUSER group is absent.";
+    case NERR_RplCannotEnum:
+      return "Cannot enumerate service records.";
+    case NERR_RplWkstaInfoCorrupted:
+      return "Workstation record information has been corrupted.";
+    case NERR_RplWkstaNotFound:
+      return "Workstation record was not found.";
+    case NERR_RplWkstaNameUnavailable:
+      return "Workstation name is in use by some other workstation.";
+    case NERR_RplProfileInfoCorrupted:
+      return "Profile record information has been corrupted.";
+    case NERR_RplProfileNotFound:
+      return "Profile record was not found.";
+    case NERR_RplProfileNameUnavailable:
+      return "Profile name is in use by some other profile.";
+    case NERR_RplProfileNotEmpty:
+      return "There are workstations using this profile.";
+    case NERR_RplConfigInfoCorrupted:
+      return "Configuration record information has been corrupted.";
+    case NERR_RplConfigNotFound:
+      return "Configuration record was not found.";
+    case NERR_RplAdapterInfoCorrupted:
+      return "Adapter ID record information has been corrupted.";
+    case NERR_RplInternal:
+      return "An internal service error has occurred.";
+    case NERR_RplVendorInfoCorrupted:
+      return "Vendor ID record information has been corrupted.";
+    case NERR_RplBootInfoCorrupted:
+      return "Boot block record information has been corrupted.";
+    case NERR_RplWkstaNeedsUserAcct:
+      return "The user account for this workstation record is missing.";
+    case NERR_RplNeedsRPLUSERAcct:
+      return "The RPLUSER local group could not be found.";
+    case NERR_RplBootNotFound:
+      return "Boot block record was not found.";
+    case NERR_RplIncompatibleProfile:
+      return "Chosen profile is incompatible with this workstation.";
+    case NERR_RplAdapterNameUnavailable:
+      return "Chosen network adapter ID is in use by some other workstation.";
+    case NERR_RplConfigNotEmpty:
+      return "There are profiles using this configuration.";
+    case NERR_RplBootInUse:
+      return "There are workstations, profiles, or configurations using this boot block.";
+    case NERR_RplBackupDatabase:
+      return "Service failed to backup Remoteboot database.";
+    case NERR_RplAdapterNotFound:
+      return "Adapter record was not found.";
+    case NERR_RplVendorNotFound:
+      return "Vendor record was not found.";
+    case NERR_RplVendorNameUnavailable:
+      return "Vendor name is in use by some other vendor record.";
+    case NERR_RplBootNameUnavailable:
+      return "(boot name, vendor ID) is in use by some other boot block record.";
+    case NERR_RplConfigNameUnavailable:
+      return "Configuration name is in use by some other configuration.";
+    case NERR_DfsInternalCorruption:
+      return "The internal database maintained by the Dfs service is corrupt.";
+    case NERR_DfsVolumeDataCorrupt:
+      return "One of the records in the internal Dfs database is corrupt.";
+    case NERR_DfsNoSuchVolume:
+      return "There is no DFS name whose entry path matches the input Entry Path.";
+    case NERR_DfsVolumeAlreadyExists:
+      return "A root or link with the given name already exists.";
+    case NERR_DfsAlreadyShared:
+      return "The server share specified is already shared in the Dfs.";
+    case NERR_DfsNoSuchShare:
+      return "The indicated server share does not support the indicated DFS namespace.";
+    case NERR_DfsNotALeafVolume:
+      return "The operation is not valid on this portion of the namespace.";
+    case NERR_DfsLeafVolume:
+      return "The operation is not valid on this portion of the namespace.";
+    case NERR_DfsVolumeHasMultipleServers:
+      return "The operation is ambiguous because the link has multiple servers.";
+    case NERR_DfsCantCreateJunctionPoint:
+      return "Unable to create a link.";
+    case NERR_DfsServerNotDfsAware:
+      return "The server is not Dfs Aware.";
+    case NERR_DfsBadRenamePath:
+      return "The specified rename target path is invalid.";
+    case NERR_DfsVolumeIsOffline:
+      return "The specified DFS link is offline.";
+    case NERR_DfsNoSuchServer:
+      return "The specified server is not a server for this link.";
+    case NERR_DfsCyclicalName:
+      return "A cycle in the Dfs name was detected.";
+    case NERR_DfsNotSupportedInServerDfs:
+      return "The operation is not supported on a server-based Dfs.";
+    case NERR_DfsDuplicateService:
+      return "This link is already supported by the specified server-share.";
+    case NERR_DfsCantRemoveLastServerShare:
+      return "Can't remove the last server-share supporting this root or link.";
+    case NERR_DfsVolumeIsInterDfs:
+      return "The operation is not supported for an Inter-DFS link.";
+    case NERR_DfsInconsistent:
+      return "The internal state of the Dfs Service has become inconsistent.";
+    case NERR_DfsServerUpgraded:
+      return "The Dfs Service has been installed on the specified server.";
+    case NERR_DfsDataIsIdentical:
+      return "The Dfs data being reconciled is identical.";
+    case NERR_DfsCantRemoveDfsRoot:
+      return "The DFS root cannot be deleted. Uninstall DFS if required.";
+    case NERR_DfsChildOrParentInDfs:
+      return "A child or parent directory of the share is already in a Dfs.";
+    case NERR_DfsInternalError:
+      return "Dfs internal error.";
+      /* the following are not defined in mingw */
+#if 0
+
+    case NERR_SetupAlreadyJoined:
+      return "This machine is already joined to a domain.";
+    case NERR_SetupNotJoined:
+      return "This machine is not currently joined to a domain.";
+    case NERR_SetupDomainController:
+      return "This machine is a domain controller and cannot be unjoined from a domain.";
+    case NERR_DefaultJoinRequired:
+      return "The destination domain controller does not support creating machine accounts in OUs.";
+    case NERR_InvalidWorkgroupName:
+      return "The specified workgroup name is invalid.";
+    case NERR_NameUsesIncompatibleCodePage:
+      return "The specified computer name is incompatible with the default language used on the domain controller.";
+    case NERR_ComputerAccountNotFound:
+      return "The specified computer account could not be found.";
+    case NERR_PersonalSku:
+      return "This version of Windows cannot be joined to a domain.";
+    case NERR_PasswordMustChange:
+      return "The password must change at the next logon.";
+    case NERR_AccountLockedOut:
+      return "The account is locked out.";
+    case NERR_PasswordTooLong:
+      return "The password is too long.";
+    case NERR_PasswordNotComplexEnough:
+      return "The password does not meet the complexity policy.";
+    case NERR_PasswordFilterError:
+      return "The password does not meet the requirements of the password filter DLLs.";
+#endif
+
+    }
+  msg = strerror (error_number);
+  if (msg == NULL)
+    msg = "unknown";
+
+  return msg;
+#endif //DBUS_WINCE
+}
+
+/**
+ * Get a printable string describing the command used to execute
+ * the process with pid.  This string should only be used for
+ * informative purposes such as logging; it may not be trusted.
+ *
+ * The command is guaranteed to be printable ASCII and no longer
+ * than max_len.
+ *
+ * @param pid Process id
+ * @param str Append command to this string
+ * @param max_len Maximum length of returned command
+ * @param error return location for errors
+ * @returns #FALSE on error
+ */
+dbus_bool_t
+_dbus_command_for_pid (unsigned long  pid,
+                       DBusString    *str,
+                       int            max_len,
+                       DBusError     *error)
+{
+  // FIXME
+  return FALSE;
+}
diff --git a/dbus/dbus/dbus-sysdeps-util.c b/dbus/dbus/dbus-sysdeps-util.c
new file mode 100644
index 0000000..4b3d16f
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-util.c
@@ -0,0 +1,199 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-util.c Tests for dbus-sysdeps.h API
+ * 
+ * Copyright (C) 2002, 2003, 2004, 2005  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-sysdeps.h"
+#include "dbus-internals.h"
+#include "dbus-string.h"
+#include "dbus-test.h"
+
+#include <stdlib.h>
+
+#ifdef DBUS_WIN
+  /* do nothing, it's in stdlib.h */
+#elif (defined __APPLE__)
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+#else
+extern char **environ;
+#endif
+
+/**
+ * Gets a #NULL-terminated list of key=value pairs from the
+ * environment. Use dbus_free_string_array to free it.
+ *
+ * @returns the environment or #NULL on OOM
+ */
+char **
+_dbus_get_environment (void)
+{
+  int i, length;
+  char **environment;
+
+  _dbus_assert (environ != NULL);
+
+  for (length = 0; environ[length] != NULL; length++);
+
+  /* Add one for NULL */
+  length++;
+
+  environment = dbus_new0 (char *, length);
+
+  if (environment == NULL)
+    return NULL;
+
+  for (i = 0; environ[i] != NULL; i++)
+    {
+      environment[i] = _dbus_strdup (environ[i]);
+
+      if (environment[i] == NULL)
+        break;
+    }
+
+  if (environ[i] != NULL)
+    {
+      dbus_free_string_array (environment);
+      environment = NULL;
+    }
+
+  return environment;
+}
+
+#ifdef DBUS_BUILD_TESTS
+static void
+check_dirname (const char *filename,
+               const char *dirname)
+{
+  DBusString f, d;
+  
+  _dbus_string_init_const (&f, filename);
+
+  if (!_dbus_string_init (&d))
+    _dbus_assert_not_reached ("no memory");
+
+  if (!_dbus_string_get_dirname (&f, &d))
+    _dbus_assert_not_reached ("no memory");
+
+  if (!_dbus_string_equal_c_str (&d, dirname))
+    {
+      _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n",
+                  filename,
+                  _dbus_string_get_const_data (&d),
+                  dirname);
+      exit (1);
+    }
+
+  _dbus_string_free (&d);
+}
+
+static void
+check_path_absolute (const char *path,
+                     dbus_bool_t expected)
+{
+  DBusString p;
+
+  _dbus_string_init_const (&p, path);
+
+  if (_dbus_path_is_absolute (&p) != expected)
+    {
+      _dbus_warn ("For path \"%s\" expected absolute = %d got %d\n",
+                  path, expected, _dbus_path_is_absolute (&p));
+      exit (1);
+    }
+}
+
+/**
+ * Unit test for dbus-sysdeps.c.
+ * 
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_sysdeps_test (void)
+{
+#ifdef DBUS_WIN
+  check_dirname ("foo\\bar", "foo");
+  check_dirname ("foo\\\\bar", "foo");
+  check_dirname ("foo/\\/bar", "foo");
+  check_dirname ("foo\\bar/", "foo");
+  check_dirname ("foo//bar\\", "foo");
+  check_dirname ("foo\\bar/", "foo");
+  check_dirname ("foo/bar\\\\", "foo");
+  check_dirname ("\\foo", "\\");
+  check_dirname ("\\\\foo", "\\");
+  check_dirname ("\\", "\\");
+  check_dirname ("\\\\", "\\");
+  check_dirname ("\\/", "\\");
+  check_dirname ("/\\/", "/");
+  check_dirname ("c:\\foo\\bar", "c:\\foo");
+  check_dirname ("c:\\foo", "c:\\");
+  check_dirname ("c:/foo", "c:/");
+  check_dirname ("c:\\", "c:\\");
+  check_dirname ("c:/", "c:/");
+  check_dirname ("", ".");  
+#else  
+  check_dirname ("foo", ".");
+  check_dirname ("foo/bar", "foo");
+  check_dirname ("foo//bar", "foo");
+  check_dirname ("foo///bar", "foo");
+  check_dirname ("foo/bar/", "foo");
+  check_dirname ("foo//bar/", "foo");
+  check_dirname ("foo///bar/", "foo");
+  check_dirname ("foo/bar//", "foo");
+  check_dirname ("foo//bar////", "foo");
+  check_dirname ("foo///bar///////", "foo");
+  check_dirname ("/foo", "/");
+  check_dirname ("////foo", "/");
+  check_dirname ("/foo/bar", "/foo");
+  check_dirname ("/foo//bar", "/foo");
+  check_dirname ("/foo///bar", "/foo");
+  check_dirname ("/", "/");
+  check_dirname ("///", "/");
+  check_dirname ("", ".");  
+#endif
+
+#ifdef DBUS_WIN
+  check_path_absolute ("c:/", TRUE);
+  check_path_absolute ("c:/foo", TRUE);
+  check_path_absolute ("", FALSE);
+  check_path_absolute ("foo", FALSE);
+  check_path_absolute ("foo/bar", FALSE);
+  check_path_absolute ("", FALSE);
+  check_path_absolute ("foo\\bar", FALSE);
+  check_path_absolute ("c:\\", TRUE);
+  check_path_absolute ("c:\\foo", TRUE);
+  check_path_absolute ("c:", TRUE);
+  check_path_absolute ("c:\\foo\\bar", TRUE);
+  check_path_absolute ("\\", TRUE);
+  check_path_absolute ("/", TRUE);
+#else  
+  check_path_absolute ("/", TRUE);
+  check_path_absolute ("/foo", TRUE);
+  check_path_absolute ("", FALSE);
+  check_path_absolute ("foo", FALSE);
+  check_path_absolute ("foo/bar", FALSE);
+#endif
+  
+  return TRUE;
+}
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-sysdeps-win.c b/dbus/dbus/dbus-sysdeps-win.c
new file mode 100644
index 0000000..bc4951b
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-win.c
@@ -0,0 +1,3643 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2005 Novell, Inc.
+ * Copyright (C) 2006 Peter Kümmel  <syntheticpp@gmx.net>
+ * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de>
+ * Copyright (C) 2006-2010 Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#define STRSAFE_NO_DEPRECATE
+
+#ifndef DBUS_WINCE
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+#endif
+
+#include "dbus-internals.h"
+#include "dbus-sha.h"
+#include "dbus-sysdeps.h"
+#include "dbus-threads.h"
+#include "dbus-protocol.h"
+#include "dbus-string.h"
+#include "dbus-sysdeps.h"
+#include "dbus-sysdeps-win.h"
+#include "dbus-protocol.h"
+#include "dbus-hash.h"
+#include "dbus-sockets-win.h"
+#include "dbus-list.h"
+#include "dbus-nonce.h"
+#include "dbus-credentials.h"
+
+#include <windows.h>
+#include <ws2tcpip.h>
+#include <wincrypt.h>
+
+/* Declarations missing in mingw's headers */
+extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR  StringSid, PSID *Sid);
+extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid);
+
+#include <stdio.h>
+
+#include <string.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifndef DBUS_WINCE
+#include <mbstring.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_WS2TCPIP_H
+/* getaddrinfo for Windows CE (and Windows).  */
+#include <ws2tcpip.h>
+#endif
+
+#ifdef HAVE_WSPIAPI_H
+// needed for w2k compatibility (getaddrinfo/freeaddrinfo/getnameinfo)
+#ifdef __GNUC__
+#define _inline
+#include "wspiapi.h"
+#else
+#include <wspiapi.h>
+#endif
+#endif // HAVE_WSPIAPI_H
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+typedef int socklen_t;
+
+
+void
+_dbus_win_set_errno (int err)
+{
+#ifdef DBUS_WINCE
+  SetLastError (err);
+#else
+  errno = err;
+#endif
+}
+
+
+/* Convert GetLastError() to a dbus error.  */
+const char*
+_dbus_win_error_from_last_error (void)
+{
+  switch (GetLastError())
+    {
+    case 0:
+      return DBUS_ERROR_FAILED;
+    
+    case ERROR_NO_MORE_FILES:
+    case ERROR_TOO_MANY_OPEN_FILES:
+      return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
+
+    case ERROR_ACCESS_DENIED:
+    case ERROR_CANNOT_MAKE:
+      return DBUS_ERROR_ACCESS_DENIED;
+
+    case ERROR_NOT_ENOUGH_MEMORY:
+      return DBUS_ERROR_NO_MEMORY;
+
+    case ERROR_FILE_EXISTS:
+      return DBUS_ERROR_FILE_EXISTS;
+
+    case ERROR_FILE_NOT_FOUND:
+    case ERROR_PATH_NOT_FOUND:
+      return DBUS_ERROR_FILE_NOT_FOUND;
+    }
+  
+  return DBUS_ERROR_FAILED;
+}
+
+
+char*
+_dbus_win_error_string (int error_number)
+{
+  char *msg;
+
+  FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_IGNORE_INSERTS |
+                  FORMAT_MESSAGE_FROM_SYSTEM,
+                  NULL, error_number, 0,
+                  (LPSTR) &msg, 0, NULL);
+
+  if (msg[strlen (msg) - 1] == '\n')
+    msg[strlen (msg) - 1] = '\0';
+  if (msg[strlen (msg) - 1] == '\r')
+    msg[strlen (msg) - 1] = '\0';
+
+  return msg;
+}
+
+void
+_dbus_win_free_error_string (char *string)
+{
+  LocalFree (string);
+}
+
+/**
+ * Socket interface
+ *
+ */
+
+/**
+ * Thin wrapper around the read() system call that appends
+ * the data it reads to the DBusString buffer. It appends
+ * up to the given count, and returns the same value
+ * and same errno as read(). The only exception is that
+ * _dbus_read_socket() handles EINTR for you. 
+ * _dbus_read_socket() can return ENOMEM, even though 
+ * regular UNIX read doesn't.
+ *
+ * @param fd the file descriptor to read from
+ * @param buffer the buffer to append data to
+ * @param count the amount of data to read
+ * @returns the number of bytes read or -1
+ */
+
+int
+_dbus_read_socket (int               fd,
+                   DBusString       *buffer,
+                   int               count)
+{
+  int bytes_read;
+  int start;
+  char *data;
+
+  _dbus_assert (count >= 0);
+
+  start = _dbus_string_get_length (buffer);
+
+  if (!_dbus_string_lengthen (buffer, count))
+    {
+      _dbus_win_set_errno (ENOMEM);
+      return -1;
+    }
+
+  data = _dbus_string_get_data_len (buffer, start, count);
+
+ again:
+ 
+  _dbus_verbose ("recv: count=%d fd=%d\n", count, fd);
+  bytes_read = recv (fd, data, count, 0);
+  
+  if (bytes_read == SOCKET_ERROR)
+	{
+	  DBUS_SOCKET_SET_ERRNO();
+	  _dbus_verbose ("recv: failed: %s (%d)\n", _dbus_strerror (errno), errno);
+	  bytes_read = -1;
+	}
+	else
+	  _dbus_verbose ("recv: = %d\n", bytes_read);
+
+  if (bytes_read < 0)
+    {
+      if (errno == EINTR)
+        goto again;
+      else    	
+        {
+          /* put length back (note that this doesn't actually realloc anything) */
+          _dbus_string_set_length (buffer, start);
+          return -1;
+        }
+    }
+  else
+    {
+      /* put length back (doesn't actually realloc) */
+      _dbus_string_set_length (buffer, start + bytes_read);
+
+#if 0
+      if (bytes_read > 0)
+        _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
+#endif
+
+      return bytes_read;
+    }
+}
+
+/**
+ * Thin wrapper around the write() system call that writes a part of a
+ * DBusString and handles EINTR for you.
+ * 
+ * @param fd the file descriptor to write
+ * @param buffer the buffer to write data from
+ * @param start the first byte in the buffer to write
+ * @param len the number of bytes to try to write
+ * @returns the number of bytes written or -1 on error
+ */
+int
+_dbus_write_socket (int               fd,
+                    const DBusString *buffer,
+                    int               start,
+                    int               len)
+{
+  const char *data;
+  int bytes_written;
+
+  data = _dbus_string_get_const_data_len (buffer, start, len);
+
+ again:
+
+  _dbus_verbose ("send: len=%d fd=%d\n", len, fd);
+  bytes_written = send (fd, data, len, 0);
+
+  if (bytes_written == SOCKET_ERROR)
+    {
+      DBUS_SOCKET_SET_ERRNO();
+      _dbus_verbose ("send: failed: %s\n", _dbus_strerror_from_errno ());
+      bytes_written = -1;
+    }
+    else
+      _dbus_verbose ("send: = %d\n", bytes_written);
+
+  if (bytes_written < 0 && errno == EINTR)
+    goto again;
+    
+#if 0
+  if (bytes_written > 0)
+    _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
+#endif
+
+  return bytes_written;
+}
+
+
+/**
+ * Closes a file descriptor.
+ *
+ * @param fd the file descriptor
+ * @param error error object
+ * @returns #FALSE if error set
+ */
+dbus_bool_t
+_dbus_close_socket (int        fd,
+                    DBusError *error)
+{
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ again:
+  if (closesocket (fd) == SOCKET_ERROR)
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      
+      if (errno == EINTR)
+        goto again;
+        
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Could not close socket: socket=%d, , %s",
+                      fd, _dbus_strerror_from_errno ());
+      return FALSE;
+    }
+  _dbus_verbose ("_dbus_close_socket: socket=%d, \n", fd);
+
+  return TRUE;
+}
+
+/**
+ * Sets the file descriptor to be close
+ * on exec. Should be called for all file
+ * descriptors in D-Bus code.
+ *
+ * @param fd the file descriptor
+ */
+void
+_dbus_fd_set_close_on_exec (intptr_t handle)
+{
+  if ( !SetHandleInformation( (HANDLE) handle,
+                        HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE,
+                        0 /*disable both flags*/ ) )
+    {
+      _dbus_win_warn_win_error ("Disabling socket handle inheritance failed:", GetLastError());
+    }
+}
+
+/**
+ * Sets a file descriptor to be nonblocking.
+ *
+ * @param fd the file descriptor.
+ * @param error address of error location.
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_set_fd_nonblocking (int             handle,
+                          DBusError      *error)
+{
+  u_long one = 1;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (ioctlsocket (handle, FIONBIO, &one) == SOCKET_ERROR)
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to set socket %d:%d to nonblocking: %s", handle,
+                      _dbus_strerror_from_errno ());
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+
+/**
+ * Like _dbus_write() but will use writev() if possible
+ * to write both buffers in sequence. The return value
+ * is the number of bytes written in the first buffer,
+ * plus the number written in the second. If the first
+ * buffer is written successfully and an error occurs
+ * writing the second, the number of bytes in the first
+ * is returned (i.e. the error is ignored), on systems that
+ * don't have writev. Handles EINTR for you.
+ * The second buffer may be #NULL.
+ *
+ * @param fd the file descriptor
+ * @param buffer1 first buffer
+ * @param start1 first byte to write in first buffer
+ * @param len1 number of bytes to write from first buffer
+ * @param buffer2 second buffer, or #NULL
+ * @param start2 first byte to write in second buffer
+ * @param len2 number of bytes to write in second buffer
+ * @returns total bytes written from both buffers, or -1 on error
+ */
+int
+_dbus_write_socket_two (int               fd,
+                        const DBusString *buffer1,
+                        int               start1,
+                        int               len1,
+                        const DBusString *buffer2,
+                        int               start2,
+                        int               len2)
+{
+  WSABUF vectors[2];
+  const char *data1;
+  const char *data2;
+  int rc;
+  DWORD bytes_written;
+
+  _dbus_assert (buffer1 != NULL);
+  _dbus_assert (start1 >= 0);
+  _dbus_assert (start2 >= 0);
+  _dbus_assert (len1 >= 0);
+  _dbus_assert (len2 >= 0);
+
+
+  data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
+
+  if (buffer2 != NULL)
+    data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
+  else
+    {
+      data2 = NULL;
+      start2 = 0;
+      len2 = 0;
+    }
+
+  vectors[0].buf = (char*) data1;
+  vectors[0].len = len1;
+  vectors[1].buf = (char*) data2;
+  vectors[1].len = len2;
+
+ again:
+ 
+  _dbus_verbose ("WSASend: len1+2=%d+%d fd=%d\n", len1, len2, fd);
+  rc = WSASend (fd, 
+                vectors,
+                data2 ? 2 : 1, 
+                &bytes_written,
+                0, 
+                NULL, 
+                NULL);
+                
+  if (rc == SOCKET_ERROR)
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      _dbus_verbose ("WSASend: failed: %s\n", _dbus_strerror_from_errno ());
+      bytes_written = -1;
+    }
+  else
+    _dbus_verbose ("WSASend: = %ld\n", bytes_written);
+    
+  if (bytes_written < 0 && errno == EINTR)
+    goto again;
+      
+  return bytes_written;
+}
+
+dbus_bool_t
+_dbus_socket_is_invalid (int fd)
+{
+    return fd == INVALID_SOCKET ? TRUE : FALSE;
+}
+
+#if 0
+
+/**
+ * Opens the client side of a Windows named pipe. The connection D-BUS
+ * file descriptor index is returned. It is set up as nonblocking.
+ * 
+ * @param path the path to named pipe socket
+ * @param error return location for error code
+ * @returns connection D-BUS file descriptor or -1 on error
+ */
+int
+_dbus_connect_named_pipe (const char     *path,
+                          DBusError      *error)
+{
+  _dbus_assert_not_reached ("not implemented");
+}
+
+#endif
+
+
+
+void
+_dbus_win_startup_winsock (void)
+{
+  /* Straight from MSDN, deuglified */
+
+  static dbus_bool_t beenhere = FALSE;
+
+  WORD wVersionRequested;
+  WSADATA wsaData;
+  int err;
+
+  if (beenhere)
+    return;
+
+  wVersionRequested = MAKEWORD (2, 0);
+
+  err = WSAStartup (wVersionRequested, &wsaData);
+  if (err != 0)
+    {
+      _dbus_assert_not_reached ("Could not initialize WinSock");
+      _dbus_abort ();
+    }
+
+  /* Confirm that the WinSock DLL supports 2.0.  Note that if the DLL
+   * supports versions greater than 2.0 in addition to 2.0, it will
+   * still return 2.0 in wVersion since that is the version we
+   * requested.
+   */
+  if (LOBYTE (wsaData.wVersion) != 2 ||
+      HIBYTE (wsaData.wVersion) != 0)
+    {
+      _dbus_assert_not_reached ("No usable WinSock found");
+      _dbus_abort ();
+    }
+
+  beenhere = TRUE;
+}
+
+
+
+
+
+
+
+
+
+/************************************************************************
+ 
+ UTF / string code
+ 
+ ************************************************************************/
+
+/**
+ * Measure the message length without terminating nul 
+ */
+int _dbus_printf_string_upper_bound (const char *format,
+                                     va_list args)
+{
+  /* MSVCRT's vsnprintf semantics are a bit different */
+  char buf[1024];
+  int bufsize;
+  int len;
+
+  bufsize = sizeof (buf);
+  len = _vsnprintf (buf, bufsize - 1, format, args);
+
+  while (len == -1) /* try again */
+    {
+      char *p;
+
+      bufsize *= 2;
+
+      p = malloc (bufsize);
+
+      if (p == NULL)
+        return -1;
+
+      len = _vsnprintf (p, bufsize - 1, format, args);
+      free (p);
+    }
+
+  return len;
+}
+
+
+/**
+ * Returns the UTF-16 form of a UTF-8 string. The result should be
+ * freed with dbus_free() when no longer needed.
+ *
+ * @param str the UTF-8 string
+ * @param error return location for error code
+ */
+wchar_t *
+_dbus_win_utf8_to_utf16 (const char *str,
+                         DBusError  *error)
+{
+  DBusString s;
+  int n;
+  wchar_t *retval;
+
+  _dbus_string_init_const (&s, str);
+
+  if (!_dbus_string_validate_utf8 (&s, 0, _dbus_string_get_length (&s)))
+    {
+      dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid UTF-8");
+      return NULL;
+    }
+
+  n = MultiByteToWideChar (CP_UTF8, 0, str, -1, NULL, 0);
+
+  if (n == 0)
+    {
+      _dbus_win_set_error_from_win_error (error, GetLastError ());
+      return NULL;
+    }
+
+  retval = dbus_new (wchar_t, n);
+
+  if (!retval)
+    {
+      _DBUS_SET_OOM (error);
+      return NULL;
+    }
+
+  if (MultiByteToWideChar (CP_UTF8, 0, str, -1, retval, n) != n)
+    {
+      dbus_free (retval);
+      dbus_set_error_const (error, DBUS_ERROR_FAILED, "MultiByteToWideChar inconsistency");
+      return NULL;
+    }
+
+  return retval;
+}
+
+/**
+ * Returns the UTF-8 form of a UTF-16 string. The result should be
+ * freed with dbus_free() when no longer needed.
+ *
+ * @param str the UTF-16 string
+ * @param error return location for error code
+ */
+char *
+_dbus_win_utf16_to_utf8 (const wchar_t *str,
+                         DBusError     *error)
+{
+  int n;
+  char *retval;
+
+  n = WideCharToMultiByte (CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
+
+  if (n == 0)
+    {
+      _dbus_win_set_error_from_win_error (error, GetLastError ());
+      return NULL;
+    }
+
+  retval = dbus_malloc (n);
+
+  if (!retval)
+    {
+      _DBUS_SET_OOM (error);
+      return NULL;
+    }
+
+  if (WideCharToMultiByte (CP_UTF8, 0, str, -1, retval, n, NULL, NULL) != n)
+    {
+      dbus_free (retval);
+      dbus_set_error_const (error, DBUS_ERROR_FAILED, "WideCharToMultiByte inconsistency");
+      return NULL;
+    }
+
+  return retval;
+}
+
+
+
+
+
+
+/************************************************************************
+ 
+ 
+ ************************************************************************/
+
+dbus_bool_t
+_dbus_win_account_to_sid (const wchar_t *waccount,
+                          void      	 **ppsid,
+                          DBusError 	  *error)
+{
+  dbus_bool_t retval = FALSE;
+  DWORD sid_length, wdomain_length;
+  SID_NAME_USE use;
+  wchar_t *wdomain;
+
+  *ppsid = NULL;
+
+  sid_length = 0;
+  wdomain_length = 0;
+  if (!LookupAccountNameW (NULL, waccount, NULL, &sid_length,
+                           NULL, &wdomain_length, &use) &&
+      GetLastError () != ERROR_INSUFFICIENT_BUFFER)
+    {
+      _dbus_win_set_error_from_win_error (error, GetLastError ());
+      return FALSE;
+    }
+
+  *ppsid = dbus_malloc (sid_length);
+  if (!*ppsid)
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  wdomain = dbus_new (wchar_t, wdomain_length);
+  if (!wdomain)
+    {
+      _DBUS_SET_OOM (error);
+      goto out1;
+    }
+
+  if (!LookupAccountNameW (NULL, waccount, (PSID) *ppsid, &sid_length,
+                           wdomain, &wdomain_length, &use))
+    {
+      _dbus_win_set_error_from_win_error (error, GetLastError ());
+      goto out2;
+    }
+
+  if (!IsValidSid ((PSID) *ppsid))
+    {
+      dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
+      goto out2;
+    }
+
+  retval = TRUE;
+
+out2:
+  dbus_free (wdomain);
+out1:
+  if (!retval)
+    {
+      dbus_free (*ppsid);
+      *ppsid = NULL;
+    }
+
+  return retval;
+}
+
+/** @} end of sysdeps-win */
+
+
+/**
+ * The only reason this is separate from _dbus_getpid() is to allow it
+ * on Windows for logging but not for other purposes.
+ * 
+ * @returns process ID to put in log messages
+ */
+unsigned long
+_dbus_pid_for_log (void)
+{
+  return _dbus_getpid ();
+}
+
+
+#ifndef DBUS_WINCE
+/** Gets our SID
+ * @param points to sid buffer, need to be freed with LocalFree()
+ * @returns process sid
+ */
+static dbus_bool_t
+_dbus_getsid(char **sid)
+{
+  HANDLE process_token = INVALID_HANDLE_VALUE;
+  TOKEN_USER *token_user = NULL;
+  DWORD n;
+  PSID psid;
+  int retval = FALSE;
+  
+  if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token)) 
+    {
+      _dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
+      goto failed;
+    }
+  if ((!GetTokenInformation (process_token, TokenUser, NULL, 0, &n)
+            && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
+           || (token_user = alloca (n)) == NULL
+           || !GetTokenInformation (process_token, TokenUser, token_user, n, &n))
+    {
+      _dbus_win_warn_win_error ("GetTokenInformation failed", GetLastError ());
+      goto failed;
+    }
+  psid = token_user->User.Sid;
+  if (!IsValidSid (psid))
+    {
+      _dbus_verbose("%s invalid sid\n",__FUNCTION__);
+      goto failed;
+    }
+  if (!ConvertSidToStringSidA (psid, sid))
+    {
+      _dbus_verbose("%s invalid sid\n",__FUNCTION__);
+      goto failed;
+    }
+//okay:
+  retval = TRUE;
+
+failed:
+  if (process_token != INVALID_HANDLE_VALUE)
+    CloseHandle (process_token);
+
+  _dbus_verbose("_dbus_getsid() returns %d\n",retval);
+  return retval;
+}
+#endif
+
+/************************************************************************
+ 
+ pipes
+ 
+ ************************************************************************/
+
+/**
+ * Creates a full-duplex pipe (as in socketpair()).
+ * Sets both ends of the pipe nonblocking.
+ *
+ * @param fd1 return location for one end
+ * @param fd2 return location for the other end
+ * @param blocking #TRUE if pipe should be blocking
+ * @param error error return
+ * @returns #FALSE on failure (if error is set)
+ */
+dbus_bool_t
+_dbus_full_duplex_pipe (int        *fd1,
+                        int        *fd2,
+                        dbus_bool_t blocking,
+                        DBusError  *error)
+{
+  SOCKET temp, socket1 = -1, socket2 = -1;
+  struct sockaddr_in saddr;
+  int len;
+  u_long arg;
+
+  _dbus_win_startup_winsock ();
+
+  temp = socket (AF_INET, SOCK_STREAM, 0);
+  if (temp == INVALID_SOCKET)
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      goto out0;
+    }
+
+  _DBUS_ZERO (saddr);
+  saddr.sin_family = AF_INET;
+  saddr.sin_port = 0;
+  saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+  if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)) == SOCKET_ERROR)
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      goto out0;
+    }
+
+  if (listen (temp, 1) == SOCKET_ERROR)
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      goto out0;
+    }
+
+  len = sizeof (saddr);
+  if (getsockname (temp, (struct sockaddr *)&saddr, &len) == SOCKET_ERROR)
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      goto out0;
+    }
+
+  socket1 = socket (AF_INET, SOCK_STREAM, 0);
+  if (socket1 == INVALID_SOCKET)
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      goto out0;
+    }
+
+  if (connect (socket1, (struct sockaddr  *)&saddr, len) == SOCKET_ERROR)
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      goto out1;
+    }
+
+  socket2 = accept (temp, (struct sockaddr *) &saddr, &len);
+  if (socket2 == INVALID_SOCKET)
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      goto out1;
+    }
+
+  if (!blocking)
+    {
+      arg = 1;
+      if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
+        {
+          DBUS_SOCKET_SET_ERRNO ();
+          goto out2;
+        }
+
+      arg = 1;
+      if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
+        {
+          DBUS_SOCKET_SET_ERRNO ();
+          goto out2;
+        }
+    }
+
+  *fd1 = socket1;
+  *fd2 = socket2;
+
+  _dbus_verbose ("full-duplex pipe %d:%d <-> %d:%d\n",
+                 *fd1, socket1, *fd2, socket2);
+
+  closesocket (temp);
+
+  return TRUE;
+
+out2:
+  closesocket (socket2);
+out1:
+  closesocket (socket1);
+out0:
+  closesocket (temp);
+
+  dbus_set_error (error, _dbus_error_from_errno (errno),
+                  "Could not setup socket pair: %s",
+                  _dbus_strerror_from_errno ());
+
+  return FALSE;
+}
+
+/**
+ * Wrapper for poll().
+ *
+ * @param fds the file descriptors to poll
+ * @param n_fds number of descriptors in the array
+ * @param timeout_milliseconds timeout or -1 for infinite
+ * @returns numbers of fds with revents, or <0 on error
+ */
+int
+_dbus_poll (DBusPollFD *fds,
+            int         n_fds,
+            int         timeout_milliseconds)
+{
+#define USE_CHRIS_IMPL 0
+
+#if USE_CHRIS_IMPL
+
+#define DBUS_POLL_CHAR_BUFFER_SIZE 2000
+  char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
+  char *msgp;
+
+  int ret = 0;
+  int i;
+  struct timeval tv;
+  int ready;
+
+#define DBUS_STACK_WSAEVENTS 256
+  WSAEVENT eventsOnStack[DBUS_STACK_WSAEVENTS];
+  WSAEVENT *pEvents = NULL;
+  if (n_fds > DBUS_STACK_WSAEVENTS)
+    pEvents = calloc(sizeof(WSAEVENT), n_fds);
+  else
+    pEvents = eventsOnStack;
+
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  msgp = msg;
+  msgp += sprintf (msgp, "WSAEventSelect: to=%d\n\t", timeout_milliseconds);
+  for (i = 0; i < n_fds; i++)
+    {
+      DBusPollFD *fdp = &fds[i];
+
+
+      if (fdp->events & _DBUS_POLLIN)
+        msgp += sprintf (msgp, "R:%d ", fdp->fd);
+
+      if (fdp->events & _DBUS_POLLOUT)
+        msgp += sprintf (msgp, "W:%d ", fdp->fd);
+
+      msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
+
+      // FIXME: more robust code for long  msg
+      //        create on heap when msg[] becomes too small
+      if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
+        {
+          _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
+        }
+    }
+
+  msgp += sprintf (msgp, "\n");
+  _dbus_verbose ("%s",msg);
+#endif
+  for (i = 0; i < n_fds; i++)
+    {
+      DBusPollFD *fdp = &fds[i];
+      WSAEVENT ev;
+      long lNetworkEvents = FD_OOB;
+
+      ev = WSACreateEvent();
+
+      if (fdp->events & _DBUS_POLLIN)
+        lNetworkEvents |= FD_READ | FD_ACCEPT | FD_CLOSE;
+
+      if (fdp->events & _DBUS_POLLOUT)
+        lNetworkEvents |= FD_WRITE | FD_CONNECT;
+
+      WSAEventSelect(fdp->fd, ev, lNetworkEvents);
+
+      pEvents[i] = ev;
+    }
+
+
+  ready = WSAWaitForMultipleEvents (n_fds, pEvents, FALSE, timeout_milliseconds, FALSE);
+
+  if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      if (errno != WSAEWOULDBLOCK)
+        _dbus_verbose ("WSAWaitForMultipleEvents: failed: %s\n", _dbus_strerror_from_errno ());
+      ret = -1;
+    }
+  else if (ready == WSA_WAIT_TIMEOUT)
+    {
+      _dbus_verbose ("WSAWaitForMultipleEvents: WSA_WAIT_TIMEOUT\n");
+      ret = 0;
+    }
+  else if (ready >= WSA_WAIT_EVENT_0 && ready < (int)(WSA_WAIT_EVENT_0 + n_fds))
+    {
+      msgp = msg;
+      msgp += sprintf (msgp, "WSAWaitForMultipleEvents: =%d\n\t", ready);
+
+      for (i = 0; i < n_fds; i++)
+        {
+          DBusPollFD *fdp = &fds[i];
+          WSANETWORKEVENTS ne;
+
+          fdp->revents = 0;
+
+          WSAEnumNetworkEvents(fdp->fd, pEvents[i], &ne);
+
+          if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
+            fdp->revents |= _DBUS_POLLIN;
+
+          if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
+            fdp->revents |= _DBUS_POLLOUT;
+
+          if (ne.lNetworkEvents & (FD_OOB))
+            fdp->revents |= _DBUS_POLLERR;
+
+          if (ne.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))
+              msgp += sprintf (msgp, "R:%d ", fdp->fd);
+
+          if (ne.lNetworkEvents & (FD_WRITE | FD_CONNECT))
+              msgp += sprintf (msgp, "W:%d ", fdp->fd);
+
+          if (ne.lNetworkEvents & (FD_OOB))
+              msgp += sprintf (msgp, "E:%d ", fdp->fd);
+
+          msgp += sprintf (msgp, "lNetworkEvents:%d ", ne.lNetworkEvents);
+
+          if(ne.lNetworkEvents)
+            ret++;
+
+          WSAEventSelect(fdp->fd, pEvents[i], 0);
+        }
+
+      msgp += sprintf (msgp, "\n");
+      _dbus_verbose ("%s",msg);
+    }
+  else
+    {
+      _dbus_verbose ("WSAWaitForMultipleEvents: failed for unknown reason!");
+      ret = -1;
+    }
+
+  for(i = 0; i < n_fds; i++)
+    {
+      WSACloseEvent(pEvents[i]);
+    }
+
+  if (n_fds > DBUS_STACK_WSAEVENTS)
+    free(pEvents);
+
+  return ret;
+
+#else   /* USE_CHRIS_IMPL */
+
+#define DBUS_POLL_CHAR_BUFFER_SIZE 2000
+  char msg[DBUS_POLL_CHAR_BUFFER_SIZE];
+  char *msgp;
+
+  fd_set read_set, write_set, err_set;
+  int max_fd = 0;
+  int i;
+  struct timeval tv;
+  int ready;
+
+  FD_ZERO (&read_set);
+  FD_ZERO (&write_set);
+  FD_ZERO (&err_set);
+
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  msgp = msg;
+  msgp += sprintf (msgp, "select: to=%d\n\t", timeout_milliseconds);
+  for (i = 0; i < n_fds; i++)
+    {
+      DBusPollFD *fdp = &fds[i];
+
+
+      if (fdp->events & _DBUS_POLLIN)
+        msgp += sprintf (msgp, "R:%d ", fdp->fd);
+
+      if (fdp->events & _DBUS_POLLOUT)
+        msgp += sprintf (msgp, "W:%d ", fdp->fd);
+
+      msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
+
+      // FIXME: more robust code for long  msg
+      //        create on heap when msg[] becomes too small
+      if (msgp >= msg + DBUS_POLL_CHAR_BUFFER_SIZE)
+        {
+          _dbus_assert_not_reached ("buffer overflow in _dbus_poll");
+        }
+    }
+
+  msgp += sprintf (msgp, "\n");
+  _dbus_verbose ("%s",msg);
+#endif
+  for (i = 0; i < n_fds; i++)
+    {
+      DBusPollFD *fdp = &fds[i]; 
+
+      if (fdp->events & _DBUS_POLLIN)
+        FD_SET (fdp->fd, &read_set);
+
+      if (fdp->events & _DBUS_POLLOUT)
+        FD_SET (fdp->fd, &write_set);
+
+      FD_SET (fdp->fd, &err_set);
+
+      max_fd = MAX (max_fd, fdp->fd);
+    }
+
+  // Avoid random lockups with send(), for lack of a better solution so far
+  tv.tv_sec = timeout_milliseconds < 0 ? 1 : timeout_milliseconds / 1000;
+  tv.tv_usec = timeout_milliseconds < 0 ? 0 : (timeout_milliseconds % 1000) * 1000;
+
+  ready = select (max_fd + 1, &read_set, &write_set, &err_set, &tv);
+
+  if (DBUS_SOCKET_API_RETURNS_ERROR (ready))
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      if (errno != WSAEWOULDBLOCK)
+        _dbus_verbose ("select: failed: %s\n", _dbus_strerror_from_errno ());
+    }
+  else if (ready == 0)
+    _dbus_verbose ("select: = 0\n");
+  else
+    if (ready > 0)
+      {
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+        msgp = msg;
+        msgp += sprintf (msgp, "select: = %d:\n\t", ready);
+
+        for (i = 0; i < n_fds; i++)
+          {
+            DBusPollFD *fdp = &fds[i];
+
+            if (FD_ISSET (fdp->fd, &read_set))
+              msgp += sprintf (msgp, "R:%d ", fdp->fd);
+
+            if (FD_ISSET (fdp->fd, &write_set))
+              msgp += sprintf (msgp, "W:%d ", fdp->fd);
+
+            if (FD_ISSET (fdp->fd, &err_set))
+              msgp += sprintf (msgp, "E:%d\n\t", fdp->fd);
+          }
+        msgp += sprintf (msgp, "\n");
+        _dbus_verbose ("%s",msg);
+#endif
+
+        for (i = 0; i < n_fds; i++)
+          {
+            DBusPollFD *fdp = &fds[i];
+
+            fdp->revents = 0;
+
+            if (FD_ISSET (fdp->fd, &read_set))
+              fdp->revents |= _DBUS_POLLIN;
+
+            if (FD_ISSET (fdp->fd, &write_set))
+              fdp->revents |= _DBUS_POLLOUT;
+
+            if (FD_ISSET (fdp->fd, &err_set))
+              fdp->revents |= _DBUS_POLLERR;
+          }
+      }
+  return ready;
+#endif  /* USE_CHRIS_IMPL */
+}
+
+
+
+
+/******************************************************************************
+ 
+Original CVS version of dbus-sysdeps.c
+ 
+******************************************************************************/
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps.c Wrappers around system/libc features (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2005 Novell, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+
+/**
+ * Exit the process, returning the given value.
+ *
+ * @param code the exit code
+ */
+void
+_dbus_exit (int code)
+{
+  _exit (code);
+}
+
+/**
+ * Creates a socket and connects to a socket at the given host 
+ * and port. The connection fd is returned, and is set up as
+ * nonblocking.
+ *
+ * @param host the host name to connect to
+ * @param port the port to connect to
+ * @param family the address family to listen on, NULL for all
+ * @param error return location for error code
+ * @returns connection file descriptor or -1 on error
+ */
+int
+_dbus_connect_tcp_socket (const char     *host,
+                          const char     *port,
+                          const char     *family,
+                          DBusError      *error)
+{
+  return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
+}
+
+int
+_dbus_connect_tcp_socket_with_nonce (const char     *host,
+                                     const char     *port,
+                                     const char     *family,
+                                     const char     *noncefile,
+                                     DBusError      *error)
+{
+  int fd = -1, res;
+  struct addrinfo hints;
+  struct addrinfo *ai, *tmp;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  _dbus_win_startup_winsock ();
+
+  _DBUS_ZERO (hints);
+
+  if (!family)
+    hints.ai_family = AF_UNSPEC;
+  else if (!strcmp(family, "ipv4"))
+    hints.ai_family = AF_INET;
+  else if (!strcmp(family, "ipv6"))
+    hints.ai_family = AF_INET6;
+  else
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_INVALID_ARGS,
+                      "Unknown address family %s", family);
+      return -1;
+    }
+  hints.ai_protocol = IPPROTO_TCP;
+  hints.ai_socktype = SOCK_STREAM;
+#ifdef AI_ADDRCONFIG
+  hints.ai_flags = AI_ADDRCONFIG;
+#else
+  hints.ai_flags = 0;
+#endif
+
+  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (res),
+                      "Failed to lookup host/port: \"%s:%s\": %s (%d)",
+                      host, port, _dbus_strerror(res), res);
+      return -1;
+    }
+
+  tmp = ai;
+  while (tmp)
+    {
+      if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET)
+        {
+          DBUS_SOCKET_SET_ERRNO ();
+          dbus_set_error (error,
+                          _dbus_error_from_errno (errno),
+                          "Failed to open socket: %s",
+                          _dbus_strerror_from_errno ());
+          freeaddrinfo(ai);
+          return -1;
+        }
+      _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+
+      if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
+        {
+          DBUS_SOCKET_SET_ERRNO ();
+          closesocket(fd);
+          fd = -1;
+          tmp = tmp->ai_next;
+          continue;
+        }
+
+      break;
+    }
+  freeaddrinfo(ai);
+
+  if (fd == -1)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (errno),
+                      "Failed to connect to socket \"%s:%s\" %s",
+                      host, port, _dbus_strerror_from_errno ());
+      return -1;
+    }
+
+  if (noncefile != NULL)
+    {
+      DBusString noncefileStr;
+      dbus_bool_t ret;
+      if (!_dbus_string_init (&noncefileStr) ||
+          !_dbus_string_append(&noncefileStr, noncefile))
+        {
+          closesocket (fd);
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          return -1;
+        }
+
+      ret = _dbus_send_nonce (fd, &noncefileStr, error);
+
+      _dbus_string_free (&noncefileStr);
+
+      if (!ret)
+        {
+          closesocket (fd);
+          return -1;
+        }
+    }
+
+  _dbus_fd_set_close_on_exec (fd);
+
+  if (!_dbus_set_fd_nonblocking (fd, error))
+    {
+      closesocket (fd);
+      return -1;
+    }
+
+  return fd;
+}
+
+/**
+ * Creates a socket and binds it to the given path, then listens on
+ * the socket. The socket is set to be nonblocking.  In case of port=0
+ * a random free port is used and returned in the port parameter.
+ * If inaddr_any is specified, the hostname is ignored.
+ *
+ * @param host the host name to listen on
+ * @param port the port to listen on, if zero a free port will be used 
+ * @param family the address family to listen on, NULL for all
+ * @param retport string to return the actual port listened on
+ * @param fds_p location to store returned file descriptors
+ * @param error return location for errors
+ * @returns the number of listening file descriptors or -1 on error
+ */
+
+int
+_dbus_listen_tcp_socket (const char     *host,
+                         const char     *port,
+                         const char     *family,
+                         DBusString     *retport,
+                         int           **fds_p,
+                         DBusError      *error)
+{
+  int nlisten_fd = 0, *listen_fd = NULL, res, i, port_num = -1;
+  struct addrinfo hints;
+  struct addrinfo *ai, *tmp;
+
+  // On Vista, sockaddr_gen must be a sockaddr_in6, and not a sockaddr_in6_old
+  //That's required for family == IPv6(which is the default on Vista if family is not given)
+  //So we use our own union instead of sockaddr_gen:
+
+  typedef union {
+	struct sockaddr Address;
+	struct sockaddr_in AddressIn;
+	struct sockaddr_in6 AddressIn6;
+  } mysockaddr_gen;
+
+  *fds_p = NULL;
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  _dbus_win_startup_winsock ();
+
+  _DBUS_ZERO (hints);
+
+  if (!family)
+    hints.ai_family = AF_UNSPEC;
+  else if (!strcmp(family, "ipv4"))
+    hints.ai_family = AF_INET;
+  else if (!strcmp(family, "ipv6"))
+    hints.ai_family = AF_INET6;
+  else
+    {
+      dbus_set_error (error,
+                      DBUS_ERROR_INVALID_ARGS,
+                      "Unknown address family %s", family);
+      return -1;
+    }
+
+  hints.ai_protocol = IPPROTO_TCP;
+  hints.ai_socktype = SOCK_STREAM;
+#ifdef AI_ADDRCONFIG
+  hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
+#else
+  hints.ai_flags = AI_PASSIVE;
+#endif
+
+ redo_lookup_with_port:
+  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
+    {
+      dbus_set_error (error,
+                      _dbus_error_from_errno (res),
+                      "Failed to lookup host/port: \"%s:%s\": %s (%d)",
+                      host ? host : "*", port, _dbus_strerror(res), res);
+      return -1;
+    }
+
+  tmp = ai;
+  while (tmp)
+    {
+      int fd = -1, *newlisten_fd;
+      if ((fd = socket (tmp->ai_family, SOCK_STREAM, 0)) == INVALID_SOCKET)
+        {
+          DBUS_SOCKET_SET_ERRNO ();
+          dbus_set_error (error,
+                          _dbus_error_from_errno (errno),
+                         "Failed to open socket: %s",
+                         _dbus_strerror_from_errno ());
+          goto failed;
+        }
+      _DBUS_ASSERT_ERROR_IS_CLEAR(error);
+
+      if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) == SOCKET_ERROR)
+        {
+          DBUS_SOCKET_SET_ERRNO ();
+          dbus_set_error (error, _dbus_error_from_errno (errno),
+                          "Failed to bind socket \"%s:%s\": %s",
+                          host ? host : "*", port, _dbus_strerror_from_errno ());
+          closesocket (fd);
+          goto failed;
+    }
+
+      if (listen (fd, 30 /* backlog */) == SOCKET_ERROR)
+        {
+          DBUS_SOCKET_SET_ERRNO ();
+          dbus_set_error (error, _dbus_error_from_errno (errno),
+                          "Failed to listen on socket \"%s:%s\": %s",
+                          host ? host : "*", port, _dbus_strerror_from_errno ());
+          closesocket (fd);
+          goto failed;
+        }
+
+      newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1));
+      if (!newlisten_fd)
+        {
+          closesocket (fd);
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
+                          "Failed to allocate file handle array");
+          goto failed;
+        }
+      listen_fd = newlisten_fd;
+      listen_fd[nlisten_fd] = fd;
+      nlisten_fd++;
+
+      if (!_dbus_string_get_length(retport))
+        {
+          /* If the user didn't specify a port, or used 0, then
+             the kernel chooses a port. After the first address
+             is bound to, we need to force all remaining addresses
+             to use the same port */
+          if (!port || !strcmp(port, "0"))
+            {
+              mysockaddr_gen addr;
+              socklen_t addrlen = sizeof(addr);
+              char portbuf[10];
+
+              if (getsockname(fd, &addr.Address, &addrlen) == SOCKET_ERROR)
+                {
+                  DBUS_SOCKET_SET_ERRNO ();
+                  dbus_set_error (error, _dbus_error_from_errno (errno),
+                                  "Failed to resolve port \"%s:%s\": %s",
+                                  host ? host : "*", port, _dbus_strerror_from_errno());
+                  goto failed;
+                }
+              snprintf( portbuf, sizeof( portbuf ) - 1, "%d", addr.AddressIn.sin_port );
+              if (!_dbus_string_append(retport, portbuf))
+                {
+                  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+                  goto failed;
+                }
+
+              /* Release current address list & redo lookup */
+              port = _dbus_string_get_const_data(retport);
+              freeaddrinfo(ai);
+              goto redo_lookup_with_port;
+            }
+          else
+            {
+              if (!_dbus_string_append(retport, port))
+                {
+                    dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+                    goto failed;
+                }
+            }
+        }
+  
+      tmp = tmp->ai_next;
+    }
+  freeaddrinfo(ai);
+  ai = NULL;
+
+  if (!nlisten_fd)
+    {
+      _dbus_win_set_errno (WSAEADDRINUSE);
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to bind socket \"%s:%s\": %s",
+                      host ? host : "*", port, _dbus_strerror_from_errno ());
+      return -1;
+    }
+
+  sscanf(_dbus_string_get_const_data(retport), "%d", &port_num);
+
+  for (i = 0 ; i < nlisten_fd ; i++)
+    {
+      _dbus_fd_set_close_on_exec (listen_fd[i]);
+      if (!_dbus_set_fd_nonblocking (listen_fd[i], error))
+        {
+          goto failed;
+        }
+    }
+
+  *fds_p = listen_fd;
+
+  return nlisten_fd;
+
+ failed:
+  if (ai)
+    freeaddrinfo(ai);
+  for (i = 0 ; i < nlisten_fd ; i++)
+    closesocket (listen_fd[i]);
+  dbus_free(listen_fd);
+  return -1;
+}
+
+
+/**
+ * Accepts a connection on a listening socket.
+ * Handles EINTR for you.
+ *
+ * @param listen_fd the listen file descriptor
+ * @returns the connection fd of the client, or -1 on error
+ */
+int
+_dbus_accept  (int listen_fd)
+{
+  int client_fd;
+
+ retry:
+  client_fd = accept (listen_fd, NULL, NULL);
+
+  if (DBUS_SOCKET_IS_INVALID (client_fd))
+    {
+      DBUS_SOCKET_SET_ERRNO ();
+      if (errno == EINTR)
+        goto retry;
+    }
+
+  _dbus_verbose ("client fd %d accepted\n", client_fd);
+  
+  return client_fd;
+}
+
+
+
+
+dbus_bool_t
+_dbus_send_credentials_socket (int            handle,
+                        DBusError      *error)
+{
+/* FIXME: for the session bus credentials shouldn't matter (?), but
+ * for the system bus they are presumably essential. A rough outline
+ * of a way to implement the credential transfer would be this:
+ *
+ * client waits to *read* a byte.
+ *
+ * server creates a named pipe with a random name, sends a byte
+ * contining its length, and its name.
+ *
+ * client reads the name, connects to it (using Win32 API).
+ *
+ * server waits for connection to the named pipe, then calls
+ * ImpersonateNamedPipeClient(), notes its now-current credentials,
+ * calls RevertToSelf(), closes its handles to the named pipe, and
+ * is done. (Maybe there is some other way to get the SID of a named
+ * pipe client without having to use impersonation?)
+ *
+ * client closes its handles and is done.
+ * 
+ * Ralf: Why not sending credentials over the given this connection ?
+ * Using named pipes makes it impossible to be connected from a unix client.  
+ *
+ */
+  int bytes_written;
+  DBusString buf; 
+
+  _dbus_string_init_const_len (&buf, "\0", 1);
+again:
+  bytes_written = _dbus_write_socket (handle, &buf, 0, 1 );
+
+  if (bytes_written < 0 && errno == EINTR)
+    goto again;
+
+  if (bytes_written < 0)
+    {
+      dbus_set_error (error, _dbus_error_from_errno (errno),
+                      "Failed to write credentials byte: %s",
+                     _dbus_strerror_from_errno ());
+      return FALSE;
+    }
+  else if (bytes_written == 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_IO_ERROR,
+                      "wrote zero bytes writing credentials byte");
+      return FALSE;
+    }
+  else
+    {
+      _dbus_assert (bytes_written == 1);
+      _dbus_verbose ("wrote 1 zero byte, credential sending isn't implemented yet\n");
+      return TRUE;
+    }
+  return TRUE;
+}
+
+/**
+ * Reads a single byte which must be nul (an error occurs otherwise),
+ * and reads unix credentials if available. Fills in pid/uid/gid with
+ * -1 if no credentials are available. Return value indicates whether
+ * a byte was read, not whether we got valid credentials. On some
+ * systems, such as Linux, reading/writing the byte isn't actually
+ * required, but we do it anyway just to avoid multiple codepaths.
+ * 
+ * Fails if no byte is available, so you must select() first.
+ *
+ * The point of the byte is that on some systems we have to
+ * use sendmsg()/recvmsg() to transmit credentials.
+ *
+ * @param client_fd the client file descriptor
+ * @param credentials struct to fill with credentials of client
+ * @param error location to store error code
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_read_credentials_socket  (int              handle,
+                                DBusCredentials *credentials,
+                                DBusError       *error)
+{
+  int bytes_read = 0;
+  DBusString buf;
+  
+  // could fail due too OOM
+  if (_dbus_string_init(&buf))
+    {
+      bytes_read = _dbus_read_socket(handle, &buf, 1 );
+
+      if (bytes_read > 0) 
+        _dbus_verbose("got one zero byte from server");
+
+      _dbus_string_free(&buf);
+    }
+
+  _dbus_credentials_add_from_current_process (credentials);
+  _dbus_verbose("FIXME: get faked credentials from current process");
+
+  return TRUE;
+}
+
+/**
+* Checks to make sure the given directory is 
+* private to the user 
+*
+* @param dir the name of the directory
+* @param error error return
+* @returns #FALSE on failure
+**/
+dbus_bool_t
+_dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error)
+{
+  /* TODO */
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  return TRUE;
+}
+
+
+/**
+ * Appends the given filename to the given directory.
+ *
+ * @todo it might be cute to collapse multiple '/' such as "foo//"
+ * concat "//bar"
+ *
+ * @param dir the directory name
+ * @param next_component the filename
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_concat_dir_and_file (DBusString       *dir,
+                           const DBusString *next_component)
+{
+  dbus_bool_t dir_ends_in_slash;
+  dbus_bool_t file_starts_with_slash;
+
+  if (_dbus_string_get_length (dir) == 0 ||
+      _dbus_string_get_length (next_component) == 0)
+    return TRUE;
+
+  dir_ends_in_slash =
+    ('/' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1) ||
+     '\\' == _dbus_string_get_byte (dir, _dbus_string_get_length (dir) - 1));
+
+  file_starts_with_slash =
+    ('/' == _dbus_string_get_byte (next_component, 0) ||
+     '\\' == _dbus_string_get_byte (next_component, 0));
+
+  if (dir_ends_in_slash && file_starts_with_slash)
+    {
+      _dbus_string_shorten (dir, 1);
+    }
+  else if (!(dir_ends_in_slash || file_starts_with_slash))
+    {
+      if (!_dbus_string_append_byte (dir, '\\'))
+        return FALSE;
+    }
+
+  return _dbus_string_copy (next_component, 0, dir,
+                            _dbus_string_get_length (dir));
+}
+
+/*---------------- DBusCredentials ----------------------------------*/
+
+/**
+ * Adds the credentials corresponding to the given username.
+ *
+ * @param credentials credentials to fill in 
+ * @param username the username
+ * @returns #TRUE if the username existed and we got some credentials
+ */
+dbus_bool_t
+_dbus_credentials_add_from_user (DBusCredentials  *credentials,
+                                     const DBusString *username)
+{
+  return _dbus_credentials_add_windows_sid (credentials,
+                    _dbus_string_get_const_data(username));
+}
+
+/**
+ * Adds the credentials of the current process to the
+ * passed-in credentials object.
+ *
+ * @param credentials credentials to add to
+ * @returns #FALSE if no memory; does not properly roll back on failure, so only some credentials may have been added
+ */
+
+dbus_bool_t
+_dbus_credentials_add_from_current_process (DBusCredentials *credentials)
+{
+  dbus_bool_t retval = FALSE;
+  char *sid = NULL;
+
+  if (!_dbus_getsid(&sid))
+    goto failed;
+
+  if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
+    goto failed;
+
+  if (!_dbus_credentials_add_windows_sid (credentials,sid))
+    goto failed;
+
+  retval = TRUE;
+  goto end;
+failed:
+  retval = FALSE;
+end:
+  if (sid)
+    LocalFree(sid);
+
+  return retval;
+}
+
+/**
+ * Append to the string the identity we would like to have when we
+ * authenticate, on UNIX this is the current process UID and on
+ * Windows something else, probably a Windows SID string.  No escaping
+ * is required, that is done in dbus-auth.c. The username here
+ * need not be anything human-readable, it can be the machine-readable
+ * form i.e. a user id.
+ * 
+ * @param str the string to append to
+ * @returns #FALSE on no memory
+ * @todo to which class belongs this 
+ */
+dbus_bool_t
+_dbus_append_user_from_current_process (DBusString *str)
+{
+  dbus_bool_t retval = FALSE;
+  char *sid = NULL;
+
+  if (!_dbus_getsid(&sid))
+    return FALSE;
+
+  retval = _dbus_string_append (str,sid);
+
+  LocalFree(sid);
+  return retval;
+}
+
+/**
+ * Gets our process ID
+ * @returns process ID
+ */
+dbus_pid_t
+_dbus_getpid (void)
+{
+  return GetCurrentProcessId ();
+}
+
+/** nanoseconds in a second */
+#define NANOSECONDS_PER_SECOND       1000000000
+/** microseconds in a second */
+#define MICROSECONDS_PER_SECOND      1000000
+/** milliseconds in a second */
+#define MILLISECONDS_PER_SECOND      1000
+/** nanoseconds in a millisecond */
+#define NANOSECONDS_PER_MILLISECOND  1000000
+/** microseconds in a millisecond */
+#define MICROSECONDS_PER_MILLISECOND 1000
+
+/**
+ * Sleeps the given number of milliseconds.
+ * @param milliseconds number of milliseconds
+ */
+void
+_dbus_sleep_milliseconds (int milliseconds)
+{
+  Sleep (milliseconds);
+}
+
+
+/**
+ * Get current time, as in gettimeofday(). Never uses the monotonic
+ * clock.
+ *
+ * @param tv_sec return location for number of seconds
+ * @param tv_usec return location for number of microseconds
+ */
+void
+_dbus_get_real_time (long *tv_sec,
+                     long *tv_usec)
+{
+  FILETIME ft;
+  dbus_uint64_t time64;
+
+  GetSystemTimeAsFileTime (&ft);
+
+  memcpy (&time64, &ft, sizeof (time64));
+
+  /* Convert from 100s of nanoseconds since 1601-01-01
+  * to Unix epoch. Yes, this is Y2038 unsafe.
+  */
+  time64 -= DBUS_INT64_CONSTANT (116444736000000000);
+  time64 /= 10;
+
+  if (tv_sec)
+    *tv_sec = time64 / 1000000;
+
+  if (tv_usec)
+    *tv_usec = time64 % 1000000;
+}
+
+/**
+ * Get current time, as in gettimeofday(). Use the monotonic clock if
+ * available, to avoid problems when the system time changes.
+ *
+ * @param tv_sec return location for number of seconds
+ * @param tv_usec return location for number of microseconds
+ */
+void
+_dbus_get_monotonic_time (long *tv_sec,
+                          long *tv_usec)
+{
+  /* no implementation yet, fall back to wall-clock time */
+  _dbus_get_real_time (tv_sec, tv_usec);
+}
+
+/**
+ * signal (SIGPIPE, SIG_IGN);
+ */
+void
+_dbus_disable_sigpipe (void)
+{
+}
+
+/**
+ * Creates a directory; succeeds if the directory
+ * is created or already existed.
+ *
+ * @param filename directory filename
+ * @param error initialized error object
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_create_directory (const DBusString *filename,
+                        DBusError        *error)
+{
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  filename_c = _dbus_string_get_const_data (filename);
+
+  if (!CreateDirectoryA (filename_c, NULL))
+    {
+      if (GetLastError () == ERROR_ALREADY_EXISTS)
+        return TRUE;
+
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Failed to create directory %s: %s\n",
+                      filename_c, _dbus_strerror_from_errno ());
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
+
+/**
+ * Generates the given number of random bytes,
+ * using the best mechanism we can come up with.
+ *
+ * @param str the string
+ * @param n_bytes the number of random bytes to append to string
+ * @returns #TRUE on success, #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_generate_random_bytes (DBusString *str,
+                             int         n_bytes)
+{
+  int old_len;
+  char *p;
+  HCRYPTPROV hprov;
+
+  old_len = _dbus_string_get_length (str);
+
+  if (!_dbus_string_lengthen (str, n_bytes))
+    return FALSE;
+
+  p = _dbus_string_get_data_len (str, old_len, n_bytes);
+
+  if (!CryptAcquireContext (&hprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+    return FALSE;
+
+  if (!CryptGenRandom (hprov, n_bytes, p))
+    {
+      CryptReleaseContext (hprov, 0);
+      return FALSE;
+    }
+
+  CryptReleaseContext (hprov, 0);
+
+  return TRUE;
+}
+
+/**
+ * Gets the temporary files directory by inspecting the environment variables 
+ * TMPDIR, TMP, and TEMP in that order. If none of those are set "/tmp" is returned
+ *
+ * @returns location of temp directory
+ */
+const char*
+_dbus_get_tmpdir(void)
+{
+  static const char* tmpdir = NULL;
+  static char buf[1000];
+
+  if (tmpdir == NULL)
+    {
+      char *last_slash;
+
+      if (!GetTempPathA (sizeof (buf), buf))
+        {
+          _dbus_warn ("GetTempPath failed\n");
+          _dbus_abort ();
+        }
+
+      /* Drop terminating backslash or slash */
+      last_slash = _mbsrchr (buf, '\\');
+      if (last_slash > buf && last_slash[1] == '\0')
+        last_slash[0] = '\0';
+      last_slash = _mbsrchr (buf, '/');
+      if (last_slash > buf && last_slash[1] == '\0')
+        last_slash[0] = '\0';
+
+      tmpdir = buf;
+    }
+
+  _dbus_assert(tmpdir != NULL);
+
+  return tmpdir;
+}
+
+
+/**
+ * Deletes the given file.
+ *
+ * @param filename the filename
+ * @param error error location
+ * 
+ * @returns #TRUE if unlink() succeeded
+ */
+dbus_bool_t
+_dbus_delete_file (const DBusString *filename,
+                   DBusError        *error)
+{
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  filename_c = _dbus_string_get_const_data (filename);
+
+  if (DeleteFileA (filename_c) == 0)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Failed to delete file %s: %s\n",
+                      filename_c, _dbus_strerror_from_errno ());
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
+/*
+ * replaces the term DBUS_PREFIX in configure_time_path by the
+ * current dbus installation directory. On unix this function is a noop
+ *
+ * @param configure_time_path
+ * @return real path
+ */
+const char *
+_dbus_replace_install_prefix (const char *configure_time_path)
+{
+#ifndef DBUS_PREFIX
+  return configure_time_path;
+#else
+  static char retval[1000];
+  static char runtime_prefix[1000];
+  int len = 1000;
+  int i;
+
+  if (!configure_time_path)
+    return NULL;
+
+  if ((!_dbus_get_install_root(runtime_prefix, len) ||
+       strncmp (configure_time_path, DBUS_PREFIX "/",
+                strlen (DBUS_PREFIX) + 1))) {
+     strcat (retval, configure_time_path);
+     return retval;
+  }
+
+  strcpy (retval, runtime_prefix);
+  strcat (retval, configure_time_path + strlen (DBUS_PREFIX) + 1);
+
+  /* Somehow, in some situations, backslashes get collapsed in the string.
+   * Since windows C library accepts both forward and backslashes as
+   * path separators, convert all backslashes to forward slashes.
+   */
+
+  for(i = 0; retval[i] != '\0'; i++) {
+    if(retval[i] == '\\')
+      retval[i] = '/';
+  }
+  return retval;
+#endif
+}
+
+#if !defined (DBUS_DISABLE_ASSERTS) || defined(DBUS_BUILD_TESTS)
+
+#if defined(_MSC_VER) || defined(DBUS_WINCE)
+# ifdef BACKTRACES
+#  undef BACKTRACES
+# endif
+#else
+# define BACKTRACES
+#endif
+
+#ifdef BACKTRACES
+/*
+ * Backtrace Generator
+ *
+ * Copyright 2004 Eric Poech
+ * Copyright 2004 Robert Shearman
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <winver.h>
+#include <imagehlp.h>
+#include <stdio.h>
+
+#define DPRINTF _dbus_warn
+
+#ifdef _MSC_VER
+#define BOOL int
+
+#define __i386__
+#endif
+
+//#define MAKE_FUNCPTR(f) static typeof(f) * p##f
+
+//MAKE_FUNCPTR(StackWalk);
+//MAKE_FUNCPTR(SymGetModuleBase);
+//MAKE_FUNCPTR(SymFunctionTableAccess);
+//MAKE_FUNCPTR(SymInitialize);
+//MAKE_FUNCPTR(SymGetSymFromAddr);
+//MAKE_FUNCPTR(SymGetModuleInfo);
+static BOOL (WINAPI *pStackWalk)(
+  DWORD MachineType,
+  HANDLE hProcess,
+  HANDLE hThread,
+  LPSTACKFRAME StackFrame,
+  PVOID ContextRecord,
+  PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
+  PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
+  PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
+  PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
+);
+#ifdef _WIN64
+static DWORD64 (WINAPI *pSymGetModuleBase)(
+  HANDLE hProcess,
+  DWORD64 dwAddr
+);
+static PVOID  (WINAPI *pSymFunctionTableAccess)(
+  HANDLE hProcess,
+  DWORD64 AddrBase
+);
+#else
+static DWORD (WINAPI *pSymGetModuleBase)(
+  HANDLE hProcess,
+  DWORD dwAddr
+);
+static PVOID  (WINAPI *pSymFunctionTableAccess)(
+  HANDLE hProcess,
+  DWORD AddrBase
+);
+#endif
+static BOOL  (WINAPI *pSymInitialize)(
+  HANDLE hProcess,
+  PSTR UserSearchPath,
+  BOOL fInvadeProcess
+);
+static BOOL  (WINAPI *pSymGetSymFromAddr)(
+  HANDLE hProcess,
+  DWORD Address,
+  PDWORD Displacement,
+  PIMAGEHLP_SYMBOL Symbol
+);
+static BOOL  (WINAPI *pSymGetModuleInfo)(
+  HANDLE hProcess,
+  DWORD dwAddr,
+  PIMAGEHLP_MODULE ModuleInfo
+);
+static DWORD  (WINAPI *pSymSetOptions)(
+  DWORD SymOptions
+);
+
+
+static BOOL init_backtrace()
+{
+    HMODULE hmodDbgHelp = LoadLibraryA("dbghelp");
+/*
+    #define GETFUNC(x) \
+    p##x = (typeof(x)*)GetProcAddress(hmodDbgHelp, #x); \
+    if (!p##x) \
+    { \
+        return FALSE; \
+    }
+    */
+
+
+//    GETFUNC(StackWalk);
+//    GETFUNC(SymGetModuleBase);
+//    GETFUNC(SymFunctionTableAccess);
+//    GETFUNC(SymInitialize);
+//    GETFUNC(SymGetSymFromAddr);
+//    GETFUNC(SymGetModuleInfo);
+
+#define FUNC(x) #x
+
+      pStackWalk = (BOOL  (WINAPI *)(
+DWORD MachineType,
+HANDLE hProcess,
+HANDLE hThread,
+LPSTACKFRAME StackFrame,
+PVOID ContextRecord,
+PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
+PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
+PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
+PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
+))GetProcAddress (hmodDbgHelp, FUNC(StackWalk));
+#ifdef _WIN64
+    pSymGetModuleBase=(DWORD64  (WINAPI *)(
+  HANDLE hProcess,
+  DWORD64 dwAddr
+))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
+    pSymFunctionTableAccess=(PVOID  (WINAPI *)(
+  HANDLE hProcess,
+  DWORD64 AddrBase
+))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
+#else
+    pSymGetModuleBase=(DWORD  (WINAPI *)(
+  HANDLE hProcess,
+  DWORD dwAddr
+))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleBase));
+    pSymFunctionTableAccess=(PVOID  (WINAPI *)(
+  HANDLE hProcess,
+  DWORD AddrBase
+))GetProcAddress (hmodDbgHelp, FUNC(SymFunctionTableAccess));
+#endif
+    pSymInitialize = (BOOL  (WINAPI *)(
+  HANDLE hProcess,
+  PSTR UserSearchPath,
+  BOOL fInvadeProcess
+))GetProcAddress (hmodDbgHelp, FUNC(SymInitialize));
+    pSymGetSymFromAddr = (BOOL  (WINAPI *)(
+  HANDLE hProcess,
+  DWORD Address,
+  PDWORD Displacement,
+  PIMAGEHLP_SYMBOL Symbol
+))GetProcAddress (hmodDbgHelp, FUNC(SymGetSymFromAddr));
+    pSymGetModuleInfo = (BOOL  (WINAPI *)(
+  HANDLE hProcess,
+  DWORD dwAddr,
+  PIMAGEHLP_MODULE ModuleInfo
+))GetProcAddress (hmodDbgHelp, FUNC(SymGetModuleInfo));
+pSymSetOptions = (DWORD  (WINAPI *)(
+DWORD SymOptions
+))GetProcAddress (hmodDbgHelp, FUNC(SymSetOptions));
+
+
+    pSymSetOptions(SYMOPT_UNDNAME);
+
+    pSymInitialize(GetCurrentProcess(), NULL, TRUE);
+
+    return TRUE;
+}
+
+static void dump_backtrace_for_thread(HANDLE hThread)
+{
+    STACKFRAME sf;
+    CONTEXT context;
+    DWORD dwImageType;
+
+    if (!pStackWalk)
+        if (!init_backtrace())
+            return;
+
+    /* can't use this function for current thread as GetThreadContext
+     * doesn't support getting context from current thread */
+    if (hThread == GetCurrentThread())
+        return;
+
+    DPRINTF("Backtrace:\n");
+
+    _DBUS_ZERO(context);
+    context.ContextFlags = CONTEXT_FULL;
+
+    SuspendThread(hThread);
+
+    if (!GetThreadContext(hThread, &context))
+    {
+        DPRINTF("Couldn't get thread context (error %ld)\n", GetLastError());
+        ResumeThread(hThread);
+        return;
+    }
+
+    _DBUS_ZERO(sf);
+
+#ifdef __i386__
+    sf.AddrFrame.Offset = context.Ebp;
+    sf.AddrFrame.Mode = AddrModeFlat;
+    sf.AddrPC.Offset = context.Eip;
+    sf.AddrPC.Mode = AddrModeFlat;
+    dwImageType = IMAGE_FILE_MACHINE_I386;
+#elif _M_X64
+  dwImageType                = IMAGE_FILE_MACHINE_AMD64;
+  sf.AddrPC.Offset    = context.Rip;
+  sf.AddrPC.Mode      = AddrModeFlat;
+  sf.AddrFrame.Offset = context.Rsp;
+  sf.AddrFrame.Mode   = AddrModeFlat;
+  sf.AddrStack.Offset = context.Rsp;
+  sf.AddrStack.Mode   = AddrModeFlat;
+#elif _M_IA64
+  dwImageType                 = IMAGE_FILE_MACHINE_IA64;
+  sf.AddrPC.Offset    = context.StIIP;
+  sf.AddrPC.Mode      = AddrModeFlat;
+  sf.AddrFrame.Offset = context.IntSp;
+  sf.AddrFrame.Mode   = AddrModeFlat;
+  sf.AddrBStore.Offset= context.RsBSP;
+  sf.AddrBStore.Mode  = AddrModeFlat;
+  sf.AddrStack.Offset = context.IntSp;
+  sf.AddrStack.Mode   = AddrModeFlat;
+#else
+# error You need to fill in the STACKFRAME structure for your architecture
+#endif
+
+    while (pStackWalk(dwImageType, GetCurrentProcess(),
+                     hThread, &sf, &context, NULL, pSymFunctionTableAccess,
+                     pSymGetModuleBase, NULL))
+    {
+        BYTE buffer[256];
+        IMAGEHLP_SYMBOL * pSymbol = (IMAGEHLP_SYMBOL *)buffer;
+        DWORD dwDisplacement;
+
+        pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
+        pSymbol->MaxNameLength = sizeof(buffer) - sizeof(IMAGEHLP_SYMBOL) + 1;
+
+        if (!pSymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset,
+                                &dwDisplacement, pSymbol))
+        {
+            IMAGEHLP_MODULE ModuleInfo;
+            ModuleInfo.SizeOfStruct = sizeof(ModuleInfo);
+
+            if (!pSymGetModuleInfo(GetCurrentProcess(), sf.AddrPC.Offset,
+                                   &ModuleInfo))
+                DPRINTF("1\t%p\n", (void*)sf.AddrPC.Offset);
+            else
+                DPRINTF("2\t%s+0x%lx\n", ModuleInfo.ImageName,
+                    sf.AddrPC.Offset - ModuleInfo.BaseOfImage);
+        }
+        else if (dwDisplacement)
+            DPRINTF("3\t%s+0x%lx\n", pSymbol->Name, dwDisplacement);
+        else
+            DPRINTF("4\t%s\n", pSymbol->Name);
+    }
+
+    ResumeThread(hThread);
+}
+
+static DWORD WINAPI dump_thread_proc(LPVOID lpParameter)
+{
+    dump_backtrace_for_thread((HANDLE)lpParameter);
+    return 0;
+}
+
+/* cannot get valid context from current thread, so we have to execute
+ * backtrace from another thread */
+static void dump_backtrace()
+{
+    HANDLE hCurrentThread;
+    HANDLE hThread;
+    DWORD dwThreadId;
+    DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
+        GetCurrentProcess(), &hCurrentThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
+    hThread = CreateThread(NULL, 0, dump_thread_proc, (LPVOID)hCurrentThread,
+        0, &dwThreadId);
+    WaitForSingleObject(hThread, INFINITE);
+    CloseHandle(hThread);
+    CloseHandle(hCurrentThread);
+}
+#endif
+#endif /* asserts or tests enabled */
+
+#ifdef BACKTRACES
+void _dbus_print_backtrace(void)
+{
+  init_backtrace();
+  dump_backtrace();
+}
+#else
+void _dbus_print_backtrace(void)
+{
+  _dbus_verbose ("  D-Bus not compiled with backtrace support\n");
+}
+#endif
+
+static dbus_uint32_t fromAscii(char ascii)
+{
+    if(ascii >= '0' && ascii <= '9')
+        return ascii - '0';
+    if(ascii >= 'A' && ascii <= 'F')
+        return ascii - 'A' + 10;
+    if(ascii >= 'a' && ascii <= 'f')
+        return ascii - 'a' + 10;
+    return 0;    
+}
+
+dbus_bool_t _dbus_read_local_machine_uuid   (DBusGUID         *machine_id,
+                                             dbus_bool_t       create_if_not_found,
+                                             DBusError        *error)
+{
+#ifdef DBUS_WINCE
+	return TRUE;
+  // TODO
+#else
+    HW_PROFILE_INFOA info;
+    char *lpc = &info.szHwProfileGuid[0];
+    dbus_uint32_t u;
+
+    //  the hw-profile guid lives long enough
+    if(!GetCurrentHwProfileA(&info))
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); // FIXME
+        return FALSE;  
+      }
+
+    // Form: {12340001-4980-1920-6788-123456789012}
+    lpc++;
+    // 12340001
+    u = ((fromAscii(lpc[0]) <<  0) |
+         (fromAscii(lpc[1]) <<  4) |
+         (fromAscii(lpc[2]) <<  8) |
+         (fromAscii(lpc[3]) << 12) |
+         (fromAscii(lpc[4]) << 16) |
+         (fromAscii(lpc[5]) << 20) |
+         (fromAscii(lpc[6]) << 24) |
+         (fromAscii(lpc[7]) << 28));
+    machine_id->as_uint32s[0] = u;
+
+    lpc += 9;
+    // 4980-1920
+    u = ((fromAscii(lpc[0]) <<  0) |
+         (fromAscii(lpc[1]) <<  4) |
+         (fromAscii(lpc[2]) <<  8) |
+         (fromAscii(lpc[3]) << 12) |
+         (fromAscii(lpc[5]) << 16) |
+         (fromAscii(lpc[6]) << 20) |
+         (fromAscii(lpc[7]) << 24) |
+         (fromAscii(lpc[8]) << 28));
+    machine_id->as_uint32s[1] = u;
+    
+    lpc += 10;
+    // 6788-1234
+    u = ((fromAscii(lpc[0]) <<  0) |
+         (fromAscii(lpc[1]) <<  4) |
+         (fromAscii(lpc[2]) <<  8) |
+         (fromAscii(lpc[3]) << 12) |
+         (fromAscii(lpc[5]) << 16) |
+         (fromAscii(lpc[6]) << 20) |
+         (fromAscii(lpc[7]) << 24) |
+         (fromAscii(lpc[8]) << 28));
+    machine_id->as_uint32s[2] = u;
+    
+    lpc += 9;
+    // 56789012
+    u = ((fromAscii(lpc[0]) <<  0) |
+         (fromAscii(lpc[1]) <<  4) |
+         (fromAscii(lpc[2]) <<  8) |
+         (fromAscii(lpc[3]) << 12) |
+         (fromAscii(lpc[4]) << 16) |
+         (fromAscii(lpc[5]) << 20) |
+         (fromAscii(lpc[6]) << 24) |
+         (fromAscii(lpc[7]) << 28));
+    machine_id->as_uint32s[3] = u;
+#endif
+    return TRUE;
+}
+
+static
+HANDLE _dbus_global_lock (const char *mutexname)
+{
+  HANDLE mutex;
+  DWORD gotMutex;
+
+  mutex = CreateMutexA( NULL, FALSE, mutexname );
+  if( !mutex )
+    {
+      return FALSE;
+    }
+
+   gotMutex = WaitForSingleObject( mutex, INFINITE );
+   switch( gotMutex )
+     {
+       case WAIT_ABANDONED:
+               ReleaseMutex (mutex);
+               CloseHandle (mutex);
+               return 0;
+       case WAIT_FAILED:
+       case WAIT_TIMEOUT:
+               return 0;
+     }
+
+   return mutex;
+}
+
+static
+void _dbus_global_unlock (HANDLE mutex)
+{
+  ReleaseMutex (mutex);
+  CloseHandle (mutex); 
+}
+
+// for proper cleanup in dbus-daemon
+static HANDLE hDBusDaemonMutex = NULL;
+static HANDLE hDBusSharedMem = NULL;
+// sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
+static const char *cUniqueDBusInitMutex = "UniqueDBusInitMutex";
+// sync _dbus_get_autolaunch_address
+static const char *cDBusAutolaunchMutex = "DBusAutolaunchMutex";
+// mutex to determine if dbus-daemon is already started (per user)
+static const char *cDBusDaemonMutex = "DBusDaemonMutex";
+// named shm for dbus adress info (per user)
+static const char *cDBusDaemonAddressInfo = "DBusDaemonAddressInfo";
+
+static dbus_bool_t
+_dbus_get_install_root_as_hash(DBusString *out)
+{
+    DBusString install_path;
+
+    char path[MAX_PATH*2];
+    int path_size = sizeof(path);
+
+    if (!_dbus_get_install_root(path,path_size))
+        return FALSE;
+
+    _dbus_string_init(&install_path);
+    _dbus_string_append(&install_path,path);
+
+    _dbus_string_init(out);
+    _dbus_string_tolower_ascii(&install_path,0,_dbus_string_get_length(&install_path));
+
+    if (!_dbus_sha_compute (&install_path, out))
+        return FALSE;
+
+    return TRUE;
+}
+
+static dbus_bool_t
+_dbus_get_address_string (DBusString *out, const char *basestring, const char *scope)
+{
+  _dbus_string_init(out);
+  _dbus_string_append(out,basestring);
+
+  if (!scope)
+    {
+      return TRUE;
+    }
+  else if (strcmp(scope,"*install-path") == 0
+        // for 1.3 compatibility
+        || strcmp(scope,"install-path") == 0)
+    {
+      DBusString temp;
+      if (!_dbus_get_install_root_as_hash(&temp))
+        {
+          _dbus_string_free(out);
+           return FALSE;
+        }
+      _dbus_string_append(out,"-");
+      _dbus_string_append(out,_dbus_string_get_const_data(&temp));
+      _dbus_string_free(&temp);
+    }
+  else if (strcmp(scope,"*user") == 0)
+    {
+      _dbus_string_append(out,"-");
+      if (!_dbus_append_user_from_current_process(out))
+        {
+           _dbus_string_free(out);
+           return FALSE;
+        }
+    }
+  else if (strlen(scope) > 0)
+    {
+      _dbus_string_append(out,"-");
+      _dbus_string_append(out,scope);
+      return TRUE;
+    }
+  return TRUE;
+}
+
+static dbus_bool_t
+_dbus_get_shm_name (DBusString *out,const char *scope)
+{
+  return _dbus_get_address_string (out,cDBusDaemonAddressInfo,scope);
+}
+
+static dbus_bool_t
+_dbus_get_mutex_name (DBusString *out,const char *scope)
+{
+  return _dbus_get_address_string (out,cDBusDaemonMutex,scope);
+}
+
+dbus_bool_t
+_dbus_daemon_is_session_bus_address_published (const char *scope)
+{
+  HANDLE lock;
+  DBusString mutex_name;
+
+  if (!_dbus_get_mutex_name(&mutex_name,scope))
+    {
+      _dbus_string_free( &mutex_name );
+      return FALSE;
+    }
+
+  if (hDBusDaemonMutex)
+      return TRUE;
+
+  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
+  lock = _dbus_global_lock( cUniqueDBusInitMutex );
+
+  // we use CreateMutex instead of OpenMutex because of possible race conditions,
+  // see http://msdn.microsoft.com/en-us/library/ms684315%28VS.85%29.aspx
+  hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) );
+
+  /* The client uses mutex ownership to detect a running server, so the server should do so too.
+     Fortunally the client deletes the mutex in the lock protected area, so checking presence 
+     will work too.  */
+
+  _dbus_global_unlock( lock );
+
+  _dbus_string_free( &mutex_name );
+
+  if (hDBusDaemonMutex  == NULL)
+      return FALSE;
+  if (GetLastError() == ERROR_ALREADY_EXISTS)
+    {
+      CloseHandle(hDBusDaemonMutex);
+      hDBusDaemonMutex = NULL;
+      return TRUE;
+    }
+  // mutex wasn't created before, so return false.
+  // We leave the mutex name allocated for later reusage
+  // in _dbus_daemon_publish_session_bus_address.
+  return FALSE;
+}
+
+dbus_bool_t
+_dbus_daemon_publish_session_bus_address (const char* address, const char *scope)
+{
+  HANDLE lock;
+  char *shared_addr = NULL;
+  DBusString shm_name;
+  DBusString mutex_name;
+
+  _dbus_assert (address);
+
+  if (!_dbus_get_mutex_name(&mutex_name,scope))
+    {
+      _dbus_string_free( &mutex_name );
+      return FALSE;
+    }
+
+  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
+  lock = _dbus_global_lock( cUniqueDBusInitMutex );
+
+  if (!hDBusDaemonMutex)
+    {
+      hDBusDaemonMutex = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) );
+    }
+  _dbus_string_free( &mutex_name );
+
+  // acquire the mutex
+  if (WaitForSingleObject( hDBusDaemonMutex, 10 ) != WAIT_OBJECT_0)
+    {
+      _dbus_global_unlock( lock );
+      CloseHandle( hDBusDaemonMutex );
+      return FALSE;
+    }
+
+  if (!_dbus_get_shm_name(&shm_name,scope))
+    {
+      _dbus_string_free( &shm_name );
+      _dbus_global_unlock( lock );
+      return FALSE;
+    }
+
+  // create shm
+  hDBusSharedMem = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
+                                       0, strlen( address ) + 1, _dbus_string_get_const_data(&shm_name) );
+  _dbus_assert( hDBusSharedMem );
+
+  shared_addr = MapViewOfFile( hDBusSharedMem, FILE_MAP_WRITE, 0, 0, 0 );
+
+  _dbus_assert (shared_addr);
+
+  strcpy( shared_addr, address);
+
+  // cleanup
+  UnmapViewOfFile( shared_addr );
+
+  _dbus_global_unlock( lock );
+  _dbus_verbose( "published session bus address at %s\n",_dbus_string_get_const_data (&shm_name) );
+
+  _dbus_string_free( &shm_name );
+  return TRUE;
+}
+
+void
+_dbus_daemon_unpublish_session_bus_address (void)
+{
+  HANDLE lock;
+
+  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
+  lock = _dbus_global_lock( cUniqueDBusInitMutex );
+
+  CloseHandle( hDBusSharedMem );
+
+  hDBusSharedMem = NULL;
+
+  ReleaseMutex( hDBusDaemonMutex );
+
+  CloseHandle( hDBusDaemonMutex );
+
+  hDBusDaemonMutex = NULL;
+
+  _dbus_global_unlock( lock );
+}
+
+static dbus_bool_t
+_dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name)
+{
+  HANDLE sharedMem;
+  char *shared_addr;
+  int i;
+
+  // read shm
+  for(i=0;i<20;++i) {
+      // we know that dbus-daemon is available, so we wait until shm is available
+      sharedMem = OpenFileMappingA( FILE_MAP_READ, FALSE, _dbus_string_get_const_data(shm_name));
+      if( sharedMem == 0 )
+          Sleep( 100 );
+      if ( sharedMem != 0)
+          break;
+  }
+
+  if( sharedMem == 0 )
+      return FALSE;
+
+  shared_addr = MapViewOfFile( sharedMem, FILE_MAP_READ, 0, 0, 0 );
+
+  if( !shared_addr )
+      return FALSE;
+
+  _dbus_string_init( address );
+
+  _dbus_string_append( address, shared_addr );
+
+  // cleanup
+  UnmapViewOfFile( shared_addr );
+
+  CloseHandle( sharedMem );
+
+  return TRUE;
+}
+
+static dbus_bool_t
+_dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char *scope)
+{
+  HANDLE lock;
+  HANDLE daemon;
+  DBusString mutex_name;
+  dbus_bool_t bRet = TRUE;
+
+  if (!_dbus_get_mutex_name(&mutex_name,scope))
+    {
+      _dbus_string_free( &mutex_name );
+      return FALSE;
+    }
+
+  // sync _dbus_daemon_publish_session_bus_address, _dbus_daemon_unpublish_session_bus_address and _dbus_daemon_already_runs
+  lock = _dbus_global_lock( cUniqueDBusInitMutex );
+
+  // do checks
+  daemon = CreateMutexA( NULL, FALSE, _dbus_string_get_const_data(&mutex_name) );
+  if(WaitForSingleObject( daemon, 10 ) != WAIT_TIMEOUT)
+    {
+      ReleaseMutex (daemon);
+      CloseHandle (daemon);
+
+      _dbus_global_unlock( lock );
+      _dbus_string_free( &mutex_name );
+      return FALSE;
+    }
+
+  // read shm
+  bRet = _dbus_get_autolaunch_shm( address, shm_name );
+
+  // cleanup
+  CloseHandle ( daemon );
+
+  _dbus_global_unlock( lock );
+  _dbus_string_free( &mutex_name );
+
+  return bRet;
+}
+
+dbus_bool_t
+_dbus_get_autolaunch_address (const char *scope, DBusString *address,
+                              DBusError *error)
+{
+  HANDLE mutex;
+  STARTUPINFOA si;
+  PROCESS_INFORMATION pi;
+  dbus_bool_t retval = FALSE;
+  LPSTR lpFile;
+  char dbus_exe_path[MAX_PATH];
+  char dbus_args[MAX_PATH * 2];
+  const char * daemon_name = DBUS_DAEMON_NAME ".exe";
+  DBusString shm_name;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (!_dbus_get_shm_name(&shm_name,scope))
+    {
+        dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not determine shm name");
+        return FALSE;
+    }
+
+  mutex = _dbus_global_lock ( cDBusAutolaunchMutex );
+
+  if (_dbus_daemon_already_runs(address,&shm_name,scope))
+    {
+        _dbus_verbose( "found running dbus daemon at %s\n",
+                       _dbus_string_get_const_data (&shm_name) );
+        retval = TRUE;
+        goto out;
+    }
+
+  if (!SearchPathA(NULL, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
+    {
+      // Look in directory containing dbus shared library
+      HMODULE hmod;
+      char dbus_module_path[MAX_PATH];
+      DWORD rc;
+
+      _dbus_verbose( "did not found dbus daemon executable on default search path, "
+            "trying path where dbus shared library is located");
+
+      hmod = _dbus_win_get_dll_hmodule();
+      rc = GetModuleFileNameA(hmod, dbus_module_path, sizeof(dbus_module_path));
+      if (rc <= 0)
+        {
+          dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not retrieve dbus shared library file name");
+          retval = FALSE;
+          goto out;
+        }
+      else
+        {
+          char *ext_idx = strrchr(dbus_module_path, '\\');
+          if (ext_idx)
+          *ext_idx = '\0';
+          if (!SearchPathA(dbus_module_path, daemon_name, NULL, sizeof(dbus_exe_path), dbus_exe_path, &lpFile))
+            {
+              dbus_set_error_const (error, DBUS_ERROR_FAILED, "could not find dbus-daemon executable");
+              retval = FALSE;
+              printf ("please add the path to %s to your PATH environment variable\n", daemon_name);
+              printf ("or start the daemon manually\n\n");
+              goto out;
+            }
+          _dbus_verbose( "found dbus daemon executable at %s",dbus_module_path);
+        }
+    }
+
+
+  // Create process
+  ZeroMemory( &si, sizeof(si) );
+  si.cb = sizeof(si);
+  ZeroMemory( &pi, sizeof(pi) );
+
+  _snprintf(dbus_args, sizeof(dbus_args) - 1, "\"%s\" %s", dbus_exe_path,  " --session");
+
+//  argv[i] = "--config-file=bus\\session.conf";
+//  printf("create process \"%s\" %s\n", dbus_exe_path, dbus_args);
+  if(CreateProcessA(dbus_exe_path, dbus_args, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
+    {
+      CloseHandle (pi.hThread);
+      CloseHandle (pi.hProcess);
+      retval = _dbus_get_autolaunch_shm( address, &shm_name );
+      if (retval == FALSE)
+        dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to get autolaunch address from launched dbus-daemon");
+    }
+  else
+    {
+      dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to launch dbus-daemon");
+      retval = FALSE;
+    }
+
+out:
+  if (retval)
+    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  else
+    _DBUS_ASSERT_ERROR_IS_SET (error);
+  
+  _dbus_global_unlock (mutex);
+
+  return retval;
+ }
+
+
+/** Makes the file readable by every user in the system.
+ *
+ * @param filename the filename
+ * @param error error location
+ * @returns #TRUE if the file's permissions could be changed.
+ */
+dbus_bool_t
+_dbus_make_file_world_readable(const DBusString *filename,
+                               DBusError *error)
+{
+  // TODO
+  return TRUE;
+}
+
+/**
+ * return the relocated DATADIR
+ *
+ * @returns relocated DATADIR static string
+ */
+
+static const char *
+_dbus_windows_get_datadir (void)
+{
+	return _dbus_replace_install_prefix(DBUS_DATADIR);
+}
+
+#undef DBUS_DATADIR
+#define DBUS_DATADIR _dbus_windows_get_datadir ()
+
+
+#define DBUS_STANDARD_SESSION_SERVICEDIR "/dbus-1/services"
+#define DBUS_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services"
+
+/**
+ * Returns the standard directories for a session bus to look for service 
+ * activation files 
+ *
+ * On Windows this should be data directories:
+ *
+ * %CommonProgramFiles%/dbus
+ *
+ * and
+ *
+ * relocated DBUS_DATADIR
+ *
+ * @param dirs the directory list we are returning
+ * @returns #FALSE on OOM 
+ */
+
+dbus_bool_t 
+_dbus_get_standard_session_servicedirs (DBusList **dirs)
+{
+  const char *common_progs;
+  DBusString servicedir_path;
+
+  if (!_dbus_string_init (&servicedir_path))
+    return FALSE;
+
+#ifdef DBUS_WINCE
+  {
+    /* On Windows CE, we adjust datadir dynamically to installation location.  */
+    const char *data_dir = _dbus_getenv ("DBUS_DATADIR");
+
+    if (data_dir != NULL)
+      {
+        if (!_dbus_string_append (&servicedir_path, data_dir))
+          goto oom;
+        
+        if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
+          goto oom;
+      }
+  }
+#else
+/*
+ the code for accessing services requires absolute base pathes
+ in case DBUS_DATADIR is relative make it absolute
+*/
+#ifdef DBUS_WIN
+  {
+    DBusString p;
+
+    _dbus_string_init_const (&p, DBUS_DATADIR);
+
+    if (!_dbus_path_is_absolute (&p))
+      {
+        char install_root[1000];
+        if (_dbus_get_install_root (install_root, sizeof(install_root)))
+          if (!_dbus_string_append (&servicedir_path, install_root))
+            goto oom;
+      }
+  }
+#endif
+  if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR))
+    goto oom;
+
+  if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
+    goto oom;
+#endif
+
+  common_progs = _dbus_getenv ("CommonProgramFiles");
+
+  if (common_progs != NULL)
+    {
+      if (!_dbus_string_append (&servicedir_path, common_progs))
+        goto oom;
+
+      if (!_dbus_string_append (&servicedir_path, _DBUS_PATH_SEPARATOR))
+        goto oom;
+    }
+
+  if (!_dbus_split_paths_and_append (&servicedir_path, 
+                               DBUS_STANDARD_SESSION_SERVICEDIR, 
+                               dirs))
+    goto oom;
+
+  _dbus_string_free (&servicedir_path);  
+  return TRUE;
+
+ oom:
+  _dbus_string_free (&servicedir_path);
+  return FALSE;
+}
+
+/**
+ * Returns the standard directories for a system bus to look for service
+ * activation files
+ *
+ * On UNIX this should be the standard xdg freedesktop.org data directories:
+ *
+ * XDG_DATA_DIRS=${XDG_DATA_DIRS-/usr/local/share:/usr/share}
+ *
+ * and
+ *
+ * DBUS_DATADIR
+ *
+ * On Windows there is no system bus and this function can return nothing.
+ *
+ * @param dirs the directory list we are returning
+ * @returns #FALSE on OOM
+ */
+
+dbus_bool_t
+_dbus_get_standard_system_servicedirs (DBusList **dirs)
+{
+  *dirs = NULL;
+  return TRUE;
+}
+
+_DBUS_DEFINE_GLOBAL_LOCK (atomic);
+
+/**
+ * Atomically increments an integer
+ *
+ * @param atomic pointer to the integer to increment
+ * @returns the value before incrementing
+ *
+ */
+dbus_int32_t
+_dbus_atomic_inc (DBusAtomic *atomic)
+{
+  // +/- 1 is needed here!
+  // no volatile argument with mingw
+  return InterlockedIncrement (&atomic->value) - 1;
+}
+
+/**
+ * Atomically decrement an integer
+ *
+ * @param atomic pointer to the integer to decrement
+ * @returns the value before decrementing
+ *
+ */
+dbus_int32_t
+_dbus_atomic_dec (DBusAtomic *atomic)
+{
+  // +/- 1 is needed here!
+  // no volatile argument with mingw
+  return InterlockedDecrement (&atomic->value) + 1;
+}
+
+/**
+ * Atomically get the value of an integer. It may change at any time
+ * thereafter, so this is mostly only useful for assertions.
+ *
+ * @param atomic pointer to the integer to get
+ * @returns the value at this moment
+ */
+dbus_int32_t
+_dbus_atomic_get (DBusAtomic *atomic)
+{
+  /* this is what GLib does, hopefully it's right... */
+  MemoryBarrier ();
+  return atomic->value;
+}
+
+/**
+ * Called when the bus daemon is signaled to reload its configuration; any
+ * caches should be nuked. Of course any caches that need explicit reload
+ * are probably broken, but c'est la vie.
+ *
+ * 
+ */
+void
+_dbus_flush_caches (void)
+{
+}
+
+/**
+ * See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently
+ * for Winsock so is abstracted)
+ *
+ * @returns #TRUE if errno == EAGAIN or errno == EWOULDBLOCK
+ */
+dbus_bool_t
+_dbus_get_is_errno_eagain_or_ewouldblock (void)
+{
+  return errno == WSAEWOULDBLOCK;
+}
+
+/**
+ * return the absolute path of the dbus installation 
+ *
+ * @param s buffer for installation path
+ * @param len length of buffer
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_get_install_root(char *prefix, int len)
+{
+    //To find the prefix, we cut the filename and also \bin\ if present
+    DWORD pathLength;
+    char *lastSlash;
+    SetLastError( 0 );
+    pathLength = GetModuleFileNameA(_dbus_win_get_dll_hmodule(), prefix, len);
+    if ( pathLength == 0 || GetLastError() != 0 ) {
+        *prefix = '\0';
+        return FALSE;
+    }
+    lastSlash = _mbsrchr(prefix, '\\');
+    if (lastSlash == NULL) {
+        *prefix = '\0';
+        return FALSE;
+    }
+    //cut off binary name
+    lastSlash[1] = 0;
+
+    //cut possible "\\bin"
+
+    //this fails if we are in a double-byte system codepage and the
+    //folder's name happens to end with the *bytes*
+    //"\\bin"... (I.e. the second byte of some Han character and then
+    //the Latin "bin", but that is not likely I think...
+    if (lastSlash - prefix >= 4 && strnicmp(lastSlash - 4, "\\bin", 4) == 0)
+        lastSlash[-3] = 0;
+    else if (lastSlash - prefix >= 10 && strnicmp(lastSlash - 10, "\\bin\\debug", 10) == 0)
+        lastSlash[-9] = 0;
+    else if (lastSlash - prefix >= 12 && strnicmp(lastSlash - 12, "\\bin\\release", 12) == 0)
+        lastSlash[-11] = 0;
+
+    return TRUE;
+}
+
+/** 
+  find config file either from installation or build root according to 
+  the following path layout 
+    install-root/
+      bin/dbus-daemon[d].exe
+      etc/<config-file>.conf *or* etc/dbus-1/<config-file>.conf
+      (the former above is what dbus4win uses, the latter above is
+      what a "normal" Unix-style "make install" uses)
+
+    build-root/
+      bin/dbus-daemon[d].exe
+      bus/<config-file>.conf 
+*/
+dbus_bool_t 
+_dbus_get_config_file_name(DBusString *config_file, char *s)
+{
+  char path[MAX_PATH*2];
+  int path_size = sizeof(path);
+
+  if (!_dbus_get_install_root(path,path_size))
+    return FALSE;
+
+  if(strlen(s) + 4 + strlen(path) > sizeof(path)-2)
+    return FALSE;
+  strcat(path,"etc\\");
+  strcat(path,s);
+  if (_dbus_file_exists(path)) 
+    {
+      // find path from executable 
+      if (!_dbus_string_append (config_file, path))
+        return FALSE;
+    }
+  else 
+    {
+      if (!_dbus_get_install_root(path,path_size))
+        return FALSE;
+      if(strlen(s) + 11 + strlen(path) > sizeof(path)-2)
+        return FALSE;
+      strcat(path,"etc\\dbus-1\\");
+      strcat(path,s);
+  
+      if (_dbus_file_exists(path)) 
+        {
+          if (!_dbus_string_append (config_file, path))
+            return FALSE;
+        }
+      else
+        {
+          if (!_dbus_get_install_root(path,path_size))
+            return FALSE;
+          if(strlen(s) + 4 + strlen(path) > sizeof(path)-2)
+            return FALSE;
+          strcat(path,"bus\\");
+          strcat(path,s);
+          
+          if (_dbus_file_exists(path)) 
+            {
+              if (!_dbus_string_append (config_file, path))
+                return FALSE;
+            }
+        }
+    }
+  return TRUE;
+}    
+
+/**
+ * Append the absolute path of the system.conf file
+ * (there is no system bus on Windows so this can just
+ * return FALSE and print a warning or something)
+ * 
+ * @param str the string to append to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_append_system_config_file (DBusString *str)
+{
+  return _dbus_get_config_file_name(str, "system.conf");
+}
+
+/**
+ * Append the absolute path of the session.conf file.
+ * 
+ * @param str the string to append to
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_append_session_config_file (DBusString *str)
+{
+  return _dbus_get_config_file_name(str, "session.conf");
+}
+
+/* See comment in dbus-sysdeps-unix.c */
+dbus_bool_t
+_dbus_lookup_session_address (dbus_bool_t *supported,
+                              DBusString  *address,
+                              DBusError   *error)
+{
+  /* Probably fill this in with something based on COM? */
+  *supported = FALSE;
+  return TRUE;
+}
+
+/**
+ * Appends the directory in which a keyring for the given credentials
+ * should be stored.  The credentials should have either a Windows or
+ * UNIX user in them.  The directory should be an absolute path.
+ *
+ * On UNIX the directory is ~/.dbus-keyrings while on Windows it should probably
+ * be something else, since the dotfile convention is not normal on Windows.
+ * 
+ * @param directory string to append directory to
+ * @param credentials credentials the directory should be for
+ *  
+ * @returns #FALSE on no memory
+ */
+dbus_bool_t
+_dbus_append_keyring_directory_for_credentials (DBusString      *directory,
+                                                DBusCredentials *credentials)
+{
+  DBusString homedir;
+  DBusString dotdir;
+  const char *homepath;
+  const char *homedrive;
+
+  _dbus_assert (credentials != NULL);
+  _dbus_assert (!_dbus_credentials_are_anonymous (credentials));
+  
+  if (!_dbus_string_init (&homedir))
+    return FALSE;
+
+  homedrive = _dbus_getenv("HOMEDRIVE");
+  if (homedrive != NULL && *homedrive != '\0')
+    {
+      _dbus_string_append(&homedir,homedrive);
+    }
+
+  homepath = _dbus_getenv("HOMEPATH");
+  if (homepath != NULL && *homepath != '\0')
+    {
+      _dbus_string_append(&homedir,homepath);
+    }
+  
+#ifdef DBUS_BUILD_TESTS
+  {
+    const char *override;
+    
+    override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
+    if (override != NULL && *override != '\0')
+      {
+        _dbus_string_set_length (&homedir, 0);
+        if (!_dbus_string_append (&homedir, override))
+          goto failed;
+
+        _dbus_verbose ("Using fake homedir for testing: %s\n",
+                       _dbus_string_get_const_data (&homedir));
+      }
+    else
+      {
+        static dbus_bool_t already_warned = FALSE;
+        if (!already_warned)
+          {
+            _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
+            already_warned = TRUE;
+          }
+      }
+  }
+#endif
+
+#ifdef DBUS_WINCE
+  /* It's not possible to create a .something directory in Windows CE
+     using the file explorer.  */
+#define KEYRING_DIR "dbus-keyrings"
+#else
+#define KEYRING_DIR ".dbus-keyrings"
+#endif
+
+  _dbus_string_init_const (&dotdir, KEYRING_DIR);
+  if (!_dbus_concat_dir_and_file (&homedir,
+                                  &dotdir))
+    goto failed;
+  
+  if (!_dbus_string_copy (&homedir, 0,
+                          directory, _dbus_string_get_length (directory))) {
+    goto failed;
+  }
+
+  _dbus_string_free (&homedir);
+  return TRUE;
+  
+ failed: 
+  _dbus_string_free (&homedir);
+  return FALSE;
+}
+
+/** Checks if a file exists
+*
+* @param file full path to the file
+* @returns #TRUE if file exists
+*/
+dbus_bool_t 
+_dbus_file_exists (const char *file)
+{
+  DWORD attributes = GetFileAttributesA (file);
+
+  if (attributes != INVALID_FILE_ATTRIBUTES && GetLastError() != ERROR_PATH_NOT_FOUND)
+    return TRUE;
+  else
+    return FALSE;  
+}
+
+/**
+ * A wrapper around strerror() because some platforms
+ * may be lame and not have strerror().
+ *
+ * @param error_number errno.
+ * @returns error description.
+ */
+const char*
+_dbus_strerror (int error_number)
+{
+#ifdef DBUS_WINCE
+  // TODO
+  return "unknown";
+#else
+  const char *msg;
+
+  switch (error_number)
+    {
+    case WSAEINTR:
+      return "Interrupted function call";
+    case WSAEACCES:
+      return "Permission denied";
+    case WSAEFAULT:
+      return "Bad address";
+    case WSAEINVAL:
+      return "Invalid argument";
+    case WSAEMFILE:
+      return "Too many open files";
+    case WSAEWOULDBLOCK:
+      return "Resource temporarily unavailable";
+    case WSAEINPROGRESS:
+      return "Operation now in progress";
+    case WSAEALREADY:
+      return "Operation already in progress";
+    case WSAENOTSOCK:
+      return "Socket operation on nonsocket";
+    case WSAEDESTADDRREQ:
+      return "Destination address required";
+    case WSAEMSGSIZE:
+      return "Message too long";
+    case WSAEPROTOTYPE:
+      return "Protocol wrong type for socket";
+    case WSAENOPROTOOPT:
+      return "Bad protocol option";
+    case WSAEPROTONOSUPPORT:
+      return "Protocol not supported";
+    case WSAESOCKTNOSUPPORT:
+      return "Socket type not supported";
+    case WSAEOPNOTSUPP:
+      return "Operation not supported";
+    case WSAEPFNOSUPPORT:
+      return "Protocol family not supported";
+    case WSAEAFNOSUPPORT:
+      return "Address family not supported by protocol family";
+    case WSAEADDRINUSE:
+      return "Address already in use";
+    case WSAEADDRNOTAVAIL:
+      return "Cannot assign requested address";
+    case WSAENETDOWN:
+      return "Network is down";
+    case WSAENETUNREACH:
+      return "Network is unreachable";
+    case WSAENETRESET:
+      return "Network dropped connection on reset";
+    case WSAECONNABORTED:
+      return "Software caused connection abort";
+    case WSAECONNRESET:
+      return "Connection reset by peer";
+    case WSAENOBUFS:
+      return "No buffer space available";
+    case WSAEISCONN:
+      return "Socket is already connected";
+    case WSAENOTCONN:
+      return "Socket is not connected";
+    case WSAESHUTDOWN:
+      return "Cannot send after socket shutdown";
+    case WSAETIMEDOUT:
+      return "Connection timed out";
+    case WSAECONNREFUSED:
+      return "Connection refused";
+    case WSAEHOSTDOWN:
+      return "Host is down";
+    case WSAEHOSTUNREACH:
+      return "No route to host";
+    case WSAEPROCLIM:
+      return "Too many processes";
+    case WSAEDISCON:
+      return "Graceful shutdown in progress";
+    case WSATYPE_NOT_FOUND:
+      return "Class type not found";
+    case WSAHOST_NOT_FOUND:
+      return "Host not found";
+    case WSATRY_AGAIN:
+      return "Nonauthoritative host not found";
+    case WSANO_RECOVERY:
+      return "This is a nonrecoverable error";
+    case WSANO_DATA:
+      return "Valid name, no data record of requested type";
+    case WSA_INVALID_HANDLE:
+      return "Specified event object handle is invalid";
+    case WSA_INVALID_PARAMETER:
+      return "One or more parameters are invalid";
+    case WSA_IO_INCOMPLETE:
+      return "Overlapped I/O event object not in signaled state";
+    case WSA_IO_PENDING:
+      return "Overlapped operations will complete later";
+    case WSA_NOT_ENOUGH_MEMORY:
+      return "Insufficient memory available";
+    case WSA_OPERATION_ABORTED:
+      return "Overlapped operation aborted";
+#ifdef WSAINVALIDPROCTABLE
+
+    case WSAINVALIDPROCTABLE:
+      return "Invalid procedure table from service provider";
+#endif
+#ifdef WSAINVALIDPROVIDER
+
+    case WSAINVALIDPROVIDER:
+      return "Invalid service provider version number";
+#endif
+#ifdef WSAPROVIDERFAILEDINIT
+
+    case WSAPROVIDERFAILEDINIT:
+      return "Unable to initialize a service provider";
+#endif
+
+    case WSASYSCALLFAILURE:
+      return "System call failure";
+    }
+  msg = strerror (error_number);
+  if (msg == NULL)
+    msg = "unknown";
+
+  return msg;
+#endif //DBUS_WINCE
+}
+
+/**
+ * Assigns an error name and message corresponding to a Win32 error
+ * code to a DBusError. Does nothing if error is #NULL.
+ *
+ * @param error the error.
+ * @param code the Win32 error code
+ */
+void
+_dbus_win_set_error_from_win_error (DBusError *error,
+                                    int        code)
+{
+  char *msg;
+
+  /* As we want the English message, use the A API */
+  FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_IGNORE_INSERTS |
+                  FORMAT_MESSAGE_FROM_SYSTEM,
+                  NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
+                  (LPSTR) &msg, 0, NULL);
+  if (msg)
+    {
+      char *msg_copy;
+
+      msg_copy = dbus_malloc (strlen (msg));
+      strcpy (msg_copy, msg);
+      LocalFree (msg);
+
+      dbus_set_error (error, "win32.error", "%s", msg_copy);
+    }
+  else
+    dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code);
+}
+
+void
+_dbus_win_warn_win_error (const char *message,
+                          int         code)
+{
+  DBusError error;
+
+  dbus_error_init (&error);
+  _dbus_win_set_error_from_win_error (&error, code);
+  _dbus_warn ("%s: %s\n", message, error.message);
+  dbus_error_free (&error);
+}
+
+/**
+ * Removes a directory; Directory must be empty
+ *
+ * @param filename directory filename
+ * @param error initialized error object
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_delete_directory (const DBusString *filename,
+                        DBusError        *error)
+{
+  const char *filename_c;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  filename_c = _dbus_string_get_const_data (filename);
+
+  if (RemoveDirectoryA (filename_c) == 0)
+    {
+      char *emsg = _dbus_win_error_string (GetLastError ());
+      dbus_set_error (error, _dbus_win_error_from_last_error (),
+                      "Failed to remove directory %s: %s",
+                      filename_c, emsg);
+      _dbus_win_free_error_string (emsg);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Checks whether the filename is an absolute path
+ *
+ * @param filename the filename
+ * @returns #TRUE if an absolute path
+ */
+dbus_bool_t
+_dbus_path_is_absolute (const DBusString *filename)
+{
+  if (_dbus_string_get_length (filename) > 0)
+    return _dbus_string_get_byte (filename, 1) == ':'
+           || _dbus_string_get_byte (filename, 0) == '\\'
+           || _dbus_string_get_byte (filename, 0) == '/';
+  else
+    return FALSE;
+}
+
+dbus_bool_t
+_dbus_check_setuid (void)
+{
+  return FALSE;
+}
+
+/** @} end of sysdeps-win */
+/* tests in dbus-sysdeps-util.c */
+
diff --git a/dbus/dbus/dbus-sysdeps-win.h b/dbus/dbus/dbus-sysdeps-win.h
new file mode 100644
index 0000000..74624b7
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-win.h
@@ -0,0 +1,90 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps.c Wrappers around system/libc features (internal to D-BUS implementation)
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2005 Novell, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_SYSDEPS_WIN_H
+#define DBUS_SYSDEPS_WIN_H
+
+extern void *_dbus_win_get_dll_hmodule (void);
+#define _WINSOCKAPI_
+
+#include "dbus-hash.h"
+#include "dbus-string.h"
+#include <ctype.h>
+#include <malloc.h>
+#include <windows.h>
+#undef interface
+
+#define DBUS_CONSOLE_DIR "/var/run/console/"
+
+
+void _dbus_win_set_errno (int err);
+const char* _dbus_win_error_from_last_error (void);
+
+void _dbus_win_startup_winsock (void);
+void _dbus_win_warn_win_error  (const char *message,
+                                int         code);
+                                
+char * _dbus_win_error_string (int error_number);
+void _dbus_win_free_error_string (char *string);
+
+extern const char* _dbus_lm_strerror  (int error_number);
+
+
+dbus_bool_t _dbus_win_account_to_sid (const wchar_t *waccount,
+                                      void         **ppsid,
+                                      DBusError     *error);
+
+dbus_bool_t
+_dbus_win32_sid_to_name_and_domain (dbus_uid_t  uid,
+                                    wchar_t   **wname,
+                                    wchar_t   **wdomain,
+                                    DBusError  *error);
+
+
+/* Don't define DBUS_CONSOLE_DIR on Win32 */
+
+wchar_t    *_dbus_win_utf8_to_utf16 (const char  *str,
+                                     DBusError   *error);
+char       *_dbus_win_utf16_to_utf8 (const wchar_t *str,
+                                     DBusError *error);
+
+void        _dbus_win_set_error_from_win_error (DBusError *error, int code);
+
+dbus_bool_t
+_dbus_win_sid_to_name_and_domain (dbus_uid_t uid,
+                                  wchar_t  **wname,
+                                  wchar_t  **wdomain,
+                                  DBusError *error);
+
+dbus_bool_t _dbus_file_exists (const char *filename);
+
+dbus_bool_t _dbus_get_config_file_name(DBusString *config_file, 
+                                       char *s);
+
+dbus_bool_t _dbus_get_install_root(char *prefix, int len);
+
+#endif
+
+/** @} end of sysdeps-win.h */
diff --git a/dbus/dbus/dbus-sysdeps-wince-glue.c b/dbus/dbus/dbus-sysdeps-wince-glue.c
new file mode 100644
index 0000000..74b1371
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-wince-glue.c
@@ -0,0 +1,1165 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-wince-glue.c Wrappers for Windows CE around system/libc features (internal to D-BUS implementation)
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2005 Novell, Inc.
+ * Copyright (C) 2006 Ralf Habacker <ralf.habacker@freenet.de>
+ * Copyright (C) 2006 Peter Kümmel  <syntheticpp@gmx.net>
+ * Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-sysdeps.h"
+#include "dbus-sysdeps-win.h"
+
+#include <windows.h>
+/* Including shlobj.h creates trouble on some compilers.  Just chicken
+   out here by defining just what we need.  */
+#ifndef CSIDL_PERSONAL
+#define CSIDL_PERSONAL 5
+#endif
+
+
+/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST.  */
+static char *
+stpcpy (char *dest, const char *src)
+{
+  char *d = dest;
+  const char *s = src;
+
+  do
+    *d++ = *s;
+  while (*s++ != '\0');
+
+  return d - 1;
+}
+
+
+/* This is special cased, because we must avoid using many dbus
+   functions (such as memory allocations): Those functions may in turn
+   cause verbose output and check the flag!  */
+static char *
+get_verbose_setting()
+{
+  const wchar_t dir[] = L"Software\\freedesktop\\DBus";
+  const wchar_t name[] = L"Verbose";
+  HKEY root_key;
+  HKEY key_handle;
+  DWORD nbytes;
+  DWORD n1;
+  DWORD type;
+  wchar_t *result_w = NULL;
+  char *result;
+  int len;
+
+  root_key = HKEY_LOCAL_MACHINE;
+  if (RegOpenKeyExW (root_key, dir, 0, KEY_READ, &key_handle))
+    return NULL;
+
+  nbytes = 1;
+  if (RegQueryValueExW (key_handle, name, 0, NULL, NULL, &nbytes))
+    {
+      RegCloseKey (key_handle);
+      return NULL;
+    }
+  /* Round up to multiple of wchar_t, convert to number of wchar_t's, and add 1.  */
+  n1 = ((nbytes + sizeof(wchar_t) - 1) / sizeof (wchar_t)) + 1;
+  result_w = malloc (n1 * sizeof (wchar_t));
+  if (!result_w)
+    {
+      RegCloseKey (key_handle);
+      return NULL;
+    }
+  if (RegQueryValueExW (key_handle, name, 0, &type, (LPBYTE) result_w, &nbytes))
+    {
+      RegCloseKey (key_handle);
+      free (result_w);
+      return NULL;
+    }
+  RegCloseKey (key_handle);
+  result_w[n1 - 1] = 0; /* Make sure it is really a string.  */
+
+  /* NOTE: REG_MULTI_SZ and REG_EXPAND_SZ not supported, because they
+     are not needed in this module.  */
+  if (type != REG_SZ)
+    {
+      free (result_w);
+      return NULL;
+    }
+
+  len = WideCharToMultiByte (CP_UTF8, 0, result_w, -1, NULL, 0, NULL, NULL);
+  if (len < 0)
+    {
+      free (result_w);
+      return NULL;
+    }
+
+  result = malloc (len + 1);
+  if (!result)
+    {
+      free (result_w);
+      return NULL;
+    }
+
+  len = WideCharToMultiByte (CP_UTF8, 0, result_w, -1, result, len, NULL, NULL);
+  free (result_w);
+  if (len < 0)
+    {
+      free (result);
+      return NULL;
+    }
+  return result;
+}
+
+
+/* Return a string from the W32 Registry or NULL in case of error.
+   Caller must release the return value.  A NULL for root is an alias
+   for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */
+static char *
+read_w32_registry_string (const char *root, const char *dir, const char *name)
+{
+  HKEY root_key, key_handle;
+  DWORD n1, nbytes, type;
+  char *result = NULL;
+	
+  if ( !root )
+    root_key = HKEY_CURRENT_USER;
+  else if ( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
+    root_key = HKEY_CLASSES_ROOT;
+  else if ( !strcmp( root, "HKEY_CURRENT_USER" ) )
+    root_key = HKEY_CURRENT_USER;
+  else if ( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
+    root_key = HKEY_LOCAL_MACHINE;
+  else if ( !strcmp( root, "HKEY_USERS" ) )
+    root_key = HKEY_USERS;
+  else
+    return NULL;
+
+  if (RegOpenKeyExA (root_key, dir, 0, KEY_READ, &key_handle))
+    {
+      if (root)
+        return NULL; /* no need for a RegClose, so return direct */
+      /* It seems to be common practise to fall back to HKLM. */
+      if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
+        return NULL; /* still no need for a RegClose, so return direct */
+    }
+
+  nbytes = 1;
+  if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
+    {
+      if (root)
+        goto out;
+      /* Try to fallback to HKLM also for a missing value.  */
+      RegCloseKey (key_handle);
+      if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
+        return NULL; /* Nope.  */
+      if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
+        goto out;
+    }
+  n1 = nbytes + 1;
+  result = malloc (n1);
+  if (!result)
+    goto out;
+  if (RegQueryValueExA (key_handle, name, 0, &type, result, &n1))
+    {
+      free(result);
+      result = NULL;
+      goto out;
+    }
+  result[nbytes] = 0; /* Make sure it is really a string.  */
+
+ out:
+  RegCloseKey (key_handle);
+  return result;
+}
+
+
+static char *
+find_inst_dir ()
+{
+  return read_w32_registry_string ("HKEY_LOCAL_MACHINE",
+				  "Software\\freedesktop\\DBus",
+				  "Install Directory");
+}
+
+
+static char *
+find_env_in_registry (const char *name)
+{
+  return read_w32_registry_string ("HKEY_LOCAL_MACHINE",
+                                   "Software\\freedesktop\\DBus",
+                                   name);
+}
+
+
+static char *
+find_program_in_inst_dir (const char *name)
+{
+  char *result = NULL;
+  char *tmp;
+
+  tmp = find_inst_dir ();
+  if (!tmp)
+    return NULL;
+
+  result = malloc (strlen (tmp) + 5 + strlen (name) + 1);
+  if (!result)
+    {
+      free (tmp);
+      return NULL;
+    }
+
+  strcpy (stpcpy (stpcpy (result, tmp), "\\bin\\"), name);
+  free (tmp);
+
+  return result;
+}
+
+
+static char *
+find_inst_subdir (const char *name)
+{
+  char *result = NULL;
+  char *tmp;
+
+  tmp = find_inst_dir ();
+  if (!tmp)
+    return NULL;
+
+  result = malloc (strlen (tmp) + 1 + strlen (name) + 1);
+  if (!result)
+    {
+      free (tmp);
+      return NULL;
+    }
+
+  strcpy (stpcpy (stpcpy (result, tmp), "\\"), name);
+  free (tmp);
+
+  return result;
+}
+
+
+static char *
+find_my_documents_folder ()
+{
+  /* One for safety, just in case.  */
+  char dir[MAX_PATH + 1];
+  char *result;
+
+  dir[0] = '\0';
+  /* May return false even if successful.  */
+  SHGetSpecialFolderPathA (0, dir, CSIDL_PERSONAL, 0);
+  if (dir[0] == '\0')
+    return NULL;
+
+  result = malloc (strlen (dir) + 1);
+  if (!result)
+    return NULL;
+  strcpy (result, dir);
+  return result;
+}
+
+
+#define MAX_ENV 30
+
+char *environ[MAX_ENV + 1];
+
+char *
+getenv (const char *name)
+{
+  static char *past_result;
+  char **envp;
+  int idx;
+
+  if (past_result)
+    {
+      free (past_result);
+      past_result = NULL;
+    }
+
+  if (! strcmp (name, "DBUS_VERBOSE"))
+    return past_result = get_verbose_setting ();
+  else if (! strcmp (name, "HOMEPATH"))
+    return past_result = find_my_documents_folder ();
+  else if (! strcmp (name, "DBUS_DATADIR"))
+    return past_result = find_inst_subdir ("share");
+
+  for (envp = environ; *envp != 0; envp++)
+    {
+      const char *varp = name;
+      char *ep = *envp;
+      int same_name = 0;
+
+      while (*varp == *ep && *varp != '\0')
+	{
+	  ++ep;
+	  ++varp;
+	};
+
+      if (*varp == '\0' && *ep == '=')
+	return ep + 1;
+    }
+
+  return NULL;
+}
+
+
+int
+putenv (char *str)
+{
+  char **envp;
+  int idx;
+  for (envp = environ; *envp != 0; envp++)
+    {
+      char *varp = str;
+      char *ep = *envp;
+      int same_name = 0;
+
+      while (*varp == *ep && *varp != '\0')
+	{
+	  if (*varp == '=')
+	    same_name = 1;
+	  ++ep;
+	  ++varp;
+	};
+
+      if (*varp == *ep && *varp == '\0')
+	return 0;
+      if (same_name)
+	{
+	  *envp = str;
+	  return 0;
+	}
+    }
+
+  idx = envp - environ;
+  if (idx > MAX_ENV)
+    {
+      _dbus_win_set_errno (ENOMEM);
+      return -1;
+    }
+
+  environ[idx] = str;
+  return 0;
+}
+
+
+clock_t
+clock (void)
+{
+  return GetTickCount ();
+}
+
+
+void
+abort (void)
+{
+  /* This is what windows does.  */
+  exit (3);
+}
+
+
+void
+GetSystemTimeAsFileTime (LPFILETIME ftp)
+{
+  SYSTEMTIME st;
+  GetSystemTime (&st);
+  SystemTimeToFileTime (&st, ftp);
+}
+
+
+unsigned char*
+_mbsrchr (const unsigned char* str, unsigned int ch)
+{
+  /* FIXME.  This is not multi-byte safe.  */
+  return strrchr (str, ch);
+}
+
+
+HANDLE OpenFileMappingA(DWORD dwDesiredAccess,
+			BOOL bInheritHandle,
+			LPCSTR lpName)
+{
+  DWORD flProtect = 0;
+  HANDLE hMapping;
+
+  if (dwDesiredAccess & FILE_MAP_READ)
+    flProtect |= PAGE_READONLY;
+
+  if (dwDesiredAccess & FILE_MAP_WRITE)
+    flProtect |= PAGE_READWRITE;
+
+  SetLastError (0);
+  hMapping = CreateFileMappingA(INVALID_HANDLE_VALUE,
+				NULL, flProtect, 0, 0, lpName);
+  if (hMapping != INVALID_HANDLE_VALUE)
+    {
+      /* Just in case Windows CE changes its behaviour, we check for
+         the right error value here.  */
+      if (GetLastError () != ERROR_ALREADY_EXISTS)
+        {
+          CloseHandle(hMapping);
+          hMapping = INVALID_HANDLE_VALUE;
+        }
+    }
+  return hMapping;
+}
+
+
+BOOL
+MoveFileExA (LPCSTR lpExistingFileName, LPCSTR lpNewFileName, DWORD dwFlags)
+{
+  _dbus_assert (dwFlags == MOVEFILE_REPLACE_EXISTING);
+
+  if (_dbus_file_exists (lpNewFileName))
+    {
+      BOOL result = DeleteFileA (lpNewFileName);
+      if (result == 0)
+	return FALSE;
+    }
+  return MoveFileA (lpExistingFileName, lpNewFileName);
+}
+
+
+BOOL
+SetHandleInformation (HANDLE hObject, DWORD dwMask, DWORD dwFlags)
+{
+  _dbus_assert (dwMask == (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE));
+  _dbus_assert (dwFlags == 0);
+
+  /* Not supported on Windows CE, and actually the default.  So just
+     return overwhelming success.  */
+  return 1;
+}
+
+
+DWORD
+SearchPathA (LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension,
+             DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart)
+{
+  char *filename;
+  char *filepart;
+  int filename_len;
+  
+  _dbus_assert (lpPath == NULL);
+  _dbus_assert (lpExtension == NULL);
+  
+  filename = find_program_in_inst_dir (lpFileName);
+  if (!filename)
+    {
+      SetLastError (ERROR_FILE_NOT_FOUND);
+      return 0;
+    }
+
+  filename_len = strlen (filename) + 1;
+  if (filename_len > nBufferLength)
+    {
+      free (filename);
+      return filename_len;
+    }
+
+  strcpy (lpBuffer, filename);
+  free (filename);
+
+  filepart = _mbsrchr (lpBuffer, '\\');
+  if (!filepart)
+    filepart = lpBuffer;
+  *lpFilePart = filepart;
+
+  return filename_len - 1;
+}
+
+
+/** Gets our SID
+ * @param points to sid buffer, need to be freed with LocalFree()
+ * @returns process sid
+ */
+dbus_bool_t
+_dbus_getsid(char **sid)
+{
+  /* There is nothing like this on Windows CE, so we fake it.  */
+  static const char asid[] = "S-1-5-21-515967899-920026266-1708537768-1000";
+  char *buf = LocalAlloc (LMEM_FIXED, sizeof (asid));
+  if (!buf)
+    {
+      _dbus_win_warn_win_error ("LocalAlloc failed", GetLastError ());
+      return FALSE;
+    }
+
+  memcpy (buf, asid, sizeof (asid));
+  *sid = buf;
+  return TRUE;
+}
+
+
+BOOL
+LookupAccountNameW (LPCWSTR lpSystemName, LPCWSTR lpAccountName, PSID Sid, PDWORD cbSid,
+                    LPWSTR ReferencedDomainName, PDWORD cchReferencedDomainName, PSID_NAME_USE peUse)
+{
+  /* Currently not needed.  */
+  return FALSE;
+}
+
+
+BOOL
+IsValidSid (PSID psid)
+{
+  /* Currently not needed.  */
+  return FALSE;
+}
+
+
+HANDLE
+CreateFileA (LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwSharedMode,
+	     LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+	     DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
+	     HANDLE hTemplateFile)
+{
+  wchar_t *filename;
+  HANDLE result;
+  int err;
+
+  filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
+  if (!filename)
+    return INVALID_HANDLE_VALUE;
+
+  result = CreateFileW (filename, dwDesiredAccess, dwSharedMode,
+			lpSecurityAttributes, dwCreationDisposition,
+			dwFlagsAndAttributes, hTemplateFile);
+
+  err = GetLastError ();
+  dbus_free (filename);
+  SetLastError (err);
+  return result;
+}
+
+
+BOOL
+DeleteFileA (LPCSTR lpFileName)
+{
+  wchar_t *filename;
+  BOOL result;
+  int err;
+
+  filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
+  if (!filename)
+    return FALSE;
+
+  result = DeleteFileW (filename);
+
+  err = GetLastError ();
+  dbus_free (filename);
+  SetLastError (err);
+  return result;
+}
+
+
+BOOL
+MoveFileA (LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
+{
+  wchar_t *existing_filename;
+  wchar_t *new_filename;
+  BOOL result;
+  int err;
+
+  existing_filename = _dbus_win_utf8_to_utf16 (lpExistingFileName, NULL);
+  if (! existing_filename)
+    return FALSE;
+
+  new_filename = _dbus_win_utf8_to_utf16 (lpNewFileName, NULL);
+  if (! new_filename)
+    {
+      dbus_free (existing_filename);
+      return FALSE;
+    }
+
+  result = MoveFileW (existing_filename, new_filename);
+
+  err = GetLastError ();
+  dbus_free (existing_filename);
+  dbus_free (new_filename);
+  SetLastError (err);
+  return result;
+}
+
+
+DWORD
+GetFileAttributesA(LPCSTR lpFileName)
+{
+  wchar_t *filename;
+  DWORD result;
+  int err;
+
+  filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
+  if (!filename)
+    return INVALID_FILE_ATTRIBUTES;
+
+  result = GetFileAttributesW (filename);
+
+  err = GetLastError ();
+  dbus_free (filename);
+  SetLastError (err);
+  return result;
+}
+
+
+BOOL
+GetFileAttributesExA (LPCSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId,
+                      PVOID lpFileInformation)
+{
+  wchar_t *filename;
+  DWORD result;
+  int err;
+
+  filename = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
+  if (!filename)
+    return INVALID_FILE_ATTRIBUTES;
+
+  result = GetFileAttributesExW (filename, fInfoLevelId, lpFileInformation);
+
+  err = GetLastError ();
+  dbus_free (filename);
+  SetLastError (err);
+  return result;
+}
+
+
+HANDLE
+CreateFileMappingA (HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes,
+		    DWORD flProtect, DWORD dwMaximumSizeHigh,
+		    DWORD dwMaximumSizeLow, LPCSTR lpName)
+{
+  wchar_t *name;
+  HANDLE result;
+  int err;
+
+  if (lpName)
+    {
+      name = _dbus_win_utf8_to_utf16 (lpName, NULL);
+      if (!name)
+	return INVALID_HANDLE_VALUE;
+    }
+  else
+    name = NULL;
+
+  result = CreateFileMappingW (hFile, lpAttributes, flProtect,
+			       dwMaximumSizeHigh, dwMaximumSizeLow,
+			       name);
+
+  err = GetLastError ();
+  dbus_free (name);
+  SetLastError (err);
+  return result;
+}
+
+
+BOOL
+CreateDirectoryA (LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
+{
+  wchar_t *pathname;
+  BOOL result;
+  int err;
+
+  pathname = _dbus_win_utf8_to_utf16 (lpPathName, NULL);
+  if (!pathname)
+    return FALSE;
+
+  result = CreateDirectoryW (pathname, lpSecurityAttributes);
+
+  err = GetLastError ();
+  dbus_free (pathname);
+  SetLastError (err);
+  return result;
+}
+
+
+BOOL
+RemoveDirectoryA (LPCSTR lpPathName)
+{
+  wchar_t *pathname;
+  BOOL result;
+  int err;
+
+  pathname = _dbus_win_utf8_to_utf16 (lpPathName, NULL);
+  if (!pathname)
+    return FALSE;
+
+  result = RemoveDirectoryW (pathname);
+
+  err = GetLastError ();
+  dbus_free (pathname);
+  SetLastError (err);
+  return result;
+}
+
+
+static BOOL
+convert_find_data (LPWIN32_FIND_DATAW fdw, LPWIN32_FIND_DATAA fda)
+{
+  char *filename;
+  int len;
+
+  fda->dwFileAttributes = fdw->dwFileAttributes;
+  fda->ftCreationTime = fdw->ftCreationTime;
+  fda->ftLastAccessTime = fdw->ftLastAccessTime;
+  fda->ftLastWriteTime = fdw->ftLastWriteTime;
+  fda->nFileSizeHigh = fdw->nFileSizeHigh;
+  fda->nFileSizeLow = fdw->nFileSizeLow;
+
+  filename = _dbus_win_utf16_to_utf8 (fdw->cFileName, NULL);
+  if (!filename)
+    return FALSE;
+
+  len = sizeof (fda->cFileName);
+  strncpy (fda->cFileName, filename, len);
+  fda->cFileName[len - 1] = '\0';
+  
+  return TRUE;
+}
+
+
+HANDLE
+FindFirstFileA (LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
+{
+  wchar_t *pathname;
+  WIN32_FIND_DATAW find_file_data;
+  HANDLE result;
+  int err;
+
+  pathname = _dbus_win_utf8_to_utf16 (lpFileName, NULL);
+  if (!pathname)
+    return INVALID_HANDLE_VALUE;
+
+  result = FindFirstFileW (pathname, &find_file_data);
+  if (result != INVALID_HANDLE_VALUE)
+    {
+      BOOL res = convert_find_data (&find_file_data, lpFindFileData);
+      if (! res)
+        {
+          err = GetLastError ();
+          FindClose (result);
+          SetLastError (err);
+          result = INVALID_HANDLE_VALUE;
+        }
+    }
+
+  err = GetLastError ();
+  dbus_free (pathname);
+  SetLastError (err);
+  return result;
+}
+
+
+BOOL
+FindNextFileA (HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
+{
+  WIN32_FIND_DATAW find_file_data;
+  BOOL result;
+  int err;
+
+  result = FindNextFileW (hFindFile, &find_file_data);
+  if (result)
+    result = convert_find_data (&find_file_data, lpFindFileData);
+
+  return result;  
+}
+
+
+HANDLE
+CreateMutexA (LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner,
+	      LPCSTR lpName)
+{
+  wchar_t *name;
+  HANDLE result;
+  int err;
+
+  if (lpName)
+    {
+      name = _dbus_win_utf8_to_utf16 (lpName, NULL);
+      if (!name)
+	return INVALID_HANDLE_VALUE;
+    }
+  else
+    name = NULL;
+
+  result = CreateMutexW (lpMutexAttributes, bInitialOwner, name);
+
+  err = GetLastError ();
+  dbus_free (name);
+  SetLastError (err);
+  return result;
+}
+
+
+BOOL
+CreateProcessA (LPCSTR pszImageName, LPSTR pszCmdLine,
+                LPSECURITY_ATTRIBUTES psaProcess,
+                LPSECURITY_ATTRIBUTES psaThread, BOOL fInheritHandles,
+                DWORD fdwCreate, PVOID pvEnvironment, LPCSTR pszCurDir,
+                LPSTARTUPINFOA psiStartInfo,
+                LPPROCESS_INFORMATION pProcInfo)
+{
+  wchar_t *image_name = NULL;
+  wchar_t *cmd_line = NULL;
+  BOOL result;
+  int err;
+
+  _dbus_assert (psaProcess == NULL);
+  _dbus_assert (psaThread == NULL);
+  _dbus_assert (fInheritHandles == FALSE);
+  _dbus_assert (pvEnvironment == NULL);
+  _dbus_assert (pszCurDir == NULL);
+  /* psiStartInfo is generally not NULL.  */
+
+  if (pszImageName)
+    {
+      image_name = _dbus_win_utf8_to_utf16 (pszImageName, NULL);
+      if (!image_name)
+	return 0;
+    }
+  if (pszCmdLine)
+    {
+      cmd_line = _dbus_win_utf8_to_utf16 (pszCmdLine, NULL);
+      if (!cmd_line)
+        {
+          if (image_name)
+            dbus_free (image_name);
+          return 0;
+        }
+    }
+
+  result = CreateProcessW (image_name, cmd_line, NULL, NULL, FALSE,
+                           fdwCreate, NULL, NULL, NULL, pProcInfo);
+
+  err = GetLastError ();
+  dbus_free (image_name);
+  dbus_free (cmd_line);
+  SetLastError (err);
+  return result;
+}
+
+
+LONG
+RegOpenKeyExA (HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions,
+               REGSAM samDesired, PHKEY phkResult)
+{
+  wchar_t *subkey;
+  LONG result;
+  int err;
+
+  if (lpSubKey)
+    {
+      subkey = _dbus_win_utf8_to_utf16 (lpSubKey, NULL);
+      if (!subkey)
+	return 0;
+    }
+  else
+    subkey = NULL;
+
+  result = RegOpenKeyEx (hKey, subkey, ulOptions, samDesired, phkResult);
+
+  err = GetLastError ();
+  dbus_free (subkey);
+  SetLastError (err);
+  return result;
+}
+
+
+LONG
+RegQueryValueExA (HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved,
+                  LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
+{
+  wchar_t *name;
+  LONG err;
+  BYTE *data;
+  DWORD data_len;
+  DWORD type;
+
+  if (lpValueName)
+    {
+      name = _dbus_win_utf8_to_utf16 (lpValueName, NULL);
+      if (!name)
+	return GetLastError ();
+    }
+  else
+    name = NULL;
+
+  data_len = 0;
+  err = RegQueryValueExW (hKey, name, lpReserved, lpType, NULL, &data_len);
+  if (err || !lpcbData)
+    {
+      dbus_free (name);
+      return err;
+    }
+
+  data = malloc (data_len + sizeof (wchar_t));
+  if (!data)
+    {
+      dbus_free (name);
+      return ERROR_NOT_ENOUGH_MEMORY;
+    }
+  
+  err = RegQueryValueExW (hKey, name, lpReserved, &type, data, &data_len);
+  if (lpType)
+    *lpType = type;
+  dbus_free (name);
+  /* If err is ERROR_MORE_DATA, there probably was a race condition.
+     We can punt this to the caller just as well.  */
+  if (err)
+    {
+      free (data);
+      return err;
+    }
+
+  /* NOTE: REG_MULTI_SZ and REG_EXPAND_SZ not supported, because they
+     are not needed in this module.  */
+  if (type == REG_SZ)
+    {
+      char *data_c;
+      int data_c_len;
+
+      /* This is valid since we allocated one more above.  */
+      data[data_len] = '\0';
+      data[data_len + 1] = '\0';
+
+      /* The cast is valid because malloc guarantees alignment of
+         basic types.  */
+      data_c = _dbus_win_utf16_to_utf8 ((wchar_t*) data, NULL);
+      if (!data_c)
+        {
+          free (data);
+          return GetLastError();
+        }
+
+      data_c_len = strlen (data_c) + 1;
+      _dbus_assert (data_c_len <= data_len + sizeof (wchar_t));
+      memcpy (data, data_c, data_c_len);
+      data_len = data_c_len;
+      dbus_free (data_c);
+    }
+
+  /* DATA and DATA_LEN now contain the result.  */
+  if (lpData)
+    {
+      if (data_len > *lpcbData)
+        err = ERROR_MORE_DATA;
+      else
+        memcpy (lpData, data, data_len);
+    }
+  free (data);
+  *lpcbData = data_len;
+  return err;
+}
+
+
+DWORD
+FormatMessageA (DWORD dwFlags, PCVOID lpSource, DWORD dwMessageId,
+		DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize,
+		va_list* Arguments)
+{
+  LPWSTR buffer_w = NULL;
+  LPSTR buffer_c;
+  DWORD len;
+  char *buffer_new;
+  DWORD buffer_new_len;
+  BOOL buffer_w_free;
+
+  len = FormatMessageW (dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+			lpSource, dwMessageId, dwLanguageId,
+			(LPWSTR) &buffer_w, 0, Arguments);
+  if (len == 0)
+    return 0;
+
+  buffer_c = _dbus_win_utf16_to_utf8 (buffer_w, NULL);
+  if (! buffer_c)
+    {
+      LocalFree (buffer_w);
+      return 0;
+    }
+
+  if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
+    {
+      /* We need to return a buffer that's freeable with LocalFree.  */
+      buffer_new = (char *) buffer_w;
+      buffer_new_len = sizeof (wchar_t) * (len + 1);
+      buffer_w_free = FALSE;
+      /* Avoid alignment issue by using memcpy.  */
+      memcpy (lpBuffer, &buffer_new, sizeof (buffer_new));
+    }
+  else
+    {
+      buffer_new = lpBuffer;
+      buffer_new_len = nSize;
+      buffer_w_free = TRUE;
+    }
+
+  strncpy (buffer_new, buffer_c, buffer_new_len);
+  dbus_free (buffer_c);
+  buffer_new[buffer_new_len - 1] = '\0';
+  if (buffer_w_free)
+    LocalFree (buffer_w);
+
+  /* strlen is correct (not _mbstrlen), because we want storage and
+     not string length.  */
+  return strlen (buffer_new);
+}
+
+
+DWORD
+GetModuleFileNameA (HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
+{
+  wchar_t *filename_w;
+  char *filename_c;
+  DWORD len;
+
+  if (nSize == 0)
+    {
+      /* Windows XP/2000.  */
+      SetLastError (0);
+      return 0;
+    }
+
+  filename_w = malloc (sizeof (wchar_t) * nSize);
+  if (! filename_w)
+    return 0;
+
+  len = GetModuleFileNameW (hModule, filename_w, nSize);
+  if (len == 0)
+    {
+      /* Note: If we fail with ERROR_INSUFFICIENT_BUFFER, this is still
+       (approximately) correct.  */
+      free (filename_w);
+      return 0;
+    }
+
+  filename_w[nSize - 1] = '\0';
+  filename_c = _dbus_win_utf16_to_utf8 (filename_w, NULL);
+  free (filename_w);
+  if (! filename_c)
+    return 0;
+
+  strncpy (lpFilename, filename_c, nSize);
+  dbus_free (filename_c);
+  lpFilename[nSize - 1] = '\0';
+  /* strlen is correct (not _mbstrlen), because we want storage and
+     not string length.  */
+  return strlen (lpFilename);
+}
+
+
+DWORD
+GetTempPathA (DWORD nBufferLength, LPSTR lpBuffer)
+{
+  wchar_t dummy[1];
+  DWORD len;
+
+  len = GetTempPathW (0, dummy);
+  if (len == 0)
+    return 0;
+
+  _dbus_assert (len <= MAX_PATH);
+
+  /* Better be safe than sorry.  MSDN doesn't say if len is with or
+     without terminating 0.  */
+  len++;
+
+  {
+    wchar_t *buffer_w;
+    DWORD len_w;
+    char *buffer_c;
+    DWORD len_c;
+
+    buffer_w = malloc (sizeof (wchar_t) * len);
+    if (! buffer_w)
+      return 0;
+
+    len_w = GetTempPathW (len, buffer_w);
+    /* Give up if we still can't get at it.  */
+    if (len_w == 0 || len_w >= len)
+      {
+        free (buffer_w);
+        return 0;
+      }
+
+    /* Better be really safe.  */
+    buffer_w[len_w] = '\0';
+
+    buffer_c = _dbus_win_utf16_to_utf8 (buffer_w, NULL);
+    free (buffer_w);
+    if (! buffer_c)
+      return 0;
+
+    /* strlen is correct (not _mbstrlen), because we want storage and
+       not string length.  */
+    len_c = strlen (buffer_c) + 1;
+    if (len_c > nBufferLength)
+      return len_c;
+
+    strcpy (lpBuffer, buffer_c);
+    dbus_free (buffer_c);
+    return len_c - 1;
+  }
+}
+
+
+BOOL
+SHGetSpecialFolderPathA (HWND hwndOwner, LPSTR lpszPath, int nFolder,
+                         BOOL fCreate)
+{
+  wchar_t path[MAX_PATH];
+  char *path_c;
+  BOOL result;
+
+  path[0] = (wchar_t) 0;
+  result = SHGetSpecialFolderPathW (hwndOwner, path, nFolder, fCreate);
+  /* Note: May return false even if succeeds.  */
+
+  path[MAX_PATH - 1] = (wchar_t) 0;
+  path_c = _dbus_win_utf16_to_utf8 (path, NULL);
+  if (! path_c)
+    return 0;
+  
+  strncpy (lpszPath, path_c, MAX_PATH);
+  dbus_free (path_c);
+  lpszPath[MAX_PATH - 1] = '\0';
+  return result;
+}
+
+
+void
+OutputDebugStringA (LPCSTR lpOutputString)
+{
+  wchar_t *str;
+  HANDLE result;
+  int err;
+
+  str = _dbus_win_utf8_to_utf16 (lpOutputString, NULL);
+  if (!str)
+    return;
+
+  OutputDebugStringW (str);
+
+  err = GetLastError ();
+  dbus_free (str);
+  SetLastError (err);
+}
diff --git a/dbus/dbus/dbus-sysdeps-wince-glue.h b/dbus/dbus/dbus-sysdeps-wince-glue.h
new file mode 100644
index 0000000..f5ac6c8
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps-wince-glue.h
@@ -0,0 +1,246 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps-wince-glue.h Emulation of system/libc features for Windows CE (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_SYSDEPS_WINCE_GLUE_H
+#define DBUS_SYSDEPS_WINCE_GLUE_H
+
+#include <time.h>
+#include <stdarg.h>
+
+/* For getaddrinfo, configure/cmake defined _WIN32_WCE to something >= 0x0401.  */
+#include <windows.h>
+#undef interface
+
+DBUS_BEGIN_DECLS
+
+/* shlobj.h declares these only for _WIN32_IE that we don't want to define.
+   In any case, with mingw32ce we only get a SHGetSpecialFolderPath.  */
+#define SHGetSpecialFolderPathW SHGetSpecialFolderPath
+BOOL WINAPI SHGetSpecialFolderPathA(HWND,LPSTR,int,BOOL);
+BOOL WINAPI SHGetSpecialFolderPathW(HWND,LPWSTR,int,BOOL);
+
+#ifndef TLS_OUT_OF_INDEXES
+#define TLS_OUT_OF_INDEXES 0xffffffff
+#endif
+
+
+/* Seriously.  Windows CE does not have errno.  Don't you hate it when
+   that happens?  */
+#define errno ((int)GetLastError ())
+
+#define ENOENT          ERROR_FILE_NOT_FOUND
+#define EMFILE          ERROR_TOO_MANY_OPEN_FILES
+#define EACCES          ERROR_ACCESS_DENIED
+#define EBADF           ERROR_INVALID_HANDLE
+#define ENOMEM          ERROR_NOT_ENOUGH_MEMORY
+#define EXDEV           ERROR_NOT_SAME_DEVICE
+#define ENFILE          ERROR_NO_MORE_FILES
+#define EROFS           ERROR_WRITE_PROTECT
+#define ENOLCK          ERROR_SHARING_BUFFER_EXCEEDED
+#define ENOSYS          ERROR_NOT_SUPPORTED
+#define EEXIST          ERROR_FILE_EXISTS
+#define EPERM           ERROR_CANNOT_MAKE
+#define EINVAL          ERROR_INVALID_PARAMETER
+#define EINTR           ERROR_INVALID_AT_INTERRUPT_TIME
+#define EPIPE           ERROR_BROKEN_PIPE
+#define ENOSPC          ERROR_DISK_FULL
+#define ENOTEMPTY       ERROR_DIR_NOT_EMPTY
+#define EBUSY           ERROR_BUSY
+#define ENAMETOOLONG    ERROR_FILENAME_EXCED_RANGE
+#define EAGAIN          ERROR_MORE_DATA
+#define ENOTDIR         ERROR_DIRECTORY
+#define ERANGE          ERROR_ARITHMETIC_OVERFLOW
+#define ENXIO           ERROR_FILE_INVALID
+#define EFAULT          ERROR_PROCESS_ABORTED
+#define EIO             ERROR_IO_DEVICE
+#define EDEADLOCK       ERROR_POSSIBLE_DEADLOCK
+#define ENODEV          ERROR_BAD_DEVICE
+
+/* Windows CE is missing more stuff that is pretty standard.  */
+
+#define strdup _strdup
+#define stricmp _stricmp
+#define strnicmp _strnicmp
+
+#define environ _dbus_wince_environ
+extern char *environ[];
+
+#define getenv _dbus_wince_getenv
+char *getenv (const char *name);
+
+#define putenv _dbus_wince_putenv
+int putenv (char *str);
+
+#define clock _dbus_wince_clock
+clock_t clock (void);
+
+#define abort _dbus_wince_abort
+void abort (void);
+
+#define _S_IFMT         0170000         /* file type mask */
+#define _S_IFDIR        0040000         /* directory */
+#define _S_IFCHR        0020000         /* character special */
+#define _S_IFIFO        0010000         /* pipe */
+#define _S_IFREG        0100000         /* regular */
+#define _S_IREAD        0000400         /* read permission, owner */
+#define _S_IWRITE       0000200         /* write permission, owner */
+#define _S_IEXEC        0000100         /* execute/search permission, owner */
+
+#ifndef __OFF_T_DEFINED
+typedef long off_t;
+#define __OFF_T_DEFINED
+#endif
+#ifndef _INTPTR_T_DEFINED
+typedef int intptr_t;
+#define _INTPTR_T_DEFINED
+#endif
+#ifndef _UINTPTR_T_DEFINED
+typedef unsigned int uintptr_t;
+#define _UINTPTR_T_DEFINED
+#endif
+
+#ifndef _MAX_FNAME
+#define _MAX_FNAME 256
+#endif
+
+#ifndef _IOFBF
+#define _IOFBF	0
+#endif
+#ifndef _IOLBF
+#define _IOLBF	1
+#endif
+#ifndef _IONBF
+#define _IONBF	2
+#endif
+
+
+/* Windows CE is missing some Windows functions that we want.  */
+
+#define GetSystemTimeAsFileTime _dbus_wince_GetSystemTimeAsFileTime
+void GetSystemTimeAsFileTime (LPFILETIME ftp);
+
+#define _mbsrchr _dbus_wince_mbsrchr
+unsigned char* _mbsrchr (const unsigned char*, unsigned int);
+
+#define OpenFileMappingA _dbus_wince_OpenFileMappingA
+HANDLE OpenFileMappingA(DWORD,BOOL,LPCSTR);
+
+#define MoveFileExA _dbus_wince_MoveFileExA
+BOOL MoveFileExA(LPCSTR,LPCSTR,DWORD);
+#ifndef MOVEFILE_REPLACE_EXISTING
+#define MOVEFILE_REPLACE_EXISTING 0x00000001
+#endif
+
+#define SetHandleInformation _dbus_wince_SetHandleInformation
+BOOL SetHandleInformation(HANDLE,DWORD,DWORD);
+#ifndef HANDLE_FLAG_INHERIT
+#define HANDLE_FLAG_INHERIT 0x01
+#endif
+#ifndef HANDLE_FLAG_PROTECT
+#define HANDLE_FLAG_PROTECT_FROM_CLOSE 0x02
+#endif
+
+#define SearchPathA _dbus_wince_SearchPathA
+DWORD SearchPathA(LPCSTR,LPCSTR,LPCSTR,DWORD,LPSTR,LPSTR*);
+
+/* Instead of emulating all functions needed for this, we replace the
+   whole thing.  */
+dbus_bool_t _dbus_getsid(char **sid);
+
+
+#define LookupAccountNameW _dbus_wince_LookupAccountNameW
+BOOL LookupAccountNameW(LPCWSTR,LPCWSTR,PSID,PDWORD,LPWSTR,PDWORD,PSID_NAME_USE);
+
+#define IsValidSid _dbus_wince_IsValidSid
+BOOL IsValidSid(PSID);
+
+
+/* Windows CE does only have the UNICODE interfaces (FooW), but we
+   want to use the ASCII interfaces (FooA).  We implement them
+   here.  */
+
+#define CreateFileA _dbus_wince_CreateFileA
+HANDLE CreateFileA(LPCSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE);
+
+#define DeleteFileA _dbus_wince_DeleteFileA
+BOOL DeleteFileA(LPCSTR);
+
+#define GetFileAttributesA _dbus_wince_GetFileAttributesA
+DWORD GetFileAttributesA(LPCSTR);
+
+#define GetFileAttributesExA _dbus_wince_GetFileAttributesExA
+BOOL GetFileAttributesExA(LPCSTR,GET_FILEEX_INFO_LEVELS,PVOID);
+
+#define CreateFileMappingA _dbus_wince_CreateFileMappingA
+HANDLE CreateFileMappingA(HANDLE,LPSECURITY_ATTRIBUTES,DWORD,DWORD,DWORD,LPCSTR);
+
+#define CreateDirectoryA _dbus_wince_CreateDirectoryA
+BOOL CreateDirectoryA(LPCSTR,LPSECURITY_ATTRIBUTES);
+
+#define RemoveDirectoryA _dbus_wince_RemoveDirectoryA
+BOOL RemoveDirectoryA(LPCSTR);
+
+#define FindFirstFileA _dbus_wince_FindFirstFileA
+HANDLE FindFirstFileA(LPCSTR,LPWIN32_FIND_DATAA);
+
+#define FindNextFileA _dbus_wince_FindNextFileA
+BOOL FindNextFileA(HANDLE,LPWIN32_FIND_DATAA);
+
+#define CreateMutexA _dbus_wince_CreateMutexA
+HANDLE CreateMutexA(LPSECURITY_ATTRIBUTES,BOOL,LPCSTR);
+
+#define CreateProcessA _dbus_wince_CreateProcessA
+BOOL CreateProcessA(LPCSTR,LPSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,PVOID,LPCSTR,LPSTARTUPINFOA,LPPROCESS_INFORMATION);
+#ifndef CREATE_NO_WINDOW
+#define CREATE_NO_WINDOW 0x08000000
+#endif
+
+
+#define RegOpenKeyExA _dbus_wince_RegOpenKeyExA
+LONG RegOpenKeyExA(HKEY,LPCSTR,DWORD,REGSAM,PHKEY);
+
+#define RegQueryValueExA _dbus_wince_RegQueryValueExA
+LONG WINAPI RegQueryValueExA(HKEY,LPCSTR,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
+
+
+#define FormatMessageA _dbus_wince_FormatMessageA
+DWORD FormatMessageA(DWORD,PCVOID,DWORD,DWORD,LPSTR,DWORD,va_list*);
+
+#define GetModuleFileNameA _dbus_wince_GetModuleFileNameA
+DWORD GetModuleFileNameA(HINSTANCE,LPSTR,DWORD);
+
+#define GetTempPathA _dbus_wince_GetTempPathA
+DWORD GetTempPathA(DWORD,LPSTR);
+
+#define SHGetSpecialFolderPathA _dbus_wince_SHGetSpecialFolderPathA
+BOOL SHGetSpecialFolderPathA(HWND,LPSTR,int,BOOL);
+
+
+#define OutputDebugStringA _dbus_wince_OutputDebugStringA
+void OutputDebugStringA(LPCSTR);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_SYSDEPS_WINCE_GLUE_H */
diff --git a/dbus/dbus/dbus-sysdeps.c b/dbus/dbus/dbus-sysdeps.c
new file mode 100644
index 0000000..04fb8d7
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps.c
@@ -0,0 +1,774 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps.c Wrappers around system/libc features shared between UNIX and Windows (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-sysdeps.h"
+#include "dbus-threads.h"
+#include "dbus-protocol.h"
+#include "dbus-string.h"
+#include "dbus-list.h"
+
+/* NOTE: If you include any unix/windows-specific headers here, you are probably doing something
+ * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c.
+ *
+ * These are the standard ANSI C headers...
+ */
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+_DBUS_DEFINE_GLOBAL_LOCK (win_fds);
+_DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache);
+_DBUS_DEFINE_GLOBAL_LOCK (system_users);
+
+#ifdef DBUS_WIN
+  #include <stdlib.h>
+#elif (defined __APPLE__)
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+#else
+extern char **environ;
+#endif
+
+/**
+ * @defgroup DBusSysdeps Internal system-dependent API
+ * @ingroup DBusInternals
+ * @brief Internal system-dependent API available on UNIX and Windows
+ *
+ * The system-dependent API has a dual purpose. First, it encapsulates
+ * all usage of operating system APIs for ease of auditing and to
+ * avoid cluttering the rest of the code with bizarre OS quirks and
+ * headers. Second, it abstracts different operating system APIs for
+ * portability.
+ * 
+ * @{
+ */
+
+/**
+ * Aborts the program with SIGABRT (dumping core).
+ */
+void
+_dbus_abort (void)
+{
+  const char *s;
+  
+  _dbus_print_backtrace ();
+  
+  s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
+  if (s && *s)
+    {
+      /* don't use _dbus_warn here since it can _dbus_abort() */
+      fprintf (stderr, "  Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
+      _dbus_sleep_milliseconds (1000 * 180);
+    }
+  
+  abort ();
+  _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
+}
+
+/**
+ * Wrapper for setenv(). If the value is #NULL, unsets
+ * the environment variable.
+ *
+ * There is an unfixable memleak in that it is unsafe to
+ * free memory malloced for use with setenv. This is because
+ * we can not rely on internal implementation details of
+ * the underlying libc library.
+ *
+ * @param varname name of environment variable
+ * @param value value of environment variable
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_setenv (const char *varname,
+              const char *value)
+{
+  _dbus_assert (varname != NULL);
+  
+  if (value == NULL)
+    {
+#ifdef HAVE_UNSETENV
+      unsetenv (varname);
+      return TRUE;
+#else
+      char *putenv_value;
+      size_t len;
+
+      len = strlen (varname);
+
+      /* Use system malloc to avoid memleaks that dbus_malloc
+       * will get upset about.
+       */
+      
+      putenv_value = malloc (len + 2);
+      if (putenv_value == NULL)
+        return FALSE;
+
+      strcpy (putenv_value, varname);
+#if defined(DBUS_WIN)
+      strcat (putenv_value, "=");
+#endif
+      
+      return (putenv (putenv_value) == 0);
+#endif
+    }
+  else
+    {
+#ifdef HAVE_SETENV
+      return (setenv (varname, value, TRUE) == 0);
+#else
+      char *putenv_value;
+      size_t len;
+      size_t varname_len;
+      size_t value_len;
+
+      varname_len = strlen (varname);
+      value_len = strlen (value);
+      
+      len = varname_len + value_len + 1 /* '=' */ ;
+
+      /* Use system malloc to avoid memleaks that dbus_malloc
+       * will get upset about.
+       */
+      
+      putenv_value = malloc (len + 1);
+      if (putenv_value == NULL)
+        return FALSE;
+
+      strcpy (putenv_value, varname);
+      strcpy (putenv_value + varname_len, "=");
+      strcpy (putenv_value + varname_len + 1, value);
+      
+      return (putenv (putenv_value) == 0);
+#endif
+    }
+}
+
+/**
+ * Wrapper for getenv().
+ *
+ * @param varname name of environment variable
+ * @returns value of environment variable or #NULL if unset
+ */
+const char*
+_dbus_getenv (const char *varname)
+{  
+  /* Don't respect any environment variables if the current process is
+   * setuid.  This is the equivalent of glibc's __secure_getenv().
+   */
+  if (_dbus_check_setuid ())
+    return NULL;
+  return getenv (varname);
+}
+
+/**
+ * Wrapper for clearenv().
+ *
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_clearenv (void)
+{
+  dbus_bool_t rc = TRUE;
+
+#ifdef HAVE_CLEARENV
+  if (clearenv () != 0)
+     rc = FALSE;
+#else
+
+  if (environ != NULL)
+    environ[0] = NULL;
+#endif
+
+  return rc;
+}
+
+/**
+ * Split paths into a list of char strings
+ * 
+ * @param dirs string with pathes 
+ * @param suffix string concated to each path in dirs
+ * @param dir_list contains a list of splitted pathes
+ * return #TRUE is pathes could be splittes,#FALSE in oom case 
+ */
+dbus_bool_t
+_dbus_split_paths_and_append (DBusString *dirs, 
+                              const char *suffix, 
+                              DBusList  **dir_list)
+{
+   int start;
+   int i;
+   int len;
+   char *cpath;
+   DBusString file_suffix;
+
+   start = 0;
+   i = 0;
+
+   _dbus_string_init_const (&file_suffix, suffix);
+
+   len = _dbus_string_get_length (dirs);
+
+   while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
+     {
+       DBusString path;
+
+       if (!_dbus_string_init (&path))
+          goto oom;
+
+       if (!_dbus_string_copy_len (dirs,
+                                   start,
+                                   i - start,
+                                   &path,
+                                   0))
+          {
+            _dbus_string_free (&path);
+            goto oom;
+          }
+
+        _dbus_string_chop_white (&path);
+
+        /* check for an empty path */
+        if (_dbus_string_get_length (&path) == 0)
+          goto next;
+
+        if (!_dbus_concat_dir_and_file (&path,
+                                        &file_suffix))
+          {
+            _dbus_string_free (&path);
+            goto oom;
+          }
+
+        if (!_dbus_string_copy_data(&path, &cpath))
+          {
+            _dbus_string_free (&path);
+            goto oom;
+          }
+
+        if (!_dbus_list_append (dir_list, cpath))
+          {
+            _dbus_string_free (&path);              
+            dbus_free (cpath);
+            goto oom;
+          }
+
+       next:
+        _dbus_string_free (&path);
+        start = i + 1;
+    } 
+      
+  if (start != len)
+    { 
+      DBusString path;
+
+      if (!_dbus_string_init (&path))
+        goto oom;
+
+      if (!_dbus_string_copy_len (dirs,
+                                  start,
+                                  len - start,
+                                  &path,
+                                  0))
+        {
+          _dbus_string_free (&path);
+          goto oom;
+        }
+
+      if (!_dbus_concat_dir_and_file (&path,
+                                      &file_suffix))
+        {
+          _dbus_string_free (&path);
+          goto oom;
+        }
+
+      if (!_dbus_string_copy_data(&path, &cpath))
+        {
+          _dbus_string_free (&path);
+          goto oom;
+        }
+
+      if (!_dbus_list_append (dir_list, cpath))
+        {
+          _dbus_string_free (&path);              
+          dbus_free (cpath);
+          goto oom;
+        }
+
+      _dbus_string_free (&path); 
+    }
+
+  return TRUE;
+
+ oom:
+  _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 
+  _dbus_list_clear (dir_list);
+  return FALSE;
+}
+
+/** @} */
+
+/**
+ * @addtogroup DBusString
+ *
+ * @{
+ */
+/**
+ * Appends an integer to a DBusString.
+ * 
+ * @param str the string
+ * @param value the integer value
+ * @returns #FALSE if not enough memory or other failure.
+ */
+dbus_bool_t
+_dbus_string_append_int (DBusString *str,
+                         long        value)
+{
+  /* this calculation is from comp.lang.c faq */
+#define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
+  int orig_len;
+  int i;
+  char *buf;
+  
+  orig_len = _dbus_string_get_length (str);
+
+  if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
+    return FALSE;
+
+  buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
+
+  snprintf (buf, MAX_LONG_LEN, "%ld", value);
+
+  i = 0;
+  while (*buf)
+    {
+      ++buf;
+      ++i;
+    }
+  
+  _dbus_string_shorten (str, MAX_LONG_LEN - i);
+  
+  return TRUE;
+}
+
+/**
+ * Appends an unsigned integer to a DBusString.
+ * 
+ * @param str the string
+ * @param value the integer value
+ * @returns #FALSE if not enough memory or other failure.
+ */
+dbus_bool_t
+_dbus_string_append_uint (DBusString    *str,
+                          unsigned long  value)
+{
+  /* this is wrong, but definitely on the high side. */
+#define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
+  int orig_len;
+  int i;
+  char *buf;
+  
+  orig_len = _dbus_string_get_length (str);
+
+  if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
+    return FALSE;
+
+  buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
+
+  snprintf (buf, MAX_ULONG_LEN, "%lu", value);
+
+  i = 0;
+  while (*buf)
+    {
+      ++buf;
+      ++i;
+    }
+  
+  _dbus_string_shorten (str, MAX_ULONG_LEN - i);
+  
+  return TRUE;
+}
+
+/**
+ * Parses an integer contained in a DBusString. Either return parameter
+ * may be #NULL if you aren't interested in it. The integer is parsed
+ * and stored in value_return. Return parameters are not initialized
+ * if the function returns #FALSE.
+ *
+ * @param str the string
+ * @param start the byte index of the start of the integer
+ * @param value_return return location of the integer value or #NULL
+ * @param end_return return location of the end of the integer, or #NULL
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_string_parse_int (const DBusString *str,
+                        int               start,
+                        long             *value_return,
+                        int              *end_return)
+{
+  long v;
+  const char *p;
+  char *end;
+
+  p = _dbus_string_get_const_data_len (str, start,
+                                       _dbus_string_get_length (str) - start);
+
+  end = NULL;
+  _dbus_set_errno_to_zero ();
+  v = strtol (p, &end, 0);
+  if (end == NULL || end == p || errno != 0)
+    return FALSE;
+
+  if (value_return)
+    *value_return = v;
+  if (end_return)
+    *end_return = start + (end - p);
+
+  return TRUE;
+}
+
+/**
+ * Parses an unsigned integer contained in a DBusString. Either return
+ * parameter may be #NULL if you aren't interested in it. The integer
+ * is parsed and stored in value_return. Return parameters are not
+ * initialized if the function returns #FALSE.
+ *
+ * @param str the string
+ * @param start the byte index of the start of the integer
+ * @param value_return return location of the integer value or #NULL
+ * @param end_return return location of the end of the integer, or #NULL
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_string_parse_uint (const DBusString *str,
+                         int               start,
+                         unsigned long    *value_return,
+                         int              *end_return)
+{
+  unsigned long v;
+  const char *p;
+  char *end;
+
+  p = _dbus_string_get_const_data_len (str, start,
+                                       _dbus_string_get_length (str) - start);
+
+  end = NULL;
+  _dbus_set_errno_to_zero ();
+  v = strtoul (p, &end, 0);
+  if (end == NULL || end == p || errno != 0)
+    return FALSE;
+
+  if (value_return)
+    *value_return = v;
+  if (end_return)
+    *end_return = start + (end - p);
+
+  return TRUE;
+}
+
+/** @} */ /* DBusString group */
+
+/**
+ * @addtogroup DBusInternalsUtils
+ * @{
+ */
+
+void
+_dbus_generate_pseudorandom_bytes_buffer (char *buffer,
+                                          int   n_bytes)
+{
+  long tv_usec;
+  int i;
+  
+  /* fall back to pseudorandom */
+  _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
+                 n_bytes);
+  
+  _dbus_get_real_time (NULL, &tv_usec);
+  srand (tv_usec);
+  
+  i = 0;
+  while (i < n_bytes)
+    {
+      double r;
+      unsigned int b;
+          
+      r = rand ();
+      b = (r / (double) RAND_MAX) * 255.0;
+
+      buffer[i] = b;
+
+      ++i;
+    }
+}
+
+/**
+ * Fills n_bytes of the given buffer with random bytes.
+ *
+ * @param buffer an allocated buffer
+ * @param n_bytes the number of bytes in buffer to write to
+ */
+void
+_dbus_generate_random_bytes_buffer (char *buffer,
+                                    int   n_bytes)
+{
+  DBusString str;
+
+  if (!_dbus_string_init (&str))
+    {
+      _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
+      return;
+    }
+
+  if (!_dbus_generate_random_bytes (&str, n_bytes))
+    {
+      _dbus_string_free (&str);
+      _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
+      return;
+    }
+
+  _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
+
+  _dbus_string_free (&str);
+}
+
+/**
+ * Generates the given number of random bytes, where the bytes are
+ * chosen from the alphanumeric ASCII subset.
+ *
+ * @param str the string
+ * @param n_bytes the number of random ASCII bytes to append to string
+ * @returns #TRUE on success, #FALSE if no memory or other failure
+ */
+dbus_bool_t
+_dbus_generate_random_ascii (DBusString *str,
+                             int         n_bytes)
+{
+  static const char letters[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
+  int i;
+  int len;
+  
+  if (!_dbus_generate_random_bytes (str, n_bytes))
+    return FALSE;
+  
+  len = _dbus_string_get_length (str);
+  i = len - n_bytes;
+  while (i < len)
+    {
+      _dbus_string_set_byte (str, i,
+                             letters[_dbus_string_get_byte (str, i) %
+                                     (sizeof (letters) - 1)]);
+
+      ++i;
+    }
+
+  _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
+                                             n_bytes));
+
+  return TRUE;
+}
+
+/**
+ * Converts a UNIX errno, or Windows errno or WinSock error value into
+ * a #DBusError name.
+ *
+ * @todo should cover more errnos, specifically those
+ * from open().
+ * 
+ * @param error_number the errno.
+ * @returns an error name
+ */
+const char*
+_dbus_error_from_errno (int error_number)
+{
+  switch (error_number)
+    {
+    case 0:
+      return DBUS_ERROR_FAILED;
+      
+#ifdef EPROTONOSUPPORT
+    case EPROTONOSUPPORT:
+      return DBUS_ERROR_NOT_SUPPORTED;
+#elif defined(WSAEPROTONOSUPPORT)
+    case WSAEPROTONOSUPPORT:
+      return DBUS_ERROR_NOT_SUPPORTED;
+#endif
+#ifdef EAFNOSUPPORT
+    case EAFNOSUPPORT:
+      return DBUS_ERROR_NOT_SUPPORTED;
+#elif defined(WSAEAFNOSUPPORT)
+    case WSAEAFNOSUPPORT:
+      return DBUS_ERROR_NOT_SUPPORTED;
+#endif
+#ifdef ENFILE
+    case ENFILE:
+      return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
+#endif
+#ifdef EMFILE
+    case EMFILE:
+      return DBUS_ERROR_LIMITS_EXCEEDED;
+#endif
+#ifdef EACCES
+    case EACCES:
+      return DBUS_ERROR_ACCESS_DENIED;
+#endif
+#ifdef EPERM
+    case EPERM:
+      return DBUS_ERROR_ACCESS_DENIED;
+#endif
+#ifdef ENOBUFS
+    case ENOBUFS:
+      return DBUS_ERROR_NO_MEMORY;
+#endif
+#ifdef ENOMEM
+    case ENOMEM:
+      return DBUS_ERROR_NO_MEMORY;
+#endif
+#ifdef ECONNREFUSED
+    case ECONNREFUSED:
+      return DBUS_ERROR_NO_SERVER;
+#elif defined(WSAECONNREFUSED)
+    case WSAECONNREFUSED:
+      return DBUS_ERROR_NO_SERVER;
+#endif
+#ifdef ETIMEDOUT
+    case ETIMEDOUT:
+      return DBUS_ERROR_TIMEOUT;
+#elif defined(WSAETIMEDOUT)
+    case WSAETIMEDOUT:
+      return DBUS_ERROR_TIMEOUT;
+#endif
+#ifdef ENETUNREACH
+    case ENETUNREACH:
+      return DBUS_ERROR_NO_NETWORK;
+#elif defined(WSAENETUNREACH)
+    case WSAENETUNREACH:
+      return DBUS_ERROR_NO_NETWORK;
+#endif
+#ifdef EADDRINUSE
+    case EADDRINUSE:
+      return DBUS_ERROR_ADDRESS_IN_USE;
+#elif defined(WSAEADDRINUSE)
+    case WSAEADDRINUSE:
+      return DBUS_ERROR_ADDRESS_IN_USE;
+#endif
+#ifdef EEXIST
+    case EEXIST:
+      return DBUS_ERROR_FILE_EXISTS;
+#endif
+#ifdef ENOENT
+    case ENOENT:
+      return DBUS_ERROR_FILE_NOT_FOUND;
+#endif
+    }
+
+  return DBUS_ERROR_FAILED;
+}
+
+/**
+ * Converts the current system errno value into a #DBusError name.
+ *
+ * @returns an error name
+ */
+const char*
+_dbus_error_from_system_errno (void)
+{
+  return _dbus_error_from_errno (errno);
+}
+
+/**
+ * Assign 0 to the global errno variable
+ */
+void
+_dbus_set_errno_to_zero (void)
+{
+#ifdef DBUS_WINCE
+  SetLastError (0);
+#else
+  errno = 0;
+#endif
+}
+
+/**
+ * See if errno is set
+ * @returns #TRUE if errno is not 0
+ */
+dbus_bool_t
+_dbus_get_is_errno_nonzero (void)
+{
+  return errno != 0;
+}
+
+/**
+ * See if errno is ENOMEM
+ * @returns #TRUE if errno == ENOMEM
+ */
+dbus_bool_t
+_dbus_get_is_errno_enomem (void)
+{
+  return errno == ENOMEM;
+}
+
+/**
+ * See if errno is EINTR
+ * @returns #TRUE if errno == EINTR
+ */
+dbus_bool_t
+_dbus_get_is_errno_eintr (void)
+{
+  return errno == EINTR;
+}
+
+/**
+ * See if errno is EPIPE
+ * @returns #TRUE if errno == EPIPE
+ */
+dbus_bool_t
+_dbus_get_is_errno_epipe (void)
+{
+  return errno == EPIPE;
+}
+
+/**
+ * Get error message from errno
+ * @returns _dbus_strerror(errno)
+ */
+const char*
+_dbus_strerror_from_errno (void)
+{
+  return _dbus_strerror (errno);
+}
+
+/** @} end of sysdeps */
+
+/* tests in dbus-sysdeps-util.c */
diff --git a/dbus/dbus/dbus-sysdeps.h b/dbus/dbus/dbus-sysdeps.h
new file mode 100644
index 0000000..eee9160
--- /dev/null
+++ b/dbus/dbus/dbus-sysdeps.h
@@ -0,0 +1,548 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-sysdeps.h Wrappers around system/libc features (internal to D-Bus implementation)
+ * 
+ * Copyright (C) 2002, 2003  Red Hat, Inc.
+ * Copyright (C) 2003 CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_SYSDEPS_H
+#define DBUS_SYSDEPS_H
+
+#include "config.h"
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-file.h>
+#include <dbus/dbus-string.h>
+
+/* this is perhaps bogus, but strcmp() etc. are faster if we use the
+ * stuff straight out of string.h, so have this here for now.
+ */
+#include <string.h>
+#include <stdarg.h>
+
+/* AIX sys/poll.h does #define events reqevents, and other
+ * wonderousness, so must include sys/poll before declaring
+ * DBusPollFD
+ */ 
+#ifdef HAVE_POLL
+#include <sys/poll.h>
+#endif
+
+#ifdef DBUS_WINCE
+/* Windows CE lacks some system functions (such as errno and clock).
+   We bring them in here.  */
+#include "dbus-sysdeps-wince-glue.h"
+#endif
+
+DBUS_BEGIN_DECLS
+
+#ifdef DBUS_WIN
+#define _DBUS_PATH_SEPARATOR ";"
+#else
+#define _DBUS_PATH_SEPARATOR ":"
+#endif
+
+/* Forward declarations */
+
+
+/** An opaque list type */
+typedef struct DBusList DBusList;
+
+/** Object that contains a list of credentials such as UNIX or Windows user ID */
+typedef struct DBusCredentials DBusCredentials;
+
+/** A wrapper around a pipe descriptor or handle */
+typedef struct DBusPipe DBusPipe;
+
+/**
+ * @addtogroup DBusSysdeps
+ *
+ * @{
+ */
+
+void _dbus_abort (void) _DBUS_GNUC_NORETURN;
+
+dbus_bool_t _dbus_check_setuid (void);
+const char* _dbus_getenv (const char *varname);
+dbus_bool_t _dbus_setenv (const char *varname,
+			  const char *value);
+dbus_bool_t _dbus_clearenv (void);
+char **     _dbus_get_environment (void);
+
+/** A process ID */
+typedef unsigned long dbus_pid_t;
+/** A user ID */
+typedef unsigned long dbus_uid_t;
+/** A group ID */
+typedef unsigned long dbus_gid_t;
+
+/** an invalid PID used to represent an uninitialized dbus_pid_t field */
+#define DBUS_PID_UNSET ((dbus_pid_t) -1)
+/** an invalid UID used to represent an uninitialized dbus_uid_t field */
+#define DBUS_UID_UNSET ((dbus_uid_t) -1)
+/** an invalid GID used to represent an uninitialized dbus_gid_t field */
+#define DBUS_GID_UNSET ((dbus_gid_t) -1)
+
+/** an appropriate printf format for dbus_pid_t */
+#define DBUS_PID_FORMAT "%lu"
+/** an appropriate printf format for dbus_uid_t */
+#define DBUS_UID_FORMAT "%lu"
+/** an appropriate printf format for dbus_gid_t */
+#define DBUS_GID_FORMAT "%lu"
+
+
+/**
+ * Socket interface
+ *
+ *  @todo Use for the file descriptors a struct
+ *           - struct DBusSocket{ int d; }; -
+ *        instead of int to get type-safety which 
+ *        will be checked by the compiler.
+ * 
+ */
+
+dbus_bool_t _dbus_close_socket     (int               fd,
+                                    DBusError        *error);
+int         _dbus_read_socket      (int               fd,
+                                    DBusString       *buffer,
+                                    int               count);
+int         _dbus_write_socket     (int               fd,
+                                    const DBusString *buffer,
+                                    int               start,
+                                    int               len);
+int         _dbus_write_socket_two (int               fd,
+                                    const DBusString *buffer1,
+                                    int               start1,
+                                    int               len1,
+                                    const DBusString *buffer2,
+                                    int               start2,
+                                    int               len2);
+
+int _dbus_read_socket_with_unix_fds      (int               fd,
+                                          DBusString       *buffer,
+                                          int               count,
+                                          int              *fds,
+                                          int              *n_fds);
+int _dbus_write_socket_with_unix_fds     (int               fd,
+                                          const DBusString *buffer,
+                                          int               start,
+                                          int               len,
+                                          const int        *fds,
+                                          int               n_fds);
+int _dbus_write_socket_with_unix_fds_two (int               fd,
+                                          const DBusString *buffer1,
+                                          int               start1,
+                                          int               len1,
+                                          const DBusString *buffer2,
+                                          int               start2,
+                                          int               len2,
+                                          const int        *fds,
+                                          int               n_fds);
+
+dbus_bool_t _dbus_socket_is_invalid (int              fd);
+
+int _dbus_connect_tcp_socket  (const char     *host,
+                               const char     *port,
+                               const char     *family,
+                               DBusError      *error);
+int _dbus_connect_tcp_socket_with_nonce  (const char     *host,
+                                          const char     *port,
+                                          const char     *family,
+                                          const char     *noncefile,
+                                          DBusError      *error);
+int _dbus_listen_tcp_socket   (const char     *host,
+                               const char     *port,
+                               const char     *family,
+                               DBusString     *retport,
+                               int           **fds_p,
+                               DBusError      *error);
+int _dbus_accept              (int             listen_fd);
+
+
+dbus_bool_t _dbus_read_credentials_socket (int               client_fd,
+                                           DBusCredentials  *credentials,
+                                           DBusError        *error);
+dbus_bool_t _dbus_send_credentials_socket (int              server_fd,
+                                           DBusError       *error);
+
+dbus_bool_t _dbus_credentials_add_from_user            (DBusCredentials  *credentials,
+                                                        const DBusString *username);
+dbus_bool_t _dbus_credentials_add_from_current_process (DBusCredentials  *credentials);
+dbus_bool_t _dbus_append_user_from_current_process     (DBusString        *str);
+
+dbus_bool_t _dbus_parse_unix_user_from_config   (const DBusString  *username,
+                                                 dbus_uid_t        *uid_p);
+dbus_bool_t _dbus_parse_unix_group_from_config  (const DBusString  *groupname,
+                                                 dbus_gid_t        *gid_p);
+dbus_bool_t _dbus_unix_groups_from_uid          (dbus_uid_t         uid,
+                                                 dbus_gid_t       **group_ids,
+                                                 int               *n_group_ids);
+dbus_bool_t _dbus_unix_user_is_at_console       (dbus_uid_t         uid,
+                                                 DBusError         *error);
+dbus_bool_t _dbus_unix_user_is_process_owner    (dbus_uid_t         uid);
+dbus_bool_t _dbus_windows_user_is_process_owner (const char        *windows_sid);
+
+dbus_bool_t _dbus_append_keyring_directory_for_credentials (DBusString      *directory,
+                                                            DBusCredentials *credentials);
+
+dbus_bool_t _dbus_daemon_is_session_bus_address_published (const char *scope);
+
+dbus_bool_t _dbus_daemon_publish_session_bus_address (const char* address, const char* shm_name);
+
+void _dbus_daemon_unpublish_session_bus_address (void);
+
+dbus_bool_t _dbus_socket_can_pass_unix_fd(int fd);
+
+/** Opaque type representing an atomically-modifiable integer
+ * that can be used from multiple threads.
+ */
+typedef struct DBusAtomic DBusAtomic;
+
+/**
+ * An atomic integer safe to increment or decrement from multiple threads.
+ */
+struct DBusAtomic
+{
+#ifdef DBUS_WIN
+  volatile long value; /**< Value of the atomic integer. */
+#else
+  volatile dbus_int32_t value; /**< Value of the atomic integer. */
+#endif
+};
+
+/* The value we get from autofoo is in the form of a cpp expression;
+ * convert that to a conventional defined/undef switch. (We can't get
+ * the conventional defined/undef because of multiarch builds only running
+ * ./configure once, on Darwin.) */
+#if DBUS_HAVE_ATOMIC_INT_COND
+#   define DBUS_HAVE_ATOMIC_INT 1
+#else
+#   undef DBUS_HAVE_ATOMIC_INT
+#endif
+
+dbus_int32_t _dbus_atomic_inc (DBusAtomic *atomic);
+dbus_int32_t _dbus_atomic_dec (DBusAtomic *atomic);
+dbus_int32_t _dbus_atomic_get (DBusAtomic *atomic);
+
+
+/* AIX uses different values for poll */
+
+#ifdef _AIX
+/** There is data to read */
+#define _DBUS_POLLIN      0x0001
+/** There is urgent data to read */
+#define _DBUS_POLLPRI     0x0004
+/** Writing now will not block */
+#define _DBUS_POLLOUT     0x0002
+/** Error condition */
+#define _DBUS_POLLERR     0x4000
+/** Hung up */
+#define _DBUS_POLLHUP     0x2000
+/** Invalid request: fd not open */
+#define _DBUS_POLLNVAL    0x8000
+#elif defined(__HAIKU__)
+/** There is data to read */
+#define _DBUS_POLLIN      0x0001
+/** Writing now will not block */
+#define _DBUS_POLLOUT     0x0002
+/** Error condition */
+#define _DBUS_POLLERR     0x0004
+/** There is urgent data to read */
+#define _DBUS_POLLPRI     0x0020
+/** Hung up */
+#define _DBUS_POLLHUP     0x0080
+/** Invalid request: fd not open */
+#define _DBUS_POLLNVAL    0x1000
+#else
+/** There is data to read */
+#define _DBUS_POLLIN      0x0001
+/** There is urgent data to read */
+#define _DBUS_POLLPRI     0x0002
+/** Writing now will not block */
+#define _DBUS_POLLOUT     0x0004
+/** Error condition */
+#define _DBUS_POLLERR     0x0008
+/** Hung up */
+#define _DBUS_POLLHUP     0x0010
+/** Invalid request: fd not open */
+#define _DBUS_POLLNVAL    0x0020
+#endif
+
+/**
+ * A portable struct pollfd wrapper. 
+ */
+typedef struct
+{
+  int fd;            /**< File descriptor */
+  short events;      /**< Events to poll for */
+  short revents;     /**< Events that occurred */
+} DBusPollFD;
+
+int _dbus_poll (DBusPollFD *fds,
+                int         n_fds,
+                int         timeout_milliseconds);
+
+void _dbus_sleep_milliseconds (int milliseconds);
+
+void _dbus_get_monotonic_time (long *tv_sec,
+                               long *tv_usec);
+
+void _dbus_get_real_time (long *tv_sec,
+                          long *tv_usec);
+
+/**
+ * directory interface
+ */
+dbus_bool_t    _dbus_create_directory        (const DBusString *filename,
+                                              DBusError        *error);
+dbus_bool_t    _dbus_delete_directory        (const DBusString *filename,
+					      DBusError        *error);
+
+dbus_bool_t _dbus_concat_dir_and_file (DBusString       *dir,
+                                       const DBusString *next_component);
+dbus_bool_t _dbus_string_get_dirname  (const DBusString *filename,
+                                       DBusString       *dirname);
+dbus_bool_t _dbus_path_is_absolute    (const DBusString *filename);
+
+dbus_bool_t _dbus_get_standard_session_servicedirs (DBusList **dirs);
+dbus_bool_t _dbus_get_standard_system_servicedirs (DBusList **dirs);
+
+dbus_bool_t _dbus_append_system_config_file  (DBusString *str);
+dbus_bool_t _dbus_append_session_config_file (DBusString *str);
+
+/** Opaque type for reading a directory listing */
+typedef struct DBusDirIter DBusDirIter;
+
+DBusDirIter* _dbus_directory_open          (const DBusString *filename,
+                                            DBusError        *error);
+dbus_bool_t  _dbus_directory_get_next_file (DBusDirIter      *iter,
+                                            DBusString       *filename,
+                                            DBusError        *error);
+void         _dbus_directory_close         (DBusDirIter      *iter);
+
+dbus_bool_t  _dbus_check_dir_is_private_to_user    (DBusString *dir,
+                                                    DBusError *error);
+
+void _dbus_fd_set_close_on_exec (intptr_t fd);
+
+const char* _dbus_get_tmpdir      (void);
+
+/**
+ * Random numbers 
+ */
+void        _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
+                                                      int   n_bytes);
+void        _dbus_generate_random_bytes_buffer (char       *buffer,
+                                                int         n_bytes);
+dbus_bool_t _dbus_generate_random_bytes        (DBusString *str,
+                                                int         n_bytes);
+dbus_bool_t _dbus_generate_random_ascii        (DBusString *str,
+                                                int         n_bytes);
+
+const char* _dbus_error_from_errno (int error_number);
+const char* _dbus_error_from_system_errno (void);
+
+void        _dbus_set_errno_to_zero                  (void);
+dbus_bool_t _dbus_get_is_errno_nonzero               (void);
+dbus_bool_t _dbus_get_is_errno_eagain_or_ewouldblock (void);
+dbus_bool_t _dbus_get_is_errno_enomem                (void);
+dbus_bool_t _dbus_get_is_errno_eintr                 (void);
+dbus_bool_t _dbus_get_is_errno_epipe                 (void);
+const char* _dbus_strerror_from_errno                (void);
+
+void _dbus_disable_sigpipe (void);
+
+
+void _dbus_exit (int code) _DBUS_GNUC_NORETURN;
+
+int _dbus_printf_string_upper_bound (const char *format,
+                                     va_list args);
+
+
+/**
+ * Portable struct with stat() results
+ */
+typedef struct
+{
+  unsigned long mode;  /**< File mode */
+  unsigned long nlink; /**< Number of hard links */
+  dbus_uid_t    uid;   /**< User owning file */
+  dbus_gid_t    gid;   /**< Group owning file */
+  unsigned long size;  /**< Size of file */
+  unsigned long atime; /**< Access time */
+  unsigned long mtime; /**< Modify time */
+  unsigned long ctime; /**< Creation time */
+} DBusStat;
+
+dbus_bool_t _dbus_stat             (const DBusString *filename,
+                                    DBusStat         *statbuf,
+                                    DBusError        *error);
+dbus_bool_t _dbus_full_duplex_pipe (int              *fd1,
+                                    int              *fd2,
+                                    dbus_bool_t       blocking,
+                                    DBusError        *error);
+
+void        _dbus_print_backtrace  (void);
+
+dbus_bool_t _dbus_become_daemon   (const DBusString *pidfile,
+                                   DBusPipe         *print_pid_pipe,
+                                   DBusError        *error,
+                                   dbus_bool_t       keep_umask);
+
+dbus_bool_t _dbus_verify_daemon_user    (const char *user);
+dbus_bool_t _dbus_change_to_daemon_user (const char *user,
+                                         DBusError  *error);
+
+dbus_bool_t _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
+                                              DBusPipe         *print_pid_pipe,
+                                              dbus_pid_t        pid_to_write,
+                                              DBusError        *error);
+
+dbus_bool_t _dbus_command_for_pid (unsigned long  pid,
+                                   DBusString    *str,
+                                   int            max_len,
+                                   DBusError     *error);
+
+/** A UNIX signal handler */
+typedef void (* DBusSignalHandler) (int sig);
+
+void _dbus_set_signal_handler (int               sig,
+                               DBusSignalHandler handler);
+
+dbus_bool_t _dbus_user_at_console (const char *username,
+                                   DBusError  *error);
+
+void _dbus_init_system_log (void);
+
+typedef enum {
+  DBUS_SYSTEM_LOG_INFO,
+  DBUS_SYSTEM_LOG_SECURITY,
+  DBUS_SYSTEM_LOG_FATAL
+} DBusSystemLogSeverity;
+
+void _dbus_system_log (DBusSystemLogSeverity severity, const char *msg, ...) _DBUS_GNUC_PRINTF (2, 3);
+void _dbus_system_logv (DBusSystemLogSeverity severity, const char *msg, va_list args);
+
+/* Define DBUS_VA_COPY() to do the right thing for copying va_list variables.
+ * config.h may have already defined DBUS_VA_COPY as va_copy or __va_copy.
+ */
+#if !defined (DBUS_VA_COPY)
+#  if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
+#    define DBUS_VA_COPY(ap1, ap2)   (*(ap1) = *(ap2))
+#  elif defined (DBUS_VA_COPY_AS_ARRAY)
+#    define DBUS_VA_COPY(ap1, ap2)   memcpy ((ap1), (ap2), sizeof (va_list))
+#  else /* va_list is a pointer */
+#    define DBUS_VA_COPY(ap1, ap2)   ((ap1) = (ap2))
+#  endif /* va_list is a pointer */
+#endif /* !DBUS_VA_COPY */
+
+
+/**
+ * Casts a primitive C type to a byte array and then indexes
+ * a particular byte of the array.
+ */
+#define _DBUS_BYTE_OF_PRIMITIVE(p, i) \
+    (((const char*)&(p))[(i)])
+/** On x86 there is an 80-bit FPU, and if you do "a == b" it may have a
+ * or b in an 80-bit register, thus failing to compare the two 64-bit
+ * doubles for bitwise equality. So this macro compares the two doubles
+ * bitwise.
+ */
+#define _DBUS_DOUBLES_BITWISE_EQUAL(a, b)                                       \
+     (_DBUS_BYTE_OF_PRIMITIVE (a, 0) == _DBUS_BYTE_OF_PRIMITIVE (b, 0) &&       \
+      _DBUS_BYTE_OF_PRIMITIVE (a, 1) == _DBUS_BYTE_OF_PRIMITIVE (b, 1) &&       \
+      _DBUS_BYTE_OF_PRIMITIVE (a, 2) == _DBUS_BYTE_OF_PRIMITIVE (b, 2) &&       \
+      _DBUS_BYTE_OF_PRIMITIVE (a, 3) == _DBUS_BYTE_OF_PRIMITIVE (b, 3) &&       \
+      _DBUS_BYTE_OF_PRIMITIVE (a, 4) == _DBUS_BYTE_OF_PRIMITIVE (b, 4) &&       \
+      _DBUS_BYTE_OF_PRIMITIVE (a, 5) == _DBUS_BYTE_OF_PRIMITIVE (b, 5) &&       \
+      _DBUS_BYTE_OF_PRIMITIVE (a, 6) == _DBUS_BYTE_OF_PRIMITIVE (b, 6) &&       \
+      _DBUS_BYTE_OF_PRIMITIVE (a, 7) == _DBUS_BYTE_OF_PRIMITIVE (b, 7))
+
+dbus_bool_t _dbus_get_autolaunch_address (const char *scope,
+                                          DBusString *address,
+					                      DBusError  *error);
+
+dbus_bool_t _dbus_lookup_session_address (dbus_bool_t *supported,
+                                          DBusString  *address,
+                                          DBusError   *error);
+
+/** Type representing a universally unique ID
+ * @todo rename to UUID instead of GUID
+ */
+typedef union DBusGUID DBusGUID;
+
+dbus_bool_t _dbus_read_local_machine_uuid   (DBusGUID         *machine_id,
+                                             dbus_bool_t       create_if_not_found,
+                                             DBusError        *error);
+
+/**
+ * Initialize threads as in dbus_threads_init_default(), appropriately
+ * for the platform.
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t _dbus_threads_init_platform_specific (void);
+
+dbus_bool_t _dbus_split_paths_and_append (DBusString *dirs, 
+                                          const char *suffix, 
+                                          DBusList **dir_list);
+
+unsigned long _dbus_pid_for_log (void);
+
+/* FIXME move back to dbus-sysdeps-unix.h probably -
+ * the PID file handling just needs a little more abstraction
+ * in the bus daemon first.
+ */
+dbus_pid_t    _dbus_getpid (void);
+
+dbus_bool_t _dbus_change_to_daemon_user (const char *user,
+                                         DBusError  *error);
+
+void _dbus_flush_caches (void);
+
+void _dbus_request_file_descriptor_limit (unsigned int limit);
+
+/*
+ * replaces the term DBUS_PREFIX in configure_time_path by the
+ * current dbus installation directory. On unix this function is a noop
+ *
+ * @param configure_time_path
+ * @return real path
+ */
+const char *
+_dbus_replace_install_prefix (const char *configure_time_path);
+
+/** @} */
+
+DBUS_END_DECLS
+
+
+#ifdef DBUS_WIN
+#include "dbus-sysdeps-win.h"
+#endif
+
+#endif /* DBUS_SYSDEPS_H */
diff --git a/dbus/dbus/dbus-test-main.c b/dbus/dbus/dbus-test-main.c
new file mode 100644
index 0000000..f6ef782
--- /dev/null
+++ b/dbus/dbus/dbus-test-main.c
@@ -0,0 +1,58 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-test.c  Program to run all tests
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+
+#include <config.h>
+#include "dbus-types.h"
+#include "dbus-test.h"
+#include <stdio.h>
+#include <stdlib.h>
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+int
+main (int    argc,
+      char **argv)
+{
+  const char *test_data_dir;
+  const char *specific_test;
+
+#if HAVE_SETLOCALE
+  setlocale(LC_ALL, "");
+#endif
+  
+  if (argc > 1)
+    test_data_dir = argv[1];
+  else
+    test_data_dir = NULL;
+
+  if (argc > 2)
+    specific_test = argv[2];
+  else
+    specific_test = NULL;
+  
+  dbus_internal_do_not_use_run_tests (test_data_dir, specific_test);
+  
+  return 0;
+}
diff --git a/dbus/dbus/dbus-test.c b/dbus/dbus/dbus-test.c
new file mode 100644
index 0000000..224a6c8
--- /dev/null
+++ b/dbus/dbus/dbus-test.c
@@ -0,0 +1,172 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-test.c  Program to run all tests
+ *
+ * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-test.h"
+#include "dbus-sysdeps.h"
+#include "dbus-internals.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef DBUS_BUILD_TESTS
+static void
+die (const char *failure)
+{
+  fprintf (stderr, "Unit test failed: %s\n", failure);
+  exit (1);
+}
+
+static void
+check_memleaks (void)
+{
+  dbus_shutdown ();
+
+  printf ("%s: checking for memleaks\n", "dbus-test");
+  if (_dbus_get_malloc_blocks_outstanding () != 0)
+    {
+      _dbus_warn ("%d dbus_malloc blocks were not freed\n",
+                  _dbus_get_malloc_blocks_outstanding ());
+      die ("memleaks");
+    }
+}
+
+typedef dbus_bool_t (*TestFunc)(void);
+typedef dbus_bool_t (*TestDataFunc)(const char *data);
+
+static void
+run_test (const char             *test_name,
+	  const char             *specific_test,
+	  TestFunc                test)
+{
+  if (!specific_test || strcmp (specific_test, test_name) == 0)
+    {
+      printf ("%s: running %s tests\n", "dbus-test", test_name);
+      if (!test ())
+	die (test_name);
+
+      check_memleaks ();
+    }
+}
+
+static void
+run_data_test (const char             *test_name,
+	       const char             *specific_test,
+	       TestDataFunc            test,
+	       const char             *test_data_dir)
+{
+  if (!specific_test || strcmp (specific_test, test_name) == 0)
+    {
+      printf ("%s: running %s tests\n", "dbus-test", test_name);
+      if (!test (test_data_dir))
+	die (test_name);
+
+      check_memleaks ();
+    }
+}
+
+#endif /* DBUS_BUILD_TESTS */
+
+/**
+ * An exported symbol to be run in order to execute
+ * unit tests. Should not be used by
+ * any app other than our test app, this symbol
+ * won't exist in some builds of the library.
+ * (with --enable-tests=no)
+ *
+ * @param test_data_dir the directory with test data (test/data normally)
+ */
+void
+dbus_internal_do_not_use_run_tests (const char *test_data_dir, const char *specific_test)
+{
+#ifdef DBUS_BUILD_TESTS
+  if (!_dbus_threads_init_debug ())
+    die ("debug threads init");
+  
+  if (test_data_dir == NULL)
+    test_data_dir = _dbus_getenv ("DBUS_TEST_DATA");
+
+  if (test_data_dir != NULL)
+    printf ("Test data in %s\n", test_data_dir);
+  else
+    printf ("No test data!\n");
+
+  run_test ("string", specific_test, _dbus_string_test);
+  
+  run_test ("sysdeps", specific_test, _dbus_sysdeps_test);
+  
+  run_test ("data-slot", specific_test, _dbus_data_slot_test);
+
+  run_test ("misc", specific_test, _dbus_misc_test);
+  
+  run_test ("address", specific_test, _dbus_address_test);
+
+  run_test ("server", specific_test, _dbus_server_test);
+
+  run_test ("object-tree", specific_test, _dbus_object_tree_test);
+
+  run_test ("signature", specific_test, _dbus_signature_test);
+  
+  run_test ("marshalling", specific_test, _dbus_marshal_test);
+
+  run_test ("marshal-recursive", specific_test, _dbus_marshal_recursive_test);
+
+  run_test ("byteswap", specific_test, _dbus_marshal_byteswap_test);
+  
+  run_test ("memory", specific_test, _dbus_memory_test);
+
+#if 1
+  run_test ("mem-pool", specific_test, _dbus_mem_pool_test);
+#endif
+  
+  run_test ("list", specific_test, _dbus_list_test);
+
+  run_test ("marshal-validate", specific_test, _dbus_marshal_validate_test);
+
+  run_data_test ("message", specific_test, _dbus_message_test, test_data_dir);
+  
+  run_test ("hash", specific_test, _dbus_hash_test);
+
+#if !defined(DBUS_WINCE)
+  run_data_test ("spawn", specific_test, _dbus_spawn_test, test_data_dir);
+#endif
+  
+  run_data_test ("credentials", specific_test, _dbus_credentials_test, test_data_dir);
+
+#ifdef DBUS_UNIX
+  run_data_test ("userdb", specific_test, _dbus_userdb_test, test_data_dir);
+
+  run_test ("transport-unix", specific_test, _dbus_transport_unix_test);
+#endif
+  
+  run_test ("keyring", specific_test, _dbus_keyring_test);
+
+  run_data_test ("sha", specific_test, _dbus_sha_test, test_data_dir);
+  
+  run_data_test ("auth", specific_test, _dbus_auth_test, test_data_dir);
+
+  printf ("%s: completed successfully\n", "dbus-test");
+#else
+  printf ("Not compiled with unit tests, not running any\n");
+#endif
+}
+
diff --git a/dbus/dbus/dbus-test.h b/dbus/dbus/dbus-test.h
new file mode 100644
index 0000000..f254388
--- /dev/null
+++ b/dbus/dbus/dbus-test.h
@@ -0,0 +1,80 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-test.h  Declarations of test functions.
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_TEST_H
+#define DBUS_TEST_H
+
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-marshal-validate.h>
+
+dbus_bool_t _dbus_hash_test              (void);
+dbus_bool_t _dbus_list_test              (void);
+dbus_bool_t _dbus_marshal_test           (void);
+dbus_bool_t _dbus_marshal_recursive_test (void);
+dbus_bool_t _dbus_marshal_byteswap_test  (void);
+dbus_bool_t _dbus_marshal_validate_test  (void);
+dbus_bool_t _dbus_misc_test              (void);
+dbus_bool_t _dbus_signature_test         (void);
+dbus_bool_t _dbus_mem_pool_test          (void);
+dbus_bool_t _dbus_string_test            (void);
+dbus_bool_t _dbus_address_test           (void);
+dbus_bool_t _dbus_server_test            (void);
+dbus_bool_t _dbus_message_test           (const char *test_data_dir);
+dbus_bool_t _dbus_auth_test              (const char *test_data_dir);
+dbus_bool_t _dbus_sha_test               (const char *test_data_dir);
+dbus_bool_t _dbus_keyring_test           (void);
+dbus_bool_t _dbus_data_slot_test         (void);
+dbus_bool_t _dbus_sysdeps_test           (void);
+dbus_bool_t _dbus_spawn_test             (const char *test_data_dir);
+dbus_bool_t _dbus_userdb_test            (const char *test_data_dir);
+dbus_bool_t _dbus_transport_unix_test    (void);
+dbus_bool_t _dbus_memory_test            (void);
+dbus_bool_t _dbus_object_tree_test       (void);
+dbus_bool_t _dbus_credentials_test       (const char *test_data_dir);
+
+void        dbus_internal_do_not_use_run_tests         (const char          *test_data_dir,
+							const char          *specific_test);
+dbus_bool_t dbus_internal_do_not_use_try_message_file  (const DBusString    *filename,
+                                                        DBusValidity         expected_validity);
+dbus_bool_t dbus_internal_do_not_use_try_message_data  (const DBusString    *data,
+                                                        DBusValidity         expected_validity);
+dbus_bool_t dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
+                                                        DBusString          *data);
+
+
+/* returns FALSE on fatal failure */
+typedef dbus_bool_t (* DBusForeachMessageFileFunc) (const DBusString   *filename,
+                                                    DBusValidity        expected_validity,
+                                                    void               *data);
+
+dbus_bool_t dbus_internal_do_not_use_foreach_message_file (const char                 *test_data_dir,
+                                                           DBusForeachMessageFileFunc  func,
+                                                           void                       *user_data);
+dbus_bool_t dbus_internal_do_not_use_generate_bodies    (int           sequence,
+                                                         int           byte_order,
+                                                         DBusString   *signature,
+                                                         DBusString   *body);
+
+
+#endif /* DBUS_TEST_H */
diff --git a/dbus/dbus/dbus-threads-internal.h b/dbus/dbus/dbus-threads-internal.h
new file mode 100644
index 0000000..64e8bac
--- /dev/null
+++ b/dbus/dbus/dbus-threads-internal.h
@@ -0,0 +1,95 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-threads-internal.h  D-Bus thread primitives
+ *
+ * Copyright (C) 2002, 2005 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_THREADS_INTERNAL_H
+#define DBUS_THREADS_INTERNAL_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-threads.h>
+
+/**
+ * @addtogroup DBusThreadsInternals
+ * @{
+ */
+
+/**
+ * A mutex which is recursive if possible, else non-recursive.
+ * This is typically recursive, but that cannot be relied upon.
+ */
+typedef struct DBusRMutex DBusRMutex;
+
+/**
+ * A mutex suitable for use with condition variables.
+ * This is typically non-recursive.
+ */
+typedef struct DBusCMutex DBusCMutex;
+
+/** @} */
+
+DBUS_BEGIN_DECLS
+
+void         _dbus_rmutex_lock               (DBusRMutex       *mutex);
+void         _dbus_rmutex_unlock             (DBusRMutex       *mutex);
+void         _dbus_rmutex_new_at_location    (DBusRMutex      **location_p);
+void         _dbus_rmutex_free_at_location   (DBusRMutex      **location_p);
+
+void         _dbus_cmutex_lock               (DBusCMutex       *mutex);
+void         _dbus_cmutex_unlock             (DBusCMutex       *mutex);
+void         _dbus_cmutex_new_at_location    (DBusCMutex      **location_p);
+void         _dbus_cmutex_free_at_location   (DBusCMutex      **location_p);
+
+DBusCondVar* _dbus_condvar_new               (void);
+void         _dbus_condvar_free              (DBusCondVar       *cond);
+void         _dbus_condvar_wait              (DBusCondVar       *cond,
+                                              DBusCMutex        *mutex);
+dbus_bool_t  _dbus_condvar_wait_timeout      (DBusCondVar       *cond,
+                                              DBusCMutex        *mutex,
+                                              int                timeout_milliseconds);
+void         _dbus_condvar_wake_one          (DBusCondVar       *cond);
+void         _dbus_condvar_new_at_location   (DBusCondVar      **location_p);
+void         _dbus_condvar_free_at_location  (DBusCondVar      **location_p);
+
+/* Private to threading implementations and dbus-threads.c */
+
+DBusRMutex  *_dbus_platform_rmutex_new       (void);
+void         _dbus_platform_rmutex_free      (DBusRMutex       *mutex);
+void         _dbus_platform_rmutex_lock      (DBusRMutex       *mutex);
+void         _dbus_platform_rmutex_unlock    (DBusRMutex       *mutex);
+
+DBusCMutex  *_dbus_platform_cmutex_new       (void);
+void         _dbus_platform_cmutex_free      (DBusCMutex       *mutex);
+void         _dbus_platform_cmutex_lock      (DBusCMutex       *mutex);
+void         _dbus_platform_cmutex_unlock    (DBusCMutex       *mutex);
+
+DBusCondVar* _dbus_platform_condvar_new      (void);
+void         _dbus_platform_condvar_free     (DBusCondVar       *cond);
+void         _dbus_platform_condvar_wait     (DBusCondVar       *cond,
+                                              DBusCMutex        *mutex);
+dbus_bool_t  _dbus_platform_condvar_wait_timeout (DBusCondVar   *cond,
+                                              DBusCMutex        *mutex,
+                                              int                timeout_milliseconds);
+void         _dbus_platform_condvar_wake_one (DBusCondVar       *cond);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_THREADS_INTERNAL_H */
diff --git a/dbus/dbus/dbus-threads.c b/dbus/dbus/dbus-threads.c
new file mode 100644
index 0000000..bb1169d
--- /dev/null
+++ b/dbus/dbus/dbus-threads.c
@@ -0,0 +1,633 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-threads.h  D-Bus threads handling
+ *
+ * Copyright (C) 2002, 2003, 2006 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#include <config.h>
+#include "dbus-threads.h"
+#include "dbus-internals.h"
+#include "dbus-threads-internal.h"
+#include "dbus-list.h"
+
+static int thread_init_generation = 0;
+ 
+static DBusList *uninitialized_rmutex_list = NULL;
+static DBusList *uninitialized_cmutex_list = NULL;
+static DBusList *uninitialized_condvar_list = NULL;
+
+/** This is used for the no-op default mutex pointer, just to be distinct from #NULL */
+#define _DBUS_DUMMY_MUTEX ((DBusMutex*)0xABCDEF)
+#define _DBUS_DUMMY_RMUTEX ((DBusRMutex *) _DBUS_DUMMY_MUTEX)
+#define _DBUS_DUMMY_CMUTEX ((DBusCMutex *) _DBUS_DUMMY_MUTEX)
+
+/** This is used for the no-op default mutex pointer, just to be distinct from #NULL */
+#define _DBUS_DUMMY_CONDVAR ((DBusCondVar*)0xABCDEF2)
+
+/**
+ * @defgroup DBusThreadsInternals Thread functions
+ * @ingroup  DBusInternals
+ * @brief _dbus_rmutex_lock(), etc.
+ *
+ * Functions and macros related to threads and thread locks.
+ *
+ * @{
+ */
+
+/**
+ * Creates a new mutex
+ * or creates a no-op mutex if threads are not initialized.
+ * May return #NULL even if threads are initialized, indicating
+ * out-of-memory.
+ *
+ * If possible, the mutex returned by this function is recursive, to
+ * avoid deadlocks. However, that cannot be relied on.
+ *
+ * The extra level of indirection given by allocating a pointer
+ * to point to the mutex location allows the threading
+ * module to swap out dummy mutexes for a real mutex so libraries
+ * can initialize threads even after the D-Bus API has been used.
+ *
+ * @param location_p the location of the new mutex, can return #NULL on OOM
+ */
+void
+_dbus_rmutex_new_at_location (DBusRMutex **location_p)
+{
+  _dbus_assert (location_p != NULL);
+
+  if (thread_init_generation == _dbus_current_generation)
+    {
+      *location_p = _dbus_platform_rmutex_new ();
+    }
+  else
+    {
+      *location_p = _DBUS_DUMMY_RMUTEX;
+
+      if (!_dbus_list_append (&uninitialized_rmutex_list, location_p))
+        *location_p = NULL;
+    }
+}
+
+/**
+ * Creates a new mutex
+ * or creates a no-op mutex if threads are not initialized.
+ * May return #NULL even if threads are initialized, indicating
+ * out-of-memory.
+ *
+ * The returned mutex is suitable for use with condition variables.
+ *
+ * The extra level of indirection given by allocating a pointer
+ * to point to the mutex location allows the threading
+ * module to swap out dummy mutexes for a real mutex so libraries
+ * can initialize threads even after the D-Bus API has been used.
+ *
+ * @param location_p the location of the new mutex, can return #NULL on OOM
+ */
+void
+_dbus_cmutex_new_at_location (DBusCMutex **location_p)
+{
+  _dbus_assert (location_p != NULL);
+
+  if (thread_init_generation == _dbus_current_generation)
+    {
+      *location_p = _dbus_platform_cmutex_new ();
+    }
+  else
+    {
+      *location_p = _DBUS_DUMMY_CMUTEX;
+
+      if (!_dbus_list_append (&uninitialized_cmutex_list, location_p))
+        *location_p = NULL;
+    }
+}
+
+/**
+ * Frees a DBusRMutex or removes it from the uninitialized mutex list;
+ * does nothing if passed a #NULL pointer.
+ */
+void
+_dbus_rmutex_free_at_location (DBusRMutex **location_p)
+{
+  if (location_p == NULL)
+    return;
+
+  if (thread_init_generation == _dbus_current_generation)
+    {
+      if (*location_p != NULL)
+        _dbus_platform_rmutex_free (*location_p);
+    }
+  else
+    {
+      _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_RMUTEX);
+
+      _dbus_list_remove (&uninitialized_rmutex_list, location_p);
+    }
+}
+
+/**
+ * Frees a DBusCMutex and removes it from the
+ * uninitialized mutex list;
+ * does nothing if passed a #NULL pointer.
+ */
+void
+_dbus_cmutex_free_at_location (DBusCMutex **location_p)
+{
+  if (location_p == NULL)
+    return;
+
+  if (thread_init_generation == _dbus_current_generation)
+    {
+      if (*location_p != NULL)
+        _dbus_platform_cmutex_free (*location_p);
+    }
+  else
+    {
+      _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_CMUTEX);
+
+      _dbus_list_remove (&uninitialized_cmutex_list, location_p);
+    }
+}
+
+/**
+ * Locks a mutex. Does nothing if passed a #NULL pointer.
+ * Locks may be recursive if threading implementation initialized
+ * recursive locks.
+ */
+void
+_dbus_rmutex_lock (DBusRMutex *mutex)
+{
+  if (mutex && thread_init_generation == _dbus_current_generation)
+    _dbus_platform_rmutex_lock (mutex);
+}
+
+/**
+ * Locks a mutex. Does nothing if passed a #NULL pointer.
+ * Locks may be recursive if threading implementation initialized
+ * recursive locks.
+ */
+void
+_dbus_cmutex_lock (DBusCMutex *mutex)
+{
+  if (mutex && thread_init_generation == _dbus_current_generation)
+    _dbus_platform_cmutex_lock (mutex);
+}
+
+/**
+ * Unlocks a mutex. Does nothing if passed a #NULL pointer.
+ *
+ * @returns #TRUE on success
+ */
+void
+_dbus_rmutex_unlock (DBusRMutex *mutex)
+{
+  if (mutex && thread_init_generation == _dbus_current_generation)
+    _dbus_platform_rmutex_unlock (mutex);
+}
+
+/**
+ * Unlocks a mutex. Does nothing if passed a #NULL pointer.
+ *
+ * @returns #TRUE on success
+ */
+void
+_dbus_cmutex_unlock (DBusCMutex *mutex)
+{
+  if (mutex && thread_init_generation == _dbus_current_generation)
+    _dbus_platform_cmutex_unlock (mutex);
+}
+
+/**
+ * Creates a new condition variable using the function supplied
+ * to dbus_threads_init(), or creates a no-op condition variable
+ * if threads are not initialized. May return #NULL even if
+ * threads are initialized, indicating out-of-memory.
+ *
+ * @returns new mutex or #NULL
+ */
+DBusCondVar *
+_dbus_condvar_new (void)
+{
+  if (thread_init_generation == _dbus_current_generation)
+    return _dbus_platform_condvar_new ();
+  else
+    return _DBUS_DUMMY_CONDVAR;
+}
+
+
+/**
+ * This does the same thing as _dbus_condvar_new.  It however
+ * gives another level of indirection by allocating a pointer
+ * to point to the condvar location.  This allows the threading
+ * module to swap out dummy condvars for a real condvar so libraries
+ * can initialize threads even after the D-Bus API has been used.
+ *
+ * @returns the location of a new condvar or #NULL on OOM
+ */
+
+void 
+_dbus_condvar_new_at_location (DBusCondVar **location_p)
+{
+  _dbus_assert (location_p != NULL);
+
+  if (thread_init_generation == _dbus_current_generation)
+    {
+      *location_p = _dbus_condvar_new();
+    }
+  else
+    {
+      *location_p = _DBUS_DUMMY_CONDVAR;
+
+      if (!_dbus_list_append (&uninitialized_condvar_list, location_p))
+        *location_p = NULL;
+    }
+}
+
+
+/**
+ * Frees a conditional variable created with dbus_condvar_new(); does
+ * nothing if passed a #NULL pointer.
+ */
+void
+_dbus_condvar_free (DBusCondVar *cond)
+{
+  if (cond && thread_init_generation == _dbus_current_generation)
+    _dbus_platform_condvar_free (cond);
+}
+
+/**
+ * Frees a conditional variable and removes it from the 
+ * uninitialized_condvar_list; 
+ * does nothing if passed a #NULL pointer.
+ */
+void
+_dbus_condvar_free_at_location (DBusCondVar **location_p)
+{
+  if (location_p == NULL)
+    return;
+
+  if (thread_init_generation == _dbus_current_generation)
+    {
+      if (*location_p != NULL)
+        _dbus_platform_condvar_free (*location_p);
+    }
+  else
+    {
+      _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_CONDVAR);
+
+      _dbus_list_remove (&uninitialized_condvar_list, location_p);
+    }
+}
+
+/**
+ * Atomically unlocks the mutex and waits for the conditions
+ * variable to be signalled. Locks the mutex again before
+ * returning.
+ * Does nothing if passed a #NULL pointer.
+ */
+void
+_dbus_condvar_wait (DBusCondVar *cond,
+                    DBusCMutex  *mutex)
+{
+  if (cond && mutex && thread_init_generation == _dbus_current_generation)
+    _dbus_platform_condvar_wait (cond, mutex);
+}
+
+/**
+ * Atomically unlocks the mutex and waits for the conditions variable
+ * to be signalled, or for a timeout. Locks the mutex again before
+ * returning.  Does nothing if passed a #NULL pointer.  Return value
+ * is #FALSE if we timed out, #TRUE otherwise.
+ *
+ * @param cond the condition variable
+ * @param mutex the mutex
+ * @param timeout_milliseconds the maximum time to wait
+ * @returns #FALSE if the timeout occurred, #TRUE if not
+ */
+dbus_bool_t
+_dbus_condvar_wait_timeout (DBusCondVar               *cond,
+                            DBusCMutex                *mutex,
+                            int                        timeout_milliseconds)
+{
+  if (cond && mutex && thread_init_generation == _dbus_current_generation)
+    return _dbus_platform_condvar_wait_timeout (cond, mutex,
+                                                timeout_milliseconds);
+  else
+    return TRUE;
+}
+
+/**
+ * If there are threads waiting on the condition variable, wake
+ * up exactly one. 
+ * Does nothing if passed a #NULL pointer.
+ */
+void
+_dbus_condvar_wake_one (DBusCondVar *cond)
+{
+  if (cond && thread_init_generation == _dbus_current_generation)
+    _dbus_platform_condvar_wake_one (cond);
+}
+
+static void
+shutdown_global_locks (void *data)
+{
+  DBusRMutex ***locks = data;
+  int i;
+
+  i = 0;
+  while (i < _DBUS_N_GLOBAL_LOCKS)
+    {
+      if (*(locks[i]) != NULL)
+        _dbus_platform_rmutex_free (*(locks[i]));
+
+      *(locks[i]) = NULL;
+      ++i;
+    }
+  
+  dbus_free (locks);
+}
+
+static void
+shutdown_uninitialized_locks (void *data)
+{
+  _dbus_list_clear (&uninitialized_rmutex_list);
+  _dbus_list_clear (&uninitialized_cmutex_list);
+  _dbus_list_clear (&uninitialized_condvar_list);
+}
+
+static dbus_bool_t
+init_uninitialized_locks (void)
+{
+  DBusList *link;
+
+  _dbus_assert (thread_init_generation != _dbus_current_generation);
+
+  link = uninitialized_rmutex_list;
+  while (link != NULL)
+    {
+      DBusRMutex **mp;
+
+      mp = link->data;
+      _dbus_assert (*mp == _DBUS_DUMMY_RMUTEX);
+
+      *mp = _dbus_platform_rmutex_new ();
+      if (*mp == NULL)
+        goto fail_mutex;
+
+      link = _dbus_list_get_next_link (&uninitialized_rmutex_list, link);
+    }
+
+  link = uninitialized_cmutex_list;
+  while (link != NULL)
+    {
+      DBusCMutex **mp;
+
+      mp = link->data;
+      _dbus_assert (*mp == _DBUS_DUMMY_CMUTEX);
+
+      *mp = _dbus_platform_cmutex_new ();
+      if (*mp == NULL)
+        goto fail_mutex;
+
+      link = _dbus_list_get_next_link (&uninitialized_cmutex_list, link);
+    }
+
+  link = uninitialized_condvar_list;
+  while (link != NULL)
+    {
+      DBusCondVar **cp;
+
+      cp = (DBusCondVar **)link->data;
+      _dbus_assert (*cp == _DBUS_DUMMY_CONDVAR);
+
+      *cp = _dbus_platform_condvar_new ();
+      if (*cp == NULL)
+        goto fail_condvar;
+
+      link = _dbus_list_get_next_link (&uninitialized_condvar_list, link);
+    }
+
+  _dbus_list_clear (&uninitialized_rmutex_list);
+  _dbus_list_clear (&uninitialized_cmutex_list);
+  _dbus_list_clear (&uninitialized_condvar_list);
+
+  if (!_dbus_register_shutdown_func (shutdown_uninitialized_locks,
+                                     NULL))
+    goto fail_condvar;
+
+  return TRUE;
+
+ fail_condvar:
+  link = uninitialized_condvar_list;
+  while (link != NULL)
+    {
+      DBusCondVar **cp;
+
+      cp = link->data;
+
+      if (*cp != _DBUS_DUMMY_CONDVAR && *cp != NULL)
+        _dbus_platform_condvar_free (*cp);
+
+      *cp = _DBUS_DUMMY_CONDVAR;
+
+      link = _dbus_list_get_next_link (&uninitialized_condvar_list, link);
+    }
+
+ fail_mutex:
+  link = uninitialized_rmutex_list;
+  while (link != NULL)
+    {
+      DBusRMutex **mp;
+
+      mp = link->data;
+
+      if (*mp != _DBUS_DUMMY_RMUTEX && *mp != NULL)
+        _dbus_platform_rmutex_free (*mp);
+
+      *mp = _DBUS_DUMMY_RMUTEX;
+
+      link = _dbus_list_get_next_link (&uninitialized_rmutex_list, link);
+    }
+
+  link = uninitialized_cmutex_list;
+  while (link != NULL)
+    {
+      DBusCMutex **mp;
+
+      mp = link->data;
+
+      if (*mp != _DBUS_DUMMY_CMUTEX && *mp != NULL)
+        _dbus_platform_cmutex_free (*mp);
+
+      *mp = _DBUS_DUMMY_CMUTEX;
+
+      link = _dbus_list_get_next_link (&uninitialized_cmutex_list, link);
+    }
+
+  return FALSE;
+}
+
+static dbus_bool_t
+init_locks (void)
+{
+  int i;
+  DBusRMutex ***dynamic_global_locks;
+  DBusRMutex **global_locks[] = {
+#define LOCK_ADDR(name) (& _dbus_lock_##name)
+    LOCK_ADDR (win_fds),
+    LOCK_ADDR (sid_atom_cache),
+    LOCK_ADDR (list),
+    LOCK_ADDR (connection_slots),
+    LOCK_ADDR (pending_call_slots),
+    LOCK_ADDR (server_slots),
+    LOCK_ADDR (message_slots),
+#if !DBUS_USE_SYNC
+    LOCK_ADDR (atomic),
+#endif
+    LOCK_ADDR (bus),
+    LOCK_ADDR (bus_datas),
+    LOCK_ADDR (shutdown_funcs),
+    LOCK_ADDR (system_users),
+    LOCK_ADDR (message_cache),
+    LOCK_ADDR (shared_connections),
+    LOCK_ADDR (machine_uuid)
+#undef LOCK_ADDR
+  };
+
+  _dbus_assert (_DBUS_N_ELEMENTS (global_locks) ==
+                _DBUS_N_GLOBAL_LOCKS);
+
+  i = 0;
+  
+  dynamic_global_locks = dbus_new (DBusRMutex**, _DBUS_N_GLOBAL_LOCKS);
+  if (dynamic_global_locks == NULL)
+    goto failed;
+  
+  while (i < _DBUS_N_ELEMENTS (global_locks))
+    {
+      *global_locks[i] = _dbus_platform_rmutex_new ();
+
+      if (*global_locks[i] == NULL)
+        goto failed;
+
+      dynamic_global_locks[i] = global_locks[i];
+
+      ++i;
+    }
+  
+  if (!_dbus_register_shutdown_func (shutdown_global_locks,
+                                     dynamic_global_locks))
+    goto failed;
+
+  if (!init_uninitialized_locks ())
+    goto failed;
+  
+  return TRUE;
+
+ failed:
+  dbus_free (dynamic_global_locks);
+                                     
+  for (i = i - 1; i >= 0; i--)
+    {
+      _dbus_platform_rmutex_free (*global_locks[i]);
+      *global_locks[i] = NULL;
+    }
+  return FALSE;
+}
+
+/** @} */ /* end of internals */
+
+/**
+ * @defgroup DBusThreads Thread functions
+ * @ingroup  DBus
+ * @brief dbus_threads_init() and dbus_threads_init_default()
+ *
+ * Functions and macros related to threads and thread locks.
+ *
+ * If threads are initialized, the D-Bus library has locks on all
+ * global data structures.  In addition, each #DBusConnection has a
+ * lock, so only one thread at a time can touch the connection.  (See
+ * @ref DBusConnection for more on connection locking.)
+ *
+ * Most other objects, however, do not have locks - they can only be
+ * used from a single thread at a time, unless you lock them yourself.
+ * For example, a #DBusMessage can't be modified from two threads
+ * at once.
+ * 
+ * @{
+ */
+
+/**
+ * Initializes threads, like dbus_threads_init_default().
+ * This version previously allowed user-specified threading
+ * primitives, but since D-Bus 1.6 it ignores them and behaves
+ * exactly like dbus_threads_init_default().
+ *
+ * @param functions ignored, formerly functions for using threads
+ * @returns #TRUE on success, #FALSE if no memory
+ */
+dbus_bool_t
+dbus_threads_init (const DBusThreadFunctions *functions)
+{
+  if (thread_init_generation == _dbus_current_generation)
+    return TRUE;
+
+  if (!init_locks ())
+    return FALSE;
+
+  thread_init_generation = _dbus_current_generation;
+  
+  return TRUE;
+}
+
+
+
+/* Default thread implemenation */
+
+/**
+ * Initializes threads. If this function is not called, the D-Bus
+ * library will not lock any data structures.  If it is called, D-Bus
+ * will do locking, at some cost in efficiency. Note that this
+ * function must be called BEFORE the second thread is started.
+ *
+ * It's safe to call dbus_threads_init_default() as many times as you
+ * want, but only the first time will have an effect.
+ *
+ * dbus_shutdown() reverses the effects of this function when it
+ * resets all global state in libdbus.
+ * 
+ * @returns #TRUE on success, #FALSE if not enough memory
+ */
+dbus_bool_t
+dbus_threads_init_default (void)
+{
+  return _dbus_threads_init_platform_specific ();
+}
+
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+
+dbus_bool_t
+_dbus_threads_init_debug (void)
+{
+  return _dbus_threads_init_platform_specific();
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-threads.h b/dbus/dbus/dbus-threads.h
new file mode 100644
index 0000000..6d28a0b
--- /dev/null
+++ b/dbus/dbus/dbus-threads.h
@@ -0,0 +1,189 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-threads.h  D-Bus threads handling
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_THREADS_H
+#define DBUS_THREADS_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-types.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusThreads
+ * @{
+ */
+
+/** An opaque mutex type provided by the #DBusThreadFunctions implementation installed by dbus_threads_init(). */
+typedef struct DBusMutex DBusMutex;
+/** An opaque condition variable type provided by the #DBusThreadFunctions implementation installed by dbus_threads_init(). */
+typedef struct DBusCondVar DBusCondVar;
+
+/** Deprecated, provide DBusRecursiveMutexNewFunction instead. */
+typedef DBusMutex*  (* DBusMutexNewFunction)    (void);
+/** Deprecated, provide DBusRecursiveMutexFreeFunction instead. */
+typedef void        (* DBusMutexFreeFunction)   (DBusMutex *mutex);
+/** Deprecated, provide DBusRecursiveMutexLockFunction instead. Return value is lock success, but gets ignored in practice. */
+typedef dbus_bool_t (* DBusMutexLockFunction)   (DBusMutex *mutex);
+/** Deprecated, provide DBusRecursiveMutexUnlockFunction instead. Return value is unlock success, but gets ignored in practice. */
+typedef dbus_bool_t (* DBusMutexUnlockFunction) (DBusMutex *mutex);
+
+/** Creates a new recursively-lockable mutex, or returns #NULL if not
+ * enough memory.  Can only fail due to lack of memory.  Found in
+ * #DBusThreadFunctions. Do not just use PTHREAD_MUTEX_RECURSIVE for
+ * this, because it does not save/restore the recursion count when
+ * waiting on a condition. libdbus requires the Java-style behavior
+ * where the mutex is fully unlocked to wait on a condition.
+ */
+typedef DBusMutex*  (* DBusRecursiveMutexNewFunction)    (void);
+/** Frees a recursively-lockable mutex.  Found in #DBusThreadFunctions.
+ */
+typedef void        (* DBusRecursiveMutexFreeFunction)   (DBusMutex *mutex);
+/** Locks a recursively-lockable mutex.  Found in #DBusThreadFunctions.
+ * Can only fail due to lack of memory.
+ */
+typedef void        (* DBusRecursiveMutexLockFunction)   (DBusMutex *mutex);
+/** Unlocks a recursively-lockable mutex.  Found in #DBusThreadFunctions.
+ * Can only fail due to lack of memory.
+ */
+typedef void        (* DBusRecursiveMutexUnlockFunction) (DBusMutex *mutex);
+
+/** Creates a new condition variable.  Found in #DBusThreadFunctions.
+ * Can only fail (returning #NULL) due to lack of memory.
+ */
+typedef DBusCondVar*  (* DBusCondVarNewFunction)         (void);
+/** Frees a condition variable.  Found in #DBusThreadFunctions.
+ */
+typedef void          (* DBusCondVarFreeFunction)        (DBusCondVar *cond);
+
+/** Waits on a condition variable.  Found in
+ * #DBusThreadFunctions. Must work with either a recursive or
+ * nonrecursive mutex, whichever the thread implementation
+ * provides. Note that PTHREAD_MUTEX_RECURSIVE does not work with
+ * condition variables (does not save/restore the recursion count) so
+ * don't try using simply pthread_cond_wait() and a
+ * PTHREAD_MUTEX_RECURSIVE to implement this, it won't work right.
+ *
+ * Has no error conditions. Must succeed if it returns.
+ */
+typedef void          (* DBusCondVarWaitFunction)        (DBusCondVar *cond,
+							  DBusMutex   *mutex);
+
+/** Waits on a condition variable with a timeout.  Found in
+ *  #DBusThreadFunctions. Returns #TRUE if the wait did not
+ *  time out, and #FALSE if it did.
+ *
+ * Has no error conditions. Must succeed if it returns. 
+ */
+typedef dbus_bool_t   (* DBusCondVarWaitTimeoutFunction) (DBusCondVar *cond,
+							  DBusMutex   *mutex,
+							  int          timeout_milliseconds);
+/** Wakes one waiting thread on a condition variable.  Found in #DBusThreadFunctions.
+ *
+ * Has no error conditions. Must succeed if it returns.
+ */
+typedef void          (* DBusCondVarWakeOneFunction) (DBusCondVar *cond);
+
+/** Wakes all waiting threads on a condition variable.  Found in #DBusThreadFunctions.
+ *
+ * Has no error conditions. Must succeed if it returns.
+ */
+typedef void          (* DBusCondVarWakeAllFunction) (DBusCondVar *cond);
+
+/**
+ * Flags indicating which functions are present in #DBusThreadFunctions. Used to allow
+ * the library to detect older callers of dbus_threads_init() if new possible functions
+ * are added to #DBusThreadFunctions.
+ */
+typedef enum 
+{
+  DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK      = 1 << 0,
+  DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK     = 1 << 1,
+  DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK     = 1 << 2,
+  DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK   = 1 << 3,
+  DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK    = 1 << 4,
+  DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK   = 1 << 5,
+  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK   = 1 << 6,
+  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK   = 1 << 7,
+  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK = 1 << 8,
+  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK = 1 << 9,
+  DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_NEW_MASK    = 1 << 10,
+  DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_FREE_MASK   = 1 << 11,
+  DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_LOCK_MASK   = 1 << 12,
+  DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_UNLOCK_MASK = 1 << 13,
+  DBUS_THREAD_FUNCTIONS_ALL_MASK     = (1 << 14) - 1
+} DBusThreadFunctionsMask;
+
+/**
+ * Functions that must be implemented to make the D-Bus library
+ * thread-aware.
+ *
+ * If you supply both recursive and non-recursive mutexes,
+ * libdbus will use the non-recursive version for condition variables,
+ * and the recursive version in other contexts.
+ *
+ * The condition variable functions have to work with nonrecursive
+ * mutexes if you provide those, or with recursive mutexes if you
+ * don't.
+ */
+typedef struct
+{
+  unsigned int mask; /**< Mask indicating which functions are present. */
+
+  DBusMutexNewFunction mutex_new; /**< Function to create a mutex; optional and deprecated. */
+  DBusMutexFreeFunction mutex_free; /**< Function to free a mutex; optional and deprecated. */
+  DBusMutexLockFunction mutex_lock; /**< Function to lock a mutex; optional and deprecated. */
+  DBusMutexUnlockFunction mutex_unlock; /**< Function to unlock a mutex; optional and deprecated. */
+
+  DBusCondVarNewFunction condvar_new; /**< Function to create a condition variable */
+  DBusCondVarFreeFunction condvar_free; /**< Function to free a condition variable */
+  DBusCondVarWaitFunction condvar_wait; /**< Function to wait on a condition */
+  DBusCondVarWaitTimeoutFunction condvar_wait_timeout; /**< Function to wait on a condition with a timeout */
+  DBusCondVarWakeOneFunction condvar_wake_one; /**< Function to wake one thread waiting on the condition */
+  DBusCondVarWakeAllFunction condvar_wake_all; /**< Function to wake all threads waiting on the condition */
+ 
+  DBusRecursiveMutexNewFunction recursive_mutex_new; /**< Function to create a recursive mutex */
+  DBusRecursiveMutexFreeFunction recursive_mutex_free; /**< Function to free a recursive mutex */
+  DBusRecursiveMutexLockFunction recursive_mutex_lock; /**< Function to lock a recursive mutex */
+  DBusRecursiveMutexUnlockFunction recursive_mutex_unlock; /**< Function to unlock a recursive mutex */
+
+  void (* padding1) (void); /**< Reserved for future expansion */
+  void (* padding2) (void); /**< Reserved for future expansion */
+  void (* padding3) (void); /**< Reserved for future expansion */
+  void (* padding4) (void); /**< Reserved for future expansion */
+  
+} DBusThreadFunctions;
+
+DBUS_EXPORT
+dbus_bool_t  dbus_threads_init         (const DBusThreadFunctions *functions);
+DBUS_EXPORT
+dbus_bool_t  dbus_threads_init_default (void);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_THREADS_H */
diff --git a/dbus/dbus/dbus-timeout.c b/dbus/dbus/dbus-timeout.c
new file mode 100644
index 0000000..a1d6ce5
--- /dev/null
+++ b/dbus/dbus/dbus-timeout.c
@@ -0,0 +1,491 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-timeout.c DBusTimeout implementation
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-timeout.h"
+#include "dbus-list.h"
+
+/**
+ * @defgroup DBusTimeoutInternals DBusTimeout implementation details
+ * @ingroup  DBusInternals
+ * @brief implementation details for DBusTimeout
+ * 
+ * @{
+ */
+
+/**
+ * Internals of DBusTimeout
+ */
+struct DBusTimeout
+{
+  int refcount;                                /**< Reference count */
+  int interval;                                /**< Timeout interval in milliseconds. */
+
+  DBusTimeoutHandler handler;                  /**< Timeout handler. */
+  void *handler_data;                          /**< Timeout handler data. */
+  DBusFreeFunction free_handler_data_function; /**< Free the timeout handler data. */
+  
+  void *data;		   	               /**< Application data. */
+  DBusFreeFunction free_data_function;         /**< Free the application data. */
+  unsigned int enabled : 1;                    /**< True if timeout is active. */
+};
+
+/**
+ * Creates a new DBusTimeout, enabled by default.
+ * @param interval the timeout interval in milliseconds.
+ * @param handler function to call when the timeout occurs.
+ * @param data data to pass to the handler
+ * @param free_data_function function to be called to free the data.
+ * @returns the new DBusTimeout object,
+ */
+DBusTimeout*
+_dbus_timeout_new (int                 interval,
+		   DBusTimeoutHandler  handler,
+		   void               *data,
+		   DBusFreeFunction    free_data_function)
+{
+  DBusTimeout *timeout;
+
+  timeout = dbus_new0 (DBusTimeout, 1);
+  if (timeout == NULL)
+    return NULL;
+  
+  timeout->refcount = 1;
+  timeout->interval = interval;
+
+  timeout->handler = handler;
+  timeout->handler_data = data;
+  timeout->free_handler_data_function = free_data_function;
+
+  timeout->enabled = TRUE;
+  
+  return timeout;
+}
+
+/**
+ * Increments the reference count of a DBusTimeout object.
+ *
+ * @param timeout the timeout object.
+ * @returns the timeout object.
+ */
+DBusTimeout *
+_dbus_timeout_ref (DBusTimeout *timeout)
+{
+  timeout->refcount += 1;
+
+  return timeout;
+}
+
+/**
+ * Decrements the reference count of a DBusTimeout object
+ * and finalizes the object if the count reaches zero.
+ *
+ * @param timeout the timeout object.
+ */
+void
+_dbus_timeout_unref (DBusTimeout *timeout)
+{
+  _dbus_assert (timeout != NULL);
+  _dbus_assert (timeout->refcount > 0);
+  
+  timeout->refcount -= 1;
+  if (timeout->refcount == 0)
+    {
+      dbus_timeout_set_data (timeout, NULL, NULL); /* call free_data_function */
+
+      if (timeout->free_handler_data_function)
+	(* timeout->free_handler_data_function) (timeout->handler_data);
+      
+      dbus_free (timeout);
+    }
+}
+
+/**
+ * Changes the timeout interval. Note that you have to disable and
+ * re-enable the timeout using the timeout toggle function
+ * (_dbus_connection_toggle_timeout_unlocked() etc.) to notify the
+ * application of this change.
+ *
+ * @param timeout the timeout
+ * @param interval the new interval
+ */
+void
+_dbus_timeout_set_interval (DBusTimeout *timeout,
+                            int          interval)
+{
+  _dbus_assert (interval >= 0);
+  
+  timeout->interval = interval;
+}
+
+/**
+ * Changes the timeout's enabled-ness. Note that you should use
+ * _dbus_connection_toggle_timeout_unlocked() etc. instead, if
+ * the timeout is passed out to an application main loop.
+ * i.e. you can't use this function in the D-Bus library, it's
+ * only used in the message bus daemon implementation.
+ *
+ * @param timeout the timeout
+ * @param enabled #TRUE if timeout should be enabled.
+ */
+void
+_dbus_timeout_set_enabled (DBusTimeout  *timeout,
+                           dbus_bool_t   enabled)
+{
+  timeout->enabled = enabled != FALSE;
+}
+
+
+/**
+ * @typedef DBusTimeoutList
+ *
+ * Opaque data type representing a list of timeouts
+ * and a set of DBusAddTimeoutFunction/DBusRemoveTimeoutFunction.
+ * Automatically handles removing/re-adding timeouts
+ * when the DBusAddTimeoutFunction is updated or changed.
+ * Holds a reference count to each timeout.
+ *
+ */
+
+/**
+ * DBusTimeoutList implementation details. All fields
+ * are private.
+ *
+ */
+struct DBusTimeoutList
+{
+  DBusList *timeouts; /**< Timeout objects. */
+
+  DBusAddTimeoutFunction add_timeout_function;       /**< Callback for adding a timeout. */
+  DBusRemoveTimeoutFunction remove_timeout_function; /**< Callback for removing a timeout. */
+  DBusTimeoutToggledFunction timeout_toggled_function; /**< Callback when timeout is enabled/disabled or changes interval */
+  void *timeout_data;                                /**< Data for timeout callbacks */
+  DBusFreeFunction timeout_free_data_function;       /**< Free function for timeout callback data */
+};
+
+/**
+ * Creates a new timeout list. Returns #NULL if insufficient
+ * memory exists.
+ *
+ * @returns the new timeout list, or #NULL on failure.
+ */
+DBusTimeoutList*
+_dbus_timeout_list_new (void)
+{
+  DBusTimeoutList *timeout_list;
+
+  timeout_list = dbus_new0 (DBusTimeoutList, 1);
+  if (timeout_list == NULL)
+    return NULL;
+
+  return timeout_list;
+}
+
+/**
+ * Frees a DBusTimeoutList.
+ *
+ * @param timeout_list the timeout list.
+ */
+void
+_dbus_timeout_list_free (DBusTimeoutList *timeout_list)
+{
+  /* free timeout_data and remove timeouts as a side effect */
+  _dbus_timeout_list_set_functions (timeout_list,
+				    NULL, NULL, NULL, NULL, NULL);
+
+  _dbus_list_foreach (&timeout_list->timeouts,
+		      (DBusForeachFunction) _dbus_timeout_unref,
+		      NULL);
+  _dbus_list_clear (&timeout_list->timeouts);
+
+  dbus_free (timeout_list);
+}
+
+/**
+ * Sets the timeout functions. This function is the "backend"
+ * for dbus_connection_set_timeout_functions().
+ *
+ * @param timeout_list the timeout list
+ * @param add_function the add timeout function.
+ * @param remove_function the remove timeout function.
+ * @param toggled_function toggle notify function, or #NULL
+ * @param data the data for those functions.
+ * @param free_data_function the function to free the data.
+ * @returns #FALSE if no memory
+ *
+ */
+dbus_bool_t
+_dbus_timeout_list_set_functions (DBusTimeoutList           *timeout_list,
+				  DBusAddTimeoutFunction     add_function,
+				  DBusRemoveTimeoutFunction  remove_function,
+                                  DBusTimeoutToggledFunction toggled_function,
+				  void                      *data,
+				  DBusFreeFunction           free_data_function)
+{
+  /* Add timeouts with the new function, failing on OOM */
+  if (add_function != NULL)
+    {
+      DBusList *link;
+      
+      link = _dbus_list_get_first_link (&timeout_list->timeouts);
+      while (link != NULL)
+        {
+          DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts,
+                                                     link);
+      
+          if (!(* add_function) (link->data, data))
+            {
+              /* remove it all again and return FALSE */
+              DBusList *link2;
+              
+              link2 = _dbus_list_get_first_link (&timeout_list->timeouts);
+              while (link2 != link)
+                {
+                  DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts,
+                                                             link2);
+
+                  (* remove_function) (link2->data, data);
+                  
+                  link2 = next;
+                }
+
+              return FALSE;
+            }
+      
+          link = next;
+        }
+    }
+  
+  /* Remove all current timeouts from previous timeout handlers */
+
+  if (timeout_list->remove_timeout_function != NULL)
+    {
+      _dbus_list_foreach (&timeout_list->timeouts,
+			  (DBusForeachFunction) timeout_list->remove_timeout_function,
+			  timeout_list->timeout_data);
+    }
+
+  if (timeout_list->timeout_free_data_function != NULL)
+    (* timeout_list->timeout_free_data_function) (timeout_list->timeout_data);
+
+  timeout_list->add_timeout_function = add_function;
+  timeout_list->remove_timeout_function = remove_function;
+  timeout_list->timeout_toggled_function = toggled_function;
+  timeout_list->timeout_data = data;
+  timeout_list->timeout_free_data_function = free_data_function;
+
+  return TRUE;
+}
+
+/**
+ * Adds a new timeout to the timeout list, invoking the
+ * application DBusAddTimeoutFunction if appropriate.
+ *
+ * @param timeout_list the timeout list.
+ * @param timeout the timeout to add.
+ * @returns #TRUE on success, #FALSE If no memory.
+ */
+dbus_bool_t
+_dbus_timeout_list_add_timeout (DBusTimeoutList *timeout_list,
+				DBusTimeout     *timeout)
+{
+  if (!_dbus_list_append (&timeout_list->timeouts, timeout))
+    return FALSE;
+
+  _dbus_timeout_ref (timeout);
+
+  if (timeout_list->add_timeout_function != NULL)
+    {
+      if (!(* timeout_list->add_timeout_function) (timeout,
+                                                   timeout_list->timeout_data))
+        {
+          _dbus_list_remove_last (&timeout_list->timeouts, timeout);
+          _dbus_timeout_unref (timeout);
+          return FALSE;
+        }
+    }
+
+  return TRUE;
+}
+
+/**
+ * Removes a timeout from the timeout list, invoking the
+ * application's DBusRemoveTimeoutFunction if appropriate.
+ *
+ * @param timeout_list the timeout list.
+ * @param timeout the timeout to remove.
+ */
+void
+_dbus_timeout_list_remove_timeout (DBusTimeoutList *timeout_list,
+				   DBusTimeout     *timeout)
+{
+  if (!_dbus_list_remove (&timeout_list->timeouts, timeout))
+    _dbus_assert_not_reached ("Nonexistent timeout was removed");
+
+  if (timeout_list->remove_timeout_function != NULL)
+    (* timeout_list->remove_timeout_function) (timeout,
+					       timeout_list->timeout_data);
+
+  _dbus_timeout_unref (timeout);
+}
+
+/**
+ * Sets a timeout to the given enabled state, invoking the
+ * application's DBusTimeoutToggledFunction if appropriate.
+ *
+ * @param timeout_list the timeout list.
+ * @param timeout the timeout to toggle.
+ * @param enabled #TRUE to enable
+ */
+void
+_dbus_timeout_list_toggle_timeout (DBusTimeoutList           *timeout_list,
+                                   DBusTimeout               *timeout,
+                                   dbus_bool_t                enabled)
+{
+  enabled = !!enabled;
+  
+  if (enabled == timeout->enabled)
+    return;
+
+  timeout->enabled = enabled;
+  
+  if (timeout_list->timeout_toggled_function != NULL)
+    (* timeout_list->timeout_toggled_function) (timeout,
+                                                timeout_list->timeout_data);
+}
+
+/** @} */
+
+/**
+ * @defgroup DBusTimeout DBusTimeout
+ * @ingroup  DBus
+ * @brief Object representing a timeout
+ *
+ * Types and functions related to DBusTimeout. A timeout
+ * represents a timeout that the main loop needs to monitor,
+ * as in Qt's QTimer or GLib's g_timeout_add().
+ *
+ * Use dbus_connection_set_timeout_functions() or dbus_server_set_timeout_functions()
+ * to be notified when libdbus needs to add or remove timeouts.
+ * 
+ * @{
+ */
+
+
+/**
+ * @typedef DBusTimeout
+ *
+ * Opaque object representing a timeout.
+ */
+
+/**
+ * Gets the timeout interval. The dbus_timeout_handle()
+ * should be called each time this interval elapses,
+ * starting after it elapses once.
+ *
+ * The interval may change during the life of the
+ * timeout; if so, the timeout will be disabled and
+ * re-enabled (calling the "timeout toggled function")
+ * to notify you of the change.
+ *
+ * @param timeout the DBusTimeout object.
+ * @returns the interval in milliseconds.
+ */
+int
+dbus_timeout_get_interval (DBusTimeout *timeout)
+{
+  return timeout->interval;
+}
+
+/**
+ * Gets data previously set with dbus_timeout_set_data()
+ * or #NULL if none.
+ *
+ * @param timeout the DBusTimeout object.
+ * @returns previously-set data.
+ */
+void*
+dbus_timeout_get_data (DBusTimeout *timeout)
+{
+  return timeout->data;
+}
+
+/**
+ * Sets data which can be retrieved with dbus_timeout_get_data().
+ * Intended for use by the DBusAddTimeoutFunction and
+ * DBusRemoveTimeoutFunction to store their own data.  For example with
+ * Qt you might store the QTimer for this timeout and with GLib
+ * you might store a g_timeout_add result id.
+ *
+ * @param timeout the DBusTimeout object.
+ * @param data the data.
+ * @param free_data_function function to be called to free the data.
+ */
+void
+dbus_timeout_set_data (DBusTimeout      *timeout,
+		       void             *data,
+		       DBusFreeFunction  free_data_function)
+{
+  if (timeout->free_data_function != NULL)
+    (* timeout->free_data_function) (timeout->data);
+
+  timeout->data = data;
+  timeout->free_data_function = free_data_function;
+}
+
+/**
+ * Calls the timeout handler for this timeout.
+ * This function should be called when the timeout
+ * occurs.
+ *
+ * If this function returns #FALSE, then there wasn't
+ * enough memory to handle the timeout. Typically just
+ * letting the timeout fire again next time it naturally
+ * times out is an adequate response to that problem,
+ * but you could try to do more if you wanted.
+ *
+ * @param timeout the DBusTimeout object.
+ * @returns #FALSE if there wasn't enough memory 
+ */
+dbus_bool_t
+dbus_timeout_handle (DBusTimeout *timeout)
+{
+  return (* timeout->handler) (timeout->handler_data);
+}
+
+
+/**
+ * Returns whether a timeout is enabled or not. If not
+ * enabled, it should not be polled by the main loop.
+ *
+ * @param timeout the DBusTimeout object
+ * @returns #TRUE if the timeout is enabled
+ */
+dbus_bool_t
+dbus_timeout_get_enabled (DBusTimeout *timeout)
+{
+  return timeout->enabled;
+}
+
+/** @} end public API docs */
diff --git a/dbus/dbus/dbus-timeout.h b/dbus/dbus/dbus-timeout.h
new file mode 100644
index 0000000..d0a8af4
--- /dev/null
+++ b/dbus/dbus/dbus-timeout.h
@@ -0,0 +1,75 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-timeout.h DBusTimeout internal interfaces
+ *
+ * Copyright (C) 2003  CodeFactory AB
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_TIMEOUT_H
+#define DBUS_TIMEOUT_H
+
+#include <dbus/dbus-connection.h>
+#include <dbus/dbus-internals.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusTimeoutInternals
+ * @{
+ */
+
+/* Public methods on DBusTimeout are in dbus-connection.h */
+
+typedef struct DBusTimeoutList DBusTimeoutList;
+
+/** function to run when the timeout is handled */
+typedef dbus_bool_t (* DBusTimeoutHandler) (void *data);
+
+DBusTimeout* _dbus_timeout_new          (int                 interval,
+                                         DBusTimeoutHandler  handler,
+                                         void               *data,
+                                         DBusFreeFunction    free_data_function);
+DBusTimeout* _dbus_timeout_ref          (DBusTimeout        *timeout);
+void         _dbus_timeout_unref        (DBusTimeout        *timeout);
+void         _dbus_timeout_set_interval (DBusTimeout        *timeout,
+                                         int                 interval);
+void         _dbus_timeout_set_enabled  (DBusTimeout        *timeout,
+                                         dbus_bool_t         enabled);
+
+DBusTimeoutList *_dbus_timeout_list_new            (void);
+void             _dbus_timeout_list_free           (DBusTimeoutList           *timeout_list);
+dbus_bool_t      _dbus_timeout_list_set_functions  (DBusTimeoutList           *timeout_list,
+						    DBusAddTimeoutFunction     add_function,
+						    DBusRemoveTimeoutFunction  remove_function,
+                                                    DBusTimeoutToggledFunction toggled_function,
+						    void                      *data,
+						    DBusFreeFunction           free_data_function);
+dbus_bool_t      _dbus_timeout_list_add_timeout    (DBusTimeoutList           *timeout_list,
+						    DBusTimeout               *timeout);
+void             _dbus_timeout_list_remove_timeout (DBusTimeoutList           *timeout_list,
+						    DBusTimeout               *timeout);
+void             _dbus_timeout_list_toggle_timeout (DBusTimeoutList           *timeout_list,
+                                                    DBusTimeout               *timeout,
+                                                    dbus_bool_t                enabled);
+
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_TIMEOUT_H */
diff --git a/dbus/dbus/dbus-transport-protected.h b/dbus/dbus/dbus-transport-protected.h
new file mode 100644
index 0000000..44b9d78
--- /dev/null
+++ b/dbus/dbus/dbus-transport-protected.h
@@ -0,0 +1,146 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-transport-protected.h Used by subclasses of DBusTransport object (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002, 2004  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_TRANSPORT_PROTECTED_H
+#define DBUS_TRANSPORT_PROTECTED_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-transport.h>
+#include <dbus/dbus-message-internal.h>
+#include <dbus/dbus-auth.h>
+#include <dbus/dbus-resources.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusTransportVTable DBusTransportVTable;
+
+/**
+ * The virtual table that must be implemented to
+ * create a new kind of transport.
+ */
+struct DBusTransportVTable
+{
+  void        (* finalize)              (DBusTransport *transport);
+  /**< The finalize method must free the transport. */
+
+  dbus_bool_t (* handle_watch)          (DBusTransport *transport,
+                                         DBusWatch     *watch,
+                                         unsigned int   flags);
+  /**< The handle_watch method handles reading/writing
+   * data as indicated by the flags.
+   */
+
+  void        (* disconnect)            (DBusTransport *transport);
+  /**< Disconnect this transport. */
+
+  dbus_bool_t (* connection_set)        (DBusTransport *transport);
+  /**< Called when transport->connection has been filled in */
+
+  void        (* do_iteration)          (DBusTransport *transport,
+                                         unsigned int   flags,
+                                         int            timeout_milliseconds);
+  /**< Called to do a single "iteration" (block on select/poll
+   * followed by reading or writing data).
+   */
+
+  void        (* live_messages_changed) (DBusTransport *transport);
+  /**< Outstanding messages counter changed */
+
+  dbus_bool_t (* get_socket_fd) (DBusTransport *transport,
+                                 int           *fd_p);
+  /**< Get socket file descriptor */
+};
+
+/**
+ * Object representing a transport such as a socket.
+ * A transport can shuttle messages from point A to point B,
+ * and is the backend for a #DBusConnection.
+ *
+ */
+struct DBusTransport
+{
+  int refcount;                               /**< Reference count. */
+
+  const DBusTransportVTable *vtable;          /**< Virtual methods for this instance. */
+
+  DBusConnection *connection;                 /**< Connection owning this transport. */
+
+  DBusMessageLoader *loader;                  /**< Message-loading buffer. */
+
+  DBusAuth *auth;                             /**< Authentication conversation */
+
+  DBusCredentials *credentials;               /**< Credentials of other end read from the socket */  
+
+  long max_live_messages_size;                /**< Max total size of received messages. */
+  long max_live_messages_unix_fds;            /**< Max total unix fds of received messages. */
+
+  DBusCounter *live_messages;                 /**< Counter for size/unix fds of all live messages. */
+
+  char *address;                              /**< Address of the server we are connecting to (#NULL for the server side of a transport) */
+
+  char *expected_guid;                        /**< GUID we expect the server to have, #NULL on server side or if we don't have an expectation */
+  
+  DBusAllowUnixUserFunction unix_user_function; /**< Function for checking whether a user is authorized. */
+  void *unix_user_data;                         /**< Data for unix_user_function */
+  
+  DBusFreeFunction free_unix_user_data;         /**< Function to free unix_user_data */
+
+  DBusAllowWindowsUserFunction windows_user_function; /**< Function for checking whether a user is authorized. */
+  void *windows_user_data;                            /**< Data for windows_user_function */
+  
+  DBusFreeFunction free_windows_user_data;            /**< Function to free windows_user_data */
+  
+  unsigned int disconnected : 1;              /**< #TRUE if we are disconnected. */
+  unsigned int authenticated : 1;             /**< Cache of auth state; use _dbus_transport_get_is_authenticated() to query value */
+  unsigned int send_credentials_pending : 1;  /**< #TRUE if we need to send credentials */
+  unsigned int receive_credentials_pending : 1; /**< #TRUE if we need to receive credentials */
+  unsigned int is_server : 1;                 /**< #TRUE if on the server side */
+  unsigned int unused_bytes_recovered : 1;    /**< #TRUE if we've recovered unused bytes from auth */
+  unsigned int allow_anonymous : 1;           /**< #TRUE if an anonymous client can connect */
+};
+
+dbus_bool_t _dbus_transport_init_base     (DBusTransport             *transport,
+                                           const DBusTransportVTable *vtable,
+                                           const DBusString          *server_guid,
+                                           const DBusString          *address);
+void        _dbus_transport_finalize_base (DBusTransport             *transport);
+
+
+typedef enum
+{
+  DBUS_TRANSPORT_OPEN_NOT_HANDLED,    /**< we aren't in charge of this address type */
+  DBUS_TRANSPORT_OPEN_OK,             /**< we set up the listen */
+  DBUS_TRANSPORT_OPEN_BAD_ADDRESS,    /**< malformed address */
+  DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT /**< well-formed address but failed to set it up */
+} DBusTransportOpenResult;
+
+DBusTransportOpenResult _dbus_transport_open_platform_specific (DBusAddressEntry  *entry,
+                                                                DBusTransport    **transport_p,
+                                                                DBusError         *error);
+
+#define DBUS_TRANSPORT_CAN_SEND_UNIX_FD(x)      \
+  _dbus_auth_get_unix_fd_negotiated((x)->auth)
+
+DBUS_END_DECLS
+
+#endif /* DBUS_TRANSPORT_PROTECTED_H */
diff --git a/dbus/dbus/dbus-transport-socket.c b/dbus/dbus/dbus-transport-socket.c
new file mode 100644
index 0000000..544d00a
--- /dev/null
+++ b/dbus/dbus/dbus-transport-socket.c
@@ -0,0 +1,1438 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-transport-socket.c  Socket subclasses of DBusTransport
+ *
+ * Copyright (C) 2002, 2003, 2004, 2006  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-connection-internal.h"
+#include "dbus-nonce.h"
+#include "dbus-transport-socket.h"
+#include "dbus-transport-protected.h"
+#include "dbus-watch.h"
+#include "dbus-credentials.h"
+
+/**
+ * @defgroup DBusTransportSocket DBusTransport implementations for sockets
+ * @ingroup  DBusInternals
+ * @brief Implementation details of DBusTransport on sockets
+ *
+ * @{
+ */
+
+/**
+ * Opaque object representing a socket file descriptor transport.
+ */
+typedef struct DBusTransportSocket DBusTransportSocket;
+
+/**
+ * Implementation details of DBusTransportSocket. All members are private.
+ */
+struct DBusTransportSocket
+{
+  DBusTransport base;                   /**< Parent instance */
+  int fd;                               /**< File descriptor. */
+  DBusWatch *read_watch;                /**< Watch for readability. */
+  DBusWatch *write_watch;               /**< Watch for writability. */
+
+  int max_bytes_read_per_iteration;     /**< To avoid blocking too long. */
+  int max_bytes_written_per_iteration;  /**< To avoid blocking too long. */
+
+  int message_bytes_written;            /**< Number of bytes of current
+                                         *   outgoing message that have
+                                         *   been written.
+                                         */
+  DBusString encoded_outgoing;          /**< Encoded version of current
+                                         *   outgoing message.
+                                         */
+  DBusString encoded_incoming;          /**< Encoded version of current
+                                         *   incoming data.
+                                         */
+};
+
+static void
+free_watches (DBusTransport *transport)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+
+  _dbus_verbose ("start\n");
+  
+  if (socket_transport->read_watch)
+    {
+      if (transport->connection)
+        _dbus_connection_remove_watch_unlocked (transport->connection,
+                                                socket_transport->read_watch);
+      _dbus_watch_invalidate (socket_transport->read_watch);
+      _dbus_watch_unref (socket_transport->read_watch);
+      socket_transport->read_watch = NULL;
+    }
+
+  if (socket_transport->write_watch)
+    {
+      if (transport->connection)
+        _dbus_connection_remove_watch_unlocked (transport->connection,
+                                                socket_transport->write_watch);
+      _dbus_watch_invalidate (socket_transport->write_watch);
+      _dbus_watch_unref (socket_transport->write_watch);
+      socket_transport->write_watch = NULL;
+    }
+
+  _dbus_verbose ("end\n");
+}
+
+static void
+socket_finalize (DBusTransport *transport)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+
+  _dbus_verbose ("\n");
+  
+  free_watches (transport);
+
+  _dbus_string_free (&socket_transport->encoded_outgoing);
+  _dbus_string_free (&socket_transport->encoded_incoming);
+  
+  _dbus_transport_finalize_base (transport);
+
+  _dbus_assert (socket_transport->read_watch == NULL);
+  _dbus_assert (socket_transport->write_watch == NULL);
+  
+  dbus_free (transport);
+}
+
+static void
+check_write_watch (DBusTransport *transport)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+  dbus_bool_t needed;
+
+  if (transport->connection == NULL)
+    return;
+
+  if (transport->disconnected)
+    {
+      _dbus_assert (socket_transport->write_watch == NULL);
+      return;
+    }
+  
+  _dbus_transport_ref (transport);
+
+  if (_dbus_transport_get_is_authenticated (transport))
+    needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection);
+  else
+    {
+      if (transport->send_credentials_pending)
+        needed = TRUE;
+      else
+        {
+          DBusAuthState auth_state;
+          
+          auth_state = _dbus_auth_do_work (transport->auth);
+          
+          /* If we need memory we install the write watch just in case,
+           * if there's no need for it, it will get de-installed
+           * next time we try reading.
+           */
+          if (auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND ||
+              auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
+            needed = TRUE;
+          else
+            needed = FALSE;
+        }
+    }
+
+  _dbus_verbose ("check_write_watch(): needed = %d on connection %p watch %p fd = %d outgoing messages exist %d\n",
+                 needed, transport->connection, socket_transport->write_watch,
+                 socket_transport->fd,
+                 _dbus_connection_has_messages_to_send_unlocked (transport->connection));
+
+  _dbus_connection_toggle_watch_unlocked (transport->connection,
+                                          socket_transport->write_watch,
+                                          needed);
+
+  _dbus_transport_unref (transport);
+}
+
+static void
+check_read_watch (DBusTransport *transport)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+  dbus_bool_t need_read_watch;
+
+  _dbus_verbose ("fd = %d\n",socket_transport->fd);
+  
+  if (transport->connection == NULL)
+    return;
+
+  if (transport->disconnected)
+    {
+      _dbus_assert (socket_transport->read_watch == NULL);
+      return;
+    }
+  
+  _dbus_transport_ref (transport);
+
+  if (_dbus_transport_get_is_authenticated (transport))
+    need_read_watch =
+      (_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) &&
+      (_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds);
+  else
+    {
+      if (transport->receive_credentials_pending)
+        need_read_watch = TRUE;
+      else
+        {
+          /* The reason to disable need_read_watch when not WAITING_FOR_INPUT
+           * is to avoid spinning on the file descriptor when we're waiting
+           * to write or for some other part of the auth process
+           */
+          DBusAuthState auth_state;
+          
+          auth_state = _dbus_auth_do_work (transport->auth);
+
+          /* If we need memory we install the read watch just in case,
+           * if there's no need for it, it will get de-installed
+           * next time we try reading. If we're authenticated we
+           * install it since we normally have it installed while
+           * authenticated.
+           */
+          if (auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT ||
+              auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY ||
+              auth_state == DBUS_AUTH_STATE_AUTHENTICATED)
+            need_read_watch = TRUE;
+          else
+            need_read_watch = FALSE;
+        }
+    }
+
+  _dbus_verbose ("  setting read watch enabled = %d\n", need_read_watch);
+  _dbus_connection_toggle_watch_unlocked (transport->connection,
+                                          socket_transport->read_watch,
+                                          need_read_watch);
+
+  _dbus_transport_unref (transport);
+}
+
+static void
+do_io_error (DBusTransport *transport)
+{
+  _dbus_transport_ref (transport);
+  _dbus_transport_disconnect (transport);
+  _dbus_transport_unref (transport);
+}
+
+/* return value is whether we successfully read any new data. */
+static dbus_bool_t
+read_data_into_auth (DBusTransport *transport,
+                     dbus_bool_t   *oom)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+  DBusString *buffer;
+  int bytes_read;
+  
+  *oom = FALSE;
+
+  _dbus_auth_get_buffer (transport->auth, &buffer);
+  
+  bytes_read = _dbus_read_socket (socket_transport->fd,
+                                  buffer, socket_transport->max_bytes_read_per_iteration);
+
+  _dbus_auth_return_buffer (transport->auth, buffer,
+                            bytes_read > 0 ? bytes_read : 0);
+
+  if (bytes_read > 0)
+    {
+      _dbus_verbose (" read %d bytes in auth phase\n", bytes_read);
+
+      return TRUE;
+    }
+  else if (bytes_read < 0)
+    {
+      /* EINTR already handled for us */
+
+      if (_dbus_get_is_errno_enomem ())
+        {
+          *oom = TRUE;
+        }
+      else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
+        ; /* do nothing, just return FALSE below */
+      else
+        {
+          _dbus_verbose ("Error reading from remote app: %s\n",
+                         _dbus_strerror_from_errno ());
+          do_io_error (transport);
+        }
+
+      return FALSE;
+    }
+  else
+    {
+      _dbus_assert (bytes_read == 0);
+      
+      _dbus_verbose ("Disconnected from remote app\n");
+      do_io_error (transport);
+
+      return FALSE;
+    }
+}
+
+/* Return value is whether we successfully wrote any bytes */
+static dbus_bool_t
+write_data_from_auth (DBusTransport *transport)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+  int bytes_written;
+  const DBusString *buffer;
+
+  if (!_dbus_auth_get_bytes_to_send (transport->auth,
+                                     &buffer))
+    return FALSE;
+  
+  bytes_written = _dbus_write_socket (socket_transport->fd,
+                                      buffer,
+                                      0, _dbus_string_get_length (buffer));
+
+  if (bytes_written > 0)
+    {
+      _dbus_auth_bytes_sent (transport->auth, bytes_written);
+      return TRUE;
+    }
+  else if (bytes_written < 0)
+    {
+      /* EINTR already handled for us */
+      
+      if (_dbus_get_is_errno_eagain_or_ewouldblock ())
+        ;
+      else
+        {
+          _dbus_verbose ("Error writing to remote app: %s\n",
+                         _dbus_strerror_from_errno ());
+          do_io_error (transport);
+        }
+    }
+
+  return FALSE;
+}
+
+/* FALSE on OOM */
+static dbus_bool_t
+exchange_credentials (DBusTransport *transport,
+                      dbus_bool_t    do_reading,
+                      dbus_bool_t    do_writing)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+  DBusError error = DBUS_ERROR_INIT;
+
+  _dbus_verbose ("exchange_credentials: do_reading = %d, do_writing = %d\n",
+                  do_reading, do_writing);
+
+  if (do_writing && transport->send_credentials_pending)
+    {
+      if (_dbus_send_credentials_socket (socket_transport->fd,
+                                         &error))
+        {
+          transport->send_credentials_pending = FALSE;
+        }
+      else
+        {
+          _dbus_verbose ("Failed to write credentials: %s\n", error.message);
+          dbus_error_free (&error);
+          do_io_error (transport);
+        }
+    }
+  
+  if (do_reading && transport->receive_credentials_pending)
+    {
+      /* FIXME this can fail due to IO error _or_ OOM, broken
+       * (somewhat tricky to fix since the OOM error can be set after
+       * we already read the credentials byte, so basically we need to
+       * separate reading the byte and storing it in the
+       * transport->credentials). Does not really matter for now
+       * because storing in credentials never actually fails on unix.
+       */      
+      if (_dbus_read_credentials_socket (socket_transport->fd,
+                                         transport->credentials,
+                                         &error))
+        {
+          transport->receive_credentials_pending = FALSE;
+        }
+      else
+        {
+          _dbus_verbose ("Failed to read credentials %s\n", error.message);
+          dbus_error_free (&error);
+          do_io_error (transport);
+        }
+    }
+
+  if (!(transport->send_credentials_pending ||
+        transport->receive_credentials_pending))
+    {
+      if (!_dbus_auth_set_credentials (transport->auth,
+                                       transport->credentials))
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+do_authentication (DBusTransport *transport,
+                   dbus_bool_t    do_reading,
+                   dbus_bool_t    do_writing,
+		   dbus_bool_t   *auth_completed)
+{
+  dbus_bool_t oom;
+  dbus_bool_t orig_auth_state;
+
+  oom = FALSE;
+  
+  orig_auth_state = _dbus_transport_get_is_authenticated (transport);
+
+  /* This is essential to avoid the check_write_watch() at the end,
+   * we don't want to add a write watch in do_iteration before
+   * we try writing and get EAGAIN
+   */
+  if (orig_auth_state)
+    {
+      if (auth_completed)
+        *auth_completed = FALSE;
+      return TRUE;
+    }
+  
+  _dbus_transport_ref (transport);
+  
+  while (!_dbus_transport_get_is_authenticated (transport) &&
+         _dbus_transport_get_is_connected (transport))
+    {      
+      if (!exchange_credentials (transport, do_reading, do_writing))
+        {
+          /* OOM */
+          oom = TRUE;
+          goto out;
+        }
+      
+      if (transport->send_credentials_pending ||
+          transport->receive_credentials_pending)
+        {
+          _dbus_verbose ("send_credentials_pending = %d receive_credentials_pending = %d\n",
+                         transport->send_credentials_pending,
+                         transport->receive_credentials_pending);
+          goto out;
+        }
+
+#define TRANSPORT_SIDE(t) ((t)->is_server ? "server" : "client")
+      switch (_dbus_auth_do_work (transport->auth))
+        {
+        case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
+          _dbus_verbose (" %s auth state: waiting for input\n",
+                         TRANSPORT_SIDE (transport));
+          if (!do_reading || !read_data_into_auth (transport, &oom))
+            goto out;
+          break;
+      
+        case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
+          _dbus_verbose (" %s auth state: waiting for memory\n",
+                         TRANSPORT_SIDE (transport));
+          oom = TRUE;
+          goto out;
+          break;
+      
+        case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
+          _dbus_verbose (" %s auth state: bytes to send\n",
+                         TRANSPORT_SIDE (transport));
+          if (!do_writing || !write_data_from_auth (transport))
+            goto out;
+          break;
+      
+        case DBUS_AUTH_STATE_NEED_DISCONNECT:
+          _dbus_verbose (" %s auth state: need to disconnect\n",
+                         TRANSPORT_SIDE (transport));
+          do_io_error (transport);
+          break;
+      
+        case DBUS_AUTH_STATE_AUTHENTICATED:
+          _dbus_verbose (" %s auth state: authenticated\n",
+                         TRANSPORT_SIDE (transport));
+          break;
+        }
+    }
+
+ out:
+  if (auth_completed)
+    *auth_completed = (orig_auth_state != _dbus_transport_get_is_authenticated (transport));
+  
+  check_read_watch (transport);
+  check_write_watch (transport);
+  _dbus_transport_unref (transport);
+
+  if (oom)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/* returns false on oom */
+static dbus_bool_t
+do_writing (DBusTransport *transport)
+{
+  int total;
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+  dbus_bool_t oom;
+  
+  /* No messages without authentication! */
+  if (!_dbus_transport_get_is_authenticated (transport))
+    {
+      _dbus_verbose ("Not authenticated, not writing anything\n");
+      return TRUE;
+    }
+
+  if (transport->disconnected)
+    {
+      _dbus_verbose ("Not connected, not writing anything\n");
+      return TRUE;
+    }
+
+#if 1
+  _dbus_verbose ("do_writing(), have_messages = %d, fd = %d\n",
+                 _dbus_connection_has_messages_to_send_unlocked (transport->connection),
+                 socket_transport->fd);
+#endif
+  
+  oom = FALSE;
+  total = 0;
+
+  while (!transport->disconnected &&
+         _dbus_connection_has_messages_to_send_unlocked (transport->connection))
+    {
+      int bytes_written;
+      DBusMessage *message;
+      const DBusString *header;
+      const DBusString *body;
+      int header_len, body_len;
+      int total_bytes_to_write;
+      
+      if (total > socket_transport->max_bytes_written_per_iteration)
+        {
+          _dbus_verbose ("%d bytes exceeds %d bytes written per iteration, returning\n",
+                         total, socket_transport->max_bytes_written_per_iteration);
+          goto out;
+        }
+      
+      message = _dbus_connection_get_message_to_send (transport->connection);
+      _dbus_assert (message != NULL);
+      dbus_message_lock (message);
+
+#if 0
+      _dbus_verbose ("writing message %p\n", message);
+#endif
+      
+      _dbus_message_get_network_data (message,
+                                      &header, &body);
+
+      header_len = _dbus_string_get_length (header);
+      body_len = _dbus_string_get_length (body);
+
+      if (_dbus_auth_needs_encoding (transport->auth))
+        {
+          /* Does fd passing even make sense with encoded data? */
+          _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
+
+          if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0)
+            {
+              if (!_dbus_auth_encode_data (transport->auth,
+                                           header, &socket_transport->encoded_outgoing))
+                {
+                  oom = TRUE;
+                  goto out;
+                }
+              
+              if (!_dbus_auth_encode_data (transport->auth,
+                                           body, &socket_transport->encoded_outgoing))
+                {
+                  _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
+                  oom = TRUE;
+                  goto out;
+                }
+            }
+          
+          total_bytes_to_write = _dbus_string_get_length (&socket_transport->encoded_outgoing);
+
+#if 0
+          _dbus_verbose ("encoded message is %d bytes\n",
+                         total_bytes_to_write);
+#endif
+          
+          bytes_written =
+            _dbus_write_socket (socket_transport->fd,
+                                &socket_transport->encoded_outgoing,
+                                socket_transport->message_bytes_written,
+                                total_bytes_to_write - socket_transport->message_bytes_written);
+        }
+      else
+        {
+          total_bytes_to_write = header_len + body_len;
+
+#if 0
+          _dbus_verbose ("message is %d bytes\n",
+                         total_bytes_to_write);
+#endif
+
+#ifdef HAVE_UNIX_FD_PASSING
+          if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
+            {
+              /* Send the fds along with the first byte of the message */
+              const int *unix_fds;
+              unsigned n;
+
+              _dbus_message_get_unix_fds(message, &unix_fds, &n);
+
+              bytes_written =
+                _dbus_write_socket_with_unix_fds_two (socket_transport->fd,
+                                                      header,
+                                                      socket_transport->message_bytes_written,
+                                                      header_len - socket_transport->message_bytes_written,
+                                                      body,
+                                                      0, body_len,
+                                                      unix_fds,
+                                                      n);
+
+              if (bytes_written > 0 && n > 0)
+                _dbus_verbose("Wrote %i unix fds\n", n);
+            }
+          else
+#endif
+            {
+              if (socket_transport->message_bytes_written < header_len)
+                {
+                  bytes_written =
+                    _dbus_write_socket_two (socket_transport->fd,
+                                            header,
+                                            socket_transport->message_bytes_written,
+                                            header_len - socket_transport->message_bytes_written,
+                                            body,
+                                            0, body_len);
+                }
+              else
+                {
+                  bytes_written =
+                    _dbus_write_socket (socket_transport->fd,
+                                        body,
+                                        (socket_transport->message_bytes_written - header_len),
+                                        body_len -
+                                        (socket_transport->message_bytes_written - header_len));
+                }
+            }
+        }
+
+      if (bytes_written < 0)
+        {
+          /* EINTR already handled for us */
+          
+          /* For some discussion of why we also ignore EPIPE here, see
+           * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html
+           */
+          
+          if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ())
+            goto out;
+          else
+            {
+              _dbus_verbose ("Error writing to remote app: %s\n",
+                             _dbus_strerror_from_errno ());
+              do_io_error (transport);
+              goto out;
+            }
+        }
+      else
+        {
+          _dbus_verbose (" wrote %d bytes of %d\n", bytes_written,
+                         total_bytes_to_write);
+          
+          total += bytes_written;
+          socket_transport->message_bytes_written += bytes_written;
+
+          _dbus_assert (socket_transport->message_bytes_written <=
+                        total_bytes_to_write);
+          
+          if (socket_transport->message_bytes_written == total_bytes_to_write)
+            {
+              socket_transport->message_bytes_written = 0;
+              _dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
+              _dbus_string_compact (&socket_transport->encoded_outgoing, 2048);
+
+              _dbus_connection_message_sent_unlocked (transport->connection,
+                                                      message);
+            }
+        }
+    }
+
+ out:
+  if (oom)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/* returns false on out-of-memory */
+static dbus_bool_t
+do_reading (DBusTransport *transport)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+  DBusString *buffer;
+  int bytes_read;
+  int total;
+  dbus_bool_t oom;
+
+  _dbus_verbose ("fd = %d\n",socket_transport->fd);
+  
+  /* No messages without authentication! */
+  if (!_dbus_transport_get_is_authenticated (transport))
+    return TRUE;
+
+  oom = FALSE;
+  
+  total = 0;
+
+ again:
+  
+  /* See if we've exceeded max messages and need to disable reading */
+  check_read_watch (transport);
+  
+  if (total > socket_transport->max_bytes_read_per_iteration)
+    {
+      _dbus_verbose ("%d bytes exceeds %d bytes read per iteration, returning\n",
+                     total, socket_transport->max_bytes_read_per_iteration);
+      goto out;
+    }
+
+  _dbus_assert (socket_transport->read_watch != NULL ||
+                transport->disconnected);
+  
+  if (transport->disconnected)
+    goto out;
+
+  if (!dbus_watch_get_enabled (socket_transport->read_watch))
+    return TRUE;
+  
+  if (_dbus_auth_needs_decoding (transport->auth))
+    {
+      /* Does fd passing even make sense with encoded data? */
+      _dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
+
+      if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0)
+        bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming);
+      else
+        bytes_read = _dbus_read_socket (socket_transport->fd,
+                                        &socket_transport->encoded_incoming,
+                                        socket_transport->max_bytes_read_per_iteration);
+
+      _dbus_assert (_dbus_string_get_length (&socket_transport->encoded_incoming) ==
+                    bytes_read);
+      
+      if (bytes_read > 0)
+        {
+          int orig_len;
+          
+          _dbus_message_loader_get_buffer (transport->loader,
+                                           &buffer);
+
+          orig_len = _dbus_string_get_length (buffer);
+          
+          if (!_dbus_auth_decode_data (transport->auth,
+                                       &socket_transport->encoded_incoming,
+                                       buffer))
+            {
+              _dbus_verbose ("Out of memory decoding incoming data\n");
+              _dbus_message_loader_return_buffer (transport->loader,
+                                              buffer,
+                                              _dbus_string_get_length (buffer) - orig_len);
+
+              oom = TRUE;
+              goto out;
+            }
+
+          _dbus_message_loader_return_buffer (transport->loader,
+                                              buffer,
+                                              _dbus_string_get_length (buffer) - orig_len);
+
+          _dbus_string_set_length (&socket_transport->encoded_incoming, 0);
+          _dbus_string_compact (&socket_transport->encoded_incoming, 2048);
+        }
+    }
+  else
+    {
+      _dbus_message_loader_get_buffer (transport->loader,
+                                       &buffer);
+
+#ifdef HAVE_UNIX_FD_PASSING
+      if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
+        {
+          int *fds, n_fds;
+
+          if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds))
+            {
+              _dbus_verbose ("Out of memory reading file descriptors\n");
+              _dbus_message_loader_return_buffer (transport->loader, buffer, 0);
+              oom = TRUE;
+              goto out;
+            }
+
+          bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd,
+                                                       buffer,
+                                                       socket_transport->max_bytes_read_per_iteration,
+                                                       fds, &n_fds);
+
+          if (bytes_read >= 0 && n_fds > 0)
+            _dbus_verbose("Read %i unix fds\n", n_fds);
+
+          _dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds);
+        }
+      else
+#endif
+        {
+          bytes_read = _dbus_read_socket (socket_transport->fd,
+                                          buffer, socket_transport->max_bytes_read_per_iteration);
+        }
+
+      _dbus_message_loader_return_buffer (transport->loader,
+                                          buffer,
+                                          bytes_read < 0 ? 0 : bytes_read);
+    }
+  
+  if (bytes_read < 0)
+    {
+      /* EINTR already handled for us */
+
+      if (_dbus_get_is_errno_enomem ())
+        {
+          _dbus_verbose ("Out of memory in read()/do_reading()\n");
+          oom = TRUE;
+          goto out;
+        }
+      else if (_dbus_get_is_errno_eagain_or_ewouldblock ())
+        goto out;
+      else
+        {
+          _dbus_verbose ("Error reading from remote app: %s\n",
+                         _dbus_strerror_from_errno ());
+          do_io_error (transport);
+          goto out;
+        }
+    }
+  else if (bytes_read == 0)
+    {
+      _dbus_verbose ("Disconnected from remote app\n");
+      do_io_error (transport);
+      goto out;
+    }
+  else
+    {
+      _dbus_verbose (" read %d bytes\n", bytes_read);
+      
+      total += bytes_read;      
+
+      if (!_dbus_transport_queue_messages (transport))
+        {
+          oom = TRUE;
+          _dbus_verbose (" out of memory when queueing messages we just read in the transport\n");
+          goto out;
+        }
+      
+      /* Try reading more data until we get EAGAIN and return, or
+       * exceed max bytes per iteration.  If in blocking mode of
+       * course we'll block instead of returning.
+       */
+      goto again;
+    }
+
+ out:
+  if (oom)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+static dbus_bool_t
+unix_error_with_read_to_come (DBusTransport *itransport,
+                              DBusWatch     *watch,
+                              unsigned int   flags)
+{
+  DBusTransportSocket *transport = (DBusTransportSocket *) itransport;
+
+  if (!(flags & DBUS_WATCH_HANGUP || flags & DBUS_WATCH_ERROR))
+    return FALSE;
+   
+  /* If we have a read watch enabled ...
+     we -might have data incoming ... => handle the HANGUP there */
+  if (watch != transport->read_watch &&
+      _dbus_watch_get_enabled (transport->read_watch))
+    return FALSE;
+      
+  return TRUE; 
+}
+
+static dbus_bool_t
+socket_handle_watch (DBusTransport *transport,
+                   DBusWatch     *watch,
+                   unsigned int   flags)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+
+  _dbus_assert (watch == socket_transport->read_watch ||
+                watch == socket_transport->write_watch);
+  _dbus_assert (watch != NULL);
+  
+  /* If we hit an error here on a write watch, don't disconnect the transport yet because data can
+   * still be in the buffer and do_reading may need several iteration to read
+   * it all (because of its max_bytes_read_per_iteration limit). 
+   */
+  if (!(flags & DBUS_WATCH_READABLE) && unix_error_with_read_to_come (transport, watch, flags))
+    {
+      _dbus_verbose ("Hang up or error on watch\n");
+      _dbus_transport_disconnect (transport);
+      return TRUE;
+    }
+  
+  if (watch == socket_transport->read_watch &&
+      (flags & DBUS_WATCH_READABLE))
+    {
+      dbus_bool_t auth_finished;
+#if 1
+      _dbus_verbose ("handling read watch %p flags = %x\n",
+                     watch, flags);
+#endif
+      if (!do_authentication (transport, TRUE, FALSE, &auth_finished))
+        return FALSE;
+
+      /* We don't want to do a read immediately following
+       * a successful authentication.  This is so we
+       * have a chance to propagate the authentication
+       * state further up.  Specifically, we need to
+       * process any pending data from the auth object.
+       */
+      if (!auth_finished)
+	{
+	  if (!do_reading (transport))
+	    {
+	      _dbus_verbose ("no memory to read\n");
+	      return FALSE;
+	    }
+	}
+      else
+        {
+          _dbus_verbose ("Not reading anything since we just completed the authentication\n");
+        }
+    }
+  else if (watch == socket_transport->write_watch &&
+           (flags & DBUS_WATCH_WRITABLE))
+    {
+#if 1
+      _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n",
+                     _dbus_connection_has_messages_to_send_unlocked (transport->connection));
+#endif
+      if (!do_authentication (transport, FALSE, TRUE, NULL))
+        return FALSE;
+      
+      if (!do_writing (transport))
+        {
+          _dbus_verbose ("no memory to write\n");
+          return FALSE;
+        }
+
+      /* See if we still need the write watch */
+      check_write_watch (transport);
+    }
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  else
+    {
+      if (watch == socket_transport->read_watch)
+        _dbus_verbose ("asked to handle read watch with non-read condition 0x%x\n",
+                       flags);
+      else if (watch == socket_transport->write_watch)
+        _dbus_verbose ("asked to handle write watch with non-write condition 0x%x\n",
+                       flags);
+      else
+        _dbus_verbose ("asked to handle watch %p on fd %d that we don't recognize\n",
+                       watch, dbus_watch_get_socket (watch));
+    }
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+
+  return TRUE;
+}
+
+static void
+socket_disconnect (DBusTransport *transport)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+
+  _dbus_verbose ("\n");
+  
+  free_watches (transport);
+  
+  _dbus_close_socket (socket_transport->fd, NULL);
+  socket_transport->fd = -1;
+}
+
+static dbus_bool_t
+socket_connection_set (DBusTransport *transport)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+
+  _dbus_watch_set_handler (socket_transport->write_watch,
+                           _dbus_connection_handle_watch,
+                           transport->connection, NULL);
+
+  _dbus_watch_set_handler (socket_transport->read_watch,
+                           _dbus_connection_handle_watch,
+                           transport->connection, NULL);
+  
+  if (!_dbus_connection_add_watch_unlocked (transport->connection,
+                                            socket_transport->write_watch))
+    return FALSE;
+
+  if (!_dbus_connection_add_watch_unlocked (transport->connection,
+                                            socket_transport->read_watch))
+    {
+      _dbus_connection_remove_watch_unlocked (transport->connection,
+                                              socket_transport->write_watch);
+      return FALSE;
+    }
+
+  check_read_watch (transport);
+  check_write_watch (transport);
+
+  return TRUE;
+}
+
+/**
+ * @todo We need to have a way to wake up the select sleep if
+ * a new iteration request comes in with a flag (read/write) that
+ * we're not currently serving. Otherwise a call that just reads
+ * could block a write call forever (if there are no incoming
+ * messages).
+ */
+static  void
+socket_do_iteration (DBusTransport *transport,
+                   unsigned int   flags,
+                   int            timeout_milliseconds)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+  DBusPollFD poll_fd;
+  int poll_res;
+  int poll_timeout;
+
+  _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n",
+                 flags & DBUS_ITERATION_DO_READING ? "read" : "",
+                 flags & DBUS_ITERATION_DO_WRITING ? "write" : "",
+                 timeout_milliseconds,
+                 socket_transport->read_watch,
+                 socket_transport->write_watch,
+                 socket_transport->fd);
+  
+  /* the passed in DO_READING/DO_WRITING flags indicate whether to
+   * read/write messages, but regardless of those we may need to block
+   * for reading/writing to do auth.  But if we do reading for auth,
+   * we don't want to read any messages yet if not given DO_READING.
+   */
+
+  poll_fd.fd = socket_transport->fd;
+  poll_fd.events = 0;
+  
+  if (_dbus_transport_get_is_authenticated (transport))
+    {
+      /* This is kind of a hack; if we have stuff to write, then try
+       * to avoid the poll. This is probably about a 5% speedup on an
+       * echo client/server.
+       *
+       * If both reading and writing were requested, we want to avoid this
+       * since it could have funky effects:
+       *   - both ends spinning waiting for the other one to read
+       *     data so they can finish writing
+       *   - prioritizing all writing ahead of reading
+       */
+      if ((flags & DBUS_ITERATION_DO_WRITING) &&
+          !(flags & (DBUS_ITERATION_DO_READING | DBUS_ITERATION_BLOCK)) &&
+          !transport->disconnected &&
+          _dbus_connection_has_messages_to_send_unlocked (transport->connection))
+        {
+          do_writing (transport);
+
+          if (transport->disconnected ||
+              !_dbus_connection_has_messages_to_send_unlocked (transport->connection))
+            goto out;
+        }
+
+      /* If we get here, we decided to do the poll() after all */
+      _dbus_assert (socket_transport->read_watch);
+      if (flags & DBUS_ITERATION_DO_READING)
+	poll_fd.events |= _DBUS_POLLIN;
+
+      _dbus_assert (socket_transport->write_watch);
+      if (flags & DBUS_ITERATION_DO_WRITING)
+        poll_fd.events |= _DBUS_POLLOUT;
+    }
+  else
+    {
+      DBusAuthState auth_state;
+      
+      auth_state = _dbus_auth_do_work (transport->auth);
+
+      if (transport->receive_credentials_pending ||
+          auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT)
+	poll_fd.events |= _DBUS_POLLIN;
+
+      if (transport->send_credentials_pending ||
+          auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
+	poll_fd.events |= _DBUS_POLLOUT;
+    }
+
+  if (poll_fd.events)
+    {
+      if (flags & DBUS_ITERATION_BLOCK)
+	poll_timeout = timeout_milliseconds;
+      else
+	poll_timeout = 0;
+
+      /* For blocking selects we drop the connection lock here
+       * to avoid blocking out connection access during a potentially
+       * indefinite blocking call. The io path is still protected
+       * by the io_path_cond condvar, so we won't reenter this.
+       */
+      if (flags & DBUS_ITERATION_BLOCK)
+        {
+          _dbus_verbose ("unlock pre poll\n");
+          _dbus_connection_unlock (transport->connection);
+        }
+      
+    again:
+      poll_res = _dbus_poll (&poll_fd, 1, poll_timeout);
+
+      if (poll_res < 0 && _dbus_get_is_errno_eintr ())
+	goto again;
+
+      if (flags & DBUS_ITERATION_BLOCK)
+        {
+          _dbus_verbose ("lock post poll\n");
+          _dbus_connection_lock (transport->connection);
+        }
+      
+      if (poll_res >= 0)
+        {
+          if (poll_res == 0)
+            poll_fd.revents = 0; /* some concern that posix does not guarantee this;
+                                  * valgrind flags it as an error. though it probably
+                                  * is guaranteed on linux at least.
+                                  */
+          
+          if (poll_fd.revents & _DBUS_POLLERR)
+            do_io_error (transport);
+          else
+            {
+              dbus_bool_t need_read = (poll_fd.revents & _DBUS_POLLIN) > 0;
+              dbus_bool_t need_write = (poll_fd.revents & _DBUS_POLLOUT) > 0;
+	      dbus_bool_t authentication_completed;
+
+              _dbus_verbose ("in iteration, need_read=%d need_write=%d\n",
+                             need_read, need_write);
+              do_authentication (transport, need_read, need_write,
+				 &authentication_completed);
+
+	      /* See comment in socket_handle_watch. */
+	      if (authentication_completed)
+                goto out;
+                                 
+              if (need_read && (flags & DBUS_ITERATION_DO_READING))
+                do_reading (transport);
+              if (need_write && (flags & DBUS_ITERATION_DO_WRITING))
+                do_writing (transport);
+            }
+        }
+      else
+        {
+          _dbus_verbose ("Error from _dbus_poll(): %s\n",
+                         _dbus_strerror_from_errno ());
+        }
+    }
+
+
+ out:
+  /* We need to install the write watch only if we did not
+   * successfully write everything. Note we need to be careful that we
+   * don't call check_write_watch *before* do_writing, since it's
+   * inefficient to add the write watch, and we can avoid it most of
+   * the time since we can write immediately.
+   * 
+   * However, we MUST always call check_write_watch(); DBusConnection code
+   * relies on the fact that running an iteration will notice that
+   * messages are pending.
+   */
+  check_write_watch (transport);
+
+  _dbus_verbose (" ... leaving do_iteration()\n");
+}
+
+static void
+socket_live_messages_changed (DBusTransport *transport)
+{
+  /* See if we should look for incoming messages again */
+  check_read_watch (transport);
+}
+
+
+static dbus_bool_t
+socket_get_socket_fd (DBusTransport *transport,
+                      int           *fd_p)
+{
+  DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
+  
+  *fd_p = socket_transport->fd;
+  
+  return TRUE;
+}
+
+static const DBusTransportVTable socket_vtable = {
+  socket_finalize,
+  socket_handle_watch,
+  socket_disconnect,
+  socket_connection_set,
+  socket_do_iteration,
+  socket_live_messages_changed,
+  socket_get_socket_fd
+};
+
+/**
+ * Creates a new transport for the given socket file descriptor.  The file
+ * descriptor must be nonblocking (use _dbus_set_fd_nonblocking() to
+ * make it so). This function is shared by various transports that
+ * boil down to a full duplex file descriptor.
+ *
+ * @param fd the file descriptor.
+ * @param server_guid non-#NULL if this transport is on the server side of a connection
+ * @param address the transport's address
+ * @returns the new transport, or #NULL if no memory.
+ */
+DBusTransport*
+_dbus_transport_new_for_socket (int               fd,
+                                const DBusString *server_guid,
+                                const DBusString *address)
+{
+  DBusTransportSocket *socket_transport;
+  
+  socket_transport = dbus_new0 (DBusTransportSocket, 1);
+  if (socket_transport == NULL)
+    return NULL;
+
+  if (!_dbus_string_init (&socket_transport->encoded_outgoing))
+    goto failed_0;
+
+  if (!_dbus_string_init (&socket_transport->encoded_incoming))
+    goto failed_1;
+  
+  socket_transport->write_watch = _dbus_watch_new (fd,
+                                                 DBUS_WATCH_WRITABLE,
+                                                 FALSE,
+                                                 NULL, NULL, NULL);
+  if (socket_transport->write_watch == NULL)
+    goto failed_2;
+  
+  socket_transport->read_watch = _dbus_watch_new (fd,
+                                                DBUS_WATCH_READABLE,
+                                                FALSE,
+                                                NULL, NULL, NULL);
+  if (socket_transport->read_watch == NULL)
+    goto failed_3;
+
+  if (!_dbus_transport_init_base (&socket_transport->base,
+                                  &socket_vtable,
+                                  server_guid, address))
+    goto failed_4;
+
+#ifdef HAVE_UNIX_FD_PASSING
+  _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd));
+#endif
+
+  socket_transport->fd = fd;
+  socket_transport->message_bytes_written = 0;
+  
+  /* These values should probably be tunable or something. */     
+  socket_transport->max_bytes_read_per_iteration = 2048;
+  socket_transport->max_bytes_written_per_iteration = 2048;
+  
+  return (DBusTransport*) socket_transport;
+
+ failed_4:
+  _dbus_watch_invalidate (socket_transport->read_watch);
+  _dbus_watch_unref (socket_transport->read_watch);
+ failed_3:
+  _dbus_watch_invalidate (socket_transport->write_watch);
+  _dbus_watch_unref (socket_transport->write_watch);
+ failed_2:
+  _dbus_string_free (&socket_transport->encoded_incoming);
+ failed_1:
+  _dbus_string_free (&socket_transport->encoded_outgoing);
+ failed_0:
+  dbus_free (socket_transport);
+  return NULL;
+}
+
+/**
+ * Creates a new transport for the given hostname and port.
+ * If host is NULL, it will default to localhost
+ *
+ * @param host the host to connect to
+ * @param port the port to connect to
+ * @param family the address family to connect to
+ * @param path to nonce file
+ * @param error location to store reason for failure.
+ * @returns a new transport, or #NULL on failure.
+ */
+DBusTransport*
+_dbus_transport_new_for_tcp_socket (const char     *host,
+                                    const char     *port,
+                                    const char     *family,
+                                    const char     *noncefile,
+                                    DBusError      *error)
+{
+  int fd;
+  DBusTransport *transport;
+  DBusString address;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (!_dbus_string_init (&address))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  if (host == NULL)
+    host = "localhost";
+
+  if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:"))
+    goto error;
+
+  if (!_dbus_string_append (&address, "host=") ||
+      !_dbus_string_append (&address, host))
+    goto error;
+
+  if (!_dbus_string_append (&address, ",port=") ||
+      !_dbus_string_append (&address, port))
+    goto error;
+
+  if (family != NULL &&
+      (!_dbus_string_append (&address, ",family=") ||
+       !_dbus_string_append (&address, family)))
+    goto error;
+
+  if (noncefile != NULL &&
+      (!_dbus_string_append (&address, ",noncefile=") ||
+       !_dbus_string_append (&address, noncefile)))
+    goto error;
+
+  fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error);
+  if (fd < 0)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      _dbus_string_free (&address);
+      return NULL;
+    }
+
+  _dbus_verbose ("Successfully connected to tcp socket %s:%s\n",
+                 host, port);
+  
+  transport = _dbus_transport_new_for_socket (fd, NULL, &address);
+  _dbus_string_free (&address);
+  if (transport == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      _dbus_close_socket (fd, NULL);
+      fd = -1;
+    }
+
+  return transport;
+
+error:
+  _dbus_string_free (&address);
+  dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+  return NULL;
+}
+
+/**
+ * Opens a TCP socket transport.
+ * 
+ * @param entry the address entry to try opening as a tcp transport.
+ * @param transport_p return location for the opened transport
+ * @param error error to be set
+ * @returns result of the attempt
+ */
+DBusTransportOpenResult
+_dbus_transport_open_socket(DBusAddressEntry  *entry,
+                            DBusTransport    **transport_p,                            
+                            DBusError         *error)
+{
+  const char *method;
+  dbus_bool_t isTcp;
+  dbus_bool_t isNonceTcp;
+  
+  method = dbus_address_entry_get_method (entry);
+  _dbus_assert (method != NULL);
+
+  isTcp = strcmp (method, "tcp") == 0;
+  isNonceTcp = strcmp (method, "nonce-tcp") == 0;
+
+  if (isTcp || isNonceTcp)
+    {
+      const char *host = dbus_address_entry_get_value (entry, "host");
+      const char *port = dbus_address_entry_get_value (entry, "port");
+      const char *family = dbus_address_entry_get_value (entry, "family");
+      const char *noncefile = dbus_address_entry_get_value (entry, "noncefile");
+
+      if ((isNonceTcp == TRUE) != (noncefile != NULL)) {
+          _dbus_set_bad_address (error, method, "noncefile", NULL);
+          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+      }
+
+      if (port == NULL)
+        {
+          _dbus_set_bad_address (error, method, "port", NULL);
+          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+        }
+
+      *transport_p = _dbus_transport_new_for_tcp_socket (host, port, family, noncefile, error);
+      if (*transport_p == NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+          return DBUS_TRANSPORT_OPEN_OK;
+        }
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+      return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
+    }
+}
+
+/** @} */
+
diff --git a/dbus/dbus/dbus-transport-socket.h b/dbus/dbus/dbus-transport-socket.h
new file mode 100644
index 0000000..8aefae3
--- /dev/null
+++ b/dbus/dbus/dbus-transport-socket.h
@@ -0,0 +1,46 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-transport-socket.h Socket subclasses of DBusTransport
+ *
+ * Copyright (C) 2002, 2006  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_TRANSPORT_SOCKET_H
+#define DBUS_TRANSPORT_SOCKET_H
+
+#include <dbus/dbus-transport-protected.h>
+
+DBUS_BEGIN_DECLS
+
+DBusTransport*          _dbus_transport_new_for_socket     (int                fd,
+                                                            const DBusString  *server_guid,
+                                                            const DBusString  *address);
+DBusTransport*          _dbus_transport_new_for_tcp_socket (const char        *host,
+                                                            const char        *port,
+                                                            const char        *family,
+                                                            const char        *noncefile,
+                                                            DBusError         *error);
+DBusTransportOpenResult _dbus_transport_open_socket        (DBusAddressEntry  *entry,
+                                                            DBusTransport    **transport_p,
+                                                            DBusError         *error);
+
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_TRANSPORT_SOCKET_H */
diff --git a/dbus/dbus/dbus-transport-unix.c b/dbus/dbus/dbus-transport-unix.c
new file mode 100644
index 0000000..6ba5c0b
--- /dev/null
+++ b/dbus/dbus/dbus-transport-unix.c
@@ -0,0 +1,442 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-transport-unix.c UNIX socket subclasses of DBusTransport
+ *
+ * Copyright (C) 2002, 2003, 2004  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include "dbus-internals.h"
+#include "dbus-connection-internal.h"
+#include "dbus-transport-unix.h"
+#include "dbus-transport-socket.h"
+#include "dbus-transport-protected.h"
+#include "dbus-watch.h"
+#include "dbus-sysdeps-unix.h"
+#include "dbus-test.h"
+
+/**
+ * @defgroup DBusTransportUnix DBusTransport implementations for UNIX
+ * @ingroup  DBusInternals
+ * @brief Implementation details of DBusTransport on UNIX
+ *
+ * @{
+ */
+
+/**
+ * Creates a new transport for the given Unix domain socket
+ * path. This creates a client-side of a transport.
+ *
+ * @todo once we add a way to escape paths in a dbus
+ * address, this function needs to do escaping.
+ *
+ * @param path the path to the domain socket.
+ * @param abstract #TRUE to use abstract socket namespace
+ * @param error address where an error can be returned.
+ * @returns a new transport, or #NULL on failure.
+ */
+DBusTransport*
+_dbus_transport_new_for_domain_socket (const char     *path,
+                                       dbus_bool_t     abstract,
+                                       DBusError      *error)
+{
+  int fd;
+  DBusTransport *transport;
+  DBusString address;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (!_dbus_string_init (&address))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  fd = -1;
+
+  if ((abstract &&
+       !_dbus_string_append (&address, "unix:abstract=")) ||
+      (!abstract &&
+       !_dbus_string_append (&address, "unix:path=")) ||
+      !_dbus_string_append (&address, path))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed_0;
+    }
+  
+  fd = _dbus_connect_unix_socket (path, abstract, error);
+  if (fd < 0)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed_0;
+    }
+
+  _dbus_verbose ("Successfully connected to unix socket %s\n",
+                 path);
+
+  transport = _dbus_transport_new_for_socket (fd, NULL, &address);
+  if (transport == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed_1;
+    }
+  
+  _dbus_string_free (&address);
+  
+  return transport;
+
+ failed_1:
+  _dbus_close_socket (fd, NULL);
+ failed_0:
+  _dbus_string_free (&address);
+  return NULL;
+}
+
+/**
+ * Creates a new transport for the given binary and arguments. This
+ * creates a client-side of a transport. The process will be forked
+ * off and executed with stdin/stdout connected to a local AF_UNIX
+ * socket.
+ *
+ * @param path the path to the domain socket.
+ * @param argv Parameters list
+ * @param error address where an error can be returned.
+ * @returns a new transport, or #NULL on failure.
+ */
+static DBusTransport*
+_dbus_transport_new_for_exec (const char     *path,
+                              char *const     argv[],
+                              DBusError      *error)
+{
+  int fd;
+  DBusTransport *transport;
+  DBusString address;
+  unsigned i;
+  char *escaped;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (!_dbus_string_init (&address))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  fd = -1;
+
+  escaped = dbus_address_escape_value (path);
+  if (!escaped)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed;
+    }
+
+  if (!_dbus_string_append (&address, "unixexec:path=") ||
+      !_dbus_string_append (&address, escaped))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      dbus_free (escaped);
+      goto failed;
+    }
+
+  dbus_free (escaped);
+
+  if (argv)
+    {
+      for (i = 0; argv[i]; i++)
+        {
+          dbus_bool_t success;
+
+          escaped = dbus_address_escape_value (argv[i]);
+          if (!escaped)
+            {
+              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+              goto failed;
+            }
+
+          success = _dbus_string_append_printf (&address, ",argv%u=%s", i, escaped);
+          dbus_free (escaped);
+
+          if (!success)
+            {
+              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+              goto failed;
+            }
+        }
+    }
+
+  fd = _dbus_connect_exec (path, argv, error);
+  if (fd < 0)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto failed;
+    }
+
+  _dbus_verbose ("Successfully connected to process %s\n",
+                 path);
+
+  transport = _dbus_transport_new_for_socket (fd, NULL, &address);
+  if (transport == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      goto failed;
+    }
+
+  _dbus_string_free (&address);
+
+  return transport;
+
+ failed:
+  if (fd >= 0)
+    _dbus_close_socket (fd, NULL);
+
+  _dbus_string_free (&address);
+  return NULL;
+}
+
+/**
+ * Opens platform specific transport types.
+ * 
+ * @param entry the address entry to try opening
+ * @param transport_p return location for the opened transport
+ * @param error error to be set
+ * @returns result of the attempt
+ */
+DBusTransportOpenResult
+_dbus_transport_open_platform_specific (DBusAddressEntry  *entry,
+                                        DBusTransport    **transport_p,
+                                        DBusError         *error)
+{
+  const char *method;
+  
+  method = dbus_address_entry_get_method (entry);
+  _dbus_assert (method != NULL);
+
+  if (strcmp (method, "unix") == 0)
+    {
+      const char *path = dbus_address_entry_get_value (entry, "path");
+      const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir");
+      const char *abstract = dbus_address_entry_get_value (entry, "abstract");
+          
+      if (tmpdir != NULL)
+        {
+          _dbus_set_bad_address (error, NULL, NULL,
+                                 "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on");
+          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+        }
+          
+      if (path == NULL && abstract == NULL)
+        {
+          _dbus_set_bad_address (error, "unix",
+                                 "path or abstract",
+                                 NULL);
+          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+        }
+
+      if (path != NULL && abstract != NULL)
+        {
+          _dbus_set_bad_address (error, NULL, NULL,
+                                 "can't specify both \"path\" and \"abstract\" options in an address");
+          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+        }
+
+      if (path)
+        *transport_p = _dbus_transport_new_for_domain_socket (path, FALSE,
+                                                           error);
+      else
+        *transport_p = _dbus_transport_new_for_domain_socket (abstract, TRUE,
+                                                           error);
+      if (*transport_p == NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+          return DBUS_TRANSPORT_OPEN_OK;
+        }
+    }
+  else if (strcmp (method, "unixexec") == 0)
+    {
+      const char *path;
+      unsigned i;
+      char **argv;
+
+      path = dbus_address_entry_get_value (entry, "path");
+      if (path == NULL)
+        {
+          _dbus_set_bad_address (error, NULL, NULL,
+                                 "No process path specified");
+          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+        }
+
+      /* First count argv arguments */
+      for (i = 1; ; i++)
+        {
+          char t[4+20+1]; /* "argv" plus space for a formatted base 10 64bit integer, plus NUL */
+
+          snprintf (t, sizeof(t), "argv%u", i);
+
+          if (!dbus_address_entry_get_value (entry, t))
+            break;
+        }
+
+      /* Allocate string array */
+      argv = dbus_new0 (char*, i+1);
+      if (!argv)
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+        }
+
+      /* Fill in string array */
+      for (i = 0; ; i++)
+        {
+          char t[4+20+1];
+          const char *p;
+
+          snprintf (t, sizeof(t), "argv%u", i);
+
+          p = dbus_address_entry_get_value (entry, t);
+          if (!p)
+            {
+              if (i == 0)
+                /* If argv0 isn't specified, fill in the path instead */
+                p = path;
+              else
+                break;
+            }
+
+          argv[i] = _dbus_strdup (p);
+          if (!argv[i])
+            {
+              dbus_free_string_array (argv);
+              dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+              return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+            }
+        }
+
+      *transport_p = _dbus_transport_new_for_exec (path, argv, error);
+      dbus_free_string_array (argv);
+
+      if (*transport_p == NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+          return DBUS_TRANSPORT_OPEN_OK;
+        }
+    }
+#ifdef DBUS_ENABLE_LAUNCHD
+  else if (strcmp (method, "launchd") == 0)
+    {
+      DBusError tmp_error = DBUS_ERROR_INIT;
+      const char *launchd_env_var = dbus_address_entry_get_value (entry, "env");
+      const char *launchd_socket;
+      DBusString socket_path;
+      dbus_bool_t valid_socket;
+
+      if (!_dbus_string_init (&socket_path))
+        {
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      if (launchd_env_var == NULL)
+        {
+          _dbus_set_bad_address (error, "launchd", "env", NULL);
+          return DBUS_TRANSPORT_OPEN_BAD_ADDRESS;
+        }
+
+      valid_socket = _dbus_lookup_launchd_socket (&socket_path, launchd_env_var, error);
+
+      if (dbus_error_is_set(error))
+        {
+          _dbus_string_free(&socket_path);
+          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+        }
+
+      if (!valid_socket)
+        {
+          dbus_set_error(&tmp_error, DBUS_ERROR_BAD_ADDRESS,
+                         "launchd's env var %s does not exist", launchd_env_var);
+          dbus_error_free(error);
+          dbus_move_error(&tmp_error, error);
+          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+        }
+
+      launchd_socket = _dbus_string_get_const_data(&socket_path);
+      *transport_p = _dbus_transport_new_for_domain_socket (launchd_socket, FALSE, error);
+
+      if (*transport_p == NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+          return DBUS_TRANSPORT_OPEN_OK;
+        }
+    }
+#endif
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+      return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
+    }
+}
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+
+dbus_bool_t
+_dbus_transport_unix_test (void)
+{
+  DBusConnection *c;
+  DBusError error;
+  dbus_bool_t ret;
+  const char *address;
+
+  dbus_error_init (&error);
+
+  c = dbus_connection_open ("unixexec:argv0=false,argv1=foobar,path=/bin/false", &error);
+  _dbus_assert (c != NULL);
+  _dbus_assert (!dbus_error_is_set (&error));
+
+  address = _dbus_connection_get_address (c);
+  _dbus_assert (address != NULL);
+
+  /* Let's see if the address got parsed, reordered and formatted correctly */
+  ret = strcmp (address, "unixexec:path=/bin/false,argv0=false,argv1=foobar") == 0;
+
+  dbus_connection_unref (c);
+
+  return ret;
+}
+
+#endif
diff --git a/dbus/dbus/dbus-transport-unix.h b/dbus/dbus/dbus-transport-unix.h
new file mode 100644
index 0000000..783a831
--- /dev/null
+++ b/dbus/dbus/dbus-transport-unix.h
@@ -0,0 +1,37 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-transport-unix.h UNIX socket subclasses of DBusTransport
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_TRANSPORT_UNIX_H
+#define DBUS_TRANSPORT_UNIX_H
+
+#include <dbus/dbus-transport.h>
+
+DBUS_BEGIN_DECLS
+
+DBusTransport* _dbus_transport_new_for_domain_socket (const char       *path,
+                                                      dbus_bool_t       abstract,
+                                                      DBusError        *error);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_TRANSPORT_UNIX_H */
diff --git a/dbus/dbus/dbus-transport-win.c b/dbus/dbus/dbus-transport-win.c
new file mode 100644
index 0000000..8fc1574
--- /dev/null
+++ b/dbus/dbus/dbus-transport-win.c
@@ -0,0 +1,58 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-transport-win.c Windows socket subclasses of DBusTransport
+ *
+ * Copyright (C) 2002, 2003, 2004  Red Hat Inc.
+ * Copyright (C) 2007 Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-connection-internal.h"
+#include "dbus-transport-socket.h"
+#include "dbus-transport-protected.h"
+#include "dbus-watch.h"
+#include "dbus-sysdeps-win.h"
+
+/**
+ * @defgroup DBusTransportUnix DBusTransport implementations for UNIX
+ * @ingroup  DBusInternals
+ * @brief Implementation details of DBusTransport on UNIX
+ *
+ * @{
+ */
+
+/**
+ * Opens platform specific transport types.
+ * 
+ * @param entry the address entry to try opening
+ * @param transport_p return location for the opened transport
+ * @param error error to be set
+ * @returns result of the attempt
+ */
+DBusTransportOpenResult
+_dbus_transport_open_platform_specific (DBusAddressEntry  *entry,
+                                        DBusTransport    **transport_p,
+                                        DBusError         *error)
+{
+  /* currently no Windows-specific transports */
+  return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
+}
+
+/** @} */
diff --git a/dbus/dbus/dbus-transport-win.h b/dbus/dbus/dbus-transport-win.h
new file mode 100644
index 0000000..af997a2
--- /dev/null
+++ b/dbus/dbus/dbus-transport-win.h
@@ -0,0 +1,33 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-transport-win.h Windows socket subclasses of DBusTransport
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ * Copyright (C) 2007 Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_TRANSPORT_WIN_H
+#define DBUS_TRANSPORT_WIN_H
+
+#include <dbus/dbus-transport.h>
+
+DBUS_BEGIN_DECLS
+
+DBUS_END_DECLS
+
+#endif /* DBUS_TRANSPORT_WIN_H */
diff --git a/dbus/dbus/dbus-transport.c b/dbus/dbus/dbus-transport.c
new file mode 100644
index 0000000..6b58fda
--- /dev/null
+++ b/dbus/dbus/dbus-transport.c
@@ -0,0 +1,1516 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-transport.c DBusTransport object (internal to D-Bus implementation)
+ *
+ * Copyright (C) 2002, 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-transport-protected.h"
+#include "dbus-transport-unix.h"
+#include "dbus-transport-socket.h"
+#include "dbus-connection-internal.h"
+#include "dbus-watch.h"
+#include "dbus-auth.h"
+#include "dbus-address.h"
+#include "dbus-credentials.h"
+#include "dbus-mainloop.h"
+#include "dbus-message.h"
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-server-debug-pipe.h"
+#endif
+
+/**
+ * @defgroup DBusTransport DBusTransport object
+ * @ingroup  DBusInternals
+ * @brief "Backend" for a DBusConnection.
+ *
+ * Types and functions related to DBusTransport.  A transport is an
+ * abstraction that can send and receive data via various kinds of
+ * network connections or other IPC mechanisms.
+ * 
+ * @{
+ */
+
+/**
+ * @typedef DBusTransport
+ *
+ * Opaque object representing a way message stream.
+ * DBusTransport abstracts various kinds of actual
+ * transport mechanism, such as different network protocols,
+ * or encryption schemes.
+ */
+
+static void
+live_messages_notify (DBusCounter *counter,
+                           void        *user_data)
+{
+  DBusTransport *transport = user_data;
+
+  _dbus_transport_ref (transport);
+
+#if 0
+  _dbus_verbose ("Size counter value is now %d\n",
+                 (int) _dbus_counter_get_size_value (counter));
+  _dbus_verbose ("Unix FD counter value is now %d\n",
+                 (int) _dbus_counter_get_unix_fd_value (counter));
+#endif
+
+  /* disable or re-enable the read watch for the transport if
+   * required.
+   */
+  if (transport->vtable->live_messages_changed)
+    {
+      _dbus_connection_lock (transport->connection);
+      (* transport->vtable->live_messages_changed) (transport);
+      _dbus_connection_unlock (transport->connection);
+    }
+
+  _dbus_transport_unref (transport);
+}
+
+/**
+ * Initializes the base class members of DBusTransport.  Chained up to
+ * by subclasses in their constructor.  The server GUID is the
+ * globally unique ID for the server creating this connection
+ * and will be #NULL for the client side of a connection. The GUID
+ * is in hex format.
+ *
+ * @param transport the transport being created.
+ * @param vtable the subclass vtable.
+ * @param server_guid non-#NULL if this transport is on the server side of a connection
+ * @param address the address of the transport
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_transport_init_base (DBusTransport             *transport,
+                           const DBusTransportVTable *vtable,
+                           const DBusString          *server_guid,
+                           const DBusString          *address)
+{
+  DBusMessageLoader *loader;
+  DBusAuth *auth;
+  DBusCounter *counter;
+  char *address_copy;
+  DBusCredentials *creds;
+  
+  loader = _dbus_message_loader_new ();
+  if (loader == NULL)
+    return FALSE;
+  
+  if (server_guid)
+    auth = _dbus_auth_server_new (server_guid);
+  else
+    auth = _dbus_auth_client_new ();
+  if (auth == NULL)
+    {
+      _dbus_message_loader_unref (loader);
+      return FALSE;
+    }
+
+  counter = _dbus_counter_new ();
+  if (counter == NULL)
+    {
+      _dbus_auth_unref (auth);
+      _dbus_message_loader_unref (loader);
+      return FALSE;
+    }  
+
+  creds = _dbus_credentials_new ();
+  if (creds == NULL)
+    {
+      _dbus_counter_unref (counter);
+      _dbus_auth_unref (auth);
+      _dbus_message_loader_unref (loader);
+      return FALSE;
+    }
+  
+  if (server_guid)
+    {
+      _dbus_assert (address == NULL);
+      address_copy = NULL;
+    }
+  else
+    {
+      _dbus_assert (address != NULL);
+
+      if (!_dbus_string_copy_data (address, &address_copy))
+        {
+          _dbus_credentials_unref (creds);
+          _dbus_counter_unref (counter);
+          _dbus_auth_unref (auth);
+          _dbus_message_loader_unref (loader);
+          return FALSE;
+        }
+    }
+  
+  transport->refcount = 1;
+  transport->vtable = vtable;
+  transport->loader = loader;
+  transport->auth = auth;
+  transport->live_messages = counter;
+  transport->authenticated = FALSE;
+  transport->disconnected = FALSE;
+  transport->is_server = (server_guid != NULL);
+  transport->send_credentials_pending = !transport->is_server;
+  transport->receive_credentials_pending = transport->is_server;
+  transport->address = address_copy;
+  
+  transport->unix_user_function = NULL;
+  transport->unix_user_data = NULL;
+  transport->free_unix_user_data = NULL;
+
+  transport->windows_user_function = NULL;
+  transport->windows_user_data = NULL;
+  transport->free_windows_user_data = NULL;
+  
+  transport->expected_guid = NULL;
+  
+  /* Try to default to something that won't totally hose the system,
+   * but doesn't impose too much of a limitation.
+   */
+  transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
+
+  /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live
+     should be more than enough */
+  transport->max_live_messages_unix_fds = 4096;
+
+  /* credentials read from socket if any */
+  transport->credentials = creds;
+
+  _dbus_counter_set_notify (transport->live_messages,
+                            transport->max_live_messages_size,
+                            transport->max_live_messages_unix_fds,
+                            live_messages_notify,
+                            transport);
+
+  if (transport->address)
+    _dbus_verbose ("Initialized transport on address %s\n", transport->address);
+
+  return TRUE;
+}
+
+/**
+ * Finalizes base class members of DBusTransport.
+ * Chained up to from subclass finalizers.
+ *
+ * @param transport the transport.
+ */
+void
+_dbus_transport_finalize_base (DBusTransport *transport)
+{
+  if (!transport->disconnected)
+    _dbus_transport_disconnect (transport);
+
+  if (transport->free_unix_user_data != NULL)
+    (* transport->free_unix_user_data) (transport->unix_user_data);
+
+  if (transport->free_windows_user_data != NULL)
+    (* transport->free_windows_user_data) (transport->windows_user_data);
+  
+  _dbus_message_loader_unref (transport->loader);
+  _dbus_auth_unref (transport->auth);
+  _dbus_counter_set_notify (transport->live_messages,
+                            0, 0, NULL, NULL);
+  _dbus_counter_unref (transport->live_messages);
+  dbus_free (transport->address);
+  dbus_free (transport->expected_guid);
+  if (transport->credentials)
+    _dbus_credentials_unref (transport->credentials);
+}
+
+
+/**
+ * Verifies if a given D-Bus address is a valid address
+ * by attempting to connect to it. If it is, returns the
+ * opened DBusTransport object. If it isn't, returns #NULL
+ * and sets @p error.
+ *
+ * @param error address where an error can be returned.
+ * @returns a new transport, or #NULL on failure.
+ */
+static DBusTransport*
+check_address (const char *address, DBusError *error)
+{
+  DBusAddressEntry **entries;
+  DBusTransport *transport = NULL;
+  int len, i;
+
+  _dbus_assert (address != NULL);
+
+  if (!dbus_parse_address (address, &entries, &len, error))
+    return NULL;              /* not a valid address */
+
+  for (i = 0; i < len; i++)
+    {
+      transport = _dbus_transport_open (entries[i], error);
+      if (transport != NULL)
+        break;
+    }
+
+  dbus_address_entries_free (entries);
+  return transport;
+}
+
+/**
+ * Creates a new transport for the "autostart" method.
+ * This creates a client-side of a transport.
+ *
+ * @param error address where an error can be returned.
+ * @returns a new transport, or #NULL on failure.
+ */
+static DBusTransport*
+_dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
+{
+  DBusString address;
+  DBusTransport *result = NULL;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (!_dbus_string_init (&address))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return NULL;
+    }
+
+  if (!_dbus_get_autolaunch_address (scope, &address, error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto out;
+    }
+
+  result = check_address (_dbus_string_get_const_data (&address), error);
+  if (result == NULL)
+    _DBUS_ASSERT_ERROR_IS_SET (error);
+  else
+    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ out:
+  _dbus_string_free (&address);
+  return result;
+}
+
+static DBusTransportOpenResult
+_dbus_transport_open_autolaunch (DBusAddressEntry  *entry,
+                                 DBusTransport    **transport_p,
+                                 DBusError         *error)
+{
+  const char *method;
+  
+  method = dbus_address_entry_get_method (entry);
+  _dbus_assert (method != NULL);
+
+  if (strcmp (method, "autolaunch") == 0)
+    {
+      const char *scope = dbus_address_entry_get_value (entry, "scope");
+
+      *transport_p = _dbus_transport_new_for_autolaunch (scope, error);
+
+      if (*transport_p == NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
+        }
+      else
+        {
+          _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+          return DBUS_TRANSPORT_OPEN_OK;
+        }      
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+      return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
+    }
+}
+
+static const struct {
+  DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
+                                    DBusTransport   **transport_p,
+                                    DBusError        *error);
+} open_funcs[] = {
+  { _dbus_transport_open_socket },
+  { _dbus_transport_open_platform_specific },
+  { _dbus_transport_open_autolaunch }
+#ifdef DBUS_BUILD_TESTS
+  , { _dbus_transport_open_debug_pipe }
+#endif
+};
+
+/**
+ * Try to open a new transport for the given address entry.  (This
+ * opens a client-side-of-the-connection transport.)
+ * 
+ * @param entry the address entry
+ * @param error location to store reason for failure.
+ * @returns new transport of #NULL on failure.
+ */
+DBusTransport*
+_dbus_transport_open (DBusAddressEntry *entry,
+                      DBusError        *error)
+{
+  DBusTransport *transport;
+  const char *expected_guid_orig;
+  char *expected_guid;
+  int i;
+  DBusError tmp_error = DBUS_ERROR_INIT;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  
+  transport = NULL;
+  expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
+  expected_guid = _dbus_strdup (expected_guid_orig);
+
+  if (expected_guid_orig != NULL && expected_guid == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return NULL;
+    }
+
+  for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
+    {
+      DBusTransportOpenResult result;
+
+      _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+      result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
+
+      switch (result)
+        {
+        case DBUS_TRANSPORT_OPEN_OK:
+          _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+          goto out;
+          break;
+        case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
+          _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+          /* keep going through the loop of open funcs */
+          break;
+        case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
+          _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+          goto out;
+          break;
+        case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
+          _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+          goto out;
+          break;
+        }
+    }
+
+ out:
+  
+  if (transport == NULL)
+    {
+      if (!dbus_error_is_set (&tmp_error))
+        _dbus_set_bad_address (&tmp_error,
+                               NULL, NULL,
+                               "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
+      
+      _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+      dbus_move_error(&tmp_error, error);
+      dbus_free (expected_guid);
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+
+      /* In the case of autostart the initial guid is NULL
+       * and the autostart transport recursively calls
+       * _dbus_open_transport wich returns a transport
+       * with a guid.  That guid is the definitive one.
+       *
+       * FIXME: if more transports are added they may have
+       * an effect on the expected_guid semantics (i.e. 
+       * expected_guid and transport->expected_guid may
+       * both have values).  This is very unlikely though
+       * we should either throw asserts here for those 
+       * corner cases or refactor the code so it is 
+       * clearer on what is expected and what is not
+       */
+      if(expected_guid)
+        transport->expected_guid = expected_guid;
+    }
+
+  return transport;
+}
+
+/**
+ * Increments the reference count for the transport.
+ *
+ * @param transport the transport.
+ * @returns the transport.
+ */
+DBusTransport *
+_dbus_transport_ref (DBusTransport *transport)
+{
+  _dbus_assert (transport->refcount > 0);
+  
+  transport->refcount += 1;
+
+  return transport;
+}
+
+/**
+ * Decrements the reference count for the transport.
+ * Disconnects and finalizes the transport if
+ * the reference count reaches zero.
+ *
+ * @param transport the transport.
+ */
+void
+_dbus_transport_unref (DBusTransport *transport)
+{
+  _dbus_assert (transport != NULL);
+  _dbus_assert (transport->refcount > 0);
+  
+  transport->refcount -= 1;
+  if (transport->refcount == 0)
+    {
+      _dbus_verbose ("finalizing\n");
+      
+      _dbus_assert (transport->vtable->finalize != NULL);
+      
+      (* transport->vtable->finalize) (transport);
+    }
+}
+
+/**
+ * Closes our end of the connection to a remote application. Further
+ * attempts to use this transport will fail. Only the first call to
+ * _dbus_transport_disconnect() will have an effect.
+ *
+ * @param transport the transport.
+ * 
+ */
+void
+_dbus_transport_disconnect (DBusTransport *transport)
+{
+  _dbus_verbose ("start\n");
+  
+  _dbus_assert (transport->vtable->disconnect != NULL);
+  
+  if (transport->disconnected)
+    return;
+
+  (* transport->vtable->disconnect) (transport);
+  
+  transport->disconnected = TRUE;
+
+  _dbus_verbose ("end\n");
+}
+
+/**
+ * Returns #TRUE if the transport has not been disconnected.
+ * Disconnection can result from _dbus_transport_disconnect()
+ * or because the server drops its end of the connection.
+ *
+ * @param transport the transport.
+ * @returns whether we're connected
+ */
+dbus_bool_t
+_dbus_transport_get_is_connected (DBusTransport *transport)
+{
+  return !transport->disconnected;
+}
+
+static dbus_bool_t
+auth_via_unix_user_function (DBusTransport *transport)
+{
+  DBusCredentials *auth_identity;
+  dbus_bool_t allow;
+  DBusConnection *connection;
+  DBusAllowUnixUserFunction unix_user_function;
+  void *unix_user_data;
+  dbus_uid_t uid;
+
+  /* Dropping the lock here probably isn't that safe. */
+  
+  auth_identity = _dbus_auth_get_identity (transport->auth);
+  _dbus_assert (auth_identity != NULL);
+
+  connection = transport->connection;
+  unix_user_function = transport->unix_user_function;
+  unix_user_data = transport->unix_user_data;
+  uid = _dbus_credentials_get_unix_uid (auth_identity);
+              
+  _dbus_verbose ("unlock\n");
+  _dbus_connection_unlock (connection);
+
+  allow = (* unix_user_function) (connection,
+                                  uid,
+                                  unix_user_data);
+              
+  _dbus_verbose ("lock post unix user function\n");
+  _dbus_connection_lock (connection);
+
+  if (allow)
+    {
+      _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
+    }
+  else
+    {
+      _dbus_verbose ("Client UID "DBUS_UID_FORMAT
+                     " was rejected, disconnecting\n",
+                     _dbus_credentials_get_unix_uid (auth_identity));
+      _dbus_transport_disconnect (transport);
+    }
+
+  return allow;
+}
+
+static dbus_bool_t
+auth_via_windows_user_function (DBusTransport *transport)
+{
+  DBusCredentials *auth_identity;  
+  dbus_bool_t allow;
+  DBusConnection *connection;
+  DBusAllowWindowsUserFunction windows_user_function;
+  void *windows_user_data;
+  char *windows_sid;
+
+  /* Dropping the lock here probably isn't that safe. */
+  
+  auth_identity = _dbus_auth_get_identity (transport->auth);
+  _dbus_assert (auth_identity != NULL);
+
+  connection = transport->connection;
+  windows_user_function = transport->windows_user_function;
+  windows_user_data = transport->unix_user_data;
+  windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
+
+  if (windows_sid == NULL)
+    {
+      /* OOM */
+      return FALSE;
+    }
+                
+  _dbus_verbose ("unlock\n");
+  _dbus_connection_unlock (connection);
+
+  allow = (* windows_user_function) (connection,
+                                     windows_sid,
+                                     windows_user_data);
+              
+  _dbus_verbose ("lock post windows user function\n");
+  _dbus_connection_lock (connection);
+
+  if (allow)
+    {
+      _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
+    }
+  else
+    {
+      _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
+                     _dbus_credentials_get_windows_sid (auth_identity));
+      _dbus_transport_disconnect (transport);
+    }
+
+  return allow;
+}
+
+static dbus_bool_t
+auth_via_default_rules (DBusTransport *transport)
+{
+  DBusCredentials *auth_identity;
+  DBusCredentials *our_identity;
+  dbus_bool_t allow;
+  
+  auth_identity = _dbus_auth_get_identity (transport->auth);
+  _dbus_assert (auth_identity != NULL);
+
+  /* By default, connection is allowed if the client is 1) root or 2)
+   * has the same UID as us or 3) anonymous is allowed.
+   */
+  
+  our_identity = _dbus_credentials_new_from_current_process ();
+  if (our_identity == NULL)
+    {
+      /* OOM */
+      return FALSE;
+    }
+              
+  if (transport->allow_anonymous ||
+      _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
+      _dbus_credentials_same_user (our_identity,
+                                   auth_identity))
+    {
+      if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
+          _dbus_verbose ("Client authorized as SID '%s'"
+                         "matching our SID '%s'\n",
+                         _dbus_credentials_get_windows_sid(auth_identity),
+                         _dbus_credentials_get_windows_sid(our_identity));
+      else
+          _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
+                         " matching our UID "DBUS_UID_FORMAT"\n",
+                         _dbus_credentials_get_unix_uid(auth_identity),
+                         _dbus_credentials_get_unix_uid(our_identity));
+      /* We have authenticated! */
+      allow = TRUE;
+    }
+  else
+    {
+      if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
+          _dbus_verbose ("Client authorized as SID '%s'"
+                         " but our SID is '%s', disconnecting\n",
+                         (_dbus_credentials_get_windows_sid(auth_identity) ?
+                          _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
+                         (_dbus_credentials_get_windows_sid(our_identity) ?
+                          _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
+      else
+          _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
+                         " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
+                         _dbus_credentials_get_unix_uid(auth_identity),
+                         _dbus_credentials_get_unix_uid(our_identity));
+      _dbus_transport_disconnect (transport);
+      allow = FALSE;
+    }  
+
+  _dbus_credentials_unref (our_identity);
+  
+  return allow;
+}
+
+
+/**
+ * Returns #TRUE if we have been authenticated.  Will return #TRUE
+ * even if the transport is disconnected.
+ *
+ * @todo we drop connection->mutex when calling the unix_user_function,
+ * and windows_user_function, which may not be safe really.
+ *
+ * @param transport the transport
+ * @returns whether we're authenticated
+ */
+dbus_bool_t
+_dbus_transport_get_is_authenticated (DBusTransport *transport)
+{  
+  if (transport->authenticated)
+    return TRUE;
+  else
+    {
+      dbus_bool_t maybe_authenticated;
+      
+      if (transport->disconnected)
+        return FALSE;
+
+      /* paranoia ref since we call user callbacks sometimes */
+      _dbus_connection_ref_unlocked (transport->connection);
+      
+      maybe_authenticated =
+        (!(transport->send_credentials_pending ||
+           transport->receive_credentials_pending));
+
+      if (maybe_authenticated)
+        {
+          switch (_dbus_auth_do_work (transport->auth))
+            {
+            case DBUS_AUTH_STATE_AUTHENTICATED:
+              /* leave as maybe_authenticated */
+              break;
+            default:
+              maybe_authenticated = FALSE;
+            }
+        }
+
+      /* If we're the client, verify the GUID
+       */
+      if (maybe_authenticated && !transport->is_server)
+        {
+          const char *server_guid;
+
+          server_guid = _dbus_auth_get_guid_from_server (transport->auth);
+          _dbus_assert (server_guid != NULL);
+
+          if (transport->expected_guid &&
+              strcmp (transport->expected_guid, server_guid) != 0)
+            {
+              _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
+                             transport->expected_guid, server_guid);
+              _dbus_transport_disconnect (transport);
+              _dbus_connection_unref_unlocked (transport->connection);
+              return FALSE;
+            }
+        }
+
+      /* If we're the server, see if we want to allow this identity to proceed.
+       */
+      if (maybe_authenticated && transport->is_server)
+        {
+          dbus_bool_t allow;
+          DBusCredentials *auth_identity;
+          
+          auth_identity = _dbus_auth_get_identity (transport->auth);
+          _dbus_assert (auth_identity != NULL);
+          
+          /* If we have an auth'd user and a user function, delegate
+           * deciding whether auth credentials are good enough to the
+           * app; otherwise, use our default decision process.
+           */
+          if (transport->unix_user_function != NULL &&
+              _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
+            {
+              allow = auth_via_unix_user_function (transport);
+            }
+          else if (transport->windows_user_function != NULL &&
+                   _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
+            {
+              allow = auth_via_windows_user_function (transport);
+            }      
+          else
+            {
+              allow = auth_via_default_rules (transport);
+            }
+          
+          if (!allow)
+            maybe_authenticated = FALSE;
+        }
+
+      transport->authenticated = maybe_authenticated;
+
+      _dbus_connection_unref_unlocked (transport->connection);
+      return maybe_authenticated;
+    }
+}
+
+/**
+ * See dbus_connection_get_is_anonymous().
+ *
+ * @param transport the transport
+ * @returns #TRUE if not authenticated or authenticated as anonymous
+ */
+dbus_bool_t
+_dbus_transport_get_is_anonymous (DBusTransport *transport)
+{
+  DBusCredentials *auth_identity;
+  
+  if (!transport->authenticated)
+    return TRUE;
+  
+  auth_identity = _dbus_auth_get_identity (transport->auth);
+
+  if (_dbus_credentials_are_anonymous (auth_identity))
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/**
+ * Returns TRUE if the transport supports sending unix fds.
+ *
+ * @param transport the transport
+ * @returns #TRUE if TRUE it is possible to send unix fds across the transport.
+ */
+dbus_bool_t
+_dbus_transport_can_pass_unix_fd(DBusTransport *transport)
+{
+  return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
+}
+
+/**
+ * Gets the address of a transport. It will be
+ * #NULL for a server-side transport.
+ *
+ * @param transport the transport
+ * @returns transport's address
+ */
+const char*
+_dbus_transport_get_address (DBusTransport *transport)
+{
+  return transport->address;
+}
+
+/**
+ * Gets the id of the server we are connected to (see
+ * dbus_server_get_id()). Only works on client side.
+ *
+ * @param transport the transport
+ * @returns transport's server's id or #NULL if we are the server side
+ */
+const char*
+_dbus_transport_get_server_id (DBusTransport *transport)
+{
+  if (transport->is_server)
+    return NULL;
+  else if (transport->authenticated)
+    return _dbus_auth_get_guid_from_server (transport->auth);
+  else
+    return transport->expected_guid;
+}
+
+/**
+ * Handles a watch by reading data, writing data, or disconnecting
+ * the transport, as appropriate for the given condition.
+ *
+ * @param transport the transport.
+ * @param watch the watch.
+ * @param condition the current state of the watched file descriptor.
+ * @returns #FALSE if not enough memory to fully handle the watch
+ */
+dbus_bool_t
+_dbus_transport_handle_watch (DBusTransport           *transport,
+                              DBusWatch               *watch,
+                              unsigned int             condition)
+{
+  dbus_bool_t retval;
+  
+  _dbus_assert (transport->vtable->handle_watch != NULL);
+
+  if (transport->disconnected)
+    return TRUE;
+
+  if (dbus_watch_get_socket (watch) < 0)
+    {
+      _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
+      return TRUE;
+    }
+  
+  _dbus_watch_sanitize_condition (watch, &condition);
+
+  _dbus_transport_ref (transport);
+  _dbus_watch_ref (watch);
+  retval = (* transport->vtable->handle_watch) (transport, watch, condition);
+  _dbus_watch_unref (watch);
+  _dbus_transport_unref (transport);
+
+  return retval;
+}
+
+/**
+ * Sets the connection using this transport. Allows the transport
+ * to add watches to the connection, queue incoming messages,
+ * and pull outgoing messages.
+ *
+ * @param transport the transport.
+ * @param connection the connection.
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_transport_set_connection (DBusTransport  *transport,
+                                DBusConnection *connection)
+{
+  _dbus_assert (transport->vtable->connection_set != NULL);
+  _dbus_assert (transport->connection == NULL);
+  
+  transport->connection = connection;
+
+  _dbus_transport_ref (transport);
+  if (!(* transport->vtable->connection_set) (transport))
+    transport->connection = NULL;
+  _dbus_transport_unref (transport);
+
+  return transport->connection != NULL;
+}
+
+/**
+ * Get the socket file descriptor, if any.
+ *
+ * @param transport the transport
+ * @param fd_p pointer to fill in with the descriptor
+ * @returns #TRUE if a descriptor was available
+ */
+dbus_bool_t
+_dbus_transport_get_socket_fd (DBusTransport *transport,
+                               int           *fd_p)
+{
+  dbus_bool_t retval;
+  
+  if (transport->vtable->get_socket_fd == NULL)
+    return FALSE;
+
+  if (transport->disconnected)
+    return FALSE;
+
+  _dbus_transport_ref (transport);
+
+  retval = (* transport->vtable->get_socket_fd) (transport,
+                                                 fd_p);
+  
+  _dbus_transport_unref (transport);
+
+  return retval;
+}
+
+/**
+ * Performs a single poll()/select() on the transport's file
+ * descriptors and then reads/writes data as appropriate,
+ * queueing incoming messages and sending outgoing messages.
+ * This is the backend for _dbus_connection_do_iteration().
+ * See _dbus_connection_do_iteration() for full details.
+ *
+ * @param transport the transport.
+ * @param flags indicates whether to read or write, and whether to block.
+ * @param timeout_milliseconds if blocking, timeout or -1 for no timeout.
+ */
+void
+_dbus_transport_do_iteration (DBusTransport  *transport,
+                              unsigned int    flags,
+                              int             timeout_milliseconds)
+{
+  _dbus_assert (transport->vtable->do_iteration != NULL);
+
+  _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
+                 flags, timeout_milliseconds, !transport->disconnected);
+  
+  if ((flags & (DBUS_ITERATION_DO_WRITING |
+                DBUS_ITERATION_DO_READING)) == 0)
+    return; /* Nothing to do */
+
+  if (transport->disconnected)
+    return;
+
+  _dbus_transport_ref (transport);
+  (* transport->vtable->do_iteration) (transport, flags,
+                                       timeout_milliseconds);
+  _dbus_transport_unref (transport);
+
+  _dbus_verbose ("end\n");
+}
+
+static dbus_bool_t
+recover_unused_bytes (DBusTransport *transport)
+{
+  if (_dbus_auth_needs_decoding (transport->auth))
+    {
+      DBusString plaintext;
+      const DBusString *encoded;
+      DBusString *buffer;
+      int orig_len;
+      
+      if (!_dbus_string_init (&plaintext))
+        goto nomem;
+      
+      _dbus_auth_get_unused_bytes (transport->auth,
+                                   &encoded);
+
+      if (!_dbus_auth_decode_data (transport->auth,
+                                   encoded, &plaintext))
+        {
+          _dbus_string_free (&plaintext);
+          goto nomem;
+        }
+      
+      _dbus_message_loader_get_buffer (transport->loader,
+                                       &buffer);
+      
+      orig_len = _dbus_string_get_length (buffer);
+      
+      if (!_dbus_string_move (&plaintext, 0, buffer,
+                              orig_len))
+        {
+          _dbus_string_free (&plaintext);
+          goto nomem;
+        }
+      
+      _dbus_verbose (" %d unused bytes sent to message loader\n", 
+                     _dbus_string_get_length (buffer) -
+                     orig_len);
+      
+      _dbus_message_loader_return_buffer (transport->loader,
+                                          buffer,
+                                          _dbus_string_get_length (buffer) -
+                                          orig_len);
+
+      _dbus_auth_delete_unused_bytes (transport->auth);
+      
+      _dbus_string_free (&plaintext);
+    }
+  else
+    {
+      const DBusString *bytes;
+      DBusString *buffer;
+      int orig_len;
+      dbus_bool_t succeeded;
+
+      _dbus_message_loader_get_buffer (transport->loader,
+                                       &buffer);
+                
+      orig_len = _dbus_string_get_length (buffer);
+                
+      _dbus_auth_get_unused_bytes (transport->auth,
+                                   &bytes);
+
+      succeeded = TRUE;
+      if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
+        succeeded = FALSE;
+      
+      _dbus_verbose (" %d unused bytes sent to message loader\n", 
+                     _dbus_string_get_length (buffer) -
+                     orig_len);
+      
+      _dbus_message_loader_return_buffer (transport->loader,
+                                          buffer,
+                                          _dbus_string_get_length (buffer) -
+                                          orig_len);
+
+      if (succeeded)
+        _dbus_auth_delete_unused_bytes (transport->auth);
+      else
+        goto nomem;
+    }
+
+  return TRUE;
+
+ nomem:
+  _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
+  return FALSE;
+}
+
+/**
+ * Reports our current dispatch status (whether there's buffered
+ * data to be queued as messages, or not, or we need memory).
+ *
+ * @param transport the transport
+ * @returns current status
+ */
+DBusDispatchStatus
+_dbus_transport_get_dispatch_status (DBusTransport *transport)
+{
+  if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
+      _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
+    return DBUS_DISPATCH_COMPLETE; /* complete for now */
+
+  if (!_dbus_transport_get_is_authenticated (transport))
+    {
+      if (_dbus_auth_do_work (transport->auth) ==
+          DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
+        return DBUS_DISPATCH_NEED_MEMORY;
+      else if (!_dbus_transport_get_is_authenticated (transport))
+        return DBUS_DISPATCH_COMPLETE;
+    }
+
+  if (!transport->unused_bytes_recovered &&
+      !recover_unused_bytes (transport))
+    return DBUS_DISPATCH_NEED_MEMORY;
+
+  transport->unused_bytes_recovered = TRUE;
+  
+  if (!_dbus_message_loader_queue_messages (transport->loader))
+    return DBUS_DISPATCH_NEED_MEMORY;
+
+  if (_dbus_message_loader_peek_message (transport->loader) != NULL)
+    return DBUS_DISPATCH_DATA_REMAINS;
+  else
+    return DBUS_DISPATCH_COMPLETE;
+}
+
+/**
+ * Processes data we've read while handling a watch, potentially
+ * converting some of it to messages and queueing those messages on
+ * the connection.
+ *
+ * @param transport the transport
+ * @returns #TRUE if we had enough memory to queue all messages
+ */
+dbus_bool_t
+_dbus_transport_queue_messages (DBusTransport *transport)
+{
+  DBusDispatchStatus status;
+
+#if 0
+  _dbus_verbose ("_dbus_transport_queue_messages()\n");
+#endif
+  
+  /* Queue any messages */
+  while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
+    {
+      DBusMessage *message;
+      DBusList *link;
+
+      link = _dbus_message_loader_pop_message_link (transport->loader);
+      _dbus_assert (link != NULL);
+      
+      message = link->data;
+      
+      _dbus_verbose ("queueing received message %p\n", message);
+
+      if (!_dbus_message_add_counter (message, transport->live_messages))
+        {
+          _dbus_message_loader_putback_message_link (transport->loader,
+                                                     link);
+          status = DBUS_DISPATCH_NEED_MEMORY;
+          break;
+        }
+      else
+        {
+          /* We didn't call the notify function when we added the counter, so
+           * catch up now. Since we have the connection's lock, it's desirable
+           * that we bypass the notify function and call this virtual method
+           * directly. */
+          if (transport->vtable->live_messages_changed)
+            (* transport->vtable->live_messages_changed) (transport);
+
+          /* pass ownership of link and message ref to connection */
+          _dbus_connection_queue_received_message_link (transport->connection,
+                                                        link);
+        }
+    }
+
+  if (_dbus_message_loader_get_is_corrupted (transport->loader))
+    {
+      _dbus_verbose ("Corrupted message stream, disconnecting\n");
+      _dbus_transport_disconnect (transport);
+    }
+
+  return status != DBUS_DISPATCH_NEED_MEMORY;
+}
+
+/**
+ * See dbus_connection_set_max_message_size().
+ *
+ * @param transport the transport
+ * @param size the max size of a single message
+ */
+void
+_dbus_transport_set_max_message_size (DBusTransport  *transport,
+                                      long            size)
+{
+  _dbus_message_loader_set_max_message_size (transport->loader, size);
+}
+
+/**
+ * See dbus_connection_set_max_message_unix_fds().
+ *
+ * @param transport the transport
+ * @param n the max number of unix fds of a single message
+ */
+void
+_dbus_transport_set_max_message_unix_fds (DBusTransport  *transport,
+                                          long            n)
+{
+  _dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
+}
+
+/**
+ * See dbus_connection_get_max_message_size().
+ *
+ * @param transport the transport
+ * @returns max message size
+ */
+long
+_dbus_transport_get_max_message_size (DBusTransport  *transport)
+{
+  return _dbus_message_loader_get_max_message_size (transport->loader);
+}
+
+/**
+ * See dbus_connection_get_max_message_unix_fds().
+ *
+ * @param transport the transport
+ * @returns max message unix fds
+ */
+long
+_dbus_transport_get_max_message_unix_fds (DBusTransport  *transport)
+{
+  return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
+}
+
+/**
+ * See dbus_connection_set_max_received_size().
+ *
+ * @param transport the transport
+ * @param size the max size of all incoming messages
+ */
+void
+_dbus_transport_set_max_received_size (DBusTransport  *transport,
+                                       long            size)
+{
+  transport->max_live_messages_size = size;
+  _dbus_counter_set_notify (transport->live_messages,
+                            transport->max_live_messages_size,
+                            transport->max_live_messages_unix_fds,
+                            live_messages_notify,
+                            transport);
+}
+
+/**
+ * See dbus_connection_set_max_received_unix_fds().
+ *
+ * @param transport the transport
+ * @param n the max unix fds of all incoming messages
+ */
+void
+_dbus_transport_set_max_received_unix_fds (DBusTransport  *transport,
+                                           long            n)
+{
+  transport->max_live_messages_unix_fds = n;
+  _dbus_counter_set_notify (transport->live_messages,
+                            transport->max_live_messages_size,
+                            transport->max_live_messages_unix_fds,
+                            live_messages_notify,
+                            transport);
+}
+
+/**
+ * See dbus_connection_get_max_received_size().
+ *
+ * @param transport the transport
+ * @returns max bytes for all live messages
+ */
+long
+_dbus_transport_get_max_received_size (DBusTransport  *transport)
+{
+  return transport->max_live_messages_size;
+}
+
+/**
+ * See dbus_connection_set_max_received_unix_fds().
+ *
+ * @param transport the transport
+ * @returns max unix fds for all live messages
+ */
+long
+_dbus_transport_get_max_received_unix_fds (DBusTransport  *transport)
+{
+  return transport->max_live_messages_unix_fds;
+}
+
+/**
+ * See dbus_connection_get_unix_user().
+ *
+ * @param transport the transport
+ * @param uid return location for the user ID
+ * @returns #TRUE if uid is filled in with a valid user ID
+ */
+dbus_bool_t
+_dbus_transport_get_unix_user (DBusTransport *transport,
+                               unsigned long *uid)
+{
+  DBusCredentials *auth_identity;
+
+  *uid = _DBUS_INT32_MAX; /* better than some root or system user in
+                           * case of bugs in the caller. Caller should
+                           * never use this value on purpose, however.
+                           */
+  
+  if (!transport->authenticated)
+    return FALSE;
+  
+  auth_identity = _dbus_auth_get_identity (transport->auth);
+
+  if (_dbus_credentials_include (auth_identity,
+                                 DBUS_CREDENTIAL_UNIX_USER_ID))
+    {
+      *uid = _dbus_credentials_get_unix_uid (auth_identity);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * See dbus_connection_get_unix_process_id().
+ *
+ * @param transport the transport
+ * @param pid return location for the process ID
+ * @returns #TRUE if uid is filled in with a valid process ID
+ */
+dbus_bool_t
+_dbus_transport_get_unix_process_id (DBusTransport *transport,
+				     unsigned long *pid)
+{
+  DBusCredentials *auth_identity;
+
+  *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
+			  * but we set it to a safe number, INT_MAX,
+			  * just to root out possible bugs in bad callers.
+			  */
+  
+  if (!transport->authenticated)
+    return FALSE;
+  
+  auth_identity = _dbus_auth_get_identity (transport->auth);
+
+  if (_dbus_credentials_include (auth_identity,
+                                 DBUS_CREDENTIAL_UNIX_PROCESS_ID))
+    {
+      *pid = _dbus_credentials_get_unix_pid (auth_identity);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * See dbus_connection_get_adt_audit_session_data().
+ *
+ * @param transport the transport
+ * @param data return location for the ADT audit data 
+ * @param data_size return length of audit data
+ * @returns #TRUE if audit data is filled in with a valid ucred
+ */
+dbus_bool_t
+_dbus_transport_get_adt_audit_session_data (DBusTransport      *transport,
+                                            void              **data,
+                                            int                *data_size)
+{
+  DBusCredentials *auth_identity;
+
+  *data = NULL;
+  *data_size = 0;
+  
+  if (!transport->authenticated)
+    return FALSE;
+  
+  auth_identity = _dbus_auth_get_identity (transport->auth);
+
+  if (_dbus_credentials_include (auth_identity,
+                                 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
+    {
+      *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
+      *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * See dbus_connection_set_unix_user_function().
+ *
+ * @param transport the transport
+ * @param function the predicate
+ * @param data data to pass to the predicate
+ * @param free_data_function function to free the data
+ * @param old_data the old user data to be freed
+ * @param old_free_data_function old free data function to free it with
+ */
+void
+_dbus_transport_set_unix_user_function (DBusTransport             *transport,
+                                        DBusAllowUnixUserFunction  function,
+                                        void                      *data,
+                                        DBusFreeFunction           free_data_function,
+                                        void                     **old_data,
+                                        DBusFreeFunction          *old_free_data_function)
+{  
+  *old_data = transport->unix_user_data;
+  *old_free_data_function = transport->free_unix_user_data;
+
+  transport->unix_user_function = function;
+  transport->unix_user_data = data;
+  transport->free_unix_user_data = free_data_function;
+}
+
+/**
+ * See dbus_connection_get_windows_user().
+ *
+ * @param transport the transport
+ * @param windows_sid_p return location for the user ID
+ * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it
+ */
+dbus_bool_t
+_dbus_transport_get_windows_user (DBusTransport              *transport,
+                                  char                      **windows_sid_p)
+{
+  DBusCredentials *auth_identity;
+
+  *windows_sid_p = NULL;
+  
+  if (!transport->authenticated)
+    return FALSE;
+  
+  auth_identity = _dbus_auth_get_identity (transport->auth);
+
+  if (_dbus_credentials_include (auth_identity,
+                                 DBUS_CREDENTIAL_WINDOWS_SID))
+    {
+      /* If no memory, we are supposed to return TRUE and set NULL */
+      *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
+
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * See dbus_connection_set_windows_user_function().
+ *
+ * @param transport the transport
+ * @param function the predicate
+ * @param data data to pass to the predicate
+ * @param free_data_function function to free the data
+ * @param old_data the old user data to be freed
+ * @param old_free_data_function old free data function to free it with
+ */
+
+void
+_dbus_transport_set_windows_user_function (DBusTransport              *transport,
+                                           DBusAllowWindowsUserFunction   function,
+                                           void                       *data,
+                                           DBusFreeFunction            free_data_function,
+                                           void                      **old_data,
+                                           DBusFreeFunction           *old_free_data_function)
+{
+  *old_data = transport->windows_user_data;
+  *old_free_data_function = transport->free_windows_user_data;
+
+  transport->windows_user_function = function;
+  transport->windows_user_data = data;
+  transport->free_windows_user_data = free_data_function;
+}
+
+/**
+ * Sets the SASL authentication mechanisms supported by this transport.
+ *
+ * @param transport the transport
+ * @param mechanisms the #NULL-terminated array of mechanisms
+ *
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
+                                     const char    **mechanisms)
+{
+  return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
+}
+
+/**
+ * See dbus_connection_set_allow_anonymous()
+ *
+ * @param transport the transport
+ * @param value #TRUE to allow anonymous connection
+ */
+void
+_dbus_transport_set_allow_anonymous (DBusTransport              *transport,
+                                     dbus_bool_t                 value)
+{
+  transport->allow_anonymous = value != FALSE;
+}
+
+#ifdef DBUS_ENABLE_STATS
+void
+_dbus_transport_get_stats (DBusTransport  *transport,
+                           dbus_uint32_t  *queue_bytes,
+                           dbus_uint32_t  *queue_fds,
+                           dbus_uint32_t  *peak_queue_bytes,
+                           dbus_uint32_t  *peak_queue_fds)
+{
+  if (queue_bytes != NULL)
+    *queue_bytes = _dbus_counter_get_size_value (transport->live_messages);
+
+  if (queue_fds != NULL)
+    *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages);
+
+  if (peak_queue_bytes != NULL)
+    *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages);
+
+  if (peak_queue_fds != NULL)
+    *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages);
+}
+#endif /* DBUS_ENABLE_STATS */
+
+/** @} */
diff --git a/dbus/dbus/dbus-transport.h b/dbus/dbus/dbus-transport.h
new file mode 100644
index 0000000..4b82151
--- /dev/null
+++ b/dbus/dbus/dbus-transport.h
@@ -0,0 +1,109 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-transport.h DBusTransport object (internal to D-BUS implementation)
+ *
+ * Copyright (C) 2002, 2004  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_TRANSPORT_H
+#define DBUS_TRANSPORT_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-connection.h>
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-address.h>
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusTransport DBusTransport;
+
+DBusTransport*     _dbus_transport_open                   (DBusAddressEntry           *entry,
+                                                           DBusError                  *error);
+DBusTransport*     _dbus_transport_ref                    (DBusTransport              *transport);
+void               _dbus_transport_unref                  (DBusTransport              *transport);
+void               _dbus_transport_disconnect             (DBusTransport              *transport);
+dbus_bool_t        _dbus_transport_get_is_connected       (DBusTransport              *transport);
+dbus_bool_t        _dbus_transport_get_is_authenticated   (DBusTransport              *transport);
+dbus_bool_t        _dbus_transport_get_is_anonymous       (DBusTransport              *transport);
+dbus_bool_t        _dbus_transport_can_pass_unix_fd       (DBusTransport              *transport);
+
+const char*        _dbus_transport_get_address            (DBusTransport              *transport);
+const char*        _dbus_transport_get_server_id          (DBusTransport              *transport);
+dbus_bool_t        _dbus_transport_handle_watch           (DBusTransport              *transport,
+                                                           DBusWatch                  *watch,
+                                                           unsigned int                condition);
+dbus_bool_t        _dbus_transport_set_connection         (DBusTransport              *transport,
+                                                           DBusConnection             *connection);
+void               _dbus_transport_do_iteration           (DBusTransport              *transport,
+                                                           unsigned int                flags,
+                                                           int                         timeout_milliseconds);
+DBusDispatchStatus _dbus_transport_get_dispatch_status    (DBusTransport              *transport);
+dbus_bool_t        _dbus_transport_queue_messages         (DBusTransport              *transport);
+
+void               _dbus_transport_set_max_message_size   (DBusTransport              *transport,
+                                                           long                        size);
+long               _dbus_transport_get_max_message_size   (DBusTransport              *transport);
+void               _dbus_transport_set_max_received_size  (DBusTransport              *transport,
+                                                           long                        size);
+long               _dbus_transport_get_max_received_size  (DBusTransport              *transport);
+
+void               _dbus_transport_set_max_message_unix_fds (DBusTransport              *transport,
+                                                             long                        n);
+long               _dbus_transport_get_max_message_unix_fds (DBusTransport              *transport);
+void               _dbus_transport_set_max_received_unix_fds(DBusTransport              *transport,
+                                                             long                        n);
+long               _dbus_transport_get_max_received_unix_fds(DBusTransport              *transport);
+
+dbus_bool_t        _dbus_transport_get_socket_fd          (DBusTransport              *transport,
+                                                           int                        *fd_p);
+dbus_bool_t        _dbus_transport_get_unix_user          (DBusTransport              *transport,
+                                                           unsigned long              *uid);
+dbus_bool_t        _dbus_transport_get_unix_process_id     (DBusTransport              *transport,
+                                                           unsigned long              *pid);
+dbus_bool_t        _dbus_transport_get_adt_audit_session_data (DBusTransport              *transport,
+                                                               void                      **data,
+                                                               int                        *data_size);
+void               _dbus_transport_set_unix_user_function (DBusTransport              *transport,
+                                                           DBusAllowUnixUserFunction   function,
+                                                           void                       *data,
+                                                           DBusFreeFunction            free_data_function,
+                                                           void                      **old_data,
+                                                           DBusFreeFunction           *old_free_data_function);
+dbus_bool_t        _dbus_transport_get_windows_user       (DBusTransport              *transport,
+                                                           char                      **windows_sid_p);
+void               _dbus_transport_set_windows_user_function (DBusTransport              *transport,
+                                                              DBusAllowWindowsUserFunction   function,
+                                                              void                       *data,
+                                                              DBusFreeFunction            free_data_function,
+                                                              void                      **old_data,
+                                                              DBusFreeFunction           *old_free_data_function);
+dbus_bool_t        _dbus_transport_set_auth_mechanisms    (DBusTransport              *transport,
+                                                           const char                **mechanisms);
+void               _dbus_transport_set_allow_anonymous    (DBusTransport              *transport,
+                                                           dbus_bool_t                 value);
+
+/* if DBUS_ENABLE_STATS */
+void _dbus_transport_get_stats (DBusTransport  *transport,
+                                dbus_uint32_t  *queue_bytes,
+                                dbus_uint32_t  *queue_fds,
+                                dbus_uint32_t  *peak_queue_bytes,
+                                dbus_uint32_t  *peak_queue_fds);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_TRANSPORT_H */
diff --git a/dbus/dbus/dbus-types.h b/dbus/dbus/dbus-types.h
new file mode 100644
index 0000000..57fc586
--- /dev/null
+++ b/dbus/dbus/dbus-types.h
@@ -0,0 +1,178 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-types.h  types such as dbus_bool_t
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_TYPES_H
+#define DBUS_TYPES_H
+
+#include <stddef.h>
+#include <dbus/dbus-arch-deps.h>
+
+typedef dbus_uint32_t  dbus_unichar_t;
+/* boolean size must be fixed at 4 bytes due to wire protocol! */
+typedef dbus_uint32_t  dbus_bool_t;
+
+/* Normally docs are in .c files, but there isn't a .c file for this. */
+/**
+ * @defgroup DBusTypes Basic types
+ * @ingroup  DBus
+ * @brief dbus_bool_t, dbus_int32_t, etc.
+ *
+ * Typedefs for common primitive types.
+ *
+ * @{
+ */
+
+/**
+ * @typedef dbus_bool_t
+ *
+ * A boolean, valid values are #TRUE and #FALSE.
+ */
+
+/**
+ * @typedef dbus_uint32_t
+ *
+ * A 32-bit unsigned integer on all platforms.
+ */
+
+/**
+ * @typedef dbus_int32_t
+ *
+ * A 32-bit signed integer on all platforms.
+ */
+
+/**
+ * @typedef dbus_uint16_t
+ *
+ * A 16-bit unsigned integer on all platforms.
+ */
+
+/**
+ * @typedef dbus_int16_t
+ *
+ * A 16-bit signed integer on all platforms.
+ */
+
+
+/**
+ * @typedef dbus_uint64_t
+ *
+ * A 64-bit unsigned integer on all platforms that support it.
+ * If supported, #DBUS_HAVE_INT64 will be defined.
+ *
+ * C99 requires a 64-bit type and most likely all interesting
+ * compilers support one. GLib for example flat-out requires
+ * a 64-bit type.
+ *
+ * You probably want to just assume #DBUS_HAVE_INT64 is always defined.
+ */
+
+/**
+ * @typedef dbus_int64_t
+ *
+ * A 64-bit signed integer on all platforms that support it.
+ * If supported, #DBUS_HAVE_INT64 will be defined.
+ *
+ * C99 requires a 64-bit type and most likely all interesting
+ * compilers support one. GLib for example flat-out requires
+ * a 64-bit type.
+ * 
+ * You probably want to just assume #DBUS_HAVE_INT64 is always defined.
+ */
+
+/**
+ * @def DBUS_HAVE_INT64
+ *
+ * Defined if 64-bit integers are available. Will be defined
+ * on any platform you care about, unless you care about
+ * some truly ancient UNIX, or some bizarre embedded platform.
+ *
+ * C99 requires a 64-bit type and most likely all interesting
+ * compilers support one. GLib for example flat-out requires
+ * a 64-bit type.
+ *
+ * You should feel comfortable ignoring this macro and just using
+ * int64 unconditionally.
+ * 
+ */
+
+/**
+ * @def DBUS_INT64_CONSTANT
+ *
+ * Declare a 64-bit signed integer constant. The macro
+ * adds the necessary "LL" or whatever after the integer,
+ * giving a literal such as "325145246765LL"
+ */
+
+/**
+ * @def DBUS_UINT64_CONSTANT
+ *
+ * Declare a 64-bit unsigned integer constant. The macro
+ * adds the necessary "ULL" or whatever after the integer,
+ * giving a literal such as "325145246765ULL"
+ */
+
+/**
+ * An 8-byte struct you could use to access int64 without having
+ * int64 support
+ */
+typedef struct
+{
+  dbus_uint32_t first32;  /**< first 32 bits in the 8 bytes (beware endian issues) */
+  dbus_uint32_t second32; /**< second 32 bits in the 8 bytes (beware endian issues) */
+} DBus8ByteStruct;
+
+/**
+ * A simple value union that lets you access bytes as if they
+ * were various types; useful when dealing with basic types via
+ * void pointers and varargs.
+ *
+ * This union also contains a pointer member (which can be used
+ * to retrieve a string from dbus_message_iter_get_basic(), for
+ * instance), so on future platforms it could conceivably be larger
+ * than 8 bytes.
+ */
+typedef union
+{
+  unsigned char bytes[8]; /**< as 8 individual bytes */
+  dbus_int16_t  i16;   /**< as int16 */
+  dbus_uint16_t u16;   /**< as int16 */
+  dbus_int32_t  i32;   /**< as int32 */
+  dbus_uint32_t u32;   /**< as int32 */
+  dbus_bool_t   bool_val; /**< as boolean */
+#ifdef DBUS_HAVE_INT64
+  dbus_int64_t  i64;   /**< as int64 */
+  dbus_uint64_t u64;   /**< as int64 */
+#endif
+  DBus8ByteStruct eight; /**< as 8-byte struct */
+  double dbl;          /**< as double */
+  unsigned char byt;   /**< as byte */
+  char *str;           /**< as char* (string, object path or signature) */
+  int fd;              /**< as Unix file descriptor */
+} DBusBasicValue;
+
+/** @} */
+
+#endif /* DBUS_TYPES_H */
diff --git a/dbus/dbus/dbus-userdb-util.c b/dbus/dbus/dbus-userdb-util.c
new file mode 100644
index 0000000..16bf229
--- /dev/null
+++ b/dbus/dbus/dbus-userdb-util.c
@@ -0,0 +1,480 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-userdb-util.c Would be in dbus-userdb.c, but not used in libdbus
+ * 
+ * Copyright (C) 2003, 2004, 2005  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#include <config.h>
+#define DBUS_USERDB_INCLUDES_PRIVATE 1
+#include "dbus-userdb.h"
+#include "dbus-test.h"
+#include "dbus-internals.h"
+#include "dbus-protocol.h"
+#include <string.h>
+
+#if HAVE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#include <systemd/sd-login.h>
+#endif
+
+/**
+ * @addtogroup DBusInternalsUtils
+ * @{
+ */
+
+/**
+ * Checks to see if the UID sent in is the console user
+ *
+ * @param uid UID of person to check 
+ * @param error return location for errors
+ * @returns #TRUE if the UID is the same as the console user and there are no errors
+ */
+dbus_bool_t
+_dbus_is_console_user (dbus_uid_t uid,
+		       DBusError *error)
+{
+
+  DBusUserDatabase *db;
+  const DBusUserInfo *info;
+  dbus_bool_t result = FALSE;
+
+#ifdef HAVE_SYSTEMD
+  if (sd_booted () > 0)
+    {
+      int r;
+
+      /* Check whether this user is logged in on at least one physical
+         seat */
+      r = sd_uid_get_seats (uid, 0, NULL);
+      if (r < 0)
+        {
+          dbus_set_error (error, _dbus_error_from_errno (-r),
+                          "Failed to determine seats of user \"" DBUS_UID_FORMAT "\": %s",
+                          uid,
+                          _dbus_strerror (-r));
+          return FALSE;
+        }
+
+      return (r > 0);
+    }
+#endif
+
+#ifdef HAVE_CONSOLE_OWNER_FILE
+
+  DBusString f;
+  DBusStat st;
+
+  if (!_dbus_string_init (&f))
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!_dbus_string_append(&f, DBUS_CONSOLE_OWNER_FILE))
+    {
+      _dbus_string_free(&f);
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (_dbus_stat(&f, &st, NULL) && (st.uid == uid))
+    {
+      _dbus_string_free(&f);
+      return TRUE;
+    }
+
+  _dbus_string_free(&f);
+
+#endif /* HAVE_CONSOLE_OWNER_FILE */
+
+  _dbus_user_database_lock_system ();
+
+  db = _dbus_user_database_get_system ();
+  if (db == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get system database.");
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  /* TPTD: this should be cache-safe, we've locked the DB and
+    _dbus_user_at_console doesn't pass it on. */
+  info = _dbus_user_database_lookup (db, uid, NULL, error);
+
+  if (info == NULL)
+    {
+      _dbus_user_database_unlock_system ();
+       return FALSE;
+    }
+
+  result = _dbus_user_at_console (info->username, error);
+
+  _dbus_user_database_unlock_system ();
+
+  return result;
+}
+
+/**
+ * Gets user ID given username
+ *
+ * @param username the username
+ * @param uid return location for UID
+ * @returns #TRUE if username existed and we got the UID
+ */
+dbus_bool_t
+_dbus_get_user_id (const DBusString  *username,
+                   dbus_uid_t        *uid)
+{
+  return _dbus_get_user_id_and_primary_group (username, uid, NULL);
+}
+
+/**
+ * Gets group ID given groupname
+ *
+ * @param groupname the groupname
+ * @param gid return location for GID
+ * @returns #TRUE if group name existed and we got the GID
+ */
+dbus_bool_t
+_dbus_get_group_id (const DBusString  *groupname,
+                    dbus_gid_t        *gid)
+{
+  DBusUserDatabase *db;
+  const DBusGroupInfo *info;
+  _dbus_user_database_lock_system ();
+
+  db = _dbus_user_database_get_system ();
+  if (db == NULL)
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  if (!_dbus_user_database_get_groupname (db, groupname,
+                                          &info, NULL))
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  *gid = info->gid;
+  
+  _dbus_user_database_unlock_system ();
+  return TRUE;
+}
+
+/**
+ * Gets user ID and primary group given username
+ *
+ * @param username the username
+ * @param uid_p return location for UID
+ * @param gid_p return location for GID
+ * @returns #TRUE if username existed and we got the UID and GID
+ */
+dbus_bool_t
+_dbus_get_user_id_and_primary_group (const DBusString  *username,
+                                     dbus_uid_t        *uid_p,
+                                     dbus_gid_t        *gid_p)
+{
+  DBusUserDatabase *db;
+  const DBusUserInfo *info;
+  _dbus_user_database_lock_system ();
+
+  db = _dbus_user_database_get_system ();
+  if (db == NULL)
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  if (!_dbus_user_database_get_username (db, username,
+                                         &info, NULL))
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  if (uid_p)
+    *uid_p = info->uid;
+  if (gid_p)
+    *gid_p = info->primary_gid;
+  
+  _dbus_user_database_unlock_system ();
+  return TRUE;
+}
+
+/**
+ * Looks up a gid or group name in the user database.  Only one of
+ * name or GID can be provided. There are wrapper functions for this
+ * that are better to use, this one does no locking or anything on the
+ * database and otherwise sort of sucks.
+ *
+ * @param db the database
+ * @param gid the group ID or #DBUS_GID_UNSET
+ * @param groupname group name or #NULL 
+ * @param error error to fill in
+ * @returns the entry in the database
+ */
+DBusGroupInfo*
+_dbus_user_database_lookup_group (DBusUserDatabase *db,
+                                  dbus_gid_t        gid,
+                                  const DBusString *groupname,
+                                  DBusError        *error)
+{
+  DBusGroupInfo *info;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+   /* See if the group is really a number */
+   if (gid == DBUS_UID_UNSET)
+    {
+      unsigned long n;
+
+      if (_dbus_is_a_number (groupname, &n))
+        gid = n;
+    }
+
+#ifdef DBUS_ENABLE_USERDB_CACHE
+  if (gid != DBUS_GID_UNSET)
+    info = _dbus_hash_table_lookup_uintptr (db->groups, gid);
+  else
+    info = _dbus_hash_table_lookup_string (db->groups_by_name,
+                                           _dbus_string_get_const_data (groupname));
+  if (info)
+    {
+      _dbus_verbose ("Using cache for GID "DBUS_GID_FORMAT" information\n",
+                     info->gid);
+      return info;
+    }
+  else
+#else
+  if (1)
+#endif
+    {
+      if (gid != DBUS_GID_UNSET)
+	_dbus_verbose ("No cache for GID "DBUS_GID_FORMAT"\n",
+		       gid);
+      else
+	_dbus_verbose ("No cache for groupname \"%s\"\n",
+		       _dbus_string_get_const_data (groupname));
+      
+      info = dbus_new0 (DBusGroupInfo, 1);
+      if (info == NULL)
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          return NULL;
+        }
+
+      if (gid != DBUS_GID_UNSET)
+        {
+          if (!_dbus_group_info_fill_gid (info, gid, error))
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (error);
+              _dbus_group_info_free_allocated (info);
+              return NULL;
+            }
+        }
+      else
+        {
+          if (!_dbus_group_info_fill (info, groupname, error))
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (error);
+              _dbus_group_info_free_allocated (info);
+              return NULL;
+            }
+        }
+
+      /* don't use these past here */
+      gid = DBUS_GID_UNSET;
+      groupname = NULL;
+
+      if (!_dbus_hash_table_insert_uintptr (db->groups, info->gid, info))
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          _dbus_group_info_free_allocated (info);
+          return NULL;
+        }
+
+
+      if (!_dbus_hash_table_insert_string (db->groups_by_name,
+                                           info->groupname,
+                                           info))
+        {
+          _dbus_hash_table_remove_uintptr (db->groups, info->gid);
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          return NULL;
+        }
+      
+      return info;
+    }
+}
+
+
+/**
+ * Gets the user information for the given group name,
+ * returned group info should not be freed. 
+ *
+ * @param db user database
+ * @param groupname the group name
+ * @param info return location for const ref to group info
+ * @param error error location
+ * @returns #FALSE if error is set
+ */
+dbus_bool_t
+_dbus_user_database_get_groupname (DBusUserDatabase     *db,
+                                   const DBusString     *groupname,
+                                   const DBusGroupInfo **info,
+                                   DBusError            *error)
+{
+  *info = _dbus_user_database_lookup_group (db, DBUS_GID_UNSET, groupname, error);
+  return *info != NULL;
+}
+
+/**
+ * Gets the user information for the given GID,
+ * returned group info should not be freed. 
+ *
+ * @param db user database
+ * @param gid the group ID
+ * @param info return location for const ref to group info
+ * @param error error location
+ * @returns #FALSE if error is set
+ */
+dbus_bool_t
+_dbus_user_database_get_gid (DBusUserDatabase     *db,
+                             dbus_gid_t            gid,
+                             const DBusGroupInfo **info,
+                             DBusError            *error)
+{
+  *info = _dbus_user_database_lookup_group (db, gid, NULL, error);
+  return *info != NULL;
+}
+
+
+/**
+ * Gets all groups  corresponding to the given UID. Returns #FALSE
+ * if no memory, or user isn't known, but always initializes
+ * group_ids to a NULL array. 
+ *
+ * @param uid the UID
+ * @param group_ids return location for array of group IDs
+ * @param n_group_ids return location for length of returned array
+ * @returns #TRUE if the UID existed and we got some credentials
+ */
+dbus_bool_t
+_dbus_groups_from_uid (dbus_uid_t         uid,
+                       dbus_gid_t       **group_ids,
+                       int               *n_group_ids)
+{
+  DBusUserDatabase *db;
+  const DBusUserInfo *info;
+  *group_ids = NULL;
+  *n_group_ids = 0;
+
+  _dbus_user_database_lock_system ();
+
+  db = _dbus_user_database_get_system ();
+  if (db == NULL)
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  if (!_dbus_user_database_get_uid (db, uid,
+                                    &info, NULL))
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  _dbus_assert (info->uid == uid);
+  
+  if (info->n_group_ids > 0)
+    {
+      *group_ids = dbus_new (dbus_gid_t, info->n_group_ids);
+      if (*group_ids == NULL)
+        {
+	  _dbus_user_database_unlock_system ();
+          return FALSE;
+        }
+
+      *n_group_ids = info->n_group_ids;
+
+      memcpy (*group_ids, info->group_ids, info->n_group_ids * sizeof (dbus_gid_t));
+    }
+
+  _dbus_user_database_unlock_system ();
+  return TRUE;
+}
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include <stdio.h>
+
+/**
+ * Unit test for dbus-userdb.c.
+ * 
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_userdb_test (const char *test_data_dir)
+{
+  const DBusString *username;
+  const DBusString *homedir;
+  dbus_uid_t uid;
+  unsigned long *group_ids;
+  int n_group_ids, i;
+  DBusError error;
+
+  if (!_dbus_username_from_current_process (&username))
+    _dbus_assert_not_reached ("didn't get username");
+
+  if (!_dbus_homedir_from_current_process (&homedir))
+    _dbus_assert_not_reached ("didn't get homedir");  
+
+  if (!_dbus_get_user_id (username, &uid))
+    _dbus_assert_not_reached ("didn't get uid");
+
+  if (!_dbus_groups_from_uid (uid, &group_ids, &n_group_ids))
+    _dbus_assert_not_reached ("didn't get groups");
+
+  printf ("    Current user: %s homedir: %s gids:",
+          _dbus_string_get_const_data (username),
+          _dbus_string_get_const_data (homedir));
+
+  for (i=0; i<n_group_ids; i++)
+      printf(" %ld", group_ids[i]);
+
+  printf ("\n");
+
+  dbus_error_init (&error);
+  printf ("Is Console user: %i\n",
+          _dbus_is_console_user (uid, &error));
+  printf ("Invocation was OK: %s\n", error.message ? error.message : "yes");
+  dbus_error_free (&error);
+  printf ("Is Console user 4711: %i\n",
+          _dbus_is_console_user (4711, &error));
+  printf ("Invocation was OK: %s\n", error.message ? error.message : "yes");
+  dbus_error_free (&error);
+
+  dbus_free (group_ids);
+
+  return TRUE;
+}
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus/dbus-userdb.c b/dbus/dbus/dbus-userdb.c
new file mode 100644
index 0000000..4e8b39a
--- /dev/null
+++ b/dbus/dbus/dbus-userdb.c
@@ -0,0 +1,668 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-userdb.c User database abstraction
+ * 
+ * Copyright (C) 2003, 2004  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#include <config.h>
+#define DBUS_USERDB_INCLUDES_PRIVATE 1
+#include "dbus-userdb.h"
+#include "dbus-hash.h"
+#include "dbus-test.h"
+#include "dbus-internals.h"
+#include "dbus-protocol.h"
+#include "dbus-credentials.h"
+#include <string.h>
+
+/**
+ * @addtogroup DBusInternalsUtils
+ * @{
+ */
+
+/**
+ * Frees the given #DBusUserInfo's members with _dbus_user_info_free()
+ * and also calls dbus_free() on the block itself
+ *
+ * @param info the info
+ */
+void
+_dbus_user_info_free_allocated (DBusUserInfo *info)
+{
+  if (info == NULL) /* hash table will pass NULL */
+    return;
+
+  _dbus_user_info_free (info);
+  dbus_free (info);
+}
+
+/**
+ * Frees the given #DBusGroupInfo's members with _dbus_group_info_free()
+ * and also calls dbus_free() on the block itself
+ *
+ * @param info the info
+ */
+void
+_dbus_group_info_free_allocated (DBusGroupInfo *info)
+{
+  if (info == NULL) /* hash table will pass NULL */
+    return;
+
+  _dbus_group_info_free (info);
+  dbus_free (info);
+}
+
+/**
+ * Frees the members of info
+ * (but not info itself)
+ * @param info the user info struct
+ */
+void
+_dbus_user_info_free (DBusUserInfo *info)
+{
+  dbus_free (info->group_ids);
+  dbus_free (info->username);
+  dbus_free (info->homedir);
+}
+
+/**
+ * Frees the members of info (but not info itself).
+ *
+ * @param info the group info
+ */
+void
+_dbus_group_info_free (DBusGroupInfo    *info)
+{
+  dbus_free (info->groupname);
+}
+
+/**
+ * Checks if a given string is actually a number 
+ * and converts it if it is 
+ *
+ * @param str the string to check
+ * @param num the memory location of the unsigned long to fill in
+ * @returns TRUE if str is a number and num is filled in 
+ */
+dbus_bool_t
+_dbus_is_a_number (const DBusString *str,
+                   unsigned long    *num)
+{
+  int end;
+
+  if (_dbus_string_parse_uint (str, 0, num, &end) &&
+      end == _dbus_string_get_length (str))
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/**
+ * Looks up a uid or username in the user database.  Only one of name
+ * or UID can be provided. There are wrapper functions for this that
+ * are better to use, this one does no locking or anything on the
+ * database and otherwise sort of sucks.
+ *
+ * @param db the database
+ * @param uid the user ID or #DBUS_UID_UNSET
+ * @param username username or #NULL 
+ * @param error error to fill in
+ * @returns the entry in the database
+ */
+DBusUserInfo*
+_dbus_user_database_lookup (DBusUserDatabase *db,
+                            dbus_uid_t        uid,
+                            const DBusString *username,
+                            DBusError        *error)
+{
+  DBusUserInfo *info;
+
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  _dbus_assert (uid != DBUS_UID_UNSET || username != NULL);
+
+  /* See if the username is really a number */
+  if (uid == DBUS_UID_UNSET)
+    {
+      unsigned long n;
+
+      if (_dbus_is_a_number (username, &n))
+        uid = n;
+    }
+
+#ifdef DBUS_ENABLE_USERDB_CACHE  
+  if (uid != DBUS_UID_UNSET)
+    info = _dbus_hash_table_lookup_uintptr (db->users, uid);
+  else
+    info = _dbus_hash_table_lookup_string (db->users_by_name, _dbus_string_get_const_data (username));
+
+  if (info)
+    {
+      _dbus_verbose ("Using cache for UID "DBUS_UID_FORMAT" information\n",
+                     info->uid);
+      return info;
+    }
+  else
+#else 
+  if (1)
+#endif
+    {
+      if (uid != DBUS_UID_UNSET)
+	_dbus_verbose ("No cache for UID "DBUS_UID_FORMAT"\n",
+		       uid);
+      else
+	_dbus_verbose ("No cache for user \"%s\"\n",
+		       _dbus_string_get_const_data (username));
+      
+      info = dbus_new0 (DBusUserInfo, 1);
+      if (info == NULL)
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          return NULL;
+        }
+
+      if (uid != DBUS_UID_UNSET)
+        {
+          if (!_dbus_user_info_fill_uid (info, uid, error))
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (error);
+              _dbus_user_info_free_allocated (info);
+              return NULL;
+            }
+        }
+      else
+        {
+          if (!_dbus_user_info_fill (info, username, error))
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (error);
+              _dbus_user_info_free_allocated (info);
+              return NULL;
+            }
+        }
+
+      /* be sure we don't use these after here */
+      uid = DBUS_UID_UNSET;
+      username = NULL;
+
+      /* insert into hash */
+      if (!_dbus_hash_table_insert_uintptr (db->users, info->uid, info))
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          _dbus_user_info_free_allocated (info);
+          return NULL;
+        }
+
+      if (!_dbus_hash_table_insert_string (db->users_by_name,
+                                           info->username,
+                                           info))
+        {
+          _dbus_hash_table_remove_uintptr (db->users, info->uid);
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          return NULL;
+        }
+      
+      return info;
+    }
+}
+
+static dbus_bool_t database_locked = FALSE;
+static DBusUserDatabase *system_db = NULL;
+static DBusString process_username;
+static DBusString process_homedir;
+      
+static void
+shutdown_system_db (void *data)
+{
+  if (system_db != NULL)
+    _dbus_user_database_unref (system_db);
+  system_db = NULL;
+  _dbus_string_free (&process_username);
+  _dbus_string_free (&process_homedir);
+}
+
+static dbus_bool_t
+init_system_db (void)
+{
+  _dbus_assert (database_locked);
+    
+  if (system_db == NULL)
+    {
+      DBusError error = DBUS_ERROR_INIT;
+      const DBusUserInfo *info;
+      
+      system_db = _dbus_user_database_new ();
+      if (system_db == NULL)
+        return FALSE;
+
+      if (!_dbus_user_database_get_uid (system_db,
+                                        _dbus_getuid (),
+                                        &info,
+                                        &error))
+        {
+          _dbus_user_database_unref (system_db);
+          system_db = NULL;
+          
+          if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+            {
+              dbus_error_free (&error);
+              return FALSE;
+            }
+          else
+            {
+              /* This really should not happen. */
+              _dbus_warn ("Could not get password database information for UID of current process: %s\n",
+                          error.message);
+              dbus_error_free (&error);
+              return FALSE;
+            }
+        }
+
+      if (!_dbus_string_init (&process_username))
+        {
+          _dbus_user_database_unref (system_db);
+          system_db = NULL;
+          return FALSE;
+        }
+
+      if (!_dbus_string_init (&process_homedir))
+        {
+          _dbus_string_free (&process_username);
+          _dbus_user_database_unref (system_db);
+          system_db = NULL;
+          return FALSE;
+        }
+
+      if (!_dbus_string_append (&process_username,
+                                info->username) ||
+          !_dbus_string_append (&process_homedir,
+                                info->homedir) ||
+          !_dbus_register_shutdown_func (shutdown_system_db, NULL))
+        {
+          _dbus_string_free (&process_username);
+          _dbus_string_free (&process_homedir);
+          _dbus_user_database_unref (system_db);
+          system_db = NULL;
+          return FALSE;
+        }
+    }
+
+  return TRUE;
+}
+
+/**
+ * Locks global system user database.
+ */
+void
+_dbus_user_database_lock_system (void)
+{
+  _DBUS_LOCK (system_users);
+  database_locked = TRUE;
+}
+
+/**
+ * Unlocks global system user database.
+ */
+void
+_dbus_user_database_unlock_system (void)
+{
+  database_locked = FALSE;
+  _DBUS_UNLOCK (system_users);
+}
+
+/**
+ * Gets the system global user database;
+ * must be called with lock held (_dbus_user_database_lock_system()).
+ *
+ * @returns the database or #NULL if no memory
+ */
+DBusUserDatabase*
+_dbus_user_database_get_system (void)
+{
+  _dbus_assert (database_locked);
+
+  init_system_db ();
+  
+  return system_db;
+}
+
+/**
+ * Flushes the system global user database;
+ */
+void
+_dbus_user_database_flush_system (void)
+{
+  _dbus_user_database_lock_system ();
+   
+   if (system_db != NULL)
+    _dbus_user_database_flush (system_db);
+
+  _dbus_user_database_unlock_system ();
+}
+
+/**
+ * Gets username of user owning current process.  The returned string
+ * is valid until dbus_shutdown() is called.
+ *
+ * @param username place to store pointer to username
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_username_from_current_process (const DBusString **username)
+{
+  _dbus_user_database_lock_system ();
+  if (!init_system_db ())
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+  *username = &process_username;
+  _dbus_user_database_unlock_system ();  
+
+  return TRUE;
+}
+
+/**
+ * Gets homedir of user owning current process.  The returned string
+ * is valid until dbus_shutdown() is called.
+ *
+ * @param homedir place to store pointer to homedir
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_homedir_from_current_process (const DBusString  **homedir)
+{
+  _dbus_user_database_lock_system ();
+  if (!init_system_db ())
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+  *homedir = &process_homedir;
+  _dbus_user_database_unlock_system ();
+
+  return TRUE;
+}
+
+/**
+ * Gets the home directory for the given user.
+ *
+ * @param username the username
+ * @param homedir string to append home directory to
+ * @returns #TRUE if user existed and we appended their homedir
+ */
+dbus_bool_t
+_dbus_homedir_from_username (const DBusString *username,
+                             DBusString       *homedir)
+{
+  DBusUserDatabase *db;
+  const DBusUserInfo *info;
+  _dbus_user_database_lock_system ();
+
+  db = _dbus_user_database_get_system ();
+  if (db == NULL)
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  if (!_dbus_user_database_get_username (db, username,
+                                         &info, NULL))
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  if (!_dbus_string_append (homedir, info->homedir))
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+  
+  _dbus_user_database_unlock_system ();
+  return TRUE;
+}
+
+/**
+ * Gets the home directory for the given user.
+ *
+ * @param uid the uid
+ * @param homedir string to append home directory to
+ * @returns #TRUE if user existed and we appended their homedir
+ */
+dbus_bool_t
+_dbus_homedir_from_uid (dbus_uid_t         uid,
+                        DBusString        *homedir)
+{
+  DBusUserDatabase *db;
+  const DBusUserInfo *info;
+  _dbus_user_database_lock_system ();
+
+  db = _dbus_user_database_get_system ();
+  if (db == NULL)
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  if (!_dbus_user_database_get_uid (db, uid,
+                                    &info, NULL))
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  if (!_dbus_string_append (homedir, info->homedir))
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+  
+  _dbus_user_database_unlock_system ();
+  return TRUE;
+}
+
+/**
+ * Adds the credentials corresponding to the given username.
+ *
+ * Used among other purposes to parses a desired identity provided
+ * from a client in the auth protocol. On UNIX this means parsing a
+ * UID, on Windows probably parsing an SID string.
+ * 
+ * @todo this is broken because it treats OOM and parse error
+ * the same way. Needs a #DBusError.
+ * 
+ * @param credentials credentials to fill in 
+ * @param username the username
+ * @returns #TRUE if the username existed and we got some credentials
+ */
+dbus_bool_t
+_dbus_credentials_add_from_user (DBusCredentials  *credentials,
+                                 const DBusString *username)
+{
+  DBusUserDatabase *db;
+  const DBusUserInfo *info;
+
+  _dbus_user_database_lock_system ();
+
+  db = _dbus_user_database_get_system ();
+  if (db == NULL)
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  if (!_dbus_user_database_get_username (db, username,
+                                         &info, NULL))
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+
+  if (!_dbus_credentials_add_unix_uid(credentials, info->uid))
+    {
+      _dbus_user_database_unlock_system ();
+      return FALSE;
+    }
+  
+  _dbus_user_database_unlock_system ();
+  return TRUE;
+}
+
+/**
+ * Creates a new user database object used to look up and
+ * cache user information.
+ * @returns new database, or #NULL on out of memory
+ */
+DBusUserDatabase*
+_dbus_user_database_new (void)
+{
+  DBusUserDatabase *db;
+  
+  db = dbus_new0 (DBusUserDatabase, 1);
+  if (db == NULL)
+    return NULL;
+
+  db->refcount = 1;
+
+  db->users = _dbus_hash_table_new (DBUS_HASH_UINTPTR,
+                                    NULL, (DBusFreeFunction) _dbus_user_info_free_allocated);
+  
+  if (db->users == NULL)
+    goto failed;
+
+  db->groups = _dbus_hash_table_new (DBUS_HASH_UINTPTR,
+                                     NULL, (DBusFreeFunction) _dbus_group_info_free_allocated);
+  
+  if (db->groups == NULL)
+    goto failed;
+
+  db->users_by_name = _dbus_hash_table_new (DBUS_HASH_STRING,
+                                            NULL, NULL);
+  if (db->users_by_name == NULL)
+    goto failed;
+  
+  db->groups_by_name = _dbus_hash_table_new (DBUS_HASH_STRING,
+                                             NULL, NULL);
+  if (db->groups_by_name == NULL)
+    goto failed;
+  
+  return db;
+  
+ failed:
+  _dbus_user_database_unref (db);
+  return NULL;
+}
+
+/**
+ * Flush all information out of the user database. 
+ */
+void
+_dbus_user_database_flush (DBusUserDatabase *db) 
+{
+  _dbus_hash_table_remove_all(db->users_by_name);
+  _dbus_hash_table_remove_all(db->groups_by_name);
+  _dbus_hash_table_remove_all(db->users);
+  _dbus_hash_table_remove_all(db->groups);
+}
+
+#ifdef DBUS_BUILD_TESTS
+/**
+ * Increments refcount of user database.
+ * @param db the database
+ * @returns the database
+ */
+DBusUserDatabase *
+_dbus_user_database_ref (DBusUserDatabase  *db)
+{
+  _dbus_assert (db->refcount > 0);
+
+  db->refcount += 1;
+
+  return db;
+}
+#endif /* DBUS_BUILD_TESTS */
+
+/**
+ * Decrements refcount of user database.
+ * @param db the database
+ */
+void
+_dbus_user_database_unref (DBusUserDatabase  *db)
+{
+  _dbus_assert (db->refcount > 0);
+
+  db->refcount -= 1;
+  if (db->refcount == 0)
+    {
+      if (db->users)
+        _dbus_hash_table_unref (db->users);
+
+      if (db->groups)
+        _dbus_hash_table_unref (db->groups);
+
+      if (db->users_by_name)
+        _dbus_hash_table_unref (db->users_by_name);
+
+      if (db->groups_by_name)
+        _dbus_hash_table_unref (db->groups_by_name);
+      
+      dbus_free (db);
+    }
+}
+
+/**
+ * Gets the user information for the given UID,
+ * returned user info should not be freed. 
+ *
+ * @param db user database
+ * @param uid the user ID
+ * @param info return location for const ref to user info
+ * @param error error location
+ * @returns #FALSE if error is set
+ */
+dbus_bool_t
+_dbus_user_database_get_uid (DBusUserDatabase    *db,
+                             dbus_uid_t           uid,
+                             const DBusUserInfo **info,
+                             DBusError           *error)
+{
+  *info = _dbus_user_database_lookup (db, uid, NULL, error);
+  return *info != NULL;
+}
+
+/**
+ * Gets the user information for the given username.
+ *
+ * @param db user database
+ * @param username the user name
+ * @param info return location for const ref to user info
+ * @param error error location
+ * @returns #FALSE if error is set
+ */
+dbus_bool_t
+_dbus_user_database_get_username  (DBusUserDatabase     *db,
+                                   const DBusString     *username,
+                                   const DBusUserInfo  **info,
+                                   DBusError            *error)
+{
+  *info = _dbus_user_database_lookup (db, DBUS_UID_UNSET, username, error);
+  return *info != NULL;
+}
+
+/** @} */
+
+/* Tests in dbus-userdb-util.c */
diff --git a/dbus/dbus/dbus-userdb.h b/dbus/dbus/dbus-userdb.h
new file mode 100644
index 0000000..cb49d9e
--- /dev/null
+++ b/dbus/dbus/dbus-userdb.h
@@ -0,0 +1,121 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-userdb.h User database abstraction
+ * 
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_USERDB_H
+#define DBUS_USERDB_H
+
+#include <dbus/dbus-sysdeps-unix.h>
+
+#ifdef DBUS_WIN
+#error "Don't include this on Windows"
+#endif
+
+DBUS_BEGIN_DECLS
+
+typedef struct DBusUserDatabase DBusUserDatabase;
+
+#ifdef DBUS_USERDB_INCLUDES_PRIVATE
+#include <dbus/dbus-hash.h>
+
+/**
+ * Internals of DBusUserDatabase
+ */
+struct DBusUserDatabase
+{
+  int refcount; /**< Reference count */
+
+  DBusHashTable *users; /**< Users in the database by UID */
+  DBusHashTable *groups; /**< Groups in the database by GID */
+  DBusHashTable *users_by_name; /**< Users in the database by name */
+  DBusHashTable *groups_by_name; /**< Groups in the database by name */
+
+};
+
+
+DBusUserDatabase* _dbus_user_database_new           (void);
+DBusUserDatabase* _dbus_user_database_ref           (DBusUserDatabase     *db);
+void              _dbus_user_database_flush         (DBusUserDatabase     *db);
+void              _dbus_user_database_unref         (DBusUserDatabase     *db);
+dbus_bool_t       _dbus_user_database_get_uid       (DBusUserDatabase     *db,
+                                                     dbus_uid_t            uid,
+                                                     const DBusUserInfo  **info,
+                                                     DBusError            *error);
+dbus_bool_t       _dbus_user_database_get_gid       (DBusUserDatabase     *db,
+                                                     dbus_gid_t            gid,
+                                                     const DBusGroupInfo **info,
+                                                     DBusError            *error);
+dbus_bool_t       _dbus_user_database_get_username  (DBusUserDatabase     *db,
+                                                     const DBusString     *username,
+                                                     const DBusUserInfo  **info,
+                                                     DBusError            *error);
+dbus_bool_t       _dbus_user_database_get_groupname (DBusUserDatabase     *db,
+                                                     const DBusString     *groupname,
+                                                     const DBusGroupInfo **info,
+                                                     DBusError            *error);
+
+DBusUserInfo*  _dbus_user_database_lookup       (DBusUserDatabase *db,
+                                                 dbus_uid_t        uid,
+                                                 const DBusString *username,
+                                                 DBusError        *error);
+DBusGroupInfo* _dbus_user_database_lookup_group (DBusUserDatabase *db,
+                                                 dbus_gid_t        gid,
+                                                 const DBusString *groupname,
+                                                 DBusError        *error);
+void           _dbus_user_info_free_allocated   (DBusUserInfo     *info);
+void           _dbus_group_info_free_allocated  (DBusGroupInfo    *info);
+#endif /* DBUS_USERDB_INCLUDES_PRIVATE */
+
+DBusUserDatabase* _dbus_user_database_get_system    (void);
+void              _dbus_user_database_lock_system   (void);
+void              _dbus_user_database_unlock_system (void);
+void              _dbus_user_database_flush_system  (void);
+
+dbus_bool_t _dbus_get_user_id                   (const DBusString  *username,
+                                                 dbus_uid_t        *uid);
+dbus_bool_t _dbus_get_group_id                  (const DBusString  *group_name,
+                                                 dbus_gid_t        *gid);
+dbus_bool_t _dbus_get_user_id_and_primary_group (const DBusString  *username,
+                                                 dbus_uid_t        *uid_p,
+                                                 dbus_gid_t        *gid_p);
+dbus_bool_t _dbus_credentials_from_uid          (dbus_uid_t         user_id,
+                                                 DBusCredentials   *credentials);
+dbus_bool_t _dbus_groups_from_uid		(dbus_uid_t            uid,
+                                                 dbus_gid_t          **group_ids,
+                                                 int                  *n_group_ids);
+dbus_bool_t _dbus_is_console_user               (dbus_uid_t         uid,
+                                                 DBusError         *error);
+
+dbus_bool_t _dbus_is_a_number                   (const DBusString *str, 
+                                                 unsigned long    *num);
+
+dbus_bool_t _dbus_username_from_current_process (const DBusString **username);
+dbus_bool_t _dbus_homedir_from_current_process  (const DBusString **homedir);
+dbus_bool_t _dbus_homedir_from_username         (const DBusString  *username,
+                                                 DBusString        *homedir);
+
+dbus_bool_t _dbus_homedir_from_uid              (dbus_uid_t         uid,
+                                                 DBusString        *homedir);
+
+DBUS_END_DECLS
+
+#endif /* DBUS_USERDB_H */
diff --git a/dbus/dbus/dbus-uuidgen.c b/dbus/dbus/dbus-uuidgen.c
new file mode 100644
index 0000000..6d7c0ae
--- /dev/null
+++ b/dbus/dbus/dbus-uuidgen.c
@@ -0,0 +1,130 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-uuidgen.c  The guts of the dbus-uuidgen binary live in libdbus, in this file.
+ *
+ * Copyright (C) 2006  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#include <config.h>
+#include "dbus-uuidgen.h"
+#include "dbus-internals.h"
+#include "dbus-string.h"
+#include "dbus-protocol.h"
+
+#ifdef DBUS_WIN
+#error "dbus-uuidgen should not be needed on Windows"
+#endif
+
+/**
+ * @defgroup DBusInternalsUuidgen dbus-uuidgen implementation
+ * @ingroup DBusInternals
+ * @brief Functions for dbus-uuidgen binary
+ *
+ * These are not considered part of the ABI, and if you call them
+ * you will get screwed by future changes.
+ * 
+ * @{
+ */
+
+static dbus_bool_t
+return_uuid (DBusGUID   *uuid,
+             char      **uuid_p,
+             DBusError  *error)
+{
+  if (uuid_p)
+    {
+      DBusString encoded;
+
+      if (!_dbus_string_init (&encoded))
+        {
+          _DBUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      if (!_dbus_uuid_encode (uuid, &encoded) ||
+          !_dbus_string_steal_data (&encoded, uuid_p))
+        {
+          _DBUS_SET_OOM (error);
+          _dbus_string_free (&encoded);
+          return FALSE;
+        }
+      _dbus_string_free (&encoded);
+    }
+  return TRUE;
+}
+
+/**
+ * For use by the dbus-uuidgen binary ONLY, do not call this.
+ * We can and will change this function without modifying
+ * the libdbus soname.
+ *
+ * @param filename the file or #NULL for the machine ID file
+ * @param uuid_p out param to return the uuid
+ * @param create_if_not_found whether to create it if not already there
+ * @param error error return
+ * @returns #FALSE if error is set
+ */
+dbus_bool_t
+dbus_internal_do_not_use_get_uuid (const char *filename,
+                                   char      **uuid_p,
+                                   dbus_bool_t create_if_not_found,
+                                   DBusError  *error)
+{
+  DBusGUID uuid;
+  
+  if (filename)
+    {
+      DBusString filename_str;
+      _dbus_string_init_const (&filename_str, filename);
+      if (!_dbus_read_uuid_file (&filename_str, &uuid, create_if_not_found, error))
+        goto error;
+    }
+  else
+    {
+      if (!_dbus_read_local_machine_uuid (&uuid, create_if_not_found, error))
+        goto error;
+    }
+
+  if (!return_uuid(&uuid, uuid_p, error))
+    goto error;
+
+  return TRUE;
+  
+ error:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  return FALSE;
+}
+
+/**
+ * For use by the dbus-uuidgen binary ONLY, do not call this.
+ * We can and will change this function without modifying
+ * the libdbus soname.
+ *
+ * @param uuid_p out param to return the uuid
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+dbus_internal_do_not_use_create_uuid (char      **uuid_p)
+{
+  DBusGUID uuid;
+
+  _dbus_generate_uuid (&uuid);
+  return return_uuid (&uuid, uuid_p, NULL);
+}
+
+/** @} */
diff --git a/dbus/dbus/dbus-uuidgen.h b/dbus/dbus/dbus-uuidgen.h
new file mode 100644
index 0000000..9c1b859
--- /dev/null
+++ b/dbus/dbus/dbus-uuidgen.h
@@ -0,0 +1,47 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-uuidgen.h  The guts of the dbus-uuidgen binary live in libdbus, in this file.
+ *
+ * Copyright (C) 2006  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifdef DBUS_INSIDE_DBUS_H
+#error "You can't include dbus-uuidgen.h in the public header dbus.h"
+#endif
+
+#ifndef DBUS_UUIDGEN_H
+#define DBUS_UUIDGEN_H
+
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-errors.h>
+
+DBUS_BEGIN_DECLS
+
+dbus_bool_t dbus_internal_do_not_use_get_uuid    (const char *filename,
+                                                  char      **uuid_p,
+                                                  dbus_bool_t create_if_not_found,
+                                                  DBusError  *error);
+dbus_bool_t dbus_internal_do_not_use_ensure_uuid (const char *filename,
+                                                  char      **uuid_p,
+                                                  DBusError  *error);
+dbus_bool_t dbus_internal_do_not_use_create_uuid (char      **uuid_p);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_UUIDGEN_H */
diff --git a/dbus/dbus/dbus-valgrind-internal.h b/dbus/dbus/dbus-valgrind-internal.h
new file mode 100644
index 0000000..55566ec
--- /dev/null
+++ b/dbus/dbus/dbus-valgrind-internal.h
@@ -0,0 +1,67 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-valgrind-internal.h - valgrind glue
+ *
+ * Copyright © 2011 Nokia Corporation
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#ifndef DBUS_VALGRIND_INTERNAL_H
+#define DBUS_VALGRIND_INTERNAL_H
+
+#include "config.h"
+#include "dbus-internals.h"
+
+#ifdef WITH_VALGRIND
+#   include <memcheck.h>
+#   include <valgrind.h>
+#else
+#   define VALGRIND_CREATE_MEMPOOL(_1, _2, _3) /* nothing */
+#   define VALGRIND_DESTROY_MEMPOOL(_1) /* nothing */
+#   define VALGRIND_MEMPOOL_ALLOC(_1, _2, _3) /* nothing */
+#   define VALGRIND_MEMPOOL_FREE(_1, _2) /* nothing */
+
+/* Recent gcc will warn if you have a statement that's just a macro
+ * expanding to (0), but not if you have an inline stub function that
+ * always returns 0, so let's do the latter. */
+static inline int
+VALGRIND_MAKE_MEM_UNDEFINED (void   *addr,
+                             size_t  len)
+{
+  return 0;
+}
+
+static inline int
+VALGRIND_PRINTF (const char *format,
+                 ...)
+{
+  return 0;
+}
+
+static inline int
+VALGRIND_PRINTF_BACKTRACE (const char *format,
+                           ...)
+{
+  return 0;
+}
+
+#   define RUNNING_ON_VALGRIND 0
+#endif /* WITH_VALGRIND */
+
+#endif /* header guard */
diff --git a/dbus/dbus/dbus-watch.c b/dbus/dbus/dbus-watch.c
new file mode 100644
index 0000000..b9f4ac2
--- /dev/null
+++ b/dbus/dbus/dbus-watch.c
@@ -0,0 +1,705 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-watch.c DBusWatch implementation
+ *
+ * Copyright (C) 2002, 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-watch.h"
+#include "dbus-list.h"
+
+/**
+ * @defgroup DBusWatchInternals DBusWatch implementation details
+ * @ingroup  DBusInternals
+ * @brief implementation details for DBusWatch
+ * 
+ * @{
+ */
+
+/**
+ * Implementation of DBusWatch
+ */
+struct DBusWatch
+{
+  int refcount;                        /**< Reference count */
+  int fd;                              /**< File descriptor. */
+  unsigned int flags;                  /**< Conditions to watch. */
+
+  DBusWatchHandler handler;                    /**< Watch handler. */
+  void *handler_data;                          /**< Watch handler data. */
+  DBusFreeFunction free_handler_data_function; /**< Free the watch handler data. */
+  
+  void *data;                          /**< Application data. */
+  DBusFreeFunction free_data_function; /**< Free the application data. */
+  unsigned int enabled : 1;            /**< Whether it's enabled. */
+  unsigned int oom_last_time : 1;      /**< Whether it was OOM last time. */
+};
+
+dbus_bool_t
+_dbus_watch_get_enabled (DBusWatch *watch)
+{
+  return watch->enabled;
+}
+
+dbus_bool_t
+_dbus_watch_get_oom_last_time (DBusWatch *watch)
+{
+  return watch->oom_last_time;
+}
+
+void
+_dbus_watch_set_oom_last_time (DBusWatch   *watch,
+                               dbus_bool_t  oom)
+{
+  watch->oom_last_time = oom;
+}
+
+/**
+ * Creates a new DBusWatch. Used to add a file descriptor to be polled
+ * by a main loop.
+ * 
+ * @param fd the file descriptor to be watched.
+ * @param flags the conditions to watch for on the descriptor.
+ * @param enabled the initial enabled state
+ * @param handler the handler function
+ * @param data data for handler function
+ * @param free_data_function function to free the data
+ * @returns the new DBusWatch object.
+ */
+DBusWatch*
+_dbus_watch_new (int               fd,
+                 unsigned int      flags,
+                 dbus_bool_t       enabled,
+                 DBusWatchHandler  handler,
+                 void             *data,
+                 DBusFreeFunction  free_data_function)
+{
+  DBusWatch *watch;
+
+#define VALID_WATCH_FLAGS (DBUS_WATCH_WRITABLE | DBUS_WATCH_READABLE)
+  
+  _dbus_assert ((flags & VALID_WATCH_FLAGS) == flags);
+  
+  watch = dbus_new0 (DBusWatch, 1);
+  if (watch == NULL)
+    return NULL;
+  
+  watch->refcount = 1;
+  watch->fd = fd;
+  watch->flags = flags;
+  watch->enabled = enabled;
+
+  watch->handler = handler;
+  watch->handler_data = data;
+  watch->free_handler_data_function = free_data_function;
+  
+  return watch;
+}
+
+/**
+ * Increments the reference count of a DBusWatch object.
+ *
+ * @param watch the watch object.
+ * @returns the watch object.
+ */
+DBusWatch *
+_dbus_watch_ref (DBusWatch *watch)
+{
+  watch->refcount += 1;
+
+  return watch;
+}
+
+/**
+ * Decrements the reference count of a DBusWatch object
+ * and finalizes the object if the count reaches zero.
+ *
+ * @param watch the watch object.
+ */
+void
+_dbus_watch_unref (DBusWatch *watch)
+{
+  _dbus_assert (watch != NULL);
+  _dbus_assert (watch->refcount > 0);
+
+  watch->refcount -= 1;
+  if (watch->refcount == 0)
+    {
+      if (watch->fd != -1)
+        _dbus_warn ("this watch should have been invalidated");
+
+      dbus_watch_set_data (watch, NULL, NULL); /* call free_data_function */
+
+      if (watch->free_handler_data_function)
+	(* watch->free_handler_data_function) (watch->handler_data);
+      
+      dbus_free (watch);
+    }
+}
+
+/**
+ * Clears the file descriptor from a now-invalid watch object so that
+ * no one tries to use it.  This is because a watch may stay alive due
+ * to reference counts after the file descriptor is closed.
+ * Invalidation makes it easier to catch bugs. It also
+ * keeps people from doing dorky things like assuming file descriptors
+ * are unique (never recycled).
+ *
+ * @param watch the watch object.
+ */
+void
+_dbus_watch_invalidate (DBusWatch *watch)
+{
+  watch->fd = -1;
+  watch->flags = 0;
+}
+
+/**
+ * Sanitizes the given condition so that it only contains
+ * flags that the DBusWatch requested. e.g. if the
+ * watch is a DBUS_WATCH_READABLE watch then
+ * DBUS_WATCH_WRITABLE will be stripped from the condition.
+ *
+ * @param watch the watch object.
+ * @param condition address of the condition to sanitize.
+ */
+void
+_dbus_watch_sanitize_condition (DBusWatch    *watch,
+                                unsigned int *condition)
+{
+  if (!(watch->flags & DBUS_WATCH_READABLE))
+    *condition &= ~DBUS_WATCH_READABLE;
+  if (!(watch->flags & DBUS_WATCH_WRITABLE))
+    *condition &= ~DBUS_WATCH_WRITABLE;
+}
+
+
+/**
+ * @typedef DBusWatchList
+ *
+ * Opaque data type representing a list of watches
+ * and a set of DBusAddWatchFunction/DBusRemoveWatchFunction.
+ * Automatically handles removing/re-adding watches
+ * when the DBusAddWatchFunction is updated or changed.
+ * Holds a reference count to each watch.
+ *
+ * Used in the implementation of both DBusServer and
+ * DBusClient.
+ *
+ */
+
+/**
+ * DBusWatchList implementation details. All fields
+ * are private.
+ *
+ */
+struct DBusWatchList
+{
+  DBusList *watches;           /**< Watch objects. */
+
+  DBusAddWatchFunction add_watch_function;    /**< Callback for adding a watch. */
+  DBusRemoveWatchFunction remove_watch_function; /**< Callback for removing a watch. */
+  DBusWatchToggledFunction watch_toggled_function; /**< Callback on toggling enablement */
+  void *watch_data;                           /**< Data for watch callbacks */
+  DBusFreeFunction watch_free_data_function;  /**< Free function for watch callback data */
+};
+
+/**
+ * Creates a new watch list. Returns #NULL if insufficient
+ * memory exists.
+ *
+ * @returns the new watch list, or #NULL on failure.
+ */
+DBusWatchList*
+_dbus_watch_list_new (void)
+{
+  DBusWatchList *watch_list;
+
+  watch_list = dbus_new0 (DBusWatchList, 1);
+  if (watch_list == NULL)
+    return NULL;
+
+  return watch_list;
+}
+
+/**
+ * Frees a DBusWatchList.
+ *
+ * @param watch_list the watch list.
+ */
+void
+_dbus_watch_list_free (DBusWatchList *watch_list)
+{
+  /* free watch_data and removes watches as a side effect */
+  _dbus_watch_list_set_functions (watch_list,
+                                  NULL, NULL, NULL, NULL, NULL);
+  _dbus_list_foreach (&watch_list->watches,
+                      (DBusForeachFunction) _dbus_watch_unref,
+                      NULL);
+  _dbus_list_clear (&watch_list->watches);
+
+  dbus_free (watch_list);
+}
+
+/**
+ * Sets the watch functions. This function is the "backend"
+ * for dbus_connection_set_watch_functions() and
+ * dbus_server_set_watch_functions().
+ *
+ * @param watch_list the watch list.
+ * @param add_function the add watch function.
+ * @param remove_function the remove watch function.
+ * @param toggled_function function on toggling enabled flag, or #NULL
+ * @param data the data for those functions.
+ * @param free_data_function the function to free the data.
+ * @returns #FALSE if not enough memory
+ *
+ */
+dbus_bool_t
+_dbus_watch_list_set_functions (DBusWatchList           *watch_list,
+                                DBusAddWatchFunction     add_function,
+                                DBusRemoveWatchFunction  remove_function,
+                                DBusWatchToggledFunction toggled_function,
+                                void                    *data,
+                                DBusFreeFunction         free_data_function)
+{
+  /* Add watches with the new watch function, failing on OOM */
+  if (add_function != NULL)
+    {
+      DBusList *link;
+      
+      link = _dbus_list_get_first_link (&watch_list->watches);
+      while (link != NULL)
+        {
+          DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
+                                                     link);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+          {
+            const char *watch_type;
+            int flags;
+
+            flags = dbus_watch_get_flags (link->data);
+            if ((flags & DBUS_WATCH_READABLE) &&
+                (flags & DBUS_WATCH_WRITABLE))
+              watch_type = "readwrite";
+            else if (flags & DBUS_WATCH_READABLE)
+              watch_type = "read";
+            else if (flags & DBUS_WATCH_WRITABLE)
+              watch_type = "write";
+            else
+              watch_type = "not read or write";
+            
+            _dbus_verbose ("Adding a %s watch on fd %d using newly-set add watch function\n",
+                           watch_type,
+                           dbus_watch_get_socket (link->data));
+          }
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+          
+          if (!(* add_function) (link->data, data))
+            {
+              /* remove it all again and return FALSE */
+              DBusList *link2;
+              
+              link2 = _dbus_list_get_first_link (&watch_list->watches);
+              while (link2 != link)
+                {
+                  DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
+                                                             link2);
+                  
+                  _dbus_verbose ("Removing watch on fd %d using newly-set remove function because initial add failed\n",
+                                 dbus_watch_get_socket (link2->data));
+                  
+                  (* remove_function) (link2->data, data);
+                  
+                  link2 = next;
+                }
+
+              return FALSE;
+            }
+      
+          link = next;
+        }
+    }
+  
+  /* Remove all current watches from previous watch handlers */
+
+  if (watch_list->remove_watch_function != NULL)
+    {
+      _dbus_verbose ("Removing all pre-existing watches\n");
+      
+      _dbus_list_foreach (&watch_list->watches,
+                          (DBusForeachFunction) watch_list->remove_watch_function,
+                          watch_list->watch_data);
+    }
+
+  if (watch_list->watch_free_data_function != NULL)
+    (* watch_list->watch_free_data_function) (watch_list->watch_data);
+  
+  watch_list->add_watch_function = add_function;
+  watch_list->remove_watch_function = remove_function;
+  watch_list->watch_toggled_function = toggled_function;
+  watch_list->watch_data = data;
+  watch_list->watch_free_data_function = free_data_function;
+
+  return TRUE;
+}
+
+/**
+ * Adds a new watch to the watch list, invoking the
+ * application DBusAddWatchFunction if appropriate.
+ *
+ * @param watch_list the watch list.
+ * @param watch the watch to add.
+ * @returns #TRUE on success, #FALSE if no memory.
+ */
+dbus_bool_t
+_dbus_watch_list_add_watch (DBusWatchList *watch_list,
+                            DBusWatch     *watch)
+{
+  if (!_dbus_list_append (&watch_list->watches, watch))
+    return FALSE;
+  
+  _dbus_watch_ref (watch);
+
+  if (watch_list->add_watch_function != NULL)
+    {
+      _dbus_verbose ("Adding watch on fd %d\n",
+                     dbus_watch_get_socket (watch));
+      
+      if (!(* watch_list->add_watch_function) (watch,
+                                               watch_list->watch_data))
+        {
+          _dbus_list_remove_last (&watch_list->watches, watch);
+          _dbus_watch_unref (watch);
+          return FALSE;
+        }
+    }
+  
+  return TRUE;
+}
+
+/**
+ * Removes a watch from the watch list, invoking the
+ * application's DBusRemoveWatchFunction if appropriate.
+ *
+ * @param watch_list the watch list.
+ * @param watch the watch to remove.
+ */
+void
+_dbus_watch_list_remove_watch  (DBusWatchList *watch_list,
+                                DBusWatch     *watch)
+{
+  if (!_dbus_list_remove (&watch_list->watches, watch))
+    _dbus_assert_not_reached ("Nonexistent watch was removed");
+  
+  if (watch_list->remove_watch_function != NULL)
+    {
+      _dbus_verbose ("Removing watch on fd %d\n",
+                     dbus_watch_get_socket (watch));
+      
+      (* watch_list->remove_watch_function) (watch,
+                                             watch_list->watch_data);
+    }
+  
+  _dbus_watch_unref (watch);
+}
+
+/**
+ * Sets a watch to the given enabled state, invoking the
+ * application's DBusWatchToggledFunction if appropriate.
+ *
+ * @param watch_list the watch list.
+ * @param watch the watch to toggle.
+ * @param enabled #TRUE to enable
+ */
+void
+_dbus_watch_list_toggle_watch (DBusWatchList           *watch_list,
+                               DBusWatch               *watch,
+                               dbus_bool_t              enabled)
+{
+  enabled = !!enabled;
+  
+  if (enabled == watch->enabled)
+    return;
+
+  watch->enabled = enabled;
+  
+  if (watch_list->watch_toggled_function != NULL)
+    {
+      _dbus_verbose ("Toggling watch %p on fd %d to %d\n",
+                     watch, dbus_watch_get_socket (watch), watch->enabled);
+      
+      (* watch_list->watch_toggled_function) (watch,
+                                              watch_list->watch_data);
+    }
+}
+
+/**
+ * Sets the handler for the watch.
+ *
+ * @todo this function only exists because of the weird
+ * way connection watches are done, see the note
+ * in docs for _dbus_connection_handle_watch().
+ *
+ * @param watch the watch
+ * @param handler the new handler
+ * @param data the data
+ * @param free_data_function free data with this
+ */
+void
+_dbus_watch_set_handler (DBusWatch        *watch,
+                         DBusWatchHandler  handler,
+                         void             *data,
+                         DBusFreeFunction  free_data_function)
+{
+  if (watch->free_handler_data_function)
+    (* watch->free_handler_data_function) (watch->handler_data);
+
+  watch->handler = handler;
+  watch->handler_data = data;
+  watch->free_handler_data_function = free_data_function;
+}
+
+/** @} */
+
+/**
+ * @defgroup DBusWatch DBusWatch
+ * @ingroup  DBus
+ * @brief Object representing a file descriptor to be watched.
+ *
+ * Types and functions related to DBusWatch. A watch represents
+ * a file descriptor that the main loop needs to monitor,
+ * as in Qt's QSocketNotifier or GLib's g_io_add_watch().
+ *
+ * Use dbus_connection_set_watch_functions() or dbus_server_set_watch_functions()
+ * to be notified when libdbus needs to add or remove watches.
+ * 
+ * @{
+ */
+
+/**
+ * @typedef DBusWatch
+ *
+ * Opaque object representing a file descriptor
+ * to be watched for changes in readability,
+ * writability, or hangup.
+ */
+
+/**
+ * Deprecated former name of dbus_watch_get_unix_fd().
+ * 
+ * @param watch the DBusWatch object.
+ * @returns the file descriptor to watch.
+ */
+int
+dbus_watch_get_fd (DBusWatch *watch)
+{
+  _dbus_return_val_if_fail (watch != NULL, -1);
+
+  return dbus_watch_get_unix_fd(watch);
+}
+
+/**
+ * Returns a UNIX file descriptor to be watched,
+ * which may be a pipe, socket, or other type of
+ * descriptor. On UNIX this is preferred to
+ * dbus_watch_get_socket() since it works with
+ * more kinds of #DBusWatch.
+ *
+ * Always returns -1 on Windows. On Windows you use
+ * dbus_watch_get_socket() to get a Winsock socket to watch.
+ * 
+ * @param watch the DBusWatch object.
+ * @returns the file descriptor to watch.
+ */
+int
+dbus_watch_get_unix_fd (DBusWatch *watch)
+{
+  _dbus_return_val_if_fail (watch != NULL, -1);
+
+  /* FIXME remove #ifdef and do this on a lower level
+   * (watch should have set_socket and set_unix_fd and track
+   * which it has, and the transport should provide the
+   * appropriate watch type)
+   */
+#ifdef DBUS_UNIX
+  return watch->fd;
+#else
+  return dbus_watch_get_socket( watch );
+#endif
+}
+
+/**
+ * Returns a socket to be watched, on UNIX this will return -1 if our
+ * transport is not socket-based so dbus_watch_get_unix_fd() is
+ * preferred.
+ *
+ * On Windows, dbus_watch_get_unix_fd() returns -1 but this function
+ * returns a Winsock socket (assuming the transport is socket-based,
+ * as it always is for now).
+ * 
+ * @param watch the DBusWatch object.
+ * @returns the socket to watch.
+ */
+int
+dbus_watch_get_socket (DBusWatch *watch)
+{
+  _dbus_return_val_if_fail (watch != NULL, -1);
+
+  return watch->fd;
+}
+
+/**
+ * Gets flags from DBusWatchFlags indicating
+ * what conditions should be monitored on the
+ * file descriptor.
+ * 
+ * The flags returned will only contain DBUS_WATCH_READABLE
+ * and DBUS_WATCH_WRITABLE, never DBUS_WATCH_HANGUP or
+ * DBUS_WATCH_ERROR; all watches implicitly include a watch
+ * for hangups, errors, and other exceptional conditions.
+ *
+ * @param watch the DBusWatch object.
+ * @returns the conditions to watch.
+ */
+unsigned int
+dbus_watch_get_flags (DBusWatch *watch)
+{
+  _dbus_return_val_if_fail (watch != NULL, 0);
+  _dbus_assert ((watch->flags & VALID_WATCH_FLAGS) == watch->flags);
+
+  return watch->flags;
+}
+
+/**
+ * Gets data previously set with dbus_watch_set_data()
+ * or #NULL if none.
+ *
+ * @param watch the DBusWatch object.
+ * @returns previously-set data.
+ */
+void*
+dbus_watch_get_data (DBusWatch *watch)
+{
+  _dbus_return_val_if_fail (watch != NULL, NULL);
+
+  return watch->data;
+}
+
+/**
+ * Sets data which can be retrieved with dbus_watch_get_data().
+ * Intended for use by the DBusAddWatchFunction and
+ * DBusRemoveWatchFunction to store their own data.  For example with
+ * Qt you might store the QSocketNotifier for this watch and with GLib
+ * you might store a GSource.
+ *
+ * @param watch the DBusWatch object.
+ * @param data the data.
+ * @param free_data_function function to be called to free the data.
+ */
+void
+dbus_watch_set_data (DBusWatch        *watch,
+                     void             *data,
+                     DBusFreeFunction  free_data_function)
+{
+  _dbus_return_if_fail (watch != NULL);
+
+  _dbus_verbose ("Setting watch fd %d data to data = %p function = %p from data = %p function = %p\n",
+                 dbus_watch_get_socket (watch),
+                 data, free_data_function, watch->data, watch->free_data_function);
+  
+  if (watch->free_data_function != NULL)
+    (* watch->free_data_function) (watch->data);
+  
+  watch->data = data;
+  watch->free_data_function = free_data_function;
+}
+
+/**
+ * Returns whether a watch is enabled or not. If not
+ * enabled, it should not be polled by the main loop.
+ *
+ * @param watch the DBusWatch object
+ * @returns #TRUE if the watch is enabled
+ */
+dbus_bool_t
+dbus_watch_get_enabled (DBusWatch *watch)
+{
+  _dbus_return_val_if_fail (watch != NULL, FALSE);
+
+  return watch->enabled;
+}
+
+
+/**
+ * Called to notify the D-Bus library when a previously-added watch is
+ * ready for reading or writing, or has an exception such as a hangup.
+ * 
+ * If this function returns #FALSE, then the file descriptor may still
+ * be ready for reading or writing, but more memory is needed in order
+ * to do the reading or writing. If you ignore the #FALSE return, your
+ * application may spin in a busy loop on the file descriptor until
+ * memory becomes available, but nothing more catastrophic should
+ * happen.
+ *
+ * dbus_watch_handle() cannot be called during the
+ * DBusAddWatchFunction, as the connection will not be ready to handle
+ * that watch yet.
+ * 
+ * It is not allowed to reference a DBusWatch after it has been passed
+ * to remove_function.
+ *
+ * @param watch the DBusWatch object.
+ * @param flags the poll condition using #DBusWatchFlags values
+ * @returns #FALSE if there wasn't enough memory 
+ */
+dbus_bool_t
+dbus_watch_handle (DBusWatch    *watch,
+                   unsigned int  flags)
+{
+  _dbus_return_val_if_fail (watch != NULL, FALSE);
+
+#ifndef DBUS_DISABLE_CHECKS
+  if (watch->fd < 0 || watch->flags == 0)
+    {
+      _dbus_warn_check_failed ("Watch is invalid, it should have been removed\n");
+      return TRUE;
+    }
+#endif
+    
+  _dbus_return_val_if_fail (watch->fd >= 0 /* fails if watch was removed */, TRUE);
+  
+  _dbus_watch_sanitize_condition (watch, &flags);
+
+  if (flags == 0)
+    {
+      _dbus_verbose ("After sanitization, watch flags on fd %d were 0\n",
+                     watch->fd);
+      return TRUE;
+    }
+  else
+    return (* watch->handler) (watch, flags,
+                               watch->handler_data);
+}
+
+
+/** @} */
diff --git a/dbus/dbus/dbus-watch.h b/dbus/dbus/dbus-watch.h
new file mode 100644
index 0000000..c583214
--- /dev/null
+++ b/dbus/dbus/dbus-watch.h
@@ -0,0 +1,89 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-watch.h DBusWatch internal interfaces
+ *
+ * Copyright (C) 2002  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+#ifndef DBUS_WATCH_H
+#define DBUS_WATCH_H
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-connection.h>
+
+DBUS_BEGIN_DECLS
+
+/**
+ * @addtogroup DBusWatchInternals
+ * @{
+ */
+
+/* Public methods on DBusWatch are in dbus-connection.h */
+
+typedef struct DBusWatchList DBusWatchList;
+
+#define _DBUS_WATCH_NVAL (1<<4)
+
+/** function to run when the watch is handled */
+typedef dbus_bool_t (* DBusWatchHandler) (DBusWatch    *watch,
+                                          unsigned int  flags,
+                                          void         *data);
+
+DBusWatch* _dbus_watch_new                (int               fd,
+                                           unsigned int      flags,
+                                           dbus_bool_t       enabled,
+                                           DBusWatchHandler  handler,
+                                           void             *data,
+                                           DBusFreeFunction  free_data_function);
+DBusWatch* _dbus_watch_ref                (DBusWatch        *watch);
+void       _dbus_watch_unref              (DBusWatch        *watch);
+void       _dbus_watch_invalidate         (DBusWatch        *watch);
+void       _dbus_watch_sanitize_condition (DBusWatch        *watch,
+                                           unsigned int     *condition);
+void       _dbus_watch_set_handler        (DBusWatch        *watch,
+                                           DBusWatchHandler  handler,
+                                           void             *data,
+                                           DBusFreeFunction  free_data_function);
+
+
+DBusWatchList* _dbus_watch_list_new           (void);
+void           _dbus_watch_list_free          (DBusWatchList           *watch_list);
+dbus_bool_t    _dbus_watch_list_set_functions (DBusWatchList           *watch_list,
+                                               DBusAddWatchFunction     add_function,
+                                               DBusRemoveWatchFunction  remove_function,
+                                               DBusWatchToggledFunction toggled_function,
+                                               void                    *data,
+                                               DBusFreeFunction         free_data_function);
+dbus_bool_t    _dbus_watch_list_add_watch     (DBusWatchList           *watch_list,
+                                               DBusWatch               *watch);
+void           _dbus_watch_list_remove_watch  (DBusWatchList           *watch_list,
+                                               DBusWatch               *watch);
+void           _dbus_watch_list_toggle_watch  (DBusWatchList           *watch_list,
+                                               DBusWatch               *watch,
+                                               dbus_bool_t              enabled);
+dbus_bool_t    _dbus_watch_get_enabled        (DBusWatch              *watch);
+
+dbus_bool_t    _dbus_watch_get_oom_last_time  (DBusWatch               *watch);
+void           _dbus_watch_set_oom_last_time  (DBusWatch               *watch,
+                                               dbus_bool_t              oom);
+
+/** @} */
+
+DBUS_END_DECLS
+
+#endif /* DBUS_WATCH_H */
diff --git a/dbus/dbus/dbus.h b/dbus/dbus/dbus.h
new file mode 100644
index 0000000..932ceab
--- /dev/null
+++ b/dbus/dbus/dbus.h
@@ -0,0 +1,104 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus.h  Convenience header including all other headers
+ *
+ * Copyright (C) 2002, 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_H
+#define DBUS_H
+
+#define DBUS_INSIDE_DBUS_H 1
+
+#include <dbus/dbus-arch-deps.h>
+#include <dbus/dbus-address.h>
+#include <dbus/dbus-bus.h>
+#include <dbus/dbus-connection.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-message.h>
+#include <dbus/dbus-misc.h>
+#include <dbus/dbus-pending-call.h>
+#include <dbus/dbus-protocol.h>
+#include <dbus/dbus-server.h>
+#include <dbus/dbus-shared.h>
+#include <dbus/dbus-signature.h>
+#include <dbus/dbus-syntax.h>
+#include <dbus/dbus-threads.h>
+#include <dbus/dbus-types.h>
+
+#undef DBUS_INSIDE_DBUS_H
+
+/**
+ * @defgroup DBus D-Bus low-level public API
+ * @brief The low-level public API of the D-Bus library
+ *
+ * libdbus provides a low-level C API intended primarily for use by
+ * bindings to specific object systems and languages.  D-Bus is most
+ * convenient when used with the GLib bindings, Python bindings, Qt
+ * bindings, Mono bindings, and so forth.  This low-level API has a
+ * lot of complexity useful only for bindings.
+ * 
+ * @{
+ */
+
+/** @} */
+
+/**
+ * @mainpage
+ *
+ * This manual documents the <em>low-level</em> D-Bus C API. <b>If you use
+ * this low-level API directly, you're signing up for some pain.</b>
+ *
+ * Caveats aside, you might get started learning the low-level API by reading
+ * about @ref DBusConnection and @ref DBusMessage.
+ * 
+ * There are several other places to look for D-Bus information, such
+ * as the tutorial and the specification; those can be found at <a
+ * href="http://www.freedesktop.org/wiki/Software/dbus">the D-Bus
+ * website</a>. If you're interested in a sysadmin or package
+ * maintainer's perspective on the dbus-daemon itself and its
+ * configuration, be sure to check out the man pages as well.
+ *
+ * The low-level API documented in this manual deliberately lacks
+ * most convenience functions - those are left up to higher-level libraries
+ * based on frameworks such as GLib, Qt, Python, Mono, Java,
+ * etc. These higher-level libraries (often called "D-Bus bindings")
+ * have features such as object systems and main loops that allow a
+ * <em>much</em> more convenient API.
+ * 
+ * The low-level API also contains plenty of clutter to support
+ * integration with arbitrary object systems, languages, main loops,
+ * and so forth. These features add a lot of noise to the API that you
+ * probably don't care about unless you're coding a binding.
+ *
+ * This manual also contains docs for @ref DBusInternals "D-Bus internals",
+ * so you can use it to get oriented to the D-Bus source code if you're
+ * interested in patching the code. You should also read the
+ * file HACKING which comes with the source code if you plan to contribute to
+ * D-Bus.
+ *
+ * As you read the code, you can identify internal D-Bus functions
+ * because they start with an underscore ('_') character. Also, any
+ * identifier or macro that lacks a DBus, dbus_, or DBUS_ namepace
+ * prefix is internal, with a couple of exceptions such as #NULL,
+ * #TRUE, and #FALSE.
+ */
+
+#endif /* DBUS_H */
diff --git a/dbus/dbus/sd-daemon.c b/dbus/dbus/sd-daemon.c
new file mode 100644
index 0000000..9c23b91
--- /dev/null
+++ b/dbus/dbus/sd-daemon.c
@@ -0,0 +1,435 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  Copyright 2010 Lennart Poettering
+
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation files
+  (the "Software"), to deal in the Software without restriction,
+  including without limitation the rights to use, copy, modify, merge,
+  publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+***/
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/fcntl.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "sd-daemon.h"
+
+int sd_listen_fds(int unset_environment) {
+
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
+        return 0;
+#else
+        int r, fd;
+        const char *e;
+        char *p = NULL;
+        unsigned long l;
+
+        if (!(e = getenv("LISTEN_PID"))) {
+                r = 0;
+                goto finish;
+        }
+
+        errno = 0;
+        l = strtoul(e, &p, 10);
+
+        if (errno != 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        if (!p || *p || l <= 0) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        /* Is this for us? */
+        if (getpid() != (pid_t) l) {
+                r = 0;
+                goto finish;
+        }
+
+        if (!(e = getenv("LISTEN_FDS"))) {
+                r = 0;
+                goto finish;
+        }
+
+        errno = 0;
+        l = strtoul(e, &p, 10);
+
+        if (errno != 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        if (!p || *p) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) {
+                int flags;
+
+                if ((flags = fcntl(fd, F_GETFD)) < 0) {
+                        r = -errno;
+                        goto finish;
+                }
+
+                if (flags & FD_CLOEXEC)
+                        continue;
+
+                if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
+                        r = -errno;
+                        goto finish;
+                }
+        }
+
+        r = (int) l;
+
+finish:
+        if (unset_environment) {
+                unsetenv("LISTEN_PID");
+                unsetenv("LISTEN_FDS");
+        }
+
+        return r;
+#endif
+}
+
+int sd_is_fifo(int fd, const char *path) {
+        struct stat st_fd;
+
+        if (fd < 0)
+                return -EINVAL;
+
+        memset(&st_fd, 0, sizeof(st_fd));
+        if (fstat(fd, &st_fd) < 0)
+                return -errno;
+
+        if (!S_ISFIFO(st_fd.st_mode))
+                return 0;
+
+        if (path) {
+                struct stat st_path;
+
+                memset(&st_path, 0, sizeof(st_path));
+                if (stat(path, &st_path) < 0) {
+
+                        if (errno == ENOENT || errno == ENOTDIR)
+                                return 0;
+
+                        return -errno;
+                }
+
+                return
+                        st_path.st_dev == st_fd.st_dev &&
+                        st_path.st_ino == st_fd.st_ino;
+        }
+
+        return 1;
+}
+
+static int sd_is_socket_internal(int fd, int type, int listening) {
+        struct stat st_fd;
+
+        if (fd < 0 || type < 0)
+                return -EINVAL;
+
+        if (fstat(fd, &st_fd) < 0)
+                return -errno;
+
+        if (!S_ISSOCK(st_fd.st_mode))
+                return 0;
+
+        if (type != 0) {
+                int other_type = 0;
+                socklen_t l = sizeof(other_type);
+
+                if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
+                        return -errno;
+
+                if (l != sizeof(other_type))
+                        return -EINVAL;
+
+                if (other_type != type)
+                        return 0;
+        }
+
+        if (listening >= 0) {
+                int accepting = 0;
+                socklen_t l = sizeof(accepting);
+
+                if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
+                        return -errno;
+
+                if (l != sizeof(accepting))
+                        return -EINVAL;
+
+                if (!accepting != !listening)
+                        return 0;
+        }
+
+        return 1;
+}
+
+union sockaddr_union {
+        struct sockaddr sa;
+        struct sockaddr_in in4;
+        struct sockaddr_in6 in6;
+        struct sockaddr_un un;
+        struct sockaddr_storage storage;
+};
+
+int sd_is_socket(int fd, int family, int type, int listening) {
+        int r;
+
+        if (family < 0)
+                return -EINVAL;
+
+        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
+                return r;
+
+        if (family > 0) {
+                union sockaddr_union sockaddr;
+                socklen_t l;
+
+                memset(&sockaddr, 0, sizeof(sockaddr));
+                l = sizeof(sockaddr);
+
+                if (getsockname(fd, &sockaddr.sa, &l) < 0)
+                        return -errno;
+
+                if (l < sizeof(sa_family_t))
+                        return -EINVAL;
+
+                return sockaddr.sa.sa_family == family;
+        }
+
+        return 1;
+}
+
+int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
+        union sockaddr_union sockaddr;
+        socklen_t l;
+        int r;
+
+        if (family != 0 && family != AF_INET && family != AF_INET6)
+                return -EINVAL;
+
+        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
+                return r;
+
+        memset(&sockaddr, 0, sizeof(sockaddr));
+        l = sizeof(sockaddr);
+
+        if (getsockname(fd, &sockaddr.sa, &l) < 0)
+                return -errno;
+
+        if (l < sizeof(sa_family_t))
+                return -EINVAL;
+
+        if (sockaddr.sa.sa_family != AF_INET &&
+            sockaddr.sa.sa_family != AF_INET6)
+                return 0;
+
+        if (family > 0)
+                if (sockaddr.sa.sa_family != family)
+                        return 0;
+
+        if (port > 0) {
+                if (sockaddr.sa.sa_family == AF_INET) {
+                        if (l < sizeof(struct sockaddr_in))
+                                return -EINVAL;
+
+                        return htons(port) == sockaddr.in4.sin_port;
+                } else {
+                        if (l < sizeof(struct sockaddr_in6))
+                                return -EINVAL;
+
+                        return htons(port) == sockaddr.in6.sin6_port;
+                }
+        }
+
+        return 1;
+}
+
+int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
+        union sockaddr_union sockaddr;
+        socklen_t l;
+        int r;
+
+        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
+                return r;
+
+        memset(&sockaddr, 0, sizeof(sockaddr));
+        l = sizeof(sockaddr);
+
+        if (getsockname(fd, &sockaddr.sa, &l) < 0)
+                return -errno;
+
+        if (l < sizeof(sa_family_t))
+                return -EINVAL;
+
+        if (sockaddr.sa.sa_family != AF_UNIX)
+                return 0;
+
+        if (path) {
+                if (length <= 0)
+                        length = strlen(path);
+
+                if (length <= 0)
+                        /* Unnamed socket */
+                        return l == sizeof(sa_family_t);
+
+                if (path[0])
+                        /* Normal path socket */
+                        return
+                                (l >= sizeof(sa_family_t) + length + 1) &&
+                                memcmp(path, sockaddr.un.sun_path, length+1) == 0;
+                else
+                        /* Abstract namespace socket */
+                        return
+                                (l == sizeof(sa_family_t) + length) &&
+                                memcmp(path, sockaddr.un.sun_path, length) == 0;
+        }
+
+        return 1;
+}
+
+int sd_notify(int unset_environment, const char *state) {
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
+        return 0;
+#else
+        int fd = -1, r;
+        struct msghdr msghdr;
+        struct iovec iovec;
+        union sockaddr_union sockaddr;
+        const char *e;
+
+        if (!state) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        if (!(e = getenv("NOTIFY_SOCKET")))
+                return 0;
+
+        /* Must be an abstract socket, or an absolute path */
+        if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
+                r = -EINVAL;
+                goto finish;
+        }
+
+        if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        memset(&sockaddr, 0, sizeof(sockaddr));
+        sockaddr.sa.sa_family = AF_UNIX;
+        strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
+
+        if (sockaddr.un.sun_path[0] == '@')
+                sockaddr.un.sun_path[0] = 0;
+
+        memset(&iovec, 0, sizeof(iovec));
+        iovec.iov_base = (char*) state;
+        iovec.iov_len = strlen(state);
+
+        memset(&msghdr, 0, sizeof(msghdr));
+        msghdr.msg_name = &sockaddr;
+        msghdr.msg_namelen = sizeof(sa_family_t) + strlen(e);
+
+        if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
+                msghdr.msg_namelen = sizeof(struct sockaddr_un);
+
+        msghdr.msg_iov = &iovec;
+        msghdr.msg_iovlen = 1;
+
+        if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
+                r = -errno;
+                goto finish;
+        }
+
+        r = 1;
+
+finish:
+        if (unset_environment)
+                unsetenv("NOTIFY_SOCKET");
+
+        if (fd >= 0)
+                close(fd);
+
+        return r;
+#endif
+}
+
+int sd_notifyf(int unset_environment, const char *format, ...) {
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
+        return 0;
+#else
+        va_list ap;
+        char *p = NULL;
+        int r;
+
+        va_start(ap, format);
+        r = vasprintf(&p, format, ap);
+        va_end(ap);
+
+        if (r < 0 || !p)
+                return -ENOMEM;
+
+        r = sd_notify(unset_environment, p);
+        free(p);
+
+        return r;
+#endif
+}
+
+int sd_booted(void) {
+#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
+        return 0;
+#else
+
+        struct stat a, b;
+
+        /* We simply test whether the systemd cgroup hierarchy is
+         * mounted */
+
+        if (lstat("/sys/fs/cgroup", &a) < 0)
+                return 0;
+
+        if (lstat("/sys/fs/cgroup/systemd", &b) < 0)
+                return 0;
+
+        return a.st_dev != b.st_dev;
+#endif
+}
diff --git a/dbus/dbus/sd-daemon.h b/dbus/dbus/sd-daemon.h
new file mode 100644
index 0000000..c68c96d
--- /dev/null
+++ b/dbus/dbus/sd-daemon.h
@@ -0,0 +1,257 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foosddaemonhfoo
+#define foosddaemonhfoo
+
+/***
+  Copyright 2010 Lennart Poettering
+
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation files
+  (the "Software"), to deal in the Software without restriction,
+  including without limitation the rights to use, copy, modify, merge,
+  publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+***/
+
+#include <sys/types.h>
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+  Reference implementation of a few systemd related interfaces for
+  writing daemons. These interfaces are trivial to implement. To
+  simplify porting we provide this reference implementation.
+  Applications are welcome to reimplement the algorithms described
+  here if they do not want to include these two source files.
+
+  The following functionality is provided:
+
+  - Support for logging with log levels on stderr
+  - File descriptor passing for socket-based activation
+  - Daemon startup and status notification
+  - Detection of systemd boots
+
+  You may compile this with -DDISABLE_SYSTEMD to disable systemd
+  support. This makes all those calls NOPs that are directly related to
+  systemd (i.e. only sd_is_xxx() will stay useful).
+
+  Since this is drop-in code we don't want any of our symbols to be
+  exported in any case. Hence we declare hidden visibility for all of
+  them.
+
+  You may find an up-to-date version of these source files online:
+
+  http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.h
+  http://cgit.freedesktop.org/systemd/plain/src/sd-daemon.c
+
+  This should compile on non-Linux systems, too, but with the
+  exception of the sd_is_xxx() calls all functions will become NOPs.
+
+  See sd-daemon(7) for more information.
+*/
+
+#if __GNUC__ >= 4
+#define _sd_printf_attr_(a,b) __attribute__ ((format (printf, a, b)))
+#define _sd_hidden_ __attribute__ ((visibility("hidden")))
+#else
+#define _sd_printf_attr_(a,b)
+#define _sd_hidden_
+#endif
+
+/*
+  Log levels for usage on stderr:
+
+          fprintf(stderr, SD_NOTICE "Hello World!\n");
+
+  This is similar to printk() usage in the kernel.
+*/
+#define SD_EMERG   "<0>"  /* system is unusable */
+#define SD_ALERT   "<1>"  /* action must be taken immediately */
+#define SD_CRIT    "<2>"  /* critical conditions */
+#define SD_ERR     "<3>"  /* error conditions */
+#define SD_WARNING "<4>"  /* warning conditions */
+#define SD_NOTICE  "<5>"  /* normal but significant condition */
+#define SD_INFO    "<6>"  /* informational */
+#define SD_DEBUG   "<7>"  /* debug-level messages */
+
+/* The first passed file descriptor is fd 3 */
+#define SD_LISTEN_FDS_START 3
+
+/*
+  Returns how many file descriptors have been passed, or a negative
+  errno code on failure. Optionally, removes the $LISTEN_FDS and
+  $LISTEN_PID file descriptors from the environment (recommended, but
+  problematic in threaded environments). If r is the return value of
+  this function you'll find the file descriptors passed as fds
+  SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative
+  errno style error code on failure. This function call ensures that
+  the FD_CLOEXEC flag is set for the passed file descriptors, to make
+  sure they are not passed on to child processes. If FD_CLOEXEC shall
+  not be set, the caller needs to unset it after this call for all file
+  descriptors that are used.
+
+  See sd_listen_fds(3) for more information.
+*/
+int sd_listen_fds(int unset_environment) _sd_hidden_;
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is a FIFO in the file system stored under the
+  specified path, 0 otherwise. If path is NULL a path name check will
+  not be done and the call only verifies if the file descriptor
+  refers to a FIFO. Returns a negative errno style error code on
+  failure.
+
+  See sd_is_fifo(3) for more information.
+*/
+int sd_is_fifo(int fd, const char *path) _sd_hidden_;
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is a socket of the specified family (AF_INET,
+  ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If
+  family is 0 a socket family check will not be done. If type is 0 a
+  socket type check will not be done and the call only verifies if
+  the file descriptor refers to a socket. If listening is > 0 it is
+  verified that the socket is in listening mode. (i.e. listen() has
+  been called) If listening is == 0 it is verified that the socket is
+  not in listening mode. If listening is < 0 no listening mode check
+  is done. Returns a negative errno style error code on failure.
+
+  See sd_is_socket(3) for more information.
+*/
+int sd_is_socket(int fd, int family, int type, int listening) _sd_hidden_;
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is an Internet socket, of the specified family
+  (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM,
+  SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version
+  check is not done. If type is 0 a socket type check will not be
+  done. If port is 0 a socket port check will not be done. The
+  listening flag is used the same way as in sd_is_socket(). Returns a
+  negative errno style error code on failure.
+
+  See sd_is_socket_inet(3) for more information.
+*/
+int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) _sd_hidden_;
+
+/*
+  Helper call for identifying a passed file descriptor. Returns 1 if
+  the file descriptor is an AF_UNIX socket of the specified type
+  (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0
+  a socket type check will not be done. If path is NULL a socket path
+  check will not be done. For normal AF_UNIX sockets set length to
+  0. For abstract namespace sockets set length to the length of the
+  socket name (including the initial 0 byte), and pass the full
+  socket path in path (including the initial 0 byte). The listening
+  flag is used the same way as in sd_is_socket(). Returns a negative
+  errno style error code on failure.
+
+  See sd_is_socket_unix(3) for more information.
+*/
+int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) _sd_hidden_;
+
+/*
+  Informs systemd about changed daemon state. This takes a number of
+  newline seperated environment-style variable assignments in a
+  string. The following variables are known:
+
+     READY=1      Tells systemd that daemon startup is finished (only
+                  relevant for services of Type=notify). The passed
+                  argument is a boolean "1" or "0". Since there is
+                  little value in signalling non-readiness the only
+                  value daemons should send is "READY=1".
+
+     STATUS=...   Passes a single-line status string back to systemd
+                  that describes the daemon state. This is free-from
+                  and can be used for various purposes: general state
+                  feedback, fsck-like programs could pass completion
+                  percentages and failing programs could pass a human
+                  readable error message. Example: "STATUS=Completed
+                  66% of file system check..."
+
+     ERRNO=...    If a daemon fails, the errno-style error code,
+                  formatted as string. Example: "ERRNO=2" for ENOENT.
+
+     BUSERROR=... If a daemon fails, the D-Bus error-style error
+                  code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut"
+
+     MAINPID=...  The main pid of a daemon, in case systemd did not
+                  fork off the process itself. Example: "MAINPID=4711"
+
+  Daemons can choose to send additional variables. However, it is
+  recommened to prefix variable names not listed above with X_.
+
+  Returns a negative errno-style error code on failure. Returns > 0
+  if systemd could be notified, 0 if it couldn't possibly because
+  systemd is not running.
+
+  Example: When a daemon finished starting up, it could issue this
+  call to notify systemd about it:
+
+     sd_notify(0, "READY=1");
+
+  See sd_notifyf() for more complete examples.
+
+  See sd_notify(3) for more information.
+*/
+int sd_notify(int unset_environment, const char *state) _sd_hidden_;
+
+/*
+  Similar to sd_notify() but takes a format string.
+
+  Example 1: A daemon could send the following after initialization:
+
+     sd_notifyf(0, "READY=1\n"
+                   "STATUS=Processing requests...\n"
+                   "MAINPID=%lu",
+                   (unsigned long) getpid());
+
+  Example 2: A daemon could send the following shortly before
+  exiting, on failure:
+
+     sd_notifyf(0, "STATUS=Failed to start up: %s\n"
+                   "ERRNO=%i",
+                   strerror(errno),
+                   errno);
+
+  See sd_notifyf(3) for more information.
+*/
+int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_attr_(2,3) _sd_hidden_;
+
+/*
+  Returns > 0 if the system was booted with systemd. Returns < 0 on
+  error. Returns 0 if the system was not booted with systemd. Note
+  that all of the functions above handle non-systemd boots just
+  fine. You should NOT protect them with a call to this function. Also
+  note that this function checks whether the system, not the user
+  session is controlled by systemd. However the functions above work
+  for both session and system services.
+
+  See sd_booted(3) for more information.
+*/
+int sd_booted(void) _sd_hidden_;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dbus/dbus/versioninfo.rc.in b/dbus/dbus/versioninfo.rc.in
new file mode 100644
index 0000000..b745b39
--- /dev/null
+++ b/dbus/dbus/versioninfo.rc.in
@@ -0,0 +1,52 @@
+/* versioninfo.rc.in - for dbus
+ * Copyright (C) 2005 g10 Code GmbH
+ * 
+ * This file is free software; as a special exception the author 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.
+ */
+ 
+/* This file is processed by configure to create versioninfo.rc */
+
+#line __LINE__ "versioninfo.rc.in"
+
+#include <afxres.h>
+
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION @BUILD_FILEVERSION@
+ PRODUCTVERSION @BUILD_FILEVERSION@
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x21L
+#else
+ FILEFLAGS 0x20L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "Comments", "Provided under the terms of the GNU Lesser General Public License.\0"
+            VALUE "CompanyName", "FreeDesktop.org\0"
+            VALUE "FileDescription", "dbus - FreeDesktop message bus system\0"
+            VALUE "FileVersion", "@DBUS_VERSION@\0"
+            VALUE "InternalName", "dbus\0"
+            VALUE "LegalCopyright", "Copyright © 2009 FreeDesktop.org\0"
+            VALUE "LegalTrademarks", "\0"
+            VALUE "OriginalFilename", "dbus-1.dll\0"
+            VALUE "PrivateBuild", "\0"
+            VALUE "ProductName", "dbus\0"
+            VALUE "ProductVersion", "@DBUS_VERSION@\0"
+            VALUE "SpecialBuild", "@BUILD_TIMESTAMP@\0"
+        END
+    END
+END
+
diff --git a/dbus/doc/Makefile.am b/dbus/doc/Makefile.am
new file mode 100644
index 0000000..b265987
--- /dev/null
+++ b/dbus/doc/Makefile.am
@@ -0,0 +1,176 @@
+apidir = @htmldir@/api
+
+# automake normally assumes that man pages are generated files;
+# these ones aren't, so we need the dist_ prefix to say that they're
+# their own source code
+dist_man1_MANS = \
+	dbus-cleanup-sockets.1 \
+	dbus-launch.1 \
+	dbus-monitor.1 \
+	dbus-send.1 \
+	dbus-uuidgen.1
+
+# on the other hand, this one is generated
+man1_MANS = \
+	dbus-daemon.1
+
+MAN_IN_FILES = dbus-daemon.1.in
+
+MAN_HTML_FILES = \
+	dbus-cleanup-sockets.1.html \
+	dbus-daemon.1.html \
+	dbus-launch.1.html \
+	dbus-monitor.1.html \
+	dbus-send.1.html \
+	dbus-uuidgen.1.html
+
+DTDS = \
+	busconfig.dtd \
+	introspect.dtd
+
+dist_doc_DATA = system-activation.txt
+
+# uploaded and distributed, but not installed
+STATIC_DOCS = \
+	dbus-faq.xml \
+	dbus-specification.xml \
+	dbus-test-plan.xml \
+	dbus-tutorial.xml \
+	dcop-howto.txt \
+	introspect.xsl \
+	$(DTDS)
+
+EXTRA_DIST = \
+	file-boilerplate.c \
+	doxygen_to_devhelp.xsl \
+	$(STATIC_DOCS) \
+	$(MAN_IN_FILES)
+
+html_DATA =
+
+dist_html_DATA =
+
+# diagram.png/diagram.svg aren't really HTML, but must go in the same
+# directory as the HTML to avoid broken links
+STATIC_HTML = \
+	diagram.png \
+	diagram.svg \
+	$(NULL)
+
+dist_html_DATA += $(STATIC_HTML)
+
+# we distribute these in the tarball so users don't necessarily need xmlto
+dist_html_DATA += $(XMLTO_OUTPUT)
+
+XMLTO_OUTPUT=					\
+	dbus-faq.html				\
+	dbus-specification.html			\
+	dbus-test-plan.html			\
+	dbus-tutorial.html
+
+if DBUS_XML_DOCS_ENABLED
+dbus-specification.html: dbus-specification.xml
+	$(XMLTO) html-nochunks $<
+
+dbus-test-plan.html: dbus-test-plan.xml
+	$(XMLTO) html-nochunks $<
+
+dbus-tutorial.html: dbus-tutorial.xml
+	$(XMLTO) html-nochunks $<
+
+dbus-faq.html: dbus-faq.xml
+	$(XMLTO) html-nochunks $<
+endif
+
+if DBUS_DOXYGEN_DOCS_ENABLED
+all-local:: doxygen.stamp
+
+doxygen.stamp: $(wildcard $(top_srcdir)/dbus/*.[ch])
+	$(AM_V_GEN)cd $(top_builddir) && doxygen Doxyfile
+	@touch $@
+
+if DBUS_HAVE_XSLTPROC
+html_DATA += dbus.devhelp
+
+dbus.devhelp: $(srcdir)/doxygen_to_devhelp.xsl doxygen.stamp
+	$(XSLTPROC) -o $@ $< api/xml/index.xml
+endif
+
+# this assumes CREATE_SUBDIRS isn't set to YES in Doxyfile
+# (which it isn't currently)
+install-data-local:: doxygen.stamp
+	$(MKDIR_P) $(DESTDIR)$(apidir)
+	$(INSTALL_DATA) api/html/* $(DESTDIR)$(apidir)
+
+uninstall-local::
+	rm -f $(DESTDIR)$(apidir)/*.html
+	rm -f $(DESTDIR)$(apidir)/*.png
+	rm -f $(DESTDIR)$(apidir)/*.css
+	rm -f $(DESTDIR)$(apidir)/*.js
+	rm -f $(DESTDIR)$(htmldir)/*.html
+	rm -f $(DESTDIR)$(docdir)/*.txt
+	rm -f $(DESTDIR)$(htmldir)/*.png
+	rm -f $(DESTDIR)$(htmldir)/*.svg
+	rmdir --ignore-fail-on-non-empty $(DESTDIR)$(apidir) || \
+		rmdir $(DESTDIR)$(apidir)
+endif
+
+if DBUS_HAVE_MAN2HTML
+html_DATA += $(MAN_HTML_FILES)
+
+%.1.html: %.1
+	$(AM_V_GEN)( $(MAN2HTML) < $< > $@.tmp && mv $@.tmp $@ )
+endif
+
+if DBUS_CAN_UPLOAD_DOCS
+BONUS_FILES = \
+	$(top_srcdir)/README \
+	$(top_srcdir)/HACKING \
+	$(top_srcdir)/AUTHORS \
+	$(top_srcdir)/NEWS \
+	$(top_srcdir)/COPYING \
+	$(top_srcdir)/ChangeLog
+
+dbus-docs: $(STATIC_DOCS) $(dist_doc_DATA) $(dist_html_DATA) $(MAN_HTML_FILES) $(BONUS_FILES) doxygen.stamp
+	$(AM_V_at)rm -rf $@ $@.tmp
+	$(AM_V_GEN)$(MKDIR_P) $@.tmp/api
+	$(AM_V_at)cd $(srcdir) && cp $(STATIC_DOCS) @abs_builddir@/$@.tmp
+	$(AM_V_at)cd $(srcdir) && cp $(dist_doc_DATA) @abs_builddir@/$@.tmp
+	$(AM_V_at)cd $(srcdir) && cp $(STATIC_HTML) @abs_builddir@/$@.tmp
+	$(AM_V_at)cp $(XMLTO_OUTPUT) @abs_builddir@/$@.tmp
+	$(AM_V_at)cp $(MAN_HTML_FILES) @abs_builddir@/$@.tmp
+	$(AM_V_at)cp $(BONUS_FILES) @abs_builddir@/$@.tmp
+	$(AM_V_at)cp -r api/html @abs_builddir@/$@.tmp/api
+	$(AM_V_at)mv $@.tmp $@
+
+dbus-docs.tar.gz: dbus-docs
+	$(AM_V_GEN)tar czf $@ $<
+
+DOC_SERVER = dbus.freedesktop.org
+DOC_WWW_DIR = /srv/dbus.freedesktop.org/www
+
+SPECIFICATION_SERVER = specifications.freedesktop.org
+SPECIFICATION_PATH = /srv/specifications.freedesktop.org/www/dbus/1.0
+
+maintainer-upload-docs: dbus-docs.tar.gz dbus-docs
+	scp dbus-docs.tar.gz $(DOC_SERVER):$(DOC_WWW_DIR)/
+	rsync -rpvzP --chmod=Dg+s,ug+rwX,o=rX \
+		dbus-docs/ $(DOC_SERVER):$(DOC_WWW_DIR)/doc/
+	cd $(srcdir) && scp -p $(DTDS) $(SPECIFICATION_SERVER):$(SPECIFICATION_PATH)/
+else
+maintainer-upload-docs:
+	@echo "Can't upload documentation! Re-run configure with"
+	@echo "  --enable-doxygen-docs --enable-xml-docs"
+	@echo "and ensure that man2html is installed."
+	@false
+endif
+
+clean-local:
+	rm -f $(html_DATA)
+	rm -rf api
+	rm -rf dbus-docs dbus-docs.tmp
+	rm -f *.1.html
+	rm -f doxygen.stamp
+
+maintainer-clean-local:
+	rm -f $(XMLTO_OUTPUT)
diff --git a/dbus/doc/TODO b/dbus/doc/TODO
new file mode 100644
index 0000000..eb4e797
--- /dev/null
+++ b/dbus/doc/TODO
@@ -0,0 +1,155 @@
+Important for 1.2
+===
+
+ - System bus activation
+
+ - Windows port
+
+Important for 1.0 GLib Bindings
+===
+
+ - Test point-to-point mode
+
+ - Add support for getting sender
+
+ - format_version in the object info doesn't look like it's handled correctly. The creator
+   of the object info should specify some fixed number per struct version; the library
+   should handle only specific numbers it knows about. There's no assumption that all 
+   numbers >= the given one are compatible. The idea is that new versions of the lib
+   can offer totally different object info structs, but old versions
+   keep working.
+
+Important for 1.0 Python bindings
+===
+
+ - Hammer down API
+
+ - Fix removing of signals from the match tree
+
+ - Fix refcounting and userdata lifecycles
+
+ - Write a generic mainloop
+
+Might as Well for 1.0
+===
+
+ - protocol version in each message is pretty silly
+
+Can Be Post 1.0
+===
+
+ - revamp dbus-launch a bit,
+   see http://lists.freedesktop.org/archives/dbus/2006-October/005906.html
+   for some thoughts.
+
+ - clean up the creds issue on *BSD's in dbus/dbus-sysdeps-unix.c.
+   They should work as is but we need to rearange it to make it
+   clearer which method is being used.  configure.in should
+   be fixed up to make that decition.
+
+ - _dbus_connection_unref_unlocked() is essentially always broken because
+   the connection finalizer calls non-unlocked functions. One fix is to make 
+   the finalizer run with the lock held, but since it calls out to the app that may 
+   be pretty broken. More likely all the uses of unref_unlocked are just wrong.
+
+ - if the GUID is obtained only during authentication, not in the address, 
+   we could still share the connection
+
+ - Allow a dbus_g_proxy_to_string()/g_object_to_string() that
+   would convert the proxy to an "IOR" and dbus_g_proxy_from_string()
+   that would decode; using these, dbus-glib users could avoid
+   DBusConnection entirely. Of course the same applies to other kinds
+   of binding. This would use dbus_connection_open()'s connection-sharing
+   feature to avoid massive proliferation of connections.
+
+ - DBusWatchList/TimeoutList duplicate a lot of code, as do
+   protected_change_watch/protected_change_timeout in dbus-connection.c
+   and dbus-server.c. This could all be mopped up, cut-and-paste 
+   fixed, code size reduced.
+
+ - change .service files to allow Names=list in addition to Name=string
+
+ - The message bus internal code still says "service" for 
+   "name", "base service" for "unique name", "activate" for 
+   "start"; would be nice to clean up.
+
+ - Property list feature on message bus (list of properties associated 
+   with a connection). May also include message matching rules 
+   that involve the properties of the source or destination
+   connection.
+
+ - Disconnecting the remote end on invalid UTF-8 is probably not a good 
+   idea. The definition of "valid" is slightly fuzzy. I think it might 
+   be better to just silently "fix" the UTF-8, or perhaps return an error.
+
+ - build and install the Doxygen manual in Makefile when --enable-docs
+
+ - if you send the same message to multiple connections, the serial number 
+   will only be right for one of them. Probably need to just write() the serial 
+   number, rather than putting it in the DBusMessage, or something.
+
+ - perhaps the bus driver should have properties that reflect attributes
+   of the session, such as hostname, architecture, operating system, 
+   etc. Could be useful for code that wants to special-case behavior 
+   for a particular host or class of hosts, for example.
+
+ - currently the security policy stuff for messages to/from 
+   the bus driver is kind of strange; basically it's hardcoded that 
+   you can always talk to the driver, but the default config file 
+   has rules for it anyway, or something. it's conceptually 
+   screwy at the moment.
+
+ - when making a method call, if the call serial were globally unique,
+   we could forward the call serial along with any method calls made
+   as a result of the first method call, and allow reentrancy that was
+   strictly part of the call stack of said method call. But I don't
+   really see how to do this without making the user pass around the
+   call serial to all method calls all the time, or disallowing 
+   async calls.
+
+   If done post 1.0 will probably be an optional/ugly-API type 
+   of thing.
+
+ - I don't want to introduce DBusObject, but refcounting and object
+   data could still be factored out into an internal "base class" 
+   perhaps.
+
+ - Keep convenience wrappers in sync with bus methods
+
+ - document the auth protocol as a set of states and transitions, and
+   then reimplement it in those terms
+
+ - recursive dispatch, see dbus_connection_dispatch()
+
+ - do we need per-display activation; if so I'd like to do this by setting a
+   "display ID" property on screen 0, with a GUID, and keying activation by 
+   said GUID. Otherwise you get all kinds of unrobust
+   string/hostname-based mess. per-screen is then done by appending screen number
+   to the display. If displays have a deterministic ID like this, you can 
+   do per-display by simply including GUID in the service name.
+
+ - optimization and profiling!
+
+ - Match rules aren't in the spec (probably a lot of methods on the bus
+   are not)
+
+ - the "break loader" and valid/invalid message tests are all disabled;
+   they need to be fixed and re-enabled with the new message args stuff.
+   I think I want to drop the .message files thing and just have code
+   that generates messages, more like the tests for
+   dbus-marshal-recursive.c (this is mostly done now, just needs some
+   cleanup)
+
+ - just before 1.0, try a HAVE_INT64=0 build and be sure it runs
+
+ - Windows port needs recursive mutexes
+
+Should Be Post 1.0
+===
+
+ - look into supporting the concept of a "connection" generically
+   (what does this TODO item mean?)
+
+ - test/name-test should be named test/with-bus or something like that
+
+
diff --git a/dbus/doc/busconfig.dtd b/dbus/doc/busconfig.dtd
new file mode 100644
index 0000000..0cc519b
--- /dev/null
+++ b/dbus/doc/busconfig.dtd
@@ -0,0 +1,65 @@
+<!ELEMENT busconfig (user |
+                     type |
+                     fork |
+                     keep_umask |
+                     listen | 
+                     pidfile |
+                     includedir |
+                     servicedir |
+                     servicehelper |
+                     auth |
+                     include |
+                     policy |
+                     limit |
+                     selinux)*>
+
+<!ELEMENT user (#PCDATA)>
+<!ELEMENT listen (#PCDATA)>
+<!ELEMENT includedir (#PCDATA)>
+<!ELEMENT servicedir (#PCDATA)>
+<!ELEMENT servicehelper (#PCDATA)>
+<!ELEMENT auth (#PCDATA)>
+<!ELEMENT type (#PCDATA)>
+<!ELEMENT pidfile (#PCDATA)>
+<!ELEMENT fork EMPTY>
+<!ELEMENT keep_umask EMPTY>
+
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include 
+          ignore_missing (yes|no) "no"
+          if_selinux_enabled (yes|no) "no"
+          selinux_root_relative (yes|no) "no">
+
+<!ELEMENT policy (allow|deny)*>
+<!ATTLIST policy 
+          context (default|mandatory) #IMPLIED
+          user CDATA #IMPLIED
+          group CDATA #IMPLIED
+          at_console (yes|no) #IMPLIED>
+
+<!ELEMENT allow EMPTY>
+<!ATTLIST allow 
+          user CDATA #IMPLIED
+          send CDATA #IMPLIED
+          receive CDATA #IMPLIED
+          own CDATA #IMPLIED
+          send_to CDATA #IMPLIED
+          receive_from CDATA #IMPLIED>
+
+<!ELEMENT deny EMPTY>
+<!ATTLIST deny
+          user CDATA #IMPLIED
+          send CDATA #IMPLIED
+          receive CDATA #IMPLIED
+          own CDATA #IMPLIED
+          send_to CDATA #IMPLIED
+          receive_from CDATA #IMPLIED>
+
+<!ELEMENT limit (#PCDATA)>
+<!ATTLIST limit name CDATA #REQUIRED>
+
+<!ELEMENT selinux (associate)*>
+<!ELEMENT associate EMPTY>
+<!ATTLIST associate
+          own CDATA #REQUIRED
+          context CDATA #REQUIRED>
diff --git a/dbus/doc/dbus-cleanup-sockets.1 b/dbus/doc/dbus-cleanup-sockets.1
new file mode 100644
index 0000000..a062d49
--- /dev/null
+++ b/dbus/doc/dbus-cleanup-sockets.1
@@ -0,0 +1,43 @@
+.\" 
+.\" dbus\-cleanup\-sockets manual page.
+.\" Copyright (C) 2003 Red Hat, Inc.
+.\"
+.TH dbus\-cleanup\-sockets 1
+.SH NAME
+dbus\-cleanup\-sockets \- clean up leftover sockets in a directory
+.SH SYNOPSIS
+.PP
+.B dbus\-cleanup\-sockets [DIRECTORY]
+
+.SH DESCRIPTION
+
+The \fIdbus\-cleanup\-sockets\fP command cleans up unused D\-Bus
+connection sockets. See http://www.freedesktop.org/software/dbus/ for
+more information about the big picture.
+
+.PP
+If given no arguments, \fIdbus\-cleanup\-sockets\fP cleans up sockets 
+in the standard default socket directory for the
+per\-user\-login\-session message bus; this is usually /tmp. 
+Optionally, you can pass a different directory on the command line.
+
+.PP
+On Linux, this program is essentially useless, because D\-Bus defaults
+to using "abstract sockets" that exist only in memory and don't have a
+corresponding file in /tmp. 
+
+.PP
+On most other flavors of UNIX, it's possible for the socket files to
+leak when programs using D\-Bus exit abnormally or without closing
+their D\-Bus connections. Thus, it might be interesting to run
+dbus\-cleanup\-sockets in a cron job to mop up any leaked sockets.
+Or you can just ignore the leaked sockets, they aren't really hurting
+anything, other than cluttering the output of "ls /tmp"
+
+.SH AUTHOR
+dbus\-cleanup\-sockets was adapted by Havoc Pennington from
+linc\-cleanup\-sockets written by Michael Meeks.
+
+.SH BUGS
+Please send bug reports to the D\-Bus mailing list or bug tracker,
+see http://www.freedesktop.org/software/dbus/
diff --git a/dbus/doc/dbus-daemon.1.in b/dbus/doc/dbus-daemon.1.in
new file mode 100644
index 0000000..53856e9
--- /dev/null
+++ b/dbus/doc/dbus-daemon.1.in
@@ -0,0 +1,766 @@
+.\"
+.\" dbus\-daemon manual page.
+.\" Copyright (C) 2003,2008 Red Hat, Inc.
+.\"
+.TH dbus\-daemon 1
+.SH NAME
+dbus\-daemon \- Message bus daemon
+.SH SYNOPSIS
+.PP
+.B dbus\-daemon
+dbus\-daemon [\-\-version] [\-\-session] [\-\-system] [\-\-config\-file=FILE]
+[\-\-print\-address[=DESCRIPTOR]] [\-\-print\-pid[=DESCRIPTOR]] [\-\-fork]
+
+.SH DESCRIPTION
+\fIdbus\-daemon\fP is the D\-Bus message bus daemon. See
+http://www.freedesktop.org/software/dbus/ for more information about
+the big picture. D\-Bus is first a library that provides one\-to\-one
+communication between any two applications; \fIdbus\-daemon\fP is an
+application that uses this library to implement a message bus
+daemon. Multiple programs connect to the message bus daemon and can
+exchange messages with one another.
+.PP
+There are two standard message bus instances: the systemwide message bus
+(installed on many systems as the "messagebus" init service) and the
+per\-user\-login\-session message bus (started each time a user logs in).
+\fIdbus\-daemon\fP is used for both of these instances, but with
+a different configuration file.
+.PP
+The \-\-session option is equivalent to
+"\-\-config\-file=@EXPANDED_SYSCONFDIR@/dbus\-1/session.conf" and the \-\-system
+option is equivalent to
+"\-\-config\-file=@EXPANDED_SYSCONFDIR@/dbus\-1/system.conf". By creating
+additional configuration files and using the \-\-config\-file option,
+additional special\-purpose message bus daemons could be created.
+.PP
+The systemwide daemon is normally launched by an init script,
+standardly called simply "messagebus".
+.PP
+The systemwide daemon is largely used for broadcasting system events,
+such as changes to the printer queue, or adding/removing devices.
+.PP
+The per\-session daemon is used for various interprocess communication
+among desktop applications (however, it is not tied to X or the GUI
+in any way).
+.PP
+SIGHUP will cause the D\-Bus daemon to PARTIALLY reload its
+configuration file and to flush its user/group information caches. Some
+configuration changes would require kicking all apps off the bus; so they will
+only take effect if you restart the daemon. Policy changes should take effect
+with SIGHUP.
+
+.SH OPTIONS
+The following options are supported:
+.TP
+.I "\-\-config\-file=FILE"
+Use the given configuration file.
+.TP
+.I "\-\-fork"
+Force the message bus to fork and become a daemon, even if
+the configuration file does not specify that it should.
+In most contexts the configuration file already gets this
+right, though.
+.I "\-\-nofork"
+Force the message bus not to fork and become a daemon, even if
+the configuration file specifies that it should.
+.TP
+.I "\-\-print\-address[=DESCRIPTOR]"
+Print the address of the message bus to standard output, or
+to the given file descriptor. This is used by programs that
+launch the message bus.
+.TP
+.I "\-\-print\-pid[=DESCRIPTOR]"
+Print the process ID of the message bus to standard output, or
+to the given file descriptor. This is used by programs that
+launch the message bus.
+.TP
+.I "\-\-session"
+Use the standard configuration file for the per\-login\-session message
+bus.
+.TP
+.I "\-\-system"
+Use the standard configuration file for the systemwide message bus.
+.TP
+.I "\-\-version"
+Print the version of the daemon.
+.TP
+.I "\-\-introspect"
+Print the introspection information for all D\-Bus internal interfaces.
+.TP
+.I "\-\-address[=ADDRESS]"
+Set the address to listen on. This option overrides the address
+configured in the configuration file.
+.TP
+.I "\-\-systemd\-activation"
+Enable systemd\-style service activation. Only useful in conjunction
+with the systemd system and session manager on Linux.
+.TP
+.I "\-\-nopidfile"
+Don't write a PID file even if one is configured in the configuration
+files.
+
+.SH CONFIGURATION FILE
+
+A message bus daemon has a configuration file that specializes it
+for a particular application. For example, one configuration
+file might set up the message bus to be a systemwide message bus,
+while another might set it up to be a per\-user\-login\-session bus.
+.PP
+The configuration file also establishes resource limits, security
+parameters, and so forth.
+.PP
+The configuration file is not part of any interoperability
+specification and its backward compatibility is not guaranteed; this
+document is documentation, not specification.
+.PP
+The standard systemwide and per\-session message bus setups are
+configured in the files "@EXPANDED_SYSCONFDIR@/dbus\-1/system.conf" and
+"@EXPANDED_SYSCONFDIR@/dbus\-1/session.conf".  These files normally
+<include> a system\-local.conf or session\-local.conf; you can put local
+overrides in those files to avoid modifying the primary configuration
+files.
+
+.PP
+The configuration file is an XML document. It must have the following
+doctype declaration:
+.nf
+
+   <!DOCTYPE busconfig PUBLIC "\-//freedesktop//DTD D\-Bus Bus Configuration 1.0//EN"
+    "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+.fi
+
+.PP
+The following elements may be present in the configuration file.
+
+.TP
+.I "<busconfig>"
+
+.PP
+Root element.
+
+.TP
+.I "<type>"
+
+.PP
+The well\-known type of the message bus. Currently known values are
+"system" and "session"; if other values are set, they should be
+either added to the D\-Bus specification, or namespaced.  The last
+<type> element "wins" (previous values are ignored). This element
+only controls which message bus specific environment variables are
+set in activated clients.  Most of the policy that distinguishes a
+session bus from the system bus is controlled from the other elements
+in the configuration file.
+
+.PP
+If the well\-known type of the message bus is "session", then the
+DBUS_STARTER_BUS_TYPE environment variable will be set to "session"
+and the DBUS_SESSION_BUS_ADDRESS environment variable will be set
+to the address of the session bus.  Likewise, if the type of the
+message bus is "system", then the DBUS_STARTER_BUS_TYPE environment
+variable will be set to "system" and the DBUS_SESSION_BUS_ADDRESS
+environment variable will be set to the address of the system bus
+(which is normally well known anyway).
+
+.PP
+Example: <type>session</type>
+
+.TP
+.I "<include>"
+
+.PP
+Include a file <include>filename.conf</include> at this point.  If the
+filename is relative, it is located relative to the configuration file
+doing the including.
+
+.PP
+<include> has an optional attribute "ignore_missing=(yes|no)"
+which defaults to "no" if not provided. This attribute
+controls whether it's a fatal error for the included file
+to be absent.
+
+.TP
+.I "<includedir>"
+
+.PP
+Include all files in <includedir>foo.d</includedir> at this
+point. Files in the directory are included in undefined order.
+Only files ending in ".conf" are included.
+
+.PP
+This is intended to allow extension of the system bus by particular
+packages. For example, if CUPS wants to be able to send out
+notification of printer queue changes, it could install a file to
+@EXPANDED_SYSCONFDIR@/dbus\-1/system.d that allowed all apps to receive
+this message and allowed the printer daemon user to send it.
+
+.TP
+.I "<user>"
+
+.PP
+The user account the daemon should run as, as either a username or a
+UID. If the daemon cannot change to this UID on startup, it will exit.
+If this element is not present, the daemon will not change or care
+about its UID.
+
+.PP
+The last <user> entry in the file "wins", the others are ignored.
+
+.PP
+The user is changed after the bus has completed initialization.  So
+sockets etc. will be created before changing user, but no data will be
+read from clients before changing user. This means that sockets
+and PID files can be created in a location that requires root
+privileges for writing.
+
+.TP
+.I "<fork>"
+
+.PP
+If present, the bus daemon becomes a real daemon (forks
+into the background, etc.). This is generally used
+rather than the \-\-fork command line option.
+
+.TP
+.I "<keep_umask>"
+
+.PP
+If present, the bus daemon keeps its original umask when forking.
+This may be useful to avoid affecting the behavior of child processes.
+
+.TP
+.I "<listen>"
+
+.PP
+Add an address that the bus should listen on. The
+address is in the standard D\-Bus format that contains
+a transport name plus possible parameters/options.
+
+.PP
+Example: <listen>unix:path=/tmp/foo</listen>
+
+.PP
+Example: <listen>tcp:host=localhost,port=1234</listen>
+
+.PP
+If there are multiple <listen> elements, then the bus listens
+on multiple addresses. The bus will pass its address to
+started services or other interested parties with
+the last address given in <listen> first. That is,
+apps will try to connect to the last <listen> address first.
+
+.PP
+tcp sockets can accept IPv4 addresses, IPv6 addresses or hostnames.
+If a hostname resolves to multiple addresses, the server will bind
+to all of them. The family=ipv4 or family=ipv6 options can be used
+to force it to bind to a subset of addresses
+
+.PP
+Example: <listen>tcp:host=localhost,port=0,family=ipv4</listen>
+
+.PP
+A special case is using a port number of zero (or omitting the port),
+which means to choose an available port selected by the operating
+system. The port number chosen can be obtained with the
+\-\-print\-address command line parameter and will be present in other
+cases where the server reports its own address, such as when
+DBUS_SESSION_BUS_ADDRESS is set.
+
+.PP
+Example: <listen>tcp:host=localhost,port=0</listen>
+
+.PP
+tcp addresses also allow a bind=hostname option, which will override
+the host option specifying what address to bind to, without changing
+the address reported by the bus. The bind option can also take a
+special name '*' to cause the bus to listen on all local address
+(INADDR_ANY). The specified host should be a valid name of the local
+machine or weird stuff will happen.
+
+.PP
+Example: <listen>tcp:host=localhost,bind=*,port=0</listen>
+
+.TP
+.I "<auth>"
+
+.PP
+Lists permitted authorization mechanisms. If this element doesn't
+exist, then all known mechanisms are allowed.  If there are multiple
+<auth> elements, all the listed mechanisms are allowed.  The order in
+which mechanisms are listed is not meaningful.
+
+.PP
+Example: <auth>EXTERNAL</auth>
+
+.PP
+Example: <auth>DBUS_COOKIE_SHA1</auth>
+
+.TP
+.I "<servicedir>"
+
+.PP
+Adds a directory to scan for .service files. Directories are
+scanned starting with the last to appear in the config file
+(the first .service file found that provides a particular
+service will be used).
+
+.PP
+Service files tell the bus how to automatically start a program.
+They are primarily used with the per\-user\-session bus,
+not the systemwide bus.
+
+.TP
+.I "<standard_session_servicedirs/>"
+
+.PP
+<standard_session_servicedirs/> is equivalent to specifying a series
+of <servicedir/> elements for each of the data directories in the "XDG
+Base Directory Specification" with the subdirectory "dbus\-1/services",
+so for example "/usr/share/dbus\-1/services" would be among the
+directories searched.
+
+.PP
+The "XDG Base Directory Specification" can be found at
+http://freedesktop.org/wiki/Standards/basedir\-spec if it hasn't moved,
+otherwise try your favorite search engine.
+
+.PP
+The <standard_session_servicedirs/> option is only relevant to the
+per\-user\-session bus daemon defined in
+@EXPANDED_SYSCONFDIR@/dbus\-1/session.conf. Putting it in any other
+configuration file would probably be nonsense.
+
+.TP
+.I "<standard_system_servicedirs/>"
+
+.PP
+<standard_system_servicedirs/> specifies the standard system\-wide
+activation directories that should be searched for service files.
+This option defaults to @EXPANDED_DATADIR@/dbus\-1/system\-services.
+
+.PP
+The <standard_system_servicedirs/> option is only relevant to the
+per\-system bus daemon defined in
+@EXPANDED_SYSCONFDIR@/dbus\-1/system.conf. Putting it in any other
+configuration file would probably be nonsense.
+
+.TP
+.I "<servicehelper/>"
+
+.PP
+<servicehelper/> specifies the setuid helper that is used to launch
+system daemons with an alternate user. Typically this should be
+the dbus\-daemon\-launch\-helper executable in located in libexec.
+
+.PP
+The <servicehelper/> option is only relevant to the per\-system bus daemon
+defined in @EXPANDED_SYSCONFDIR@/dbus\-1/system.conf. Putting it in any other
+configuration file would probably be nonsense.
+
+.TP
+.I "<limit>"
+
+.PP
+<limit> establishes a resource limit. For example:
+.nf
+  <limit name="max_message_size">64</limit>
+  <limit name="max_completed_connections">512</limit>
+.fi
+
+.PP
+The name attribute is mandatory.
+Available limit names are:
+.nf
+      "max_incoming_bytes"         : total size in bytes of messages
+                                     incoming from a single connection
+      "max_incoming_unix_fds"      : total number of unix fds of messages
+                                     incoming from a single connection
+      "max_outgoing_bytes"         : total size in bytes of messages
+                                     queued up for a single connection
+      "max_outgoing_unix_fds"      : total number of unix fds of messages
+                                     queued up for a single connection
+      "max_message_size"           : max size of a single message in
+                                     bytes
+      "max_message_unix_fds"       : max unix fds of a single message
+      "service_start_timeout"      : milliseconds (thousandths) until
+                                     a started service has to connect
+      "auth_timeout"               : milliseconds (thousandths) a
+                                     connection is given to
+                                     authenticate
+      "max_completed_connections"  : max number of authenticated connections
+      "max_incomplete_connections" : max number of unauthenticated
+                                     connections
+      "max_connections_per_user"   : max number of completed connections from
+                                     the same user
+      "max_pending_service_starts" : max number of service launches in
+                                     progress at the same time
+      "max_names_per_connection"   : max number of names a single
+                                     connection can own
+      "max_match_rules_per_connection": max number of match rules for a single
+                                        connection
+      "max_replies_per_connection" : max number of pending method
+                                     replies per connection
+                                     (number of calls\-in\-progress)
+      "reply_timeout"              : milliseconds (thousandths)
+                                     until a method call times out
+.fi
+
+.PP
+The max incoming/outgoing queue sizes allow a new message to be queued
+if one byte remains below the max. So you can in fact exceed the max
+by max_message_size.
+
+.PP
+max_completed_connections divided by max_connections_per_user is the
+number of users that can work together to denial\-of\-service all other users by using
+up all connections on the systemwide bus.
+
+.PP
+Limits are normally only of interest on the systemwide bus, not the user session
+buses.
+
+.TP
+.I "<policy>"
+
+.PP
+The <policy> element defines a security policy to be applied to a particular
+set of connections to the bus. A policy is made up of
+<allow> and <deny> elements. Policies are normally used with the systemwide bus;
+they are analogous to a firewall in that they allow expected traffic
+and prevent unexpected traffic.
+
+.PP
+Currently, the system bus has a default\-deny policy for sending method calls
+and owning bus names.  Everything else, in particular reply messages, receive
+checks, and signals has a default allow policy.
+
+.PP
+In general, it is best to keep system services as small, targeted programs which
+run in their own process and provide a single bus name.  Then, all that is needed
+is an <allow> rule for the "own" permission to let the process claim the bus
+name, and a "send_destination" rule to allow traffic from some or all uids to
+your service.
+
+.PP
+The <policy> element has one of four attributes:
+.nf
+  context="(default|mandatory)"
+  at_console="(true|false)"
+  user="username or userid"
+  group="group name or gid"
+.fi
+
+.PP
+Policies are applied to a connection as follows:
+.nf
+   \- all context="default" policies are applied
+   \- all group="connection's user's group" policies are applied
+     in undefined order
+   \- all user="connection's auth user" policies are applied
+     in undefined order
+   \- all at_console="true" policies are applied
+   \- all at_console="false" policies are applied
+   \- all context="mandatory" policies are applied
+.fi
+
+.PP
+Policies applied later will override those applied earlier,
+when the policies overlap. Multiple policies with the same
+user/group/context are applied in the order they appear
+in the config file.
+
+.TP
+.I "<deny>"
+.I "<allow>"
+
+.PP
+A <deny> element appears below a <policy> element and prohibits some
+action. The <allow> element makes an exception to previous <deny>
+statements, and works just like <deny> but with the inverse meaning.
+
+.PP
+The possible attributes of these elements are:
+.nf
+   send_interface="interface_name"
+   send_member="method_or_signal_name"
+   send_error="error_name"
+   send_destination="name"
+   send_type="method_call" | "method_return" | "signal" | "error"
+   send_path="/path/name"
+
+   receive_interface="interface_name"
+   receive_member="method_or_signal_name"
+   receive_error="error_name"
+   receive_sender="name"
+   receive_type="method_call" | "method_return" | "signal" | "error"
+   receive_path="/path/name"
+
+   send_requested_reply="true" | "false"
+   receive_requested_reply="true" | "false"
+
+   eavesdrop="true" | "false"
+
+   own="name"
+   own_prefix="name"
+   user="username"
+   group="groupname"
+.fi
+
+.PP
+Examples:
+.nf
+   <deny send_destination="org.freedesktop.Service" send_interface="org.freedesktop.System" send_member="Reboot"/>
+   <deny send_destination="org.freedesktop.System"/>
+   <deny receive_sender="org.freedesktop.System"/>
+   <deny user="john"/>
+   <deny group="enemies"/>
+.fi
+
+.PP
+The <deny> element's attributes determine whether the deny "matches" a
+particular action. If it matches, the action is denied (unless later
+rules in the config file allow it).
+.PP
+send_destination and receive_sender rules mean that messages may not be
+sent to or received from the *owner* of the given name, not that
+they may not be sent *to that name*. That is, if a connection
+owns services A, B, C, and sending to A is denied, sending to B or C
+will not work either.
+.PP
+The other send_* and receive_* attributes are purely textual/by\-value
+matches against the given field in the message header.
+.PP
+"Eavesdropping" occurs when an application receives a message that
+was explicitly addressed to a name the application does not own, or
+is a reply to such a message. Eavesdropping thus only applies to
+messages that are addressed to services and replies to such messages
+(i.e. it does not apply to signals).
+.PP
+For <allow>, eavesdrop="true" indicates that the rule matches even
+when eavesdropping. eavesdrop="false" is the default and means that
+the rule only allows messages to go to their specified recipient.
+For <deny>, eavesdrop="true" indicates that the rule matches
+only when eavesdropping. eavesdrop="false" is the default for <deny>
+also, but here it means that the rule applies always, even when
+not eavesdropping. The eavesdrop attribute can only be combined with
+send and receive rules (with send_* and receive_* attributes).
+.PP
+The [send|receive]_requested_reply attribute works similarly to the eavesdrop
+attribute. It controls whether the <deny> or <allow> matches a reply
+that is expected (corresponds to a previous method call message).
+This attribute only makes sense for reply messages (errors and method
+returns), and is ignored for other message types.
+
+.PP
+For <allow>, [send|receive]_requested_reply="true" is the default and indicates that
+only requested replies are allowed by the
+rule. [send|receive]_requested_reply="false" means that the rule allows any reply
+even if unexpected.
+
+.PP
+For <deny>, [send|receive]_requested_reply="false" is the default but indicates that
+the rule matches only when the reply was not
+requested. [send|receive]_requested_reply="true" indicates that the rule applies
+always, regardless of pending reply state.
+
+.PP
+user and group denials mean that the given user or group may
+not connect to the message bus.
+
+.PP
+For "name", "username", "groupname", etc.
+the character "*" can be substituted, meaning "any." Complex globs
+like "foo.bar.*" aren't allowed for now because they'd be work to
+implement and maybe encourage sloppy security anyway.
+
+.PP
+<allow own_prefix="a.b"/> allows you to own the name "a.b" or any
+name whose first dot-separated elements are "a.b": in particular,
+you can own "a.b.c" or "a.b.c.d", but not "a.bc" or "a.c".
+This is useful when services like Telepathy and ReserveDevice
+define a meaning for subtrees of well-known names, such as
+org.freedesktop.Telepathy.ConnectionManager.(anything)
+and org.freedesktop.ReserveDevice1.(anything).
+
+.PP
+It does not make sense to deny a user or group inside a <policy>
+for a user or group; user/group denials can only be inside
+context="default" or context="mandatory" policies.
+
+.PP
+A single <deny> rule may specify combinations of attributes such as
+send_destination and send_interface and send_type. In this case, the
+denial applies only if both attributes match the message being denied.
+e.g. <deny send_interface="foo.bar" send_destination="foo.blah"/> would
+deny messages with the given interface AND the given bus name.
+To get an OR effect you specify multiple <deny> rules.
+
+.PP
+You can't include both send_ and receive_ attributes on the same
+rule, since "whether the message can be sent" and "whether it can be
+received" are evaluated separately.
+
+.PP
+Be careful with send_interface/receive_interface, because the
+interface field in messages is optional.  In particular, do NOT
+specify <deny send_interface="org.foo.Bar"/>!  This will cause
+no\-interface messages to be blocked for all services, which is
+almost certainly not what you intended.  Always use rules of
+the form: <deny send_interface="org.foo.Bar" send_destination="org.foo.Service"/>
+
+.TP
+.I "<selinux>"
+
+.PP
+The <selinux> element contains settings related to Security Enhanced Linux.
+More details below.
+
+.TP
+.I "<associate>"
+
+.PP
+An <associate> element appears below an <selinux> element and
+creates a mapping. Right now only one kind of association is possible:
+.nf
+   <associate own="org.freedesktop.Foobar" context="foo_t"/>
+.fi
+
+.PP
+This means that if a connection asks to own the name
+"org.freedesktop.Foobar" then the source context will be the context
+of the connection and the target context will be "foo_t" \- see the
+short discussion of SELinux below.
+
+.PP
+Note, the context here is the target context when requesting a name,
+NOT the context of the connection owning the name.
+
+.PP
+There's currently no way to set a default for owning any name, if
+we add this syntax it will look like:
+.nf
+   <associate own="*" context="foo_t"/>
+.fi
+If you find a reason this is useful, let the developers know.
+Right now the default will be the security context of the bus itself.
+
+.PP
+If two <associate> elements specify the same name, the element
+appearing later in the configuration file will be used.
+
+.SH SELinux
+
+.PP
+See http://www.nsa.gov/selinux/ for full details on SELinux. Some useful excerpts:
+
+.IP "" 8
+Every subject (process) and object (e.g. file, socket, IPC object,
+etc) in the system is assigned a collection of security attributes,
+known as a security context. A security context contains all of the
+security attributes associated with a particular subject or object
+that are relevant to the security policy.
+
+.IP "" 8
+In order to better encapsulate security contexts and to provide
+greater efficiency, the policy enforcement code of SELinux typically
+handles security identifiers (SIDs) rather than security contexts. A
+SID is an integer that is mapped by the security server to a security
+context at runtime.
+
+.IP "" 8
+When a security decision is required, the policy enforcement code
+passes a pair of SIDs (typically the SID of a subject and the SID of
+an object, but sometimes a pair of subject SIDs or a pair of object
+SIDs), and an object security class to the security server. The object
+security class indicates the kind of object, e.g. a process, a regular
+file, a directory, a TCP socket, etc.
+
+.IP "" 8
+Access decisions specify whether or not a permission is granted for a
+given pair of SIDs and class. Each object class has a set of
+associated permissions defined to control operations on objects with
+that class.
+
+.PP
+D\-Bus performs SELinux security checks in two places.
+
+.PP
+First, any time a message is routed from one connection to another
+connection, the bus daemon will check permissions with the security context of
+the first connection as source, security context of the second connection
+as target, object class "dbus" and requested permission "send_msg".
+
+.PP
+If a security context is not available for a connection
+(impossible when using UNIX domain sockets), then the target
+context used is the context of the bus daemon itself.
+There is currently no way to change this default, because we're
+assuming that only UNIX domain sockets will be used to
+connect to the systemwide bus. If this changes, we'll
+probably add a way to set the default connection context.
+
+.PP
+Second, any time a connection asks to own a name,
+the bus daemon will check permissions with the security
+context of the connection as source, the security context specified
+for the name in the config file as target, object
+class "dbus" and requested permission "acquire_svc".
+
+.PP
+The security context for a bus name is specified with the
+<associate> element described earlier in this document.
+If a name has no security context associated in the
+configuration file, the security context of the bus daemon
+itself will be used.
+
+.SH DEBUGGING
+
+.PP
+If you're trying to figure out where your messages are going or why
+you aren't getting messages, there are several things you can try.
+.PP
+Remember that the system bus is heavily locked down and if you
+haven't installed a security policy file to allow your message
+through, it won't work. For the session bus, this is not a concern.
+.PP
+The simplest way to figure out what's happening on the bus is to run
+the \fIdbus\-monitor\fP program, which comes with the D\-Bus
+package. You can also send test messages with \fIdbus\-send\fP. These
+programs have their own man pages.
+.PP
+If you want to know what the daemon itself is doing, you might consider
+running a separate copy of the daemon to test against. This will allow you
+to put the daemon under a debugger, or run it with verbose output, without
+messing up your real session and system daemons.
+.PP
+To run a separate test copy of the daemon, for example you might open a terminal
+and type:
+.nf
+  DBUS_VERBOSE=1 dbus\-daemon \-\-session \-\-print\-address
+.fi
+.PP
+The test daemon address will be printed when the daemon starts. You will need
+to copy\-and\-paste this address and use it as the value of the
+DBUS_SESSION_BUS_ADDRESS environment variable when you launch the applications
+you want to test. This will cause those applications to connect to your
+test bus instead of the DBUS_SESSION_BUS_ADDRESS of your real session bus.
+.PP
+DBUS_VERBOSE=1 will have NO EFFECT unless your copy of D\-Bus
+was compiled with verbose mode enabled. This is not recommended in
+production builds due to performance impact. You may need to rebuild
+D\-Bus if your copy was not built with debugging in mind. (DBUS_VERBOSE
+also affects the D\-Bus library and thus applications using D\-Bus; it may
+be useful to see verbose output on both the client side and from the daemon.)
+.PP
+If you want to get fancy, you can create a custom bus
+configuration for your test bus (see the session.conf and system.conf
+files that define the two default configurations for example). This
+would allow you to specify a different directory for .service files,
+for example.
+
+.SH AUTHOR
+See http://www.freedesktop.org/software/dbus/doc/AUTHORS
+
+.SH BUGS
+Please send bug reports to the D\-Bus mailing list or bug tracker,
+see http://www.freedesktop.org/software/dbus/
diff --git a/dbus/doc/dbus-faq.xml b/dbus/doc/dbus-faq.xml
new file mode 100644
index 0000000..69ac3f1
--- /dev/null
+++ b/dbus/doc/dbus-faq.xml
@@ -0,0 +1,674 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+]>
+
+<article id="index">
+  <articleinfo>
+    <title>D-Bus FAQ</title>
+    <releaseinfo>Version 0.3</releaseinfo>
+    <date>17 November 2006</date>
+    <authorgroup>
+      <author>
+	<firstname>Havoc</firstname>
+	<surname>Pennington</surname>
+	<affiliation>
+	  <orgname>Red Hat, Inc.</orgname>
+	  <address>
+	    <email>hp@pobox.com</email>
+	  </address>
+	</affiliation>
+      </author>
+      <author>
+	<firstname>David</firstname>
+        <othername role="mi">A</othername>
+	<surname>Wheeler</surname>
+      </author>
+    </authorgroup>
+  </articleinfo>
+
+  <qandaset id="faq">
+
+    <qandaentry>
+      <question>
+        <para>
+          What is D-Bus?
+        </para>
+      </question>
+      <answer>
+        <para>
+          This is probably best answered by reading the D-Bus <ulink url="dbus-tutorial.html">tutorial</ulink> or
+          the introduction to the <ulink url="dbus-specification.html">specification</ulink>. In
+          short, it is a system consisting of 1) a wire protocol for exposing a
+          typical object-oriented language/framework to other applications; and
+          2) a bus daemon that allows applications to find and monitor one another.
+          Phrased differently, D-Bus is 1) an interprocess communication (IPC) system and 2) some higher-level 
+          structure (lifecycle tracking, service activation, security policy) provided by two bus daemons,
+          one systemwide and one per-user-session.
+        </para>
+      </answer>
+    </qandaentry>
+
+    <qandaentry>
+      <question>
+        <para>
+          Is D-Bus stable/finished?
+        </para>
+      </question>
+      <answer>
+        <para>
+          The low-level library "libdbus" and the protocol specification are considered 
+          ABI stable. The <ulink url="README">README</ulink>
+          file has a discussion of the API/ABI stability guarantees.
+          Higher-level bindings (such as those for Qt, GLib, Python, Java, C#) each 
+          have their own release schedules and degree of maturity, not linked to 
+          the low-level library and bus daemon release. Check the project page for
+          the binding you're considering to understand that project's policies.
+        </para>
+      </answer>
+    </qandaentry>
+
+    <qandaentry>
+      <question>
+        <para>
+          How is the reference implementation licensed? Can I use it in 
+          proprietary applications?
+        </para>
+      </question>
+      <answer>
+        <para>
+          The short answer is yes, you can use it in proprietary applications.
+          You should read the <ulink url="COPYING">COPYING</ulink> file, which
+          offers you the choice of two licenses. These are the GPL and the
+          AFL. The GPL requires that your application be licensed under the GPL
+          as well. The AFL is an "X-style" or "BSD-style" license compatible
+          with proprietary licensing, but it does have some requirements; in
+          particular it prohibits you from filing a lawsuit alleging that the
+          D-Bus software infringes your patents <emphasis>while you continue to
+          use D-Bus</emphasis>.  If you're going to sue, you have to stop using
+          the software. Read the licenses to determine their meaning, this FAQ
+          entry is not intended to change the meaning or terms of the licenses.
+        </para>
+      </answer>
+    </qandaentry>
+
+    <qandaentry>
+      <question>
+        <para>
+          What is the difference between a bus name, and object path, 
+          and an interface?
+        </para>
+      </question>
+      <answer>
+        <para>
+          If you imagine a C++ program that implements a network service, then
+          the bus name is the hostname of the computer running this C++ program,
+          the object path is a C++ object instance pointer, and an interface is
+          a C++ class (a pure virtual or abstract class, to be exact).
+        </para>
+        <para>
+          In Java terms, the object path is an object reference, 
+          and an interface is a Java interface.
+        </para>
+        <para>
+          People get confused because if they write an application 
+          with a single object instance and a single interface, 
+          then the bus name, object path, and interface look 
+          redundant. For example, you might have a text editor 
+          that uses the bus name <literal>org.freedesktop.TextEditor</literal>,
+          has a global singleton object called 
+          <literal>/org/freedesktop/TextEditor</literal>, and 
+          that singleton object could implement the interface 
+          <literal>org.freedesktop.TextEditor</literal>.
+        </para>
+        <para>
+          However, a text editor application could as easily own multiple bus
+          names (for example, <literal>org.kde.KWrite</literal> in addition to
+          generic <literal>TextEditor</literal>), have multiple objects (maybe
+          <literal>/org/kde/documents/4352</literal> where the number changes
+          according to the document), and each object could implement multiple
+          interfaces, such as <literal>org.freedesktop.DBus.Introspectable</literal>,
+          <literal>org.freedesktop.BasicTextField</literal>,
+          <literal>org.kde.RichTextDocument</literal>.
+        </para>
+      </answer>
+    </qandaentry>
+
+
+    <qandaentry id="service">
+      <question>
+        <para>
+          What is a "service"?
+        </para>
+      </question>
+      <answer>
+        <para>
+          A service is a program that can be launched by the bus daemon 
+          to provide some functionality to other programs. Services
+          are normally launched according to the bus name they will 
+          have.
+        </para>
+        <para>
+          People often misuse the word "service" for any 
+          bus name, but this tends to be ambiguous and confusing so is discouraged.
+          In the D-Bus docs we try to use "service" only when talking about 
+          programs the bus knows how to launch, i.e. a service always has a 
+          .service file.
+        </para>
+      </answer>
+    </qandaentry>
+
+    <qandaentry id="components">
+      <question>
+        <para>
+          Is D-Bus a "component system"?
+        </para>
+      </question>
+      <answer>
+        <para>
+          It helps to keep these concepts separate in your mind:
+          <orderedlist>
+            <listitem>
+              <para>
+                Object/component system
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                GUI control/widget embedding interfaces
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                Interprocess communication system or wire protocol
+              </para>
+            </listitem>
+          </orderedlist>
+        </para>
+        <para>
+          D-Bus is not a component system. "Component system" was originally
+          defined by COM, and was essentially a workaround for the limitations
+          of the C++ object system (adding introspection, runtime location of
+          objects, ABI guarantees, and so forth). With the C# language and CLR,
+          Microsoft added these features to the primary object system, leaving
+          COM obsolete. Similarly, Java has much less need for something like
+          COM than C++ did. Even QObject (from Qt) and GObject (from GLib) offer
+          some of the same features found in COM.
+        </para>
+        <para>
+          Component systems are not about GUI control embedding. Embedding
+          a spreadsheet in a word processor document is a matter of defining
+          some specific <emphasis>interfaces</emphasis> that objects
+          can implement. These interfaces provide methods related to 
+          GUI controls. So an object implementing those interfaces 
+          can be embedded.
+        </para>
+        <para>
+          The word "component" just means "object with some fancy features" and
+          in modern languages all objects are effectively "components."
+        </para>
+        <para>
+          So components are fancy objects, and some objects are GUI controls.
+        </para>
+        <para>
+          A third, unrelated feature is interprocess communication or IPC.
+          D-Bus is an IPC system. Given an object (or "component" if you must), 
+          you can expose the functionality of that object over an IPC system.
+          Examples of IPC systems are DCOM, CORBA, SOAP, XML-RPC, and D-Bus.
+          You can use any of these IPC systems with any object/component system,
+          though some of them are "tuned" for specific object systems.
+          You can think of an IPC system primarily as a wire protocol.
+        </para>
+        <para>
+          If you combine an IPC system with a set of GUI control interfaces, 
+          then you can have an out-of-process or dynamically-loaded GUI control.
+        </para>
+        <para>
+          Another related concept is the <firstterm>plugin</firstterm> or
+          <firstterm>extension</firstterm>.  Generic plugin systems such as the
+          <ulink url="http://eclipse.org">Eclipse</ulink> system are not so different
+          from component/object systems, though perhaps a "plugin" tends to be a
+          bundle of objects with a user-visible name and can be
+          downloaded/packaged as a unit.
+        </para>
+      </answer>
+    </qandaentry>
+
+    <qandaentry id="speed">
+      <question>
+        <para>
+          How fast is the D-Bus reference implementation?
+        </para>
+      </question>
+      <answer>
+        <para>
+          Of course it depends a bit on what you're doing. 
+          <ulink url="http://lists.freedesktop.org/pipermail/dbus/2004-November/001779.html">
+            This mail</ulink> contains some benchmarking.  At the time of that
+          benchmark, D-Bus one-to-one communication was about 2.5x slower than
+          simply pushing the data raw over a socket. After the recent rewrite of
+          the marshaling code, D-Bus is slower than that because a lot of
+          optimization work was lost. But it can probably be sped up again.
+        </para>
+        <para>
+          D-Bus communication with the intermediate bus daemon should be 
+          (and as last profiled, was) about twice as slow as one-to-one 
+          mode, because a round trip involves four socket reads/writes rather 
+          than two socket reads/writes.
+        </para>
+        <para>
+          The overhead comes from a couple of places; part of it is simply 
+          "abstraction penalty" (there are layers of code to support 
+          multiple main loops, multiple transport types, security, etc.).
+          Probably the largest part comes from data validation
+          (because the reference implementation does not trust incoming data).
+          It would be simple to add a "no validation" mode, but probably 
+          not a good idea all things considered.
+        </para>
+        <para>
+          Raw bandwidth isn't the only concern; D-Bus is designed to 
+          enable asynchronous communication and avoid round trips.
+          This is frequently a more important performance issue 
+          than throughput.
+        </para>
+      </answer>
+    </qandaentry>
+
+
+    <qandaentry id="size">
+      <question>
+        <para>
+          How large is the D-Bus reference implementation?
+        </para>
+      </question>
+      <answer>
+        <para>
+          A production build (with assertions, unit tests, and verbose logging
+          disabled) is on the order of a 150K shared library.
+        </para>
+        <para>
+          A much, much smaller implementation would be possible by omitting out
+          of memory handling, hardcoding a main loop (or always using blocking
+          I/O), skipping validation, and otherwise simplifying things.
+        </para>
+      </answer>
+    </qandaentry>
+    
+    <qandaentry id="other-ipc">
+      <question>
+        <para>
+          How does D-Bus differ from other interprocess communication
+          or networking protocols?
+        </para>
+      </question>
+      <answer>
+        <para>
+          Keep in mind, it is not only an IPC system; it also includes
+          lifecycle tracking, service activation, security policy, and other
+          higher-level structure and assumptions.
+        </para>
+        <para>
+          The best place to start is to read the D-Bus <ulink url="dbus-tutorial.html">tutorial</ulink>, so 
+          you have a concrete idea what D-Bus actually is. If you 
+          understand other protocols on a wire format level, you 
+          may also want to read the D-Bus <ulink url="dbus-specification.html">specification</ulink> to see what 
+          D-Bus looks like on a low level.
+        </para>
+        <para>
+          As the <ulink url="dbus-tutorial.html">tutorial</ulink> and <ulink url="dbus-specification.html">specification</ulink> both explain, D-Bus is tuned 
+          for some specific use cases. Thus, it probably isn't tuned 
+          for what you want to do, unless you are doing the things 
+          D-Bus was designed for. Don't make the mistake of thinking 
+          that any system involving "IPC" is the same thing.
+        </para>
+        <para>
+          The D-Bus authors would not recommend using D-Bus 
+          for applications where it doesn't make sense.
+          The following questions compare D-Bus to some other 
+          protocols primarily to help you understand D-Bus 
+          and decide whether it's appropriate; D-Bus is neither intended
+          nor claimed to be the right choice for every application.
+        </para>
+        <para>
+          It should be possible to bridge D-Bus to other IPC systems, 
+          just as D-Bus can be bridged to object systems.
+        </para>
+        <para>
+          Note: the D-Bus mailing list subscribers are <emphasis>very much not
+          interested</emphasis> in debating which IPC system is the One True
+          System. So if you want to discuss that, please use another forum.
+        </para>
+      </answer>      
+    </qandaentry>
+
+    
+    <qandaentry id="corba">
+      <question>
+        <para>
+          How does D-Bus differ from CORBA?
+        </para>
+      </question>
+      <answer>
+        <para>
+          Start by reading <xref linkend="other-ipc"/>.
+        </para>
+        <para>
+          <ulink url="http://www.omg.org">CORBA</ulink> is designed to support
+         object-oriented IPC between objects, automatically marshalling
+         parameters as necessary. CORBA is strongly supported by the <ulink
+         url="http://www.omg.org">Open Management Group (OMG)</ulink>, which
+         produces various standards and supporting documents for CORBA and has
+         the backing of many large organizations.  There are many CORBA ORBs
+         available, both proprietary ORBs and free / open source software ORBs
+         (the latter include <ulink
+         url="http://orbit-resource.sourceforge.net/">ORBit</ulink>, <ulink
+         url="http://www.mico.org/">MICO</ulink>, and <ulink
+         url="http://www.theaceorb.com/">The ACE Orb (TAO)</ulink>).  Many
+         organizations continue to use CORBA ORBs for various kinds of IPC.
+        </para>
+        <para>
+          Both GNOME and KDE have used CORBA and then moved away from it.  KDE
+          had more success with a system called DCOP, and GNOME layered a system
+          called Bonobo on top of CORBA. Without custom extensions, CORBA does
+          not support many of the things one wants to do in a desktop
+          environment with the GNOME/KDE architecture.
+        </para>
+        <para>
+          CORBA on the other hand has a number of features of interest for
+          enterprise and web application development, though XML systems such as
+          SOAP are the latest fad.
+        </para>
+        <para>
+          Like D-Bus, CORBA uses a fast binary protocol (IIOP). Both systems
+          work in terms of objects and methods, and have concepts such as
+          "oneway" calls. Only D-Bus has direct support for "signals" as in
+          GLib/Qt (or Java listeners, or C# delegates).
+        </para>
+        <para>
+          D-Bus hardcodes and specifies a lot of things that CORBA leaves open-ended,
+          because CORBA is more generic and D-Bus has two specific use-cases in mind.
+          This makes D-Bus a bit simpler.
+        </para>
+        <para>
+          However, unlike CORBA D-Bus does <emphasis>not</emphasis> specify the
+          API for the language bindings. Instead, "native" bindings adapted
+          specifically to the conventions of a framework such as QObject,
+          GObject, C#, Java, Python, etc. are encouraged. The libdbus reference
+          implementation is designed to be a backend for bindings of this
+          nature, rather than to be used directly. The rationale is that an IPC
+          system API should not "leak" all over a program; it should come into
+          play only just before data goes over the wire. As an aside, OMG is
+          apparently working on a simpler C++ binding for CORBA.
+        </para>
+        <para>
+          Many CORBA implementations such as ORBit are faster than the libdbus
+          reference implementation.  One reason is that D-Bus considers data
+          from the other end of the connection to be untrusted and extensively
+          validates it. But generally speaking other priorities were placed
+          ahead of raw speed in the libdbus implementation. A fast D-Bus
+          implementation along the lines of ORBit should be possible, of course.
+        </para>
+        <para>
+          On a more trivial note, D-Bus involves substantially fewer acronyms
+          than CORBA.
+        </para>
+      </answer>
+    </qandaentry>
+
+
+    <qandaentry id="xmlrpcsoap">
+      <question>
+        <para>
+          How does D-Bus differ from XML-RPC and SOAP?
+        </para>
+      </question>
+      <answer>
+        <para>
+          Start by reading <xref linkend="other-ipc"/>.
+        </para>
+        <para>
+          In <ulink url="http://www.w3.org/TR/SOAP/">SOAP</ulink> and <ulink
+            url="http://www.xmlrpc.com">XML-RPC</ulink>, RPC calls are transformed
+          into an XML-based format, then sent over the wire (typically using the
+          HTTP protocol), where they are processed and returned.  XML-RPC is the
+          simple protocol (its spec is only a page or two), and SOAP is the
+          full-featured protocol.
+        </para>
+        <para>
+          XML-RPC and SOAP impose XML parsing overhead that is normally
+          irrelevant in the context of the Internet, but significant for
+          constant fine-grained IPC among applications in a desktop session.
+        </para>
+        <para>
+          D-Bus offers persistent connections and with the bus daemon 
+          supports lifecycle tracking of other applications connected
+          to the bus. With XML-RPC and SOAP, typically each method call 
+          exists in isolation and has its own HTTP connection.
+        </para>
+      </answer>
+    </qandaentry>
+
+    <qandaentry id="dce">
+      <question>
+        <para>
+          How does D-Bus differ from DCE?
+        </para>
+      </question>
+      <answer>
+        <para>
+          Start by reading <xref linkend="other-ipc"/>.
+        </para>
+        <para>
+          <ulink url="http://www.opengroup.org/dce/">Distributed Computing
+          Environment (DCE)</ulink> is an industry-standard vendor-neutral
+          standard that includes an IPC mechanism.  <ulink
+          url="http://www.opengroup.org/comm/press/05-01-12.htm">The Open Group
+          has released an implementation as open source software</ulink>.  DCE
+          is quite capable, and includes a vast amount of functionality such as
+          a distributed time service.  As the name implies, DCE is intended for
+          use in a large, multi-computer distributed application. D-Bus would
+          not be well-suited for this.
+        </para>
+      </answer>
+    </qandaentry>    
+
+
+    <qandaentry id="dcom">
+      <question>
+        <para>
+          How does D-Bus differ from DCOM and COM?
+        </para>
+      </question>
+      <answer>
+        <para>
+          Start by reading <xref linkend="other-ipc"/>.
+        </para>
+        <para>
+          Comparing D-Bus to COM is apples and oranges; 
+          see <xref linkend="components"/>.
+        </para>
+        <para>
+          DCOM (distributed COM) is a Windows IPC system designed for use with
+          the COM object system. It's similar in some ways to DCE and CORBA.
+        </para>
+      </answer>
+    </qandaentry>    
+
+    <qandaentry id="internet-communications-engine">
+      <question>
+        <para>
+          How does D-Bus differ from ZeroC's Internet Communications Engine (Ice)
+        </para>
+      </question>
+      <answer>
+        <para>
+          Start by reading <xref linkend="other-ipc"/>.
+        </para>
+        <para>
+          The <ulink url="http://www.zeroc.com/ice.html"> Internet
+          Communications Engine (Ice)</ulink> is a powerful IPC mechanism more
+          on the level of SOAP or CORBA than D-Bus.  Ice has a "dual-license"
+          business around it; i.e. you can use it under the GPL, or pay for a
+          proprietary license.
+        </para>
+      </answer>
+    </qandaentry>    
+
+    <qandaentry id="inter-client-exchange">
+      <question>
+        <para>
+          How does D-Bus differ from Inter-Client Exchange (ICE)?
+        </para>
+      </question>
+      <answer>
+        <para>
+          <ulink url="http://www.x.org/X11R6.8.1/docs/ICE/ice.pdf">ICE</ulink>
+          was developed for the X Session Management protocol (XSMP), as part of
+          the X Window System (X11R6.1). The idea was to allow desktop sessions
+          to contain nongraphical clients in addition to X clients.
+        </para>
+        <para>
+          ICE is a binary protocol designed for desktop use, and KDE's DCOP
+          builds on ICE.  ICE is substantially simpler than D-Bus (in contrast
+          to most of the other IPC systems mentioned here, which are more
+          complex). ICE doesn't really define a mapping to objects and methods
+          (DCOP adds that layer).  The reference implementation of ICE (libICE)
+          is often considered to be horrible (and horribly insecure).
+        </para>
+        <para>
+          DCOP and XSMP are the only two widely-used applications of ICE,
+          and both could in principle be replaced by D-Bus. (Though whether 
+          GNOME and KDE will bother is an open question.)
+        </para>
+      </answer>
+    </qandaentry>
+
+    
+
+    <qandaentry id="dcop">
+      <question>
+        <para>
+          How does D-Bus differ from DCOP?
+        </para>
+      </question>
+      <answer>
+        <para>
+          Start by reading <xref linkend="other-ipc"/>.
+        </para>
+        <para>
+          D-Bus is intentionally pretty similar to <ulink
+          url="http://developer.kde.org/documentation/library/kdeqt/dcop.html">DCOP</ulink>,
+          and can be thought of as a "DCOP the next generation" suitable for 
+          sharing between the various open source desktop projects.
+        </para>
+        <para>
+          D-Bus is a bit more complex than DCOP, though the Qt binding for D-Bus
+          should not be more complex for programmers. The additional complexity
+          of D-Bus arises from its separation of object references vs. bus names
+          vs. interfaces as distinct concepts, and its support for one-to-one
+          connections in addition to connections over the bus. The libdbus
+          reference implementation has a lot of API to support multiple bindings
+          and main loops, and performs data validation and out-of-memory handling 
+          in order to support secure applications such as the systemwide bus.
+        </para>
+        <para>
+          D-Bus is probably somewhat slower than DCOP due to data validation 
+          and more "layers" in the reference implementation. A comparison 
+          hasn't been posted to the list though.
+        </para>
+        <para>
+          At this time, KDE has not committed to using D-Bus, but there have
+          been discussions of KDE bridging D-Bus and DCOP, or even changing
+          DCOP's implementation to use D-Bus internally (so that GNOME and KDE
+          would end up using exactly the same bus). See the KDE mailing list 
+          archives for some of these discussions.
+        </para>
+      </answer>
+    </qandaentry>
+
+
+    <qandaentry id="yet-more-ipc">
+      <question>
+        <para>
+          How does D-Bus differ from [yet more IPC mechanisms]?
+        </para>
+      </question>
+      <answer>
+        <para>
+          Start by reading <xref linkend="other-ipc"/>.
+        </para>
+        <para>
+          There are countless uses of network sockets in the world.  <ulink
+          url="http://www.mbus.org/">MBUS</ulink>, Sun ONC/RPC, Jabber/XMPP,
+          SIP, are some we can think of quickly.
+        </para>
+      </answer>
+    </qandaentry>
+
+
+    <qandaentry id="which-ipc">
+      <question>
+        <para>
+          Which IPC mechanism should I use?
+        </para>
+      </question>
+      <answer>
+        <para>
+          Start by reading <xref linkend="other-ipc"/>.
+        </para>
+        <para>
+          If you're writing an Internet or Intranet application, XML-RPC or SOAP
+          work for many people. These are standard, available for most
+          languages, simple to debug and easy to use.
+        </para>
+        <para>
+          If you're writing a desktop application for UNIX, 
+          then D-Bus is of course our recommendation for 
+          talking to other parts of the desktop session.
+        </para>
+        <para>
+          D-Bus is also designed for communications between system daemons and
+          communications between the desktop and system daemons.
+        </para>
+        <para>
+          If you're doing something complicated such as clustering, 
+          distributed swarms, peer-to-peer, or whatever then 
+          the authors of this FAQ don't have expertise in these
+          areas and you should ask someone else or try a search engine.
+          D-Bus is most likely a poor choice but could be appropriate
+          for some things.
+        </para>
+        <para>
+          Note: the D-Bus mailing list is probably not the place to 
+          discuss which system is appropriate for your application, 
+          though you are welcome to ask specific questions about 
+          D-Bus <emphasis>after reading this FAQ, the tutorial, and 
+            searching the list archives</emphasis>. The best way 
+          to search the list archives is probably to use 
+          an Internet engine such as Google. On Google, 
+          include "site:freedesktop.org" in your search.
+        </para>
+      </answer>
+    </qandaentry>
+
+
+    <qandaentry>
+      <question>
+        <para>
+          How can I submit a bug or patch?
+        </para>
+      </question>
+      <answer>
+        <para>
+          The D-Bus <ulink url="http://dbus.freedesktop.org">web site</ulink>
+          has a link to the bug tracker, which is the best place to store
+          patches.  You can also post them to the list, especially if you want
+          to discuss the patch or get feedback.
+        </para>
+      </answer>
+    </qandaentry>
+
+  </qandaset>
+
+</article>
diff --git a/dbus/doc/dbus-launch.1 b/dbus/doc/dbus-launch.1
new file mode 100644
index 0000000..e22a3be
--- /dev/null
+++ b/dbus/doc/dbus-launch.1
@@ -0,0 +1,211 @@
+.\" 
+.\" dbus\-launch manual page.
+.\" Copyright (C) 2003 Red Hat, Inc.
+.\"
+.TH dbus\-launch 1
+.SH NAME
+dbus\-launch \- Utility to start a message bus from a shell script
+.SH SYNOPSIS
+.PP
+.B dbus\-launch [\-\-version] [\-\-sh\-syntax] [\-\-csh\-syntax] [\-\-auto\-syntax] [\-\-exit\-with\-session] [\-\-autolaunch=MACHINEID] [\-\-config\-file=FILENAME] [PROGRAM] [ARGS...]
+
+.SH DESCRIPTION
+
+The \fIdbus\-launch\fP command is used to start a session bus 
+instance of \fIdbus\-daemon\fP from a shell script.
+It would normally be called from a user's login
+scripts. Unlike the daemon itself, \fIdbus\-launch\fP exits, so
+backticks or the $() construct can be used to read information from
+\fIdbus\-launch\fP.
+
+With no arguments, \fIdbus\-launch\fP will launch a session bus
+instance and print the address and PID of that instance to standard
+output.
+
+You may specify a program to be run; in this case, \fIdbus\-launch\fP
+will launch a session bus instance, set the appropriate environment
+variables so the specified program can find the bus, and then execute the
+specified program, with the specified arguments.  See below for
+examples.
+
+If you launch a program, \fIdbus\-launch\fP will not print the
+information about the new bus to standard output.
+
+When \fIdbus\-launch\fP prints bus information to standard output, by
+default it is in a simple key\-value pairs format. However, you may 
+request several alternate syntaxes using the \-\-sh\-syntax, \-\-csh\-syntax,
+\-\-binary\-syntax, or
+\-\-auto\-syntax options. Several of these cause \fIdbus\-launch\fP to emit shell code
+to set up the environment.
+
+With the \-\-auto\-syntax option, \fIdbus\-launch\fP looks at the value
+of the SHELL environment variable to determine which shell syntax
+should be used.  If SHELL ends in "csh", then csh\-compatible code is
+emitted; otherwise Bourne shell code is emitted.  Instead of passing
+\-\-auto\-syntax, you may explicitly specify a particular one by using
+\-\-sh\-syntax for Bourne syntax, or \-\-csh\-syntax for csh syntax.
+In scripts, it's more robust to avoid \-\-auto\-syntax and you hopefully
+know which shell your script is written in.
+
+.PP
+See http://www.freedesktop.org/software/dbus/ for more information
+about D\-Bus. See also the man page for \fIdbus\-daemon\fP.
+
+.SH EXAMPLES
+
+Distributions running
+.B dbus\-launch
+as part of a standard X session should run
+.B "dbus\-launch \-\-exit\-with\-session"
+after the X server has started and become available, as a wrapper around
+the "main" X client (typically a session manager or window manager), as in
+these examples:
+
+.RS
+.B "dbus\-launch \-\-exit\-with\-session gnome\-session"
+
+.B "dbus\-launch \-\-exit\-with\-session openbox"
+
+.B "dbus\-launch \-\-exit\-with\-session ~/.xsession"
+.RE
+
+If your distribution does not do this, you can achieve similar results
+by running your session or window manager in the same way in a script
+run by your X session, such as
+.BR ~/.xsession ,
+.B ~/.xinitrc
+or
+.BR ~/.Xclients .
+
+To start a D-Bus session within a text-mode session, you can run
+dbus-launch in the background. For instance, in a sh-compatible shell:
+
+.nf
+  ## test for an existing bus daemon, just to be safe
+  if test \-z "$DBUS_SESSION_BUS_ADDRESS" ; then
+      ## if not found, launch a new one
+      eval `dbus\-launch \-\-sh\-syntax`
+      echo "D\-Bus per\-session daemon address is: $DBUS_SESSION_BUS_ADDRESS"
+  fi
+.fi
+Note that in this case, dbus-launch will exit, and dbus-daemon will not be
+terminated automatically on logout.
+
+.SH AUTOMATIC LAUNCHING
+
+.PP
+If DBUS_SESSION_BUS_ADDRESS is not set for a process that tries to use
+D\-Bus, by default the process will attempt to invoke dbus\-launch with
+the \-\-autolaunch option to start up a new session bus or find the 
+existing bus address on the X display or in a file in
+~/.dbus/session\-bus/
+
+.PP
+Whenever an autolaunch occurs, the application that had to
+start a new bus will be in its own little world; it can effectively
+end up starting a whole new session if it tries to use a lot of 
+bus services. This can be suboptimal or even totally broken, depending
+on the app and what it tries to do.
+
+.PP
+There are two common reasons for autolaunch. One is ssh to a remote
+machine. The ideal fix for that would be forwarding of
+DBUS_SESSION_BUS_ADDRESS in the same way that DISPLAY is forwarded.
+In the meantime, you can edit the session.conf config file to 
+have your session bus listen on TCP, and manually set
+DBUS_SESSION_BUS_ADDRESS, if you like.
+
+.PP
+The second common reason for autolaunch is an su to another user, and
+display of X applications running as the second user on the display
+belonging to the first user. Perhaps the ideal fix in this case
+would be to allow the second user to connect to the session bus of the
+first user, just as they can connect to the first user's display.
+However, a mechanism for that has not been coded.
+
+.PP
+You can always avoid autolaunch by manually setting
+DBUS_SESSION_BUS_ADDRESS. Autolaunch happens because the default
+address if none is set is "autolaunch:", so if any other address is
+set there will be no autolaunch. You can however include autolaunch in
+an explicit session bus address as a fallback, for example
+DBUS_SESSION_BUS_ADDRESS="something:,autolaunch:" \- in that case if
+the first address doesn't work, processes will autolaunch. (The bus
+address variable contains a comma\-separated list of addresses to try.)
+
+.PP
+The \-\-autolaunch option is considered an internal implementation
+detail of libdbus, and in fact there are plans to change it. There's
+no real reason to use it outside of the libdbus implementation anyhow.
+
+.SH OPTIONS
+The following options are supported:
+.TP
+.I "\-\-auto\-syntax"
+Choose \-\-csh\-syntax or \-\-sh\-syntax based on the SHELL environment variable.
+
+.I "\-\-binary\-syntax"
+Write to stdout a nul\-terminated bus address, then the bus PID as a
+binary integer of size sizeof(pid_t), then the bus X window ID as a
+binary integer of size sizeof(long). Integers are in the machine's
+byte order, not network byte order or any other canonical byte order.
+
+.TP
+.I "\-\-close\-stderr"
+Close the standard error output stream before starting the D\-Bus
+daemon. This is useful if you want to capture dbus\-launch error
+messages but you don't want dbus\-daemon to keep the stream open to
+your application.
+
+.TP
+.I "\-\-config\-file=FILENAME"
+Pass \-\-config\-file=FILENAME to the bus daemon, instead of passing it 
+the \-\-session argument. See the man page for dbus\-daemon
+
+.TP
+.I "\-\-csh\-syntax"
+Emit csh compatible code to set up environment variables.
+
+.TP
+.I "\-\-exit\-with\-session"
+If this option is provided, a persistent "babysitter" process will be 
+created that watches stdin for HUP and tries to connect to the X
+server. If this process gets a HUP on stdin or loses its X connection,
+it kills the message bus daemon.
+
+.TP
+.I "\-\-autolaunch=MACHINEID"
+This option implies that \fIdbus\-launch\fP should scan for a
+previously\-started session and reuse the values found there. If no
+session is found, it will start a new session. The
+\-\-exit\-with\-session option is implied if \-\-autolaunch is given.
+This option is for the exclusive use of libdbus, you do not want to
+use it manually. It may change in the future.
+
+.TP
+.I "\-\-sh\-syntax"
+Emit Bourne\-shell compatible code to set up environment variables.
+
+.TP
+.I "\-\-version"
+Print the version of dbus\-launch
+
+.SH NOTES
+
+If you run
+.B "dbus\-launch myapp"
+(with any other options), dbus\-daemon will
+.I not
+exit when
+.B myapp
+terminates: this is because
+.B myapp
+is assumed to be part of a larger session, rather than a session in its
+own right.
+
+.SH AUTHOR
+See http://www.freedesktop.org/software/dbus/doc/AUTHORS
+
+.SH BUGS
+Please send bug reports to the D\-Bus mailing list or bug tracker,
+see http://www.freedesktop.org/software/dbus/
diff --git a/dbus/doc/dbus-monitor.1 b/dbus/doc/dbus-monitor.1
new file mode 100644
index 0000000..6282b9e
--- /dev/null
+++ b/dbus/doc/dbus-monitor.1
@@ -0,0 +1,78 @@
+.\" 
+.\" dbus\-monitor manual page.
+.\" Copyright (C) 2003 Red Hat, Inc.
+.\"
+.TH dbus\-monitor 1
+.SH NAME
+dbus\-monitor \- debug probe to print message bus messages
+.SH SYNOPSIS
+.PP
+.B dbus\-monitor
+[\-\-system | \-\-session | \-\-address ADDRESS] [\-\-profile | \-\-monitor]
+[watch expressions]
+
+.SH DESCRIPTION
+
+The \fIdbus\-monitor\fP command is used to monitor messages going
+through a D\-Bus message bus.  See
+http://www.freedesktop.org/software/dbus/ for more information about
+the big picture.
+
+.PP
+There are two well\-known message buses: the systemwide message bus
+(installed on many systems as the "messagebus" service) and the
+per\-user\-login\-session message bus (started each time a user logs in).
+The \-\-system and \-\-session options direct \fIdbus\-monitor\fP to
+monitor the system or session buses respectively.  If neither is
+specified, \fIdbus\-monitor\fP monitors the session bus.
+
+.PP
+\fIdbus\-monitor\fP has two different output modes, the 'classic'\-style
+monitoring mode and profiling mode. The profiling format is a compact
+format with a single line per message and microsecond\-resolution timing
+information. The \-\-profile and \-\-monitor options select the profiling
+and monitoring output format respectively. If neither is specified,
+\fIdbus\-monitor\fP uses the monitoring output format.
+
+.PP
+In order to get \fIdbus\-monitor\fP to see the messages you are interested
+in, you should specify a set of watch expressions as you would expect to
+be passed to the \fIdbus_bus_add_match\fP function.
+
+.PP 
+The message bus configuration may keep \fIdbus\-monitor\fP from seeing
+all messages, especially if you run the monitor as a non\-root user.
+
+.SH OPTIONS
+.TP
+.I "\-\-system"
+Monitor the system message bus.
+.TP
+.I "\-\-session"
+Monitor the session message bus.  (This is the default.)
+.TP
+.I "\-\-address ADDRESS"
+Monitor an arbitrary message bus given at ADDRESS.
+.TP
+.I "\-\-profile"
+Use the profiling output format.
+.TP
+.I "\-\-monitor"
+Use the monitoring output format.  (This is the default.)
+
+.SH EXAMPLE
+Here is an example of using dbus\-monitor to watch for the gnome typing
+monitor to say things
+.nf
+
+  dbus\-monitor "type='signal',sender='org.gnome.TypingMonitor',interface='org.gnome.TypingMonitor'"
+
+.fi
+
+.SH AUTHOR
+dbus\-monitor was written by Philip Blundell.
+The profiling output mode was added by Olli Salli.
+
+.SH BUGS
+Please send bug reports to the D\-Bus mailing list or bug tracker,
+see http://www.freedesktop.org/software/dbus/
diff --git a/dbus/doc/dbus-send.1 b/dbus/doc/dbus-send.1
new file mode 100644
index 0000000..131a60d
--- /dev/null
+++ b/dbus/doc/dbus-send.1
@@ -0,0 +1,109 @@
+.\" 
+.\" dbus\-send manual page.
+.\" Copyright (C) 2003 Red Hat, Inc.
+.\"
+.TH dbus\-send 1
+.SH NAME
+dbus\-send \- Send a message to a message bus
+.SH SYNOPSIS
+.PP
+.B dbus\-send
+[\fB\-\-system\fP | \fB\-\-session\fP]
+[\fB\-\-dest=\fINAME\fP]
+[\fB\-\-print\-reply\fP[\fB=literal\fP]]
+[\fB\-\-reply\-timeout=\fIMSEC\fP]
+[\fB\-\-type=\fITYPE\fP]
+\fIOBJECT_PATH\fP \fIINTERFACE\fB.\fIMEMBER\fP [\fICONTENTS\fP ...]
+
+.SH DESCRIPTION
+
+The \fIdbus\-send\fP command is used to send a message to a D\-Bus message
+bus. See http://www.freedesktop.org/software/dbus/ for more 
+information about the big picture.
+
+.PP
+There are two well\-known message buses: the systemwide message bus 
+(installed on many systems as the "messagebus" service) and the 
+per\-user\-login\-session message bus (started each time a user logs in).
+The \fB\-\-system\fP and \fB\-\-session\fP options direct
+\fBdbus\-send\fP to send messages to the system or session buses respectively.
+If neither is specified, \fBdbus\-send\fP sends to the session bus.
+
+.PP 
+Nearly all uses of \fBdbus\-send\fP must provide the \fB\-\-dest\fP argument
+which is the name of a connection on the bus to send the message to. If
+\fB\-\-dest\fP is omitted, no destination is set.
+
+.PP
+The object path and the name of the message to send must always be
+specified. Following arguments, if any, are the message contents
+(message arguments).  These are given as type\-specified values and 
+may include containers (arrays, dicts, and variants) as described below.
+
+.nf
+<contents>   ::= <item> | <container> [ <item> | <container>...]
+<item>       ::= <type>:<value>
+<container>  ::= <array> | <dict> | <variant>
+<array>      ::= array:<type>:<value>[,<value>...] 
+<dict>       ::= dict:<type>:<type>:<key>,<value>[,<key>,<value>...]
+<variant>    ::= variant:<type>:<value>
+<type>       ::= string | int16 | uint 16 | int32 | uint32 | int64 | uint64 | double | byte | boolean | objpath
+.fi
+
+D\-Bus supports more types than these, but \fBdbus\-send\fP currently
+does not.  Also, \fBdbus\-send\fP does not permit empty containers
+or nested containers (e.g. arrays of variants).
+
+.PP
+Here is an example invocation:
+.nf
+
+  dbus\-send \-\-dest=org.freedesktop.ExampleName               \\
+            /org/freedesktop/sample/object/name              \\
+            org.freedesktop.ExampleInterface.ExampleMethod   \\
+            int32:47 string:'hello world' double:65.32       \\
+            array:string:"1st item","next item","last item"  \\
+            dict:string:int32:"one",1,"two",2,"three",3      \\
+            variant:int32:\-8                                 \\
+            objpath:/org/freedesktop/sample/object/name 
+
+.fi
+
+Note that the interface is separated from a method or signal 
+name by a dot, though in the actual protocol the interface
+and the interface member are separate fields.
+
+.SH OPTIONS
+The following options are supported:
+.TP
+.BI \-\-dest= NAME
+Specify the name of the connection to receive the message.
+.TP
+.B "\-\-print\-reply"
+Block for a reply to the message sent, and print any reply received
+in a human-readable form.
+.TP
+.B "\-\-print\-reply=literal"
+Block for a reply to the message sent, and print the body of the
+reply. If the reply is an object path or a string, it is printed
+literally, with no punctuation, escape characters etc.
+.TP
+.BI \-\-reply\-timeout= MSEC
+Wait for a reply for up to \fIMSEC\fP milliseconds.
+The default is implementation\(hydefined, typically 25 seconds.
+.TP
+.B "\-\-system"
+Send to the system message bus.
+.TP
+.B "\-\-session"
+Send to the session message bus.  (This is the default.)
+.TP
+.BI \-\-type= TYPE
+Specify \fBmethod_call\fP or \fBsignal\fP (defaults to "\fBsignal\fP").
+
+.SH AUTHOR
+dbus\-send was written by Philip Blundell.
+
+.SH BUGS
+Please send bug reports to the D\-Bus mailing list or bug tracker,
+see http://www.freedesktop.org/software/dbus/
diff --git a/dbus/doc/dbus-specification.xml b/dbus/doc/dbus-specification.xml
new file mode 100644
index 0000000..d806b8e
--- /dev/null
+++ b/dbus/doc/dbus-specification.xml
@@ -0,0 +1,5579 @@
+<?xml version="1.0" standalone="no" ?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+]>
+<article id="index">
+  <articleinfo>
+    <title>D-Bus Specification</title>
+    <releaseinfo>Version 0.19</releaseinfo>
+    <date>2012-02-21</date>
+    <authorgroup>
+      <author>
+	<firstname>Havoc</firstname>
+	<surname>Pennington</surname>
+	<affiliation>
+	  <orgname>Red Hat, Inc.</orgname>
+	  <address>
+	    <email>hp@pobox.com</email>
+	  </address>
+	</affiliation>
+      </author>
+      <author>
+	<firstname>Anders</firstname>
+	<surname>Carlsson</surname>
+	<affiliation>
+	  <orgname>CodeFactory AB</orgname>
+	  <address>
+            <email>andersca@codefactory.se</email>
+          </address>
+	</affiliation>
+      </author>
+      <author>
+	<firstname>Alexander</firstname>
+	<surname>Larsson</surname>
+	<affiliation>
+	  <orgname>Red Hat, Inc.</orgname>
+	  <address>
+            <email>alexl@redhat.com</email>
+          </address>
+	</affiliation>
+      </author>
+      <author>
+	<firstname>Sven</firstname>
+	<surname>Herzberg</surname>
+	<affiliation>
+	  <orgname>Imendio AB</orgname>
+	  <address>
+            <email>sven@imendio.com</email>
+          </address>
+	</affiliation>
+      </author>
+      <author>
+        <firstname>Simon</firstname>
+        <surname>McVittie</surname>
+        <affiliation>
+          <orgname>Collabora Ltd.</orgname>
+          <address>
+            <email>simon.mcvittie@collabora.co.uk</email>
+          </address>
+        </affiliation>
+      </author>
+      <author>
+        <firstname>David</firstname>
+        <surname>Zeuthen</surname>
+        <affiliation>
+          <orgname>Red Hat, Inc.</orgname>
+          <address>
+            <email>davidz@redhat.com</email>
+          </address>
+        </affiliation>
+      </author>
+    </authorgroup>
+   <revhistory>
+     <revision>
+       <revnumber>current</revnumber>
+       <date><ulink url='http://cgit.freedesktop.org/dbus/dbus/log/doc/dbus-specification.xml'>commit log</ulink></date>
+       <authorinitials></authorinitials>
+       <revremark></revremark>
+     </revision>
+     <revision>
+       <revnumber>0.19</revnumber>
+       <date>20 February 2012</date>
+       <authorinitials>smcv/lp</authorinitials>
+       <revremark>formally define unique connection names and well-known
+        bus names; document best practices for interface, bus, member and
+        error names, and object paths; document the search path for session
+        and system services on Unix; document the systemd transport</revremark>
+     </revision>
+     <revision>
+       <revnumber>0.18</revnumber>
+       <date>29 July 2011</date>
+       <authorinitials>smcv</authorinitials>
+       <revremark>define eavesdropping, unicast, broadcast; add eavesdrop
+         match keyword; promote type system to a top-level section</revremark>
+     </revision>
+     <revision>
+       <revnumber>0.17</revnumber>
+       <date>1 June 2011</date>
+       <authorinitials>smcv/davidz</authorinitials>
+       <revremark>define ObjectManager; reserve extra pseudo-type-codes used
+         by GVariant</revremark>
+     </revision>
+     <revision>
+       <revnumber>0.16</revnumber>
+       <date>11 April 2011</date>
+       <authorinitials></authorinitials>
+       <revremark>add path_namespace, arg0namespace; argNpath matches object
+        paths</revremark>
+     </revision>
+     <revision>
+       <revnumber>0.15</revnumber>
+       <date>3 November 2010</date>
+       <authorinitials></authorinitials>
+       <revremark></revremark>
+     </revision>
+     <revision>
+       <revnumber>0.14</revnumber>
+       <date>12 May 2010</date>
+       <authorinitials></authorinitials>
+       <revremark></revremark>
+     </revision>
+     <revision>
+       <revnumber>0.13</revnumber>
+       <date>23 Dezember 2009</date>
+       <authorinitials></authorinitials>
+       <revremark></revremark>
+     </revision>
+     <revision>
+       <revnumber>0.12</revnumber>
+       <date>7 November, 2006</date>
+       <authorinitials></authorinitials>
+       <revremark></revremark>
+     </revision>
+     <revision>
+       <revnumber>0.11</revnumber>
+       <date>6 February 2005</date>
+       <authorinitials></authorinitials>
+       <revremark></revremark>
+     </revision>
+     <revision>
+       <revnumber>0.10</revnumber>
+       <date>28 January 2005</date>
+       <authorinitials></authorinitials>
+       <revremark></revremark>
+     </revision>
+     <revision>
+       <revnumber>0.9</revnumber>
+       <date>7 Januar 2005</date>
+       <authorinitials></authorinitials>
+       <revremark></revremark>
+     </revision>
+     <revision>
+       <revnumber>0.8</revnumber>
+       <date>06 September 2003</date>
+       <authorinitials></authorinitials>
+       <revremark>First released document.</revremark>
+     </revision>
+   </revhistory>
+  </articleinfo>
+
+  <sect1 id="introduction">
+    <title>Introduction</title>
+    <para>
+      D-Bus is a system for low-latency, low-overhead, easy to use
+      interprocess communication (IPC). In more detail:
+      <itemizedlist>
+        <listitem>
+          <para>
+            D-Bus is <emphasis>low-latency</emphasis> because it is designed 
+            to avoid round trips and allow asynchronous operation, much like 
+            the X protocol.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            D-Bus is <emphasis>low-overhead</emphasis> because it uses a
+            binary protocol, and does not have to convert to and from a text
+            format such as XML. Because D-Bus is intended for potentially
+            high-resolution same-machine IPC, not primarily for Internet IPC,
+            this is an interesting optimization.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            D-Bus is <emphasis>easy to use</emphasis> because it works in terms
+            of <firstterm>messages</firstterm> rather than byte streams, and
+            automatically handles a lot of the hard IPC issues. Also, the D-Bus
+            library is designed to be wrapped in a way that lets developers use
+            their framework's existing object/type system, rather than learning
+            a new one specifically for IPC.
+          </para>
+        </listitem>
+      </itemizedlist>
+    </para>
+
+    <para>
+      The base D-Bus protocol is a one-to-one (peer-to-peer or client-server)
+      protocol, specified in <xref linkend="message-protocol"/>. That is, it is
+      a system for one application to talk to a single other
+      application. However, the primary intended application of the protocol is the
+      D-Bus <firstterm>message bus</firstterm>, specified in <xref
+      linkend="message-bus"/>. The message bus is a special application that
+      accepts connections from multiple other applications, and forwards
+      messages among them.
+    </para>
+
+    <para>
+      Uses of D-Bus include notification of system changes (notification of when
+      a camera is plugged in to a computer, or a new version of some software
+      has been installed), or desktop interoperability, for example a file
+      monitoring service or a configuration service.
+    </para>
+
+    <para>
+      D-Bus is designed for two specific use cases:
+      <itemizedlist>
+        <listitem>
+          <para>
+            A "system bus" for notifications from the system to user sessions,
+            and to allow the system to request input from user sessions.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            A "session bus" used to implement desktop environments such as 
+            GNOME and KDE.
+          </para>
+        </listitem>
+      </itemizedlist>
+      D-Bus is not intended to be a generic IPC system for any possible 
+      application, and intentionally omits many features found in other 
+      IPC systems for this reason.
+    </para>
+
+    <para>
+      At the same time, the bus daemons offer a number of features not found in
+      other IPC systems, such as single-owner "bus names" (similar to X
+      selections), on-demand startup of services, and security policies.
+      In many ways, these features are the primary motivation for developing 
+      D-Bus; other systems would have sufficed if IPC were the only goal.
+    </para>
+
+    <para>
+      D-Bus may turn out to be useful in unanticipated applications, but future
+      versions of this spec and the reference implementation probably will not
+      incorporate features that interfere with the core use cases.
+    </para>
+
+    <para>
+      The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+      "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+      document are to be interpreted as described in RFC 2119. However, the
+      document could use a serious audit to be sure it makes sense to do
+      so. Also, they are not capitalized.
+    </para>
+
+    <sect2 id="stability">
+      <title>Protocol and Specification Stability</title>
+      <para>
+        The D-Bus protocol is frozen (only compatible extensions are allowed) as
+        of November 8, 2006.  However, this specification could still use a fair
+        bit of work to make interoperable reimplementation possible without
+        reference to the D-Bus reference implementation. Thus, this
+        specification is not marked 1.0. To mark it 1.0, we'd like to see
+        someone invest significant effort in clarifying the specification
+        language, and growing the specification to cover more aspects of the
+        reference implementation's behavior.
+      </para>
+      <para>
+        Until this work is complete, any attempt to reimplement D-Bus will 
+        probably require looking at the reference implementation and/or asking
+        questions on the D-Bus mailing list about intended behavior. 
+        Questions on the list are very welcome.
+      </para>
+      <para>
+        Nonetheless, this document should be a useful starting point and is 
+        to our knowledge accurate, though incomplete.
+      </para>
+    </sect2>
+    
+  </sect1>
+
+  <sect1 id="type-system">
+    <title>Type System</title>
+
+    <para>
+      D-Bus has a type system, in which values of various types can be
+      serialized into a sequence of bytes referred to as the
+      <firstterm>wire format</firstterm> in a standard way.
+      Converting a value from some other representation into the wire
+      format is called <firstterm>marshaling</firstterm> and converting
+      it back from the wire format is <firstterm>unmarshaling</firstterm>.
+    </para>
+
+    <sect2 id="message-protocol-signatures">
+      <title>Type Signatures</title>
+
+      <para>
+        The D-Bus protocol does not include type tags in the marshaled data; a
+        block of marshaled values must have a known <firstterm>type
+        signature</firstterm>.  The type signature is made up of <firstterm>type
+        codes</firstterm>. A type code is an ASCII character representing the
+        type of a value. Because ASCII characters are used, the type signature
+        will always form a valid ASCII string. A simple string compare 
+        determines whether two type signatures are equivalent.
+      </para>
+
+      <para>
+        As a simple example, the type code for 32-bit integer (<literal>INT32</literal>) is
+        the ASCII character 'i'. So the signature for a block of values 
+        containing a single <literal>INT32</literal> would be:
+        <programlisting>
+          "i"
+        </programlisting>
+        A block of values containing two <literal>INT32</literal> would have this signature:
+        <programlisting>
+          "ii"
+        </programlisting>        
+      </para>
+
+      <para>
+        All <firstterm>basic</firstterm> types work like 
+        <literal>INT32</literal> in this example. To marshal and unmarshal 
+        basic types, you simply read one value from the data
+        block corresponding to each type code in the signature.
+        In addition to basic types, there are four <firstterm>container</firstterm> 
+        types: <literal>STRUCT</literal>, <literal>ARRAY</literal>, <literal>VARIANT</literal>, 
+        and <literal>DICT_ENTRY</literal>.
+      </para>
+
+      <para>
+        <literal>STRUCT</literal> has a type code, ASCII character 'r', but this type 
+        code does not appear in signatures. Instead, ASCII characters
+        '(' and ')' are used to mark the beginning and end of the struct.
+        So for example, a struct containing two integers would have this 
+        signature:
+        <programlisting>
+          "(ii)"
+        </programlisting>
+        Structs can be nested, so for example a struct containing 
+        an integer and another struct:
+        <programlisting>
+          "(i(ii))"
+        </programlisting>
+        The value block storing that struct would contain three integers; the
+        type signature allows you to distinguish "(i(ii))" from "((ii)i)" or
+        "(iii)" or "iii".
+      </para>
+
+      <para>
+        The <literal>STRUCT</literal> type code 'r' is not currently used in the D-Bus protocol,
+        but is useful in code that implements the protocol. This type code 
+        is specified to allow such code to interoperate in non-protocol contexts.
+      </para>
+
+      <para>
+        Empty structures are not allowed; there must be at least one
+        type code between the parentheses.
+      </para>
+
+      <para>
+        <literal>ARRAY</literal> has ASCII character 'a' as type code. The array type code must be
+        followed by a <firstterm>single complete type</firstterm>. The single
+        complete type following the array is the type of each array element. So
+        the simple example is:
+        <programlisting>
+          "ai"
+        </programlisting>
+        which is an array of 32-bit integers. But an array can be of any type, 
+        such as this array-of-struct-with-two-int32-fields:
+        <programlisting>
+          "a(ii)"
+        </programlisting>
+        Or this array of array of integer:
+        <programlisting>
+          "aai"
+        </programlisting>
+      </para>
+
+      <para>
+        The phrase <firstterm>single complete type</firstterm> deserves some 
+        definition. A single complete type is a basic type code, a variant type code, 
+        an array with its element type, or a struct with its fields. 
+        So the following signatures are not single complete types:
+        <programlisting>
+          "aa"
+        </programlisting>
+        <programlisting>
+          "(ii"
+        </programlisting>
+        <programlisting>
+          "ii)"
+        </programlisting>
+        And the following signatures contain multiple complete types:
+        <programlisting>
+          "ii"
+        </programlisting>
+        <programlisting>
+          "aiai"
+        </programlisting>
+        <programlisting>
+          "(ii)(ii)"
+        </programlisting>
+        Note however that a single complete type may <emphasis>contain</emphasis>
+        multiple other single complete types.
+      </para>
+
+      <para>
+        <literal>VARIANT</literal> has ASCII character 'v' as its type code. A marshaled value of
+        type <literal>VARIANT</literal> will have the signature of a single complete type as part
+        of the <emphasis>value</emphasis>.  This signature will be followed by a
+        marshaled value of that type.
+      </para>
+
+      <para>
+        A <literal>DICT_ENTRY</literal> works exactly like a struct, but rather
+        than parentheses it uses curly braces, and it has more restrictions.
+        The restrictions are: it occurs only as an array element type; it has
+        exactly two single complete types inside the curly braces; the first
+        single complete type (the "key") must be a basic type rather than a
+        container type. Implementations must not accept dict entries outside of
+        arrays, must not accept dict entries with zero, one, or more than two
+        fields, and must not accept dict entries with non-basic-typed keys. A
+        dict entry is always a key-value pair.
+      </para>
+      
+      <para>
+        The first field in the <literal>DICT_ENTRY</literal> is always the key.
+        A message is considered corrupt if the same key occurs twice in the same
+        array of <literal>DICT_ENTRY</literal>. However, for performance reasons
+        implementations are not required to reject dicts with duplicate keys.
+      </para>
+
+      <para>
+        In most languages, an array of dict entry would be represented as a 
+        map, hash table, or dict object.
+      </para>
+
+      <para>
+        The following table summarizes the D-Bus types.
+        <informaltable>
+          <tgroup cols="3">
+            <thead>
+              <row>
+                <entry>Conventional Name</entry>
+                <entry>Code</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry><literal>INVALID</literal></entry>
+                <entry>0 (ASCII NUL)</entry>
+                <entry>Not a valid type code, used to terminate signatures</entry>
+              </row><row>
+		<entry><literal>BYTE</literal></entry>
+		<entry>121 (ASCII 'y')</entry>
+		<entry>8-bit unsigned integer</entry>
+              </row><row>
+		<entry><literal>BOOLEAN</literal></entry>
+		<entry>98 (ASCII 'b')</entry>
+		<entry>Boolean value, 0 is <literal>FALSE</literal> and 1 is <literal>TRUE</literal>. Everything else is invalid.</entry>
+	      </row><row>
+                <entry><literal>INT16</literal></entry>
+                <entry>110 (ASCII 'n')</entry>
+                <entry>16-bit signed integer</entry>
+              </row><row>
+                <entry><literal>UINT16</literal></entry>
+                <entry>113 (ASCII 'q')</entry>
+                <entry>16-bit unsigned integer</entry>
+	      </row><row>
+                <entry><literal>INT32</literal></entry>
+                <entry>105 (ASCII 'i')</entry>
+                <entry>32-bit signed integer</entry>
+              </row><row>
+                <entry><literal>UINT32</literal></entry>
+                <entry>117 (ASCII 'u')</entry>
+                <entry>32-bit unsigned integer</entry>
+	      </row><row>
+                <entry><literal>INT64</literal></entry>
+                <entry>120 (ASCII 'x')</entry>
+                <entry>64-bit signed integer</entry>
+              </row><row>
+                <entry><literal>UINT64</literal></entry>
+                <entry>116 (ASCII 't')</entry>
+                <entry>64-bit unsigned integer</entry>
+              </row><row>
+                <entry><literal>DOUBLE</literal></entry>
+                <entry>100 (ASCII 'd')</entry>
+                <entry>IEEE 754 double</entry>
+              </row><row>
+                <entry><literal>STRING</literal></entry>
+                <entry>115 (ASCII 's')</entry>
+                <entry>UTF-8 string (<emphasis>must</emphasis> be valid UTF-8). Must be nul terminated and contain no other nul bytes.</entry>
+              </row><row>
+                <entry><literal>OBJECT_PATH</literal></entry>
+                <entry>111 (ASCII 'o')</entry>
+                <entry>Name of an object instance</entry>
+              </row><row>
+                <entry><literal>SIGNATURE</literal></entry>
+                <entry>103 (ASCII 'g')</entry>
+                <entry>A type signature</entry>
+              </row><row>
+                <entry><literal>ARRAY</literal></entry>
+                <entry>97 (ASCII 'a')</entry>
+                <entry>Array</entry>
+              </row><row>
+                <entry><literal>STRUCT</literal></entry>
+                <entry>114 (ASCII 'r'), 40 (ASCII '('), 41 (ASCII ')')</entry>
+                <entry>Struct; type code 114 'r' is reserved for use in
+                  bindings and implementations to represent the general
+                  concept of a struct, and must not appear in signatures
+                  used on D-Bus.</entry>
+              </row><row>
+                <entry><literal>VARIANT</literal></entry>
+                <entry>118 (ASCII 'v') </entry>
+                <entry>Variant type (the type of the value is part of the value itself)</entry>
+              </row><row>
+                <entry><literal>DICT_ENTRY</literal></entry>
+                <entry>101 (ASCII 'e'), 123 (ASCII '{'), 125 (ASCII '}') </entry>
+                <entry>Entry in a dict or map (array of key-value pairs).
+                  Type code 101 'e' is reserved for use in bindings and
+                  implementations to represent the general concept of a
+                  dict or dict-entry, and must not appear in signatures
+                  used on D-Bus.</entry>
+              </row><row>
+                <entry><literal>UNIX_FD</literal></entry>
+                <entry>104 (ASCII 'h')</entry>
+                <entry>Unix file descriptor</entry>
+              </row>
+              <row>
+                <entry>(reserved)</entry>
+                <entry>109 (ASCII 'm')</entry>
+                <entry>Reserved for <ulink
+                    url="https://bugs.freedesktop.org/show_bug.cgi?id=27857">a
+                  'maybe' type compatible with the one in GVariant</ulink>,
+                  and must not appear in signatures used on D-Bus until
+                  specified here</entry>
+              </row>
+              <row>
+                <entry>(reserved)</entry>
+                <entry>42 (ASCII '*')</entry>
+                <entry>Reserved for use in bindings/implementations to
+                  represent any <firstterm>single complete type</firstterm>,
+                  and must not appear in signatures used on D-Bus.</entry>
+              </row>
+              <row>
+                <entry>(reserved)</entry>
+                <entry>63 (ASCII '?')</entry>
+                <entry>Reserved for use in bindings/implementations to
+                  represent any <firstterm>basic type</firstterm>, and must
+                  not appear in signatures used on D-Bus.</entry>
+              </row>
+              <row>
+                <entry>(reserved)</entry>
+                <entry>64 (ASCII '@'), 38 (ASCII '&amp;'),
+                  94 (ASCII '^')</entry>
+                <entry>Reserved for internal use by bindings/implementations,
+                  and must not appear in signatures used on D-Bus.
+                  GVariant uses these type-codes to encode calling
+                  conventions.</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+      </para>
+
+    </sect2>
+
+    <sect2 id="message-protocol-marshaling">
+      <title>Marshaling (Wire Format)</title>
+
+      <para>
+        Given a type signature, a block of bytes can be converted into typed
+        values. This section describes the format of the block of bytes.  Byte
+        order and alignment issues are handled uniformly for all D-Bus types.
+      </para>
+
+      <para>
+        A block of bytes has an associated byte order. The byte order 
+        has to be discovered in some way; for D-Bus messages, the 
+        byte order is part of the message header as described in 
+        <xref linkend="message-protocol-messages"/>. For now, assume 
+        that the byte order is known to be either little endian or big 
+          endian.
+      </para>
+
+      <para>
+        Each value in a block of bytes is aligned "naturally," for example
+        4-byte values are aligned to a 4-byte boundary, and 8-byte values to an
+        8-byte boundary. To properly align a value, <firstterm>alignment
+        padding</firstterm> may be necessary. The alignment padding must always
+        be the minimum required padding to properly align the following value;
+        and it must always be made up of nul bytes. The alignment padding must
+        not be left uninitialized (it can't contain garbage), and more padding
+        than required must not be used.
+      </para>
+
+      <para>
+        Given all this, the types are marshaled on the wire as follows:
+        <informaltable>
+          <tgroup cols="3">
+            <thead>
+              <row>
+                <entry>Conventional Name</entry>
+                <entry>Encoding</entry>
+                <entry>Alignment</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry><literal>INVALID</literal></entry>
+                <entry>Not applicable; cannot be marshaled.</entry>
+                <entry>N/A</entry>
+              </row><row>
+                <entry><literal>BYTE</literal></entry>
+                <entry>A single 8-bit byte.</entry>
+                <entry>1</entry>
+              </row><row>
+                <entry><literal>BOOLEAN</literal></entry>
+                <entry>As for <literal>UINT32</literal>, but only 0 and 1 are valid values.</entry>
+                <entry>4</entry>
+              </row><row>
+                <entry><literal>INT16</literal></entry>
+                <entry>16-bit signed integer in the message's byte order.</entry>
+                <entry>2</entry>
+              </row><row>
+                <entry><literal>UINT16</literal></entry>
+                <entry>16-bit unsigned integer in the message's byte order.</entry>
+                <entry>2</entry>
+              </row><row>
+                <entry><literal>INT32</literal></entry>
+                <entry>32-bit signed integer in the message's byte order.</entry>
+                <entry>4</entry>
+              </row><row>
+                <entry><literal>UINT32</literal></entry>
+                <entry>32-bit unsigned integer in the message's byte order.</entry>
+                <entry>4</entry>
+              </row><row>
+                <entry><literal>INT64</literal></entry>
+                <entry>64-bit signed integer in the message's byte order.</entry>
+                <entry>8</entry>
+              </row><row>
+                <entry><literal>UINT64</literal></entry>
+                <entry>64-bit unsigned integer in the message's byte order.</entry>
+                <entry>8</entry>
+              </row><row>
+                <entry><literal>DOUBLE</literal></entry>
+                <entry>64-bit IEEE 754 double in the message's byte order.</entry>
+                <entry>8</entry>
+              </row><row>
+                <entry><literal>STRING</literal></entry>
+                <entry>A <literal>UINT32</literal> indicating the string's 
+                  length in bytes excluding its terminating nul, followed by 
+                  non-nul string data of the given length, followed by a terminating nul 
+                  byte.
+                </entry>
+                <entry>
+                  4 (for the length)
+                </entry>
+              </row><row>
+                <entry><literal>OBJECT_PATH</literal></entry>
+                <entry>Exactly the same as <literal>STRING</literal> except the 
+                  content must be a valid object path (see below).
+                </entry>
+                <entry>
+                  4 (for the length)
+                </entry>
+              </row><row>
+                <entry><literal>SIGNATURE</literal></entry>
+                <entry>The same as <literal>STRING</literal> except the length is a single 
+                  byte (thus signatures have a maximum length of 255)
+                  and the content must be a valid signature (see below).
+                </entry>
+                <entry>
+                  1
+                </entry>
+              </row><row>
+                <entry><literal>ARRAY</literal></entry>
+                <entry>
+                  A <literal>UINT32</literal> giving the length of the array data in bytes, followed by 
+                  alignment padding to the alignment boundary of the array element type, 
+                  followed by each array element. The array length is from the 
+                  end of the alignment padding to the end of the last element,
+                  i.e. it does not include the padding after the length,
+                  or any padding after the last element.
+                  Arrays have a maximum length defined to be 2 to the 26th power or
+                  67108864. Implementations must not send or accept arrays exceeding this
+                  length.
+                </entry>
+                <entry>
+                  4 (for the length)
+                </entry>
+              </row><row>
+                <entry><literal>STRUCT</literal></entry>
+                <entry>
+                  A struct must start on an 8-byte boundary regardless of the
+                  type of the struct fields. The struct value consists of each
+                  field marshaled in sequence starting from that 8-byte
+                  alignment boundary.
+                </entry>
+                <entry>
+                  8
+                </entry>
+	      </row><row>
+                <entry><literal>VARIANT</literal></entry>
+                <entry>
+                  A variant type has a marshaled
+                  <literal>SIGNATURE</literal> followed by a marshaled
+                  value with the type given in the signature.  Unlike
+                  a message signature, the variant signature can
+                  contain only a single complete type.  So "i", "ai"
+                  or "(ii)" is OK, but "ii" is not.  Use of variants may not
+                  cause a total message depth to be larger than 64, including
+		  other container types such as structures.
+                </entry>
+                <entry>
+                  1 (alignment of the signature)
+                </entry>
+	      </row><row>
+                <entry><literal>DICT_ENTRY</literal></entry>
+                <entry>
+                  Identical to STRUCT.
+                </entry>
+                <entry>
+                  8
+                </entry>
+              </row><row>
+                <entry><literal>UNIX_FD</literal></entry>
+                <entry>32-bit unsigned integer in the message's byte
+                order. The actual file descriptors need to be
+                transferred out-of-band via some platform specific
+                mechanism. On the wire, values of this type store the index to the
+                file descriptor in the array of file descriptors that
+                accompany the message.</entry>
+                <entry>4</entry>
+	      </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+      </para>
+      
+      <sect3 id="message-protocol-marshaling-object-path">
+        <title>Valid Object Paths</title>
+        
+        <para>
+          An object path is a name used to refer to an object instance.
+          Conceptually, each participant in a D-Bus message exchange may have
+          any number of object instances (think of C++ or Java objects) and each
+          such instance will have a path. Like a filesystem, the object
+          instances in an application form a hierarchical tree.
+        </para>
+        
+        <para>
+          The following rules define a valid object path. Implementations must 
+          not send or accept messages with invalid object paths.
+          <itemizedlist>
+            <listitem>
+              <para>
+                The path may be of any length.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The path must begin with an ASCII '/' (integer 47) character, 
+                and must consist of elements separated by slash characters.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                Each element must only contain the ASCII characters 
+                "[A-Z][a-z][0-9]_"
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                No element may be the empty string.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                Multiple '/' characters cannot occur in sequence.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                A trailing '/' character is not allowed unless the 
+                path is the root path (a single '/' character).
+              </para>
+            </listitem>
+          </itemizedlist>
+        </para>
+
+        <para>
+          Object paths are often namespaced by starting with a reversed
+          domain name and containing an interface version number, in the
+          same way as
+          <link linkend="message-protocol-names-interface">interface
+            names</link> and
+          <link linkend="message-protocol-names-bus">well-known
+            bus names</link>.
+          This makes it possible to implement more than one service, or
+          more than one version of a service, in the same process,
+          even if the services share a connection but cannot otherwise
+          co-operate (for instance, if they are implemented by different
+          plugins).
+        </para>
+
+        <para>
+          For instance, if the owner of <literal>example.com</literal> is
+          developing a D-Bus API for a music player, they might use the
+          hierarchy of object paths that start with
+          <literal>/com/example/MusicPlayer1</literal> for its objects.
+        </para>
+      </sect3>
+
+      <sect3 id="message-protocol-marshaling-signature">
+        <title>Valid Signatures</title>
+        <para>
+          An implementation must not send or accept invalid signatures.
+          Valid signatures will conform to the following rules:
+          <itemizedlist>
+            <listitem>
+              <para>
+                The signature ends with a nul byte.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The signature is a list of single complete types. 
+                Arrays must have element types, and structs must 
+                have both open and close parentheses.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                Only type codes and open and close parentheses are 
+                allowed in the signature. The <literal>STRUCT</literal> type code
+                is not allowed in signatures, because parentheses
+                are used instead.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The maximum depth of container type nesting is 32 array type
+                codes and 32 open parentheses. This implies that the maximum
+                total depth of recursion is 64, for an "array of array of array
+                of ... struct of struct of struct of ..."  where there are 32
+                array and 32 struct.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The maximum length of a signature is 255.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                Signatures must be nul-terminated.
+              </para>
+            </listitem>
+          </itemizedlist>
+        </para>
+      </sect3>
+      
+    </sect2>
+
+  </sect1>
+
+  <sect1 id="message-protocol">
+    <title>Message Protocol</title>
+
+    <para>
+      A <firstterm>message</firstterm> consists of a
+      <firstterm>header</firstterm> and a <firstterm>body</firstterm>. If you
+      think of a message as a package, the header is the address, and the body
+      contains the package contents. The message delivery system uses the header
+      information to figure out where to send the message and how to interpret
+      it; the recipient interprets the body of the message.
+    </para>
+    
+    <para>
+      The body of the message is made up of zero or more
+      <firstterm>arguments</firstterm>, which are typed values, such as an
+      integer or a byte array.
+    </para>
+
+    <para>
+      Both header and body use the D-Bus <link linkend="type-system">type
+        system</link> and format for serializing data.
+    </para>
+
+    <sect2 id="message-protocol-messages">
+      <title>Message Format</title>
+
+      <para>
+        A message consists of a header and a body. The header is a block of
+        values with a fixed signature and meaning.  The body is a separate block
+        of values, with a signature specified in the header.
+      </para>
+
+      <para>
+        The length of the header must be a multiple of 8, allowing the body to
+        begin on an 8-byte boundary when storing the entire message in a single
+        buffer. If the header does not naturally end on an 8-byte boundary 
+        up to 7 bytes of nul-initialized alignment padding must be added.
+      </para>
+
+      <para>
+        The message body need not end on an 8-byte boundary.
+      </para>
+
+      <para>
+        The maximum length of a message, including header, header alignment padding, 
+        and body is 2 to the 27th power or 134217728. Implementations must not 
+        send or accept messages exceeding this size.
+      </para>
+      
+      <para>
+        The signature of the header is:
+        <programlisting>
+          "yyyyuua(yv)"
+        </programlisting>
+        Written out more readably, this is:
+        <programlisting>
+          BYTE, BYTE, BYTE, BYTE, UINT32, UINT32, ARRAY of STRUCT of (BYTE,VARIANT)
+        </programlisting>
+      </para>
+
+      <para>
+        These values have the following meanings:
+        <informaltable>
+          <tgroup cols="2">
+            <thead>
+              <row>
+                <entry>Value</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>1st <literal>BYTE</literal></entry>
+                <entry>Endianness flag; ASCII 'l' for little-endian 
+                  or ASCII 'B' for big-endian. Both header and body are 
+                in this endianness.</entry>
+              </row>
+              <row>
+                <entry>2nd <literal>BYTE</literal></entry>
+                <entry><firstterm>Message type</firstterm>. Unknown types must be ignored. 
+                  Currently-defined types are described below.
+                </entry>
+              </row>
+              <row>
+                <entry>3rd <literal>BYTE</literal></entry>
+                <entry>Bitwise OR of flags. Unknown flags
+                  must be ignored. Currently-defined flags are described below.
+                </entry>
+              </row>
+              <row>
+                <entry>4th <literal>BYTE</literal></entry>
+                <entry>Major protocol version of the sending application.  If
+                the major protocol version of the receiving application does not
+                match, the applications will not be able to communicate and the
+                D-Bus connection must be disconnected. The major protocol
+                version for this version of the specification is 1.
+                </entry>
+              </row>
+              <row>
+                <entry>1st <literal>UINT32</literal></entry>
+                <entry>Length in bytes of the message body, starting 
+                  from the end of the header. The header ends after 
+                  its alignment padding to an 8-boundary.
+                </entry>
+              </row>
+              <row>
+                <entry>2nd <literal>UINT32</literal></entry>
+                <entry>The serial of this message, used as a cookie 
+                  by the sender to identify the reply corresponding
+                  to this request. This must not be zero.
+                </entry>
+              </row>      
+              <row>
+                <entry><literal>ARRAY</literal> of <literal>STRUCT</literal> of (<literal>BYTE</literal>,<literal>VARIANT</literal>)</entry>
+                <entry>An array of zero or more <firstterm>header
+                  fields</firstterm> where the byte is the field code, and the
+                  variant is the field value. The message type determines 
+                  which fields are required.
+                </entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+      </para>
+      <para>
+        <firstterm>Message types</firstterm> that can appear in the second byte
+        of the header are:
+        <informaltable>
+          <tgroup cols="3">
+            <thead>
+              <row>
+                <entry>Conventional name</entry>
+                <entry>Decimal value</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry><literal>INVALID</literal></entry>
+                <entry>0</entry>
+                <entry>This is an invalid type.</entry>
+              </row>
+              <row>
+                <entry><literal>METHOD_CALL</literal></entry>
+                <entry>1</entry>
+                <entry>Method call.</entry>
+              </row>
+              <row>
+                <entry><literal>METHOD_RETURN</literal></entry>
+                <entry>2</entry>
+                <entry>Method reply with returned data.</entry>
+              </row>
+              <row>
+                <entry><literal>ERROR</literal></entry>
+                <entry>3</entry>
+                <entry>Error reply. If the first argument exists and is a
+                string, it is an error message.</entry>
+              </row>
+              <row>
+                <entry><literal>SIGNAL</literal></entry>
+                <entry>4</entry>
+                <entry>Signal emission.</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+      </para>
+      <para>
+        Flags that can appear in the third byte of the header:
+        <informaltable>
+          <tgroup cols="3">
+            <thead>
+              <row>
+                <entry>Conventional name</entry>
+                <entry>Hex value</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry><literal>NO_REPLY_EXPECTED</literal></entry>
+                <entry>0x1</entry>
+                <entry>This message does not expect method return replies or
+                error replies; the reply can be omitted as an
+                optimization. However, it is compliant with this specification
+                to return the reply despite this flag and the only harm 
+                  from doing so is extra network traffic.
+                </entry>
+              </row>
+              <row>
+                <entry><literal>NO_AUTO_START</literal></entry>
+                <entry>0x2</entry>
+                <entry>The bus must not launch an owner
+                  for the destination name in response to this message.
+                </entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+      </para>
+
+      <sect3 id="message-protocol-header-fields">
+        <title>Header Fields</title>
+
+        <para>
+          The array at the end of the header contains <firstterm>header
+          fields</firstterm>, where each field is a 1-byte field code followed
+          by a field value. A header must contain the required header fields for
+          its message type, and zero or more of any optional header
+          fields. Future versions of this protocol specification may add new
+          fields. Implementations must ignore fields they do not
+          understand. Implementations must not invent their own header fields;
+          only changes to this specification may introduce new header fields.
+        </para>
+
+        <para>
+          Again, if an implementation sees a header field code that it does not
+          expect, it must ignore that field, as it will be part of a new
+          (but compatible) version of this specification. This also applies 
+          to known header fields appearing in unexpected messages, for 
+          example: if a signal has a reply serial it must be ignored
+          even though it has no meaning as of this version of the spec.
+        </para>
+
+        <para>
+          However, implementations must not send or accept known header fields
+          with the wrong type stored in the field value. So for example a
+          message with an <literal>INTERFACE</literal> field of type
+          <literal>UINT32</literal> would be considered corrupt.
+        </para>
+
+        <para>
+          Here are the currently-defined header fields:
+          <informaltable>
+            <tgroup cols="5">
+              <thead>
+                <row>
+                  <entry>Conventional Name</entry>
+                  <entry>Decimal Code</entry>
+                  <entry>Type</entry>
+                  <entry>Required In</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry><literal>INVALID</literal></entry>
+                  <entry>0</entry>
+                  <entry>N/A</entry>
+                  <entry>not allowed</entry>
+                  <entry>Not a valid field name (error if it appears in a message)</entry>
+                </row>
+                <row>
+                  <entry><literal>PATH</literal></entry>
+                  <entry>1</entry>
+                  <entry><literal>OBJECT_PATH</literal></entry>
+                  <entry><literal>METHOD_CALL</literal>, <literal>SIGNAL</literal></entry>
+                  <entry>The object to send a call to,
+                    or the object a signal is emitted from.
+                    The special path
+                    <literal>/org/freedesktop/DBus/Local</literal> is reserved;
+                    implementations should not send messages with this path,
+                    and the reference implementation of the bus daemon will
+                    disconnect any application that attempts to do so.
+                  </entry>
+                </row>
+                <row>
+                  <entry><literal>INTERFACE</literal></entry>
+                  <entry>2</entry>
+                  <entry><literal>STRING</literal></entry>
+                  <entry><literal>SIGNAL</literal></entry>
+                  <entry>
+                    The interface to invoke a method call on, or 
+                    that a signal is emitted from. Optional for 
+                    method calls, required for signals.
+                    The special interface
+                    <literal>org.freedesktop.DBus.Local</literal> is reserved;
+                    implementations should not send messages with this
+                    interface, and the reference implementation of the bus
+                    daemon will disconnect any application that attempts to
+                    do so.
+                  </entry>
+                </row>
+                <row>
+                  <entry><literal>MEMBER</literal></entry>
+                  <entry>3</entry>
+                  <entry><literal>STRING</literal></entry>
+                  <entry><literal>METHOD_CALL</literal>, <literal>SIGNAL</literal></entry>
+                  <entry>The member, either the method name or signal name.</entry>
+                </row>
+                <row>
+                  <entry><literal>ERROR_NAME</literal></entry>
+                  <entry>4</entry>
+                  <entry><literal>STRING</literal></entry>
+                  <entry><literal>ERROR</literal></entry>
+                  <entry>The name of the error that occurred, for errors</entry>
+                </row>
+                <row>
+                  <entry><literal>REPLY_SERIAL</literal></entry>
+                  <entry>5</entry>
+                  <entry><literal>UINT32</literal></entry>
+                  <entry><literal>ERROR</literal>, <literal>METHOD_RETURN</literal></entry>
+                  <entry>The serial number of the message this message is a reply
+                    to. (The serial number is the second <literal>UINT32</literal> in the header.)</entry>
+                </row>
+                <row>
+                  <entry><literal>DESTINATION</literal></entry>
+                  <entry>6</entry>
+                  <entry><literal>STRING</literal></entry>
+                  <entry>optional</entry>
+                  <entry>The name of the connection this message is intended for.
+                    Only used in combination with the message bus, see 
+                    <xref linkend="message-bus"/>.</entry>
+                </row>
+                <row>
+                  <entry><literal>SENDER</literal></entry>
+                  <entry>7</entry>
+                  <entry><literal>STRING</literal></entry>
+                  <entry>optional</entry>
+                  <entry>Unique name of the sending connection.
+                    The message bus fills in this field so it is reliable; the field is
+                    only meaningful in combination with the message bus.</entry>
+                </row>
+                <row>
+                  <entry><literal>SIGNATURE</literal></entry>
+                  <entry>8</entry>
+                  <entry><literal>SIGNATURE</literal></entry>
+                  <entry>optional</entry>
+                  <entry>The signature of the message body.
+                  If omitted, it is assumed to be the 
+                  empty signature "" (i.e. the body must be 0-length).</entry>
+                </row>
+                <row>
+                  <entry><literal>UNIX_FDS</literal></entry>
+                  <entry>9</entry>
+                  <entry><literal>UINT32</literal></entry>
+                  <entry>optional</entry>
+                  <entry>The number of Unix file descriptors that
+                  accompany the message.  If omitted, it is assumed
+                  that no Unix file descriptors accompany the
+                  message. The actual file descriptors need to be
+                  transferred via platform specific mechanism
+                  out-of-band. They must be sent at the same time as
+                  part of the message itself. They may not be sent
+                  before the first byte of the message itself is
+                  transferred or after the last byte of the message
+                  itself.</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+      </sect3>
+    </sect2>
+
+    <sect2 id="message-protocol-names">
+      <title>Valid Names</title>
+      <para>
+        The various names in D-Bus messages have some restrictions.
+      </para>
+      <para>
+        There is a <firstterm>maximum name length</firstterm> 
+        of 255 which applies to bus names, interfaces, and members. 
+      </para>
+      <sect3 id="message-protocol-names-interface">
+        <title>Interface names</title>
+        <para>
+          Interfaces have names with type <literal>STRING</literal>, meaning that 
+          they must be valid UTF-8. However, there are also some 
+          additional restrictions that apply to interface names 
+          specifically:
+          <itemizedlist>
+            <listitem><para>Interface names are composed of 1 or more elements separated by
+                a period ('.') character. All elements must contain at least 
+                one character.
+                </para>
+            </listitem>
+            <listitem><para>Each element must only contain the ASCII characters 
+                "[A-Z][a-z][0-9]_" and must not begin with a digit.
+                </para>
+            </listitem>
+
+	    <listitem><para>Interface names must contain at least one '.' (period)
+              character (and thus at least two elements).
+              </para></listitem>
+
+	    <listitem><para>Interface names must not begin with a '.' (period) character.</para></listitem>
+	    <listitem><para>Interface names must not exceed the maximum name length.</para></listitem>
+          </itemizedlist>
+        </para>
+
+        <para>
+          Interface names should start with the reversed DNS domain name of
+          the author of the interface (in lower-case), like interface names
+          in Java. It is conventional for the rest of the interface name
+          to consist of words run together, with initial capital letters
+          on all words ("CamelCase"). Several levels of hierarchy can be used.
+          It is also a good idea to include the major version of the interface
+          in the name, and increment it if incompatible changes are made;
+          this way, a single object can implement several versions of an
+          interface in parallel, if necessary.
+        </para>
+
+        <para>
+          For instance, if the owner of <literal>example.com</literal> is
+          developing a D-Bus API for a music player, they might define
+          interfaces called <literal>com.example.MusicPlayer1</literal>,
+          <literal>com.example.MusicPlayer1.Track</literal> and
+          <literal>com.example.MusicPlayer1.Seekable</literal>.
+        </para>
+
+        <para>
+          D-Bus does not distinguish between the concepts that would be
+          called classes and interfaces in Java: either can be identified on
+          D-Bus by an interface name.
+        </para>
+      </sect3>
+      <sect3 id="message-protocol-names-bus">
+        <title>Bus names</title>
+        <para>
+          Connections have one or more bus names associated with them.
+          A connection has exactly one bus name that is a <firstterm>unique
+            connection name</firstterm>. The unique connection name remains
+          with the connection for its entire lifetime.
+          A bus name is of type <literal>STRING</literal>,
+          meaning that it must be valid UTF-8. However, there are also
+          some additional restrictions that apply to bus names 
+          specifically:
+          <itemizedlist>
+            <listitem><para>Bus names that start with a colon (':')
+                character are unique connection names. Other bus names
+                are called <firstterm>well-known bus names</firstterm>.
+                </para>
+            </listitem>
+            <listitem><para>Bus names are composed of 1 or more elements separated by
+                a period ('.') character. All elements must contain at least 
+                one character.
+                </para>
+            </listitem>
+            <listitem><para>Each element must only contain the ASCII characters 
+                "[A-Z][a-z][0-9]_-". Only elements that are part of a unique
+                connection name may begin with a digit, elements in
+                other bus names must not begin with a digit.
+                </para>
+            </listitem>
+
+	    <listitem><para>Bus names must contain at least one '.' (period)
+              character (and thus at least two elements).
+              </para></listitem>
+
+	    <listitem><para>Bus names must not begin with a '.' (period) character.</para></listitem>
+	    <listitem><para>Bus names must not exceed the maximum name length.</para></listitem>
+          </itemizedlist>
+        </para>
+        <para>
+          Note that the hyphen ('-') character is allowed in bus names but
+          not in interface names.
+        </para>
+
+        <para>
+          Like <link linkend="message-protocol-names-interface">interface
+            names</link>, well-known bus names should start with the
+          reversed DNS domain name of the author of the interface (in
+          lower-case), and it is conventional for the rest of the well-known
+          bus name to consist of words run together, with initial
+          capital letters. As with interface names, including a version
+          number in well-known bus names is a good idea; it's possible to
+          have the well-known bus name for more than one version
+          simultaneously if backwards compatibility is required.
+        </para>
+
+        <para>
+          If a well-known bus name implies the presence of a "main" interface,
+          that "main" interface is often given the same name as
+          the well-known bus name, and situated at the corresponding object
+          path. For instance, if the owner of <literal>example.com</literal>
+          is developing a D-Bus API for a music player, they might define
+          that any application that takes the well-known name
+          <literal>com.example.MusicPlayer1</literal> should have an object
+          at the object path <literal>/com/example/MusicPlayer1</literal>
+          which implements the interface
+          <literal>com.example.MusicPlayer1</literal>.
+        </para>
+      </sect3>
+      <sect3 id="message-protocol-names-member">
+        <title>Member names</title>
+        <para>
+          Member (i.e. method or signal) names:
+          <itemizedlist>
+	    <listitem><para>Must only contain the ASCII characters
+                "[A-Z][a-z][0-9]_" and may not begin with a
+                digit.</para></listitem>
+	    <listitem><para>Must not contain the '.' (period) character.</para></listitem>
+	    <listitem><para>Must not exceed the maximum name length.</para></listitem>
+	    <listitem><para>Must be at least 1 byte in length.</para></listitem>
+          </itemizedlist>
+        </para>
+
+        <para>
+          It is conventional for member names on D-Bus to consist of
+          capitalized words with no punctuation ("camel-case").
+          Method names should usually be verbs, such as
+          <literal>GetItems</literal>, and signal names should usually be
+          a description of an event, such as <literal>ItemsChanged</literal>.
+        </para>
+      </sect3>
+      <sect3 id="message-protocol-names-error">
+        <title>Error names</title>
+        <para>
+          Error names have the same restrictions as interface names.
+        </para>
+
+        <para>
+          Error names have the same naming conventions as interface
+          names, and often contain <literal>.Error.</literal>; for instance,
+          the owner of <literal>example.com</literal> might define the
+          errors <literal>com.example.MusicPlayer.Error.FileNotFound</literal>
+          and <literal>com.example.MusicPlayer.Error.OutOfMemory</literal>.
+          The errors defined by D-Bus itself, such as
+          <literal>org.freedesktop.DBus.Error.Failed</literal>, follow a
+          similar pattern.
+        </para>
+      </sect3>
+    </sect2>
+
+    <sect2 id="message-protocol-types">
+      <title>Message Types</title>
+      <para>
+        Each of the message types (<literal>METHOD_CALL</literal>, <literal>METHOD_RETURN</literal>, <literal>ERROR</literal>, and
+        <literal>SIGNAL</literal>) has its own expected usage conventions and header fields.
+        This section describes these conventions.
+      </para>
+      <sect3 id="message-protocol-types-method">
+        <title>Method Calls</title>
+        <para>
+          Some messages invoke an operation on a remote object.  These are
+          called method call messages and have the type tag <literal>METHOD_CALL</literal>. Such
+          messages map naturally to methods on objects in a typical program.
+        </para>
+        <para>
+          A method call message is required to have a <literal>MEMBER</literal> header field
+          indicating the name of the method. Optionally, the message has an
+          <literal>INTERFACE</literal> field giving the interface the method is a part of. In the
+          absence of an <literal>INTERFACE</literal> field, if two interfaces on the same object have
+          a method with the same name, it is undefined which of the two methods
+          will be invoked. Implementations may also choose to return an error in
+          this ambiguous case. However, if a method name is unique
+          implementations must not require an interface field.
+        </para>
+        <para>
+          Method call messages also include a <literal>PATH</literal> field
+          indicating the object to invoke the method on. If the call is passing
+          through a message bus, the message will also have a
+          <literal>DESTINATION</literal> field giving the name of the connection
+          to receive the message.
+        </para>
+        <para>
+          When an application handles a method call message, it is required to
+          return a reply. The reply is identified by a <literal>REPLY_SERIAL</literal> header field
+          indicating the serial number of the <literal>METHOD_CALL</literal> being replied to. The
+          reply can have one of two types; either <literal>METHOD_RETURN</literal> or <literal>ERROR</literal>.
+        </para>
+        <para>
+          If the reply has type <literal>METHOD_RETURN</literal>, the arguments to the reply message 
+          are the return value(s) or "out parameters" of the method call. 
+          If the reply has type <literal>ERROR</literal>, then an "exception" has been thrown, 
+          and the call fails; no return value will be provided. It makes 
+          no sense to send multiple replies to the same method call.
+        </para>
+        <para>
+          Even if a method call has no return values, a <literal>METHOD_RETURN</literal> 
+          reply is required, so the caller will know the method 
+          was successfully processed.
+        </para>
+        <para>
+          The <literal>METHOD_RETURN</literal> or <literal>ERROR</literal> reply message must have the <literal>REPLY_SERIAL</literal> 
+          header field.
+        </para>
+        <para>
+          If a <literal>METHOD_CALL</literal> message has the flag <literal>NO_REPLY_EXPECTED</literal>, 
+          then as an optimization the application receiving the method 
+          call may choose to omit the reply message (regardless of 
+          whether the reply would have been <literal>METHOD_RETURN</literal> or <literal>ERROR</literal>). 
+          However, it is also acceptable to ignore the <literal>NO_REPLY_EXPECTED</literal>
+          flag and reply anyway.
+        </para>
+        <para>
+          Unless a message has the flag <literal>NO_AUTO_START</literal>, if the
+          destination name does not exist then a program to own the destination
+          name will be started before the message is delivered.  The message
+          will be held until the new program is successfully started or has
+          failed to start; in case of failure, an error will be returned. This
+          flag is only relevant in the context of a message bus, it is ignored
+          during one-to-one communication with no intermediate bus.
+        </para>
+        <sect4 id="message-protocol-types-method-apis">
+          <title>Mapping method calls to native APIs</title>
+          <para>
+            APIs for D-Bus may map method calls to a method call in a specific
+            programming language, such as C++, or may map a method call written
+            in an IDL to a D-Bus message.
+          </para>
+          <para>
+            In APIs of this nature, arguments to a method are often termed "in"
+            (which implies sent in the <literal>METHOD_CALL</literal>), or "out" (which implies
+            returned in the <literal>METHOD_RETURN</literal>). Some APIs such as CORBA also have
+            "inout" arguments, which are both sent and received, i.e. the caller
+            passes in a value which is modified. Mapped to D-Bus, an "inout"
+            argument is equivalent to an "in" argument, followed by an "out"
+            argument. You can't pass things "by reference" over the wire, so
+            "inout" is purely an illusion of the in-process API.
+          </para>
+          <para>
+            Given a method with zero or one return values, followed by zero or more
+            arguments, where each argument may be "in", "out", or "inout", the
+            caller constructs a message by appending each "in" or "inout" argument,
+            in order. "out" arguments are not represented in the caller's message.
+          </para>
+          <para>
+            The recipient constructs a reply by appending first the return value 
+            if any, then each "out" or "inout" argument, in order. 
+            "in" arguments are not represented in the reply message.
+          </para>
+          <para>
+            Error replies are normally mapped to exceptions in languages that have
+            exceptions.
+          </para>
+          <para>
+            In converting from native APIs to D-Bus, it is perhaps nice to 
+            map D-Bus naming conventions ("FooBar") to native conventions 
+            such as "fooBar" or "foo_bar" automatically. This is OK 
+            as long as you can say that the native API is one that 
+            was specifically written for D-Bus. It makes the most sense
+            when writing object implementations that will be exported 
+            over the bus. Object proxies used to invoke remote D-Bus 
+            objects probably need the ability to call any D-Bus method,
+            and thus a magic name mapping like this could be a problem.
+          </para>
+          <para>
+            This specification doesn't require anything of native API bindings;
+            the preceding is only a suggested convention for consistency 
+            among bindings.
+          </para>
+        </sect4>
+      </sect3>
+
+      <sect3 id="message-protocol-types-signal">
+        <title>Signal Emission</title>
+        <para>
+          Unlike method calls, signal emissions have no replies. 
+          A signal emission is simply a single message of type <literal>SIGNAL</literal>.
+          It must have three header fields: <literal>PATH</literal> giving the object 
+          the signal was emitted from, plus <literal>INTERFACE</literal> and <literal>MEMBER</literal> giving
+          the fully-qualified name of the signal. The <literal>INTERFACE</literal> header is required
+          for signals, though it is optional for method calls.
+        </para>
+      </sect3>
+
+      <sect3 id="message-protocol-types-errors">
+        <title>Errors</title>
+        <para>
+          Messages of type <literal>ERROR</literal> are most commonly replies 
+          to a <literal>METHOD_CALL</literal>, but may be returned in reply 
+          to any kind of message. The message bus for example
+          will return an <literal>ERROR</literal> in reply to a signal emission if 
+          the bus does not have enough memory to send the signal.
+        </para>
+        <para>
+          An <literal>ERROR</literal> may have any arguments, but if the first 
+          argument is a <literal>STRING</literal>, it must be an error message.
+          The error message may be logged or shown to the user
+          in some way.
+        </para>
+      </sect3>
+
+      <sect3 id="message-protocol-types-notation">
+        <title>Notation in this document</title>
+        <para>
+          This document uses a simple pseudo-IDL to describe particular method 
+          calls and signals. Here is an example of a method call:
+          <programlisting>
+            org.freedesktop.DBus.StartServiceByName (in STRING name, in UINT32 flags,
+                                                     out UINT32 resultcode)
+          </programlisting>
+          This means <literal>INTERFACE</literal> = org.freedesktop.DBus, <literal>MEMBER</literal> = StartServiceByName, 
+          <literal>METHOD_CALL</literal> arguments are <literal>STRING</literal> and <literal>UINT32</literal>, <literal>METHOD_RETURN</literal> argument
+          is <literal>UINT32</literal>. Remember that the <literal>MEMBER</literal> field can't contain any '.' (period)
+          characters so it's known that the last part of the name in
+          the "IDL" is the member name.
+        </para>
+        <para>
+          In C++ that might end up looking like this:
+          <programlisting>
+            unsigned int org::freedesktop::DBus::StartServiceByName (const char  *name,
+                                                                     unsigned int flags);
+          </programlisting>
+          or equally valid, the return value could be done as an argument:
+          <programlisting>
+            void org::freedesktop::DBus::StartServiceByName (const char   *name, 
+                                                             unsigned int  flags,
+                                                             unsigned int *resultcode);
+          </programlisting>
+          It's really up to the API designer how they want to make 
+          this look. You could design an API where the namespace wasn't used 
+          in C++, using STL or Qt, using varargs, or whatever you wanted.
+        </para>
+        <para>
+          Signals are written as follows:
+          <programlisting>
+            org.freedesktop.DBus.NameLost (STRING name)
+          </programlisting>
+          Signals don't specify "in" vs. "out" because only 
+          a single direction is possible.
+        </para>
+        <para>
+          It isn't especially encouraged to use this lame pseudo-IDL in actual
+          API implementations; you might use the native notation for the
+          language you're using, or you might use COM or CORBA IDL, for example.
+        </para>
+      </sect3>
+    </sect2>
+
+    <sect2 id="message-protocol-handling-invalid">
+      <title>Invalid Protocol and Spec Extensions</title>
+      
+      <para>
+        For security reasons, the D-Bus protocol should be strictly parsed and
+        validated, with the exception of defined extension points. Any invalid
+        protocol or spec violations should result in immediately dropping the
+        connection without notice to the other end. Exceptions should be
+        carefully considered, e.g. an exception may be warranted for a
+        well-understood idiosyncrasy of a widely-deployed implementation.  In
+        cases where the other end of a connection is 100% trusted and known to
+        be friendly, skipping validation for performance reasons could also make
+        sense in certain cases.
+      </para>
+
+      <para>
+        Generally speaking violations of the "must" requirements in this spec 
+        should be considered possible attempts to exploit security, and violations 
+        of the "should" suggestions should be considered legitimate (though perhaps
+        they should generate an error in some cases).
+      </para>
+
+      <para>
+        The following extension points are built in to D-Bus on purpose and must
+        not be treated as invalid protocol. The extension points are intended
+        for use by future versions of this spec, they are not intended for third
+        parties.  At the moment, the only way a third party could extend D-Bus
+        without breaking interoperability would be to introduce a way to negotiate new
+        feature support as part of the auth protocol, using EXTENSION_-prefixed
+        commands. There is not yet a standard way to negotiate features.
+        <itemizedlist>
+          <listitem>
+            <para>
+              In the authentication protocol (see <xref linkend="auth-protocol"/>) unknown 
+                commands result in an ERROR rather than a disconnect. This enables 
+                future extensions to the protocol. Commands starting with EXTENSION_ are 
+                reserved for third parties.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The authentication protocol supports pluggable auth mechanisms.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The address format (see <xref linkend="addresses"/>) supports new
+              kinds of transport.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Messages with an unknown type (something other than
+              <literal>METHOD_CALL</literal>, <literal>METHOD_RETURN</literal>,
+              <literal>ERROR</literal>, <literal>SIGNAL</literal>) are ignored. 
+              Unknown-type messages must still be well-formed in the same way 
+              as the known messages, however. They still have the normal 
+              header and body.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Header fields with an unknown or unexpected field code must be ignored, 
+              though again they must still be well-formed.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              New standard interfaces (with new methods and signals) can of course be added.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+
+    </sect2>
+
+  </sect1>
+
+  <sect1 id="auth-protocol">
+    <title>Authentication Protocol</title>
+    <para>
+      Before the flow of messages begins, two applications must
+      authenticate. A simple plain-text protocol is used for
+      authentication; this protocol is a SASL profile, and maps fairly
+      directly from the SASL specification. The message encoding is
+      NOT used here, only plain text messages.
+    </para>
+    <para>
+      In examples, "C:" and "S:" indicate lines sent by the client and
+      server respectively.
+    </para>
+    <sect2 id="auth-protocol-overview">
+      <title>Protocol Overview</title>
+      <para>
+        The protocol is a line-based protocol, where each line ends with
+        \r\n. Each line begins with an all-caps ASCII command name containing
+        only the character range [A-Z_], a space, then any arguments for the
+        command, then the \r\n ending the line. The protocol is
+        case-sensitive. All bytes must be in the ASCII character set.
+
+        Commands from the client to the server are as follows:
+
+        <itemizedlist>
+	  <listitem><para>AUTH [mechanism] [initial-response]</para></listitem>
+	  <listitem><para>CANCEL</para></listitem>
+	  <listitem><para>BEGIN</para></listitem>
+	  <listitem><para>DATA &lt;data in hex encoding&gt;</para></listitem>
+	  <listitem><para>ERROR [human-readable error explanation]</para></listitem>
+	  <listitem><para>NEGOTIATE_UNIX_FD</para></listitem>
+	</itemizedlist>
+
+        From server to client are as follows:
+
+        <itemizedlist>
+	  <listitem><para>REJECTED &lt;space-separated list of mechanism names&gt;</para></listitem>
+	  <listitem><para>OK &lt;GUID in hex&gt;</para></listitem>
+	  <listitem><para>DATA &lt;data in hex encoding&gt;</para></listitem>
+	  <listitem><para>ERROR</para></listitem>
+	  <listitem><para>AGREE_UNIX_FD</para></listitem>
+	</itemizedlist>
+      </para>
+      <para>
+        Unofficial extensions to the command set must begin with the letters 
+        "EXTENSION_", to avoid conflicts with future official commands.
+        For example, "EXTENSION_COM_MYDOMAIN_DO_STUFF".
+      </para>
+    </sect2>
+    <sect2 id="auth-nul-byte">
+      <title>Special credentials-passing nul byte</title>
+      <para>
+        Immediately after connecting to the server, the client must send a
+        single nul byte. This byte may be accompanied by credentials
+        information on some operating systems that use sendmsg() with
+        SCM_CREDS or SCM_CREDENTIALS to pass credentials over UNIX domain
+        sockets. However, the nul byte must be sent even on other kinds of
+        socket, and even on operating systems that do not require a byte to be
+        sent in order to transmit credentials. The text protocol described in
+        this document begins after the single nul byte. If the first byte
+        received from the client is not a nul byte, the server may disconnect 
+        that client.
+      </para>
+      <para>
+        A nul byte in any context other than the initial byte is an error; 
+        the protocol is ASCII-only.
+      </para>
+      <para>
+        The credentials sent along with the nul byte may be used with the 
+        SASL mechanism EXTERNAL.
+      </para>
+    </sect2>
+    <sect2 id="auth-command-auth">
+      <title>AUTH command</title>
+      <para>
+        If an AUTH command has no arguments, it is a request to list
+        available mechanisms. The server must respond with a REJECTED
+        command listing the mechanisms it understands, or with an error.
+      </para>
+      <para>
+        If an AUTH command specifies a mechanism, and the server supports
+        said mechanism, the server should begin exchanging SASL
+        challenge-response data with the client using DATA commands.
+      </para>
+      <para>
+        If the server does not support the mechanism given in the AUTH
+        command, it must send either a REJECTED command listing the mechanisms
+        it does support, or an error.
+      </para>
+      <para>
+        If the [initial-response] argument is provided, it is intended for use
+        with mechanisms that have no initial challenge (or an empty initial
+        challenge), as if it were the argument to an initial DATA command. If
+        the selected mechanism has an initial challenge and [initial-response]
+        was provided, the server should reject authentication by sending
+        REJECTED.
+      </para>
+      <para>
+        If authentication succeeds after exchanging DATA commands, 
+        an OK command must be sent to the client.
+      </para>
+      <para>
+        The first octet received by the server after the \r\n of the BEGIN
+        command from the client must be the first octet of the
+        authenticated/encrypted stream of D-Bus messages.
+      </para>
+      <para>
+        If BEGIN is received by the server, the first octet received
+        by the client after the \r\n of the OK command must be the
+        first octet of the authenticated/encrypted stream of D-Bus
+        messages.
+      </para>
+    </sect2>
+    <sect2 id="auth-command-cancel">
+      <title>CANCEL Command</title>
+      <para>
+        At any time up to sending the BEGIN command, the client may send a
+        CANCEL command. On receiving the CANCEL command, the server must
+        send a REJECTED command and abort the current authentication
+        exchange.
+      </para>
+    </sect2>
+    <sect2 id="auth-command-data">
+      <title>DATA Command</title>
+      <para>
+        The DATA command may come from either client or server, and simply 
+        contains a hex-encoded block of data to be interpreted 
+        according to the SASL mechanism in use.
+      </para>
+      <para>
+        Some SASL mechanisms support sending an "empty string"; 
+        FIXME we need some way to do this.
+      </para>
+    </sect2>
+    <sect2 id="auth-command-begin">
+      <title>BEGIN Command</title>
+      <para>
+        The BEGIN command acknowledges that the client has received an 
+        OK command from the server, and that the stream of messages
+        is about to begin. 
+      </para>
+      <para>
+        The first octet received by the server after the \r\n of the BEGIN
+        command from the client must be the first octet of the
+        authenticated/encrypted stream of D-Bus messages.
+      </para>
+    </sect2>
+    <sect2 id="auth-command-rejected">
+      <title>REJECTED Command</title>
+      <para>
+        The REJECTED command indicates that the current authentication
+        exchange has failed, and further exchange of DATA is inappropriate.
+        The client would normally try another mechanism, or try providing
+        different responses to challenges.
+      </para><para>
+        Optionally, the REJECTED command has a space-separated list of
+        available auth mechanisms as arguments. If a server ever provides
+        a list of supported mechanisms, it must provide the same list 
+        each time it sends a REJECTED message. Clients are free to 
+        ignore all lists received after the first.
+      </para>
+    </sect2>
+    <sect2 id="auth-command-ok">
+      <title>OK Command</title>
+      <para>
+        The OK command indicates that the client has been
+        authenticated. The client may now proceed with negotiating
+        Unix file descriptor passing. To do that it shall send
+        NEGOTIATE_UNIX_FD to the server.
+      </para>
+      <para>
+        Otherwise, the client must respond to the OK command by
+        sending a BEGIN command, followed by its stream of messages,
+        or by disconnecting.  The server must not accept additional
+        commands using this protocol after the BEGIN command has been
+        received. Further communication will be a stream of D-Bus
+        messages (optionally encrypted, as negotiated) rather than
+        this protocol.
+      </para>
+      <para>
+        If a client sends BEGIN the first octet received by the client
+        after the \r\n of the OK command must be the first octet of
+        the authenticated/encrypted stream of D-Bus messages.
+      </para>
+      <para>
+        The OK command has one argument, which is the GUID of the server.
+        See <xref linkend="addresses"/> for more on server GUIDs.
+      </para>
+    </sect2>
+    <sect2 id="auth-command-error">
+      <title>ERROR Command</title>
+      <para>
+        The ERROR command indicates that either server or client did not
+        know a command, does not accept the given command in the current
+        context, or did not understand the arguments to the command. This
+        allows the protocol to be extended; a client or server can send a
+        command present or permitted only in new protocol versions, and if
+        an ERROR is received instead of an appropriate response, fall back
+        to using some other technique.
+      </para>
+      <para>
+        If an ERROR is sent, the server or client that sent the
+        error must continue as if the command causing the ERROR had never been
+        received. However, the the server or client receiving the error 
+        should try something other than whatever caused the error; 
+        if only canceling/rejecting the authentication.
+      </para>
+      <para>
+        If the D-Bus protocol changes incompatibly at some future time,
+        applications implementing the new protocol would probably be able to
+        check for support of the new protocol by sending a new command and
+        receiving an ERROR from applications that don't understand it. Thus the
+        ERROR feature of the auth protocol is an escape hatch that lets us
+        negotiate extensions or changes to the D-Bus protocol in the future.
+      </para>
+    </sect2>
+    <sect2 id="auth-command-negotiate-unix-fd">
+      <title>NEGOTIATE_UNIX_FD Command</title>
+      <para>
+        The NEGOTIATE_UNIX_FD command indicates that the client
+        supports Unix file descriptor passing. This command may only
+        be sent after the connection is authenticated, i.e. after OK
+        was received by the client. This command may only be sent on
+        transports that support Unix file descriptor passing.
+      </para>
+      <para>
+        On receiving NEGOTIATE_UNIX_FD the server must respond with
+        either AGREE_UNIX_FD or ERROR. It shall respond the former if
+        the transport chosen supports Unix file descriptor passing and
+        the server supports this feature. It shall respond the latter
+        if the transport does not support Unix file descriptor
+        passing, the server does not support this feature, or the
+        server decides not to enable file descriptor passing due to
+        security or other reasons.
+      </para>
+    </sect2>
+    <sect2 id="auth-command-agree-unix-fd">
+      <title>AGREE_UNIX_FD Command</title>
+      <para>
+        The AGREE_UNIX_FD command indicates that the server supports
+        Unix file descriptor passing. This command may only be sent
+        after the connection is authenticated, and the client sent
+        NEGOTIATE_UNIX_FD to enable Unix file descriptor passing. This
+        command may only be sent on transports that support Unix file
+        descriptor passing.
+      </para>
+      <para>
+        On receiving AGREE_UNIX_FD the client must respond with BEGIN,
+        followed by its stream of messages, or by disconnecting.  The
+        server must not accept additional commands using this protocol
+        after the BEGIN command has been received. Further
+        communication will be a stream of D-Bus messages (optionally
+        encrypted, as negotiated) rather than this protocol.
+      </para>
+    </sect2>
+    <sect2 id="auth-command-future">
+      <title>Future Extensions</title>
+      <para>
+        Future extensions to the authentication and negotiation
+        protocol are possible. For that new commands may be
+        introduced. If a client or server receives an unknown command
+        it shall respond with ERROR and not consider this fatal. New
+        commands may be introduced both before, and after
+        authentication, i.e. both before and after the OK command.
+      </para>
+    </sect2>
+    <sect2 id="auth-examples">
+      <title>Authentication examples</title>
+      
+      <para>
+        <figure>
+	  <title>Example of successful magic cookie authentication</title>
+	  <programlisting>
+            (MAGIC_COOKIE is a made up mechanism)
+
+            C: AUTH MAGIC_COOKIE 3138363935333137393635383634
+            S: OK 1234deadbeef
+            C: BEGIN
+          </programlisting>
+	</figure>
+        <figure>
+	  <title>Example of finding out mechanisms then picking one</title>
+	  <programlisting>
+            C: AUTH
+            S: REJECTED KERBEROS_V4 SKEY
+            C: AUTH SKEY 7ab83f32ee
+            S: DATA 8799cabb2ea93e
+            C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f
+            S: OK 1234deadbeef
+            C: BEGIN
+          </programlisting>
+	</figure>
+        <figure>
+	  <title>Example of client sends unknown command then falls back to regular auth</title>
+	  <programlisting>
+            C: FOOBAR
+            S: ERROR
+            C: AUTH MAGIC_COOKIE 3736343435313230333039
+            S: OK 1234deadbeef
+            C: BEGIN
+          </programlisting>
+	</figure>
+        <figure>
+	  <title>Example of server doesn't support initial auth mechanism</title>
+	  <programlisting>
+            C: AUTH MAGIC_COOKIE 3736343435313230333039
+            S: REJECTED KERBEROS_V4 SKEY
+            C: AUTH SKEY 7ab83f32ee
+            S: DATA 8799cabb2ea93e
+            C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f
+            S: OK 1234deadbeef
+            C: BEGIN
+          </programlisting>
+	</figure>
+        <figure>
+	  <title>Example of wrong password or the like followed by successful retry</title>
+	  <programlisting>
+            C: AUTH MAGIC_COOKIE 3736343435313230333039
+            S: REJECTED KERBEROS_V4 SKEY
+            C: AUTH SKEY 7ab83f32ee
+            S: DATA 8799cabb2ea93e
+            C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f
+            S: REJECTED
+            C: AUTH SKEY 7ab83f32ee
+            S: DATA 8799cabb2ea93e
+            C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f
+            S: OK 1234deadbeef
+            C: BEGIN
+          </programlisting>
+	</figure>
+        <figure>
+	  <title>Example of skey cancelled and restarted</title>
+	  <programlisting>
+            C: AUTH MAGIC_COOKIE 3736343435313230333039
+            S: REJECTED KERBEROS_V4 SKEY
+            C: AUTH SKEY 7ab83f32ee
+            S: DATA 8799cabb2ea93e
+            C: CANCEL
+            S: REJECTED
+            C: AUTH SKEY 7ab83f32ee
+            S: DATA 8799cabb2ea93e
+            C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f
+            S: OK 1234deadbeef
+            C: BEGIN
+          </programlisting>
+	</figure>
+        <figure>
+	  <title>Example of successful magic cookie authentication with successful negotiation of Unix FD passing</title>
+	  <programlisting>
+            (MAGIC_COOKIE is a made up mechanism)
+
+            C: AUTH MAGIC_COOKIE 3138363935333137393635383634
+            S: OK 1234deadbeef
+            C: NEGOTIATE_UNIX_FD
+            S: AGREE_UNIX_FD
+            C: BEGIN
+          </programlisting>
+	</figure>
+        <figure>
+	  <title>Example of successful magic cookie authentication with unsuccessful negotiation of Unix FD passing</title>
+	  <programlisting>
+            (MAGIC_COOKIE is a made up mechanism)
+
+            C: AUTH MAGIC_COOKIE 3138363935333137393635383634
+            S: OK 1234deadbeef
+            C: NEGOTIATE_UNIX_FD
+            S: ERROR
+            C: BEGIN
+          </programlisting>
+	</figure>
+      </para>
+    </sect2>
+    <sect2 id="auth-states">
+      <title>Authentication state diagrams</title>
+      
+      <para>
+        This section documents the auth protocol in terms of 
+        a state machine for the client and the server. This is 
+        probably the most robust way to implement the protocol.
+      </para>
+
+      <sect3 id="auth-states-client">
+        <title>Client states</title>
+        
+        <para>
+          To more precisely describe the interaction between the
+          protocol state machine and the authentication mechanisms the
+          following notation is used: MECH(CHALL) means that the
+          server challenge CHALL was fed to the mechanism MECH, which
+          returns one of
+
+          <itemizedlist>
+            <listitem>
+              <para>
+                CONTINUE(RESP) means continue the auth conversation
+                and send RESP as the response to the server;
+              </para>
+            </listitem>
+
+            <listitem>
+              <para>
+                OK(RESP) means that after sending RESP to the server
+                the client side of the auth conversation is finished
+                and the server should return "OK";
+              </para>
+            </listitem>
+
+            <listitem>
+              <para>
+                ERROR means that CHALL was invalid and could not be
+                processed.
+              </para>
+            </listitem>
+          </itemizedlist>
+          
+          Both RESP and CHALL may be empty.
+        </para>
+        
+        <para>
+          The Client starts by getting an initial response from the
+          default mechanism and sends AUTH MECH RESP, or AUTH MECH if
+          the mechanism did not provide an initial response.  If the
+          mechanism returns CONTINUE, the client starts in state
+          <emphasis>WaitingForData</emphasis>, if the mechanism
+          returns OK the client starts in state
+          <emphasis>WaitingForOK</emphasis>.
+        </para>
+        
+        <para>
+          The client should keep track of available mechanisms and
+          which it mechanisms it has already attempted. This list is
+          used to decide which AUTH command to send. When the list is
+          exhausted, the client should give up and close the
+          connection.
+        </para>
+
+        <formalpara>
+          <title><emphasis>WaitingForData</emphasis></title>
+          <para>
+            <itemizedlist>
+              <listitem>
+                <para>
+                  Receive DATA CHALL
+                  <simplelist>
+                    <member>
+                      MECH(CHALL) returns CONTINUE(RESP) &rarr; send
+                      DATA RESP, goto
+                      <emphasis>WaitingForData</emphasis>
+                    </member>
+
+                    <member>
+                      MECH(CHALL) returns OK(RESP) &rarr; send DATA
+                      RESP, goto <emphasis>WaitingForOK</emphasis>
+                    </member>
+
+                    <member>
+                      MECH(CHALL) returns ERROR &rarr; send ERROR
+                      [msg], goto <emphasis>WaitingForData</emphasis>
+                    </member>
+                  </simplelist>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive REJECTED [mechs] &rarr;
+                  send AUTH [next mech], goto
+                  WaitingForData or <emphasis>WaitingForOK</emphasis>
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  Receive ERROR &rarr; send
+                  CANCEL, goto
+                  <emphasis>WaitingForReject</emphasis>
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  Receive OK &rarr; send
+                  BEGIN, terminate auth
+                  conversation, authenticated
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  Receive anything else &rarr; send
+                  ERROR, goto
+                  <emphasis>WaitingForData</emphasis>
+                </para>
+              </listitem>
+            </itemizedlist>
+          </para>
+        </formalpara>
+
+        <formalpara>
+          <title><emphasis>WaitingForOK</emphasis></title>
+          <para>
+            <itemizedlist>
+              <listitem>
+                <para>
+                  Receive OK &rarr; send BEGIN, terminate auth
+                  conversation, <emphasis>authenticated</emphasis>
+                </para>
+              </listitem>
+              <listitem>
+                <para>
+                  Receive REJECT [mechs] &rarr; send AUTH [next mech],
+                  goto <emphasis>WaitingForData</emphasis> or
+                  <emphasis>WaitingForOK</emphasis>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive DATA &rarr; send CANCEL, goto
+                  <emphasis>WaitingForReject</emphasis>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive ERROR &rarr; send CANCEL, goto
+                  <emphasis>WaitingForReject</emphasis>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive anything else &rarr; send ERROR, goto
+                  <emphasis>WaitingForOK</emphasis>
+                </para>
+              </listitem>
+            </itemizedlist>
+          </para>
+        </formalpara>
+
+        <formalpara>
+          <title><emphasis>WaitingForReject</emphasis></title>
+          <para>
+            <itemizedlist>
+              <listitem>
+                <para>
+                  Receive REJECT [mechs] &rarr; send AUTH [next mech],
+                  goto <emphasis>WaitingForData</emphasis> or
+                  <emphasis>WaitingForOK</emphasis>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive anything else &rarr; terminate auth
+                  conversation, disconnect
+                </para>
+              </listitem>
+            </itemizedlist>
+          </para>
+        </formalpara>
+
+      </sect3>
+
+      <sect3 id="auth-states-server">
+        <title>Server states</title>
+ 
+        <para>
+          For the server MECH(RESP) means that the client response
+          RESP was fed to the the mechanism MECH, which returns one of
+
+          <itemizedlist>
+            <listitem>
+              <para>
+                CONTINUE(CHALL) means continue the auth conversation and
+                send CHALL as the challenge to the client;
+              </para>
+            </listitem>
+
+            <listitem>
+              <para>
+                OK means that the client has been successfully
+                authenticated;
+              </para>
+            </listitem>
+
+            <listitem>
+              <para>
+                REJECT means that the client failed to authenticate or
+                there was an error in RESP.
+              </para>
+            </listitem>
+          </itemizedlist>
+
+          The server starts out in state
+          <emphasis>WaitingForAuth</emphasis>.  If the client is
+          rejected too many times the server must disconnect the
+          client.
+        </para>
+
+        <formalpara>
+          <title><emphasis>WaitingForAuth</emphasis></title>
+          <para>
+            <itemizedlist>
+
+              <listitem>
+                <para>
+                  Receive AUTH &rarr; send REJECTED [mechs], goto
+                  <emphasis>WaitingForAuth</emphasis>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive AUTH MECH RESP
+
+                  <simplelist>
+                    <member>
+                      MECH not valid mechanism &rarr; send REJECTED
+                      [mechs], goto
+                      <emphasis>WaitingForAuth</emphasis>
+                    </member>
+
+                    <member>
+                      MECH(RESP) returns CONTINUE(CHALL) &rarr; send
+                      DATA CHALL, goto
+                      <emphasis>WaitingForData</emphasis>
+                    </member>
+
+                    <member>
+                      MECH(RESP) returns OK &rarr; send OK, goto
+                      <emphasis>WaitingForBegin</emphasis>
+                    </member>
+
+                    <member>
+                      MECH(RESP) returns REJECT &rarr; send REJECTED
+                      [mechs], goto
+                      <emphasis>WaitingForAuth</emphasis>
+                    </member>
+                  </simplelist>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive BEGIN &rarr; terminate
+                  auth conversation, disconnect
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive ERROR &rarr; send REJECTED [mechs], goto
+                  <emphasis>WaitingForAuth</emphasis>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive anything else &rarr; send
+                  ERROR, goto
+                  <emphasis>WaitingForAuth</emphasis>
+                </para>
+              </listitem>
+            </itemizedlist>
+          </para>
+        </formalpara>
+
+       
+        <formalpara>
+          <title><emphasis>WaitingForData</emphasis></title>
+          <para>
+            <itemizedlist>
+              <listitem>
+                <para>
+                  Receive DATA RESP
+                  <simplelist>
+                    <member>
+                      MECH(RESP) returns CONTINUE(CHALL) &rarr; send
+                      DATA CHALL, goto
+                      <emphasis>WaitingForData</emphasis>
+                    </member>
+
+                    <member>
+                      MECH(RESP) returns OK &rarr; send OK, goto
+                      <emphasis>WaitingForBegin</emphasis>
+                    </member>
+
+                    <member>
+                      MECH(RESP) returns REJECT &rarr; send REJECTED
+                      [mechs], goto
+                      <emphasis>WaitingForAuth</emphasis>
+                    </member>
+                  </simplelist>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive BEGIN &rarr; terminate auth conversation,
+                  disconnect
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive CANCEL &rarr; send REJECTED [mechs], goto
+                  <emphasis>WaitingForAuth</emphasis>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive ERROR &rarr; send REJECTED [mechs], goto
+                  <emphasis>WaitingForAuth</emphasis>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive anything else &rarr; send ERROR, goto
+                  <emphasis>WaitingForData</emphasis>
+                </para>
+              </listitem>
+            </itemizedlist>
+          </para>
+        </formalpara>
+
+        <formalpara>
+          <title><emphasis>WaitingForBegin</emphasis></title>
+          <para>
+            <itemizedlist>
+              <listitem>
+                <para>
+                  Receive BEGIN &rarr; terminate auth conversation,
+                  client authenticated
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive CANCEL &rarr; send REJECTED [mechs], goto
+                  <emphasis>WaitingForAuth</emphasis>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive ERROR &rarr; send REJECTED [mechs], goto
+                  <emphasis>WaitingForAuth</emphasis>
+                </para>
+              </listitem>
+
+              <listitem>
+                <para>
+                  Receive anything else &rarr; send ERROR, goto
+                  <emphasis>WaitingForBegin</emphasis>
+                </para>
+              </listitem>
+            </itemizedlist>
+          </para>
+        </formalpara>
+
+      </sect3>
+      
+    </sect2>
+    <sect2 id="auth-mechanisms">
+      <title>Authentication mechanisms</title>
+      <para>
+        This section describes some new authentication mechanisms.
+        D-Bus also allows any standard SASL mechanism of course.
+      </para>
+      <sect3 id="auth-mechanisms-sha">
+        <title>DBUS_COOKIE_SHA1</title>
+        <para>
+          The DBUS_COOKIE_SHA1 mechanism is designed to establish that a client
+          has the ability to read a private file owned by the user being
+          authenticated. If the client can prove that it has access to a secret
+          cookie stored in this file, then the client is authenticated. 
+          Thus the security of DBUS_COOKIE_SHA1 depends on a secure home 
+          directory.
+        </para>
+        <para>
+          Throughout this description, "hex encoding" must output the digits
+          from a to f in lower-case; the digits A to F must not be used
+          in the DBUS_COOKIE_SHA1 mechanism.
+        </para>
+        <para>
+          Authentication proceeds as follows:
+          <itemizedlist>
+            <listitem>
+              <para>
+                The client sends the username it would like to authenticate 
+                as, hex-encoded.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The server sends the name of its "cookie context" (see below); a
+                space character; the integer ID of the secret cookie the client
+                must demonstrate knowledge of; a space character; then a
+                randomly-generated challenge string, all of this hex-encoded into
+                one, single string.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The client locates the cookie and generates its own
+                randomly-generated challenge string. The client then concatenates
+                the server's decoded challenge, a ":" character, its own challenge,
+                another ":" character, and the cookie. It computes the SHA-1 hash
+                of this composite string as a hex digest. It concatenates the
+                client's challenge string, a space character, and the SHA-1 hex
+                digest, hex-encodes the result and sends it back to the server.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The server generates the same concatenated string used by the
+                client and computes its SHA-1 hash. It compares the hash with
+                the hash received from the client; if the two hashes match, the
+                client is authenticated.
+              </para>
+            </listitem>
+          </itemizedlist>
+        </para>
+        <para>
+          Each server has a "cookie context," which is a name that identifies a
+          set of cookies that apply to that server. A sample context might be
+          "org_freedesktop_session_bus". Context names must be valid ASCII,
+          nonzero length, and may not contain the characters slash ("/"),
+          backslash ("\"), space (" "), newline ("\n"), carriage return ("\r"),
+          tab ("\t"), or period ("."). There is a default context,
+          "org_freedesktop_general" that's used by servers that do not specify
+          otherwise.
+        </para>
+        <para>
+          Cookies are stored in a user's home directory, in the directory
+          <filename>~/.dbus-keyrings/</filename>. This directory must 
+          not be readable or writable by other users. If it is, 
+          clients and servers must ignore it. The directory 
+          contains cookie files named after the cookie context.
+        </para>
+        <para>
+          A cookie file contains one cookie per line. Each line 
+          has three space-separated fields:
+          <itemizedlist>
+            <listitem>
+              <para>
+                The cookie ID number, which must be a non-negative integer and
+                may not be used twice in the same file.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The cookie's creation time, in UNIX seconds-since-the-epoch
+                format.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The cookie itself, a hex-encoded random block of bytes. The cookie
+                may be of any length, though obviously security increases 
+                as the length increases.
+              </para>
+            </listitem>
+          </itemizedlist>
+        </para>
+        <para>
+          Only server processes modify the cookie file.
+          They must do so with this procedure:
+          <itemizedlist>
+            <listitem>
+              <para>
+                Create a lockfile name by appending ".lock" to the name of the
+                cookie file.  The server should attempt to create this file
+                using <literal>O_CREAT | O_EXCL</literal>.  If file creation
+                fails, the lock fails. Servers should retry for a reasonable
+                period of time, then they may choose to delete an existing lock
+                to keep users from having to manually delete a stale
+                lock. <footnote><para>Lockfiles are used instead of real file
+                locking <literal>fcntl()</literal> because real locking
+                implementations are still flaky on network
+                filesystems.</para></footnote>
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                Once the lockfile has been created, the server loads the cookie
+                file. It should then delete any cookies that are old (the
+                timeout can be fairly short), or more than a reasonable
+                time in the future (so that cookies never accidentally 
+                become permanent, if the clock was set far into the future 
+                at some point). If no recent keys remain, the 
+                server may generate a new key.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The pruned and possibly added-to cookie file 
+                must be resaved atomically (using a temporary 
+                file which is rename()'d).
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                The lock must be dropped by deleting the lockfile.
+              </para>
+            </listitem>
+          </itemizedlist>
+        </para>
+        <para>
+          Clients need not lock the file in order to load it, 
+          because servers are required to save the file atomically.          
+        </para>
+      </sect3>
+    </sect2>
+  </sect1>
+  <sect1 id="addresses">
+    <title>Server Addresses</title>
+    <para>
+      Server addresses consist of a transport name followed by a colon, and
+      then an optional, comma-separated list of keys and values in the form key=value.
+      Each value is escaped.
+    </para>
+    <para>
+      For example: 
+      <programlisting>unix:path=/tmp/dbus-test</programlisting>
+      Which is the address to a unix socket with the path /tmp/dbus-test.
+    </para>
+    <para>
+      Value escaping is similar to URI escaping but simpler.
+      <itemizedlist>
+        <listitem>
+          <para>
+            The set of optionally-escaped bytes is:
+            <literal>[0-9A-Za-z_-/.\]</literal>. To escape, each
+            <emphasis>byte</emphasis> (note, not character) which is not in the
+            set of optionally-escaped bytes must be replaced with an ASCII
+            percent (<literal>%</literal>) and the value of the byte in hex.
+            The hex value must always be two digits, even if the first digit is
+            zero. The optionally-escaped bytes may be escaped if desired.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            To unescape, append each byte in the value; if a byte is an ASCII
+            percent (<literal>%</literal>) character then append the following
+            hex value instead. It is an error if a <literal>%</literal> byte
+            does not have two hex digits following. It is an error if a
+            non-optionally-escaped byte is seen unescaped.
+          </para>
+        </listitem>
+      </itemizedlist>
+      The set of optionally-escaped bytes is intended to preserve address 
+      readability and convenience.
+    </para>
+
+    <para>
+      A server may specify a key-value pair with the key <literal>guid</literal>
+      and the value a hex-encoded 16-byte sequence. <xref linkend="uuids"/>
+      describes the format of the <literal>guid</literal> field.  If present,
+      this UUID may be used to distinguish one server address from another. A
+      server should use a different UUID for each address it listens on. For
+      example, if a message bus daemon offers both UNIX domain socket and TCP
+      connections, but treats clients the same regardless of how they connect,
+      those two connections are equivalent post-connection but should have
+      distinct UUIDs to distinguish the kinds of connection.
+    </para>
+    
+    <para>
+      The intent of the address UUID feature is to allow a client to avoid
+      opening multiple identical connections to the same server, by allowing the
+      client to check whether an address corresponds to an already-existing
+      connection.  Comparing two addresses is insufficient, because addresses
+      can be recycled by distinct servers, and equivalent addresses may look
+      different if simply compared as strings (for example, the host in a TCP
+      address can be given as an IP address or as a hostname).
+    </para>
+
+    <para>
+      Note that the address key is <literal>guid</literal> even though the 
+      rest of the API and documentation says "UUID," for historical reasons.
+    </para>
+
+    <para>
+      [FIXME clarify if attempting to connect to each is a requirement 
+      or just a suggestion]
+      When connecting to a server, multiple server addresses can be
+      separated by a semi-colon. The library will then try to connect
+      to the first address and if that fails, it'll try to connect to
+      the next one specified, and so forth. For example
+      <programlisting>unix:path=/tmp/dbus-test;unix:path=/tmp/dbus-test2</programlisting>
+    </para>
+
+  </sect1>
+  
+  <sect1 id="transports">
+    <title>Transports</title>
+    <para>
+      [FIXME we need to specify in detail each transport and its possible arguments]
+    
+      Current transports include: unix domain sockets (including 
+      abstract namespace on linux), launchd, systemd, TCP/IP, an executed subprocess and a debug/testing transport
+      using in-process pipes. Future possible transports include one that
+      tunnels over X11 protocol.
+    </para>
+  
+    <sect2 id="transports-unix-domain-sockets">
+      <title>Unix Domain Sockets</title>
+      <para>
+        Unix domain sockets can be either paths in the file system or on Linux 
+	kernels, they can be abstract which are similar to paths but
+	do not show up in the file system.  
+      </para>
+
+      <para>
+        When a socket is opened by the D-Bus library it truncates the path 
+	name right before the first trailing Nul byte.  This is true for both
+	normal paths and abstract paths.  Note that this is a departure from
+	previous versions of D-Bus that would create sockets with a fixed 
+	length path name.  Names which were shorter than the fixed length
+	would be padded by Nul bytes.
+      </para>
+      <para>
+        Unix domain sockets are not available on Windows.
+      </para>
+      <sect3 id="transports-unix-domain-sockets-addresses">
+        <title>Server Address Format</title>
+        <para> 
+          Unix domain socket addresses are identified by the "unix:" prefix 
+          and support the following key/value pairs:
+        </para>
+        <informaltable>
+         <tgroup cols="3">
+          <thead>
+           <row>
+            <entry>Name</entry>
+            <entry>Values</entry>
+            <entry>Description</entry>
+           </row>
+          </thead>
+          <tbody>
+           <row>
+            <entry>path</entry>
+            <entry>(path)</entry>
+            <entry>path of the unix domain socket. If set, the "tmpdir" and "abstract" key must not be set.</entry>
+          </row>
+          <row>
+            <entry>tmpdir</entry>
+            <entry>(path)</entry>
+            <entry>temporary directory in which a socket file with a random file name starting with 'dbus-' will be created by the server. This key can only be used in server addresses, not in client addresses. If set, the "path" and "abstract" key must not be set.</entry>
+          </row>
+          <row>
+            <entry>abstract</entry>
+            <entry>(string)</entry>
+            <entry>unique string (path) in the abstract namespace. If set, the "path" or "tempdir" key must not be set.</entry>
+          </row>
+        </tbody>
+        </tgroup>
+       </informaltable>
+      </sect3>
+    </sect2>
+    <sect2 id="transports-launchd">
+      <title>launchd</title>
+      <para>
+        launchd is an open-source server management system that replaces init, inetd
+        and cron on Apple Mac OS X versions 10.4 and above. It provides a common session
+        bus address for each user and deprecates the X11-enabled D-Bus launcher on OSX.
+      </para>
+
+      <para>
+        launchd allocates a socket and provides it with the unix path through the
+        DBUS_LAUNCHD_SESSION_BUS_SOCKET variable in launchd's environment. Every process
+        spawned by launchd (or dbus-daemon, if it was started by launchd) can access
+        it through its environment.
+        Other processes can query for the launchd socket by executing:
+        $ launchctl getenv DBUS_LAUNCHD_SESSION_BUS_SOCKET
+        This is normally done by the D-Bus client library so doesn't have to be done
+        manually.
+      </para>
+      <para>
+        launchd is not available on Microsoft Windows.
+      </para>
+      <sect3 id="transports-launchd-addresses">
+        <title>Server Address Format</title>
+        <para>
+          launchd addresses are identified by the "launchd:" prefix
+          and support the following key/value pairs:
+        </para>
+        <informaltable>
+         <tgroup cols="3">
+          <thead>
+           <row>
+            <entry>Name</entry>
+            <entry>Values</entry>
+            <entry>Description</entry>
+           </row>
+          </thead>
+          <tbody>
+           <row>
+            <entry>env</entry>
+            <entry>(environment variable)</entry>
+            <entry>path of the unix domain socket for the launchd created dbus-daemon.</entry>
+          </row>
+        </tbody>
+        </tgroup>
+       </informaltable>
+      </sect3>
+    </sect2>
+    <sect2 id="transports-systemd">
+      <title>systemd</title>
+      <para>
+        systemd is an open-source server management system that
+        replaces init and inetd on newer Linux systems. It supports
+        socket activation. The D-Bus systemd transport is used to acquire
+        socket activation file descriptors from systemd and use them
+        as D-Bus transport when the current process is spawned by
+        socket activation from it.
+      </para>
+      <para>
+        The systemd transport accepts only one or more Unix domain or
+        TCP streams sockets passed in via socket activation.
+      </para>
+      <para>
+        The systemd transport is not available on non-Linux operating systems.
+      </para>
+      <para>
+        The systemd transport defines no parameter keys.
+      </para>
+    </sect2>
+    <sect2 id="transports-tcp-sockets">
+      <title>TCP Sockets</title>
+      <para>
+        The tcp transport provides TCP/IP based connections between clients
+        located on the same or different hosts. 
+      </para>
+      <para>
+        Using tcp transport without any additional secure authentification mechanismus 
+        over a network is unsecure. 
+      </para>
+      <para>  
+        Windows notes: Because of the tcp stack on Windows does not provide sending
+        credentials over a tcp connection, the EXTERNAL authentification 
+        mechanismus does not work. 
+      </para>
+      <sect3 id="transports-tcp-sockets-addresses">
+        <title>Server Address Format</title>
+        <para> 
+         TCP/IP socket addresses are identified by the "tcp:" prefix 
+         and support the following key/value pairs:
+        </para>
+        <informaltable>
+         <tgroup cols="3">
+          <thead>
+           <row>
+            <entry>Name</entry>
+            <entry>Values</entry>
+            <entry>Description</entry>
+           </row>
+          </thead>
+          <tbody>
+           <row>
+            <entry>host</entry>
+            <entry>(string)</entry>
+            <entry>dns name or ip address</entry>
+          </row>
+          <row>
+           <entry>port</entry>
+           <entry>(number)</entry>
+           <entry>The tcp port the server will open. A zero value let the server 
+            choose a free port provided from the underlaying operating system. 
+            libdbus is able to retrieve the real used port from the server.  
+           </entry>
+          </row>
+          <row>
+           <entry>family</entry>
+           <entry>(string)</entry>
+           <entry>If set, provide the type of socket family either "ipv4" or "ipv6". If unset, the family is unspecified.</entry>
+          </row>
+         </tbody>
+        </tgroup>
+       </informaltable>
+      </sect3>
+    </sect2>
+    <sect2 id="transports-nonce-tcp-sockets">
+      <title>Nonce-secured TCP Sockets</title>
+      <para>
+        The nonce-tcp transport provides a secured TCP transport, using a
+        simple authentication mechanism to ensure that only clients with read
+        access to a certain location in the filesystem can connect to the server.
+        The server writes a secret, the nonce, to a file and an incoming client
+        connection is only accepted if the client sends the nonce right after
+        the connect. The nonce mechanism requires no setup and is orthogonal to
+        the higher-level authentication mechanisms described in the
+        Authentication section.
+      </para>
+
+      <para>
+        On start, the server generates a random 16 byte nonce and writes it
+        to a file in the user's temporary directory. The nonce file location
+        is published as part of the server's D-Bus address using the
+        "noncefile" key-value pair.
+
+        After an accept, the server reads 16 bytes from the socket. If the
+        read bytes do not match the nonce stored in the nonce file, the
+        server MUST immediately drop the connection.
+        If the nonce match the received byte sequence, the client is accepted
+        and the transport behaves like an unsecured tcp transport.
+      </para>
+      <para>
+        After a successful connect to the server socket, the client MUST read
+        the nonce from the file published by the server via the noncefile=
+        key-value pair and send it over the socket. After that, the
+        transport behaves like an unsecured tcp transport.
+      </para>
+      <sect3 id="transports-nonce-tcp-sockets-addresses">
+        <title>Server Address Format</title>
+        <para> 
+         Nonce TCP/IP socket addresses uses the "nonce-tcp:" prefix 
+         and support the following key/value pairs:
+        </para>
+        <informaltable>
+         <tgroup cols="3">
+          <thead>
+           <row>
+            <entry>Name</entry>
+            <entry>Values</entry>
+            <entry>Description</entry>
+           </row>
+          </thead>
+          <tbody>
+           <row>
+            <entry>host</entry>
+            <entry>(string)</entry>
+            <entry>dns name or ip address</entry>
+          </row>
+          <row>
+           <entry>port</entry>
+           <entry>(number)</entry>
+           <entry>The tcp port the server will open. A zero value let the server 
+            choose a free port provided from the underlaying operating system. 
+            libdbus is able to retrieve the real used port from the server.  
+           </entry>
+          </row>
+          <row>
+           <entry>family</entry>
+           <entry>(string)</entry>
+           <entry>If set, provide the type of socket family either "ipv4" or "ipv6". If unset, the family is unspecified.</entry>
+          </row>
+          <row>
+           <entry>noncefile</entry>
+           <entry>(path)</entry>
+           <entry>file location containing the secret</entry>
+          </row>
+         </tbody>
+        </tgroup>
+       </informaltable>
+      </sect3>
+    </sect2>
+    <sect2 id="transports-exec">
+      <title>Executed Subprocesses on Unix</title>
+      <para>
+        This transport forks off a process and connects its standard
+        input and standard output with an anonymous Unix domain
+        socket. This socket is then used for communication by the
+        transport. This transport may be used to use out-of-process
+        forwarder programs as basis for the D-Bus protocol.
+      </para>
+      <para>
+        The forked process will inherit the standard error output and
+        process group from the parent process.
+      </para>
+      <para>
+        Executed subprocesses are not available on Windows.
+      </para>
+      <sect3 id="transports-exec-addresses">
+        <title>Server Address Format</title>
+        <para>
+          Executed subprocess addresses are identified by the "unixexec:" prefix
+          and support the following key/value pairs:
+        </para>
+        <informaltable>
+         <tgroup cols="3">
+          <thead>
+           <row>
+            <entry>Name</entry>
+            <entry>Values</entry>
+            <entry>Description</entry>
+           </row>
+          </thead>
+          <tbody>
+           <row>
+            <entry>path</entry>
+            <entry>(path)</entry>
+            <entry>Path of the binary to execute, either an absolute
+            path or a binary name that is searched for in the default
+            search path of the OS. This corresponds to the first
+            argument of execlp(). This key is mandatory.</entry>
+          </row>
+          <row>
+            <entry>argv0</entry>
+            <entry>(string)</entry>
+            <entry>The program name to use when executing the
+            binary. If omitted the same value as specified for path=
+            will be used. This corresponds to the second argument of
+            execlp().</entry>
+          </row>
+          <row>
+            <entry>argv1, argv2, ...</entry>
+            <entry>(string)</entry>
+            <entry>Arguments to pass to the binary. This corresponds
+            to the third and later arguments of execlp(). If a
+            specific argvX is not specified no further argvY for Y > X
+            are taken into account.</entry>
+          </row>
+        </tbody>
+        </tgroup>
+       </informaltable>
+      </sect3>
+    </sect2>
+   </sect1>
+   <sect1 id="meta-transports">
+    <title>Meta Transports</title>
+    <para>
+      Meta transports are a kind of transport with special enhancements or
+      behavior. Currently available meta transports include: autolaunch
+    </para>
+
+    <sect2 id="meta-transports-autolaunch">
+     <title>Autolaunch</title>
+     <para>The autolaunch transport provides a way for dbus clients to autodetect
+       a running dbus session bus and to autolaunch a session bus if not present.
+     </para>
+     <sect3 id="meta-transports-autolaunch-addresses">
+       <title>Server Address Format</title>
+       <para>
+         Autolaunch addresses uses the "autolaunch:" prefix and support the
+         following key/value pairs:
+       </para>
+       <informaltable>
+        <tgroup cols="3">
+         <thead>
+          <row>
+           <entry>Name</entry>
+           <entry>Values</entry>
+           <entry>Description</entry>
+          </row>
+         </thead>
+         <tbody>
+          <row>
+           <entry>scope</entry>
+           <entry>(string)</entry>
+           <entry>scope of autolaunch (Windows only)
+            <itemizedlist>
+             <listitem>
+              <para>
+               "*install-path" - limit session bus to dbus installation path.
+               The dbus installation path is determined from the location of
+               the shared dbus library. If the library is located in a 'bin'
+               subdirectory the installation root is the directory above,
+               otherwise the directory where the library lives is taken as
+               installation root.
+               <programlisting>
+                   &lt;install-root&gt;/bin/[lib]dbus-1.dll
+                   &lt;install-root&gt;/[lib]dbus-1.dll
+               </programlisting>
+              </para>
+             </listitem>
+             <listitem>
+              <para>
+               "*user" - limit session bus to the recent user.
+              </para>
+             </listitem>
+             <listitem>
+              <para>
+               other values - specify dedicated session bus like "release",
+               "debug" or other
+              </para>
+             </listitem>
+            </itemizedlist>
+           </entry>
+         </row>
+        </tbody>
+       </tgroup>
+      </informaltable>
+     </sect3>
+
+     <sect3 id="meta-transports-autolaunch-windows-implementation">
+      <title>Windows implementation</title>
+      <para>
+        On start, the server opens a platform specific transport, creates a mutex
+        and a shared memory section containing the related session bus address.
+        This mutex will be inspected by the dbus client library to detect a
+        running dbus session bus. The access to the mutex and the shared memory
+        section are protected by global locks.
+      </para>
+      <para>
+       In the recent implementation the autolaunch transport uses a tcp transport
+       on localhost with a port choosen from the operating system. This detail may
+       change in the future.
+      </para>
+      <para>
+        Disclaimer: The recent implementation is in an early state and may not
+        work in all cirumstances and/or may have security issues. Because of this
+        the implementation is not documentated yet.
+      </para>
+     </sect3>
+    </sect2>
+   </sect1>
+
+  <sect1 id="uuids">
+    <title>UUIDs</title>
+    <para>
+      A working D-Bus implementation uses universally-unique IDs in two places.
+      First, each server address has a UUID identifying the address, 
+      as described in <xref linkend="addresses"/>. Second, each operating
+      system kernel instance running a D-Bus client or server has a UUID
+      identifying that kernel, retrieved by invoking the method
+      org.freedesktop.DBus.Peer.GetMachineId() (see <xref
+      linkend="standard-interfaces-peer"/>).
+    </para>
+    <para>
+      The term "UUID" in this document is intended literally, i.e. an
+      identifier that is universally unique. It is not intended to refer to
+      RFC4122, and in fact the D-Bus UUID is not compatible with that RFC.
+    </para>
+    <para>
+      The UUID must contain 128 bits of data and be hex-encoded.  The
+      hex-encoded string may not contain hyphens or other non-hex-digit
+      characters, and it must be exactly 32 characters long.  To generate a
+      UUID, the current reference implementation concatenates 96 bits of random
+      data followed by the 32-bit time in seconds since the UNIX epoch (in big
+      endian byte order).
+    </para>
+    <para>
+      It would also be acceptable and probably better to simply generate 128
+      bits of random data, as long as the random number generator is of high
+      quality. The timestamp could conceivably help if the random bits are not
+      very random. With a quality random number generator, collisions are
+      extremely unlikely even with only 96 bits, so it's somewhat academic.
+    </para>
+    <para>
+      Implementations should, however, stick to random data for the first 96 bits
+      of the UUID.
+    </para>
+  </sect1>
+    
+  <sect1 id="standard-interfaces">
+    <title>Standard Interfaces</title>
+    <para>
+      See <xref linkend="message-protocol-types-notation"/> for details on 
+       the notation used in this section. There are some standard interfaces
+      that may be useful across various D-Bus applications.
+    </para>
+    <sect2 id="standard-interfaces-peer">
+      <title><literal>org.freedesktop.DBus.Peer</literal></title>
+      <para>
+        The <literal>org.freedesktop.DBus.Peer</literal> interface 
+        has two methods:
+        <programlisting>
+          org.freedesktop.DBus.Peer.Ping ()
+          org.freedesktop.DBus.Peer.GetMachineId (out STRING machine_uuid)
+        </programlisting>
+      </para>
+      <para>
+        On receipt of the <literal>METHOD_CALL</literal> message
+        <literal>org.freedesktop.DBus.Peer.Ping</literal>, an application should do
+        nothing other than reply with a <literal>METHOD_RETURN</literal> as
+        usual.  It does not matter which object path a ping is sent to.  The
+        reference implementation handles this method automatically.
+      </para>
+      <para>
+        On receipt of the <literal>METHOD_CALL</literal> message
+        <literal>org.freedesktop.DBus.Peer.GetMachineId</literal>, an application should 
+        reply with a <literal>METHOD_RETURN</literal> containing a hex-encoded 
+        UUID representing the identity of the machine the process is running on.
+        This UUID must be the same for all processes on a single system at least
+        until that system next reboots. It should be the same across reboots 
+        if possible, but this is not always possible to implement and is not 
+        guaranteed.
+        It does not matter which object path a GetMachineId is sent to.  The
+        reference implementation handles this method automatically.
+      </para>
+      <para>
+        The UUID is intended to be per-instance-of-the-operating-system, so may represent
+        a virtual machine running on a hypervisor, rather than a physical machine.
+        Basically if two processes see the same UUID, they should also see the same
+        shared memory, UNIX domain sockets, process IDs, and other features that require 
+        a running OS kernel in common between the processes.
+      </para>
+      <para>
+        The UUID is often used where other programs might use a hostname. Hostnames 
+        can change without rebooting, however, or just be "localhost" - so the UUID
+        is more robust.
+      </para>
+      <para>
+        <xref linkend="uuids"/> explains the format of the UUID.
+      </para>
+    </sect2>
+
+    <sect2 id="standard-interfaces-introspectable">
+      <title><literal>org.freedesktop.DBus.Introspectable</literal></title>
+      <para>
+        This interface has one method:
+        <programlisting>
+          org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data)
+        </programlisting>
+      </para>
+      <para>
+        Objects instances may implement
+        <literal>Introspect</literal> which returns an XML description of
+        the object, including its interfaces (with signals and methods), objects
+        below it in the object path tree, and its properties.
+      </para>
+      <para>
+        <xref linkend="introspection-format"/> describes the format of this XML string.
+      </para>
+    </sect2>
+    <sect2 id="standard-interfaces-properties">
+      <title><literal>org.freedesktop.DBus.Properties</literal></title>
+      <para>
+        Many native APIs will have a concept of object <firstterm>properties</firstterm> 
+        or <firstterm>attributes</firstterm>. These can be exposed via the 
+        <literal>org.freedesktop.DBus.Properties</literal> interface.
+      </para>
+      <para>
+        <programlisting>
+              org.freedesktop.DBus.Properties.Get (in STRING interface_name,
+                                                   in STRING property_name,
+                                                   out VARIANT value);
+              org.freedesktop.DBus.Properties.Set (in STRING interface_name,
+                                                   in STRING property_name,
+                                                   in VARIANT value);
+              org.freedesktop.DBus.Properties.GetAll (in STRING interface_name,
+                                                      out DICT&lt;STRING,VARIANT&gt; props);
+        </programlisting>
+      </para>
+      <para>
+        It is conventional to give D-Bus properties names consisting of
+        capitalized words without punctuation ("CamelCase"), like
+        <link linkend="message-protocol-names-member">member names</link>.
+        For instance, the GObject property
+        <literal>connection-status</literal> or the Qt property
+        <literal>connectionStatus</literal> could be represented on D-Bus
+        as <literal>ConnectionStatus</literal>.
+      </para>
+      <para>
+        Strictly speaking, D-Bus property names are not required to follow
+        the same naming restrictions as member names, but D-Bus property
+        names that would not be valid member names (in particular,
+        GObject-style dash-separated property names) can cause interoperability
+        problems and should be avoided.
+      </para>
+      <para>
+        The available properties and whether they are writable can be determined
+        by calling <literal>org.freedesktop.DBus.Introspectable.Introspect</literal>,
+        see <xref linkend="standard-interfaces-introspectable"/>.
+      </para>
+      <para>
+        An empty string may be provided for the interface name; in this case, 
+        if there are multiple properties on an object with the same name, 
+        the results are undefined (picking one by according to an arbitrary 
+        deterministic rule, or returning an error, are the reasonable 
+        possibilities).
+      </para>
+      <para>
+        If one or more properties change on an object, the
+        <literal>org.freedesktop.DBus.Properties.PropertiesChanged</literal>
+        signal may be emitted (this signal was added in 0.14):
+      </para>
+      <para>
+        <programlisting>
+              org.freedesktop.DBus.Properties.PropertiesChanged (STRING interface_name,
+                                                                 DICT&lt;STRING,VARIANT&gt; changed_properties,
+                                                                 ARRAY&lt;STRING&gt; invalidated_properties);
+        </programlisting>
+      </para>
+      <para>
+        where <literal>changed_properties</literal> is a dictionary
+        containing the changed properties with the new values and
+        <literal>invalidated_properties</literal> is an array of
+        properties that changed but the value is not conveyed.
+      </para>
+      <para>
+        Whether the <literal>PropertiesChanged</literal> signal is
+        supported can be determined by calling
+        <literal>org.freedesktop.DBus.Introspectable.Introspect</literal>. Note
+        that the signal may be supported for an object but it may
+        differ how whether and how it is used on a per-property basis
+        (for e.g. performance or security reasons). Each property (or
+        the parent interface) must be annotated with the
+        <literal>org.freedesktop.DBus.Property.EmitsChangedSignal</literal>
+        annotation to convey this (usually the default value
+        <literal>true</literal> is sufficient meaning that the
+        annotation does not need to be used). See <xref
+        linkend="introspection-format"/> for details on this
+        annotation.
+      </para>
+    </sect2>
+
+    <sect2 id="standard-interfaces-objectmanager">
+      <title><literal>org.freedesktop.DBus.ObjectManager</literal></title>
+      <para>
+        An API can optionally make use of this interface for one or
+        more sub-trees of objects. The root of each sub-tree implements
+        this interface so other applications can get all objects,
+        interfaces and properties in a single method call.  It is
+        appropriate to use this interface if users of the tree of
+        objects are expected to be interested in all interfaces of all
+        objects in the tree; a more granular API should be used if
+        users of the objects are expected to be interested in a small
+        subset of the objects, a small subset of their interfaces, or
+        both.
+      </para>
+      <para>
+        The method that applications can use to get all objects and
+        properties is <literal>GetManagedObjects</literal>:
+      </para>
+      <para>
+        <programlisting>
+          org.freedesktop.DBus.ObjectManager.GetManagedObjects (out DICT&lt;OBJPATH,DICT&lt;STRING,DICT&lt;STRING,VARIANT&gt;&gt;&gt; objpath_interfaces_and_properties);
+        </programlisting>
+      </para>
+      <para>
+        The return value of this method is a dict whose keys are
+        object paths. All returned object paths are children of the
+        object path implementing this interface, i.e. their object
+        paths start with the ObjectManager's object path plus '/'.
+      </para>
+      <para>
+        Each value is a dict whose keys are interfaces names.  Each
+        value in this inner dict is the same dict that would be
+        returned by the <link
+        linkend="standard-interfaces-properties">org.freedesktop.DBus.Properties.GetAll()</link>
+        method for that combination of object path and interface. If
+        an interface has no properties, the empty dict is returned.
+      </para>
+      <para>
+        Changes are emitted using the following two signals:
+      </para>
+      <para>
+        <programlisting>
+          org.freedesktop.DBus.ObjectManager.InterfacesAdded (OBJPATH object_path,
+                                                              DICT&lt;STRING,DICT&lt;STRING,VARIANT&gt;&gt; interfaces_and_properties);
+          org.freedesktop.DBus.ObjectManager.InterfacesRemoved (OBJPATH object_path,
+                                                                ARRAY&lt;STRING&gt; interfaces);
+        </programlisting>
+      </para>
+      <para>
+        The <literal>InterfacesAdded</literal> signal is emitted when
+        either a new object is added or when an existing object gains
+        one or more interfaces. The
+        <literal>InterfacesRemoved</literal> signal is emitted
+        whenever an object is removed or it loses one or more
+        interfaces. The second parameter of the
+        <literal>InterfacesAdded</literal> signal contains a dict with
+        the interfaces and properties (if any) that have been added to
+        the given object path. Similarly, the second parameter of the
+        <literal>InterfacesRemoved</literal> signal contains an array
+        of the interfaces that were removed. Note that changes on
+        properties on existing interfaces are not reported using this
+        interface - an application should also monitor the existing <link
+        linkend="standard-interfaces-properties">PropertiesChanged</link>
+        signal on each object.
+      </para>
+      <para>
+        Applications SHOULD NOT export objects that are children of an
+        object (directly or otherwise) implementing this interface but
+        which are not returned in the reply from the
+        <literal>GetManagedObjects()</literal> method of this
+        interface on the given object.
+      </para>
+      <para>
+        The intent of the <literal>ObjectManager</literal> interface
+        is to make it easy to write a robust client
+        implementation. The trivial client implementation only needs
+        to make two method calls:
+      </para>
+      <para>
+        <programlisting>
+          org.freedesktop.DBus.AddMatch (bus_proxy,
+                                         "type='signal',name='org.example.App',path_namespace='/org/example/App'");
+          objects = org.freedesktop.DBus.ObjectManager.GetManagedObjects (app_proxy);
+        </programlisting>
+      </para>
+      <para>
+        on the message bus and the remote application's
+        <literal>ObjectManager</literal>, respectively. Whenever a new
+        remote object is created (or an existing object gains a new
+        interface), the <literal>InterfacesAdded</literal> signal is
+        emitted, and since this signal contains all properties for the
+        interfaces, no calls to the
+        <literal>org.freedesktop.Properties</literal> interface on the
+        remote object are needed. Additionally, since the initial
+        <literal>AddMatch()</literal> rule already includes signal
+        messages from the newly created child object, no new
+        <literal>AddMatch()</literal> call is needed.
+      </para>
+
+      <para>
+        <emphasis>
+          The <literal>org.freedesktop.DBus.ObjectManager</literal>
+          interface was added in version 0.17 of the D-Bus
+          specification.
+        </emphasis>
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="introspection-format">
+    <title>Introspection Data Format</title>
+    <para>
+      As described in <xref linkend="standard-interfaces-introspectable"/>, 
+      objects may be introspected at runtime, returning an XML string 
+      that describes the object. The same XML format may be used in 
+      other contexts as well, for example as an "IDL" for generating 
+      static language bindings.
+    </para>
+    <para>
+      Here is an example of introspection data:
+      <programlisting>
+        &lt;!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+         "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"&gt;
+        &lt;node name="/org/freedesktop/sample_object"&gt;
+          &lt;interface name="org.freedesktop.SampleInterface"&gt;
+            &lt;method name="Frobate"&gt;
+              &lt;arg name="foo" type="i" direction="in"/&gt;
+              &lt;arg name="bar" type="s" direction="out"/&gt;
+              &lt;arg name="baz" type="a{us}" direction="out"/&gt;
+              &lt;annotation name="org.freedesktop.DBus.Deprecated" value="true"/&gt;
+            &lt;/method&gt;
+            &lt;method name="Bazify"&gt;
+              &lt;arg name="bar" type="(iiu)" direction="in"/&gt;
+              &lt;arg name="bar" type="v" direction="out"/&gt;
+            &lt;/method&gt;
+            &lt;method name="Mogrify"&gt;
+              &lt;arg name="bar" type="(iiav)" direction="in"/&gt;
+            &lt;/method&gt;
+            &lt;signal name="Changed"&gt;
+              &lt;arg name="new_value" type="b"/&gt;
+            &lt;/signal&gt;
+            &lt;property name="Bar" type="y" access="readwrite"/&gt;
+          &lt;/interface&gt;
+          &lt;node name="child_of_sample_object"/&gt;
+          &lt;node name="another_child_of_sample_object"/&gt;
+       &lt;/node&gt;
+      </programlisting>
+    </para>
+    <para>
+      A more formal DTD and spec needs writing, but here are some quick notes.
+      <itemizedlist>
+        <listitem>
+          <para>
+            Only the root &lt;node&gt; element can omit the node name, as it's
+            known to be the object that was introspected.  If the root
+            &lt;node&gt; does have a name attribute, it must be an absolute
+            object path. If child &lt;node&gt; have object paths, they must be
+            relative.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            If a child &lt;node&gt; has any sub-elements, then they 
+            must represent a complete introspection of the child.
+            If a child &lt;node&gt; is empty, then it may or may 
+            not have sub-elements; the child must be introspected
+            in order to find out. The intent is that if an object 
+            knows that its children are "fast" to introspect
+            it can go ahead and return their information, but 
+            otherwise it can omit it.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            The direction element on &lt;arg&gt; may be omitted, 
+            in which case it defaults to "in" for method calls 
+            and "out" for signals. Signals only allow "out" 
+            so while direction may be specified, it's pointless.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            The possible directions are "in" and "out", 
+            unlike CORBA there is no "inout"
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            The possible property access flags are 
+            "readwrite", "read", and "write"
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            Multiple interfaces can of course be listed for 
+            one &lt;node&gt;.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            The "name" attribute on arguments is optional.
+          </para>
+        </listitem>
+      </itemizedlist>
+    </para>
+    <para>
+        Method, interface, property, and signal elements may have
+        "annotations", which are generic key/value pairs of metadata.
+	They are similar conceptually to Java's annotations and C# attributes.
+        Well-known annotations:
+     </para>
+     <informaltable>
+       <tgroup cols="3">
+	 <thead>
+	   <row>
+	     <entry>Name</entry>
+	     <entry>Values (separated by ,)</entry>
+	     <entry>Description</entry>
+	   </row>
+	 </thead>
+	 <tbody>
+	   <row>
+	     <entry>org.freedesktop.DBus.Deprecated</entry>
+	     <entry>true,false</entry>
+	     <entry>Whether or not the entity is deprecated; defaults to false</entry>
+	   </row>
+	   <row>
+	     <entry>org.freedesktop.DBus.GLib.CSymbol</entry>
+	     <entry>(string)</entry>
+	     <entry>The C symbol; may be used for methods and interfaces</entry>
+	   </row>
+	   <row>
+	     <entry>org.freedesktop.DBus.Method.NoReply</entry>
+	     <entry>true,false</entry>
+	     <entry>If set, don't expect a reply to the method call; defaults to false.</entry>
+	   </row>
+	   <row>
+	     <entry>org.freedesktop.DBus.Property.EmitsChangedSignal</entry>
+	     <entry>true,invalidates,false</entry>
+	     <entry>
+               <para>
+                 If set to <literal>false</literal>, the
+                 <literal>org.freedesktop.DBus.Properties.PropertiesChanged</literal>
+                 signal, see <xref
+                 linkend="standard-interfaces-properties"/> is not
+                 guaranteed to be emitted if the property changes.
+               </para>
+               <para>
+                 If set to <literal>invalidates</literal> the signal
+                 is emitted but the value is not included in the
+                 signal.
+               </para>
+               <para>
+                 If set to <literal>true</literal> the signal is
+                 emitted with the value included.
+               </para>
+               <para>
+                 The value for the annotation defaults to
+                 <literal>true</literal> if the enclosing interface
+                 element does not specify the annotation. Otherwise it
+                 defaults to the value specified in the enclosing
+                 interface element.
+               </para>
+             </entry>
+	   </row>
+	 </tbody>
+       </tgroup>
+     </informaltable>
+  </sect1>
+  <sect1 id="message-bus">
+    <title>Message Bus Specification</title>
+    <sect2 id="message-bus-overview">
+      <title>Message Bus Overview</title>
+      <para>
+        The message bus accepts connections from one or more applications. 
+        Once connected, applications can exchange messages with other 
+        applications that are also connected to the bus.
+      </para>
+      <para>
+        In order to route messages among connections, the message bus keeps a
+        mapping from names to connections. Each connection has one
+        unique-for-the-lifetime-of-the-bus name automatically assigned.
+        Applications may request additional names for a connection. Additional
+        names are usually "well-known names" such as
+        "org.freedesktop.TextEditor". When a name is bound to a connection,
+        that connection is said to <firstterm>own</firstterm> the name.
+      </para>
+      <para>
+        The bus itself owns a special name, <literal>org.freedesktop.DBus</literal>. 
+        This name routes messages to the bus, allowing applications to make 
+        administrative requests. For example, applications can ask the bus 
+        to assign a name to a connection.
+      </para>
+      <para>
+        Each name may have <firstterm>queued owners</firstterm>.  When an
+        application requests a name for a connection and the name is already in
+        use, the bus will optionally add the connection to a queue waiting for 
+        the name. If the current owner of the name disconnects or releases
+        the name, the next connection in the queue will become the new owner.
+      </para>
+
+      <para>
+        This feature causes the right thing to happen if you start two text
+        editors for example; the first one may request "org.freedesktop.TextEditor", 
+        and the second will be queued as a possible owner of that name. When 
+        the first exits, the second will take over.
+      </para>
+
+      <para>
+        Applications may send <firstterm>unicast messages</firstterm> to
+        a specific recipient or to the message bus itself, or
+        <firstterm>broadcast messages</firstterm> to all interested recipients.
+        See <xref linkend="message-bus-routing"/> for details.
+      </para>
+    </sect2>
+
+    <sect2 id="message-bus-names">
+      <title>Message Bus Names</title>
+      <para>
+        Each connection has at least one name, assigned at connection time and
+        returned in response to the
+        <literal>org.freedesktop.DBus.Hello</literal> method call.  This
+        automatically-assigned name is called the connection's <firstterm>unique
+        name</firstterm>.  Unique names are never reused for two different
+        connections to the same bus.
+      </para>
+      <para>
+        Ownership of a unique name is a prerequisite for interaction with 
+        the message bus. It logically follows that the unique name is always 
+        the first name that an application comes to own, and the last 
+        one that it loses ownership of.
+      </para>
+      <para>
+        Unique connection names must begin with the character ':' (ASCII colon
+        character); bus names that are not unique names must not begin
+        with this character. (The bus must reject any attempt by an application
+        to manually request a name beginning with ':'.) This restriction
+        categorically prevents "spoofing"; messages sent to a unique name
+        will always go to the expected connection.
+      </para>
+      <para>
+        When a connection is closed, all the names that it owns are deleted (or
+        transferred to the next connection in the queue if any).
+      </para>
+      <para>
+        A connection can request additional names to be associated with it using
+        the <literal>org.freedesktop.DBus.RequestName</literal> message. <xref
+        linkend="message-protocol-names-bus"/> describes the format of a valid
+        name. These names can be released again using the
+        <literal>org.freedesktop.DBus.ReleaseName</literal> message.
+      </para>
+
+      <sect3 id="bus-messages-request-name">
+        <title><literal>org.freedesktop.DBus.RequestName</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            UINT32 RequestName (in STRING name, in UINT32 flags)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Name to request</entry>
+                </row>
+	        <row>
+		  <entry>1</entry>
+		  <entry>UINT32</entry>
+		  <entry>Flags</entry>
+	        </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+          Reply arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>UINT32</entry>
+                  <entry>Return value</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+        <para>
+          This method call should be sent to
+          <literal>org.freedesktop.DBus</literal> and asks the message bus to
+          assign the given name to the method caller. Each name maintains a
+          queue of possible owners, where the head of the queue is the primary
+          or current owner of the name. Each potential owner in the queue
+          maintains the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and
+          DBUS_NAME_FLAG_DO_NOT_QUEUE settings from its latest RequestName
+          call.  When RequestName is invoked the following occurs:
+          <itemizedlist>
+            <listitem>
+              <para>
+                If the method caller is currently the primary owner of the name,
+                the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and DBUS_NAME_FLAG_DO_NOT_QUEUE
+                values are updated with the values from the new RequestName call, 
+                and nothing further happens.
+              </para>
+            </listitem>
+
+            <listitem>
+              <para>
+                If the current primary owner (head of the queue) has
+                DBUS_NAME_FLAG_ALLOW_REPLACEMENT set, and the RequestName
+                invocation has the DBUS_NAME_FLAG_REPLACE_EXISTING flag, then
+                the caller of RequestName replaces the current primary owner at
+                the head of the queue and the current primary owner moves to the
+                second position in the queue. If the caller of RequestName was 
+                in the queue previously its flags are updated with the values from 
+                the new RequestName in addition to moving it to the head of the queue.
+              </para>
+            </listitem>
+
+            <listitem>
+              <para>
+                If replacement is not possible, and the method caller is
+                currently in the queue but not the primary owner, its flags are
+                updated with the values from the new RequestName call.
+              </para>
+            </listitem>
+
+            <listitem>
+              <para>
+                If replacement is not possible, and the method caller is
+                currently not in the queue, the method caller is appended to the
+                queue.
+              </para>
+            </listitem>
+
+            <listitem>
+              <para>
+                If any connection in the queue has DBUS_NAME_FLAG_DO_NOT_QUEUE
+                set and is not the primary owner, it is removed from the
+                queue. This can apply to the previous primary owner (if it
+                was replaced) or the method caller (if it updated the
+                DBUS_NAME_FLAG_DO_NOT_QUEUE flag while still stuck in the
+                queue, or if it was just added to the queue with that flag set).
+              </para>
+            </listitem>
+          </itemizedlist>
+        </para>
+        <para>
+          Note that DBUS_NAME_FLAG_REPLACE_EXISTING results in "jumping the
+          queue," even if another application already in the queue had specified
+          DBUS_NAME_FLAG_REPLACE_EXISTING.  This comes up if a primary owner
+          that does not allow replacement goes away, and the next primary owner
+          does allow replacement. In this case, queued items that specified
+          DBUS_NAME_FLAG_REPLACE_EXISTING <emphasis>do not</emphasis>
+          automatically replace the new primary owner. In other words,
+          DBUS_NAME_FLAG_REPLACE_EXISTING is not saved, it is only used at the
+          time RequestName is called. This is deliberate to avoid an infinite loop
+          anytime two applications are both DBUS_NAME_FLAG_ALLOW_REPLACEMENT 
+          and DBUS_NAME_FLAG_REPLACE_EXISTING.
+        </para>
+        <para>
+          The flags argument contains any of the following values logically ORed
+          together:
+
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Conventional Name</entry>
+                  <entry>Value</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+	        <row>
+		  <entry>DBUS_NAME_FLAG_ALLOW_REPLACEMENT</entry>
+		  <entry>0x1</entry>
+		  <entry>
+
+                    If an application A specifies this flag and succeeds in
+                    becoming the owner of the name, and another application B
+                    later calls RequestName with the
+                    DBUS_NAME_FLAG_REPLACE_EXISTING flag, then application A
+                    will lose ownership and receive a
+                    <literal>org.freedesktop.DBus.NameLost</literal> signal, and
+                    application B will become the new owner. If DBUS_NAME_FLAG_ALLOW_REPLACEMENT
+                    is not specified by application A, or DBUS_NAME_FLAG_REPLACE_EXISTING
+                    is not specified by application B, then application B will not replace
+                    application A as the owner.
+
+                  </entry>
+	        </row>
+	        <row>
+		  <entry>DBUS_NAME_FLAG_REPLACE_EXISTING</entry>
+		  <entry>0x2</entry>
+		  <entry>
+
+                    Try to replace the current owner if there is one. If this
+                    flag is not set the application will only become the owner of
+                    the name if there is no current owner. If this flag is set,
+                    the application will replace the current owner if
+                    the current owner specified DBUS_NAME_FLAG_ALLOW_REPLACEMENT.
+
+                  </entry>
+	        </row>
+	        <row>
+		  <entry>DBUS_NAME_FLAG_DO_NOT_QUEUE</entry>
+		  <entry>0x4</entry>
+		  <entry>
+
+                    Without this flag, if an application requests a name that is
+                    already owned, the application will be placed in a queue to
+                    own the name when the current owner gives it up. If this
+                    flag is given, the application will not be placed in the
+                    queue, the request for the name will simply fail.  This flag
+                    also affects behavior when an application is replaced as
+                    name owner; by default the application moves back into the
+                    waiting queue, unless this flag was provided when the application
+                    became the name owner.
+
+                  </entry>
+	        </row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+
+          The return code can be one of the following values:
+
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Conventional Name</entry>
+                  <entry>Value</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+	        <row>
+                  <entry>DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER</entry>
+		  <entry>1</entry> <entry>The caller is now the primary owner of
+		  the name, replacing any previous owner. Either the name had no
+		  owner before, or the caller specified
+		  DBUS_NAME_FLAG_REPLACE_EXISTING and the current owner specified
+                  DBUS_NAME_FLAG_ALLOW_REPLACEMENT.</entry>
+	        </row>
+	        <row>
+		  <entry>DBUS_REQUEST_NAME_REPLY_IN_QUEUE</entry>
+		  <entry>2</entry>
+
+		  <entry>The name already had an owner,
+                    DBUS_NAME_FLAG_DO_NOT_QUEUE was not specified, and either
+                    the current owner did not specify
+                    DBUS_NAME_FLAG_ALLOW_REPLACEMENT or the requesting
+                    application did not specify DBUS_NAME_FLAG_REPLACE_EXISTING.
+                    </entry>
+	        </row>
+	        <row>
+		  <entry>DBUS_REQUEST_NAME_REPLY_EXISTS</entry> <entry>3</entry>
+		  <entry>The name already has an owner,
+		  DBUS_NAME_FLAG_DO_NOT_QUEUE was specified, and either
+		  DBUS_NAME_FLAG_ALLOW_REPLACEMENT was not specified by the
+		  current owner, or DBUS_NAME_FLAG_REPLACE_EXISTING was not
+		  specified by the requesting application.</entry>
+	        </row>
+	        <row>
+		  <entry>DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER</entry>
+		  <entry>4</entry>
+		  <entry>The application trying to request ownership of a name is already the owner of it.</entry>
+	        </row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+        </para>
+       </sect3>
+
+       <sect3 id="bus-messages-release-name">
+        <title><literal>org.freedesktop.DBus.ReleaseName</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            UINT32 ReleaseName (in STRING name)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Name to release</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+          Reply arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>UINT32</entry>
+                  <entry>Return value</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+        <para>
+          This method call should be sent to
+          <literal>org.freedesktop.DBus</literal> and asks the message bus to
+          release the method caller's claim to the given name. If the caller is
+          the primary owner, a new primary owner will be selected from the
+          queue if any other owners are waiting. If the caller is waiting in
+          the queue for the name, the caller will removed from the queue and
+          will not be made an owner of the name if it later becomes available.
+          If there are no other owners in the queue for the name, it will be
+          removed from the bus entirely.
+
+          The return code can be one of the following values:
+
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Conventional Name</entry>
+                  <entry>Value</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+	        <row>
+                  <entry>DBUS_RELEASE_NAME_REPLY_RELEASED</entry>
+                  <entry>1</entry> <entry>The caller has released his claim on
+                  the given name. Either the caller was the primary owner of
+                  the name, and the name is now unused or taken by somebody
+                  waiting in the queue for the name, or the caller was waiting
+                  in the queue for the name and has now been removed from the
+                  queue.</entry>
+	        </row>
+	        <row>
+		  <entry>DBUS_RELEASE_NAME_REPLY_NON_EXISTENT</entry>
+		  <entry>2</entry>
+		  <entry>The given name does not exist on this bus.</entry>
+	        </row>
+	        <row>
+		  <entry>DBUS_RELEASE_NAME_REPLY_NOT_OWNER</entry>
+		  <entry>3</entry>
+		  <entry>The caller was not the primary owner of this name,
+                  and was also not waiting in the queue to own this name.</entry>
+	        </row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+        </para>
+       </sect3>
+
+       <sect3 id="bus-messages-list-queued-owners">
+        <title><literal>org.freedesktop.DBus.ListQueuedOwners</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            ARRAY of STRING ListQueuedOwners (in STRING name)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>The well-known bus name to query, such as
+                    <literal>com.example.cappuccino</literal></entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+          Reply arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>ARRAY of STRING</entry>
+                  <entry>The unique bus names of connections currently queued
+                    for the name</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+        <para>
+          This method call should be sent to
+          <literal>org.freedesktop.DBus</literal> and lists the connections
+          currently queued for a bus name (see
+          <xref linkend="term-queued-owner"/>).
+        </para>
+       </sect3>
+    </sect2>
+
+    <sect2 id="message-bus-routing">
+      <title>Message Bus Message Routing</title>
+
+      <para>
+        Messages may have a <literal>DESTINATION</literal> field (see <xref
+          linkend="message-protocol-header-fields"/>), resulting in a
+        <firstterm>unicast message</firstterm>.  If the
+        <literal>DESTINATION</literal> field is present, it specifies a message
+        recipient by name. Method calls and replies normally specify this field.
+        The message bus must send messages (of any type) with the
+        <literal>DESTINATION</literal> field set to the specified recipient,
+        regardless of whether the recipient has set up a match rule matching
+        the message.
+      </para>
+
+      <para>
+        When the message bus receives a signal, if the
+        <literal>DESTINATION</literal> field is absent, it is considered to
+        be a <firstterm>broadcast signal</firstterm>, and is sent to all
+        applications with <firstterm>message matching rules</firstterm> that
+        match the message. Most signal messages are broadcasts.
+      </para>
+
+      <para>
+        Unicast signal messages (those with a <literal>DESTINATION</literal>
+        field) are not commonly used, but they are treated like any unicast
+        message: they are delivered to the specified receipient,
+        regardless of its match rules.  One use for unicast signals is to
+        avoid a race condition in which a signal is emitted before the intended
+        recipient can call <xref linkend="bus-messages-add-match"/> to
+        receive that signal: if the signal is sent directly to that recipient
+        using a unicast message, it does not need to add a match rule at all,
+        and there is no race condition.  Another use for unicast signals,
+        on message buses whose security policy prevents eavesdropping, is to
+        send sensitive information which should only be visible to one
+        recipient.
+      </para>
+
+      <para>
+        When the message bus receives a method call, if the
+        <literal>DESTINATION</literal> field is absent, the call is taken to be
+        a standard one-to-one message and interpreted by the message bus
+        itself. For example, sending an
+        <literal>org.freedesktop.DBus.Peer.Ping</literal> message with no
+        <literal>DESTINATION</literal> will cause the message bus itself to
+        reply to the ping immediately; the message bus will not make this
+        message visible to other applications.
+      </para>
+
+      <para>
+        Continuing the <literal>org.freedesktop.DBus.Peer.Ping</literal> example, if
+        the ping message were sent with a <literal>DESTINATION</literal> name of
+        <literal>com.yoyodyne.Screensaver</literal>, then the ping would be
+        forwarded, and the Yoyodyne Corporation screensaver application would be
+        expected to reply to the ping.
+      </para>
+
+      <para>
+        Message bus implementations may impose a security policy which
+        prevents certain messages from being sent or received.
+        When a message cannot be sent or received due to a security
+        policy, the message bus should send an error reply, unless the
+        original message had the <literal>NO_REPLY</literal> flag.
+      </para>
+
+      <sect3 id="message-bus-routing-eavesdropping">
+        <title>Eavesdropping</title>
+        <para>
+          Receiving a unicast message whose <literal>DESTINATION</literal>
+          indicates a different recipient is called
+          <firstterm>eavesdropping</firstterm>. On a message bus which acts as
+          a security boundary (like the standard system bus), the security
+          policy should usually prevent eavesdropping, since unicast messages
+          are normally kept private and may contain security-sensitive
+          information.
+        </para>
+
+        <para>
+          Eavesdropping is mainly useful for debugging tools, such as
+          the <literal>dbus-monitor</literal> tool in the reference
+          implementation of D-Bus. Tools which eavesdrop on the message bus
+          should be careful to avoid sending a reply or error in response to
+          messages intended for a different client.
+        </para>
+
+        <para>
+          Clients may attempt to eavesdrop by adding match rules
+          (see <xref linkend="message-bus-routing-match-rules"/>) containing
+          the <literal>eavesdrop='true'</literal> match. If the message bus'
+          security policy does not allow eavesdropping, the match rule can
+          still be added, but will not have any practical effect. For
+          compatibility with older message bus implementations, if adding such
+          a match rule results in an error reply, the client may fall back to
+          adding the same rule with the <literal>eavesdrop</literal> match
+          omitted.
+        </para>
+      </sect3>
+
+      <sect3 id="message-bus-routing-match-rules">
+        <title>Match Rules</title>
+        <para>
+	  An important part of the message bus routing protocol is match
+          rules. Match rules describe the messages that should be sent to a
+          client, based on the contents of the message.  Broadcast signals
+          are only sent to clients which have a suitable match rule: this
+          avoids waking up client processes to deal with signals that are
+          not relevant to that client.
+        </para>
+        <para>
+          Messages that list a client as their <literal>DESTINATION</literal>
+          do not need to match the client's match rules, and are sent to that
+          client regardless. As a result, match rules are mainly used to
+          receive a subset of broadcast signals.
+        </para>
+        <para>
+          Match rules can also be used for eavesdropping
+          (see <xref linkend="message-bus-routing-eavesdropping"/>),
+          if the security policy of the message bus allows it.
+        </para>
+        <para>
+          Match rules are added using the AddMatch bus method 
+          (see <xref linkend="bus-messages-add-match"/>).  Rules are
+          specified as a string of comma separated key/value pairs. 
+          Excluding a key from the rule indicates a wildcard match.  
+          For instance excluding the the member from a match rule but 
+          adding a sender would let all messages from that sender through.
+          An example of a complete rule would be 
+          "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',path='/bar/foo',destination=':452345.34',arg2='bar'"
+        </para>
+        <para>
+          The following table describes the keys that can be used to create 
+          a match rule:
+          The following table summarizes the D-Bus types.
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Key</entry>
+                  <entry>Possible Values</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry><literal>type</literal></entry>
+                  <entry>'signal', 'method_call', 'method_return', 'error'</entry>
+                  <entry>Match on the message type.  An example of a type match is type='signal'</entry>
+                </row>
+                <row>
+                  <entry><literal>sender</literal></entry>
+                  <entry>A bus or unique name (see <xref linkend="term-bus-name"/>
+                  and <xref linkend="term-unique-name"/> respectively)
+                  </entry>
+                  <entry>Match messages sent by a particular sender.  An example of a sender match
+                  is sender='org.freedesktop.Hal'</entry>
+                </row>
+                <row>
+                  <entry><literal>interface</literal></entry>
+                  <entry>An interface name (see <xref linkend="message-protocol-names-interface"/>)</entry>
+                  <entry>Match messages sent over or to a particular interface.  An example of an
+                  interface match is interface='org.freedesktop.Hal.Manager'.
+                  If a message omits the interface header, it must not match any rule 
+                  that specifies this key.</entry>
+                </row>
+                <row>
+                  <entry><literal>member</literal></entry>
+                  <entry>Any valid method or signal name</entry>
+                  <entry>Matches messages which have the give method or signal name. An example of
+                  a member match is member='NameOwnerChanged'</entry>
+                </row>
+                <row>
+                  <entry><literal>path</literal></entry>
+                  <entry>An object path (see <xref linkend="message-protocol-marshaling-object-path"/>)</entry>
+                  <entry>Matches messages which are sent from or to the given object. An example of a
+                  path match is path='/org/freedesktop/Hal/Manager'</entry>
+                </row>
+                <row>
+                  <entry><literal>path_namespace</literal></entry>
+                  <entry>An object path</entry>
+                  <entry>
+                    <para>
+                      Matches messages which are sent from or to an
+                      object for which the object path is either the
+                      given value, or that value followed by one or
+                      more path components.
+                    </para>
+
+                    <para>
+                      For example,
+                      <literal>path_namespace='/com/example/foo'</literal>
+                      would match signals sent by
+                      <literal>/com/example/foo</literal>
+                      or by
+                      <literal>/com/example/foo/bar</literal>,
+                      but not by
+                      <literal>/com/example/foobar</literal>.
+                    </para>
+
+                    <para>
+                      Using both <literal>path</literal> and
+                      <literal>path_namespace</literal> in the same match
+                      rule is not allowed.
+                    </para>
+
+                    <para>
+                      <emphasis>
+                        This match key was added in version 0.16 of the
+                        D-Bus specification and implemented by the bus
+                        daemon in dbus 1.5.0 and later.
+                      </emphasis>
+                    </para>
+                </entry>
+                </row>
+                <row>
+                  <entry><literal>destination</literal></entry>
+                  <entry>A unique name (see <xref linkend="term-unique-name"/>)</entry>
+                  <entry>Matches messages which are being sent to the given unique name. An
+                  example of a destination match is destination=':1.0'</entry>
+                </row>
+                <row>
+                  <entry><literal>arg[0, 1, 2, 3, ...]</literal></entry>
+                  <entry>Any string</entry>
+                  <entry>Arg matches are special and are used for further restricting the 
+                  match based on the arguments in the body of a message. Only arguments of type
+                  STRING can be matched in this way. An example of an argument match 
+                  would be arg3='Foo'. Only argument indexes from 0 to 63 should be 
+                  accepted.</entry>
+                </row>
+                <row>
+                  <entry><literal>arg[0, 1, 2, 3, ...]path</literal></entry>
+                  <entry>Any string</entry>
+                  <entry>
+                    <para>Argument path matches provide a specialised form of wildcard matching for
+                      path-like namespaces. They can match arguments whose type is either STRING or
+                      OBJECT_PATH. As with normal argument matches,
+                      if the argument is exactly equal to the string given in the match
+                      rule then the rule is satisfied. Additionally, there is also a
+                      match when either the string given in the match rule or the
+                      appropriate message argument ends with '/' and is a prefix of the
+                      other. An example argument path match is arg0path='/aa/bb/'. This
+                      would match messages with first arguments of '/', '/aa/',
+                      '/aa/bb/', '/aa/bb/cc/' and '/aa/bb/cc'. It would not match
+                      messages with first arguments of '/aa/b', '/aa' or even '/aa/bb'.</para>
+
+                    <para>This is intended for monitoring “directories” in file system-like
+                      hierarchies, as used in the <citetitle>dconf</citetitle> configuration
+                      system. An application interested in all nodes in a particular hierarchy would
+                      monitor <literal>arg0path='/ca/example/foo/'</literal>. Then the service could
+                      emit a signal with zeroth argument <literal>"/ca/example/foo/bar"</literal> to
+                      represent a modification to the “bar” property, or a signal with zeroth
+                      argument <literal>"/ca/example/"</literal> to represent atomic modification of
+                      many properties within that directory, and the interested application would be
+                      notified in both cases.</para>
+                    <para>
+                      <emphasis>
+                        This match key was added in version 0.12 of the
+                        D-Bus specification, implemented for STRING
+                        arguments by the bus daemon in dbus 1.2.0 and later,
+                        and implemented for OBJECT_PATH arguments in dbus 1.5.0
+                        and later.
+                      </emphasis>
+                    </para>
+                  </entry>
+                </row>
+                <row>
+                  <entry><literal>arg0namespace</literal></entry>
+                  <entry>Like a bus name, except that the string is not
+                    required to contain a '.' (period)</entry>
+                  <entry>
+                    <para>Match messages whose first argument is of type STRING, and is a bus name
+                      or interface name within the specified namespace. This is primarily intended
+                      for watching name owner changes for a group of related bus names, rather than
+                      for a single name or all name changes.</para>
+
+                    <para>Because every valid interface name is also a valid
+                      bus name, this can also be used for messages whose
+                      first argument is an interface name.</para>
+
+                    <para>For example, the match rule
+                      <literal>member='NameOwnerChanged',arg0namespace='com.example.backend'</literal>
+                      matches name owner changes for bus names such as
+                      <literal>com.example.backend.foo</literal>,
+                      <literal>com.example.backend.foo.bar</literal>, and
+                      <literal>com.example.backend</literal> itself.</para>
+
+                    <para>See also <xref linkend='bus-messages-name-owner-changed'/>.</para>
+                    <para>
+                      <emphasis>
+                        This match key was added in version 0.16 of the
+                        D-Bus specification and implemented by the bus
+                        daemon in dbus 1.5.0 and later.
+                      </emphasis>
+                    </para>
+                  </entry>
+                </row>
+                <row>
+                  <entry><literal>eavesdrop</literal></entry>
+                  <entry><literal>'true'</literal>, <literal>'false'</literal></entry>
+                  <entry>Since D-Bus 1.5.6, match rules do not
+                    match messages which have a <literal>DESTINATION</literal>
+                    field unless the match rule specifically
+                    requests this
+                    (see <xref linkend="message-bus-routing-eavesdropping"/>)
+                    by specifying <literal>eavesdrop='true'</literal>
+                    in the match rule.  <literal>eavesdrop='false'</literal>
+                    restores the default behaviour. Messages are
+                    delivered to their <literal>DESTINATION</literal>
+                    regardless of match rules, so this match does not
+                    affect normal delivery of unicast messages.
+                    If the message bus has a security policy which forbids
+                    eavesdropping, this match may still be used without error,
+                    but will not have any practical effect.
+                    In older versions of D-Bus, this match was not allowed
+                    in match rules, and all match rules behaved as if
+                    <literal>eavesdrop='true'</literal> had been used.
+                  </entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+      </sect3>
+    </sect2>
+    <sect2 id="message-bus-starting-services">
+      <title>Message Bus Starting Services</title>
+      <para>
+        The message bus can start applications on behalf of other applications.
+        In CORBA terms, this would be called <firstterm>activation</firstterm>.
+        An application that can be started in this way is called a
+        <firstterm>service</firstterm>.
+      </para>
+      <para>
+        With D-Bus, starting a service is normally done by name. That is,
+        applications ask the message bus to start some program that will own a
+        well-known name, such as <literal>org.freedesktop.TextEditor</literal>.
+        This implies a contract documented along with the name 
+        <literal>org.freedesktop.TextEditor</literal> for which objects 
+        the owner of that name will provide, and what interfaces those 
+        objects will have.
+      </para>
+      <para>
+        To find an executable corresponding to a particular name, the bus daemon
+        looks for <firstterm>service description files</firstterm>.  Service
+        description files define a mapping from names to executables. Different
+        kinds of message bus will look for these files in different places, see
+        <xref linkend="message-bus-types"/>.
+      </para>
+      <para>
+        Service description files have the ".service" file
+        extension. The message bus will only load service description files
+        ending with .service; all other files will be ignored.  The file format
+        is similar to that of <ulink
+        url="http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html">desktop
+        entries</ulink>. All service description files must be in UTF-8
+        encoding. To ensure that there will be no name collisions, service files
+        must be namespaced using the same mechanism as messages and service
+        names.
+      </para>
+
+      <para>
+        [FIXME the file format should be much better specified than "similar to
+        .desktop entries" esp. since desktop entries are already
+        badly-specified. ;-)]
+        These sections from the specification apply to service files as well:
+
+        <itemizedlist>
+          <listitem><para>General syntax</para></listitem>
+          <listitem><para>Comment format</para></listitem>
+        </itemizedlist>
+
+        <figure>
+	  <title>Example service description file</title>
+	  <programlisting>
+            # Sample service description file
+            [D-BUS Service]
+            Names=org.freedesktop.ConfigurationDatabase;org.gnome.GConf;
+            Exec=/usr/libexec/gconfd-2
+          </programlisting>
+	</figure>
+      </para>
+      <para>
+        When an application asks to start a service by name, the bus daemon tries to
+        find a service that will own that name. It then tries to spawn the
+        executable associated with it. If this fails, it will report an
+        error. [FIXME what happens if two .service files offer the same service;
+        what kind of error is reported, should we have a way for the client to
+        choose one?]
+      </para>
+      <para>
+        The executable launched will have the environment variable
+        <literal>DBUS_STARTER_ADDRESS</literal> set to the address of the
+        message bus so it can connect and request the appropriate names.
+      </para>
+      <para>
+        The executable being launched may want to know whether the message bus
+        starting it is one of the well-known message buses (see <xref
+        linkend="message-bus-types"/>). To facilitate this, the bus must also set
+        the <literal>DBUS_STARTER_BUS_TYPE</literal> environment variable if it is one
+        of the well-known buses. The currently-defined values for this variable
+        are <literal>system</literal> for the systemwide message bus,
+        and <literal>session</literal> for the per-login-session message
+        bus. The new executable must still connect to the address given
+        in <literal>DBUS_STARTER_ADDRESS</literal>, but may assume that the
+        resulting connection is to the well-known bus.
+      </para>
+      <para>
+        [FIXME there should be a timeout somewhere, either specified
+        in the .service file, by the client, or just a global value
+        and if the client being activated fails to connect within that
+        timeout, an error should be sent back.]
+      </para>
+
+      <sect3 id="message-bus-starting-services-scope">
+        <title>Message Bus Service Scope</title>
+        <para>
+          The "scope" of a service is its "per-", such as per-session,
+          per-machine, per-home-directory, or per-display. The reference
+          implementation doesn't yet support starting services in a different
+          scope from the message bus itself. So e.g. if you start a service
+          on the session bus its scope is per-session.
+        </para>
+        <para>
+          We could add an optional scope to a bus name. For example, for
+          per-(display,session pair), we could have a unique ID for each display
+          generated automatically at login and set on screen 0 by executing a
+          special "set display ID" binary. The ID would be stored in a
+          <literal>_DBUS_DISPLAY_ID</literal> property and would be a string of
+          random bytes. This ID would then be used to scope names.
+          Starting/locating a service could be done by ID-name pair rather than
+          only by name.
+        </para>
+        <para>
+          Contrast this with a per-display scope. To achieve that, we would 
+          want a single bus spanning all sessions using a given display.
+          So we might set a <literal>_DBUS_DISPLAY_BUS_ADDRESS</literal> 
+          property on screen 0 of the display, pointing to this bus.
+        </para>
+      </sect3>
+    </sect2>
+
+    <sect2 id="message-bus-types">
+      <title>Well-known Message Bus Instances</title>
+      <para>
+        Two standard message bus instances are defined here, along with how 
+        to locate them and where their service files live.
+      </para>
+      <sect3 id="message-bus-types-login">
+        <title>Login session message bus</title>
+        <para>
+          Each time a user logs in, a <firstterm>login session message
+            bus</firstterm> may be started. All applications in the user's login
+          session may interact with one another using this message bus.
+        </para>
+        <para>
+          The address of the login session message bus is given 
+          in the <literal>DBUS_SESSION_BUS_ADDRESS</literal> environment 
+          variable. If that variable is not set, applications may 
+          also try to read the address from the X Window System root 
+          window property <literal>_DBUS_SESSION_BUS_ADDRESS</literal>.
+          The root window property must have type <literal>STRING</literal>.
+          The environment variable should have precedence over the 
+          root window property.
+        </para>
+        <para>The address of the login session message bus is given in the
+        <literal>DBUS_SESSION_BUS_ADDRESS</literal> environment variable. If
+        DBUS_SESSION_BUS_ADDRESS is not set, or if it's set to the string
+        "autolaunch:", the system should use platform-specific methods of
+        locating a running D-Bus session server, or starting one if a running
+        instance cannot be found. Note that this mechanism is not recommended
+        for attempting to determine if a daemon is running. It is inherently
+        racy to attempt to make this determination, since the bus daemon may
+        be started just before or just after the determination is made.
+        Therefore, it is recommended that applications do not try to make this
+        determination for their functionality purposes, and instead they
+        should attempt to start the server.</para>
+
+        <sect4 id="message-bus-types-login-x-windows">
+          <title>X Windowing System</title>
+          <para>
+            For the X Windowing System, the application must locate the
+            window owner of the selection represented by the atom formed by
+            concatenating:
+            <itemizedlist>
+              <listitem>
+                <para>the literal string "_DBUS_SESSION_BUS_SELECTION_"</para>
+              </listitem>
+
+              <listitem>
+                <para>the current user's username</para>
+              </listitem>
+
+              <listitem>
+                <para>the literal character '_' (underscore)</para>
+              </listitem>
+
+              <listitem>
+                <para>the machine's ID</para>
+              </listitem>
+            </itemizedlist>
+          </para>
+
+          <para>
+            The following properties are defined for the window that owns
+            this X selection:
+            <informaltable frame="all">
+              <tgroup cols="2">
+                <tbody>
+                  <row>
+                    <entry>
+                      <para>Atom</para>
+                    </entry>
+
+                    <entry>
+                      <para>meaning</para>
+                    </entry>
+                  </row>
+
+                  <row>
+                    <entry>
+                      <para>_DBUS_SESSION_BUS_ADDRESS</para>
+                    </entry>
+
+                    <entry>
+                      <para>the actual address of the server socket</para>
+                    </entry>
+                  </row>
+
+                  <row>
+                    <entry>
+                      <para>_DBUS_SESSION_BUS_PID</para>
+                    </entry>
+
+                    <entry>
+                      <para>the PID of the server process</para>
+                    </entry>
+                  </row>
+                </tbody>
+              </tgroup>
+            </informaltable>
+          </para>
+
+          <para>
+            At least the _DBUS_SESSION_BUS_ADDRESS property MUST be
+            present in this window.
+          </para>
+
+          <para>
+            If the X selection cannot be located or if reading the
+            properties from the window fails, the implementation MUST conclude
+            that there is no D-Bus server running and proceed to start a new
+            server. (See below on concurrency issues)
+          </para>
+
+          <para>
+            Failure to connect to the D-Bus server address thus obtained
+            MUST be treated as a fatal connection error and should be reported
+            to the application.
+          </para>
+
+          <para>
+            As an alternative, an implementation MAY find the information
+            in the following file located in the current user's home directory,
+            in subdirectory .dbus/session-bus/:
+            <itemizedlist>
+              <listitem>
+                <para>the machine's ID</para>
+              </listitem>
+
+              <listitem>
+                <para>the literal character '-' (dash)</para>
+              </listitem>
+
+              <listitem>
+                <para>the X display without the screen number, with the
+                following prefixes removed, if present: ":", "localhost:"
+                ."localhost.localdomain:". That is, a display of
+                "localhost:10.0" produces just the number "10"</para>
+              </listitem>
+            </itemizedlist>
+          </para>
+
+          <para>
+            The contents of this file NAME=value assignment pairs and
+            lines starting with # are comments (no comments are allowed
+            otherwise). The following variable names are defined:
+            <informaltable
+              frame="all">
+              <tgroup cols="2">
+                <tbody>
+                  <row>
+                    <entry>
+                      <para>Variable</para>
+                    </entry>
+
+                    <entry>
+                      <para>meaning</para>
+                    </entry>
+                  </row>
+
+                  <row>
+                    <entry>
+                      <para>DBUS_SESSION_BUS_ADDRESS</para>
+                    </entry>
+
+                    <entry>
+                      <para>the actual address of the server socket</para>
+                    </entry>
+                  </row>
+
+                  <row>
+                    <entry>
+                      <para>DBUS_SESSION_BUS_PID</para>
+                    </entry>
+
+                    <entry>
+                      <para>the PID of the server process</para>
+                    </entry>
+                  </row>
+
+                  <row>
+                    <entry>
+                      <para>DBUS_SESSION_BUS_WINDOWID</para>
+                    </entry>
+
+                    <entry>
+                      <para>the window ID</para>
+                    </entry>
+                  </row>
+                </tbody>
+              </tgroup>
+            </informaltable>
+          </para>
+
+          <para>
+            At least the DBUS_SESSION_BUS_ADDRESS variable MUST be present
+            in this file.
+          </para>
+
+          <para>
+            Failure to open this file MUST be interpreted as absence of a
+            running server. Therefore, the implementation MUST proceed to
+            attempting to launch a new bus server if the file cannot be
+            opened.
+          </para>
+
+          <para>
+            However, success in opening this file MUST NOT lead to the
+            conclusion that the server is running. Thus, a failure to connect to
+            the bus address obtained by the alternative method MUST NOT be
+            considered a fatal error. If the connection cannot be established,
+            the implementation MUST proceed to check the X selection settings or
+            to start the server on its own.
+          </para>
+
+          <para>
+            If the implementation concludes that the D-Bus server is not
+            running it MUST attempt to start a new server and it MUST also
+            ensure that the daemon started as an effect of the "autolaunch"
+            mechanism provides the lookup mechanisms described above, so
+            subsequent calls can locate the newly started server. The
+            implementation MUST also ensure that if two or more concurrent
+            initiations happen, only one server remains running and all other
+            initiations are able to obtain the address of this server and
+            connect to it. In other words, the implementation MUST ensure that
+            the X selection is not present when it attempts to set it, without
+            allowing another process to set the selection between the
+            verification and the setting (e.g., by using XGrabServer /
+            XungrabServer).
+          </para>
+        </sect4>
+        <sect4>
+          <title></title>
+          <para>
+            On Unix systems, the session bus should search for .service files
+            in <literal>$XDG_DATA_DIRS/dbus-1/services</literal> as defined
+            by the
+            <ulink url="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG Base Directory Specification</ulink>.
+            Implementations may also search additional locations, which
+            should be searched with lower priority than anything in
+            XDG_DATA_HOME, XDG_DATA_DIRS or their respective defaults;
+            for example, the reference implementation also
+            looks in <literal>${datadir}/dbus-1/services</literal> as
+            set at compile time.
+          </para>
+          <para>
+            As described in the XDG Base Directory Specification, software
+            packages should install their session .service files to their
+            configured <literal>${datadir}/dbus-1/services</literal>,
+            where <literal>${datadir}</literal> is as defined by the GNU
+            coding standards. System administrators or users can arrange
+            for these service files to be read by setting XDG_DATA_DIRS or by
+            symlinking them into the default locations.
+          </para>
+        </sect4>
+      </sect3>
+      <sect3 id="message-bus-types-system">
+        <title>System message bus</title>
+        <para>
+          A computer may have a <firstterm>system message bus</firstterm>,
+          accessible to all applications on the system. This message bus may be
+          used to broadcast system events, such as adding new hardware devices, 
+          changes in the printer queue, and so forth.
+        </para>
+        <para>
+          The address of the system message bus is given 
+          in the <literal>DBUS_SYSTEM_BUS_ADDRESS</literal> environment 
+          variable. If that variable is not set, applications should try 
+          to connect to the well-known address
+          <literal>unix:path=/var/run/dbus/system_bus_socket</literal>.
+          <footnote>
+            <para>
+              The D-Bus reference implementation actually honors the 
+              <literal>$(localstatedir)</literal> configure option 
+              for this address, on both client and server side.
+            </para>
+          </footnote>
+        </para>
+        <para>
+          On Unix systems, the system bus should default to searching
+          for .service files in
+          <literal>/usr/local/share/dbus-1/system-services</literal>,
+          <literal>/usr/share/dbus-1/system-services</literal> and
+          <literal>/lib/dbus-1/system-services</literal>, with that order
+          of precedence. It may also search other implementation-specific
+          locations, but should not vary these locations based on environment
+          variables.
+          <footnote>
+            <para>
+              The system bus is security-sensitive and is typically executed
+              by an init system with a clean environment. Its launch helper
+              process is particularly security-sensitive, and specifically
+              clears its own environment.
+            </para>
+          </footnote>
+        </para>
+        <para>
+          Software packages should install their system .service
+          files to their configured
+          <literal>${datadir}/dbus-1/system-services</literal>,
+          where <literal>${datadir}</literal> is as defined by the GNU
+          coding standards. System administrators can arrange
+          for these service files to be read by editing the system bus'
+          configuration file or by symlinking them into the default
+          locations.
+        </para>
+      </sect3>
+    </sect2>
+
+    <sect2 id="message-bus-messages">
+      <title>Message Bus Messages</title>
+      <para>
+        The special message bus name <literal>org.freedesktop.DBus</literal>
+        responds to a number of additional messages.
+      </para>
+
+      <sect3 id="bus-messages-hello">
+        <title><literal>org.freedesktop.DBus.Hello</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            STRING Hello ()
+          </programlisting>
+          Reply arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Unique name assigned to the connection</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+        <para>
+          Before an application is able to send messages to other applications
+          it must send the <literal>org.freedesktop.DBus.Hello</literal> message
+          to the message bus to obtain a unique name. If an application without
+          a unique name tries to send a message to another application, or a
+          message to the message bus itself that isn't the
+          <literal>org.freedesktop.DBus.Hello</literal> message, it will be
+          disconnected from the bus.
+        </para>
+        <para>
+          There is no corresponding "disconnect" request; if a client wishes to
+          disconnect from the bus, it simply closes the socket (or other 
+          communication channel).
+        </para>
+      </sect3>
+      <sect3 id="bus-messages-list-names">
+        <title><literal>org.freedesktop.DBus.ListNames</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            ARRAY of STRING ListNames ()
+          </programlisting>
+          Reply arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>ARRAY of STRING</entry>
+                  <entry>Array of strings where each string is a bus name</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+        <para>
+          Returns a list of all currently-owned names on the bus.
+        </para>
+      </sect3>
+      <sect3 id="bus-messages-list-activatable-names">
+        <title><literal>org.freedesktop.DBus.ListActivatableNames</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            ARRAY of STRING ListActivatableNames ()
+          </programlisting>
+          Reply arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>ARRAY of STRING</entry>
+                  <entry>Array of strings where each string is a bus name</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+        <para>
+          Returns a list of all names that can be activated on the bus.
+        </para>
+      </sect3>
+      <sect3 id="bus-messages-name-exists">
+        <title><literal>org.freedesktop.DBus.NameHasOwner</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            BOOLEAN NameHasOwner (in STRING name)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Name to check</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+          Reply arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>BOOLEAN</entry>
+                  <entry>Return value, true if the name exists</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+        <para>
+          Checks if the specified name exists (currently has an owner).
+        </para>
+      </sect3>
+
+      <sect3 id="bus-messages-name-owner-changed">
+        <title><literal>org.freedesktop.DBus.NameOwnerChanged</literal></title>
+        <para>
+          This is a signal:
+          <programlisting>
+            NameOwnerChanged (STRING name, STRING old_owner, STRING new_owner)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Name with a new owner</entry>
+                </row>
+	        <row>
+		  <entry>1</entry>
+		  <entry>STRING</entry>
+		  <entry>Old owner or empty string if none</entry>
+	        </row>
+	        <row>
+		  <entry>2</entry>
+		  <entry>STRING</entry>
+		  <entry>New owner or empty string if none</entry>
+	        </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+        <para>
+          This signal indicates that the owner of a name has changed.
+          It's also the signal to use to detect the appearance of 
+          new names on the bus.
+        </para>
+      </sect3>
+      <sect3 id="bus-messages-name-lost">
+        <title><literal>org.freedesktop.DBus.NameLost</literal></title>
+        <para>
+          This is a signal:
+          <programlisting>
+            NameLost (STRING name)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Name which was lost</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+        <para>
+          This signal is sent to a specific application when it loses
+          ownership of a name.
+        </para>
+      </sect3>
+
+      <sect3 id="bus-messages-name-acquired">
+        <title><literal>org.freedesktop.DBus.NameAcquired</literal></title>
+        <para>
+          This is a signal:
+          <programlisting>
+            NameAcquired (STRING name)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Name which was acquired</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        </para>
+        <para>
+          This signal is sent to a specific application when it gains
+          ownership of a name.
+        </para>
+      </sect3>
+
+      <sect3 id="bus-messages-start-service-by-name">
+        <title><literal>org.freedesktop.DBus.StartServiceByName</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            UINT32 StartServiceByName (in STRING name, in UINT32 flags)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Name of the service to start</entry>
+                </row>
+	        <row>
+		  <entry>1</entry>
+		  <entry>UINT32</entry>
+		  <entry>Flags (currently not used)</entry>
+	        </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        Reply arguments:
+        <informaltable>
+          <tgroup cols="3">
+            <thead>
+              <row>
+                <entry>Argument</entry>
+                <entry>Type</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>0</entry>
+                <entry>UINT32</entry>
+                <entry>Return value</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+          Tries to launch the executable associated with a name. For more information, see <xref linkend="message-bus-starting-services"/>.
+
+        </para>
+        <para>
+          The return value can be one of the following values:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Identifier</entry>
+                  <entry>Value</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+	        <row>
+                  <entry>DBUS_START_REPLY_SUCCESS</entry>
+                  <entry>1</entry>
+                  <entry>The service was successfully started.</entry>
+                </row>
+                <row>
+                  <entry>DBUS_START_REPLY_ALREADY_RUNNING</entry>
+                  <entry>2</entry>
+                  <entry>A connection already owns the given name.</entry>
+                </row>
+              </tbody>
+             </tgroup>
+           </informaltable>
+        </para>
+
+      </sect3>
+
+      <sect3 id="bus-messages-update-activation-environment">
+        <title><literal>org.freedesktop.DBus.UpdateActivationEnvironment</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            UpdateActivationEnvironment (in ARRAY of DICT&lt;STRING,STRING&gt; environment)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>ARRAY of DICT&lt;STRING,STRING&gt;</entry>
+                  <entry>Environment to add or update</entry>
+                </row>
+              </tbody>
+            </tgroup>
+            </informaltable>
+            Normally, session bus activated services inherit the environment of the bus daemon.  This method adds to or modifies that environment when activating services.
+        </para>
+        <para>
+          Some bus instances, such as the standard system bus, may disable access to this method for some or all callers.
+        </para>
+        <para>
+          Note, both the environment variable names and values must be valid UTF-8.  There's no way to update the activation environment with data that is invalid UTF-8.
+        </para>
+
+      </sect3>
+
+      <sect3 id="bus-messages-get-name-owner">
+        <title><literal>org.freedesktop.DBus.GetNameOwner</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            STRING GetNameOwner (in STRING name)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Name to get the owner of</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        Reply arguments:
+        <informaltable>
+          <tgroup cols="3">
+            <thead>
+              <row>
+                <entry>Argument</entry>
+                <entry>Type</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>0</entry>
+                <entry>STRING</entry>
+                <entry>Return value, a unique connection name</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+        Returns the unique connection name of the primary owner of the name
+        given. If the requested name doesn't have an owner, returns a
+        <literal>org.freedesktop.DBus.Error.NameHasNoOwner</literal> error.
+       </para>
+      </sect3>
+
+      <sect3 id="bus-messages-get-connection-unix-user">
+        <title><literal>org.freedesktop.DBus.GetConnectionUnixUser</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            UINT32 GetConnectionUnixUser (in STRING bus_name)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Unique or well-known bus name of the connection to
+                    query, such as <literal>:12.34</literal> or
+                    <literal>com.example.tea</literal></entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        Reply arguments:
+        <informaltable>
+          <tgroup cols="3">
+            <thead>
+              <row>
+                <entry>Argument</entry>
+                <entry>Type</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>0</entry>
+                <entry>UINT32</entry>
+                <entry>Unix user ID</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+        Returns the Unix user ID of the process connected to the server. If
+        unable to determine it (for instance, because the process is not on the
+        same machine as the bus daemon), an error is returned.
+       </para>
+      </sect3>
+
+      <sect3 id="bus-messages-get-connection-unix-process-id">
+        <title><literal>org.freedesktop.DBus.GetConnectionUnixProcessID</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            UINT32 GetConnectionUnixProcessID (in STRING bus_name)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Unique or well-known bus name of the connection to
+                    query, such as <literal>:12.34</literal> or
+                    <literal>com.example.tea</literal></entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        Reply arguments:
+        <informaltable>
+          <tgroup cols="3">
+            <thead>
+              <row>
+                <entry>Argument</entry>
+                <entry>Type</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>0</entry>
+                <entry>UINT32</entry>
+                <entry>Unix process id</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+        Returns the Unix process ID of the process connected to the server. If
+        unable to determine it (for instance, because the process is not on the
+        same machine as the bus daemon), an error is returned.
+       </para>
+      </sect3>
+
+      <sect3 id="bus-messages-add-match">
+        <title><literal>org.freedesktop.DBus.AddMatch</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            AddMatch (in STRING rule)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Match rule to add to the connection</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        Adds a match rule to match messages going through the message bus (see <xref linkend='message-bus-routing-match-rules'/>). 
+	If the bus does not have enough resources the <literal>org.freedesktop.DBus.Error.OOM</literal>
+	error is returned.
+       </para>
+      </sect3>
+      <sect3 id="bus-messages-remove-match">
+        <title><literal>org.freedesktop.DBus.RemoveMatch</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            RemoveMatch (in STRING rule)
+          </programlisting>
+          Message arguments:
+          <informaltable>
+            <tgroup cols="3">
+              <thead>
+                <row>
+                  <entry>Argument</entry>
+                  <entry>Type</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+              <tbody>
+                <row>
+                  <entry>0</entry>
+                  <entry>STRING</entry>
+                  <entry>Match rule to remove from the connection</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </informaltable>
+        Removes the first rule that matches (see <xref linkend='message-bus-routing-match-rules'/>). 
+	If the rule is not found the <literal>org.freedesktop.DBus.Error.MatchRuleNotFound</literal>
+	error is returned.
+       </para>
+      </sect3>
+
+      <sect3 id="bus-messages-get-id">
+        <title><literal>org.freedesktop.DBus.GetId</literal></title>
+        <para>
+          As a method:
+          <programlisting>
+            GetId (out STRING id)
+          </programlisting>
+        Reply arguments:
+        <informaltable>
+          <tgroup cols="3">
+            <thead>
+              <row>
+                <entry>Argument</entry>
+                <entry>Type</entry>
+                <entry>Description</entry>
+              </row>
+            </thead>
+            <tbody>
+              <row>
+                <entry>0</entry>
+                <entry>STRING</entry>
+                <entry>Unique ID identifying the bus daemon</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </informaltable>
+        Gets the unique ID of the bus. The unique ID here is shared among all addresses the 
+        bus daemon is listening on (TCP, UNIX domain socket, etc.) and its format is described in 
+        <xref linkend="uuids"/>. Each address the bus is listening on also has its own unique 
+        ID, as described in <xref linkend="addresses"/>. The per-bus and per-address IDs are not related.
+        There is also a per-machine ID, described in <xref linkend="standard-interfaces-peer"/> and returned
+        by org.freedesktop.DBus.Peer.GetMachineId().
+        For a desktop session bus, the bus ID can be used as a way to uniquely identify a user's session.
+        </para>
+      </sect3>
+
+    </sect2>
+
+  </sect1>
+<!--
+  <appendix id="implementation-notes">
+    <title>Implementation notes</title>
+    <sect1 id="implementation-notes-subsection">
+      <title></title>
+      <para>
+      </para>
+    </sect1>
+  </appendix>
+-->
+
+  <glossary><title>Glossary</title>
+    <para>
+      This glossary defines some of the terms used in this specification.
+    </para>
+
+    <glossentry id="term-bus-name"><glossterm>Bus Name</glossterm>
+      <glossdef>
+        <para>
+          The message bus maintains an association between names and
+          connections. (Normally, there's one connection per application.)  A
+          bus name is simply an identifier used to locate connections. For
+          example, the hypothetical <literal>com.yoyodyne.Screensaver</literal>
+          name might be used to send a message to a screensaver from Yoyodyne
+          Corporation.  An application is said to <firstterm>own</firstterm> a
+          name if the message bus has associated the application's connection
+          with the name.  Names may also have <firstterm>queued
+          owners</firstterm> (see <xref linkend="term-queued-owner"/>).
+            The bus assigns a unique name to each connection, 
+            see <xref linkend="term-unique-name"/>. Other names 
+              can be thought of as "well-known names" and are 
+              used to find applications that offer specific functionality.
+        </para>
+
+        <para>
+          See <xref linkend="message-protocol-names-bus"/> for details of
+          the syntax and naming conventions for bus names.
+        </para>
+      </glossdef>
+    </glossentry>
+      
+    <glossentry id="term-message"><glossterm>Message</glossterm>
+      <glossdef>
+        <para>
+          A message is the atomic unit of communication via the D-Bus
+          protocol. It consists of a <firstterm>header</firstterm> and a
+          <firstterm>body</firstterm>; the body is made up of
+          <firstterm>arguments</firstterm>.
+        </para>
+      </glossdef>
+    </glossentry>
+
+    <glossentry id="term-message-bus"><glossterm>Message Bus</glossterm>
+      <glossdef>
+        <para>
+          The message bus is a special application that forwards 
+          or routes messages between a group of applications
+          connected to the message bus. It also manages 
+          <firstterm>names</firstterm> used for routing
+          messages.
+        </para>
+      </glossdef>
+    </glossentry>
+
+    <glossentry id="term-name"><glossterm>Name</glossterm>
+      <glossdef>
+        <para>
+          See <xref linkend="term-bus-name"/>. "Name" may 
+            also be used to refer to some of the other names
+            in D-Bus, such as interface names.
+        </para>
+      </glossdef>
+    </glossentry>
+
+    <glossentry id="namespace"><glossterm>Namespace</glossterm>
+      <glossdef>
+        <para>
+          Used to prevent collisions when defining new interfaces, bus names
+          etc. The convention used is the same one Java uses for defining
+          classes: a reversed domain name.
+          See <xref linkend="message-protocol-names-bus"/>,
+          <xref linkend="message-protocol-names-interface"/>,
+          <xref linkend="message-protocol-names-error"/>,
+          <xref linkend="message-protocol-marshaling-object-path"/>.
+        </para>
+      </glossdef>
+    </glossentry>
+
+    <glossentry id="term-object"><glossterm>Object</glossterm>
+      <glossdef>
+        <para>
+          Each application contains <firstterm>objects</firstterm>, which have
+          <firstterm>interfaces</firstterm> and
+          <firstterm>methods</firstterm>. Objects are referred to by a name,
+          called a <firstterm>path</firstterm>.
+        </para>
+      </glossdef>
+    </glossentry>
+
+    <glossentry id="one-to-one"><glossterm>One-to-One</glossterm>
+      <glossdef>
+	<para>
+          An application talking directly to another application, without going
+          through a message bus. One-to-one connections may be "peer to peer" or
+          "client to server." The D-Bus protocol has no concept of client
+          vs. server after a connection has authenticated; the flow of messages
+          is symmetrical (full duplex).
+        </para>
+      </glossdef>
+    </glossentry>
+
+    <glossentry id="term-path"><glossterm>Path</glossterm>
+      <glossdef>
+        <para>
+          Object references (object names) in D-Bus are organized into a
+          filesystem-style hierarchy, so each object is named by a path. As in
+          LDAP, there's no difference between "files" and "directories"; a path
+          can refer to an object, while still having child objects below it.
+        </para>
+      </glossdef>
+    </glossentry>
+
+    <glossentry id="term-queued-owner"><glossterm>Queued Name Owner</glossterm>
+      <glossdef>
+        <para>
+          Each bus name has a primary owner; messages sent to the name go to the
+          primary owner. However, certain names also maintain a queue of
+          secondary owners "waiting in the wings." If the primary owner releases
+          the name, then the first secondary owner in the queue automatically
+          becomes the new owner of the name.
+        </para>
+      </glossdef>
+    </glossentry>
+
+    <glossentry id="term-service"><glossterm>Service</glossterm>
+      <glossdef>
+        <para>
+          A service is an executable that can be launched by the bus daemon.
+          Services normally guarantee some particular features, for example they
+          may guarantee that they will request a specific name such as
+          "org.freedesktop.Screensaver", have a singleton object
+          "/org/freedesktop/Application", and that object will implement the
+          interface "org.freedesktop.ScreensaverControl".
+        </para>
+      </glossdef>
+    </glossentry>
+
+    <glossentry id="term-service-description-files"><glossterm>Service Description Files</glossterm>
+      <glossdef>
+        <para>
+          ".service files" tell the bus about service applications that can be
+          launched (see <xref linkend="term-service"/>). Most importantly they
+          provide a mapping from bus names to services that will request those
+            names when they start up.
+        </para>
+      </glossdef>
+    </glossentry>
+
+    <glossentry id="term-unique-name"><glossterm>Unique Connection Name</glossterm>
+      <glossdef>
+        <para>
+          The special name automatically assigned to each connection by the
+          message bus. This name will never change owner, and will be unique
+          (never reused during the lifetime of the message bus).
+          It will begin with a ':' character.
+        </para>
+      </glossdef>
+    </glossentry>
+
+  </glossary>
+</article>
diff --git a/dbus/doc/dbus-test-plan.xml b/dbus/doc/dbus-test-plan.xml
new file mode 100644
index 0000000..e6aafb9
--- /dev/null
+++ b/dbus/doc/dbus-test-plan.xml
@@ -0,0 +1,232 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+]>
+
+<article id="index">
+  <articleinfo>
+    <title>D-Bus Test Plan</title>
+    <date>14 February 2003</date>
+    <authorgroup>
+      <author>
+	<firstname>Anders</firstname>
+	<surname>Carlsson</surname>
+	<affiliation>
+	  <orgname>CodeFactory AB</orgname>
+	  <address><email>andersca@codefactory.se</email></address>
+	</affiliation>
+      </author>
+    </authorgroup>
+  </articleinfo>
+  <sect1 id="introduction">
+    <title>Introduction</title>
+    <para>
+      This document tries to explain the details of the test plan for D-Bus
+    </para>
+    <sect2 id="importance-of-testing">
+      <title>The importance of testing</title>
+      <para>
+        As with any big library or program, testing is important. It
+        can help find bugs and regressions and make the code better
+        overall. 
+      </para>
+      <para>
+        D-Bus is a large and complex piece of software (about 25,000
+        lines of code for the client library, and 2,500 lines of code
+        for the bus daemon) and it's therefore important to try to make sure
+        that all parts of the software is functioning correctly.
+      </para>
+      <para>
+        D-Bus can be built with support for testing by passing
+        <literal>--enable-tests</literal>. to the configure script. It
+        is recommended that production systems build without testing
+        since that reduces the D-Bus client library size.
+      </para>
+    </sect2>
+  </sect1>
+  <sect1 id="client-library">
+    <title>Testing the D-Bus client library</title>
+    <para>
+      The tests for the client library consist of the dbus-test
+      program which is a unit test for all aspects of the client
+      library. Whenever a bug in the client library is found and
+      fixed, a test is added to make sure that the bug won't occur again.
+    </para>
+    <sect2 id="data-structures">
+      <title>Data Structures</title>
+      <para>
+      The D-Bus client library consists of some data structures that
+      are used internally; a linked list class, a hashtable class and
+      a string class. All aspects of those are tested by dbus-test.
+      </para>
+    </sect2>
+    <sect2 id="message-loader">
+      <title>Message loader</title>
+      <para>
+        The message loader is the part of D-Bus that takes messages in
+        raw character form and parses them, turning them into DBusMessages.
+      </para>
+      <para>
+        This is one of the parts of D-Bus that
+        <emphasis>must</emphasis> be absolutely bug-free and
+        robust. The message loader should be able to handle invalid
+        and incomplete messages without crashing. Not doing so is a
+        serious issue and can easily result in D-Bus being exploitable
+        to DoS attacks.
+      </para>
+      <para>
+        To solve these problems, there is a testing feature called the
+        Message Builder. The message builder can take a serialized
+        message in string-form and convert it into a raw character
+        string which can then be loaded by the message loader. 
+      </para>
+      <figure>
+	<title>Example of a message in string form</title>
+	<programlisting>
+          # Standard org.freedesktop.DBus.Hello message
+
+          VALID_HEADER
+          FIELD_NAME name
+          TYPE STRING
+          STRING 'org.freedesktop.DBus.Hello'
+          FIELD_NAME srvc
+          TYPE STRING
+          STRING 'org.freedesktop.DBus'
+          ALIGN 8
+          END_LENGTH Header
+          START_LENGTH Body
+          END_LENGTH Body
+        </programlisting>
+      </figure>
+      <para>
+        The file format of messages in string form is documented in
+        the D-Bus Reference Manual.
+      </para>
+      <para>
+        The message test part of dbus-test is using the message
+        builder to build different kinds of messages, both valid,
+        invalid, and invalid ones, to make sure that the loader won't
+        crash or leak memory of any of those, and that the loader
+        knows if a message is valid or not.
+      </para>
+      <para>
+        There is also a test program called
+        <literal>break-loader</literal> that loads a message in
+        string-form into raw character form using the message
+        builder. It then randomly changes the message, it can for
+        example replace single bytes of data or modify the length of
+        the message. This is to simulate network errors. The
+        break-loader program saves all the messages leading to errors
+        so it can easily be run for a long period of time.
+      </para>
+    </sect2>
+    <sect2 id="authentication">
+      <title>Authentication</title>
+      <para>
+        For testing authentication, there is a testing feature that
+        can read authentication sequences from a file and play them
+        back to a dummy server and client to make sure that
+        authentication is working according to the specification.
+      </para>
+      <figure>
+	<title>Example of an authentication script</title>
+	<programlisting>
+          ## this tests a successful auth of type EXTERNAL
+          
+          SERVER
+          SEND 'AUTH EXTERNAL USERNAME_HEX'
+          EXPECT_COMMAND OK
+          EXPECT_STATE WAITING_FOR_INPUT
+          SEND 'BEGIN'
+          EXPECT_STATE AUTHENTICATED
+        </programlisting>
+      </figure>
+    </sect2>
+  </sect1>
+  <sect1 id="daemon">
+    <title>Testing the D-Bus bus daemon</title>
+    <para>
+      Since the D-Bus bus daemon is using the D-Bus client library it
+      will benefit from all tests done on the client library, but
+      there is still the issue of testing client-server communication.
+      This is more complicated since it it may require another process
+      running.
+    </para>
+    <sect2 id="debug-transport">
+      <title>The debug transport</title>
+      <para>
+        In D-Bus, a <emphasis>transport</emphasis> is a class that
+        handles sending and receiving raw data over a certain
+        medium. The transport that is used most in D-Bus is the UNIX
+        transport with sends and recevies data over a UNIX socket. A
+        transport that tunnels data through X11 client messages is
+        also under development.
+      </para>
+      <para>
+        The D-Bus debug transport is a specialized transport that
+        works in-process. This means that a client and server that
+        exists in the same process can talk to eachother without using
+        a socket.
+      </para>
+    </sect2>
+    <sect2 id="bus-test">
+      <title>The bus-test program</title>
+      <para>
+        The bus-test program is a program that is used to test various
+        parts of the D-Bus bus daemon; robustness and that it conforms
+        to the specifications.
+      </para>
+      <para>
+        The test program has the necessary code from the bus daemon
+        linked in, and it uses the debug transport for
+        communication. This means that the bus daemon code can be
+        tested without the real bus actually running, which makes
+        testing easier.
+      </para>
+      <para>
+        The bus-test program should test all major features of the
+        bus, such as service registration, notification when things
+        occurs and message matching.
+      </para>
+    </sect2>
+  </sect1>
+  <sect1 id="other-tests">
+    <title>Other tests</title>
+
+    <sect2 id="oom-robustness">
+      <title>Out-Of-Memory robustness</title>
+      <para>
+        Since D-Bus should be able to be used in embedded devices, and
+        also as a system service, it should be able to cope with
+        low-memory situations without exiting or crashing.
+      </para>
+      <para>
+        In practice, this means that both the client and server code
+        must be able to handle dbus_malloc returning NULL. 
+      </para>
+      <para>
+        To test this, two environment variables
+        exist. <literal>DBUS_MALLOC_FAIL_NTH</literal> will make every
+        nth call to dbus_malloc return NULL, and
+        <literal>DBUS_MALLOC_FAIL_GREATER_THAN</literal> will make any
+        dbus_malloc call with a request for more than the specified
+        number of bytes fail.
+      </para>
+    </sect2>
+
+    <sect2 id="leaks-and-other-stuff">
+      <title>Memory leaks and code robustness</title> 
+      <para>
+        Naturally there are some things that tests can't be written
+        for, for example things like memory leaks and out-of-bounds
+        memory reading or writing.
+      </para>
+      <para>
+        Luckily there exists good tools for catching such errors. One
+        free good tool is <ulink url="http://devel-home.kde.org/~sewardj/">Valgrind</ulink>, which runs the program in a
+        virtual CPU which makes catching errors easy. All test programs can be run under Valgrind, 
+      </para>
+    </sect2>
+  </sect1>
+</article>
diff --git a/dbus/doc/dbus-tutorial.xml b/dbus/doc/dbus-tutorial.xml
new file mode 100644
index 0000000..5c385f0
--- /dev/null
+++ b/dbus/doc/dbus-tutorial.xml
@@ -0,0 +1,1667 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+]>
+
+<article id="index">
+  <articleinfo>
+    <title>D-Bus Tutorial</title>
+    <releaseinfo>Version 0.5.0</releaseinfo>
+    <date>20 August 2006</date>
+    <authorgroup>
+      <author>
+	<firstname>Havoc</firstname>
+	<surname>Pennington</surname>
+	<affiliation>
+	  <orgname>Red Hat, Inc.</orgname>
+	  <address><email>hp@pobox.com</email></address>
+	</affiliation>
+      </author>
+      <author>
+	<firstname>David</firstname>
+	<surname>Wheeler</surname>
+      </author>
+      <author>
+	<firstname>John</firstname>
+	<surname>Palmieri</surname>
+	<affiliation>
+	  <orgname>Red Hat, Inc.</orgname>
+	  <address><email>johnp@redhat.com</email></address>
+	</affiliation>
+      </author>
+      <author>
+	<firstname>Colin</firstname>
+	<surname>Walters</surname>
+	<affiliation>
+	  <orgname>Red Hat, Inc.</orgname>
+	  <address><email>walters@redhat.com</email></address>
+	</affiliation>
+      </author>
+    </authorgroup>
+  </articleinfo>
+
+  <sect1 id="meta">
+    <title>Tutorial Work In Progress</title>
+    
+    <para>
+      This tutorial is not complete; it probably contains some useful information, but 
+      also has plenty of gaps. Right now, you'll also need to refer to the D-Bus specification,
+      Doxygen reference documentation, and look at some examples of how other apps use D-Bus.
+    </para>
+
+    <para>
+      Enhancing the tutorial is definitely encouraged - send your patches or suggestions to the
+      mailing list. If you create a D-Bus binding, please add a section to the tutorial for your 
+      binding, if only a short section with a couple of examples.
+    </para>
+
+  </sect1>
+
+  <sect1 id="whatis">
+    <title>What is D-Bus?</title>
+    <para>
+      D-Bus is a system for <firstterm>interprocess communication</firstterm>
+      (IPC). Architecturally, it has several layers:
+
+      <itemizedlist>
+        <listitem>
+          <para>
+            A library, <firstterm>libdbus</firstterm>, that allows two
+            applications to connect to each other and exchange messages.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            A <firstterm>message bus daemon</firstterm> executable, built on
+            libdbus, that multiple applications can connect to. The daemon can
+            route messages from one application to zero or more other
+            applications.
+          </para>
+        </listitem>
+        <listitem>
+          <para>
+            <firstterm>Wrapper libraries</firstterm> or <firstterm>bindings</firstterm> 
+            based on particular application frameworks.  For example, libdbus-glib and
+            libdbus-qt. There are also bindings to languages such as
+            Python. These wrapper libraries are the API most people should use,
+            as they simplify the details of D-Bus programming. libdbus is 
+            intended to be a low-level backend for the higher level bindings.
+            Much of the libdbus API is only useful for binding implementation.
+          </para>
+        </listitem>
+      </itemizedlist>
+    </para>
+
+    <para>
+      libdbus only supports one-to-one connections, just like a raw network
+      socket. However, rather than sending byte streams over the connection, you
+      send <firstterm>messages</firstterm>. Messages have a header identifying
+      the kind of message, and a body containing a data payload. libdbus also
+      abstracts the exact transport used (sockets vs. whatever else), and
+      handles details such as authentication.
+    </para>
+
+    <para>
+      The message bus daemon forms the hub of a wheel. Each spoke of the wheel
+      is a one-to-one connection to an application using libdbus.  An
+      application sends a message to the bus daemon over its spoke, and the bus
+      daemon forwards the message to other connected applications as
+      appropriate. Think of the daemon as a router.
+    </para>
+
+    <para>
+      The bus daemon has multiple instances on a typical computer.  The
+      first instance is a machine-global singleton, that is, a system daemon
+      similar to sendmail or Apache. This instance has heavy security
+      restrictions on what messages it will accept, and is used for systemwide
+      communication. The other instances are created one per user login session.
+      These instances allow applications in the user's session to communicate 
+      with one another.
+    </para>
+
+    <para>
+      The systemwide and per-user daemons are separate.  Normal within-session
+      IPC does not involve the systemwide message bus process and vice versa.
+    </para>
+
+    <sect2 id="uses">
+      <title>D-Bus applications</title>
+      <para>
+        There are many, many technologies in the world that have "Inter-process
+        communication" or "networking" in their stated purpose: <ulink
+        url="http://www.omg.org">CORBA</ulink>, <ulink
+        url="http://www.opengroup.org/dce/">DCE</ulink>, <ulink
+        url="http://www.microsoft.com/com/">DCOM</ulink>, <ulink
+        url="http://developer.kde.org/documentation/library/kdeqt/dcop.html">DCOP</ulink>, <ulink
+        url="http://www.xmlrpc.com">XML-RPC</ulink>, <ulink
+        url="http://www.w3.org/TR/SOAP/">SOAP</ulink>, <ulink
+        url="http://www.mbus.org/">MBUS</ulink>, <ulink
+        url="http://www.zeroc.com/ice.html">Internet Communications Engine (ICE)</ulink>,
+        and probably hundreds more.
+        Each of these is tailored for particular kinds of application.
+        D-Bus is designed for two specific cases:
+        <itemizedlist>
+          <listitem>
+            <para>
+              Communication between desktop applications in the same desktop
+              session; to allow integration of the desktop session as a whole,
+              and address issues of process lifecycle (when do desktop components 
+              start and stop running).
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Communication between the desktop session and the operating system, 
+              where the operating system would typically include the kernel 
+              and any system daemons or processes.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+      <para>
+        For the within-desktop-session use case, the GNOME and KDE desktops 
+        have significant previous experience with different IPC solutions
+        such as CORBA and DCOP. D-Bus is built on that experience and 
+        carefully tailored to meet the needs of these desktop projects 
+        in particular. D-Bus may or may not be appropriate for other 
+        applications; the FAQ has some comparisons to other IPC systems.
+      </para>
+      <para>
+        The problem solved by the systemwide or communication-with-the-OS case 
+        is explained well by the following text from the Linux Hotplug project:
+        <blockquote>
+          <para>
+           A gap in current Linux support is that policies with any sort of
+           dynamic "interact with user" component aren't currently
+           supported. For example, that's often needed the first time a network
+           adapter or printer is connected, and to determine appropriate places
+           to mount disk drives. It would seem that such actions could be
+           supported for any case where a responsible human can be identified:
+           single user workstations, or any system which is remotely
+           administered.
+          </para>
+
+          <para>
+            This is a classic "remote sysadmin" problem, where in this case
+            hotplugging needs to deliver an event from one security domain
+            (operating system kernel, in this case) to another (desktop for
+            logged-in user, or remote sysadmin). Any effective response must go
+            the other way: the remote domain taking some action that lets the
+            kernel expose the desired device capabilities. (The action can often
+            be taken asynchronously, for example letting new hardware be idle
+            until a meeting finishes.) At this writing, Linux doesn't have
+            widely adopted solutions to such problems. However, the new D-Bus
+            work may begin to solve that problem.
+          </para>
+        </blockquote>
+      </para>
+      <para>
+        D-Bus may happen to be useful for purposes other than the one it was
+        designed for. Its general properties that distinguish it from 
+        other forms of IPC are:
+        <itemizedlist>
+          <listitem>
+            <para>
+              Binary protocol designed to be used asynchronously 
+              (similar in spirit to the X Window System protocol).
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Stateful, reliable connections held open over time.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The message bus is a daemon, not a "swarm" or 
+              distributed architecture.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Many implementation and deployment issues are specified rather
+              than left ambiguous/configurable/pluggable.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Semantics are similar to the existing DCOP system, allowing 
+              KDE to adopt it more easily.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Security features to support the systemwide mode of the 
+              message bus.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+    </sect2>
+  </sect1>
+  <sect1 id="concepts">
+    <title>Concepts</title>
+    <para>
+      Some basic concepts apply no matter what application framework you're
+      using to write a D-Bus application. The exact code you write will be
+      different for GLib vs. Qt vs. Python applications, however.
+    </para>
+    
+    <para>
+      Here is a diagram (<ulink url="diagram.png">png</ulink> <ulink
+      url="diagram.svg">svg</ulink>) that may help you visualize the concepts
+      that follow.
+    </para>
+
+    <sect2 id="objects">
+      <title>Native Objects and Object Paths</title>
+      <para>
+        Your programming framework probably defines what an "object" is like;
+        usually with a base class. For example: java.lang.Object, GObject, QObject,
+        python's base Object, or whatever. Let's call this a <firstterm>native object</firstterm>.
+      </para>
+      <para>
+        The low-level D-Bus protocol, and corresponding libdbus API, does not care about native objects. 
+        However, it provides a concept called an 
+        <firstterm>object path</firstterm>. The idea of an object path is that 
+        higher-level bindings can name native object instances, and allow remote applications 
+        to refer to them.
+      </para>
+      <para>
+        The object path
+        looks like a filesystem path, for example an object could be 
+        named <literal>/org/kde/kspread/sheets/3/cells/4/5</literal>. 
+        Human-readable paths are nice, but you are free to create an 
+        object named <literal>/com/mycompany/c5yo817y0c1y1c5b</literal> 
+        if it makes sense for your application.
+      </para>
+      <para>
+        Namespacing object paths is smart, by starting them with the components
+        of a domain name you own (e.g. <literal>/org/kde</literal>). This 
+        keeps different code modules in the same process from stepping 
+        on one another's toes.
+      </para>
+    </sect2>    
+
+    <sect2 id="members">
+      <title>Methods and Signals</title>
+
+      <para>
+        Each object has <firstterm>members</firstterm>; the two kinds of member
+        are <firstterm>methods</firstterm> and
+        <firstterm>signals</firstterm>. Methods are operations that can be
+        invoked on an object, with optional input (aka arguments or "in
+        parameters") and output (aka return values or "out parameters").
+        Signals are broadcasts from the object to any interested observers 
+        of the object; signals may contain a data payload.
+      </para>
+
+      <para>
+        Both methods and signals are referred to by name, such as 
+        "Frobate" or "OnClicked".
+      </para>
+
+    </sect2>
+
+    <sect2 id="interfaces">
+      <title>Interfaces</title>
+      <para>
+        Each object supports one or more <firstterm>interfaces</firstterm>.
+        Think of an interface as a named group of methods and signals, 
+        just as it is in GLib or Qt or Java. Interfaces define the 
+        <emphasis>type</emphasis> of an object instance.
+      </para>
+      <para>
+        DBus identifies interfaces with a simple namespaced string,
+        something like <literal>org.freedesktop.Introspectable</literal>.
+        Most bindings will map these interface names directly to 
+        the appropriate programming language construct, for example 
+        to Java interfaces or C++ pure virtual classes.
+      </para>
+    </sect2>
+
+    <sect2 id="proxies">
+      <title>Proxies</title>
+      <para>
+        A <firstterm>proxy object</firstterm> is a convenient native object created to 
+        represent a remote object in another process. The low-level DBus API involves manually creating 
+        a method call message, sending it, then manually receiving and processing 
+        the method reply message. Higher-level bindings provide proxies as an alternative.
+        Proxies look like a normal native object; but when you invoke a method on the proxy 
+        object, the binding converts it into a DBus method call message, waits for the reply 
+        message, unpacks the return value, and returns it from the native method..
+      </para>
+      <para>
+        In pseudocode, programming without proxies might look like this:
+        <programlisting>
+          Message message = new Message("/remote/object/path", "MethodName", arg1, arg2);
+          Connection connection = getBusConnection();
+          connection.send(message);
+          Message reply = connection.waitForReply(message);
+          if (reply.isError()) {
+             
+          } else {
+             Object returnValue = reply.getReturnValue();
+          }
+        </programlisting>
+      </para>
+      <para>
+        Programming with proxies might look like this:
+        <programlisting>
+          Proxy proxy = new Proxy(getBusConnection(), "/remote/object/path");
+          Object returnValue = proxy.MethodName(arg1, arg2);
+        </programlisting>
+      </para>
+    </sect2>
+
+    <sect2 id="bus-names">
+      <title>Bus Names</title>
+
+      <para>
+        When each application connects to the bus daemon, the daemon immediately
+        assigns it a name, called the <firstterm>unique connection name</firstterm>.
+        A unique name begins with a ':' (colon) character. These names are never 
+        reused during the lifetime of the bus daemon - that is, you know 
+        a given name will always refer to the same application.
+        An example of a unique name might be
+        <literal>:34-907</literal>. The numbers after the colon have 
+        no meaning other than their uniqueness.
+      </para>
+
+      <para>
+        When a name is mapped 
+        to a particular application's connection, that application is said to 
+        <firstterm>own</firstterm> that name.
+      </para>
+
+      <para>
+        Applications may ask to own additional <firstterm>well-known
+        names</firstterm>. For example, you could write a specification to
+        define a name called <literal>com.mycompany.TextEditor</literal>.
+        Your definition could specify that to own this name, an application
+        should have an object at the path
+        <literal>/com/mycompany/TextFileManager</literal> supporting the
+        interface <literal>org.freedesktop.FileHandler</literal>.
+      </para>
+      
+      <para>
+        Applications could then send messages to this bus name, 
+        object, and interface to execute method calls.
+      </para>
+
+      <para>
+        You could think of the unique names as IP addresses, and the
+        well-known names as domain names. So
+        <literal>com.mycompany.TextEditor</literal> might map to something like
+        <literal>:34-907</literal> just as <literal>mycompany.com</literal> maps
+        to something like <literal>192.168.0.5</literal>.
+      </para>
+      
+      <para>
+        Names have a second important use, other than routing messages.  They
+        are used to track lifecycle. When an application exits (or crashes), its
+        connection to the message bus will be closed by the operating system
+        kernel. The message bus then sends out notification messages telling
+        remaining applications that the application's names have lost their
+        owner. By tracking these notifications, your application can reliably
+        monitor the lifetime of other applications.
+      </para>
+
+      <para>
+        Bus names can also be used to coordinate single-instance applications.
+        If you want to be sure only one
+        <literal>com.mycompany.TextEditor</literal> application is running for
+        example, have the text editor application exit if the bus name already
+        has an owner.
+      </para>
+
+    </sect2>
+
+    <sect2 id="addresses">
+      <title>Addresses</title>
+
+      <para>
+        Applications using D-Bus are either servers or clients.  A server
+        listens for incoming connections; a client connects to a server. Once
+        the connection is established, it is a symmetric flow of messages; the
+        client-server distinction only matters when setting up the 
+        connection.
+      </para>
+
+      <para>
+        If you're using the bus daemon, as you probably are, your application 
+        will be a client of the bus daemon. That is, the bus daemon listens 
+        for connections and your application initiates a connection to the bus 
+        daemon.
+      </para>
+
+      <para>
+        A D-Bus <firstterm>address</firstterm> specifies where a server will
+        listen, and where a client will connect.  For example, the address
+        <literal>unix:path=/tmp/abcdef</literal> specifies that the server will
+        listen on a UNIX domain socket at the path
+        <literal>/tmp/abcdef</literal> and the client will connect to that
+        socket. An address can also specify TCP/IP sockets, or any other
+        transport defined in future iterations of the D-Bus specification.
+      </para>
+
+      <para>
+        When using D-Bus with a message bus daemon,
+        libdbus automatically discovers the address of the per-session bus 
+        daemon by reading an environment variable. It discovers the 
+        systemwide bus daemon by checking a well-known UNIX domain socket path
+        (though you can override this address with an environment variable).
+      </para>
+
+      <para>
+        If you're using D-Bus without a bus daemon, it's up to you to 
+        define which application will be the server and which will be 
+        the client, and specify a mechanism for them to agree on 
+        the server's address. This is an unusual case.
+      </para>
+
+    </sect2>
+
+    <sect2 id="bigpicture">
+      <title>Big Conceptual Picture</title>
+
+      <para>
+        Pulling all these concepts together, to specify a particular 
+        method call on a particular object instance, a number of 
+        nested components have to be named:
+        <programlisting>
+          Address -&gt; [Bus Name] -&gt; Path -&gt; Interface -&gt; Method
+        </programlisting>
+        The bus name is in brackets to indicate that it's optional -- you only
+        provide a name to route the method call to the right application
+        when using the bus daemon. If you have a direct connection to another
+        application, bus names aren't used; there's no bus daemon.
+      </para>
+
+      <para>
+        The interface is also optional, primarily for historical 
+        reasons; DCOP does not require specifying the interface, 
+        instead simply forbidding duplicate method names 
+        on the same object instance. D-Bus will thus let you 
+        omit the interface, but if your method name is ambiguous 
+        it is undefined which method will be invoked.
+      </para>
+
+    </sect2>
+
+    <sect2 id="messages">
+      <title>Messages - Behind the Scenes</title>
+      <para>
+        D-Bus works by sending messages between processes. If you're using 
+        a sufficiently high-level binding, you may never work with messages directly.
+      </para>
+      <para>
+        There are 4 message types:
+        <itemizedlist>
+          <listitem>
+            <para>
+              Method call messages ask to invoke a method 
+              on an object.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Method return messages return the results 
+              of invoking a method.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Error messages return an exception caused by 
+              invoking a method.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Signal messages are notifications that a given signal 
+              has been emitted (that an event has occurred). 
+              You could also think of these as "event" messages.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+      <para>
+        A method call maps very simply to messages: you send a method call
+        message, and receive either a method return message or an error message
+        in reply.
+      </para>
+      <para>
+        Each message has a <firstterm>header</firstterm>, including <firstterm>fields</firstterm>, 
+        and a <firstterm>body</firstterm>, including <firstterm>arguments</firstterm>. You can think 
+        of the header as the routing information for the message, and the body as the payload.
+        Header fields might include the sender bus name, destination bus name, method or signal name, 
+        and so forth. One of the header fields is a <firstterm>type signature</firstterm> describing the 
+        values found in the body. For example, the letter "i" means "32-bit integer" so the signature 
+        "ii" means the payload has two 32-bit integers.
+      </para>
+    </sect2>
+
+    <sect2 id="callprocedure">
+      <title>Calling a Method - Behind the Scenes</title>
+
+      <para>
+        A method call in DBus consists of two messages; a method call message sent from process A to process B, 
+        and a matching method reply message sent from process B to process A. Both the call and the reply messages
+        are routed through the bus daemon. The caller includes a different serial number in each call message, and the
+        reply message includes this number to allow the caller to match replies to calls.
+      </para>
+
+      <para>
+        The call message will contain any arguments to the method.
+        The reply message may indicate an error, or may contain data returned by the method.
+      </para>
+
+      <para>
+        A method invocation in DBus happens as follows:
+        <itemizedlist>
+          <listitem>
+            <para>
+              The language binding may provide a proxy, such that invoking a method on 
+              an in-process object invokes a method on a remote object in another process. If so, the 
+              application calls a method on the proxy, and the proxy
+              constructs a method call message to send to the remote process.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              For more low-level APIs, the application may construct a method call message itself, without
+              using a proxy.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              In either case, the method call message contains: a bus name belonging to the remote process; the name of the method; 
+              the arguments to the method; an object path inside the remote process; and optionally the name of the 
+              interface that specifies the method.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The method call message is sent to the bus daemon.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The bus daemon looks at the destination bus name. If a process owns that name, 
+              the bus daemon forwards the method call to that process. Otherwise, the bus daemon
+              creates an error message and sends it back as the reply to the method call message.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The receiving process unpacks the method call message. In a simple low-level API situation, it 
+              may immediately run the method and send a method reply message to the bus daemon.
+              When using a high-level binding API, the binding might examine the object path, interface,
+              and method name, and convert the method call message into an invocation of a method on 
+              a native object (GObject, java.lang.Object, QObject, etc.), then convert the return 
+              value from the native method into a method reply message.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The bus daemon receives the method reply message and sends it to the process that 
+              made the method call.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The process that made the method call looks at the method reply and makes use of any 
+              return values included in the reply. The reply may also indicate that an error occurred.
+              When using a binding, the method reply message may be converted into the return value of 
+              of a proxy method, or into an exception.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+
+      <para>
+        The bus daemon never reorders messages. That is, if you send two method call messages to the same recipient, 
+        they will be received in the order they were sent. The recipient is not required to reply to the calls
+        in order, however; for example, it may process each method call in a separate thread, and return reply messages
+        in an undefined order depending on when the threads complete. Method calls have a unique serial 
+        number used by the method caller to match reply messages to call messages.
+      </para>
+
+    </sect2>
+
+    <sect2 id="signalprocedure">
+      <title>Emitting a Signal - Behind the Scenes</title>
+
+      <para>
+        A signal in DBus consists of a single message, sent by one process to any number of other processes. 
+        That is, a signal is a unidirectional broadcast. The signal may contain arguments (a data payload), but 
+        because it is a broadcast, it never has a "return value." Contrast this with a method call 
+        (see <xref linkend="callprocedure"/>) where the method call message has a matching method reply message.
+      </para>
+
+      <para>
+        The emitter (aka sender) of a signal has no knowledge of the signal recipients. Recipients register
+        with the bus daemon to receive signals based on "match rules" - these rules would typically include the sender and 
+        the signal name. The bus daemon sends each signal only to recipients who have expressed interest in that 
+        signal.
+      </para>
+
+      <para>
+        A signal in DBus happens as follows:
+        <itemizedlist>
+          <listitem>
+            <para>
+              A signal message is created and sent to the bus daemon. When using the low-level API this may be 
+              done manually, with certain bindings it may be done for you by the binding when a native object
+              emits a native signal or event.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The signal message contains the name of the interface that specifies the signal;
+              the name of the signal; the bus name of the process sending the signal; and 
+              any arguments 
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Any process on the message bus can register "match rules" indicating which signals it 
+              is interested in. The bus has a list of registered match rules.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              The bus daemon examines the signal and determines which processes are interested in it.
+              It sends the signal message to these processes.
+            </para>
+          </listitem>
+          <listitem>
+            <para>
+              Each process receiving the signal decides what to do with it; if using a binding, 
+              the binding may choose to emit a native signal on a proxy object. If using the 
+              low-level API, the process may just look at the signal sender and name and decide
+              what to do based on that.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+
+    </sect2>
+
+    <sect2 id="introspection">
+      <title>Introspection</title>
+
+      <para>
+        D-Bus objects may support the interface <literal>org.freedesktop.DBus.Introspectable</literal>.
+        This interface has one method <literal>Introspect</literal> which takes no arguments and returns
+        an XML string. The XML string describes the interfaces, methods, and signals of the object.
+        See the D-Bus specification for more details on this introspection format.
+      </para>
+
+    </sect2>
+
+  </sect1>
+
+  <sect1 id="glib-client">
+    <title>GLib API: Using Remote Objects</title>
+
+    <para>
+      The GLib binding is defined in the header file
+      <literal>&lt;dbus/dbus-glib.h&gt;</literal>.
+    </para>
+
+    <sect2 id="glib-typemappings">
+      <title>D-Bus - GLib type mappings</title>
+      <para>
+	The heart of the GLib bindings for D-Bus is the mapping it
+	provides between D-Bus "type signatures" and GLib types
+	(<literal>GType</literal>). The D-Bus type system is composed of
+	a number of "basic" types, along with several "container" types.
+      </para>
+      <sect3 id="glib-basic-typemappings">
+	<title>Basic type mappings</title>
+	<para>
+	  Below is a list of the basic types, along with their associated
+	  mapping to a <literal>GType</literal>.
+	  <informaltable>
+	    <tgroup cols="4">
+	      <thead>
+		<row>
+		  <entry>D-Bus basic type</entry>
+		  <entry>GType</entry>
+		  <entry>Free function</entry>
+		  <entry>Notes</entry>
+		</row>
+	      </thead>
+	      <tbody>
+		<row>
+		  <entry><literal>BYTE</literal></entry>
+		  <entry><literal>G_TYPE_UCHAR</literal></entry>
+		  <entry></entry>
+		  <entry></entry>
+		  </row><row>
+		  <entry><literal>BOOLEAN</literal></entry>
+		  <entry><literal>G_TYPE_BOOLEAN</literal></entry>
+		  <entry></entry>
+		  <entry></entry>
+		  </row><row>
+		  <entry><literal>INT16</literal></entry>
+		  <entry><literal>G_TYPE_INT</literal></entry>
+		  <entry></entry>
+		  <entry>Will be changed to a <literal>G_TYPE_INT16</literal> once GLib has it</entry>
+		  </row><row>
+		  <entry><literal>UINT16</literal></entry>
+		  <entry><literal>G_TYPE_UINT</literal></entry>
+		  <entry></entry>
+		  <entry>Will be changed to a <literal>G_TYPE_UINT16</literal> once GLib has it</entry>
+		  </row><row>
+		  <entry><literal>INT32</literal></entry>
+		  <entry><literal>G_TYPE_INT</literal></entry>
+		  <entry></entry>
+		  <entry>Will be changed to a <literal>G_TYPE_INT32</literal> once GLib has it</entry>
+		  </row><row>
+		  <entry><literal>UINT32</literal></entry>
+		  <entry><literal>G_TYPE_UINT</literal></entry>
+		  <entry></entry>
+		  <entry>Will be changed to a <literal>G_TYPE_UINT32</literal> once GLib has it</entry>
+		  </row><row>
+		  <entry><literal>INT64</literal></entry>
+		  <entry><literal>G_TYPE_GINT64</literal></entry>
+		  <entry></entry>
+		  <entry></entry>
+		  </row><row>
+		  <entry><literal>UINT64</literal></entry>
+		  <entry><literal>G_TYPE_GUINT64</literal></entry>
+		  <entry></entry>
+		  <entry></entry>
+		  </row><row>
+		  <entry><literal>DOUBLE</literal></entry>
+		  <entry><literal>G_TYPE_DOUBLE</literal></entry>
+		  <entry></entry>
+		  <entry></entry>
+		  </row><row>
+		  <entry><literal>STRING</literal></entry>
+		  <entry><literal>G_TYPE_STRING</literal></entry>
+		  <entry><literal>g_free</literal></entry>
+		  <entry></entry>
+		  </row><row>
+		  <entry><literal>OBJECT_PATH</literal></entry>
+		  <entry><literal>DBUS_TYPE_G_PROXY</literal></entry>
+		  <entry><literal>g_object_unref</literal></entry>
+		  <entry>The returned proxy does not have an interface set; use <literal>dbus_g_proxy_set_interface</literal> to invoke methods</entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	  As you can see, the basic mapping is fairly straightforward.
+	</para>
+      </sect3>
+      <sect3 id="glib-container-typemappings">
+	<title>Container type mappings</title>
+	<para>
+	  The D-Bus type system also has a number of "container"
+	  types, such as <literal>DBUS_TYPE_ARRAY</literal> and
+	  <literal>DBUS_TYPE_STRUCT</literal>.  The D-Bus type system
+	  is fully recursive, so one can for example have an array of
+	  array of strings (i.e. type signature
+	  <literal>aas</literal>).
+	</para>
+	<para>
+	  However, not all of these types are in common use; for
+	  example, at the time of this writing the author knows of no
+	  one using <literal>DBUS_TYPE_STRUCT</literal>, or a
+	  <literal>DBUS_TYPE_ARRAY</literal> containing any non-basic
+	  type.  The approach the GLib bindings take is pragmatic; try
+	  to map the most common types in the most obvious way, and
+	  let using less common and more complex types be less
+	  "natural".
+	</para>
+	<para>
+	  First, D-Bus type signatures which have an "obvious"
+	  corresponding built-in GLib type are mapped using that type:
+	  <informaltable>
+	    <tgroup cols="6">
+	      <thead>
+		<row>
+		  <entry>D-Bus type signature</entry>
+		  <entry>Description</entry>
+		  <entry>GType</entry>
+		  <entry>C typedef</entry>
+		  <entry>Free function</entry>
+		  <entry>Notes</entry>
+		</row>
+	      </thead>
+	      <tbody>
+		<row>
+		  <entry><literal>as</literal></entry>
+		  <entry>Array of strings</entry>
+		  <entry><literal>G_TYPE_STRV</literal></entry>
+		  <entry><literal>char **</literal></entry>
+		  <entry><literal>g_strfreev</literal></entry>
+		  <entry></entry>
+		  </row><row>
+		  <entry><literal>v</literal></entry>
+		  <entry>Generic value container</entry>
+		  <entry><literal>G_TYPE_VALUE</literal></entry>
+		  <entry><literal>GValue *</literal></entry>
+		  <entry><literal>g_value_unset</literal></entry>
+		  <entry>The calling conventions for values expect that method callers have allocated return values; see below.</entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	</para>
+	<para>
+	  The next most common recursive type signatures are arrays of
+	  basic values.  The most obvious mapping for arrays of basic
+	  types is a <literal>GArray</literal>.  Now, GLib does not
+	  provide a builtin <literal>GType</literal> for
+	  <literal>GArray</literal>.  However, we actually need more than
+	  that - we need a "parameterized" type which includes the
+	  contained type.  Why we need this we will see below.
+	</para>
+	<para>
+	  The approach taken is to create these types in the D-Bus GLib
+	  bindings; however, there is nothing D-Bus specific about them.
+	  In the future, we hope to include such "fundamental" types in GLib
+	  itself.
+	  <informaltable>
+	    <tgroup cols="6">
+	      <thead>
+		<row>
+		  <entry>D-Bus type signature</entry>
+		  <entry>Description</entry>
+		  <entry>GType</entry>
+		  <entry>C typedef</entry>
+		  <entry>Free function</entry>
+		  <entry>Notes</entry>
+		</row>
+	      </thead>
+	      <tbody>
+		<row>
+		  <entry><literal>ay</literal></entry>
+		  <entry>Array of bytes</entry>
+		  <entry><literal>DBUS_TYPE_G_BYTE_ARRAY</literal></entry>
+		  <entry><literal>GArray *</literal></entry>
+		  <entry>g_array_free</entry>
+		  <entry></entry>
+		</row>
+		<row>
+		  <entry><literal>au</literal></entry>
+		  <entry>Array of uint</entry>
+		  <entry><literal>DBUS_TYPE_G_UINT_ARRAY</literal></entry>
+		  <entry><literal>GArray *</literal></entry>
+		  <entry>g_array_free</entry>
+		  <entry></entry>
+		</row>
+		<row>
+		  <entry><literal>ai</literal></entry>
+		  <entry>Array of int</entry>
+		  <entry><literal>DBUS_TYPE_G_INT_ARRAY</literal></entry>
+		  <entry><literal>GArray *</literal></entry>
+		  <entry>g_array_free</entry>
+		  <entry></entry>
+		</row>
+		<row>
+		  <entry><literal>ax</literal></entry>
+		  <entry>Array of int64</entry>
+		  <entry><literal>DBUS_TYPE_G_INT64_ARRAY</literal></entry>
+		  <entry><literal>GArray *</literal></entry>
+		  <entry>g_array_free</entry>
+		  <entry></entry>
+		</row>
+		<row>
+		  <entry><literal>at</literal></entry>
+		  <entry>Array of uint64</entry>
+		  <entry><literal>DBUS_TYPE_G_UINT64_ARRAY</literal></entry>
+		  <entry><literal>GArray *</literal></entry>
+		  <entry>g_array_free</entry>
+		  <entry></entry>
+		</row>
+		<row>
+		  <entry><literal>ad</literal></entry>
+		  <entry>Array of double</entry>
+		  <entry><literal>DBUS_TYPE_G_DOUBLE_ARRAY</literal></entry>
+		  <entry><literal>GArray *</literal></entry>
+		  <entry>g_array_free</entry>
+		  <entry></entry>
+		</row>
+		<row>
+		  <entry><literal>ab</literal></entry>
+		  <entry>Array of boolean</entry>
+		  <entry><literal>DBUS_TYPE_G_BOOLEAN_ARRAY</literal></entry>
+		  <entry><literal>GArray *</literal></entry>
+		  <entry>g_array_free</entry>
+		  <entry></entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	</para>
+	<para>
+	  D-Bus also includes a special type DBUS_TYPE_DICT_ENTRY which
+	  is only valid in arrays.  It's intended to be mapped to a "dictionary"
+	  type by bindings.  The obvious GLib mapping here is GHashTable.  Again,
+	  however, there is no builtin <literal>GType</literal> for a GHashTable.
+	  Moreover, just like for arrays, we need a parameterized type so that
+	  the bindings can communiate which types are contained in the hash table.
+	</para>
+	<para>
+	  At present, only strings are supported.  Work is in progress to
+	  include more types.
+	  <informaltable>
+	    <tgroup cols="6">
+	      <thead>
+		<row>
+		  <entry>D-Bus type signature</entry>
+		  <entry>Description</entry>
+		  <entry>GType</entry>
+		  <entry>C typedef</entry>
+		  <entry>Free function</entry>
+		  <entry>Notes</entry>
+		</row>
+	      </thead>
+	      <tbody>
+		<row>
+		  <entry><literal>a{ss}</literal></entry>
+		  <entry>Dictionary mapping strings to strings</entry>
+		  <entry><literal>DBUS_TYPE_G_STRING_STRING_HASHTABLE</literal></entry>
+		  <entry><literal>GHashTable *</literal></entry>
+		  <entry>g_hash_table_destroy</entry>
+		  <entry></entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	</para>
+      </sect3>
+      <sect3 id="glib-generic-typemappings">
+	<title>Arbitrarily recursive type mappings</title>
+	<para>
+	  Finally, it is possible users will want to write or invoke D-Bus
+	  methods which have arbitrarily complex type signatures not
+	  directly supported by these bindings.  For this case, we have a
+	  <literal>DBusGValue</literal> which acts as a kind of special
+	  variant value which may be iterated over manually.  The
+	  <literal>GType</literal> associated is
+	  <literal>DBUS_TYPE_G_VALUE</literal>.
+	</para>
+	<para>
+	  TODO insert usage of <literal>DBUS_TYPE_G_VALUE</literal> here.
+	</para>
+      </sect3>
+    </sect2>
+    <sect2 id="sample-program-1">
+      <title>A sample program</title>
+      <para>Here is a D-Bus program using the GLib bindings.
+<programlisting>      
+int
+main (int argc, char **argv)
+{
+  DBusGConnection *connection;
+  GError *error;
+  DBusGProxy *proxy;
+  char **name_list;
+  char **name_list_ptr;
+  
+  g_type_init ();
+
+  error = NULL;
+  connection = dbus_g_bus_get (DBUS_BUS_SESSION,
+                               &amp;error);
+  if (connection == NULL)
+    {
+      g_printerr ("Failed to open connection to bus: %s\n",
+                  error-&gt;message);
+      g_error_free (error);
+      exit (1);
+    }
+
+  /* Create a proxy object for the "bus driver" (name "org.freedesktop.DBus") */
+  
+  proxy = dbus_g_proxy_new_for_name (connection,
+                                     DBUS_SERVICE_DBUS,
+                                     DBUS_PATH_DBUS,
+                                     DBUS_INTERFACE_DBUS);
+
+  /* Call ListNames method, wait for reply */
+  error = NULL;
+  if (!dbus_g_proxy_call (proxy, "ListNames", &amp;error, G_TYPE_INVALID,
+                          G_TYPE_STRV, &amp;name_list, G_TYPE_INVALID))
+    {
+      /* Just do demonstrate remote exceptions versus regular GError */
+      if (error->domain == DBUS_GERROR &amp;&amp; error->code == DBUS_GERROR_REMOTE_EXCEPTION)
+        g_printerr ("Caught remote method exception %s: %s",
+	            dbus_g_error_get_name (error),
+	            error-&gt;message);
+      else
+        g_printerr ("Error: %s\n", error-&gt;message);
+      g_error_free (error);
+      exit (1);
+    }
+
+  /* Print the results */
+ 
+  g_print ("Names on the message bus:\n");
+  
+  for (name_list_ptr = name_list; *name_list_ptr; name_list_ptr++)
+    {
+      g_print ("  %s\n", *name_list_ptr);
+    }
+  g_strfreev (name_list);
+
+  g_object_unref (proxy);
+
+  return 0;
+}
+</programlisting>
+    </para>
+    </sect2>
+    <sect2 id="glib-program-setup">
+      <title>Program initalization</title>
+      <para>
+	A connection to the bus is acquired using
+	<literal>dbus_g_bus_get</literal>.  Next, a proxy
+	is created for the object "/org/freedesktop/DBus" with
+	interface <literal>org.freedesktop.DBus</literal>
+	on the service <literal>org.freedesktop.DBus</literal>.
+	This is a proxy for the message bus itself.
+      </para>
+    </sect2>
+    <sect2 id="glib-method-invocation">
+      <title>Understanding method invocation</title>
+      <para>
+	You have a number of choices for method invocation.  First, as
+	used above, <literal>dbus_g_proxy_call</literal> sends a
+	method call to the remote object, and blocks until a reply is
+	recieved.  The outgoing arguments are specified in the varargs
+	array, terminated with <literal>G_TYPE_INVALID</literal>.
+	Next, pointers to return values are specified, followed again
+	by <literal>G_TYPE_INVALID</literal>.
+      </para>
+      <para>
+	To invoke a method asynchronously, use
+	<literal>dbus_g_proxy_begin_call</literal>.  This returns a
+	<literal>DBusGPendingCall</literal> object; you may then set a
+	notification function using
+	<literal>dbus_g_pending_call_set_notify</literal>.
+      </para>
+    </sect2>
+    <sect2 id="glib-signal-connection">
+      <title>Connecting to object signals</title>
+      <para>
+	You may connect to signals using
+	<literal>dbus_g_proxy_add_signal</literal> and
+	<literal>dbus_g_proxy_connect_signal</literal>.  You must
+	invoke <literal>dbus_g_proxy_add_signal</literal> to specify
+	the signature of your signal handlers; you may then invoke
+	<literal>dbus_g_proxy_connect_signal</literal> multiple times.
+      </para>
+      <para>
+	Note that it will often be the case that there is no builtin
+	marshaller for the type signature of a remote signal.  In that
+	case, you must generate a marshaller yourself by using
+	<application>glib-genmarshal</application>, and then register
+	it using <literal>dbus_g_object_register_marshaller</literal>.
+      </para>
+    </sect2>
+    <sect2 id="glib-error-handling">
+      <title>Error handling and remote exceptions</title>
+      <para>
+	All of the GLib binding methods such as
+	<literal>dbus_g_proxy_end_call</literal> return a
+	<literal>GError</literal>.  This <literal>GError</literal> can
+	represent two different things:
+      <itemizedlist>
+	<listitem>
+	  <para>
+	    An internal D-Bus error, such as an out-of-memory
+	    condition, an I/O error, or a network timeout.  Errors
+	    generated by the D-Bus library itself have the domain
+	    <literal>DBUS_GERROR</literal>, and a corresponding code
+	    such as <literal>DBUS_GERROR_NO_MEMORY</literal>.  It will
+	    not be typical for applications to handle these errors
+	    specifically.
+	  </para>
+	</listitem>
+	<listitem>
+	  <para>
+	    A remote D-Bus exception, thrown by the peer, bus, or
+	    service.  D-Bus remote exceptions have both a textual
+	    "name" and a "message".  The GLib bindings store this
+	    information in the <literal>GError</literal>, but some
+	    special rules apply.
+	  </para>
+	  <para>
+	    The set error will have the domain
+	    <literal>DBUS_GERROR</literal> as above, and will also
+	    have the code
+	    <literal>DBUS_GERROR_REMOTE_EXCEPTION</literal>.  In order
+	    to access the remote exception name, you must use a
+	    special accessor, such as
+	    <literal>dbus_g_error_has_name</literal> or
+	    <literal>dbus_g_error_get_name</literal>.  The remote
+	    exception detailed message is accessible via the regular
+	    GError <literal>message</literal> member.
+	  </para>
+	</listitem>
+      </itemizedlist>
+      </para>
+    </sect2>
+    <sect2 id="glib-more-examples">
+      <title>More examples of method invocation</title>
+      <sect3 id="glib-sending-stuff">
+	<title>Sending an integer and string, receiving an array of bytes</title>
+	<para>
+<programlisting>
+  GArray *arr;
+  
+  error = NULL;
+  if (!dbus_g_proxy_call (proxy, "Foobar", &amp;error,
+                          G_TYPE_INT, 42, G_TYPE_STRING, "hello",
+			  G_TYPE_INVALID,
+			  DBUS_TYPE_G_UCHAR_ARRAY, &amp;arr, G_TYPE_INVALID))
+    {
+      /* Handle error */
+    }
+   g_assert (arr != NULL);
+   printf ("got back %u values", arr->len);
+</programlisting>
+	</para>
+      </sect3>
+      <sect3 id="glib-sending-hash">
+	<title>Sending a GHashTable</title>
+	<para>
+<programlisting>
+  GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
+  guint32 ret;
+  
+  g_hash_table_insert (hash, "foo", "bar");
+  g_hash_table_insert (hash, "baz", "whee");
+
+  error = NULL;
+  if (!dbus_g_proxy_call (proxy, "HashSize", &amp;error,
+                          DBUS_TYPE_G_STRING_STRING_HASH, hash, G_TYPE_INVALID,
+			  G_TYPE_UINT, &amp;ret, G_TYPE_INVALID))
+    {
+      /* Handle error */
+    }
+  g_assert (ret == 2);
+  g_hash_table_destroy (hash);
+</programlisting>
+	</para>
+      </sect3>
+      <sect3 id="glib-receiving-bool-int">
+	<title>Receiving a boolean and a string</title>
+	<para>
+<programlisting>
+  gboolean boolret;
+  char *strret;
+  
+  error = NULL;
+  if (!dbus_g_proxy_call (proxy, "GetStuff", &amp;error,
+			  G_TYPE_INVALID,
+                          G_TYPE_BOOLEAN, &amp;boolret,
+                          G_TYPE_STRING, &amp;strret,
+			  G_TYPE_INVALID))
+    {
+      /* Handle error */
+    }
+  printf ("%s %s", boolret ? "TRUE" : "FALSE", strret);
+  g_free (strret);
+</programlisting>
+	</para>
+      </sect3>
+      <sect3 id="glib-sending-str-arrays">
+	<title>Sending two arrays of strings</title>
+	<para>
+<programlisting>
+  /* NULL terminate */
+  char *strs_static[] = {"foo", "bar", "baz", NULL};
+  /* Take pointer to array; cannot pass array directly */
+  char **strs_static_p = strs_static;
+  char **strs_dynamic;
+
+  strs_dynamic = g_new (char *, 4);
+  strs_dynamic[0] = g_strdup ("hello");
+  strs_dynamic[1] = g_strdup ("world");
+  strs_dynamic[2] = g_strdup ("!");
+  /* NULL terminate */
+  strs_dynamic[3] = NULL;
+  
+  error = NULL;
+  if (!dbus_g_proxy_call (proxy, "TwoStrArrays", &amp;error,
+                          G_TYPE_STRV, strs_static_p,
+                          G_TYPE_STRV, strs_dynamic,
+			  G_TYPE_INVALID,
+			  G_TYPE_INVALID))
+    {
+      /* Handle error */
+    }
+   g_strfreev (strs_dynamic);
+</programlisting>
+	</para>
+      </sect3>
+      <sect3 id="glib-getting-str-array">
+	<title>Sending a boolean, receiving an array of strings</title>
+	<para>
+<programlisting>
+  char **strs;
+  char **strs_p;
+  gboolean blah;
+
+  error = NULL;
+  blah = TRUE;
+  if (!dbus_g_proxy_call (proxy, "GetStrs", &amp;error,
+                          G_TYPE_BOOLEAN, blah,
+			  G_TYPE_INVALID,
+                          G_TYPE_STRV, &amp;strs,
+			  G_TYPE_INVALID))
+    {
+      /* Handle error */
+    }
+   for (strs_p = strs; *strs_p; strs_p++)
+     printf ("got string: \"%s\"", *strs_p);
+   g_strfreev (strs);
+</programlisting>
+	</para>
+      </sect3>
+      <sect3 id="glib-sending-variant">
+	<title>Sending a variant</title>
+	<para>
+<programlisting>
+  GValue val = {0, };
+
+  g_value_init (&amp;val, G_TYPE_STRING);
+  g_value_set_string (&amp;val, "hello world");
+  
+  error = NULL;
+  if (!dbus_g_proxy_call (proxy, "SendVariant", &amp;error,
+                          G_TYPE_VALUE, &amp;val, G_TYPE_INVALID,
+			  G_TYPE_INVALID))
+    {
+      /* Handle error */
+    }
+  g_assert (ret == 2);
+  g_value_unset (&amp;val);
+</programlisting>
+	</para>
+      </sect3>
+      <sect3 id="glib-receiving-variant">
+	<title>Receiving a variant</title>
+	<para>
+<programlisting>
+  GValue val = {0, };
+
+  error = NULL;
+  if (!dbus_g_proxy_call (proxy, "GetVariant", &amp;error, G_TYPE_INVALID,
+                          G_TYPE_VALUE, &amp;val, G_TYPE_INVALID))
+    {
+      /* Handle error */
+    }
+  if (G_VALUE_TYPE (&amp;val) == G_TYPE_STRING)
+    printf ("%s\n", g_value_get_string (&amp;val));
+  else if (G_VALUE_TYPE (&amp;val) == G_TYPE_INT)
+    printf ("%d\n", g_value_get_int (&amp;val));
+  else
+    ...
+  g_value_unset (&amp;val);
+</programlisting>
+	</para>
+      </sect3>
+    </sect2>
+
+    <sect2 id="glib-generated-bindings">
+      <title>Generated Bindings</title>
+      <para>
+        By using the Introspection XML files, convenient client-side bindings
+        can be automatically created to ease the use of a remote DBus object.
+      </para>
+      <para>
+        Here is a sample XML file which describes an object that exposes
+        one method, named <literal>ManyArgs</literal>.
+        <programlisting>
+&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
+&lt;node name="/com/example/MyObject"&gt;
+  &lt;interface name="com.example.MyObject"&gt;
+    &lt;method name="ManyArgs"&gt;
+      &lt;arg type="u" name="x" direction="in" /&gt;
+      &lt;arg type="s" name="str" direction="in" /&gt;
+      &lt;arg type="d" name="trouble" direction="in" /&gt;
+      &lt;arg type="d" name="d_ret" direction="out" /&gt;
+      &lt;arg type="s" name="str_ret" direction="out" /&gt;
+    &lt;/method&gt;
+  &lt;/interface&gt;
+&lt;/node&gt;
+</programlisting>
+      </para>
+      <para>
+        Run <literal>dbus-binding-tool --mode=glib-client
+          <replaceable>FILENAME</replaceable> &gt;
+          <replaceable>HEADER_NAME</replaceable></literal> to generate the header
+        file.  For example: <command>dbus-binding-tool --mode=glib-client
+          my-object.xml &gt; my-object-bindings.h</command>.  This will generate
+        inline functions with the following prototypes:
+        <programlisting>
+/* This is a blocking call */
+gboolean
+com_example_MyObject_many_args (DBusGProxy *proxy, const guint IN_x,
+                                const char * IN_str, const gdouble IN_trouble,
+                                gdouble* OUT_d_ret, char ** OUT_str_ret,
+                                GError **error);
+
+/* This is a non-blocking call */
+DBusGProxyCall*
+com_example_MyObject_many_args_async (DBusGProxy *proxy, const guint IN_x,
+                                      const char * IN_str, const gdouble IN_trouble,
+                                      com_example_MyObject_many_args_reply callback,
+                                      gpointer userdata);
+
+/* This is the typedef for the non-blocking callback */
+typedef void
+(*com_example_MyObject_many_args_reply)
+(DBusGProxy *proxy, gdouble OUT_d_ret, char * OUT_str_ret,
+ GError *error, gpointer userdata);
+</programlisting>
+        The first argument in all functions is a <literal>DBusGProxy
+        *</literal>, which you should create with the usual
+        <literal>dbus_g_proxy_new_*</literal> functions.  Following that are the
+        "in" arguments, and then either the "out" arguments and a
+        <literal>GError *</literal> for the synchronous (blocking) function, or
+        callback and user data arguments for the asynchronous (non-blocking)
+        function.  The callback in the asynchronous function passes the
+        <literal>DBusGProxy *</literal>, the returned "out" arguments, an
+        <literal>GError *</literal> which is set if there was an error otherwise
+        <literal>NULL</literal>, and the user data.
+      </para>
+      <para>
+        As with the server-side bindings support (see <xref
+        linkend="glib-server"/>), the exact behaviour of the client-side
+        bindings can be manipulated using "annotations".  Currently the only
+        annotation used by the client bindings is
+        <literal>org.freedesktop.DBus.GLib.NoReply</literal>, which sets the
+        flag indicating that the client isn't expecting a reply to the method
+        call, so a reply shouldn't be sent.  This is often used to speed up
+        rapid method calls where there are no "out" arguments, and not knowing
+        if the method succeeded is an acceptable compromise to half the traffic
+        on the bus.
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="glib-server">
+    <title>GLib API: Implementing Objects</title>
+    <para>
+      At the moment, to expose a GObject via D-Bus, you must
+      write XML by hand which describes the methods exported
+      by the object.  In the future, this manual step will
+      be obviated by the upcoming GLib introspection support.
+    </para>
+    <para>
+      Here is a sample XML file which describes an object that exposes
+      one method, named <literal>ManyArgs</literal>.
+<programlisting>
+&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
+
+&lt;node name="/com/example/MyObject"&gt;
+
+  &lt;interface name="com.example.MyObject"&gt;
+    &lt;annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object"/&gt;
+    &lt;method name="ManyArgs"&gt;
+      &lt;!-- This is optional, and in this case is redunundant --&gt;
+      &lt;annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object_many_args"/&gt;
+      &lt;arg type="u" name="x" direction="in" /&gt;
+      &lt;arg type="s" name="str" direction="in" /&gt;
+      &lt;arg type="d" name="trouble" direction="in" /&gt;
+      &lt;arg type="d" name="d_ret" direction="out" /&gt;
+      &lt;arg type="s" name="str_ret" direction="out" /&gt;
+    &lt;/method&gt;
+  &lt;/interface&gt;
+&lt;/node&gt;
+</programlisting>
+    </para>
+    <para>
+      This XML is in the same format as the D-Bus introspection XML
+      format. Except we must include an "annotation" which give the C
+      symbols corresponding to the object implementation prefix
+      (<literal>my_object</literal>).  In addition, if particular
+      methods symbol names deviate from C convention
+      (i.e. <literal>ManyArgs</literal> -&gt;
+      <literal>many_args</literal>), you may specify an annotation
+      giving the C symbol.
+    </para>
+    <para>
+      Once you have written this XML, run <literal>dbus-binding-tool --mode=glib-server <replaceable>FILENAME</replaceable> &gt; <replaceable>HEADER_NAME</replaceable>.</literal> to
+      generate a header file.  For example: <command>dbus-binding-tool --mode=glib-server my-object.xml &gt; my-object-glue.h</command>.
+    </para>
+    <para>
+      Next, include the generated header in your program, and invoke
+      <literal>dbus_g_object_class_install_info</literal> in the class
+      initializer, passing the object class and "object info" included in the
+      header.  For example:
+      <programlisting>
+	dbus_g_object_type_install_info (COM_FOO_TYPE_MY_OBJECT, &amp;com_foo_my_object_info);
+      </programlisting>
+      This should be done exactly once per object class.
+    </para>
+    <para>
+      To actually implement the method, just define a C function named e.g.
+      <literal>my_object_many_args</literal> in the same file as the info
+      header is included.  At the moment, it is required that this function
+      conform to the following rules:
+      <itemizedlist>
+	<listitem>
+	  <para>
+	    The function must return a value of type <literal>gboolean</literal>;
+	    <literal>TRUE</literal> on success, and <literal>FALSE</literal>
+	    otherwise.
+	  </para>
+	</listitem>
+	<listitem>
+	  <para>
+	    The first parameter is a pointer to an instance of the object.
+	  </para>
+	</listitem>
+	<listitem>
+	  <para>
+	    Following the object instance pointer are the method
+	    input values.
+	  </para>
+	</listitem>
+	<listitem>
+	  <para>
+	    Following the input values are pointers to return values.
+	  </para>
+	</listitem>
+	<listitem>
+	  <para>
+	    The final parameter must be a <literal>GError **</literal>.
+	    If the function returns <literal>FALSE</literal> for an
+	    error, the error parameter must be initalized with
+	    <literal>g_set_error</literal>.
+	  </para>
+	</listitem>
+      </itemizedlist>
+    </para>
+    <para>
+      Finally, you can export an object using <literal>dbus_g_connection_register_g_object</literal>.  For example:
+      <programlisting>
+	  dbus_g_connection_register_g_object (connection,
+                                               "/com/foo/MyObject",
+                                               obj);
+      </programlisting>
+    </para>
+
+    <sect2 id="glib-annotations">
+      <title>Server-side Annotations</title>
+      <para>
+        There are several annotations that are used when generating the
+        server-side bindings.  The most common annotation is
+        <literal>org.freedesktop.DBus.GLib.CSymbol</literal> but there are other
+        annotations which are often useful.
+        <variablelist>
+          <varlistentry>
+            <term><literal>org.freedesktop.DBus.GLib.CSymbol</literal></term>
+            <listitem>
+              <para>
+                This annotation is used to specify the C symbol names for
+                the various types (interface, method, etc), if it differs from the
+                name DBus generates.
+              </para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>org.freedesktop.DBus.GLib.Async</literal></term>
+            <listitem>
+              <para>
+                This annotation marks the method implementation as an
+                asynchronous function, which doesn't return a response straight
+                away but will send the response at some later point to complete
+                the call.  This is used to implement non-blocking services where
+                method calls can take time.
+              </para>
+              <para>
+                When a method is asynchronous, the function prototype is
+                different. It is required that the function conform to the
+                following rules:
+                <itemizedlist>
+                  <listitem>
+                    <para>
+                      The function must return a value of type <literal>gboolean</literal>;
+                      <literal>TRUE</literal> on success, and <literal>FALSE</literal>
+                      otherwise. TODO: the return value is currently ignored.
+                    </para>
+                  </listitem>
+                  <listitem>
+                    <para>
+                      The first parameter is a pointer to an instance of the object.
+                    </para>
+                  </listitem>
+                  <listitem>
+                    <para>
+                      Following the object instance pointer are the method
+                      input values.
+                    </para>
+                  </listitem>
+                  <listitem>
+                    <para>
+                      The final parameter must be a
+                      <literal>DBusGMethodInvocation *</literal>.  This is used
+                      when sending the response message back to the client, by
+                      calling <literal>dbus_g_method_return</literal> or
+                      <literal>dbus_g_method_return_error</literal>.
+                    </para>
+                  </listitem>
+                </itemizedlist>
+              </para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>org.freedesktop.DBus.GLib.Const</literal></term>
+            <listitem>
+              <para>This attribute can only be applied to "out"
+              <literal>&lt;arg&gt;</literal> nodes, and specifies that the
+              parameter isn't being copied when returned.  For example, this
+              turns a 's' argument from a <literal>char **</literal> to a
+              <literal>const char **</literal>, and results in the argument not
+              being freed by DBus after the message is sent.
+              </para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>org.freedesktop.DBus.GLib.ReturnVal</literal></term>
+            <listitem>
+              <para>
+                This attribute can only be applied to "out"
+                <literal>&lt;arg&gt;</literal> nodes, and alters the expected
+                function signature.  It currently can be set to two values:
+                <literal>""</literal> or <literal>"error"</literal>.  The
+                argument marked with this attribute is not returned via a
+                pointer argument, but by the function's return value.  If the
+                attribute's value is the empty string, the <literal>GError
+                *</literal> argument is also omitted so there is no standard way
+                to return an error value.  This is very useful for interfacing
+                with existing code, as it is possible to match existing APIs.
+                If the attribute's value is <literal>"error"</literal>, then the
+                final argument is a <literal>GError *</literal> as usual.
+              </para>
+              <para>
+                Some examples to demonstrate the usage. This introspection XML:
+                <programlisting>
+&lt;method name="Increment"&gt;
+  &lt;arg type="u" name="x" /&gt;
+  &lt;arg type="u" direction="out" /&gt;
+&lt;/method&gt;
+                </programlisting>
+                Expects the following function declaration:
+                <programlisting>
+gboolean
+my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error);
+                </programlisting>
+              </para>
+              <para>
+                This introspection XML:
+                <programlisting>
+&lt;method name="IncrementRetval"&gt;
+  &lt;arg type="u" name="x" /&gt;
+  &lt;arg type="u" direction="out" &gt;
+    &lt;annotation name="org.freedesktop.DBus.GLib.ReturnVal" value=""/&gt;
+  &lt;/arg&gt;
+&lt;/method&gt;
+                </programlisting>
+                Expects the following function declaration:
+                <programlisting>
+gint32
+my_object_increment_retval (MyObject *obj, gint32 x)
+                </programlisting>
+              </para>
+              <para>
+                This introspection XML:
+                <programlisting>
+&lt;method name="IncrementRetvalError"&gt;
+  &lt;arg type="u" name="x" /&gt;
+  &lt;arg type="u" direction="out" &gt;
+    &lt;annotation name="org.freedesktop.DBus.GLib.ReturnVal" value="error"/&gt;
+  &lt;/arg&gt;
+&lt;/method&gt;
+                </programlisting>
+                Expects the following function declaration:
+                <programlisting>
+gint32
+my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error)
+                </programlisting>
+              </para>
+            </listitem>
+          </varlistentry>
+        </variablelist>
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="python-client">
+    <title>Python API</title>
+    <para>
+      The Python API, dbus-python, is now documented separately in
+      <ulink url="http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html">the dbus-python tutorial</ulink> (also available in doc/tutorial.txt,
+      and doc/tutorial.html if built with python-docutils, in the dbus-python
+      source distribution).
+    </para>
+  </sect1>
+
+  <sect1 id="qt-client">
+    <title>Qt API: Using Remote Objects</title>
+    <para>
+      
+      The Qt bindings are not yet documented.
+
+    </para>
+  </sect1>
+
+  <sect1 id="qt-server">
+    <title>Qt API: Implementing Objects</title>
+    <para>
+      The Qt bindings are not yet documented.
+    </para>
+  </sect1>
+</article>
diff --git a/dbus/doc/dbus-uuidgen.1 b/dbus/doc/dbus-uuidgen.1
new file mode 100644
index 0000000..8ed8dd2
--- /dev/null
+++ b/dbus/doc/dbus-uuidgen.1
@@ -0,0 +1,89 @@
+.\" 
+.\" dbus\-uuidgen manual page.
+.\" Copyright (C) 2006 Red Hat, Inc.
+.\"
+.TH dbus\-uuidgen 1
+.SH NAME
+dbus\-uuidgen \- Utility to generate UUIDs
+.SH SYNOPSIS
+.PP
+.B dbus\-uuidgen [\-\-version] [\-\-ensure[=FILENAME]] [\-\-get[=FILENAME]]
+
+.SH DESCRIPTION
+
+The \fIdbus\-uuidgen\fP command generates or reads a universally unique ID.
+
+.PP
+Note that the D\-Bus UUID has no relationship to RFC 4122 and does not generate
+UUIDs compatible with that spec. Many systems have a separate command
+for that (often called "uuidgen").
+
+.PP
+See http://www.freedesktop.org/software/dbus/ for more information
+about D\-Bus.
+
+.PP
+The primary usage of \fIdbus\-uuidgen\fP is to run in the post\-install
+script of a D\-Bus package like this:
+.nf
+  dbus\-uuidgen \-\-ensure
+.fi
+
+.PP
+This will ensure that /var/lib/dbus/machine\-id exists and has the uuid in it.
+It won't overwrite an existing uuid, since this id should remain fixed
+for a single machine until the next reboot at least.
+
+.PP
+The important properties of the machine UUID are that 1) it remains
+unchanged until the next reboot and 2) it is different for any two 
+running instances of the OS kernel. That is, if two processes see the 
+same UUID, they should also see the same shared memory, UNIX domain
+sockets, local X displays, localhost.localdomain resolution, process
+IDs, and so forth.
+
+.PP
+If you run \fIdbus\-uuidgen\fP with no options it just prints a new uuid made
+up out of thin air.
+
+.PP
+If you run it with \-\-get, it prints the machine UUID by default, or
+the UUID in the specified file if you specify a file.
+
+.PP
+If you try to change an existing machine\-id on a running system, it will
+probably result in bad things happening. Don't try to change this file. Also,
+don't make it the same on two different systems; it needs to be different
+anytime there are two different kernels running.
+
+.PP
+The UUID should be different on two different virtual machines,
+because there are two different kernels.
+
+.SH OPTIONS
+The following options are supported:
+.TP
+.I "\-\-get[=FILENAME]"
+If a filename is not given, defaults to localstatedir/lib/dbus/machine\-id
+(localstatedir is usually /var). If this file exists and is valid, the
+uuid in the file is printed on stdout. Otherwise, the command exits 
+with a nonzero status.
+
+.TP
+.I "\-\-ensure[=FILENAME]"
+If a filename is not given, defaults to localstatedir/lib/dbus/machine\-id
+(localstatedir is usually /var). If this file exists then it will be
+validated, and a failure code returned if it contains the wrong thing.
+If the file does not exist, it will be created with a new uuid in it.
+On success, prints no output.
+
+.TP
+.I "\-\-version"
+Print the version of dbus\-uuidgen
+
+.SH AUTHOR
+See http://www.freedesktop.org/software/dbus/doc/AUTHORS
+
+.SH BUGS
+Please send bug reports to the D\-Bus mailing list or bug tracker,
+see http://www.freedesktop.org/software/dbus/
diff --git a/dbus/doc/dcop-howto.txt b/dbus/doc/dcop-howto.txt
new file mode 100644
index 0000000..dfd3bcf
--- /dev/null
+++ b/dbus/doc/dcop-howto.txt
@@ -0,0 +1,559 @@
+		DCOP: Desktop COmmunications Protocol
+
+		    Preston Brown <pbrown@kde.org>
+			   October 14, 1999
+
+	 Revised and extended by Matthias Ettrich <ettrich@kde.org>
+			   Mar 29, 2000
+
+        Extended with DCOP Signals by Waldo Bastian <bastian@kde.org>
+                           Feb 19, 2001
+
+
+Motivation and Background:
+--------------------------
+
+The motivation behind building a protocol like DCOP is simple.  For
+the past year, we have been attempting to enable interprocess
+communication between KDE applications. KDE already has an extremely
+simple IPC mechanism called KWMcom, which is (was!) used for communicating
+between the panel and the window manager for instance.  It is about as
+simple as it gets, passing messages via X Atoms.  For this reason it
+is limited in the size and complexity of the data that can be passed
+(X atoms must be small to remain efficient) and it also makes it so
+that X is required.  CORBA was thought to be a more effective IPC/RPC
+solution.  However, after a year of attempting to make heavy use of
+CORBA in KDE, we have realized that it is a bit slow and memory
+intensive for simple use.  It also has no authentication available.
+
+What we really needed was an extremely simple protocol with basic
+authorization, along the lines of MIT-MAGIC-COOKIE, as used by X.  It
+would not be able to do NEARLY what CORBA was able to do, but for the
+simple tasks required it would be sufficient. Some examples of such
+tasks might be an application sending a message to the panel saying,
+"I have started, stop displaying the 'application starting' wait
+state," or having a new application that starts query to see if any
+other applications of the same name are running.  If they are, simply
+call a function on the remote application to create a new window,
+rather than starting a new process.
+
+Implementation:
+---------------
+
+DCOP is a simple IPC/RPC mechanism built to operate over sockets.
+Either unix domain sockets or tcp/ip sockets are supported. DCOP is
+built on top of the Inter Client Exchange (ICE) protocol, which comes
+standard as a part of X11R6 and later. It also depends on Qt, but
+beyond that it does not require any other libraries. Because of this,
+it is extremely lightweight, enabling it to be linked into all KDE
+applications with low overhead.
+
+Model:
+------
+
+The model is simple.  Each application using DCOP is a client.  They
+communicate to each other through a DCOP server, which functions like
+a traffic director, dispatching messages/calls to the proper
+destinations.  All clients are peers of each other.
+
+Two types of actions are possible with DCOP: "send and forget"
+messages, which do not block, and "calls," which block waiting for
+some data to be returned.
+
+Any data that will be sent is serialized (marshalled, for you CORBA
+types) using the built-in QDataStream operators available in all of
+the Qt classes.  This is fast and easy.  In fact it's so little work
+that you can easily write the marshalling code by hand. In addition,
+there's a simple IDL-like compiler available (dcopidl and dcopidl2cpp)
+that generates stubs and skeletons for you. Using the dcopidl compiler
+has the additional benefit of type safety.
+
+This HOWTO describes the manual method first and covers the dcopidl
+compiler later.
+
+Establishing the Connection:
+----------------------------
+
+KApplication has gained a method called "KApplication::dcopClient()"
+which returns a pointer to a DCOPClient instance.  The first time this
+method is called, the client class will be created.  DCOPClients have
+unique identifiers attached to them which are based on what
+KApplication::name() returns.  In fact, if there is only a single
+instance of the program running, the appId will be equal to
+KApplication::name().
+
+To actually enable DCOP communication to begin, you must use
+DCOPClient::attach().  This will attempt to attach to the DCOP server.
+If no server is found or there is any other type of error, attach()
+will return false. KApplication will catch a dcop signal and display an
+appropriate error message box in that case.
+
+After connecting with the server via DCOPClient::attach(), you need to
+register this appId with the server so it knows about you.  Otherwise,
+you are communicating anonymously.  Use the
+DCOPClient::registerAs(const QCString &name) to do so.  In the simple
+case:
+
+/*
+ * returns the appId that is actually registered, which _may_ be
+ * different from what you passed
+ */
+appId = client->registerAs(kApp->name());
+
+If you never retrieve the DCOPClient pointer from KApplication, the
+object will not be created and thus there will be no memory overhead.
+
+You may also detach from the server by calling DCOPClient::detach().
+If you wish to attach again you will need to re-register as well.  If
+you only wish to change the ID under which you are registered, simply
+call DCOPClient::registerAs() with the new name.
+
+KUniqueApplication automatically registers itself to DCOP. If you
+are using KUniqueApplication you should not attach or register
+yourself, this is already done. The appId is by definition
+equal to kapp->name(). You can retrieve the registered DCOP client
+by calling kapp->dcopClient().
+
+Sending Data to a Remote Application:
+-------------------------------------
+
+To actually communicate, you have one of two choices.  You may either
+call the "send" or the "call" method.  Both methods require three
+identification parameters: an application identifier, a remote object,
+a remote function. Sending is asynchronous (i.e. it returns immediately)
+and may or may not result in your own application being sent a message at
+some point in the future. Then "send" requires one and "call" requires
+two data parameters.
+
+The remote object must be specified as an object hierarchy.  That is,
+if the toplevel object is called "fooObject" and has the child
+"barObject", you would reference this object as "fooObject/barObject".
+Functions must be described by a full function signature.  If the
+remote function is called "doIt", and it takes an int, it would be
+described as "doIt(int)".  Please note that the return type is not
+specified here, as it is not part of the function signature (or at
+least the C++ understanding of a function signature).  You will get
+the return type of a function back as an extra parameter to
+DCOPClient::call().  See the section on call() for more details.
+
+In order to actually get the data to the remote client, it must be
+"serialized" via a QDataStream operating on a QByteArray. This is how
+the data parameter is "built". A few examples will make clear how this
+works.
+
+Say you want to call "doIt" as described above, and not block (or wait
+for a response).  You will not receive the return value of the remotely
+called function, but you will not hang while the RPC is processed either.
+The return value of send() indicates whether DCOP communication succeeded
+or not.
+
+QByteArray data;
+QDataStream arg(data, IO_WriteOnly);
+arg << 5;
+if (!client->send("someAppId", "fooObject/barObject", "doIt(int)",
+	          data))
+  qDebug("there was some error using DCOP.");
+
+OK, now let's say we wanted to get the data back from the remotely
+called function.  You have to execute a call() instead of a send().
+The returned value will then be available in the data parameter "reply".
+The actual return value of call() is still whether or not DCOP
+communication was successful.
+
+QByteArray data, replyData;
+QCString replyType;
+QDataStream arg(data, IO_WriteOnly);
+arg << 5;
+if (!client->call("someAppId", "fooObject/barObject", "doIt(int)",
+                  data, replyType, replyData))
+  qDebug("there was some error using DCOP.");
+else {
+  QDataStream reply(replyData, IO_ReadOnly);
+  if (replyType == "QString") {
+    QString result;
+    reply >> result;
+    print("the result is: %s",result.latin1());
+  } else
+    qDebug("doIt returned an unexpected type of reply!");
+}
+
+N.B.: You cannot call() a method belonging to an application which has
+registered with an unique numeric id appended to its textual name (see
+dcopclient.h for more info). In this case, DCOP would not know which
+application it should connect with to call the method. This is not an issue
+with send(), as you can broadcast to all applications that have registered
+with appname-<numeric_id> by using a wildcard (e.g. 'konsole-*'), which
+will send your signal to all applications called 'konsole'.
+
+Receiving Data via DCOP:
+------------------------
+
+Currently the only real way to receive data from DCOP is to multiply
+inherit from the normal class that you are inheriting (usually some
+sort of QWidget subclass or QObject) as well as the DCOPObject class.
+DCOPObject provides one very important method: DCOPObject::process().
+This is a pure virtual method that you must implement in order to
+process DCOP messages that you receive.  It takes a function
+signature, QByteArray of parameters, and a reference to a QByteArray
+for the reply data that you must fill in.
+
+Think of DCOPObject::process() as a sort of dispatch agent.  In the
+future, there will probably be a precompiler for your sources to write
+this method for you.  However, until that point you need to examine
+the incoming function signature and take action accordingly.  Here is
+an example implementation.
+
+bool BarObject::process(const QCString &fun, const QByteArray &data,
+		        QCString &replyType, QByteArray &replyData)
+{
+  if (fun == "doIt(int)") {
+    QDataStream arg(data, IO_ReadOnly);
+    int i; // parameter
+    arg >> i;
+    QString result = self->doIt (i);
+    QDataStream reply(replyData, IO_WriteOnly);
+    reply << result;
+    replyType = "QString";
+    return true;
+  } else {
+    qDebug("unknown function call to BarObject::process()");
+    return false;
+  }
+}
+
+Receiving Calls and processing them:
+------------------------------------
+
+If your applications is able to process incoming function calls
+right away the above code is all you need. When your application
+needs to do more complex tasks you might want to do the processing
+out of 'process' function call and send the result back later when
+it becomes available.
+
+For this you can ask your DCOPClient for a transactionId. You can
+then return from the 'process' function and when the result is
+available finish the transaction. In the mean time your application
+can receive incoming DCOP function calls from other clients.
+
+Such code could like this:
+
+bool BarObject::process(const QCString &fun, const QByteArray &data,
+		        QCString &, QByteArray &)
+{
+  if (fun == "doIt(int)") {
+    QDataStream arg(data, IO_ReadOnly);
+    int i; // parameter
+    arg >> i;
+    QString result = self->doIt(i);
+
+    DCOPClientTransaction *myTransaction;
+    myTransaction = kapp->dcopClient()->beginTransaction();
+
+    // start processing...
+    // Calls slotProcessingDone when finished.
+    startProcessing( myTransaction, i);
+
+    return true;
+  } else {
+    qDebug("unknown function call to BarObject::process()");
+    return false;
+  }
+}
+
+slotProcessingDone(DCOPClientTransaction *myTransaction, const QString &result)
+{
+    QCString replyType = "QString";
+    QByteArray replyData;
+    QDataStream reply(replyData, IO_WriteOnly);
+    reply << result;
+    kapp->dcopClient()->endTransaction( myTransaction, replyType, replyData );
+}
+
+DCOP Signals
+------------
+
+Sometimes a component wants to send notifications via DCOP to other
+components but does not know which components will be interested in these
+notifications. One could use a broadcast in such a case but this is a very
+crude method. For a more sophisticated method DCOP signals have been invented.
+
+DCOP signals are very similair to Qt signals, there are some differences 
+though. A DCOP signal can be connected to a DCOP function. Whenever the DCOP
+signal gets emitted, the DCOP functions to which the signal is connected are
+being called. DCOP signals are, just like Qt signals, one way. They do not
+provide a return value. 
+
+A DCOP signal originates from a DCOP Object/DCOP Client combination (sender). 
+It can be connected to a function of another DCOP Object/DCOP Client 
+combination (receiver).
+
+There are two major differences between connections of Qt signals and 
+connections of DCOP signals. In DCOP, unlike Qt, a signal connections can
+have an anonymous sender and, unlike Qt, a DCOP signal connection can be
+non-volatile.
+
+With DCOP one can connect a signal without specifying the sending DCOP Object 
+or DCOP Client. In that case signals from any DCOP Object and/or DCOP Client
+will be delivered. This allows the specification of certain events without
+tying oneself to a certain object that implementes the events.
+
+Another DCOP feature are so called non-volatile connections. With Qt signal
+connections, the connection gets deleted when either sender or receiver of
+the signal gets deleted. A volatile DCOP signal connection will behave the
+same. However, a non-volatile DCOP signal connection will not get deleted 
+when the sending object gets deleted. Once a new object gets created with 
+the same name as the original sending object, the connection will be restored.
+There is no difference between the two when the receiving object gets deleted,
+in that case the signal connection will always be deleted.
+
+A receiver can create a non-volatile connection while the sender doesn't (yet)
+exist. An anonymous DCOP connection should always be non-volatile.
+
+The following example shows how KLauncher emits a signal whenever it notices
+that an application that was started via KLauncher terminates.
+
+   QByteArray params;
+   QDataStream stream(params, IO_WriteOnly);
+   stream << pid;
+   kapp->dcopClient()->emitDCOPSignal("clientDied(pid_t)", params);
+
+The task manager of the KDE panel connects to this signal. It uses an 
+anonymous connection (it doesn't require that the signal is being emitted
+by KLauncher) that is non-volatile:
+
+   connectDCOPSignal(0, 0, "clientDied(pid_t)", "clientDied(pid_t)", false);
+
+It connects the clientDied(pid_t) signal to its own clientDied(pid_t) DCOP
+function. In this case the signal and the function to call have the same name.
+This isn't needed as long as the arguments of both signal and receiving function
+match. The receiving function may ignore one or more of the trailing arguments
+of the signal. E.g. it is allowed to connect the clientDied(pid_t) signal to
+a clientDied(void) DCOP function.
+
+Using the dcopidl compiler
+---------------------
+
+dcopidl makes setting up a DCOP server easy. Instead of having to implement
+the process() method and unmarshalling (retrieving from QByteArray) parameters
+manually, you can let dcopidl create the necessary code on your behalf.
+
+This also allows you to describe the interface for your class in a
+single, separate header file.
+
+Writing an IDL file is very similar to writing a normal C++ header. An
+exception is the keyword 'ASYNC'. It indicates that a call to this
+function shall be processed asynchronously. For the C++ compiler, it
+expands to 'void'.
+
+Example:
+
+#ifndef MY_INTERFACE_H
+#define MY_INTERFACE_H
+
+#include <dcopobject.h>
+
+class MyInterface : virtual public DCOPObject
+{
+  K_DCOP
+
+  k_dcop:
+
+    virtual ASYNC myAsynchronousMethod(QString someParameter) = 0;
+    virtual QRect mySynchronousMethod() = 0;
+};
+
+#endif
+
+As you can see, you're essentially declaring an abstract base class, which
+virtually inherits from DCOPObject.
+
+If you're using the standard KDE build scripts, then you can simply
+add this file (which you would call MyInterface.h) to your sources
+directory. Then you edit your Makefile.am, adding 'MyInterface.skel'
+to your SOURCES list and MyInterface.h to include_HEADERS.
+
+The build scripts will use dcopidl to parse MyInterface.h, converting
+it to an XML description in MyInterface.kidl. Next, a file called
+MyInterface_skel.cpp will automatically be created, compiled and
+linked with your binary.
+
+The next thing you have to do is to choose which of your classes will
+implement the interface described in MyInterface.h. Alter the inheritance
+of this class such that it virtually inherits from MyInterface. Then
+add declarations to your class interface similar to those on MyInterface.h,
+but virtual, not pure virtual.
+
+Example:
+
+class MyClass: public QObject, virtual public MyInterface
+{
+  Q_OBJECT
+  
+  public:
+    MyClass(); 
+    ~MyClass();
+
+    ASYNC myAsynchronousMethod(QString someParameter);
+    QRect mySynchronousMethod();
+};
+
+Note: (Qt issue) Remember that if you are inheriting from QObject, you must
+place it first in the list of inherited classes.
+
+In the implementation of your class' ctor, you must explicitly initialize
+those classes from which you are inheriting from. This is, of course, good
+practise, but it is essential here as you need to tell DCOPObject the name of
+the interface which your are implementing.
+
+Example:
+
+MyClass::MyClass()
+  : QObject(),
+    DCOPObject("MyInterface")
+{
+  // whatever...
+}
+
+Now you can simply implement the methods you have declared in your interface,
+exactly the same as you would normally.
+
+Example:
+
+void MyClass::myAsynchronousMethod(QString someParameter)
+{
+  qDebug("myAsyncMethod called with param `" + someParameter + "'");
+}
+
+
+It is not necessary (though very clean) to define an interface as an
+abstract class of its own, like we did in the example above. We could
+just as well have defined a k_dcop section directly within MyClass:
+
+class MyClass: public QObject, virtual public DCOPObject
+{
+  Q_OBJECT
+  K_DCOP
+
+  public:
+    MyClass(); 
+    ~MyClass();
+
+  k_dcop:
+    ASYNC myAsynchronousMethod(QString someParameter);
+    QRect mySynchronousMethod();
+};
+
+In addition to skeletons, dcopidl2cpp also generate stubs. Those make
+it easy to call a DCOP interface without doing the marshalling
+manually. To use a stub, add MyInterface.stub to the SOURCES list of
+your Makefile.am. The stub class will then be called MyInterface_stub.
+
+Conclusion:
+-----------
+
+Hopefully this document will get you well on your way into the world
+of inter-process communication with KDE!  Please direct all comments
+and/or suggestions to Preston Brown <pbrown@kde.org> and Matthias
+Ettrich <ettrich@kde.org>.
+
+
+Inter-user communication
+------------------------
+
+Sometimes it might be interesting to use DCOP between processes
+belonging to different users, e.g. a frontend process running
+with the user's id, and a backend process running as root.
+
+To do this, two steps have to be taken:
+
+a) both processes need to talk to the same DCOP server
+b) the authentication must be ensured
+
+For the first step, you simply pass the server address (as
+found in .DCOPserver) to the second process. For the authentication,
+you can use the ICEAUTHORITY environment variable to tell the
+second process where to find the authentication information.
+(Note that this implies that the second process is able to
+read the authentication file, so it will probably only work
+if the second process runs as root. If it should run as another
+user, a similar approach to what kdesu does with xauth must
+be taken. In fact, it would be a very good idea to add DCOP
+support to kdesu!)
+
+For example
+
+ICEAUTHORITY=~user/.ICEauthority kdesu root -c kcmroot -dcopserver `cat ~user/.DCOPserver`
+
+will, after kdesu got the root password, execute kcmroot as root, talking
+to the user's dcop server.
+
+
+NOTE: DCOP communication is not encrypted, so please do not
+pass important information around this way.
+
+
+Performance Tests:
+------------------
+A few back-of-the-napkin tests folks:
+
+Code:
+
+#include <kapplication.h>
+
+int main(int argc, char **argv)
+{
+  KApplication *app;
+
+  app = new KApplication(argc, argv, "testit");
+  return app->exec();
+}
+
+Compiled with:
+
+g++ -O2 -o testit testit.cpp -I$QTDIR/include -L$QTDIR/lib -lkdecore
+
+on Linux yields the following memory use statistics:
+
+VmSize:     8076 kB
+VmLck:         0 kB
+VmRSS:      4532 kB
+VmData:      208 kB
+VmStk:        20 kB
+VmExe:         4 kB
+VmLib:      6588 kB
+
+If I create the KApplication's DCOPClient, and call attach() and
+registerAs(), it changes to this:
+
+VmSize:     8080 kB
+VmLck:         0 kB
+VmRSS:      4624 kB
+VmData:      208 kB
+VmStk:        20 kB
+VmExe:         4 kB
+VmLib:      6588 kB
+
+Basically it appears that using DCOP causes 100k more memory to be
+resident, but no more data or stack.  So this will be shared between all
+processes, right?  100k to enable DCOP in all apps doesn't seem bad at
+all. :)
+
+OK now for some timings.  Just creating a KApplication and then exiting
+(i.e. removing the call to KApplication::exec) takes this much time:
+
+0.28user 0.02system 0:00.32elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k
+0inputs+0outputs (1084major+62minor)pagefaults 0swaps
+
+I.e. about 1/3 of a second on my PII-233.  Now, if we create our DCOP
+object and attach to the server, it takes this long:
+
+0.27user 0.03system 0:00.34elapsed 87%CPU (0avgtext+0avgdata 0maxresident)k
+0inputs+0outputs (1107major+65minor)pagefaults 0swaps
+
+I.e. about 1/3 of a second.  Basically DCOPClient creation and attaching
+gets lost in the statistical variation ("noise").  I was getting times
+between .32 and .48 over several runs for both of the example programs, so
+obviously system load is more relevant than the extra two calls to
+DCOPClient::attach and DCOPClient::registerAs, as well as the actual
+DCOPClient constructor time.
+
diff --git a/dbus/doc/diagram.png b/dbus/doc/diagram.png
new file mode 100644
index 0000000..5cb84a9
--- /dev/null
+++ b/dbus/doc/diagram.png
Binary files differ
diff --git a/dbus/doc/diagram.svg b/dbus/doc/diagram.svg
new file mode 100644
index 0000000..193c567
--- /dev/null
+++ b/dbus/doc/diagram.svg
@@ -0,0 +1,590 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   id="svg1"
+   sodipodi:version="0.32"
+   inkscape:version="0.39"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   width="841.88975pt"
+   height="595.27559pt"
+   sodipodi:docbase="/home/hp/dbus-cvs/dbus/doc"
+   sodipodi:docname="diagram.svg">
+  <defs
+     id="defs3">
+    <marker
+       style="overflow:visible;"
+       id="Arrow1M"
+       refX="0.0"
+       refY="0.0"
+       orient="auto"
+       inkscape:stockid="Arrow1M">
+      <path
+         transform="scale(0.4)"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         id="path3519"
+         sodipodi:nodetypes="ccccc" />
+    </marker>
+    <marker
+       style="overflow:visible;"
+       id="Arrow2L"
+       refX="0.0"
+       refY="0.0"
+       orient="auto"
+       inkscape:stockid="Arrow2L">
+      <path
+         transform="scale(1.1) translate(-5,0)"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         id="path3515"
+         sodipodi:nodetypes="cccc" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.90210318"
+     inkscape:cx="420.94487"
+     inkscape:cy="297.63779"
+     inkscape:window-width="1024"
+     inkscape:window-height="701"
+     showgrid="false"
+     inkscape:grid-bbox="false"
+     inkscape:grid-points="true"
+     inkscape:window-x="0"
+     inkscape:window-y="24"
+     gridspacingy="2.5000000mm"
+     gridspacingx="2.5000000mm"
+     showguides="true"
+     inkscape:guide-bbox="true">
+    <sodipodi:guide
+       orientation="horizontal"
+       position="268.85797"
+       id="guide3566" />
+    <sodipodi:guide
+       orientation="horizontal"
+       position="294.31223"
+       id="guide4235" />
+    <sodipodi:guide
+       orientation="horizontal"
+       position="300.40909"
+       id="guide4882" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata4">
+    <rdf:RDF
+       id="RDF5">
+      <cc:Work
+         rdf:about=""
+         id="Work6">
+        <dc:format
+           id="format7">image/svg+xml</dc:format>
+        <dc:type
+           id="type9"
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.7500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;"
+     id="rect908"
+     width="325.23203"
+     height="354.33072"
+     x="17.716536"
+     y="372.04724" />
+  <text
+     xml:space="preserve"
+     style="font-size:18.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;"
+     x="70.778252"
+     y="712.73920"
+     id="text1532"
+     sodipodi:linespacing="100%"><tspan
+       id="tspan1533">Application Process 1</tspan></text>
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.5000000 2.5000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;"
+     id="rect1535"
+     width="148.46259"
+     height="46.656849"
+     x="106.29921"
+     y="378.54001" />
+  <text
+     xml:space="preserve"
+     style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;"
+     x="180.61389"
+     y="400.40048"
+     id="text2158"
+     sodipodi:linespacing="100%"><tspan
+       id="tspan2159">DBusConnection</tspan><tspan
+       sodipodi:role="line"
+       id="tspan2161"
+       x="180.61389"
+       y="414.40048">Instance</tspan></text>
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.9950929;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.9950928 2.9950928 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;"
+     id="rect2170"
+     width="148.46259"
+     height="66.966240"
+     x="28.702768"
+     y="549.21259" />
+  <text
+     xml:space="preserve"
+     style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;"
+     x="103.01745"
+     y="577.56586"
+     id="text2171"
+     sodipodi:linespacing="100%"><tspan
+       x="103.01745"
+       y="577.56586"
+       sodipodi:role="line"
+       id="tspan2176">C/C++/Python/etc.</tspan><tspan
+       x="103.01745"
+       y="591.56586"
+       sodipodi:role="line"
+       id="tspan2178">Object Instance</tspan></text>
+  <path
+     style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
+     id="path3535"
+     d="M 98.938952,408.61479 C 98.744753,409.20303 97.917886,409.67295 97.440945,410.11435 C 95.534947,411.94763 94.266934,414.11555 93.172614,416.33858 C 91.902056,419.02725 90.969281,421.79944 90.107252,424.59229 C 89.589105,426.27374 88.983534,427.90634 88.266907,429.53700 C 87.919667,430.33438 87.622593,431.17598 87.120464,431.91970 C 86.832222,432.30665 86.469422,432.65145 86.167985,433.03184 C 86.015931,433.22254 85.868997,433.41563 85.722131,433.60898 L 82.914336,433.11743 C 83.063402,432.91879 83.213428,432.72069 83.368121,432.52498 C 83.654681,432.15308 83.980737,431.80834 84.285389,431.44731 C 84.811957,430.77175 85.122523,429.97914 85.482400,429.23872 C 86.253056,427.64929 86.903084,426.03861 87.474578,424.39321 C 88.439548,421.58552 89.442843,418.78792 90.703938,416.05898 C 91.810966,413.77525 92.999191,411.45961 94.849464,409.50748 C 95.094704,409.24876 96.091789,407.90149 95.865737,408.61479 L 98.938952,408.61479 z " />
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;"
+     x="34.109497"
+     y="446.13382"
+     id="text3536"><tspan
+       id="tspan3537">Locate Object</tspan><tspan
+       sodipodi:role="line"
+       id="tspan3539"
+       x="34.109497"
+       y="458.13382">via Object Path</tspan></text>
+  <path
+     style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
+     id="path3541"
+     d="M 60.509867,462.78767 C 60.704066,463.37591 61.530933,463.84583 62.007874,464.28723 C 63.913872,466.12051 65.181885,468.28843 66.276205,470.51146 C 67.546763,473.20013 68.479538,475.97232 69.341567,478.76517 C 69.859714,480.44662 70.465285,482.07922 71.181912,483.70988 C 71.529152,484.50726 71.826226,485.34886 72.328355,486.09258 C 72.616597,486.47953 72.979397,486.82433 73.280834,487.20472 C 73.432888,487.39542 73.579822,487.58851 73.726688,487.78186 L 76.534483,487.29031 C 76.385417,487.09167 76.235391,486.89357 76.080698,486.69786 C 75.794138,486.32596 75.468082,485.98122 75.163430,485.62019 C 74.636862,484.94463 74.326296,484.15202 73.966419,483.41160 C 73.195763,481.82217 72.545735,480.21149 71.974241,478.56609 C 71.009271,475.75840 70.005976,472.96080 68.744881,470.23186 C 67.637853,467.94813 66.449628,465.63249 64.599355,463.68036 C 64.354115,463.42164 63.357030,462.07437 63.583082,462.78767 L 60.509867,462.78767 z " />
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;"
+     x="49.100315"
+     y="501.60959"
+     id="text3542"
+     sodipodi:linespacing="100%"><tspan
+       x="49.100315"
+       y="501.60959"
+       sodipodi:role="line"
+       id="tspan3547">Bindings Marshal</tspan><tspan
+       x="49.100315"
+       y="513.60959"
+       sodipodi:role="line"
+       id="tspan3549">to Method Call</tspan></text>
+  <path
+     style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
+     id="path3551"
+     d="M 95.295239,519.43211 C 95.101039,520.02035 94.274169,520.49027 93.797229,520.93167 C 91.891239,522.76495 90.623219,524.93287 89.528899,527.15590 C 88.258339,529.84457 87.325569,532.61676 86.463539,535.40961 C 85.945389,537.09106 85.339819,538.72366 84.623199,540.35432 C 84.275959,541.15170 83.978879,541.99330 83.476749,542.73702 C 83.188509,543.12397 82.825709,543.46877 82.524269,543.84916 C 82.372219,544.03986 82.225289,544.23295 82.078419,544.42630 L 79.270619,543.93475 C 79.419689,543.73611 79.569719,543.53801 79.724409,543.34230 C 80.010969,542.97040 80.337029,542.62566 80.641679,542.26463 C 81.168249,541.58907 81.478809,540.79646 81.838689,540.05604 C 82.609339,538.46661 83.259369,536.85593 83.830869,535.21053 C 84.795839,532.40284 85.799129,529.60524 87.060229,526.87630 C 88.167249,524.59257 89.355479,522.27693 91.205749,520.32480 C 91.450989,520.06608 92.448079,518.71881 92.222029,519.43211 L 95.295239,519.43211 z " />
+  <path
+     style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
+     id="path3552"
+     d="M 261.83533,408.61479 C 262.02953,409.20303 262.85640,409.67295 263.33334,410.11435 C 265.23934,411.94763 266.50735,414.11555 267.60167,416.33858 C 268.87223,419.02725 269.80501,421.79944 270.66703,424.59229 C 271.18518,426.27374 271.79075,427.90634 272.50738,429.53700 C 272.85462,430.33438 273.15169,431.17598 273.65382,431.91970 C 273.94206,432.30665 274.30486,432.65145 274.60630,433.03184 C 274.75836,433.22254 274.90529,433.41563 275.05216,433.60898 L 277.85995,433.11743 C 277.71088,432.91879 277.56086,432.72069 277.40617,432.52498 C 277.11961,432.15308 276.79355,431.80834 276.48890,431.44731 C 275.96233,430.77175 275.65176,429.97914 275.29189,429.23872 C 274.52123,427.64929 273.87120,426.03861 273.29971,424.39321 C 272.33474,421.58552 271.33144,418.78792 270.07035,416.05898 C 268.96332,413.77525 267.77510,411.45961 265.92482,409.50748 C 265.67958,409.24876 264.68250,407.90149 264.90855,408.61479 L 261.83533,408.61479 z " />
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;"
+     x="223.98749"
+     y="446.13382"
+     id="text3553"
+     sodipodi:linespacing="100%"><tspan
+       x="223.98749"
+       y="446.13382"
+       sodipodi:role="line"
+       id="tspan3562">Marshal Method</tspan><tspan
+       x="223.98749"
+       y="458.13382"
+       sodipodi:role="line"
+       id="tspan3564">Call to Message</tspan></text>
+  <path
+     style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
+     id="path3567"
+     d="M 278.96485,463.29453 C 278.77065,463.88277 277.94378,464.35269 277.46684,464.79409 C 275.56085,466.62737 274.29283,468.79529 273.19851,471.01832 C 271.92795,473.70699 270.99518,476.47918 270.13315,479.27203 C 269.61500,480.95348 269.00943,482.58608 268.29281,484.21674 C 267.94557,485.01412 267.64849,485.85572 267.14636,486.59944 C 266.85812,486.98639 266.49532,487.33119 266.19388,487.71158 C 266.04183,487.90228 265.89490,488.09537 265.74803,488.28872 L 262.94023,487.79717 C 263.08930,487.59853 263.23933,487.40043 263.39402,487.20472 C 263.68058,486.83282 264.00664,486.48808 264.31129,486.12705 C 264.83786,485.45149 265.14842,484.65888 265.50830,483.91846 C 266.27895,482.32903 266.92898,480.71835 267.50048,479.07295 C 268.46545,476.26526 269.46874,473.46766 270.72984,470.73872 C 271.83686,468.45499 273.02509,466.13935 274.87536,464.18722 C 275.12060,463.92850 276.11769,462.58123 275.89164,463.29453 L 278.96485,463.29453 z " />
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.7377086;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.7377084 2.7377084 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;"
+     id="rect3568"
+     width="124.01746"
+     height="66.979813"
+     x="189.79265"
+     y="495.08902" />
+  <text
+     xml:space="preserve"
+     style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;"
+     x="248.94049"
+     y="523.44220"
+     id="text3569"
+     sodipodi:linespacing="100%"><tspan
+       x="248.94049"
+       y="523.44220"
+       sodipodi:role="line"
+       id="tspan3574">Bindings Proxy</tspan><tspan
+       x="248.94049"
+       y="537.44220"
+       sodipodi:role="line"
+       id="tspan3576">Object Instance</tspan></text>
+  <path
+     style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
+     id="path3578"
+     d="M 259.03547,566.92913 C 259.22967,567.51737 260.05653,567.98729 260.53348,568.42869 C 262.43947,570.26197 263.70749,572.42989 264.80181,574.65292 C 266.07236,577.34159 267.00514,580.11378 267.86717,582.90663 C 268.38532,584.58808 268.99089,586.22068 269.70751,587.85134 C 270.05475,588.64872 270.35183,589.49032 270.85396,590.23404 C 271.14220,590.62099 271.50500,590.96579 271.80644,591.34618 C 271.95849,591.53688 272.10542,591.72997 272.25229,591.92332 L 275.06008,591.43177 C 274.91102,591.23313 274.76099,591.03503 274.60630,590.83932 C 274.31974,590.46742 273.99368,590.12268 273.68903,589.76165 C 273.16246,589.08609 272.85190,588.29348 272.49202,587.55306 C 271.72136,585.96363 271.07134,584.35295 270.49984,582.70755 C 269.53487,579.89986 268.53158,577.10226 267.27048,574.37332 C 266.16345,572.08959 264.97523,569.77395 263.12496,567.82182 C 262.87972,567.56310 261.88263,566.21583 262.10868,566.92913 L 259.03547,566.92913 z " />
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;"
+     x="217.40741"
+     y="607.90881"
+     id="text3579"
+     sodipodi:linespacing="100%"><tspan
+       x="217.40741"
+       y="607.90881"
+       sodipodi:role="line"
+       id="tspan3584">Application Code</tspan></text>
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.96172028pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);"
+     d="M 26.574803,408.60009 C 26.574803,539.68912 26.574803,539.68911 26.574803,531.49606"
+     id="path3586"
+     sodipodi:nodetypes="cc" />
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;"
+     x="25.977146"
+     y="386.45212"
+     id="text4220"
+     sodipodi:linespacing="100%"><tspan
+       id="tspan4221">Incoming</tspan><tspan
+       sodipodi:role="line"
+       id="tspan4223"
+       x="25.977146"
+       y="398.45212">Call</tspan></text>
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:end;writing-mode:lr;"
+     x="335.61411"
+     y="386.45212"
+     id="text4226"
+     sodipodi:linespacing="100%"><tspan
+       x="335.61411"
+       y="386.45212"
+       sodipodi:role="line"
+       id="tspan4231">Outgoing</tspan><tspan
+       x="335.61411"
+       y="398.45212"
+       sodipodi:role="line"
+       id="tspan4233">Call</tspan></text>
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.96172028pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:url(#Arrow1M);marker-end:none;"
+     d="M 327.75591,416.33858 C 327.75591,547.42761 327.75591,547.42760 327.75591,539.23455"
+     id="path4236"
+     sodipodi:nodetypes="cc" />
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:5.7914310;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;"
+     id="rect4870"
+     width="885.86591"
+     height="310.27252"
+     x="88.582680"
+     y="8.8582621" />
+  <text
+     xml:space="preserve"
+     style="font-size:18.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;"
+     x="515.42737"
+     y="305.44489"
+     id="text4871"
+     sodipodi:linespacing="100%"><tspan
+       x="515.42737"
+       y="305.44489"
+       sodipodi:role="line"
+       id="tspan4874">Bus Daemon Process</tspan></text>
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.7500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;"
+     id="rect4876"
+     width="325.23203"
+     height="354.33072"
+     x="708.66144"
+     y="373.08359" />
+  <text
+     xml:space="preserve"
+     style="font-size:18.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;"
+     x="761.72314"
+     y="713.77551"
+     id="text4877"
+     sodipodi:linespacing="100%"><tspan
+       x="761.72314"
+       y="713.77551"
+       sodipodi:role="line"
+       id="tspan4880">Application Process 2</tspan></text>
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;"
+     x="823.49664"
+     y="505.18018"
+     id="text4883"
+     sodipodi:linespacing="100%"><tspan
+       x="823.49664"
+       y="505.18018"
+       sodipodi:role="line"
+       id="tspan4888">Same Stuff as in</tspan><tspan
+       x="823.49664"
+       y="517.18018"
+       sodipodi:role="line"
+       id="tspan4890">Process 1</tspan></text>
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;"
+     x="47.891071"
+     y="638.05420"
+     id="text4892"
+     sodipodi:linespacing="100%"><tspan
+       x="47.891071"
+       y="638.05420"
+       sodipodi:role="line"
+       id="tspan4901">(Object Instance Has</tspan><tspan
+       x="47.891071"
+       y="650.05420"
+       sodipodi:role="line"
+       id="tspan4903">1 or More Interfaces)</tspan></text>
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-start:url(#Arrow1M);marker-end:url(#Arrow1M);stroke-dasharray:none;"
+     d="M 162.57260,358.02041 C 165.25213,354.60516 186.01858,328.13688 184.00893,330.69832"
+     id="path4905"
+     sodipodi:nodetypes="cc" />
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;"
+     x="190.57170"
+     y="342.62018"
+     id="text5539"><tspan
+       id="tspan5540">Socket</tspan><tspan
+       sodipodi:role="line"
+       id="tspan5544"
+       x="190.57170"
+       y="354.62018">(Bidirectional Message Stream)</tspan></text>
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-start:url(#Arrow1M);marker-end:url(#Arrow1M);"
+     d="M 827.53876,363.18897 C 824.85916,359.77372 804.09276,333.30544 806.10236,335.86688"
+     id="path5546"
+     sodipodi:nodetypes="cc" />
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;"
+     x="840.79150"
+     y="345.73135"
+     id="text5547"><tspan
+       id="tspan5548">Socket</tspan><tspan
+       sodipodi:role="line"
+       id="tspan5550"
+       x="840.79150"
+       y="357.73135">(Bidirectional Message Stream)</tspan></text>
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.5000000 2.5000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;"
+     id="rect5552"
+     width="148.46259"
+     height="46.656849"
+     x="124.01575"
+     y="263.38251" />
+  <text
+     xml:space="preserve"
+     style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;"
+     x="198.33043"
+     y="285.24298"
+     id="text5553"
+     sodipodi:linespacing="100%"><tspan
+       id="tspan5554">DBusConnection</tspan><tspan
+       sodipodi:role="line"
+       id="tspan5556"
+       x="198.33043"
+       y="299.24298">Instance</tspan></text>
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.5000000 2.5000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;"
+     id="rect5558"
+     width="148.46259"
+     height="46.656849"
+     x="719.64764"
+     y="263.38251" />
+  <text
+     xml:space="preserve"
+     style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;"
+     x="793.96234"
+     y="285.24298"
+     id="text5559"
+     sodipodi:linespacing="100%"><tspan
+       id="tspan5560">DBusConnection</tspan><tspan
+       sodipodi:role="line"
+       id="tspan5562"
+       x="793.96234"
+       y="299.24298">Instance</tspan></text>
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.5000000 2.5000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;"
+     id="rect5564"
+     width="148.46259"
+     height="46.656849"
+     x="763.77222"
+     y="378.54001" />
+  <text
+     xml:space="preserve"
+     style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;"
+     x="838.08691"
+     y="400.40048"
+     id="text5565"
+     sodipodi:linespacing="100%"><tspan
+       id="tspan5566">DBusConnection</tspan><tspan
+       sodipodi:role="line"
+       id="tspan5568"
+       x="838.08691"
+       y="414.40048">Instance</tspan></text>
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);"
+     d="M 186.02362,248.03149 C 106.29921,26.574797 372.04724,26.574797 372.04724,26.574797"
+     id="path5571"
+     sodipodi:nodetypes="cc" />
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.1854961;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.1854960 2.1854960 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;"
+     id="rect6205"
+     width="148.46259"
+     height="35.656227"
+     x="391.89175"
+     y="17.493374" />
+  <text
+     xml:space="preserve"
+     style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;"
+     x="466.20642"
+     y="39.577003"
+     id="text6206"
+     sodipodi:linespacing="100%"><tspan
+       x="466.20642"
+       y="39.577003"
+       sodipodi:role="line"
+       id="tspan6211">Message Dispatcher</tspan></text>
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);"
+     d="M 806.10236,248.03149 C 814.96063,17.716530 549.21260,26.574797 558.07087,26.574797"
+     id="path6213"
+     sodipodi:nodetypes="cc" />
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;"
+     x="380.24341"
+     y="71.125053"
+     id="text6214"
+     sodipodi:linespacing="100%"><tspan
+       x="380.24341"
+       y="71.125053"
+       sodipodi:role="line"
+       id="tspan6860">if (message is signal)</tspan><tspan
+       x="380.24341"
+       y="83.125053"
+       sodipodi:role="line"
+       id="tspan6862">  broadcast</tspan><tspan
+       x="380.24341"
+       y="95.125053"
+       sodipodi:role="line"
+       id="tspan6864">else</tspan><tspan
+       x="380.24341"
+       y="107.12505"
+       sodipodi:role="line"
+       id="tspan6866">  find destination named by message</tspan></text>
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);"
+     d="M 380.90551,79.724404 C 177.16536,53.149601 203.74016,256.88976 203.74016,248.03149"
+     id="path6868"
+     sodipodi:nodetypes="cc" />
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);"
+     d="M 451.77165,79.724404 C 788.38583,44.291333 779.52756,256.88976 779.52756,248.03149"
+     id="path6869"
+     sodipodi:nodetypes="cc" />
+  <rect
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#6a6a6a;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:1.2500000,1.2500000;stroke-dashoffset:0.0000000;"
+     id="rect7503"
+     width="318.89764"
+     height="168.30708"
+     x="345.47244"
+     y="115.15748" />
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;"
+     x="507.10016"
+     y="132.70409"
+     id="text8137"
+     sodipodi:linespacing="100%"><tspan
+       id="tspan8138">Destination Table</tspan></text>
+  <text
+     xml:space="preserve"
+     style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;font-stretch:normal;font-variant:normal;text-anchor:start;writing-mode:lr;"
+     x="422.71124"
+     y="158.39366"
+     id="text8140"
+     sodipodi:linespacing="120%"><tspan
+       x="422.71124"
+       y="158.39366"
+       sodipodi:role="line"
+       id="tspan8818">Connection 1</tspan><tspan
+       x="422.71124"
+       y="172.79366"
+       sodipodi:role="line"
+       id="tspan8820">Connection 2</tspan><tspan
+       x="422.71124"
+       y="187.19366"
+       sodipodi:role="line"
+       id="tspan8822">&quot;The Session Manager&quot;</tspan><tspan
+       x="422.71124"
+       y="201.59366"
+       sodipodi:role="line"
+       id="tspan8824">&quot;The Window Manager&quot;</tspan><tspan
+       x="422.71124"
+       y="215.99366"
+       sodipodi:role="line"
+       id="tspan8826">&quot;The Screensaver&quot;</tspan><tspan
+       x="422.71124"
+       y="230.39366"
+       sodipodi:role="line"
+       id="tspan8828">&quot;The Text Editor&quot;</tspan><tspan
+       x="422.71124"
+       y="244.79366"
+       sodipodi:role="line"
+       id="tspan8830">&quot;The Hardware Directory&quot;</tspan><tspan
+       x="422.71124"
+       y="259.19367"
+       sodipodi:role="line"
+       id="tspan8832">&quot;The Address Book&quot;</tspan><tspan
+       x="422.71124"
+       y="273.59367"
+       sodipodi:role="line"
+       id="tspan8834">&quot;The Dictionary&quot;</tspan></text>
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);"
+     d="M 416.33858,150.59055 C 239.17323,97.440935 221.45669,256.88976 221.45669,248.03149"
+     id="path8179"
+     sodipodi:nodetypes="cc" />
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);"
+     d="M 504.92126,168.30708 C 726.37795,106.29921 770.66929,265.74802 761.81102,239.17322"
+     id="path8180"
+     sodipodi:nodetypes="cc" />
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
+     d=""
+     id="path8181"
+     sodipodi:nodetypes="" />
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);"
+     d="M 584.64567,239.17322 C 717.51969,194.88188 761.81102,256.88976 752.95276,248.03149"
+     id="path8182"
+     sodipodi:nodetypes="cc" />
+  <path
+     style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);"
+     d="M 416.33858,177.16535 C 301.18111,124.01574 230.31496,265.74803 239.17323,248.03149"
+     id="path8184"
+     sodipodi:nodetypes="cc" />
+</svg>
diff --git a/dbus/doc/doxygen_to_devhelp.xsl b/dbus/doc/doxygen_to_devhelp.xsl
new file mode 100644
index 0000000..72098f9
--- /dev/null
+++ b/dbus/doc/doxygen_to_devhelp.xsl
@@ -0,0 +1,40 @@
+<xsl:stylesheet
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:fo="http://www.w3.org/1999/XSL/Format"
+    version="1.0">
+
+<xsl:output method="xml" version="1.0" indent="yes"/>
+
+<xsl:param name="prefix"></xsl:param>
+
+<xsl:template match="/">
+  <book title="D-Bus: A system for interprocess communication"
+        name="dbus"
+        link="dbus-tutorial.html">
+  <chapters>
+     <sub name="Tutorial" link="{$prefix}dbus-tutorial.html"/>
+     <sub name="FAQ" link="{$prefix}dbus-faq.html"/>
+     <sub name="Specification" link="{$prefix}dbus-specification.html"/>
+     <sub name="API Reference" link="{$prefix}api/index.html"/>
+  </chapters>
+
+  <functions>
+    <xsl:apply-templates select="doxygenindex/compound[@kind='group']/member[@kind='function']"/>
+  </functions>
+  </book>
+</xsl:template>
+
+<xsl:template match="member">
+  <xsl:param name="name"><xsl:value-of select="name"/></xsl:param>
+  <xsl:param name="refid"><xsl:value-of select="@refid"/></xsl:param>
+  <xsl:param name="before"><xsl:value-of select="substring-before($refid,'_1')"/></xsl:param>
+  <xsl:param name="after"><xsl:value-of select="substring-after($refid,'_1')"/></xsl:param>
+  <xsl:param name="link"><xsl:value-of select="$before"/>.html#<xsl:value-of select="$after"/></xsl:param>
+  <xsl:if test="starts-with($name,'dbus') or starts-with($name, 'DBus')">
+    <xsl:if test="starts-with($refid,'group__') and contains($refid, '_1')">
+       <function name="{$name}" link="{$prefix}api/{$link}"/>
+    </xsl:if>
+  </xsl:if>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/dbus/doc/file-boilerplate.c b/dbus/doc/file-boilerplate.c
new file mode 100644
index 0000000..bc365f8
--- /dev/null
+++ b/dbus/doc/file-boilerplate.c
@@ -0,0 +1,27 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* FILENAME  BRIEF FILE DESCRIPTION
+ *
+ * Copyright (C) YEAR  COPYRIGHT HOLDER
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_FOO_H
+#define DBUS_FOO_H
+
+#endif /* DBUS_FOO_H */
diff --git a/dbus/doc/introspect.dtd b/dbus/doc/introspect.dtd
new file mode 100644
index 0000000..ba263d3
--- /dev/null
+++ b/dbus/doc/introspect.dtd
@@ -0,0 +1,37 @@
+<!-- DTD for D-Bus Introspection data -->
+<!-- (C) 2005-02-02 David A. Wheeler; released under the D-Bus licenses,
+         GNU GPL version 2 (or greater) and AFL 1.1 (or greater) -->
+
+<!-- see D-Bus specification for documentation -->
+
+<!ELEMENT node (node|interface)*>
+<!ATTLIST node name CDATA #IMPLIED>
+
+<!ELEMENT interface (method|signal|property|annotation)*>
+<!ATTLIST interface name CDATA #REQUIRED>
+
+<!ELEMENT method (arg|annotation)*>
+<!ATTLIST method name CDATA #REQUIRED>
+
+<!ELEMENT signal (arg|annotation)*>
+<!ATTLIST signal name CDATA #REQUIRED>
+
+<!ELEMENT arg EMPTY>
+<!ATTLIST arg name CDATA #IMPLIED>
+<!ATTLIST arg type CDATA #REQUIRED>
+<!-- Method arguments SHOULD include "direction",
+     while signal and error arguments SHOULD not (since there's no point).
+     The DTD format can't express that subtlety. -->
+<!ATTLIST arg direction (in|out) "in">
+
+<!-- AKA "attribute" -->
+<!ELEMENT property (annotation)*>
+<!ATTLIST property name CDATA #REQUIRED>
+<!ATTLIST property type CDATA #REQUIRED> 
+<!ATTLIST property access (read|write|readwrite) #REQUIRED>
+
+<!ELEMENT annotation EMPTY>  <!-- Generic metadata -->
+<!ATTLIST annotation name CDATA #REQUIRED>
+<!ATTLIST annotation value CDATA #REQUIRED>
+
+
diff --git a/dbus/doc/introspect.xsl b/dbus/doc/introspect.xsl
new file mode 100644
index 0000000..2a34474
--- /dev/null
+++ b/dbus/doc/introspect.xsl
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="ISO-8859-15"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
+
+<!-- 
+ Copyright (C) 2005 Lennart Poettering.
+
+ Licensed under the Academic Free License version 2.1
+
+ 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
+-->
+
+<!-- $Id$ -->
+
+<xsl:output method="xml" version="1.0" encoding="iso-8859-15" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes"/>
+
+<xsl:template match="/">
+  <html>
+    <head>
+      <title>DBUS Introspection data</title>
+      <style type="text/css">
+        body { color: black; background-color: white } 
+        h1 { font-family: sans-serif }
+        ul { list-style-type: none; margin-bottom: 10px }
+        li { font-family: sans-serif }
+        .keyword { font-style: italic }
+        .type { font-weight: bold }
+        .symbol { font-family: monospace }
+        .interface { padding: 10px; margin: 10px }
+      </style>
+    </head>
+    <body>
+      <xsl:for-each select="node/interface">
+        <div class="interface">
+          <h1>
+            <span class="keyword">interface</span><xsl:text> </xsl:text>
+            <span class="symbol"><xsl:value-of select="@name"/></span>
+          </h1>   
+          
+          <ul>
+
+            <xsl:apply-templates select="annotation"/> 
+
+            <xsl:for-each select="method|signal|property">
+              <li>
+                <span class="keyword"><xsl:value-of select="name()"/></span>
+                <xsl:text> </xsl:text>
+                <span class="symbol"><xsl:value-of select="@name"/></span>
+                
+                <ul>
+                  <xsl:apply-templates select="annotation"/> 
+                  <xsl:for-each select="arg">
+                    <li>
+                      <span class="keyword">
+                        <xsl:choose>
+                          <xsl:when test="@direction != &quot;&quot;">
+                            <xsl:value-of select="@direction"/> 
+                          </xsl:when>
+                          <xsl:when test="name(..) = &quot;signal&quot;">
+                            out
+                          </xsl:when>
+                          <xsl:otherwise>
+                            in
+                          </xsl:otherwise>
+                        </xsl:choose>
+                      </span>
+
+                      <xsl:text> </xsl:text>
+                      
+                      <span class="type"><xsl:value-of select="@type"/></span><xsl:text> </xsl:text>
+                      <span class="symbol"><xsl:value-of select="@name"/></span><xsl:text> </xsl:text>
+                    </li>
+                  </xsl:for-each>
+                </ul>
+
+              </li>
+            </xsl:for-each>
+
+          </ul>
+        </div>
+      </xsl:for-each>
+    </body>
+  </html>
+</xsl:template>
+
+
+<xsl:template match="annotation"> 
+  <li>
+    <span class="keyword">annotation</span>
+    <code><xsl:value-of select="@name"/></code><xsl:text> = </xsl:text>
+    <code><xsl:value-of select="@value"/></code>
+  </li>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/dbus/doc/system-activation.txt b/dbus/doc/system-activation.txt
new file mode 100644
index 0000000..dd195f7
--- /dev/null
+++ b/dbus/doc/system-activation.txt
@@ -0,0 +1,80 @@
+D-BUS System Activation
+
+Introduction:
+
+The dbus-daemon runs as the dbus user, and is therefore unprivileged.
+Earlier attempts [1] by David Zeuthen at launching system scripts using a
+custom DBUS protocol were reviewed, but deemed too difficult to audit, and
+also due to a multi-threaded design, too difficult to test.
+In the next few paragraphs I will outline a simpler setuid approach for
+launching daemons as a configured user.
+
+Scope:
+
+Launching programs using dbus has been a topic of interest for many months.
+This would allow simple systems to only start services that are needed,
+and that are automatically started only when first requested.
+This removes the need for an init system, and means that we can trivially
+startup services in parallel.
+This has immediate pressing need for OLPC, with a longer term evaluation for
+perhaps Fedora and RHEL.
+
+Details:
+
+Setuid applications have to used only when absolutely necessary.
+In this implementation I have an single executable,
+dbus-daemon-launch-helper, with the ownership root:dbus.
+This has the permissions 4750, i.e. u+rwx g+rx +setuid.
+It is located in /usr/libexec/ and thus is not designed to be invoked by a
+user directly.
+
+The helper must not be passed input that can be changed maliciously, and
+therefore passing a random path with user id is totally out of the question.
+In this implementation a similar idea as discussed with Davids' patch was
+taken, that to pass a single name argument to the helper.
+The service filename of "org.me.test.service" is then searched for in
+/usr/share/dbus-1/system-services or other specified directories.
+
+If applications want to be activated on the system _and_ session busses, then
+service files should be installed in both directories.
+
+A typical service file would look like:
+
+[D-BUS Service]
+Name=org.me.test
+Exec=/usr/sbin/dbus-test-server.py
+User=ftp
+
+This gives the user to switch to, and also the path of the executable.
+The service name must match that specified in the /etc/dbus-1/system.d conf file.
+
+Precautions taken:
+
+* Only the bus name is passed to the helper, and this is validated
+* We are super paranoid about the user that called us, and what permissions we have.
+* We clear all environment variables except for DBUS_VERBOSE which is used for debugging
+* Anything out of the ordinary causes the helper to abort.
+
+Launching services:
+
+Trivial methods on services can be called directly and the launch helper will
+start the service and execute the method on the service. The lauching of the
+service is completely transparent to the caller, e.g.:
+
+dbus-send --system --print-reply			\
+	--dest=org.freedesktop.Hal			\
+	/org/freedesktop/Hal/Manager			\
+	org.freedesktop.Hal.Manager.DeviceExists	\
+	string:/org/freedesktop/Hal/devices/computer
+
+If you wish to activate the service without calling a well known method,
+the standard dbus method StartServiceByName can be used:
+
+dbus-send --system --print-reply			\
+	--dest=org.freedesktop.DBus			\
+	/org/freedesktop/DBus				\
+	org.freedesktop.DBus.StartServiceByName		\
+	string:org.freedesktop.Hal uint32:0
+
+[1] http://lists.freedesktop.org/archives/dbus/2006-October/006096.html
+
diff --git a/dbus/m4/as-ac-expand.m4 b/dbus/m4/as-ac-expand.m4
new file mode 100644
index 0000000..deebd2b
--- /dev/null
+++ b/dbus/m4/as-ac-expand.m4
@@ -0,0 +1,49 @@
+dnl as-ac-expand.m4 0.2.0                                   -*- autoconf -*-
+dnl autostars m4 macro for expanding directories using configure's prefix
+
+dnl (C) 2003, 2004, 2005 Thomas Vander Stichele <thomas at apestaart dot org>
+
+dnl Copying and distribution of this file, with or without modification,
+dnl are permitted in any medium without royalty provided the copyright
+dnl notice and this notice are preserved.
+
+dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR)
+
+dnl example:
+dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
+dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local
+
+AC_DEFUN([AS_AC_EXPAND],
+[
+  EXP_VAR=[$1]
+  FROM_VAR=[$2]
+
+  dnl first expand prefix and exec_prefix if necessary
+  prefix_save=$prefix
+  exec_prefix_save=$exec_prefix
+
+  dnl if no prefix given, then use /usr/local, the default prefix
+  if test "x$prefix" = "xNONE"; then
+    prefix="$ac_default_prefix"
+  fi
+  dnl if no exec_prefix given, then use prefix
+  if test "x$exec_prefix" = "xNONE"; then
+    exec_prefix=$prefix
+  fi
+
+  full_var="$FROM_VAR"
+  dnl loop until it doesn't change anymore
+  while true; do
+    new_full_var="`eval echo $full_var`"
+    if test "x$new_full_var" = "x$full_var"; then break; fi
+    full_var=$new_full_var
+  done
+
+  dnl clean up
+  full_var=$new_full_var
+  AC_SUBST([$1], "$full_var")
+
+  dnl restore prefix and exec_prefix
+  prefix=$prefix_save
+  exec_prefix=$exec_prefix_save
+])
diff --git a/dbus/m4/compiler.m4 b/dbus/m4/compiler.m4
new file mode 100644
index 0000000..5aff5d8
--- /dev/null
+++ b/dbus/m4/compiler.m4
@@ -0,0 +1,67 @@
+# compiler.m4 - autoconf macros for compiler settings
+#
+# Copyright © 2005 Scott James Remnant <scott@netsplit.com>.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+# COMPILER_WARNINGS
+# ----------------------
+# Add configure option to enable additional compiler warnings and treat
+# them as errors.
+AC_DEFUN([COMPILER_WARNINGS],
+[AC_ARG_ENABLE(compiler-warnings,
+	AS_HELP_STRING([--enable-compiler-warnings],
+	               [Enable additional compiler warnings]),
+[if test "x$enable_compiler_warnings" = "xyes"; then
+	if test "x$GCC" = "xyes"; then
+                CFLAGS="-Wall -Werror $CFLAGS"
+        fi
+	if test "x$GXX" = "xyes"; then
+		CXXFLAGS="-Wall -Werror $CXXFLAGS"
+	fi
+fi])dnl
+])# COMPILER_WARNINGS
+
+# COMPILER_OPTIMISATIONS
+# ---------------------------
+# Add configure option to disable optimisations.
+AC_DEFUN([COMPILER_OPTIMISATIONS],
+[AC_ARG_ENABLE(compiler-optimisations,
+	AS_HELP_STRING([--disable-compiler-optimisations],
+		       [Disable compiler optimisations]),
+[if test "x$enable_compiler_optimisations" = "xno"; then
+	[CFLAGS=`echo "$CFLAGS" | sed -e "s/ -O[1-9]*\b/ -O0/g"`]
+fi])dnl
+])# COMPILER_OPTIMISATIONS
+
+# COMPILER_COVERAGE
+# ----------------------
+# Add configure option to enable coverage data.
+AC_DEFUN([COMPILER_COVERAGE],
+[AC_ARG_ENABLE(compiler-coverage,
+	AS_HELP_STRING([--enable-compiler-coverage],
+		       [Enable generation of coverage data]),
+[if test "x$enable_compiler_coverage" = "xyes"; then
+	if test "x$GCC" = "xyes"; then
+		CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage"
+	fi
+fi])dnl
+])# COMPILER_COVERAGE
diff --git a/dbus/m4/pkg.m4 b/dbus/m4/pkg.m4
new file mode 100644
index 0000000..64be747
--- /dev/null
+++ b/dbus/m4/pkg.m4
@@ -0,0 +1,155 @@
+# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=m4_default([$1], [0.9.0])
+	AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		AC_MSG_RESULT([yes])
+	else
+		AC_MSG_RESULT([no])
+		PKG_CONFIG=""
+	fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists.  Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+		     [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
+        else
+	        $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+	ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+		[AC_MSG_RESULT([no])
+                $4])
+elif test $pkg_failed = untried; then
+	ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
+		[$4])
+else
+	$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+	$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+	ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
diff --git a/dbus/m4/tp-compiler-flag.m4 b/dbus/m4/tp-compiler-flag.m4
new file mode 100644
index 0000000..06deaba
--- /dev/null
+++ b/dbus/m4/tp-compiler-flag.m4
@@ -0,0 +1,43 @@
+dnl A version of AS_COMPILER_FLAG that supports both C and C++.
+dnl Based on:
+
+dnl as-compiler-flag.m4 0.1.0
+dnl autostars m4 macro for detection of compiler flags
+dnl David Schleef <ds@schleef.org>
+dnl $Id: as-compiler-flag.m4,v 1.1 2005/06/18 18:02:46 burgerman Exp $
+
+dnl TP_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
+dnl Tries to compile with the given CFLAGS and CXXFLAGS.
+dnl
+dnl Runs ACTION-IF-ACCEPTED if the compiler for the currently selected
+dnl AC_LANG can compile with the flags, and ACTION-IF-NOT-ACCEPTED otherwise.
+
+AC_DEFUN([TP_COMPILER_FLAG],
+[
+  AC_MSG_CHECKING([to see if compiler understands $1])
+
+  save_CFLAGS="$CFLAGS"
+  save_CXXFLAGS="$CXXFLAGS"
+  CFLAGS="$CFLAGS $1"
+  CXXFLAGS="$CXXFLAGS $1"
+
+  AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
+  CFLAGS="$save_CFLAGS"
+  CXXFLAGS="$save_CXXFLAGS"
+
+  if test "X$flag_ok" = Xyes ; then
+    $2
+    true
+  else
+    $3
+    true
+  fi
+  AC_MSG_RESULT([$flag_ok])
+])
+
+dnl TP_ADD_COMPILER_FLAG(VARIABLE, CFLAGS)
+dnl Append CFLAGS to VARIABLE if the compiler supports them.
+AC_DEFUN([TP_ADD_COMPILER_FLAG],
+[
+  TP_COMPILER_FLAG([$2], [$1="[$]$1 $2"])
+])
diff --git a/dbus/m4/tp-compiler-warnings.m4 b/dbus/m4/tp-compiler-warnings.m4
new file mode 100644
index 0000000..ee4af31
--- /dev/null
+++ b/dbus/m4/tp-compiler-warnings.m4
@@ -0,0 +1,49 @@
+dnl TP_COMPILER_WARNINGS(VARIABLE, WERROR_BY_DEFAULT, DESIRABLE, UNDESIRABLE)
+dnl $1 (VARIABLE): the variable to put flags into
+dnl $2 (WERROR_BY_DEFAULT): a command returning true if -Werror should be the
+dnl     default
+dnl $3 (DESIRABLE): warning flags we want (e.g. all extra shadow)
+dnl $4 (UNDESIRABLE): warning flags we don't want (e.g.
+dnl   missing-field-initializers unused-parameter)
+AC_DEFUN([TP_COMPILER_WARNINGS],
+[
+  AC_REQUIRE([AC_ARG_ENABLE])dnl
+  AC_REQUIRE([AC_HELP_STRING])dnl
+  AC_REQUIRE([TP_COMPILER_FLAG])dnl
+
+  tp_warnings=""
+  for tp_flag in $3; do
+    TP_COMPILER_FLAG([-W$tp_flag], [tp_warnings="$tp_warnings -W$tp_flag"])
+  done
+
+  tp_error_flags="-Werror"
+  TP_COMPILER_FLAG([-Werror], [tp_werror=yes], [tp_werror=no])
+
+  for tp_flag in $4; do
+    TP_COMPILER_FLAG([-Wno-$tp_flag],
+      [tp_warnings="$tp_warnings -Wno-$tp_flag"])
+dnl Yes, we do need to use both -Wno-foo and -Wno-error=foo. Simon says:
+dnl     some warnings we explicitly don't want, like unused-parameter, but
+dnl     they're in -Wall. when a distro using cdbs compiles us, we have:
+dnl       -Werror -Wno-unused-parameter      -Wall
+dnl         ^ from us                         ^ from cdbs
+dnl     which turns -Wunused-parameter back on, in effect
+    TP_COMPILER_FLAG([-Wno-error=$tp_flag],
+      [tp_error_flags="$tp_error_flags -Wno-error=$tp_flag"], [tp_werror=no])
+  done
+
+  AC_ARG_ENABLE([Werror],
+    AC_HELP_STRING([--disable-Werror],
+      [compile without -Werror (normally enabled in development builds)]),
+    tp_werror=$enableval, :)
+
+  if test "x$tp_werror" = xyes && $2; then
+dnl We put -Wno-error=foo before -Wno-foo because clang interprets -Wall
+dnl -Werror -Wno-foo -Wno-error=foo as “make foo a non-fatal warning”, but does
+dnl what we want if you reverse them.
+    $1="$tp_error_flags $tp_warnings"
+  else
+    $1="$tp_warnings"
+  fi
+
+])
diff --git a/dbus/test/Makefile.am b/dbus/test/Makefile.am
new file mode 100644
index 0000000..e944899
--- /dev/null
+++ b/dbus/test/Makefile.am
@@ -0,0 +1,327 @@
+## the "name-test" subdir in fact contains a bunch of tests now that need a temporary bus 
+## to be running to do stuff with. The directory should be renamed.
+## We want to build the current directory first to pick up the testutils lib
+SUBDIRS= . name-test 
+DIST_SUBDIRS=name-test
+
+# CPPFLAGS for binaries that are normally dynamic
+AM_CPPFLAGS = \
+	-I$(top_srcdir) \
+	$(DBUS_STATIC_BUILD_CPPFLAGS) \
+	$(GLIB_CFLAGS) \
+	$(DBUS_GLIB_CFLAGS) \
+	$(NULL)
+
+# improve backtraces from test stuff
+AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
+
+# CPPFLAGS for binaries that are always static
+static_cppflags = \
+	$(AM_CPPFLAGS) \
+	-DDBUS_STATIC_BUILD \
+	$(NULL)
+
+libdbus_testutils_la_CPPFLAGS = \
+	$(static_cppflags)
+libdbus_testutils_la_SOURCES = \
+	test-utils.c \
+	test-utils.h \
+	$(NULL)
+libdbus_testutils_la_LIBADD = \
+	$(top_builddir)/dbus/libdbus-internal.la \
+	$(NULL)
+
+noinst_LTLIBRARIES = libdbus-testutils.la
+
+if DBUS_BUILD_TESTS
+## break-loader removed for now
+## these binaries are used in tests but are not themselves tests
+TEST_BINARIES = \
+	spawn-test \
+	test-exit \
+	test-names \
+	test-segfault \
+	test-service \
+	test-shell-service \
+	test-sleep-forever \
+	$(NULL)
+
+## These are conceptually part of directories that come earlier in SUBDIRS
+## order, but we don't want to run them til we arrive in this directory,
+## since they depend on stuff from this directory
+TESTS = \
+	../bus/bus-test$(EXEEXT) \
+	../bus/bus-test-system$(EXEEXT) \
+	../dbus/dbus-test$(EXEEXT) \
+	$(NULL)
+
+if DBUS_UNIX
+TESTS += ../bus/bus-test-launch-helper$(EXEEXT)
+endif
+
+else !DBUS_BUILD_TESTS
+
+TEST_BINARIES=
+TESTS=
+
+endif !DBUS_BUILD_TESTS
+
+noinst_PROGRAMS= $(TEST_BINARIES)
+
+test_service_CPPFLAGS = $(static_cppflags)
+test_service_LDADD = libdbus-testutils.la
+test_names_CPPFLAGS = $(static_cppflags)
+test_names_LDADD = libdbus-testutils.la
+## break_loader_CPPFLAGS = $(static_cppflags)
+## break_loader_LDADD = $(top_builddir)/dbus/libdbus-internal.la
+test_shell_service_CPPFLAGS = $(static_cppflags)
+test_shell_service_LDADD = libdbus-testutils.la
+shell_test_CPPFLAGS = $(static_cppflags)
+shell_test_LDADD = libdbus-testutils.la
+spawn_test_CPPFLAGS = $(static_cppflags)
+spawn_test_LDADD = $(top_builddir)/dbus/libdbus-internal.la
+
+test_refs_SOURCES = internals/refs.c
+test_refs_CPPFLAGS = $(static_cppflags)
+test_refs_LDADD = libdbus-testutils.la $(GLIB_LIBS)
+
+test_syslog_SOURCES = internals/syslog.c
+test_syslog_CPPFLAGS = $(static_cppflags)
+test_syslog_LDADD = libdbus-testutils.la $(GLIB_LIBS)
+
+EXTRA_DIST = dbus-test-runner
+
+testexecdir = $(libdir)/dbus-1.0/test
+
+testexec_PROGRAMS =
+
+installable_tests = \
+	shell-test \
+	$(NULL)
+
+if DBUS_WITH_GLIB
+installable_tests += \
+	test-corrupt \
+	test-dbus-daemon \
+	test-dbus-daemon-eavesdrop \
+	test-loopback \
+	test-marshal \
+	test-refs \
+	test-relay \
+	test-syntax \
+	test-syslog \
+	$(NULL)
+endif DBUS_WITH_GLIB
+
+installcheck_tests =
+installcheck_environment = \
+	DBUS_TEST_DAEMON=$(DESTDIR)$(DBUS_DAEMONDIR)/dbus-daemon$(EXEEXT) \
+	DBUS_TEST_HOMEDIR=@abs_top_builddir@/dbus \
+	DBUS_TEST_SYSCONFDIR=$(DESTDIR)$(sysconfdir)
+
+TESTS_ENVIRONMENT = \
+	DBUS_BLOCK_ON_ABORT=1 \
+	DBUS_FATAL_WARNINGS=1 \
+	DBUS_TEST_DAEMON=@abs_top_builddir@/bus/dbus-daemon$(EXEEXT) \
+	DBUS_TEST_DATA=@abs_top_builddir@/test/data \
+	DBUS_TEST_HOMEDIR=@abs_top_builddir@/dbus \
+	$(NULL)
+
+test_corrupt_SOURCES = corrupt.c
+test_corrupt_LDADD = $(top_builddir)/dbus/libdbus-1.la \
+    $(GLIB_LIBS) \
+    $(DBUS_GLIB_LIBS)
+
+test_loopback_SOURCES = loopback.c
+test_loopback_LDADD = $(top_builddir)/dbus/libdbus-1.la \
+    $(GLIB_LIBS) \
+    $(DBUS_GLIB_LIBS)
+
+test_relay_SOURCES = relay.c
+test_relay_LDADD = $(top_builddir)/dbus/libdbus-1.la \
+    $(GLIB_LIBS) \
+    $(DBUS_GLIB_LIBS)
+
+test_dbus_daemon_SOURCES = dbus-daemon.c
+test_dbus_daemon_LDADD = $(top_builddir)/dbus/libdbus-1.la \
+    $(GLIB_LIBS) \
+    $(DBUS_GLIB_LIBS)
+
+test_dbus_daemon_eavesdrop_SOURCES = dbus-daemon-eavesdrop.c
+test_dbus_daemon_eavesdrop_CPPFLAGS = $(GLIB_CFLAGS) $(DBUS_GLIB_CFLAGS)
+test_dbus_daemon_eavesdrop_LDFLAGS = @R_DYNAMIC_LDFLAG@
+test_dbus_daemon_eavesdrop_LDADD = $(top_builddir)/dbus/libdbus-1.la \
+    $(GLIB_LIBS) \
+    $(DBUS_GLIB_LIBS)
+
+test_marshal_SOURCES = marshal.c
+test_marshal_LDADD = $(top_builddir)/dbus/libdbus-1.la \
+    $(GLIB_LIBS) \
+    $(DBUS_GLIB_LIBS)
+
+test_syntax_SOURCES = syntax.c
+test_syntax_LDADD = $(top_builddir)/dbus/libdbus-1.la \
+    $(GLIB_LIBS)
+
+if DBUS_ENABLE_MODULAR_TESTS
+TESTS += $(installable_tests)
+installcheck_tests += $(installable_tests)
+
+if DBUS_ENABLE_INSTALLED_TESTS
+  testexec_PROGRAMS += $(installable_tests)
+else !DBUS_ENABLE_INSTALLED_TESTS
+  noinst_PROGRAMS += $(installable_tests)
+endif !DBUS_ENABLE_INSTALLED_TESTS
+
+endif DBUS_ENABLE_MODULAR_TESTS
+
+# If we're installing the tests into a DESTDIR we can't run them
+# again using the installed copy, because we don't know how to
+# do a portable equivalent of setting LD_LIBRARY_PATH.
+installcheck-local:
+	$(MAKE) check-TESTS TESTS='$$(installcheck_tests)' \
+		TESTS_ENVIRONMENT='$$(installcheck_environment)'
+if DBUS_ENABLE_INSTALLED_TESTS
+	test -n "$(DESTDIR)" || \
+	$(installcheck_environment) \
+		$(srcdir)/dbus-test-runner \
+		$(testexecdir) \
+		$(testexec_PROGRAMS)
+endif DBUS_ENABLE_INSTALLED_TESTS
+
+in_data = \
+	data/valid-config-files-system/debug-allow-all-fail.conf.in \
+	data/valid-config-files-system/debug-allow-all-pass.conf.in \
+	data/valid-config-files/debug-allow-all-sha1.conf.in \
+	data/valid-config-files/debug-allow-all.conf.in \
+	data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service.in \
+	data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.in \
+	data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoUser.service.in \
+	data/valid-service-files-system/org.freedesktop.DBus.TestSuiteEchoService.service.in \
+	data/valid-service-files-system/org.freedesktop.DBus.TestSuiteSegfaultService.service.in \
+	data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service.in \
+	data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service.in \
+	data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service.in \
+	data/valid-service-files/org.freedesktop.DBus.TestSuiteEchoService.service.in \
+	data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service.in \
+	data/valid-service-files/org.freedesktop.DBus.TestSuiteSegfaultService.service.in \
+	data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service.in \
+	data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service.in \
+	$(NULL)
+
+EXTRA_DIST += $(in_data)
+
+static_data = \
+	name-test/tmp-session-like-system.conf \
+	data/auth/anonymous-client-successful.auth-script \
+	data/auth/anonymous-server-successful.auth-script \
+	data/auth/cancel.auth-script \
+	data/auth/client-out-of-mechanisms.auth-script \
+	data/auth/external-failed.auth-script \
+	data/auth/external-root.auth-script \
+	data/auth/external-silly.auth-script \
+	data/auth/external-successful.auth-script \
+	data/auth/extra-bytes.auth-script \
+	data/auth/fail-after-n-attempts.auth-script \
+	data/auth/fallback.auth-script \
+	data/auth/invalid-command-client.auth-script \
+	data/auth/invalid-command.auth-script \
+	data/auth/invalid-hex-encoding.auth-script \
+	data/auth/mechanisms.auth-script \
+	data/equiv-config-files/basic/basic-1.conf \
+	data/equiv-config-files/basic/basic-2.conf \
+	data/equiv-config-files/basic/basic.d/basic.conf \
+	data/equiv-config-files/entities/basic.d/basic.conf \
+	data/equiv-config-files/entities/entities-1.conf \
+	data/equiv-config-files/entities/entities-2.conf \
+	data/incomplete-messages/missing-body.message \
+	data/invalid-config-files/badselinux-1.conf \
+	data/invalid-config-files/badselinux-2.conf \
+	data/invalid-config-files/circular-1.conf \
+	data/invalid-config-files/circular-2.conf \
+	data/invalid-config-files/circular-3.conf \
+	data/invalid-config-files/not-well-formed.conf \
+	data/invalid-config-files/truncated-file.conf \
+	data/invalid-messages/array-of-nil.message \
+	data/invalid-messages/array-with-mixed-types.message \
+	data/invalid-messages/bad-boolean-array.message \
+	data/invalid-messages/bad-boolean.message \
+	data/invalid-messages/bad-endian.message \
+	data/invalid-messages/bad-header-field-alignment.message \
+	data/invalid-messages/boolean-has-no-value.message-raw \
+	data/invalid-messages/local-namespace.message \
+	data/invalid-messages/no-dot-in-name.message \
+	data/invalid-messages/not-nul-header-padding.message \
+	data/invalid-messages/overlong-name.message \
+	data/invalid-messages/too-little-header-padding.message \
+	data/invalid-messages/too-much-header-padding-by-far.message \
+	data/invalid-messages/too-much-header-padding.message \
+	data/invalid-messages/too-short-dict.message \
+	data/sha-1/Readme.txt \
+	data/sha-1/bit-hashes.sha1 \
+	data/sha-1/bit-messages.sha1 \
+	data/sha-1/byte-hashes.sha1 \
+	data/sha-1/byte-messages.sha1 \
+	data/valid-config-files/basic.conf \
+	data/valid-config-files/basic.d/basic.conf \
+	data/valid-config-files/entities.conf \
+	data/valid-config-files/incoming-limit.conf \
+	data/valid-config-files/many-rules.conf \
+	data/valid-config-files/system.d/test.conf \
+	data/valid-messages/array-of-array-of-uint32.message \
+	data/valid-messages/dict-simple.message \
+	data/valid-messages/dict.message \
+	data/valid-messages/emptiness.message \
+	data/valid-messages/lots-of-arguments.message \
+	data/valid-messages/no-padding.message \
+	data/valid-messages/opposite-endian.message \
+	data/valid-messages/recursive-types.message \
+	data/valid-messages/simplest-manual.message \
+	data/valid-messages/simplest.message \
+	data/valid-messages/standard-acquire-service.message \
+	data/valid-messages/standard-hello.message \
+	data/valid-messages/standard-list-services.message \
+	data/valid-messages/standard-service-exists.message \
+	data/valid-messages/unknown-header-field.message \
+	$(NULL)
+
+EXTRA_DIST += $(static_data)
+
+## copy tests to builddir so that generated tests and static tests
+## are all in one place.
+all-local:
+	$(AM_V_at)$(MKDIR_P) data/valid-config-files/session.d
+	$(AM_V_at)set -e && \
+	if test $(srcdir) = . || test $(srcdir) -ef .; then \
+		echo '-- No need to copy test data as srcdir = builddir'; \
+	else \
+		for F in $(static_data); do \
+			$(MKDIR_P) $${F%/*}; \
+			rm -f $$F; \
+			cp $(srcdir)/$$F $$F; \
+		done; \
+	fi
+
+## this doesn't clean most copied test data files when srcdir=builddir
+clean-local:
+	$(AM_V_at)if test $(srcdir) = . || test $(srcdir) -ef .; then \
+		echo '-- No need to clean test data as srcdir = builddir'; \
+	else \
+		rm -f $(static_data); \
+	fi
+
+imported_data = \
+	data/valid-config-files/session.conf \
+	data/valid-config-files/system.conf \
+	$(NULL)
+
+noinst_DATA = $(imported_data)
+CLEANFILES = $(noinst_DATA)
+
+data/valid-config-files/session.conf: $(top_builddir)/bus/session.conf
+	$(AM_V_at)$(MKDIR_P) data/valid-config-files
+	$(AM_V_GEN)cp $< $@
+
+data/valid-config-files/system.conf: $(top_builddir)/bus/system.conf
+	$(AM_V_at)$(MKDIR_P) data/valid-config-files
+	$(AM_V_GEN)cp $< $@
diff --git a/dbus/test/break-loader.c b/dbus/test/break-loader.c
new file mode 100644
index 0000000..e62b8c2
--- /dev/null
+++ b/dbus/test/break-loader.c
@@ -0,0 +1,764 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-break-loader.c  Program to find byte streams that break the message loader
+ *
+ * Copyright (C) 2003  Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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
+ *
+ */
+
+#include <config.h>
+#include <dbus/dbus.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <string.h>
+
+#define DBUS_COMPILATION 
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-test.h>
+#include <dbus/dbus-marshal-basic.h>
+#undef DBUS_COMPILATION
+
+static DBusString failure_dir;
+static int total_attempts;
+static int failures_this_iteration;
+
+static int
+random_int_in_range (int start,
+                     int end)
+{
+  /* such elegant math */
+  double gap;
+  double v_double;
+  int v;
+
+  if (start == end)
+    return start;
+
+  _dbus_assert (end > start);
+  
+  gap = end - start - 1; /* -1 to not include "end" */
+  v_double = ((double)start) + (((double)rand ())/RAND_MAX) * gap;
+  if (v_double < 0.0)
+    v = (v_double - 0.5);
+  else
+    v = (v_double + 0.5);
+  
+  if (v < start)
+    {
+      fprintf (stderr, "random_int_in_range() generated %d for range [%d,%d)\n",
+               v, start, end);
+      v = start;
+    }
+  else if (v >= end)
+    {
+      fprintf (stderr, "random_int_in_range() generated %d for range [%d,%d)\n",
+               v, start, end);
+      v = end - 1;
+    }
+
+  /* printf ("  %d of [%d,%d)\n", v, start, end); */
+  
+  return v;
+}
+
+static dbus_bool_t
+try_mutated_data (const DBusString *data)
+{
+  int pid;
+
+  total_attempts += 1;
+  /* printf ("  attempt %d\n", total_attempts); */
+  
+  pid = fork ();
+
+  if (pid < 0)
+    {
+      fprintf (stderr, "fork() failed: %s\n",
+               strerror (errno));
+      exit (1);
+      return FALSE;
+    }
+
+  if (pid == 0)
+    {
+      /* Child, try loading the data */
+      if (!dbus_internal_do_not_use_try_message_data (data, _DBUS_MESSAGE_UNKNOWN))
+        exit (1);
+      else
+        exit (0);
+    }
+  else
+    {
+      /* Parent, wait for child */
+      int status;
+      DBusString filename;
+      dbus_bool_t failed;
+
+      if (waitpid (pid, &status, 0) < 0)
+        {
+          fprintf (stderr, "waitpid() failed: %s\n", strerror (errno));
+          exit (1);
+          return FALSE;
+        }
+
+      failed = FALSE;
+
+      if (!_dbus_string_init (&filename) ||
+          !_dbus_string_copy (&failure_dir, 0,
+                              &filename, 0) ||
+          !_dbus_string_append_byte (&filename, '/'))
+        {
+          fprintf (stderr, "out of memory\n");
+          exit (1);
+        }
+
+      _dbus_string_append_int (&filename, total_attempts);
+
+      if (WIFEXITED (status))
+        {
+          if (WEXITSTATUS (status) != 0)
+            {
+              _dbus_string_append (&filename, "-exited-");
+              _dbus_string_append_int (&filename, WEXITSTATUS (status));
+              failed = TRUE;
+            }
+        }
+      else if (WIFSIGNALED (status))
+        {
+          _dbus_string_append (&filename, "signaled-");
+          _dbus_string_append_int (&filename, WTERMSIG (status));
+          failed = TRUE;
+        }
+
+      if (failed)
+        {
+          DBusError error;
+
+          _dbus_string_append (&filename, ".message-raw");
+          
+          printf ("Child failed, writing %s\n", _dbus_string_get_const_data (&filename));
+
+          dbus_error_init (&error);
+          if (!_dbus_string_save_to_file (data, &filename, FALSE, &error))
+            {
+              fprintf (stderr, "Failed to save failed message data: %s\n",
+                       error.message);
+              dbus_error_free (&error);
+              exit (1); /* so we can see the seed that was printed out */
+            }
+
+          failures_this_iteration += 1;
+
+	  _dbus_string_free (&filename);
+	  
+          return FALSE;
+        }
+      else
+	{
+	  _dbus_string_free (&filename);	  
+	  return TRUE;
+	}
+    }
+
+  _dbus_assert_not_reached ("should not be reached");
+  return TRUE;
+}
+
+static void
+randomly_shorten_or_lengthen (const DBusString *orig_data,
+                              DBusString       *mutated)
+{
+  int delta;
+
+  if (orig_data != mutated)
+    {
+      _dbus_string_set_length (mutated, 0);
+      
+      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
+        _dbus_assert_not_reached ("out of mem");
+    }
+
+  if (_dbus_string_get_length (mutated) == 0)
+    delta = random_int_in_range (0, 10);
+  else
+    delta = random_int_in_range (- _dbus_string_get_length (mutated),
+                                 _dbus_string_get_length (mutated) * 3);
+  
+  if (delta < 0)
+    _dbus_string_shorten (mutated, - delta);
+  else if (delta > 0)
+    {
+      int i = 0;
+
+      i = _dbus_string_get_length (mutated);
+      if (!_dbus_string_lengthen (mutated, delta))
+        _dbus_assert_not_reached ("couldn't lengthen string");
+
+      while (i < _dbus_string_get_length (mutated))
+        {
+          _dbus_string_set_byte (mutated,
+                                 i,
+                                 random_int_in_range (0, 256));
+          ++i;
+        }
+    }
+}
+
+static void
+randomly_change_one_byte (const DBusString *orig_data,
+                          DBusString       *mutated)
+{
+  int i;
+
+  if (orig_data != mutated)
+    {
+      _dbus_string_set_length (mutated, 0);
+      
+      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
+        _dbus_assert_not_reached ("out of mem");
+    }
+
+  if (_dbus_string_get_length (mutated) == 0)
+    return;
+  
+  i = random_int_in_range (0, _dbus_string_get_length (mutated));
+
+  _dbus_string_set_byte (mutated, i,
+                         random_int_in_range (0, 256));
+}
+
+static void
+randomly_remove_one_byte (const DBusString *orig_data,
+                          DBusString       *mutated)
+{
+  int i;
+
+  if (orig_data != mutated)
+    {
+      _dbus_string_set_length (mutated, 0);
+      
+      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
+        _dbus_assert_not_reached ("out of mem");
+    }
+
+  if (_dbus_string_get_length (mutated) == 0)
+    return;
+  
+  i = random_int_in_range (0, _dbus_string_get_length (mutated));
+
+  _dbus_string_delete (mutated, i, 1);
+}
+
+
+static void
+randomly_add_one_byte (const DBusString *orig_data,
+                       DBusString       *mutated)
+{
+  int i;
+
+  if (orig_data != mutated)
+    {
+      _dbus_string_set_length (mutated, 0);
+      
+      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
+        _dbus_assert_not_reached ("out of mem");
+    }
+
+  i = random_int_in_range (0, _dbus_string_get_length (mutated));
+
+  _dbus_string_insert_bytes (mutated, i, 1,
+			     random_int_in_range (0, 256));
+}
+
+static void
+randomly_modify_length (const DBusString *orig_data,
+                        DBusString       *mutated)
+{
+  int i;
+  int byte_order;
+  const char *d;
+  dbus_uint32_t orig;
+  int delta;
+  
+  if (orig_data != mutated)
+    {
+      _dbus_string_set_length (mutated, 0);
+      
+      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
+        _dbus_assert_not_reached ("out of mem");
+    }
+
+  if (_dbus_string_get_length (mutated) < 12)
+    return;
+  
+  d = _dbus_string_get_const_data (mutated);
+
+  if (!(*d == DBUS_LITTLE_ENDIAN ||
+        *d == DBUS_BIG_ENDIAN))
+    return;
+
+  byte_order = *d;
+  
+  i = random_int_in_range (4, _dbus_string_get_length (mutated) - 8);
+  i = _DBUS_ALIGN_VALUE (i, 4);
+
+  orig = _dbus_demarshal_uint32 (mutated, byte_order, i, NULL);
+
+  delta = random_int_in_range (-10, 10);  
+  
+  _dbus_marshal_set_uint32 (mutated, byte_order, i,
+                            (unsigned) (orig + delta));
+}
+
+static void
+randomly_set_extreme_ints (const DBusString *orig_data,
+                           DBusString       *mutated)
+{
+  int i;
+  int byte_order;
+  const char *d;
+  dbus_uint32_t orig;
+  static int which = 0;
+  unsigned int extreme_ints[] = {
+    _DBUS_INT_MAX,
+    _DBUS_UINT_MAX,
+    _DBUS_INT_MAX - 1,
+    _DBUS_UINT_MAX - 1,
+    _DBUS_INT_MAX - 2,
+    _DBUS_UINT_MAX - 2,
+    _DBUS_INT_MAX - 17,
+    _DBUS_UINT_MAX - 17,
+    _DBUS_INT_MAX / 2,
+    _DBUS_INT_MAX / 3,
+    _DBUS_UINT_MAX / 2,
+    _DBUS_UINT_MAX / 3,
+    0, 1, 2, 3,
+    (unsigned int) -1,
+    (unsigned int) -2,
+    (unsigned int) -3
+  };
+    
+  if (orig_data != mutated)
+    {
+      _dbus_string_set_length (mutated, 0);
+      
+      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
+        _dbus_assert_not_reached ("out of mem");
+    }
+
+  if (_dbus_string_get_length (mutated) < 12)
+    return;
+  
+  d = _dbus_string_get_const_data (mutated);
+
+  if (!(*d == DBUS_LITTLE_ENDIAN ||
+        *d == DBUS_BIG_ENDIAN))
+    return;
+
+  byte_order = *d;
+  
+  i = random_int_in_range (4, _dbus_string_get_length (mutated) - 8);
+  i = _DBUS_ALIGN_VALUE (i, 4);
+
+  orig = _dbus_demarshal_uint32 (mutated, byte_order, i, NULL);
+
+  which = random_int_in_range (0, _DBUS_N_ELEMENTS (extreme_ints));
+
+  _dbus_assert (which >= 0);
+  _dbus_assert (which < _DBUS_N_ELEMENTS (extreme_ints));
+  
+  _dbus_marshal_set_uint32 (mutated, byte_order, i,
+                            extreme_ints[which]);
+}
+
+static int
+random_type (void)
+{
+  const char types[] = {
+    DBUS_TYPE_INVALID,
+    DBUS_TYPE_NIL,
+    DBUS_TYPE_BYTE,
+    DBUS_TYPE_BOOLEAN,
+    DBUS_TYPE_INT32,
+    DBUS_TYPE_UINT32,
+    DBUS_TYPE_INT64,
+    DBUS_TYPE_UINT64,
+    DBUS_TYPE_DOUBLE,
+    DBUS_TYPE_STRING,
+    DBUS_TYPE_CUSTOM,
+    DBUS_TYPE_ARRAY,
+    DBUS_TYPE_DICT,
+    DBUS_TYPE_OBJECT_PATH
+  };
+
+  _dbus_assert (_DBUS_N_ELEMENTS (types) == DBUS_NUMBER_OF_TYPES + 1);
+
+  return types[ random_int_in_range (0, _DBUS_N_ELEMENTS (types)) ];
+}
+
+static void
+randomly_change_one_type (const DBusString *orig_data,
+                          DBusString       *mutated)
+{
+  int i;
+  int len;
+  
+  if (orig_data != mutated)
+    {
+      _dbus_string_set_length (mutated, 0);
+      
+      if (!_dbus_string_copy (orig_data, 0, mutated, 0))
+        _dbus_assert_not_reached ("out of mem");
+    }
+
+  if (_dbus_string_get_length (mutated) == 0)
+    return;
+
+  len = _dbus_string_get_length (mutated);
+  i = random_int_in_range (0, len);
+
+  /* Look for a type starting at a random location,
+   * and replace with a different type
+   */
+  while (i < len)
+    {
+      int b;
+      b = _dbus_string_get_byte (mutated, i);
+      if (dbus_type_is_valid (b))
+        {
+          _dbus_string_set_byte (mutated, i, random_type ());
+          return;
+        }
+      ++i;
+    }
+}
+
+static int times_we_did_each_thing[7] = { 0, };
+
+static void
+randomly_do_n_things (const DBusString *orig_data,
+                      DBusString       *mutated,
+                      int               n)
+{
+  int i;
+  void (* functions[]) (const DBusString *orig_data,
+                        DBusString       *mutated) =
+    {
+      randomly_shorten_or_lengthen,
+      randomly_change_one_byte,
+      randomly_add_one_byte,
+      randomly_remove_one_byte,
+      randomly_modify_length,
+      randomly_set_extreme_ints,
+      randomly_change_one_type
+    };
+
+  _dbus_string_set_length (mutated, 0);
+
+  if (!_dbus_string_copy (orig_data, 0, mutated, 0))
+    _dbus_assert_not_reached ("out of mem");
+
+  i = 0;
+  while (i < n)
+    {
+      int which;
+
+      which = random_int_in_range (0, _DBUS_N_ELEMENTS (functions));
+
+      (* functions[which]) (mutated, mutated);
+      times_we_did_each_thing[which] += 1;
+      
+      ++i;
+    }
+}
+
+static dbus_bool_t
+find_breaks_based_on (const DBusString   *filename,
+                      dbus_bool_t         is_raw,
+                      DBusMessageValidity expected_validity,
+                      void               *data)
+{
+  DBusString orig_data;
+  DBusString mutated;
+  const char *filename_c;
+  dbus_bool_t retval;
+  int i;
+
+  filename_c = _dbus_string_get_const_data (filename);
+
+  retval = FALSE;
+
+  if (!_dbus_string_init (&orig_data))
+    _dbus_assert_not_reached ("could not allocate string\n");
+
+  if (!_dbus_string_init (&mutated))
+    _dbus_assert_not_reached ("could not allocate string\n");
+
+  if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
+                                                   &orig_data))
+    {
+      fprintf (stderr, "could not load file %s\n", filename_c);
+      goto failed;
+    }
+
+  printf ("        changing one random byte 100 times\n");
+  i = 0;
+  while (i < 100)
+    {
+      randomly_change_one_byte (&orig_data, &mutated);
+      try_mutated_data (&mutated);
+
+      ++i;
+    }
+
+  printf ("        changing length 50 times\n");
+  i = 0;
+  while (i < 50)
+    {
+      randomly_modify_length (&orig_data, &mutated);
+      try_mutated_data (&mutated);
+
+      ++i;
+    }
+
+  printf ("        removing one byte 50 times\n");
+  i = 0;
+  while (i < 50)
+    {
+      randomly_remove_one_byte (&orig_data, &mutated);
+      try_mutated_data (&mutated);
+
+      ++i;
+    }
+
+  printf ("        adding one byte 50 times\n");
+  i = 0;
+  while (i < 50)
+    {
+      randomly_add_one_byte (&orig_data, &mutated);
+      try_mutated_data (&mutated);
+
+      ++i;
+    }
+
+  printf ("        changing ints to boundary values 50 times\n");
+  i = 0;
+  while (i < 50)
+    {
+      randomly_set_extreme_ints (&orig_data, &mutated);
+      try_mutated_data (&mutated);
+
+      ++i;
+    }
+
+  printf ("        changing typecodes 50 times\n");
+  i = 0;
+  while (i < 50)
+    {
+      randomly_change_one_type (&orig_data, &mutated);
+      try_mutated_data (&mutated);
+
+      ++i;
+    }
+
+  printf ("        changing message length 15 times\n");
+  i = 0;
+  while (i < 15)
+    {
+      randomly_shorten_or_lengthen (&orig_data, &mutated);
+      try_mutated_data (&mutated);
+
+      ++i;
+    }
+
+  printf ("        randomly making 2 of above modifications 42 times\n");
+  i = 0;
+  while (i < 42)
+    {
+      randomly_do_n_things (&orig_data, &mutated, 2);
+      try_mutated_data (&mutated);
+
+      ++i;
+    }
+
+  printf ("        randomly making 3 of above modifications 42 times\n");
+  i = 0;
+  while (i < 42)
+    {
+      randomly_do_n_things (&orig_data, &mutated, 3);
+      try_mutated_data (&mutated);
+
+      ++i;
+    }
+
+  printf ("        randomly making 4 of above modifications 42 times\n");
+  i = 0;
+  while (i < 42)
+    {
+      randomly_do_n_things (&orig_data, &mutated, 4);
+      try_mutated_data (&mutated);
+
+      ++i;
+    }
+  
+  retval = TRUE;
+  
+ failed:
+
+  _dbus_string_free (&orig_data);
+  _dbus_string_free (&mutated);
+
+  /* FALSE means end the whole process */
+  return retval;
+}
+
+static unsigned int
+get_random_seed (void)
+{
+  DBusString bytes;
+  unsigned int seed;
+  int fd;
+  const char *s;
+
+  seed = 0;
+
+  if (!_dbus_string_init (&bytes))
+    exit (1);
+
+  fd = open ("/dev/urandom", O_RDONLY);
+  if (fd < 0)
+    goto use_fallback;
+
+  if (_dbus_read (fd, &bytes, 4) != 4)
+    goto use_fallback;
+
+  close (fd);
+
+  s = _dbus_string_get_const_data (&bytes);
+
+  seed = * (unsigned int*) s;
+  goto out;
+
+ use_fallback:
+  {
+    long tv_usec;
+
+    fprintf (stderr, "could not open/read /dev/urandom, using current time for seed\n");
+
+    _dbus_get_monotonic_time (NULL, &tv_usec);
+
+    seed = tv_usec;
+  }
+
+ out:
+  _dbus_string_free (&bytes);
+
+  return seed;
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  const char *test_data_dir;
+  const char *failure_dir_c;
+  int total_failures_found;
+  
+  if (argc > 1)
+    test_data_dir = argv[1];
+  else
+    {
+      fprintf (stderr, "Must specify a top_srcdir/test/data directory\n");
+      return 1;
+    }
+
+  total_failures_found = 0;
+  total_attempts = 0;
+
+  if (!_dbus_string_init (&failure_dir))
+    return 1;
+
+  /* so you can leave it overnight safely */
+#define MAX_FAILURES 1000
+
+  while (total_failures_found < MAX_FAILURES)
+    {
+      unsigned int seed;
+
+      failures_this_iteration = 0;
+
+      seed = get_random_seed ();
+
+      _dbus_string_set_length (&failure_dir, 0);
+
+      if (!_dbus_string_append (&failure_dir, "failures-"))
+        return 1;
+
+      if (!_dbus_string_append_uint (&failure_dir, seed))
+        return 1;
+
+      failure_dir_c = _dbus_string_get_const_data (&failure_dir);
+
+      if (mkdir (failure_dir_c, 0700) < 0)
+        {
+          if (errno != EEXIST)
+            fprintf (stderr, "didn't mkdir %s: %s\n",
+                     failure_dir_c, strerror (errno));
+        }
+
+      printf ("next seed = %u \ttotal failures %d of %d attempts\n",
+              seed, total_failures_found, total_attempts);
+
+      srand (seed);
+
+      if (!dbus_internal_do_not_use_foreach_message_file (test_data_dir,
+                                                          find_breaks_based_on,
+                                                          NULL))
+        {
+          fprintf (stderr, "fatal error iterating over message files\n");
+          rmdir (failure_dir_c);
+          return 1;
+        }
+
+      printf ("  did %d random mutations: %d %d %d %d %d %d %d\n",
+              _DBUS_N_ELEMENTS (times_we_did_each_thing),
+              times_we_did_each_thing[0],
+              times_we_did_each_thing[1],
+              times_we_did_each_thing[2],
+              times_we_did_each_thing[3],
+              times_we_did_each_thing[4],
+              times_we_did_each_thing[5],
+              times_we_did_each_thing[6]);
+      
+      printf ("Found %d failures with seed %u stored in %s\n",
+              failures_this_iteration, seed, failure_dir_c);
+
+      total_failures_found += failures_this_iteration;
+
+      rmdir (failure_dir_c); /* does nothing if non-empty */
+    }
+
+  return 0;
+}
diff --git a/dbus/test/corrupt.c b/dbus/test/corrupt.c
new file mode 100644
index 0000000..0249590
--- /dev/null
+++ b/dbus/test/corrupt.c
@@ -0,0 +1,376 @@
+/* Regression test for being disconnected by a corrupt message (fd.o #15578)
+ *
+ * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
+ * Copyright © 2010-2011 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+typedef struct {
+    DBusError e;
+
+    DBusServer *server;
+    DBusConnection *server_conn;
+    /* queue of DBusMessage */
+    GQueue client_messages;
+
+    DBusConnection *client_conn;
+} Fixture;
+
+static void
+assert_no_error (const DBusError *e)
+{
+  if (G_UNLIKELY (dbus_error_is_set (e)))
+    g_error ("expected success but got error: %s: %s", e->name, e->message);
+}
+
+static DBusHandlerResult
+client_message_cb (DBusConnection *client_conn,
+    DBusMessage *message,
+    void *data)
+{
+  Fixture *f = data;
+
+  g_assert (client_conn == f->client_conn);
+  g_queue_push_tail (&f->client_messages, dbus_message_ref (message));
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+new_conn_cb (DBusServer *server,
+    DBusConnection *server_conn,
+    void *data)
+{
+  Fixture *f = data;
+
+  g_assert (f->server_conn == NULL);
+  f->server_conn = dbus_connection_ref (server_conn);
+  dbus_connection_setup_with_g_main (server_conn, NULL);
+}
+
+static void
+setup (Fixture *f,
+    gconstpointer addr)
+{
+  dbus_error_init (&f->e);
+  g_queue_init (&f->client_messages);
+
+  f->server = dbus_server_listen (addr, &f->e);
+  assert_no_error (&f->e);
+  g_assert (f->server != NULL);
+
+  dbus_server_set_new_connection_function (f->server,
+      new_conn_cb, f, NULL);
+  dbus_server_setup_with_g_main (f->server, NULL);
+}
+
+static void
+test_connect (Fixture *f,
+    gconstpointer addr G_GNUC_UNUSED)
+{
+  dbus_bool_t have_mem;
+
+  g_assert (f->server_conn == NULL);
+
+  f->client_conn = dbus_connection_open_private (
+      dbus_server_get_address (f->server), &f->e);
+  assert_no_error (&f->e);
+  g_assert (f->client_conn != NULL);
+  dbus_connection_setup_with_g_main (f->client_conn, NULL);
+
+  while (f->server_conn == NULL)
+    {
+      g_print (".");
+      g_main_context_iteration (NULL, TRUE);
+    }
+
+  have_mem = dbus_connection_add_filter (f->client_conn,
+      client_message_cb, f, NULL);
+  g_assert (have_mem);
+}
+
+static void
+test_message (Fixture *f,
+    gconstpointer addr)
+{
+  dbus_bool_t have_mem;
+  dbus_uint32_t serial;
+  DBusMessage *outgoing, *incoming;
+
+  test_connect (f, addr);
+
+  outgoing = dbus_message_new_signal ("/com/example/Hello",
+      "com.example.Hello", "Greeting");
+  g_assert (outgoing != NULL);
+
+  have_mem = dbus_connection_send (f->server_conn, outgoing, &serial);
+  g_assert (have_mem);
+  g_assert (serial != 0);
+
+  while (g_queue_is_empty (&f->client_messages))
+    {
+      g_print (".");
+      g_main_context_iteration (NULL, TRUE);
+    }
+
+  g_assert_cmpuint (g_queue_get_length (&f->client_messages), ==, 1);
+
+  incoming = g_queue_pop_head (&f->client_messages);
+
+  g_assert (!dbus_message_contains_unix_fds (incoming));
+  g_assert_cmpstr (dbus_message_get_destination (incoming), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_error_name (incoming), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_interface (incoming), ==,
+      "com.example.Hello");
+  g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Greeting");
+  g_assert_cmpstr (dbus_message_get_sender (incoming), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_signature (incoming), ==, "");
+  g_assert_cmpstr (dbus_message_get_path (incoming), ==, "/com/example/Hello");
+  g_assert_cmpuint (dbus_message_get_serial (incoming), ==, serial);
+
+  dbus_message_unref (incoming);
+
+  dbus_message_unref (outgoing);
+}
+
+static void
+send_n_bytes (GSocket *socket,
+              const gchar *blob,
+              gssize blob_len)
+{
+  gssize len, total_sent;
+  GError *gerror = NULL;
+
+  total_sent = 0;
+
+  while (total_sent < blob_len)
+    {
+      len = g_socket_send (socket,
+                           blob + total_sent,
+                           blob_len - total_sent,
+                           NULL, &gerror);
+
+      /* this is NULL-safe: a NULL error does not match */
+      if (g_error_matches (gerror, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
+        {
+          /* we could wait for G_IO_OUT, but life's too short; just sleep */
+          g_clear_error (&gerror);
+          g_usleep (G_USEC_PER_SEC / 10);
+          continue;
+        }
+
+      g_assert_no_error (gerror);
+      g_assert (len >= 0);
+      total_sent += len;
+    }
+}
+
+/* Enough bytes for it to be obvious that this connection is broken */
+#define CORRUPT_LEN 1024
+
+/* All-zero is not a valid D-Bus message header - for a start, this is
+ * protocol version 1, not 0 */
+static const gchar not_a_dbus_message[CORRUPT_LEN] = { 0 };
+
+static void
+test_corrupt (Fixture *f,
+    gconstpointer addr)
+{
+  GSocket *socket;
+  GError *gerror = NULL;
+  int fd;
+  DBusMessage *incoming;
+
+  test_message (f, addr);
+
+  dbus_connection_flush (f->server_conn);
+
+  /* OK, now the connection is working, let's break it! Don't try this
+   * at home; splicing arbitrary bytes into the middle of the stream is
+   * specifically documented as not a valid thing to do. Who'd have thought? */
+  if (!dbus_connection_get_socket (f->server_conn, &fd))
+    g_error ("failed to steal fd from server connection");
+
+  socket = g_socket_new_from_fd (fd, &gerror);
+  g_assert_no_error (gerror);
+  g_assert (socket != NULL);
+
+  send_n_bytes (socket, not_a_dbus_message, CORRUPT_LEN);
+
+  /* Now spin on the client connection: the server just sent it complete
+   * rubbish, so it should disconnect */
+  while (g_queue_is_empty (&f->client_messages))
+    {
+      g_print (".");
+      g_main_context_iteration (NULL, TRUE);
+    }
+
+  incoming = g_queue_pop_head (&f->client_messages);
+
+  g_assert (!dbus_message_contains_unix_fds (incoming));
+  g_assert_cmpstr (dbus_message_get_destination (incoming), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_error_name (incoming), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_interface (incoming), ==,
+      "org.freedesktop.DBus.Local");
+  g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Disconnected");
+  g_assert_cmpstr (dbus_message_get_sender (incoming), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_signature (incoming), ==, "");
+  g_assert_cmpstr (dbus_message_get_path (incoming), ==,
+      "/org/freedesktop/DBus/Local");
+
+  dbus_message_unref (incoming);
+  g_object_unref (socket);
+}
+
+static void
+test_byte_order (Fixture *f,
+    gconstpointer addr)
+{
+  GSocket *socket;
+  GError *gerror = NULL;
+  int fd;
+  char *blob;
+  const gchar *arg = not_a_dbus_message;
+  const gchar * const *args = &arg;
+  int blob_len;
+  DBusMessage *message;
+  dbus_bool_t mem;
+
+  test_message (f, addr);
+
+  message = dbus_message_new_signal ("/", "a.b", "c");
+  g_assert (message != NULL);
+  /* Append 0xFF bytes, so that the length of the body when byte-swapped
+   * is 0xFF000000, which is invalid */
+  mem = dbus_message_append_args (message,
+      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &args, 0xFF,
+      DBUS_TYPE_INVALID);
+  g_assert (mem);
+  mem = dbus_message_marshal (message, &blob, &blob_len);
+  g_assert (mem);
+  g_assert_cmpuint (blob_len, >, 0xFF);
+  g_assert (blob != NULL);
+
+  dbus_message_unref (message);
+
+  /* Break the message by changing its claimed byte order, without actually
+   * byteswapping anything. We happen to know that byte order is the first
+   * byte. */
+  if (blob[0] == 'B')
+    blob[0] = 'l';
+  else
+    blob[0] = 'B';
+
+  /* OK, now the connection is working, let's break it */
+
+  dbus_connection_flush (f->server_conn);
+
+  if (!dbus_connection_get_socket (f->server_conn, &fd))
+    g_error ("failed to steal fd from server connection");
+
+  socket = g_socket_new_from_fd (fd, &gerror);
+  g_assert_no_error (gerror);
+  g_assert (socket != NULL);
+
+  send_n_bytes (socket, blob, blob_len);
+
+  dbus_free (blob);
+
+  /* Now spin on the client connection: the server just sent it a faulty
+   * message, so it should disconnect */
+  while (g_queue_is_empty (&f->client_messages))
+    {
+      g_print (".");
+      g_main_context_iteration (NULL, TRUE);
+    }
+
+  message = g_queue_pop_head (&f->client_messages);
+
+  g_assert (!dbus_message_contains_unix_fds (message));
+  g_assert_cmpstr (dbus_message_get_destination (message), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_error_name (message), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_interface (message), ==,
+      "org.freedesktop.DBus.Local");
+  g_assert_cmpstr (dbus_message_get_member (message), ==, "Disconnected");
+  g_assert_cmpstr (dbus_message_get_sender (message), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_signature (message), ==, "");
+  g_assert_cmpstr (dbus_message_get_path (message), ==,
+      "/org/freedesktop/DBus/Local");
+
+  dbus_message_unref (message);
+  g_object_unref (socket);
+}
+
+static void
+teardown (Fixture *f,
+    gconstpointer addr G_GNUC_UNUSED)
+{
+  if (f->client_conn != NULL)
+    {
+      dbus_connection_close (f->client_conn);
+      dbus_connection_unref (f->client_conn);
+      f->client_conn = NULL;
+    }
+
+  if (f->server_conn != NULL)
+    {
+      dbus_connection_close (f->server_conn);
+      dbus_connection_unref (f->server_conn);
+      f->server_conn = NULL;
+    }
+
+  if (f->server != NULL)
+    {
+      dbus_server_disconnect (f->server);
+      dbus_server_unref (f->server);
+      f->server = NULL;
+    }
+}
+
+int
+main (int argc,
+    char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+  g_type_init ();
+
+  g_test_add ("/corrupt/tcp", Fixture, "tcp:host=127.0.0.1", setup,
+      test_corrupt, teardown);
+
+#ifdef DBUS_UNIX
+  g_test_add ("/corrupt/unix", Fixture, "unix:tmpdir=/tmp", setup,
+      test_corrupt, teardown);
+#endif
+
+  g_test_add ("/corrupt/byte-order/tcp", Fixture, "tcp:host=127.0.0.1", setup,
+      test_byte_order, teardown);
+
+  return g_test_run ();
+}
diff --git a/dbus/test/data/auth/anonymous-client-successful.auth-script b/dbus/test/data/auth/anonymous-client-successful.auth-script
new file mode 100644
index 0000000..9a1620b
--- /dev/null
+++ b/dbus/test/data/auth/anonymous-client-successful.auth-script
@@ -0,0 +1,16 @@
+## this tests that a client can login anonymously
+
+CLIENT
+
+## Reject whatever mechanism the client picks first
+EXPECT_COMMAND AUTH
+SEND 'REJECTED DBUS_TEST_NONEXISTENT_MECH1 ANONYMOUS DBUS_TEST_NONEXISTENT_MECH2'
+
+## And this time we get ANONYMOUS
+
+EXPECT_COMMAND AUTH
+## of course real DBUS_COOKIE_SHA1 would not send this here...
+SEND 'OK 1234deadbeef'
+
+EXPECT_COMMAND BEGIN
+EXPECT_STATE AUTHENTICATED
diff --git a/dbus/test/data/auth/anonymous-server-successful.auth-script b/dbus/test/data/auth/anonymous-server-successful.auth-script
new file mode 100644
index 0000000..172ae9d
--- /dev/null
+++ b/dbus/test/data/auth/anonymous-server-successful.auth-script
@@ -0,0 +1,13 @@
+## this tests the server side in a successful auth of type ANONYMOUS 
+
+SERVER
+## verify that prior to doing anything, we haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
+SEND 'AUTH ANONYMOUS 442d42757320312e312e31'
+EXPECT_COMMAND OK
+EXPECT_STATE WAITING_FOR_INPUT
+SEND 'BEGIN'
+EXPECT_STATE AUTHENTICATED
+## verify that we are still anonymous
+EXPECT_HAVE_NO_CREDENTIALS
+
diff --git a/dbus/test/data/auth/cancel.auth-script b/dbus/test/data/auth/cancel.auth-script
new file mode 100644
index 0000000..f2c519a
--- /dev/null
+++ b/dbus/test/data/auth/cancel.auth-script
@@ -0,0 +1,19 @@
+## this tests canceling EXTERNAL
+
+SERVER
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND OK
+EXPECT_STATE WAITING_FOR_INPUT
+SEND 'CANCEL'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+
+## now start over and see if it works
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND OK
+EXPECT_STATE WAITING_FOR_INPUT
+SEND 'BEGIN'
+EXPECT_STATE AUTHENTICATED
+
+
+
diff --git a/dbus/test/data/auth/client-out-of-mechanisms.auth-script b/dbus/test/data/auth/client-out-of-mechanisms.auth-script
new file mode 100644
index 0000000..ce6d3ad
--- /dev/null
+++ b/dbus/test/data/auth/client-out-of-mechanisms.auth-script
@@ -0,0 +1,7 @@
+## this tests that tests that the client disconnects when it's out of
+## known mechanisms
+
+CLIENT
+EXPECT_COMMAND AUTH
+SEND 'REJECTED BONGO_MD5'
+EXPECT_STATE NEED_DISCONNECT
diff --git a/dbus/test/data/auth/external-failed.auth-script b/dbus/test/data/auth/external-failed.auth-script
new file mode 100644
index 0000000..7c4e900
--- /dev/null
+++ b/dbus/test/data/auth/external-failed.auth-script
@@ -0,0 +1,11 @@
+## this tests that auth of type EXTERNAL without credentials will fail
+
+SERVER
+NO_CREDENTIALS
+## verify that prior to doing anything, we haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+## verify that we still haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
diff --git a/dbus/test/data/auth/external-root.auth-script b/dbus/test/data/auth/external-root.auth-script
new file mode 100644
index 0000000..b4c4b43
--- /dev/null
+++ b/dbus/test/data/auth/external-root.auth-script
@@ -0,0 +1,11 @@
+## this tests we can auth EXTERNAL as ourselves, with root credentials
+UNIX_ONLY
+SERVER
+ROOT_CREDENTIALS
+## 30 is ASCII '0' in hex
+SEND 'AUTH EXTERNAL 30'
+EXPECT_COMMAND OK
+EXPECT_STATE WAITING_FOR_INPUT
+SEND 'BEGIN'
+EXPECT_STATE AUTHENTICATED
+
diff --git a/dbus/test/data/auth/external-silly.auth-script b/dbus/test/data/auth/external-silly.auth-script
new file mode 100644
index 0000000..4e18ee8
--- /dev/null
+++ b/dbus/test/data/auth/external-silly.auth-script
@@ -0,0 +1,12 @@
+## this tests we can't auth if socket reports silly credentials but we ask for our own uid
+
+SERVER
+## verify that prior to doing anything, we haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
+SILLY_CREDENTIALS
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+## verify that we still haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
+
diff --git a/dbus/test/data/auth/external-successful.auth-script b/dbus/test/data/auth/external-successful.auth-script
new file mode 100644
index 0000000..222938c
--- /dev/null
+++ b/dbus/test/data/auth/external-successful.auth-script
@@ -0,0 +1,12 @@
+## this tests a successful auth of type EXTERNAL
+
+SERVER
+## verify that prior to doing anything, we haven't authed as anyone
+EXPECT_HAVE_NO_CREDENTIALS
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND OK
+EXPECT_STATE WAITING_FOR_INPUT
+SEND 'BEGIN'
+EXPECT_STATE AUTHENTICATED
+## verify that we now have some credentials
+EXPECT_HAVE_SOME_CREDENTIALS
diff --git a/dbus/test/data/auth/extra-bytes.auth-script b/dbus/test/data/auth/extra-bytes.auth-script
new file mode 100644
index 0000000..cd1e01d
--- /dev/null
+++ b/dbus/test/data/auth/extra-bytes.auth-script
@@ -0,0 +1,10 @@
+## this tests that we have the expected extra bytes at the end
+
+SERVER
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND OK
+EXPECT_STATE WAITING_FOR_INPUT
+SEND 'BEGIN\r\nHello'
+EXPECT_STATE AUTHENTICATED_WITH_UNUSED_BYTES
+EXPECT_UNUSED 'Hello\r\n'
+EXPECT_STATE AUTHENTICATED
diff --git a/dbus/test/data/auth/fail-after-n-attempts.auth-script b/dbus/test/data/auth/fail-after-n-attempts.auth-script
new file mode 100644
index 0000000..0ced386
--- /dev/null
+++ b/dbus/test/data/auth/fail-after-n-attempts.auth-script
@@ -0,0 +1,34 @@
+## this tests that after retrying too often we fail
+
+SERVER
+NO_CREDENTIALS
+
+# 1
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+
+# 2
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+
+# 3
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+
+# 4
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+
+# 5
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+
+# 6
+SEND 'AUTH EXTERNAL USERID_HEX'
+EXPECT_COMMAND REJECTED
+EXPECT_STATE NEED_DISCONNECT
diff --git a/dbus/test/data/auth/fallback.auth-script b/dbus/test/data/auth/fallback.auth-script
new file mode 100644
index 0000000..0d880c0
--- /dev/null
+++ b/dbus/test/data/auth/fallback.auth-script
@@ -0,0 +1,17 @@
+## this tests that a client can fallback to a secondary auth mech 
+
+CLIENT
+
+## Will try EXTERNAL by default first without first calling AUTH alone.
+
+EXPECT_COMMAND AUTH
+SEND 'REJECTED EXTERNAL DBUS_COOKIE_SHA1 DBUS_TEST_NONEXISTENT_MECH'
+
+## And this time we get DBUS_COOKIE_SHA1
+
+EXPECT_COMMAND AUTH
+## of course real DBUS_COOKIE_SHA1 would not send this here...
+SEND 'OK 1234deadbeef'
+
+EXPECT_COMMAND BEGIN
+EXPECT_STATE AUTHENTICATED
diff --git a/dbus/test/data/auth/invalid-command-client.auth-script b/dbus/test/data/auth/invalid-command-client.auth-script
new file mode 100644
index 0000000..ac17e7b
--- /dev/null
+++ b/dbus/test/data/auth/invalid-command-client.auth-script
@@ -0,0 +1,8 @@
+## this tests that receiving a nonexistent command is handled properly
+## by a client
+
+CLIENT
+EXPECT_COMMAND AUTH
+SEND 'NONEXISTENT_COMMAND foo bar baz blah blah'
+EXPECT_COMMAND ERROR
+EXPECT_STATE WAITING_FOR_INPUT
diff --git a/dbus/test/data/auth/invalid-command.auth-script b/dbus/test/data/auth/invalid-command.auth-script
new file mode 100644
index 0000000..c49cb8d
--- /dev/null
+++ b/dbus/test/data/auth/invalid-command.auth-script
@@ -0,0 +1,7 @@
+## this tests that receiving a nonexistent command is handled properly
+## by a server
+
+SERVER
+SEND 'NONEXISTENT_COMMAND foo bar baz blah blah'
+EXPECT_COMMAND ERROR
+EXPECT_STATE WAITING_FOR_INPUT
diff --git a/dbus/test/data/auth/invalid-hex-encoding.auth-script b/dbus/test/data/auth/invalid-hex-encoding.auth-script
new file mode 100644
index 0000000..1f15c43
--- /dev/null
+++ b/dbus/test/data/auth/invalid-hex-encoding.auth-script
@@ -0,0 +1,6 @@
+## this tests an invalid hex encoding followed by successful authentication
+
+SERVER
+SEND 'AUTH EXTERNAL willy'
+EXPECT_COMMAND ERROR
+EXPECT_STATE WAITING_FOR_INPUT
diff --git a/dbus/test/data/auth/mechanisms.auth-script b/dbus/test/data/auth/mechanisms.auth-script
new file mode 100644
index 0000000..be44791
--- /dev/null
+++ b/dbus/test/data/auth/mechanisms.auth-script
@@ -0,0 +1,8 @@
+## this tests that the server sends a list of mechanisms
+## in response to blank AUTH
+
+SERVER
+SEND AUTH
+EXPECT_COMMAND REJECTED
+EXPECT_STATE WAITING_FOR_INPUT
+
diff --git a/dbus/test/data/equiv-config-files/basic/basic-1.conf b/dbus/test/data/equiv-config-files/basic/basic-1.conf
new file mode 100644
index 0000000..99f41e8
--- /dev/null
+++ b/dbus/test/data/equiv-config-files/basic/basic-1.conf
@@ -0,0 +1,25 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/bar</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.d</includedir>
+  <servicedir>/usr/share/foo</servicedir>
+  <include ignore_missing="yes">nonexistent.conf</include>
+  <policy context="default">
+    <allow user="*"/>
+  </policy>
+
+  <limit name="max_incoming_bytes">5000</limit>   
+  <limit name="max_outgoing_bytes">5000</limit>
+  <limit name="max_message_size">300</limit>
+  <limit name="service_start_timeout">5000</limit>
+  <limit name="auth_timeout">6000</limit>
+  <limit name="max_completed_connections">50</limit>  
+  <limit name="max_incomplete_connections">80</limit>
+  <limit name="max_connections_per_user">64</limit>
+  <limit name="max_pending_service_starts">64</limit>
+  <limit name="max_names_per_connection">256</limit>
+                                   
+</busconfig>
diff --git a/dbus/test/data/equiv-config-files/basic/basic-2.conf b/dbus/test/data/equiv-config-files/basic/basic-2.conf
new file mode 100644
index 0000000..49e707e
--- /dev/null
+++ b/dbus/test/data/equiv-config-files/basic/basic-2.conf
@@ -0,0 +1,5 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+<include>basic-1.conf</include>
+</busconfig>
\ No newline at end of file
diff --git a/dbus/test/data/equiv-config-files/basic/basic.d/basic.conf b/dbus/test/data/equiv-config-files/basic/basic.d/basic.conf
new file mode 100644
index 0000000..d109d71
--- /dev/null
+++ b/dbus/test/data/equiv-config-files/basic/basic.d/basic.conf
@@ -0,0 +1,13 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/bar</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.d</includedir>
+  <servicedir>/usr/share/foo</servicedir>
+  <include ignore_missing="yes">nonexistent.conf</include>
+  <policy context="default">
+    <allow user="*"/>
+  </policy>
+</busconfig>
diff --git a/dbus/test/data/equiv-config-files/entities/basic.d/basic.conf b/dbus/test/data/equiv-config-files/entities/basic.d/basic.conf
new file mode 100644
index 0000000..d109d71
--- /dev/null
+++ b/dbus/test/data/equiv-config-files/entities/basic.d/basic.conf
@@ -0,0 +1,13 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/bar</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.d</includedir>
+  <servicedir>/usr/share/foo</servicedir>
+  <include ignore_missing="yes">nonexistent.conf</include>
+  <policy context="default">
+    <allow user="*"/>
+  </policy>
+</busconfig>
diff --git a/dbus/test/data/equiv-config-files/entities/entities-1.conf b/dbus/test/data/equiv-config-files/entities/entities-1.conf
new file mode 100644
index 0000000..3d3cea7
--- /dev/null
+++ b/dbus/test/data/equiv-config-files/entities/entities-1.conf
@@ -0,0 +1,14 @@
+<!-- This config file contains XML entities -->
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/&lt;bar&gt;</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.&#100;</includedir>
+  <servicedir>/usr/&amp;share/foo</servicedir>
+  <include ignore_missing="ye&#115;">nonexistent.conf&#110;</include>
+  <policy context="&#100;efault">
+    <allow user="*"/>
+  </policy>
+</busconfig>
diff --git a/dbus/test/data/equiv-config-files/entities/entities-2.conf b/dbus/test/data/equiv-config-files/entities/entities-2.conf
new file mode 100644
index 0000000..9ffabea
--- /dev/null
+++ b/dbus/test/data/equiv-config-files/entities/entities-2.conf
@@ -0,0 +1,5 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+<include>entities-1.conf</include>
+</busconfig>
\ No newline at end of file
diff --git a/dbus/test/data/incomplete-messages/missing-body.message b/dbus/test/data/incomplete-messages/missing-body.message
new file mode 100644
index 0000000..138e9ea
--- /dev/null
+++ b/dbus/test/data/incomplete-messages/missing-body.message
@@ -0,0 +1,19 @@
+## message that's missing an expected body
+
+VALID_HEADER method_call
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+ALIGN 8
+END_LENGTH Header
+
+## create the body, then chop it off
+START_LENGTH Body
+TYPE INT32
+INT32 37
+END_LENGTH Body
+
+CHOP 8
diff --git a/dbus/test/data/invalid-config-files/badselinux-1.conf b/dbus/test/data/invalid-config-files/badselinux-1.conf
new file mode 100644
index 0000000..4852ded
--- /dev/null
+++ b/dbus/test/data/invalid-config-files/badselinux-1.conf
@@ -0,0 +1,10 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/bar</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.d</includedir>
+  <servicedir>/usr/share/foo</servicedir>
+  <include selinux_root_relative="jomoma">blah</include>
+</busconfig>
diff --git a/dbus/test/data/invalid-config-files/badselinux-2.conf b/dbus/test/data/invalid-config-files/badselinux-2.conf
new file mode 100644
index 0000000..ac3b95c
--- /dev/null
+++ b/dbus/test/data/invalid-config-files/badselinux-2.conf
@@ -0,0 +1,10 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/bar</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.d</includedir>
+  <servicedir>/usr/share/foo</servicedir>
+  <include if_selinux_enabled="moo">blah</include>
+</busconfig>
diff --git a/dbus/test/data/invalid-config-files/circular-1.conf b/dbus/test/data/invalid-config-files/circular-1.conf
new file mode 100644
index 0000000..faa895a
--- /dev/null
+++ b/dbus/test/data/invalid-config-files/circular-1.conf
@@ -0,0 +1,4 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+<include>circular-1.conf</include>
+</busconfig>
\ No newline at end of file
diff --git a/dbus/test/data/invalid-config-files/circular-2.conf b/dbus/test/data/invalid-config-files/circular-2.conf
new file mode 100644
index 0000000..46a7e78
--- /dev/null
+++ b/dbus/test/data/invalid-config-files/circular-2.conf
@@ -0,0 +1,4 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+<include>circular-3.conf</include>
+</busconfig>
\ No newline at end of file
diff --git a/dbus/test/data/invalid-config-files/circular-3.conf b/dbus/test/data/invalid-config-files/circular-3.conf
new file mode 100644
index 0000000..87e354d
--- /dev/null
+++ b/dbus/test/data/invalid-config-files/circular-3.conf
@@ -0,0 +1,4 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+<include>circular-2.conf</include>
+</busconfig>
\ No newline at end of file
diff --git a/dbus/test/data/invalid-config-files/not-well-formed.conf b/dbus/test/data/invalid-config-files/not-well-formed.conf
new file mode 100644
index 0000000..9e59cbc
--- /dev/null
+++ b/dbus/test/data/invalid-config-files/not-well-formed.conf
@@ -0,0 +1,5 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</foo>
+</busconfig>
diff --git a/dbus/test/data/invalid-config-files/truncated-file.conf b/dbus/test/data/invalid-config-files/truncated-file.conf
new file mode 100644
index 0000000..e8d6088
--- /dev/null
+++ b/dbus/test/data/invalid-config-files/truncated-file.conf
@@ -0,0 +1,9 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/bar</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.d</includedir>
+  <servicedir>/usr/share/foo</servicedir>
+  <include ignore_missing="y
diff --git a/dbus/test/data/invalid-messages/array-of-nil.message b/dbus/test/data/invalid-messages/array-of-nil.message
new file mode 100644
index 0000000..1197a13
--- /dev/null
+++ b/dbus/test/data/invalid-messages/array-of-nil.message
@@ -0,0 +1,31 @@
+# Message with an array of NIL (not allowed)
+
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH 
+OBJECT_PATH '/foo'
+
+ALIGN 8
+END_LENGTH Header
+
+START_LENGTH Body
+TYPE ARRAY
+TYPE NIL
+UINT32 5
+
+## we want it to fail because of type nil, not because the length is no good
+## so pad out the message with 5 bytes
+BYTE 1
+BYTE 2
+BYTE 3
+BYTE 4
+BYTE 5
+
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/array-with-mixed-types.message b/dbus/test/data/invalid-messages/array-with-mixed-types.message
new file mode 100644
index 0000000..dea2d1e
--- /dev/null
+++ b/dbus/test/data/invalid-messages/array-with-mixed-types.message
@@ -0,0 +1,52 @@
+# Message with an array of array where the child arrays are of
+# different types
+
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+ALIGN 8
+END_LENGTH Header
+
+START_LENGTH Body
+
+TYPE ARRAY
+TYPE ARRAY
+TYPE UINT32
+
+LENGTH Array
+START_LENGTH Array
+
+## array of uint32
+LENGTH SubArray1
+START_LENGTH SubArray1
+UINT32 1
+UINT32 2
+UINT32 3
+END_LENGTH SubArray1
+
+## array of uint32
+LENGTH SubArray2
+START_LENGTH SubArray2
+UINT32 4
+UINT32 5
+END_LENGTH SubArray2
+
+## array of boolean
+LENGTH SubArray3
+START_LENGTH SubArray3
+BOOLEAN false
+BOOLEAN true
+END_LENGTH SubArray3
+
+END_LENGTH Array
+
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/bad-boolean-array.message b/dbus/test/data/invalid-messages/bad-boolean-array.message
new file mode 100644
index 0000000..48000af
--- /dev/null
+++ b/dbus/test/data/invalid-messages/bad-boolean-array.message
@@ -0,0 +1,27 @@
+## a message with an invalid boolean array
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+ALIGN 8
+END_LENGTH Header
+
+START_LENGTH Body
+TYPE ARRAY
+TYPE BOOLEAN
+ALIGN 4
+INT32 3
+BYTE 0
+BYTE 1
+BYTE 3
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/bad-boolean.message b/dbus/test/data/invalid-messages/bad-boolean.message
new file mode 100644
index 0000000..09026db
--- /dev/null
+++ b/dbus/test/data/invalid-messages/bad-boolean.message
@@ -0,0 +1,22 @@
+## a message with an invalid boolean value
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+ALIGN 8
+END_LENGTH Header
+
+START_LENGTH Body
+TYPE BOOLEAN
+BYTE 3
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/bad-endian.message b/dbus/test/data/invalid-messages/bad-endian.message
new file mode 100644
index 0000000..e979baa
--- /dev/null
+++ b/dbus/test/data/invalid-messages/bad-endian.message
@@ -0,0 +1,25 @@
+## message with invalid endianness tag
+
+BYTE 'i'
+BYTE 1
+BYTE 0
+BYTE 0
+
+LENGTH Header
+LENGTH Body
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+ALIGN 8
+END_LENGTH Header
+
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/bad-header-field-alignment.message b/dbus/test/data/invalid-messages/bad-header-field-alignment.message
new file mode 100644
index 0000000..22c0d7e
--- /dev/null
+++ b/dbus/test/data/invalid-messages/bad-header-field-alignment.message
@@ -0,0 +1,38 @@
+## last field incorrectly aligned to 4 bytes
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+HEADER_FIELD UNKNOWN
+TYPE STRING
+STRING 'a'
+
+ALIGN 4
+
+HEADER_FIELD UNKNOWN
+TYPE ARRAY
+TYPE BYTE
+ALIGN 4
+LENGTH ThisByteArray
+START_LENGTH ThisByteArray
+BYTE 1
+BYTE 2
+END_LENGTH ThisByteArray
+
+
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/boolean-has-no-value.message-raw b/dbus/test/data/invalid-messages/boolean-has-no-value.message-raw
new file mode 100644
index 0000000..11b15c8
--- /dev/null
+++ b/dbus/test/data/invalid-messages/boolean-has-no-value.message-raw
Binary files differ
diff --git a/dbus/test/data/invalid-messages/local-namespace.message b/dbus/test/data/invalid-messages/local-namespace.message
new file mode 100644
index 0000000..8a72018
--- /dev/null
+++ b/dbus/test/data/invalid-messages/local-namespace.message
@@ -0,0 +1,21 @@
+## a message that is in the org.freedesktop.Local. namespace and thus
+## invalid
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.DBus.Local'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Disconnected'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+ALIGN 8
+END_LENGTH Header
+
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/no-dot-in-name.message b/dbus/test/data/invalid-messages/no-dot-in-name.message
new file mode 100644
index 0000000..6d6317a
--- /dev/null
+++ b/dbus/test/data/invalid-messages/no-dot-in-name.message
@@ -0,0 +1,19 @@
+## a message with dotless interface
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'NoDotInHere'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/not-nul-header-padding.message b/dbus/test/data/invalid-messages/not-nul-header-padding.message
new file mode 100644
index 0000000..be846da
--- /dev/null
+++ b/dbus/test/data/invalid-messages/not-nul-header-padding.message
@@ -0,0 +1,25 @@
+## has one non-nul byte in header padding
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+HEADER_FIELD UNKNOWN
+TYPE STRING
+STRING 'a'
+ALIGN 8
+## kill a padding byte and replace it
+CHOP 1
+BYTE 'q'
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/overlong-name.message b/dbus/test/data/invalid-messages/overlong-name.message
new file mode 100644
index 0000000..c1f9079
--- /dev/null
+++ b/dbus/test/data/invalid-messages/overlong-name.message
@@ -0,0 +1,20 @@
+## a message with too-long name field
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.foo.bar.this.is.really.long 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200'
+
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/too-little-header-padding.message b/dbus/test/data/invalid-messages/too-little-header-padding.message
new file mode 100644
index 0000000..358815a
--- /dev/null
+++ b/dbus/test/data/invalid-messages/too-little-header-padding.message
@@ -0,0 +1,24 @@
+## has one byte missing from header padding
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+HEADER_FIELD UNKNOWN
+TYPE STRING
+STRING 'a'
+ALIGN 8
+## kill a padding byte
+CHOP 1
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/too-much-header-padding-by-far.message b/dbus/test/data/invalid-messages/too-much-header-padding-by-far.message
new file mode 100644
index 0000000..2d2be3a
--- /dev/null
+++ b/dbus/test/data/invalid-messages/too-much-header-padding-by-far.message
@@ -0,0 +1,26 @@
+## has one byte extra header padding
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+HEADER_FIELD UNKNOWN
+TYPE STRING
+STRING 'a'
+ALIGN 8
+BYTE 0
+ALIGN 8
+BYTE 0
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/too-much-header-padding.message b/dbus/test/data/invalid-messages/too-much-header-padding.message
new file mode 100644
index 0000000..0b1c294
--- /dev/null
+++ b/dbus/test/data/invalid-messages/too-much-header-padding.message
@@ -0,0 +1,23 @@
+## has one byte extra header padding
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+HEADER_FIELD UNKNOWN
+TYPE STRING
+STRING 'a'
+ALIGN 8
+BYTE 0
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-messages/too-short-dict.message b/dbus/test/data/invalid-messages/too-short-dict.message
new file mode 100644
index 0000000..ffc3cc5
--- /dev/null
+++ b/dbus/test/data/invalid-messages/too-short-dict.message
@@ -0,0 +1,28 @@
+# Message with lots of different argument types
+
+VALID_HEADER method_call
+
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+
+ALIGN 8
+
+END_LENGTH Header
+
+START_LENGTH Body
+TYPE DICT
+LENGTH Dict
+START_LENGTH Dict
+STRING 'uint32'
+TYPE UINT32
+UINT32 0x8765432
+STRING 'uint32'
+END_LENGTH Dict
+END_LENGTH Body
diff --git a/dbus/test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service.in b/dbus/test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service.in
new file mode 100644
index 0000000..189214e
--- /dev/null
+++ b/dbus/test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteNoExec
+User=anyrandomuser
+
diff --git a/dbus/test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.in b/dbus/test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.in
new file mode 100644
index 0000000..7822ffc
--- /dev/null
+++ b/dbus/test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Exec=@DBUS_TEST_EXEC@/test-service@EXEEXT@
+User=anyrandomuser
+
diff --git a/dbus/test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoUser.service.in b/dbus/test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoUser.service.in
new file mode 100644
index 0000000..691e009
--- /dev/null
+++ b/dbus/test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoUser.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteNoUser
+Exec=@DBUS_TEST_EXEC@/test-service@EXEEXT@
diff --git a/dbus/test/data/sha-1/Readme.txt b/dbus/test/data/sha-1/Readme.txt
new file mode 100644
index 0000000..0fca3f9
--- /dev/null
+++ b/dbus/test/data/sha-1/Readme.txt
@@ -0,0 +1,83 @@
+Test suite from http://csrc.nist.gov/cryptval/shs.html
+
+				Sample Vectors for SHA-1 Testing
+
+	This file describes tests and vectors that can be used in verifying the correctness of 
+an SHA-1 implementation.  However, use of these vectors does not take the place of validation 
+obtained through the Cryptographic Module Validation Program.
+
+	There are three areas of the Secure Hash Standard for which test vectors are supplied:
+short messages of varying length, selected long messages, and pseudorandomly generated messages.
+Since it is possible for an implementation to correctly handle the hashing of byte-oriented
+messages (and not messages of a non-byte length), the SHS tests each come in two flavors.  For
+both byte oriented and bit oriented messages, the message lengths are given in bits.
+
+Type I Test: Messages of Varying Length
+
+	An implementation of the SHS must be able to correctly generate message digests for
+messages of arbitrary length.  This functionality can be tested by supplying the implementation
+with 1025 pseudorandomly generated messages with lengths from 0 to 1024 bits (for an implementation
+that only hashes byte-oriented data correctly, 129 messages of length 0, 8, 16, 24,...,1024 bits
+will be supplied).
+
+Type II Test: Selected Long Messages
+
+	Additional testing of an implementation can be performed by testing that the implementation
+can correctly generate digests for longer messages.  A list of 100 messages, each of length > 1024,
+is supplied.  These can be used to verify the hashing of longer message lengths.  For bit oriented
+testing the messages are from 1025 to 103425 bits long (length=1025+i*1024, where 0<=i<100).  For
+byte oriented testing the messages are from 1032 to 103432 (length=1032+i*1024, where 0<=i<100).
+
+Type III Test: Pseudorandomly Generated Messages
+
+	This test determines whether the implementation can compute message digests for messages
+that are generated using a given seed.  A sequence of 100 message digests is generated using this
+seed.  The digests are generated according to the following pseudocode:
+
+procedure MonteCarlo(string SEED)
+{
+	integer i, j, a;
+	string	M;
+
+	M := SEED;
+	for j = 0 to 99 do {
+		for i = 1 to 50000 do {
+			for a = 1 to (j/4*8 + 24) do M := M || ’0’;	/*‘0' is the binary zero bit. */
+			M := M || i; 	/* Here, the value for ‘i’ is expressed as a 32-bit word
+					   and concatenated with ‘M’. The first bit
+					   concatenated with ‘M’ is the most significant bit of
+					   this 32-bit word. */
+			M := SHA(M);
+			}
+		print(M);
+		}
+	}
+
+NOTE: In the above procedure, || denotes concatenation. Also, M || i denotes appending the 32-bit
+word representing the value ‘i’, as defined in section 2 of the SHS.  Within the procedure, M is a string
+of variable length. The initial length of 416 bits ensures that the length of M never exceeds 512 bits
+during execution of the above procedure, and it ensures that messages will be of a byte length.  Each
+element printed should be 160 bits in length.
+
+
+File formats:
+
+There are two files included for each test type (bit-oriented and byte-oriented).  One file contains
+the messages and the other file contains the hashes.
+
+The message files provided use "compact strings" to store the message values.  Compact strings are 
+used to represented the messages in a compact form.  A compact string has the form
+	z || b || n(1) || n(2) || ... || n(z)
+where z>=0 that represents the number of n, b is either 0 or 1, and each n(i) is a decimal integer
+representing a positive number.  The length of the compact string is given by the summation of the n(i).
+
+The compact string is interpreted as the representation of the bit string consisting of b repeated n(1) times,
+followed by 1-b repeated n(2) times, followed by b repeated n(3) times, and so on.
+
+Example:
+	M = 5 1 7 13 5 1 2
+	where z = 5 and b = 1.  Then the compact string M represents the bit string
+	1111111000000000000011111011
+	where 1 is repeated 7 times, 0 is repeated 13 times, 1 is repeated 5 times,
+	0 is repeated 1 time, and 1 is repeated 2 times.
+
diff --git a/dbus/test/data/sha-1/bit-hashes.sha1 b/dbus/test/data/sha-1/bit-hashes.sha1
new file mode 100644
index 0000000..e30e90b
--- /dev/null
+++ b/dbus/test/data/sha-1/bit-hashes.sha1
@@ -0,0 +1,1239 @@
+#  Configuration information for "SHA-1 Test"
+#  SHA tests are configured for BIT oriented implementations
+H>SHS Type 1 Hashes<H
+D>
+DA39A3EE5E6B4B0D3255BFEF95601890AFD80709 ^
+59C4526AA2CC59F9A5F56B5579BA7108E7CCB61A ^
+6E42FB84067CFF056C43A49E484997AF23190879 ^
+C63FBB9A87171A176E6E054890E29A8C5F125F6C ^
+3109E33C1C4B9A0169D1599169D0E5A520A1E71C ^
+9195E1E73CC68D7170F44BD1D83CB624BC87FA0B ^
+64F7C374527278C0436DBC8DE5AABEC2BBF634BC ^
+154B622EA426FB151B1FF1BE1CE871752B9EDEB4 ^
+12BDD00FD4038756CBCF8ECDAD1B0CD862603CD8 ^
+6700F93E1691E83735279E167F67AF61FEE9813B ^
+84AF20A06799F366435BA20F99B9A10955B6D276 ^
+C622FE003FD16220357F88FC6B9DE4789E77C321 ^
+C8DEA5A98DADA1F9662D5C150618140A150ECA46 ^
+FBB7127E77A39D856EC849D755C868CA7B9F11E9 ^
+B7D8A7A39AB33ED8C3AFD8F76201BF0904149437 ^
+154535460A12B9E100E251BB3A4D4DBCD80A309A ^
+82FC6020C7A9B62F334F7156ADA608532DCA6A3B ^
+9DD980B8073B32D21E9B2324F982024375C2951F ^
+419F97A9899486DC53C58C761CEB564314FD47BD ^
+A212E43EBFB31388F64C0C0B0B1CC7019704B744 ^
+D8F1623C186A5615F58E846C9D164F35A8956E44 ^
+AA32848DE1499365730A3650A3A7703FD404259A ^
+79BDB01E55B61A8C1AFBF63D3CE2DCCAB8CF3DFB ^
+23BF3164A448A727BA71457EBA9FCFABFBAC4F70 ^
+BA26E846EBEF7434B63F5862FDA005A1CEB5656E ^
+98622869A474EA85FE575CD979354248141A14A7 ^
+5C9E7E6951D386205542DA0680E07E60EC61D64E ^
+8EF07A02A7023AA0E6EE4BE1518627A521D1F9D5 ^
+CDEA382A5DFDA1C633F8BBC77F291F40E8801CE3 ^
+3C0A709FEF85DDBCC1B362AA162010461F31AECD ^
+10ABD6B8D97E688AF5CDA7955CD3CC0850A4A75F ^
+0EC53133F7FF955CA37D25491B592DFC0256BF23 ^
+1A46A67FEED1604523C062AACC2455223B366D05 ^
+FA3DD749E8F3D9029D9261F25157B3C0E2DF6834 ^
+43DCAC2CF20E7CCB1DED6E379CC302F302655F3B ^
+8BA25BDF331671CCB4B60961E4AF356224027862 ^
+AC3A3EA0FB8727334A4478ED165128581BBC5BEA ^
+CA4406A231EA2CA06CD1D8F3C77FEF9118B1501A ^
+5B83465B8EED14871FB51D9E6CE499FB2E4B4209 ^
+9445F521861946D4063E0CA3F41F580855A7454E ^
+C2410140818962F95506B407AE8514F11F892AEC ^
+F8F826FE0D93F415426ADB6956242116CBAB2426 ^
+C803F7539AA036CBB31B735238120FB85180D8C8 ^
+162EB5163692D9BC7B4529D214BBB932157361B6 ^
+D4B0D876A1952ADB5D27A1A6BF71BCF22731A4C5 ^
+CB5CD26AA39E45F248706604EDB9A2DB8EDC1BF6 ^
+F1AC987F30FF0375F6115C0CCD6E22DDFD0FAFE7 ^
+692E209D3A6A0228EB9823DCB738B16BDF97A4E9 ^
+FB9E1E71F7645EEEEB3DDE66716DC44444CD657C ^
+D51F071E360D96124DA49AD37E37DE17B564920D ^
+0667AFCDBB82B4213447D0B22006DC4A1320CD21 ^
+8FBFC65FEB2565F2FB8A9966B74702350C87CF40 ^
+8A8BBCD6AF76E71067EB0AF54F90EE5AC2B5882F ^
+8D831EF2344E336CC27281227185A34356B856A6 ^
+DE7AA7424F92CBC50966FC4E6A577F98905998FC ^
+1064EE6BEF704F3A618CB9C58F299B22A4D34293 ^
+95F8CF7E864FEBBF77E46067063D08D5175FC508 ^
+79381F230970F120D19B115BF864C794878E7797 ^
+D82A30F49538561D5A7D1324ECAD321DD05E1202 ^
+5926CEEAE43D29A7BE4C0EDCA626C43ABE00416A ^
+563458C9F2C16C5AF96915FCD9306F1D9BA579C9 ^
+C92B0BD604E45D7479AE19F641B2DB067E4CA774 ^
+D69D013EE5C871D3AE3E388090BC1AAF9852A83C ^
+7C341ECDEE7298605933465EA9ADBE7E044C8A79 ^
+83EC687D22A13EDDCD470C52C45276A6E1554982 ^
+6D27928F014269CEC4E8745EB73FA714BE2DC62E ^
+75C0BF312C05231DAF7E9CD4CA33ACA78BCAA59A ^
+015D799C602DD4E30D2C0104A57B1E214A423D66 ^
+D2F43ECAD20F0B4C57DD07D3CECE562B6B72C7FB ^
+27948CE5A56D57248D4DF683DC3FE023D2B9B43A ^
+2D5A984BF32DE28242744406469E18B7A5178A97 ^
+FFC5C4ECF0CC051320E071D14C7DCA4A4DDA305A ^
+CED8A5487AD13AF0003129659DE2556183836C54 ^
+599BB509863CC5D275416F6DB6C5D2BD827DC347 ^
+3981DAC895DDB9294D933C1CE78828E3A558B152 ^
+91EB715904123D326B23ACD684DFBD7203CABECB ^
+5A9AC8C3705AF14DDE50E6CF2FE5B0C15C4BD282 ^
+E2620DFB42B5ECAF85F590A71DF696906AC41C4D ^
+CBAADDA7B5DB389BF1775AE50040081A05A0EE48 ^
+AAF80D079F3F980BF9D5366C5B1991A3E3D9FDCE ^
+2A861F616604C526ACB157732DC431E81BC9A1F6 ^
+FBDB22AA0B87718F464C0D1AA39695A1BDCE053F ^
+4331BA331522D4F9CD6137858DB9AA16AC95316E ^
+33F6BFE23A4C0E04B8BF642CD96437EF0055AAF7 ^
+2046138F7899FDB2063CD84B84E821525172C03B ^
+E4FDC812C5F7A37FC7A81005F1E78BFF59666887 ^
+6477F931AC20B2FCE1C92171FA4DCF2D266B3DC5 ^
+ED0DD516FA7FE2DB7AFCC3DBEED0879A0C10F1C2 ^
+FCEDA0311C085368A5751BCAD8EAED2063C2D40A ^
+23EB08B5100C8FBAF7B3049887A11CC531B6CD78 ^
+A6C42B757DF078A69FFF6819A8ABC46E1B09F435 ^
+0615EE4840B1F1CD628636D1B4F4495639DEDEBC ^
+E2288110007AE6DBCCFC74B7735F4D94B0AA10A1 ^
+159E01DC348EB067E90A63BC6FEFBF4C45A01F9A ^
+A16286459CC989AE662C731F3D7D0CD487DCCB3B ^
+8FDAFE2DE37215E142E27A65A881F80E0430BF49 ^
+1BF978B58D98FC15731F4111E7C7A49F9CFD7C65 ^
+C1F61CD4B4DB14AA60C6448C0398EEC72107826C ^
+5CF0A7F6F46A730CD9103A54F1EC8A7549FA5788 ^
+FDC104217940BE5A7AD1C02D128B31747C972A5C ^
+DFF58BEF4FF418D26A35B55215CE419D3579A194 ^
+3A2EFD444F4AA7A3DB9765E027CE5D82B51F6737 ^
+EB616B6F97C5BFD02C1B9E4AFBA8A5151DD4167F ^
+62F31F9A28D0587BD8253601A7EFB698B03205FA ^
+E87645B2CB7DF66DA2771ABE0CEDA0F625FC8AFA ^
+E801C3071CA6AEE278B222747BFA819C118A2DDD ^
+EC70223BD963C122E4FCE2928934DDD2D7661CBC ^
+82261D26377A5A5DC69E0F39D0BBF59A1B2B2248 ^
+2E4DE781E4407AE536F70DC5A5DBEB178DBA2FC3 ^
+AD3D958B884CAA28D5858DA103463C300862DEE6 ^
+2A6A563C7FE33129637FABB4D40F5F0EE8B5C500 ^
+7EA6003A8BEF4D5BFA6BFEFBCB6A5B3B1A3B7991 ^
+6DDC620DB14882575D5BA1219284CF1C3068094F ^
+91AD7E588EC829739C3632656DE1915AC23C8CF5 ^
+311A491C1B5D8A26EA2A77A36B5D53FDABA1FB2A ^
+9D4B752AA8FDAF92897B03C4D65B65EABBDF062C ^
+C569FF6F0592664F690B008EE7A12EDA5740F0C7 ^
+1AE35E9CD3D0A8A165B2758E1DC4F9D1CD30FBF9 ^
+819A83318700EA861CB69F6CD8ED4ECD78CC3CB7 ^
+98099B550A82CE22EFAE48B5935F636D5814FDB4 ^
+CFADB998167DB289A7C17BA94DF7EDA00B29085E ^
+3F5A90A8F757936987938DFB95F10239F91AC264 ^
+7402265908EEA5DA183490FEF2EA2E55C9FC2862 ^
+EA6EF0F7050EDA6B78F35597E85B7A85AE0097E4 ^
+73F2780548F7C79E15945D7EE2A3E03B30DF35CA ^
+8EC3C93C7307E14E9C65F26DD847CEB195DE277A ^
+CFBC571A35B82FB0B7CB59753C4E8DE36A751195 ^
+3C4802A956CF93A148B9034FB8F041ECD8DD4532 ^
+5DA269C1D5CCEE3C7A66E31BD9F5E0B83BA06CE1 ^
+706D90C00800DB9790AF66788D1B3DC81E3FF7A1 ^
+59AC856447FDD27421C52EA66E465C64C5033722 ^
+EACA9E82D043F2B6E12E64CF03D82ED92FD6A64D ^
+8160755BA09C74F79DE8F9496BF0C9248DB7D45E ^
+8CE4390C185BDFC8BC9C4D3BEB1AB757C44F6434 ^
+1A1ADB628EB7B9CAA821AE9DE417E09A42A97113 ^
+97C4F92A46EF3F9169A977E1643C10745ECDAA4E ^
+408E53C03D10E2B32222F2B54D118AC4D65A9386 ^
+710628E811C207784E3255DA8432CE6E14B61FE7 ^
+4F6DB622778F4B1B6203BD239312D86589F1B261 ^
+888AD8FC1CA5B893294FDB8FC94AB7762018C1F8 ^
+AE36C2F54223BC082DDA0D528B70B2AEA190779C ^
+4BD2BF914223DCD0CBBCC444323FBF0E487F27B6 ^
+7526D5DF7B2ECFAC7BFF62DD7A4B5F38463305F8 ^
+0ED7C87B68F50813AAD5E50159CBE0BBF9BF05D2 ^
+4D5CD4E40A6668893EEA15F025ECB8187475DF4F ^
+D38446E842C0A94F175B772BDC707CD2EE79D098 ^
+DDA868BC2903C55CF273F48E9B92C09D90CD0179 ^
+0841268B95ECFAAB9FE3787BA7261227A1F23294 ^
+D3DDF20B4C0DB668421DE1F242B65A8C83FA867B ^
+112F3CF7DACA7527819D16704EB41302A4EE52AA ^
+96072A3EA4463A156B3BD9EAEC16ADB0905160C9 ^
+715F195F09E3EAD3D70AE51DEF1C9709500C0A6A ^
+8A112CA82CFEB5F3001B7A00591462F4120DDC02 ^
+50FC91E915270D1202F6FC8792BE16ECB73CE405 ^
+907736EC45BE7BEDA1B154EA282C51B5795991F8 ^
+05D49462991278720EB44BEA656AB4442C8845C3 ^
+6FD56D08A2D4630F72AC97E3C94A9575F3046729 ^
+DD1883376CF713C8D7AEBFEC60D51FF8E2A806E8 ^
+E0457FE00F9DEEE958DD6AD948EDF9CD9412F73A ^
+BA6538E91B276504C84E213B325B4A7703E924B4 ^
+C20A9B848503650DE9463B9992EB977422BB53DF ^
+BA4A565E5C0F9FAC89D55A2B784F291C7BAD4255 ^
+6510E09AAD8288AB81CA54DD5656DF57D0EABBE6 ^
+33996C9C5AD04883BCEB9771A5C4A272F88550B1 ^
+7B96F3C1272AD765DBDC35A59243F6A8F75FA351 ^
+5AA76B16EA4DFB267D88FF7DBE4F055184A56E56 ^
+33B9CCEB1A6EDC8C91F6034245B2E3AAC898C678 ^
+701A32FC0B1163BC55DB76FA46F69B574B3803A0 ^
+5D6F44A4B5175BA873BFA3369DC8BFB0AD1AC26C ^
+0727F12D8E554EDCB435AE3BD6425B197DF6EE2E ^
+6E1F46DC4FAD671759AC969998694BD79326246E ^
+85233F9CFD0780BD60240A22E037C14EB8286C33 ^
+B66CC7332341FA9261D96362F0BBD7B676F95E02 ^
+782A78F2FC32E0B627702C541341ED28B009BB6F ^
+6B7935265C529880DA5B166EDD660BAE14A770A9 ^
+49C298B1C10D380BACE26E907C213C90052D7523 ^
+49CE4D4FF9FFF6724DA032FF33F8C5A7792D24E2 ^
+CD2C4F19C12B086C071BB6B20E8E8210AFDD2D50 ^
+39710F77BE564C417C80CB6E4B87BE72FA805A40 ^
+F74A6A45F5B2979B5E773007B90804F322F13AD8 ^
+6FD6A34339047CF13F777C4B7D9E287F499FB19C ^
+FDB04F04D3B364A6953C341E343E310F2383A655 ^
+981E8717538CE98998E950EAD28596B527736841 ^
+E099987DB0CC61CF607C9852336CDAF478DEE33F ^
+E9C42F25A3E3542D1510DD09BF516AD809D42702 ^
+F7E580FB21C725CBEA563B193896862B9BEF7F24 ^
+D778A3287F68F47B0AA421410292D47805997A94 ^
+534DFE759735723649EDC89BCB063C0CCFEEC34F ^
+9381FB5BD26677A7760FC0288532755062986DF1 ^
+27E97EE829820399595DA0A0047B74D3C4E0DBF1 ^
+D38450071D1B079A9FD518D2F317C83C33094F43 ^
+0221B8E4D2FA66D2EBE1B04E679662CE41405E48 ^
+B9BC4FDC4A5CE00EFB911C3062D6F33304701C28 ^
+461B4206618B766C89E6D9AB2F8DB07903860234 ^
+122A9306B102F2C50B7364E1D24FECB0662E2958 ^
+61E91F5D167066EC904134AB1C4F9D116C9D3E80 ^
+6B7558BD8F4D3C5914A9AB5D7418F7DB77583B55 ^
+CE48EA94843854555DC48D24D32405DAB9DBA612 ^
+5A722AAC576F4078C001D06DA91C28131A4F92C5 ^
+9B8FE0F1E6573CC6832BA69DEC9F6E646228A374 ^
+F98429CA2799E5CAAEDDFB168B782A54384EF0A8 ^
+142877754AB95F57AA541CB978BA400E812AECC9 ^
+6D84D053CCD9E68CAC5780892409F61B39DDFD48 ^
+B58CC9CE0AE3DAAA02E3C040100D4B568D29E0FA ^
+17FB18FA32A8237D32CF83A9664B1B2E40DC5B11 ^
+C7F65E54E608CEF1C7A120BE8A29FA6C94B680D2 ^
+9C46329BA34077394B439C5476B91D9DF019BA76 ^
+3612B381B80A1DF6DA75AB2656BD5BA8DE6996B5 ^
+EDD9BCA1C431200D3234C099791C81D8605091AB ^
+C1951DDECB9796C0D39ED9AFCCBB65200AEAB0CB ^
+55E4F7846D9B90D8B31EAA5B9371D395590B6528 ^
+5D40B432ADBDF3A01355FFFDDBA47586B3DC7C52 ^
+AF5C675D2249F4CD20E70DC9E18B88D3ACFBD6BF ^
+B0EB6796A21876FAAF50FCDBA2EB121C4B742166 ^
+3C577C70B76810DDF9AD579910347312B881C30F ^
+0C16897D20C5F352FA6110C70F9A8C33CA35CA21 ^
+DBE0B4341526060C5B37576F6B972A1EB8954059 ^
+1567B10E33FBBE20033F5A52EB810348ED154F19 ^
+C1E47289412D3ACC208620A1EA676CE2815DD4FB ^
+ABC227EFFDCE3758061C77971860247E850382AD ^
+B29EACEC903BB8AF7CC1A63516163640FFE62822 ^
+5C8976A1A4FCC6B6FAB5EE631E3CDC561ED5FB10 ^
+1A1EA5107CC46BE909DF8165C3EFEE8676161991 ^
+268E86BA3A81FADDB20F74DD44C5BC71A98C3D08 ^
+05057E5E7934AC9A9141D39B8D4F5EA6AA14F74F ^
+C03EA72C4D68945726DF63803564E434426302BA ^
+54AF20BFBFEAD6BB2DD68E65D39D427DF7E17FD9 ^
+FDE938DB0843A844DC0F6601497A39ACF167D6DD ^
+ED0292D0BD869B66E80014824A3D7886CD6D3590 ^
+749B69964F5C0D9D02BF5CF903B2E56D09CF1B9C ^
+6B143D30366C45F159B83A8D1AE8AAEC88E44136 ^
+01169D65E71014946D0BF64BF439068978AA5B3A ^
+4C36E0A8C19C0AA6C80DF0611BA3404C1025E9CC ^
+A4DA9EEC2F682AF5B2EE7CC8525EB07DF66E5945 ^
+F1349AD0124D11613CFA46D498671484E5F37790 ^
+6A8E82D2D27D3EDD6E8B119F746761B8FE83182A ^
+52E7C7C4AE02659953079DAE20F442353EE2BB29 ^
+49C8D822724274B85DE62D9DF586FE880AF396E6 ^
+57866C0BB976B4F8AAA7ACF3C9A0F700E73216DA ^
+541A675DD37C5D6F2CF242163A5CF6B728DF9995 ^
+55B26D9344D4D644CBB69C4789473543262E8B91 ^
+3A8F3F0A96297020EEA583E9A280D53E0248DE26 ^
+D1FF7A0CD0B69A76B5B80D2BB5736B8440DA7F7B ^
+53E715FA39D3732F38FB4748D46409D998D67973 ^
+377781ABB4AB4E974B9C1670867E74F87AB4950A ^
+8E7DA96971265ACC0FF7C381127C966DF9F9F13A ^
+28038713A33ACAAC730FB4DDC3A707886E598DD5 ^
+5F6BD44D07A1C811D5B75661A61BB69A81444EE2 ^
+D465E6C767BD02D457D601765DD0FE5521BA2AC7 ^
+487D9E02912004E961968F387C21A65A0E653AE7 ^
+1F54DF00052B3740301C43420CC2CB85B2770095 ^
+7C5BB678083868EB817E616BD09421B910021649 ^
+4D31526E4E2FE3BD6DD4B3F59DC2EE2A52A9FB42 ^
+669F9FA9D71FB92D51ADE15C70742FB31B013901 ^
+38D1E74FE26AA43D45DABC160DEFF113B7740211 ^
+3724EF50CDEAEB856123BEBB190F38834461664D ^
+E2634112D2977A179D4C9AF35F220D3A626AA04C ^
+F14CF8133FF66A3E20D25E5DCFF70605F6B8A0BC ^
+809E04A38340D010B78B5287C8FDD20C391FB61B ^
+E5349D4D6EC31E2CF41001DFC440ADFF6D25B4F7 ^
+139F25FDC344EC2456F6E4DD9938F65693F0CB2D ^
+7C628B0954D4340B0851C89F1106589C5C6465C6 ^
+E65E65D7050258B6B6B5B35866840B5ACE0DBF0D ^
+77D33B87E0C13529D3AAC4D6606213EFE81FF398 ^
+5BA456BA49ABE50BBCB772FAACB71D4F3AECBD45 ^
+801A21F7AB73585AE3531058DB9512BD69BA5CB1 ^
+192AC4D5210EC863604FC1BA388AEA8455D4175D ^
+FD9F103EDFC4CC9F9C424266EE54A79C1C987F9E ^
+361AC46D96A69DD6E416D4563D7C69D3B487EFC1 ^
+3A7629045C0193FE08928F7D41B801827593116B ^
+545B2F5FD015F81BDE1DAFAFCA184D25590560C9 ^
+FEF2C50DA33621206450E21D92951B25385991A3 ^
+913A417AC1ECE08952A60E0035F70993F161EF05 ^
+4FFC95481F6F625B1B8E67B133F11619CE5C1460 ^
+5D6D0765B156FE028780331B6A53F84DFB130F0A ^
+2C5EC89F1018D34AB11E0CB6FDC812F82470B168 ^
+34D62CDFF955233FE7A5308925C24CBCDC0579B8 ^
+1148994D30F80C5689D7BB19CFBE33546872B4FC ^
+074FCA22A8A63F446C8D196612F7C812C22CCD8B ^
+228FE29FD13928D8FF0B850E50DB41DB406EFCBB ^
+EFF7BBF8F2F7DF36AD51EF3D748AAB8D8DAB7B7D ^
+C3AEA6AA17971C0A143ACE54A8CF515F9EEB0BD6 ^
+4C3A980E40602D4621C2AF1BEB1CAE27DF19AD32 ^
+E5CE2A41C72229D584E40FBA67C697EFA08F451D ^
+64A5368264959C73FB0A12F85D4FA16F8E25FF08 ^
+8FB770AEC165A93A6D99A0DC52F38444E0313073 ^
+BCFF3C5E5C56876A3DD8C4C90D4E819B67D71394 ^
+0EF20523757E25611C49C1F259D94381B08FB90A ^
+5D9F05DAB91C46ADDCE4B163C6FCDFB5230BDFFA ^
+11B3BDC5F3BE09148DA07CD42EC9C28C718D6A5B ^
+1EAD76EF18840B3176296FA57791D832B7E4035C ^
+AF8EBCBBDF5B8CFC203FBD8644B154445690B02E ^
+0A156DAD35A10AA7E41C5CB3B3043A051B7180B6 ^
+9B3E5F797BA246E5DE660B9A36E52C204BACE822 ^
+78780359CD24A2B7157FD6D55CDFA6F9DE149FF5 ^
+F2DADAB4275633F7ECDFA971D824A31B1C8D6643 ^
+EA68BA8F16D8368E6673A5C5AEE86BA5C36F2D97 ^
+788AA9451196E2BDD031E747B098D73BE113C093 ^
+18FE259B3573F52F23DAD33F05D9C91942B516DD ^
+0E4787F46AE8D5D7CC9589B76D00D60983079D75 ^
+148E4FDF031CAFB726099DCD1EB591BC2F24D179 ^
+3981DF8658AC2FA5C3151A424262324D41940DBA ^
+3C50A3800636EF877D89059F66CD697A9DF44BD1 ^
+D9BAB0471E2DB97FD5F3A42884DFC708768F62F9 ^
+52DD1063326E2550B6EF40D5EE4E1AD67C7BB6BA ^
+13CA27827127C698810AECA158DCAA7894F0C912 ^
+086BDB17EC1B8CAC68030A56FBD4C741D4F95DBA ^
+F7F389BC5ED225BD6399CC43EF22AFD77E895D06 ^
+67F173AD3A24C26E95E2EA8B37FC0259B1DE955C ^
+A7F348A3B6F67CCF7C7C69ED065B3FBFA832A8A2 ^
+ECECBB25354468FB62AC87D5CEB688E4A671DC42 ^
+62330BC400108DFAFF298EFB76BDC28CDC153AC1 ^
+BB0ECF9CB3CE448B4EA9C57CF5F1F997F81082B4 ^
+12C9741672CE8DBA14CC66AF3338B61E234F9E68 ^
+DB4CB5961A2FF6964CEDECAED3DA03D140112EA4 ^
+45E4D2BE3D9729BE9F69ADB245A5A9CC75064534 ^
+E35253550C84BEFC26C2E97F0C236CFF1D85C36F ^
+7D6D950A168107702CE3B6BCEF9298F9C8FC8F3C ^
+812F459AB5887364D1F2A9A00CBEE5FC352C39A2 ^
+7EE27F33C59B68C34604416D38606BD3F5CB6B06 ^
+D57E2A4F15DF5C50F2485909EE3149735C6DFB84 ^
+3D12D88B61EF0972808D8CAD41D8A16AA7ECCC87 ^
+CF9A7CEA9B105ADAB6BBA3CFB6D090B76603F7CE ^
+1D43CA164CAD0B616BE5763D7F5EA88355953F4B ^
+3600F085A53FB0115C26DA90D1180FD34EEB6301 ^
+E9F9C088C30A37E6CDF067F724BE6C4786F27C9E ^
+2BB86B47EA34400D434F8F4F94830CBDA9D4E573 ^
+3255A7D9A7A0B56D0D9C665EC13F7A8C8F05DA7B ^
+453597500A7D5BEC8CFB950926A2BFC0F92E149B ^
+A15EC452476870AC459B942F6A6B73822A07899C ^
+5B1821BFAF917BAB3DB1284A1D1FD40EA011BCBC ^
+8DDC25C7CA330A18CF39827B7CBEC00B874AF193 ^
+283832F45BB5E69649FC10DD607BAF8BAD61783E ^
+F39426F9C0474596B0251F0CBB5F92385D862D24 ^
+714E32DD5BB8FCC75B1013E6F1F56F96D97B36F2 ^
+988AC4592D50113B13F6EDB5C113A22E4D0F518E ^
+93BF1463788B7F4A4A06AD4C17482DC260797A3F ^
+5532535ACC8AC5668977B2A2F322B23AEB443DB2 ^
+85CC7AF0929F206FA44FCAACDC24C4E78345BD80 ^
+392196E3F2F4074D1D485A52119012D8C05740B6 ^
+3BA88B91F1EA18E712292301FBBC375E9B48BFC6 ^
+3DAAD1DAB1795F2C1C8C5CF5305B549ABFB85398 ^
+6EC93AFA3AB617708276E99066FDC331C84F028D ^
+CDA219303B91AF3C3FBD0B926758914984AD7C8D ^
+599CE24745EB5408554077354BD10A65F6BC3037 ^
+0798C1B53F949D643F7BD66C194715E7CAFC6E19 ^
+A17230F164E98AB83AC1141730B23389F0EB473D ^
+2C2B95173F1B06165E17EAE36A53C7AB641267C3 ^
+A7F408EF449DC92961617D4C51B55AE4E4536E97 ^
+2266C5133B6D6B08A09897AEFA355C768F718C6C ^
+343F10EE6EB34DF005E749D1C4A98F64537272B1 ^
+90EEB76B126E632308F8655FD49C52000027AA48 ^
+C7EA3C7D4AA8DCBE9580C4434075017934268419 ^
+455D4E7C988356A56588C40313D28E425AE219F9 ^
+5C0F3090992138D34B4E33029CF83A64ED8AB03D ^
+CB3C5288839D6FE79EB2E50D3AC34BBC4A942E46 ^
+E605842205079D83BDD489DCF6F8A2D1EE074C60 ^
+ABCBEC56EA20B6B369C85A931B2201FECB826F4A ^
+480C1CB97C3419DA610D9783E6047E6C9A6101A4 ^
+874818464DA1753D3AEDDB7D3B46E2D04614D7E6 ^
+C95B65E3A37ED4A2FE2B27A2D52BF1BFD307ED20 ^
+5E188A4F625C05482BF161C45F5094844CE70461 ^
+6B2EBCFE74E0BF32480D4BCF9A5698A527AEBEAD ^
+ABD3E28A2A528B7963EA8D8896651A17337304D9 ^
+B873FDE2C312C2279EC8950EC2C2E9DF990F006F ^
+4F1A18714689BDB766AF686623BEF08DAFDFE1F5 ^
+BA886793A89E7EC62692A8690164BF072EAF7AA4 ^
+A15C8DDAA0448DE7B361552FC51AF0D72C0737FA ^
+6FB516CBB4CCE9681C44EFABABC7A26C79C79CB5 ^
+C6DA89D3F7EC4D2FCDB36432042A78EAC9F04DC6 ^
+2A94A9023F7D54DB26C8C2A6A4C951126712C2E5 ^
+B0F115B8BF0A1464A378420A1F1F574AA1869FC8 ^
+A3C1794F58FFDC361BCAD4779B5DEF48E02ABD1A ^
+2DBA5D80C4B17167E715A8012876095577030D5C ^
+062C3CB7A059766125B368AD6C19BE8FAA981950 ^
+ECEA96EB623919DF4E22FB106616EF1FB2ACF5AF ^
+C0CD5E555861FFBCB2FF4045A46CE30AE6CA1758 ^
+A0150D931980E1D82A21928837F7E9E198E5D1B9 ^
+BF877B202812184CA74DE61FE34DB95BA2AC5D0B ^
+C863A0D2232E901920752F2AF92C201FC73609B5 ^
+C54E676209D81CFED2E7ECEA6F7E35A5459A58AE ^
+CBF376E8571F81792AAC49BA7E1D7F41713ACDCE ^
+9CD248C07EEF6303C71901AC484F30788D9269F9 ^
+AEA41C5B2260E0DC57094C5E1F80A70B85E79E77 ^
+B1016F26E32624C5328566B243329A2F75A36D06 ^
+3EDE118F7E2764CC49FBC3873508D38A2C6A4592 ^
+03DF0C882FEED72F81B303414178976ABD089EEF ^
+2A8E36B6A545D1ABE7B02D6DDD782AE032F7ED41 ^
+D90588E606FBDF3CC6030756DF92FB3729441E6F ^
+BCC413133B6D84621B482A7D2163EA955AC733BF ^
+BE1F36D34DEC54306EF20D8326FF603A716F4331 ^
+A2BAE41EA01E8AE9D59F5E8E663D22C9F414B0F6 ^
+D2295FE26206DE9ED169FEA487B198E7CA0DE78B ^
+06B13130DD10C94A24CB50DE6A612867F85E17FA ^
+2CF4C4F2F270AF63D7035903231CF7E7180E66E5 ^
+0A9EE3293A2C9B2ACC2F9B99BF17AAC618347857 ^
+C338F14C156D8777ECFC36ADF1850B64EE9E6179 ^
+E9BC6DA35AEB1CC399733CD0AD3B22E4E2C83E92 ^
+7A42F820210158AD33935CB77D78C28F9FE7A940 ^
+ECDEFA7817A436E43C3DFA35069F87948181A58A ^
+761EBF336F1229BF80702C9C7798DAC37ACF3086 ^
+1975B716880B49BA0863136736942E688C9EEC7C ^
+A4232C3227DBB91581B86FABB1C5AB0A29801DFC ^
+49947AF1D9488F146BE4C77782CB2FCF6EB13FC9 ^
+A3402AE17DB9E6EC899B0E15973073CF9404A2DF ^
+DCAFC2DC5BAB38629DFA0DE1454C300E5B9A2D66 ^
+A7F915F745E30E4CF6AFFABF214AB6D950C66FAE ^
+764515277D4AF73A14FAE2D9CFA4F9BAF306CCB5 ^
+B021EB08A436B02658EAA7BA3C88D49F1219C035 ^
+B97FE9E1C5918FEFBEDD986B757CCF4EC4AFA75D ^
+6917353596BFAF1A5A06119ECDABB37CB017D71E ^
+FCB4BCEBEBBAB66142AD2A5B35AB5DBF78C6A463 ^
+BCA454B69F4486960C633D2C4453FD01D6758BCE ^
+5CD25E62AD97AA5DB3A9CEE99C58439DFBF6073B ^
+E8405E583D31B3B8E8B365087F2AB391753324A4 ^
+39E32AE405420DEB07275224817B57187079886F ^
+63AC20AFAEDAFBFC018755F4CEB13A042BDEFDFE ^
+27245C74B61D19EA28FED81E59AA48EFC22946C9 ^
+7254C8F5A2DF0E747760E2EB353C4AB24E253602 ^
+32DD49B796ABCA76356AA9AB07D669CB7BC7F899 ^
+B83F3FBE6DB38223253344E69C399C474E4C64A5 ^
+B3E0EB484AE5B10B017F509730F350481A60F634 ^
+A99FC247C177D66CBC6C21C10C21E10FB2F33EF9 ^
+A7D033A946AA0315CD2E4B7025164B77E5979CBE ^
+F2DE5CD912D5CFE727B353ADECB6B7FD11E80189 ^
+111BA90582E17CB5E1BB70AB72C99FCF647876A0 ^
+9AF7F1A742235C0E396F6D1319BD1104518F8475 ^
+923B3E5246FB50FB5448742B8EA8CF4920E70702 ^
+CBFC4563334D104E4DF24443A295F4E9A7D7D4AA ^
+48F4BEDE76C6DDE9B72A9FED50D0BDBD0DF7E7AE ^
+2A21E7828C064DB0D684561622802C86A504DD37 ^
+2D599572D6E57A437A2A845546FBEF9F2FA11AD8 ^
+CB4CFD92FFEFFDDFD87A4786D60E28C7622C71DF ^
+FA6DB9D1EB92461454E7DADC36C9CE7A1F30C63E ^
+98C264B7CDF774C7D82F4DA5E1160AE4370665CB ^
+D503D3C5CAF7A2D124A7F9F0E7D8D0F5E29B6F19 ^
+AEFF5AF0023868EF6E3AD49F2C30D65E963B6308 ^
+73B1464B9D05509BE72E83C819F9D618B3121336 ^
+791774666D2629D4304BC81138B4D8A7599E77D6 ^
+362A2D419BAF263F1E77C5689F611AE301C044F2 ^
+B4D4796D1BC1851DDB75F5D3BA3089D1D0E0A15D ^
+B7C4FD404A73C0AE43FABAEB471FDB6F9B24A27C ^
+B9DC118349DDAB37DD82B65E092277C1E2F20C5F ^
+144782913DF2FA8F76D210A7A321F362FA5DA779 ^
+29D64351A178E52EDDA9A4B2F5279B70F3FEF39C ^
+31098A70FB95128BECC2C729CE5A2A4BCA121845 ^
+9C05D6B171C60C37822CDBD7E8C1C57286E27461 ^
+6FF7C4960E35463A8FDB77844A29DDAD1FF04F53 ^
+2E08B9088646737620F1B448E81EA5E42C40C595 ^
+AF2342D8F4BF12F9E524E44BCD42066F84620727 ^
+543A1A99B497DBB7776403F3252A9B2E11A0610A ^
+A2A46BEF09D21A9BA32AAE4FCF7A846D128F0358 ^
+81960A20A755F84B3623D1E2A395EDB12DFDE73F ^
+B016C90B350A5A9AD4C1F3AFE49E3EB21AAE8B7A ^
+41D03A8D79E8BAAE116C2F5573D869D97D7F6E0B ^
+831237F5BDAC37C58BA31F6131982AFE680BAC1F ^
+2E8ACF5FDE18542BDC2D0B95D3AED7FC48B5993B ^
+171763D880D45885EA61F5ED04BB51B79C6A2724 ^
+405AD282A2141C38D3D731F9DF630667064B9ED0 ^
+07F2ECB944D01DDF9C68AA68762BF07F385E7E6D ^
+EB5FEBB813E4DD7BF852FB32466025F7D4E79DD9 ^
+52DE090DB027385F17C9FD41F61272525FE108B1 ^
+103E352A261134E1154ED3C312D890646FED38AE ^
+65C73969E35E8F307B518ABBDE85654CAD13D0C7 ^
+FB380C0099EADED9ED8DD48D70E15C7A26E2F417 ^
+EF9E122E0B8F968EF262E1A98BBFED7B461846B9 ^
+771A162BDE3CC4C07BE7A1DD25470286F133020E ^
+5F892353DC5C65A1D8C9510ACEC43DD96F432742 ^
+4E658B8743D510221B968F2C78C72A588A5DF6D6 ^
+5D5295ACEC24F8A52ECC5B174E4884732BD216E2 ^
+7791BD0E1C4136D97C46CCD66D36E98443C4182A ^
+515419AE59BE4E824E575E497F361C3382C21783 ^
+7669D0D083B3A0A7B631EE4871AD2A2AF8C512F9 ^
+90A1A9BD93501D9AFE5040DDEE395F94E5594EE4 ^
+B8E48F79618CDE951296F1D28B87653C3CDA6FDB ^
+FE94D5373EF009ED2C06F632C739717791EB6BB6 ^
+B5C3871DA2466E4635DD3BCD085A2B8E222CE8F4 ^
+43032D022D24B65394F7A707C8441C2A7F3CD980 ^
+87C13448017DB3B6C553250C59DF4D3D57676788 ^
+F38FCA4589543051935D4F1525710AB366161F22 ^
+921E3C3DE773F987452CAE28D3C10DF9804632DB ^
+32308D5BCA33E694071B8C17470C6469EDC1DCCE ^
+AC5258297BA22FE60B464DEE22349C70FDFAB219 ^
+599322BC214D7248216F0C6ECF00CC34C792C5FB ^
+99EBA91FAFC27288B3FF32DE55BF17BC6D76B16C ^
+899DF7C21779CC0F54EDCD441051CACBD2B06941 ^
+E5E0BA18BF3C99062BA444847876C5CA2DB8F9C4 ^
+94B8B90566B2E3BDDA8FF8D37BDD9F95CF9BE0B2 ^
+86422BAD65C5E0B22F02B9D1510B9D24F4227AC9 ^
+427694B772A08400381D472854FA5FD4D4CC1D62 ^
+3732DA8EBA84CB4591DD4A87BAE958635C85DD71 ^
+D41C28C028E42AD1DF5057C97BB953B03AE8F6AE ^
+4C44286F5979D44AB4CA5E3776F30CA04CE539EC ^
+E695D9B049A1497A86765195BA7884E8869142DE ^
+2A5DE9C5489375B8EFDB09CA29D32FDADAA07402 ^
+012356EB46A587763ECD1EC9F3114B8B8B7987B7 ^
+6B803DF07E5A47FBBE412149D8258B526D2BE96B ^
+14A1090C3B382482AAD5EF49B30D842317792745 ^
+C2A576DE385017FA84855388EE6CB1F51F43A6C4 ^
+5746B8C88CE540313A0429E64841ECD0AD569299 ^
+298EFB87E9C09299DEC17171902682D919899C9D ^
+55AEB7930CD6202CD52E6513ED4C35824B574198 ^
+ECDAA8404F88334E9C2C6FCC9209795581654C25 ^
+061FFFCE8F69BE0D0C9B63E30BB065C6CC73DF33 ^
+229F3A8BD2F6FFB5CE2DB330ACFBC4C4D7796D7F ^
+0BABE60803248059F3B05E06E273B5F41A619C9A ^
+5F496A5AAA1FC38B76069BF9F08C63777EE7530C ^
+91FC8994FAA03E9A2D9D565F04478C6DF035AFE3 ^
+A68552B9049E192BBF98E82E2A69E405FFC2D93F ^
+7910393D1D9D8B876EC89FE9100320D371789C23 ^
+9B923F97F2D2B057950DC3C0E89981F22F96EC2F ^
+1EAD9C237CF3B1CB95E7ED79EF2E5842E9263447 ^
+F51E5C202D698C75F8F0C2926081D4C28F641812 ^
+8842D9CD97868196B31F34C02BA63CE34493DCA2 ^
+26C8977BC36C3298582CE6703F62DFE4488E0DDE ^
+955BEF358ACA4D44E33F31051A3B92D96BA669E3 ^
+68D841B29DA285DA53A31E823462E794B3126914 ^
+BB52C1806605DD37113035390D97036EFB3FE2BF ^
+BC55772BC9B6066112512E1A8B633411B9508FA2 ^
+BDD2CA4B43157C04CE7043F57B7E2610D3E175D9 ^
+8E493F25E110F6244FBD7585CF18F285933950EC ^
+650242DF99E985DE23A5CFC25C8CA72C80D7F23E ^
+56A061FE49B428798C329336D4B184BFE69C4102 ^
+59FF817CEE946CB948056227607A119F4C7DDA89 ^
+BD4F03F1878CEA86E2AD981C6A80701E0AD30B4A ^
+A635F528CC4028877184E8918CF73E1AEE6F777F ^
+15DCAE87F7E40CA577C61C2AA5B6D90F0CBE6DCE ^
+D67BD85A353CEBB99ADE4CD86B54673DD6D64360 ^
+1619DE7229032800CDF071830CBCC3208B1EDB09 ^
+09DC18BEE0C2DD9A2C7189AA6D3DEB8B7CC41CE5 ^
+4165ED470D85FEDD9593577A9101306C31825E00 ^
+C52942DABF4F9D72B31B2B3291705EF5201B3343 ^
+88296035BE79F5281B91C0F1006E57C28671CBF3 ^
+82593804880F168B9FF50D89CD149E9F263EB557 ^
+52E4F42FC2EC2EB7C0A728D2251A14A6C5EA5A00 ^
+C91B243CBA2031B29F365BA4451FEFD6A902298A ^
+90F6F5A65E6BC9430A34C06631208AAE8B7555F5 ^
+7535D77C8809B4EA21678BF9686791418FC71931 ^
+027070AC6B5D77BFA0398B8AD556A23AB8E99EBF ^
+B48335F6FB6EA27CE2156A1D3E00E42D3E3A8489 ^
+B67303D71BF125F2441BFC599106177A32E43BAA ^
+46E98D49BDC5A4604F62AAF76E964838291BFAF4 ^
+F1ACC562D96999493EEBD2531A289264C3E1BEF6 ^
+0B261712C3F4D0D74EBDDD052E1A058BCFF412D0 ^
+50446AA7A1A81A97B1DD524AD0DB4D09971D383C ^
+E3A51B6AA5AA586803EF2183DECA0CB5CA869B11 ^
+C81B52FD60ABEA8CD5E3184E206F693211F008E4 ^
+197270C0DF693622DFE871857A7C87B7BE2E439F ^
+43453DF7620D71CAD56DEF9CEE616AD9E7C73EBA ^
+3E3C6EE1141AB3D7EA5215ACEF4E876EFA89D03B ^
+5773C28260C2B2D325883AE73B04D28BFD2E8884 ^
+EB6F26A0E774022773CD86E1C8DFEA461CE6F8F8 ^
+6C26410B11A0CFC97849F6E43E77B8E48D5C5363 ^
+F0236CEF2298ED3D86A95E9F5247C17499A772DD ^
+704B5496CE0AFF4289F3D915230F69ADC7A1ED7B ^
+B0D4FF6B50F09FBBA19F76693AC9CA87768E2758 ^
+10DE4F687577CCAD9E16AEDC9958021D90DE8726 ^
+785741949059E8508DB8D132A9B053EB4277119A ^
+CB041BAF13AD22778A1C73A8AAAB7458B664B1C5 ^
+B4B0ADDBEFA078AA497045629840FD965BEEC33D ^
+68F0E43B7DF89F484F3CBD6984C95168142E4A82 ^
+D042BE14A23D0CA1A0466179C119F2A959E1E118 ^
+DD23CC2824A881FDB6566AE6A57B1A2D1624E895 ^
+15B75E7E13B374039B8C9FB4A1122BB8A22FAD6F ^
+849F0D379A2775CCB5EBB0A88839516F30A665FB ^
+8B4125FF2EBFA9459075459C1EE149D68C4F98F6 ^
+1D632D3EEC63D18243FF48702AB894EA05A1AED3 ^
+F2C2E1082004EDCBE3DF96C25D8860C0F5B432BD ^
+4B96C3C284E9E12C3D2F18AB8C8FC6776F30C6DB ^
+F40DC8B94D9FE9910117BCD66F3FFB22F6977447 ^
+D65D126DF604DE306AEB41A641DE0B214449D69C ^
+90FBEFF058E825EB940122B6D8B7492FC574B32A ^
+AE4414AD47216DA0AFD9AD1E22C882F665429C54 ^
+5F9D97E91B7E4810AE765A09803ABFA50B6F64E4 ^
+A2D4E6AF7AFD87E303E867D0E03E1945A0F0B72C ^
+14ABF713982D4DC7C1CCFCE7A48680576082DCAC ^
+BEB8F77A7D211D9451B698D65FBC0B5E38D26086 ^
+B35F660629962D5F1F8529203999FCA0169F2675 ^
+07AC5B04166E739A9FB87FCCA74112AD93A08128 ^
+2D8272C9D620A730561EDFDAF2A129666CEBB5C9 ^
+C25C1971EAB264F44CEE1F44614579EE6D8C7858 ^
+76F8234E2F0A533E810545F79AE28A7C46056AF3 ^
+35025EA09EA111E299814FBC958977DDBC3A2387 ^
+0A2EF548A38D84F6A1CBB2AE01D48D296D6CD8FD ^
+6F546DD1623E92DDA185BDA01618DF7E7E7B82F6 ^
+A0C1C2AED8C3F436DE200E2A3F4C2A9D2DA8DD7D ^
+8DC10195B967FC7FE57B338494C2C42FB43599D5 ^
+0D9192B27851CAA766D90A5376CE255B2FDE906A ^
+7799450D003824356EDFEE1B408AA59E830175A8 ^
+2EA6F3188D3010EDF4EBB55E009CC4D99296F578 ^
+2A73ACB83FB8E25D65FBC1B8085BE67342F5858E ^
+67F9928A27118ECC38EE231E05977A694AD0F7AA ^
+27E2078CC9FDDF5C5DD6CE629F3EF071B2107936 ^
+F50540B4DEE071C64D861872F1E0BC4C7DE75B52 ^
+87DC9AF771F2EE543F96DB0C924AE650A063F854 ^
+76DB885DD797249A4E2F794171DD559FF056A9FB ^
+9AC2E9CD3881BF14D758A7FEBDA81BC9DDD31652 ^
+D3D8595D75AF4D1EEEBEA8166CAFB156E827DE90 ^
+5F7D9D9BD0DDC5A2AD4772610FE2A4923A826486 ^
+F437BB6CFAA9139A1201FEB58841B18C3809F00E ^
+8C3EB402D92E6543D885A9FDE2FC80B9D4340E8E ^
+134307C50C24BBD7822DBA30F644B874EBB54F0A ^
+24774DA4669C2037F7B2A43BCD1C8D574715F071 ^
+69FEF8FBC9034D05F3C9BD9C663D2198AB48FA30 ^
+0390F1C49421806B19DF1F886902F37088DF77DF ^
+DD535B129F482256503AD2744B712BFEB8BF216B ^
+ABEC552E41020144EFE06854149BE03F1BD7F6F6 ^
+3FC8C8A14D1452713E76EDD5EF95C239F3F8A4E4 ^
+8861A84429E238D94E75D3CC191FB4D128215F7D ^
+DBA6377C376AED4D1E79C198EA864B6E6D90C494 ^
+4E5DBF823DC5BFF56C999A1FD0ABBC51155017D3 ^
+6699420C6FF512BE5CABFE1EBAEFB0AE40CDD902 ^
+77CAE0D7EDFD2D13506D096D66A32B9907AB9B23 ^
+F6022F2A1545842915029B344B19F4C69757925D ^
+6ECD085FF34032636E7BE7269D29DA62BC4BFB5B ^
+60CC512BE506BE1A580CEEAD2A009DB8D7A1BBC6 ^
+0F34DFD7EDFA6A5DD132B2EE77B52EEAD98DC701 ^
+1BD542585AB33A0A3694BE45D6C7EEBC266D4806 ^
+1524F20389EBC2D7DE777F96156DF9B2A8652373 ^
+451282E6DA707668886AF7E77DB4C58F73CA6EC2 ^
+BB7D59890BC39F7F87D4DD7E2583C737B2B40B86 ^
+255D67E3AF65376A1D71FFCCF505812481AF182B ^
+4D559BC171516F79E22938DE999685F9FF05383D ^
+2F7EB16081B2338D631153D5B70DE67F050E348F ^
+5902CE6CF7700D2E23CEDEE742E273F4A6A39F6D ^
+7D37A7515D1E04D44CA0F314306919C0307FF4AD ^
+18C215A5B8AA9CA5C55DF8BCFC79683E9982B159 ^
+63520C9DD2CF321388DC89CC69D0D9F6772A3553 ^
+5FA13E6697196EBD0E40FEAED4B945CC93375DAD ^
+BF8CA60D07D1B69767056B2F80A9AC4B1F9FA99D ^
+6CDD13431EB70D9E346102B708E9F8AB233CF959 ^
+4CB448B4131DEB8F1AC3085765303CF214436A26 ^
+1FDC9CC58A748A9478A9E55C66C6446775382ECD ^
+0EDC5CC7CF8C6CB318616D62CC08CD1449960315 ^
+D5D0D540287D21AA519CE90B6E3D81958A2E307D ^
+BA5CCD323B987F54E06AE04A09957BC417ADA611 ^
+26846FD68BA956CEB2899DDC18324843DC211485 ^
+12BD70565F701BB35B87364B47F73C93287E7672 ^
+C57A0F96959C7DEDD353462099EFE380CB273E90 ^
+9900D5268B99165BE1AA2A6B41B9FB66455B865C ^
+D5AC2C2BF36B04EAEF95E8B93958BE28B5A4C836 ^
+82788DAA7F95292B266CA17E86631D866D68FD47 ^
+37B9E638610418C4CE4CF9AAC0D3E64F033D3D74 ^
+9845A156240CE847508A1D3762362FA90216E59D ^
+9E59DC76EA01567183A4B4AD65CD31F169706CA9 ^
+B2B4A1500A176C883268447A09DE920F0CF77F76 ^
+E14FA11B60B9389D3B9B2C1E7C45931992F666AE ^
+922D169C624E79DABDB79B76E777F6994C339EF9 ^
+AE99C2F46A3939CC5EE3F8CF68D6EA486392C23D ^
+154F915F90340CBB03B9514810FD399EED06CE3B ^
+C440E1E74C75266822919080966AB74D96FF43E2 ^
+405155FA99EF5E4A0F4E93D107CAEC89A80B94A2 ^
+0AA9625455A0CCDF37D486B4538E790BE407A59C ^
+46D633F7F2EC56496D53138A56D11D9ABDB701E1 ^
+75C1BD5738EB5380E25EC4FCFCC7BB3FD8164460 ^
+B618C9E52303919BF762D452F5681D23ABFF23B6 ^
+D08BE1F5485939677D294C4198FA15B118938B3F ^
+F931441259B793DABAF082D1B0024ACAD3CB48A6 ^
+096E206E3753BBEEC8F0F0D3F97EBF2EB3063B1D ^
+13AA397D03C60AA4414271D33CAC2361C138422B ^
+777E2979834E8C6E89D219E9109F0A2852961EFA ^
+13960A648DB8B7CF541A56B9009A5F7FBCC1ABAB ^
+B3447A3C462B53945F8295032FC9A057BC301FB7 ^
+8C42386A2436DE83E1959E92B44EBF61E6C8D093 ^
+D9EF91B04DD4371968E1978CBFEDB50C2BABBE67 ^
+E84042479D1D669AB5871B71D1342AD6D15105C2 ^
+4ACD112CD8CAC72DF2D4DA76910C2CD3BE1EC25D ^
+AA20982E2B138FB2407EF99509075CE8366F10BC ^
+5E3BC535BBFF471686885331CD9831C80FEB18CD ^
+53C55C80D64411221C7311654921523D2BD0E227 ^
+3FB8C850B9BC7A923767D036992AD79ED7F0E1AD ^
+AF0BCA4D440D6599BB91396A0823DE64764C2112 ^
+30B13703A702572257D54DC09463768F5AAEF759 ^
+59C44B99EDC297B476402310044554B3F29F9CCF ^
+FED078596C584810E5336545F6F6B93027D9CBD6 ^
+6499E70E5455F9C8FFD2D5F600009A43FAE710ED ^
+D26C0718A9C8222F30D021E8FA6508935E80BC85 ^
+1F4152447ECB8D7CD725B57B65E30F79B466BBDE ^
+6C4958665DDDFC828C1427E57D23359E9C5D1190 ^
+B88EAD843C4897B2A691612B837E5A5D9F58172C ^
+A51097DC1883B160AB799D2D103C443336EAC2CA ^
+5DA1B85BBF4F3912C5E964242A61EBE83A3DA5B8 ^
+4E9A45C0410F0211DD4D9123BFB8C29C53A5E03A ^
+C2B7C89F7DEA6E5A6CF909388471DEC4CA362255 ^
+4EF3B7E7846115212B3E77C29AACA6198422BEF2 ^
+78C74563BB2CF819F83E73CC00072378C114639F ^
+FAF96E836C381EC80FE1EA8AF76E9D8D8AD95FBD ^
+3B30A2BBF84AB70E8220349CBA249DB87FFDCBFF ^
+6CE0CC298D12597F801E0F1BDE66CA9DDF6AE66A ^
+8274B1DB8C0C7390C383C837FDABDEBBEDD1A8C1 ^
+D0F90D63ACD0126C84D714AD7C9EB673DFB459B2 ^
+D1E63EB5C373C78EDF968E0651DC1171907258F7 ^
+1530DC99565BE2B5AE91D1D70B027EDFD4EC6E93 ^
+FEC0946FB9CC04713C67BA36FA36EA9211131281 ^
+BD2BA680D2200AFC5CAFB362A5517BE9DAB7E593 ^
+5FB57E1AAD5BD9C1D176E1CA03C1A5A8E33DDE2D ^
+F6D5E7B1B28C9070115DB6665309B8DDF5F81281 ^
+BFE88F7A0FD5F6A1B26A5E15D0A109A1DA7C1FC1 ^
+E5668AA40375C8CA35FB3046EDD8AD9EDBA82FE3 ^
+C854D5C5A0A100411FCC9189D6307C47B57228CF ^
+1EE384076308AC6B80FB66856D5FA19952B3D6D5 ^
+CAA4DCFEE058D22D726292B2C722D3147F1DCD63 ^
+1887C76092C9275B2DE333014C99FD13E5E533BA ^
+AEAC6ACB4561985DCFF6C9696BE836FBF75E24E9 ^
+CA46F23773B30BF0ABF5C38EB9D0EE021D713F8C ^
+2EF007988B2161FED07E5181C342E724D3F640A3 ^
+F0F1422DFD34EDE00A8B0741F4F395234480FDB8 ^
+2C471BF867F5A02CC241E35D95C97B43D6536E7D ^
+D4906C8804B241E28F3F2E6380019FB739EC8503 ^
+632183EEF8C6EC8EAA3016A43E568DC38E29379C ^
+1808120D461A867C90222469985769AF1756EE5B ^
+08C2F97B6FA6E1433DAF56403CDFE8CEECF6BCFE ^
+2767E111977A20D318EAE19D59E1E551A4AA7F1E ^
+B1A7158CE56666BCD1FDE7DC87B40C92705BFDE5 ^
+7CE90514AD734390F6FE58BAE8FFCD66391E9595 ^
+C57F4C2D8B78DB8464EF1F719B8B1DA270867480 ^
+C97938F34C6DF26BFD509658838F7C35FDB0C58B ^
+A5CAA6946300B1C4B5F53A69AAAD67961C4C6821 ^
+DDF684947B1667A77A22C7DFE8B6A0A8484E2509 ^
+8FB1310F1F215E4EF62C41566C523275BC929670 ^
+1573CC447B398532BFB9A2E5AB3880F23CA7C27D ^
+D6E0B674B9E4D283C0AAC355989CC0E8BBF09678 ^
+7D083BB9C3E005B41FE32629F84B9E292D80FC67 ^
+D3E2591B7D7CD29E9ACE61DF6019D8787AC93BE6 ^
+7159B10AACA9E7610C7404DE961ABFDB17B89156 ^
+B4A0248088E850FFC5CCA99EA2F28ECACBFF1960 ^
+CA63F54FDB6C46E877760EF4E50E56F3164A417F ^
+C41DF52EB252961619BD4861C4AACCF1AB392B69 ^
+FE3EFE453C8705E1CEDD06F15DF5B35A7311DB32 ^
+5E2E8BB04B327E91572992A8A61063F7A76A93FF ^
+8EA0191E8491400038CC5B1416E5A56622EF1E8F ^
+47727D4D7E8D9738608AEEDEB0E12C9F2427EBCB ^
+7340F405BC428DA514E7B2F39728CD77FA2177F9 ^
+5E451C7A51AEBABCEF9FDFBF3538AFECB968872B ^
+528038274803D6DB419F6923993A45C999433336 ^
+281D30FD3C725A4646A6287329140BEA4AC7A5B8 ^
+922A57DBF62C01DA19B89F90F36C433817F089B0 ^
+C79AB225BBD03145A981DBE7BF6FDD16A5E95D8A ^
+301B4D0E270F2AEC6E1372560385D37875EB682C ^
+1EF2EC6A3642C7FD61C4F1C3DFC55302535254B7 ^
+1D94ECF29D2310B1A5A2042CFA616BA0D19E7C41 ^
+52DDA9BEEFAAAE667A6D12BE414FAD8619750040 ^
+B14486D16D1521D1283698E651A10FC14AFF8996 ^
+4BBFBD0244BFEE440DBEDC8361806CADFF673253 ^
+662E0E466C9D700C50C5F98CD77CFECF8278D708 ^
+1AC5B8197B0689681B0F474832F316CD25147AF3 ^
+8720E012F16588A3C368689113902119C9791FF2 ^
+D892C1E257A997A8DF95B229C9D24C99F60EF205 ^
+57F5C45286EC3D29CEC19939C04045D9C38E761E ^
+07151D2EC889D24730AAA5282FA4DFC49A66E439 ^
+6AC94690EA6DB4A8DC982271490EE18282A3B33D ^
+32DD19F12AC0854998C7B14D1D96C15FA8995DBD ^
+7817A25C6CF1EBFAA8DED7A80063D1A299AF8B18 ^
+01C5EAC1830D1F5A7F186E039663CE925FCBACDF ^
+B9F32F67FF4937F44094CB4A62BE12474AC3E1AA ^
+05BE2CD6882447472AD2E02B08590EDED62C7638 ^
+CEF149F6D6FC8987C3693D5F5CCAC0CDDD3D0787 ^
+6A7CC99DAD86DA9797B1F8336356C9864F279D35 ^
+3A72F8EFE64CF60D49589AB92D48301620CEC0ED ^
+F1F5939419E375182A2AA928DAE3CF6C378E4589 ^
+3EC1C1B74B8881F86C1D3EDE42F6689C61132710 ^
+7164A5B4A69A004FD76EA4C6CDFE0273D35CFF71 ^
+224325A309FDF2378C5776B1751BB0694ED30C28 ^
+64E0FECBF5F94517EA9E0F4E1E16FC700EE275B8 ^
+69CDF3321850BB640D5231D3B3458F83738CCE6C ^
+0684349A2ABEC06CE05100EB69D01CD4FB7AB193 ^
+1DFA49225C0FD725046AFCAFED17B1ABA6871FB7 ^
+ECF4B1B9C78A802F748D58BF6E27FAF1B274EEC3 ^
+A44B67EF91F2AAA9EB2DA8B166A1A316886E8909 ^
+CF38B0F7DDD2F72A891B41AD026FCC3282218747 ^
+F917033D4494A1CCC8580C1DBED6F28FEB3E2E57 ^
+3C326F550039F815ECF5E236F6DDE5DB0E2E9F65 ^
+7332001002A11FDAF501914A867398625398D5CD ^
+DEA189DC41AF695109ADCD93906EB5372B512A57 ^
+E0F14BCA9240B27E44647ECEB4A40408E2880DB9 ^
+77545EF84146F952212D9E1FDBAF62243CDA630A ^
+D162F654DEB5BB0D54179319D8DF9F1BB6D8A13B ^
+3BF79007252537CC2EB11E148842E7AC443CA91A ^
+6CB2F291C7198C9E4112B991FD4D829DBAD7EFB1 ^
+C850258036781C0AE8A083D6A791D3FAEC946C99 ^
+DC64C5037BDC93A3D38613D203FB3D7C82A18A24 ^
+620B7714289FD82ABB9FC776B644571F72A9557F ^
+4BEBC1EF44C30B0B033153F883D5C58E4AE6876D ^
+E3815A4E6BF3B50EE312E5A795B3E9AA2D7832AD ^
+9CB13D19C64752209D5D4D7033FAF9DE8960C147 ^
+3182B9F03D0ABA3BD91A1EB8CDD0F465FD9CCB51 ^
+73D8E8B9E6A04E88E29797CC5E2F489350D978A7 ^
+732734CCEC18944BCA784B953DCC0E582225AB89 ^
+A2152DB03048AE27B47C25DDF99D249504A8ADF1 ^
+AB70B32A28D9BFAAE1CA868C4A161B6D4B3A92E5 ^
+AB8B90085B47050B87F4BDAFDF971790B7950900 ^
+B315A8C87011BACA969A1B79EBAC80A7343742E6 ^
+B78A044908CDA9640633DC8BE828E22F90E6D7F3 ^
+AC2BC5246C1BD99231CDCCF3CECDEF5688E58D71 ^
+0679F888F8C353B807F544C2379BB5A4AE8EB9A4 ^
+464B5754E3D42864CC0A98B4E696C827E3254317 ^
+7E5385C8A1BFF0FF476905BB6B7515B6D438CC0D ^
+0F5C968CA2FCB4A17E0AF0B94682B3AC347C2D12 ^
+4F5E353500D63C99F58A28F5870064FA278FC7BA ^
+E7A104651C4D6DFD0778EC8AC8E4F001BC7B9DD3 ^
+23DCF9A854D1D5B5599B14A0E9A19AB4F2E3BB77 ^
+588E429FA1C3055C4DCC99EE5407A64115B54345 ^
+39215ACE01669CADFB81E9FB085710EB5B97461B ^
+23566449DD29A315D413604A2DBCFAE0D40579A2 ^
+1EA87C13DA38FE4C59691D96AF590EAF3908C0F1 ^
+5A6170FC6BD7E8C01140E16F248C56890B51323A ^
+FF328DFB506B72FDB8DF5716E291A1830BC539D4 ^
+7B4DA846F9074254C676F00948BD4C9698148C4D ^
+2AC310393EE1ECC5844A4BEC15A9CFC1B5022294 ^
+3AE36316FA94B369D7320A8B71304CE6490FECCD ^
+7078C7041275BCBE8403DE24D16A646B4462882B ^
+8325A8716A2C879888BA9F674C869B1FF31BF363 ^
+586200B55B5D537B59B5E0BC6FD9BACE1E72C6EE ^
+0B675E7F434756F5E310B80B58F861E789495F5D ^
+749C4C0856CC4629DC397678C0E8BDCBD649A6E2 ^
+25327C66FF46C4466F81EE635E8EC02C5CA60F2A ^
+BD9DFB59EB5E53BA6988734FBE0894194A119D33 ^
+3084040E5ECA5E77406B4DF3CB7F324ACC96B506 ^
+1E14A09FEDB61CEBE255B94F533C4018E5AF4BAE ^
+C8840C051A204F8A13420CF17FE77EEE2FD7945D ^
+4790265B5231F9A1738CB9F8423BEEF219DF110D ^
+354947C0F2F25EB491D21BD0BD1D809FDD140A66 ^
+23762BF3CDF3F484C70D2003B55E6F447BAF46FA ^
+E5BFC99555CED5C1743B152A64AE08C9ED1365D6 ^
+4CB44DC507F716BED4B4CAC742E79E1A2DFA308F ^
+62790EC14E8CFD1A0D6FAF93D7984A1E9416FD5C ^
+5C2D3ED988F5BD9579D2F710D5DD68B11584295C ^
+CF8414ED85FA0135E44B37A8F8B40756BAED23DF ^
+03432064C1C05D28393C9AC5878C9A9BAA6E5C7E ^
+C37A6D64CF81CDF7DBB1B81509A67A0A1BB5F278 ^
+F341D89B75E599048A911D0AE756E0065669B4FB ^
+269E1529285414A74B76586EA4FCECA895C7D1EC ^
+FF9BB39F9FEA1EA63D944BF12ADC98D1D4255096 ^
+DD114F2DF3D92977F9DB98AEC04F367CFF9FBA2D ^
+69B53BB13375F9E123FC30098CD9EDB3C1A1FDF8 ^
+2A60984DC79682E96C29CC7050E1ACF988D9E4D6 ^
+09AC4CA1A40A7D83A463AF0804C4EDA208E09D36 ^
+A2EE2473C270A0637FAAF17DA54237D37E0C6960 ^
+B3A7817ADE962DCEEA7FB6F960EBE2BC1F9BCBA7 ^
+85A46CCE01A7968104496225483ECE2C198F2A27 ^
+BC028F5ECD8773AE47563F1216E0BC36A9E37E4E ^
+C65C40CCC3DD80045D6A4EFF3E9C7D6E4E0E5583 ^
+BD9C189A639FD3D70167367DF61F14868CE7E313 ^
+C6899A84B8E66548BFB50781632CC3D2D1BE8B9E ^
+92F3C8E436227976F32F005469DE91B2363150DC ^
+7D2A80A5C5CC88988F38334AFFE31C04AA1AFC9C ^
+D60FACFA57F663C4A399B1FDDD75973910F27294 ^
+CEEB9661BED2E89DDB07A21EEBF590BB1AD644A0 ^
+0465C9DF2E0886AC79F46BBBEB0A243DF7D6BAAA ^
+98073013597B7AE84CB884BD932E20E6CB47709C ^
+3CB4F76B602BF6B58B316A2D8D169D432F02CE23 ^
+5CD4EB05E8612974BD9C3B19E48D192BE8B96A09 ^
+BB188D5FDE806BD30648B6058143F1802F15FA10 ^
+84EF1D3DE5C1144C2C928CD4D9070A6E79543417 ^
+73BE2AA66F5FD6BF63273EA136350D29491A3305 ^
+53CF3BB07761910BBB486C3C0C643943D5BF17C3 ^
+9A774BDBD27C3704871B52CD5F7F924C8EE4A67D ^
+B106B6582F0F6C9E2EFBC4860CFC7028F2C47F74 ^
+FEAFF44298CBB7517B14B81A6AAD501828C773A0 ^
+B5BB48BED969F15D162301966C537A81C40CF4B3 ^
+3495D7E36747B824D33465B5DB72D6C623EDA72F ^
+D7F49178B43847D9984B923DEAA6DE9571690B92 ^
+3AB7E26BDB0409E55063AFFF456B7A29CF098AF0 ^
+7984E1565BADCD2249EDCA0A3AADB4346104A556 ^
+42DD99B41801B0C347580DF1FDFB2397D55D2A85 ^
+8D59C00401EFB314A0DFA4D82E1D85711C77E246 ^
+50CF74894F7CF5A9F37C37B47327047E910D88A1 ^
+1FC40E2840C4B68F40C205B6BB06C3E106B6B8D8 ^
+A49F56DFC293411736F27C19FA2A362A545C761E ^
+221E48845FE8B3D2C79AFED37414C0D732A69F4F ^
+AFC12E7BDF9F48FAB1B595FD656776A39F0F6CA8 ^
+5EAA114491E88938276FC3ACCDE659623C024BD7 ^
+5081444C3F81E18114B289020D9AEC75FB205597 ^
+D4F69156DE85C61E9B4150AC9F6F6A54F8E193A6 ^
+3D7C7EF4D362DE137AF0625925B36837C1FC7572 ^
+575D772F9C1CBCA8FF38243348E0DFE02643C28C ^
+0C821F27FD82C55CB4D76D386F41DDC92F79493E ^
+C3D0101DDF552A11C8E1EE6BFADB72A983F38571 ^
+F4D650440127390F3A3C2EE991C185CE7650FAEB ^
+54460FDAFEF3022BC2C7D1D497CBE5CED73624C2 ^
+9B3F7B9D594AAF6A26F5C21BD6E4717F46267418 ^
+14E2B34F0B2C89DAE1732400C02E2CA19A767F8E ^
+1072ABC4DFD2FDC6C114314D3C08457772421713 ^
+C9EA4B020C11DEB794D1D05957473A46A906B472 ^
+90BA4272464A020612F0085B7DB9367B7BA8E15E ^
+8713A3997A3CD5DA87E97AB94851B68E748268CF ^
+370358D54C819703E20EF63A2498C8586B48D44E ^
+0DE40249A8B215E98E849008FB7CAE80EC23F4A6 ^
+BBDB96306594D13598BB0109258E488D486D98E4 ^
+DF7DB9CB2FD8A86854C5DEFCE59C4E2F0245F582 ^
+84DE32ED88B3D2BD5F4E33BA3398CD2EC1E9BDF3 ^
+D20967844FED11CA71D28D72B28ACFDB14A7DBB2 ^
+B13A0A6A7723BCD9098E2B04FA04320C4A0E605D ^
+BE66BE38F97E7DDB02EDC8E0ACE97CDF83F034FE ^
+28ECC25FFB394AA8DE18F8ADE8B3577955346FBB ^
+45068B6A0F61D0AEF708AF7D848683DABE817C2C ^
+EAAD829C32C3AD4EAEA8B7E6090A5CF6B2FCAA82 ^
+F445FEB22DF5A9E49E2CF7AAD7CC1F5F72F18B77 ^
+73C424FA0B7863F1F170A850F6A0F85C87820841 ^
+71F0155D40CC55F3D64BEA645608FD184E2543F2 ^
+4542FFCF50267B77502D1A0ED0C2A5050CAD5200 ^
+FB48F26F320D7A4B803ED459BDF92BC1F8703631 ^
+C9F9A37E34BEA6220BEBC167E34B0BAC6B55A6B6 ^
+B0C836CC2831FB8BFE5988360CC39FAA6A904A89 ^
+B0CF783D84BF5383EF30EF2071E0FBA9ABB553EA ^
+8411C8D1A4FC3F130143DEC5232B59BBDDF11B7C ^
+ACB6D9EB22D474CFD5836C8CE22F387E12DC20B7 ^
+D582FA3DE1DC425AE6A394FE5AC321DFE96B9305 ^
+15CA32D0E246F395DE22FAF8F0FD90036C4016C8 ^
+F1832FEECBFFF1330C7A6AC47D6FC1880E79550D ^
+C4846BEA159D1D43427CB5802C46E479F9157392 ^
+C84FF09BA6A2EE9BD1972B8C0BF25240F5A7EE72 ^
+4E6B4F363D7FDB4083AA6F5E7979966FB8FF6C5A ^
+7A543B81CB4DC93081D8CB6AED436A31C4018A84 ^
+85990A1C35B86BA244F60BA0EBD6F6E801552FD4 ^
+D3E07F5D14AE219D3CB59B034764C40056BA95F4 ^
+F4C4DCCC63E8FC5402E93CF50533E51D1BECED43 ^
+3806AFF9AD3859B150F1E2A40FBC047FB624CB14 ^
+B51A4E4FA213D22548CFF28323C6679D2693110A ^
+A7C70C19BAC1040698C7AE6A23B0688B58405153 ^
+E74FD8C457581CD09F75EE3D43485130609FA9B7 ^
+86ED1E49D4CA868934D7C254D3AE0D5BF7323CD7 ^
+A16507DABC3A0CF7137150C4E6F88D5AC9A0AA3C ^
+DDC76D7BA54354112C2D7D31E1A80F0048551E5E ^
+D943F6028146EEB0386BB3084FD354CE86ABCF00 ^
+4ABCAB65C7DAA52BDBD13BCC9098643F5A165329 ^
+D75FE22162C538BA1E2687D66E2923CEC7375E01 ^
+1A11A2B12D93FB030B0C3441D7AAC06DAD6FB527 ^
+F8F3D414C26D09C6CA1B88BE44BE69AC879D3C5C ^
+D2D0BC98795740002B2EB6EA6AECA5559340B54B ^
+A8A3838BA45AB6B05D1D464E8681AD61B136B6A5 ^
+5B162923200439D870F57AEC584A67CA2E8939B9 ^
+A8FE0B55CFB15D977E871152905D8FDB18AA6B59 ^
+02D5D4928969C7A852B5A8AC772A3D1EB424C9A3 ^
+4ECE08DFF1FDE1258B1BF0423E1E31D83C57557F ^
+F701430EF6CB54BF0D138B54FB13A1B586A1CDCC ^
+E3242A71106CB77D25A60D164BD17FE07EAC4951 ^
+D8B18DE86132672EDB330190BE895E3106F92D2C ^
+8CF05FF1387C61A8CC3724BB1283AAD3E2F85EEF ^
+797B311DC2B5D14B5277E49A38A787D3D6A58C2D ^
+6472BC5881A62BA95651DBB3DFF9B3885949C9B6 ^
+86AED4B53D8617FC135D0E1FCB762271B2545A45 ^
+E3C888A1C00301AA7CE203A5590D82C1CE77C6D4 ^
+8A081A7A672F91493AC09D95B29FABD043DA83DD ^
+D47F87022DB4FAE551FF3FA09FFF02D92D112527 ^
+B2271E377E9B158ACBCA1EDAE0ED6BA4C59CB722 ^
+71EDE0C9488A21E62456D06EE393F390478C3F31 ^
+437A1B709176598020EBA1E92386C3979A18915D ^
+E3F4AC4384848071C8A9F9868376D941DEC2A9FB ^
+00444CAF6A3F4210FD97DCB8F10F43B28D890600 ^
+9B6BB350E30CEE209C77A3E20BB6ACE867546313 ^
+935D2688AE2B16B79B517BFB79D48CE7E4F0F4E9 ^
+16B21F19ADE7B6DEE665D45A847491B7F055C46D ^
+853397C3565C807AE72EDFA37F4198E801103FD4 ^
+10992C2FFE5127006BAFB2172359701AB10FA4BE ^
+C82D6BA4BA621E36872ACEE4AE3BDF33C2381B07 ^
+D7852DBC8FF592E08A1F1EE57A70BEFF327D8EBD ^
+CF67308422F072415EFB75B43D5B67C7F5362B0D ^
+30DDF35E1E99243F85311A0994D91B8AA543F729 ^
+DB2FE340F62A89400AE4A16B61435204405350D3 ^
+744980FA26DE503743EED298B966ED5FA8471DF6 ^
+D2C8B803D3DDB54CDE6464D126CE3009A9F0FB73 ^
+885700ECC04EB97943A9C100EB6EC4ACFE59DF81 ^
+770F9CAC5D4E9C878A6636EB0306EE8DDF0CF915 ^
+03C3F0553D7CF16CFE3D3F01C0A4CE26A914512C ^
+93B304BDB138DB6790DFF8A84FFF3D3506770CDC ^
+D5C5FA0488C5A6E14770F216B575997950A94184 ^
+2F695B8EB18C28250D7C8B35BA000042EABDB245 ^
+0353FFA7F7085D3B7888F96B8498486EE7DE16CD ^
+239FE3AAC0D3739F5EEEC82B2BF6F5F47D058548 ^
+16DE8684395CCA8A5DBAC72ECFAFA4BC3DBFC5D6 ^
+AEB2BA742708DBC048B01FD77B1560CD3A23E707 ^
+FAAE178B97175A7A68E51BD7EEC06234723B670A ^
+B3F1311247D920110972772C3DC30F789D3FDBAB ^
+466F682842C07D2C770B41B66A66BE9F6651C046 ^
+39724BD29138F776ED20633B66A3A241FACD817E ^
+5931F19A1985CD5F7171A5D2B81CE1CB3BA8EBBB ^
+27DE5C33A18DF1A731051D6644DE8900E30E242E ^
+A4E1C4F20A34C033589ED0985E80168A28C2377A ^
+9BE820B134475CA31513EE1C79D06E299D70E017 ^
+98F396D147EDF3D3079A6B2DCDDE92D48C9CC52B ^
+D6108901909418CF7E7AECD9E4D1CA121E992E90 ^
+F2E8F0FF1C652356E6056644B81FF8270A07F56A ^
+EA1669ED509120F2B42CFA547A3FD6002FFB862D ^
+219BAB55653B03A3CA7886212DF27B23C082B2E0 ^
+BBE95F8BBEEB6F9A0062D151A7155630F2010B88 ^
+FF6BFC90FE3EAB299892A5D9CA4D17DF2C6C604E ^
+8D0E1DBFCC419AEB1C7827C7649333E34AC7E30C ^
+EF3847F7FEA054F0E080836D0F2BFB676E3573EE ^
+F60A15E6A28A5CCC9C4EFB1B3107A54C9AAEC26C ^
+76328CDE5EFE6961B2CED4E3457D219229E161F7 ^
+FFAF03FB632A042B837F8660412B72B1099394B1 ^
+211BA6675C52CBD9E7F5F5B366A64A2466532AA7 ^
+51E05B7481381358782FDF73CB958E1434CF3330 ^
+BB5CEAD1F3B68227CB032B2B8E5B627461071637 ^
+3EBCF1D78998D4D11C094BF28FD522EA9F5A1E37 ^
+3E7186CB1D39C64CEFD28BDA2CCAA073E71A5327 ^
+415B6A0083386054D3B77026A38654D45D3BA106 ^
+2297372256479E31E139AA16E63C27C207519C0C ^
+65A79FC4B322F655ADCF63432D295349FDCA9E7B ^
+2D1130EE6E4156151C637B46527FAC54D9E79DF7 ^
+80E18DE7C798F040C008B3BFE3054261740E1444 ^
+0710A3A300290CC1C3BAB56CF00A682C1B711BB7 ^
+C6BE5E337A1A976C253CBF356687F359548B6A3E ^
+3D6E4E514277223BADE6A317C478F17EA6EBC9DC ^
+25C66C904C35EBAD2613A30B73283E0FC23CCC10 ^
+125709FDFD511180B08DB77366DC7E5A2B46F0CB ^
+AFB5C53BB272826DB7A1C030B89C7F3AE956F65A ^
+D166E71D8142E26E58E0F7A69C50CF19CFE225FC ^
+426007235D8F06FDCFF20CE7FD00E994F2FC422C ^
+8CA2730163EA816BF9B63CC653B443A8E8BD7656 ^
+BB2DA623B5FD10032BAFA1A2F9FB1E13F74AC4EB ^
+82238EC3C90BAF3227885BE78534A1B08213660C ^
+64BA275EE9422356EAC19A46A4C5C9BDB4D63C05 ^
+4995323B85FD3879631B439BF4F8D7D39639A7FA ^
+41F95B512991A4E05B219479842285900DF8425E ^
+3CEBE929AC763F2FD85F21354C9158E5169A844E ^
+BAD5D53D67CBCD7767B6009546A91D59188DE99D ^
+E9C2909F6F0A3079890193C8772E745A317C48B0 ^
+BB97E31E9B8EAA8CE758DD775D8326F94720E198 ^
+109471A1C3A427C65C4BBAF8C785DB99C748E5FA ^
+751D9CC64F00176E424A1F331C63EAF2910A75CB ^
+27EC395B07FC740569612741E5CF13A9A6048010 ^
+F674BD87556FD0F71D9BF23A0ECCE9F39AC82099 ^
+93B2F9109A25C511865D15E1683C0683555FFC01 ^
+<D
+
+H>SHS Type 2 Hashes<H
+D>
+EFA3EC89797EE3F1A5BE4B8D34747136CA7DFB99 ^
+D146D467E321E4EA4C73E8424029BEA461F3D90B ^
+25ACD32DED334AD20DDCCF01059B6B8B864E8D7A ^
+25416D69665007C3EDD24161F3DF0F6ACBD0E859 ^
+542A29E5C04A5B79AD0986FAD49BE741F09942B9 ^
+5B197E1011286E5C130F9379843DE89776C37C59 ^
+467277EB8887EDE0F2369C6E7D12281EE3B51857 ^
+BC1610204E15A37D533B74412683767898B35DFF ^
+3DC7C4726B3EF75AB89193701C990F86AA6DE80F ^
+4AD4348E5022685C70A2B9806698664C281E7123 ^
+A33E4996BD9980ED505F8AAAF0F6D64E97D7E619 ^
+06280ACC2D0DA15EAD7C963253349C86A6C3C6C4 ^
+33BE29779F42EE504A3CDAE0422F7B9C5CC994DE ^
+412941272C5CE344AC144B69D4BA5F61F1474F4E ^
+C33ECAC1FA74D54685669F8B9F85918471A88D60 ^
+C48272E42F921A2749D60418965D8A7CB1C7BF0D ^
+44ABEEAD2C278098062D934460E565ED3C646880 ^
+08DF185007816E3EF01D6226C72B03256478F23F ^
+289E89F8F15DD709701AA22B12C69E8F90C93F1D ^
+5B93CAB369C99B85EEE3130F833B7BB06D4FC041 ^
+7B2872C58FB340C9A1D068B618E4980B04FDFF2D ^
+62783421CF58EA66366ADDCBFA96968FB1369918 ^
+C8BD732D0181051698160B2FBC2025476297C96B ^
+038D587CC069C9B89DBC2FE9D86A98C031D340B9 ^
+3059031A68585DA8F09B87B0BE3413987EB390BF ^
+1B74A4A95713083609B27E67140708EDA15F80B1 ^
+6EACEA69922C7ACE38E0560A91DA459C0CC89B55 ^
+60E21F5299EC719D2832A82268B24AF6B2815DEB ^
+3D7D51782A532F4F410AA2AB3DC9178C21A55F0A ^
+B2423D96008FB800E5E35E19DA6BEA27487585E0 ^
+5038FE9AEAC82966A4EE5CC69ACC8ACCF55E63DC ^
+90BF0A90F88F5F1DA51E4494E2D5D4C6250D2D4B ^
+F858434E0A5FD61A220CC792380801D19E0D9F77 ^
+C31E0BB45FF1DC0DE44C77C53C59B15C3BDE9EB4 ^
+DF5628CF6445C409B51F46A86488A95DD34A3DA5 ^
+744CDCC9A51B1AD14FAFD673D4104433B7A24739 ^
+CEA5E7B91773DFE13649ACA78907769B5BEBCA1F ^
+DC23EC1A04F7417D9704B844E9F39F39EAABE6D8 ^
+D39DDE97297B7D1C9FFD6B6733349D0B8E802688 ^
+65219E79F5A3C61FC075660258A9C5F13A159271 ^
+D2A86164D1366B60F146651464761B01353F9028 ^
+8E3D1E4E0438EABC58AB967B1CDDDAE3CDD9B078 ^
+EE9BEEC73D0E760CFD05CF62382A461C7DE3CE2A ^
+5C4FDD604751596BE5419D4AC256C3D982012149 ^
+43ECD0DE83F087815CF257982914611E4BFF698C ^
+1A1BCA41BA127DF4264D3795E2EBCEDCD1BD8EC7 ^
+FF82BC6904520E186803FFE861DCE7E566D75F03 ^
+764546FFA014DF8278974BE66D01485251B8B0CF ^
+A06BC97DACB07EF207808684978841C425AE1238 ^
+6C7E6E0E89F2A070EDF3C4333353869942F3D883 ^
+572437B2B35C5BA00EBC74521B12D20E6F14ACBC ^
+08703186E74A9397CEBB1B2034A6770995AF3D0F ^
+E4F9055356AABA933EEF0C0B07B6FCE90361D208 ^
+2020203EFD4C5FFA02E593B7A658024B33FB368E ^
+2BB2F32D64ADA56A3E53A6D750A05F8D2B5D7A7D ^
+C719AEE4708E7A242440C9429B7236DFDEC02B4B ^
+924A26B46649287197E142CB42506C96E309EB26 ^
+0463F94B5452A2D8BA3A0DBFE9C490A371C19975 ^
+9FB2FE5393238EAAF58034BC934B190784A10DD3 ^
+AD4A6962A6A59CA32789AC3BBA368583B9122AF4 ^
+2A89459657F9E2685D794E7AEAF30A05B06AA573 ^
+9B65CB91D0A24773AC8675FE9862E28A7B84954F ^
+9CB7CADEDD391A3689B04427B461C4113717B6C8 ^
+F1B922D7EC240FC99692EC28C1A6CC7D907B1018 ^
+DE301A1413C36A5CB891FBCD9CF9258DF4EF14A4 ^
+B330738D2AD53448C287BEEFE5C5583F2B817A03 ^
+B80EBE0104A25840CAEF6AD74C4676D524571A29 ^
+3B5CD01661A279BA72DFC1272E683573B4F16DCD ^
+1412D6A2DBBC9D00641A71164A690C640852B56E ^
+0EF514429CAC95CDCBE8A2E60C2AA8B892AC5B33 ^
+5F32CFF3B07D47EC13EB54E7C39E4F5216FDBDC5 ^
+B931966169D171DE8F9488E8B5E0960124BC7451 ^
+E5034D3A5A573442781EF0C6EEA7BD39FAD0B94A ^
+F97CAC5013135944FDF8BDCF02B4CC61241BEA6A ^
+FF74C93CF32506B4E17A0B596AB564989F20F1D4 ^
+5CA42E33BCE4301B8FBCE56BFBDB43EF79E956D8 ^
+87F5D981EDFA01A2E9885BD52CC4E649A2330621 ^
+63F43844ECDDF338203DFB116FA79CBAF4E5C92B ^
+92C5E2A5D380D2BB5E19E9E65DC9A77F4B8B25F4 ^
+E3D78501969ACDD78A71042E7B0BD0C14882E402 ^
+4E1FD6F5CFE29A0E33248F2E2EFB74E7E0A99765 ^
+5FF5DADC93B2E452A60677C8CD0CBAF7BD4895E4 ^
+CA490FAA2D6723F9F682D5C96586460D0C8B2010 ^
+94F099C2FF7DB694FD2DCF5A9A6B06855B2A9948 ^
+CF3B1E0DA7BE87180BF1847DEBEC706788C53B8B ^
+F85305C4BF149B92068D363EF19B914DB90618DA ^
+B4BAFCA3176B80E9800E319FB3BB74E5D65BEB64 ^
+38CCF51915A38559A96E6F3258148D5E63230984 ^
+6FF43B0D25C7171FF178DEAB13D7F488D21C4216 ^
+3E4A034152D86E4568A2197A5328E8E97363287E ^
+F231D4C3ABBE0FDF77C71EB2C28E50ACD9584537 ^
+23E1A4F73F288233847E647CF8623289F1F89E55 ^
+726DAEAE724E79232611CBB216B7722594E814FB ^
+0E5FE512B0AF52B4183119508CB01AF5338C63E3 ^
+4A5D3E12EB29B224202C0B319B086535E99F5E32 ^
+363574A910830EDCFDAED1055975F0613D1B5C95 ^
+4820BE6C74AD34D8A43A5DD0130CBDE3F890C53B ^
+FEB6E5BF7A66ED9B838A10305F850052DDF9207E ^
+D50B331AD6925545264B6614C3B4C39375AB1F65 ^
+36B1BF39BF4AEF05FB054BD02FAD9062D2337239 ^
+<D
+
+H>SHS Type 3 Hashes<H
+D>
+9B30CAFDD7F5E525221EC036D55A9C8D78294DBD ^
+9BCA33B3DAD2201D0F1981CCD0AF4874E162A6DB ^
+8B06697E4A75DA5F020CEB860A29040B3DF6EF21 ^
+F0D48401AE22498E281CDAAF045FFEBAA87A9776 ^
+6247DF62DF5D4857A795996039B5A6271F7A2031 ^
+D98433C3372F1405FCC2475959B9F35DF27D32E9 ^
+C4D14B2873B0BDF01CA7C1628EE01D61682CF1C8 ^
+C027A9C010F8EBE89FC88C1C9FB68DAB09A0CFCD ^
+4D8D19F35FAECDEB015E116130A0A4C836A42A6A ^
+928E2E95D3F09D8EE63CB8F10296EE6EF7455FFF ^
+55F3E770DCA28CFB711D059174CC7A9EC2B2DD7B ^
+4500987086FD8C275330E0F27E8A3ED8596D01AA ^
+60BC57D16F50E2ADD1724E0C7DDD5E47DDF8E300 ^
+59D174272AE602AC092EE7EF393AC19B87B8E865 ^
+8C25614E6E4D825D6AEDD93A62D1A0458583EE84 ^
+695390D1E57BCC4CDD442879F0978BD823322E5C ^
+6F353EE6B5F4B8272E4A0D3D4BBCC83B1B942516 ^
+4B3F671874220DCCF49B580189E6B13FFF0F531D ^
+BC6C473B4824D8E2FA04DDA86A5865D4A36E8E91 ^
+1BFEC269FD18D25DC5C56ACD83810022775F3EC8 ^
+3E9921E2F685413C0AEA64801945B48CB76E195E ^
+EEC7221FBAC5F27B56CF68C396B7EBBCAA3C0B05 ^
+F86DDD2A8229532C3F183EA9903AD228A2521593 ^
+FA17B5DF33E4326BCDCB27F1CE8B83BE8B8EF890 ^
+A4AFC0B41D30CE796C2B4B06E368A5D390735889 ^
+745AF12B4EF985E4D2F848D7C7ADB6B32404B6E6 ^
+5CE4B657409033BF67DB7B0CA480EC2ACCA801EC ^
+0B5AABC9D3A8E861103D6B5B9B994F9C743BF058 ^
+86A1198983A73298BF4EB41A61EAAC3E4B06B408 ^
+460A107A6AF329B330DE9425B3077755553AD370 ^
+62C81D06AFE8C8F3E642AD42374FFE486DE86F2F ^
+FC1EECA32F7E434BBC74F4360808EDB141087BDC ^
+BF494B4E8D3311F167B1EAAE58A3343683F337EE ^
+961247D01E1C4CC0D71307637CD559D530521FD5 ^
+B34F846411BE61E15361922E0E2AF83F3F03B291 ^
+CD845B240FC2551DCB2CE487646648CF249AE8F0 ^
+5C124B615FAC548DAA35AD0287E032EC77D220BD ^
+3C74771D838CCF7FAE2DAB100CEA7B46BE2FFF3F ^
+62860DB8C0C897C7369A1AB61747B04C0AE9F8A6 ^
+C98400CDD7FE71C7B35488C16D3395C04300EDFA ^
+95167E2BBFC0349C0DB7CB7BD2030BC30F9F286A ^
+9F835DBB27076B5F0D8880603F417CE83A0D2242 ^
+08442B715C84B7A8B2C7FFB46010AE56A0C8C05D ^
+B7132DBA522C54F42903CAEB705167485AAD30B0 ^
+9E99F03ED08374EFA4F9A26551A909F40BEE503C ^
+999977E6AFFAE0451E93E7F77C7D177DE121402C ^
+30E0BB7F21433A348E3B446F08D80CEAAE06DB71 ^
+B3A41EEDF017DA7B20FBD9111BA6E2E59842CED2 ^
+5B9CA331BD03D97E8D057DFD35C9E600F90C57DC ^
+5338A25B31CC9C64552B6F6742F9FEBDC13D9733 ^
+1B3A55BF6FD748B3B650EA5BE839B61530C871C0 ^
+1503F21523CE8BC5A19E6A7F5CB0EC34A7E9F75C ^
+7F6A16B30377D3D0014B0B0B4C8639160C721DDB ^
+8F621F8CFB6AF216746D8B99C913267DB14ADB08 ^
+42E9177C487B4B711A4451C360BD7E2C6DA73446 ^
+5B2497CA6EC2426B12653D711E6BFDBEEFD4A389 ^
+30F4690FD4F09AC8E29B926F64C673539D7FB65D ^
+CE12D1AA4961245E606097B672EC3E16103D0D16 ^
+9BE5D693BC0CC56B34B8DDB92FACEC2F8F4B638A ^
+D2040005AE230EFDAE95942372607577EFA5DBC2 ^
+8A920F9407C74FA37D9C93C3606B996DB945841D ^
+F26915C08DC1D3D31D9CA73F18F04DBB57E8A672 ^
+E449381C8148837B9E44251B17825530D8754C94 ^
+BD8402B21520E40E31D1EAFD9C99A9E409C3A77D ^
+624CCE538A78CF0FF788B9BE433A008FA7779280 ^
+B796B521B90D55396E8EC02AD9B69B7E91093E4C ^
+5C4D584F97C1D8FAF810CEF3A4CA0915FB0B630A ^
+A179FEAF341BA97B1D0278822ACCAE5FCF8F4ADE ^
+693DCF85919E06A5423F92780E79C2C0C4528D67 ^
+DB94BEADFEA3682051D622519AF9F87BAB28C5F9 ^
+2E20D1925FBD460E7A5E6B48A92964A7DDCB874F ^
+86651FD71862CF72F01F099F68CC164DEF0E9625 ^
+D5948BDCA91D6707015C79BBC2BC74C1B60573F5 ^
+8870B8A6884FF54E0E400441FB2EC74F2452F39C ^
+7DF1C3C052E8396D251E9D522C4227344DF92C11 ^
+59A290A0BD41B973DEE35947CB240006DBCEC582 ^
+DD0EDB3AA60CDEBB85DC01258B9F49F3A5E83589 ^
+FC6794E4B4F2735773A195F9BB2022C70AA4C754 ^
+8BBC40A02D87A8CF14D6CBA0A2C9857D93EFDEFA ^
+D28FF6E2366097135EE565F10263E8798140C5DC ^
+2E4289EBE02E75E53B52D6724CDC16B89ECF3DC6 ^
+F2E716831CC0CB5CB2A623197D14C2C9FC25A914 ^
+47B926A13D65377A8E2AF27A84E175BE93739E38 ^
+D368B8ACC50353EC8070936C73242A2BF6CEC3AA ^
+8556025BED695B975CB924DDFB372F6899A7B09D ^
+9B4ED89E63D17B7210A3FC1BBF0FDA607694F5D9 ^
+0D2221F5CDA184EC7F6CCA29A75F502FCA25673A ^
+3C152CCB811DD9BC16529B23DFA1757D744FE676 ^
+48D1808CD62F868FB6F45560137CFB1DFD856266 ^
+8A3FA42A984C95CA75D6AE51391AAAC0688C2ABD ^
+AB570D91E9B6F3F1188DC8639A3B144837EF1ED8 ^
+673F62A7D205D5C90B7454E81A5EDA9A60650D91 ^
+D00575E45FA324FA05142359BC3A07C803836EE4 ^
+B908BE44A2A66F7370DCC022378A9C2F9BA70B38 ^
+1EF79029F88E7A091D6F2FA2F44A96829C120C62 ^
+491CB2EE0994EE6A4FAC59C4B9FBC9CF8183DE8C ^
+CEAAC4E211E7DDDCE3931C47ACA3D626B62E5054 ^
+BE2041CB55A4882A8335A46B744ECB8611336F5D ^
+E4C0BC6857AFFE0C2B77B38FC01829B44247B6CC ^
+122A6AF11DEB6C3B97E6ADF5E077B5D6363887E3 ^
+<D
+
diff --git a/dbus/test/data/sha-1/bit-messages.sha1 b/dbus/test/data/sha-1/bit-messages.sha1
new file mode 100644
index 0000000..3dc6bd6
--- /dev/null
+++ b/dbus/test/data/sha-1/bit-messages.sha1
@@ -0,0 +1,4009 @@
+#  Configuration information for "SHA-1 Test"
+#  SHA tests are configured for BIT oriented implementations
+H>SHS Type 1 Strings<H
+D>
+0 1 ^
+1 1 1 ^
+2 1 1 1 ^
+3 0 1 1 1 ^
+2 0 2 2 ^
+4 1 1 1 2 1 ^
+3 0 2 2 2 ^
+4 1 1 2 2 2 ^
+5 1 2 2 1 1 2 ^
+5 0 2 2 1 1 3 ^
+4 0 3 3 3 1 ^
+5 0 2 2 3 2 2 ^
+5 1 2 3 3 1 3 ^
+5 0 3 3 3 2 2 ^
+6 0 2 3 1 2 3 3 ^
+7 1 3 3 3 1 1 1 3 ^
+7 0 2 3 1 2 3 2 3 ^
+6 1 2 4 3 3 3 2 ^
+7 0 2 4 3 3 1 1 4 ^
+8 0 2 3 1 1 2 2 4 4 ^
+7 0 2 4 2 3 1 4 4 ^
+9 0 4 1 2 1 1 2 4 4 2 ^
+8 1 4 4 1 1 4 2 2 4 ^
+7 0 3 3 4 3 4 4 2 ^
+11 0 1 3 1 1 2 1 2 4 4 4 1 ^
+6 0 4 3 4 5 5 4 ^
+7 1 2 5 2 4 5 4 4 ^
+12 1 1 2 3 3 1 1 1 4 2 1 5 3 ^
+11 0 2 3 3 3 1 2 2 4 1 5 2 ^
+8 1 3 3 5 5 2 5 2 4 ^
+9 1 5 4 5 1 2 1 5 3 4 ^
+9 1 5 1 5 2 3 4 4 4 3 ^
+12 1 1 2 5 1 1 5 5 1 4 1 5 1 ^
+12 1 5 3 2 1 3 2 2 2 1 4 5 3 ^
+10 0 5 1 4 5 5 4 1 1 3 5 ^
+12 1 1 5 2 3 1 5 1 3 3 5 1 5 ^
+12 0 1 1 2 3 2 5 1 3 3 6 4 5 ^
+11 1 3 1 5 1 3 4 3 1 5 5 6 ^
+8 1 4 6 4 5 4 4 5 6 ^
+10 1 6 5 4 3 3 3 2 6 2 5 ^
+10 1 2 3 4 4 5 5 2 5 6 4 ^
+13 1 3 1 3 1 4 1 6 6 5 1 2 6 2 ^
+10 1 4 3 3 6 6 6 3 2 6 3 ^
+13 0 3 5 3 1 4 1 4 3 5 3 4 1 6 ^
+10 0 2 5 5 2 6 6 5 2 6 5 ^
+12 1 2 2 5 3 6 6 4 3 2 4 3 5 ^
+13 1 2 6 3 6 5 2 3 2 1 2 3 5 6 ^
+13 1 3 5 6 2 1 1 6 2 4 5 4 5 3 ^
+16 1 2 1 4 3 2 3 2 5 3 4 1 4 1 5 3 5 ^
+11 1 3 1 3 6 7 7 4 1 6 5 6 ^
+12 0 2 5 2 7 5 5 4 2 2 6 7 3 ^
+13 1 6 4 4 1 4 2 5 2 4 2 7 4 6 ^
+12 1 3 4 7 6 7 1 4 4 3 2 5 6 ^
+16 0 3 2 4 5 6 1 1 1 5 3 4 1 4 4 5 4 ^
+14 1 5 1 3 7 6 3 1 3 7 3 1 5 7 2 ^
+14 0 1 5 3 2 7 1 5 5 4 6 5 3 6 2 ^
+14 0 4 7 6 6 2 3 5 1 1 3 6 2 3 7 ^
+13 1 6 4 6 3 7 5 1 4 5 1 7 4 4 ^
+13 0 7 5 3 1 4 7 4 2 2 7 5 4 7 ^
+15 1 7 3 6 1 1 2 7 5 1 5 4 6 1 6 4 ^
+16 0 2 5 3 2 7 2 3 5 2 1 3 3 3 7 5 7 ^
+18 1 3 7 2 4 1 7 3 4 1 5 1 5 1 1 6 1 2 7 ^
+17 0 2 1 7 3 7 1 2 1 4 3 6 6 6 2 2 5 4 ^
+22 1 2 2 1 1 2 6 2 4 1 1 3 5 2 3 4 5 6 1 1 2 6 3 ^
+12 1 7 8 7 2 1 3 5 7 8 7 4 5 ^
+15 1 3 5 5 2 2 2 7 4 2 8 7 4 5 5 4 ^
+16 0 1 4 4 6 1 2 7 1 6 4 1 8 4 7 4 6 ^
+16 0 8 7 7 2 5 2 1 5 6 1 1 5 1 5 6 5 ^
+14 0 7 3 2 3 8 3 3 8 2 8 3 7 7 4 ^
+14 0 4 2 6 5 4 5 3 8 8 4 8 2 6 4 ^
+14 0 8 7 1 3 5 8 2 8 1 4 5 2 8 8 ^
+16 0 5 5 2 2 4 2 4 7 6 1 5 8 3 8 7 2 ^
+16 0 1 6 6 6 6 4 2 2 6 4 2 4 4 6 7 6 ^
+16 1 2 3 7 4 1 7 7 5 7 2 4 7 2 6 6 3 ^
+13 0 7 4 8 6 5 7 6 3 5 7 5 8 3 ^
+16 1 4 1 1 5 4 3 6 5 5 8 5 4 8 5 3 8 ^
+13 0 7 4 4 5 8 3 8 3 8 6 6 6 8 ^
+14 1 5 4 7 5 8 4 6 1 6 2 7 8 6 8 ^
+18 1 3 4 4 5 3 4 1 6 3 7 6 7 3 3 2 8 4 5 ^
+19 0 5 8 1 2 1 3 5 3 1 6 6 3 7 4 5 7 1 4 7 ^
+17 0 5 7 7 2 2 6 4 7 1 7 8 1 5 3 2 7 6 ^
+14 0 9 3 6 9 3 4 7 6 9 1 7 2 9 6 ^
+21 1 8 6 5 2 2 4 3 1 1 6 2 8 4 2 5 4 5 1 2 5 6 ^
+16 1 2 6 5 4 9 8 1 8 1 7 6 7 7 1 2 9 ^
+15 0 6 9 5 4 7 1 7 3 9 4 7 7 5 2 8 ^
+16 0 1 7 8 2 7 2 9 8 8 3 4 5 2 4 8 7 ^
+16 1 1 6 8 2 8 1 6 7 7 5 9 2 9 2 8 5 ^
+16 0 4 2 9 6 2 6 6 7 9 9 1 9 4 1 5 7 ^
+18 1 6 9 2 7 2 8 5 8 4 3 4 4 6 6 3 1 6 4 ^
+19 0 1 7 4 4 4 6 1 6 3 9 5 6 4 7 2 2 5 5 8 ^
+17 1 8 5 3 7 3 5 6 4 1 9 2 6 5 7 9 1 9 ^
+18 0 8 8 6 3 5 3 3 5 5 3 8 3 2 5 5 4 7 8 ^
+16 1 4 7 7 2 7 3 8 5 7 5 6 8 5 2 8 8 ^
+19 0 3 7 2 3 9 5 9 7 7 6 5 3 1 1 5 2 3 9 6 ^
+18 0 2 4 6 7 8 1 2 9 7 2 3 5 8 9 1 7 9 4 ^
+21 1 4 1 8 3 3 1 7 3 5 7 4 1 8 3 6 3 5 7 6 8 2 ^
+17 0 4 8 3 7 9 8 6 8 4 2 8 7 2 4 4 5 7 ^
+18 1 3 9 7 1 4 5 6 9 2 9 1 3 8 4 7 8 7 4 ^
+25 1 2 4 8 1 7 2 7 5 5 3 2 3 2 1 2 1 1 2 4 2 8 7 8 7 4 ^
+25 0 9 4 6 5 8 1 1 1 3 2 1 3 1 1 1 5 3 3 6 5 7 4 5 6 8 ^
+19 1 7 5 6 6 8 2 4 1 8 7 1 6 3 4 8 5 8 5 6 ^
+19 0 6 1 2 1 7 1 10 7 4 5 1 6 4 6 8 7 10 9 6 ^
+16 0 10 10 5 5 9 7 2 5 4 3 6 3 10 10 5 8 ^
+18 1 2 3 5 9 8 5 10 6 8 4 2 2 4 7 9 6 9 4 ^
+18 0 5 10 3 1 4 5 4 6 8 3 7 7 7 5 9 2 9 9 ^
+18 1 4 9 7 5 4 4 10 6 9 3 6 6 8 6 2 4 6 6 ^
+17 0 5 7 4 8 5 9 10 4 9 1 4 8 6 6 5 9 6 ^
+17 1 3 4 8 9 1 5 8 10 5 10 3 8 1 6 8 9 9 ^
+18 0 8 3 6 1 3 10 3 7 6 5 9 3 10 9 4 6 10 5 ^
+16 1 9 1 9 6 5 7 7 10 9 6 1 5 7 10 8 9 ^
+20 0 6 4 10 10 4 3 9 8 10 3 3 5 2 1 8 1 3 2 9 9 ^
+17 1 10 6 10 6 8 3 6 7 3 10 8 6 6 4 4 9 5 ^
+19 1 9 4 3 4 7 3 8 10 2 4 10 7 6 10 1 3 5 7 9 ^
+21 1 2 2 2 3 9 2 8 3 9 3 7 7 4 9 9 5 4 2 6 10 7 ^
+17 1 5 9 8 8 9 10 9 1 8 3 10 2 7 2 10 4 9 ^
+23 0 5 4 10 4 10 7 8 3 1 1 3 4 2 1 1 10 2 1 4 10 10 10 4 ^
+19 0 9 2 5 7 9 6 7 1 8 9 1 2 1 10 8 10 4 7 10 ^
+22 1 2 6 8 8 9 7 2 1 3 3 10 6 2 6 2 6 5 2 5 10 5 9 ^
+22 1 8 7 8 10 1 6 3 7 4 5 5 5 1 9 2 2 5 5 2 10 9 4 ^
+21 0 1 10 2 6 10 9 4 3 3 7 10 2 9 6 10 2 1 5 6 3 10 ^
+21 1 8 5 7 10 5 6 7 3 3 1 2 9 4 8 6 3 9 1 7 7 9 ^
+22 0 5 5 6 5 2 3 5 3 11 4 5 1 10 6 4 11 8 3 6 5 6 7 ^
+20 0 2 1 9 9 3 6 1 8 11 6 7 11 6 1 10 6 7 5 5 8 ^
+19 0 4 1 7 10 4 8 10 8 10 4 11 9 6 1 4 5 6 11 4 ^
+19 1 9 2 4 11 11 11 7 1 1 6 8 1 9 8 5 11 5 4 10 ^
+20 0 8 3 10 1 7 6 10 8 2 9 3 8 6 8 9 3 7 5 1 11 ^
+22 0 4 5 8 4 10 6 5 4 5 3 3 4 1 5 9 4 10 9 6 7 3 11 ^
+21 0 6 5 8 7 8 11 2 1 11 10 3 3 2 9 1 3 6 9 10 10 2 ^
+24 1 3 1 1 9 4 2 5 7 3 10 11 5 6 7 1 7 7 8 7 2 2 7 4 9 ^
+23 1 9 4 6 3 7 5 10 9 8 9 3 2 1 7 2 2 7 6 2 8 3 6 10 ^
+22 1 7 10 2 10 5 1 8 7 7 3 8 6 6 8 3 2 11 6 3 4 7 6 ^
+20 1 11 3 7 2 10 10 7 5 2 4 3 5 11 3 11 8 9 5 5 10 ^
+19 0 6 2 6 8 5 9 4 9 10 9 8 3 2 10 11 2 6 11 11 ^
+20 1 8 2 4 2 7 3 9 9 11 8 2 11 4 8 4 8 10 6 9 8 ^
+21 0 6 10 10 7 9 2 5 11 9 10 7 3 1 4 5 4 10 1 2 8 10 ^
+18 1 8 11 6 10 8 9 11 6 7 7 2 6 2 6 10 6 9 11 ^
+21 0 5 11 1 6 8 11 8 10 5 10 3 7 8 9 9 1 1 1 10 2 10 ^
+25 1 5 10 2 9 9 9 7 2 2 4 6 1 11 7 3 3 5 5 2 11 2 5 5 10 2 ^
+21 1 1 8 1 11 6 9 3 6 11 7 11 8 6 9 4 4 10 7 1 8 7 ^
+23 1 7 7 5 11 1 4 7 11 11 11 9 2 1 3 8 2 8 7 4 5 2 5 8 ^
+24 1 4 11 5 10 7 7 9 5 1 5 6 2 9 1 5 7 9 9 11 1 1 3 1 11 ^
+27 1 10 4 6 8 5 7 11 4 10 8 6 4 3 4 4 2 1 1 3 3 1 11 2 3 4 10 6 ^
+21 1 7 11 2 7 10 10 9 10 1 3 10 4 3 11 10 2 5 3 9 11 4 ^
+22 0 7 9 10 9 5 2 6 6 9 2 7 4 9 8 4 9 2 5 9 8 10 3 ^
+21 0 12 2 6 12 7 9 3 5 11 6 11 3 5 4 4 11 10 2 1 10 10 ^
+27 1 1 4 12 2 10 1 6 5 5 4 1 10 3 1 12 3 2 11 5 1 4 6 4 6 11 11 4 ^
+22 1 8 9 4 8 12 5 5 9 3 5 2 3 4 12 12 8 5 3 1 9 10 9 ^
+24 0 5 12 8 6 2 4 11 11 2 7 11 9 4 5 2 1 8 3 10 2 5 2 8 9 ^
+21 0 3 7 7 7 5 9 11 5 9 11 2 9 7 5 6 11 2 12 4 9 7 ^
+26 0 4 4 6 4 7 2 4 2 5 7 2 6 11 5 9 8 2 5 10 2 10 8 8 5 2 11 ^
+23 1 3 3 2 6 9 10 5 6 8 5 8 11 3 6 10 4 6 9 2 11 10 3 10 ^
+25 1 1 3 12 3 7 4 5 5 3 8 9 2 4 8 7 7 9 1 9 11 4 5 7 7 10 ^
+20 1 11 9 8 10 11 1 7 12 6 7 4 2 12 12 2 3 9 10 8 8 ^
+20 0 12 11 1 4 10 6 10 3 9 7 12 4 11 8 4 6 12 4 7 12 ^
+24 0 8 6 4 8 2 2 9 2 9 6 3 6 3 3 10 12 2 7 8 7 8 12 10 7 ^
+26 0 5 11 11 7 3 3 9 10 3 9 3 3 7 2 9 9 1 2 4 12 2 5 5 6 10 4 ^
+22 1 12 9 10 10 12 12 7 8 2 7 1 6 8 2 8 7 6 3 1 1 12 12 ^
+22 1 11 10 2 11 10 8 1 2 8 12 8 3 9 5 7 9 8 7 11 1 10 4 ^
+22 0 10 1 8 6 12 2 11 7 10 4 10 6 5 7 10 11 3 3 8 8 4 12 ^
+26 0 8 5 5 12 1 8 6 7 6 11 8 10 4 3 7 6 1 5 1 1 9 1 5 8 9 12 ^
+21 0 1 12 4 11 12 9 2 12 12 3 12 5 4 12 4 1 5 8 12 9 10 ^
+26 1 5 3 8 1 11 4 7 3 3 10 4 9 6 6 4 3 9 11 1 3 7 10 7 9 6 11 ^
+23 0 7 12 3 5 8 9 7 10 8 11 10 11 6 1 8 1 1 6 3 9 8 12 6 ^
+25 0 1 5 5 6 5 12 1 1 1 11 9 9 3 11 9 6 1 11 3 1 12 8 11 11 10 ^
+22 1 10 9 7 3 10 2 6 4 11 3 11 6 4 5 5 11 12 9 7 8 12 9 ^
+22 0 8 5 10 7 12 8 3 4 4 5 8 9 12 6 8 10 6 7 11 4 8 10 ^
+26 0 3 5 3 11 11 2 1 9 1 10 4 4 6 9 4 7 6 5 10 10 1 8 9 9 6 12 ^
+24 0 12 11 4 10 1 3 7 5 11 9 11 7 2 11 5 4 7 8 1 6 12 7 4 9 ^
+28 0 1 12 10 2 2 2 4 9 11 4 11 7 2 4 3 11 7 10 5 10 5 5 3 5 2 7 5 9 ^
+26 1 4 1 4 2 13 6 11 5 6 8 5 1 5 6 3 8 1 5 8 9 9 10 12 13 12 2 ^
+26 0 12 3 1 11 2 12 6 8 6 8 11 4 11 10 9 6 3 3 2 2 2 13 2 1 13 9 ^
+22 0 3 3 12 13 13 7 12 2 8 11 9 10 10 1 1 13 11 13 4 1 11 3 ^
+26 1 2 6 2 8 12 3 7 12 8 9 8 3 12 7 4 9 2 6 4 9 9 4 8 2 4 12 ^
+24 1 8 11 11 3 13 2 10 3 10 8 6 6 4 4 13 4 2 4 8 1 11 12 9 10 ^
+29 1 1 2 5 1 1 10 3 2 4 9 11 8 2 5 2 8 10 2 10 11 7 8 12 6 1 9 8 4 12 ^
+23 0 6 12 7 10 7 7 13 2 2 7 10 2 8 13 10 7 11 2 5 9 11 13 1 ^
+25 1 3 11 2 10 5 11 5 7 10 8 10 1 10 3 11 7 9 5 3 3 4 5 13 12 8 ^
+26 1 5 13 9 4 3 3 4 3 13 1 6 11 10 8 13 3 4 11 9 1 9 1 7 8 7 11 ^
+22 1 1 3 13 8 11 3 4 10 10 12 7 2 11 4 7 7 6 13 13 9 13 11 ^
+26 1 7 9 7 8 9 9 5 1 13 3 3 4 9 2 1 8 9 3 9 12 8 10 10 6 11 3 ^
+23 1 3 8 12 8 10 4 3 8 5 5 7 11 13 11 12 11 4 12 3 6 5 11 8 ^
+27 0 3 10 9 6 9 7 2 10 4 4 5 5 2 12 13 5 3 1 10 1 4 7 8 13 13 12 3 ^
+30 0 2 6 5 4 7 3 10 6 13 6 3 9 6 2 10 5 3 8 4 1 11 3 5 3 7 11 1 12 9 7 ^
+29 0 5 2 13 6 5 2 6 3 2 9 5 3 6 6 4 10 2 4 7 7 10 13 9 6 10 6 5 9 8 ^
+31 1 9 8 2 7 3 5 11 3 7 7 5 6 2 1 1 6 2 11 5 4 5 7 9 1 11 10 2 3 9 12 10 ^
+28 0 11 1 4 1 12 10 5 5 1 7 2 3 10 7 12 9 2 8 2 6 10 5 12 12 4 9 2 13 ^
+26 1 11 9 8 12 4 12 7 3 4 4 6 1 2 7 12 4 6 8 10 11 11 1 10 2 9 12 ^
+28 0 10 9 7 10 1 10 9 12 7 10 7 6 6 5 3 2 3 1 3 12 1 4 13 3 9 7 9 8 ^
+27 1 4 11 1 5 6 9 12 12 13 13 13 1 2 13 1 2 1 12 12 3 2 2 8 3 13 7 7 ^
+29 0 6 5 5 2 4 2 11 4 4 13 9 13 7 3 12 8 3 7 6 4 12 3 1 8 11 1 6 13 6 ^
+23 1 11 6 6 11 7 13 11 6 7 4 4 12 2 13 5 12 5 7 9 6 11 11 11 ^
+23 0 11 13 11 7 4 3 6 12 13 10 11 5 12 13 11 6 1 1 4 7 13 10 7 ^
+27 1 7 5 13 5 4 8 7 3 9 6 7 11 7 1 9 3 8 5 8 8 2 13 13 8 5 13 4 ^
+30 1 2 5 8 4 13 10 6 4 2 6 1 1 12 4 13 5 10 4 10 8 5 7 1 5 5 12 4 8 6 12 ^
+28 1 12 1 12 11 10 2 3 10 1 2 6 11 12 9 11 12 2 1 9 4 1 5 7 2 12 11 4 11 ^
+29 0 6 8 7 8 8 12 2 7 4 12 11 5 5 3 5 13 4 11 8 8 9 2 2 1 6 2 8 6 12 ^
+28 1 7 13 5 7 11 3 1 9 2 5 12 8 6 2 5 9 10 10 11 4 5 12 5 4 6 5 6 13 ^
+25 1 14 4 8 2 9 11 7 4 3 2 8 14 6 14 7 13 5 5 14 6 5 11 6 6 13 ^
+26 1 3 5 12 1 11 13 1 3 3 10 11 5 6 12 11 12 7 14 4 3 6 6 10 11 14 4 ^
+27 0 4 2 3 10 7 12 13 8 8 12 10 13 1 7 10 2 7 2 13 10 2 3 3 6 4 13 14 ^
+24 1 11 1 9 14 4 14 14 8 10 13 4 3 2 7 6 6 8 14 5 11 7 14 14 1 ^
+22 1 13 13 10 9 13 8 14 9 3 14 3 11 9 9 12 13 2 10 1 5 8 12 ^
+25 0 9 10 9 8 4 14 6 9 3 13 10 11 3 1 4 6 10 3 4 3 12 12 14 11 13 ^
+26 1 11 8 11 7 8 10 9 12 11 6 10 6 3 9 9 1 7 5 6 7 7 12 4 5 8 11 ^
+26 1 12 10 8 14 7 4 13 13 8 4 5 3 2 4 7 14 3 10 6 9 13 9 2 1 9 14 ^
+28 0 6 12 2 4 7 8 11 10 12 2 14 3 1 1 1 12 5 13 9 12 5 9 10 5 1 12 10 8 ^
+29 1 2 6 5 14 14 3 6 13 1 2 6 2 12 1 2 10 1 4 5 14 10 12 11 2 3 14 14 12 5 ^
+30 1 5 2 3 5 11 12 3 7 12 7 9 8 3 3 14 10 5 2 9 3 8 6 11 8 7 8 1 6 12 7 ^
+28 1 14 5 2 14 7 8 1 5 4 12 9 6 12 1 1 7 9 5 14 11 9 4 1 10 1 14 10 12 ^
+27 0 7 2 8 5 3 14 8 9 4 6 11 3 11 6 12 1 7 14 9 14 6 10 6 1 8 14 10 ^
+26 1 6 14 2 2 12 10 5 10 10 8 3 7 13 10 1 14 1 14 7 11 12 9 1 8 8 12 ^
+30 0 6 13 5 13 3 5 8 8 8 2 5 5 4 2 13 14 7 2 12 12 3 3 5 7 5 11 3 7 13 7 ^
+26 0 13 7 2 8 4 10 14 2 7 1 10 8 11 11 2 13 9 11 2 9 11 7 13 11 2 14 ^
+31 1 7 7 8 5 13 4 1 12 14 1 9 11 3 5 3 13 11 7 3 2 9 1 3 13 6 3 10 12 1 13 3 ^
+23 0 9 8 8 7 14 13 6 13 14 12 13 12 7 4 14 10 1 3 9 7 11 14 5 ^
+27 1 1 10 4 12 4 11 5 13 13 4 12 13 7 12 12 4 13 6 2 7 5 2 8 7 13 12 3 ^
+26 1 7 6 11 12 14 12 3 12 8 7 4 9 14 1 8 11 6 5 10 10 6 8 5 2 11 14 ^
+33 1 1 11 1 5 3 8 1 12 14 5 1 3 7 2 3 9 3 4 14 4 4 10 8 5 14 1 11 12 12 10 4 13 
+2 ^
+32 0 11 4 4 9 5 5 8 9 5 10 4 2 4 7 9 9 6 3 5 1 8 3 2 13 3 14 9 8 9 10 14 5 ^
+28 0 12 9 5 8 7 2 14 12 3 8 14 6 6 4 7 5 7 10 7 11 10 1 9 6 7 12 8 9 ^
+25 0 9 9 2 11 13 12 11 11 6 14 13 10 5 6 8 10 4 3 11 11 14 5 5 10 7 ^
+30 0 13 9 14 11 4 8 12 9 5 9 1 2 9 13 12 6 1 14 11 10 7 8 6 1 4 3 2 2 2 13 ^
+33 1 13 5 9 6 13 9 1 13 2 6 8 9 1 3 12 13 3 4 4 12 5 2 1 12 1 6 2 1 8 2 14 13 9 
+^
+32 1 8 6 7 1 4 4 6 1 13 3 3 1 13 7 6 11 6 4 9 10 4 8 13 1 9 10 12 7 10 11 10 5 ^
+30 0 12 6 6 3 4 13 1 4 11 10 2 6 14 6 9 12 6 2 2 11 9 13 4 7 9 14 2 11 8 7 ^
+26 1 2 11 13 2 9 11 8 11 11 15 13 13 3 15 2 12 1 15 3 8 4 9 13 1 13 7 ^
+32 1 9 6 1 2 2 1 15 3 15 1 10 1 4 11 14 14 6 10 2 5 9 10 10 9 1 2 14 10 12 1 1 
+15 ^
+29 1 13 2 3 8 12 5 14 9 8 9 2 14 1 4 6 15 10 9 2 7 9 4 8 7 9 10 11 11 5 ^
+34 1 12 2 7 2 12 8 2 8 6 3 12 4 4 10 1 14 12 11 5 15 3 3 3 14 13 2 2 3 8 2 1 8 
+8 8 ^
+31 0 6 2 7 10 1 13 10 6 6 6 2 8 7 6 7 14 3 12 6 8 9 3 11 1 3 10 12 11 11 9 9 ^
+24 1 13 15 4 7 11 13 10 14 14 13 4 11 5 6 11 8 12 13 9 1 10 9 10 7 ^
+33 0 3 1 3 3 4 13 1 6 14 8 3 4 3 2 1 14 14 14 5 13 13 11 10 13 4 3 10 11 3 6 1 
+10 7 ^
+28 0 7 9 13 9 15 2 4 12 10 10 4 12 3 8 5 6 13 1 6 15 1 8 9 6 12 11 7 14 ^
+32 1 3 1 13 6 4 1 9 4 5 7 1 8 8 11 10 5 15 14 2 8 14 9 7 12 2 4 13 7 4 3 9 14 ^
+31 1 14 12 13 8 4 12 2 6 5 12 9 3 11 8 5 13 5 10 5 2 3 7 12 14 4 1 7 3 6 9 9 ^
+32 1 10 15 7 2 13 5 7 2 5 2 10 7 11 5 5 9 8 2 9 3 3 6 3 13 10 3 5 7 15 11 10 12 
+^
+38 0 2 3 7 1 6 3 3 12 5 2 9 4 5 11 2 1 7 6 14 7 14 10 4 11 6 3 11 2 10 6 4 8 1 
+4 9 4 15 4 ^
+27 0 7 7 4 14 2 3 14 15 10 7 12 7 5 8 7 15 15 14 10 2 3 1 10 12 15 9 9 ^
+31 1 15 3 9 9 5 4 2 6 14 4 9 5 12 8 1 6 1 4 8 7 10 14 3 10 14 8 11 9 8 10 9 ^
+28 0 14 11 8 3 5 5 7 2 11 4 4 4 6 14 13 10 14 10 3 9 6 9 7 5 10 15 15 15 ^
+30 1 8 13 4 2 13 6 4 7 4 4 15 2 2 12 13 3 14 12 7 11 6 2 14 2 6 6 9 14 13 12 ^
+27 1 13 14 15 12 14 5 14 15 11 4 1 1 9 5 13 10 6 5 5 6 14 13 1 5 3 14 13 ^
+29 0 4 2 13 12 15 7 3 15 5 1 6 7 6 13 1 14 11 9 5 15 6 13 3 6 11 7 15 8 9 ^
+31 0 5 4 4 14 3 13 8 13 3 7 13 7 9 12 3 11 15 11 5 14 1 3 4 10 12 7 12 1 2 13 4 
+^
+28 1 12 7 13 14 7 7 1 9 13 8 5 14 2 5 9 9 15 9 13 7 8 9 8 1 12 3 9 15 ^
+34 1 6 12 4 14 12 5 3 15 4 4 6 8 2 11 8 4 2 5 1 15 15 1 15 2 11 4 10 9 4 7 3 2 
+15 6 ^
+26 0 14 5 6 5 11 12 14 12 12 11 15 2 14 9 15 1 7 12 11 12 13 14 1 1 12 5 ^
+32 0 2 2 4 5 2 11 12 5 4 12 9 14 5 5 8 6 2 15 15 6 13 11 3 5 15 5 11 3 12 7 10 
+8 ^
+26 1 2 15 14 9 14 7 6 15 9 3 4 8 8 12 14 2 9 11 14 6 11 15 10 8 14 8 ^
+34 1 15 7 4 5 10 1 13 7 1 1 8 3 13 11 2 8 15 11 12 6 6 1 3 2 2 11 3 13 9 10 3 6 
+12 15 ^
+25 0 15 7 10 2 10 15 5 10 13 12 8 15 3 1 11 14 15 8 15 12 9 6 8 13 13 ^
+27 0 10 8 13 10 15 13 5 8 4 10 10 6 7 13 6 12 12 9 12 2 5 10 12 10 8 15 6 ^
+28 0 5 3 8 12 15 8 14 15 9 12 12 3 10 13 6 11 10 4 13 14 8 9 1 8 1 5 11 12 ^
+29 0 9 12 4 13 15 5 9 11 7 14 11 1 11 7 8 8 11 1 13 15 12 1 5 8 3 8 10 7 14 ^
+30 0 1 5 13 12 14 5 3 6 4 12 15 6 6 10 11 13 9 1 11 6 10 3 7 14 4 14 11 7 8 13 ^
+34 1 1 12 5 1 7 4 6 7 5 11 1 4 7 12 10 10 8 15 13 4 11 15 11 6 9 1 2 15 5 1 5 
+12 6 13 ^
+35 1 12 15 4 11 13 3 6 5 10 8 1 3 9 3 11 1 2 16 12 10 6 1 9 1 16 5 6 15 1 12 4 
+4 2 15 4 ^
+27 0 15 11 15 5 11 9 7 15 16 6 16 12 3 2 10 16 5 5 7 1 7 11 13 7 9 11 12 ^
+31 1 5 5 5 4 13 13 14 4 7 12 6 4 8 2 9 9 13 13 3 3 6 7 16 7 6 15 5 8 15 6 15 ^
+30 1 6 16 15 11 14 14 4 7 10 3 4 10 3 6 7 14 4 6 6 5 2 7 8 16 2 12 16 10 14 7 ^
+36 1 2 3 7 14 6 9 4 4 5 9 7 12 3 9 2 5 1 3 10 11 11 6 12 7 1 7 12 2 1 2 8 12 15 
+16 9 13 ^
+34 1 6 3 12 11 16 15 8 8 8 14 13 7 7 8 2 7 6 2 2 14 7 1 4 2 4 11 11 5 7 2 12 1 
+14 11 ^
+29 0 12 11 2 9 8 5 6 14 10 12 5 11 5 3 1 13 15 9 12 11 13 4 14 5 16 3 5 13 15 ^
+30 1 5 16 11 2 6 13 16 3 6 4 9 10 9 8 6 14 8 9 5 13 6 5 14 2 8 15 8 7 14 11 ^
+28 1 14 10 13 13 11 10 13 9 8 4 11 14 11 6 10 10 1 9 13 16 5 3 4 7 9 12 10 8 ^
+36 1 10 15 12 8 8 10 13 5 6 11 4 6 2 3 5 6 11 1 1 8 6 13 15 6 3 15 5 10 1 6 2 5 
+2 11 10 10 ^
+31 1 4 14 7 2 14 3 1 12 7 15 13 1 5 9 8 3 3 14 12 13 2 15 12 7 16 12 3 8 11 5 
+15 ^
+34 0 10 2 10 16 4 16 7 8 1 16 6 14 9 5 12 16 8 9 4 4 4 1 7 13 10 1 7 10 5 7 4 1 
+5 15 ^
+30 0 16 3 8 7 3 8 8 11 8 13 4 16 8 16 1 4 16 11 4 12 1 14 5 1 16 11 8 14 12 9 ^
+33 0 7 9 9 16 11 7 6 1 11 14 12 14 10 9 11 8 11 7 5 10 15 2 6 9 3 9 4 2 1 1 9 
+14 6 ^
+32 0 5 8 14 15 4 1 6 1 10 8 1 15 15 3 10 7 8 10 12 4 3 11 15 8 5 3 3 16 15 7 14 
+13 ^
+36 0 3 10 12 2 11 9 2 1 4 3 8 10 14 2 11 3 2 4 15 14 5 2 8 16 16 1 5 7 5 9 5 15 
+9 11 3 14 ^
+31 1 5 4 14 4 8 3 3 1 10 4 15 15 13 2 13 9 7 13 11 9 1 15 15 15 16 7 7 6 5 13 9 
+^
+30 0 14 16 12 1 11 11 7 3 7 3 3 13 4 13 14 5 15 12 5 14 16 14 4 5 9 6 6 3 16 11 
+^
+28 1 10 16 10 14 13 6 16 14 3 14 15 7 13 12 4 1 8 4 10 6 1 13 6 14 11 3 16 14 ^
+33 0 15 11 13 8 11 1 15 2 10 9 9 14 8 13 2 13 8 1 2 1 3 12 8 5 4 11 10 14 8 9 4 
+5 16 ^
+34 1 12 12 6 7 13 13 12 1 13 14 1 1 6 3 13 2 16 3 1 16 9 9 15 3 13 1 8 3 2 6 12 
+8 9 13 ^
+27 0 11 12 15 14 12 10 8 15 9 15 2 7 5 11 8 9 7 16 6 15 4 15 7 11 15 4 14 ^
+29 1 9 1 14 7 4 14 16 11 10 11 12 14 6 12 11 15 7 14 3 15 6 1 12 5 12 13 3 6 14 
+^
+28 0 6 10 7 7 9 10 7 11 12 16 9 6 9 14 10 10 2 7 4 15 16 13 11 8 10 15 10 15 ^
+32 1 8 12 1 10 3 7 15 14 9 16 14 1 15 3 14 9 2 2 12 14 7 3 5 14 5 15 10 2 14 1 
+15 8 ^
+33 0 9 16 10 16 6 13 1 6 2 8 13 5 7 2 15 11 12 6 8 7 1 5 8 13 9 4 8 12 9 15 1 
+10 13 ^
+30 0 10 4 16 4 13 12 2 4 14 6 11 3 15 8 4 12 3 11 16 16 16 2 13 7 10 2 13 10 15 
+10 ^
+33 1 16 2 15 10 4 1 13 12 12 9 12 7 16 4 12 4 2 16 4 9 16 8 2 6 15 2 3 4 9 12 6 
+8 12 ^
+34 1 13 11 11 4 9 13 14 2 9 6 8 6 10 11 9 3 12 9 13 4 10 3 5 1 14 11 11 16 1 2 
+2 11 6 14 ^
+33 1 15 12 6 5 16 2 14 2 10 12 2 5 5 6 10 13 12 3 10 8 16 9 5 12 15 4 11 13 3 6 
+5 10 8 ^
+35 1 1 3 9 3 11 1 2 16 12 10 6 1 9 1 16 5 6 15 1 12 4 4 2 15 13 15 11 15 5 11 9 
+7 15 16 4 ^
+36 0 16 12 3 2 10 16 5 5 7 1 7 11 13 7 9 11 2 5 5 5 4 13 13 14 4 7 12 6 4 8 2 9 
+9 13 13 4 ^
+35 0 3 6 7 16 7 6 15 5 8 15 6 4 6 16 15 11 14 14 4 7 10 3 4 10 3 6 7 14 4 6 6 5 
+2 7 16 ^
+31 0 7 4 8 17 16 16 11 14 2 10 14 15 10 9 1 14 10 14 6 6 16 3 2 3 8 3 12 8 11 
+17 2 ^
+30 1 9 7 16 14 4 11 15 5 13 9 5 12 17 17 13 8 2 6 8 16 1 12 5 17 2 9 8 10 13 6 ^
+27 0 11 17 12 5 14 9 11 9 11 4 11 13 16 6 10 5 8 3 17 16 14 1 15 15 15 6 17 ^
+29 1 2 11 6 13 11 13 4 6 7 11 11 12 16 13 1 16 16 14 16 2 4 16 11 6 15 7 4 17 
+11 ^
+32 0 5 7 6 3 14 16 5 17 11 13 1 1 14 13 3 6 14 5 17 5 4 8 14 3 16 7 13 4 14 8 9 
+17 ^
+31 1 8 12 8 15 9 6 6 1 5 13 16 5 8 4 6 10 6 11 16 17 15 15 12 4 13 5 3 4 10 15 
+16 ^
+33 0 7 15 16 12 12 11 8 13 14 5 8 1 11 10 9 3 14 3 1 9 6 15 12 16 4 5 9 7 1 9 4 
+8 17 ^
+36 1 7 9 16 11 11 6 13 7 1 7 8 1 14 12 2 7 4 5 15 16 12 3 1 6 11 4 15 8 9 9 2 1 
+13 2 14 14 ^
+29 1 6 8 8 15 13 13 10 2 16 12 17 6 7 14 13 12 13 3 14 12 12 2 15 2 5 15 10 7 
+15 ^
+38 1 5 15 7 8 10 10 1 11 2 4 3 11 11 3 5 2 3 11 5 12 12 8 6 2 17 15 6 16 15 4 3 
+14 6 3 2 10 5 15 ^
+30 0 12 11 15 14 2 16 14 7 6 15 9 3 11 8 8 5 16 2 16 2 16 6 9 6 12 10 16 7 15 
+10 ^
+36 0 11 5 3 16 1 15 7 10 17 10 10 13 2 2 17 6 2 5 6 6 10 12 2 9 11 12 6 1 1 8 
+12 2 6 16 12 16 ^
+30 1 10 17 5 1 6 14 17 8 12 10 11 16 15 1 8 3 9 13 7 7 16 8 13 11 10 8 15 3 15 
+12 ^
+31 1 14 8 4 12 1 6 5 13 15 3 5 11 14 11 14 17 5 10 17 7 8 13 5 12 15 3 6 17 7 
+17 7 ^
+31 0 12 3 10 10 4 13 13 8 11 13 7 17 11 1 10 1 5 11 11 9 14 13 15 8 14 2 7 16 
+11 8 15 ^
+32 1 7 16 17 17 4 1 13 15 5 1 5 6 14 15 1 5 1 9 9 17 12 13 12 7 12 3 7 15 4 16 
+12 13 ^
+36 0 8 17 1 11 4 10 2 6 10 3 16 16 2 7 13 9 15 7 17 14 3 10 16 13 6 7 5 2 1 4 
+16 3 10 1 15 5 ^
+32 0 4 6 4 15 11 4 2 17 9 15 5 10 7 12 15 16 15 17 12 14 9 2 13 4 9 2 4 15 2 11 
+9 16 ^
+29 0 4 4 3 17 2 14 17 17 1 17 13 11 15 17 4 9 15 8 11 16 9 10 8 9 12 15 1 17 11 
+^
+35 0 16 4 2 14 14 15 1 2 12 9 1 10 16 10 11 7 1 12 17 8 2 15 11 1 7 17 12 7 3 7 
+6 9 9 14 6 ^
+36 0 2 15 17 10 11 9 5 9 4 17 16 3 11 2 10 12 11 5 3 8 17 15 3 3 4 7 2 1 10 7 
+14 4 16 6 12 8 ^
+36 1 12 14 6 9 3 17 11 10 6 8 14 6 11 7 10 8 6 17 4 4 9 8 2 8 14 8 7 14 1 3 6 8 
+11 10 17 1 ^
+39 1 12 14 9 4 11 7 6 6 13 14 2 13 1 14 9 7 7 15 2 2 5 15 13 17 3 15 16 9 1 1 2 
+3 2 12 1 3 3 13 9 ^
+34 0 13 10 15 5 8 10 15 10 8 7 5 5 14 4 13 11 12 4 4 12 10 13 12 4 10 3 3 7 9 
+13 16 9 17 1 ^
+36 0 4 12 1 9 12 13 5 10 1 3 15 4 1 13 17 1 8 9 6 12 4 7 7 10 17 13 17 6 17 9 6 
+9 3 5 17 10 ^
+34 0 1 4 10 12 17 14 11 8 5 16 5 5 2 13 13 16 9 13 10 9 9 5 3 13 6 4 3 9 15 14 
+14 7 3 16 ^
+38 1 9 17 3 6 5 16 10 14 9 1 16 7 3 5 4 17 14 7 12 6 2 8 8 17 7 2 4 5 7 12 2 1 
+7 11 3 14 9 15 ^
+41 0 2 12 3 4 1 4 1 16 10 5 16 8 7 2 10 3 5 9 16 8 16 13 3 12 5 5 11 2 2 7 4 2 
+8 16 4 14 5 14 10 4 17 ^
+36 0 6 1 2 7 1 15 13 1 17 4 7 4 8 17 16 16 11 14 2 10 14 15 10 9 1 14 10 14 6 6 
+16 3 2 3 8 14 ^
+32 1 12 8 11 17 3 9 7 16 14 4 11 15 5 13 9 5 12 17 17 13 8 2 6 8 16 1 12 5 17 2 
+9 14 ^
+29 0 10 13 14 11 17 12 5 14 9 11 9 11 4 11 13 16 6 10 5 8 3 17 16 14 1 15 15 15 
+14 ^
+32 0 13 2 11 6 13 11 13 4 6 7 11 11 12 16 13 1 16 16 14 16 2 4 16 11 6 15 7 4 
+17 6 5 15 ^
+35 1 6 3 14 16 5 17 11 13 1 1 14 13 3 6 14 5 17 5 4 8 14 3 16 7 13 4 14 8 9 3 8 
+12 8 15 11 ^
+33 1 6 6 1 5 13 16 5 8 4 6 10 6 11 16 17 15 15 12 4 13 5 3 4 10 15 12 7 15 16 
+12 12 11 11 ^
+40 0 13 14 5 8 1 11 10 9 3 14 3 1 9 6 15 12 16 4 5 9 7 1 9 4 8 5 7 9 16 11 11 6 
+13 7 1 7 8 1 14 10 ^
+34 0 2 10 15 10 14 8 18 9 9 12 12 3 13 12 6 4 9 17 13 13 5 7 3 2 1 17 14 4 16 6 
+13 1 13 13 ^
+35 1 6 10 1 3 18 3 11 7 9 5 7 11 17 1 9 16 5 15 10 17 3 8 15 17 8 15 11 3 15 17 
+11 1 1 4 15 ^
+36 1 14 18 4 2 18 8 15 6 4 6 3 15 11 16 10 17 17 9 6 3 2 6 16 4 9 12 6 8 1 11 3 
+2 12 2 14 16 ^
+37 0 4 1 5 11 16 18 16 8 11 15 2 18 7 5 14 5 15 13 3 3 5 4 3 11 4 4 5 10 3 12 
+17 1 4 17 10 10 17 ^
+35 0 1 3 4 2 1 12 5 14 11 10 4 6 14 9 1 5 8 2 9 15 12 13 7 16 2 13 17 15 9 18 
+15 9 13 16 17 ^
+34 1 18 10 4 11 13 9 6 1 17 6 8 6 5 11 5 14 16 9 13 11 10 9 15 4 14 7 14 3 1 15 
+5 5 18 16 ^
+34 0 13 8 13 16 5 17 5 10 1 8 8 12 6 13 18 9 6 17 3 16 2 8 9 8 7 2 14 14 8 10 
+13 9 11 11 ^
+40 0 7 11 4 6 9 10 11 12 2 14 1 13 1 7 1 15 7 9 8 2 1 4 9 14 17 8 17 15 3 4 15 
+15 2 2 3 16 13 2 9 12 ^
+33 0 14 6 6 5 2 13 4 16 11 3 10 18 2 15 5 9 4 8 4 18 18 17 18 3 14 12 9 11 15 
+16 1 9 16 ^
+32 1 18 5 10 6 7 17 7 12 3 13 8 12 3 8 9 3 17 12 8 18 6 14 3 6 14 14 10 14 13 
+17 18 8 ^
+36 1 18 12 17 9 17 2 12 5 9 12 1 18 10 5 5 2 18 3 6 16 18 3 1 2 10 15 2 5 8 16 
+10 14 3 9 8 13 ^
+33 1 16 14 1 16 15 16 17 4 12 12 16 5 3 9 14 5 7 17 12 11 12 18 14 2 7 7 15 8 3 
+5 1 8 13 ^
+34 1 7 6 7 14 9 15 15 18 16 3 10 5 16 6 8 11 4 1 10 1 16 4 12 17 15 14 8 5 4 6 
+4 17 16 16 ^
+38 0 4 5 18 18 12 9 3 9 6 9 7 6 10 15 4 9 17 5 17 5 6 1 6 2 8 17 7 7 4 4 13 16 
+3 4 10 16 12 13 ^
+33 0 16 7 18 3 3 11 9 13 14 15 18 2 12 10 3 15 3 1 10 6 15 13 17 13 5 9 7 11 9 
+5 18 15 12 ^
+33 1 16 11 1 6 18 13 8 1 18 8 1 5 13 1 18 5 15 15 16 12 13 2 17 12 14 17 8 1 10 
+12 10 4 18 ^
+34 0 5 6 18 18 7 10 13 14 10 12 7 4 10 8 16 16 15 5 13 14 4 14 2 4 12 6 11 5 17 
+8 5 1 14 16 ^
+31 1 17 9 11 2 11 11 3 13 13 11 12 13 5 12 12 11 6 13 4 18 15 12 18 6 6 7 15 13 
+12 14 16 ^
+38 1 4 11 2 5 6 12 10 2 7 15 11 8 14 7 16 16 1 4 3 9 14 16 3 18 1 7 17 1 7 3 16 
+17 6 16 12 5 3 17 ^
+40 1 10 15 18 10 8 10 2 5 11 2 7 3 5 6 7 1 12 2 9 2 4 15 1 11 11 17 3 3 16 8 3 
+11 18 16 11 6 15 8 8 13 ^
+40 1 10 3 17 7 10 18 13 14 8 7 8 14 2 2 8 6 3 7 5 6 9 5 12 10 7 6 5 16 4 14 2 
+15 3 15 9 15 1 9 7 12 ^
+35 0 14 15 12 7 2 16 18 8 18 1 13 12 1 1 14 14 13 3 14 7 2 10 10 11 14 3 12 5 
+13 6 17 14 1 11 13 ^
+34 0 7 12 8 12 17 17 18 17 13 2 4 7 5 1 15 7 14 17 11 6 10 9 18 9 14 13 3 8 4 
+13 8 7 13 7 ^
+35 0 4 16 8 17 10 2 13 10 2 2 6 2 3 18 17 2 17 4 18 7 16 18 14 4 11 7 4 15 17 6 
+11 11 14 17 4 ^
+37 0 10 17 16 13 15 14 6 1 14 11 8 16 6 2 16 13 7 8 6 2 15 1 9 12 4 4 11 13 7 2 
+11 9 18 4 5 4 18 ^
+39 0 2 14 9 9 1 8 13 11 15 8 5 9 10 16 9 2 7 1 1 17 13 6 11 10 8 5 12 15 6 15 
+10 12 4 18 1 2 8 11 15 ^
+32 1 16 10 12 18 11 16 12 11 17 17 4 7 13 7 10 7 10 6 1 12 7 18 11 18 2 10 15 
+10 14 8 18 2 ^
+40 1 9 12 12 3 13 12 6 4 9 17 13 13 5 7 3 2 1 17 14 4 16 6 13 1 13 6 6 10 1 3 
+18 3 11 7 9 5 7 11 17 12 ^
+36 1 9 16 5 15 10 17 3 8 15 17 8 15 11 3 15 17 11 1 1 4 3 14 18 4 2 18 8 15 6 4 
+6 3 15 11 16 8 ^
+39 1 17 17 9 6 3 2 6 16 4 9 12 6 8 1 11 3 2 12 2 14 12 4 1 5 11 16 18 16 8 11 
+15 2 18 7 5 14 5 15 10 ^
+47 1 3 3 5 4 3 11 4 4 5 10 3 12 17 1 4 17 10 10 9 1 3 4 2 1 12 5 14 11 10 4 6 
+14 9 1 5 8 2 9 15 12 13 7 16 2 13 17 3 ^
+34 1 9 18 15 9 13 16 18 10 4 11 13 9 6 1 17 6 8 6 5 11 5 14 16 9 13 11 10 9 15 
+4 14 7 14 9 ^
+37 1 1 15 5 5 18 13 13 8 13 16 5 17 5 10 1 8 8 12 6 13 18 9 6 17 3 16 2 8 9 8 7 
+2 14 14 8 10 13 ^
+42 0 9 11 10 7 11 4 6 9 10 11 12 2 14 1 13 1 7 1 15 7 9 8 2 1 4 9 14 17 8 17 15 
+3 4 15 15 2 2 3 16 13 2 17 ^
+36 0 16 14 6 6 5 2 13 4 16 11 3 10 18 2 15 5 9 4 8 4 18 18 17 18 3 14 12 9 11 
+15 16 1 9 2 18 6 ^
+33 1 10 6 7 17 7 12 3 13 8 12 3 8 9 3 17 12 8 18 6 14 3 6 14 14 10 14 13 17 18 
+14 18 12 13 ^
+39 1 9 17 2 12 5 9 12 1 18 10 5 5 2 18 3 6 16 18 3 1 2 10 15 2 5 8 16 10 14 3 9 
+8 10 16 14 1 16 15 14 ^
+30 1 17 19 5 7 14 4 11 3 6 18 13 7 18 18 19 19 13 9 10 19 14 12 4 15 15 18 2 10 
+7 15 ^
+34 1 2 13 8 19 15 1 11 14 7 7 17 6 16 4 16 17 2 18 12 5 14 19 17 1 8 12 6 6 6 
+19 13 10 16 5 ^
+36 1 14 13 6 16 14 15 4 13 15 4 4 11 4 10 3 17 4 19 6 17 14 3 2 16 1 14 16 5 17 
+8 1 1 19 13 12 12 ^
+34 0 17 11 13 5 19 11 18 19 1 3 12 11 8 4 11 13 17 3 8 9 4 5 12 15 12 6 7 16 16 
+12 1 13 17 15 ^
+40 0 18 9 3 16 2 16 4 19 6 6 18 3 13 1 5 3 2 6 15 11 6 4 14 15 15 9 13 8 1 9 15 
+2 7 5 11 5 12 7 16 15 ^
+37 0 18 4 3 1 4 11 15 7 6 9 1 14 7 1 17 17 16 14 13 14 12 14 9 12 11 18 7 14 3 
+1 6 1 15 8 15 19 9 ^
+32 0 3 9 9 7 7 10 12 13 7 11 12 16 9 9 9 17 13 13 2 17 10 4 18 17 19 16 11 11 
+13 18 13 12 ^
+35 0 8 15 18 10 6 10 18 17 9 2 14 1 17 18 6 14 12 5 5 15 17 10 3 8 8 1 10 5 1 
+18 18 9 16 10 14 ^
+38 1 6 16 1 6 3 5 8 16 8 7 5 18 11 15 17 6 11 10 4 8 14 16 6 7 8 12 12 18 1 10 
+4 7 1 19 7 19 15 12 ^
+34 0 1 14 6 11 18 5 4 12 6 14 2 19 2 5 13 10 10 2 16 10 18 16 19 2 15 10 7 18 
+16 17 15 15 9 13 ^
+38 1 10 16 4 15 7 5 19 1 15 16 11 19 9 18 2 4 6 12 9 8 7 13 14 11 4 12 13 5 9 6 
+5 6 16 11 9 3 15 6 ^
+40 0 16 1 13 6 8 18 11 11 2 1 2 2 14 9 13 1 15 6 5 16 19 14 19 7 18 5 2 2 3 13 
+13 12 13 11 2 12 2 12 18 5 ^
+35 0 7 8 13 6 9 8 17 10 11 1 9 14 4 19 19 3 15 13 9 18 12 17 1 16 8 9 15 1 12 4 
+4 19 18 13 11 ^
+36 1 14 18 8 14 9 3 4 18 16 9 19 12 3 17 5 10 16 5 8 4 4 10 14 13 4 9 11 19 8 8 
+5 1 13 16 14 13 ^
+41 1 10 15 3 4 8 2 12 9 16 3 16 3 6 17 3 10 19 7 6 1 5 11 18 9 4 6 2 15 11 17 
+17 17 4 10 13 3 7 10 3 9 14 ^
+42 0 7 9 3 3 8 19 10 8 2 19 12 19 13 6 19 3 4 17 6 9 1 7 2 9 7 18 6 15 2 2 4 3 
+10 11 11 6 12 10 18 4 12 10 ^
+35 1 4 5 11 12 15 19 12 10 6 15 14 19 18 11 8 11 17 16 7 7 11 2 10 6 19 5 14 7 
+1 7 3 19 4 17 15 ^
+36 1 5 10 2 18 1 17 8 12 17 2 9 8 8 3 14 10 15 2 14 8 3 1 16 18 12 18 11 16 7 
+17 5 19 2 19 12 19 ^
+37 0 16 14 2 9 16 2 6 6 7 9 10 9 11 9 14 11 15 5 16 9 2 17 2 8 15 8 4 3 14 14 
+16 16 13 11 10 16 14 ^
+40 0 11 7 14 14 14 6 10 10 1 6 13 19 5 6 4 7 12 12 10 5 10 15 15 8 5 13 17 13 5 
+6 14 1 9 2 6 5 17 9 11 13 ^
+38 0 18 8 6 13 15 3 3 15 5 13 18 3 2 5 5 14 7 13 4 17 7 2 17 3 18 15 7 15 16 18 
+5 12 8 6 3 17 12 13 ^
+38 1 19 15 9 7 17 16 15 3 11 11 5 2 13 19 16 2 4 16 7 8 1 2 9 17 12 3 5 18 19 
+11 17 9 1 4 1 18 10 10 ^
+41 1 13 1 7 13 5 7 4 1 8 13 16 3 5 7 6 8 8 14 8 13 7 19 8 16 18 4 2 8 7 12 4 14 
+5 1 3 19 17 11 14 15 19 ^
+39 0 10 9 12 19 11 10 3 18 14 17 18 17 7 12 14 8 11 7 2 10 17 15 5 3 12 3 12 1 
+2 1 1 12 14 10 2 8 17 18 2 ^
+45 1 4 9 4 16 5 18 1 1 10 10 11 3 10 12 1 3 11 1 11 5 3 3 16 15 10 17 14 15 6 
+13 12 2 3 14 3 9 19 4 4 8 10 14 5 11 9 ^
+35 0 2 7 15 14 8 2 11 19 19 4 5 10 8 9 5 15 9 17 19 5 7 14 4 11 3 6 18 13 7 18 
+18 19 19 13 13 ^
+35 1 10 19 14 12 4 15 15 18 2 10 7 9 2 13 8 19 15 1 11 14 7 7 17 6 16 4 16 17 2 
+18 12 5 14 19 9 ^
+38 1 1 8 12 6 6 6 19 13 10 16 13 14 13 6 16 14 15 4 13 15 4 4 11 4 10 3 17 4 19 
+6 17 14 3 2 16 1 14 19 ^
+38 0 5 17 8 1 1 19 13 12 12 17 11 13 5 19 11 18 19 1 3 12 11 8 4 11 13 17 3 8 9 
+4 5 12 15 12 6 7 16 11 ^
+43 0 12 1 13 17 4 18 9 3 16 2 16 4 19 6 6 18 3 13 1 5 3 2 6 15 11 6 4 14 15 15 
+9 13 8 1 9 15 2 7 5 11 5 12 16 ^
+39 1 16 6 18 4 3 1 4 11 15 7 6 9 1 14 7 1 17 17 16 14 13 14 12 14 9 12 11 18 7 
+14 3 1 6 1 15 8 15 19 12 ^
+35 0 3 9 9 7 7 10 12 13 7 11 12 16 9 9 9 17 13 13 2 17 10 4 18 17 19 16 11 11 
+13 18 13 8 8 15 6 ^
+40 0 10 6 10 18 17 9 2 14 1 17 18 6 14 12 5 5 15 17 10 3 8 8 1 10 5 1 18 18 9 
+16 10 19 6 16 1 6 3 5 8 16 ^
+40 0 8 7 5 18 11 15 17 6 11 10 4 8 14 16 6 7 8 12 12 18 1 10 4 7 1 19 7 19 15 2 
+1 14 6 11 18 5 4 12 6 19 ^
+35 0 2 19 2 5 13 10 10 2 16 10 18 16 19 2 15 10 7 18 16 17 15 15 9 15 10 16 4 
+15 7 5 19 1 15 16 6 ^
+43 1 19 9 18 2 4 6 12 9 8 7 13 14 11 4 12 13 5 9 6 5 6 16 11 9 3 15 12 16 1 13 
+6 8 18 11 11 2 1 2 2 14 9 13 11 ^
+39 1 15 6 5 16 19 14 19 7 18 5 2 2 3 13 13 12 13 11 2 12 2 12 18 7 8 13 6 9 8 
+17 10 11 1 9 14 4 19 19 3 ^
+34 1 15 13 9 18 12 17 1 16 8 9 15 1 12 4 4 19 18 13 15 14 18 8 14 9 3 4 18 16 9 
+19 12 3 17 15 ^
+45 1 10 16 5 8 4 4 10 14 13 4 9 11 19 8 8 5 1 13 16 14 1 10 15 3 4 8 2 12 9 16 
+3 16 3 6 17 3 10 19 7 6 1 5 11 18 2 ^
+43 1 15 4 13 14 3 4 1 3 1 5 11 4 9 7 20 8 15 4 16 7 19 11 1 11 2 13 13 11 12 13 
+15 12 1 5 13 3 8 15 12 8 16 16 6 ^
+44 0 5 13 12 14 5 3 1 4 16 12 20 1 6 15 11 18 4 17 16 6 10 3 2 9 9 14 6 2 8 6 7 
+10 17 12 20 6 7 5 16 1 4 2 17 9 ^
+38 0 15 8 20 18 20 11 15 11 11 9 6 2 15 5 17 12 1 9 1 3 5 11 7 2 2 6 18 2 9 11 
+8 16 11 16 15 18 18 18 ^
+35 1 20 2 17 17 10 8 13 20 4 18 6 18 9 4 1 1 18 5 2 17 15 16 19 15 1 10 17 16 4 
+16 14 14 11 15 10 ^
+38 0 5 9 15 10 9 17 18 14 15 12 6 1 16 8 18 8 13 12 10 14 14 13 9 2 14 17 9 1 
+20 10 4 2 12 9 4 13 16 5 ^
+36 0 14 10 11 16 17 12 18 12 7 17 8 7 3 1 3 17 4 9 5 17 14 17 11 5 20 19 8 19 
+14 13 2 18 3 3 18 13 ^
+41 1 13 8 14 6 18 7 10 1 13 10 11 11 16 1 2 8 7 1 7 14 8 17 6 8 4 3 11 17 3 5 7 
+16 11 11 14 7 13 20 20 7 20 ^
+40 1 13 15 14 16 14 8 9 16 5 1 6 3 17 18 16 9 1 15 9 10 9 19 1 3 3 20 11 13 17 
+1 19 8 3 4 3 7 1 14 19 17 ^
+37 1 18 13 11 5 18 4 19 10 6 19 11 17 10 10 7 9 13 16 9 10 18 4 12 5 16 5 20 12 
+3 8 10 1 18 1 6 20 14 ^
+36 0 8 9 6 12 11 7 7 3 17 13 6 20 17 9 20 16 10 12 17 8 11 8 11 10 5 10 14 18 8 
+19 9 12 12 2 20 12 ^
+38 0 12 16 20 3 9 9 19 17 13 13 4 17 2 11 7 14 3 6 16 13 10 13 5 16 10 2 8 2 17 
+19 4 17 7 19 6 9 15 7 ^
+41 1 20 7 2 18 5 7 18 5 2 15 7 11 10 9 3 2 14 19 3 11 8 18 15 5 3 5 12 15 16 10 
+17 7 19 16 2 1 16 6 3 19 10 ^
+46 0 5 18 9 9 11 2 1 12 11 14 12 14 10 4 11 6 8 16 7 5 11 20 8 17 4 14 4 15 3 2 
+2 4 3 2 3 14 15 10 2 12 7 3 7 20 20 5 ^
+41 1 10 2 3 1 10 12 15 14 11 20 3 16 14 9 4 18 1 19 20 9 5 12 13 6 6 1 9 13 7 
+15 9 8 5 19 3 16 9 8 10 20 8 ^
+39 1 11 13 19 5 7 16 18 16 4 4 4 6 9 13 10 19 15 3 14 6 4 12 10 15 15 4 8 13 13 
+9 18 13 6 4 7 20 4 20 7 ^
+31 1 18 18 12 16 13 19 19 5 7 2 6 11 18 9 18 6 11 14 14 18 10 13 19 20 17 11 14 
+5 19 20 13 ^
+46 1 20 1 1 4 13 10 6 5 6 19 18 1 3 9 14 20 7 18 7 15 2 3 15 5 1 1 2 6 13 1 19 
+6 14 16 5 15 11 13 3 6 11 2 20 8 1 20 ^
+37 0 4 20 19 3 18 3 8 19 7 8 12 14 12 19 11 15 6 19 1 19 4 10 16 17 7 17 1 2 13 
+18 12 2 18 19 2 7 15 ^
+42 1 9 18 8 5 14 2 5 4 4 20 14 13 7 8 14 8 1 7 19 9 7 11 12 4 19 12 10 19 20 4 
+4 1 8 2 16 16 8 20 2 1 20 13 ^
+37 1 1 15 7 6 20 10 14 9 12 19 18 20 6 14 6 5 6 17 14 12 12 16 4 2 19 14 15 17 
+7 12 11 12 8 14 1 17 7 ^
+39 0 15 18 2 4 10 18 11 17 5 9 17 4 19 5 5 8 6 2 20 15 6 5 18 11 3 10 20 10 16 
+3 12 7 5 14 18 15 14 9 14 ^
+44 0 14 7 6 15 9 3 4 8 8 12 19 2 9 16 19 6 16 20 5 3 19 7 4 7 4 5 10 5 1 18 7 
+17 6 3 3 13 16 2 3 20 16 12 6 16 ^
+38 0 17 19 2 2 11 19 13 4 15 8 1 12 9 20 2 5 2 10 20 5 15 13 7 13 15 19 17 11 9 
+15 8 15 17 9 6 16 8 13 ^
+38 1 18 10 8 8 10 15 13 8 4 5 15 6 12 13 1 17 12 4 7 18 10 12 10 3 15 20 5 19 8 
+17 20 13 14 10 9 12 17 5 ^
+46 1 10 18 6 6 15 4 13 14 3 4 1 3 1 5 11 4 9 7 20 8 15 4 16 7 19 11 1 11 2 13 
+13 11 12 13 15 12 1 5 13 3 8 15 12 8 16 6 ^
+45 1 17 5 13 12 14 5 3 1 4 16 12 20 1 6 15 11 18 4 17 16 6 10 3 2 9 9 14 6 2 8 
+6 7 10 17 12 20 6 7 5 16 1 4 2 17 16 ^
+40 0 15 8 20 18 20 11 15 11 11 9 6 2 15 5 17 12 1 9 1 3 5 11 7 2 2 6 18 2 9 11 
+8 16 11 16 15 18 18 3 20 19 ^
+38 0 17 17 10 8 13 20 4 18 6 18 9 4 1 1 18 5 2 17 15 16 19 15 1 10 17 16 4 16 
+14 14 11 15 2 5 9 15 10 15 ^
+38 0 17 18 14 15 12 6 1 16 8 18 8 13 12 10 14 14 13 9 2 14 17 9 1 20 10 4 2 12 
+9 4 13 16 7 14 10 11 16 19 ^
+39 0 12 18 12 7 17 8 7 3 1 3 17 4 9 5 17 14 17 11 5 20 19 8 19 14 13 2 18 3 3 
+18 17 13 8 14 6 18 7 10 12 ^
+41 0 13 10 11 11 16 1 2 8 7 1 7 14 8 17 6 8 4 3 11 17 3 5 7 16 11 11 14 7 13 20 
+20 7 16 13 15 14 16 14 8 9 16 ^
+43 1 5 1 6 3 17 18 16 9 1 15 9 10 9 19 1 3 3 20 11 13 17 1 19 8 3 4 3 7 1 14 19 
+19 18 13 11 5 18 4 19 10 6 19 4 ^
+41 1 17 10 10 7 9 13 16 9 10 18 4 12 5 16 5 20 12 3 8 10 1 18 1 6 20 12 8 9 6 
+12 11 7 7 3 17 13 6 20 17 9 15 ^
+37 0 16 10 12 17 8 11 8 11 10 5 10 14 18 8 19 9 12 12 2 20 13 12 16 20 3 9 9 19 
+17 13 13 4 17 2 11 7 16 ^
+43 0 3 6 16 13 10 13 5 16 10 2 8 2 17 19 4 17 7 19 6 9 15 15 20 7 2 18 5 7 18 5 
+2 15 7 11 10 9 3 2 14 19 3 11 14 ^
+43 1 18 15 5 3 5 12 15 16 10 17 7 19 16 2 1 16 6 3 19 12 5 18 9 9 11 2 1 12 11 
+14 12 14 10 4 11 6 8 16 7 5 11 20 2 ^
+45 0 17 4 14 4 15 3 2 2 4 3 2 3 14 15 10 2 12 7 3 7 20 20 19 10 2 3 1 10 12 15 
+14 11 20 3 16 14 9 4 18 1 19 20 9 5 18 ^
+42 0 13 6 6 1 9 13 7 15 9 8 5 19 3 16 9 8 10 20 14 11 13 19 5 7 16 18 16 4 4 4 
+6 9 13 10 19 15 3 14 6 4 12 18 ^
+36 1 15 15 4 8 13 13 9 18 13 6 4 7 20 4 20 18 18 12 16 13 19 19 5 7 2 6 11 18 9 
+18 6 11 14 14 18 15 ^
+43 1 13 19 20 17 11 14 5 19 20 11 20 1 1 4 13 10 6 5 6 19 18 1 3 9 14 20 7 18 7 
+15 2 3 15 5 1 1 2 6 13 1 19 6 19 ^
+40 1 16 5 15 11 13 3 6 11 2 20 8 1 5 4 20 19 3 18 3 8 19 7 8 12 14 12 19 11 15 
+6 19 1 19 4 10 16 17 7 17 16 ^
+39 1 12 19 20 1 13 12 10 8 21 15 7 19 13 6 8 19 20 18 2 12 14 3 10 6 2 6 2 17 
+16 2 5 21 5 17 19 7 8 11 15 ^
+33 0 12 17 14 18 15 16 16 16 12 20 13 2 5 5 2 10 20 16 12 10 2 17 21 20 15 14 
+14 18 21 13 9 17 10 ^
+40 1 2 12 16 17 3 9 19 5 7 10 5 11 17 18 14 14 12 2 20 15 8 17 3 20 11 12 18 7 
+12 7 9 8 3 18 14 3 5 17 9 14 ^
+43 0 8 21 11 8 8 16 21 12 5 8 7 20 10 14 7 1 9 5 4 5 2 21 12 1 1 9 20 14 11 9 
+19 16 3 1 14 10 2 8 20 18 7 8 18 ^
+40 1 2 19 6 11 18 11 15 6 5 16 14 9 7 21 3 15 21 16 8 7 3 6 14 17 17 5 10 20 10 
+15 10 1 15 18 6 10 9 7 16 6 ^
+39 0 11 15 12 2 9 1 1 6 6 13 8 20 6 18 8 5 8 1 1 17 20 20 19 17 13 14 17 12 5 3 
+18 20 20 11 18 15 13 16 7 ^
+48 1 7 10 1 19 10 7 17 7 16 3 8 4 4 15 17 13 9 11 2 2 11 7 13 4 17 7 1 5 13 19 
+16 5 14 16 2 11 18 5 11 6 4 7 3 17 2 1 18 12 ^
+41 1 21 18 3 5 16 6 11 2 8 8 7 14 13 21 6 14 12 6 12 19 14 3 16 3 2 7 11 14 8 
+16 10 19 12 19 4 5 6 13 19 12 13 ^
+44 1 7 5 12 4 13 21 2 5 17 15 15 1 13 5 21 6 4 12 14 15 5 18 12 1 19 2 14 1 8 8 
+11 6 20 10 3 21 8 20 2 4 1 16 11 21 ^
+42 1 5 3 8 16 15 8 12 14 20 16 18 7 2 18 2 18 19 7 4 19 3 1 20 7 15 1 4 5 12 10 
+19 6 11 4 4 9 20 20 8 2 20 18 ^
+42 1 19 2 8 4 15 7 2 2 6 18 20 16 1 18 17 13 3 14 2 1 2 10 14 19 12 9 15 20 1 7 
+15 17 7 12 18 1 15 14 8 21 21 5 ^
+43 1 7 20 10 11 10 1 9 21 7 5 1 12 15 2 9 17 4 13 5 4 11 21 14 13 3 20 21 1 3 
+12 18 11 4 14 20 5 3 14 13 15 9 21 3 ^
+40 1 19 8 1 5 9 5 9 16 17 9 6 12 6 16 7 4 3 1 21 16 19 15 18 17 17 17 21 13 20 
+9 6 6 9 1 13 17 21 1 9 14 ^
+36 0 11 12 13 18 19 19 15 12 20 2 16 12 9 21 17 16 8 2 14 6 4 1 6 16 15 19 19 
+21 9 13 18 3 16 8 13 11 ^
+47 0 21 15 4 21 4 2 3 8 15 19 8 6 16 2 15 3 12 3 11 3 17 12 21 6 3 4 13 1 12 4 
+10 2 6 7 6 9 12 21 10 10 11 2 13 19 2 14 17 ^
+44 1 11 8 10 19 1 11 11 9 3 13 15 4 3 18 9 14 5 15 18 5 6 17 11 19 2 4 12 8 18 
+12 17 3 4 8 5 19 16 16 6 1 13 1 18 18 ^
+39 1 10 18 15 11 5 1 17 4 17 19 11 18 21 9 2 10 10 5 5 20 18 13 5 15 3 6 3 10 
+10 16 13 13 14 16 20 19 11 16 8 ^
+42 1 6 8 15 13 11 13 15 18 11 20 17 20 4 16 10 14 1 4 16 4 17 8 3 7 7 18 16 20 
+2 9 9 4 20 7 16 4 11 4 10 6 20 4 ^
+41 0 17 6 19 17 2 15 6 5 7 4 8 11 16 9 10 15 20 12 15 8 6 17 5 9 3 3 4 19 20 12 
+5 19 21 5 21 11 14 19 1 17 6 ^
+39 0 9 4 19 3 17 1 14 21 14 7 6 5 20 14 21 20 4 6 21 7 11 20 12 9 11 6 16 18 18 
+10 11 20 6 12 11 5 7 21 3 ^
+43 1 18 6 15 21 10 4 14 9 19 10 3 3 5 13 1 8 12 3 13 9 7 10 17 10 6 8 3 17 18 3 
+21 19 6 17 15 4 9 15 9 15 14 4 18 ^
+45 1 14 8 10 13 4 11 10 7 6 21 1 14 5 11 7 7 2 13 13 3 9 13 8 14 9 3 7 18 4 9 9 
+5 15 13 17 10 15 16 20 8 19 9 10 9 13 ^
+40 1 19 14 21 2 18 13 10 4 18 16 4 21 15 10 18 19 3 12 12 14 4 13 11 1 11 1 10 
+2 12 4 21 10 21 18 9 2 16 7 20 7 ^
+41 0 7 12 19 20 1 13 12 10 8 21 15 7 19 13 6 8 19 20 18 2 12 14 3 10 6 2 6 2 17 
+16 2 5 21 5 17 19 7 8 11 10 21 ^
+35 0 17 14 18 15 16 16 16 12 20 13 2 5 5 2 10 20 16 12 10 2 17 21 20 15 14 14 
+18 21 13 9 17 21 2 12 10 ^
+40 0 17 3 9 19 5 7 10 5 11 17 18 14 14 12 2 20 15 8 17 3 20 11 12 18 7 12 7 9 8 
+3 18 14 3 5 17 9 18 8 21 20 ^
+46 1 8 8 16 21 12 5 8 7 20 10 14 7 1 9 5 4 5 2 21 12 1 1 9 20 14 11 9 19 16 3 1 
+14 10 2 8 20 18 7 8 15 2 19 6 11 18 10 ^
+44 1 15 6 5 16 14 9 7 21 3 15 21 16 8 7 3 6 14 17 17 5 10 20 10 15 10 1 15 18 6 
+10 9 7 16 14 11 15 12 2 9 1 1 6 6 19 ^
+38 1 8 20 6 18 8 5 8 1 1 17 20 20 19 17 13 14 17 12 5 3 18 20 20 11 18 15 13 16 
+13 7 10 1 19 10 7 17 7 15 ^
+50 0 3 8 4 4 15 17 13 9 11 2 2 11 7 13 4 17 7 1 5 13 19 16 5 14 16 2 11 18 5 11 
+6 4 7 3 17 2 1 18 13 21 18 3 5 16 6 11 2 8 8 18 ^
+42 1 14 13 21 6 14 12 6 12 19 14 3 16 3 2 7 11 14 8 16 10 19 12 19 4 5 6 13 19 
+12 13 7 5 12 4 13 21 2 5 17 15 15 12 ^
+45 1 13 5 21 6 4 12 14 15 5 18 12 1 19 2 14 1 8 8 11 6 20 10 3 21 8 20 2 4 1 16 
+11 1 5 3 8 16 15 8 12 14 20 16 18 7 18 ^
+46 0 18 2 18 19 7 4 19 3 1 20 7 15 1 4 5 12 10 19 6 11 4 4 9 20 20 8 2 20 3 19 
+2 8 4 15 7 2 2 6 18 20 16 1 18 17 13 14 ^
+43 1 14 2 1 2 10 14 19 12 9 15 20 1 7 15 17 7 12 18 1 15 14 8 21 21 19 7 20 10 
+11 10 1 9 21 7 5 1 12 15 2 9 17 4 19 ^
+45 1 5 4 11 21 14 13 3 20 21 1 3 12 18 11 4 14 20 5 3 14 13 15 9 21 11 19 8 1 5 
+9 5 9 16 17 9 6 12 6 16 7 4 3 1 21 15 ^
+35 0 19 15 18 17 17 17 21 13 20 9 6 6 9 1 13 17 21 1 9 16 11 12 13 18 19 19 15 
+12 20 2 16 12 9 21 12 ^
+44 1 16 8 2 14 6 4 1 6 16 15 19 19 21 9 13 18 3 16 8 13 21 15 4 21 4 2 3 8 15 
+19 8 6 16 2 15 3 12 3 11 3 17 12 21 9 ^
+48 0 3 4 13 1 12 4 10 2 6 7 6 9 12 21 10 10 11 2 13 19 2 14 17 11 8 10 19 1 11 
+11 9 3 13 15 4 3 18 9 14 5 15 18 5 6 17 11 19 15 ^
+44 0 4 12 8 18 12 17 3 4 8 5 19 16 16 6 1 13 1 18 1 10 18 15 11 5 1 17 4 17 19 
+11 18 21 9 2 10 10 5 5 20 18 13 5 15 18 ^
+39 1 6 3 10 10 16 13 13 14 16 20 19 11 16 21 6 8 15 13 11 13 15 18 11 20 17 20 
+4 16 10 14 1 4 16 4 17 8 3 7 21 ^
+46 1 18 16 20 2 9 9 4 20 7 16 4 11 4 10 6 20 14 17 6 19 17 2 15 6 5 7 4 8 11 16 
+9 10 15 20 12 15 8 6 17 5 9 3 3 4 19 3 ^
+40 0 12 5 19 21 5 21 11 14 19 1 17 8 9 4 19 3 17 1 14 21 14 7 6 5 20 14 21 20 4 
+6 21 7 11 20 12 9 11 6 16 11 ^
+44 0 18 10 11 20 6 12 11 5 7 21 19 18 6 15 21 10 4 14 9 19 10 3 3 5 13 1 8 12 3 
+13 9 7 10 17 10 6 8 3 17 18 3 21 19 8 ^
+47 0 4 12 22 5 11 20 16 15 4 17 22 1 8 16 11 6 13 18 3 14 8 13 2 19 16 1 19 1 5 
+3 16 9 8 20 7 5 1 11 15 2 3 17 3 12 7 4 19 ^
+42 0 18 16 13 7 1 19 5 12 18 12 6 15 19 4 4 9 13 13 8 17 13 18 12 2 8 4 7 17 17 
+14 11 13 1 16 11 2 21 3 22 17 16 11 ^
+39 0 18 22 12 20 17 13 1 7 10 7 20 11 1 7 8 14 14 12 15 13 15 18 15 11 18 1 17 
+14 15 20 16 20 8 2 17 10 4 21 2 ^
+44 1 19 19 14 22 21 18 13 14 1 3 12 11 11 4 22 13 5 18 7 21 9 22 19 12 8 16 5 
+17 5 9 1 2 9 6 12 6 1 7 4 3 15 1 14 16 ^
+42 1 12 3 10 2 10 14 21 13 17 6 6 17 1 21 2 14 16 17 9 11 20 21 11 12 12 8 20 
+13 2 9 20 9 14 10 1 16 2 22 6 4 16 18 ^
+51 0 15 1 12 4 14 9 21 3 3 9 8 21 15 14 8 4 14 4 2 3 8 12 8 6 1 2 18 20 15 3 19 
+3 10 20 14 6 3 4 21 1 12 4 18 2 6 7 6 9 20 14 13 ^
+40 1 10 19 17 21 12 15 17 7 10 11 8 10 12 1 19 19 9 18 21 4 18 11 9 22 5 15 8 
+15 3 5 6 2 19 12 17 4 20 8 11 20 ^
+45 0 2 18 4 16 20 12 9 9 6 16 21 16 3 16 18 3 19 5 16 2 4 2 12 11 15 11 14 17 2 
+10 18 5 5 13 3 21 5 3 6 18 18 10 1 21 15 ^
+45 1 7 1 13 12 19 1 14 6 8 21 19 21 11 19 13 2 13 4 1 10 22 16 4 9 4 10 16 3 7 
+15 11 9 13 17 15 9 9 15 4 13 15 9 4 19 9 ^
+46 0 18 6 13 22 10 6 12 2 17 15 6 5 7 4 8 11 1 9 10 8 5 20 16 6 10 5 17 3 3 19 
+12 13 20 5 12 14 5 14 11 22 12 16 10 8 9 16 ^
+39 0 15 12 3 2 16 22 14 22 7 6 5 13 22 14 13 4 6 14 7 11 13 20 9 19 6 9 11 11 
+18 19 13 6 20 19 20 7 22 12 12 ^
+41 0 6 14 18 19 7 17 12 10 3 18 15 5 21 16 8 20 3 21 9 15 18 10 15 10 6 8 18 2 
+11 3 14 4 6 10 19 9 8 17 8 22 20 ^
+36 1 7 22 16 18 21 4 11 10 15 6 22 16 22 5 19 15 7 7 2 21 21 3 17 21 16 22 9 3 
+7 11 4 17 17 20 21 21 ^
+37 1 18 9 5 8 12 17 18 17 16 12 22 14 17 11 21 10 4 3 1 4 14 10 11 4 3 20 20 22 
+19 21 19 16 19 16 10 17 17 ^
+40 1 19 14 18 14 3 9 17 1 7 13 6 7 15 20 12 13 16 21 20 10 8 22 7 12 21 6 16 4 
+13 11 2 12 15 22 3 18 6 17 6 22 ^
+42 0 10 9 2 5 22 5 10 4 7 8 19 10 20 10 22 11 8 1 9 1 20 13 21 17 5 5 17 10 13 
+9 20 18 17 2 14 13 22 22 3 14 21 10 ^
+46 0 2 14 2 20 1 10 18 9 12 5 7 18 20 19 10 11 22 7 12 2 13 8 8 2 3 13 19 20 3 
+7 20 7 9 8 3 11 22 3 5 10 9 11 16 14 19 16 ^
+46 1 15 8 1 14 20 5 8 7 13 10 22 7 16 9 5 4 5 2 14 20 1 1 15 17 13 22 19 17 4 1 
+3 1 22 10 15 15 2 16 13 11 7 16 17 12 6 20 ^
+40 1 3 19 8 6 5 9 15 22 17 7 14 18 14 9 16 7 18 14 22 2 2 5 18 13 18 8 18 16 8 
+11 15 6 18 9 7 9 22 19 20 15 ^
+44 0 9 16 16 6 6 21 8 13 6 11 8 5 16 16 1 10 13 13 4 10 21 22 15 10 20 5 3 3 13 
+15 13 11 11 15 21 1 21 7 10 1 12 18 7 20 ^
+51 0 7 1 18 8 4 19 2 21 17 19 2 2 19 7 21 19 2 7 15 15 16 5 21 12 1 5 22 1 17 
+19 11 5 11 6 4 7 3 10 2 1 3 6 14 11 18 5 1 6 11 17 8 ^
+39 1 8 15 22 21 14 6 22 20 6 20 12 22 18 1 3 2 7 19 22 8 9 18 4 20 12 4 5 6 21 
+12 20 21 7 5 20 4 21 14 14 ^
+45 0 15 5 2 16 15 21 5 14 15 6 4 12 22 5 11 20 16 15 4 17 22 1 8 16 11 6 13 18 
+3 14 8 13 2 19 16 1 19 1 5 3 16 9 8 20 14 ^
+48 1 5 1 11 15 2 3 17 3 12 7 4 12 18 16 13 7 1 19 5 12 18 12 6 15 19 4 4 9 13 
+13 8 17 13 18 12 2 8 4 7 17 17 14 11 13 1 16 11 22 ^
+38 0 21 3 22 17 16 17 18 22 12 20 17 13 1 7 10 7 20 11 1 7 8 14 14 12 15 13 15 
+18 15 11 18 1 17 14 15 20 16 10 ^
+43 0 8 2 17 10 4 21 5 19 19 14 22 21 18 13 14 1 3 12 11 11 4 22 13 5 18 7 21 9 
+22 19 12 8 16 5 17 5 9 1 2 9 6 12 22 ^
+47 1 1 7 4 3 15 1 14 1 12 3 10 2 10 14 21 13 17 6 6 17 1 21 2 14 16 17 9 11 20 
+21 11 12 12 8 20 13 2 9 20 9 14 10 1 16 2 22 20 ^
+53 0 4 16 14 15 1 12 4 14 9 21 3 3 9 8 21 15 14 8 4 14 4 2 3 8 12 8 6 1 2 18 20 
+15 3 19 3 10 20 14 6 3 4 21 1 12 4 18 2 6 7 6 9 20 15 ^
+42 1 10 10 19 17 21 12 15 17 7 10 11 8 10 12 1 19 19 9 18 21 4 18 11 9 22 5 15 
+8 15 3 5 6 2 19 12 17 4 20 8 11 20 12 ^
+45 0 18 4 16 20 12 9 9 6 16 21 16 3 16 18 3 19 5 16 2 4 2 12 11 15 11 14 17 2 
+10 18 5 5 13 3 21 5 3 6 18 18 10 1 21 21 18 ^
+45 0 1 13 12 19 1 14 6 8 21 19 21 11 19 13 2 13 4 1 10 22 16 4 9 4 10 16 3 7 15 
+11 9 13 17 15 9 9 15 4 13 15 9 4 19 19 19 ^
+49 0 6 13 22 10 6 12 2 17 15 6 5 7 4 8 11 1 9 10 8 5 20 16 6 10 5 17 3 3 19 12 
+13 20 5 12 14 5 14 11 22 12 16 10 8 9 4 15 12 3 22 ^
+39 0 16 22 14 22 7 6 5 13 22 14 13 4 6 14 7 11 13 20 9 19 6 9 11 11 18 19 13 6 
+20 19 20 7 22 12 11 6 14 18 17 ^
+43 1 7 17 12 10 3 18 15 5 21 16 8 20 3 21 9 15 18 10 15 10 6 8 18 2 11 3 14 4 6 
+10 19 9 8 17 8 22 4 7 22 16 18 21 11 ^
+39 0 11 10 15 6 22 16 22 5 19 15 7 7 2 21 21 3 17 21 16 22 9 3 7 11 4 17 17 20 
+21 10 18 9 5 8 12 17 18 17 17 ^
+40 1 12 22 14 17 11 21 10 4 3 1 4 14 10 11 4 3 20 20 22 19 21 19 16 19 16 10 17 
+20 19 14 18 14 3 9 17 1 7 13 6 18 ^
+44 1 15 20 12 13 16 21 20 10 8 22 7 12 21 6 16 4 13 11 2 12 15 22 3 18 6 17 6 2 
+10 9 2 5 22 5 10 4 7 8 19 10 20 10 22 7 ^
+43 0 8 1 9 1 20 13 21 17 5 5 17 10 13 9 20 18 17 2 14 13 22 22 3 14 21 9 2 14 2 
+20 1 10 18 9 12 5 7 18 20 19 10 11 19 ^
+53 1 7 12 2 13 8 8 2 3 13 19 20 3 7 20 7 9 8 3 11 22 3 5 10 9 11 16 14 19 8 15 
+8 1 14 20 5 8 7 13 10 22 7 16 9 5 4 5 2 14 20 1 1 15 8 ^
+42 0 13 22 19 17 4 1 3 1 22 10 15 15 2 16 13 11 7 16 17 12 6 19 3 19 8 6 5 9 15 
+22 17 7 14 18 14 9 16 7 18 14 22 19 ^
+43 0 2 5 18 13 18 8 18 16 8 11 15 6 18 9 7 9 22 19 20 17 9 16 16 6 6 21 8 13 6 
+11 8 5 16 16 1 10 13 13 4 10 21 22 14 ^
+48 0 10 20 5 3 3 13 15 13 11 11 15 21 1 21 7 10 1 12 18 7 2 7 1 18 8 4 19 2 21 
+17 19 2 2 19 7 21 19 2 7 15 15 16 5 21 12 1 5 21 ^
+49 1 1 17 19 11 5 11 6 4 7 3 10 2 1 3 6 14 11 18 5 1 6 11 17 8 8 15 22 21 14 6 
+22 20 6 20 12 22 18 1 3 2 7 19 22 8 9 18 4 20 10 ^
+45 1 4 5 6 21 12 20 21 7 5 20 4 21 14 2 15 5 2 16 15 21 5 14 15 6 4 12 22 5 11 
+20 16 15 4 17 22 1 8 16 11 6 13 18 3 14 13 ^
+52 0 13 2 19 16 1 19 1 5 3 16 9 8 20 7 5 1 11 15 2 3 17 3 12 7 4 12 18 16 13 7 
+1 19 5 12 18 12 6 15 19 4 4 9 13 13 8 17 13 18 12 2 8 15 ^
+46 0 20 1 1 11 21 2 3 16 8 12 21 22 1 16 1 10 22 17 4 14 7 2 16 9 18 23 9 4 8 
+16 7 9 18 11 11 17 20 2 7 10 20 8 10 16 14 14 ^
+41 1 20 4 16 4 18 1 14 12 19 13 15 19 19 11 22 13 10 2 11 16 10 17 8 8 6 22 2 
+15 10 9 13 18 14 22 8 6 18 16 15 14 20 ^
+43 1 14 3 12 14 17 11 3 9 19 10 20 16 11 3 17 7 21 23 12 23 11 13 2 14 14 16 13 
+12 11 5 14 3 8 4 13 8 17 17 18 17 2 12 22 ^
+43 1 17 3 11 12 16 5 1 22 6 16 11 20 3 18 17 6 22 14 13 21 21 3 18 13 20 11 18 
+19 11 6 1 10 18 7 17 5 16 1 7 10 4 20 22 ^
+46 0 8 10 12 4 11 21 6 13 16 17 6 23 1 9 14 4 11 23 23 19 1 13 6 20 1 9 12 8 5 
+23 17 16 8 8 3 10 13 7 6 10 8 14 9 15 20 20 ^
+46 0 20 21 15 12 19 17 1 6 4 5 8 4 12 10 6 5 4 17 3 3 16 13 5 21 16 10 21 18 19 
+15 16 12 6 12 17 8 7 8 11 14 1 23 10 15 15 13 ^
+43 0 21 13 15 18 21 10 10 23 3 13 13 9 16 2 17 19 3 22 11 5 18 19 13 7 7 8 19 2 
+12 2 19 16 23 9 16 6 3 19 12 5 10 9 17 ^
+47 0 21 3 2 1 7 14 14 7 6 2 20 3 6 19 19 10 2 22 12 17 12 1 20 7 7 15 20 6 18 8 
+3 14 23 18 15 4 7 5 23 15 7 14 10 10 19 17 11 ^
+44 0 4 15 17 11 15 11 8 9 17 5 12 18 14 6 20 17 21 12 16 9 22 9 20 15 2 22 11 2 
+6 11 9 8 2 4 14 19 3 21 21 23 8 2 11 15 ^
+37 0 8 4 20 22 6 21 18 22 10 19 9 14 17 23 21 10 7 15 13 16 5 4 10 13 14 20 23 
+12 20 23 18 10 12 8 21 11 19 ^
+39 0 12 7 19 14 18 14 18 22 6 9 22 5 23 13 6 8 23 20 22 5 22 15 19 20 9 9 1 13 
+13 10 14 13 5 22 14 21 9 21 3 ^
+45 1 14 14 4 18 13 12 23 7 3 15 5 17 14 23 14 5 17 22 11 1 8 13 23 6 21 3 6 11 
+7 23 8 6 21 4 4 22 19 13 8 5 19 7 5 23 3 ^
+50 1 4 19 11 23 11 21 14 1 3 20 2 20 7 4 17 2 5 13 4 23 5 22 7 7 9 17 13 5 6 2 
+21 1 17 7 9 21 23 1 1 12 3 1 15 22 4 12 6 20 5 23 ^
+46 1 23 4 12 22 8 18 16 3 16 4 2 13 1 15 15 1 23 2 3 4 10 1 12 7 11 2 7 22 22 
+21 22 13 3 12 22 12 4 3 23 10 14 17 15 9 23 20 ^
+44 0 19 12 21 22 9 17 12 2 18 18 12 21 2 19 4 21 20 4 9 14 5 21 8 22 10 15 23 
+14 8 5 11 19 5 7 5 3 11 4 15 18 9 2 23 4 ^
+46 0 9 16 14 15 6 15 1 11 4 16 16 20 14 2 9 19 14 6 3 7 10 16 22 23 7 7 12 5 2 
+8 9 5 7 1 17 19 21 19 18 15 3 20 22 14 9 16 ^
+44 1 10 18 11 3 5 9 10 11 22 12 12 15 23 2 10 18 23 5 18 21 20 23 3 9 3 22 7 8 
+7 4 1 14 16 16 13 18 2 21 18 15 5 5 16 21 ^
+46 0 2 2 6 23 13 22 20 12 17 4 10 21 2 20 2 8 8 7 20 13 3 20 23 16 6 23 9 12 20 
+3 10 5 6 19 18 12 13 14 8 1 1 8 9 13 19 23 ^
+47 0 9 20 20 5 15 13 17 3 15 22 3 1 19 8 15 8 19 9 21 7 12 1 16 21 11 8 10 15 
+16 8 1 5 5 20 22 13 11 22 4 4 7 6 22 10 3 21 4 ^
+45 1 9 19 22 18 3 23 6 4 6 19 15 13 17 4 13 9 15 4 6 7 13 11 1 20 15 12 18 18 
+16 7 13 4 11 7 11 6 17 9 18 15 21 17 5 20 11 ^
+49 0 1 22 16 18 5 8 11 2 23 10 11 5 2 1 19 16 3 19 16 15 21 5 3 7 18 4 9 15 3 8 
+20 1 21 1 21 17 9 6 17 10 16 2 9 7 16 19 15 17 9 ^
+51 0 17 20 19 6 6 14 2 2 5 1 2 10 17 1 18 6 18 20 1 1 11 21 2 3 16 8 12 21 22 1 
+16 1 10 22 17 4 14 7 2 16 9 18 23 9 4 8 16 7 9 18 17 ^
+45 1 11 17 20 2 7 10 20 8 10 16 14 11 20 4 16 4 18 1 14 12 19 13 15 19 19 11 22 
+13 10 2 11 16 10 17 8 8 6 22 2 15 10 9 13 18 8 ^
+44 0 22 8 6 18 16 15 14 15 14 3 12 14 17 11 3 9 19 10 20 16 11 3 17 7 21 23 12 
+23 11 13 2 14 14 16 13 12 11 5 14 3 8 4 13 20 ^
+43 0 17 17 18 17 2 12 3 17 3 11 12 16 5 1 22 6 16 11 20 3 18 17 6 22 14 13 21 
+21 3 18 13 20 11 18 19 11 6 1 10 18 7 17 20 ^
+50 1 16 1 7 10 4 20 10 8 10 12 4 11 21 6 13 16 17 6 23 1 9 14 4 11 23 23 19 1 
+13 6 20 1 9 12 8 5 23 17 16 8 8 3 10 13 7 6 10 8 14 17 ^
+46 1 15 20 18 20 21 15 12 19 17 1 6 4 5 8 4 12 10 6 5 4 17 3 3 16 13 5 21 16 10 
+21 18 19 15 16 12 6 12 17 8 7 8 11 14 1 23 21 ^
+45 0 15 15 2 21 13 15 18 21 10 10 23 3 13 13 9 16 2 17 19 3 22 11 5 18 19 13 7 
+7 8 19 2 12 2 19 16 23 9 16 6 3 19 12 5 10 15 ^
+48 1 20 21 3 2 1 7 14 14 7 6 2 20 3 6 19 19 10 2 22 12 17 12 1 20 7 7 15 20 6 
+18 8 3 14 23 18 15 4 7 5 23 15 7 14 10 10 19 17 12 ^
+47 0 4 15 17 11 15 11 8 9 17 5 12 18 14 6 20 17 21 12 16 9 22 9 20 15 2 22 11 2 
+6 11 9 8 2 4 14 19 3 21 21 23 8 2 11 4 8 4 20 ^
+39 0 22 6 21 18 22 10 19 9 14 17 23 21 10 7 15 13 16 5 4 10 13 14 20 23 12 20 
+23 18 10 12 8 21 11 6 12 7 19 14 14 ^
+40 0 14 18 22 6 9 22 5 23 13 6 8 23 20 22 5 22 15 19 20 9 9 1 13 13 10 14 13 5 
+22 14 21 9 21 19 14 14 4 18 13 12 ^
+46 0 23 7 3 15 5 17 14 23 14 5 17 22 11 1 8 13 23 6 21 3 6 11 7 23 8 6 21 4 4 
+22 19 13 8 5 19 7 5 23 1 4 19 11 23 11 21 9 ^
+52 0 1 3 20 2 20 7 4 17 2 5 13 4 23 5 22 7 7 9 17 13 5 6 2 21 1 17 7 9 21 23 1 
+1 12 3 1 15 22 4 12 6 20 5 19 23 4 12 22 8 18 16 3 22 ^
+48 0 4 2 13 1 15 15 1 23 2 3 4 10 1 12 7 11 2 7 22 22 21 22 13 3 12 22 12 4 3 
+23 10 14 17 15 9 23 4 19 12 21 22 9 17 12 2 18 18 9 ^
+46 0 21 2 19 4 21 20 4 9 14 5 21 8 22 10 15 23 14 8 5 11 19 5 7 5 3 11 4 15 18 
+9 2 23 22 9 16 14 15 6 15 1 11 4 16 16 20 22 ^
+47 0 2 9 19 14 6 3 7 10 16 22 23 7 7 12 5 2 8 9 5 7 1 17 19 21 19 18 15 3 20 22 
+14 9 11 10 18 11 3 5 9 10 11 22 12 12 15 23 22 ^
+45 0 10 18 23 5 18 21 20 23 3 9 3 22 7 8 7 4 1 14 16 16 13 18 2 21 18 15 5 5 16 
+12 2 2 6 23 13 22 20 12 17 4 10 21 2 20 19 ^
+47 0 8 8 7 20 13 3 20 23 16 6 23 9 12 20 3 10 5 6 19 18 12 13 14 8 1 1 8 9 13 
+19 12 9 20 20 5 15 13 17 3 15 22 3 1 19 8 15 23 ^
+48 0 19 9 21 7 12 1 16 21 11 8 10 15 16 8 1 5 5 20 22 13 11 22 4 4 7 6 22 10 3 
+21 1 9 19 22 18 3 23 6 4 6 19 15 13 17 4 13 9 17 ^
+49 1 4 6 7 13 11 1 20 15 12 18 18 16 7 13 4 11 7 11 6 17 9 18 15 21 17 5 20 6 1 
+22 16 18 5 8 11 2 23 10 11 5 2 1 19 16 3 19 16 15 18 ^
+55 1 5 3 7 18 4 9 15 3 8 20 1 21 1 21 17 9 6 17 10 16 2 9 7 16 19 15 17 10 17 
+20 19 6 6 14 2 2 5 1 2 10 17 1 18 6 18 20 1 1 11 21 2 3 16 8 17 ^
+47 0 21 22 1 16 1 10 22 17 4 14 7 2 16 9 18 23 9 4 8 16 7 9 18 11 11 17 20 2 7 
+10 20 8 10 16 14 11 20 4 16 4 18 1 14 12 19 13 19 ^
+45 1 19 19 11 22 13 10 2 11 16 10 17 8 8 6 22 2 15 10 9 13 18 14 22 8 6 18 16 
+15 14 15 14 3 12 14 17 11 3 9 19 10 20 16 11 3 21 ^
+47 1 7 21 23 12 23 11 13 2 14 14 16 13 12 11 5 14 3 8 4 13 8 17 17 18 17 2 12 3 
+17 3 11 12 16 5 1 22 6 16 11 20 3 18 17 6 22 14 20 ^
+47 1 21 21 3 18 13 20 11 18 19 11 6 1 10 18 7 17 5 16 1 7 10 4 20 10 8 10 12 4 
+11 21 6 13 16 17 6 23 1 9 14 4 11 23 23 19 1 13 22 ^
+51 0 20 1 9 12 8 5 23 17 16 8 8 3 10 13 7 6 10 8 14 9 15 20 18 20 21 15 12 19 
+17 1 6 4 5 8 4 12 10 6 5 4 17 3 3 16 13 5 21 16 10 21 21 ^
+52 0 15 13 4 8 12 22 9 6 3 1 13 16 12 23 10 14 2 1 6 11 8 19 24 16 2 5 21 2 7 
+22 4 5 23 3 12 20 8 4 5 17 9 18 18 18 4 10 13 2 4 7 24 21 ^
+51 1 10 21 4 8 24 2 6 19 10 6 22 22 14 22 13 21 5 22 2 4 18 5 11 21 1 7 8 4 17 
+5 14 1 2 10 9 12 5 11 10 20 4 14 3 1 3 21 12 11 17 22 21 ^
+43 1 7 5 21 14 15 19 20 12 6 12 18 19 4 7 12 10 5 22 3 15 21 7 23 7 2 22 4 18 
+18 3 24 10 17 24 23 18 6 11 18 22 8 6 20 ^
+45 0 2 12 10 14 12 9 2 23 16 20 14 17 9 16 7 21 6 22 24 19 11 9 19 21 15 11 19 
+2 2 7 8 10 8 9 8 15 9 14 6 16 8 21 21 22 13 ^
+50 1 17 9 4 24 21 15 15 16 16 13 9 10 16 14 12 7 12 15 15 5 10 10 23 5 13 22 3 
+5 1 4 11 14 7 6 10 17 14 6 3 13 18 16 3 5 15 23 8 5 3 22 ^
+47 0 8 12 20 20 9 2 13 24 17 2 2 17 3 13 20 2 6 3 15 7 13 1 18 7 22 18 24 20 14 
+7 17 16 20 3 11 6 5 2 18 14 16 22 14 11 7 18 22 ^
+48 1 17 24 12 12 3 13 19 16 22 4 16 4 6 23 8 18 11 2 3 20 22 9 21 8 23 1 23 20 
+7 16 13 23 4 13 3 7 4 23 6 13 19 2 3 7 2 9 9 19 ^
+45 1 6 13 4 22 6 19 20 1 9 7 14 1 15 3 23 24 22 18 12 12 17 19 10 8 11 22 12 10 
+2 20 15 18 17 18 7 11 12 21 6 12 4 7 18 17 18 ^
+44 0 2 14 24 14 1 23 1 11 15 10 6 18 20 7 1 8 1 16 6 20 23 23 21 10 10 12 24 10 
+11 23 2 12 23 9 3 24 24 19 14 10 18 15 14 12 ^
+50 1 16 11 22 2 15 24 8 22 1 4 24 9 10 15 3 9 5 4 17 15 9 12 19 19 1 3 10 6 8 3 
+17 8 18 24 19 3 4 15 4 9 2 24 5 20 13 7 20 17 19 11 ^
+43 0 13 8 10 19 15 11 1 14 17 20 22 10 7 11 16 9 21 22 17 23 12 15 4 24 7 21 18 
+2 21 16 1 19 18 20 11 3 15 19 18 1 6 14 15 ^
+45 0 5 5 19 13 10 24 19 16 24 15 13 2 19 15 24 21 17 4 13 17 1 1 9 1 10 2 18 1 
+21 19 5 18 12 2 22 16 23 15 19 6 18 9 1 23 20 ^
+49 0 21 13 14 11 18 12 13 3 19 9 20 22 20 2 11 12 6 1 12 16 18 2 9 8 4 3 11 17 
+11 5 4 19 16 11 23 13 18 1 20 8 2 16 16 21 4 19 5 5 24 ^
+46 0 24 13 23 6 24 5 17 12 5 1 15 17 17 21 11 13 9 23 11 14 21 7 6 9 6 14 7 16 
+2 17 1 24 23 4 12 14 4 2 11 23 12 4 23 21 21 4 ^
+49 1 15 13 15 14 15 8 14 9 17 7 15 2 23 2 1 17 6 14 19 24 2 8 8 7 7 10 14 13 7 
+9 11 16 11 8 8 18 13 13 18 10 1 20 18 22 19 12 9 16 12 ^
+43 1 13 6 9 17 20 10 5 7 20 18 8 15 23 21 20 5 15 11 3 3 14 21 10 24 6 21 21 6 
+23 10 3 21 23 17 20 8 16 10 22 5 16 1 24 ^
+50 0 24 3 9 16 6 7 3 20 12 17 18 21 5 9 7 1 9 12 19 5 7 6 24 11 11 20 23 10 4 7 
+1 19 7 19 17 23 15 5 12 21 20 3 1 14 2 15 22 3 16 11 ^
+45 1 10 19 10 20 16 19 17 10 4 21 20 16 21 14 14 8 17 10 19 1 17 4 3 22 23 14 
+16 9 22 8 20 24 1 5 11 11 6 4 13 15 12 1 11 13 22 ^
+45 0 3 8 5 6 5 16 12 11 2 17 14 19 23 16 5 6 20 21 9 24 9 22 23 22 12 8 13 23 
+17 5 3 16 22 15 22 7 17 3 2 13 13 11 24 13 17 ^
+42 1 21 11 14 20 24 24 4 9 13 5 8 9 18 7 12 1 21 8 24 15 1 22 19 24 14 13 8 20 
+14 18 23 19 9 8 14 23 11 4 4 22 20 17 ^
+49 1 17 15 20 6 15 8 24 4 20 19 8 19 14 21 24 18 3 10 16 3 6 4 1 10 15 13 4 8 
+12 22 9 6 3 1 13 16 12 23 10 14 2 1 6 11 8 19 24 16 23 ^
+50 0 5 21 2 7 22 4 5 23 3 12 20 8 4 5 17 9 18 18 18 4 10 13 2 4 7 24 8 10 21 4 
+8 24 2 6 19 10 6 22 22 14 22 13 21 5 22 2 4 18 5 24 ^
+53 1 21 1 7 8 4 17 5 14 1 2 10 9 12 5 11 10 20 4 14 3 1 3 21 12 11 17 22 11 7 5 
+21 14 15 19 20 12 6 12 18 19 4 7 12 10 5 22 3 15 21 7 23 7 18 ^
+43 1 22 4 18 18 3 24 10 17 24 23 18 6 11 18 22 8 6 6 2 12 10 14 12 9 2 23 16 20 
+14 17 9 16 7 21 6 22 24 19 11 9 19 21 6 ^
+49 1 11 19 2 2 7 8 10 8 9 8 15 9 14 6 16 8 21 21 22 6 17 9 4 24 21 15 15 16 16 
+13 9 10 16 14 12 7 12 15 15 5 10 10 23 5 13 22 3 5 22 ^
+52 0 4 11 14 7 6 10 17 14 6 3 13 18 16 3 5 15 23 8 5 3 18 8 12 20 20 9 2 13 24 
+17 2 2 17 3 13 20 2 6 3 15 7 13 1 18 7 22 18 24 20 14 7 23 ^
+45 1 16 20 3 11 6 5 2 18 14 16 22 14 11 7 18 16 17 24 12 12 3 13 19 16 22 4 16 
+4 6 23 8 18 11 2 3 20 22 9 21 8 23 1 23 20 23 ^
+51 1 16 13 23 4 13 3 7 4 23 6 13 19 2 3 7 2 9 9 15 6 13 4 22 6 19 20 1 9 7 14 1 
+15 3 23 24 22 18 12 12 17 19 10 8 11 22 12 10 2 20 15 15 ^
+48 1 17 18 7 11 12 21 6 12 4 7 18 17 3 2 14 24 14 1 23 1 11 15 10 6 18 20 7 1 8 
+1 16 6 20 23 23 21 10 10 12 24 10 11 23 2 12 23 9 20 ^
+49 1 24 24 19 14 10 18 15 14 5 16 11 22 2 15 24 8 22 1 4 24 9 10 15 3 9 5 4 17 
+15 9 12 19 19 1 3 10 6 8 3 17 8 18 24 19 3 4 15 4 24 ^
+43 0 2 24 5 20 13 7 20 17 19 22 13 8 10 19 15 11 1 14 17 20 22 10 7 11 16 9 21 
+22 17 23 12 15 4 24 7 21 18 2 21 16 1 19 11 ^
+48 1 20 11 3 15 19 18 1 6 14 5 5 5 19 13 10 24 19 16 24 15 13 2 19 15 24 21 17 
+4 13 17 1 1 9 1 10 2 18 1 21 19 5 18 12 2 22 16 23 19 ^
+50 1 19 6 18 9 1 23 22 21 13 14 11 18 12 13 3 19 9 20 22 20 2 11 12 6 1 12 16 
+18 2 9 8 4 3 11 17 11 5 4 19 16 11 23 13 18 1 20 8 2 16 16 ^
+48 1 16 21 4 19 5 5 20 24 13 23 6 24 5 17 12 5 1 15 17 17 21 11 13 9 23 11 14 
+21 7 6 9 6 14 7 16 2 17 1 24 23 4 12 14 4 2 11 23 15 ^
+50 1 4 23 21 21 16 15 13 15 14 15 8 14 9 17 7 15 2 23 2 1 17 6 14 19 24 2 8 8 7 
+7 10 14 13 7 9 11 16 11 8 8 18 13 13 18 10 1 20 18 22 3 ^
+44 1 12 9 16 17 13 6 9 17 20 10 5 7 20 18 8 15 23 21 20 5 15 11 3 3 14 21 10 24 
+6 21 21 6 23 10 3 21 23 17 20 8 16 10 22 12 ^
+53 0 16 1 5 24 3 9 16 6 7 3 20 12 17 18 21 5 9 7 1 9 12 19 5 7 6 24 11 11 20 23 
+10 4 7 1 19 7 19 17 23 15 5 12 21 20 3 1 14 2 15 22 3 16 9 ^
+46 1 10 19 10 20 16 19 17 10 4 21 20 16 21 14 14 8 17 10 19 1 17 4 3 22 23 14 
+16 9 22 8 20 24 1 5 11 11 6 4 13 15 12 1 11 13 21 21 ^
+46 0 8 5 6 5 16 12 11 2 17 14 19 23 16 5 6 20 21 9 24 9 22 23 22 12 8 13 23 17 
+5 3 16 22 15 22 7 17 3 2 13 13 11 24 13 12 21 7 ^
+43 1 14 20 24 24 4 9 13 5 8 9 18 7 12 1 21 8 24 15 1 22 19 24 14 13 8 20 14 18 
+23 19 9 8 14 23 11 4 4 22 20 13 17 15 24 ^
+55 0 6 15 8 24 4 20 19 8 19 14 21 24 18 3 10 16 3 6 4 1 10 15 13 4 8 12 22 9 6 
+3 1 13 16 12 23 10 14 2 1 6 11 8 19 24 16 2 5 21 2 7 22 4 5 23 4 ^
+55 1 12 20 8 4 5 17 9 18 18 18 4 10 13 2 4 7 24 8 10 21 4 8 24 2 6 19 10 6 22 
+22 14 22 13 21 5 22 2 4 18 5 11 21 1 7 8 4 17 5 14 1 2 10 9 12 14 ^
+49 0 11 10 20 4 14 3 1 3 21 12 11 17 22 11 7 5 21 14 15 19 20 12 6 12 18 19 4 7 
+12 10 5 22 3 15 21 7 23 7 2 22 4 18 18 3 24 10 17 24 12 ^
+50 0 18 6 11 18 22 8 6 6 2 12 10 14 12 9 2 23 16 20 14 17 9 16 7 21 6 22 24 19 
+11 9 19 21 15 11 19 2 2 7 8 10 8 9 8 15 9 14 6 16 8 22 ^
+51 1 21 22 6 17 9 4 24 21 15 15 16 16 13 9 10 16 14 12 7 12 15 15 5 10 10 23 5 
+13 22 3 5 1 4 11 14 7 6 10 17 14 6 3 13 18 16 3 5 15 23 8 21 ^
+51 1 5 3 18 8 12 20 20 9 2 13 24 17 2 2 17 3 13 20 2 6 3 15 7 13 1 18 7 22 18 
+24 20 14 7 17 16 20 3 11 6 5 2 18 14 16 22 14 11 7 18 16 20 ^
+52 0 24 12 12 3 13 19 16 22 4 16 4 6 23 8 18 11 2 3 20 22 9 21 8 23 1 23 20 7 
+16 13 23 4 13 3 7 4 23 6 13 19 2 3 7 2 9 9 15 6 13 4 22 16 ^
+49 1 19 20 1 9 7 14 1 15 3 23 24 22 18 12 12 17 19 10 8 11 22 12 10 2 20 15 18 
+17 18 7 11 12 21 6 12 4 7 18 17 3 2 14 24 14 1 23 1 11 16 ^
+47 0 10 6 18 20 7 1 8 1 16 6 20 23 23 21 10 10 12 24 10 11 23 2 12 23 9 3 24 24 
+19 14 10 18 15 14 5 16 11 22 2 15 24 8 22 1 4 24 3 ^
+45 0 17 6 24 11 7 21 9 17 8 25 5 5 22 16 13 5 2 16 4 25 25 8 18 13 13 3 1 22 23 
+24 18 12 21 19 2 4 24 13 11 2 7 24 22 17 21 ^
+46 1 15 1 8 3 10 15 18 15 8 10 16 20 20 7 18 22 11 18 9 11 15 22 20 18 6 24 15 
+25 4 22 12 17 4 6 17 20 2 4 2 5 20 15 19 24 18 15 ^
+52 1 8 2 5 23 2 10 21 8 5 2 9 16 16 15 6 22 23 5 6 21 5 21 24 3 6 10 17 19 9 15 
+11 23 16 17 1 3 12 3 20 4 5 5 3 21 22 15 4 21 20 7 22 18 ^
+43 0 9 24 4 18 7 7 25 24 22 21 23 24 14 20 12 6 7 4 2 12 25 15 3 9 23 8 16 25 
+11 14 4 10 19 23 16 13 9 20 25 17 11 8 19 ^
+55 0 19 25 17 7 16 21 6 4 8 2 15 9 2 9 19 3 6 3 3 10 25 13 15 7 8 20 21 12 10 
+12 5 24 11 20 3 13 13 16 9 13 10 3 9 16 3 7 15 9 9 14 2 13 17 25 3 ^
+46 0 18 5 19 23 9 25 9 10 23 12 12 7 13 8 15 7 1 6 21 2 8 7 6 16 14 14 12 15 13 
+24 10 15 11 10 8 14 15 21 25 21 16 9 18 20 22 21 ^
+50 1 20 11 14 23 22 10 13 14 8 19 12 2 11 20 23 13 4 10 6 5 7 23 11 3 16 8 21 4 
+8 18 5 12 14 8 6 20 19 24 8 23 17 3 7 19 1 18 1 14 22 11 ^
+44 1 14 5 8 22 18 14 25 17 11 12 22 2 12 12 16 12 13 18 17 12 17 14 18 8 25 9 
+23 5 3 8 14 24 17 7 3 3 23 17 22 19 19 17 16 19 ^
+51 0 24 14 16 20 23 20 9 19 16 7 12 16 5 8 9 7 10 21 24 10 11 19 1 21 14 14 19 
+3 22 8 12 20 1 18 5 6 5 12 14 1 1 11 9 22 3 24 9 6 1 11 20 ^
+47 0 1 12 8 11 11 17 10 22 7 3 10 2 6 4 24 16 24 19 4 5 18 11 12 9 20 21 25 2 
+21 18 10 20 25 21 3 17 17 5 8 22 25 19 8 10 19 7 25 ^
+55 1 4 8 18 3 18 3 11 24 2 14 9 1 10 4 4 13 19 22 4 7 19 5 10 10 1 8 22 22 6 8 
+13 12 11 17 23 14 16 7 5 11 22 24 7 2 11 13 18 4 20 8 1 6 25 20 16 ^
+51 1 20 1 25 10 15 15 2 17 13 9 24 17 24 20 13 15 17 3 11 20 10 5 13 23 18 5 3 
+18 15 7 5 7 4 15 20 16 2 17 1 7 4 12 7 25 14 1 4 7 19 19 22 ^
+52 0 3 13 12 4 3 14 4 14 11 6 3 25 18 16 20 24 12 19 18 25 6 23 6 15 5 4 4 6 14 
+13 20 5 14 15 2 13 21 11 5 17 2 2 10 11 13 14 12 11 21 15 23 20 ^
+50 1 2 5 7 23 10 20 6 12 1 19 10 24 21 22 25 16 12 19 22 15 10 18 24 1 5 16 10 
+18 2 19 14 3 5 1 7 20 7 16 6 20 6 6 25 10 22 20 2 1 15 18 ^
+48 0 23 25 23 4 11 15 15 6 9 22 22 19 22 25 6 19 6 2 20 21 7 22 18 10 7 17 4 16 
+12 10 25 12 23 23 9 2 22 1 20 2 8 3 14 7 1 2 3 24 ^
+38 1 21 21 23 20 22 11 25 20 24 25 1 9 21 20 14 10 14 19 9 17 15 13 5 15 24 21 
+12 13 25 22 21 1 16 23 7 24 15 22 ^
+54 1 22 5 25 3 4 2 9 12 24 6 19 1 14 9 5 9 1 17 9 4 23 21 1 3 15 16 11 1 12 18 
+6 2 7 8 17 8 21 13 22 9 21 4 9 1 13 17 21 10 9 18 24 23 13 24 ^
+43 1 23 23 19 23 22 17 18 23 18 21 17 1 10 12 4 6 1 21 11 18 2 6 6 12 18 13 16 
+16 18 19 13 11 21 19 15 12 15 16 19 2 23 19 23 ^
+48 0 1 2 25 14 11 25 24 16 8 14 21 21 16 6 13 1 23 15 8 17 4 3 4 9 23 12 8 8 24 
+13 6 11 3 8 24 19 8 23 1 24 24 18 25 13 2 6 25 14 ^
+51 1 9 3 5 11 19 11 16 5 4 17 24 23 15 14 10 7 14 17 25 15 10 14 6 18 18 4 1 13 
+10 16 1 25 16 2 24 5 1 17 6 17 6 24 11 7 21 9 17 8 25 5 23 ^
+48 1 22 16 13 5 2 16 4 25 25 8 18 13 13 3 1 22 23 24 18 12 21 19 2 4 24 13 11 2 
+7 24 22 17 5 15 1 8 3 10 15 18 15 8 10 16 20 20 7 25 ^
+49 0 22 11 18 9 11 15 22 20 18 6 24 15 25 4 22 12 17 4 6 17 20 2 4 2 5 20 15 19 
+24 18 9 8 2 5 23 2 10 21 8 5 2 9 16 16 15 6 22 23 17 ^
+47 1 6 21 5 21 24 3 6 10 17 19 9 15 11 23 16 17 1 3 12 3 20 4 5 5 3 21 22 15 4 
+21 20 7 22 14 9 24 4 18 7 7 25 24 22 21 23 24 14 ^
+53 0 20 12 6 7 4 2 12 25 15 3 9 23 8 16 25 11 14 4 10 19 23 16 13 9 20 25 17 11 
+8 4 19 25 17 7 16 21 6 4 8 2 15 9 2 9 19 3 6 3 3 10 25 13 15 ^
+54 1 7 8 20 21 12 10 12 5 24 11 20 3 13 13 16 9 13 10 3 9 16 3 7 15 9 9 14 2 13 
+17 25 2 18 5 19 23 9 25 9 10 23 12 12 7 13 8 15 7 1 6 21 2 8 25 ^
+44 1 6 16 14 14 12 15 13 24 10 15 11 10 8 14 15 21 25 21 16 9 18 20 22 21 20 11 
+14 23 22 10 13 14 8 19 12 2 11 20 23 13 4 10 6 25 ^
+49 1 7 23 11 3 16 8 21 4 8 18 5 12 14 8 6 20 19 24 8 23 17 3 7 19 1 18 1 14 22 
+13 14 5 8 22 18 14 25 17 11 12 22 2 12 12 16 12 13 18 25 ^
+45 1 12 17 14 18 8 25 9 23 5 3 8 14 24 17 7 3 3 23 17 22 19 19 17 16 22 24 14 
+16 20 23 20 9 19 16 7 12 16 5 8 9 7 10 21 24 7 ^
+58 0 11 19 1 21 14 14 19 3 22 8 12 20 1 18 5 6 5 12 14 1 1 11 9 22 3 24 9 6 1 
+11 16 1 12 8 11 11 17 10 22 7 3 10 2 6 4 24 16 24 19 4 5 18 11 12 9 20 21 7 ^
+54 1 2 21 18 10 20 25 21 3 17 17 5 8 22 25 19 8 10 19 7 11 4 8 18 3 18 3 11 24 
+2 14 9 1 10 4 4 13 19 22 4 7 19 5 10 10 1 8 22 22 6 8 13 12 11 21 ^
+47 1 23 14 16 7 5 11 22 24 7 2 11 13 18 4 20 8 1 6 25 20 17 20 1 25 10 15 15 2 
+17 13 9 24 17 24 20 13 15 17 3 11 20 10 5 13 23 18 21 ^
+57 1 3 18 15 7 5 7 4 15 20 16 2 17 1 7 4 12 7 25 14 1 4 7 19 19 20 3 13 12 4 3 
+14 4 14 11 6 3 25 18 16 20 24 12 19 18 25 6 23 6 15 5 4 4 6 14 13 20 7 ^
+51 1 14 15 2 13 21 11 5 17 2 2 10 11 13 14 12 11 21 15 23 3 2 5 7 23 10 20 6 12 
+1 19 10 24 21 22 25 16 12 19 22 15 10 18 24 1 5 16 10 18 2 19 8 ^
+49 0 3 5 1 7 20 7 16 6 20 6 6 25 10 22 20 2 1 15 14 23 25 23 4 11 15 15 6 9 22 
+22 19 22 25 6 19 6 2 20 21 7 22 18 10 7 17 4 16 12 24 ^
+46 0 10 25 12 23 23 9 2 22 1 20 2 8 3 14 7 1 2 3 19 21 21 23 20 22 11 25 20 24 
+25 1 9 21 20 14 10 14 19 9 17 15 13 5 15 24 21 14 ^
+55 0 13 25 22 21 1 16 23 7 24 15 3 22 5 25 3 4 2 9 12 24 6 19 1 14 9 5 9 1 17 9 
+4 23 21 1 3 15 16 11 1 12 18 6 2 7 8 17 8 21 13 22 9 21 4 9 22 ^
+45 1 13 17 21 10 9 18 24 23 13 7 23 23 19 23 22 17 18 23 18 21 17 1 10 12 4 6 1 
+21 11 18 2 6 6 12 18 13 16 16 18 19 13 11 21 19 8 ^
+50 1 12 15 16 19 2 23 19 4 1 2 25 14 11 25 24 16 8 14 21 21 16 6 13 1 23 15 8 
+17 4 3 4 9 23 12 8 8 24 13 6 11 3 8 24 19 8 23 1 24 24 12 ^
+53 0 25 13 2 6 25 7 9 3 5 11 19 11 16 5 4 17 24 23 15 14 10 7 14 17 25 15 10 14 
+6 18 18 4 1 13 10 16 1 25 16 2 24 5 1 17 6 17 6 24 11 7 21 9 19 ^
+51 1 8 25 5 5 22 16 13 5 2 16 4 25 25 8 18 13 13 3 1 22 23 24 18 12 21 19 2 4 
+24 13 11 2 7 24 22 17 5 15 1 8 3 10 15 18 15 8 10 16 20 20 8 ^
+50 1 18 22 11 18 9 11 15 22 20 18 6 24 15 25 4 22 12 17 4 6 17 20 2 4 2 5 20 15 
+19 24 18 9 8 2 5 23 2 10 21 8 5 2 9 16 16 15 6 22 23 18 ^
+48 1 6 21 5 21 24 3 6 10 17 19 9 15 11 23 16 17 1 3 12 3 20 4 5 5 3 21 22 15 4 
+21 20 7 22 14 9 24 4 18 7 7 25 24 22 21 23 24 14 19 ^
+55 0 12 6 7 4 2 12 25 15 3 9 23 8 16 25 11 14 4 10 19 23 16 13 9 20 25 17 11 8 
+4 19 25 17 7 16 21 6 4 8 2 15 9 2 9 19 3 6 3 3 10 25 13 15 7 8 24 ^
+56 0 21 12 10 12 5 24 11 20 3 13 13 16 9 13 10 3 9 16 3 7 15 9 9 14 2 13 17 25 
+2 18 5 19 23 9 25 9 10 23 12 12 7 13 8 15 7 1 6 21 2 8 7 6 16 14 14 22 ^
+47 0 15 13 24 10 15 11 10 8 14 15 21 25 21 16 9 18 20 22 21 20 11 14 23 22 10 
+13 14 8 19 12 2 11 20 23 13 4 10 6 5 7 23 11 3 16 8 21 12 ^
+49 0 4 8 18 5 12 14 8 6 20 19 24 8 23 17 3 7 19 1 18 1 14 22 13 14 5 8 22 18 14 
+25 17 11 12 22 2 12 12 16 12 13 18 17 12 17 14 18 8 25 22 ^
+46 1 23 5 3 8 14 24 17 7 3 3 23 17 22 19 19 17 16 22 24 14 16 20 23 20 9 19 16 
+7 12 16 5 8 9 7 10 21 24 10 11 19 1 21 14 14 19 20 ^
+57 1 22 8 12 20 1 18 5 6 5 12 14 1 1 11 9 22 3 24 9 6 1 11 16 1 12 8 11 11 17 
+10 22 7 3 10 2 6 4 24 16 24 19 4 5 18 11 12 9 20 21 25 2 21 18 10 20 25 7 ^
+56 1 3 17 17 5 8 22 25 19 8 10 19 7 11 4 8 18 3 18 3 11 24 2 14 9 1 10 4 4 13 
+19 22 4 7 19 5 10 10 1 8 22 22 6 8 13 12 11 17 23 14 16 7 5 11 22 24 18 ^
+54 1 2 11 13 18 4 20 8 1 6 25 20 17 20 1 25 10 15 15 2 17 13 9 24 17 24 20 13 
+15 17 3 11 20 10 5 13 23 18 5 3 18 15 7 5 7 4 15 20 16 2 17 1 7 4 23 ^
+56 0 7 25 14 1 4 7 19 19 20 3 13 12 4 3 14 4 14 11 6 3 25 18 16 20 24 12 19 18 
+25 6 23 6 15 5 4 4 6 14 13 20 5 14 15 2 13 21 11 5 17 2 2 10 11 13 14 24 ^
+49 0 12 11 20 3 14 2 3 2 23 12 12 17 24 11 8 6 24 16 15 22 21 14 6 12 20 19 5 5 
+12 11 6 23 2 16 23 7 24 6 21 2 17 17 5 25 11 25 20 25 19 ^
+54 0 18 6 12 19 25 7 6 5 2 14 12 16 1 15 7 1 26 19 19 13 20 11 17 6 20 5 24 24 
+1 21 11 9 20 21 15 10 19 26 3 2 6 7 12 9 10 8 14 10 15 5 17 8 21 7 ^
+56 0 20 25 6 19 8 3 22 16 16 16 17 13 11 10 17 15 12 6 13 14 17 4 12 10 24 5 13 
+24 3 5 2 5 11 14 8 5 10 17 16 8 4 14 21 15 3 6 17 25 8 2 3 3 19 10 13 23 ^
+51 1 22 8 2 13 25 17 2 1 19 1 14 20 2 5 4 15 8 14 20 7 25 20 26 20 16 7 17 17 
+22 1 13 6 5 1 18 14 15 23 15 10 5 19 18 18 26 12 13 3 25 12 18 ^
+51 1 16 24 4 16 3 6 26 26 10 20 13 1 20 24 10 21 7 25 2 25 22 9 15 16 26 5 12 1 
+7 4 24 7 14 20 1 4 7 3 10 10 15 6 13 6 22 6 20 22 2 26 26 ^
+47 1 6 14 1 16 3 24 25 24 17 12 14 18 18 9 9 11 22 13 9 2 22 15 20 20 18 8 13 
+13 21 8 11 5 26 8 19 17 4 2 15 26 13 24 26 11 16 9 24 ^
+52 0 8 18 21 6 1 8 1 16 4 20 23 23 24 10 11 12 10 10 25 1 11 25 10 3 26 26 20 
+15 11 19 16 17 3 16 12 25 15 9 23 1 2 24 8 10 18 2 9 5 4 17 16 12 ^
+50 0 12 20 20 1 3 11 5 9 3 17 9 17 24 21 3 4 16 2 10 1 25 5 22 16 6 21 19 21 23 
+15 9 9 21 17 11 1 15 17 23 24 11 7 10 26 15 8 22 22 18 16 ^
+48 0 11 17 5 26 7 23 19 3 24 17 2 19 18 26 21 12 5 18 22 20 7 15 6 4 5 20 13 10 
+23 18 16 25 18 15 2 20 14 24 22 17 3 15 16 1 10 2 12 16 ^
+47 0 21 1 21 21 4 18 13 1 24 18 23 17 19 6 19 9 26 25 23 23 14 13 13 20 12 13 4 
+21 10 22 21 22 1 12 12 7 13 16 18 8 9 4 3 10 18 12 25 ^
+47 1 5 19 19 12 24 13 18 1 22 8 1 17 18 24 3 22 7 7 19 26 13 26 6 26 6 18 12 5 
+26 17 18 19 22 10 12 8 23 11 17 23 25 5 5 11 4 13 20 ^
+52 0 18 4 19 23 3 13 15 4 3 9 24 14 5 25 21 22 18 17 12 15 14 16 10 14 9 19 7 
+16 3 23 4 26 18 5 16 21 24 2 8 8 8 7 11 13 14 7 9 12 18 11 10 20 ^
+47 1 20 12 14 19 11 21 21 22 19 13 10 16 19 14 7 8 16 20 10 3 9 23 18 7 26 16 
+22 21 21 5 14 11 2 2 16 22 11 26 7 22 23 5 23 10 4 22 5 ^
+50 0 19 20 9 16 10 24 4 19 26 4 25 4 8 17 7 7 2 23 11 18 19 23 6 10 9 1 9 14 19 
+5 6 6 25 12 11 21 26 12 3 8 20 8 21 18 25 25 14 4 11 25 ^
+45 1 23 4 14 3 17 26 22 26 2 15 9 8 25 19 12 23 17 20 17 10 4 23 20 17 21 14 14 
+9 18 11 18 2 18 4 2 22 25 15 18 10 23 8 21 26 15 ^
+54 0 7 14 10 6 6 15 15 13 2 11 15 22 2 9 4 4 6 16 11 11 3 16 13 19 25 16 5 7 20 
+22 9 25 11 24 24 25 13 8 15 23 16 6 3 18 23 16 23 8 20 4 1 1 14 16 ^
+43 1 12 24 14 14 26 23 13 26 14 21 25 25 4 9 13 5 8 9 21 8 12 26 24 9 24 15 1 
+23 22 16 14 8 22 15 19 24 20 7 8 15 24 12 18 ^
+57 0 4 23 21 13 19 15 21 7 15 7 3 21 20 8 22 14 23 26 19 2 10 18 3 5 3 1 9 15 
+15 3 7 13 23 9 7 1 13 17 14 25 9 16 2 2 6 13 7 19 25 17 1 5 21 2 7 22 5 ^
+55 1 6 25 3 12 19 6 2 4 24 17 9 18 20 19 4 11 14 1 6 8 26 6 9 22 4 10 2 7 21 9 
+8 24 25 14 22 12 22 3 23 3 3 20 6 11 23 6 1 7 5 18 5 15 25 26 23 ^
+53 0 1 10 11 11 4 12 11 20 3 14 2 3 2 23 12 12 17 24 11 8 6 24 16 15 22 21 14 6 
+12 20 19 5 5 12 11 6 23 2 16 23 7 24 6 21 2 17 17 5 25 11 25 20 26 ^
+54 0 24 18 6 12 19 25 7 6 5 2 14 12 16 1 15 7 1 26 19 19 13 20 11 17 6 20 5 24 
+24 1 21 11 9 20 21 15 10 19 26 3 2 6 7 12 9 10 8 14 10 15 5 17 8 23 ^
+58 0 1 20 25 6 19 8 3 22 16 16 16 17 13 11 10 17 15 12 6 13 14 17 4 12 10 24 5 
+13 24 3 5 2 5 11 14 8 5 10 17 16 8 4 14 21 15 3 6 17 25 8 2 3 3 19 10 13 22 19 ^
+52 1 8 2 13 25 17 2 1 19 1 14 20 2 5 4 15 8 14 20 7 25 20 26 20 16 7 17 17 22 1 
+13 6 5 1 18 14 15 23 15 10 5 19 18 18 26 12 13 3 25 12 21 16 22 ^
+56 1 4 16 3 6 26 26 10 20 13 1 20 24 10 21 7 25 2 25 22 9 15 16 26 5 12 1 7 4 
+24 7 14 20 1 4 7 3 10 10 15 6 13 6 22 6 20 22 2 26 9 6 14 1 16 3 24 12 ^
+52 0 24 17 12 14 18 18 9 9 11 22 13 9 2 22 15 20 20 18 8 13 13 21 8 11 5 26 8 
+19 17 4 2 15 26 13 24 26 11 16 9 1 8 18 21 6 1 8 1 16 4 20 23 5 ^
+54 0 24 10 11 12 10 10 25 1 11 25 10 3 26 26 20 15 11 19 16 17 3 16 12 25 15 9 
+23 1 2 24 8 10 18 2 9 5 4 17 16 9 12 20 20 1 3 11 5 9 3 17 9 17 24 20 ^
+49 1 3 4 16 2 10 1 25 5 22 16 6 21 19 21 23 15 9 9 21 17 11 1 15 17 23 24 11 7 
+10 26 15 8 22 22 18 26 11 17 5 26 7 23 19 3 24 17 2 19 8 ^
+49 0 26 21 12 5 18 22 20 7 15 6 4 5 20 13 10 23 18 16 25 18 15 2 20 14 24 22 17 
+3 15 16 1 10 2 12 2 21 1 21 21 4 18 13 1 24 18 23 17 19 23 ^
+50 1 19 9 26 25 23 23 14 13 13 20 12 13 4 21 10 22 21 22 1 12 12 7 13 16 18 8 9 
+4 3 10 18 12 4 5 19 19 12 24 13 18 1 22 8 1 17 18 24 3 22 21 ^
+48 1 7 19 26 13 26 6 26 6 18 12 5 26 17 18 19 22 10 12 8 23 11 17 23 25 5 5 11 
+4 13 7 18 4 19 23 3 13 15 4 3 9 24 14 5 25 21 22 18 25 ^
+53 1 12 15 14 16 10 14 9 19 7 16 3 23 4 26 18 5 16 21 24 2 8 8 8 7 11 13 14 7 9 
+12 18 11 10 7 20 12 14 19 11 21 21 22 19 13 10 16 19 14 7 8 16 20 7 ^
+49 0 3 9 23 18 7 26 16 22 21 21 5 14 11 2 2 16 22 11 26 7 22 23 5 23 10 4 22 24 
+19 20 9 16 10 24 4 19 26 4 25 4 8 17 7 7 2 23 11 18 19 ^
+49 0 23 6 10 9 1 9 14 19 5 6 6 25 12 11 21 26 12 3 8 20 8 21 18 25 25 14 4 11 
+24 23 4 14 3 17 26 22 26 2 15 9 8 25 19 12 23 17 20 17 10 ^
+54 0 4 23 20 17 21 14 14 9 18 11 18 2 18 4 2 22 25 15 18 10 23 8 21 26 7 14 10 
+6 6 15 15 13 2 11 15 22 2 9 4 4 6 16 11 11 3 16 13 19 25 16 5 7 20 23 ^
+47 0 9 25 11 24 24 25 13 8 15 23 16 6 3 18 23 16 23 8 20 4 1 1 14 13 12 24 14 
+14 26 23 13 26 14 21 25 25 4 9 13 5 8 9 21 8 12 26 15 ^
+51 1 9 24 15 1 23 22 16 14 8 22 15 19 24 20 7 8 15 24 12 4 4 23 21 13 19 15 21 
+7 15 7 3 21 20 8 22 14 23 26 19 2 10 18 3 5 3 1 9 15 15 3 24 ^
+60 0 13 23 9 7 1 13 17 14 25 9 16 2 2 6 13 7 19 25 17 1 5 21 2 7 22 5 6 25 3 12 
+19 6 2 4 24 17 9 18 20 19 4 11 14 1 6 8 26 6 9 22 4 10 2 7 21 9 8 24 25 10 ^
+59 0 22 12 22 3 23 3 3 20 6 11 23 6 1 7 5 18 5 15 25 26 1 1 10 11 11 4 12 11 20 
+3 14 2 3 2 23 12 12 17 24 11 8 6 24 16 15 22 21 14 6 12 20 19 5 5 12 11 6 23 8 ^
+50 0 16 23 7 24 6 21 2 17 17 5 25 11 25 20 25 24 18 6 12 19 25 7 6 5 2 14 12 16 
+1 15 7 1 26 19 19 13 20 11 17 6 20 5 24 24 1 21 11 9 20 14 ^
+60 0 15 10 19 26 3 2 6 7 12 9 10 8 14 10 15 5 17 8 21 1 20 25 6 19 8 3 22 16 16 
+16 17 13 11 10 17 15 12 6 13 14 17 4 12 10 24 5 13 24 3 5 2 5 11 14 8 5 10 17 
+16 13 ^
+57 0 4 14 21 15 3 6 17 25 8 2 3 3 19 10 13 22 22 8 2 13 25 17 2 1 19 1 14 20 2 
+5 4 15 8 14 20 7 25 20 26 20 16 7 17 17 22 1 13 6 5 1 18 14 15 23 15 10 21 ^
+52 1 19 18 18 26 12 13 3 25 12 21 16 24 4 16 3 6 26 26 10 20 13 1 20 24 10 21 7 
+25 2 25 22 9 15 16 26 5 12 1 7 4 24 7 14 20 1 4 7 3 10 10 15 19 ^
+51 0 13 6 22 6 20 22 2 26 9 6 14 1 16 3 24 25 24 17 12 14 18 18 9 9 11 22 13 9 
+2 22 15 20 20 18 8 13 13 21 8 11 5 26 8 19 17 4 2 15 26 13 21 ^
+52 1 24 26 11 16 9 1 8 18 21 6 1 8 1 16 4 20 23 23 24 10 11 12 10 10 25 1 11 25 
+10 3 26 26 20 15 11 19 16 17 3 16 12 25 15 9 23 1 2 24 8 10 18 15 ^
+55 1 9 5 4 17 16 9 12 20 20 1 3 11 5 9 3 17 9 17 24 21 3 4 16 2 10 1 25 5 22 16 
+6 21 19 21 23 15 9 9 21 17 11 1 15 17 23 24 11 7 10 26 15 8 22 22 11 ^
+50 1 26 11 17 5 26 7 23 19 3 24 17 2 19 18 26 21 12 5 18 22 20 7 15 6 4 5 20 13 
+10 23 18 16 25 18 15 2 20 14 24 22 17 3 15 16 1 10 2 12 2 25 ^
+51 0 1 21 21 4 18 13 1 24 18 23 17 19 6 19 9 26 25 23 23 14 13 13 20 12 13 4 21 
+10 22 21 22 1 12 12 7 13 16 18 8 9 4 3 10 18 12 4 5 19 19 12 24 ^
+53 1 13 18 1 22 8 1 17 18 24 3 22 7 7 19 26 13 26 6 26 6 18 12 5 26 17 18 19 22 
+10 12 8 23 11 17 23 25 5 5 11 4 13 7 18 4 19 23 3 13 15 4 3 9 18 ^
+51 1 14 5 25 21 22 18 17 12 15 14 16 10 14 9 19 7 16 3 23 4 26 18 5 16 21 24 2 
+8 8 8 7 11 13 14 7 9 12 18 11 10 7 20 12 14 19 11 21 21 22 19 26 ^
+49 0 10 16 19 14 7 8 16 20 10 3 9 23 18 7 26 16 22 21 21 5 14 11 2 2 16 22 11 
+26 7 22 23 5 23 10 4 22 24 19 20 9 16 10 24 4 19 26 4 25 14 ^
+52 0 8 17 7 7 2 23 11 18 19 23 6 10 9 1 9 14 19 5 6 6 25 12 11 21 26 12 3 8 20 
+8 21 18 25 25 14 4 11 24 23 4 14 3 17 26 22 26 2 15 9 8 25 24 ^
+55 1 12 23 17 20 17 10 4 23 20 17 21 14 14 9 18 11 18 2 18 4 2 22 25 15 18 10 
+23 8 21 26 7 14 10 6 6 15 15 13 2 11 15 22 2 9 4 4 6 16 11 11 3 16 13 19 15 ^
+49 0 16 5 7 20 22 9 25 11 24 24 25 13 8 15 23 16 6 3 18 23 16 23 8 20 4 1 1 14 
+13 12 24 14 14 26 23 13 26 14 21 25 25 4 9 13 5 8 9 21 9 ^
+55 0 22 24 9 27 23 1 13 18 24 1 8 24 8 6 14 1 4 5 15 27 12 20 1 17 5 4 14 25 14 
+3 19 24 24 14 8 13 12 19 8 3 6 13 7 10 23 19 10 17 17 11 6 13 8 18 18 ^
+51 0 7 3 25 1 17 8 26 25 11 23 14 27 1 22 11 9 7 19 4 15 18 2 27 20 11 5 20 22 
+19 15 5 6 17 8 1 19 22 9 23 10 26 27 26 14 12 3 14 15 11 2 26 ^
+50 0 6 22 20 8 25 4 25 24 23 20 3 3 16 2 2 27 2 15 14 27 3 17 12 27 27 7 26 2 
+22 11 9 10 24 15 1 27 11 27 4 1 25 25 16 6 2 22 12 17 21 14 ^
+52 0 8 9 22 17 12 7 18 14 23 2 6 4 23 9 4 22 16 18 23 8 11 25 17 27 16 10 3 24 
+8 20 20 18 18 13 4 2 18 22 15 25 26 9 3 1 2 19 15 1 24 17 16 18 ^
+49 0 9 14 11 8 16 19 16 22 10 16 24 25 7 22 12 20 15 23 22 18 22 14 6 26 21 10 
+21 7 13 2 16 7 24 16 22 13 10 7 11 16 5 9 25 13 9 14 14 17 14 ^
+54 1 2 10 5 25 5 7 10 22 10 1 24 3 11 7 23 5 17 14 3 18 5 13 26 15 5 13 23 18 
+17 3 18 3 27 15 6 25 24 22 27 17 4 25 23 15 9 15 21 8 7 7 15 3 13 25 ^
+47 0 25 3 4 10 24 12 7 16 25 18 21 21 20 27 13 14 23 27 1 21 9 21 14 22 9 9 5 
+15 13 17 3 4 9 16 1 8 23 17 23 26 8 24 10 20 25 27 25 ^
+58 1 8 26 8 10 4 3 8 14 5 5 7 11 13 11 26 11 4 26 17 20 19 11 10 3 10 14 9 6 9 
+7 16 10 4 4 19 19 2 26 13 19 17 15 24 15 4 21 22 13 13 12 22 2 14 20 5 18 7 25 ^
+58 0 17 24 20 13 6 17 9 20 2 10 19 3 22 4 1 11 3 5 3 21 11 15 12 23 26 5 2 27 6 
+5 16 6 3 2 23 5 3 20 20 4 24 2 18 21 7 14 10 27 23 6 24 6 19 23 3 9 22 15 ^
+54 0 21 17 19 25 17 7 21 19 6 16 15 15 20 14 2 25 19 14 18 19 7 9 1 14 11 10 16 
+3 23 14 26 10 11 1 18 1 12 24 19 19 1 7 2 3 24 7 12 9 2 8 16 20 24 25 ^
+49 1 26 26 4 9 2 7 25 9 8 12 18 14 26 7 17 18 4 20 1 16 14 21 26 4 6 8 24 11 25 
+15 24 16 23 4 10 23 21 24 15 10 9 26 7 14 24 21 6 20 19 ^
+56 1 17 16 17 1 3 12 1 4 13 3 9 21 23 7 18 11 1 19 20 23 12 12 27 13 13 15 16 
+13 1 16 15 12 26 3 16 16 8 17 13 21 4 6 5 19 14 16 4 16 11 14 18 18 27 9 13 22 ^
+51 1 3 26 22 3 7 6 4 26 3 15 8 25 1 20 13 9 11 20 6 11 21 27 25 20 7 4 18 26 16 
+27 5 12 19 7 23 6 25 25 2 11 13 25 21 18 17 6 12 14 13 24 13 ^
+48 1 14 19 26 27 25 6 1 15 4 7 27 24 27 21 5 27 19 18 8 21 3 23 20 21 25 21 1 9 
+17 22 5 22 8 2 13 27 8 19 27 21 2 5 8 4 27 10 6 25 ^
+52 0 2 6 1 1 26 18 13 5 10 18 10 8 5 21 15 5 14 19 12 4 8 20 21 26 1 12 25 10 2 
+17 10 15 2 20 25 26 23 25 12 16 15 9 18 15 19 21 16 26 11 18 20 26 ^
+53 0 6 22 7 8 8 12 2 21 18 12 11 5 19 3 19 27 18 25 22 22 23 16 2 1 20 16 14 22 
+6 15 22 1 21 6 6 10 2 26 12 11 6 27 14 7 20 26 20 17 7 19 5 23 14 ^
+61 0 16 12 7 15 17 7 5 11 12 15 7 1 10 10 8 4 2 4 17 4 11 17 26 23 24 4 5 12 5 
+1 6 9 6 8 27 5 11 11 24 24 13 17 2 24 26 19 11 22 21 2 2 14 21 13 1 23 10 25 8 
+15 13 ^
+52 0 19 23 2 9 26 6 23 13 5 24 12 21 11 14 4 12 10 12 22 4 3 20 17 10 13 16 9 
+10 27 9 12 13 20 10 12 23 23 11 19 13 25 22 8 1 5 16 20 9 19 9 24 26 ^
+51 0 12 15 6 21 27 22 26 24 18 9 15 8 22 24 9 27 23 1 13 18 24 1 8 24 8 6 14 1 
+4 5 15 27 12 20 1 17 5 4 14 25 14 3 19 24 24 14 8 13 12 19 22 ^
+56 0 3 6 13 7 10 23 19 10 17 17 11 6 13 8 18 6 7 3 25 1 17 8 26 25 11 23 14 27 
+1 22 11 9 7 19 4 15 18 2 27 20 11 5 20 22 19 15 5 6 17 8 1 19 22 9 23 17 ^
+50 0 26 27 26 14 12 3 14 15 11 2 12 6 22 20 8 25 4 25 24 23 20 3 3 16 2 2 27 2 
+15 14 27 3 17 12 27 27 7 26 2 22 11 9 10 24 15 1 27 11 27 21 ^
+52 0 1 25 25 16 6 2 22 12 17 21 12 8 9 22 17 12 7 18 14 23 2 6 4 23 9 4 22 16 
+18 23 8 11 25 17 27 16 10 3 24 8 20 20 18 18 13 4 2 18 22 15 25 10 ^
+52 0 9 3 1 2 19 15 1 24 17 16 18 9 14 11 8 16 19 16 22 10 16 24 25 7 22 12 20 
+15 23 22 18 22 14 6 26 21 10 21 7 13 2 16 7 24 16 22 13 10 7 11 16 13 ^
+53 1 9 25 13 9 14 14 17 25 2 10 5 25 5 7 10 22 10 1 24 3 11 7 23 5 17 14 3 18 5 
+13 26 15 5 13 23 18 17 3 18 3 27 15 6 25 24 22 27 17 4 25 23 15 15 ^
+52 1 15 21 8 7 7 15 3 13 22 25 3 4 10 24 12 7 16 25 18 21 21 20 27 13 14 23 27 
+1 21 9 21 14 22 9 9 5 15 13 17 3 4 9 16 1 8 23 17 23 26 8 24 14 ^
+58 0 20 25 27 3 8 26 8 10 4 3 8 14 5 5 7 11 13 11 26 11 4 26 17 20 19 11 10 3 
+10 14 9 6 9 7 16 10 4 4 19 19 2 26 13 19 17 15 24 15 4 21 22 13 13 12 22 2 14 
+18 ^
+60 0 5 18 7 17 24 20 13 6 17 9 20 2 10 19 3 22 4 1 11 3 5 3 21 11 15 12 23 26 5 
+2 27 6 5 16 6 3 2 23 5 3 20 20 4 24 2 18 21 7 14 10 27 23 6 24 6 19 23 3 9 25 ^
+55 0 16 21 17 19 25 17 7 21 19 6 16 15 15 20 14 2 25 19 14 18 19 7 9 1 14 11 10 
+16 3 23 14 26 10 11 1 18 1 12 24 19 19 1 7 2 3 24 7 12 9 2 8 16 20 24 27 ^
+51 1 26 26 4 9 2 7 25 9 8 12 18 14 26 7 17 18 4 20 1 16 14 21 26 4 6 8 24 11 25 
+15 24 16 23 4 10 23 21 24 15 10 9 26 7 14 24 21 6 20 5 17 15 ^
+57 0 17 1 3 12 1 4 13 3 9 21 23 7 18 11 1 19 20 23 12 12 27 13 13 15 16 13 1 16 
+15 12 26 3 16 16 8 17 13 21 4 6 5 19 14 16 4 16 11 14 18 18 27 9 13 21 3 26 23 ^
+52 0 3 7 6 4 26 3 15 8 25 1 20 13 9 11 20 6 11 21 27 25 20 7 4 18 26 16 27 5 12 
+19 7 23 6 25 25 2 11 13 25 21 18 17 6 12 14 13 24 11 14 19 26 12 ^
+55 1 25 6 1 15 4 7 27 24 27 21 5 27 19 18 8 21 3 23 20 21 25 21 1 9 17 22 5 22 
+8 2 13 27 8 19 27 21 2 5 8 4 27 10 6 18 2 6 1 1 26 18 13 5 10 18 11 ^
+52 0 8 5 21 15 5 14 19 12 4 8 20 21 26 1 12 25 10 2 17 10 15 2 20 25 26 23 25 
+12 16 15 9 18 15 19 21 16 26 11 18 20 6 22 7 8 8 12 2 21 18 12 11 27 ^
+53 1 19 3 19 27 18 25 22 22 23 16 2 1 20 16 14 22 6 15 22 1 21 6 6 10 2 26 12 
+11 6 27 14 7 20 26 20 17 7 19 5 23 18 16 12 7 15 17 7 5 11 12 15 7 22 ^
+57 1 10 10 8 4 2 4 17 4 11 17 26 23 24 4 5 12 5 1 6 9 6 8 27 5 11 11 24 24 13 
+17 2 24 26 19 11 22 21 2 2 14 21 13 1 23 10 25 8 15 26 19 23 2 9 26 6 23 22 ^
+52 1 5 24 12 21 11 14 4 12 10 12 22 4 3 20 17 10 13 16 9 10 27 9 12 13 20 10 12 
+23 23 11 19 13 25 22 8 1 5 16 20 9 19 9 24 20 12 15 6 21 27 22 26 16 ^
+58 0 18 9 15 8 22 24 9 27 23 1 13 18 24 1 8 24 8 6 14 1 4 5 15 27 12 20 1 17 5 
+4 14 25 14 3 19 24 24 14 8 13 12 19 8 3 6 13 7 10 23 19 10 17 17 11 6 13 8 22 ^
+55 0 6 7 3 25 1 17 8 26 25 11 23 14 27 1 22 11 9 7 19 4 15 18 2 27 20 11 5 20 
+22 19 15 5 6 17 8 1 19 22 9 23 10 26 27 26 14 12 3 14 15 11 2 12 6 22 16 ^
+53 0 8 25 4 25 24 23 20 3 3 16 2 2 27 2 15 14 27 3 17 12 27 27 7 26 2 22 11 9 
+10 24 15 1 27 11 27 4 1 25 25 16 6 2 22 12 17 21 12 8 9 22 17 12 18 ^
+54 0 7 18 14 23 2 6 4 23 9 4 22 16 18 23 8 11 25 17 27 16 10 3 24 8 20 20 18 18 
+13 4 2 18 22 15 25 26 9 3 1 2 19 15 1 24 17 16 18 9 14 11 8 16 19 27 ^
+52 0 22 10 16 24 25 7 22 12 20 15 23 22 18 22 14 6 26 21 10 21 7 13 2 16 7 24 
+16 22 13 10 7 11 16 5 9 25 13 9 14 14 17 25 2 10 5 25 5 7 10 22 10 22 ^
+54 1 24 3 11 7 23 5 17 14 3 18 5 13 26 15 5 13 23 18 17 3 18 3 27 15 6 25 24 22 
+27 17 4 25 23 15 9 15 21 8 7 7 15 3 13 22 25 3 4 10 24 12 7 16 25 10 ^
+56 0 21 21 20 27 13 14 23 27 1 21 9 21 14 22 9 9 5 15 13 17 3 4 9 16 1 8 23 17 
+23 26 8 24 10 20 25 27 3 8 26 8 10 4 3 8 14 5 5 7 11 13 11 26 11 4 26 2 ^
+61 1 20 19 11 10 3 10 14 9 6 9 7 16 10 4 4 19 19 2 26 13 19 17 15 24 15 4 21 22 
+13 13 12 22 2 14 20 5 18 7 17 24 20 13 6 17 9 20 2 10 19 3 22 4 1 11 3 5 3 21 
+11 15 22 ^
+53 0 23 26 5 2 27 6 5 16 6 3 2 23 5 3 20 20 4 24 2 18 21 7 14 10 27 23 6 24 6 
+19 23 3 9 22 16 21 17 19 25 17 7 21 19 6 16 15 15 20 14 2 25 19 25 ^
+60 0 18 19 7 9 1 14 11 10 16 3 23 14 26 10 11 1 18 1 12 24 19 19 1 7 2 3 24 7 
+12 9 2 8 16 20 24 5 26 26 4 9 2 7 25 9 8 12 18 14 26 7 17 18 4 20 1 16 14 21 26 
+18 ^
+54 0 6 8 24 11 25 15 24 16 23 4 10 23 21 24 15 10 9 26 7 14 24 21 6 20 5 17 16 
+17 1 3 12 1 4 13 3 9 21 23 7 18 11 1 19 20 23 12 12 27 13 13 15 16 13 24 ^
+57 0 1 16 15 12 26 3 16 16 8 17 13 21 4 6 5 19 14 16 4 16 11 14 18 18 27 9 13 
+21 3 26 22 3 7 6 4 26 3 15 8 25 1 20 13 9 11 20 6 11 21 27 25 20 7 4 18 26 10 ^
+48 0 27 5 12 19 7 23 6 25 25 2 11 13 25 21 18 17 6 12 14 13 24 11 14 19 26 27 
+25 6 1 15 4 7 27 24 27 21 5 27 19 18 8 21 3 23 20 21 25 8 ^
+60 1 1 9 17 22 5 22 8 2 13 27 8 19 27 21 2 5 8 4 27 10 6 18 2 6 1 1 26 18 13 5 
+10 18 10 8 5 21 15 5 14 19 12 4 8 20 21 26 1 12 25 10 2 17 10 15 2 20 25 26 23 
+21 ^
+54 1 12 16 15 9 18 15 19 21 16 26 11 18 20 6 22 7 8 8 12 2 21 18 12 11 5 19 3 
+19 27 18 25 22 22 23 16 2 1 20 16 14 22 6 15 22 1 21 6 6 10 2 26 12 11 24 ^
+60 0 27 14 7 20 26 20 17 7 19 5 23 18 16 12 7 15 17 7 5 11 12 15 7 1 10 10 8 4 
+2 4 17 4 11 17 26 23 24 4 5 12 5 1 6 9 6 8 27 5 11 11 24 24 13 17 2 24 26 19 11 
+22 ^
+55 0 21 2 2 14 21 13 1 23 10 25 8 15 26 19 23 2 9 26 6 23 13 5 24 12 21 11 14 4 
+12 10 12 22 4 3 20 17 10 13 16 9 10 27 9 12 13 20 10 12 23 23 11 19 13 25 13 ^
+55 0 8 1 5 16 20 9 19 9 24 20 12 15 6 21 27 22 26 24 18 9 15 8 22 24 9 27 23 1 
+13 18 24 1 8 24 8 6 14 1 4 5 15 27 12 20 1 17 5 4 14 25 14 3 19 24 16 ^
+60 0 14 8 13 12 19 8 3 6 13 7 10 23 19 10 17 17 11 6 13 8 18 6 7 3 25 1 17 8 26 
+25 11 23 14 27 1 22 11 9 7 19 4 15 18 2 27 20 11 5 20 22 19 15 5 6 17 8 1 19 22 
+10 ^
+55 1 15 9 11 26 19 22 27 2 21 8 20 23 26 12 10 21 9 15 13 25 7 26 1 13 5 9 1 3 
+9 21 22 7 1 23 28 1 2 8 22 12 18 28 5 18 14 7 11 17 20 20 7 21 13 8 22 ^
+52 1 21 22 2 16 20 15 28 9 3 22 13 10 23 4 16 11 14 1 10 8 14 14 15 18 13 12 21 
+18 25 15 27 17 5 1 23 7 17 20 11 14 10 4 21 17 19 25 17 22 18 21 19 17 ^
+57 0 10 15 26 20 8 13 19 7 8 18 7 12 14 6 8 22 21 11 10 14 23 25 9 15 22 18 6 
+17 24 7 13 6 12 7 2 18 18 26 13 13 16 8 24 10 3 26 9 20 1 12 2 14 13 23 12 25 5 
+^
+57 0 24 11 6 3 8 27 8 21 26 3 11 19 18 5 5 25 26 24 4 23 15 15 23 21 24 5 15 21 
+3 3 18 2 24 27 11 20 10 11 4 5 12 2 23 6 5 3 1 14 26 15 12 6 28 12 19 20 9 ^
+55 0 6 23 4 7 7 3 10 24 28 6 10 9 6 20 14 27 10 19 11 1 15 21 5 10 7 11 8 16 9 
+27 5 2 6 6 27 20 24 21 2 20 16 14 24 17 15 3 2 26 25 25 14 24 20 28 28 ^
+59 1 17 5 9 10 25 20 12 9 18 3 16 4 10 7 18 23 17 2 8 1 28 7 2 15 5 18 11 23 2 
+1 18 22 14 7 20 21 2 11 12 3 15 12 4 1 27 21 16 27 19 18 13 21 14 5 20 9 19 27 
+25 ^
+55 0 3 5 16 16 22 2 13 7 4 13 19 27 15 7 16 25 3 4 4 17 12 13 11 12 26 6 1 10 
+15 18 4 19 10 27 9 4 25 13 21 25 26 21 20 12 25 21 7 17 28 27 3 13 14 19 18 ^
+53 1 23 19 4 28 3 20 18 9 7 15 4 26 5 6 20 5 23 28 10 24 19 13 28 1 9 12 23 16 
+10 13 2 19 21 6 25 22 28 23 16 7 20 4 2 22 11 26 22 6 9 17 11 21 10 ^
+47 0 1 3 28 11 27 25 12 8 26 26 28 24 13 22 17 6 4 24 15 17 18 4 22 23 9 24 12 
+27 27 25 9 13 15 11 9 22 28 26 11 18 15 10 6 16 17 14 24 ^
+55 1 25 27 16 28 22 24 1 1 11 7 24 3 28 7 5 28 16 15 1 7 14 9 7 6 15 25 19 9 3 
+19 23 1 26 20 17 17 1 16 24 9 16 8 15 6 21 17 22 9 28 8 8 5 4 24 26 ^
+47 1 14 4 21 26 23 7 8 27 23 23 22 19 24 25 16 19 12 22 10 20 3 7 14 1 20 6 26 
+23 27 4 16 20 18 12 20 15 19 16 18 20 27 11 11 17 24 18 16 ^
+50 0 19 1 25 23 2 15 16 26 27 23 14 12 28 22 15 8 19 2 20 13 1 24 2 25 1 6 19 
+19 8 11 24 24 21 13 27 5 11 28 17 7 25 6 23 24 14 25 12 5 13 25 ^
+60 0 2 5 8 10 16 11 5 26 18 19 21 3 12 11 13 4 14 22 22 14 16 13 3 22 16 23 5 
+19 6 13 10 26 17 27 26 4 3 25 6 14 2 3 5 7 23 11 22 8 25 2 9 25 18 17 8 2 14 4 
+19 22 ^
+54 1 5 27 13 9 2 27 28 2 17 23 10 27 18 26 7 22 16 3 27 1 26 21 28 10 3 6 2 2 
+10 17 13 16 6 17 21 23 13 20 22 5 6 11 12 12 8 23 13 17 9 23 20 3 28 21 ^
+56 0 12 17 25 28 19 5 21 4 27 8 1 19 14 20 6 7 9 1 6 22 3 19 26 14 8 6 7 19 15 
+23 1 17 16 6 26 14 5 22 25 4 7 10 16 21 10 18 19 24 16 23 8 3 17 28 18 13 ^
+58 0 2 5 3 21 21 15 6 24 1 4 24 18 10 22 1 21 12 5 4 4 20 25 24 26 8 25 11 2 7 
+27 22 19 4 18 27 10 28 4 12 24 8 16 12 11 16 17 25 8 12 16 1 9 9 10 5 24 23 11 ^
+62 1 5 14 18 8 4 9 5 17 8 28 1 22 4 11 3 2 17 3 14 9 27 13 18 24 9 8 7 28 25 14 
+21 27 24 6 18 16 2 12 15 9 14 10 1 8 17 4 6 15 26 11 15 2 28 20 26 16 3 7 5 8 9 
+24 ^
+50 1 10 12 25 11 9 13 24 15 20 2 4 8 2 22 20 19 4 15 14 28 13 25 10 10 12 28 24 
+22 26 28 15 9 11 26 19 22 27 2 21 8 20 23 26 12 10 21 9 15 13 17 ^
+60 1 7 26 1 13 5 9 1 3 9 21 22 7 1 23 28 1 2 8 22 12 18 28 5 18 14 7 11 17 20 
+20 7 21 13 8 28 21 22 2 16 20 15 28 9 3 22 13 10 23 4 16 11 14 1 10 8 14 14 15 
+18 17 ^
+52 0 12 21 18 25 15 27 17 5 1 23 7 17 20 11 14 10 4 21 17 19 25 17 22 18 21 19 
+17 10 15 26 20 8 13 19 7 8 18 7 12 14 6 8 22 21 11 10 14 23 25 9 15 19 ^
+57 1 18 6 17 24 7 13 6 12 7 2 18 18 26 13 13 16 8 24 10 3 26 9 20 1 12 2 14 13 
+23 12 25 3 24 11 6 3 8 27 8 21 26 3 11 19 18 5 5 25 26 24 4 23 15 15 23 21 12 ^
+67 1 5 15 21 3 3 18 2 24 27 11 20 10 11 4 5 12 2 23 6 5 3 1 14 26 15 12 6 28 12 
+19 20 6 23 4 7 7 3 10 24 28 6 10 9 6 20 14 27 10 19 11 1 15 21 5 10 7 11 8 16 9 
+27 5 2 6 6 27 2 ^
+56 1 24 21 2 20 16 14 24 17 15 3 2 26 25 25 14 24 20 28 14 17 5 9 10 25 20 12 9 
+18 3 16 4 10 7 18 23 17 2 8 1 28 7 2 15 5 18 11 23 2 1 18 22 14 7 20 21 24 ^
+60 1 11 12 3 15 12 4 1 27 21 16 27 19 18 13 21 14 5 20 9 19 27 6 3 5 16 16 22 2 
+13 7 4 13 19 27 15 7 16 25 3 4 4 17 12 13 11 12 26 6 1 10 15 18 4 19 10 27 9 4 
+25 27 ^
+51 0 21 25 26 21 20 12 25 21 7 17 28 27 3 13 14 19 3 23 19 4 28 3 20 18 9 7 15 
+4 26 5 6 20 5 23 28 10 24 19 13 28 1 9 12 23 16 10 13 2 19 21 23 ^
+49 1 25 22 28 23 16 7 20 4 2 22 11 26 22 6 9 17 11 21 5 1 3 28 11 27 25 12 8 26 
+26 28 24 13 22 17 6 4 24 15 17 18 4 22 23 9 24 12 27 27 9 ^
+56 0 9 13 15 11 9 22 28 26 11 18 15 10 6 16 17 14 11 25 27 16 28 22 24 1 1 11 7 
+24 3 28 7 5 28 16 15 1 7 14 9 7 6 15 25 19 9 3 19 23 1 26 20 17 17 1 16 16 ^
+51 0 9 16 8 15 6 21 17 22 9 28 8 8 5 4 24 27 14 4 21 26 23 7 8 27 23 23 22 19 
+24 25 16 19 12 22 10 20 3 7 14 1 20 6 26 23 27 4 16 20 18 12 22 ^
+51 0 15 19 16 18 20 27 11 11 17 24 18 1 19 1 25 23 2 15 16 26 27 23 14 12 28 22 
+15 8 19 2 20 13 1 24 2 25 1 6 19 19 8 11 24 24 21 13 27 5 11 28 16 ^
+59 0 7 25 6 23 24 14 25 12 5 13 26 2 5 8 10 16 11 5 26 18 19 21 3 12 11 13 4 14 
+22 22 14 16 13 3 22 16 23 5 19 6 13 10 26 17 27 26 4 3 25 6 14 2 3 5 7 23 11 22 
+10 ^
+59 0 25 2 9 25 18 17 8 2 14 4 19 1 5 27 13 9 2 27 28 2 17 23 10 27 18 26 7 22 
+16 3 27 1 26 21 28 10 3 6 2 2 10 17 13 16 6 17 21 23 13 20 22 5 6 11 12 12 8 23 
+7 ^
+56 1 17 9 23 20 3 28 27 12 17 25 28 19 5 21 4 27 8 1 19 14 20 6 7 9 1 6 22 3 19 
+26 14 8 6 7 19 15 23 1 17 16 6 26 14 5 22 25 4 7 10 16 21 10 18 19 24 16 ^
+57 1 23 8 3 17 28 18 10 2 5 3 21 21 15 6 24 1 4 24 18 10 22 1 21 12 5 4 4 20 25 
+24 26 8 25 11 2 7 27 22 19 4 18 27 10 28 4 12 24 8 16 12 11 16 17 25 8 12 18 ^
+63 0 1 9 9 10 5 24 23 18 5 14 18 8 4 9 5 17 8 28 1 22 4 11 3 2 17 3 14 9 27 13 
+18 24 9 8 7 28 25 14 21 27 24 6 18 16 2 12 15 9 14 10 1 8 17 4 6 15 26 11 15 2 
+28 20 16 ^
+52 1 16 3 7 5 8 9 26 10 12 25 11 9 13 24 15 20 2 4 8 2 22 20 19 4 15 14 28 13 
+25 10 10 12 28 24 22 26 28 15 9 11 26 19 22 27 2 21 8 20 23 26 12 28 ^
+60 0 21 9 15 13 25 7 26 1 13 5 9 1 3 9 21 22 7 1 23 28 1 2 8 22 12 18 28 5 18 
+14 7 11 17 20 20 7 21 13 8 28 21 22 2 16 20 15 28 9 3 22 13 10 23 4 16 11 14 1 
+10 20 ^
+54 1 14 14 15 18 13 12 21 18 25 15 27 17 5 1 23 7 17 20 11 14 10 4 21 17 19 25 
+17 22 18 21 19 17 10 15 26 20 8 13 19 7 8 18 7 12 14 6 8 22 21 11 10 14 23 11 ^
+58 0 9 15 22 18 6 17 24 7 13 6 12 7 2 18 18 26 13 13 16 8 24 10 3 26 9 20 1 12 
+2 14 13 23 12 25 3 24 11 6 3 8 27 8 21 26 3 11 19 18 5 5 25 26 24 4 23 15 15 27 
+^
+64 1 21 24 5 15 21 3 3 18 2 24 27 11 20 10 11 4 5 12 2 23 6 5 3 1 14 26 15 12 6 
+28 12 19 20 6 23 4 7 7 3 10 24 28 6 10 9 6 20 14 27 10 19 11 1 15 21 5 10 7 11 
+8 16 9 27 20 ^
+58 1 2 6 6 27 20 24 21 2 20 16 14 24 17 15 3 2 26 25 25 14 24 20 28 14 17 5 9 
+10 25 20 12 9 18 3 16 4 10 7 18 23 17 2 8 1 28 7 2 15 5 18 11 23 2 1 18 22 14 
+28 ^
+62 0 20 21 2 11 12 3 15 12 4 1 27 21 16 27 19 18 13 21 14 5 20 9 19 27 6 3 5 16 
+16 22 2 13 7 4 13 19 27 15 7 16 25 3 4 4 17 12 13 11 12 26 6 1 10 15 18 4 19 10 
+27 9 4 26 ^
+52 0 13 21 25 26 21 20 12 25 21 7 17 28 27 3 13 14 19 3 23 19 4 28 3 20 18 9 7 
+15 4 26 5 6 20 5 23 28 10 24 19 13 28 1 9 12 23 16 10 13 2 19 21 27 ^
+49 1 25 22 28 23 16 7 20 4 2 22 11 26 22 6 9 17 11 21 5 1 3 28 11 27 25 12 8 26 
+26 28 24 13 22 17 6 4 24 15 17 18 4 22 23 9 24 12 27 27 26 ^
+57 0 9 13 15 11 9 22 28 26 11 18 15 10 6 16 17 14 11 25 27 16 28 22 24 1 1 11 7 
+24 3 28 7 5 28 16 15 1 7 14 9 7 6 15 25 19 9 3 19 23 1 26 20 17 17 1 16 24 9 ^
+52 1 9 16 8 15 6 21 17 22 9 28 8 8 5 4 24 27 14 4 21 26 23 7 8 27 23 23 22 19 
+24 25 16 19 12 22 10 20 3 7 14 1 20 6 26 23 27 4 16 20 18 12 20 19 ^
+52 1 19 16 18 20 27 11 11 17 24 18 1 19 1 25 23 2 15 16 26 27 23 14 12 28 22 15 
+8 19 2 20 13 1 24 2 25 1 6 19 19 8 11 24 24 21 13 27 5 11 28 17 7 24 ^
+59 0 6 23 24 14 25 12 5 13 26 2 5 8 10 16 11 5 26 18 19 21 3 12 11 13 4 14 22 
+22 14 16 13 3 22 16 23 5 19 6 13 10 26 17 27 26 4 3 25 6 14 2 3 5 7 23 11 22 8 
+25 26 ^
+59 0 9 25 18 17 8 2 14 4 19 1 5 27 13 9 2 27 28 2 17 23 10 27 18 26 7 22 16 3 
+27 1 26 21 28 10 3 6 2 2 10 17 13 16 6 17 21 23 13 20 22 5 6 11 12 12 8 23 13 
+17 21 ^
+56 1 23 20 3 28 27 12 17 25 28 19 5 21 4 27 8 1 19 14 20 6 7 9 1 6 22 3 19 26 
+14 8 6 7 19 15 23 1 17 16 6 26 14 5 22 25 4 7 10 16 21 10 18 19 24 16 23 20 ^
+60 0 3 17 28 18 10 2 5 3 21 21 15 6 24 1 4 24 18 10 22 1 21 12 5 4 4 20 25 24 
+26 8 25 11 2 7 27 22 19 4 18 27 10 28 4 12 24 8 16 12 11 16 17 25 8 12 16 1 9 9 
+10 21 ^
+60 0 24 23 18 5 14 18 8 4 9 5 17 8 28 1 22 4 11 3 2 17 3 14 9 27 13 18 24 9 8 7 
+28 25 14 21 27 24 6 18 16 2 12 15 9 14 10 1 8 17 4 6 15 26 11 15 2 28 20 26 16 
+25 ^
+53 1 7 5 8 9 26 10 12 25 11 9 13 24 15 20 2 4 8 2 22 20 19 4 15 14 28 13 25 10 
+10 12 28 24 22 26 28 15 9 11 26 19 22 27 2 21 8 20 23 26 12 10 21 9 24 ^
+62 1 13 25 7 26 1 13 5 9 1 3 9 21 22 7 1 23 28 1 2 8 22 12 18 28 5 18 14 7 11 
+17 20 20 7 21 13 8 28 21 22 2 16 20 15 28 9 3 22 13 10 23 4 16 11 14 1 10 8 14 
+14 15 18 13 ^
+54 0 12 21 18 25 15 27 17 5 1 23 7 17 20 11 14 10 4 21 17 19 25 17 22 18 21 19 
+17 10 15 26 20 8 13 19 7 8 18 7 12 14 6 8 22 21 11 10 14 23 25 9 15 22 18 13 ^
+58 0 17 24 7 13 6 12 7 2 18 18 26 13 13 16 8 24 10 3 26 9 20 1 12 2 14 13 23 12 
+25 3 24 11 6 3 8 27 8 21 26 3 11 19 18 5 5 25 26 24 4 23 15 15 23 21 24 5 15 26 
+^
+67 1 3 3 18 2 24 27 11 20 10 11 4 5 12 2 23 6 5 3 1 14 26 15 12 6 28 12 19 20 6 
+23 4 7 7 3 10 24 28 6 10 9 6 20 14 27 10 19 11 1 15 21 5 10 7 11 8 16 9 27 5 2 
+6 6 27 20 24 21 12 ^
+62 0 20 16 14 24 17 15 3 2 26 25 25 14 24 20 28 14 17 5 9 10 25 20 12 9 18 3 16 
+4 10 7 18 23 17 2 8 1 28 7 2 15 5 18 11 23 2 1 18 22 14 7 20 21 2 11 12 3 15 12 
+4 1 27 18 ^
+61 1 4 9 14 16 15 8 11 21 20 10 10 21 23 20 2 11 23 1 11 1 5 3 23 16 15 27 14 5 
+16 3 22 2 3 24 3 19 29 4 4 10 8 20 14 15 1 26 12 27 25 4 28 22 11 19 19 24 5 20 
+8 9 26 ^
+55 1 25 19 17 19 15 7 24 24 21 3 20 16 8 3 17 28 18 29 9 23 9 10 29 4 12 24 15 
+5 8 22 17 29 12 3 8 29 15 21 21 4 7 20 7 10 7 26 10 16 24 6 7 12 8 12 28 ^
+52 1 24 9 17 11 28 12 26 26 6 29 13 10 20 6 23 10 4 3 26 26 14 20 20 25 14 13 
+15 24 14 11 4 23 27 24 20 9 16 17 24 13 12 6 1 14 26 25 7 8 21 1 19 27 ^
+65 0 3 2 2 17 21 13 5 9 21 28 9 1 13 2 21 8 24 1 3 27 13 18 19 4 15 12 5 2 16 
+27 16 6 2 1 23 17 14 28 19 23 6 22 16 4 19 6 16 28 3 3 1 15 13 22 6 15 11 6 4 
+24 25 15 19 23 12 ^
+55 0 1 9 15 10 12 7 25 11 25 2 27 6 6 18 4 13 1 4 11 25 17 6 29 21 24 27 21 17 
+17 26 24 13 4 22 24 29 2 11 8 17 4 23 11 26 1 25 28 15 19 10 3 9 29 27 24 ^
+53 1 22 3 27 21 2 26 19 9 19 27 23 3 12 17 10 4 8 27 19 16 1 21 23 28 23 18 8 
+25 18 26 20 8 17 19 2 4 11 7 18 6 24 2 25 25 5 27 20 3 28 20 18 21 11 ^
+55 0 25 10 1 28 28 29 16 20 19 26 16 21 6 23 15 28 26 28 7 15 18 11 5 17 20 26 
+1 10 14 8 4 16 26 17 8 10 22 22 18 1 20 24 7 1 9 7 19 5 22 1 4 26 11 10 20 ^
+58 0 5 14 2 6 4 2 9 22 15 13 20 22 26 18 16 9 2 15 20 27 8 6 17 5 15 9 25 10 26 
+4 5 27 5 19 21 5 6 11 29 19 8 2 24 26 22 19 18 17 23 14 21 14 22 13 20 5 29 12 ^
+54 0 5 26 6 21 29 3 5 12 16 11 13 16 18 18 10 11 20 21 12 11 12 22 14 19 3 21 
+15 6 25 26 29 24 19 17 18 25 22 12 13 23 23 12 10 13 1 22 10 2 22 2 28 10 17 28 
+^
+56 0 3 6 19 28 17 11 1 9 14 4 29 29 23 25 13 19 18 2 7 21 6 8 29 5 11 22 14 14 
+9 28 13 25 24 28 8 14 9 3 14 18 26 9 9 12 13 17 25 16 5 8 4 24 10 24 23 25 ^
+49 0 29 21 9 18 28 25 11 3 16 4 21 25 3 4 18 12 12 29 26 13 26 23 26 7 23 10 9 
+27 26 21 25 21 18 9 24 16 22 5 21 7 7 27 4 20 23 13 27 10 27 ^
+58 1 29 7 19 13 13 8 19 20 18 2 19 22 29 3 10 6 9 13 24 17 16 9 20 21 27 2 19 7 
+8 26 25 12 2 14 3 1 1 16 12 20 28 24 12 5 24 25 20 1 12 25 9 2 6 20 15 14 29 20 
+^
+56 0 21 28 1 17 6 17 27 1 2 10 16 19 5 14 10 27 11 17 3 29 14 27 17 5 2 18 20 
+11 27 18 22 27 22 9 8 18 3 14 10 5 2 24 18 23 21 26 8 22 8 1 6 27 27 15 29 18 ^
+64 0 2 29 22 8 16 20 4 12 9 6 12 16 16 7 9 20 29 11 9 4 1 15 25 16 29 10 22 7 2 
+8 5 18 14 23 24 4 6 26 3 11 6 12 1 7 14 24 14 6 10 21 16 23 29 25 6 14 17 2 12 
+10 5 10 15 25 ^
+62 1 8 15 3 7 13 25 16 14 1 29 22 26 15 27 9 1 8 8 28 6 13 5 13 3 15 5 23 8 23 
+2 5 5 4 17 13 14 7 17 12 27 3 18 5 7 5 26 18 15 22 28 16 13 7 2 23 19 25 29 17 
+7 16 22 ^
+55 1 23 11 11 15 2 13 9 26 2 24 26 7 28 11 2 29 7 22 23 5 28 19 1 27 29 1 24 11 
+18 20 3 13 11 7 3 15 17 24 1 18 13 6 3 25 27 16 28 18 24 8 23 7 29 28 15 ^
+52 0 28 14 12 28 27 22 4 14 25 1 3 9 7 11 14 15 16 10 19 12 19 11 20 13 28 4 27 
+28 7 27 12 4 28 21 17 22 20 17 15 15 23 22 13 12 21 22 21 11 12 14 12 28 ^
+62 0 27 8 7 4 9 14 16 15 8 11 21 20 10 10 21 23 20 2 11 23 1 11 1 5 3 23 16 15 
+27 14 5 16 3 22 2 3 24 3 19 29 4 4 10 8 20 14 15 1 26 12 27 25 4 28 22 11 19 19 
+24 5 20 18 ^
+58 0 9 5 25 19 17 19 15 7 24 24 21 3 20 16 8 3 17 28 18 29 9 23 9 10 29 4 12 24 
+15 5 8 22 17 29 12 3 8 29 15 21 21 4 7 20 7 10 7 26 10 16 24 6 7 12 8 12 15 16 ^
+56 0 9 17 11 28 12 26 26 6 29 13 10 20 6 23 10 4 3 26 26 14 20 20 25 14 13 15 
+24 14 11 4 23 27 24 20 9 16 17 24 13 12 6 1 14 26 25 7 8 21 1 19 3 2 2 17 21 23 
+^
+64 1 5 9 21 28 9 1 13 2 21 8 24 1 3 27 13 18 19 4 15 12 5 2 16 27 16 6 2 1 23 
+17 14 28 19 23 6 22 16 4 19 6 16 28 3 3 1 15 13 22 6 15 11 6 4 24 25 15 19 23 
+28 1 9 15 10 24 ^
+54 0 7 25 11 25 2 27 6 6 18 4 13 1 4 11 25 17 6 29 21 24 27 21 17 17 26 24 13 4 
+22 24 29 2 11 8 17 4 23 11 26 1 25 28 15 19 10 3 9 29 27 7 22 3 27 29 ^
+54 1 2 26 19 9 19 27 23 3 12 17 10 4 8 27 19 16 1 21 23 28 23 18 8 25 18 26 20 
+8 17 19 2 4 11 7 18 6 24 2 25 25 5 27 20 3 28 20 18 21 10 25 10 1 28 27 ^
+60 0 29 16 20 19 26 16 21 6 23 15 28 26 28 7 15 18 11 5 17 20 26 1 10 14 8 4 16 
+26 17 8 10 22 22 18 1 20 24 7 1 9 7 19 5 22 1 4 26 11 10 28 5 14 2 6 4 2 9 22 
+15 22 ^
+54 1 20 22 26 18 16 9 2 15 20 27 8 6 17 5 15 9 25 10 26 4 5 27 5 19 21 5 6 11 
+29 19 8 2 24 26 22 19 18 17 23 14 21 14 22 13 20 5 29 6 5 26 6 21 29 28 ^
+57 1 5 12 16 11 13 16 18 18 10 11 20 21 12 11 12 22 14 19 3 21 15 6 25 26 29 24 
+19 17 18 25 22 12 13 23 23 12 10 13 1 22 10 2 22 2 28 10 17 18 3 6 19 28 17 11 
+1 9 23 ^
+54 0 14 4 29 29 23 25 13 19 18 2 7 21 6 8 29 5 11 22 14 14 9 28 13 25 24 28 8 
+14 9 3 14 18 26 9 9 12 13 17 25 16 5 8 4 24 10 24 23 4 29 21 9 18 28 27 ^
+52 1 11 3 16 4 21 25 3 4 18 12 12 29 26 13 26 23 26 7 23 10 9 27 26 21 25 21 18 
+9 24 16 22 5 21 7 7 27 4 20 23 13 27 10 23 29 7 19 13 13 8 19 20 23 ^
+61 0 2 19 22 29 3 10 6 9 13 24 17 16 9 20 21 27 2 19 7 8 26 25 12 2 14 3 1 1 16 
+12 20 28 24 12 5 24 25 20 1 12 25 9 2 6 20 15 14 29 18 21 28 1 17 6 17 27 1 2 
+10 16 19 ^
+57 1 5 14 10 27 11 17 3 29 14 27 17 5 2 18 20 11 27 18 22 27 22 9 8 18 3 14 10 
+5 2 24 18 23 21 26 8 22 8 1 6 27 27 15 29 20 2 29 22 8 16 20 4 12 9 6 12 16 24 ^
+64 0 7 9 20 29 11 9 4 1 15 25 16 29 10 22 7 2 8 5 18 14 23 24 4 6 26 3 11 6 12 
+1 7 14 24 14 6 10 21 16 23 29 25 6 14 17 2 12 10 5 10 15 25 8 15 3 7 13 25 16 
+14 1 29 22 26 10 ^
+63 1 27 9 1 8 8 28 6 13 5 13 3 15 5 23 8 23 2 5 5 4 17 13 14 7 17 12 27 3 18 5 
+7 5 26 18 15 22 28 16 13 7 2 23 19 25 29 17 7 16 25 23 11 11 15 2 13 9 26 2 24 
+26 7 28 11 ^
+56 1 2 29 7 22 23 5 28 19 1 27 29 1 24 11 18 20 3 13 11 7 3 15 17 24 1 18 13 6 
+3 25 27 16 28 18 24 8 23 7 29 28 6 28 14 12 28 27 22 4 14 25 1 3 9 7 11 29 ^
+54 0 15 16 10 19 12 19 11 20 13 28 4 27 28 7 27 12 4 28 21 17 22 20 17 15 15 23 
+22 13 12 21 22 21 11 12 14 12 18 27 8 7 4 9 14 16 15 8 11 21 20 10 10 21 23 22 ^
+63 0 2 11 23 1 11 1 5 3 23 16 15 27 14 5 16 3 22 2 3 24 3 19 29 4 4 10 8 20 14 
+15 1 26 12 27 25 4 28 22 11 19 19 24 5 20 8 9 5 25 19 17 19 15 7 24 24 21 3 20 
+16 8 3 17 19 ^
+59 0 18 29 9 23 9 10 29 4 12 24 15 5 8 22 17 29 12 3 8 29 15 21 21 4 7 20 7 10 
+7 26 10 16 24 6 7 12 8 12 15 24 9 17 11 28 12 26 26 6 29 13 10 20 6 23 10 4 3 
+26 10 ^
+62 0 14 20 20 25 14 13 15 24 14 11 4 23 27 24 20 9 16 17 24 13 12 6 1 14 26 25 
+7 8 21 1 19 3 2 2 17 21 13 5 9 21 28 9 1 13 2 21 8 24 1 3 27 13 18 19 4 15 12 5 
+2 16 27 29 ^
+62 0 6 2 1 23 17 14 28 19 23 6 22 16 4 19 6 16 28 3 3 1 15 13 22 6 15 11 6 4 24 
+25 15 19 23 28 1 9 15 10 12 7 25 11 25 2 27 6 6 18 4 13 1 4 11 25 17 6 29 21 24 
+27 21 18 ^
+54 1 17 26 24 13 4 22 24 29 2 11 8 17 4 23 11 26 1 25 28 15 19 10 3 9 29 27 7 
+22 3 27 21 2 26 19 9 19 27 23 3 12 17 10 4 8 27 19 16 1 21 23 28 23 18 17 ^
+52 0 25 18 26 20 8 17 19 2 4 11 7 18 6 24 2 25 25 5 27 20 3 28 20 18 21 10 25 
+10 1 28 28 29 16 20 19 26 16 21 6 23 15 28 26 28 7 15 18 11 5 17 20 13 ^
+68 0 1 10 14 8 4 16 26 17 8 10 22 22 18 1 20 24 7 1 9 7 19 5 22 1 4 26 11 10 28 
+5 14 2 6 4 2 9 22 15 13 20 22 26 18 16 9 2 15 20 27 8 6 17 5 15 9 25 10 26 4 5 
+27 5 19 21 5 6 11 19 ^
+54 1 19 8 2 24 26 22 19 18 17 23 14 21 14 22 13 20 5 29 6 5 26 6 21 29 3 5 12 
+16 11 13 16 18 18 10 11 20 21 12 11 12 22 14 19 3 21 15 6 25 26 29 24 19 17 24 ^
+59 0 25 22 12 13 23 23 12 10 13 1 22 10 2 22 2 28 10 17 18 3 6 19 28 17 11 1 9 
+14 4 29 29 23 25 13 19 18 2 7 21 6 8 29 5 11 22 14 14 9 28 13 25 24 28 8 14 9 3 
+14 16 ^
+53 0 26 9 9 12 13 17 25 16 5 8 4 24 10 24 23 4 29 21 9 18 28 25 11 3 16 4 21 25 
+3 4 18 12 12 29 26 13 26 23 26 7 23 10 9 27 26 21 25 21 18 9 24 16 17 ^
+59 0 5 21 7 7 27 4 20 23 13 27 10 23 29 7 19 13 13 8 19 20 18 2 19 22 29 3 10 6 
+9 13 24 17 16 9 20 21 27 2 19 7 8 26 25 12 2 14 3 1 1 16 12 20 28 24 12 5 24 25 
+19 ^
+60 0 1 12 25 9 2 6 20 15 14 29 18 21 28 1 17 6 17 27 1 2 10 16 19 5 14 10 27 11 
+17 3 29 14 27 17 5 2 18 20 11 27 18 22 27 22 9 8 18 3 14 10 5 2 24 18 23 21 26 
+8 22 13 ^
+62 0 1 6 27 27 15 29 20 2 29 22 8 16 20 4 12 9 6 12 16 16 7 9 20 29 11 9 4 1 15 
+25 16 29 10 22 7 2 8 5 18 14 23 24 4 6 26 3 11 6 12 1 7 14 24 14 6 10 21 16 23 
+29 25 24 ^
+67 0 14 17 2 12 10 5 10 15 25 8 15 3 7 13 25 16 14 1 29 22 26 15 27 9 1 8 8 28 
+6 13 5 13 3 15 5 23 8 23 2 5 5 4 17 13 14 7 17 12 27 3 18 5 7 5 26 18 15 22 28 
+16 13 7 2 23 19 25 14 ^
+58 1 17 7 16 25 23 11 11 15 2 13 9 26 2 24 26 7 28 11 2 29 7 22 23 5 28 19 1 27 
+29 1 24 11 18 20 3 13 11 7 3 15 17 24 1 18 13 6 3 25 27 16 28 18 24 8 23 7 29 
+11 ^
+55 0 6 28 14 12 28 27 22 4 14 25 1 3 9 7 11 14 15 16 10 19 12 19 11 20 13 28 4 
+27 28 7 27 12 4 28 21 17 22 20 17 15 15 23 22 13 12 21 22 21 11 12 14 12 18 27 
+10 ^
+65 0 7 4 9 14 16 15 8 11 21 20 10 10 21 23 20 2 11 23 1 11 1 5 3 23 16 15 27 14 
+5 16 3 22 2 3 24 3 19 29 4 4 10 8 20 14 15 1 26 12 27 25 4 28 22 11 19 19 24 5 
+20 8 9 5 25 19 20 ^
+59 1 19 15 7 24 24 21 3 20 16 8 3 17 28 18 29 9 23 9 10 29 4 12 24 15 5 8 22 17 
+29 12 3 8 29 15 21 21 4 7 20 7 10 7 26 10 16 24 6 7 12 8 12 15 24 9 17 11 28 12 
+23 ^
+61 0 26 6 29 13 10 20 6 23 10 4 3 26 26 14 20 20 25 14 13 15 24 14 11 4 23 27 
+24 20 9 16 17 24 13 12 6 1 14 26 25 7 8 21 1 19 3 2 2 17 21 13 5 9 21 28 9 1 13 
+2 21 8 29 ^
+68 0 1 3 27 13 18 19 4 15 12 5 2 16 27 16 6 2 1 23 17 14 28 19 23 6 22 16 4 19 
+6 16 28 3 3 1 15 13 22 6 15 11 6 4 24 25 15 19 23 28 1 9 15 10 12 7 25 11 25 2 
+27 6 6 18 4 13 1 4 11 26 ^
+54 1 17 6 29 21 24 27 21 17 17 26 24 13 4 22 24 29 2 11 8 17 4 23 11 26 1 25 28 
+15 19 10 3 9 29 27 7 22 3 27 21 2 26 19 9 19 27 23 3 12 17 10 4 8 27 20 ^
+52 1 16 1 21 23 28 23 18 8 25 18 26 20 8 17 19 2 4 11 7 18 6 24 2 25 25 5 27 20 
+3 28 20 18 21 10 25 10 1 28 28 29 16 20 19 26 16 21 6 23 15 28 26 12 ^
+67 0 7 15 18 11 5 17 20 26 1 10 14 8 4 16 26 17 8 10 22 22 18 1 20 24 7 1 9 7 
+19 5 22 1 4 26 11 10 28 5 14 2 6 4 2 9 22 15 13 20 22 26 18 16 9 2 15 20 27 8 6 
+17 5 15 9 25 10 26 19 ^
+58 0 5 27 5 19 21 5 6 11 29 19 8 2 24 26 22 19 18 17 23 14 21 14 22 13 20 5 29 
+6 5 26 6 21 29 3 5 12 16 11 13 16 18 18 10 11 20 21 12 11 12 22 14 19 3 21 15 6 
+25 27 ^
+57 0 29 24 19 17 18 25 22 12 13 23 23 12 10 13 1 22 10 2 22 2 28 10 17 18 3 6 
+19 28 17 11 1 9 14 4 29 29 23 25 13 19 18 2 7 21 6 8 29 5 11 22 14 14 9 28 13 
+25 25 ^
+52 0 15 29 9 28 20 2 30 26 21 17 8 28 17 22 29 24 8 11 18 29 15 6 7 27 27 17 24 
+18 23 11 19 8 30 5 24 22 12 25 15 28 23 5 10 21 5 8 7 3 10 19 17 18 ^
+62 0 9 15 29 10 7 4 1 16 21 16 29 13 18 5 3 8 15 8 21 29 20 5 27 2 13 27 7 7 30 
+2 18 26 10 2 5 29 21 15 25 26 24 8 12 20 3 9 10 30 7 12 24 5 13 1 6 10 25 13 9 
+29 30 7 ^
+62 0 29 17 26 6 25 4 7 25 8 15 26 30 11 2 9 6 22 6 21 28 3 3 6 12 13 15 7 17 16 
+26 3 19 3 5 2 29 16 16 22 26 13 12 9 19 16 27 25 16 7 15 22 22 5 6 13 4 12 11 
+27 5 19 15 ^
+57 0 9 30 9 1 28 3 21 22 7 17 2 25 1 28 21 11 17 20 28 12 10 10 3 15 13 20 1 20 
+11 1 30 22 23 15 26 12 21 7 27 9 27 29 5 26 16 11 23 28 18 1 13 23 30 6 3 11 25 
+^
+61 1 16 10 13 13 19 15 18 7 22 10 29 3 25 30 8 22 13 4 4 27 22 18 21 23 17 15 
+16 19 20 17 10 17 21 20 6 14 14 1 10 18 4 5 5 9 17 18 14 5 12 22 22 11 8 18 24 
+21 3 7 21 9 22 ^
+58 1 3 4 23 14 17 25 27 10 5 16 30 23 2 4 25 3 16 28 4 6 6 17 12 18 2 23 7 29 
+23 29 27 19 7 20 21 25 5 17 9 7 1 21 20 19 29 19 14 8 23 23 19 3 18 17 3 29 14 
+17 ^
+62 1 23 28 5 22 8 10 1 1 11 27 18 3 2 22 28 14 24 12 1 3 30 29 11 22 19 7 16 1 
+11 4 28 8 20 25 2 6 8 5 14 11 21 9 16 8 25 6 26 27 1 29 12 8 16 4 17 5 30 30 24 
+12 19 21 ^
+57 1 25 11 13 12 27 16 14 3 24 20 24 23 22 9 14 19 26 8 13 6 13 25 19 5 1 19 1 
+17 28 30 13 21 11 4 10 23 25 7 5 11 20 7 24 29 27 13 16 17 1 15 12 29 4 16 27 
+12 21 ^
+65 0 2 2 24 17 13 22 20 22 4 20 16 2 17 3 11 29 1 5 10 14 23 3 14 9 2 7 18 20 
+13 2 16 25 24 4 4 14 7 13 8 20 12 23 1 26 7 9 19 6 16 3 8 26 21 10 26 23 24 28 
+16 12 14 25 22 16 15 ^
+53 0 21 24 27 30 15 10 15 2 18 13 26 28 23 16 23 10 2 11 26 26 4 29 18 4 24 24 
+1 24 13 5 21 29 26 2 10 16 6 5 7 23 19 11 28 22 21 1 24 19 7 26 18 30 26 ^
+58 0 21 6 18 22 2 1 14 2 14 5 25 1 27 24 6 23 16 5 1 20 29 22 25 9 25 10 3 28 
+28 25 19 18 16 24 14 15 5 28 12 28 26 29 2 15 15 9 5 18 19 22 12 15 4 6 15 24 
+16 22 ^
+59 0 4 26 25 18 27 19 20 4 26 12 3 22 1 22 30 3 28 10 9 24 14 29 6 30 3 10 20 
+14 6 3 19 21 21 28 16 18 11 30 11 20 30 1 9 8 11 5 19 10 24 4 22 4 2 26 5 15 20 
+8 25 ^
+55 1 13 30 18 8 1 25 28 20 20 15 21 18 18 12 16 13 24 9 21 2 28 6 1 23 9 18 27 
+27 4 9 13 10 8 14 16 15 12 11 14 21 14 10 11 25 17 17 30 21 13 27 26 26 22 14 
+21 ^
+57 0 17 21 19 9 9 20 23 13 7 10 28 24 10 22 27 23 27 8 17 14 6 4 21 26 15 1 8 
+29 27 6 28 15 3 27 25 25 14 19 13 29 8 24 2 8 2 4 12 19 11 10 6 26 14 22 24 30 
+2 ^
+56 1 11 12 2 12 17 23 8 8 12 28 13 14 28 2 17 4 8 3 26 9 23 21 30 30 20 4 13 28 
+29 9 3 17 7 19 30 28 1 2 20 9 12 24 15 30 20 27 3 23 11 6 29 25 23 26 17 23 ^
+61 1 10 22 15 23 6 25 5 4 30 2 19 23 15 27 14 26 1 1 7 19 12 7 6 20 18 14 4 15 
+17 28 7 11 7 8 9 22 17 12 5 23 18 25 18 6 12 26 30 12 30 14 3 1 18 10 20 27 21 
+8 6 24 30 ^
+54 0 20 11 24 7 2 4 18 15 14 30 16 19 2 27 15 4 19 25 29 29 7 14 18 9 11 9 27 
+11 15 29 9 28 20 2 30 26 21 17 8 28 17 22 29 24 8 11 18 29 15 6 7 27 27 7 ^
+63 1 24 18 23 11 19 8 30 5 24 22 12 25 15 28 23 5 10 21 5 8 7 3 10 19 17 6 9 15 
+29 10 7 4 1 16 21 16 29 13 18 5 3 8 15 8 21 29 20 5 27 2 13 27 7 7 30 2 18 26 
+10 2 5 29 12 ^
+63 1 15 25 26 24 8 12 20 3 9 10 30 7 12 24 5 13 1 6 10 25 13 9 29 30 17 29 17 
+26 6 25 4 7 25 8 15 26 30 11 2 9 6 22 6 21 28 3 3 6 12 13 15 7 17 16 26 3 19 3 
+5 2 29 16 17 ^
+60 1 22 26 13 12 9 19 16 27 25 16 7 15 22 22 5 6 13 4 12 11 27 5 19 28 9 30 9 1 
+28 3 21 22 7 17 2 25 1 28 21 11 17 20 28 12 10 10 3 15 13 20 1 20 11 1 30 22 23 
+15 26 6 ^
+56 0 21 7 27 9 27 29 5 26 16 11 23 28 18 1 13 23 30 6 3 11 11 16 10 13 13 19 15 
+18 7 22 10 29 3 25 30 8 22 13 4 4 27 22 18 21 23 17 15 16 19 20 17 10 17 21 20 
+11 ^
+64 1 14 14 1 10 18 4 5 5 9 17 18 14 5 12 22 22 11 8 18 24 21 3 7 21 9 4 3 4 23 
+14 17 25 27 10 5 16 30 23 2 4 25 3 16 28 4 6 6 17 12 18 2 23 7 29 23 29 27 19 7 
+20 21 25 5 30 ^
+63 1 9 7 1 21 20 19 29 19 14 8 23 23 19 3 18 17 3 29 14 27 23 28 5 22 8 10 1 1 
+11 27 18 3 2 22 28 14 24 12 1 3 30 29 11 22 19 7 16 1 11 4 28 8 20 25 2 6 8 5 
+14 11 21 9 29 ^
+57 0 8 25 6 26 27 1 29 12 8 16 4 17 5 30 30 24 12 19 24 25 11 13 12 27 16 14 3 
+24 20 24 23 22 9 14 19 26 8 13 6 13 25 19 5 1 19 1 17 28 30 13 21 11 4 10 23 25 
+6 ^
+68 0 5 11 20 7 24 29 27 13 16 17 1 15 12 29 4 16 27 12 6 2 2 24 17 13 22 20 22 
+4 20 16 2 17 3 11 29 1 5 10 14 23 3 14 9 2 7 18 20 13 2 16 25 24 4 4 14 7 13 8 
+20 12 23 1 26 7 9 19 6 30 ^
+54 1 3 8 26 21 10 26 23 24 28 16 12 14 25 22 16 2 21 24 27 30 15 10 15 2 18 13 
+26 28 23 16 23 10 2 11 26 26 4 29 18 4 24 24 1 24 13 5 21 29 26 2 10 16 6 27 ^
+56 0 7 23 19 11 28 22 21 1 24 19 7 26 18 30 25 21 6 18 22 2 1 14 2 14 5 25 1 27 
+24 6 23 16 5 1 20 29 22 25 9 25 10 3 28 28 25 19 18 16 24 14 15 5 28 12 28 9 ^
+58 0 29 2 15 15 9 5 18 19 22 12 15 4 6 15 24 16 9 4 26 25 18 27 19 20 4 26 12 3 
+22 1 22 30 3 28 10 9 24 14 29 6 30 3 10 20 14 6 3 19 21 21 28 16 18 11 30 11 20 
+29 ^
+65 0 1 9 8 11 5 19 10 24 4 22 4 2 26 5 15 20 8 3 13 30 18 8 1 25 28 20 20 15 21 
+18 18 12 16 13 24 9 21 2 28 6 1 23 9 18 27 27 4 9 13 10 8 14 16 15 12 11 14 21 
+14 10 11 25 17 17 20 ^
+55 0 21 13 27 26 26 22 14 13 17 21 19 9 9 20 23 13 7 10 28 24 10 22 27 23 27 8 
+17 14 6 4 21 26 15 1 8 29 27 6 28 15 3 27 25 25 14 19 13 29 8 24 2 8 2 4 30 ^
+57 1 19 11 10 6 26 14 22 24 30 10 11 12 2 12 17 23 8 8 12 28 13 14 28 2 17 4 8 
+3 26 9 23 21 30 30 20 4 13 28 29 9 3 17 7 19 30 28 1 2 20 9 12 24 15 30 20 27 
+30 ^
+59 0 23 11 6 29 25 23 26 17 20 10 22 15 23 6 25 5 4 30 2 19 23 15 27 14 26 1 1 
+7 19 12 7 6 20 18 14 4 15 17 28 7 11 7 8 9 22 17 12 5 23 18 25 18 6 12 26 30 12 
+30 18 ^
+56 0 3 1 18 10 20 27 21 8 6 24 26 20 11 24 7 2 4 18 15 14 30 16 19 2 27 15 4 19 
+25 29 29 7 14 18 9 11 9 27 11 15 29 9 28 20 2 30 26 21 17 8 28 17 22 29 24 7 ^
+62 0 11 18 29 15 6 7 27 27 17 24 18 23 11 19 8 30 5 24 22 12 25 15 28 23 5 10 
+21 5 8 7 3 10 19 17 6 9 15 29 10 7 4 1 16 21 16 29 13 18 5 3 8 15 8 21 29 20 5 
+27 2 13 27 7 ^
+62 1 7 30 2 18 26 10 2 5 29 21 15 25 26 24 8 12 20 3 9 10 30 7 12 24 5 13 1 6 
+10 25 13 9 29 30 17 29 17 26 6 25 4 7 25 8 15 26 30 11 2 9 6 22 6 21 28 3 3 6 
+12 13 15 26 ^
+62 0 17 16 26 3 19 3 5 2 29 16 16 22 26 13 12 9 19 16 27 25 16 7 15 22 22 5 6 
+13 4 12 11 27 5 19 28 9 30 9 1 28 3 21 22 7 17 2 25 1 28 21 11 17 20 28 12 10 
+10 3 15 13 20 19 ^
+56 1 20 11 1 30 22 23 15 26 12 21 7 27 9 27 29 5 26 16 11 23 28 18 1 13 23 30 6 
+3 11 11 16 10 13 13 19 15 18 7 22 10 29 3 25 30 8 22 13 4 4 27 22 18 21 23 17 
+22 ^
+66 1 16 19 20 17 10 17 21 20 6 14 14 1 10 18 4 5 5 9 17 18 14 5 12 22 22 11 8 
+18 24 21 3 7 21 9 4 3 4 23 14 17 25 27 10 5 16 30 23 2 4 25 3 16 28 4 6 6 17 12 
+18 2 23 7 29 23 29 24 ^
+62 0 19 7 20 21 25 5 17 9 7 1 21 20 19 29 19 14 8 23 23 19 3 18 17 3 29 14 27 
+23 28 5 22 8 10 1 1 11 27 18 3 2 22 28 14 24 12 1 3 30 29 11 22 19 7 16 1 11 4 
+28 8 20 25 7 ^
+59 0 6 8 5 14 11 21 9 16 8 25 6 26 27 1 29 12 8 16 4 17 5 30 30 24 12 19 24 25 
+11 13 12 27 16 14 3 24 20 24 23 22 9 14 19 26 8 13 6 13 25 19 5 1 19 1 17 28 30 
+13 26 ^
+70 0 11 4 10 23 25 7 5 11 20 7 24 29 27 13 16 17 1 15 12 29 4 16 27 12 6 2 2 24 
+17 13 22 20 22 4 20 16 2 17 3 11 29 1 5 10 14 23 3 14 9 2 7 18 20 13 2 16 25 24 
+4 4 14 7 13 8 20 12 23 1 26 7 ^
+54 1 9 19 6 16 3 8 26 21 10 26 23 24 28 16 12 14 25 22 16 2 21 24 27 30 15 10 
+15 2 18 13 26 28 23 16 23 10 2 11 26 26 4 29 18 4 24 24 1 24 13 5 21 29 26 27 ^
+58 1 10 16 6 5 7 23 19 11 28 22 21 1 24 19 7 26 18 30 25 21 6 18 22 2 1 14 2 14 
+5 25 1 27 24 6 23 16 5 1 20 29 22 25 9 25 10 3 28 28 25 19 18 16 24 14 15 5 28 
+28 ^
+58 1 28 26 29 2 15 15 9 5 18 19 22 12 15 4 6 15 24 16 9 4 26 25 18 27 19 20 4 
+26 12 3 22 1 22 30 3 28 10 9 24 14 29 6 30 3 10 20 14 6 3 19 21 21 28 16 18 11 
+30 22 ^
+65 1 20 30 1 9 8 11 5 19 10 24 4 22 4 2 26 5 15 20 8 3 13 30 18 8 1 25 28 20 20 
+15 21 18 18 12 16 13 24 9 21 2 28 6 1 23 9 18 27 27 4 9 13 10 8 14 16 15 12 11 
+14 21 14 10 11 25 20 ^
+53 0 17 30 21 13 27 26 26 22 14 13 17 21 19 9 9 20 23 13 7 10 28 24 10 22 27 23 
+27 8 17 14 6 4 21 26 15 1 8 29 27 6 28 15 3 27 25 25 14 19 13 29 8 24 15 ^
+61 0 8 2 4 12 19 11 10 6 26 14 22 24 30 10 11 12 2 12 17 23 8 8 12 28 13 14 28 
+2 17 4 8 3 26 9 23 21 30 30 20 4 13 28 29 9 3 17 7 19 30 28 1 2 20 9 12 24 15 
+30 20 27 20 ^
+60 0 23 11 6 29 25 23 26 17 20 10 22 15 23 6 25 5 4 30 2 19 23 15 27 14 26 1 1 
+7 19 12 7 6 20 18 14 4 15 17 28 7 11 7 8 9 22 17 12 5 23 18 25 18 6 12 26 30 12 
+30 14 20 ^
+56 0 3 1 18 10 20 27 21 8 6 24 26 20 11 24 7 2 4 18 15 14 30 16 19 2 27 15 4 19 
+25 29 29 7 14 18 9 11 9 27 11 15 29 9 28 20 2 30 26 21 17 8 28 17 22 29 24 23 ^
+62 0 11 18 29 15 6 7 27 27 17 24 18 23 11 19 8 30 5 24 22 12 25 15 28 23 5 10 
+21 5 8 7 3 10 19 17 6 9 15 29 10 7 4 1 16 21 16 29 13 18 5 3 8 15 8 21 29 20 5 
+27 2 13 27 23 ^
+64 1 7 30 2 18 26 10 2 5 29 21 15 25 26 24 8 12 20 3 9 10 30 7 12 24 5 13 1 6 
+10 25 13 9 29 30 17 29 17 26 6 25 4 7 25 8 15 26 30 11 2 9 6 22 6 21 28 3 3 6 
+12 13 15 7 17 18 ^
+65 0 26 3 19 3 5 2 29 16 16 22 26 13 12 9 19 16 27 25 16 7 15 22 22 5 6 13 4 12 
+11 27 5 19 28 9 30 9 1 28 3 21 22 7 17 2 25 1 28 21 11 17 20 28 12 10 10 3 15 
+13 20 1 20 11 1 30 5 ^
+57 0 23 15 26 12 21 7 27 9 27 29 5 26 16 11 23 28 18 1 13 23 30 6 3 11 11 16 10 
+13 13 19 15 18 7 22 10 29 3 25 30 8 22 13 4 4 27 22 18 21 23 17 15 16 19 20 17 
+10 25 ^
+66 1 21 20 6 14 14 1 10 18 4 5 5 9 17 18 14 5 12 22 22 11 8 18 24 21 3 7 21 9 4 
+3 4 23 14 17 25 27 10 5 16 30 23 2 4 25 3 16 28 4 6 6 17 12 18 2 23 7 29 23 29 
+27 19 7 20 21 25 20 ^
+65 1 17 9 7 1 21 20 19 29 19 14 8 23 23 19 3 18 17 3 29 14 27 23 28 5 22 8 10 1 
+1 11 27 18 3 2 22 28 14 24 12 1 3 30 29 11 22 19 7 16 1 11 4 28 8 20 25 2 6 8 5 
+14 11 21 9 16 28 ^
+59 1 25 6 26 27 1 29 12 8 16 4 17 5 30 30 24 12 19 24 25 11 13 12 27 16 14 3 24 
+20 24 23 22 9 14 19 26 8 13 6 13 25 19 5 1 19 1 17 28 30 13 21 11 4 10 23 25 7 
+5 11 23 ^
+70 0 20 7 24 29 27 13 16 17 1 15 12 29 4 16 27 12 6 2 2 24 17 13 22 20 22 4 20 
+16 2 17 3 11 29 1 5 10 14 23 3 14 9 2 7 18 20 13 2 16 25 24 4 4 14 7 13 8 20 12 
+23 1 26 7 9 19 6 16 3 8 26 25 ^
+56 0 10 26 23 24 28 16 12 14 25 22 16 2 21 24 27 30 15 10 15 2 18 13 26 28 23 
+16 23 10 2 11 26 26 4 29 18 4 24 24 1 24 13 5 21 29 26 2 10 16 6 5 7 23 19 11 
+28 24 ^
+59 1 21 1 24 19 7 26 18 30 25 21 6 18 22 2 1 14 2 14 5 25 1 27 24 6 23 16 5 1 
+20 29 22 25 9 25 10 3 28 28 25 19 18 16 24 14 15 5 28 12 28 26 29 2 15 15 9 5 
+18 19 13 ^
+63 1 12 15 4 6 15 24 16 9 4 26 25 18 27 19 20 4 26 12 3 22 1 22 30 3 28 10 9 24 
+14 29 6 30 3 10 20 14 6 3 19 21 21 28 16 18 11 30 11 20 30 1 9 8 11 5 19 10 24 
+4 22 4 2 26 20 ^
+59 1 15 20 8 3 13 30 18 8 1 25 28 20 20 15 21 18 18 12 16 13 24 9 21 2 28 6 1 
+23 9 18 27 27 4 9 13 10 8 14 16 15 12 11 14 21 14 10 11 25 17 17 30 21 13 27 26 
+26 22 14 23 ^
+61 0 16 21 30 25 8 9 18 30 17 4 6 31 26 16 25 18 23 9 20 8 7 25 26 11 27 17 28 
+2 23 2 12 24 2 8 6 3 12 20 16 4 10 17 30 12 11 5 31 19 19 19 30 13 18 2 3 8 2 
+17 8 24 28 ^
+69 0 22 2 7 26 1 13 26 6 6 6 18 24 7 6 7 30 19 12 22 24 25 3 11 17 3 10 12 11 
+11 25 7 13 31 4 7 27 13 10 30 16 30 16 29 4 27 5 6 27 8 12 29 9 1 10 9 26 4 19 
+1 3 3 4 16 13 17 6 16 14 28 ^
+62 0 3 20 3 2 1 30 14 14 21 29 13 11 10 29 20 19 26 27 19 6 17 26 26 7 9 13 16 
+9 31 2 20 28 10 10 4 28 3 24 21 6 29 16 1 22 31 1 24 9 16 22 28 11 7 7 3 17 13 
+22 4 17 9 27 ^
+60 0 21 23 17 24 16 24 11 26 5 31 30 2 24 14 9 23 28 18 4 13 23 4 3 9 9 14 12 
+13 8 20 12 18 6 21 12 25 3 27 8 21 13 5 26 21 18 19 23 16 12 14 20 17 16 7 16 
+19 22 9 15 25 ^
+64 0 31 7 18 29 5 7 2 5 16 18 10 7 11 21 21 9 8 18 25 19 3 6 19 29 10 3 5 23 15 
+16 27 26 12 2 19 23 1 22 3 19 28 5 2 9 4 21 11 18 1 23 6 30 23 30 26 20 11 22 
+19 27 2 16 10 31 ^
+60 0 4 24 17 20 25 20 15 8 23 23 20 30 18 16 3 30 15 26 23 28 7 21 8 7 31 31 14 
+26 18 3 1 26 28 15 25 11 31 3 25 9 21 20 2 6 14 4 9 5 28 8 17 22 1 4 8 7 10 14 
+19 19 ^
+62 0 14 8 27 9 24 26 4 30 11 8 19 5 21 7 2 27 20 16 20 20 22 14 13 16 26 14 10 
+3 25 22 25 23 21 10 15 15 29 8 13 4 2 13 22 20 7 4 20 31 16 2 2 28 13 19 14 12 
+23 27 6 2 14 24 ^
+62 0 22 6 25 30 29 31 13 14 16 31 12 16 30 5 14 31 11 4 1 1 25 21 13 26 22 21 5 
+22 14 29 1 21 3 14 30 4 2 29 12 15 23 3 15 5 1 6 23 22 13 1 14 27 25 5 15 6 13 
+3 22 11 23 21 ^
+56 1 24 6 5 20 4 14 3 29 8 29 19 7 29 23 25 28 19 11 15 27 21 14 1 19 20 26 12 
+7 12 1 18 13 29 28 23 29 14 23 7 1 9 29 24 5 30 18 5 25 25 31 25 13 7 24 25 11 ^
+54 0 1 12 19 9 7 6 28 20 14 28 21 19 31 20 20 6 24 18 27 24 4 18 21 1 31 15 1 
+15 2 27 4 26 25 4 23 19 2 31 22 30 21 22 5 27 12 30 28 28 27 15 18 14 25 23 ^
+59 1 17 7 28 11 28 29 30 1 17 12 10 2 18 20 21 2 11 12 5 4 12 25 14 5 5 24 22 
+18 31 15 22 29 11 3 21 31 21 27 3 28 7 10 25 2 15 30 9 30 7 22 15 9 3 20 24 24 
+28 14 25 ^
+58 0 9 27 14 22 27 31 10 8 14 7 15 7 20 5 26 1 29 7 17 17 8 3 13 27 18 8 31 27 
+28 22 22 17 19 18 18 11 19 13 25 10 19 6 28 4 31 23 10 18 26 31 5 10 13 12 8 15 
+19 24 ^
+56 1 11 14 15 24 15 12 9 22 16 16 24 13 2 26 24 29 26 15 13 21 24 20 10 10 22 
+23 13 6 12 28 25 12 2 21 26 28 26 8 16 15 4 5 19 24 12 31 8 30 31 9 28 12 3 26 
+29 8 ^
+65 0 27 10 20 13 30 8 25 1 8 1 5 11 20 9 12 4 29 15 21 25 27 7 14 11 1 11 16 23 
+8 8 11 1 13 15 28 1 16 5 8 3 24 10 23 24 17 5 13 28 30 5 3 16 6 20 28 31 6 22 
+10 11 29 25 17 27 23 ^
+60 0 26 3 23 14 4 30 27 23 24 21 17 12 21 17 23 4 22 7 5 27 1 20 23 12 26 10 24 
+31 29 4 11 15 11 6 9 17 18 15 5 17 21 28 6 9 6 8 10 21 16 11 2 23 18 27 29 18 9 
+11 24 24 ^
+58 1 11 15 29 29 3 31 18 12 17 31 19 8 4 25 29 17 29 9 25 6 1 2 18 17 15 19 15 
+1 26 17 20 27 30 30 6 10 18 5 9 10 26 9 17 2 30 10 28 17 1 27 29 2 19 16 8 28 
+16 28 ^
+61 1 30 25 8 9 18 30 17 4 6 31 26 16 25 18 23 9 20 8 7 25 26 11 27 17 28 2 23 2 
+12 24 2 8 6 3 12 20 16 4 10 17 30 12 11 5 31 19 19 19 30 13 18 2 3 8 2 17 8 24 
+30 22 29 ^
+70 0 7 26 1 13 26 6 6 6 18 24 7 6 7 30 19 12 22 24 25 3 11 17 3 10 12 11 11 25 
+7 13 31 4 7 27 13 10 30 16 30 16 29 4 27 5 6 27 8 12 29 9 1 10 9 26 4 19 1 3 3 
+4 16 13 17 6 16 14 24 3 20 21 ^
+62 1 2 1 30 14 14 21 29 13 11 10 29 20 19 26 27 19 6 17 26 26 7 9 13 16 9 31 2 
+20 28 10 10 4 28 3 24 21 6 29 16 1 22 31 1 24 9 16 22 28 11 7 7 3 17 13 22 4 17 
+9 4 21 23 21 ^
+62 1 24 16 24 11 26 5 31 30 2 24 14 9 23 28 18 4 13 23 4 3 9 9 14 12 13 8 20 12 
+18 6 21 12 25 3 27 8 21 13 5 26 21 18 19 23 16 12 14 20 17 16 7 16 19 22 9 15 
+10 31 7 18 29 7 ^
+66 1 7 2 5 16 18 10 7 11 21 21 9 8 18 25 19 3 6 19 29 10 3 5 23 15 16 27 26 12 
+2 19 23 1 22 3 19 28 5 2 9 4 21 11 18 1 23 6 30 23 30 26 20 11 22 19 27 2 16 10 
+6 4 24 17 20 25 20 21 ^
+62 1 8 23 23 20 30 18 16 3 30 15 26 23 28 7 21 8 7 31 31 14 26 18 3 1 26 28 15 
+25 11 31 3 25 9 21 20 2 6 14 4 9 5 28 8 17 22 1 4 8 7 10 14 19 10 14 8 27 9 24 
+26 4 30 8 ^
+62 1 8 19 5 21 7 2 27 20 16 20 20 22 14 13 16 26 14 10 3 25 22 25 23 21 10 15 
+15 29 8 13 4 2 13 22 20 7 4 20 31 16 2 2 28 13 19 14 12 23 27 6 2 14 2 22 6 25 
+30 29 31 13 14 21 ^
+65 0 31 12 16 30 5 14 31 11 4 1 1 25 21 13 26 22 21 5 22 14 29 1 21 3 14 30 4 2 
+29 12 15 23 3 15 5 1 6 23 22 13 1 14 27 25 5 15 6 13 3 22 11 23 31 24 6 5 20 4 
+14 3 29 8 29 19 31 ^
+55 1 29 23 25 28 19 11 15 27 21 14 1 19 20 26 12 7 12 1 18 13 29 28 23 29 14 23 
+7 1 9 29 24 5 30 18 5 25 25 31 25 13 7 24 25 24 1 12 19 9 7 6 28 20 14 28 27 ^
+53 1 19 31 20 20 6 24 18 27 24 4 18 21 1 31 15 1 15 2 27 4 26 25 4 23 19 2 31 
+22 30 21 22 5 27 12 30 28 28 27 15 18 14 25 15 17 7 28 11 28 29 30 1 17 21 ^
+61 0 10 2 18 20 21 2 11 12 5 4 12 25 14 5 5 24 22 18 31 15 22 29 11 3 21 31 21 
+27 3 28 7 10 25 2 15 30 9 30 7 22 15 9 3 20 24 24 28 14 18 9 27 14 22 27 31 10 
+8 14 7 15 19 ^
+59 1 20 5 26 1 29 7 17 17 8 3 13 27 18 8 31 27 28 22 22 17 19 18 18 11 19 13 25 
+10 19 6 28 4 31 23 10 18 26 31 5 10 13 12 8 15 19 17 11 14 15 24 15 12 9 22 16 
+16 24 13 23 ^
+57 0 26 24 29 26 15 13 21 24 20 10 10 22 23 13 6 12 28 25 12 2 21 26 28 26 8 16 
+15 4 5 19 24 12 31 8 30 31 9 28 12 3 26 29 22 27 10 20 13 30 8 25 1 8 1 5 11 20 
+16 ^
+61 1 12 4 29 15 21 25 27 7 14 11 1 11 16 23 8 8 11 1 13 15 28 1 16 5 8 3 24 10 
+23 24 17 5 13 28 30 5 3 16 6 20 28 31 6 22 10 11 29 25 17 27 22 26 3 23 14 4 30 
+27 23 24 31 ^
+61 1 17 12 21 17 23 4 22 7 5 27 1 20 23 12 26 10 24 31 29 4 11 15 11 6 9 17 18 
+15 5 17 21 28 6 9 6 8 10 21 16 11 2 23 18 27 29 18 9 11 24 27 11 15 29 29 3 31 
+18 12 17 31 12 ^
+60 1 8 4 25 29 17 29 9 25 6 1 2 18 17 15 19 15 1 26 17 20 27 30 30 6 10 18 5 9 
+10 26 9 17 2 30 10 28 17 1 27 29 2 19 16 8 28 16 21 30 25 8 9 18 30 17 4 6 31 
+26 16 18 ^
+67 1 18 23 9 20 8 7 25 26 11 27 17 28 2 23 2 12 24 2 8 6 3 12 20 16 4 10 17 30 
+12 11 5 31 19 19 19 30 13 18 2 3 8 2 17 8 24 30 22 2 7 26 1 13 26 6 6 6 18 24 7 
+6 7 30 19 12 22 24 28 ^
+69 1 3 11 17 3 10 12 11 11 25 7 13 31 4 7 27 13 10 30 16 30 16 29 4 27 5 6 27 8 
+12 29 9 1 10 9 26 4 19 1 3 3 4 16 13 17 6 16 14 24 3 20 3 2 1 30 14 14 21 29 13 
+11 10 29 20 19 26 27 19 6 28 ^
+62 1 26 26 7 9 13 16 9 31 2 20 28 10 10 4 28 3 24 21 6 29 16 1 22 31 1 24 9 16 
+22 28 11 7 7 3 17 13 22 4 17 9 4 21 23 17 24 16 24 11 26 5 31 30 2 24 14 9 23 
+28 18 4 13 26 ^
+70 1 4 3 9 9 14 12 13 8 20 12 18 6 21 12 25 3 27 8 21 13 5 26 21 18 19 23 16 12 
+14 20 17 16 7 16 19 22 9 15 10 31 7 18 29 5 7 2 5 16 18 10 7 11 21 21 9 8 18 25 
+19 3 6 19 29 10 3 5 23 15 16 17 ^
+60 1 26 12 2 19 23 1 22 3 19 28 5 2 9 4 21 11 18 1 23 6 30 23 30 26 20 11 22 19 
+27 2 16 10 6 4 24 17 20 25 20 15 8 23 23 20 30 18 16 3 30 15 26 23 28 7 21 8 7 
+31 31 7 ^
+66 0 26 18 3 1 26 28 15 25 11 31 3 25 9 21 20 2 6 14 4 9 5 28 8 17 22 1 4 8 7 
+10 14 19 10 14 8 27 9 24 26 4 30 11 8 19 5 21 7 2 27 20 16 20 20 22 14 13 16 26 
+14 10 3 25 22 25 23 17 ^
+64 1 10 15 15 29 8 13 4 2 13 22 20 7 4 20 31 16 2 2 28 13 19 14 12 23 27 6 2 14 
+2 22 6 25 30 29 31 13 14 16 31 12 16 30 5 14 31 11 4 1 1 25 21 13 26 22 21 5 22 
+14 29 1 21 3 14 27 ^
+64 0 4 2 29 12 15 23 3 15 5 1 6 23 22 13 1 14 27 25 5 15 6 13 3 22 11 23 31 24 
+6 5 20 4 14 3 29 8 29 19 7 29 23 25 28 19 11 15 27 21 14 1 19 20 26 12 7 12 1 
+18 13 29 28 23 29 13 ^
+58 0 23 7 1 9 29 24 5 30 18 5 25 25 31 25 13 7 24 25 24 1 12 19 9 7 6 28 20 14 
+28 21 19 31 20 20 6 24 18 27 24 4 18 21 1 31 15 1 15 2 27 4 26 25 4 23 19 2 31 
+28 ^
+57 0 30 21 22 5 27 12 30 28 28 27 15 18 14 25 15 17 7 28 11 28 29 30 1 17 12 10 
+2 18 20 21 2 11 12 5 4 12 25 14 5 5 24 22 18 31 15 22 29 11 3 21 31 21 27 3 28 
+7 26 ^
+59 0 25 2 15 30 9 30 7 22 15 9 3 20 24 24 28 14 18 9 27 14 22 27 31 10 8 14 7 
+15 7 20 5 26 1 29 7 17 17 8 3 13 27 18 8 31 27 28 22 22 17 19 18 18 11 19 13 25 
+10 19 19 ^
+59 0 28 4 31 23 10 18 26 31 5 10 13 12 8 15 19 17 11 14 15 24 15 12 9 22 16 16 
+24 13 2 26 24 29 26 15 13 21 24 20 10 10 22 23 13 6 12 28 25 12 2 21 26 28 26 8 
+16 15 4 5 31 ^
+66 1 24 12 31 8 30 31 9 28 12 3 26 29 22 27 10 20 13 30 8 25 1 8 1 5 11 20 9 12 
+4 29 15 21 25 27 7 14 11 1 11 16 23 8 8 11 1 13 15 28 1 16 5 8 3 24 10 23 24 17 
+5 13 28 30 5 3 16 21 ^
+59 0 20 28 31 6 22 10 11 29 25 17 27 22 26 3 23 14 4 30 27 23 24 21 17 12 21 17 
+23 4 22 7 5 27 1 20 23 12 26 10 24 31 29 4 11 15 11 6 9 17 18 15 5 17 21 28 6 9 
+6 8 26 ^
+59 0 21 16 11 2 23 18 27 29 18 9 11 24 27 11 15 29 29 3 31 18 12 17 31 19 8 4 
+25 29 17 29 9 25 6 1 2 18 17 15 19 15 1 26 17 20 27 30 30 6 10 18 5 9 10 26 9 
+17 2 30 24 ^
+61 0 28 17 1 27 29 2 19 16 8 28 16 21 30 25 8 9 18 30 17 4 6 31 26 16 25 18 23 
+9 20 8 7 25 26 11 27 17 28 2 23 2 12 24 2 8 6 3 12 20 16 4 10 17 30 12 11 5 31 
+19 19 19 25 ^
+74 0 13 18 2 3 8 2 17 8 24 30 22 2 7 26 1 13 26 6 6 6 18 24 7 6 7 30 19 12 22 
+24 25 3 11 17 3 10 12 11 11 25 7 13 31 4 7 27 13 10 30 16 30 16 29 4 27 5 6 27 
+8 12 29 9 1 10 9 26 4 19 1 3 3 4 16 16 ^
+64 1 17 6 16 14 24 3 20 3 2 1 30 14 14 21 29 13 11 10 29 20 19 26 27 19 6 17 26 
+26 7 9 13 16 9 31 2 20 28 10 10 4 28 3 24 21 6 29 16 1 22 31 1 24 9 16 22 28 11 
+7 7 3 17 13 22 27 ^
+65 0 17 9 4 21 23 17 24 16 24 11 26 5 31 30 2 24 14 9 23 28 18 4 13 23 4 3 9 9 
+14 12 13 8 20 12 18 6 21 12 25 3 27 8 21 13 5 26 21 18 19 23 16 12 14 20 17 16 
+7 16 19 22 9 15 10 31 1 ^
+68 1 18 29 5 7 2 5 16 18 10 7 11 21 21 9 8 18 25 19 3 6 19 29 10 3 5 23 15 16 
+27 26 12 2 19 23 1 22 3 19 28 5 2 9 4 21 11 18 1 23 6 30 23 30 26 20 11 22 19 
+27 2 16 10 6 4 24 17 20 25 20 ^
+63 0 15 8 23 23 20 30 18 16 3 30 15 26 23 28 7 21 8 7 31 31 14 26 18 3 1 26 28 
+15 25 11 31 3 25 9 21 20 2 6 14 4 9 5 28 8 17 22 1 4 8 7 10 14 19 10 14 8 27 9 
+24 26 4 30 24 ^
+64 1 8 19 5 21 7 2 27 20 16 20 20 22 14 13 16 26 14 10 3 25 22 25 23 21 10 15 
+15 29 8 13 4 2 13 22 20 7 4 20 31 16 2 2 28 13 19 14 12 23 27 6 2 14 2 22 6 25 
+30 29 31 13 14 16 31 5 ^
+67 0 16 30 5 14 31 11 4 1 1 25 21 13 26 22 21 5 22 14 29 1 21 3 14 30 4 2 29 12 
+15 23 3 15 5 1 6 23 22 13 1 14 27 25 5 15 6 13 3 22 11 23 31 24 6 5 20 4 14 3 
+29 8 29 19 7 29 23 25 21 ^
+58 0 19 11 15 27 21 14 1 19 20 26 12 7 12 1 18 13 29 28 23 29 14 23 7 1 9 29 24 
+5 30 18 5 25 25 31 25 13 7 24 25 24 1 12 19 9 7 6 28 20 14 28 21 19 31 20 20 6 
+24 22 ^
+60 0 27 24 4 18 21 1 31 15 1 15 2 27 4 26 25 4 23 19 2 31 22 30 21 22 5 27 12 
+30 28 28 27 15 18 14 25 15 17 7 28 11 28 29 30 1 17 12 10 2 18 20 21 2 11 12 5 
+4 12 25 14 22 ^
+60 1 5 24 22 18 31 15 22 29 11 3 21 31 21 27 3 28 7 10 25 2 15 30 9 30 7 22 15 
+9 3 20 24 24 28 14 18 9 27 14 22 27 31 10 8 14 7 15 7 20 5 26 1 29 7 17 17 8 3 
+13 27 31 ^
+58 0 8 31 27 28 22 22 17 19 18 18 11 19 13 25 10 19 6 28 4 31 23 10 18 26 31 5 
+10 13 12 8 15 19 17 11 14 15 24 15 12 9 22 16 16 24 13 2 26 24 29 26 15 13 21 
+24 20 10 10 25 ^
+65 0 23 13 6 12 28 25 12 2 21 26 28 26 8 16 15 4 5 19 24 12 31 8 30 31 9 28 12 
+3 26 29 22 27 10 20 13 30 8 25 1 8 1 5 11 20 9 12 4 29 15 21 25 27 7 14 11 1 11 
+16 23 8 8 11 1 13 21 ^
+60 1 28 1 16 5 8 3 24 10 23 24 17 5 13 28 30 5 3 16 6 20 28 31 6 22 10 11 29 25 
+17 27 22 26 3 23 14 4 30 27 23 24 21 17 12 21 17 23 4 22 7 5 27 1 20 23 12 26 
+10 24 31 11 ^
+64 1 4 11 15 11 6 9 17 18 15 5 17 21 28 6 9 6 8 10 21 16 11 2 23 18 27 29 18 9 
+11 24 27 11 15 29 29 3 31 18 12 17 31 19 8 4 25 29 17 29 9 25 6 1 2 18 17 15 19 
+15 1 26 17 20 27 25 ^
+64 0 30 6 10 18 5 9 10 26 9 17 2 30 10 28 17 1 27 29 2 19 16 8 28 16 21 30 25 8 
+9 18 30 17 4 6 31 26 16 25 18 23 9 20 8 7 25 26 11 27 17 28 2 23 2 12 24 2 8 6 
+3 12 20 16 4 31 ^
+60 0 28 5 24 16 10 27 28 19 29 19 22 10 23 17 25 7 26 5 5 27 1 20 24 13 27 16 
+24 32 31 5 12 21 13 6 11 21 20 15 3 14 18 32 2 9 6 10 13 23 16 17 3 20 19 27 29 
+21 5 11 28 14 ^
+<D
+
+H>SHS Type 2 Strings<H
+D>
+60 1 16 13 19 5 16 14 27 2 22 7 5 28 15 18 25 17 13 12 29 24 21 29 25 16 5 17 
+22 24 8 8 18 3 13 10 28 3 23 28 12 8 3 25 5 25 24 7 14 30 27 32 30 23 8 15 27 
+28 13 8 12 21 ^
+86 1 33 5 40 26 3 19 12 36 43 5 35 37 5 14 11 45 35 16 10 8 32 4 15 35 26 2 39 
+22 37 22 30 29 28 36 45 14 36 4 29 37 30 34 36 20 9 42 29 9 11 11 18 42 13 6 20 
+42 20 30 22 35 34 6 14 41 19 30 17 35 33 26 41 15 5 44 39 8 20 3 44 32 15 18 10 
+15 10 36 ^
+112 0 10 44 24 53 35 22 40 20 15 51 22 18 22 42 6 54 49 38 21 7 13 30 16 7 52 
+16 22 13 38 7 11 44 33 9 25 13 37 42 14 45 53 30 38 5 25 5 35 38 22 28 10 29 52 
+31 39 35 23 5 17 14 31 46 5 41 54 43 33 13 23 46 45 3 46 3 55 15 6 53 28 52 22 
+27 45 32 53 51 15 37 15 49 36 35 35 15 3 13 22 25 3 4 10 24 12 7 44 25 18 21 21 
+20 55 24 ^
+123 1 43 9 1 52 4 21 49 61 18 50 23 13 46 62 23 45 62 9 56 18 23 31 8 30 27 36 
+13 38 4 58 53 47 24 18 41 58 19 12 18 52 42 29 44 45 26 63 34 32 41 64 15 26 55 
+19 2 49 6 30 53 13 54 12 53 37 12 37 29 60 53 21 47 42 45 52 40 10 28 47 43 17 
+16 17 61 36 12 34 60 37 13 52 58 37 39 29 34 11 45 8 36 1 50 50 5 51 13 15 32 
+51 33 61 16 31 50 58 63 16 5 30 17 24 10 26 52 ^
+144 1 64 62 63 30 15 1 35 28 16 40 20 14 50 33 19 38 30 27 55 10 16 46 47 7 55 
+12 53 26 56 33 29 55 25 17 48 43 21 43 18 24 63 27 68 46 38 33 35 10 18 11 27 5 
+9 58 35 70 36 36 39 47 2 10 66 47 5 18 21 44 71 51 57 3 22 7 56 55 28 25 14 40 
+16 24 48 37 66 50 24 45 18 39 53 29 64 60 26 50 6 47 61 46 44 60 17 4 58 45 26 
+20 26 32 8 7 68 37 3 24 44 47 64 54 71 57 12 68 27 58 29 54 43 42 60 13 14 56 
+49 1 32 9 61 43 36 33 20 59 ^
+166 0 7 38 57 33 61 73 7 64 1 49 35 76 14 27 21 45 68 38 58 73 13 72 47 73 33 8 
+66 23 38 4 56 77 47 10 71 13 20 31 41 6 51 3 18 17 61 47 14 48 76 46 28 34 43 1 
+56 4 25 7 65 41 1 34 37 23 59 59 27 26 13 15 14 75 60 14 1 28 59 26 65 61 16 23 
+17 28 6 19 2 35 49 30 29 48 2 63 73 59 1 3 76 41 11 19 18 43 54 63 67 51 4 9 78 
+60 8 72 31 35 77 54 58 20 36 58 51 76 40 20 37 49 3 75 1 29 20 57 64 22 25 6 25 
+59 32 43 58 40 51 77 1 2 36 10 12 28 39 11 46 2 41 27 27 53 76 13 66 69 76 28 ^
+186 1 5 73 38 30 30 48 21 75 80 40 21 8 53 9 26 30 34 81 71 71 51 23 75 33 41 
+23 32 5 8 66 40 72 40 16 66 45 14 48 34 21 41 27 3 55 27 37 23 41 65 4 57 51 74 
+22 19 75 42 16 19 46 16 10 48 20 19 37 41 14 57 9 17 55 38 5 60 7 46 20 43 36 
+39 52 20 10 62 45 23 46 7 35 75 29 70 35 36 34 25 12 15 84 26 10 6 71 29 79 33 
+32 25 59 76 82 64 58 7 8 19 41 74 2 53 65 24 1 55 51 36 21 79 28 5 17 41 36 63 
+51 18 48 25 46 45 36 77 76 22 57 14 44 63 56 45 56 20 1 64 49 9 12 28 30 72 82 
+73 33 3 22 30 43 56 67 62 2 57 13 50 20 57 38 43 61 9 8 57 65 76 9 ^
+183 1 54 34 83 10 33 51 86 81 82 69 18 8 22 64 19 86 62 58 33 37 17 34 5 29 83 
+42 76 50 54 66 39 9 1 36 43 17 65 6 35 56 72 71 83 88 10 1 8 87 22 6 21 78 25 
+89 43 62 40 55 85 31 89 74 63 46 28 24 26 31 17 7 8 27 19 12 85 17 20 27 77 10 
+2 54 80 17 52 74 76 69 78 11 20 80 4 29 24 85 75 18 39 23 70 83 29 57 67 72 70 
+33 4 15 46 42 2 69 13 53 33 69 64 33 64 14 40 69 59 78 71 19 85 16 65 38 82 55 
+40 56 40 24 84 29 25 44 68 13 85 76 64 32 18 25 45 23 6 80 31 30 30 58 14 13 72 
+57 14 41 28 52 73 26 76 83 56 54 2 36 11 65 66 38 50 8 41 88 77 ^
+200 1 25 57 40 46 78 57 34 78 61 36 66 57 38 80 22 32 68 71 30 74 37 81 66 77 
+66 55 2 51 24 93 61 40 68 45 61 12 63 24 89 59 52 72 43 20 20 69 36 40 88 46 9 
+62 55 77 84 20 18 6 77 15 52 39 75 3 26 4 85 17 62 29 11 92 46 58 29 59 28 42 
+80 71 96 2 49 85 37 63 4 61 14 2 53 87 25 86 6 75 76 93 41 39 93 92 42 56 41 63 
+26 28 18 77 11 50 78 79 1 12 12 91 29 13 58 5 56 92 66 59 4 39 47 95 5 5 62 33 
+13 80 69 60 43 51 22 30 32 42 5 38 3 50 7 48 90 56 96 68 47 41 61 60 96 20 14 4 
+19 19 23 25 13 9 38 52 17 11 96 48 19 25 88 42 7 74 59 48 70 55 24 18 28 44 46 
+3 24 38 56 19 96 22 50 60 17 96 ^
+195 1 25 51 45 35 66 19 61 60 9 31 93 64 70 30 42 86 53 1 71 46 42 22 38 96 10 
+99 34 76 26 55 73 63 63 97 23 92 81 64 46 1 30 31 35 86 91 88 64 87 16 37 69 84 
+94 60 100 3 47 52 8 71 87 57 29 76 43 18 45 46 15 65 12 44 42 66 60 15 68 19 58 
+39 62 76 9 92 101 57 32 4 34 15 41 62 32 89 71 43 35 31 41 21 17 82 33 96 27 62 
+29 82 57 46 62 15 24 99 37 83 40 52 46 56 80 98 3 91 74 6 27 7 58 94 10 41 79 
+97 84 77 74 26 99 95 61 19 17 24 55 15 85 84 30 45 93 44 100 44 39 59 46 18 95 
+3 41 15 82 77 16 48 18 51 83 20 82 60 53 53 12 99 92 54 5 99 51 39 100 61 2 31 
+52 49 86 94 16 78 84 91 42 ^
+212 0 56 98 16 98 78 22 72 33 103 104 52 84 12 65 15 85 101 97 84 31 51 26 100 
+100 38 80 13 2 78 7 24 44 84 103 27 7 28 16 33 99 25 103 54 14 42 62 87 92 27 
+22 42 5 52 100 84 73 72 63 24 48 56 52 23 5 17 76 31 1 95 58 43 60 50 62 30 23 
+35 79 20 35 3 72 32 45 51 87 41 84 27 79 77 70 102 15 54 15 100 8 52 69 105 3 
+30 84 42 93 66 89 69 74 24 33 42 97 4 38 99 106 13 93 6 106 74 100 54 45 21 59 
+56 37 9 50 32 75 79 31 77 9 61 1 8 68 6 60 81 7 100 99 14 61 48 25 73 26 70 72 
+94 3 11 98 31 5 67 7 39 92 73 88 101 32 105 34 82 81 11 72 48 10 59 71 51 71 35 
+33 27 49 49 19 98 47 43 75 64 17 15 24 94 49 4 84 58 58 74 39 47 104 82 5 63 69 
+90 19 ^
+236 1 29 79 41 40 72 51 12 92 34 52 44 69 104 21 97 89 96 48 21 4 61 40 28 67 
+34 23 85 44 22 62 52 33 84 23 30 73 74 4 79 12 81 47 80 53 47 89 40 19 80 62 34 
+61 29 41 95 43 1 70 63 55 53 18 19 13 48 10 19 89 49 4 52 53 56 76 10 8 104 77 
+15 28 38 75 109 3 85 90 8 40 8 93 90 43 39 14 60 17 36 78 56 105 80 35 75 36 58 
+82 50 100 98 45 74 13 66 95 72 71 95 34 14 98 72 33 38 37 52 6 14 107 59 3 29 
+61 67 98 92 5 93 17 98 36 87 41 75 71 57 88 17 25 91 84 3 58 20 92 69 51 50 36 
+31 14 25 18 30 18 1 41 104 30 82 59 87 70 34 96 28 47 62 81 103 109 103 100 7 
+17 16 104 1 12 34 5 102 42 16 22 71 39 5 73 45 45 54 41 13 2 26 41 22 100 109 
+30 44 4 90 108 53 38 104 68 28 56 47 51 94 22 7 81 85 26 50 9 72 98 54 59 96 52 
+^
+232 1 92 72 47 37 33 38 92 17 8 28 88 22 62 69 32 89 75 3 72 96 85 13 105 24 38 
+37 94 115 83 72 108 114 24 93 76 103 60 99 102 9 43 10 59 95 46 33 93 15 26 69 
+44 2 86 107 55 45 61 65 92 66 9 55 39 70 83 29 98 67 13 111 15 20 31 62 8 2 51 
+20 19 33 44 14 115 71 112 97 10 41 28 53 51 26 57 15 38 98 55 106 22 56 31 50 
+95 107 110 84 70 10 108 96 73 100 25 36 55 88 71 63 96 30 90 96 79 22 7 30 23 
+28 59 89 8 51 99 47 86 34 18 43 65 98 104 107 49 7 79 71 8 57 21 29 80 2 74 78 
+44 57 9 61 22 13 68 52 91 74 98 43 30 58 68 95 101 72 102 76 42 99 108 47 25 73 
+27 104 34 59 52 36 104 20 98 14 97 4 50 46 106 83 17 22 105 79 77 46 39 15 113 
+20 37 100 106 65 66 76 7 12 72 35 8 22 50 40 68 101 23 54 96 44 51 87 18 6 46 
+110 ^
+245 0 70 30 81 46 53 119 85 6 104 47 92 72 70 5 70 15 115 68 105 33 97 13 85 
+106 14 61 29 22 86 45 57 69 91 38 38 28 66 13 60 95 103 3 15 5 113 38 23 62 5 
+65 94 107 73 104 37 47 102 117 3 78 35 7 95 56 78 45 52 28 46 43 37 32 53 19 55 
+29 47 97 76 115 83 71 11 45 62 73 99 116 2 24 116 7 28 41 2 29 37 52 23 5 118 
+79 31 57 89 61 24 101 78 50 93 73 41 7 33 45 47 24 1 48 73 36 3 25 87 46 28 108 
+54 68 53 67 119 28 36 118 104 42 88 27 112 4 74 85 1 63 39 97 71 74 75 76 10 49 
+12 79 11 50 103 118 94 117 118 37 27 12 94 60 28 51 47 82 110 17 15 105 23 52 
+43 12 21 22 81 41 12 74 90 42 108 117 98 67 4 69 44 76 105 38 101 21 80 70 10 
+111 23 110 32 101 83 91 101 31 5 3 83 76 15 90 57 74 95 46 33 112 62 63 54 63 
+49 59 4 64 40 68 110 74 105 91 86 102 27 55 34 88 55 ^
+240 0 55 79 75 84 113 22 4 113 109 31 33 17 96 11 29 63 98 103 107 116 34 14 9 
+95 38 18 51 75 33 109 118 55 66 4 76 7 75 70 82 74 23 1 26 69 40 112 99 47 65 
+31 70 119 52 103 88 85 86 28 16 12 76 25 22 78 64 21 86 27 61 77 72 108 2 18 
+106 119 121 54 16 85 72 2 73 26 88 66 60 80 35 24 117 63 24 44 67 52 122 119 33 
+72 16 99 98 69 54 19 42 28 53 114 32 117 81 100 57 49 123 56 21 68 80 53 95 1 
+45 95 107 98 87 1 27 24 99 116 16 67 1 113 91 84 25 40 25 72 3 28 90 87 112 80 
+16 117 45 77 36 90 105 59 88 122 64 108 108 71 98 18 50 115 93 105 77 35 6 46 
+55 47 102 4 26 87 111 120 81 113 4 57 105 3 84 94 115 61 3 121 72 71 24 62 14 
+60 99 61 96 103 51 107 6 65 81 114 83 121 109 49 104 30 73 82 92 94 9 8 11 98 
+19 10 55 97 22 97 95 88 67 15 20 39 65 13 123 77 ^
+253 1 45 7 15 24 51 5 98 115 24 49 90 104 117 66 128 94 64 80 12 43 91 46 111 
+59 58 77 30 14 88 60 123 68 41 44 68 40 104 118 41 43 93 90 105 92 16 127 26 54 
+125 114 79 71 24 48 21 25 118 40 103 49 91 44 67 65 25 119 109 18 48 23 69 112 
+38 61 64 87 84 104 119 110 122 92 22 1 8 83 34 100 32 62 41 46 112 34 102 76 56 
+39 4 127 30 13 19 110 124 7 16 128 95 4 124 11 104 116 126 49 95 3 55 96 70 90 
+101 4 122 96 75 118 39 128 99 92 18 42 20 87 83 35 75 111 61 67 71 28 101 9 56 
+34 105 95 71 23 73 71 26 57 15 23 76 55 99 89 128 98 117 68 43 88 62 38 62 39 2 
+83 36 15 26 60 128 96 73 74 10 1 12 42 22 2 77 33 33 32 57 13 14 82 57 12 39 3 
+58 80 14 87 85 44 69 109 19 117 67 68 44 63 106 37 88 64 82 56 37 89 4 126 55 
+98 114 84 99 91 43 92 21 26 58 84 102 75 116 124 5 101 5 97 46 109 15 29 79 72 
+93 92 110 ^
+289 1 83 5 76 20 32 15 10 1 103 18 22 116 98 9 51 104 102 44 33 15 12 24 31 89 
+1 6 28 101 8 64 72 106 30 5 52 89 111 39 108 64 85 17 57 124 22 105 78 115 3 40 
+108 66 108 77 128 103 44 35 38 13 95 10 111 63 98 117 61 51 126 69 96 70 70 59 
+39 13 97 33 112 2 77 7 123 70 83 29 66 67 49 79 19 104 115 14 60 2 55 40 71 33 
+28 114 51 91 17 46 45 128 57 87 62 25 115 38 50 55 90 74 8 51 102 79 43 94 36 
+122 94 12 41 36 25 104 91 24 7 99 80 30 126 32 63 122 107 114 27 28 79 41 12 35 
+51 115 122 70 22 79 65 2 88 27 17 59 15 23 44 57 5 65 6 26 78 80 125 93 84 100 
+45 22 129 68 36 111 74 118 11 50 42 120 47 21 8 86 112 26 67 60 99 45 93 47 8 
+38 59 52 56 124 20 82 18 117 24 18 46 106 19 117 26 41 47 45 130 7 15 1 4 5 100 
+10 85 50 44 11 48 92 119 108 42 118 24 20 69 107 90 96 48 103 7 2 90 50 18 130 
+126 45 106 17 35 25 102 68 23 68 120 58 41 34 75 103 20 45 117 37 61 73 34 62 1 
+125 58 74 21 21 129 7 86 110 76 66 124 ^
+263 1 100 135 7 75 23 5 81 110 31 118 29 1 62 11 41 88 109 119 102 37 3 30 123 
+47 31 56 134 29 124 116 118 99 21 56 77 91 23 37 135 81 44 51 67 95 51 133 30 
+57 67 116 122 48 100 7 132 97 106 69 93 4 95 125 102 103 119 81 57 133 96 37 
+118 50 117 113 81 127 17 45 103 32 121 129 60 43 65 127 30 36 132 110 52 53 35 
+71 12 76 22 72 130 112 99 76 26 21 73 63 63 97 23 58 115 132 114 1 132 31 35 18 
+23 54 30 53 118 37 35 84 94 60 100 3 47 18 110 105 87 57 63 76 43 52 45 46 49 
+65 12 10 42 66 60 117 34 19 92 5 28 76 9 126 101 125 32 38 34 15 7 62 32 21 3 
+43 69 31 109 123 51 116 135 130 129 130 63 14 57 80 62 15 126 31 105 83 108 120 
+80 124 46 98 105 91 6 6 27 7 58 128 78 7 79 63 84 77 74 128 65 61 95 121 17 24 
+123 117 51 50 64 79 59 44 134 78 73 59 114 18 27 3 109 49 82 43 118 116 52 119 
+15 122 82 26 87 53 114 133 92 88 39 99 17 107 134 95 104 31 52 49 94 ^
+286 0 120 16 104 136 117 82 138 32 65 114 119 137 121 8 12 46 126 26 119 73 130 
+60 76 113 100 14 133 26 116 34 120 80 95 84 53 15 24 44 51 4 10 23 77 24 99 66 
+37 54 63 42 136 21 34 76 5 17 128 101 1 59 40 113 112 32 97 31 93 105 79 91 18 
+39 1 103 132 51 68 124 111 13 97 43 128 69 84 85 72 15 12 26 87 16 16 92 101 13 
+77 4 118 89 103 56 42 16 60 44 39 126 46 18 83 93 41 105 3 82 106 115 91 6 4 54 
+115 15 120 109 113 48 41 9 95 20 62 67 105 111 25 132 7 116 46 138 44 83 61 124 
+131 35 107 6 109 81 114 67 41 137 77 56 74 73 34 12 14 69 52 11 98 47 54 83 81 
+6 1 15 88 35 139 80 83 49 89 27 47 130 92 133 87 51 112 76 49 109 49 57 93 73 
+22 117 50 64 58 97 139 36 131 111 133 58 33 8 88 55 38 90 46 30 118 57 29 82 74 
+41 117 38 46 94 92 5 105 15 117 70 103 68 60 120 48 21 110 85 40 81 38 58 129 
+56 10 99 86 76 81 26 23 25 68 16 28 127 65 18 71 75 77 100 26 11 130 104 28 34 
+56 106 7 8 120 112 12 58 21 130 124 67 61 19 87 119 ^
+286 1 35 94 61 130 98 35 88 34 65 104 56 126 118 50 87 10 81 109 90 86 118 32 6 
+114 88 39 38 39 62 3 12 134 72 137 35 75 81 115 106 140 112 11 123 41 103 45 95 
+84 71 107 13 26 110 96 62 16 109 84 59 53 38 27 8 28 13 32 137 17 138 41 122 36 
+99 65 99 83 36 112 29 49 70 96 126 136 131 116 3 18 17 126 142 14 37 141 141 
+123 42 13 20 83 42 139 83 54 49 58 42 7 137 29 48 16 121 127 34 52 140 106 128 
+58 36 124 83 24 69 54 61 112 17 6 95 97 24 57 86 124 59 71 119 67 1 109 54 68 
+49 57 132 32 5 71 113 40 80 104 75 106 133 31 126 130 104 62 9 39 44 66 116 141 
+135 96 132 19 41 121 126 124 77 8 4 60 82 6 101 124 89 51 123 48 40 85 77 21 
+112 10 69 66 115 87 16 108 30 84 65 80 103 32 131 134 73 47 10 63 39 50 93 37 
+135 114 69 48 34 58 23 27 133 37 9 40 98 41 115 99 70 83 29 42 67 133 55 79 80 
+91 122 12 2 115 112 23 33 16 102 3 19 60 101 130 105 116 117 27 2 1 103 38 14 
+55 78 26 116 123 54 67 139 82 74 70 84 72 17 132 25 68 31 120 103 140 ^
+285 1 65 30 51 119 48 107 92 84 69 28 136 143 54 20 6 70 47 142 64 4 65 59 73 
+99 134 146 102 125 116 57 137 137 72 48 128 78 5 80 63 54 85 30 22 129 68 21 21 
+74 28 128 107 27 60 2 93 95 71 37 11 37 15 39 102 3 104 65 80 59 52 113 34 20 
+67 60 27 81 135 46 106 106 102 68 128 17 15 100 124 15 43 136 122 100 67 142 35 
+14 53 120 2 89 93 99 73 9 122 39 77 15 96 90 43 79 134 60 92 105 55 96 31 119 
+77 97 72 23 140 38 30 43 83 136 88 107 117 72 109 118 58 91 119 73 95 100 59 
+138 123 54 49 143 50 133 66 106 45 80 88 42 93 5 59 77 101 74 110 104 40 92 19 
+77 76 86 102 129 3 144 101 139 134 56 90 18 91 94 85 55 10 137 11 58 1 107 113 
+70 22 7 56 29 143 111 8 46 45 116 122 129 89 7 121 53 95 14 49 118 62 125 91 37 
+97 15 35 100 63 140 63 50 51 58 26 127 6 45 59 102 121 114 85 141 135 10 72 19 
+106 66 66 41 53 13 38 1 21 103 50 108 46 66 70 43 140 124 40 63 144 97 137 47 
+60 88 103 115 132 145 116 143 115 10 133 9 118 37 105 51 94 60 67 117 116 ^
+305 1 109 110 75 42 12 139 137 43 128 106 107 19 126 12 101 148 127 15 117 125 
+125 62 96 13 76 70 96 101 110 138 8 95 76 143 17 32 97 79 149 39 31 94 123 21 
+41 135 55 84 70 33 135 118 50 62 121 81 1 45 144 93 60 5 64 137 8 105 91 82 67 
+27 113 119 53 18 98 79 48 84 32 135 128 5 1 20 76 17 85 108 72 36 141 140 49 
+150 105 104 3 149 14 54 18 148 64 49 125 37 28 28 101 22 104 91 32 82 117 12 
+114 69 58 2 58 115 9 108 47 59 65 14 92 7 4 86 98 16 82 92 95 38 94 10 10 48 97 
+104 66 115 97 142 115 122 119 40 97 16 32 47 34 88 89 26 50 12 76 80 51 40 9 
+133 24 44 40 122 84 108 22 142 140 99 44 15 54 8 42 125 150 130 21 79 124 62 46 
+119 15 29 91 57 150 42 138 71 61 68 80 114 6 1 70 121 18 35 113 56 87 86 10 73 
+14 29 41 72 89 1 133 87 101 123 59 90 142 77 133 52 78 48 34 138 134 27 17 60 
+131 147 61 93 148 39 132 49 62 71 36 91 4 139 49 100 120 43 113 144 30 94 73 
+127 40 34 50 100 110 88 114 94 35 138 33 72 61 58 65 24 107 6 54 81 114 56 137 
+71 11 23 19 73 1 108 110 25 148 11 98 132 150 17 70 146 50 ^
+314 1 99 88 7 139 24 13 35 47 97 145 74 36 119 3 51 84 48 119 53 49 15 79 17 
+120 103 148 64 30 41 97 120 75 111 63 58 131 134 18 13 10 48 18 16 48 43 15 54 
+18 41 47 122 144 80 92 145 77 1 33 89 54 46 78 48 21 54 43 40 53 24 16 73 42 94 
+29 44 34 151 152 23 123 12 142 140 43 37 88 29 19 35 72 96 151 130 62 112 34 36 
+91 120 50 112 138 2 105 60 68 137 131 5 17 19 139 74 11 120 78 149 58 128 15 
+104 16 126 78 20 57 134 71 49 90 76 108 126 100 54 68 39 132 153 42 147 146 124 
+62 87 35 75 61 65 46 100 82 105 113 31 63 5 95 54 71 77 127 150 80 36 144 2 130 
+59 74 39 3 152 121 122 18 117 12 117 141 118 135 62 36 69 5 39 53 150 52 153 
+143 30 66 96 126 131 56 137 8 7 86 142 14 7 111 141 93 136 137 134 43 12 89 23 
+44 9 152 146 121 97 19 38 110 91 67 14 32 110 66 68 8 130 84 73 118 59 24 41 72 
+121 150 55 37 138 27 104 66 124 9 51 109 47 125 109 148 8 29 47 72 146 149 61 
+93 10 20 54 15 76 133 125 106 110 94 32 9 29 148 36 66 121 125 56 112 9 1 111 
+116 94 57 8 108 50 62 140 71 74 89 1 83 152 20 85 17 145 102 39 56 115 47 150 
+108 64 98 ^
+335 1 28 103 19 92 95 152 152 10 11 13 155 67 11 83 101 69 153 152 45 141 14 
+120 129 140 119 59 2 89 73 70 83 29 16 67 81 29 1 54 65 96 117 2 37 47 128 33 3 
+89 108 98 139 49 78 27 103 39 119 94 132 90 38 132 55 65 131 90 58 2 54 100 69 
+118 22 44 19 7 148 93 25 29 123 81 64 131 55 30 1 89 38 97 82 64 9 28 86 123 
+151 10 133 40 154 102 4 111 65 9 63 59 124 116 72 105 76 57 137 97 32 145 108 
+78 112 50 43 34 75 20 22 129 68 11 118 74 125 118 57 17 20 129 53 65 61 144 1 
+17 142 156 52 100 54 15 20 59 52 63 131 20 57 124 31 125 46 106 76 92 8 98 154 
+152 80 114 15 140 136 112 100 17 92 25 151 150 80 99 69 83 49 43 156 102 19 57 
+122 96 30 3 39 134 40 32 75 5 76 127 138 99 17 57 52 150 130 18 127 33 23 116 
+107 78 77 77 42 69 68 48 41 69 33 75 40 49 128 103 4 146 93 10 83 66 96 152 30 
+38 12 33 5 39 47 41 34 60 74 20 42 156 67 46 56 102 89 3 124 81 99 104 56 50 8 
+61 74 55 15 87 108 28 138 47 93 60 2 124 46 126 103 91 145 36 25 116 122 79 79 
+7 111 13 85 121 9 98 32 125 81 134 77 112 15 70 33 110 13 50 148 8 133 127 153 
+45 19 42 121 94 45 91 95 117 22 9 46 6 26 31 53 150 8 148 128 53 141 ^
+326 0 80 123 24 147 1 112 82 159 63 74 97 109 33 151 32 89 87 132 117 46 129 59 
+115 91 114 118 37 21 9 94 60 25 89 47 79 110 55 12 143 99 87 43 88 56 57 160 76 
+12 71 128 77 146 117 95 105 42 66 3 76 20 76 101 100 118 149 45 26 143 148 32 
+57 39 129 19 31 84 123 1 152 135 5 54 30 13 125 68 30 62 101 51 142 5 94 83 20 
+116 24 107 109 105 91 42 17 27 93 69 3 139 68 79 38 84 2 85 128 126 122 131 46 
+17 35 98 42 26 111 100 29 120 55 84 114 109 145 14 18 138 14 9 85 7 18 129 91 2 
+94 51 133 82 87 123 64 39 8 103 38 75 110 78 7 9 45 115 42 138 135 86 78 16 62 
+52 75 159 54 151 121 149 77 74 16 85 47 102 105 82 119 10 67 137 153 148 135 28 
+49 26 151 153 36 80 11 130 113 24 44 30 102 24 58 133 122 140 99 24 156 54 119 
+42 115 140 90 132 19 94 2 157 99 136 19 71 7 130 153 108 51 21 58 70 74 137 1 
+40 111 149 5 103 6 27 76 141 23 125 140 1 72 29 152 103 87 51 93 29 80 132 77 
+123 153 68 159 14 98 114 158 121 158 81 137 41 93 118 140 122 19 22 31 147 41 4 
+89 150 50 120 144 113 104 20 44 53 97 20 4 90 60 48 84 74 25 138 23 62 61 159 5 
+14 107 6 4 81 114 46 97 11 112 154 130 73 132 60 ^
+325 0 58 137 96 11 98 67 98 103 57 146 21 59 88 151 139 148 127 25 17 47 115 34 
+160 109 107 51 64 28 69 13 49 149 69 141 90 93 118 64 10 1 67 80 35 111 13 58 
+101 124 132 147 154 18 162 6 162 33 5 34 142 41 161 82 114 70 92 145 57 155 137 
+114 79 44 36 48 48 21 14 13 40 33 14 150 33 32 54 143 14 4 101 142 23 93 136 
+132 120 147 17 38 163 143 5 52 46 151 130 32 72 34 124 150 51 100 112 128 126 
+65 10 28 87 81 159 131 19 99 54 125 110 58 119 28 78 129 104 140 126 38 154 27 
+114 61 153 90 66 98 76 50 158 48 39 82 123 22 147 136 114 52 37 35 75 41 15 150 
+60 52 55 103 21 23 129 95 24 71 47 97 130 50 140 144 106 100 9 64 19 117 122 71 
+92 8 77 156 97 121 98 85 2 36 39 109 143 23 120 156 133 93 154 36 66 116 131 
+160 127 162 161 46 142 14 141 81 141 63 86 117 104 3 146 39 127 34 133 102 106 
+91 57 9 28 60 61 7 158 12 80 26 8 122 80 44 63 68 49 158 21 32 81 150 15 141 
+108 161 64 46 124 123 31 99 27 105 109 98 112 9 37 12 116 149 51 73 144 124 4 
+119 46 133 75 86 90 84 2 9 19 108 6 16 101 115 16 92 163 125 101 106 64 37 8 68 
+40 42 130 41 24 89 115 43 112 85 121 125 92 154 9 46 115 7 140 108 158 ^
+336 0 38 42 155 103 9 62 65 102 122 10 138 160 125 47 158 43 91 69 123 132 35 
+121 4 110 89 130 69 29 139 69 53 70 83 29 163 67 41 9 108 34 45 76 87 2 144 164 
+98 33 160 79 78 48 89 9 38 134 93 146 79 54 122 80 38 112 55 55 101 70 8 129 44 
+70 59 98 149 24 136 124 138 63 25 166 83 51 34 91 45 30 118 59 28 87 72 44 116 
+28 36 103 101 113 10 114 62 111 71 65 126 53 19 114 86 42 85 36 57 137 57 159 
+95 88 78 72 20 23 14 65 10 22 129 68 1 68 74 75 108 7 7 147 109 13 35 51 104 
+158 164 122 126 2 50 4 132 127 59 52 13 81 20 47 107 74 148 115 46 106 46 82 
+115 68 144 142 60 104 15 90 136 102 100 134 42 15 141 100 40 49 49 73 166 13 
+156 82 166 37 82 96 137 130 166 134 20 139 45 122 56 107 98 79 124 17 32 130 
+120 165 77 23 130 96 67 68 47 37 12 29 18 38 158 19 160 55 147 39 118 83 121 96 
+43 137 33 66 86 112 147 155 149 140 5 19 17 148 161 10 44 159 146 57 16 26 102 
+49 3 104 61 59 74 56 10 165 31 54 25 142 157 37 58 165 128 154 73 50 149 94 36 
+76 63 71 135 26 5 116 122 29 69 7 101 140 75 81 136 78 2 125 71 84 57 62 162 40 
+3 80 130 50 98 125 93 127 153 45 146 149 121 74 5 41 55 77 139 166 153 113 153 
+21 53 140 145 148 88 162 ^
+341 0 4 62 78 167 102 144 94 55 141 63 29 97 91 24 115 166 80 69 132 99 1 120 
+23 88 64 87 118 37 137 152 94 60 168 71 47 52 110 37 155 125 63 42 43 52 11 12 
+151 31 12 44 110 32 128 117 68 87 24 39 164 76 145 58 101 91 100 140 151 143 
+130 32 21 3 111 1 31 75 123 153 116 135 130 27 164 165 116 23 12 62 83 24 133 
+139 49 74 154 80 158 80 64 105 91 6 142 27 75 24 128 112 41 79 29 84 145 40 128 
+99 95 95 19 17 160 89 15 17 84 64 11 93 10 66 78 73 127 148 18 129 139 143 49 
+150 9 84 82 154 85 15 88 82 60 87 19 12 133 58 20 39 65 51 141 134 27 70 167 
+120 117 86 60 16 44 16 57 132 18 142 85 104 59 47 141 58 2 66 96 46 119 153 40 
+110 126 103 90 144 13 26 106 144 80 145 134 103 95 24 44 21 84 140 13 97 104 
+140 99 6 147 54 83 42 106 131 54 96 135 67 118 121 81 109 10 53 132 112 117 81 
+33 155 49 61 38 119 1 13 102 131 148 94 131 143 67 123 148 89 104 135 72 145 
+152 76 87 6 66 2 71 123 77 114 108 59 123 166 62 96 140 94 149 116 36 128 23 93 
+91 95 113 162 156 165 111 166 4 44 105 5 120 99 113 68 11 169 35 70 2 147 125 
+81 15 12 57 56 16 138 14 53 61 114 121 5 107 6 129 81 114 37 61 127 67 136 94 
+73 114 32 34 119 72 11 98 37 74 73 51 146 161 35 146 ^
+349 0 142 139 121 91 16 163 2 88 171 133 100 62 51 46 10 24 150 49 131 60 114 
+63 84 91 64 165 138 40 44 172 111 141 58 74 115 96 129 145 164 153 170 126 24 
+169 16 115 41 125 46 87 61 92 145 39 155 92 78 70 35 27 21 48 21 151 159 40 15 
+5 132 170 23 18 107 160 150 56 133 23 66 109 123 102 102 172 166 145 116 151 34 
+1 151 130 5 36 34 97 114 15 82 128 112 119 99 29 138 165 42 36 159 95 19 63 36 
+89 101 40 92 1 33 93 104 113 126 2 136 96 52 108 90 57 89 31 5 113 30 39 37 96 
+4 147 127 105 43 165 35 75 23 143 105 24 25 10 94 12 160 102 95 170 71 20 70 
+112 23 95 144 61 73 137 55 1 81 95 26 65 172 41 147 79 103 80 40 121 36 12 64 
+98 169 93 111 115 48 127 9 39 107 131 115 118 162 161 10 142 14 123 54 141 36 
+41 99 77 140 128 167 82 25 106 57 70 64 21 19 15 34 126 149 167 53 163 127 86 
+35 8 54 23 40 140 3 169 45 150 152 96 81 143 28 28 124 87 13 90 9 87 109 53 67 
+164 28 131 89 149 42 55 126 79 132 74 19 133 30 68 72 75 148 9 10 72 152 144 83 
+106 153 74 163 98 92 97 37 19 8 32 31 24 121 14 152 89 79 7 76 155 85 76 107 83 
+154 155 37 115 144 131 108 116 26 36 137 103 3 44 47 72 104 10 120 154 107 35 
+152 19 85 69 105 120 29 109 171 104 65 124 39 11 127 57 41 70 83 29 157 67 164 ^
+370 1 167 63 16 27 58 60 2 99 128 71 33 160 70 51 3 44 149 2 89 84 101 43 18 
+113 71 38 94 55 46 74 52 139 102 35 43 50 80 122 6 100 88 129 36 25 148 47 24 7 
+55 36 30 82 32 19 78 63 26 71 28 167 85 56 167 95 159 78 26 66 35 65 90 44 159 
+105 59 15 67 57 137 21 132 50 70 78 36 169 5 172 56 1 22 129 68 168 23 74 30 99 
+138 174 120 91 153 8 42 68 158 155 104 99 133 5 135 96 82 59 52 144 36 20 38 62 
+29 112 106 46 106 19 73 70 41 135 133 42 95 15 45 136 93 100 98 173 6 132 55 4 
+4 31 64 130 162 156 64 157 19 46 96 92 103 139 134 2 94 18 86 38 89 62 61 79 
+157 14 112 111 156 32 14 85 78 31 59 20 1 161 169 149 29 122 150 133 37 102 30 
+109 65 85 51 174 110 164 66 77 76 111 119 131 95 5 1 166 103 134 141 17 158 123 
+137 48 165 175 102 13 3 86 43 23 47 56 150 165 4 36 174 115 157 168 13 147 119 
+109 55 41 140 67 27 31 27 53 126 17 163 116 122 160 60 7 92 113 66 45 109 60 
+151 125 62 39 39 17 153 13 152 53 94 50 53 89 57 127 153 45 119 104 121 56 145 
+172 19 41 103 166 108 68 126 12 53 131 127 148 52 134 168 50 48 155 72 132 82 
+37 129 63 175 97 79 18 91 148 74 57 132 87 147 114 175 70 46 69 118 37 107 140 
+94 60 156 59 47 34 110 25 143 113 39 12 43 28 157 158 145 1 12 26 98 2 116 117 
+50 75 12 21 164 76 121 46 101 85 88 134 146 127 143 79 ^
+364 0 32 164 146 93 162 31 66 123 144 80 135 94 137 156 107 157 173 62 65 176 
+124 112 4 65 127 44 131 53 19 105 91 149 106 27 57 158 92 85 14 79 20 84 127 
+174 128 72 68 59 171 17 124 80 167 8 57 28 172 66 144 48 42 37 109 121 18 120 
+103 116 13 132 39 73 145 76 158 43 82 33 51 153 164 97 13 2 3 20 24 114 98 9 25 
+131 102 99 86 42 16 26 159 39 105 161 133 49 59 41 20 105 31 136 30 87 10 119 
+135 13 83 99 58 45 99 156 26 61 135 143 80 118 107 76 77 24 44 12 66 95 147 61 
+86 140 99 167 138 54 47 42 97 122 18 60 90 40 73 85 63 82 1 35 96 94 81 54 15 
+128 40 52 2 101 1 165 93 113 130 85 95 98 58 105 112 53 68 108 72 100 152 49 87 
+140 39 154 62 114 77 105 63 50 87 157 26 78 122 67 140 71 170 119 5 93 64 50 
+104 144 129 138 75 130 4 178 60 139 120 54 113 32 2 133 17 43 163 129 89 72 149 
+155 30 38 7 138 5 44 61 69 76 175 107 6 93 81 114 28 25 82 22 118 58 73 96 175 
+177 92 36 11 98 171 38 28 42 146 125 178 88 136 139 103 67 10 151 151 70 153 
+115 94 32 51 34 177 173 132 49 119 54 96 45 78 73 64 159 120 22 20 154 111 117 
+58 56 109 72 117 139 152 147 170 102 18 169 4 97 41 101 22 69 55 92 145 27 155 
+62 54 64 29 21 3 48 21 133 147 40 3 178 120 152 17 173 83 148 138 26 127 23 48 
+91 117 90 72 166 142 133 98 139 22 150 151 130 140 ^
+372 0 34 70 78 161 64 92 112 110 72 175 102 138 179 173 159 59 19 27 18 53 92 
+22 65 156 170 57 104 86 126 148 118 155 78 43 63 90 48 80 168 142 68 12 39 174 
+69 168 147 118 96 34 129 35 75 5 107 60 170 180 147 85 3 133 75 95 152 71 175 
+43 94 178 50 144 16 46 101 46 165 45 68 163 38 172 5 138 61 85 62 177 76 36 167 
+19 53 151 66 66 97 3 100 164 12 98 131 70 109 162 161 156 142 14 105 27 141 9 
+178 81 50 113 110 131 37 16 79 12 34 37 167 173 10 152 7 81 140 158 26 136 82 
+50 172 154 45 160 31 122 167 142 9 150 125 51 54 125 174 10 124 51 177 81 173 
+69 109 8 22 155 19 86 62 149 33 37 108 34 96 29 174 133 167 50 54 66 130 9 1 36 
+134 108 65 97 126 56 163 71 83 88 10 1 8 178 22 6 112 169 116 89 43 153 40 146 
+85 31 89 74 154 137 28 115 117 122 108 98 8 27 110 103 176 17 20 27 77 10 93 
+145 80 17 143 165 76 69 78 102 20 91 171 95 29 115 176 166 109 39 23 70 83 29 
+148 67 163 161 33 4 15 46 42 2 69 104 53 33 160 64 33 155 14 131 160 59 78 71 
+19 176 107 65 38 82 55 40 56 40 115 84 29 25 44 68 104 176 76 64 123 18 25 136 
+23 6 171 31 30 30 58 14 13 72 57 14 41 28 143 73 26 167 83 147 54 2 36 11 65 66 
+38 141 99 41 179 55 158 57 137 179 114 20 58 78 12 157 175 166 50 177 22 129 68 
+168 175 74 93 114 174 102 79 135 172 36 44 158 149 92 81 109 157 111 72 119 ^
+372 0 59 52 112 180 20 30 22 173 80 98 46 106 179 65 30 17 127 125 26 87 15 5 
+136 85 100 66 141 182 124 15 156 148 15 56 98 146 156 48 149 3 14 96 52 79 115 
+134 170 54 178 54 22 73 30 45 39 133 182 96 103 148 176 6 45 62 183 51 180 153 
+145 145 117 21 90 118 109 21 62 22 101 49 53 11 142 86 132 66 69 44 79 87 115 
+55 5 169 150 63 110 109 177 150 91 129 40 149 159 102 165 3 70 27 175 23 56 126 
+165 164 20 158 91 157 136 157 131 111 69 39 33 132 43 19 175 179 37 118 9 155 
+116 122 128 52 7 84 89 58 13 85 44 135 125 54 183 23 161 145 173 136 29 62 50 
+13 57 25 127 153 45 95 64 121 40 121 140 171 9 71 166 68 28 102 4 53 123 111 
+148 20 102 160 34 8 139 32 116 66 13 113 63 143 97 63 10 59 124 66 41 132 71 
+115 106 151 46 22 45 118 37 67 124 94 60 140 43 47 10 110 9 127 97 7 156 43 180 
+125 126 137 145 12 2 82 146 100 117 26 59 180 181 164 76 89 30 101 77 72 126 
+114 95 143 102 32 149 131 83 157 31 61 123 139 60 135 74 169 122 151 102 137 
+168 62 55 166 119 97 163 60 112 24 116 38 178 105 91 134 86 27 47 138 72 70 183 
+79 15 84 117 154 128 57 53 39 161 17 104 75 157 3 42 8 167 51 124 38 22 17 99 
+106 18 115 83 101 177 122 179 14 68 140 71 143 18 82 18 31 133 154 77 172 176 
+167 179 9 99 78 183 111 92 89 86 32 16 16 144 29 90 146 128 29 34 31 5 85 16 
+116 10 82 174 119 125 79 ^
+391 0 59 75 18 5 59 132 26 21 127 119 80 94 83 52 61 24 44 4 50 55 115 29 70 
+140 99 159 130 54 15 42 89 114 173 28 50 16 33 53 47 58 180 19 64 78 49 30 186 
+104 32 44 157 85 1 149 85 97 114 77 63 58 50 89 80 21 36 84 72 60 152 25 87 108 
+15 138 54 106 77 97 23 42 55 149 181 62 106 43 132 31 138 111 176 93 40 10 96 
+128 105 114 43 98 4 146 20 107 120 14 113 181 101 1 19 155 113 57 64 117 131 6 
+22 186 138 184 36 61 29 36 175 107 6 61 81 114 20 180 42 169 102 26 73 80 151 
+153 68 4 11 98 139 6 175 34 146 93 154 88 128 139 79 35 2 135 119 46 129 91 86 
+179 51 18 169 141 108 49 103 46 72 21 70 49 64 151 96 185 175 130 111 85 58 32 
+101 40 101 131 136 139 170 70 10 169 175 73 41 69 177 45 47 92 145 11 155 22 22 
+56 21 13 166 48 21 109 131 40 174 178 104 128 9 149 51 132 122 173 119 23 24 67 
+109 74 32 158 110 117 74 123 6 118 151 130 150 167 34 55 58 146 54 72 112 105 
+57 160 82 123 159 153 159 39 19 7 8 33 87 12 50 146 150 37 104 71 126 133 108 
+145 68 38 38 90 43 75 148 122 43 2 39 154 54 163 147 113 91 29 109 35 75 182 87 
+35 155 170 127 80 185 118 60 95 142 71 165 28 84 168 25 144 178 31 81 41 160 25 
+53 143 23 172 172 133 51 75 52 157 51 36 157 181 28 141 51 41 87 165 85 154 184 
+93 131 45 104 162 161 141 142 14 95 12 141 181 158 71 35 98 100 111 12 11 64 
+174 14 22 152 173 5 132 179 56 135 153 11 121 57 30 152 139 40 140 53 ^
+384 1 106 159 118 167 150 101 11 30 109 150 184 124 19 169 73 165 53 109 158 
+172 147 11 46 38 149 25 21 92 184 64 179 158 133 135 34 38 58 114 9 183 4 118 
+76 49 89 102 40 163 47 75 80 176 175 8 154 14 180 104 153 84 89 11 129 8 138 85 
+181 73 66 154 121 20 115 93 114 108 82 182 19 86 103 176 183 186 177 53 10 69 
+137 56 1 135 141 68 69 54 86 12 75 171 87 187 107 144 150 93 23 7 70 83 29 140 
+67 139 153 183 178 189 30 18 2 29 72 29 33 160 56 9 123 164 107 136 19 70 31 
+177 152 99 57 38 66 55 32 32 24 83 60 21 1 36 52 80 168 44 32 115 184 25 120 
+181 172 155 189 22 30 26 180 5 64 49 188 1 28 111 57 176 167 67 131 22 160 186 
+169 65 34 30 117 91 17 163 39 134 57 137 155 90 170 42 78 170 141 167 158 42 
+177 22 129 68 168 143 74 150 85 82 174 78 63 111 156 28 12 158 141 76 57 77 125 
+79 40 12 59 52 88 156 20 24 182 149 56 92 46 106 167 59 189 121 119 14 81 15 
+165 136 79 100 42 117 182 118 175 138 124 3 50 74 134 156 36 143 181 180 96 22 
+61 97 134 164 24 166 30 10 61 6 33 9 115 176 84 97 142 152 15 50 165 45 168 135 
+133 127 93 15 66 94 91 9 32 16 95 37 29 171 118 68 108 66 63 20 55 63 103 25 5 
+163 138 33 92 85 165 144 67 123 34 137 147 102 147 3 58 15 157 5 56 108 165 152 
+8 146 73 157 112 133 119 105 39 27 27 126 25 13 151 161 25 112 3 149 116 122 
+104 46 7 78 71 52 179 67 32 123 125 48 159 11 137 139 161 110 ^
+394 0 2 26 50 161 21 182 127 153 45 68 19 121 22 94 104 144 166 35 166 23 176 
+75 188 53 114 93 148 177 66 151 16 156 121 180 98 48 179 95 63 107 97 45 1 23 
+97 57 23 132 53 79 97 124 19 188 18 118 37 22 106 94 60 122 25 47 176 110 184 
+109 79 164 120 43 153 89 90 128 109 12 168 64 110 82 117 192 41 171 163 164 76 
+53 12 101 68 54 117 78 59 143 84 32 122 104 65 148 31 52 123 130 24 135 38 151 
+95 142 93 101 159 62 37 148 110 70 127 51 85 181 89 11 142 105 91 107 50 27 29 
+102 36 43 165 79 6 84 99 118 128 30 26 3 143 17 68 66 139 187 15 165 158 24 88 
+20 179 174 81 79 18 106 47 74 150 104 179 162 59 131 62 116 166 82 184 188 97 
+136 41 136 167 140 143 175 72 42 174 148 75 74 71 86 14 16 191 117 11 63 119 
+119 186 182 13 171 49 182 80 167 73 147 119 107 164 41 57 181 168 29 114 26 184 
+121 101 80 76 65 34 49 24 44 191 38 25 91 5 58 140 99 153 124 54 184 42 83 108 
+155 4 20 191 3 29 35 40 180 7 40 66 25 12 180 86 26 38 139 73 1 137 79 85 102 
+71 39 28 44 77 56 190 12 66 72 30 152 7 87 84 190 126 48 100 77 91 186 36 31 
+143 163 50 94 25 126 1 114 105 170 93 22 173 90 116 87 96 19 74 4 122 183 83 
+120 177 113 169 181 77 182 1 149 101 33 58 93 113 181 10 186 138 184 30 61 192 
+6 175 107 6 37 81 114 14 162 12 145 90 2 73 68 133 135 50 173 11 98 115 175 151 
+28 146 69 136 88 122 139 61 11 189 123 95 28 111 73 80 155 51 6 163 117 90 49 
+91 40 54 189 ^
+390 0 62 25 64 143 72 169 151 106 111 53 58 8 93 8 85 123 120 131 170 38 2 169 
+167 49 41 37 153 21 39 92 145 190 155 177 185 48 13 5 150 48 21 85 115 40 166 
+178 88 104 1 125 19 116 106 141 111 23 43 101 58 187 150 78 101 50 107 185 86 
+151 130 134 143 34 31 26 122 38 40 112 97 33 136 50 99 127 121 159 7 19 170 187 
+1 79 191 26 130 118 5 104 47 126 109 92 129 52 30 193 90 35 67 116 90 3 181 39 
+122 30 155 147 105 83 21 77 35 75 174 55 190 131 154 95 72 185 94 36 95 126 71 
+149 4 68 152 180 144 146 7 49 33 152 188 29 111 194 172 148 125 35 59 36 125 11 
+36 141 149 183 125 27 1 71 133 61 138 168 85 131 5 96 162 161 117 142 14 79 183 
+141 165 126 55 11 74 84 79 167 3 40 142 177 193 128 173 192 100 163 16 127 145 
+182 97 17 193 120 115 32 108 18 96 154 103 152 150 86 181 15 99 135 179 124 194 
+164 68 160 43 109 138 152 142 6 21 23 149 20 11 82 164 44 159 148 133 115 24 28 
+53 104 9 183 179 108 56 39 84 87 30 163 32 70 75 166 170 8 139 9 175 99 143 64 
+89 186 114 183 133 85 161 63 61 154 111 15 115 78 109 108 72 177 14 71 103 176 
+173 176 157 38 10 54 132 41 186 130 126 63 69 39 76 7 65 171 82 172 102 124 140 
+83 13 192 70 83 29 135 67 124 148 163 173 184 20 3 2 4 52 14 33 160 51 189 103 
+144 92 121 189 65 6 162 137 94 52 38 56 55 27 17 14 63 45 16 181 31 42 65 163 
+24 12 110 174 25 110 166 162 145 174 17 30 6 170 59 44 183 171 28 91 47 156 172 
+^
+400 1 51 115 188 136 154 145 65 2 22 93 83 191 147 23 110 57 137 131 66 138 26 
+78 146 125 159 150 34 177 22 129 68 168 111 74 118 77 50 174 54 47 87 140 20 
+178 158 133 60 33 45 93 47 8 170 59 52 56 124 20 16 150 117 24 84 46 106 151 51 
+158 173 113 111 196 73 15 133 136 71 100 10 85 182 110 143 114 92 185 42 42 118 
+156 20 135 173 156 96 180 37 73 134 156 182 150 196 192 45 172 17 167 91 168 68 
+89 134 120 190 173 34 141 37 152 111 117 103 61 7 34 62 67 191 190 8 87 21 195 
+139 86 44 76 66 55 186 23 31 87 183 5 155 122 191 68 53 149 136 35 115 26 121 
+131 102 123 3 42 197 133 179 56 84 165 136 190 130 49 157 80 101 103 97 197 11 
+19 118 1 5 119 137 9 104 193 141 116 122 72 38 7 70 47 44 155 43 16 107 125 40 
+127 193 105 131 145 108 185 6 50 141 1 167 127 153 45 53 192 121 12 79 84 129 
+151 15 166 196 156 60 188 53 109 83 148 162 46 146 6 136 111 160 88 38 169 85 
+63 87 97 35 194 3 82 52 13 132 43 59 92 109 4 178 3 118 37 195 96 94 60 112 15 
+47 166 110 179 99 69 149 100 43 138 69 70 123 89 12 158 54 90 72 117 182 31 166 
+153 164 76 33 2 101 63 44 112 58 39 143 74 32 107 89 55 143 31 47 123 125 4 135 
+18 141 80 137 88 81 154 62 27 138 105 55 107 46 70 166 74 194 122 105 91 92 30 
+27 19 82 16 28 155 79 1 84 89 98 128 15 11 181 133 17 48 61 129 187 150 153 9 
+68 10 164 159 71 64 18 101 27 59 135 94 179 142 54 126 57 101 146 82 174 173 77 
+126 21 116 162 125 123 165 57 22 169 153 ^
+394 0 47 60 57 86 16 184 96 197 42 98 112 165 154 199 157 21 168 52 146 66 126 
+119 93 150 20 36 153 140 194 93 26 156 114 80 80 55 44 13 35 24 44 191 24 190 
+63 177 44 140 99 146 117 54 163 42 76 101 134 176 185 177 168 1 21 19 180 193 
+12 52 197 191 173 65 19 31 118 59 1 123 72 71 88 64 11 193 37 63 28 169 184 45 
+72 195 152 186 87 56 176 112 41 93 77 84 158 29 3 136 142 36 80 4 119 166 86 98 
+163 93 1 145 83 102 66 75 191 46 4 94 155 55 120 149 113 148 181 49 175 180 142 
+87 5 51 65 92 167 196 186 138 184 23 61 164 171 175 107 6 9 81 114 7 141 177 
+117 76 174 73 54 112 114 29 152 11 98 87 154 123 21 146 41 115 88 115 139 40 
+183 189 109 67 7 90 52 73 127 51 192 156 89 69 49 77 33 33 182 57 10 64 138 57 
+159 136 91 111 33 58 193 88 188 75 118 110 126 170 18 197 169 162 34 41 17 138 
+6 34 92 145 185 155 157 170 43 8 140 48 21 70 105 40 161 178 78 89 196 110 199 
+106 96 121 106 23 185 28 96 48 167 145 58 91 35 97 180 66 151 130 124 128 34 16 
+6 107 28 20 112 92 18 121 30 84 107 101 159 187 19 155 182 181 74 186 11 120 98 
+185 104 32 126 94 82 119 42 25 173 90 30 62 96 70 178 176 39 102 15 150 147 100 
+78 16 57 35 75 169 35 170 116 144 75 67 185 79 21 95 116 71 139 189 58 142 160 
+144 126 192 29 28 147 173 14 91 184 172 133 120 25 49 26 105 186 36 131 129 163 
+115 12 176 61 113 46 128 158 80 131 180 91 162 161 102 142 14 69 173 141 155 
+106 45 196 59 74 59 147 195 ^
+412 0 16 110 153 177 104 173 192 68 147 179 119 137 166 73 180 169 88 91 24 76 
+10 80 146 79 128 150 62 149 194 83 111 171 124 170 156 60 152 27 109 106 120 
+134 201 184 202 149 12 198 66 132 12 127 132 133 83 8 12 45 88 9 183 155 92 24 
+23 76 63 14 163 8 62 67 150 162 8 115 1 167 91 127 32 89 162 90 159 125 85 129 
+47 53 154 95 7 115 54 101 108 56 169 6 47 103 176 157 160 125 14 10 30 124 17 
+178 122 102 55 69 15 60 202 49 171 74 148 94 92 124 67 200 184 70 83 29 127 67 
+100 140 131 165 176 4 182 2 167 20 193 33 160 43 173 71 112 68 97 157 57 169 
+138 113 86 44 38 40 55 19 196 201 31 21 8 165 23 26 41 155 195 183 102 158 25 
+94 142 146 129 150 9 30 177 154 195 51 36 175 139 28 59 31 124 167 41 105 173 
+121 134 130 65 185 17 78 78 181 137 13 95 57 137 116 51 118 16 78 131 115 154 
+145 29 177 22 129 68 168 91 74 98 72 30 174 39 37 72 130 15 163 158 128 50 18 
+25 73 27 191 150 59 52 36 104 20 11 130 97 4 79 46 106 141 46 138 163 108 106 
+191 68 15 113 136 66 100 193 65 182 105 123 99 72 180 37 22 108 156 10 130 168 
+141 96 160 22 58 134 151 162 140 181 187 35 157 7 147 76 163 58 84 129 100 190 
+153 24 126 32 142 96 107 88 41 2 14 42 52 186 170 3 82 11 180 119 66 29 56 66 
+50 171 3 11 77 163 5 150 112 171 53 33 139 131 15 110 21 111 121 102 108 3 32 
+192 118 169 56 69 165 126 185 120 34 157 60 81 93 92 177 1 14 113 189 99 122 
+202 99 193 136 116 122 52 33 7 65 32 39 140 28 6 97 125 35 107 188 85 126 135 
+98 175 189 50 121 184 116 ^
+413 1 127 153 45 32 164 121 203 58 56 108 130 192 166 168 128 39 188 53 102 69 
+148 141 18 139 197 108 97 132 74 24 155 71 63 59 97 21 194 180 61 45 204 132 29 
+31 85 88 188 164 187 118 37 167 82 94 60 98 1 47 152 110 172 85 55 128 72 43 
+117 41 42 116 61 12 144 40 62 58 117 168 17 159 139 164 76 5 193 101 56 30 105 
+30 11 143 60 32 86 68 41 136 31 40 123 118 181 135 195 127 59 130 81 53 147 62 
+13 124 98 34 79 39 49 145 53 180 94 105 91 71 2 27 5 54 193 7 141 79 199 84 75 
+70 128 199 195 160 119 17 20 54 115 187 184 129 146 193 40 201 143 138 57 43 18 
+94 204 38 114 80 179 114 47 119 50 80 118 82 160 152 49 112 198 88 155 104 95 
+151 36 199 162 100 27 50 47 86 195 16 179 81 192 27 83 107 150 134 194 147 1 
+158 32 131 61 111 119 83 140 5 21 133 120 174 78 26 136 109 65 80 40 29 203 25 
+24 44 191 14 170 43 162 34 140 99 141 112 54 148 42 71 96 119 161 165 167 148 
+186 11 4 180 188 197 42 182 181 168 50 14 26 103 49 1 113 67 61 78 59 196 173 
+32 53 8 154 169 30 72 175 152 176 87 36 166 102 36 88 77 79 138 24 188 131 127 
+26 70 194 114 146 66 93 158 93 191 125 78 92 51 60 176 26 4 74 135 35 120 129 
+113 133 181 29 170 170 137 77 190 46 45 77 157 191 186 138 184 18 61 144 151 
+175 107 6 194 81 114 2 126 157 97 66 159 73 44 97 99 14 137 11 98 67 139 103 16 
+146 21 100 88 110 139 25 168 189 99 47 197 75 37 68 107 51 187 151 69 54 49 67 
+28 18 172 52 200 64 133 42 149 121 76 111 13 58 183 83 173 65 113 100 121 170 
+203 197 169 157 19 202 ^
+434 1 193 114 190 26 92 145 177 155 125 146 35 200 124 48 21 46 89 40 153 178 
+62 65 196 86 175 90 80 89 98 23 169 4 88 32 135 137 26 75 11 81 172 34 151 130 
+108 104 34 200 182 83 12 196 112 84 202 97 206 60 75 69 159 163 19 131 174 157 
+66 178 195 104 66 161 104 8 126 70 66 103 26 17 141 90 22 54 64 38 146 168 39 
+70 199 142 147 92 70 8 25 35 75 161 3 138 92 128 43 59 185 55 205 95 100 71 123 
+173 42 126 128 144 94 176 205 20 139 149 198 59 168 172 109 112 9 33 10 73 154 
+36 115 97 131 99 196 144 45 81 22 112 142 72 131 148 83 162 161 78 142 14 53 
+157 141 139 74 29 180 35 58 27 115 198 1 90 138 167 89 173 192 48 137 159 114 
+132 156 58 160 154 68 76 19 56 5 70 141 64 113 150 47 129 184 73 96 166 124 155 
+151 55 147 17 109 86 100 129 201 164 192 149 7 193 56 112 200 107 122 133 63 
+206 2 40 78 9 183 140 82 4 13 71 48 4 163 201 57 62 140 157 8 100 204 162 86 
+117 12 89 147 75 144 120 85 109 37 48 154 85 2 115 39 96 108 46 164 1 32 103 
+176 147 150 105 207 10 15 119 2 173 117 87 50 69 50 202 39 171 69 133 89 72 114 
+57 195 179 70 83 29 122 67 85 135 111 160 171 202 172 2 147 183 33 160 38 163 
+51 92 53 82 137 52 149 123 98 81 39 38 30 55 14 186 196 11 6 3 155 18 16 26 150 
+180 168 97 148 25 84 127 136 119 135 4 30 162 144 195 46 31 170 119 28 39 21 
+104 167 31 95 158 106 114 115 65 170 12 63 73 171 127 3 80 57 137 101 36 98 6 
+78 116 105 149 140 24 177 22 129 68 168 71 74 78 67 10 174 24 27 57 120 10 148 
+158 123 40 3 5 53 7 176 130 59 52 16 84 20 6 110 77 192 74 46 106 131 41 118 
+153 144 ^
+438 1 99 184 61 15 85 136 59 100 172 37 182 98 95 78 44 173 30 204 94 156 206 
+123 161 120 96 132 1 37 134 144 134 126 160 180 21 136 203 119 55 156 44 77 122 
+72 190 125 10 105 25 128 75 93 67 13 205 196 14 31 179 142 206 75 207 159 91 38 
+8 28 66 43 150 185 193 63 135 5 143 98 143 32 5 125 124 197 103 14 97 107 102 
+87 3 18 185 97 155 56 48 165 112 178 106 13 157 32 53 79 85 149 197 7 106 175 
+203 71 101 195 92 193 129 116 122 24 26 7 58 11 32 119 7 202 83 125 28 79 181 
+57 119 121 84 161 168 50 93 163 131 127 153 45 17 144 121 198 43 36 93 115 177 
+166 148 108 24 188 53 97 59 148 126 208 134 192 88 87 112 64 14 145 61 63 39 97 
+11 194 165 46 40 199 132 19 11 80 73 178 154 177 118 37 147 72 94 60 88 201 47 
+142 110 167 75 45 113 52 43 102 21 22 111 41 12 134 30 42 48 117 158 7 154 129 
+164 76 195 188 101 51 20 100 10 201 143 50 32 71 53 31 131 31 35 123 113 166 
+135 180 117 44 125 76 33 142 62 3 114 93 19 59 34 34 130 38 170 74 105 91 56 
+192 27 205 34 178 202 131 79 199 84 65 50 128 189 185 145 109 17 49 105 187 174 
+114 141 183 20 196 128 123 47 28 18 89 189 23 99 70 179 94 42 114 45 65 98 82 
+150 137 29 102 183 68 150 89 75 141 21 184 157 80 7 40 37 86 190 16 174 66 187 
+12 68 102 135 114 189 137 191 148 12 116 56 96 119 73 130 200 6 113 100 154 63 
+26 116 104 50 80 25 14 193 15 24 44 191 4 150 23 147 24 140 99 136 107 54 133 
+42 66 91 104 146 145 157 128 171 1 199 180 183 182 32 167 171 163 35 9 21 88 39 
+1 103 62 51 68 54 181 153 27 43 198 139 154 15 72 155 152 166 87 16 156 92 31 
+83 77 74 118 19 173 126 202 ^
+431 0 10 54 178 106 114 34 85 150 93 175 93 70 76 27 36 152 207 4 42 103 3 120 
+97 113 109 181 210 162 154 129 61 166 38 13 53 141 183 186 138 184 10 61 112 
+119 175 107 6 170 81 114 207 102 125 65 50 135 73 28 73 75 203 113 11 98 35 115 
+71 8 146 202 76 88 102 139 1 144 189 83 15 181 51 13 60 75 51 179 143 37 30 49 
+51 20 207 156 44 184 64 125 18 133 97 52 111 194 58 167 75 149 49 105 84 113 
+170 179 197 169 149 208 41 178 99 180 21 92 145 172 155 105 131 30 208 200 114 
+48 21 31 79 40 148 178 52 50 196 71 160 80 70 69 93 23 159 202 83 22 115 132 6 
+65 209 71 167 14 151 130 98 89 34 190 167 68 2 181 112 79 192 82 191 45 55 49 
+159 148 19 116 169 142 61 173 185 94 46 146 104 206 126 55 56 93 16 12 121 90 
+17 49 44 18 126 163 39 50 189 137 147 87 65 3 5 35 75 156 196 118 77 118 23 54 
+185 40 195 95 90 71 113 163 32 116 108 144 74 166 190 15 134 134 188 39 158 172 
+94 107 212 23 53 134 36 105 77 111 89 186 124 35 61 7 102 132 67 131 128 78 162 
+161 63 142 14 43 147 141 129 54 19 170 20 48 7 95 198 199 70 123 157 74 173 192 
+28 127 139 109 127 146 43 140 139 48 61 14 36 60 136 49 98 150 32 109 174 63 81 
+161 124 140 146 50 142 7 109 66 80 124 201 144 182 149 2 188 46 92 185 87 112 
+133 43 201 205 35 68 9 183 125 72 197 3 66 33 207 163 191 52 57 130 152 8 85 
+204 157 81 107 205 89 132 60 129 115 85 89 27 43 154 75 210 115 24 91 108 36 
+159 209 17 103 176 137 140 85 197 10 114 200 168 112 72 45 69 198 40 202 29 171 
+64 118 84 52 104 47 190 174 70 83 29 117 67 70 130 91 155 166 197 162 2 127 193 
+173 82 ^
+464 1 160 31 149 23 64 32 61 109 45 121 102 77 74 32 38 16 55 7 172 189 198 200 
+211 141 11 2 5 143 159 147 90 134 25 70 106 122 105 114 212 30 141 130 195 39 
+24 163 91 28 11 7 76 167 17 81 137 85 86 94 65 149 5 42 66 157 113 204 59 57 
+137 80 15 70 207 78 95 91 142 133 17 177 22 129 68 168 43 74 50 60 197 174 3 13 
+36 106 3 127 158 116 26 197 192 25 194 155 102 59 52 203 56 20 214 82 49 171 67 
+46 106 117 34 90 139 96 94 179 56 15 65 136 54 100 157 17 182 93 75 63 24 168 
+25 189 84 156 201 118 156 105 96 112 201 22 134 139 114 116 145 175 11 121 198 
+99 40 151 34 72 117 52 190 105 90 20 118 60 83 52 208 205 181 209 16 174 122 
+206 70 202 144 71 18 208 8 66 38 135 170 178 53 115 5 138 88 123 17 200 115 119 
+182 98 9 87 97 102 72 3 8 180 82 145 56 33 165 102 173 96 213 157 12 33 69 80 
+129 192 2 101 165 203 51 86 190 87 193 124 116 122 4 21 7 53 211 27 104 207 197 
+73 125 23 59 176 37 114 111 74 151 153 50 73 148 116 127 153 45 2 124 121 193 
+28 16 78 100 162 166 128 88 9 188 53 92 49 148 111 193 129 187 68 77 92 54 4 
+135 51 63 19 97 1 194 150 31 35 194 132 9 206 75 58 168 144 167 118 37 127 62 
+94 60 78 196 47 132 110 162 65 35 98 32 43 87 1 2 106 21 12 124 20 22 38 117 
+148 212 149 119 164 76 180 183 101 46 10 95 205 186 143 40 32 56 38 21 126 31 
+30 123 108 151 135 165 107 29 120 71 13 137 62 208 104 88 4 39 29 19 115 23 160 
+54 105 91 41 177 27 200 14 163 192 121 79 199 84 55 30 128 179 175 130 99 17 
+195 44 95 187 164 99 136 173 191 113 108 37 13 18 84 174 8 84 60 179 74 37 109 
+40 50 78 82 140 122 9 92 168 48 145 74 55 131 6 169 152 60 202 30 27 86 185 16 
+169 51 182 212 53 97 185 ^
+452 1 82 181 121 167 132 198 92 48 72 119 57 114 184 200 81 68 122 39 26 84 96 
+26 80 1 208 177 217 24 44 191 206 118 209 123 8 140 99 128 99 54 109 42 58 83 
+80 122 113 141 96 147 203 183 180 175 158 16 143 155 155 11 1 13 64 23 1 87 54 
+35 52 46 157 121 19 27 174 115 130 209 72 123 152 150 87 202 140 76 23 75 77 66 
+86 11 149 118 88 44 168 101 94 14 80 145 93 165 73 65 66 12 21 137 192 4 22 83 
+201 120 77 113 94 181 195 157 144 124 51 151 33 211 38 131 178 186 138 184 5 61 
+92 99 175 107 6 155 81 114 207 87 105 45 40 120 73 18 58 60 193 98 11 98 15 100 
+51 3 146 187 61 88 97 139 204 129 189 73 213 171 36 216 55 55 51 174 138 17 15 
+49 41 15 197 146 39 174 64 120 3 123 82 37 111 179 58 157 70 134 39 100 74 108 
+170 164 197 169 144 198 41 163 84 170 16 92 145 167 155 85 116 25 208 200 104 
+48 21 16 69 40 143 178 42 35 196 56 145 70 60 49 88 23 149 192 78 12 95 127 204 
+55 199 61 162 212 151 130 88 74 34 180 152 53 210 166 112 74 182 67 176 30 35 
+29 159 133 19 101 164 127 56 168 175 84 26 131 104 196 126 40 46 83 6 7 101 90 
+12 44 24 216 106 158 39 30 179 132 147 82 60 216 203 35 75 151 181 98 62 108 3 
+49 185 25 185 95 80 71 103 153 22 106 88 144 54 156 175 10 129 119 178 19 148 
+172 79 102 207 13 208 33 114 36 95 57 91 79 176 104 25 41 210 92 122 62 131 108 
+73 162 161 48 142 14 33 137 141 119 34 9 160 5 38 205 75 198 189 50 108 147 59 
+173 192 8 117 119 104 122 136 28 120 124 28 46 9 16 213 50 131 34 83 150 17 89 
+164 53 66 156 124 125 141 45 137 215 109 46 60 119 201 124 172 149 215 183 36 
+72 170 67 102 133 23 196 200 30 58 9 183 110 62 182 211 61 18 202 163 97 ^
+463 1 45 50 116 145 8 64 204 150 74 93 184 89 111 39 108 108 85 61 13 36 154 61 
+210 115 3 84 108 22 152 209 216 103 176 123 126 57 183 10 199 107 186 161 105 
+51 38 69 184 26 202 15 171 57 97 77 24 90 33 183 167 70 83 29 110 67 49 123 63 
+148 159 190 148 2 99 172 159 33 160 26 139 3 44 17 46 89 40 101 87 62 69 27 38 
+6 55 2 162 184 183 190 211 131 6 212 210 138 144 132 85 124 25 60 91 112 95 99 
+212 30 126 120 195 34 19 158 71 28 211 217 56 167 7 71 122 70 66 79 65 134 27 
+61 147 103 199 44 57 137 65 50 202 78 80 81 137 128 12 177 22 129 68 168 23 74 
+30 55 182 174 208 3 21 96 218 112 158 111 16 187 177 5 179 140 82 59 52 188 36 
+20 214 62 29 156 62 46 106 107 29 70 129 91 89 174 51 15 45 136 49 100 142 217 
+182 88 55 48 4 163 20 174 74 156 196 113 151 90 96 92 191 7 134 134 94 106 130 
+170 1 106 193 79 25 146 24 67 112 32 190 85 210 75 15 108 45 73 37 193 205 166 
+194 1 169 102 206 65 197 129 51 218 198 208 66 33 120 155 163 43 95 5 133 78 
+103 2 185 105 114 167 93 4 77 87 102 57 3 218 175 67 135 56 18 165 92 168 86 
+203 157 212 13 59 75 109 187 217 96 155 203 31 71 185 82 193 119 116 122 204 16 
+7 48 201 22 89 197 192 63 125 18 39 171 17 109 101 64 141 138 50 53 133 101 127 
+153 45 207 104 121 188 13 216 63 85 147 166 108 68 214 188 53 87 39 148 96 178 
+124 182 48 67 72 44 214 125 41 63 219 97 211 194 135 16 30 189 132 219 191 70 
+43 158 134 157 118 37 107 52 94 60 68 191 47 122 110 157 55 25 83 12 43 72 201 
+202 101 1 12 114 10 2 28 117 138 207 144 109 164 76 165 178 101 41 90 190 171 
+143 30 32 41 23 11 121 31 25 123 103 136 135 150 97 14 115 66 213 132 62 203 94 
+83 209 19 24 4 100 8 150 160 ^
+474 0 105 91 20 156 27 193 208 142 178 107 79 199 84 41 2 128 165 161 109 85 17 
+174 37 81 187 150 78 129 159 194 184 92 87 23 214 18 77 153 209 63 46 179 46 30 
+102 33 29 50 82 126 101 203 78 147 20 138 53 27 117 207 148 145 32 181 16 13 86 
+178 16 162 30 175 198 32 90 99 66 177 113 155 124 186 80 44 60 119 49 106 176 
+192 65 52 106 27 26 68 92 14 80 211 200 169 213 24 44 191 202 102 197 111 140 
+99 124 95 54 97 42 54 79 68 110 97 133 80 135 199 175 180 171 146 8 131 147 151 
+221 219 9 52 15 1 79 50 27 44 42 145 105 15 19 162 103 118 201 72 107 152 142 
+87 190 132 68 19 71 77 62 70 7 137 114 76 214 36 160 97 78 220 76 141 93 157 57 
+61 58 9 125 180 4 6 67 189 120 61 113 82 181 183 153 136 120 43 139 29 199 26 
+123 174 186 138 184 1 61 76 83 175 107 6 143 81 114 207 75 89 29 32 108 73 10 
+46 48 185 86 11 98 221 88 35 221 146 175 49 88 93 139 196 117 189 65 201 163 24 
+208 51 39 51 170 134 1 3 49 33 11 189 138 35 166 64 116 213 115 70 25 111 167 
+58 149 66 122 31 96 66 104 170 152 197 169 140 190 41 151 72 162 12 92 145 163 
+155 69 104 21 208 200 96 48 21 4 61 40 139 178 34 23 196 44 133 62 52 33 84 23 
+141 184 74 4 79 123 192 47 191 53 158 200 151 130 80 62 34 172 140 41 206 154 
+112 70 174 55 164 18 19 13 159 121 19 89 160 115 52 164 167 76 10 119 104 188 
+126 28 38 75 220 3 85 90 8 40 8 204 90 154 39 14 171 128 147 78 56 216 191 35 
+75 147 169 82 50 100 209 45 185 13 177 95 72 71 95 145 14 98 72 144 38 148 163 
+6 125 107 170 3 140 172 67 98 203 5 204 17 98 36 87 41 75 71 168 88 17 25 202 
+84 114 58 131 92 69 162 161 36 142 14 25 129 141 111 18 1 152 215 30 193 59 198 
+181 34 96 139 47 173 192 214 109 103 100 118 128 16 104 112 198 ^
+466 0 25 2 213 213 36 124 13 62 150 221 61 150 39 45 149 124 104 134 38 130 208 
+109 18 32 112 201 96 158 149 215 176 22 44 149 39 88 133 220 189 193 23 44 9 
+183 89 48 161 204 54 222 195 163 167 40 45 106 140 8 49 204 145 69 83 169 89 96 
+24 93 103 85 41 3 31 154 51 210 115 213 79 108 12 147 209 206 103 176 113 116 
+37 173 10 189 102 176 156 100 36 33 69 174 16 202 5 171 52 82 72 4 80 23 178 
+162 70 83 29 105 67 34 118 43 143 154 185 138 2 79 157 149 33 160 21 129 208 24 
+2 31 69 35 81 72 47 64 22 38 221 55 222 152 179 168 180 211 121 1 207 200 133 
+129 117 80 114 25 50 76 102 85 84 212 30 111 110 195 29 14 153 51 28 196 212 36 
+167 222 61 107 55 46 64 65 119 220 12 56 137 93 194 29 57 137 50 210 30 197 78 
+65 71 132 123 7 177 22 129 68 168 3 74 10 50 167 174 198 218 6 86 218 97 158 
+106 6 177 162 210 164 125 62 59 52 173 16 20 214 42 9 141 57 46 106 97 24 50 
+119 86 84 169 46 15 25 136 44 100 127 202 182 83 35 33 209 158 15 159 64 156 
+191 108 146 75 96 72 181 217 134 129 74 96 115 165 216 91 188 59 10 141 14 62 
+107 12 190 65 205 60 10 98 30 63 22 178 205 151 179 211 164 82 206 60 192 114 
+31 203 188 193 66 28 105 140 148 33 75 5 128 68 83 212 170 95 109 152 88 224 67 
+77 102 42 3 213 170 52 125 56 3 165 82 163 76 193 157 197 218 49 70 89 182 217 
+91 145 203 11 56 180 77 193 114 116 122 189 11 7 43 191 17 74 187 187 53 125 13 
+19 166 222 104 91 54 131 123 50 33 118 86 127 153 45 197 84 121 183 223 201 48 
+70 132 166 88 48 204 188 53 82 29 148 81 163 119 177 28 57 52 34 209 115 31 63 
+204 97 206 194 120 1 25 184 132 214 176 65 28 148 124 147 118 37 87 42 94 60 58 
+186 47 112 110 152 45 15 68 217 43 57 186 187 218 ^
+477 1 200 12 100 223 201 14 117 124 200 137 95 164 76 144 171 101 34 213 83 169 
+150 143 16 32 20 2 224 114 31 18 123 96 115 135 129 83 220 108 59 192 125 62 
+196 80 76 195 218 17 210 79 214 136 6 105 91 5 141 27 188 193 127 168 97 79 199 
+84 31 209 128 155 151 94 75 17 159 32 71 187 140 63 124 149 179 179 77 72 13 
+204 18 72 138 199 48 36 179 26 25 97 28 14 30 82 116 86 188 68 132 133 38 7 107 
+197 133 140 12 166 6 3 86 173 16 157 15 170 188 17 85 84 46 172 103 140 114 171 
+65 39 45 119 39 96 166 182 45 32 86 12 26 48 87 226 80 201 190 159 208 24 44 
+191 197 82 182 96 217 140 99 119 90 54 82 42 49 74 53 95 77 123 60 120 194 165 
+180 166 131 225 116 137 146 211 219 4 37 5 1 69 45 17 34 37 130 85 10 9 147 88 
+103 191 72 87 152 132 87 175 122 58 14 66 77 57 50 2 122 109 61 209 26 150 92 
+58 205 71 136 93 147 37 56 48 212 221 110 165 4 213 47 174 120 41 113 67 181 
+168 148 126 115 33 124 24 184 11 113 169 186 138 184 223 61 56 63 175 107 6 128 
+81 114 207 60 69 9 22 93 73 31 33 175 71 11 98 206 73 15 221 146 160 34 88 88 
+139 186 102 189 55 186 153 9 198 46 19 51 165 129 208 215 49 23 6 179 128 30 
+156 64 111 203 105 55 10 111 152 58 139 61 107 21 91 56 99 170 137 197 169 135 
+180 41 136 57 152 7 92 145 158 155 49 89 16 208 200 86 48 21 216 51 40 134 178 
+24 8 196 29 118 52 42 13 79 23 131 174 69 221 59 118 177 37 181 43 153 185 151 
+130 70 47 34 162 125 26 201 139 112 65 164 40 149 3 226 220 159 106 19 74 155 
+100 47 159 157 66 217 104 104 178 126 13 28 65 215 225 65 90 3 35 215 189 70 
+149 39 221 161 123 147 73 51 216 176 35 75 142 154 62 35 90 194 40 185 225 167 
+95 62 71 85 135 4 88 52 144 18 138 148 1 120 92 160 210 130 172 52 93 198 222 
+199 224 19 ^
+479 0 36 73 13 47 57 154 60 3 226 188 70 100 51 131 64 62 162 161 15 142 14 11 
+115 141 97 219 216 138 201 16 172 31 198 167 6 75 125 26 173 192 193 95 75 93 
+111 114 224 76 91 213 13 227 201 213 28 120 1 50 150 213 45 142 31 33 145 124 
+92 130 34 126 204 109 2 16 108 201 80 150 149 215 172 14 28 137 23 80 133 208 
+185 189 19 36 9 183 77 40 149 200 50 214 191 163 159 36 41 98 136 8 37 204 141 
+65 75 157 89 84 12 81 99 85 25 224 27 154 43 210 115 205 75 108 4 143 209 198 
+103 176 105 108 21 165 10 181 98 168 152 96 24 29 69 166 8 202 226 171 48 70 68 
+217 72 15 174 158 70 83 29 101 67 22 114 27 139 150 181 130 2 63 145 141 33 160 
+17 121 196 8 219 19 53 31 65 60 35 60 18 38 217 55 222 144 175 156 172 211 113 
+226 203 192 129 117 105 76 106 25 42 64 94 77 72 212 30 99 102 195 25 10 149 35 
+28 184 208 20 167 218 53 95 43 30 52 65 107 220 52 129 85 190 17 57 137 38 202 
+14 193 78 53 63 128 119 3 177 22 129 68 168 216 74 223 46 155 174 190 214 223 
+78 218 85 158 102 227 169 150 198 152 113 46 59 52 161 20 214 26 222 129 53 46 
+106 89 20 34 111 82 80 165 42 15 9 136 40 100 115 190 182 79 19 21 197 154 11 
+147 56 156 187 104 142 63 96 56 173 209 134 125 58 88 103 161 212 79 184 43 227 
+137 6 58 103 225 190 49 201 48 6 90 18 55 10 166 205 139 167 203 160 66 206 56 
+188 102 15 191 180 181 66 24 93 128 136 25 59 5 124 60 67 204 158 87 105 140 84 
+224 59 69 102 30 3 209 166 40 117 56 220 165 74 159 68 185 157 185 206 41 66 73 
+178 217 87 137 203 224 44 176 73 193 110 116 122 177 7 7 39 183 13 62 179 183 
+45 125 9 3 162 210 100 83 46 123 111 50 17 106 74 127 153 45 189 68 121 179 215 
+189 36 58 120 166 72 32 196 188 53 78 21 148 69 151 115 173 12 49 36 26 205 107 
+23 63 192 112 ^
+485 1 200 194 102 214 19 178 132 208 158 59 10 136 112 135 118 37 63 30 94 60 
+46 180 47 100 110 146 33 3 50 199 43 39 168 169 90 188 12 92 219 189 6 117 116 
+196 133 87 164 76 132 167 101 30 209 79 157 138 143 8 32 8 221 220 110 31 14 
+123 92 103 135 117 75 212 104 55 180 121 62 192 72 72 187 206 13 202 67 206 128 
+221 105 91 224 129 27 184 181 115 160 89 79 199 84 23 197 128 147 143 82 67 17 
+147 28 63 187 132 51 120 141 167 175 65 60 5 196 18 68 126 191 36 28 179 10 21 
+93 24 2 14 82 108 74 176 60 120 215 129 26 222 99 189 121 136 227 154 229 226 
+86 169 16 153 3 166 180 5 81 72 30 168 95 128 106 159 53 35 33 119 31 88 158 
+174 29 16 70 26 32 83 218 80 193 182 151 204 24 44 191 193 66 170 84 213 140 99 
+115 86 54 70 42 45 70 41 83 61 115 44 108 190 157 180 162 119 221 104 129 142 
+203 219 25 228 1 61 41 9 26 33 118 69 6 1 135 76 91 183 72 71 152 124 87 163 
+114 50 10 62 77 53 34 229 110 105 49 205 18 142 88 42 193 67 132 93 139 21 52 
+40 204 213 98 153 4 201 31 162 120 25 113 55 181 156 144 118 111 25 112 20 172 
+230 105 165 186 138 184 223 61 40 47 175 107 6 116 81 114 207 48 53 224 14 81 
+73 223 19 21 167 59 11 98 194 61 230 221 146 148 22 88 84 139 178 90 189 47 174 
+145 228 190 42 3 51 161 125 196 207 49 15 2 171 120 26 148 64 107 195 97 43 229 
+111 140 58 131 57 95 13 87 48 95 170 125 197 169 131 172 41 124 45 144 3 92 145 
+154 155 33 77 12 208 200 78 48 21 208 43 40 130 178 16 227 196 17 106 44 34 228 
+75 23 123 166 65 217 43 114 165 29 173 35 149 173 151 130 62 35 34 154 113 14 
+197 127 112 61 156 28 137 222 214 208 159 94 19 62 151 88 43 155 149 58 205 92 
+104 170 126 1 20 57 211 225 49 90 230 31 203 177 54 145 39 209 153 119 147 69 
+47 216 164 35 75 138 142 46 23 82 182 36 185 198 ^
+483 1 155 95 50 71 73 123 225 76 28 144 227 126 130 228 114 74 148 192 118 172 
+34 87 192 216 193 206 54 36 65 230 31 49 146 44 228 214 180 62 92 47 131 48 58 
+162 161 3 142 14 3 107 141 89 207 212 130 193 8 160 15 198 159 223 63 117 14 
+173 192 181 87 59 89 107 106 216 60 79 201 1 227 189 213 20 116 222 38 150 205 
+29 134 23 21 141 124 80 126 30 122 200 109 219 104 201 64 142 149 215 168 6 12 
+125 7 72 133 196 181 185 15 28 9 183 65 32 137 196 46 206 187 163 151 32 37 90 
+132 8 25 204 137 61 67 145 89 72 69 95 85 9 220 23 154 35 210 115 197 71 108 
+229 139 209 190 103 176 97 100 5 157 10 173 94 160 148 92 12 25 69 158 202 222 
+171 44 58 64 205 64 7 170 154 70 83 29 97 67 10 110 11 135 146 177 122 2 47 133 
+133 33 160 13 113 184 225 211 7 37 27 49 48 23 56 14 38 213 55 222 136 171 144 
+164 211 105 226 199 184 125 105 93 72 98 25 34 52 86 69 60 212 30 87 94 195 21 
+6 145 19 28 172 204 4 167 214 45 83 31 14 40 65 95 220 221 48 121 77 186 5 57 
+137 26 194 231 189 78 41 55 124 115 232 177 22 129 68 168 204 74 211 42 143 174 
+182 210 215 70 218 73 158 98 223 161 138 186 140 101 30 59 52 149 217 20 214 10 
+210 117 49 46 106 81 16 18 103 78 76 161 38 15 226 136 36 100 103 178 182 75 3 
+9 185 150 7 135 48 156 183 100 138 51 96 40 165 201 134 121 42 80 91 157 208 67 
+180 27 219 133 231 54 99 213 190 33 197 36 2 82 6 47 231 154 205 127 155 195 
+156 50 206 52 184 90 232 179 172 169 66 20 81 116 124 17 43 5 120 52 51 196 146 
+79 101 128 80 224 51 61 102 18 3 205 162 28 109 56 212 165 66 155 60 177 157 
+173 194 33 62 57 174 217 83 129 203 212 32 172 69 193 106 116 122 165 3 7 35 
+175 9 50 171 179 37 125 5 220 158 198 96 75 38 115 99 50 1 94 62 127 153 45 181 
+52 121 175 207 177 24 46 108 164 ^
+499 0 44 4 182 188 53 71 7 148 48 130 108 166 220 35 8 12 198 93 9 63 171 97 
+195 194 87 204 14 173 132 203 143 54 231 126 102 125 118 37 43 20 94 60 36 175 
+47 90 110 141 23 229 35 184 43 24 153 154 85 173 12 82 214 174 232 117 106 191 
+128 77 164 76 117 162 101 25 204 74 142 123 143 234 32 229 211 215 105 31 9 123 
+87 88 135 102 65 202 99 50 165 116 62 187 62 67 177 191 8 192 52 196 118 206 
+105 91 214 114 27 179 166 100 150 79 79 199 84 13 182 128 137 133 67 57 17 132 
+23 53 187 122 36 115 131 152 170 50 45 231 186 18 63 111 181 21 18 179 226 16 
+88 19 223 230 82 98 59 161 50 105 200 124 11 207 89 179 106 131 212 139 224 221 
+86 164 16 148 224 161 170 226 76 57 10 163 85 113 96 144 38 30 18 119 21 78 148 
+164 9 232 50 221 26 12 78 208 80 183 172 141 199 24 44 191 188 46 155 69 208 
+140 99 110 81 54 55 42 40 65 26 68 41 105 24 93 185 147 180 157 104 216 89 119 
+137 193 219 231 10 223 1 51 36 235 16 28 103 49 1 227 120 61 76 173 72 51 152 
+114 87 148 104 40 5 57 77 48 14 229 95 100 34 200 8 132 83 22 178 62 127 93 129 
+1 47 30 194 203 83 138 4 186 11 147 120 5 113 40 181 141 139 108 106 15 97 15 
+157 220 95 160 186 138 184 223 61 20 27 175 107 6 101 81 114 207 33 33 209 4 66 
+73 218 4 6 157 44 11 98 179 46 215 221 146 133 7 88 79 139 168 75 189 37 159 
+135 218 180 37 219 51 156 120 181 197 49 5 233 161 110 21 138 64 102 185 87 28 
+219 111 125 58 121 52 80 3 82 38 90 170 110 197 169 126 162 41 109 30 134 234 
+92 145 149 155 13 62 7 208 200 68 48 21 198 33 40 125 178 6 217 196 2 91 34 24 
+213 70 23 113 156 60 212 23 109 150 19 163 25 144 158 151 130 52 20 34 144 98 
+235 192 112 112 56 146 13 122 212 199 193 159 79 19 47 146 73 38 150 139 48 190 
+77 104 160 126 222 10 47 206 225 29 90 230 26 188 162 34 140 39 194 143 114 147 
+64 42 216 149 174 ^
+473 1 75 131 121 18 2 68 161 29 185 203 145 95 40 71 63 113 220 66 8 144 212 
+116 115 228 109 59 138 177 108 172 19 82 187 211 188 191 34 36 55 215 11 39 136 
+24 223 199 170 52 82 42 131 28 53 162 161 226 142 14 231 97 141 79 192 207 120 
+183 236 145 233 198 149 208 48 107 237 173 192 166 77 39 84 102 96 206 40 64 
+186 224 227 174 213 10 111 212 23 150 195 9 124 13 6 136 124 65 121 25 117 195 
+109 204 218 99 201 44 132 149 215 163 234 230 110 225 62 133 181 176 180 10 18 
+9 183 50 22 122 191 41 196 182 163 141 27 32 80 127 8 10 204 132 56 57 130 89 
+57 223 54 90 85 227 215 18 154 25 210 115 187 66 108 224 134 209 180 103 176 87 
+90 223 147 10 163 89 150 143 87 235 20 69 148 228 202 217 171 39 43 59 190 54 
+235 165 149 70 83 29 92 67 233 105 229 130 141 172 112 2 27 118 123 33 160 8 
+103 169 210 201 230 17 22 29 33 8 51 9 38 208 55 222 126 166 129 154 211 95 226 
+194 174 120 90 78 67 88 25 24 37 76 59 45 212 30 72 84 195 16 1 140 237 28 157 
+199 222 167 209 35 68 16 232 25 65 80 220 211 43 111 67 181 228 57 137 11 184 
+216 184 78 26 45 119 110 232 177 22 129 68 168 189 74 196 37 128 174 172 205 
+205 60 218 58 158 93 218 151 123 171 125 86 10 59 52 134 202 20 214 228 195 102 
+44 46 106 71 11 236 93 73 71 156 33 15 211 136 31 100 88 163 182 70 221 232 170 
+145 2 120 38 156 178 95 133 36 96 20 155 191 134 116 22 70 76 152 203 52 175 7 
+209 128 226 49 94 198 190 13 192 21 235 72 229 37 221 139 205 112 140 185 151 
+30 206 47 179 75 217 164 162 154 66 15 66 101 109 7 23 5 115 42 31 186 131 69 
+96 113 75 224 41 51 102 3 3 200 157 13 99 56 202 165 56 150 50 167 157 158 179 
+23 57 37 169 217 78 119 203 197 17 167 64 193 101 116 122 150 236 7 30 165 4 35 
+161 174 27 125 205 153 148 ^
+502 1 89 61 24 101 78 50 213 73 41 127 153 45 167 24 121 168 193 156 3 25 87 
+166 28 228 174 188 53 67 239 148 36 118 104 162 208 27 232 4 194 85 1 63 159 97 
+191 194 75 196 10 169 132 199 131 50 223 118 94 117 118 37 27 12 94 60 28 171 
+47 82 110 137 15 225 23 172 43 12 141 142 81 161 12 74 210 162 228 117 98 187 
+124 69 164 76 105 158 101 21 200 70 130 111 143 230 32 221 203 211 101 31 5 123 
+83 76 135 90 57 194 95 46 153 112 62 183 54 63 169 179 4 184 40 188 110 194 105 
+91 206 102 27 175 154 88 142 71 79 199 84 5 170 128 129 125 55 49 17 120 19 45 
+187 114 24 111 123 140 166 38 33 227 178 18 59 99 173 9 10 179 214 12 84 15 215 
+218 82 90 47 149 42 93 188 120 239 195 81 171 94 127 200 127 220 217 86 160 16 
+144 216 157 162 218 72 45 234 159 77 101 88 132 26 26 6 119 13 70 140 156 233 
+220 34 213 26 236 74 200 80 175 164 133 195 24 44 191 184 30 143 57 204 140 99 
+106 77 54 43 42 36 61 14 56 25 97 8 81 181 139 180 153 92 212 77 111 133 185 
+219 231 238 219 1 43 32 231 8 24 91 33 237 223 108 49 64 165 72 35 152 106 87 
+136 96 32 1 53 77 44 238 229 83 96 22 196 124 79 6 166 58 123 93 121 225 43 22 
+186 195 71 126 4 174 235 135 120 229 113 28 181 129 135 100 102 7 85 11 145 212 
+87 156 186 138 184 223 61 4 11 175 107 6 89 81 114 207 21 17 197 236 54 73 214 
+232 234 149 32 11 98 167 34 203 221 146 121 235 88 75 139 160 63 189 29 147 127 
+210 172 33 207 51 152 116 169 189 49 237 233 153 102 17 130 64 98 177 79 16 211 
+111 113 58 113 48 68 235 78 30 86 170 98 197 169 122 154 41 97 18 126 234 92 
+145 145 155 237 50 3 208 200 60 48 21 190 25 40 121 178 238 209 196 230 79 26 
+16 201 66 23 105 148 56 208 7 105 138 11 155 17 140 146 151 130 44 8 34 136 86 
+227 188 100 112 52 138 1 110 204 187 181 159 67 19 35 142 61 34 146 131 40 178 
+65 104 152 126 214 2 39 202 173 ^
+486 1 5 90 230 20 170 144 10 134 39 176 131 108 147 58 36 216 131 35 75 127 109 
+2 232 60 149 25 185 195 137 95 32 71 55 105 216 58 234 144 200 108 103 228 105 
+47 130 165 100 172 7 78 183 207 184 179 18 36 47 203 237 31 128 8 219 187 162 
+44 74 38 131 12 49 162 161 218 142 14 227 89 141 71 180 203 112 175 232 133 221 
+198 141 196 36 99 229 173 192 154 69 23 80 98 88 198 24 52 174 216 227 162 213 
+2 107 204 11 150 187 235 116 5 236 132 124 53 117 21 113 191 109 192 206 95 201 
+28 124 149 215 159 230 218 98 213 54 133 169 172 176 6 10 9 183 38 14 110 187 
+37 188 178 163 133 23 28 72 123 8 240 204 128 52 49 118 89 45 215 42 86 85 215 
+211 14 154 17 210 115 179 62 108 220 130 209 172 103 176 79 82 211 139 10 155 
+85 142 139 83 227 16 69 140 224 202 213 171 35 31 55 178 46 231 161 145 70 83 
+29 88 67 225 101 217 126 137 168 104 2 11 106 115 33 160 4 95 157 198 193 222 1 
+18 13 21 238 47 5 38 204 55 222 118 162 117 146 211 87 226 190 166 116 78 66 63 
+80 25 16 25 68 51 33 212 30 60 76 195 12 239 136 225 28 145 195 210 167 205 27 
+56 4 220 13 65 68 220 203 39 103 59 177 220 57 137 241 176 204 180 78 14 37 115 
+106 232 177 22 129 68 168 177 74 184 33 116 174 164 201 197 52 218 46 158 89 
+214 143 111 159 113 74 236 59 52 122 190 20 214 216 183 90 40 46 106 63 7 224 
+85 69 67 152 29 15 199 136 27 100 76 151 182 66 209 224 158 141 240 108 30 156 
+174 91 129 24 96 4 147 183 134 112 6 62 64 148 199 40 171 233 201 124 222 45 90 
+186 190 239 188 9 235 64 221 29 213 127 205 100 128 177 147 14 206 43 175 63 
+205 152 154 142 66 11 54 89 97 241 7 5 111 34 15 178 119 61 92 101 71 224 33 43 
+102 233 3 196 153 1 91 56 194 165 48 146 42 159 157 146 167 15 53 21 165 217 74 
+111 203 185 5 163 60 193 97 116 122 138 236 7 26 157 23 153 170 184 ^
+505 1 125 238 187 147 165 85 53 16 93 66 50 201 61 29 127 153 45 159 8 121 164 
+185 144 235 13 75 166 12 216 166 188 53 63 235 148 24 106 100 158 196 19 220 
+240 190 77 237 63 147 97 187 194 63 188 6 165 132 195 119 46 215 110 86 109 118 
+37 11 4 94 60 20 167 47 74 110 133 7 221 11 160 43 129 130 77 149 12 66 206 150 
+224 117 90 183 120 61 164 76 93 154 101 17 196 66 118 99 143 226 32 213 195 207 
+97 31 1 123 79 64 135 78 49 186 91 42 141 108 62 179 46 59 161 167 176 28 180 
+102 182 105 91 198 90 27 171 142 76 134 63 79 199 84 241 158 128 121 117 43 41 
+17 108 15 37 187 106 12 107 115 128 162 26 21 223 170 18 55 87 165 241 2 179 
+202 8 80 11 207 206 82 82 35 137 34 81 176 116 231 183 73 163 82 123 188 115 
+216 213 86 156 16 140 208 153 154 210 68 33 222 155 69 89 80 120 14 22 238 119 
+5 62 132 148 221 208 18 205 26 224 70 192 80 167 156 125 191 24 44 191 180 14 
+131 45 200 140 99 102 73 54 31 42 32 57 2 44 9 89 236 69 177 131 180 149 80 208 
+65 103 129 177 219 231 230 215 1 35 28 227 20 79 17 237 219 96 37 52 157 72 19 
+152 98 87 124 88 24 241 49 77 40 226 229 71 92 10 192 236 116 75 234 154 54 119 
+93 113 213 39 14 178 187 59 114 4 162 223 123 120 217 113 16 181 117 131 92 98 
+243 73 7 133 204 79 152 186 138 184 223 61 232 239 175 107 6 77 81 114 207 9 1 
+185 232 42 73 210 224 226 141 20 11 98 155 22 191 221 146 109 227 88 71 139 152 
+51 189 21 135 119 202 164 29 195 51 148 112 157 181 49 233 233 145 94 13 122 64 
+94 169 71 4 203 111 101 58 105 44 56 231 74 22 82 170 86 197 169 118 146 41 85 
+6 118 234 92 145 141 155 225 38 243 208 200 52 48 21 182 17 40 117 178 234 201 
+196 222 67 18 8 189 62 23 97 140 52 204 235 101 126 3 147 9 136 134 151 130 36 
+240 34 128 74 219 184 88 112 48 130 233 98 196 175 169 159 55 19 23 138 49 30 
+142 123 32 166 53 104 144 126 206 238 31 198 203 ^
+483 1 235 90 230 16 158 132 240 130 39 164 123 104 147 54 32 216 119 35 75 123 
+97 232 224 52 137 21 185 187 129 95 24 71 47 97 212 50 222 144 188 100 91 228 
+101 35 122 153 92 172 241 74 179 203 180 167 2 36 39 191 225 23 120 238 215 175 
+154 36 66 34 131 242 45 162 161 210 142 14 223 81 141 63 168 199 104 167 228 
+121 209 198 133 184 24 91 221 173 192 142 61 7 76 94 80 190 8 40 162 208 227 
+150 213 240 103 196 245 150 179 223 108 243 228 128 124 41 113 17 109 187 109 
+180 194 91 201 12 116 149 215 155 226 206 86 201 46 133 157 168 172 2 2 9 183 
+26 6 98 183 33 180 174 163 125 19 24 64 119 8 232 204 124 48 41 106 89 33 207 
+30 82 85 203 207 10 154 9 210 115 171 58 108 216 126 209 164 103 176 71 74 199 
+131 10 147 81 134 135 79 219 12 69 132 220 202 209 171 31 19 51 166 38 227 157 
+141 70 83 29 84 67 217 97 205 122 133 164 96 2 241 94 107 33 160 87 145 186 185 
+214 231 14 243 9 230 43 1 38 200 55 222 110 158 105 138 211 79 226 186 158 112 
+66 54 59 72 25 8 13 60 43 21 212 30 48 68 195 8 239 132 213 28 133 191 198 167 
+201 19 44 238 208 1 65 56 220 195 35 95 51 173 212 57 137 233 168 192 176 78 2 
+29 111 102 232 177 22 129 68 168 165 74 172 29 104 174 156 197 189 44 218 34 
+158 85 210 135 99 147 101 62 224 59 52 110 178 20 214 204 171 78 36 46 106 55 3 
+212 77 65 63 148 25 15 187 136 23 100 64 139 182 62 197 216 146 137 240 96 22 
+156 170 87 125 12 96 234 139 175 134 108 236 54 52 144 195 28 167 221 193 120 
+218 41 86 174 190 227 184 243 235 56 213 21 205 115 205 88 116 169 143 244 206 
+39 171 51 193 140 146 130 66 7 42 77 85 237 237 5 107 26 245 170 107 53 88 89 
+67 224 25 35 102 225 3 192 149 235 83 56 186 165 40 142 34 151 157 134 155 7 49 
+5 161 217 70 103 203 173 239 159 56 193 93 116 122 126 236 7 22 149 242 178 ^
+507 1 141 164 7 125 238 175 143 153 81 45 8 85 54 50 189 49 17 127 153 45 151 
+240 121 160 177 132 227 1 63 166 244 204 158 188 53 59 231 148 12 94 96 154 184 
+11 208 236 186 69 233 63 135 97 183 194 51 180 2 161 132 191 107 42 207 102 78 
+101 118 37 243 244 94 60 12 163 47 66 110 129 247 217 247 148 43 236 117 118 73 
+137 12 58 202 138 220 117 82 179 116 53 164 76 81 150 101 13 192 62 106 87 143 
+222 32 205 187 203 93 31 245 123 75 52 135 66 41 178 87 38 129 104 62 175 38 55 
+153 155 244 168 16 172 94 170 105 91 190 78 27 167 130 64 126 55 79 199 84 237 
+146 128 113 109 31 33 17 96 11 29 187 98 103 107 116 158 14 9 219 162 18 51 75 
+157 233 242 179 190 4 76 7 199 194 82 74 23 125 26 69 164 112 223 171 65 155 70 
+119 176 103 212 209 86 152 16 136 200 149 146 202 64 21 210 151 61 77 72 108 2 
+18 230 119 245 54 124 140 209 196 2 197 26 212 66 184 80 159 148 117 187 24 44 
+191 176 246 119 33 196 140 99 98 69 54 19 42 28 53 238 32 241 81 224 57 173 123 
+180 145 68 204 53 95 125 169 219 231 222 211 1 27 24 223 240 16 67 1 237 215 84 
+25 40 149 72 3 152 90 87 112 80 16 241 45 77 36 214 229 59 88 246 188 232 108 
+71 222 142 50 115 93 105 201 35 6 170 179 47 102 4 150 211 111 120 205 113 4 
+181 105 127 84 94 239 61 3 121 196 71 148 186 138 184 223 61 220 227 175 107 6 
+65 81 114 207 245 233 173 228 30 73 206 216 218 133 8 11 98 143 10 179 221 146 
+97 219 88 67 139 144 39 189 13 123 111 194 156 25 183 51 144 108 145 173 49 229 
+233 137 86 9 114 64 90 161 63 240 195 111 89 58 97 40 44 227 70 14 78 170 74 
+197 169 114 138 41 73 242 110 234 92 145 137 155 213 26 243 208 200 44 48 21 
+174 9 40 113 178 230 193 196 214 55 10 177 58 23 89 132 48 200 223 97 114 243 
+139 1 132 122 151 130 28 232 34 120 62 211 180 76 112 44 122 225 86 188 163 157 
+159 43 19 11 134 37 26 138 115 24 154 41 104 136 126 198 234 140 ^
+490 1 192 225 223 90 230 12 146 120 228 126 39 152 115 100 147 50 28 216 107 35 
+75 119 85 220 216 44 125 17 185 179 121 95 16 71 39 89 208 42 210 144 176 92 79 
+228 97 23 114 141 84 172 233 70 175 199 176 155 236 36 31 179 213 15 112 226 
+211 163 146 28 58 30 131 230 41 162 161 202 142 14 219 73 141 55 156 195 96 159 
+224 109 197 198 125 172 12 83 213 173 192 130 53 241 72 90 72 182 242 28 150 
+200 227 138 213 236 99 188 237 150 171 211 100 239 220 124 124 29 109 13 105 
+183 109 168 182 87 201 246 108 149 215 151 222 194 74 189 38 133 145 164 168 
+248 244 9 183 14 248 86 179 29 172 170 163 117 15 20 56 115 8 224 204 120 44 33 
+94 89 21 199 18 78 85 191 203 6 154 1 210 115 163 54 108 212 122 209 156 103 
+176 63 66 187 123 10 139 77 126 131 75 211 8 69 124 216 202 205 171 27 7 47 154 
+30 223 153 137 70 83 29 80 67 209 93 193 118 129 160 88 2 229 82 99 33 160 246 
+79 133 174 177 206 219 10 231 247 222 39 247 38 196 55 222 102 154 93 130 211 
+71 226 182 150 108 54 42 55 64 25 1 52 35 9 212 30 36 60 195 4 239 128 201 28 
+121 187 186 167 197 11 32 230 196 239 65 44 220 187 31 87 43 169 204 57 137 225 
+160 180 172 78 240 21 107 98 232 177 22 129 68 168 153 74 160 25 92 174 148 193 
+181 36 218 22 158 81 206 127 87 135 89 50 212 59 52 98 166 20 214 192 159 66 32 
+46 106 47 249 200 69 61 59 144 21 15 175 136 19 100 52 127 182 58 185 208 134 
+133 240 84 14 156 166 83 121 96 222 131 167 134 104 224 46 40 140 191 16 163 
+209 185 116 214 37 82 162 190 215 180 235 235 48 205 13 197 103 205 76 104 161 
+139 232 206 35 167 39 181 128 138 118 66 3 30 65 73 233 225 5 103 18 233 162 95 
+45 84 77 63 224 17 27 102 217 3 188 145 227 75 56 178 165 32 138 26 143 157 122 
+143 249 45 239 157 217 66 95 203 161 231 155 52 193 89 116 122 114 236 7 18 141 
+242 249 137 162 3 125 238 69 ^
+514 1 139 141 77 37 77 42 50 177 37 5 127 153 45 143 228 121 156 169 120 219 
+241 51 166 232 192 150 188 53 55 227 148 82 92 150 172 3 196 232 182 61 229 63 
+123 97 179 194 39 172 250 157 132 187 95 38 199 94 70 93 118 37 231 240 94 60 4 
+159 47 58 110 125 243 213 239 136 43 228 105 106 69 125 12 50 198 126 216 117 
+74 175 112 45 164 76 69 146 101 9 188 58 94 75 143 218 32 197 179 199 89 31 245 
+123 71 40 135 54 33 170 83 34 117 100 62 171 30 51 145 143 244 160 4 164 86 158 
+105 91 182 66 27 163 118 52 118 47 79 199 84 233 134 128 105 101 19 25 17 84 7 
+21 187 90 240 99 99 104 154 2 249 215 154 18 47 63 149 225 238 179 178 72 3 191 
+182 82 66 11 113 18 57 152 108 215 159 57 147 58 115 164 91 208 205 86 148 16 
+132 192 145 138 194 60 9 198 147 53 65 64 96 242 14 222 119 241 46 116 132 197 
+184 238 189 26 200 62 176 80 151 140 109 183 24 44 191 172 234 107 21 192 140 
+99 94 65 54 7 42 24 49 230 20 229 73 212 45 169 115 180 141 56 200 41 87 121 
+161 219 231 214 207 1 19 20 219 236 12 55 237 237 211 72 13 28 141 72 239 152 
+82 87 100 72 8 241 41 77 32 202 229 47 84 238 184 228 100 67 210 130 46 111 93 
+97 189 31 250 162 171 35 90 4 138 199 99 120 193 113 244 181 93 123 76 90 235 
+49 251 109 188 63 144 186 138 184 223 61 208 215 175 107 6 53 81 114 207 237 
+221 161 224 18 73 202 208 210 125 248 11 98 131 250 167 221 146 85 211 88 63 
+139 136 27 189 5 111 103 186 148 21 171 51 140 104 133 165 49 225 233 129 78 5 
+106 64 86 153 55 232 187 111 77 58 89 36 32 223 66 6 74 170 62 197 169 110 130 
+41 61 234 102 234 92 145 133 155 201 14 243 208 200 36 48 21 166 1 40 109 178 
+226 185 196 206 43 2 244 165 54 23 81 124 44 196 211 93 102 239 131 245 128 110 
+151 130 20 224 34 112 50 203 176 64 112 40 114 217 74 180 151 145 159 31 19 251 
+130 25 22 134 107 16 142 29 104 128 126 190 230 15 190 225 217 90 230 10 140 
+114 222 124 39 146 111 217 ^
+510 0 147 46 24 216 95 35 75 115 73 208 208 36 113 13 185 171 113 95 8 71 31 81 
+204 34 198 144 164 84 67 228 93 11 106 129 76 172 225 66 171 195 172 143 224 36 
+23 167 201 7 104 214 207 151 138 20 50 26 131 218 37 162 161 194 142 14 215 65 
+141 47 144 191 88 151 220 97 185 198 117 160 75 205 173 192 118 45 229 68 86 64 
+174 230 16 138 192 227 126 213 232 95 180 229 150 163 199 92 235 212 120 124 17 
+105 9 101 179 109 156 170 83 201 234 100 149 215 147 218 182 62 177 30 133 133 
+160 164 248 240 9 183 2 244 74 175 25 164 166 163 109 11 16 48 111 8 216 204 
+116 40 25 82 89 9 191 6 74 85 179 199 2 154 247 210 115 155 50 108 208 118 209 
+148 103 176 55 58 175 115 10 131 73 118 127 71 203 4 69 116 212 202 201 171 23 
+249 43 142 22 219 149 133 70 83 29 76 67 201 89 181 114 125 156 80 2 217 70 91 
+33 160 246 71 121 162 169 198 207 6 219 239 214 35 247 38 192 55 222 94 150 81 
+122 211 63 226 178 142 104 42 30 51 56 25 246 243 44 27 251 212 30 24 52 195 
+239 124 189 28 109 183 174 167 193 3 20 222 184 231 65 32 220 179 27 79 35 165 
+196 57 137 217 152 168 168 78 232 13 103 94 232 177 22 129 68 168 141 74 148 21 
+80 174 140 189 173 28 218 10 158 77 202 119 75 123 77 38 200 59 52 86 154 20 
+214 180 147 54 28 46 106 39 249 188 61 57 55 140 17 15 163 136 15 100 40 115 
+182 54 173 200 122 129 240 72 6 156 162 79 117 242 96 210 123 159 134 100 212 
+38 28 136 187 4 159 197 177 112 210 33 78 150 190 203 176 227 235 40 197 5 189 
+91 205 64 92 153 135 220 206 31 163 27 169 116 130 106 66 253 18 53 61 229 213 
+5 99 10 221 154 83 37 80 65 59 224 9 19 102 209 3 184 141 219 67 56 170 165 24 
+134 18 135 157 110 131 245 41 227 153 217 62 87 203 149 223 151 48 193 85 116 
+122 102 236 7 14 133 242 241 129 158 249 125 238 157 137 135 75 33 250 73 36 50 
+171 31 253 127 153 45 139 222 121 154 165 114 215 237 45 166 226 186 146 188 53 
+53 225 148 248 118 ^
+533 0 87 145 157 250 181 227 177 51 224 63 108 97 174 194 24 162 250 152 132 
+182 80 33 189 84 60 83 118 37 216 235 94 60 251 154 47 48 110 120 238 208 229 
+121 43 218 90 91 64 110 12 40 193 111 211 117 64 170 107 35 164 76 54 141 101 4 
+183 53 79 60 143 213 32 187 169 194 84 31 245 123 66 25 135 39 23 160 78 29 102 
+95 62 166 20 46 135 128 244 150 246 154 76 143 105 91 172 51 27 158 103 37 108 
+37 79 199 84 228 119 128 95 91 4 15 17 69 2 11 187 80 230 94 89 89 149 244 239 
+210 144 18 42 48 139 215 233 179 163 252 67 255 181 167 82 56 253 98 8 42 137 
+103 205 144 47 137 43 110 149 76 203 200 86 143 16 127 182 140 128 184 55 251 
+183 142 43 50 54 81 232 9 212 119 236 36 106 122 182 169 223 179 26 185 57 166 
+80 141 130 99 178 24 44 191 167 219 92 6 187 140 99 89 60 54 249 42 19 44 220 5 
+214 63 197 30 164 105 180 136 41 195 26 77 116 151 219 231 204 202 1 9 15 214 
+231 7 40 222 237 206 57 255 13 131 72 224 152 72 87 85 62 255 241 36 77 27 187 
+229 32 79 228 179 223 90 62 195 115 41 106 93 87 174 26 245 152 161 20 75 4 123 
+184 84 120 178 113 234 181 78 118 66 85 230 34 251 94 178 53 139 186 138 184 
+223 61 193 200 175 107 6 38 81 114 207 227 206 146 219 3 73 197 198 200 115 238 
+11 98 116 240 152 221 146 70 201 88 58 139 126 12 189 252 96 93 176 138 16 156 
+51 135 99 118 155 49 220 233 119 68 96 64 81 143 45 222 177 111 62 58 79 31 17 
+218 61 253 69 170 47 197 169 105 120 41 46 224 92 234 92 145 128 155 186 256 
+243 208 200 26 48 21 156 248 40 104 178 221 175 196 196 28 249 239 150 49 23 71 
+114 39 191 196 88 87 234 121 240 123 95 151 130 10 214 34 102 35 193 171 49 112 
+35 104 207 59 170 136 130 159 16 19 241 125 10 17 129 97 6 127 14 104 118 126 
+180 225 5 185 225 202 90 230 5 125 99 207 119 39 131 101 93 147 43 21 216 86 35 
+75 112 64 199 202 30 104 10 185 165 107 95 2 71 25 75 201 28 189 144 155 78 58 
+228 90 2 100 120 70 172 219 63 168 192 169 134 215 36 17 158 192 1 98 205 137 ^
+522 1 139 130 12 42 22 131 206 33 162 161 186 142 14 211 57 141 39 132 187 80 
+143 216 85 173 198 109 148 246 67 197 173 192 106 37 217 64 82 56 166 218 4 126 
+184 227 114 213 228 91 172 221 150 155 187 84 231 204 116 124 5 101 5 97 175 
+109 144 158 79 201 222 92 149 215 143 214 170 50 165 22 133 121 156 160 248 236 
+9 183 248 240 62 171 21 156 162 163 101 7 12 40 107 8 208 204 112 36 17 70 89 
+255 183 252 70 85 167 195 256 154 243 210 115 147 46 108 204 114 209 140 103 
+176 47 50 163 107 10 123 69 110 123 67 195 69 108 208 202 197 171 19 241 39 130 
+14 215 145 129 70 83 29 72 67 193 85 169 110 121 152 72 2 205 58 83 33 160 246 
+63 109 150 161 190 195 2 207 231 206 31 247 38 188 55 222 86 146 69 114 211 55 
+226 174 134 100 30 18 47 48 25 242 235 36 19 243 212 30 12 44 195 254 239 120 
+177 28 97 179 162 167 189 253 8 214 172 223 65 20 220 171 23 71 27 161 188 57 
+137 209 144 156 164 78 224 5 99 90 232 177 22 129 68 168 129 74 136 17 68 174 
+132 185 165 20 218 256 158 73 198 111 63 111 65 26 188 59 52 74 142 20 214 168 
+135 42 24 46 106 31 249 176 53 53 51 136 13 15 151 136 11 100 28 103 182 50 161 
+192 110 125 240 60 256 156 158 75 113 234 96 198 115 151 134 96 200 30 16 132 
+183 250 155 185 169 108 206 29 74 138 190 191 172 219 235 32 189 255 181 79 205 
+52 80 145 131 208 206 27 159 15 157 104 122 94 66 253 6 41 49 225 201 5 95 2 
+209 146 71 29 76 53 55 224 1 11 102 201 3 180 137 211 59 56 162 165 16 130 10 
+127 157 98 119 241 37 215 149 217 58 79 203 137 215 147 44 193 81 116 122 90 
+236 7 10 125 242 233 121 154 245 125 238 145 133 123 71 25 246 65 24 50 159 19 
+245 127 153 45 131 210 121 150 157 102 207 229 33 166 214 174 138 188 53 49 221 
+148 240 64 86 144 154 249 178 226 176 49 223 63 105 97 173 194 21 160 250 151 
+132 181 77 32 187 82 58 81 118 37 213 234 94 60 250 153 47 46 110 119 237 207 
+227 118 43 216 87 88 63 107 12 38 192 108 210 117 62 169 106 33 164 76 51 211 ^
+540 0 101 1 180 50 70 51 143 210 32 181 163 191 81 31 245 123 63 16 135 30 17 
+154 75 26 93 92 62 163 14 43 129 119 244 144 240 148 70 134 105 91 166 42 27 
+155 94 28 102 31 79 199 84 225 110 128 89 85 255 9 17 60 259 5 187 74 224 91 83 
+80 146 238 233 207 138 18 39 39 133 209 230 179 154 252 64 255 175 158 82 50 
+247 89 2 33 128 100 199 135 41 131 34 107 140 67 200 197 86 140 16 124 176 137 
+122 178 52 245 174 139 37 41 48 72 226 6 206 119 233 30 100 116 173 160 214 173 
+26 176 54 160 80 135 124 93 175 24 44 191 164 210 83 257 184 140 99 86 57 54 
+243 42 16 41 214 256 205 57 188 21 161 99 180 133 32 192 17 71 113 145 219 231 
+198 199 1 3 12 211 228 4 31 213 237 203 48 249 4 125 72 215 152 66 87 76 56 252 
+241 33 77 24 178 229 23 76 222 176 220 84 59 186 106 38 103 93 81 165 23 242 
+146 155 11 66 4 114 175 75 120 169 113 228 181 69 115 60 82 227 25 251 85 172 
+47 136 186 138 184 223 61 184 191 175 107 6 29 81 114 207 221 197 137 216 254 
+73 194 192 194 109 232 11 98 107 234 143 221 146 61 195 88 55 139 120 3 189 249 
+87 87 170 132 13 147 51 132 96 109 149 49 217 233 113 62 257 90 64 78 137 39 
+216 171 111 53 58 73 28 8 215 58 250 66 170 38 197 169 102 114 41 37 218 86 234 
+92 145 125 155 177 250 243 208 200 20 48 21 150 245 40 101 178 218 169 196 190 
+19 246 236 141 46 23 65 108 36 188 187 85 78 231 115 237 120 86 151 130 4 208 
+34 96 26 187 168 40 112 32 98 201 50 164 127 121 159 7 19 235 122 1 14 126 91 
+118 5 104 112 126 174 222 259 182 225 193 90 230 2 116 90 198 116 39 122 95 90 
+147 40 18 216 77 35 75 109 55 190 196 24 95 7 185 159 101 95 256 71 19 69 198 
+22 180 144 146 72 49 228 87 253 94 111 64 172 213 60 165 189 166 125 206 36 11 
+149 183 255 92 196 201 133 126 8 38 20 131 200 31 162 161 182 142 14 209 53 141 
+35 126 185 76 139 214 79 167 198 105 142 242 63 193 173 192 100 33 211 62 80 52 
+162 212 258 120 180 227 108 213 226 89 168 217 150 151 181 80 229 200 114 124 
+259 99 3 95 173 109 138 152 77 201 129 ^
+555 0 84 149 215 139 210 158 38 153 14 133 109 152 156 248 232 9 183 240 236 50 
+167 17 148 158 163 93 3 8 32 103 8 200 204 108 32 9 58 89 247 175 244 66 85 155 
+191 256 154 239 210 115 139 42 108 200 110 209 132 103 176 39 42 151 99 10 115 
+65 102 119 63 187 258 69 100 204 202 193 171 15 233 35 118 6 211 141 125 70 83 
+29 68 67 185 81 157 106 117 148 64 2 193 46 75 33 160 246 55 97 138 153 182 183 
+260 195 223 198 27 247 38 184 55 222 78 142 57 106 211 47 226 170 126 96 18 6 
+43 40 25 238 227 28 11 235 212 30 36 195 254 239 116 165 28 85 175 150 167 185 
+249 258 206 160 215 65 8 220 163 19 63 19 157 180 57 137 201 136 144 160 78 216 
+259 95 86 232 177 22 129 68 168 117 74 124 13 56 174 124 181 157 12 218 248 158 
+69 194 103 51 99 53 14 176 59 52 62 130 20 214 156 123 30 20 46 106 23 249 164 
+45 49 47 132 9 15 139 136 7 100 16 91 182 46 149 184 98 121 240 48 252 156 154 
+71 109 226 96 186 107 143 134 92 188 22 4 128 179 242 151 173 161 104 202 25 70 
+126 190 179 168 211 235 24 181 251 173 67 205 40 68 137 127 196 206 23 155 3 
+145 92 114 82 66 253 256 29 37 221 189 5 91 256 197 138 59 21 72 41 51 224 255 
+3 102 193 3 176 133 203 51 56 154 165 8 126 2 119 157 86 107 237 33 203 145 217 
+54 71 203 125 207 143 40 193 77 116 122 78 236 7 6 117 242 225 113 150 241 125 
+238 133 129 111 67 17 242 57 12 50 147 7 237 127 153 45 123 198 121 146 149 90 
+199 221 21 166 202 162 130 188 53 45 217 148 232 52 82 140 142 245 166 222 172 
+41 219 63 93 97 169 194 9 152 250 147 132 177 65 28 179 74 50 73 118 37 201 230 
+94 60 246 149 47 38 110 115 233 203 219 106 43 208 75 76 59 95 12 30 188 96 206 
+117 54 165 102 25 164 76 39 136 101 261 178 48 64 45 143 208 32 177 159 189 79 
+31 245 123 61 10 135 24 13 150 73 24 87 90 62 161 10 41 125 113 244 140 236 144 
+66 128 105 91 162 36 27 153 88 22 98 27 79 199 84 223 104 128 85 81 251 5 17 54 
+259 1 187 70 220 89 79 74 144 234 229 205 134 18 37 33 129 205 228 179 148 252 
+62 255 171 152 82 46 243 83 260 27 122 98 195 129 37 127 28 105 134 207 ^
+545 1 196 193 86 136 16 120 168 133 114 170 48 237 162 135 29 29 40 60 218 2 
+198 119 229 22 92 108 161 148 202 165 26 164 50 152 80 127 116 85 171 24 44 191 
+160 198 71 249 180 140 99 82 53 54 235 42 12 37 206 248 193 49 176 9 157 91 180 
+129 20 188 5 63 109 137 219 231 190 195 1 259 8 207 224 19 201 237 199 36 241 
+256 117 72 203 152 58 87 64 48 248 241 29 77 20 166 229 11 72 214 172 216 76 55 
+174 94 34 99 93 73 153 19 238 138 147 263 54 4 102 163 63 120 157 113 220 181 
+57 111 52 78 223 13 251 73 164 39 132 186 138 184 223 61 172 179 175 107 6 17 
+81 114 207 213 185 125 212 246 73 190 184 186 101 224 11 98 95 226 131 221 146 
+49 187 88 51 139 112 255 189 245 75 79 162 124 9 135 51 128 92 97 141 49 213 
+233 105 54 257 82 64 74 129 31 208 163 111 41 58 65 24 260 211 54 246 62 170 26 
+197 169 98 106 41 25 210 78 234 92 145 121 155 165 242 243 208 200 12 48 21 142 
+241 40 97 178 214 161 196 182 7 242 232 129 42 23 57 100 32 184 175 81 66 227 
+107 233 116 74 151 130 260 200 34 88 14 179 164 28 112 28 90 193 38 156 115 109 
+159 259 19 227 118 253 10 122 83 256 106 257 104 104 126 166 218 255 178 225 
+181 90 230 262 104 78 186 112 39 110 87 86 147 36 14 216 65 35 75 105 43 178 
+188 16 83 3 185 151 93 95 252 71 11 61 194 14 168 144 134 64 37 228 83 245 86 
+99 56 172 205 56 161 185 162 113 194 36 3 137 171 251 84 184 197 121 118 30 16 
+131 188 27 162 161 174 142 14 205 45 141 27 114 181 68 131 210 67 155 198 97 
+130 234 55 185 173 192 88 25 199 58 76 44 154 200 250 108 172 227 96 213 222 85 
+160 209 150 143 169 72 225 192 110 124 251 95 263 91 169 109 126 140 73 201 204 
+80 149 215 137 208 152 32 147 10 133 103 150 154 248 230 9 183 236 234 44 165 
+15 144 156 163 89 1 6 28 101 8 196 204 106 30 5 52 89 243 171 240 64 85 149 189 
+256 154 237 210 115 135 40 108 198 108 209 128 103 176 35 38 145 95 10 111 63 
+98 117 61 183 258 69 96 202 202 191 171 13 229 33 112 2 209 139 123 70 83 29 66 
+67 181 79 151 104 115 146 60 2 187 40 71 33 160 246 51 91 132 178 ^
+563 1 174 171 260 183 215 190 23 247 38 180 55 222 70 138 45 98 211 39 226 166 
+118 92 6 260 39 32 25 234 219 20 3 227 212 30 254 28 195 254 239 112 153 28 73 
+171 138 167 181 245 250 198 148 207 65 262 220 155 15 55 11 153 172 57 137 193 
+128 132 156 78 208 255 91 82 232 177 22 129 68 168 105 74 112 9 44 174 116 177 
+149 4 218 240 158 65 190 95 39 87 41 2 164 59 52 50 118 20 214 144 111 18 16 46 
+106 15 249 152 37 45 43 128 5 15 127 136 3 100 4 79 182 42 137 176 86 117 240 
+36 248 156 150 67 105 218 96 174 99 135 134 88 176 14 258 124 175 234 147 161 
+153 100 198 21 66 114 190 167 164 203 235 16 173 247 165 55 205 28 56 129 123 
+184 206 19 151 257 133 80 106 70 66 253 248 17 25 217 177 5 87 252 185 130 47 
+13 68 29 47 224 251 261 102 185 3 172 129 195 43 56 146 165 122 260 111 157 74 
+95 233 29 191 141 217 50 63 203 113 199 139 36 193 73 116 122 66 236 7 2 109 
+242 217 105 146 237 125 238 121 125 99 63 9 238 49 50 135 261 229 127 153 45 
+115 186 121 142 141 78 191 213 9 166 190 150 122 188 53 41 213 148 224 40 78 
+136 130 241 154 218 168 33 215 63 81 97 165 194 263 144 250 143 132 173 53 24 
+171 66 42 65 118 37 189 226 94 60 242 145 47 30 110 111 229 199 211 94 43 200 
+63 64 55 83 12 22 184 84 202 117 46 161 98 17 164 76 27 132 101 261 174 44 52 
+33 143 204 32 169 151 185 75 31 245 123 57 264 135 12 5 142 69 20 75 86 62 157 
+2 37 117 101 244 132 228 136 58 116 105 91 154 24 27 149 76 10 90 19 79 199 84 
+219 92 128 77 73 243 263 17 42 259 259 187 62 212 85 71 62 140 226 221 201 126 
+18 33 21 121 197 224 179 136 252 58 255 163 140 82 38 235 71 256 15 110 94 187 
+117 29 119 16 101 122 49 194 191 86 134 16 118 164 131 110 166 46 233 156 133 
+25 23 36 54 214 194 119 227 18 88 104 155 142 196 161 26 158 48 148 80 123 112 
+81 169 24 44 191 158 192 65 245 178 140 99 80 51 54 231 42 10 35 202 244 187 45 
+170 3 155 87 180 127 14 186 265 59 107 133 219 231 186 193 1 257 6 205 222 264 
+13 195 237 197 30 237 252 113 72 197 152 54 87 58 44 246 241 27 77 18 160 229 5 
+70 210 170 214 72 53 168 88 32 97 93 69 261 ^
+563 1 15 234 130 139 255 42 4 90 151 51 120 145 113 212 181 45 107 44 74 219 1 
+251 61 156 31 128 186 138 184 223 61 160 167 175 107 6 5 81 114 207 205 173 113 
+208 238 73 186 176 178 93 216 11 98 83 218 119 221 146 37 179 88 47 139 104 247 
+189 241 63 71 154 116 5 123 51 124 88 85 133 49 209 233 97 46 257 74 64 70 121 
+23 200 155 111 29 58 57 20 252 207 50 242 58 170 14 197 169 94 98 41 13 202 70 
+234 92 145 117 155 153 234 243 208 200 4 48 21 134 237 40 93 178 210 153 196 
+174 263 238 228 117 38 23 49 92 28 180 163 77 54 223 99 229 112 62 151 130 256 
+192 34 80 2 171 160 16 112 24 82 185 26 148 103 97 159 251 19 219 114 245 6 118 
+75 252 94 249 104 96 126 158 214 251 174 225 169 90 230 262 92 66 174 108 39 98 
+79 82 147 32 10 216 53 35 75 101 31 166 180 8 71 267 185 143 85 95 248 71 3 53 
+190 6 156 144 122 56 25 228 79 237 78 87 48 172 197 52 157 181 158 101 182 36 
+263 125 159 247 76 172 193 109 110 260 22 12 131 176 23 162 161 166 142 14 201 
+37 141 19 102 177 60 123 206 55 143 198 89 118 226 47 177 173 192 76 17 187 54 
+72 36 146 188 242 96 164 227 84 213 218 81 152 201 150 135 157 64 221 184 106 
+124 243 91 263 87 165 109 114 128 69 201 192 72 149 215 133 204 140 20 135 2 
+133 91 146 150 248 226 9 183 228 230 32 161 11 136 152 163 81 265 2 20 97 8 188 
+204 102 26 265 40 89 235 163 232 60 85 137 185 256 154 233 210 115 127 36 108 
+194 104 209 120 103 176 27 30 133 87 10 103 59 90 113 57 175 258 69 88 198 202 
+187 171 9 221 29 100 262 205 135 119 70 83 29 62 67 173 75 139 100 111 142 52 2 
+175 28 63 33 160 246 43 79 120 141 170 165 260 177 211 186 21 247 38 178 55 222 
+66 136 39 94 211 35 226 164 114 90 256 37 28 25 232 215 16 267 223 212 30 250 
+24 195 254 239 110 147 28 67 169 132 167 179 243 246 194 142 203 65 258 220 151 
+13 51 7 151 168 57 137 189 124 126 154 78 204 253 89 80 232 177 22 129 68 168 
+99 74 106 7 38 174 112 175 145 218 236 158 63 188 91 33 81 35 264 158 59 52 44 
+112 20 214 138 105 12 14 46 106 11 249 146 33 43 41 126 3 15 121 136 1 100 266 
+73 182 40 131 172 80 115 240 30 246 186 ^
+573 0 146 63 101 210 96 162 91 127 134 84 164 6 250 120 171 226 143 149 145 96 
+194 17 62 102 190 155 160 195 235 8 165 243 157 43 205 16 44 121 119 172 206 15 
+147 249 121 68 98 58 66 253 240 5 13 213 165 5 83 248 173 122 35 5 64 17 43 224 
+247 257 102 177 3 168 125 187 35 56 138 165 262 118 256 103 157 62 83 229 25 
+179 137 217 46 55 203 101 191 135 32 193 69 116 122 54 236 7 268 101 242 209 97 
+142 233 125 238 109 121 87 59 1 234 41 258 50 123 253 221 127 153 45 107 174 
+121 138 133 66 183 205 267 166 178 138 114 188 53 37 209 148 216 28 74 132 118 
+237 142 214 164 25 211 63 69 97 161 194 255 136 250 139 132 169 41 20 163 58 34 
+57 118 37 177 222 94 60 238 141 47 22 110 107 225 195 203 82 43 192 51 52 51 71 
+12 14 180 72 198 117 38 157 94 9 164 76 15 128 101 261 170 40 40 21 143 200 32 
+161 143 181 71 31 245 123 53 256 135 267 134 65 16 63 82 62 153 264 33 109 89 
+244 124 220 128 50 104 105 91 146 12 27 145 64 268 82 11 79 199 84 215 80 128 
+69 65 235 259 17 30 259 255 187 54 204 81 63 50 136 218 213 197 118 18 29 9 113 
+189 220 179 124 252 54 255 155 128 82 30 227 59 252 3 98 90 179 105 21 111 4 97 
+110 37 190 187 86 130 16 114 156 127 102 158 42 225 144 129 17 11 28 42 206 266 
+186 119 223 10 80 96 143 130 184 153 26 146 44 140 80 115 104 73 165 24 44 191 
+154 180 53 237 174 140 99 76 47 54 223 42 6 31 194 236 175 37 158 261 151 79 
+180 123 2 182 257 51 103 125 219 231 178 189 1 253 2 201 218 264 1 183 237 193 
+18 229 244 105 72 185 152 46 87 46 36 242 241 23 77 14 148 229 263 66 202 166 
+210 64 49 156 76 28 93 93 61 135 13 232 126 135 251 36 4 84 145 45 120 139 113 
+208 181 39 105 40 72 217 265 251 55 152 27 126 186 138 184 223 61 154 161 175 
+107 6 269 81 114 207 201 167 107 206 234 73 184 172 174 89 212 11 98 77 214 113 
+221 146 31 175 88 45 139 100 243 189 239 57 67 150 112 3 117 51 122 86 79 129 
+49 207 233 93 42 257 70 64 68 117 19 196 151 111 23 58 53 18 248 205 48 240 56 
+170 8 197 169 92 94 41 7 198 66 234 92 145 115 155 147 230 243 208 200 48 21 
+130 235 40 91 178 208 149 196 170 259 236 226 111 36 23 45 88 26 178 157 207 ^
+566 1 42 219 91 225 108 50 151 130 252 184 34 72 262 163 156 4 112 20 74 177 14 
+140 91 85 159 243 19 211 110 237 2 114 67 248 82 241 104 88 126 150 210 247 170 
+225 157 90 230 262 80 54 162 104 39 86 71 78 147 28 6 216 41 35 75 97 19 154 
+172 59 267 185 135 77 95 244 71 267 45 186 270 144 144 110 48 13 228 75 229 70 
+75 40 172 189 48 153 177 154 89 170 36 259 113 147 243 68 160 189 97 102 256 14 
+8 131 164 19 162 161 158 142 14 197 29 141 11 90 173 52 115 202 43 131 198 81 
+106 218 39 169 173 192 64 9 175 50 68 28 138 176 234 84 156 227 72 213 214 77 
+144 193 150 127 145 56 217 176 102 124 235 87 263 83 161 109 102 116 65 201 180 
+64 149 215 129 200 128 8 123 266 133 79 142 146 248 222 9 183 220 226 20 157 7 
+128 148 163 73 265 270 12 93 8 180 204 98 22 261 28 89 227 155 224 56 85 125 
+181 256 154 229 210 115 119 32 108 190 100 209 112 103 176 19 22 121 79 10 95 
+55 82 109 53 167 258 69 80 194 202 183 171 5 213 25 88 258 201 131 115 70 83 29 
+58 67 165 71 127 96 107 138 44 2 163 16 55 33 160 246 35 67 108 133 162 153 260 
+165 203 178 17 247 38 174 55 222 58 132 27 86 211 27 226 160 106 86 260 248 33 
+20 25 228 207 8 263 215 212 30 242 16 195 254 239 106 135 28 55 165 120 167 175 
+239 238 186 130 195 65 250 220 143 9 43 271 147 160 57 137 181 116 114 150 78 
+196 249 85 76 232 177 22 129 68 168 87 74 94 3 26 174 104 171 137 264 218 228 
+158 59 184 83 21 69 23 256 146 59 52 32 100 20 214 126 93 10 46 106 3 249 134 
+25 39 37 122 271 15 109 136 269 100 258 61 182 36 119 164 68 111 240 18 242 156 
+144 61 99 206 96 156 87 123 134 82 158 2 246 118 169 222 141 143 141 94 192 15 
+60 96 190 149 158 191 235 4 161 241 153 37 205 10 38 117 117 166 206 13 145 245 
+115 62 94 52 66 253 236 271 7 211 159 5 81 246 167 118 29 1 62 11 41 224 245 
+255 102 173 3 166 123 183 31 56 134 165 260 116 254 99 157 56 77 227 23 173 135 
+217 44 51 203 95 187 133 30 193 67 116 122 48 236 7 268 97 242 205 93 140 231 
+125 238 103 119 81 57 269 232 37 254 50 117 249 217 127 153 45 103 168 121 136 
+129 60 179 201 263 166 172 132 110 188 53 35 207 148 212 262 ^
+589 0 70 128 106 233 130 210 160 17 207 63 57 97 157 194 247 128 250 135 132 
+165 29 16 155 50 26 49 118 37 165 218 94 60 234 137 47 14 110 103 221 191 195 
+70 43 184 39 40 47 59 12 6 176 60 194 117 30 153 90 1 164 76 3 124 101 261 166 
+36 28 9 143 196 32 153 135 177 67 31 245 123 49 248 135 262 263 126 61 12 51 78 
+62 149 260 29 101 77 244 116 212 120 42 92 105 91 138 27 141 52 260 74 3 79 199 
+84 211 68 128 61 57 227 255 17 18 259 251 187 46 196 77 55 38 132 210 205 193 
+110 18 25 271 105 181 216 179 112 252 50 255 147 116 82 22 219 47 248 265 86 86 
+171 93 13 103 266 93 98 25 186 183 86 126 16 110 148 123 94 150 38 217 132 125 
+9 273 20 30 198 266 178 119 219 2 72 88 131 118 172 145 26 134 40 132 80 107 96 
+65 161 24 44 191 150 168 41 229 170 140 99 72 43 54 215 42 2 27 186 228 163 29 
+146 253 147 71 180 119 264 178 249 43 99 117 219 231 170 185 1 249 272 197 214 
+264 263 171 237 189 6 221 236 97 72 173 152 38 87 34 28 238 241 19 77 10 136 
+229 255 62 194 162 206 56 45 144 64 24 89 93 53 123 9 228 118 127 243 24 4 72 
+133 33 120 127 113 200 181 27 101 32 68 213 257 251 43 144 19 122 186 138 184 
+223 61 142 149 175 107 6 261 81 114 207 193 155 95 202 226 73 180 164 166 81 
+204 11 98 65 206 101 221 146 19 167 88 41 139 92 235 189 235 45 59 142 104 273 
+105 51 118 82 67 121 49 203 233 85 34 257 62 64 64 109 11 188 143 111 11 58 45 
+14 240 201 44 236 52 170 270 197 169 88 86 41 269 190 58 234 92 145 111 155 135 
+222 243 208 200 266 48 21 122 231 40 87 178 204 141 196 162 251 232 222 99 32 
+23 37 80 22 174 145 71 36 217 87 223 106 44 151 130 250 180 34 68 258 159 154 
+272 112 18 70 173 8 136 85 79 159 239 19 207 108 233 112 63 246 76 237 104 84 
+126 146 208 245 168 225 151 90 230 262 74 48 156 102 39 80 67 76 147 26 4 216 
+35 35 75 95 13 148 168 270 53 267 185 131 73 95 242 71 265 41 184 268 138 144 
+104 44 7 228 73 225 66 69 36 172 185 46 151 175 152 83 164 36 257 107 141 241 
+64 154 187 91 98 254 10 6 131 158 17 162 161 154 142 14 195 25 141 7 84 171 48 
+111 200 37 125 198 77 100 214 35 165 173 192 58 5 169 48 66 24 134 170 230 78 
+152 227 66 213 212 75 140 189 150 123 139 52 215 172 124 ^
+584 0 124 227 83 263 79 157 109 90 104 61 201 168 56 149 215 125 196 116 272 
+111 262 133 67 138 142 248 218 9 183 212 222 8 153 3 120 144 163 65 265 270 4 
+89 8 172 204 94 18 257 16 89 219 147 216 52 85 113 177 256 154 225 210 115 111 
+28 108 186 96 209 104 103 176 11 14 109 71 10 87 51 74 105 49 159 258 69 72 190 
+202 179 171 1 205 21 76 254 197 127 111 70 83 29 54 67 157 67 115 92 103 134 36 
+2 151 4 47 33 160 246 27 55 96 125 154 141 260 153 195 170 13 247 38 170 55 222 
+50 128 15 78 211 19 226 156 98 82 252 240 29 12 25 224 199 259 207 212 30 234 8 
+195 254 239 102 123 28 43 161 108 167 171 235 230 178 118 187 65 242 220 135 5 
+35 267 143 152 57 137 173 108 102 146 78 188 245 81 72 232 177 22 129 68 168 75 
+74 82 275 14 174 96 167 129 260 218 220 158 55 180 75 9 57 11 248 134 59 52 20 
+88 20 214 114 81 264 6 46 106 271 249 122 17 35 33 118 271 15 97 136 269 100 
+250 49 182 32 107 156 56 107 240 6 238 156 140 57 95 198 96 144 79 115 134 78 
+146 270 238 114 165 214 137 131 133 90 188 11 56 84 190 137 154 183 235 272 153 
+237 145 25 205 274 26 109 113 154 206 9 141 237 103 50 86 40 66 253 228 263 271 
+207 147 5 77 242 155 110 17 269 58 275 37 224 241 251 102 165 3 162 119 175 23 
+56 126 165 256 112 250 91 157 44 65 223 19 161 131 217 40 43 203 83 179 129 26 
+193 63 116 122 36 236 7 268 89 242 197 85 136 227 125 238 91 115 69 53 265 228 
+29 246 50 105 241 209 127 153 45 95 156 121 132 121 48 171 193 255 166 160 120 
+102 188 53 31 203 148 204 10 68 126 100 231 124 208 158 13 205 63 51 97 155 194 
+243 124 250 133 132 163 23 14 151 46 22 45 118 37 159 216 94 60 232 135 47 10 
+110 101 219 189 191 64 43 180 33 34 45 53 12 2 174 54 192 117 26 151 88 273 164 
+76 273 122 101 261 164 34 22 3 143 194 32 149 131 175 65 31 245 123 47 244 135 
+258 261 122 59 10 45 76 62 147 258 27 97 71 244 112 208 116 38 86 105 91 134 
+270 27 139 46 256 70 275 79 199 84 209 62 128 57 53 223 253 17 12 259 249 187 
+42 192 75 51 32 130 206 201 191 106 18 23 267 101 177 214 179 106 252 48 255 
+143 110 82 18 215 41 246 261 80 84 167 87 9 99 262 91 92 19 184 181 86 124 16 
+108 144 121 90 146 36 213 126 123 5 269 230 ^
+587 0 18 190 266 170 119 215 272 64 80 119 106 160 137 26 122 36 124 80 99 88 
+57 157 24 44 191 146 156 29 221 166 140 99 68 39 54 207 42 276 23 178 220 151 
+21 134 245 143 63 180 115 256 174 241 35 95 109 219 231 162 181 1 245 272 193 
+210 264 255 159 237 185 272 213 228 89 72 161 152 30 87 22 20 234 241 15 77 6 
+124 229 247 58 186 158 202 48 41 132 52 20 85 93 45 111 5 224 110 119 235 12 4 
+60 121 21 120 115 113 192 181 15 97 24 64 209 249 251 31 136 11 118 186 138 184 
+223 61 130 137 175 107 6 253 81 114 207 185 143 83 198 218 73 176 156 158 73 
+196 11 98 53 198 89 221 146 7 159 88 37 139 84 227 189 231 33 51 134 96 273 93 
+51 114 78 55 113 49 199 233 77 26 257 54 64 60 101 3 180 135 111 277 58 37 10 
+232 197 40 232 48 170 262 197 169 84 78 41 261 182 50 234 92 145 107 155 123 
+214 243 208 200 262 48 21 114 227 40 83 178 200 133 196 154 243 228 218 87 28 
+23 29 72 18 170 133 67 24 213 79 219 102 32 151 130 246 172 34 60 250 151 150 
+264 112 14 62 165 274 128 73 67 159 231 19 199 104 225 274 108 55 242 64 229 
+104 76 126 138 204 241 164 225 139 90 230 262 62 36 144 98 39 68 59 72 147 22 
+216 23 35 75 91 1 136 160 266 41 267 185 123 65 95 238 71 261 33 180 264 126 
+144 92 36 273 228 69 217 58 57 28 172 177 42 147 171 148 71 152 36 253 95 129 
+237 56 142 183 79 90 250 2 2 131 146 13 162 161 146 142 14 191 17 141 277 72 
+167 40 103 196 25 113 198 69 88 206 27 157 173 192 46 275 157 44 62 16 126 158 
+222 66 144 227 54 213 208 71 132 181 150 115 127 44 211 164 96 124 223 81 263 
+77 155 109 84 98 59 201 162 52 149 215 123 194 110 268 105 260 133 61 136 140 
+248 216 9 183 208 220 2 151 1 116 142 163 61 265 270 87 8 168 204 92 16 255 10 
+89 215 143 212 50 85 107 175 256 154 223 210 115 107 26 108 184 94 209 100 103 
+176 7 10 103 67 10 83 49 70 103 47 155 258 69 68 188 202 177 171 277 201 19 70 
+252 195 125 109 70 83 29 52 67 153 65 109 90 101 132 32 2 145 276 43 33 160 246 
+23 49 90 121 150 135 260 147 191 166 11 247 38 168 55 222 46 126 9 74 211 15 
+226 154 94 80 248 236 27 8 25 222 195 274 257 203 212 30 230 4 195 254 239 100 
+117 28 37 159 102 167 169 233 226 174 112 183 65 238 220 131 3 31 270 ^
+609 1 140 146 57 137 167 102 93 143 78 182 242 78 69 232 177 22 129 68 168 66 
+74 73 275 5 174 90 164 123 257 218 214 158 52 177 69 48 2 242 125 59 52 11 79 
+20 214 105 72 258 3 46 106 268 249 113 11 32 30 115 271 15 88 136 269 100 244 
+40 182 29 98 150 47 104 240 276 235 156 137 54 92 192 96 135 73 109 134 75 137 
+267 232 111 162 208 134 122 127 87 185 8 53 75 190 128 151 177 235 269 147 234 
+139 16 205 268 17 103 110 145 206 6 138 231 94 41 80 31 66 253 222 257 265 204 
+138 5 74 239 146 104 8 266 55 269 34 224 238 248 102 159 3 159 116 169 17 56 
+120 165 253 109 247 85 157 35 56 220 16 152 128 217 37 37 203 74 173 126 23 193 
+60 116 122 27 236 7 268 83 242 191 79 133 224 125 238 82 112 60 50 262 225 23 
+240 50 96 235 203 127 153 45 89 147 121 129 115 39 165 187 249 166 151 111 96 
+188 53 28 200 148 198 1 65 123 91 228 115 205 155 7 202 63 42 97 152 194 237 
+118 250 130 132 160 14 11 145 40 16 39 118 37 150 213 94 60 229 132 47 4 110 98 
+216 186 185 55 43 174 24 25 42 44 12 275 171 45 189 117 20 148 85 270 164 76 
+267 119 101 261 161 31 13 273 143 191 32 143 125 172 62 31 245 123 44 238 135 
+252 258 116 56 7 36 73 62 144 255 24 91 62 244 106 202 110 32 77 105 91 128 264 
+27 136 37 250 64 272 79 199 84 206 53 128 51 47 217 250 17 3 259 246 187 36 186 
+72 45 23 127 200 195 188 100 18 20 261 95 171 211 179 97 252 45 255 137 101 82 
+12 209 32 243 255 71 81 161 78 3 93 256 88 83 10 181 178 86 121 16 105 138 118 
+84 140 33 207 117 120 278 263 10 15 188 266 168 119 214 271 62 78 116 103 157 
+135 26 119 35 122 80 97 86 55 156 24 44 191 145 153 26 219 165 140 99 67 38 54 
+205 42 276 22 176 218 148 19 131 243 142 61 180 114 254 173 239 33 94 107 219 
+231 160 180 1 244 272 192 209 264 253 156 237 184 270 211 226 87 72 158 152 28 
+87 19 18 233 241 14 77 5 121 229 245 57 184 157 201 46 40 129 49 19 84 93 43 
+108 4 223 108 117 233 9 4 57 118 18 120 112 113 190 181 12 96 22 63 208 247 251 
+28 134 9 117 186 138 184 223 61 127 134 175 107 6 251 81 114 207 183 140 80 197 
+216 73 175 154 156 71 194 11 98 50 196 86 221 146 4 157 88 36 139 82 225 189 
+230 30 49 132 94 273 90 51 113 77 52 111 49 198 233 75 24 257 52 64 59 99 1 178 
+133 111 275 58 35 9 230 196 39 231 47 170 216 ^
+589 0 197 169 81 72 41 255 176 44 234 92 145 104 155 114 208 243 208 200 259 48 
+21 108 224 40 80 178 197 127 196 148 237 225 215 78 25 23 23 66 15 167 124 64 
+15 210 73 216 99 23 151 130 243 166 34 54 244 145 147 258 112 11 56 159 268 122 
+64 58 159 225 19 193 101 219 274 105 49 239 55 223 104 70 126 132 201 238 161 
+225 130 90 230 262 53 27 135 95 39 59 53 69 147 19 278 216 14 35 75 88 273 127 
+154 263 32 267 185 117 59 95 235 71 258 27 177 261 117 144 83 30 267 228 66 211 
+52 48 22 172 171 39 144 168 145 62 143 36 250 86 120 234 50 133 180 70 84 247 
+277 280 131 137 10 162 161 140 142 14 188 11 141 274 63 164 34 97 193 16 104 
+198 63 79 200 21 151 173 192 37 272 148 41 59 10 120 149 216 57 138 227 45 213 
+205 68 126 175 150 109 118 38 208 158 93 124 217 78 263 74 152 109 75 89 56 201 
+153 46 149 215 120 191 101 262 96 257 133 52 133 137 248 213 9 183 202 217 274 
+148 279 110 139 163 55 265 270 275 84 8 162 204 89 13 252 1 89 209 137 206 47 
+85 98 172 256 154 220 210 115 101 23 108 181 91 209 94 103 176 1 4 94 61 10 77 
+46 64 100 44 149 258 69 62 185 202 174 171 277 195 16 61 249 192 122 106 70 83 
+29 49 67 147 62 100 87 98 129 26 2 136 270 37 33 160 246 17 40 81 115 144 126 
+260 138 185 160 8 247 38 165 55 222 40 123 68 211 9 226 151 88 77 242 230 24 2 
+25 219 189 271 254 197 212 30 224 279 195 254 239 97 108 28 28 156 93 167 166 
+230 220 168 103 177 65 232 220 125 25 262 138 142 57 137 163 98 87 141 78 178 
+240 76 67 232 177 22 129 68 168 60 74 67 275 280 174 86 162 119 255 218 210 158 
+50 175 65 275 42 277 238 119 59 52 5 73 20 214 99 66 254 1 46 106 266 249 107 7 
+30 28 113 271 15 82 136 269 100 240 34 182 27 92 146 41 102 240 272 233 156 135 
+52 90 188 96 129 69 105 134 73 131 265 228 109 160 204 132 116 123 85 183 6 51 
+69 190 122 149 173 235 267 143 232 135 10 205 264 11 99 108 139 206 4 136 227 
+88 35 76 25 66 253 218 253 261 202 132 5 72 237 140 100 2 264 53 265 32 224 236 
+246 102 155 3 157 114 165 13 56 116 165 251 107 245 81 157 29 50 218 14 146 126 
+217 35 33 203 68 169 124 21 193 58 116 122 21 236 7 268 79 242 187 75 131 222 
+125 238 76 110 54 48 260 223 19 236 50 90 231 199 127 153 45 270 ^
+623 1 135 121 125 107 27 157 179 241 166 139 99 88 188 53 24 196 148 190 272 61 
+119 79 224 103 201 151 282 198 63 30 97 148 194 229 110 250 126 132 156 2 7 137 
+32 8 31 118 37 138 209 94 60 225 128 47 279 110 94 212 182 177 43 43 166 12 13 
+38 32 12 271 167 33 185 117 12 144 81 266 164 76 259 115 101 261 157 27 1 265 
+143 187 32 135 117 168 58 31 245 123 40 230 135 244 254 108 52 3 24 69 62 140 
+251 20 83 50 244 98 194 102 24 65 105 91 120 256 27 132 25 242 56 268 79 199 84 
+202 41 128 43 39 209 246 17 274 259 242 187 28 178 68 37 11 123 192 187 184 92 
+18 16 253 87 163 207 179 85 252 41 255 129 89 82 4 201 20 239 247 59 77 153 66 
+278 85 248 84 71 281 177 174 86 117 16 101 130 114 76 132 29 199 105 116 274 
+255 2 3 180 266 160 119 210 267 54 70 104 91 145 127 26 107 31 114 80 89 78 47 
+152 24 44 191 141 141 14 211 161 140 99 63 34 54 197 42 276 18 168 210 136 11 
+119 235 138 53 180 110 246 169 231 25 90 99 219 231 152 176 1 240 272 188 205 
+264 245 144 237 180 262 203 218 79 72 146 152 20 87 7 10 229 241 10 77 1 109 
+229 237 53 176 153 197 38 36 117 37 15 80 93 35 96 219 100 109 225 280 4 45 106 
+6 120 100 113 182 181 92 14 59 204 239 251 16 126 1 113 186 138 184 223 61 115 
+122 175 107 6 243 81 114 207 175 128 68 193 208 73 171 146 148 63 186 11 98 38 
+188 74 221 146 275 149 88 32 139 74 217 189 226 18 41 124 86 273 78 51 109 73 
+40 103 49 194 233 67 16 257 44 64 55 91 276 170 125 111 267 58 27 5 222 192 35 
+227 43 170 252 197 169 79 68 41 251 172 40 234 92 145 102 155 108 204 243 208 
+200 257 48 21 104 222 40 78 178 195 123 196 144 233 223 213 72 23 23 19 62 13 
+165 118 62 9 208 69 214 97 17 151 130 241 162 34 50 240 141 145 254 112 9 52 
+155 264 118 58 52 159 221 19 189 99 215 274 103 45 237 49 219 104 66 126 128 
+199 236 159 225 124 90 230 262 47 21 129 93 39 53 49 67 147 17 278 216 8 35 75 
+86 269 121 150 261 26 267 185 113 55 95 233 71 256 23 175 259 111 144 77 26 263 
+228 64 207 48 42 18 172 167 37 142 166 143 56 137 36 248 80 114 232 46 127 178 
+64 80 245 275 280 131 131 8 162 161 136 142 14 186 7 141 272 57 162 30 93 191 
+10 98 198 59 73 196 17 147 173 192 31 270 142 39 57 6 116 143 212 51 134 227 39 
+213 203 66 122 171 150 105 112 34 206 154 91 124 213 76 263 72 150 109 69 83 54 
+201 147 42 149 202 ^
+602 1 116 187 89 254 84 253 133 40 129 133 248 209 9 183 194 213 266 144 279 
+102 135 163 47 265 270 271 80 8 154 204 85 9 248 274 89 201 129 198 43 85 86 
+168 256 154 216 210 115 93 19 108 177 87 209 86 103 176 278 281 82 53 10 69 42 
+56 96 40 141 258 69 54 181 202 170 171 277 187 12 49 245 188 118 102 70 83 29 
+45 67 139 58 88 83 94 125 18 2 124 262 29 33 160 246 9 28 69 107 136 114 260 
+126 177 152 4 247 38 161 55 222 32 119 273 60 211 1 226 147 80 73 234 222 20 
+279 25 215 181 267 250 189 212 30 216 275 195 254 239 93 96 28 16 152 81 167 
+162 226 212 160 91 169 65 224 220 117 281 17 258 134 134 57 137 155 90 75 137 
+78 170 236 72 63 232 177 22 129 68 168 48 74 55 275 272 174 78 158 111 251 218 
+202 158 46 171 57 267 30 269 230 107 59 52 278 61 20 214 87 54 246 282 46 106 
+262 249 95 284 26 24 109 271 15 70 136 269 100 232 22 182 23 80 138 29 98 240 
+264 229 156 131 48 86 180 96 117 61 97 134 69 119 261 220 105 156 196 128 104 
+115 81 179 2 47 57 190 110 145 165 235 263 135 228 127 283 205 256 284 91 104 
+127 206 132 219 76 23 68 13 66 253 210 245 253 198 120 5 68 233 128 92 275 260 
+49 257 28 224 232 242 102 147 3 153 110 157 5 56 108 165 247 103 241 73 157 17 
+38 214 10 134 122 217 31 25 203 56 161 120 17 193 54 116 122 9 236 7 268 71 242 
+179 67 127 218 125 238 64 106 42 44 256 219 11 228 50 78 223 191 127 153 45 77 
+129 121 123 103 21 153 175 237 166 133 93 84 188 53 22 194 148 186 268 59 117 
+73 222 97 199 149 280 196 63 24 97 146 194 225 106 250 124 132 154 281 5 133 28 
+4 27 118 37 132 207 94 60 223 126 47 277 110 92 210 180 173 37 43 162 6 7 36 26 
+12 269 165 27 183 117 8 142 79 264 164 76 255 113 101 261 155 25 280 261 143 
+185 32 131 113 166 56 31 245 123 38 226 135 240 252 104 50 1 18 67 62 138 249 
+18 79 44 244 94 190 98 20 59 105 91 116 252 27 130 19 238 52 266 79 199 84 200 
+35 128 39 35 205 244 17 270 259 240 187 24 174 66 33 5 121 188 183 182 88 18 14 
+249 83 159 205 179 79 252 39 255 125 83 82 197 14 237 243 53 75 149 60 276 81 
+244 82 65 277 175 172 86 115 16 99 126 112 72 128 27 195 99 114 272 251 283 282 
+176 266 156 119 208 265 50 66 98 85 139 123 26 101 29 110 80 85 74 43 150 24 44 
+191 139 135 8 207 159 140 99 61 248 ^
+609 1 54 189 42 276 14 160 202 124 3 107 227 134 45 180 106 238 165 223 17 86 
+91 219 231 144 172 1 236 272 184 201 264 237 132 237 176 254 195 210 71 72 134 
+152 12 87 282 2 225 241 6 77 284 97 229 229 49 168 149 193 30 32 105 25 11 76 
+93 27 84 283 215 92 101 217 272 4 33 94 281 120 88 113 174 181 275 88 6 55 200 
+231 251 4 118 280 109 186 138 184 223 61 103 110 175 107 6 235 81 114 207 167 
+116 56 189 200 73 167 138 140 55 178 11 98 26 180 62 221 146 267 141 88 28 139 
+66 209 189 222 6 33 116 78 273 66 51 105 69 28 95 49 190 233 59 8 257 36 64 51 
+83 272 162 117 111 259 58 19 1 214 188 31 223 39 170 244 197 169 75 60 41 243 
+164 32 234 92 145 98 155 96 196 243 208 200 253 48 21 96 218 40 74 178 191 115 
+196 136 225 219 209 60 19 23 11 54 9 161 106 58 284 204 61 210 93 5 151 130 237 
+154 34 42 232 133 141 246 112 5 44 147 256 110 46 40 159 213 19 181 95 207 274 
+99 37 233 37 211 104 58 126 120 195 232 155 225 112 90 230 262 35 9 117 89 39 
+41 41 63 147 13 278 216 283 35 75 82 261 109 142 257 14 267 185 105 47 95 229 
+71 252 15 171 255 99 144 65 18 255 228 60 199 40 30 10 172 159 33 138 162 139 
+44 125 36 244 68 102 228 38 115 174 52 72 241 271 280 131 119 4 162 161 128 142 
+14 182 286 141 268 45 158 22 85 187 285 86 198 51 61 188 9 139 173 192 19 266 
+130 35 53 285 108 131 204 39 126 227 27 213 199 62 114 163 150 97 100 26 202 
+146 87 124 205 72 263 68 146 109 57 71 50 201 135 34 149 215 114 185 83 250 78 
+251 133 34 127 131 248 207 9 183 190 211 262 142 279 98 133 163 43 265 270 269 
+78 8 150 204 83 7 246 270 89 197 125 194 41 85 80 166 256 154 214 210 115 89 17 
+108 175 85 209 82 103 176 276 279 76 49 10 65 40 52 94 38 137 258 69 50 179 202 
+168 171 277 183 10 43 243 186 116 100 70 83 29 43 67 135 56 82 81 92 123 14 2 
+118 258 25 33 160 246 5 22 63 103 132 108 260 120 173 148 2 247 38 159 55 222 
+28 117 269 56 211 284 226 145 76 71 230 218 18 277 25 213 177 265 248 185 212 
+30 212 273 195 254 239 91 90 28 10 150 75 167 160 224 208 156 85 165 65 220 220 
+113 281 13 256 132 130 57 137 151 86 69 135 78 166 234 70 61 232 177 22 129 68 
+168 42 74 49 275 268 174 74 156 107 249 218 198 158 44 169 53 263 24 265 226 
+101 59 52 274 55 20 214 81 48 242 282 46 106 260 145 ^
+614 1 83 280 22 20 105 271 15 58 136 269 100 224 10 182 19 68 130 17 94 240 256 
+225 156 127 44 82 172 96 105 53 89 134 65 107 257 212 101 152 188 124 92 107 77 
+175 287 43 45 190 98 141 157 235 259 127 224 119 275 205 248 276 83 100 115 206 
+285 128 211 64 11 60 1 66 253 202 237 245 194 108 5 64 229 116 84 267 256 45 
+249 24 224 228 238 102 139 3 149 106 149 286 56 100 165 243 99 237 65 157 5 26 
+210 6 122 118 217 27 17 203 44 153 116 13 193 50 116 122 286 236 7 268 63 242 
+171 59 123 214 125 238 52 102 30 40 252 215 3 220 50 66 215 183 127 153 45 69 
+117 121 119 95 9 145 167 229 166 121 81 76 188 53 18 190 148 178 260 55 113 61 
+218 85 195 145 276 192 63 12 97 142 194 217 98 250 120 132 150 273 1 125 20 285 
+19 118 37 120 203 94 60 219 122 47 273 110 88 206 176 165 25 43 154 283 284 32 
+14 12 265 161 15 179 117 138 75 260 164 76 247 109 101 261 151 21 272 253 143 
+181 32 123 105 162 52 31 245 123 34 218 135 232 248 96 46 286 6 63 62 134 245 
+14 71 32 244 86 182 90 12 47 105 91 108 244 27 126 7 230 44 262 79 199 84 196 
+23 128 31 27 197 240 17 262 259 236 187 16 166 62 25 282 117 180 175 178 80 18 
+10 241 75 151 201 179 67 252 35 255 117 71 82 281 189 2 233 235 41 71 141 48 
+272 73 236 78 53 269 171 168 86 111 16 95 118 108 64 120 23 187 87 110 268 243 
+279 274 168 266 148 119 204 261 42 58 86 73 127 115 26 89 25 102 80 77 66 35 
+146 24 44 191 135 123 285 199 155 140 99 57 28 54 185 42 276 12 156 198 118 288 
+101 223 132 41 180 104 234 163 219 13 84 87 219 231 140 170 1 234 272 182 199 
+264 233 126 237 174 250 191 206 67 72 128 152 8 87 278 287 223 241 4 77 284 91 
+229 225 47 164 147 191 26 30 99 19 9 74 93 23 78 283 213 88 97 213 268 4 27 88 
+277 120 82 113 170 181 271 86 2 53 198 227 251 287 114 278 107 186 138 184 223 
+61 97 104 175 107 6 231 81 114 207 163 110 50 187 196 73 165 134 136 51 174 11 
+98 20 176 56 221 146 263 137 88 26 139 62 205 189 220 29 112 74 273 60 51 103 
+67 22 91 49 188 233 55 4 257 32 64 49 79 270 158 113 111 255 58 15 288 210 186 
+29 221 37 170 240 197 169 73 56 41 239 160 28 234 92 145 96 155 90 192 243 208 
+200 251 48 21 92 216 40 72 178 189 111 196 132 221 217 207 54 17 23 7 50 7 159 
+100 56 280 202 57 208 91 288 151 130 235 150 34 38 228 129 139 242 112 226 ^
+619 0 38 141 250 104 37 31 159 207 19 175 92 201 274 96 31 230 28 205 104 52 
+126 114 192 229 152 225 103 90 230 262 26 108 86 39 32 35 60 147 10 278 216 277 
+35 75 79 255 100 136 254 5 267 185 99 41 95 226 71 249 9 168 252 90 144 56 12 
+249 228 57 193 34 21 4 172 153 30 135 159 136 35 116 36 241 59 93 225 32 106 
+171 43 66 238 268 280 131 110 1 162 161 122 142 14 179 283 141 265 36 155 16 79 
+184 279 77 198 45 52 182 3 133 173 192 10 263 121 32 50 282 102 122 198 30 120 
+227 18 213 196 59 108 157 150 91 91 20 199 140 84 124 199 69 263 65 143 109 48 
+62 47 201 126 28 149 215 111 182 74 244 69 248 133 25 124 128 248 204 9 183 184 
+208 256 139 279 92 130 163 37 265 270 266 75 8 144 204 80 4 243 264 89 191 119 
+188 38 85 71 163 256 154 211 210 115 83 14 108 172 82 209 76 103 176 273 276 67 
+43 10 59 37 46 91 35 131 258 69 44 176 202 165 171 277 177 7 34 240 183 113 97 
+70 83 29 40 67 129 53 73 78 89 120 8 2 109 252 19 33 160 246 289 13 54 97 126 
+99 260 111 167 142 289 247 38 156 55 222 22 114 263 50 211 281 226 142 70 68 
+224 212 15 274 25 210 171 262 245 179 212 30 206 270 195 254 239 88 81 28 1 147 
+66 167 157 221 202 150 76 159 65 214 220 107 281 7 253 129 124 57 137 145 80 60 
+132 78 160 231 67 58 232 177 22 129 68 168 33 74 40 275 262 174 68 153 101 246 
+218 192 158 41 166 47 257 15 259 220 92 59 52 268 46 20 214 72 39 236 282 46 
+106 257 249 80 279 21 19 104 271 15 55 136 269 100 222 7 182 18 65 128 14 93 
+240 254 224 156 126 43 81 170 96 102 51 87 134 64 104 256 210 100 151 186 123 
+89 105 76 174 287 42 42 190 95 140 155 235 258 125 223 117 273 205 246 274 81 
+99 112 206 285 127 209 61 8 58 288 66 253 200 235 243 193 105 5 63 228 113 82 
+265 255 44 247 23 224 227 237 102 137 3 148 105 147 285 56 98 165 242 98 236 63 
+157 2 23 209 5 119 117 217 26 15 203 41 151 115 12 193 49 116 122 284 236 7 268 
+61 242 169 57 122 213 125 238 49 101 27 39 251 214 1 218 50 63 213 181 127 153 
+45 67 114 121 118 93 6 143 165 227 166 118 78 74 188 53 17 189 148 176 258 54 
+112 58 217 82 194 144 275 191 63 9 97 141 194 215 96 250 119 132 149 271 123 18 
+284 17 118 37 117 202 94 60 218 121 47 272 110 87 205 175 163 22 43 152 281 282 
+31 11 12 264 160 12 178 117 288 137 74 259 164 76 245 108 101 261 150 20 270 
+251 143 180 264 ^
+639 0 117 99 159 49 31 245 123 31 212 135 226 245 90 43 286 289 60 62 131 242 
+11 65 23 244 80 176 84 6 38 105 91 102 238 27 123 290 224 38 259 79 199 84 193 
+14 128 25 21 191 237 17 256 259 233 187 10 160 59 19 276 114 174 169 175 74 18 
+7 235 69 145 198 179 58 252 32 255 111 62 82 278 183 285 230 229 32 68 135 39 
+269 67 230 75 44 263 168 165 86 108 16 92 112 105 58 114 20 181 78 107 265 237 
+276 268 162 266 142 119 201 258 36 52 77 64 118 109 26 80 22 96 80 71 60 29 143 
+24 44 191 132 114 279 193 152 140 99 54 25 54 179 42 276 9 150 192 109 285 92 
+217 129 35 180 101 228 160 213 7 81 81 219 231 134 167 1 231 272 179 196 264 
+227 117 237 171 244 185 200 61 72 119 152 2 87 272 284 220 241 1 77 284 82 229 
+219 44 158 144 188 20 27 90 10 6 71 93 17 69 283 210 82 91 207 262 4 18 79 271 
+120 73 113 164 181 265 83 288 50 195 221 251 281 108 275 104 186 138 184 223 61 
+88 95 175 107 6 225 81 114 207 157 101 41 184 190 73 162 128 130 45 168 11 98 
+11 170 47 221 146 257 131 88 23 139 56 199 189 217 283 23 106 68 273 51 51 100 
+64 13 85 49 185 233 49 290 257 26 64 46 73 267 152 107 111 249 58 9 288 204 183 
+26 218 34 170 234 197 169 70 50 41 233 154 22 234 92 145 93 155 81 186 243 208 
+200 248 48 21 86 213 40 69 178 186 105 196 126 215 214 204 45 14 23 1 44 4 156 
+91 53 274 199 51 205 88 282 151 130 232 144 34 32 222 123 136 236 112 34 137 
+246 100 31 25 159 203 19 171 90 197 274 94 27 228 22 201 104 48 126 110 190 227 
+150 225 97 90 230 262 20 286 102 84 39 26 31 58 147 8 278 216 273 35 75 77 251 
+94 132 252 291 267 185 95 37 95 224 71 247 5 166 250 84 144 50 8 245 228 55 189 
+30 15 172 149 28 133 157 134 29 110 36 239 53 87 223 28 100 169 37 62 236 266 
+280 131 104 291 162 161 118 142 14 177 281 141 263 30 153 12 75 182 275 71 198 
+41 46 178 291 129 173 192 4 261 115 30 48 280 98 116 194 24 116 227 12 213 194 
+57 104 153 150 87 85 16 197 136 82 124 195 67 263 63 141 109 42 56 45 201 120 
+24 149 215 109 180 68 240 63 246 133 19 122 126 248 202 9 183 180 206 252 137 
+279 88 128 163 33 265 270 264 73 8 140 204 78 2 241 260 89 187 115 184 36 85 65 
+161 256 154 209 210 115 79 12 108 170 80 209 72 103 176 271 274 61 39 10 55 35 
+42 89 33 127 258 69 40 174 202 163 171 277 173 5 28 238 181 111 95 70 83 29 38 
+67 125 51 67 76 87 118 4 2 103 248 15 33 160 246 287 7 48 93 283 ^
+611 0 87 260 99 159 134 289 247 38 152 55 222 14 110 255 42 211 277 226 138 62 
+64 216 204 11 270 25 206 163 258 241 171 212 30 198 266 195 254 239 84 69 28 
+283 143 54 167 153 217 194 142 64 151 65 206 220 99 281 293 249 125 116 57 137 
+137 72 48 128 78 152 227 63 54 232 177 22 129 68 168 21 74 28 275 254 174 60 
+149 93 242 218 184 158 37 162 39 249 3 251 212 80 59 52 260 34 20 214 60 27 228 
+282 46 106 253 249 68 275 17 15 100 271 15 43 136 269 100 214 289 182 14 53 120 
+2 89 240 246 220 156 122 39 77 162 96 90 43 79 134 60 92 252 202 96 147 178 119 
+77 97 72 170 287 38 30 190 83 136 147 235 254 117 219 109 265 205 238 266 73 95 
+100 206 285 123 201 49 290 50 280 66 253 192 227 235 189 93 5 59 224 101 74 257 
+251 40 239 19 224 223 233 102 129 3 144 101 139 281 56 90 165 238 94 232 55 157 
+284 11 205 1 107 113 217 22 7 203 29 143 111 8 193 45 116 122 276 236 7 268 53 
+242 161 49 118 209 125 238 37 97 15 35 247 210 287 210 50 51 205 173 127 153 45 
+59 102 121 114 85 288 135 157 219 166 106 66 66 188 53 13 185 148 168 250 50 
+108 46 213 70 190 140 271 187 63 291 97 137 194 207 88 250 115 132 145 263 290 
+115 10 280 9 118 37 105 198 94 60 214 117 47 268 110 83 201 171 155 10 43 144 
+273 274 27 293 12 260 156 174 117 284 133 70 255 164 76 237 104 101 261 146 16 
+262 243 143 176 32 113 95 157 47 31 245 123 29 208 135 222 243 86 41 286 285 58 
+62 129 240 9 61 17 244 76 172 80 2 32 105 91 98 234 27 121 286 220 34 257 79 
+199 84 191 8 128 21 17 187 235 17 252 259 231 187 6 156 57 15 272 112 170 165 
+173 70 18 5 231 65 141 196 179 52 252 30 255 107 56 82 276 179 281 228 225 26 
+66 131 33 267 63 226 73 38 259 166 163 86 106 16 90 108 103 54 110 18 177 72 
+105 263 233 274 264 158 266 138 119 199 256 32 48 71 58 112 105 26 74 20 92 80 
+67 56 25 141 24 44 191 130 108 275 189 150 140 99 52 23 54 175 42 276 7 146 188 
+103 283 86 213 127 31 180 99 224 158 209 3 79 77 219 231 130 165 1 229 272 177 
+194 264 223 111 237 169 240 181 196 57 72 113 152 292 87 268 282 218 241 293 77 
+284 76 229 215 42 154 142 186 16 25 84 4 4 69 93 13 63 283 208 78 87 203 258 4 
+12 73 267 120 67 113 160 181 261 81 286 48 193 217 251 277 104 273 102 186 138 
+184 223 61 82 89 175 107 6 221 81 114 207 153 95 35 182 186 73 275 ^
+634 0 120 122 37 160 11 98 295 162 35 221 146 249 123 88 19 139 48 191 189 213 
+275 15 98 60 273 39 51 96 60 1 77 49 181 233 41 286 257 18 64 42 65 263 144 99 
+111 241 58 1 288 196 179 22 214 30 170 226 197 169 66 42 41 225 146 14 234 92 
+145 89 155 69 178 243 208 200 244 48 21 78 209 40 65 178 182 97 196 118 207 210 
+200 33 10 23 289 36 152 79 49 266 195 43 201 84 274 151 130 228 136 34 24 214 
+115 132 228 112 292 26 129 238 92 19 13 159 195 19 163 86 189 274 90 19 224 10 
+193 104 40 126 102 186 223 146 225 85 90 230 262 8 278 90 80 39 14 23 54 147 4 
+278 216 265 35 75 73 243 82 124 248 283 267 185 87 29 95 220 71 243 293 162 246 
+72 144 38 237 228 51 181 22 3 288 172 141 24 129 153 130 17 98 36 235 41 75 219 
+20 88 165 25 54 232 262 280 131 92 291 162 161 110 142 14 173 277 141 259 18 
+149 4 67 178 267 59 198 33 34 170 287 121 173 192 288 257 103 26 44 276 90 104 
+186 12 108 227 213 190 53 96 145 150 79 73 8 193 128 78 124 187 63 263 59 137 
+109 30 44 41 201 108 16 149 215 105 176 56 232 51 242 133 7 118 122 248 198 9 
+183 172 202 244 133 279 80 124 163 25 265 270 260 69 8 132 204 74 294 237 252 
+89 179 107 176 32 85 53 157 256 154 205 210 115 71 8 108 166 76 209 64 103 176 
+267 270 49 31 10 47 31 34 85 29 119 258 69 32 170 202 159 171 277 165 1 16 234 
+177 107 91 70 83 29 34 67 117 47 55 72 83 114 292 2 91 240 7 33 160 246 283 291 
+36 85 114 81 260 93 155 130 289 247 38 150 55 222 10 108 251 38 211 275 226 136 
+58 62 212 200 9 268 25 204 159 256 239 167 212 30 194 264 195 254 239 82 63 28 
+279 141 48 167 151 215 190 138 58 147 65 202 220 95 281 291 247 123 112 57 137 
+133 68 42 126 78 148 225 61 52 232 177 22 129 68 168 15 74 22 275 250 174 56 
+147 89 240 218 180 158 35 160 35 245 293 247 208 74 59 52 256 28 20 214 54 21 
+224 282 46 106 251 249 62 273 15 13 98 271 15 37 136 269 100 210 285 182 12 47 
+116 292 87 240 242 218 156 120 37 75 158 96 84 39 75 134 58 86 250 198 94 145 
+174 117 71 93 70 168 287 36 24 190 77 134 143 235 252 113 217 105 261 205 234 
+262 69 93 94 206 285 121 197 43 286 46 276 66 253 188 223 231 187 87 5 57 222 
+95 70 253 249 38 235 17 224 221 231 102 125 3 142 99 135 279 56 86 165 236 92 
+230 51 157 280 5 203 295 101 111 217 20 3 203 23 139 109 6 193 43 116 122 272 
+236 7 268 49 242 157 45 116 207 125 238 31 95 9 33 245 220 ^
+638 0 284 204 50 42 199 167 127 153 45 53 93 121 111 79 282 129 151 213 166 97 
+57 60 188 53 10 182 148 162 244 47 105 37 210 61 187 137 268 184 63 285 97 134 
+194 201 82 250 112 132 142 257 290 109 4 277 3 118 37 96 195 94 60 211 114 47 
+265 110 80 198 168 149 1 43 138 267 268 24 287 12 257 153 288 171 117 281 130 
+67 252 164 76 231 101 101 261 143 13 256 237 143 173 32 107 89 154 44 31 245 
+123 26 202 135 216 240 80 38 286 279 55 62 126 237 6 55 8 244 70 166 74 293 23 
+105 91 92 228 27 118 280 214 28 254 79 199 84 188 296 128 15 11 181 232 17 246 
+259 228 187 150 54 9 266 109 164 159 170 64 18 2 225 59 135 193 179 43 252 27 
+255 101 47 82 273 173 275 225 219 17 63 125 24 264 57 220 70 29 253 163 160 86 
+103 16 87 102 100 48 104 15 171 63 102 260 227 271 258 152 266 132 119 196 253 
+26 42 62 49 103 99 26 65 17 86 80 61 50 19 138 24 44 191 127 99 269 183 147 140 
+99 49 20 54 169 42 276 4 140 182 94 280 77 207 124 25 180 96 218 155 203 294 76 
+71 219 231 124 162 1 226 272 174 191 264 217 102 237 166 234 175 190 51 72 104 
+152 289 87 262 279 215 241 293 77 284 67 229 209 39 148 139 183 10 22 75 292 1 
+66 93 7 54 283 205 72 81 197 252 4 3 64 261 120 58 113 154 181 255 78 283 45 
+190 211 251 271 98 270 99 186 138 184 223 61 73 80 175 107 6 215 81 114 207 147 
+86 26 179 180 73 157 118 120 35 158 11 98 293 160 32 221 146 247 121 88 18 139 
+46 189 189 212 273 13 96 58 273 36 51 95 59 295 75 49 180 233 39 285 257 16 64 
+41 63 262 142 97 111 239 58 296 288 194 178 21 213 29 170 224 197 169 65 40 41 
+223 144 12 234 92 145 88 155 66 176 243 208 200 243 48 21 76 208 40 64 178 181 
+95 196 116 205 209 199 30 9 23 288 34 296 151 76 48 264 194 41 200 83 272 151 
+130 227 134 34 22 212 113 131 226 112 292 24 127 236 90 16 10 159 193 19 161 85 
+187 274 89 17 223 7 191 104 38 126 100 185 222 145 225 82 90 230 262 5 276 87 
+79 39 11 21 53 147 3 278 216 263 35 75 72 241 79 122 247 281 267 185 85 27 95 
+219 71 242 292 161 245 69 144 35 295 235 228 50 179 20 287 172 139 23 128 152 
+129 14 95 36 234 38 72 218 18 85 164 22 52 231 261 280 131 89 291 162 161 108 
+142 14 172 276 141 258 15 148 2 65 177 265 56 198 31 31 168 286 119 173 192 286 
+256 100 25 43 275 88 101 184 9 106 227 294 213 189 52 94 143 150 77 70 6 192 
+126 77 124 185 62 263 58 136 109 27 41 40 201 105 14 149 215 104 175 53 230 219 
+^
+635 1 239 133 297 115 119 248 195 9 183 166 199 238 130 279 74 121 163 19 265 
+270 257 66 8 126 204 71 294 234 246 89 173 101 170 29 85 44 154 256 154 202 210 
+115 65 5 108 163 73 209 58 103 176 264 267 40 25 10 41 28 28 82 26 113 258 69 
+26 167 202 156 171 277 159 297 7 231 174 104 88 70 83 29 31 67 111 44 46 69 80 
+111 289 2 82 234 1 33 160 246 280 285 27 79 108 72 260 84 149 124 289 247 38 
+147 55 222 4 105 245 32 211 272 226 133 52 59 206 194 6 265 25 201 153 253 236 
+161 212 30 188 261 195 254 239 79 54 28 273 138 39 167 148 212 184 132 49 141 
+65 196 220 89 281 288 244 120 106 57 137 127 62 33 123 78 142 222 58 49 232 177 
+22 129 68 168 6 74 13 275 244 174 50 144 83 237 218 174 158 32 157 29 239 287 
+241 202 65 59 52 250 19 20 214 45 12 218 282 46 106 248 249 53 270 12 10 95 271 
+15 28 136 269 100 204 279 182 9 38 110 286 84 240 236 215 156 117 34 72 152 96 
+75 33 69 134 55 77 247 192 91 142 168 114 62 87 67 165 287 33 15 190 68 131 137 
+235 249 107 214 99 255 205 228 256 63 90 85 206 285 118 191 34 280 40 270 66 
+253 182 217 225 184 78 5 54 219 86 64 247 246 35 229 14 224 218 228 102 119 3 
+139 96 129 276 56 80 165 233 89 227 45 157 274 295 200 295 92 108 217 17 296 
+203 14 133 106 3 193 40 116 122 266 236 7 268 43 242 151 39 113 204 125 238 22 
+92 30 242 205 282 200 50 36 195 163 127 153 45 49 87 121 109 75 278 125 147 209 
+166 91 51 56 188 53 8 180 148 158 240 45 103 31 208 55 185 135 266 182 63 281 
+97 132 194 197 78 250 110 132 140 253 290 105 275 298 118 37 90 193 94 60 209 
+112 47 263 110 78 196 166 145 294 43 134 263 264 22 283 12 255 151 284 169 117 
+279 128 65 250 164 76 227 99 101 261 141 11 252 233 143 171 32 103 85 152 42 31 
+245 123 24 198 135 212 238 76 36 286 275 53 62 124 235 4 51 2 244 66 162 70 291 
+17 105 91 88 224 27 116 276 210 24 252 79 199 84 186 292 128 11 7 177 230 17 
+242 259 226 187 295 146 52 5 262 107 160 155 168 60 18 221 55 131 191 179 37 
+252 25 255 97 41 82 271 169 271 223 215 11 61 121 18 262 53 216 68 23 249 161 
+158 86 101 16 85 98 98 44 100 13 167 57 100 258 223 269 254 148 266 128 119 194 
+251 22 38 56 43 97 95 26 59 15 82 80 57 46 15 136 24 44 191 125 93 265 179 145 
+140 99 47 18 54 165 42 276 2 136 178 88 278 71 203 122 21 180 94 214 153 199 
+292 74 67 219 231 120 160 1 224 272 172 189 264 213 96 237 164 230 171 186 153 ^
+638 1 72 92 152 285 87 254 275 211 241 293 77 284 55 229 201 35 140 135 179 2 
+18 63 284 298 62 93 300 42 283 201 64 73 189 244 4 292 52 253 120 46 113 146 
+181 247 74 279 41 186 203 251 263 90 266 95 186 138 184 223 61 61 68 175 107 6 
+207 81 114 207 139 74 14 175 172 73 153 110 112 27 150 11 98 285 152 20 221 146 
+239 113 88 14 139 38 181 189 208 265 5 88 50 273 24 51 91 55 287 67 49 176 233 
+31 281 257 8 64 37 55 258 134 89 111 231 58 292 288 186 174 17 209 25 170 216 
+197 169 61 32 41 215 136 4 234 92 145 84 155 54 168 243 208 200 239 48 21 68 
+204 40 60 178 177 87 196 108 197 205 195 18 5 23 284 26 296 147 64 44 256 190 
+33 196 79 264 151 130 223 126 34 14 204 105 127 218 112 292 16 119 228 82 4 299 
+159 185 19 153 81 179 274 85 9 219 296 183 104 30 126 92 181 218 141 225 70 90 
+230 262 294 268 75 75 39 300 13 49 147 300 278 216 255 35 75 68 233 67 114 243 
+273 267 185 77 19 95 215 71 238 288 157 241 57 144 23 291 227 228 46 171 12 289 
+283 172 131 19 124 148 125 2 83 36 230 26 60 214 10 73 160 10 44 227 257 280 
+131 77 291 162 161 100 142 14 168 272 141 254 3 144 295 57 173 257 44 198 23 19 
+160 282 111 173 192 278 252 88 21 39 271 80 89 176 298 98 227 286 213 185 48 86 
+135 150 69 58 299 188 118 73 124 177 58 263 54 132 109 15 29 36 201 93 6 149 
+215 100 171 41 222 36 237 133 293 113 117 248 193 9 183 162 197 234 128 279 70 
+119 163 15 265 270 255 64 8 122 204 69 294 232 242 89 169 97 166 27 85 38 152 
+256 154 200 210 115 61 3 108 161 71 209 54 103 176 262 265 34 21 10 37 26 24 80 
+24 109 258 69 22 165 202 154 171 277 155 297 1 229 172 102 86 70 83 29 29 67 
+107 42 40 67 78 109 287 2 76 230 298 33 160 246 278 281 21 75 104 66 260 78 145 
+120 289 247 38 145 55 222 103 241 28 211 270 226 131 48 57 202 190 4 263 25 199 
+149 251 234 157 212 30 184 259 195 254 239 77 48 28 269 136 33 167 146 210 180 
+128 43 137 65 192 220 85 281 286 242 118 102 57 137 123 58 27 121 78 138 220 56 
+47 232 177 22 129 68 168 74 7 275 240 174 46 142 79 235 218 170 158 30 155 25 
+235 283 237 198 59 59 52 246 13 20 214 39 6 214 282 46 106 246 249 47 268 10 8 
+93 271 15 22 136 269 100 200 275 182 7 32 106 282 82 240 232 213 156 115 32 70 
+148 96 69 29 65 134 53 71 245 188 89 140 164 112 56 83 65 163 287 31 9 190 62 
+129 133 235 247 103 212 95 251 205 224 252 59 88 79 206 285 116 187 28 276 263 ^
+640 0 264 66 253 176 211 219 181 69 5 51 216 77 58 241 243 32 223 11 224 215 
+225 102 113 3 136 93 123 273 56 74 165 230 86 224 39 157 268 289 197 295 83 105 
+217 14 293 203 5 127 103 193 37 116 122 260 236 7 268 37 242 145 33 110 201 125 
+238 13 89 293 27 239 202 279 194 50 27 189 157 127 153 45 43 78 121 106 69 272 
+119 141 203 166 82 42 50 188 53 5 177 148 152 234 42 100 22 205 46 182 132 263 
+179 63 275 97 129 194 191 72 250 107 132 137 247 290 99 296 272 295 118 37 81 
+190 94 60 206 109 47 260 110 75 193 163 139 288 43 128 257 258 19 277 12 252 
+148 278 166 117 276 125 62 247 164 76 221 96 101 261 138 8 246 227 143 168 32 
+97 79 149 39 31 245 123 21 192 135 206 235 70 33 286 269 50 62 121 232 1 45 295 
+244 60 156 64 288 8 105 91 82 218 27 113 270 204 18 249 79 199 84 183 286 128 5 
+1 171 227 17 236 259 223 187 292 140 49 301 256 104 154 149 165 54 18 299 215 
+49 125 188 179 28 252 22 255 91 32 82 268 163 265 220 209 2 58 115 9 259 47 210 
+65 14 243 158 155 86 98 16 82 92 95 38 94 10 161 48 97 255 217 266 248 142 266 
+122 119 191 248 16 32 47 34 88 89 26 50 12 76 80 51 40 9 133 24 44 191 122 84 
+259 173 142 140 99 44 15 54 159 42 276 301 130 172 79 275 62 197 119 15 180 91 
+208 150 193 289 71 61 219 231 114 157 1 221 272 169 186 264 207 87 237 161 224 
+165 180 41 72 89 152 284 87 252 274 210 241 293 77 284 52 229 199 34 138 134 
+178 17 60 282 298 61 93 299 39 283 200 62 71 187 242 4 290 49 251 120 43 113 
+144 181 245 73 278 40 185 201 251 261 88 265 94 186 138 184 223 61 58 65 175 
+107 6 205 81 114 207 137 71 11 174 170 73 152 108 110 25 148 11 98 283 150 17 
+221 146 237 111 88 13 139 36 179 189 207 263 3 86 48 273 21 51 90 54 285 65 49 
+175 233 29 280 257 6 64 36 53 257 132 87 111 229 58 291 288 184 173 16 208 24 
+170 214 197 169 60 30 41 213 134 2 234 92 145 83 155 51 166 243 208 200 238 48 
+21 66 203 40 59 178 176 85 196 106 195 204 194 15 4 23 283 24 296 146 61 43 254 
+189 31 195 78 262 151 130 222 124 34 12 202 103 126 216 112 292 14 117 226 80 1 
+297 159 183 19 151 80 177 274 84 7 218 294 181 104 28 126 90 180 217 140 225 67 
+90 230 262 292 266 72 74 39 298 11 48 147 300 278 216 253 35 75 67 231 64 112 
+242 271 267 185 75 17 95 214 71 237 287 156 240 54 144 20 290 225 228 45 169 10 
+287 282 172 129 18 123 147 124 301 80 36 229 23 57 213 8 70 159 7 42 226 256 
+280 131 213 ^
+640 0 291 162 161 94 142 14 165 269 141 251 298 141 292 51 170 251 35 198 17 10 
+154 279 105 173 192 272 249 79 18 36 268 74 80 170 292 92 227 280 213 182 45 80 
+129 150 63 49 296 185 112 70 124 171 55 263 51 129 109 6 20 33 201 84 149 215 
+97 168 32 216 27 234 133 287 110 114 248 190 9 183 156 194 228 125 279 64 116 
+163 9 265 270 252 61 8 116 204 66 294 229 236 89 163 91 160 24 85 29 149 256 
+154 197 210 115 55 108 158 68 209 48 103 176 259 262 25 15 10 31 23 18 77 21 
+103 258 69 16 162 202 151 171 277 149 297 296 226 169 99 83 70 83 29 26 67 101 
+39 31 64 75 106 284 2 67 224 295 33 160 246 275 275 12 69 98 57 260 69 139 114 
+289 247 38 142 55 222 298 100 235 22 211 267 226 128 42 54 196 184 1 260 25 196 
+143 248 231 151 212 30 178 256 195 254 239 74 39 28 263 133 24 167 143 207 174 
+122 34 131 65 186 220 79 281 283 239 115 96 57 137 117 52 18 118 78 132 217 53 
+44 232 177 22 129 68 168 295 74 302 275 234 174 40 139 73 232 218 164 158 27 
+152 19 229 277 231 192 50 59 52 240 4 20 214 30 301 208 282 46 106 243 249 38 
+265 7 5 90 271 15 13 136 269 100 194 269 182 4 23 100 276 79 240 226 210 156 
+112 29 67 142 96 60 23 59 134 50 62 242 182 86 137 158 109 47 77 62 160 287 28 
+190 53 126 127 235 244 97 209 89 245 205 218 246 53 85 70 206 285 113 181 19 
+270 30 260 66 253 172 207 215 179 63 5 49 214 71 54 237 241 30 219 9 224 213 
+223 102 109 3 134 91 119 271 56 70 165 228 84 222 35 157 264 285 195 295 77 103 
+217 12 291 203 303 123 101 302 193 35 116 122 256 236 7 268 33 242 141 29 108 
+199 125 238 7 87 289 25 237 200 277 190 50 21 185 153 127 153 45 39 72 121 104 
+65 268 115 137 199 166 76 36 46 188 53 3 175 148 148 230 40 98 16 203 40 180 
+130 261 177 63 271 97 127 194 187 68 250 105 132 135 243 290 95 294 270 293 118 
+37 75 188 94 60 204 107 47 258 110 73 191 161 135 284 43 124 253 254 17 273 12 
+250 146 274 164 117 274 123 60 245 164 76 217 94 101 261 136 6 242 223 143 166 
+32 93 75 147 37 31 245 123 19 188 135 202 233 66 31 286 265 48 62 119 230 303 
+41 291 244 56 152 60 286 2 105 91 78 214 27 111 266 200 14 247 79 199 84 181 
+282 128 1 301 167 225 17 232 259 221 187 290 136 47 299 252 102 150 145 163 50 
+18 299 211 45 121 186 179 22 252 20 255 87 26 82 266 159 261 218 205 300 56 111 
+3 257 43 206 63 8 239 156 153 86 96 16 80 88 93 34 90 8 157 42 95 253 213 264 
+244 138 266 118 119 189 246 79 ^
+650 0 24 35 22 76 81 26 38 8 68 80 43 32 1 129 24 44 191 118 72 251 165 138 140 
+99 40 11 54 151 42 276 301 122 164 67 271 50 189 115 7 180 87 200 146 185 285 
+67 53 219 231 106 153 1 217 272 165 182 264 199 75 237 157 216 157 172 33 72 77 
+152 280 87 244 270 206 241 293 77 284 40 229 191 30 130 130 174 298 13 48 274 
+298 57 93 295 27 283 196 54 63 179 234 4 282 37 243 120 31 113 136 181 237 69 
+274 36 181 193 251 253 80 261 90 186 138 184 223 61 46 53 175 107 6 197 81 114 
+207 129 59 305 170 162 73 148 100 102 17 140 11 98 275 142 5 221 146 229 103 88 
+9 139 28 171 189 203 255 301 78 40 273 9 51 86 50 277 57 49 171 233 21 276 257 
+304 64 32 45 253 124 79 111 221 58 287 288 176 169 12 204 20 170 206 197 169 56 
+22 41 205 126 300 234 92 145 79 155 39 158 243 208 200 234 48 21 58 199 40 55 
+178 172 77 196 98 187 200 190 3 23 279 16 296 142 49 39 246 185 23 191 74 254 
+151 130 218 116 34 4 194 95 122 208 112 292 6 109 218 72 295 289 159 175 19 143 
+76 169 274 80 305 214 286 173 104 20 126 82 176 213 136 225 55 90 230 262 284 
+258 60 70 39 290 3 44 147 300 278 216 245 35 75 63 223 52 104 238 263 267 185 
+67 9 95 210 71 233 283 152 236 42 144 8 286 217 228 41 161 2 279 278 172 121 14 
+119 143 120 293 68 36 225 11 45 209 58 155 301 34 222 252 280 131 62 291 162 
+161 90 142 14 163 267 141 249 294 139 290 47 168 247 29 198 13 4 150 277 101 
+173 192 268 247 73 16 34 266 70 74 166 288 88 227 276 213 180 43 76 125 150 59 
+43 294 183 108 68 124 167 53 263 49 127 109 14 31 201 78 302 149 215 95 166 26 
+212 21 232 133 283 108 112 248 188 9 183 152 192 224 123 279 60 114 163 5 265 
+270 250 59 8 112 204 64 294 227 232 89 159 87 156 22 85 23 147 256 154 195 210 
+115 51 304 108 156 66 209 44 103 176 257 260 19 11 10 27 21 14 75 19 99 258 69 
+12 160 202 149 171 277 145 297 292 224 167 97 81 70 83 29 24 67 97 37 25 62 73 
+104 282 2 61 220 293 33 160 246 273 271 6 65 94 51 260 63 135 110 289 247 38 
+140 55 222 296 98 231 18 211 265 226 126 38 52 192 180 305 258 25 194 139 246 
+229 147 212 30 174 254 195 254 239 72 33 28 259 131 18 167 141 205 170 118 28 
+127 65 182 220 75 281 281 237 113 92 57 137 113 48 12 116 78 128 215 51 42 232 
+177 22 129 68 168 291 74 298 275 230 174 36 137 69 230 218 160 158 25 150 15 
+225 273 227 188 44 59 52 236 304 20 214 24 297 204 282 46 106 241 249 32 263 5 
+3 88 271 15 7 136 269 100 190 265 182 2 17 96 283 ^
+649 0 76 240 220 207 156 109 26 64 136 96 51 17 53 134 47 53 239 176 83 134 152 
+106 38 71 59 157 287 25 298 190 44 123 121 235 241 91 206 83 239 205 212 240 47 
+82 61 206 285 110 175 10 264 24 254 66 253 166 201 209 176 54 5 46 211 62 48 
+231 238 27 213 6 224 210 220 102 103 3 131 88 113 268 56 64 165 225 81 219 29 
+157 258 279 192 295 68 100 217 9 288 203 297 117 98 302 193 32 116 122 250 236 
+7 268 27 242 135 23 105 196 125 238 305 84 283 22 234 197 274 184 50 12 179 147 
+127 153 45 33 63 121 101 59 262 109 131 193 166 67 27 40 188 53 172 148 142 224 
+37 95 7 200 31 177 127 258 174 63 265 97 124 194 181 62 250 102 132 132 237 290 
+89 291 267 290 118 37 66 185 94 60 201 104 47 255 110 70 188 158 129 278 43 118 
+247 248 14 267 12 247 143 268 161 117 271 120 57 242 164 76 211 91 101 261 133 
+3 236 217 143 163 32 87 69 144 34 31 245 123 16 182 135 196 230 60 28 286 259 
+45 62 116 227 303 35 285 244 50 146 54 283 300 105 91 72 208 27 108 260 194 8 
+244 79 199 84 178 276 128 302 298 161 222 17 226 259 218 187 287 130 44 296 246 
+99 144 139 160 44 18 299 205 39 115 183 179 13 252 17 255 81 17 82 263 153 255 
+215 199 294 53 105 301 254 37 200 60 306 233 153 150 86 93 16 77 82 90 28 84 5 
+151 33 92 250 207 261 238 132 266 112 119 186 243 6 22 32 19 73 79 26 35 7 66 
+80 41 30 306 128 24 44 191 117 69 249 163 137 140 99 39 10 54 149 42 276 301 
+120 162 64 270 47 187 114 5 180 86 198 145 183 284 66 51 219 231 104 152 1 216 
+272 164 181 264 197 72 237 156 214 155 170 31 72 74 152 279 87 242 269 205 241 
+293 77 284 37 229 189 29 128 129 173 297 12 45 272 298 56 93 294 24 283 195 52 
+61 177 232 4 280 34 241 120 28 113 134 181 235 68 273 35 180 191 251 251 78 260 
+89 186 138 184 223 61 43 50 175 107 6 195 81 114 207 127 56 303 169 160 73 147 
+98 100 15 138 11 98 273 140 2 221 146 227 101 88 8 139 26 169 189 202 253 300 
+76 38 273 6 51 85 49 275 55 49 170 233 19 275 257 303 64 31 43 252 122 77 111 
+219 58 286 288 174 168 11 203 19 170 204 197 169 55 20 41 203 124 299 234 92 
+145 78 155 36 156 243 208 200 233 48 21 56 198 40 54 178 171 75 196 96 185 199 
+189 306 23 278 14 296 141 46 38 244 184 21 190 73 252 151 130 217 114 34 2 192 
+93 121 206 112 292 4 107 216 70 293 287 159 173 19 141 75 167 274 79 304 213 
+284 171 104 18 126 80 175 212 135 225 52 90 230 262 282 256 57 69 39 288 1 43 
+147 300 278 216 243 35 75 62 221 49 102 237 261 267 140 ^
+649 1 61 3 95 207 71 230 280 149 233 33 144 308 283 211 228 38 155 305 273 275 
+172 115 11 116 140 117 287 59 36 222 2 36 206 303 49 152 295 28 219 249 280 131 
+53 291 162 161 84 142 14 160 264 141 246 288 136 287 41 165 241 20 198 7 304 
+144 274 95 173 192 262 244 64 13 31 263 64 65 160 282 82 227 270 213 177 40 70 
+119 150 53 34 291 180 102 65 124 161 50 263 46 124 109 300 5 28 201 69 299 149 
+215 92 163 17 206 12 229 133 277 105 109 248 185 9 183 146 189 218 120 279 54 
+111 163 308 265 270 247 56 8 106 204 61 294 224 226 89 153 81 150 19 85 14 144 
+256 154 192 210 115 45 304 108 153 63 209 38 103 176 254 257 10 5 10 21 18 8 72 
+16 93 258 69 6 157 202 146 171 277 139 297 286 221 164 94 78 70 83 29 21 67 91 
+34 16 59 70 101 279 2 52 214 290 33 160 246 270 265 306 59 88 42 260 54 129 104 
+289 247 38 137 55 222 293 95 225 12 211 262 226 123 32 49 186 174 305 255 25 
+191 133 243 226 141 212 30 168 251 195 254 239 69 24 28 253 128 9 167 138 202 
+164 112 19 121 65 176 220 69 281 278 234 110 86 57 137 107 42 3 113 78 122 212 
+48 39 232 177 22 129 68 168 285 74 292 275 224 174 30 134 63 227 218 154 158 22 
+147 9 219 267 221 182 35 59 52 230 298 20 214 15 291 198 282 46 106 238 249 23 
+260 2 85 271 15 307 136 269 100 184 259 182 308 8 90 266 74 240 216 205 156 107 
+24 62 132 96 45 13 49 134 45 47 237 172 81 132 148 104 32 67 57 155 287 23 294 
+190 38 121 117 235 239 87 204 79 235 205 208 236 43 80 55 206 285 108 171 4 260 
+20 250 66 253 162 197 205 174 48 5 44 209 56 44 227 236 25 209 4 224 208 218 
+102 99 3 129 86 109 266 56 60 165 223 79 217 25 157 254 275 190 295 62 98 217 7 
+286 203 293 113 96 302 193 30 116 122 246 236 7 268 23 242 131 19 103 194 125 
+238 301 82 279 20 232 195 272 180 50 6 175 143 127 153 45 29 57 121 99 55 258 
+105 127 189 166 61 21 36 188 53 307 170 148 138 220 35 93 1 198 25 175 125 256 
+172 63 261 97 122 194 177 58 250 100 132 130 233 290 85 289 265 288 118 37 60 
+183 94 60 199 102 47 253 110 68 186 156 125 274 43 114 243 244 12 263 12 245 
+141 264 159 117 269 118 55 240 164 76 207 89 101 261 131 1 232 213 143 161 32 
+83 65 142 32 31 245 123 14 178 135 192 228 56 26 286 255 43 62 114 225 303 31 
+281 244 46 142 50 281 296 105 91 68 204 27 106 256 190 4 242 79 199 84 176 272 
+128 300 296 157 220 17 222 259 216 187 285 126 42 294 242 97 140 135 158 40 18 
+299 201 35 111 181 179 7 252 15 255 77 11 82 261 149 251 69 ^
+655 0 191 286 49 97 293 250 29 192 56 298 225 149 146 86 89 16 73 74 86 20 76 1 
+143 21 88 246 199 257 230 124 266 104 119 182 239 309 14 20 7 61 71 26 23 3 58 
+80 33 22 302 124 24 44 191 113 57 241 155 133 140 99 35 6 54 141 42 276 301 112 
+154 52 266 35 179 110 308 180 82 190 141 175 280 62 43 219 231 96 148 1 212 272 
+160 177 264 189 60 237 152 206 147 162 23 72 62 152 275 87 234 265 201 241 293 
+77 284 25 229 181 25 120 125 169 293 8 33 264 298 52 93 290 12 283 191 44 53 
+169 224 4 272 22 233 120 16 113 126 181 227 64 269 31 176 183 251 243 70 256 85 
+186 138 184 223 61 31 38 175 107 6 187 81 114 207 119 44 295 165 152 73 143 90 
+92 7 130 11 98 265 132 301 221 146 219 93 88 4 139 18 161 189 198 245 296 68 30 
+273 305 51 81 45 267 47 49 166 233 11 271 257 299 64 27 35 248 114 69 111 211 
+58 282 288 166 164 7 199 15 170 196 197 169 51 12 41 195 116 295 234 92 145 74 
+155 24 148 243 208 200 229 48 21 48 194 40 50 178 167 67 196 88 177 195 185 299 
+306 23 274 6 296 137 34 34 236 180 13 186 69 244 151 130 213 106 34 305 184 85 
+117 198 112 292 307 99 208 62 285 279 159 165 19 133 71 159 274 75 300 209 276 
+163 104 10 126 72 171 208 131 225 40 90 230 262 274 248 45 65 39 280 304 39 147 
+300 278 216 235 35 75 58 213 37 94 233 253 267 185 57 310 95 205 71 228 278 147 
+231 27 144 304 281 207 228 36 151 303 269 273 172 111 9 114 138 115 283 53 36 
+220 307 30 204 301 43 150 291 24 217 247 280 131 47 291 162 161 80 142 14 158 
+262 141 244 284 134 285 37 163 237 14 198 3 300 140 272 91 173 192 258 242 58 
+11 29 261 60 59 156 278 78 227 266 213 175 38 66 115 150 49 28 289 178 98 63 
+124 157 48 263 44 122 109 296 310 26 201 63 297 149 215 90 161 11 202 6 227 133 
+273 103 107 248 183 9 183 142 187 214 118 279 50 109 163 306 265 270 245 54 8 
+102 204 59 294 222 222 89 149 77 146 17 85 8 142 256 154 190 210 115 41 304 108 
+151 61 209 34 103 176 252 255 4 1 10 17 16 4 70 14 89 258 69 2 155 202 144 171 
+277 135 297 282 219 162 92 76 70 83 29 19 67 87 32 10 57 68 99 277 2 46 210 288 
+33 160 246 268 261 302 55 84 36 260 48 125 100 289 247 38 135 55 222 291 93 221 
+8 211 260 226 121 28 47 182 170 305 253 25 189 129 241 224 137 212 30 164 249 
+195 254 239 67 18 28 249 126 3 167 136 200 160 108 13 117 65 172 220 65 281 276 
+232 108 82 57 137 103 38 308 111 78 118 210 46 37 232 177 22 129 68 168 281 74 
+288 275 220 174 26 132 59 225 218 150 158 20 145 5 215 263 100 ^
+661 1 176 26 59 52 224 292 20 214 6 285 192 282 46 106 235 249 14 257 311 309 
+82 271 15 301 136 269 100 178 253 182 308 311 84 260 71 240 210 202 156 104 21 
+59 126 96 36 7 43 134 42 38 234 166 78 129 142 101 23 61 54 152 287 20 288 190 
+29 118 111 235 236 81 201 73 229 205 202 230 37 77 46 206 285 105 165 307 254 
+14 244 66 253 156 191 199 171 39 5 41 206 47 38 221 233 22 203 1 224 205 215 
+102 93 3 126 83 103 263 56 54 165 220 76 214 19 157 248 269 187 295 53 95 217 4 
+283 203 287 107 93 302 193 27 116 122 240 236 7 268 17 242 125 13 100 191 125 
+238 295 79 273 17 229 192 269 174 50 309 169 137 127 153 45 23 48 121 96 49 252 
+99 121 183 166 52 12 30 188 53 307 167 148 132 214 32 90 304 195 16 172 122 253 
+169 63 255 97 119 194 171 52 250 97 132 127 227 290 79 286 262 285 118 37 51 
+180 94 60 196 99 47 250 110 65 183 153 119 268 43 108 237 238 9 257 12 242 138 
+258 156 117 266 115 52 237 164 76 201 86 101 261 128 310 226 207 143 158 32 77 
+59 139 29 31 245 123 11 172 135 186 225 50 23 286 249 40 62 111 222 303 25 275 
+244 40 136 44 278 290 105 91 62 198 27 103 250 184 310 239 79 199 84 173 266 
+128 297 293 151 217 17 216 259 213 187 282 120 39 291 236 94 134 129 155 34 18 
+299 195 29 105 178 179 310 252 12 255 71 2 82 258 143 245 210 189 284 48 95 291 
+249 27 190 55 296 223 148 145 86 88 16 72 72 85 18 74 141 18 87 245 197 256 228 
+122 266 102 119 181 238 308 12 17 4 58 69 26 20 2 56 80 31 20 301 123 24 44 191 
+112 54 239 153 132 140 99 34 5 54 139 42 276 301 110 152 49 265 32 177 109 307 
+180 81 188 140 173 279 61 41 219 231 94 147 1 211 272 159 176 264 187 57 237 
+151 204 145 160 21 72 59 152 274 87 232 264 200 241 293 77 284 22 229 179 24 
+118 124 168 292 7 30 262 298 51 93 289 9 283 190 42 51 167 222 4 270 19 231 120 
+13 113 124 181 225 63 268 30 175 181 251 241 68 255 84 186 138 184 223 61 28 35 
+175 107 6 185 81 114 207 117 41 293 164 150 73 142 88 90 5 128 11 98 263 130 
+299 221 146 217 91 88 3 139 16 159 189 197 243 295 66 28 273 303 51 80 44 265 
+45 49 165 233 9 270 257 298 64 26 33 247 112 67 111 209 58 281 288 164 163 6 
+198 14 170 194 197 169 50 10 41 193 114 294 234 92 145 73 155 21 146 243 208 
+200 228 48 21 46 193 40 49 178 166 65 196 86 175 194 184 297 306 23 273 4 296 
+136 31 33 234 179 11 185 68 242 151 130 212 104 34 304 182 83 116 196 112 292 
+306 97 206 60 283 277 159 163 19 131 70 157 274 74 299 208 274 161 104 8 126 70 
+170 207 130 225 37 90 230 194 ^
+643 0 268 242 36 62 39 274 301 36 147 300 278 216 229 35 75 55 207 28 88 230 
+247 267 185 51 307 95 202 71 225 275 144 228 18 144 298 278 201 228 33 145 300 
+263 270 172 105 6 111 135 112 277 44 36 217 301 21 201 298 34 147 285 18 214 
+244 280 131 38 291 162 161 74 142 14 155 259 141 241 278 131 282 31 160 231 5 
+198 311 294 134 269 85 173 192 252 239 49 8 26 258 54 50 150 272 72 227 260 213 
+172 35 60 109 150 43 19 286 175 92 60 124 151 45 263 41 119 109 290 304 23 201 
+54 294 149 215 87 158 2 196 311 224 133 267 100 104 248 180 9 183 136 184 208 
+115 279 44 106 163 303 265 270 242 51 8 96 204 56 294 219 216 89 143 71 140 14 
+85 313 139 256 154 187 210 115 35 304 108 148 58 209 28 103 176 249 252 309 309 
+10 11 13 312 67 11 83 258 69 310 152 202 141 171 277 129 297 276 216 159 89 73 
+70 83 29 16 67 81 29 1 54 65 96 274 2 37 204 285 33 160 246 265 255 296 49 78 
+27 260 39 119 94 289 247 38 132 55 222 288 90 215 2 211 257 226 118 22 44 176 
+164 305 250 25 186 123 238 221 131 212 30 158 246 195 254 239 64 9 28 243 123 
+308 167 133 197 154 102 4 111 65 166 220 59 281 273 229 105 76 57 137 97 32 302 
+108 78 112 207 43 34 232 177 22 129 68 168 275 74 282 275 214 174 20 129 53 222 
+218 144 158 17 142 313 209 257 211 172 20 59 52 220 288 20 214 281 188 282 46 
+106 233 249 8 255 311 309 80 271 15 297 136 269 100 174 249 182 308 307 80 256 
+69 240 206 200 156 102 19 57 122 96 30 3 39 134 40 32 232 162 76 127 138 99 17 
+57 52 150 287 18 284 190 23 116 107 235 234 77 199 69 225 205 198 226 33 75 40 
+206 285 103 161 303 250 10 240 66 253 152 187 195 169 33 5 39 204 41 34 217 231 
+20 199 313 224 203 213 102 89 3 124 81 99 261 56 50 165 218 74 212 15 157 244 
+265 185 295 47 93 217 2 281 203 283 103 91 302 193 25 116 122 236 236 7 268 13 
+242 121 9 98 189 125 238 291 77 269 15 227 190 267 170 50 305 165 133 127 153 
+45 19 42 121 94 45 248 95 117 179 166 46 6 26 188 53 307 165 148 128 210 30 88 
+300 193 10 170 120 251 167 63 251 97 117 194 167 48 250 95 132 125 223 290 75 
+284 260 283 118 37 45 178 94 60 194 97 47 248 110 63 181 151 115 264 43 104 233 
+234 7 253 12 240 136 254 154 117 264 113 50 235 164 76 197 84 101 261 126 310 
+222 203 143 156 32 73 55 137 27 31 245 123 9 168 135 182 223 46 21 286 245 38 
+62 109 220 303 21 271 244 36 132 40 276 286 105 91 58 194 27 101 246 180 308 
+237 79 199 84 171 262 128 295 291 147 215 17 212 259 219 ^
+652 1 187 278 112 35 287 228 90 126 121 151 26 18 299 187 21 97 174 179 302 252 
+8 255 63 306 82 254 135 237 206 181 276 44 87 283 245 19 182 51 288 215 144 141 
+86 84 16 68 64 81 10 66 312 133 6 83 241 189 252 220 114 266 94 119 177 234 304 
+4 5 308 46 61 26 8 314 48 80 23 12 297 119 24 44 191 108 42 231 145 128 140 99 
+30 1 54 131 42 276 301 102 144 37 261 20 169 105 303 180 77 180 136 165 275 57 
+33 219 231 86 143 1 207 272 155 172 264 179 45 237 147 196 137 152 13 72 47 152 
+270 87 224 260 196 241 293 77 284 10 229 171 20 110 120 164 288 3 18 254 298 47 
+93 285 313 283 186 34 43 159 214 4 262 7 223 120 1 113 116 181 217 59 264 26 
+171 173 251 233 60 251 80 186 138 184 223 61 16 23 175 107 6 177 81 114 207 109 
+29 285 160 142 73 138 80 82 313 120 11 98 255 122 291 221 146 209 83 88 315 139 
+8 151 189 193 235 291 58 20 273 295 51 76 40 257 37 49 161 233 1 266 257 294 64 
+22 25 243 104 59 111 201 58 277 288 156 159 2 194 10 170 186 197 169 46 2 41 
+185 106 290 234 92 145 69 155 9 138 243 208 200 224 48 21 38 189 40 45 178 162 
+57 196 78 167 190 180 289 306 23 269 312 296 132 19 29 226 175 3 181 64 234 151 
+130 208 96 34 300 174 75 112 188 112 292 302 89 198 52 275 269 159 155 19 123 
+66 149 274 70 295 204 266 153 104 126 62 166 203 126 225 25 90 230 262 264 238 
+30 60 39 270 299 34 147 300 278 216 225 35 75 53 203 22 84 228 243 267 185 47 
+305 95 200 71 223 273 142 226 12 144 294 276 197 228 31 141 298 259 268 172 101 
+4 109 133 110 273 38 36 215 297 15 199 296 28 145 281 14 212 242 280 131 32 291 
+162 161 70 142 14 153 257 141 239 274 129 280 27 158 227 315 198 309 290 130 
+267 81 173 192 248 237 43 6 24 256 50 44 146 268 68 227 256 213 170 33 56 105 
+150 39 13 284 173 88 58 124 147 43 263 39 117 109 286 300 21 201 48 292 149 215 
+85 156 312 192 307 222 133 263 98 102 248 178 9 183 132 182 204 113 279 40 104 
+163 301 265 270 240 49 8 92 204 54 294 217 212 89 139 67 136 12 85 309 137 256 
+154 185 210 115 31 304 108 146 56 209 24 103 176 247 250 305 307 10 7 11 310 65 
+9 79 258 69 308 150 202 139 171 277 125 297 272 214 157 87 71 70 83 29 14 67 77 
+27 311 52 63 94 272 2 31 200 283 33 160 246 263 251 292 45 74 21 260 33 115 90 
+289 247 38 130 55 222 286 88 211 314 211 255 226 116 18 42 172 160 305 248 25 
+184 119 236 219 127 212 30 154 244 195 254 239 62 3 28 239 121 304 167 131 195 
+150 98 314 107 65 162 220 55 281 271 227 103 72 57 137 93 28 308 ^
+670 0 105 78 106 204 40 31 232 177 22 129 68 168 269 74 276 275 208 174 14 126 
+47 219 218 138 158 14 139 310 203 251 205 166 11 59 52 214 282 20 214 308 275 
+182 282 46 106 230 249 316 252 311 309 77 271 15 291 136 269 100 168 243 182 
+308 301 74 250 66 240 200 197 156 99 16 54 116 96 21 314 33 134 37 23 229 156 
+73 124 132 96 8 51 49 147 287 15 278 190 14 113 101 235 231 71 196 63 219 205 
+192 220 27 72 31 206 285 100 155 297 244 4 234 66 253 146 181 189 166 24 5 36 
+201 32 28 211 228 17 193 313 224 200 210 102 83 3 121 78 93 258 56 44 165 215 
+71 209 9 157 238 259 182 295 38 90 217 316 278 203 277 97 88 302 193 22 116 122 
+230 236 7 268 7 242 115 3 95 186 125 238 285 74 263 12 224 187 264 164 50 299 
+159 127 127 153 45 13 33 121 91 39 242 89 111 173 166 37 314 20 188 53 307 162 
+148 122 204 27 85 294 190 1 167 117 248 164 63 245 97 114 194 161 42 250 92 132 
+122 217 290 69 281 257 280 118 37 36 175 94 60 191 94 47 245 110 60 178 148 109 
+258 43 98 227 228 4 247 12 237 133 248 151 117 261 110 47 232 164 76 191 81 101 
+261 123 310 216 197 143 153 32 67 49 134 24 31 245 123 6 162 135 176 220 40 18 
+286 239 35 62 106 217 303 15 265 244 30 126 34 273 280 105 91 52 188 27 98 240 
+174 305 234 79 199 84 168 256 128 292 288 141 212 17 206 259 208 187 277 110 34 
+286 226 89 124 119 150 24 18 299 185 19 95 173 179 300 252 7 255 61 304 82 253 
+133 235 205 179 274 43 85 281 244 17 180 50 286 213 143 140 86 83 16 67 62 80 8 
+64 312 131 3 82 240 187 251 218 112 266 92 119 176 233 303 2 2 306 43 59 26 5 
+314 46 80 21 10 296 118 24 44 191 107 39 229 143 127 140 99 29 54 129 42 276 
+301 100 142 34 260 17 167 104 302 180 76 178 135 163 274 56 31 219 231 84 142 1 
+206 272 154 171 264 177 42 237 146 194 135 150 11 72 44 152 269 87 222 259 195 
+241 293 77 284 7 229 169 19 108 119 163 287 2 15 252 298 46 93 284 311 283 185 
+32 41 157 212 4 260 4 221 120 315 113 114 181 215 58 263 25 170 171 251 231 58 
+250 79 186 138 184 223 61 13 20 175 107 6 175 81 114 207 107 26 283 159 140 73 
+137 78 80 312 118 11 98 253 120 289 221 146 207 81 88 315 139 6 149 189 192 233 
+290 56 18 273 293 51 75 39 255 35 49 160 233 316 265 257 293 64 21 23 242 102 
+57 111 199 58 276 288 154 158 1 193 9 170 184 197 169 45 41 183 104 289 234 92 
+145 68 155 6 136 243 208 200 223 48 21 36 188 40 44 178 161 55 196 76 165 189 
+179 287 306 23 268 311 296 131 16 28 224 174 1 180 63 232 151 130 207 94 34 299 
+172 73 111 186 112 292 301 87 196 50 273 267 159 153 235 ^
+658 1 117 63 143 274 67 292 201 260 147 104 313 126 56 163 200 123 225 16 90 
+230 262 258 232 21 57 39 264 296 31 147 300 278 216 219 35 75 50 197 13 78 225 
+237 267 185 41 302 95 197 71 220 270 139 223 3 144 288 273 191 228 28 135 295 
+253 265 172 95 1 106 130 107 267 29 36 212 291 6 196 293 19 142 275 8 209 239 
+280 131 23 291 162 161 64 142 14 150 254 141 236 268 126 277 21 155 221 309 198 
+306 284 124 264 75 173 192 242 234 34 3 21 253 44 35 140 262 62 227 250 213 167 
+30 50 99 150 33 4 281 170 82 55 124 141 40 263 36 114 109 280 294 18 201 39 289 
+149 215 82 153 306 186 301 219 133 257 95 99 248 175 9 183 126 179 198 110 279 
+34 101 163 298 265 270 237 46 8 86 204 51 294 214 206 89 133 61 130 9 85 303 
+134 256 154 182 210 115 25 304 108 143 53 209 18 103 176 244 247 299 304 10 1 8 
+307 62 6 73 258 69 305 147 202 136 171 277 119 297 266 211 154 84 68 70 83 29 
+11 67 71 24 305 49 60 91 269 2 22 194 280 33 160 246 260 245 286 39 68 12 260 
+24 109 84 289 247 38 127 55 222 283 85 205 311 211 252 226 113 12 39 166 154 
+305 245 25 181 113 233 216 121 212 30 148 241 195 254 239 59 313 28 233 118 298 
+167 128 192 144 92 308 101 65 156 220 49 281 268 224 100 66 57 137 87 22 292 
+103 78 102 202 38 29 232 177 22 129 68 168 265 74 272 275 204 174 10 124 43 217 
+218 134 158 12 137 308 199 247 201 162 5 59 52 210 278 20 214 304 271 178 282 
+46 106 228 249 312 250 311 309 75 271 15 287 136 269 100 164 239 182 308 297 70 
+246 64 240 196 195 156 97 14 52 112 96 15 312 29 134 35 17 227 152 71 122 128 
+94 2 47 47 145 287 13 274 190 8 111 97 235 229 67 194 59 215 205 188 216 23 70 
+25 206 285 98 151 293 240 230 66 253 142 177 185 164 18 5 34 199 26 24 207 226 
+15 189 313 224 198 208 102 79 3 119 76 89 256 56 40 165 213 69 207 5 157 234 
+255 180 295 32 88 217 316 276 203 273 93 86 302 193 20 116 122 226 236 7 268 3 
+242 111 318 93 184 125 238 281 72 259 10 222 185 262 160 50 295 155 123 127 153 
+45 9 27 121 89 35 238 85 107 169 166 31 310 16 188 53 307 160 148 118 200 25 83 
+290 188 314 165 115 246 162 63 241 97 112 194 157 38 250 90 132 120 213 290 65 
+279 255 278 118 37 30 173 94 60 189 92 47 243 110 58 176 146 105 254 43 94 223 
+224 2 243 12 235 131 244 149 117 259 108 45 230 164 76 187 79 101 261 121 310 
+212 193 143 151 32 63 45 132 22 31 245 123 4 158 135 172 218 36 16 286 235 33 
+62 104 215 303 11 261 244 26 122 30 271 276 105 91 48 184 27 96 236 170 303 232 
+79 199 84 166 252 128 290 283 ^
+649 1 133 208 17 198 259 204 187 273 102 30 282 218 85 116 111 146 16 18 299 
+177 11 87 169 179 292 252 3 255 53 296 82 249 125 227 201 171 266 39 77 273 240 
+9 172 46 278 205 139 136 86 79 16 63 54 76 56 312 123 312 78 236 179 247 210 
+104 266 84 119 172 229 299 315 311 298 31 51 26 314 314 38 80 13 2 292 114 24 
+44 191 103 27 221 135 123 140 99 25 317 54 121 42 276 301 92 134 22 256 5 159 
+100 298 180 72 170 131 155 270 52 23 219 231 76 138 1 202 272 150 167 264 169 
+30 237 142 186 127 142 3 72 32 152 265 87 214 255 191 241 293 77 284 316 229 
+161 15 100 115 159 283 319 3 244 298 42 93 280 303 283 181 24 33 149 204 4 252 
+313 213 120 307 113 106 181 207 54 259 21 166 163 251 223 50 246 75 186 138 184 
+223 61 1 8 175 107 6 167 81 114 207 99 14 275 155 132 73 133 70 72 308 110 11 
+98 245 112 281 221 146 199 73 88 315 139 319 141 189 188 225 286 48 10 273 285 
+51 71 35 247 27 49 156 233 312 261 257 289 64 17 15 238 94 49 111 191 58 272 
+288 146 154 318 189 5 170 176 197 169 41 313 41 175 96 285 234 92 145 64 155 
+315 128 243 208 200 219 48 21 28 184 40 40 178 157 47 196 68 157 185 175 279 
+306 23 264 307 296 127 4 24 216 170 314 176 59 224 151 130 203 86 34 295 164 65 
+107 178 112 292 297 79 188 42 265 259 159 145 19 113 61 139 274 65 290 199 256 
+143 104 311 126 52 161 198 121 225 10 90 230 262 254 228 15 55 39 260 294 29 
+147 300 278 216 215 35 75 48 193 7 74 223 233 267 185 37 300 95 195 71 218 268 
+137 221 318 144 284 271 187 228 26 131 293 249 263 172 91 320 104 128 105 263 
+23 36 210 287 194 291 13 140 271 4 207 237 280 131 17 291 162 161 60 142 14 148 
+252 141 234 264 124 275 17 153 217 305 198 304 280 120 262 71 173 192 238 232 
+28 1 19 251 40 29 136 258 58 227 246 213 165 28 46 95 150 29 319 279 168 78 53 
+124 137 38 263 34 112 109 276 290 16 201 33 287 149 215 80 151 302 182 297 217 
+133 253 93 97 248 173 9 183 122 177 194 108 279 30 99 163 296 265 270 235 44 8 
+82 204 49 294 212 202 89 129 57 126 7 85 299 132 256 154 180 210 115 21 304 108 
+141 51 209 14 103 176 242 245 295 302 10 318 6 305 60 4 69 258 69 303 145 202 
+134 171 277 115 297 262 209 152 82 66 70 83 29 9 67 67 22 301 47 58 89 267 2 16 
+190 278 33 160 246 258 241 282 35 64 6 260 18 105 80 289 247 38 125 55 222 281 
+83 201 309 211 250 226 111 8 37 162 150 305 243 25 179 109 231 214 117 212 30 
+144 239 195 254 239 57 309 28 229 116 294 167 126 190 140 88 304 97 65 152 220 
+45 281 178 ^
+<D
+
+H>SHS Type 3 Strings<H
+D>
+40 1 18 20 11 15 11 11 9 6 2 15 5 17 12 1 9 1 3 5 11 7 2 2 6 18 2 9 11 8 16 11 
+16 15 18 18 3 20 2 17 17 16 ^
+<D
+
diff --git a/dbus/test/data/sha-1/byte-hashes.sha1 b/dbus/test/data/sha-1/byte-hashes.sha1
new file mode 100644
index 0000000..5f33c2b
--- /dev/null
+++ b/dbus/test/data/sha-1/byte-hashes.sha1
@@ -0,0 +1,343 @@
+#  Configuration information for "SHA-1 Test"
+#  SHA tests are configured for BYTE oriented implementations
+H>SHS Type 1 Hashes<H
+D>
+DA39A3EE5E6B4B0D3255BFEF95601890AFD80709 ^
+3CDF2936DA2FC556BFA533AB1EB59CE710AC80E5 ^
+19C1E2048FA7393CFBF2D310AD8209EC11D996E5 ^
+CA775D8C80FAA6F87FA62BECA6CA6089D63B56E5 ^
+71AC973D0E4B50AE9E5043FF4D615381120A25A0 ^
+A6B5B9F854CFB76701C3BDDBF374B3094EA49CBA ^
+D87A0EE74E4B9AD72E6847C87BDEEB3D07844380 ^
+1976B8DD509FE66BF09C9A8D33534D4EF4F63BFD ^
+5A78F439B6DB845BB8A558E4CEB106CD7B7FF783 ^
+F871BCE62436C1E280357416695EE2EF9B83695C ^
+62B243D1B780E1D31CF1BA2DE3F01C72AEEA0E47 ^
+1698994A273404848E56E7FDA4457B5900DE1342 ^
+056F4CDC02791DA7ED1EB2303314F7667518DEEF ^
+9FE2DA967BD8441EEA1C32DF68DDAA9DC1FC8E4B ^
+73A31777B4ACE9384EFA8BBEAD45C51A71ABA6DD ^
+3F9D7C4E2384EDDABFF5DD8A31E23DE3D03F42AC ^
+4814908F72B93FFD011135BEE347DE9A08DA838F ^
+0978374B67A412A3102C5AA0B10E1A6596FC68EB ^
+44AD6CB618BD935460D46D3F921D87B99AB91C1E ^
+02DC989AF265B09CF8485640842128DCF95E9F39 ^
+67507B8D497B35D6E99FC01976D73F54AECA75CF ^
+1EAE0373C1317CB60C36A42A867B716039D441F5 ^
+9C3834589E5BFFAC9F50950E0199B3EC2620BEC8 ^
+209F7ABC7F3B878EE46CDF3A1FBB9C21C3474F32 ^
+05FC054B00D97753A9B3E2DA8FBBA3EE808CEF22 ^
+0C4980EA3A46C757DFBFC5BAA38AC6C8E72DDCE7 ^
+96A460D2972D276928B69864445BEA353BDCFFD2 ^
+F3EF04D8FA8C6FA9850F394A4554C080956FA64B ^
+F2A31D875D1D7B30874D416C4D2EA6BAF0FFBAFE ^
+F4942D3B9E9588DCFDC6312A84DF75D05F111C20 ^
+310207DF35B014E4676D30806FA34424813734DD ^
+4DA1955B2FA7C7E74E3F47D7360CE530BBF57CA3 ^
+74C4BC5B26FB4A08602D40CCEC6C6161B6C11478 ^
+0B103CE297338DFC7395F7715EE47539B556DDB6 ^
+EFC72D99E3D2311CE14190C0B726BDC68F4B0821 ^
+660EDAC0A8F4CE33DA0D8DBAE597650E97687250 ^
+FE0A55A988B3B93946A63EB36B23785A5E6EFC3E ^
+0CBDF2A5781C59F907513147A0DE3CC774B54BF3 ^
+663E40FEE5A44BFCB1C99EA5935A6B5BC9F583B0 ^
+00162134256952DD9AE6B51EFB159B35C3C138C7 ^
+CEB88E4736E354416E2010FC1061B3B53B81664B ^
+A6A2C4B6BCC41DDC67278F3DF4D8D0B9DD7784EF ^
+C23D083CD8820B57800A869F5F261D45E02DC55D ^
+E8AC31927B78DDEC41A31CA7A44EB7177165E7AB ^
+E864EC5DBAB0F9FF6984AB6AD43A8C9B81CC9F9C ^
+CFED6269069417A84D6DE2347220F4B858BCD530 ^
+D9217BFB46C96348722C3783D29D4B1A3FEDA38C ^
+DEC24E5554F79697218D317315FA986229CE3350 ^
+83A099DF7071437BA5495A5B0BFBFEFE1C0EF7F3 ^
+AA3198E30891A83E33CE3BFA0587D86A197D4F80 ^
+9B6ACBEB4989CBEE7015C7D515A75672FFDE3442 ^
+B021EB08A436B02658EAA7BA3C88D49F1219C035 ^
+CAE36DAB8AEA29F62E0855D9CB3CD8E7D39094B1 ^
+02DE8BA699F3C1B0CB5AD89A01F2346E630459D7 ^
+88021458847DD39B4495368F7254941859FAD44B ^
+91A165295C666FE85C2ADBC5A10329DAF0CB81A0 ^
+4B31312EAF8B506811151A9DBD162961F7548C4B ^
+3FE70971B20558F7E9BAC303ED2BC14BDE659A62 ^
+93FB769D5BF49D6C563685954E2AECC024DC02D6 ^
+BC8827C3E614D515E83DEA503989DEA4FDA6EA13 ^
+E83868DBE4A389AB48E61CFC4ED894F32AE112AC ^
+55C95459CDE4B33791B4B2BCAAF840930AF3F3BD ^
+36BB0E2BA438A3E03214D9ED2B28A4D5C578FCAA ^
+3ACBF874199763EBA20F3789DFC59572ACA4CF33 ^
+86BE037C4D509C9202020767D860DAB039CADACE ^
+51B57D7080A87394EEC3EB2E0B242E553F2827C9 ^
+1EFBFA78866315CE6A71E457F3A750A38FACAB41 ^
+57D6CB41AEEC20236F365B3A490C61D0CFA39611 ^
+C532CB64B4BA826372BCCF2B4B5793D5B88BB715 ^
+15833B5631032663E783686A209C6A2B47A1080E ^
+D04F2043C96E10CD83B574B1E1C217052CD4A6B2 ^
+E8882627C64DB743F7DB8B4413DD033FC63BEB20 ^
+CD2D32286B8867BC124A0AF2236FC74BE3622199 ^
+019B70D745375091ED5C7B218445EC986D0F5A82 ^
+E5FF5FEC1DADBAED02BF2DAD4026BE6A96B3F2AF ^
+6F4E23B3F2E2C068D13921FE4E5E053FFED4E146 ^
+25E179602A575C915067566FBA6DA930E97F8678 ^
+67DED0E68E235C8A523E051E86108EEB757EFBFD ^
+AF78536EA83C822796745556D62A3EE82C7BE098 ^
+64D7AC52E47834BE72455F6C64325F9C358B610D ^
+9D4866BAA3639C13E541F250FFA3D8BC157A491F ^
+2E258811961D3EB876F30E7019241A01F9517BEC ^
+8E0EBC487146F83BC9077A1630E0FB3AB3C89E63 ^
+CE8953741FFF3425D2311FBBF4AB481B669DEF70 ^
+789D1D2DAB52086BD90C0E137E2515ED9C6B59B5 ^
+B76CE7472700DD68D6328B7AA8437FB051D15745 ^
+F218669B596C5FFB0B1C14BD03C467FC873230A0 ^
+1FF3BDBE0D504CB0CDFAB17E6C37ABA6B3CFFDED ^
+2F3CBACBB14405A4652ED52793C1814FD8C4FCE0 ^
+982C8AB6CE164F481915AF59AAED9FFF2A391752 ^
+5CD92012D488A07ECE0E47901D0E083B6BD93E3F ^
+69603FEC02920851D4B3B8782E07B92BB2963009 ^
+3E90F76437B1EA44CF98A08D83EA24CECF6E6191 ^
+34C09F107C42D990EB4881D4BF2DDDCAB01563AE ^
+474BE0E5892EB2382109BFC5E3C8249A9283B03D ^
+A04B4F75051786682483252438F6A75BF4705EC6 ^
+BE88A6716083EB50ED9416719D6A247661299383 ^
+C67E38717FEE1A5F65EC6C7C7C42AFC00CD37F04 ^
+959AC4082388E19E9BE5DE571C047EF10C174A8D ^
+BAA7AA7B7753FA0ABDC4A541842B5D238D949F0A ^
+351394DCEBC08155D100FCD488578E6AE71D0E9C ^
+AB8BE94C5AF60D9477EF1252D604E58E27B2A9EE ^
+3429EC74A695FDD3228F152564952308AFE0680A ^
+907FA46C029BC67EAA8E4F46E3C2A232F85BD122 ^
+2644C87D1FBBBC0FC8D65F64BCA2492DA15BAAE4 ^
+110A3EEB408756E2E81ABAF4C5DCD4D4C6AFCF6D ^
+CD4FDC35FAC7E1ADB5DE40F47F256EF74D584959 ^
+8E6E273208AC256F9ECCF296F3F5A37BC8A0F9F7 ^
+FE0606100BDBC268DB39B503E0FDFE3766185828 ^
+6C63C3E58047BCDB35A17F74EEBA4E9B14420809 ^
+BCC2BD305F0BCDA8CF2D478EF9FE080486CB265F ^
+CE5223FD3DD920A3B666481D5625B16457DCB5E8 ^
+948886776E42E4F5FAE1B2D0C906AC3759E3F8B0 ^
+4C12A51FCFE242F832E3D7329304B11B75161EFB ^
+C54BDD2050504D92F551D378AD5FC72C9ED03932 ^
+8F53E8FA79EA09FD1B682AF5ED1515ECA965604C ^
+2D7E17F6294524CE78B33EAB72CDD08E5FF6E313 ^
+64582B4B57F782C9302BFE7D07F74AA176627A3A ^
+6D88795B71D3E386BBD1EB830FB9F161BA98869F ^
+86AD34A6463F12CEE6DE9596ABA72F0DF1397FD1 ^
+7EB46685A57C0D466152DC339C8122548C757ED1 ^
+E7A98FB0692684054407CC221ABC60C199D6F52A ^
+34DF1306662206FD0A5FC2969A4BEEC4EB0197F7 ^
+56CF7EBF08D10F0CB9FE7EE3B63A5C3A02BCB450 ^
+3BAE5CB8226642088DA760A6F78B0CF8EDDEA9F1 ^
+6475DF681E061FA506672C27CBABFA9AA6DDFF62 ^
+79D81991FA4E4957C8062753439DBFD47BBB277D ^
+BAE224477B20302E881F5249F52EC6C34DA8ECEF ^
+EDE4DEB4293CFE4138C2C056B7C46FF821CC0ACC ^
+<D
+
+H>SHS Type 2 Hashes<H
+D>
+A771FA5C812BD0C9596D869EC99E4F4AC988B13F ^
+E99D566212BBBCEEE903946F6100C9C96039A8F4 ^
+B48CE6B1D13903E3925AE0C88CB931388C013F9C ^
+E647D5BAF670D4BF3AFC0A6B72A2424B0C64F194 ^
+65C1CD932A06B05CD0B43AFB3BC7891F6BCEF45C ^
+70FFAE353A5CD0F8A65A8B2746D0F16281B25EC7 ^
+CC8221F2B829B8CF39646BF46888317C3EB378EA ^
+26ACCC2D6D51FF7BF3E5895588907765111BB69B ^
+01072915B8E868D9B28E759CF2BC1AEA4BB92165 ^
+3016115711D74236ADF0C371E47992F87A428598 ^
+BF30417999C1368F008C1F19FECA4D18A5E1C3C9 ^
+62BA49087185F2742C26E1C1F4844112178BF673 ^
+E1F6B9536F384DD3098285BBFD495A474140DC5A ^
+B522DAE1D67726EBA7C4136D4E2F6D6D645AC43E ^
+E9A021C3EB0B9F2C710554D4BF21B19F78E09478 ^
+DF13573188F3BF705E697A3E1F580145F2183377 ^
+188835CFE52ECFA0C4135C2825F245DC29973970 ^
+41B615A34EE2CEC9D84A91B141CFAB115821950B ^
+AB3DD6221D2AFE6613B815DA1C389EEC74AA0337 ^
+0706D414B4AA7FB4A9051AA70D6856A7264054FB ^
+3CBF8151F3A00B1D5A809CBB8C4F3135055A6BD1 ^
+DA5D6A0319272BBCCEA63ACFA6799756FFDA6840 ^
+FB4429C95F6277B346D3B389413758DFFFEEDC98 ^
+2C6E30D9C895B42DCCCFC84C906EC88C09B20DE1 ^
+3DE3189A5E19F225CDCE254DFF23DACD22C61363 ^
+93530A9BC9A817F6922518A73A1505C411D05DA2 ^
+E31354345F832D31E05C1B842D405D4BD4588EC8 ^
+3FF76957E80B60CF74D015AD431FCA147B3AF232 ^
+34AE3B806BE143A84DCE82E4B830EB7D3D2BAC69 ^
+D7447E53D66BB5E4C26E8B41F83EFD107BF4ADDA ^
+77DD2A4482705BC2E9DC96EC0A13395771AC850C ^
+EAA1465DB1F59DE3F25EB8629602B568E693BB57 ^
+9329D5B40E0DC43AA25FED69A0FA9C211A948411 ^
+E94C0B6AA62AA08C625FAF817DDF8F51EC645273 ^
+7FF02B909D82AD668E31E547E0FB66CB8E213771 ^
+5BB3570858FA1744123BAC2873B0BB9810F53FA1 ^
+905F43940B3591CE39D1145ACB1ECA80AB5E43CD ^
+336C79FBD82F33E490C577E3F791C3CBFE842AFF ^
+5C6D07A6B44F7A75A64F6CE592F3BAE91E022210 ^
+7E0D3E9D33127F4A30EB8D9C134A58409FA8695B ^
+9A5F50DFCFB19286206C229019F0ABF25283028C ^
+DCA737E269F9D8626D488988C996E06B352C0708 ^
+B8FFC1D4972FCE63241E0E77850AC46DDE75DBFA ^
+E9C9BF41C8549354151B977003CE1D830BE667DB ^
+0942908960B54F96CB43452E583F4F9CB66E398A ^
+FCE34051C34D4B81B85DDC4B543CDE8007E284B3 ^
+61E8916532503627F4024D13884640A46F1D61D4 ^
+F008D5D7853B6A17B7466CD9E18BD135E520FAF4 ^
+BD8D2E873CF659B5C77AAC1616827EF8A3B1A3B3 ^
+B25A04DD425302ED211A1C2412D2410FA10C63B6 ^
+A404E21588123E0893718B4B44E91414A785B91F ^
+A1E13BC55BF6DAD83CF3AABDA3287AD68681EA64 ^
+D5FD35FFABED6733C92365929DF0FB4CAE864D15 ^
+C12E9C280EE9C079E0506FF89F9B20536E0A83EF ^
+E22769DC00748A9BBD6C05BBC8E81F2CD1DC4E2D ^
+F29835A93475740E888E8C14318F3CA45A3C8606 ^
+1A1D77C6D0F97C4B620FAA90F3F8644408E4B13D ^
+4EC84870E9BDD25F523C6DFB6EDD605052CA4EAA ^
+D689513FED08B80C39B67371959BC4E3FECB0537 ^
+C4FED58F209FC3C34AD19F86A6DACADC86C04D33 ^
+051888C6D00029C176DE792B84DECE2DC1C74B00 ^
+1A3540BEE05518505827954F58B751C475AEECE0 ^
+DFA19180359D5A7A38E842F172359CAF4208FC05 ^
+7B0FA84EBBCFF7D7F4500F73D79660C4A3431B67 ^
+9E886081C9ACAAD0F97B10810D1DE6FCDCE6B5F4 ^
+A4D46E4BA0AE4B012F75B1B50D0534D578AE9CB6 ^
+6342B199EE64C7B2C9CBCD4F2DCB65ACEF51516F ^
+AABFD63688EB678357869130083E1B52F6EA861D ^
+F732B7372DAF44801F81EFFE3108726239837936 ^
+5E9347FE4574CDCB80281ED092191199BADD7B42 ^
+D5776B7DFFF75C1358ABDBBB3F27A20BB6CA7C55 ^
+022B7ADA472FB7A9DA9219621C9C5F563D3792F6 ^
+7F1DE4ECA20362DA624653D225A5B3F7964A9FF2 ^
+CA0F2B1BFB4469C11ED006A994734F0F2F5EFD17 ^
+833D63F5C2EA0CD43EC15F2B9DD97FF12B030479 ^
+14FD356190416C00592B86FF7CA50B622F85593A ^
+4AB6B57EDDEF1CE935622F935C1619AE7C1667D6 ^
+B456A6A968ACD66CAA974F96A9A916E700AA3C5D ^
+FD1C257FE046B2A27E2F0CD55ED2DECA845F01D7 ^
+66E0D01780F1063E2929EAAD74826BC64060E38C ^
+A8478DF406F179FD4EF97F4574D7F99EA1CE9EB8 ^
+248E58CF09A372114FC2F93B09C5FC14F3D0059E ^
+F15767DE91796A6816977EFA4FCED4B7FD9B8A57 ^
+36A6BC5E680E15675D9696338C88B36248BBBAF4 ^
+4DEA6251B2A6DF017A8093AB066EE3863A4EC369 ^
+D30E70E357D57E3D82CA554B8A3D58DFF528FA94 ^
+70CA84D827F7FD61446233F88CF2F990B0F3E2AA ^
+8D500C9CFDE0288530A2106B70BED39326C52C3C ^
+F3D4D139EDFC24596377BC97A96FB7621F27FFC7 ^
+5509BAFFAC6D507860CEFC5AB5832CB63CD4B687 ^
+0C0AEA0C2FD7A620C77866B1A177481E26B4F592 ^
+149176007FEE58A591E3F00F8DB658B605F8390C ^
+17C0D7B0256159F3626786FFDB20237AE154FA84 ^
+741A58618ABEB1D983D67AFDCBC49AA397A3B8E0 ^
+B738D6B3409EB9ED2F1719B84D13F7C36169CDEC ^
+3D33DE31F64055D3B128AC9A6AA3F92DFD4F5330 ^
+B6925F4DF94949B8844C867428BA3DEDF4CF2B51 ^
+CF5E7256292ABEC431D8E8B9CBEAF22AF072377E ^
+975DCE94902923977F129C0E4ACF40AD28DDB9AA ^
+333B0259B18CE64D6B52CF563DD3041E5F63A516 ^
+<D
+
+H>SHS Type 3 Hashes<H
+D>
+80E044703A880C20EC41F645120A8A5B5D194ECE ^
+E142829CA08FC9787F17AA16CE727396169B2713 ^
+6A2BAF62469D311F9257A0727F52C7EAA87CCEB4 ^
+362E3E7136CA611D7FBF687D3BBDC54CDA64843F ^
+F5900ADC6223A5D24A7526ABFC60FA8E2D59A5AB ^
+AD0CAC6A21D5B10833DDE7FA85927D74EDA142A9 ^
+47AD337EAFFDC177AAF7CBD035BE6F398B9D0536 ^
+9CF58595DF80872535BCC7C056E223546F0BB4EE ^
+7151CEB1918278CED2902B1D663D596F8D1B986F ^
+ADDC9F09AA4026EF6C4B7F1A84D3A13B4CDC65B3 ^
+921FE78A863A317B1FA1FB3CA3BE1948DE7EF754 ^
+64BE10732D71D52CE8A486DA23E6B453DF7C6FBD ^
+4A450659470DD759ABFAE1D73972A6D2E63AC16C ^
+0D665E4BBF30B7EAB955BDE84759E185EECAB4CB ^
+0C1B8EE94D61CDD0837EAED9FE33DE4A8334B596 ^
+D93BFE2A6227A4BF9B7C61EBCE4A8CDE131593FE ^
+BDA883F804B470C90BD6AC490DFC34EBC27F9648 ^
+46A0969373552213632591C52030C38E5DBDC49E ^
+4781289E48B910C550DC23CA7D3AF5324C03532D ^
+693A34CFCDDED0F3AC72E7197FCE9BB66A8E3981 ^
+AE088AF1D8865140963B3ABFB63E32E04CD1506F ^
+ADF0F8F1D85CA97586F5DC6DC5FD11FA39270F55 ^
+E484F5AD86C5F4D09E366ADF6E0DE73449F97B28 ^
+81C49842BA3D7072FB42288E03CE737A2672C091 ^
+F6CC71AD897C23A16835490DED289BFD45500AB0 ^
+23E71AED62FE8E28F34F58E7FE5594EC5EB0486C ^
+92BA7934AA5867EE52960F4E0EDFB90AA7B69305 ^
+C3D1CC8CBD1B6FFEE0D90CE962CD9C09AB1548AA ^
+3CE37A583B71A6A77BE325066A0F00C5D11DFC3E ^
+76EF5D236E1042D356A3234A422C092F86003064 ^
+8C3F703436C6C882E60263540A8E4C3E5646DC15 ^
+6138F9F3AB43B988DD3857422CCB304352459F40 ^
+B812DE98775B4690B4FC2ECFCAB61C73C7271DC7 ^
+06660985CD80D48E7B9F88455B4233924C3B64BB ^
+76AB4B6378D6F63499A94EB67EB1CB31AFF8D775 ^
+F31F6B0BE7AB059A1F59A46481967E88392979E6 ^
+0C1638498FBB7DB9600B98B4B22EF85E0FE245FB ^
+5607C6AF600939736795AC523FA43B736F41A118 ^
+8A03244866BDD21B9D8A82E98436C894FAD86ECC ^
+8A75BFD911AF87303B9B8FB7A1A47CCA52D3D98A ^
+16F0F3B5D37411236A1E3D6B1EDAB74CDA25ED4B ^
+AC72BF45477481F58A302628DC5299FFA32E7C9F ^
+74CFFD5881F75AC20726E1447DCF7F47024380EF ^
+5BFBECEECBC27DA05729C4D1AC8C1286EA6DCEC9 ^
+012AACBC0579FA4CB4F107E9A9AD1A86AD2F6A4D ^
+F7D552CBC5EF90F1A579388B5A8A9EC71EB67681 ^
+10C70115C4C34753274BFED477DF01440A67A361 ^
+078D2FACD293B6B6219D89899C16AA1AA8E3DE82 ^
+83C6BF9FB0D3091ADF374EBFA0A69916F17E6D26 ^
+2CDB1924DA62AB64C007C6505FF657E4ADDEA9C1 ^
+E95D209BCB9864B076FF4DFCA8F8BD75D62D1B48 ^
+632824CF5025F8F90AD2923BDDF449550D64C0F5 ^
+02B1C0B41FC27EC5A32E586F1AC480BF0061E56A ^
+28156BC6769AE390BF32C6512C46169181E1536D ^
+F730E6E287D992E7F3E013B6F1E088F0B9C41598 ^
+B056A6A832FA5FE964EF77FF3E0BE1C32E0D58C0 ^
+D5B3D19AFBB48FB56BA6D44A82DE6BD08DB208DE ^
+0215AD79BD6B8023C05FD2F8966211897DF6337A ^
+EC4CF38C244EB6526A44F70570925247145DA8CA ^
+C0D931262ECE93DA5A6ABC89CD6AD3162EA6B09E ^
+6BB48FAC26AA2B4859BBDEFCFB53AE4D1D9A0340 ^
+58611D43741E67A7F0DA9CB337A59DCD1EBE758E ^
+7C2AEC216AF231509E47B7EED06BB17859812B7E ^
+F60EE5DBF4A7A676EC98B3DDB1CDD6CDF3CDA33B ^
+0492E59B1F4C94E97F29A26C3EE7D57E1B0FDD72 ^
+4FCF549D902D9BE1101A756DB9E45415FB61BCD2 ^
+95C71D26AD6B38CC771376B4A4F962F12E1E3D4F ^
+F6A2449E773C72FB886B3C43E2B30EC2A1B7454A ^
+CDE86695E00AEC9A5DB6FDDB5D5A5934448D58E0 ^
+502318A758FABFF6AC53844E9E2BCD159C678510 ^
+589D295148F95F75DAE964DD743FE981FA236D4E ^
+7973DD33AE3599A556BACC77E8656E782E029EFF ^
+9F5BE43AADD43C6DB3883C9DA4B52E1A50257AEE ^
+454289D8FFB237A56D5214EAE88F0A9D328FEA1A ^
+7E686B36595BEB4C0D4528FF960EDB55088A028D ^
+F9789D1EF19A0084AC0E9F43A4BC0EE0478939EF ^
+2F32B0E7CC8BE19C325545C816E77056D7BBE70F ^
+6B1617746F073CFCD2CEBCAFBBE6FD0E28ED2D56 ^
+CF8D2EA3888AD76761799383E5A15979F6DB7A88 ^
+557AF6D9D5947203C60E98C9A79B92B8BD085E2B ^
+C61A217423DE68ED6CD34C91756C8DD3A650A2A2 ^
+73F3F79C151B6C1BD9369EDB26B932C2362B0593 ^
+364141E5FBCDE83F210C5BBBEB6810F6299DE14B ^
+F806BECD025D264FD59E93D9E3606A674C40F216 ^
+E0C761A57F00CBFB07D49BCB034C36A7122F4C5B ^
+5D3831044B9E0032FBE3C3425FFD13698F413B33 ^
+7EB1AB41E9997753C5D530DF118E71E72D7B86FC ^
+CC053EA1556269D7E8BCBA30B208FCBF0EE2EE64 ^
+A57739B1DD41E7DC0C40D6B6159A7E73CE2748AA ^
+90DA527C9DB9ACC2FD530D560A2F1191A80D0567 ^
+6AC1F2A0B8CA0E5ABC9FDF1ADCE588FBDF5CC53E ^
+43C1A0A0EE4163EC929726989F92B03639B233AB ^
+8927F299462413AC29A74080E54D8EE2DB7165E7 ^
+0C8D7E22226D91B423E781B508F31517EAAB607B ^
+7286E20D7F08D18A893254FBD3CC833F7973DCAF ^
+0CB8C235928B8E936C43B8F29EF3758B9FD54A7B ^
+F67C24CC23E440CA3F206CEEB5504ECA54CD5CA3 ^
+D78A25DEAA1E7ADADDB3C145ED0E5263BA4F2910 ^
+00AA68174D29492C578AC853FFCD55908292D41A ^
+D5570EEDB09A62A5948F7F311F7ED5EF247F9AD9 ^
+<D
+
diff --git a/dbus/test/data/sha-1/byte-messages.sha1 b/dbus/test/data/sha-1/byte-messages.sha1
new file mode 100644
index 0000000..7ad9078
--- /dev/null
+++ b/dbus/test/data/sha-1/byte-messages.sha1
@@ -0,0 +1,2294 @@
+#  Configuration information for "SHA-1 Test"
+#  SHA tests are configured for BYTE oriented implementations
+H>SHS Type 1 Strings<H
+D>
+0 1 ^
+5 0 2 1 2 1 2 ^
+5 0 1 3 4 4 4 ^
+7 0 4 3 4 4 1 4 4 ^
+10 0 4 1 5 3 4 4 3 1 3 4 ^
+10 0 3 1 6 5 5 1 3 6 6 4 ^
+13 1 3 2 5 3 3 3 4 6 6 1 4 6 2 ^
+16 1 3 5 5 1 2 1 3 3 6 3 5 2 3 5 7 2 ^
+15 1 8 1 5 3 2 7 4 5 6 7 3 3 1 6 3 ^
+15 1 4 6 8 2 1 4 2 5 1 6 8 8 6 4 7 ^
+18 1 1 2 7 3 8 6 7 5 4 3 4 3 5 3 3 2 6 8 ^
+16 0 9 8 1 8 1 7 6 7 7 1 2 6 9 5 4 7 ^
+18 0 7 1 7 3 9 4 7 7 5 2 8 1 7 8 2 7 2 9 ^
+19 1 2 3 1 8 8 6 9 10 3 10 8 9 2 4 1 5 1 5 9 ^
+19 1 8 5 4 8 1 3 9 5 7 7 2 7 2 7 8 7 4 8 10 ^
+20 1 1 9 7 4 1 4 5 1 10 8 6 4 4 9 9 9 8 2 9 10 ^
+19 1 11 6 7 7 2 6 2 6 10 6 9 10 5 11 1 6 8 11 4 ^
+22 0 10 5 10 3 7 8 9 9 1 1 1 10 2 1 5 10 2 9 9 9 7 8 ^
+21 0 1 10 1 6 9 4 2 5 2 11 8 12 12 9 8 1 3 10 7 11 12 ^
+24 1 3 9 5 12 3 4 2 9 12 11 6 6 1 1 9 5 9 1 4 9 4 10 8 9 ^
+25 1 3 2 3 11 1 12 5 6 2 7 8 4 8 8 9 9 8 4 9 1 4 8 10 9 9 ^
+23 0 11 10 7 10 10 6 10 9 4 5 10 5 8 4 1 10 12 4 6 1 8 11 6 ^
+22 0 12 8 10 4 3 8 5 5 7 11 13 11 12 11 4 12 3 6 5 11 10 5 ^
+26 1 10 9 6 9 7 2 10 4 4 5 5 2 12 13 5 3 1 10 1 4 7 8 13 13 12 9 ^
+31 0 2 6 5 4 7 3 10 6 13 6 3 9 6 2 10 5 3 8 4 1 11 3 5 3 7 11 1 12 9 12 5 ^
+27 1 14 5 1 3 7 2 3 9 3 4 14 4 4 10 8 5 14 1 11 12 12 10 4 13 7 11 9 ^
+30 1 4 9 5 5 8 9 5 10 4 2 4 7 9 9 6 3 5 1 8 3 2 13 3 14 9 8 9 10 14 10 ^
+27 0 12 9 5 8 7 2 14 12 3 8 14 6 6 4 7 5 7 10 7 11 10 1 9 6 7 12 14 ^
+24 0 12 9 9 2 11 13 12 11 11 6 14 13 10 5 6 8 10 4 3 11 11 14 5 14 ^
+24 0 15 4 5 3 8 12 15 8 14 15 9 12 12 3 10 13 6 11 10 4 13 14 8 8 ^
+28 1 1 8 1 5 11 4 9 12 4 13 15 5 9 11 7 14 11 1 11 7 8 8 11 1 13 15 12 13 ^
+32 1 5 8 3 8 10 7 8 1 5 13 12 14 5 3 6 4 12 15 6 6 10 11 13 9 1 11 6 10 3 7 14 
+2 ^
+31 0 10 3 5 1 14 11 11 16 1 2 2 11 6 13 15 12 6 5 16 2 14 2 10 12 2 5 5 6 10 13 
+15 ^
+34 0 3 10 8 16 9 5 12 15 4 11 13 3 6 5 10 8 1 3 9 3 11 1 2 16 12 10 6 1 9 1 16 
+5 6 14 ^
+30 1 1 12 4 4 2 15 13 15 11 15 5 11 9 7 15 16 6 16 12 3 2 10 16 5 5 7 1 7 11 16 
+^
+34 0 7 9 11 2 5 5 5 4 13 13 14 4 7 12 6 4 8 2 9 9 13 13 3 3 6 7 16 7 6 15 5 8 
+15 14 ^
+36 1 4 6 16 15 11 14 14 4 7 10 3 4 10 3 6 7 14 4 6 6 5 2 7 8 16 2 12 16 10 14 3 
+2 3 7 14 3 ^
+32 0 15 10 9 1 14 10 14 6 6 16 3 2 3 8 3 12 8 11 17 3 9 7 16 14 4 11 15 5 13 9 
+5 17 ^
+30 0 17 17 13 8 2 6 8 16 1 12 5 17 2 9 8 10 13 14 11 17 12 5 14 9 11 9 11 4 11 
+12 ^
+30 1 16 6 10 5 8 3 17 16 14 1 15 15 15 6 13 2 11 6 13 11 13 4 6 7 11 11 12 16 
+13 16 ^
+33 1 16 16 14 16 2 4 16 11 6 15 7 4 17 6 5 7 6 3 14 16 5 17 11 13 1 1 14 13 3 6 
+14 5 16 ^
+39 1 2 16 13 7 8 6 2 15 1 9 12 4 4 11 13 7 2 11 9 18 4 5 4 8 2 14 9 9 1 8 13 11 
+15 8 5 9 10 16 7 ^
+34 0 2 7 1 1 17 13 6 11 10 8 5 12 15 6 15 10 12 4 18 1 2 8 11 12 16 10 12 18 11 
+16 12 11 17 6 ^
+34 1 4 7 13 7 10 7 10 6 1 12 7 18 11 18 2 10 15 10 14 8 18 9 9 12 12 3 13 12 6 
+4 9 17 13 17 ^
+40 0 5 7 3 2 1 17 14 4 16 6 13 1 13 6 6 10 1 3 18 3 11 7 9 5 7 11 17 1 9 16 5 
+15 10 17 3 8 15 17 8 12 ^
+40 0 11 3 15 17 11 1 1 4 3 14 18 4 2 18 8 15 6 4 6 3 15 11 16 10 17 17 9 6 3 2 
+6 16 4 9 12 6 8 1 11 17 ^
+37 1 2 19 12 8 16 14 2 9 16 2 6 6 7 9 10 9 11 9 14 11 15 5 16 9 2 17 2 8 15 8 4 
+3 14 14 16 16 12 ^
+37 1 11 10 16 12 11 7 14 14 14 6 10 10 1 6 13 19 5 6 4 7 12 12 10 5 10 15 15 8 
+5 13 17 13 5 6 14 1 19 ^
+38 1 2 6 5 17 9 11 18 18 8 6 13 15 3 3 15 5 13 18 3 2 5 5 14 7 13 4 17 7 2 17 3 
+18 15 7 15 16 18 11 ^
+38 1 12 8 6 3 17 12 13 19 15 9 7 17 16 15 3 11 11 5 2 13 19 16 2 4 16 7 8 1 2 9 
+17 12 3 5 18 19 11 9 ^
+39 1 14 16 14 8 9 16 5 1 6 3 17 18 16 9 1 15 9 10 9 19 1 3 3 20 11 13 17 1 19 8 
+3 4 3 7 1 14 19 19 19 ^
+37 1 18 13 11 5 18 4 19 10 6 19 11 17 10 10 7 9 13 16 9 10 18 4 12 5 16 5 20 12 
+3 8 10 1 18 1 6 20 14 ^
+36 0 8 9 6 12 11 7 7 3 17 13 6 20 17 9 20 16 10 12 17 8 11 8 11 10 5 10 14 18 8 
+19 9 12 12 2 20 19 ^
+39 0 12 16 20 3 9 9 19 17 13 13 4 17 2 11 7 14 3 6 16 13 10 13 5 16 10 2 8 2 17 
+19 4 17 7 19 6 9 15 15 6 ^
+43 0 7 2 18 5 7 18 5 2 15 7 11 10 9 3 2 14 19 3 11 8 18 15 5 3 5 12 15 16 10 17 
+7 19 16 2 1 16 6 3 19 12 5 18 16 ^
+49 1 9 11 2 1 12 11 14 12 14 10 4 11 6 8 16 7 5 11 20 8 17 4 14 4 15 3 2 2 4 3 
+2 3 14 15 10 2 12 7 3 7 20 20 19 10 2 3 1 10 20 ^
+36 0 19 20 12 5 19 21 5 21 11 14 19 1 17 8 9 4 19 3 17 1 14 21 14 7 6 5 20 14 
+21 20 4 6 21 7 11 12 ^
+41 0 12 9 11 6 16 18 18 10 11 20 6 12 11 5 7 21 19 18 6 15 21 10 4 14 9 19 10 3 
+3 5 13 1 8 12 3 13 9 7 10 17 14 ^
+45 0 10 6 8 3 17 18 3 21 19 6 17 15 4 9 15 9 15 14 4 7 14 8 10 13 4 11 10 7 6 
+21 1 14 5 11 7 7 2 13 13 3 9 13 8 14 20 ^
+39 1 3 7 18 4 9 9 5 15 13 17 10 15 16 20 8 19 9 10 9 1 19 14 21 2 18 13 10 4 18 
+16 4 21 15 10 18 19 3 12 18 ^
+41 0 14 4 13 11 1 11 1 10 2 12 4 21 10 21 18 9 2 16 7 20 6 7 12 19 20 1 13 12 
+10 8 21 15 7 19 13 6 8 19 20 18 19 ^
+37 0 11 18 1 17 14 15 20 16 20 8 2 17 10 4 21 5 19 19 14 22 21 18 13 14 1 3 12 
+11 11 4 22 13 5 18 7 21 21 ^
+48 0 9 22 19 12 8 16 5 17 5 9 1 2 9 6 12 6 1 7 4 3 15 1 14 1 12 3 10 2 10 14 21 
+13 17 6 6 17 1 21 2 14 16 17 9 11 20 21 11 18 ^
+50 1 12 8 20 13 2 9 20 9 14 10 1 16 2 22 6 4 16 14 15 1 12 4 14 9 21 3 3 9 8 21 
+15 14 8 4 14 4 2 3 8 12 8 6 1 2 18 20 15 3 19 10 ^
+44 0 10 20 14 6 3 4 21 1 12 4 18 2 6 7 6 9 20 14 10 10 19 17 21 12 15 17 7 10 
+11 8 10 12 1 19 19 9 18 21 4 18 11 9 22 5 ^
+47 0 15 8 15 3 5 6 2 19 12 17 4 20 8 11 20 2 18 4 16 20 12 9 9 6 16 21 16 3 16 
+18 3 19 5 16 2 4 2 12 11 15 11 14 17 2 10 18 8 ^
+48 1 5 13 3 21 5 3 6 18 18 10 1 21 21 7 1 13 12 19 1 14 6 8 21 19 21 11 19 13 2 
+13 4 1 10 22 16 4 9 4 10 16 3 7 15 11 9 13 17 12 ^
+45 0 14 7 6 2 20 3 6 19 19 10 2 22 12 17 12 1 20 7 7 15 20 6 18 8 3 14 23 18 15 
+4 7 5 23 15 7 14 10 10 19 17 2 4 15 17 21 ^
+45 1 15 11 8 9 17 5 12 18 14 6 20 17 21 12 16 9 22 9 20 15 2 22 11 2 6 11 9 8 2 
+4 14 19 3 21 21 23 8 2 11 4 8 4 20 22 11 ^
+38 0 21 18 22 10 19 9 14 17 23 21 10 7 15 13 16 5 4 10 13 14 20 23 12 20 23 18 
+10 12 8 21 11 6 12 7 19 14 18 17 ^
+40 0 18 22 6 9 22 5 23 13 6 8 23 20 22 5 22 15 19 20 9 9 1 13 13 10 14 13 5 22 
+14 21 9 21 19 14 14 4 18 13 12 14 ^
+48 1 7 3 15 5 17 14 23 14 5 17 22 11 1 8 13 23 6 21 3 6 11 7 23 8 6 21 4 4 22 
+19 13 8 5 19 7 5 23 1 4 19 11 23 11 21 14 1 3 21 ^
+43 0 22 14 11 7 18 16 17 24 12 12 3 13 19 16 22 4 16 4 6 23 8 18 11 2 3 20 22 9 
+21 8 23 1 23 20 7 16 13 23 4 13 3 7 22 ^
+47 1 23 6 13 19 2 3 7 2 9 9 15 6 13 4 22 6 19 20 1 9 7 14 1 15 3 23 24 22 18 12 
+12 17 19 10 8 11 22 12 10 2 20 15 18 17 18 7 19 ^
+47 1 12 21 6 12 4 7 18 17 3 2 14 24 14 1 23 1 11 15 10 6 18 20 7 1 8 1 16 6 20 
+23 23 21 10 10 12 24 10 11 23 2 12 23 9 3 24 24 10 ^
+52 0 14 10 18 15 14 5 16 11 22 2 15 24 8 22 1 4 24 9 10 15 3 9 5 4 17 15 9 12 
+19 19 1 3 10 6 8 3 17 8 18 24 19 3 4 15 4 9 2 24 5 20 13 13 ^
+42 0 20 17 19 22 13 8 10 19 15 11 1 14 17 20 22 10 7 11 16 9 21 22 17 23 12 15 
+4 24 7 21 18 2 21 16 1 19 18 20 11 3 15 17 ^
+50 0 18 1 6 14 5 5 5 19 13 10 24 19 16 24 15 13 2 19 15 24 21 17 4 13 17 1 1 9 
+1 10 2 18 1 21 19 5 18 12 2 22 16 23 15 19 6 18 9 1 23 5 ^
+51 0 21 13 14 11 18 12 13 3 19 9 20 22 20 2 11 12 6 1 12 16 18 2 9 8 4 3 11 17 
+11 5 4 19 16 11 23 13 18 1 20 8 2 16 16 21 4 19 5 5 20 24 16 ^
+53 1 20 25 17 11 8 4 19 25 17 7 16 21 6 4 8 2 15 9 2 9 19 3 6 3 3 10 25 13 15 7 
+8 20 21 12 10 12 5 24 11 20 3 13 13 16 9 13 10 3 9 16 3 7 25 ^
+49 1 9 9 14 2 13 17 25 2 18 5 19 23 9 25 9 10 23 12 12 7 13 8 15 7 1 6 21 2 8 7 
+6 16 14 14 12 15 13 24 10 15 11 10 8 14 15 21 25 21 25 ^
+47 0 9 18 20 22 21 20 11 14 23 22 10 13 14 8 19 12 2 11 20 23 13 4 10 6 5 7 23 
+11 3 16 8 21 4 8 18 5 12 14 8 6 20 19 24 8 23 17 23 ^
+48 1 7 19 1 18 1 14 22 13 14 5 8 22 18 14 25 17 11 12 22 2 12 12 16 12 13 18 17 
+12 17 14 18 8 25 9 23 5 3 8 14 24 17 7 3 3 23 17 22 19 ^
+51 1 19 17 16 22 24 14 16 20 23 20 9 19 16 7 12 16 5 8 9 7 10 21 24 10 11 19 1 
+21 14 14 19 3 22 8 12 20 1 18 5 6 5 12 14 1 1 11 9 22 3 24 4 ^
+52 1 6 1 11 16 1 12 8 11 11 17 10 22 7 3 10 2 6 4 24 16 24 19 4 5 18 11 12 9 20 
+21 25 2 21 18 10 20 25 21 3 17 17 5 8 22 25 19 8 10 19 7 11 18 ^
+44 0 26 14 21 25 25 4 9 13 5 8 9 21 8 12 26 24 9 24 15 1 23 22 16 14 8 22 15 19 
+24 20 7 8 15 24 12 4 4 23 21 13 19 15 21 12 ^
+59 1 15 7 3 21 20 8 22 14 23 26 19 2 10 18 3 5 3 1 9 15 15 3 7 13 23 9 7 1 13 
+17 14 25 9 16 2 2 6 13 7 19 25 17 1 5 21 2 7 22 5 6 25 3 12 19 6 2 4 24 17 ^
+60 0 9 18 20 19 4 11 14 1 6 8 26 6 9 22 4 10 2 7 21 9 8 24 25 14 22 12 22 3 23 
+3 3 20 6 11 23 6 1 7 5 18 5 15 25 26 1 1 10 11 11 4 12 11 20 3 14 2 3 2 23 15 ^
+49 0 12 17 24 11 8 6 24 16 15 22 21 14 6 12 20 19 5 5 12 11 6 23 2 16 23 7 24 6 
+21 2 17 17 5 25 11 25 20 25 24 18 6 12 19 25 7 6 5 2 25 ^
+54 1 12 16 1 15 7 1 26 19 19 13 20 11 17 6 20 5 24 24 1 21 11 9 20 21 15 10 19 
+26 3 2 6 7 12 9 10 8 14 10 15 5 17 8 21 1 20 25 6 19 8 3 22 16 16 20 ^
+63 0 17 13 11 10 17 15 12 6 13 14 17 4 12 10 24 5 13 24 3 5 2 5 11 14 8 5 10 17 
+16 8 4 14 21 15 3 6 17 25 8 2 3 3 19 10 13 22 22 8 2 13 25 17 2 1 19 1 14 20 2 
+5 4 15 24 ^
+49 0 14 20 7 25 20 26 20 16 7 17 17 22 1 13 6 5 1 18 14 15 23 15 10 5 19 18 18 
+26 12 13 3 25 12 21 16 24 4 16 3 6 26 26 10 20 13 1 20 24 15 ^
+56 0 3 8 14 5 5 7 11 13 11 26 11 4 26 17 20 19 11 10 3 10 14 9 6 9 7 16 10 4 4 
+19 19 2 26 13 19 17 15 24 15 4 21 22 13 13 12 22 2 14 20 5 18 7 17 24 20 20 ^
+58 1 6 17 9 20 2 10 19 3 22 4 1 11 3 5 3 21 11 15 12 23 26 5 2 27 6 5 16 6 3 2 
+23 5 3 20 20 4 24 2 18 21 7 14 10 27 23 6 24 6 19 23 3 9 22 16 21 17 19 23 ^
+58 1 17 7 21 19 6 16 15 15 20 14 2 25 19 14 18 19 7 9 1 14 11 10 16 3 23 14 26 
+10 11 1 18 1 12 24 19 19 1 7 2 3 24 7 12 9 2 8 16 20 24 5 26 26 4 9 2 7 25 17 ^
+54 1 8 12 18 14 26 7 17 18 4 20 1 16 14 21 26 4 6 8 24 11 25 15 24 16 23 4 10 
+23 21 24 15 10 9 26 7 14 24 21 6 20 5 17 16 17 1 3 12 1 4 13 3 9 21 26 ^
+56 1 7 18 11 1 19 20 23 12 12 27 13 13 15 16 13 1 16 15 12 26 3 16 16 8 17 13 
+21 4 6 5 19 14 16 4 16 11 14 18 18 27 9 13 21 3 26 22 3 7 6 4 26 3 15 8 25 21 ^
+50 1 20 13 9 11 20 6 11 21 27 25 20 7 4 18 26 16 27 5 12 19 7 23 6 25 25 2 11 
+13 25 21 18 17 6 12 14 13 24 11 14 19 26 27 25 6 1 15 4 7 27 15 ^
+51 0 15 16 26 27 23 14 12 28 22 15 8 19 2 20 13 1 24 2 25 1 6 19 19 8 11 24 24 
+21 13 27 5 11 28 17 7 25 6 23 24 14 25 12 5 13 26 2 5 8 10 16 17 ^
+58 1 5 26 18 19 21 3 12 11 13 4 14 22 22 14 16 13 3 22 16 23 5 19 6 13 10 26 17 
+27 26 4 3 25 6 14 2 3 5 7 23 11 22 8 25 2 9 25 18 17 8 2 14 4 19 1 5 27 13 24 ^
+53 0 2 27 28 2 17 23 10 27 18 26 7 22 16 3 27 1 26 21 28 10 3 6 2 2 10 17 13 16 
+6 17 21 23 13 20 22 5 6 11 12 12 8 23 13 17 9 23 20 3 28 27 12 17 22 ^
+59 0 28 19 5 21 4 27 8 1 19 14 20 6 7 9 1 6 22 3 19 26 14 8 6 7 19 15 23 1 17 
+16 6 26 14 5 22 25 4 7 10 16 21 10 18 19 24 16 23 8 3 17 28 18 10 2 5 3 21 21 
+15 ^
+58 0 6 24 1 4 24 18 10 22 1 21 12 5 4 4 20 25 24 26 8 25 11 2 7 27 22 19 4 18 
+27 10 28 4 12 24 8 16 12 11 16 17 25 8 12 16 1 9 9 10 5 24 23 18 5 14 18 8 4 28 
+^
+61 0 5 17 8 28 1 22 4 11 3 2 17 3 14 9 27 13 18 24 9 8 7 28 25 14 21 27 24 6 18 
+16 2 12 15 9 14 10 1 8 17 4 6 15 26 11 15 2 28 20 26 16 3 7 5 8 9 26 10 12 25 
+11 22 ^
+53 0 9 13 24 15 20 2 4 8 2 22 20 19 4 15 14 28 13 25 10 10 12 28 24 22 26 28 15 
+9 11 26 19 22 27 2 21 8 20 23 26 12 10 21 9 15 13 25 7 26 1 13 5 9 20 ^
+58 0 3 9 21 22 7 1 23 28 1 2 8 22 12 18 28 5 18 14 7 11 17 20 20 7 21 13 8 28 
+21 22 2 16 20 15 28 9 3 22 13 10 23 4 16 11 14 1 10 8 14 14 15 18 13 12 21 18 
+25 28 ^
+60 1 29 20 2 29 22 8 16 20 4 12 9 6 12 16 16 7 9 20 29 11 9 4 1 15 25 16 29 10 
+22 7 2 8 5 18 14 23 24 4 6 26 3 11 6 12 1 7 14 24 14 6 10 21 16 23 29 25 6 14 
+17 24 ^
+64 0 12 10 5 10 15 25 8 15 3 7 13 25 16 14 1 29 22 26 15 27 9 1 8 8 28 6 13 5 
+13 3 15 5 23 8 23 2 5 5 4 17 13 14 7 17 12 27 3 18 5 7 5 26 18 15 22 28 16 13 7 
+2 23 19 25 15 ^
+56 1 17 7 16 25 23 11 11 15 2 13 9 26 2 24 26 7 28 11 2 29 7 22 23 5 28 19 1 27 
+29 1 24 11 18 20 3 13 11 7 3 15 17 24 1 18 13 6 3 25 27 16 28 18 24 8 23 22 ^
+51 1 29 28 6 28 14 12 28 27 22 4 14 25 1 3 9 7 11 14 15 16 10 19 12 19 11 20 13 
+28 4 27 28 7 27 12 4 28 21 17 22 20 17 15 15 23 22 13 12 21 22 21 29 ^
+64 1 12 14 12 18 27 8 7 4 9 14 16 15 8 11 21 20 10 10 21 23 20 2 11 23 1 11 1 5 
+3 23 16 15 27 14 5 16 3 22 2 3 24 3 19 29 4 4 10 8 20 14 15 1 26 12 27 25 4 28 
+22 11 19 19 24 9 ^
+60 1 20 8 9 5 25 19 17 19 15 7 24 24 21 3 20 16 8 3 17 28 18 29 9 23 9 10 29 4 
+12 24 15 5 8 22 17 29 12 3 8 29 15 21 21 4 7 20 7 10 7 26 10 16 24 6 7 12 8 12 
+15 17 ^
+60 0 9 17 11 28 12 26 26 6 29 13 10 20 6 23 10 4 3 26 26 14 20 20 25 14 13 15 
+24 14 11 4 23 27 24 20 9 16 17 24 13 12 6 1 14 26 25 7 8 21 1 19 3 2 2 17 21 13 
+5 9 21 11 ^
+54 0 25 1 27 24 6 23 16 5 1 20 29 22 25 9 25 10 3 28 28 25 19 18 16 24 14 15 5 
+28 12 28 26 29 2 15 15 9 5 18 19 22 12 15 4 6 15 24 16 9 4 26 25 18 27 12 ^
+61 1 20 4 26 12 3 22 1 22 30 3 28 10 9 24 14 29 6 30 3 10 20 14 6 3 19 21 21 28 
+16 18 11 30 11 20 30 1 9 8 11 5 19 10 24 4 22 4 2 26 5 15 20 8 3 13 30 18 8 1 
+25 28 19 ^
+56 1 20 15 21 18 18 12 16 13 24 9 21 2 28 6 1 23 9 18 27 27 4 9 13 10 8 14 16 
+15 12 11 14 21 14 10 11 25 17 17 30 21 13 27 26 26 22 14 13 17 21 19 9 9 20 23 
+13 28 ^
+59 1 10 28 24 10 22 27 23 27 8 17 14 6 4 21 26 15 1 8 29 27 6 28 15 3 27 25 25 
+14 19 13 29 8 24 2 8 2 4 12 19 11 10 6 26 14 22 24 30 10 11 12 2 12 17 23 8 8 
+12 28 12 ^
+56 0 14 28 2 17 4 8 3 26 9 23 21 30 30 20 4 13 28 29 9 3 17 7 19 30 28 1 2 20 9 
+12 24 15 30 20 27 3 23 11 6 29 25 23 26 17 20 10 22 15 23 6 25 5 4 30 2 29 ^
+63 1 23 15 27 14 26 1 1 7 19 12 7 6 20 18 14 4 15 17 28 7 11 7 8 9 22 17 12 5 
+23 18 25 18 6 12 26 30 12 30 14 3 1 18 10 20 27 21 8 6 24 26 20 11 24 7 2 4 18 
+15 14 30 16 19 14 ^
+52 0 27 15 4 19 25 29 29 7 14 18 9 11 9 27 11 15 29 9 28 20 2 30 26 21 17 8 28 
+17 22 29 24 8 11 18 29 15 6 7 27 27 17 24 18 23 11 19 8 30 5 24 22 24 ^
+66 1 25 15 28 23 5 10 21 5 8 7 3 10 19 17 6 9 15 29 10 7 4 1 16 21 16 29 13 18 
+5 3 8 15 8 21 29 20 5 27 2 13 27 7 7 30 2 18 26 10 2 5 29 21 15 25 26 24 8 12 
+20 3 9 10 30 7 12 29 ^
+53 1 30 26 20 11 22 19 27 2 16 10 6 4 24 17 20 25 20 15 8 23 23 20 30 18 16 3 
+30 15 26 23 28 7 21 8 7 31 31 14 26 18 3 1 26 28 15 25 11 31 3 25 9 21 30 ^
+67 0 2 6 14 4 9 5 28 8 17 22 1 4 8 7 10 14 19 10 14 8 27 9 24 26 4 30 11 8 19 5 
+21 7 2 27 20 16 20 20 22 14 13 16 26 14 10 3 25 22 25 23 21 10 15 15 29 8 13 4 
+2 13 22 20 7 4 20 31 23 ^
+65 0 2 2 28 13 19 14 12 23 27 6 2 14 2 22 6 25 30 29 31 13 14 16 31 12 16 30 5 
+14 31 11 4 1 1 25 21 13 26 22 21 5 22 14 29 1 21 3 14 30 4 2 29 12 15 23 3 15 5 
+1 6 23 22 13 1 14 23 ^
+59 1 25 5 15 6 13 3 22 11 23 31 24 6 5 20 4 14 3 29 8 29 19 7 29 23 25 28 19 11 
+15 27 21 14 1 19 20 26 12 7 12 1 18 13 29 28 23 29 14 23 7 1 9 29 24 5 30 18 5 
+25 30 ^
+55 1 31 25 13 7 24 25 24 1 12 19 9 7 6 28 20 14 28 21 19 31 20 20 6 24 18 27 24 
+4 18 21 1 31 15 1 15 2 27 4 26 25 4 23 19 2 31 22 30 21 22 5 27 12 30 28 31 ^
+62 0 27 15 18 14 25 15 17 7 28 11 28 29 30 1 17 12 10 2 18 20 21 2 11 12 5 4 12 
+25 14 5 5 24 22 18 31 15 22 29 11 3 21 31 21 27 3 28 7 10 25 2 15 30 9 30 7 22 
+15 9 3 20 24 14 ^
+60 0 28 14 18 9 27 14 22 27 31 10 8 14 7 15 7 20 5 26 1 29 7 17 17 8 3 13 27 18 
+8 31 27 28 22 22 17 19 18 18 11 19 13 25 10 19 6 28 4 31 23 10 18 26 31 5 10 13 
+12 8 15 27 ^
+60 1 24 22 4 29 22 31 28 20 4 16 21 3 1 15 5 15 6 30 3 29 29 7 27 20 2 20 31 22 
+26 9 29 16 4 26 32 17 20 14 28 17 19 6 24 11 26 28 5 18 15 8 16 20 21 4 9 12 4 
+8 17 29 ^
+<D
+
+H>SHS Type 2 Strings<H
+D>
+69 1 5 3 11 15 12 24 31 23 1 6 28 2 8 31 6 7 30 5 19 23 12 6 9 31 19 17 24 25 
+22 6 12 16 3 7 9 9 11 29 4 11 2 5 13 29 10 12 30 32 18 28 18 27 3 30 4 4 26 6 
+13 31 13 2 11 7 24 4 17 29 12 ^
+95 0 21 19 21 23 11 42 36 2 13 4 1 33 22 16 27 9 4 33 16 3 30 15 11 32 13 17 38 
+32 9 38 4 36 15 32 27 19 42 18 6 36 22 10 29 12 25 40 15 29 23 28 30 4 8 11 24 
+9 10 31 28 43 23 16 29 33 5 40 26 3 19 12 36 43 5 35 37 5 14 11 45 35 16 10 8 
+32 4 15 35 26 2 39 22 37 22 30 29 ^
+106 1 18 14 51 2 6 32 51 9 32 50 44 46 51 8 11 53 45 55 16 10 3 52 8 20 20 46 
+46 13 32 2 46 50 43 25 54 9 31 29 2 47 15 29 24 45 44 18 37 14 28 39 36 44 47 
+16 50 10 44 24 53 35 22 40 20 15 51 22 18 22 42 6 54 49 38 21 7 13 30 16 7 52 
+16 22 13 38 7 11 44 33 9 25 13 37 42 14 45 53 30 38 5 25 5 35 38 22 28 53 ^
+127 0 58 35 43 28 5 28 63 8 12 25 9 47 53 29 62 7 37 2 3 48 5 12 55 56 28 35 12 
+63 6 58 27 27 48 44 35 14 17 22 56 10 8 1 16 15 42 63 14 51 57 19 41 7 8 56 47 
+34 52 22 48 60 43 9 1 52 4 21 49 61 18 50 23 13 46 62 23 45 62 9 56 18 23 31 8 
+30 27 36 13 38 4 58 53 47 24 18 41 58 19 12 18 52 42 29 44 45 26 63 34 32 41 64 
+15 26 55 19 2 49 6 30 53 13 54 12 53 37 12 37 43 ^
+148 0 60 4 51 47 58 38 17 63 33 23 28 43 12 69 70 33 17 12 50 18 18 36 45 2 67 
+4 45 20 4 33 38 29 45 8 22 58 39 71 38 32 53 35 19 53 31 29 51 35 4 63 18 33 26 
+47 70 9 64 62 63 30 15 1 35 28 16 40 20 14 50 33 19 38 30 27 55 10 16 46 47 7 
+55 12 53 26 56 33 29 55 25 17 48 43 21 43 18 24 63 27 68 46 38 33 35 10 18 11 
+27 5 9 58 35 70 36 36 39 47 2 10 66 47 5 18 21 44 71 51 57 3 22 7 56 55 28 25 
+14 40 16 24 48 37 66 50 24 45 18 39 53 55 ^
+165 1 15 62 35 29 15 40 19 76 67 4 5 71 46 61 26 8 77 48 1 23 12 60 40 24 44 33 
+29 42 73 66 49 61 20 30 1 54 52 42 39 64 23 65 37 24 20 11 26 66 22 77 22 57 7 
+38 57 33 61 73 7 64 1 49 35 76 14 27 21 45 68 38 58 73 13 72 47 73 33 8 66 23 
+38 4 56 77 47 10 71 13 20 31 41 6 51 3 18 17 61 47 14 48 76 46 28 34 43 1 56 4 
+25 7 65 41 1 34 37 23 59 59 27 26 13 15 14 75 60 14 1 28 59 26 65 61 16 23 17 
+28 6 19 2 35 49 30 29 48 2 63 73 59 1 3 76 41 11 19 18 43 54 63 67 51 4 9 78 60 
+66 ^
+181 0 18 19 84 17 12 10 57 18 77 51 52 16 39 74 49 52 63 38 72 2 15 64 83 62 49 
+56 11 26 68 58 83 33 23 50 63 71 53 27 84 22 39 41 52 58 11 64 7 60 45 70 22 5 
+73 38 30 30 48 21 75 80 40 21 8 53 9 26 30 34 81 71 71 51 23 75 33 41 23 32 5 8 
+66 40 72 40 16 66 45 14 48 34 21 41 27 3 55 27 37 23 41 65 4 57 51 74 22 19 75 
+42 16 19 46 16 10 48 20 19 37 41 14 57 9 17 55 38 5 60 7 46 20 43 36 39 52 20 
+10 62 45 23 46 7 35 75 29 70 35 36 34 25 12 15 84 26 10 6 71 29 79 33 32 25 59 
+76 82 64 58 7 8 19 41 74 2 53 65 24 1 55 51 36 21 79 7 ^
+184 1 60 66 66 6 3 9 73 12 7 40 70 18 71 70 65 51 14 14 27 50 9 87 81 50 22 19 
+40 37 16 79 12 34 37 76 82 10 61 7 81 49 67 26 45 82 50 81 63 45 69 31 31 76 51 
+9 59 34 51 54 34 83 10 33 51 86 81 82 69 18 8 22 64 19 86 62 58 33 37 17 34 5 
+29 83 42 76 50 54 66 39 9 1 36 43 17 65 6 35 56 72 71 83 88 10 1 8 87 22 6 21 
+78 25 89 43 62 40 55 85 31 89 74 63 46 28 24 26 31 17 7 8 27 19 12 85 17 20 27 
+77 10 2 54 80 17 52 74 76 69 78 11 20 80 4 29 24 85 75 18 39 23 70 83 29 57 67 
+72 70 33 4 15 46 42 2 69 13 53 33 69 64 33 64 14 40 69 59 78 54 ^
+193 1 68 43 95 53 38 58 55 28 20 16 67 48 17 86 32 44 68 67 28 16 14 79 25 15 
+72 67 50 80 18 30 10 75 1 60 45 87 78 28 95 49 63 70 59 26 6 51 73 60 65 18 26 
+8 87 5 58 31 25 57 40 46 78 57 34 78 61 36 66 57 38 80 22 32 68 71 30 74 37 81 
+66 77 66 55 2 51 24 93 61 40 68 45 61 12 63 24 89 59 52 72 43 20 20 69 36 40 88 
+46 9 62 55 77 84 20 18 6 77 15 52 39 75 3 26 4 85 17 62 29 11 92 46 58 29 59 28 
+42 80 71 96 2 49 85 37 63 4 61 14 2 53 87 25 86 6 75 76 93 41 39 93 92 42 56 41 
+63 26 28 18 77 11 50 78 79 1 12 12 91 29 13 58 5 56 92 66 59 4 39 47 95 5 5 62 
+33 13 80 27 ^
+203 1 35 28 11 7 20 7 17 3 3 30 89 13 65 56 66 63 22 82 16 31 55 56 77 91 91 71 
+101 13 10 85 101 95 17 99 98 91 33 14 20 48 32 7 64 29 38 35 25 4 95 23 34 1 85 
+81 23 31 96 71 84 50 15 79 47 25 51 45 35 66 19 61 60 9 31 93 64 70 30 42 86 53 
+1 71 46 42 22 38 96 10 99 34 76 26 55 73 63 63 97 23 92 81 64 46 1 30 31 35 86 
+91 88 64 87 16 37 69 84 94 60 100 3 47 52 8 71 87 57 29 76 43 18 45 46 15 65 12 
+44 42 66 60 15 68 19 58 39 62 76 9 92 101 57 32 4 34 15 41 62 32 89 71 43 35 31 
+41 21 17 82 33 96 27 62 29 82 57 46 62 15 24 99 37 83 40 52 46 56 80 98 3 91 74 
+6 27 7 58 94 10 41 79 97 84 77 74 26 99 35 ^
+212 1 26 101 17 91 45 97 80 59 102 30 68 4 85 9 4 39 16 18 85 70 11 87 62 72 78 
+38 3 41 53 82 82 35 18 13 94 64 52 39 77 59 26 9 65 46 64 98 32 29 86 79 16 63 
+54 76 56 98 16 98 78 22 72 33 103 104 52 84 12 65 15 85 101 97 84 31 51 26 100 
+100 38 80 13 2 78 7 24 44 84 103 27 7 28 16 33 99 25 103 54 14 42 62 87 92 27 
+22 42 5 52 100 84 73 72 63 24 48 56 52 23 5 17 76 31 1 95 58 43 60 50 62 30 23 
+35 79 20 35 3 72 32 45 51 87 41 84 27 79 77 70 102 15 54 15 100 8 52 69 105 3 
+30 84 42 93 66 89 69 74 24 33 42 97 4 38 99 106 13 93 6 106 74 100 54 45 21 59 
+56 37 9 50 32 75 79 31 77 9 61 1 8 68 6 60 81 7 100 99 14 61 48 25 73 26 70 72 
+94 34 ^
+233 0 11 98 110 88 35 110 35 64 49 88 93 28 85 6 78 65 90 52 24 97 51 39 51 59 
+23 1 3 49 33 11 78 27 35 55 64 5 102 4 70 25 56 58 38 66 11 31 96 66 104 59 41 
+86 58 29 79 41 40 72 51 12 92 34 52 44 69 104 21 97 89 96 48 21 4 61 40 28 67 
+34 23 85 44 22 62 52 33 84 23 30 73 74 4 79 12 81 47 80 53 47 89 40 19 80 62 34 
+61 29 41 95 43 1 70 63 55 53 18 19 13 48 10 19 89 49 4 52 53 56 76 10 8 104 77 
+15 28 38 75 109 3 85 90 8 40 8 93 90 43 39 14 60 17 36 78 56 105 80 35 75 36 58 
+82 50 100 98 45 74 13 66 95 72 71 95 34 14 98 72 33 38 37 52 6 14 107 59 3 29 
+61 67 98 92 5 93 17 98 36 87 41 75 71 57 88 17 25 91 84 3 58 20 92 69 51 50 36 
+31 14 25 18 30 18 1 41 104 30 82 59 87 70 34 96 28 47 62 81 103 48 ^
+234 1 63 90 108 108 102 64 82 88 4 111 76 97 22 1 108 41 34 91 33 20 25 24 26 8 
+83 11 31 7 85 109 106 4 105 85 68 28 33 99 53 8 16 12 11 74 17 83 66 70 16 30 9 
+67 68 34 24 81 47 92 72 47 37 33 38 92 17 8 28 88 22 62 69 32 89 75 3 72 96 85 
+13 105 24 38 37 94 115 83 72 108 114 24 93 76 103 60 99 102 9 43 10 59 95 46 33 
+93 15 26 69 44 2 86 107 55 45 61 65 92 66 9 55 39 70 83 29 98 67 13 111 15 20 
+31 62 8 2 51 20 19 33 44 14 115 71 112 97 10 41 28 53 51 26 57 15 38 98 55 106 
+22 56 31 50 95 107 110 84 70 10 108 96 73 100 25 36 55 88 71 63 96 30 90 96 79 
+22 7 30 23 28 59 89 8 51 99 47 86 34 18 43 65 98 104 107 49 7 79 71 8 57 21 29 
+80 2 74 78 44 57 9 61 22 13 68 52 91 74 98 43 30 58 68 95 101 72 102 76 42 99 
+61 ^
+249 0 27 117 45 119 80 2 59 52 8 76 20 94 102 69 96 42 46 106 67 9 110 89 71 69 
+34 31 15 85 16 29 100 82 37 62 68 95 108 44 23 114 34 36 56 93 11 30 96 12 31 
+67 14 114 14 66 70 30 81 46 53 119 85 6 104 47 92 72 70 5 70 15 115 68 105 33 
+97 13 85 106 14 61 29 22 86 45 57 69 91 38 38 28 66 13 60 95 103 3 15 5 113 38 
+23 62 5 65 94 107 73 104 37 47 102 117 3 78 35 7 95 56 78 45 52 28 46 43 37 32 
+53 19 55 29 47 97 76 115 83 71 11 45 62 73 99 116 2 24 116 7 28 41 2 29 37 52 
+23 5 118 79 31 57 89 61 24 101 78 50 93 73 41 7 33 45 47 24 1 48 73 36 3 25 87 
+46 28 108 54 68 53 67 119 28 36 118 104 42 88 27 112 4 74 85 1 63 39 97 71 74 
+75 76 10 49 12 79 11 50 103 118 94 117 118 37 27 12 94 60 28 51 47 82 110 17 15 
+105 23 52 43 12 21 22 81 41 12 74 90 42 108 117 98 67 4 69 85 ^
+243 0 76 81 26 101 13 68 62 106 87 19 98 32 81 63 79 93 31 121 123 75 52 11 66 
+41 54 87 38 5 104 62 51 38 55 29 31 120 44 16 48 94 46 105 91 66 78 27 43 6 64 
+2 55 79 75 84 113 22 4 113 109 31 33 17 96 11 29 63 98 103 107 116 34 14 9 95 
+38 18 51 75 33 109 118 55 66 4 76 7 75 70 82 74 23 1 26 69 40 112 99 47 65 31 
+70 119 52 103 88 85 86 28 16 12 76 25 22 78 64 21 86 27 61 77 72 108 2 18 106 
+119 121 54 16 85 72 2 73 26 88 66 60 80 35 24 117 63 24 44 67 52 122 119 33 72 
+16 99 98 69 54 19 42 28 53 114 32 117 81 100 57 49 123 56 21 68 80 53 95 1 45 
+95 107 98 87 1 27 24 99 116 16 67 1 113 91 84 25 40 25 72 3 28 90 87 112 80 16 
+117 45 77 36 90 105 59 88 122 64 108 108 71 98 18 50 115 93 105 77 35 6 46 55 
+47 102 4 26 87 111 120 81 113 4 57 105 3 84 94 115 61 73 ^
+255 1 91 47 51 9 57 9 55 94 61 61 68 46 107 6 35 81 114 78 96 74 14 89 73 67 67 
+69 113 107 11 98 113 109 20 92 17 67 70 88 57 10 124 9 60 122 93 91 45 7 15 24 
+51 5 98 115 24 49 90 104 117 66 128 94 64 80 12 43 91 46 111 59 58 77 30 14 88 
+60 123 68 41 44 68 40 104 118 41 43 93 90 105 92 16 127 26 54 125 114 79 71 24 
+48 21 25 118 40 103 49 91 44 67 65 25 119 109 18 48 23 69 112 38 61 64 87 84 
+104 119 110 122 92 22 1 8 83 34 100 32 62 41 46 112 34 102 76 56 39 4 127 30 13 
+19 110 124 7 16 128 95 4 124 11 104 116 126 49 95 3 55 96 70 90 101 4 122 96 75 
+118 39 128 99 92 18 42 20 87 83 35 75 111 61 67 71 28 101 9 56 34 105 95 71 23 
+73 71 26 57 15 23 76 55 99 89 128 98 117 68 43 88 62 38 62 39 2 83 36 15 26 60 
+128 96 73 74 10 1 12 42 22 2 77 33 33 32 57 13 14 82 57 12 39 3 58 80 14 87 85 
+44 69 109 119 ^
+283 0 102 55 53 41 60 88 25 67 58 76 44 22 68 118 108 40 95 96 81 90 85 28 77 
+18 11 37 72 93 60 110 124 119 95 131 91 37 109 126 8 73 69 72 80 17 83 5 76 20 
+32 15 10 1 103 18 22 116 98 9 51 104 102 44 33 15 12 24 31 89 1 6 28 101 8 64 
+72 106 30 5 52 89 111 39 108 64 85 17 57 124 22 105 78 115 3 40 108 66 108 77 
+128 103 44 35 38 13 95 10 111 63 98 117 61 51 126 69 96 70 70 59 39 13 97 33 
+112 2 77 7 123 70 83 29 66 67 49 79 19 104 115 14 60 2 55 40 71 33 28 114 51 91 
+17 46 45 128 57 87 62 25 115 38 50 55 90 74 8 51 102 79 43 94 36 122 94 12 41 
+36 25 104 91 24 7 99 80 30 126 32 63 122 107 114 27 28 79 41 12 35 51 115 122 
+70 22 79 65 2 88 27 17 59 15 23 44 57 5 65 6 26 78 80 125 93 84 100 45 22 129 
+68 36 111 74 118 11 50 42 120 47 21 8 86 112 26 67 60 99 45 93 47 8 38 59 52 56 
+124 20 82 18 117 24 18 46 106 19 117 26 41 47 45 130 7 15 1 4 5 100 10 85 50 44 
+11 48 92 119 108 42 118 125 ^
+272 0 8 61 99 70 96 20 87 123 134 82 22 2 110 118 33 86 5 7 5 94 56 15 60 96 54 
+13 22 55 99 4 25 105 17 37 69 10 38 117 117 30 70 13 9 109 115 62 94 52 66 117 
+100 135 7 75 23 5 81 110 31 118 29 1 62 11 41 88 109 119 102 37 3 30 123 47 31 
+56 134 29 124 116 118 99 21 56 77 91 23 37 135 81 44 51 67 95 51 133 30 57 67 
+116 122 48 100 7 132 97 106 69 93 4 95 125 102 103 119 81 57 133 96 37 118 50 
+117 113 81 127 17 45 103 32 121 129 60 43 65 127 30 36 132 110 52 53 35 71 12 
+76 22 72 130 112 99 76 26 21 73 63 63 97 23 58 115 132 114 1 132 31 35 18 23 54 
+30 53 118 37 35 84 94 60 100 3 47 18 110 105 87 57 63 76 43 52 45 46 49 65 12 
+10 42 66 60 117 34 19 92 5 28 76 9 126 101 125 32 38 34 15 7 62 32 21 3 43 69 
+31 109 123 51 116 135 130 129 130 63 14 57 80 62 15 126 31 105 83 108 120 80 
+124 46 98 105 91 6 6 27 7 58 128 78 7 79 63 84 77 74 128 65 61 95 121 17 24 123 
+117 51 122 ^
+284 0 44 71 43 20 126 58 53 47 98 18 19 119 93 29 70 39 94 112 44 115 135 98 82 
+10 67 29 102 113 68 80 19 75 1 91 114 87 80 7 40 37 86 120 16 104 136 117 82 
+138 32 65 114 119 137 121 8 12 46 126 26 119 73 130 60 76 113 100 14 133 26 116 
+34 120 80 95 84 53 15 24 44 51 4 10 23 77 24 99 66 37 54 63 42 136 21 34 76 5 
+17 128 101 1 59 40 113 112 32 97 31 93 105 79 91 18 39 1 103 132 51 68 124 111 
+13 97 43 128 69 84 85 72 15 12 26 87 16 16 92 101 13 77 4 118 89 103 56 42 16 
+60 44 39 126 46 18 83 93 41 105 3 82 106 115 91 6 4 54 115 15 120 109 113 48 41 
+9 95 20 62 67 105 111 25 132 7 116 46 138 44 83 61 124 131 35 107 6 109 81 114 
+67 41 137 77 56 74 73 34 12 14 69 52 11 98 47 54 83 81 6 1 15 88 35 139 80 83 
+49 89 27 47 130 92 133 87 51 112 76 49 109 49 57 93 73 22 117 50 64 58 97 139 
+36 131 111 133 58 33 8 88 55 38 90 46 30 118 57 29 82 74 41 117 38 46 94 92 5 
+105 15 117 70 103 68 60 120 48 21 110 85 40 81 66 ^
+291 0 46 113 52 134 79 74 64 57 18 23 9 52 8 16 103 57 138 59 59 65 92 2 7 130 
+92 8 34 40 86 131 140 100 112 4 42 1 110 108 43 37 15 67 19 35 94 61 130 98 35 
+88 34 65 104 56 126 118 50 87 10 81 109 90 86 118 32 6 114 88 39 38 39 62 3 12 
+134 72 137 35 75 81 115 106 140 112 11 123 41 103 45 95 84 71 107 13 26 110 96 
+62 16 109 84 59 53 38 27 8 28 13 32 137 17 138 41 122 36 99 65 99 83 36 112 29 
+49 70 96 126 136 131 116 3 18 17 126 142 14 37 141 141 123 42 13 20 83 42 139 
+83 54 49 58 42 7 137 29 48 16 121 127 34 52 140 106 128 58 36 124 83 24 69 54 
+61 112 17 6 95 97 24 57 86 124 59 71 119 67 1 109 54 68 49 57 132 32 5 71 113 
+40 80 104 75 106 133 31 126 130 104 62 9 39 44 66 116 141 135 96 132 19 41 121 
+126 124 77 8 4 60 82 6 101 124 89 51 123 48 40 85 77 21 112 10 69 66 115 87 16 
+108 30 84 65 80 103 32 131 134 73 47 10 63 39 50 93 37 135 114 69 48 34 58 23 
+27 133 37 9 40 98 41 115 99 70 83 29 42 67 133 55 79 80 91 122 12 2 115 112 47 ^
+293 1 33 13 99 138 1 42 89 118 87 113 99 12 134 142 100 38 5 55 75 14 110 108 
+42 64 130 79 138 62 64 69 57 11 123 25 59 16 111 94 24 65 30 51 119 48 107 92 
+84 69 28 136 143 54 20 6 70 47 142 64 4 65 59 73 99 134 146 102 125 116 57 137 
+137 72 48 128 78 5 80 63 54 85 30 22 129 68 21 21 74 28 128 107 27 60 2 93 95 
+71 37 11 37 15 39 102 3 104 65 80 59 52 113 34 20 67 60 27 81 135 46 106 106 
+102 68 128 17 15 100 124 15 43 136 122 100 67 142 35 14 53 120 2 89 93 99 73 9 
+122 39 77 15 96 90 43 79 134 60 92 105 55 96 31 119 77 97 72 23 140 38 30 43 83 
+136 88 107 117 72 109 118 58 91 119 73 95 100 59 138 123 54 49 143 50 133 66 
+106 45 80 88 42 93 5 59 77 101 74 110 104 40 92 19 77 76 86 102 129 3 144 101 
+139 134 56 90 18 91 94 85 55 10 137 11 58 1 107 113 70 22 7 56 29 143 111 8 46 
+45 116 122 129 89 7 121 53 95 14 49 118 62 125 91 37 97 15 35 100 63 140 63 50 
+51 58 26 127 6 45 59 102 121 114 85 141 135 10 72 19 106 66 66 41 53 13 38 1 21 
+103 50 108 46 119 ^
+297 1 46 31 132 112 28 63 124 97 129 43 40 72 99 107 132 137 96 139 99 145 121 
+144 118 37 81 39 94 60 55 109 47 109 110 75 42 12 139 137 43 128 106 107 19 126 
+12 101 148 127 15 117 125 125 62 96 13 76 70 96 101 110 138 8 95 76 143 17 32 
+97 79 149 39 31 94 123 21 41 135 55 84 70 33 135 118 50 62 121 81 1 45 144 93 
+60 5 64 137 8 105 91 82 67 27 113 119 53 18 98 79 48 84 32 135 128 5 1 20 76 17 
+85 108 72 36 141 140 49 150 105 104 3 149 14 54 18 148 64 49 125 37 28 28 101 
+22 104 91 32 82 117 12 114 69 58 2 58 115 9 108 47 59 65 14 92 7 4 86 98 16 82 
+92 95 38 94 10 10 48 97 104 66 115 97 142 115 122 119 40 97 16 32 47 34 88 89 
+26 50 12 76 80 51 40 9 133 24 44 40 122 84 108 22 142 140 99 44 15 54 8 42 125 
+150 130 21 79 124 62 46 119 15 29 91 57 150 42 138 71 61 68 80 114 6 1 70 121 
+18 35 113 56 87 86 10 73 14 29 41 72 89 1 133 87 101 123 59 90 142 77 133 52 78 
+48 34 138 134 27 17 60 131 147 61 93 148 39 132 49 62 71 36 91 4 139 49 100 120 
+43 113 144 30 94 73 127 40 125 ^
+313 1 35 97 95 76 105 88 32 138 30 69 61 40 47 21 107 6 39 81 114 53 125 53 147 
+14 4 73 146 96 98 13 136 11 98 117 138 153 67 146 71 99 88 7 139 24 13 35 47 97 
+145 74 36 119 3 51 84 48 119 53 49 15 79 17 120 103 148 64 30 41 97 120 75 111 
+63 58 131 134 18 13 10 48 18 16 48 43 15 54 18 41 47 122 144 80 92 145 77 1 33 
+89 54 46 78 48 21 54 43 40 53 24 16 73 42 94 29 44 34 151 152 23 123 12 142 140 
+43 37 88 29 19 35 72 96 151 130 62 112 34 36 91 120 50 112 138 2 105 60 68 137 
+131 5 17 19 139 74 11 120 78 149 58 128 15 104 16 126 78 20 57 134 71 49 90 76 
+108 126 100 54 68 39 132 153 42 147 146 124 62 87 35 75 61 65 46 100 82 105 113 
+31 63 5 95 54 71 77 127 150 80 36 144 2 130 59 74 39 3 152 121 122 18 117 12 
+117 141 118 135 62 36 69 5 39 53 150 52 153 143 30 66 96 126 131 56 137 8 7 86 
+142 14 7 111 141 93 136 137 134 43 12 89 23 44 9 152 146 121 97 19 38 110 91 67 
+14 32 110 66 68 8 130 84 73 118 59 24 41 72 121 150 55 37 138 27 104 66 124 9 
+51 109 47 125 109 148 8 29 47 72 146 149 61 93 10 20 54 15 76 133 125 106 110 
+67 ^
+330 0 23 9 26 136 27 51 115 122 44 106 6 146 108 113 85 51 8 96 47 56 137 62 59 
+89 143 71 140 14 85 156 139 99 154 30 53 115 35 147 108 148 58 52 28 103 19 92 
+95 152 152 10 11 13 155 67 11 83 101 69 153 152 45 141 14 120 129 140 119 59 2 
+89 73 70 83 29 16 67 81 29 1 54 65 96 117 2 37 47 128 33 3 89 108 98 139 49 78 
+27 103 39 119 94 132 90 38 132 55 65 131 90 58 2 54 100 69 118 22 44 19 7 148 
+93 25 29 123 81 64 131 55 30 1 89 38 97 82 64 9 28 86 123 151 10 133 40 154 102 
+4 111 65 9 63 59 124 116 72 105 76 57 137 97 32 145 108 78 112 50 43 34 75 20 
+22 129 68 11 118 74 125 118 57 17 20 129 53 65 61 144 1 17 142 156 52 100 54 15 
+20 59 52 63 131 20 57 124 31 125 46 106 76 92 8 98 154 152 80 114 15 140 136 
+112 100 17 92 25 151 150 80 99 69 83 49 43 156 102 19 57 122 96 30 3 39 134 40 
+32 75 5 76 127 138 99 17 57 52 150 130 18 127 33 23 116 107 78 77 77 42 69 68 
+48 41 69 33 75 40 49 128 103 4 146 93 10 83 66 96 152 30 38 12 33 5 39 47 41 34 
+60 74 20 42 156 67 46 56 102 89 3 124 81 99 104 56 50 8 61 74 55 15 87 108 28 
+138 47 93 60 2 124 46 126 103 91 145 36 25 116 122 51 ^
+322 0 75 7 107 158 81 105 154 90 20 125 77 114 69 92 7 58 21 98 154 50 128 149 
+117 127 153 45 3 18 121 86 29 71 79 101 2 5 22 143 10 27 53 146 157 148 112 33 
+22 80 123 24 147 1 112 82 159 63 74 97 109 33 151 32 89 87 132 117 46 129 59 
+115 91 114 118 37 21 9 94 60 25 89 47 79 110 55 12 143 99 87 43 88 56 57 160 76 
+12 71 128 77 146 117 95 105 42 66 3 76 20 76 101 100 118 149 45 26 143 148 32 
+57 39 129 19 31 84 123 1 152 135 5 54 30 13 125 68 30 62 101 51 142 5 94 83 20 
+116 24 107 109 105 91 42 17 27 93 69 3 139 68 79 38 84 2 85 128 126 122 131 46 
+17 35 98 42 26 111 100 29 120 55 84 114 109 145 14 18 138 14 9 85 7 18 129 91 2 
+94 51 133 82 87 123 64 39 8 103 38 75 110 78 7 9 45 115 42 138 135 86 78 16 62 
+52 75 159 54 151 121 149 77 74 16 85 47 102 105 82 119 10 67 137 153 148 135 28 
+49 26 151 153 36 80 11 130 113 24 44 30 102 24 58 133 122 140 99 24 156 54 119 
+42 115 140 90 132 19 94 2 157 99 136 19 71 7 130 153 108 51 21 58 70 74 137 1 
+40 111 149 5 103 6 27 76 141 23 125 140 1 72 29 152 103 87 51 93 29 80 132 77 
+123 153 68 159 14 98 114 158 121 158 81 131 ^
+322 0 35 93 109 125 119 10 10 19 135 26 4 74 135 35 120 129 113 92 17 29 47 88 
+14 159 149 87 45 36 75 68 22 138 20 59 61 144 151 11 107 6 153 81 114 43 85 157 
+97 148 118 73 126 56 58 137 96 11 98 67 98 103 57 146 21 59 88 151 139 148 127 
+25 17 47 115 34 160 109 107 51 64 28 69 13 49 149 69 141 90 93 118 64 10 1 67 
+80 35 111 13 58 101 124 132 147 154 18 162 6 162 33 5 34 142 41 161 82 114 70 
+92 145 57 155 137 114 79 44 36 48 48 21 14 13 40 33 14 150 33 32 54 143 14 4 
+101 142 23 93 136 132 120 147 17 38 163 143 5 52 46 151 130 32 72 34 124 150 51 
+100 112 128 126 65 10 28 87 81 159 131 19 99 54 125 110 58 119 28 78 129 104 
+140 126 38 154 27 114 61 153 90 66 98 76 50 158 48 39 82 123 22 147 136 114 52 
+37 35 75 41 15 150 60 52 55 103 21 23 129 95 24 71 47 97 130 50 140 144 106 100 
+9 64 19 117 122 71 92 8 77 156 97 121 98 85 2 36 39 109 143 23 120 156 133 93 
+154 36 66 116 131 160 127 162 161 46 142 14 141 81 141 63 86 117 104 3 146 39 
+127 34 133 102 106 91 57 9 28 60 61 7 158 12 80 26 8 122 80 44 63 68 49 158 21 
+32 81 150 15 141 108 161 64 46 124 123 31 99 27 105 109 98 112 144 ^
+336 1 34 161 107 149 48 67 138 109 156 104 37 133 60 80 84 81 160 9 16 96 164 1 
+95 112 4 86 163 116 98 103 55 31 8 56 37 36 127 32 9 89 103 31 100 161 85 106 
+119 89 154 43 115 162 137 108 128 38 42 155 103 9 62 65 102 122 10 138 160 125 
+47 158 43 91 69 123 132 35 121 4 110 89 130 69 29 139 69 53 70 83 29 163 67 41 
+9 108 34 45 76 87 2 144 164 98 33 160 79 78 48 89 9 38 134 93 146 79 54 122 80 
+38 112 55 55 101 70 8 129 44 70 59 98 149 24 136 124 138 63 25 166 83 51 34 91 
+45 30 118 59 28 87 72 44 116 28 36 103 101 113 10 114 62 111 71 65 126 53 19 
+114 86 42 85 36 57 137 57 159 95 88 78 72 20 23 14 65 10 22 129 68 1 68 74 75 
+108 7 7 147 109 13 35 51 104 158 164 122 126 2 50 4 132 127 59 52 13 81 20 47 
+107 74 148 115 46 106 46 82 115 68 144 142 60 104 15 90 136 102 100 134 42 15 
+141 100 40 49 49 73 166 13 156 82 166 37 82 96 137 130 166 134 20 139 45 122 56 
+107 98 79 124 17 32 130 120 165 77 23 130 96 67 68 47 37 12 29 18 38 158 19 160 
+55 147 39 118 83 121 96 43 137 33 66 86 112 147 155 149 140 5 19 17 148 161 10 
+44 159 146 57 16 26 102 49 3 104 61 59 74 56 10 165 31 54 25 142 157 37 58 165 
+128 154 73 50 149 94 137 ^
+330 1 61 51 65 132 23 169 116 122 14 66 7 98 131 72 69 127 72 163 125 68 69 51 
+47 159 31 164 71 118 50 83 113 81 127 153 45 137 134 121 68 163 26 43 65 127 
+166 138 98 144 18 53 137 139 148 76 158 4 62 78 167 102 144 94 55 141 63 29 97 
+91 24 115 166 80 69 132 99 1 120 23 88 64 87 118 37 137 152 94 60 168 71 47 52 
+110 37 155 125 63 42 43 52 11 12 151 31 12 44 110 32 128 117 68 87 24 39 164 76 
+145 58 101 91 100 140 151 143 130 32 21 3 111 1 31 75 123 153 116 135 130 27 
+164 165 116 23 12 62 83 24 133 139 49 74 154 80 158 80 64 105 91 6 142 27 75 24 
+128 112 41 79 29 84 145 40 128 99 95 95 19 17 160 89 15 17 84 64 11 93 10 66 78 
+73 127 148 18 129 139 143 49 150 9 84 82 154 85 15 88 82 60 87 19 12 133 58 20 
+39 65 51 141 134 27 70 167 120 117 86 60 16 44 16 57 132 18 142 85 104 59 47 
+141 58 2 66 96 46 119 153 40 110 126 103 90 144 13 26 106 144 80 145 134 103 95 
+24 44 21 84 140 13 97 104 140 99 6 147 54 83 42 106 131 54 96 135 67 118 121 81 
+109 10 53 132 112 117 81 33 155 49 61 38 119 1 13 102 131 148 94 131 143 67 123 
+148 89 104 135 72 145 152 76 87 6 66 2 71 123 77 114 108 59 123 166 62 96 140 
+94 149 116 169 ^
+349 0 125 17 93 82 80 110 156 147 156 99 154 4 29 90 163 120 84 113 56 8 157 29 
+61 169 141 113 78 48 50 13 138 11 50 61 99 106 2 107 6 117 81 114 34 49 112 52 
+130 82 73 108 20 22 110 60 11 98 22 62 58 48 146 149 23 88 142 139 121 91 16 
+163 2 88 171 133 100 62 51 46 10 24 150 49 131 60 114 63 84 91 64 165 138 40 44 
+172 111 141 58 74 115 96 129 145 164 153 170 126 24 169 16 115 41 125 46 87 61 
+92 145 39 155 92 78 70 35 27 21 48 21 151 159 40 15 5 132 170 23 18 107 160 150 
+56 133 23 66 109 123 102 102 172 166 145 116 151 34 1 151 130 5 36 34 97 114 15 
+82 128 112 119 99 29 138 165 42 36 159 95 19 63 36 89 101 40 92 1 33 93 104 113 
+126 2 136 96 52 108 90 57 89 31 5 113 30 39 37 96 4 147 127 105 43 165 35 75 23 
+143 105 24 25 10 94 12 160 102 95 170 71 20 70 112 23 95 144 61 73 137 55 1 81 
+95 26 65 172 41 147 79 103 80 40 121 36 12 64 98 169 93 111 115 48 127 9 39 107 
+131 115 118 162 161 10 142 14 123 54 141 36 41 99 77 140 128 167 82 25 106 57 
+70 64 21 19 15 34 126 149 167 53 163 127 86 35 8 54 23 40 140 3 169 45 150 152 
+96 81 143 28 28 124 87 13 90 9 87 109 53 67 164 28 131 89 149 42 55 126 79 132 
+74 19 133 30 68 72 75 148 9 10 72 152 144 83 106 153 74 163 98 152 ^
+375 1 94 28 13 8 20 28 18 118 5 140 89 67 171 64 152 85 61 101 80 154 149 34 
+115 135 128 108 110 20 33 128 103 35 38 57 95 10 111 151 98 29 149 7 82 69 96 
+114 26 103 171 101 53 121 24 2 121 51 35 70 83 29 154 67 5 167 63 16 27 58 60 2 
+99 128 71 33 160 70 51 3 44 149 2 89 84 101 43 18 113 71 38 94 55 46 74 52 139 
+102 35 43 50 80 122 6 100 88 129 36 25 148 47 24 7 55 36 30 82 32 19 78 63 26 
+71 28 167 85 56 167 95 159 78 26 66 35 65 90 44 159 105 59 15 67 57 137 21 132 
+50 70 78 36 169 5 172 56 1 22 129 68 168 23 74 30 99 138 174 120 91 153 8 42 68 
+158 155 104 99 133 5 135 96 82 59 52 144 36 20 38 62 29 112 106 46 106 19 73 70 
+41 135 133 42 95 15 45 136 93 100 98 173 6 132 55 4 4 31 64 130 162 156 64 157 
+19 46 96 92 103 139 134 2 94 18 86 38 89 62 61 79 157 14 112 111 156 32 14 85 
+78 31 59 20 1 161 169 149 29 122 150 133 37 102 30 109 65 85 51 174 110 164 66 
+77 76 111 119 131 95 5 1 166 103 134 141 17 158 123 137 48 165 175 102 13 3 86 
+43 23 47 56 150 165 4 36 174 115 157 168 13 147 119 109 55 41 140 67 27 31 27 
+53 126 17 163 116 122 160 60 7 92 113 66 45 109 60 151 125 62 39 39 17 153 13 
+152 53 94 50 53 89 57 127 153 45 119 104 121 56 145 172 19 41 103 166 108 68 
+126 12 53 131 127 148 52 134 168 50 48 155 72 132 82 37 129 63 175 160 ^
+366 1 73 15 79 139 71 51 132 81 135 111 166 61 37 60 118 37 92 134 94 60 150 53 
+47 25 110 19 137 107 27 176 43 16 145 146 142 165 12 17 92 166 110 117 41 69 6 
+12 164 76 109 40 101 82 82 131 134 115 143 112 32 164 146 93 162 31 66 123 144 
+80 135 94 137 156 107 157 173 62 65 176 124 112 4 65 127 44 131 53 19 105 91 
+149 106 27 57 158 92 85 14 79 20 84 127 174 128 72 68 59 171 17 124 80 167 8 57 
+28 172 66 144 48 42 37 109 121 18 120 103 116 13 132 39 73 145 76 158 43 82 33 
+51 153 164 97 13 2 3 20 24 114 98 9 25 131 102 99 86 42 16 26 159 39 105 161 
+133 49 59 41 20 105 31 136 30 87 10 119 135 13 83 99 58 45 99 156 26 61 135 143 
+80 118 107 76 77 24 44 12 66 95 147 61 86 140 99 167 138 54 47 42 97 122 18 60 
+90 40 73 85 63 82 1 35 96 94 81 54 15 128 40 52 2 101 1 165 93 113 130 85 95 98 
+58 105 112 53 68 108 72 100 152 49 87 140 39 154 62 114 77 105 63 50 87 157 26 
+78 122 67 140 71 170 119 5 93 64 50 104 144 129 138 75 130 4 178 60 139 120 54 
+113 32 2 133 17 43 163 129 89 72 149 155 30 38 7 138 5 44 61 69 76 175 107 6 93 
+81 114 28 25 82 22 118 58 73 96 175 177 92 36 11 98 171 38 28 42 146 125 178 88 
+136 139 103 67 10 151 151 70 153 115 94 32 51 34 177 173 132 49 119 54 96 45 78 
+73 64 159 120 22 20 154 111 117 58 56 109 72 143 ^
+372 1 136 146 144 170 90 15 169 180 88 41 89 10 60 52 92 145 21 155 47 42 61 26 
+18 176 48 21 124 141 40 179 178 114 143 14 164 71 142 132 11 124 23 39 82 114 
+84 57 163 130 127 89 133 16 138 151 130 160 34 70 78 161 64 92 112 110 72 175 
+102 138 179 173 159 59 19 27 18 53 92 22 65 156 170 57 104 86 126 148 118 155 
+78 43 63 90 48 80 168 142 68 12 39 174 69 168 147 118 96 34 129 35 75 5 107 60 
+170 180 147 85 3 133 75 95 152 71 175 43 94 178 50 144 16 46 101 46 165 45 68 
+163 38 172 5 138 61 85 62 177 76 36 167 19 53 151 66 66 97 3 100 164 12 98 131 
+70 109 162 161 156 142 14 105 27 141 9 178 81 50 113 110 131 37 16 79 12 34 37 
+167 173 10 152 7 81 140 158 26 136 82 50 172 154 45 160 31 122 167 142 9 150 
+125 51 54 125 174 10 124 51 177 81 173 69 109 8 22 155 19 86 62 149 33 37 108 
+34 96 29 174 133 167 50 54 66 130 9 1 36 134 108 65 97 126 56 163 71 83 88 10 1 
+8 178 22 6 112 169 116 89 43 153 40 146 85 31 89 74 154 137 28 115 117 122 108 
+98 8 27 110 103 176 17 20 27 77 10 93 145 80 17 143 165 76 69 78 102 20 91 171 
+95 29 115 176 166 109 39 23 70 83 29 148 67 163 161 33 4 15 46 42 2 69 104 53 
+33 160 64 33 155 14 131 160 59 78 71 19 176 107 65 38 82 55 40 56 40 115 84 29 
+25 44 68 104 176 76 64 123 18 25 136 23 6 171 31 30 30 58 14 13 72 57 14 41 177 
+^
+363 0 135 69 16 167 79 143 46 178 26 3 65 58 36 135 97 35 175 51 152 57 137 173 
+108 10 54 78 4 153 173 164 48 177 22 129 68 168 167 74 174 91 106 174 96 75 129 
+168 34 36 158 147 88 75 101 149 103 64 42 59 52 112 180 20 30 22 173 80 98 46 
+106 179 65 30 17 127 125 26 87 15 5 136 85 100 66 141 182 124 15 156 148 15 56 
+98 146 156 48 149 3 14 96 52 79 115 134 170 54 178 54 22 73 30 45 39 133 182 96 
+103 148 176 6 45 62 183 51 180 153 145 145 117 21 90 118 109 21 62 22 101 49 53 
+11 142 86 132 66 69 44 79 87 115 55 5 169 150 63 110 109 177 150 91 129 40 149 
+159 102 165 3 70 27 175 23 56 126 165 164 20 158 91 157 136 157 131 111 69 39 
+33 132 43 19 175 179 37 118 9 155 116 122 128 52 7 84 89 58 13 85 44 135 125 54 
+183 23 161 145 173 136 29 62 50 13 57 25 127 153 45 95 64 121 40 121 140 171 9 
+71 166 68 28 102 4 53 123 111 148 20 102 160 34 8 139 32 116 66 13 113 63 143 
+97 63 10 59 124 66 41 132 71 115 106 151 46 22 45 118 37 67 124 94 60 140 43 47 
+10 110 9 127 97 7 156 43 180 125 126 137 145 12 2 82 146 100 117 26 59 180 181 
+164 76 89 30 101 77 72 126 114 95 143 102 32 149 131 83 157 31 61 123 139 60 
+135 74 169 122 151 102 137 168 62 55 166 119 97 163 60 112 24 116 38 178 105 91 
+134 86 27 47 138 72 70 183 79 15 84 117 154 128 57 53 39 161 88 ^
+393 1 92 72 151 33 183 164 42 112 32 10 5 93 97 18 112 71 92 168 116 179 186 65 
+137 68 134 3 82 9 19 121 148 65 160 173 158 167 90 66 180 172 99 86 83 86 26 16 
+10 135 23 81 137 125 17 19 25 183 73 7 104 185 79 165 119 119 176 59 75 18 5 59 
+132 26 21 127 119 80 94 83 52 61 24 44 4 50 55 115 29 70 140 99 159 130 54 15 
+42 89 114 173 28 50 16 33 53 47 58 180 19 64 78 49 30 186 104 32 44 157 85 1 
+149 85 97 114 77 63 58 50 89 80 21 36 84 72 60 152 25 87 108 15 138 54 106 77 
+97 23 42 55 149 181 62 106 43 132 31 138 111 176 93 40 10 96 128 105 114 43 98 
+4 146 20 107 120 14 113 181 101 1 19 155 113 57 64 117 131 6 22 186 138 184 36 
+61 29 36 175 107 6 61 81 114 20 180 42 169 102 26 73 80 151 153 68 4 11 98 139 
+6 175 34 146 93 154 88 128 139 79 35 2 135 119 46 129 91 86 179 51 18 169 141 
+108 49 103 46 72 21 70 49 64 151 96 185 175 130 111 85 58 32 101 40 101 131 136 
+139 170 70 10 169 175 73 41 69 177 45 47 92 145 11 155 22 22 56 21 13 166 48 21 
+109 131 40 174 178 104 128 9 149 51 132 122 173 119 23 24 67 109 74 32 158 110 
+117 74 123 6 118 151 130 150 167 34 55 58 146 54 72 112 105 57 160 82 123 159 
+153 159 39 19 7 8 33 87 12 50 146 150 37 104 71 126 133 108 145 68 38 38 90 43 
+75 148 122 43 2 39 154 54 163 147 113 91 29 109 35 75 182 87 35 155 170 127 80 
+185 118 60 95 142 71 165 28 84 168 25 144 178 31 81 41 160 25 53 143 ^
+381 1 14 172 163 130 45 69 46 145 36 36 151 169 13 135 42 26 81 153 76 148 178 
+90 131 30 101 162 161 132 142 14 89 3 141 175 146 65 26 89 94 99 187 8 55 162 2 
+13 143 173 2 120 173 41 132 150 2 112 42 18 140 130 37 128 23 106 159 118 167 
+150 101 11 30 109 150 184 124 19 169 73 165 53 109 158 172 147 11 46 38 149 25 
+21 92 184 64 179 158 133 135 34 38 58 114 9 183 4 118 76 49 89 102 40 163 47 75 
+80 176 175 8 154 14 180 104 153 84 89 11 129 8 138 85 181 73 66 154 121 20 115 
+93 114 108 82 182 19 86 103 176 183 186 177 53 10 69 137 56 1 135 141 68 69 54 
+86 12 75 171 87 187 107 144 150 93 23 7 70 83 29 140 67 139 153 183 178 189 30 
+18 2 29 72 29 33 160 56 9 123 164 107 136 19 70 31 177 152 99 57 38 66 55 32 32 
+24 83 60 21 1 36 52 80 168 44 32 115 184 25 120 181 172 155 189 22 30 26 180 5 
+64 49 188 1 28 111 57 176 167 67 131 22 160 186 169 65 34 30 117 91 17 163 39 
+134 57 137 155 90 170 42 78 170 141 167 158 42 177 22 129 68 168 143 74 150 85 
+82 174 78 63 111 156 28 12 158 141 76 57 77 125 79 40 12 59 52 88 156 20 24 182 
+149 56 92 46 106 167 59 189 121 119 14 81 15 165 136 79 100 42 117 182 118 175 
+138 124 3 50 74 134 156 36 143 181 180 96 22 61 97 134 164 24 166 30 10 61 6 33 
+9 115 176 84 97 142 152 15 50 165 45 168 135 133 127 93 15 66 94 91 9 32 16 95 
+37 29 171 118 68 108 66 63 20 55 186 ^
+396 1 97 10 5 160 132 18 83 73 159 141 55 120 31 131 141 102 138 3 52 9 148 189 
+56 99 165 146 2 140 64 157 100 121 113 102 24 21 24 123 16 10 139 152 19 109 
+146 116 122 92 43 7 75 62 49 170 58 26 117 125 45 147 5 125 136 155 118 2 26 50 
+161 21 182 127 153 45 68 19 121 22 94 104 144 166 35 166 23 176 75 188 53 114 
+93 148 177 66 151 16 156 121 180 98 48 179 95 63 107 97 45 1 23 97 57 23 132 53 
+79 97 124 19 188 18 118 37 22 106 94 60 122 25 47 176 110 184 109 79 164 120 43 
+153 89 90 128 109 12 168 64 110 82 117 192 41 171 163 164 76 53 12 101 68 54 
+117 78 59 143 84 32 122 104 65 148 31 52 123 130 24 135 38 151 95 142 93 101 
+159 62 37 148 110 70 127 51 85 181 89 11 142 105 91 107 50 27 29 102 36 43 165 
+79 6 84 99 118 128 30 26 3 143 17 68 66 139 187 15 165 158 24 88 20 179 174 81 
+79 18 106 47 74 150 104 179 162 59 131 62 116 166 82 184 188 97 136 41 136 167 
+140 143 175 72 42 174 148 75 74 71 86 14 16 191 117 11 63 119 119 186 182 13 
+171 49 182 80 167 73 147 119 107 164 41 57 181 168 29 114 26 184 121 101 80 76 
+65 34 49 24 44 191 38 25 91 5 58 140 99 153 124 54 184 42 83 108 155 4 20 191 3 
+29 35 40 180 7 40 66 25 12 180 86 26 38 139 73 1 137 79 85 102 71 39 28 44 77 
+56 190 12 66 72 30 152 7 87 84 190 126 48 100 77 91 186 36 31 143 163 50 94 25 
+126 1 114 105 170 93 22 173 90 116 87 96 19 74 4 122 183 83 120 177 113 169 181 
+77 182 1 149 186 ^
+384 1 25 56 85 107 177 6 186 138 184 28 61 184 191 175 107 6 29 81 114 12 156 2 
+137 86 189 73 64 127 129 44 167 11 98 107 169 143 26 146 61 130 88 120 139 55 3 
+189 119 87 22 105 67 78 147 51 2 161 109 84 49 87 38 48 192 62 25 64 143 72 169 
+151 106 111 53 58 8 93 8 85 123 120 131 170 38 2 169 167 49 41 37 153 21 39 92 
+145 190 155 177 185 48 13 5 150 48 21 85 115 40 166 178 88 104 1 125 19 116 106 
+141 111 23 43 101 58 187 150 78 101 50 107 185 86 151 130 134 143 34 31 26 122 
+38 40 112 97 33 136 50 99 127 121 159 7 19 170 187 1 79 191 26 130 118 5 104 47 
+126 109 92 129 52 30 193 90 35 67 116 90 3 181 39 122 30 155 147 105 83 21 77 
+35 75 174 55 190 131 154 95 72 185 94 36 95 126 71 149 4 68 152 180 144 146 7 
+49 33 152 188 29 111 194 172 148 125 35 59 36 125 11 36 141 149 183 125 27 1 71 
+133 61 138 168 85 131 5 96 162 161 117 142 14 79 183 141 165 126 55 11 74 84 79 
+167 3 40 142 177 193 128 173 192 100 163 16 127 145 182 97 17 193 120 115 32 
+108 18 96 154 103 152 150 86 181 15 99 135 179 124 194 164 68 160 43 109 138 
+152 142 6 21 23 149 20 11 82 164 44 159 148 133 115 24 28 53 104 9 183 179 108 
+56 39 84 87 30 163 32 70 75 166 170 8 139 9 175 99 143 64 89 186 114 183 133 85 
+161 63 61 154 111 15 115 78 109 108 72 177 14 71 103 176 173 176 157 38 10 54 
+132 41 186 130 126 63 69 39 76 7 65 171 82 172 102 124 140 83 113 ^
+396 1 189 70 83 29 132 67 115 145 151 170 181 14 192 2 187 40 5 33 160 48 183 
+91 132 83 112 177 62 189 153 128 91 49 38 50 55 24 8 8 51 36 13 175 28 36 56 
+160 12 107 168 25 104 157 156 139 165 14 30 192 164 195 56 41 180 159 28 79 41 
+144 167 51 115 188 136 154 145 65 2 22 93 83 191 147 23 110 57 137 131 66 138 
+26 78 146 125 159 150 34 177 22 129 68 168 111 74 118 77 50 174 54 47 87 140 20 
+178 158 133 60 33 45 93 47 8 170 59 52 56 124 20 16 150 117 24 84 46 106 151 51 
+158 173 113 111 196 73 15 133 136 71 100 10 85 182 110 143 114 92 185 42 42 118 
+156 20 135 173 156 96 180 37 73 134 156 182 150 196 192 45 172 17 167 91 168 68 
+89 134 120 190 173 34 141 37 152 111 117 103 61 7 34 62 67 191 190 8 87 21 195 
+139 86 44 76 66 55 186 23 31 87 183 5 155 122 191 68 53 149 136 35 115 26 121 
+131 102 123 3 42 197 133 179 56 84 165 136 190 130 49 157 80 101 103 97 197 11 
+19 118 1 5 119 137 9 104 193 141 116 122 72 38 7 70 47 44 155 43 16 107 125 40 
+127 193 105 131 145 108 185 6 50 141 1 167 127 153 45 53 192 121 12 79 84 129 
+151 15 166 196 156 60 188 53 109 83 148 162 46 146 6 136 111 160 88 38 169 85 
+63 87 97 35 194 3 82 52 13 132 43 59 92 109 4 178 3 118 37 195 96 94 60 112 15 
+47 166 110 179 99 69 149 100 43 138 69 70 123 89 12 158 54 90 72 117 182 31 166 
+153 164 76 33 2 101 63 44 112 58 39 143 74 32 107 89 55 143 31 47 123 125 4 135 
+18 141 80 137 88 81 154 187 ^
+406 0 23 134 103 49 99 44 64 160 68 190 114 105 91 86 22 27 15 74 8 22 151 79 
+199 84 85 90 128 9 5 175 129 17 40 59 125 187 194 144 151 3 60 6 158 153 67 58 
+18 99 19 53 129 90 179 134 52 124 55 95 138 82 170 167 69 122 13 108 160 119 
+115 161 51 14 167 120 47 60 57 86 16 184 96 197 42 98 112 165 154 199 157 21 
+168 52 146 66 126 119 93 150 20 36 153 140 194 93 26 156 114 80 80 55 44 13 35 
+24 44 191 24 190 63 177 44 140 99 146 117 54 163 42 76 101 134 176 185 177 168 
+1 21 19 180 193 12 52 197 191 173 65 19 31 118 59 1 123 72 71 88 64 11 193 37 
+63 28 169 184 45 72 195 152 186 87 56 176 112 41 93 77 84 158 29 3 136 142 36 
+80 4 119 166 86 98 163 93 1 145 83 102 66 75 191 46 4 94 155 55 120 149 113 148 
+181 49 175 180 142 87 5 51 65 92 167 196 186 138 184 23 61 164 171 175 107 6 9 
+81 114 7 141 177 117 76 174 73 54 112 114 29 152 11 98 87 154 123 21 146 41 115 
+88 115 139 40 183 189 109 67 7 90 52 73 127 51 192 156 89 69 49 77 33 33 182 57 
+10 64 138 57 159 136 91 111 33 58 193 88 188 75 118 110 126 170 18 197 169 162 
+34 41 17 138 6 34 92 145 185 155 157 170 43 8 140 48 21 70 105 40 161 178 78 89 
+196 110 199 106 96 121 106 23 185 28 96 48 167 145 58 91 35 97 180 66 151 130 
+124 128 34 16 6 107 28 20 112 92 18 121 30 84 107 101 159 187 19 155 182 181 74 
+186 11 120 98 185 104 32 126 94 82 119 42 25 173 90 30 62 96 70 178 176 39 102 
+15 150 147 100 78 16 57 35 75 169 35 170 116 144 75 146 ^
+409 1 185 70 12 95 110 71 133 183 52 136 148 144 114 186 17 25 144 164 5 79 178 
+172 124 117 19 43 20 93 174 36 125 117 151 109 3 164 55 101 37 122 152 77 131 
+168 88 162 161 93 142 14 63 167 141 149 94 39 190 50 68 47 135 198 16 110 153 
+177 104 173 192 68 147 179 119 137 166 73 180 169 88 91 24 76 10 80 146 79 128 
+150 62 149 194 83 111 171 124 170 156 60 152 27 109 106 120 134 201 184 202 149 
+12 198 66 132 12 127 132 133 83 8 12 45 88 9 183 155 92 24 23 76 63 14 163 8 62 
+67 150 162 8 115 1 167 91 127 32 89 162 90 159 125 85 129 47 53 154 95 7 115 54 
+101 108 56 169 6 47 103 176 157 160 125 14 10 30 124 17 178 122 102 55 69 15 60 
+202 49 171 74 148 94 92 124 67 200 184 70 83 29 127 67 100 140 131 165 176 4 
+182 2 167 20 193 33 160 43 173 71 112 68 97 157 57 169 138 113 86 44 38 40 55 
+19 196 201 31 21 8 165 23 26 41 155 195 183 102 158 25 94 142 146 129 150 9 30 
+177 154 195 51 36 175 139 28 59 31 124 167 41 105 173 121 134 130 65 185 17 78 
+78 181 137 13 95 57 137 116 51 118 16 78 131 115 154 145 29 177 22 129 68 168 
+91 74 98 72 30 174 39 37 72 130 15 163 158 128 50 18 25 73 27 191 150 59 52 36 
+104 20 11 130 97 4 79 46 106 141 46 138 163 108 106 191 68 15 113 136 66 100 
+193 65 182 105 123 99 72 180 37 22 108 156 10 130 168 141 96 160 22 58 134 151 
+162 140 181 187 35 157 7 147 76 163 58 84 129 100 190 153 24 126 32 142 96 107 
+88 41 2 14 42 52 186 170 3 82 11 180 119 66 29 56 66 50 171 3 11 77 163 5 150 
+112 128 ^
+413 1 47 25 135 129 7 108 19 107 117 102 102 3 28 190 112 165 56 63 165 122 183 
+116 28 157 52 73 89 90 169 202 12 111 185 203 91 116 200 97 193 134 116 122 44 
+31 7 63 26 37 134 22 2 93 125 33 99 186 77 124 131 94 171 183 50 113 178 146 
+127 153 45 32 164 121 203 58 56 108 130 192 166 168 128 39 188 53 102 69 148 
+141 18 139 197 108 97 132 74 24 155 71 63 59 97 21 194 180 61 45 204 132 29 31 
+85 88 188 164 187 118 37 167 82 94 60 98 1 47 152 110 172 85 55 128 72 43 117 
+41 42 116 61 12 144 40 62 58 117 168 17 159 139 164 76 5 193 101 56 30 105 30 
+11 143 60 32 86 68 41 136 31 40 123 118 181 135 195 127 59 130 81 53 147 62 13 
+124 98 34 79 39 49 145 53 180 94 105 91 71 2 27 5 54 193 7 141 79 199 84 75 70 
+128 199 195 160 119 17 20 54 115 187 184 129 146 193 40 201 143 138 57 43 18 94 
+204 38 114 80 179 114 47 119 50 80 118 82 160 152 49 112 198 88 155 104 95 151 
+36 199 162 100 27 50 47 86 195 16 179 81 192 27 83 107 150 134 194 147 1 158 32 
+131 61 111 119 83 140 5 21 133 120 174 78 26 136 109 65 80 40 29 203 25 24 44 
+191 14 170 43 162 34 140 99 141 112 54 148 42 71 96 119 161 165 167 148 186 11 
+4 180 188 197 42 182 181 168 50 14 26 103 49 1 113 67 61 78 59 196 173 32 53 8 
+154 169 30 72 175 152 176 87 36 166 102 36 88 77 79 138 24 188 131 127 26 70 
+194 114 146 66 93 158 93 191 125 78 92 51 60 176 26 4 74 135 35 120 129 113 133 
+181 29 170 170 137 77 190 46 45 77 157 191 186 138 184 18 61 144 151 175 107 6 
+194 81 114 2 126 110 ^
+427 1 85 60 150 73 38 88 90 5 128 11 98 55 130 91 13 146 9 91 88 107 139 16 159 
+189 93 35 191 66 28 65 95 51 184 148 57 45 49 61 25 9 166 49 194 64 130 33 143 
+112 67 111 1 58 177 80 164 59 110 94 118 170 194 197 169 154 10 41 193 114 190 
+26 92 145 177 155 125 146 35 200 124 48 21 46 89 40 153 178 62 65 196 86 175 90 
+80 89 98 23 169 4 88 32 135 137 26 75 11 81 172 34 151 130 108 104 34 200 182 
+83 12 196 112 84 202 97 206 60 75 69 159 163 19 131 174 157 66 178 195 104 66 
+161 104 8 126 70 66 103 26 17 141 90 22 54 64 38 146 168 39 70 199 142 147 92 
+70 8 25 35 75 161 3 138 92 128 43 59 185 55 205 95 100 71 123 173 42 126 128 
+144 94 176 205 20 139 149 198 59 168 172 109 112 9 33 10 73 154 36 115 97 131 
+99 196 144 45 81 22 112 142 72 131 148 83 162 161 78 142 14 53 157 141 139 74 
+29 180 35 58 27 115 198 1 90 138 167 89 173 192 48 137 159 114 132 156 58 160 
+154 68 76 19 56 5 70 141 64 113 150 47 129 184 73 96 166 124 155 151 55 147 17 
+109 86 100 129 201 164 192 149 7 193 56 112 200 107 122 133 63 206 2 40 78 9 
+183 140 82 4 13 71 48 4 163 201 57 62 140 157 8 100 204 162 86 117 12 89 147 75 
+144 120 85 109 37 48 154 85 2 115 39 96 108 46 164 1 32 103 176 147 150 105 207 
+10 15 119 2 173 117 87 50 69 50 202 39 171 69 133 89 72 114 57 195 179 70 83 29 
+122 67 85 135 111 160 171 202 172 2 147 183 33 160 38 163 51 92 53 82 137 52 
+149 123 98 81 39 38 30 55 14 186 196 11 6 3 155 18 16 26 150 180 168 97 148 25 
+84 127 136 119 135 4 30 162 144 195 46 31 170 119 28 190 ^
+443 1 17 96 167 27 91 152 100 106 109 65 164 10 57 71 167 123 209 74 57 137 95 
+30 90 2 78 110 101 147 138 22 177 22 129 68 168 63 74 70 65 2 174 18 23 51 116 
+8 142 158 121 36 207 207 45 209 170 122 59 52 8 76 20 4 102 69 186 72 46 106 
+127 39 110 149 101 99 184 61 15 85 136 59 100 172 37 182 98 95 78 44 173 30 204 
+94 156 206 123 161 120 96 132 1 37 134 144 134 126 160 180 21 136 203 119 55 
+156 44 77 122 72 190 125 10 105 25 128 75 93 67 13 205 196 14 31 179 142 206 75 
+207 159 91 38 8 28 66 43 150 185 193 63 135 5 143 98 143 32 5 125 124 197 103 
+14 97 107 102 87 3 18 185 97 155 56 48 165 112 178 106 13 157 32 53 79 85 149 
+197 7 106 175 203 71 101 195 92 193 129 116 122 24 26 7 58 11 32 119 7 202 83 
+125 28 79 181 57 119 121 84 161 168 50 93 163 131 127 153 45 17 144 121 198 43 
+36 93 115 177 166 148 108 24 188 53 97 59 148 126 208 134 192 88 87 112 64 14 
+145 61 63 39 97 11 194 165 46 40 199 132 19 11 80 73 178 154 177 118 37 147 72 
+94 60 88 201 47 142 110 167 75 45 113 52 43 102 21 22 111 41 12 134 30 42 48 
+117 158 7 154 129 164 76 195 188 101 51 20 100 10 201 143 50 32 71 53 31 131 31 
+35 123 113 166 135 180 117 44 125 76 33 142 62 3 114 93 19 59 34 34 130 38 170 
+74 105 91 56 192 27 205 34 178 202 131 79 199 84 65 50 128 189 185 145 109 17 
+49 105 187 174 114 141 183 20 196 128 123 47 28 18 89 189 23 99 70 179 94 42 
+114 45 65 98 82 150 137 29 102 183 68 150 89 75 141 21 184 157 80 7 40 37 86 
+190 16 174 66 187 12 68 102 135 114 189 137 191 148 12 116 56 96 119 73 130 200 
+6 113 100 154 63 26 116 104 50 80 25 14 193 83 ^
+436 1 24 44 191 211 138 11 138 18 140 99 133 104 54 124 42 63 88 95 137 133 151 
+116 162 208 193 180 180 173 26 158 165 160 26 6 18 79 33 1 97 59 45 62 51 172 
+141 24 37 189 130 145 6 72 143 152 160 87 4 150 86 28 80 77 71 106 16 164 123 
+103 10 54 178 106 114 34 85 150 93 175 93 70 76 27 36 152 207 4 42 103 3 120 97 
+113 109 181 210 162 154 129 61 166 38 13 53 141 183 186 138 184 10 61 112 119 
+175 107 6 170 81 114 207 102 125 65 50 135 73 28 73 75 203 113 11 98 35 115 71 
+8 146 202 76 88 102 139 1 144 189 83 15 181 51 13 60 75 51 179 143 37 30 49 51 
+20 207 156 44 184 64 125 18 133 97 52 111 194 58 167 75 149 49 105 84 113 170 
+179 197 169 149 208 41 178 99 180 21 92 145 172 155 105 131 30 208 200 114 48 
+21 31 79 40 148 178 52 50 196 71 160 80 70 69 93 23 159 202 83 22 115 132 6 65 
+209 71 167 14 151 130 98 89 34 190 167 68 2 181 112 79 192 82 191 45 55 49 159 
+148 19 116 169 142 61 173 185 94 46 146 104 206 126 55 56 93 16 12 121 90 17 49 
+44 18 126 163 39 50 189 137 147 87 65 3 5 35 75 156 196 118 77 118 23 54 185 40 
+195 95 90 71 113 163 32 116 108 144 74 166 190 15 134 134 188 39 158 172 94 107 
+212 23 53 134 36 105 77 111 89 186 124 35 61 7 102 132 67 131 128 78 162 161 63 
+142 14 43 147 141 129 54 19 170 20 48 7 95 198 199 70 123 157 74 173 192 28 127 
+139 109 127 146 43 140 139 48 61 14 36 60 136 49 98 150 32 109 174 63 81 161 
+124 140 146 50 142 7 109 66 80 124 201 144 182 149 2 188 46 92 185 87 112 133 
+43 201 205 35 68 9 183 125 72 197 3 66 33 207 163 191 52 57 130 152 8 85 204 
+157 81 107 205 187 ^
+462 1 126 54 123 113 85 81 23 41 154 71 210 115 18 89 108 32 157 209 11 103 176 
+133 136 77 193 10 209 112 196 166 110 66 43 69 194 36 202 25 171 62 112 82 44 
+100 43 188 172 70 83 29 115 67 64 128 83 153 164 195 158 2 119 187 169 33 160 
+31 149 23 64 32 61 109 45 121 102 77 74 32 38 16 55 7 172 189 198 200 211 141 
+11 2 5 143 159 147 90 134 25 70 106 122 105 114 212 30 141 130 195 39 24 163 91 
+28 11 7 76 167 17 81 137 85 86 94 65 149 5 42 66 157 113 204 59 57 137 80 15 70 
+207 78 95 91 142 133 17 177 22 129 68 168 43 74 50 60 197 174 3 13 36 106 3 127 
+158 116 26 197 192 25 194 155 102 59 52 203 56 20 214 82 49 171 67 46 106 117 
+34 90 139 96 94 179 56 15 65 136 54 100 157 17 182 93 75 63 24 168 25 189 84 
+156 201 118 156 105 96 112 201 22 134 139 114 116 145 175 11 121 198 99 40 151 
+34 72 117 52 190 105 90 20 118 60 83 52 208 205 181 209 16 174 122 206 70 202 
+144 71 18 208 8 66 38 135 170 178 53 115 5 138 88 123 17 200 115 119 182 98 9 
+87 97 102 72 3 8 180 82 145 56 33 165 102 173 96 213 157 12 33 69 80 129 192 2 
+101 165 203 51 86 190 87 193 124 116 122 4 21 7 53 211 27 104 207 197 73 125 23 
+59 176 37 114 111 74 151 153 50 73 148 116 127 153 45 2 124 121 193 28 16 78 
+100 162 166 128 88 9 188 53 92 49 148 111 193 129 187 68 77 92 54 4 135 51 63 
+19 97 1 194 150 31 35 194 132 9 206 75 58 168 144 167 118 37 127 62 94 60 78 
+196 47 132 110 162 65 35 98 32 43 87 1 2 106 21 12 124 20 22 38 117 148 212 149 
+119 164 76 180 183 101 46 10 95 205 186 143 40 32 56 38 21 126 31 30 123 108 
+151 135 165 107 29 120 71 13 137 62 208 104 88 4 39 29 19 115 23 160 54 105 91 
+41 177 27 200 14 163 124 ^
+453 0 115 79 199 84 49 18 128 173 169 121 93 17 186 41 89 187 158 90 133 167 
+206 188 104 99 31 4 18 81 165 217 75 54 179 62 34 106 37 41 66 82 134 113 215 
+86 159 36 142 65 43 125 215 160 149 48 193 24 21 86 182 16 166 42 179 206 44 94 
+111 82 181 121 167 132 198 92 48 72 119 57 114 184 200 81 68 122 39 26 84 96 26 
+80 1 208 177 217 24 44 191 206 118 209 123 8 140 99 128 99 54 109 42 58 83 80 
+122 113 141 96 147 203 183 180 175 158 16 143 155 155 11 1 13 64 23 1 87 54 35 
+52 46 157 121 19 27 174 115 130 209 72 123 152 150 87 202 140 76 23 75 77 66 86 
+11 149 118 88 44 168 101 94 14 80 145 93 165 73 65 66 12 21 137 192 4 22 83 201 
+120 77 113 94 181 195 157 144 124 51 151 33 211 38 131 178 186 138 184 5 61 92 
+99 175 107 6 155 81 114 207 87 105 45 40 120 73 18 58 60 193 98 11 98 15 100 51 
+3 146 187 61 88 97 139 204 129 189 73 213 171 36 216 55 55 51 174 138 17 15 49 
+41 15 197 146 39 174 64 120 3 123 82 37 111 179 58 157 70 134 39 100 74 108 170 
+164 197 169 144 198 41 163 84 170 16 92 145 167 155 85 116 25 208 200 104 48 21 
+16 69 40 143 178 42 35 196 56 145 70 60 49 88 23 149 192 78 12 95 127 204 55 
+199 61 162 212 151 130 88 74 34 180 152 53 210 166 112 74 182 67 176 30 35 29 
+159 133 19 101 164 127 56 168 175 84 26 131 104 196 126 40 46 83 6 7 101 90 12 
+44 24 216 106 158 39 30 179 132 147 82 60 216 203 35 75 151 181 98 62 108 3 49 
+185 25 185 95 80 71 103 153 22 106 88 144 54 156 175 10 129 119 178 19 148 172 
+79 102 207 13 208 33 114 36 95 57 91 79 176 104 25 41 210 92 122 62 131 108 73 
+162 161 48 142 14 33 137 141 119 34 9 160 5 38 205 75 198 189 50 108 112 ^
+454 1 53 173 192 113 111 102 120 132 22 112 118 20 40 7 8 213 46 129 28 77 150 
+11 81 160 49 60 154 124 119 139 43 135 213 109 38 52 117 201 116 168 149 215 
+181 32 64 164 59 98 133 15 194 198 28 54 9 183 104 58 176 209 59 12 200 163 177 
+45 50 116 145 8 64 204 150 74 93 184 89 111 39 108 108 85 61 13 36 154 61 210 
+115 3 84 108 22 152 209 216 103 176 123 126 57 183 10 199 107 186 161 105 51 38 
+69 184 26 202 15 171 57 97 77 24 90 33 183 167 70 83 29 110 67 49 123 63 148 
+159 190 148 2 99 172 159 33 160 26 139 3 44 17 46 89 40 101 87 62 69 27 38 6 55 
+2 162 184 183 190 211 131 6 212 210 138 144 132 85 124 25 60 91 112 95 99 212 
+30 126 120 195 34 19 158 71 28 211 217 56 167 7 71 122 70 66 79 65 134 27 61 
+147 103 199 44 57 137 65 50 202 78 80 81 137 128 12 177 22 129 68 168 23 74 30 
+55 182 174 208 3 21 96 218 112 158 111 16 187 177 5 179 140 82 59 52 188 36 20 
+214 62 29 156 62 46 106 107 29 70 129 91 89 174 51 15 45 136 49 100 142 217 182 
+88 55 48 4 163 20 174 74 156 196 113 151 90 96 92 191 7 134 134 94 106 130 170 
+1 106 193 79 25 146 24 67 112 32 190 85 210 75 15 108 45 73 37 193 205 166 194 
+1 169 102 206 65 197 129 51 218 198 208 66 33 120 155 163 43 95 5 133 78 103 2 
+185 105 114 167 93 4 77 87 102 57 3 218 175 67 135 56 18 165 92 168 86 203 157 
+212 13 59 75 109 187 217 96 155 203 31 71 185 82 193 119 116 122 204 16 7 48 
+201 22 89 197 192 63 125 18 39 171 17 109 101 64 141 138 50 53 133 101 127 153 
+45 207 104 121 188 13 216 63 85 147 166 108 68 214 188 53 87 39 148 96 178 124 
+182 48 67 72 44 214 125 41 63 219 97 211 194 135 16 30 189 132 219 191 70 43 
+158 181 ^
+475 0 153 118 37 99 48 94 60 64 189 47 118 110 155 51 21 77 4 43 66 195 196 99 
+215 12 110 6 216 24 117 134 205 142 105 164 76 159 176 101 39 218 88 184 165 
+143 26 32 35 17 7 119 31 23 123 101 130 135 144 93 8 113 64 207 130 62 201 90 
+81 205 11 22 220 94 2 146 26 105 91 20 156 27 193 208 142 178 107 79 199 84 41 
+2 128 165 161 109 85 17 174 37 81 187 150 78 129 159 194 184 92 87 23 214 18 77 
+153 209 63 46 179 46 30 102 33 29 50 82 126 101 203 78 147 20 138 53 27 117 207 
+148 145 32 181 16 13 86 178 16 162 30 175 198 32 90 99 66 177 113 155 124 186 
+80 44 60 119 49 106 176 192 65 52 106 27 26 68 92 14 80 211 200 169 213 24 44 
+191 202 102 197 111 140 99 124 95 54 97 42 54 79 68 110 97 133 80 135 199 175 
+180 171 146 8 131 147 151 221 219 9 52 15 1 79 50 27 44 42 145 105 15 19 162 
+103 118 201 72 107 152 142 87 190 132 68 19 71 77 62 70 7 137 114 76 214 36 160 
+97 78 220 76 141 93 157 57 61 58 9 125 180 4 6 67 189 120 61 113 82 181 183 153 
+136 120 43 139 29 199 26 123 174 186 138 184 1 61 76 83 175 107 6 143 81 114 
+207 75 89 29 32 108 73 10 46 48 185 86 11 98 221 88 35 221 146 175 49 88 93 139 
+196 117 189 65 201 163 24 208 51 39 51 170 134 1 3 49 33 11 189 138 35 166 64 
+116 213 115 70 25 111 167 58 149 66 122 31 96 66 104 170 152 197 169 140 190 41 
+151 72 162 12 92 145 163 155 69 104 21 208 200 96 48 21 4 61 40 139 178 34 23 
+196 44 133 62 52 33 84 23 141 184 74 4 79 123 192 47 191 53 158 200 151 130 80 
+62 34 172 140 41 206 154 112 70 174 55 164 18 19 13 159 121 19 89 160 115 52 
+164 167 76 10 119 104 188 126 28 38 75 220 3 85 90 8 40 8 204 90 154 39 14 171 
+128 147 78 56 216 191 35 75 147 169 82 50 100 209 45 185 13 177 95 150 ^
+471 0 71 89 139 8 92 60 144 26 142 154 3 122 98 164 216 134 172 58 95 200 224 
+201 5 86 36 81 29 63 65 162 76 11 13 196 78 108 55 131 80 66 162 161 27 142 14 
+19 123 141 105 6 220 146 209 24 184 47 198 175 22 87 133 38 173 192 205 103 91 
+97 115 122 7 92 103 25 2 213 213 36 124 13 62 150 221 61 150 39 45 149 124 104 
+134 38 130 208 109 18 32 112 201 96 158 149 215 176 22 44 149 39 88 133 220 189 
+193 23 44 9 183 89 48 161 204 54 222 195 163 167 40 45 106 140 8 49 204 145 69 
+83 169 89 96 24 93 103 85 41 3 31 154 51 210 115 213 79 108 12 147 209 206 103 
+176 113 116 37 173 10 189 102 176 156 100 36 33 69 174 16 202 5 171 52 82 72 4 
+80 23 178 162 70 83 29 105 67 34 118 43 143 154 185 138 2 79 157 149 33 160 21 
+129 208 24 2 31 69 35 81 72 47 64 22 38 221 55 222 152 179 168 180 211 121 1 
+207 200 133 129 117 80 114 25 50 76 102 85 84 212 30 111 110 195 29 14 153 51 
+28 196 212 36 167 222 61 107 55 46 64 65 119 220 12 56 137 93 194 29 57 137 50 
+210 30 197 78 65 71 132 123 7 177 22 129 68 168 3 74 10 50 167 174 198 218 6 86 
+218 97 158 106 6 177 162 210 164 125 62 59 52 173 16 20 214 42 9 141 57 46 106 
+97 24 50 119 86 84 169 46 15 25 136 44 100 127 202 182 83 35 33 209 158 15 159 
+64 156 191 108 146 75 96 72 181 217 134 129 74 96 115 165 216 91 188 59 10 141 
+14 62 107 12 190 65 205 60 10 98 30 63 22 178 205 151 179 211 164 82 206 60 192 
+114 31 203 188 193 66 28 105 140 148 33 75 5 128 68 83 212 170 95 109 152 88 
+224 67 77 102 42 3 213 170 52 125 56 3 165 82 163 76 193 157 197 218 49 70 89 
+182 217 91 145 203 11 56 180 77 193 114 116 122 189 11 7 43 191 17 74 187 187 
+53 125 13 19 166 222 104 91 54 131 123 50 33 118 86 127 167 ^
+480 1 45 193 76 121 181 219 195 42 64 126 166 80 40 200 188 53 80 25 148 75 157 
+117 175 20 53 44 30 207 111 27 63 198 97 204 194 114 222 23 182 132 212 170 63 
+22 144 120 143 118 37 79 38 94 60 54 184 47 108 110 150 41 11 62 211 43 51 180 
+181 94 200 12 100 223 201 14 117 124 200 137 95 164 76 144 171 101 34 213 83 
+169 150 143 16 32 20 2 224 114 31 18 123 96 115 135 129 83 220 108 59 192 125 
+62 196 80 76 195 218 17 210 79 214 136 6 105 91 5 141 27 188 193 127 168 97 79 
+199 84 31 209 128 155 151 94 75 17 159 32 71 187 140 63 124 149 179 179 77 72 
+13 204 18 72 138 199 48 36 179 26 25 97 28 14 30 82 116 86 188 68 132 133 38 7 
+107 197 133 140 12 166 6 3 86 173 16 157 15 170 188 17 85 84 46 172 103 140 114 
+171 65 39 45 119 39 96 166 182 45 32 86 12 26 48 87 226 80 201 190 159 208 24 
+44 191 197 82 182 96 217 140 99 119 90 54 82 42 49 74 53 95 77 123 60 120 194 
+165 180 166 131 225 116 137 146 211 219 4 37 5 1 69 45 17 34 37 130 85 10 9 147 
+88 103 191 72 87 152 132 87 175 122 58 14 66 77 57 50 2 122 109 61 209 26 150 
+92 58 205 71 136 93 147 37 56 48 212 221 110 165 4 213 47 174 120 41 113 67 181 
+168 148 126 115 33 124 24 184 11 113 169 186 138 184 223 61 56 63 175 107 6 128 
+81 114 207 60 69 9 22 93 73 31 33 175 71 11 98 206 73 15 221 146 160 34 88 88 
+139 186 102 189 55 186 153 9 198 46 19 51 165 129 208 215 49 23 6 179 128 30 
+156 64 111 203 105 55 10 111 152 58 139 61 107 21 91 56 99 170 137 197 169 135 
+180 41 136 57 152 7 92 145 158 155 49 89 16 208 200 86 48 21 216 51 40 134 178 
+24 8 196 29 118 52 42 13 79 23 131 174 69 221 59 118 177 37 181 43 153 185 151 
+130 70 47 34 162 125 26 201 139 112 65 164 40 149 3 226 220 159 106 19 74 155 
+100 47 159 157 193 ^
+471 0 211 98 104 174 126 7 24 61 213 225 57 90 1 33 209 183 62 147 39 215 157 
+121 147 71 49 216 170 35 75 140 148 54 29 86 188 38 185 221 163 95 58 71 81 131 
+84 44 144 10 134 142 228 118 86 156 204 126 172 46 91 196 220 197 218 70 36 73 
+13 47 57 154 60 3 226 188 70 100 51 131 64 62 162 161 15 142 14 11 115 141 97 
+219 216 138 201 16 172 31 198 167 6 75 125 26 173 192 193 95 75 93 111 114 224 
+76 91 213 13 227 201 213 28 120 1 50 150 213 45 142 31 33 145 124 92 130 34 126 
+204 109 2 16 108 201 80 150 149 215 172 14 28 137 23 80 133 208 185 189 19 36 9 
+183 77 40 149 200 50 214 191 163 159 36 41 98 136 8 37 204 141 65 75 157 89 84 
+12 81 99 85 25 224 27 154 43 210 115 205 75 108 4 143 209 198 103 176 105 108 
+21 165 10 181 98 168 152 96 24 29 69 166 8 202 226 171 48 70 68 217 72 15 174 
+158 70 83 29 101 67 22 114 27 139 150 181 130 2 63 145 141 33 160 17 121 196 8 
+219 19 53 31 65 60 35 60 18 38 217 55 222 144 175 156 172 211 113 226 203 192 
+129 117 105 76 106 25 42 64 94 77 72 212 30 99 102 195 25 10 149 35 28 184 208 
+20 167 218 53 95 43 30 52 65 107 220 52 129 85 190 17 57 137 38 202 14 193 78 
+53 63 128 119 3 177 22 129 68 168 216 74 223 46 155 174 190 214 223 78 218 85 
+158 102 227 169 150 198 152 113 46 59 52 161 20 214 26 222 129 53 46 106 89 20 
+34 111 82 80 165 42 15 9 136 40 100 115 190 182 79 19 21 197 154 11 147 56 156 
+187 104 142 63 96 56 173 209 134 125 58 88 103 161 212 79 184 43 227 137 6 58 
+103 225 190 49 201 48 6 90 18 55 10 166 205 139 167 203 160 66 206 56 188 102 
+15 191 180 181 66 24 93 128 136 25 59 5 124 60 67 204 158 87 105 140 84 224 59 
+69 102 30 3 209 166 40 117 56 220 165 74 159 68 185 157 185 206 41 66 167 ^
+490 1 176 217 85 133 203 218 38 174 71 193 108 116 122 171 5 7 37 179 11 56 175 
+181 41 125 7 226 160 204 98 79 42 119 105 50 9 100 68 127 153 45 185 60 121 177 
+211 183 30 52 114 166 64 24 192 188 53 76 17 148 63 145 113 171 4 45 28 22 203 
+103 19 63 186 97 200 194 102 214 19 178 132 208 158 59 10 136 112 135 118 37 63 
+30 94 60 46 180 47 100 110 146 33 3 50 199 43 39 168 169 90 188 12 92 219 189 6 
+117 116 196 133 87 164 76 132 167 101 30 209 79 157 138 143 8 32 8 221 220 110 
+31 14 123 92 103 135 117 75 212 104 55 180 121 62 192 72 72 187 206 13 202 67 
+206 128 221 105 91 224 129 27 184 181 115 160 89 79 199 84 23 197 128 147 143 
+82 67 17 147 28 63 187 132 51 120 141 167 175 65 60 5 196 18 68 126 191 36 28 
+179 10 21 93 24 2 14 82 108 74 176 60 120 215 129 26 222 99 189 121 136 227 154 
+229 226 86 169 16 153 3 166 180 5 81 72 30 168 95 128 106 159 53 35 33 119 31 
+88 158 174 29 16 70 26 32 83 218 80 193 182 151 204 24 44 191 193 66 170 84 213 
+140 99 115 86 54 70 42 45 70 41 83 61 115 44 108 190 157 180 162 119 221 104 
+129 142 203 219 25 228 1 61 41 9 26 33 118 69 6 1 135 76 91 183 72 71 152 124 
+87 163 114 50 10 62 77 53 34 229 110 105 49 205 18 142 88 42 193 67 132 93 139 
+21 52 40 204 213 98 153 4 201 31 162 120 25 113 55 181 156 144 118 111 25 112 
+20 172 230 105 165 186 138 184 223 61 40 47 175 107 6 116 81 114 207 48 53 224 
+14 81 73 223 19 21 167 59 11 98 194 61 230 221 146 148 22 88 84 139 178 90 189 
+47 174 145 228 190 42 3 51 161 125 196 207 49 15 2 171 120 26 148 64 107 195 97 
+43 229 111 140 58 131 57 95 13 87 48 95 170 125 197 169 131 172 41 124 45 144 3 
+92 145 154 155 33 77 12 208 200 78 48 21 208 43 40 130 178 16 227 196 17 106 44 
+34 228 75 23 123 166 65 217 43 114 165 29 173 35 200 ^
+479 0 167 151 130 58 29 34 150 107 8 195 121 112 59 152 22 131 218 208 202 159 
+88 19 56 149 82 41 153 145 54 199 86 104 166 126 228 16 53 209 225 41 90 230 29 
+197 171 46 143 39 203 149 117 147 67 45 216 158 35 75 136 136 38 17 78 176 34 
+185 213 155 95 50 71 73 123 225 76 28 144 227 126 130 228 114 74 148 192 118 
+172 34 87 192 216 193 206 54 36 65 230 31 49 146 44 228 214 180 62 92 47 131 48 
+58 162 161 3 142 14 3 107 141 89 207 212 130 193 8 160 15 198 159 223 63 117 14 
+173 192 181 87 59 89 107 106 216 60 79 201 1 227 189 213 20 116 222 38 150 205 
+29 134 23 21 141 124 80 126 30 122 200 109 219 104 201 64 142 149 215 168 6 12 
+125 7 72 133 196 181 185 15 28 9 183 65 32 137 196 46 206 187 163 151 32 37 90 
+132 8 25 204 137 61 67 145 89 72 69 95 85 9 220 23 154 35 210 115 197 71 108 
+229 139 209 190 103 176 97 100 5 157 10 173 94 160 148 92 12 25 69 158 202 222 
+171 44 58 64 205 64 7 170 154 70 83 29 97 67 10 110 11 135 146 177 122 2 47 133 
+133 33 160 13 113 184 225 211 7 37 27 49 48 23 56 14 38 213 55 222 136 171 144 
+164 211 105 226 199 184 125 105 93 72 98 25 34 52 86 69 60 212 30 87 94 195 21 
+6 145 19 28 172 204 4 167 214 45 83 31 14 40 65 95 220 221 48 121 77 186 5 57 
+137 26 194 231 189 78 41 55 124 115 232 177 22 129 68 168 204 74 211 42 143 174 
+182 210 215 70 218 73 158 98 223 161 138 186 140 101 30 59 52 149 217 20 214 10 
+210 117 49 46 106 81 16 18 103 78 76 161 38 15 226 136 36 100 103 178 182 75 3 
+9 185 150 7 135 48 156 183 100 138 51 96 40 165 201 134 121 42 80 91 157 208 67 
+180 27 219 133 231 54 99 213 190 33 197 36 2 82 6 47 231 154 205 127 155 195 
+156 50 206 52 184 90 232 179 172 169 66 20 81 116 124 17 43 5 120 52 51 196 146 
+79 101 128 80 224 65 ^
+503 1 55 102 9 3 202 159 19 103 56 206 165 60 152 54 171 157 164 185 27 59 45 
+171 217 80 123 203 203 23 169 66 193 103 116 122 156 7 32 169 6 41 165 176 31 
+125 2 211 155 189 93 69 32 109 90 50 225 85 53 127 153 45 175 40 121 172 201 
+168 15 37 99 166 44 4 182 188 53 71 7 148 48 130 108 166 220 35 8 12 198 93 9 
+63 171 97 195 194 87 204 14 173 132 203 143 54 231 126 102 125 118 37 43 20 94 
+60 36 175 47 90 110 141 23 229 35 184 43 24 153 154 85 173 12 82 214 174 232 
+117 106 191 128 77 164 76 117 162 101 25 204 74 142 123 143 234 32 229 211 215 
+105 31 9 123 87 88 135 102 65 202 99 50 165 116 62 187 62 67 177 191 8 192 52 
+196 118 206 105 91 214 114 27 179 166 100 150 79 79 199 84 13 182 128 137 133 
+67 57 17 132 23 53 187 122 36 115 131 152 170 50 45 231 186 18 63 111 181 21 18 
+179 226 16 88 19 223 230 82 98 59 161 50 105 200 124 11 207 89 179 106 131 212 
+139 224 221 86 164 16 148 224 161 170 226 76 57 10 163 85 113 96 144 38 30 18 
+119 21 78 148 164 9 232 50 221 26 12 78 208 80 183 172 141 199 24 44 191 188 46 
+155 69 208 140 99 110 81 54 55 42 40 65 26 68 41 105 24 93 185 147 180 157 104 
+216 89 119 137 193 219 231 10 223 1 51 36 235 16 28 103 49 1 227 120 61 76 173 
+72 51 152 114 87 148 104 40 5 57 77 48 14 229 95 100 34 200 8 132 83 22 178 62 
+127 93 129 1 47 30 194 203 83 138 4 186 11 147 120 5 113 40 181 141 139 108 106 
+15 97 15 157 220 95 160 186 138 184 223 61 20 27 175 107 6 101 81 114 207 33 33 
+209 4 66 73 218 4 6 157 44 11 98 179 46 215 221 146 133 7 88 79 139 168 75 189 
+37 159 135 218 180 37 219 51 156 120 181 197 49 5 233 161 110 21 138 64 102 185 
+87 28 219 111 125 58 121 52 80 3 82 38 90 170 110 197 169 126 162 41 109 30 134 
+234 92 145 149 155 13 62 7 208 200 68 48 21 198 33 40 125 178 6 217 196 2 91 34 
+24 213 70 23 113 161 ^
+470 0 58 210 15 107 144 15 159 21 142 152 151 130 48 14 34 140 92 231 190 106 
+112 54 142 7 116 208 193 187 159 73 19 41 144 67 36 148 135 44 184 71 104 156 
+126 218 6 43 204 225 21 90 230 24 182 156 26 138 39 188 139 112 147 62 40 216 
+143 35 75 131 121 18 2 68 161 29 185 203 145 95 40 71 63 113 220 66 8 144 212 
+116 115 228 109 59 138 177 108 172 19 82 187 211 188 191 34 36 55 215 11 39 136 
+24 223 199 170 52 82 42 131 28 53 162 161 226 142 14 231 97 141 79 192 207 120 
+183 236 145 233 198 149 208 48 107 237 173 192 166 77 39 84 102 96 206 40 64 
+186 224 227 174 213 10 111 212 23 150 195 9 124 13 6 136 124 65 121 25 117 195 
+109 204 218 99 201 44 132 149 215 163 234 230 110 225 62 133 181 176 180 10 18 
+9 183 50 22 122 191 41 196 182 163 141 27 32 80 127 8 10 204 132 56 57 130 89 
+57 223 54 90 85 227 215 18 154 25 210 115 187 66 108 224 134 209 180 103 176 87 
+90 223 147 10 163 89 150 143 87 235 20 69 148 228 202 217 171 39 43 59 190 54 
+235 165 149 70 83 29 92 67 233 105 229 130 141 172 112 2 27 118 123 33 160 8 
+103 169 210 201 230 17 22 29 33 8 51 9 38 208 55 222 126 166 129 154 211 95 226 
+194 174 120 90 78 67 88 25 24 37 76 59 45 212 30 72 84 195 16 1 140 237 28 157 
+199 222 167 209 35 68 16 232 25 65 80 220 211 43 111 67 181 228 57 137 11 184 
+216 184 78 26 45 119 110 232 177 22 129 68 168 189 74 196 37 128 174 172 205 
+205 60 218 58 158 93 218 151 123 171 125 86 10 59 52 134 202 20 214 228 195 102 
+44 46 106 71 11 236 93 73 71 156 33 15 211 136 31 100 88 163 182 70 221 232 170 
+145 2 120 38 156 178 95 133 36 96 20 155 191 134 116 22 70 76 152 203 52 175 7 
+209 128 226 49 94 198 190 13 192 21 235 72 229 37 221 139 205 112 140 185 151 
+30 206 47 179 75 217 101 ^
+502 0 158 148 66 13 60 95 103 3 15 5 113 38 23 182 125 65 94 107 73 224 37 47 
+102 237 3 198 155 7 95 56 198 165 52 148 46 163 157 152 173 19 55 29 167 217 76 
+115 203 191 11 165 62 193 99 116 122 144 236 7 28 161 2 29 157 172 23 125 238 
+199 151 177 89 61 24 101 78 50 213 73 41 127 153 45 167 24 121 168 193 156 3 25 
+87 166 28 228 174 188 53 67 239 148 36 118 104 162 208 27 232 4 194 85 1 63 159 
+97 191 194 75 196 10 169 132 199 131 50 223 118 94 117 118 37 27 12 94 60 28 
+171 47 82 110 137 15 225 23 172 43 12 141 142 81 161 12 74 210 162 228 117 98 
+187 124 69 164 76 105 158 101 21 200 70 130 111 143 230 32 221 203 211 101 31 5 
+123 83 76 135 90 57 194 95 46 153 112 62 183 54 63 169 179 4 184 40 188 110 194 
+105 91 206 102 27 175 154 88 142 71 79 199 84 5 170 128 129 125 55 49 17 120 19 
+45 187 114 24 111 123 140 166 38 33 227 178 18 59 99 173 9 10 179 214 12 84 15 
+215 218 82 90 47 149 42 93 188 120 239 195 81 171 94 127 200 127 220 217 86 160 
+16 144 216 157 162 218 72 45 234 159 77 101 88 132 26 26 6 119 13 70 140 156 
+233 220 34 213 26 236 74 200 80 175 164 133 195 24 44 191 184 30 143 57 204 140 
+99 106 77 54 43 42 36 61 14 56 25 97 8 81 181 139 180 153 92 212 77 111 133 185 
+219 231 238 219 1 43 32 231 8 24 91 33 237 223 108 49 64 165 72 35 152 106 87 
+136 96 32 1 53 77 44 238 229 83 96 22 196 124 79 6 166 58 123 93 121 225 43 22 
+186 195 71 126 4 174 235 135 120 229 113 28 181 129 135 100 102 7 85 11 145 212 
+87 156 186 138 184 223 61 4 11 175 107 6 89 81 114 207 21 17 197 236 54 73 214 
+232 234 149 32 11 98 167 34 203 221 146 121 235 88 75 139 160 63 189 29 147 127 
+210 172 33 207 51 152 116 169 189 49 237 233 153 102 17 130 64 98 177 79 16 211 
+111 113 58 113 48 68 235 78 30 86 170 98 197 169 122 154 41 97 18 126 234 92 
+145 145 155 237 50 209 ^
+481 1 208 200 56 48 21 186 21 40 119 178 236 205 196 226 73 22 12 195 64 23 101 
+144 54 206 241 103 132 7 151 13 138 140 151 130 40 2 34 132 80 223 186 94 112 
+50 134 237 104 200 181 175 159 61 19 29 140 55 32 144 127 36 172 59 104 148 126 
+210 240 35 200 225 5 90 230 20 170 144 10 134 39 176 131 108 147 58 36 216 131 
+35 75 127 109 2 232 60 149 25 185 195 137 95 32 71 55 105 216 58 234 144 200 
+108 103 228 105 47 130 165 100 172 7 78 183 207 184 179 18 36 47 203 237 31 128 
+8 219 187 162 44 74 38 131 12 49 162 161 218 142 14 227 89 141 71 180 203 112 
+175 232 133 221 198 141 196 36 99 229 173 192 154 69 23 80 98 88 198 24 52 174 
+216 227 162 213 2 107 204 11 150 187 235 116 5 236 132 124 53 117 21 113 191 
+109 192 206 95 201 28 124 149 215 159 230 218 98 213 54 133 169 172 176 6 10 9 
+183 38 14 110 187 37 188 178 163 133 23 28 72 123 8 240 204 128 52 49 118 89 45 
+215 42 86 85 215 211 14 154 17 210 115 179 62 108 220 130 209 172 103 176 79 82 
+211 139 10 155 85 142 139 83 227 16 69 140 224 202 213 171 35 31 55 178 46 231 
+161 145 70 83 29 88 67 225 101 217 126 137 168 104 2 11 106 115 33 160 4 95 157 
+198 193 222 1 18 13 21 238 47 5 38 204 55 222 118 162 117 146 211 87 226 190 
+166 116 78 66 63 80 25 16 25 68 51 33 212 30 60 76 195 12 239 136 225 28 145 
+195 210 167 205 27 56 4 220 13 65 68 220 203 39 103 59 177 220 57 137 241 176 
+204 180 78 14 37 115 106 232 177 22 129 68 168 177 74 184 33 116 174 164 201 
+197 52 218 46 158 89 214 143 111 159 113 74 236 59 52 122 190 20 214 216 183 90 
+40 46 106 63 7 224 85 69 67 152 29 15 199 136 27 100 76 151 182 66 209 224 158 
+141 240 108 30 156 174 91 129 24 96 4 147 183 134 112 6 62 64 148 199 40 171 
+233 201 124 222 45 90 186 190 239 188 9 235 64 221 29 213 127 178 ^
+508 1 94 122 173 145 6 206 41 173 57 199 146 150 136 66 9 48 83 91 239 243 5 
+109 30 7 174 113 57 90 95 69 224 29 39 102 229 3 194 151 239 87 56 190 165 44 
+144 38 155 157 140 161 11 51 13 163 217 72 107 203 179 243 161 58 193 95 116 
+122 132 236 7 24 153 242 17 149 168 15 125 238 187 147 165 85 53 16 93 66 50 
+201 61 29 127 153 45 159 8 121 164 185 144 235 13 75 166 12 216 166 188 53 63 
+235 148 24 106 100 158 196 19 220 240 190 77 237 63 147 97 187 194 63 188 6 165 
+132 195 119 46 215 110 86 109 118 37 11 4 94 60 20 167 47 74 110 133 7 221 11 
+160 43 129 130 77 149 12 66 206 150 224 117 90 183 120 61 164 76 93 154 101 17 
+196 66 118 99 143 226 32 213 195 207 97 31 1 123 79 64 135 78 49 186 91 42 141 
+108 62 179 46 59 161 167 176 28 180 102 182 105 91 198 90 27 171 142 76 134 63 
+79 199 84 241 158 128 121 117 43 41 17 108 15 37 187 106 12 107 115 128 162 26 
+21 223 170 18 55 87 165 241 2 179 202 8 80 11 207 206 82 82 35 137 34 81 176 
+116 231 183 73 163 82 123 188 115 216 213 86 156 16 140 208 153 154 210 68 33 
+222 155 69 89 80 120 14 22 238 119 5 62 132 148 221 208 18 205 26 224 70 192 80 
+167 156 125 191 24 44 191 180 14 131 45 200 140 99 102 73 54 31 42 32 57 2 44 9 
+89 236 69 177 131 180 149 80 208 65 103 129 177 219 231 230 215 1 35 28 227 20 
+79 17 237 219 96 37 52 157 72 19 152 98 87 124 88 24 241 49 77 40 226 229 71 92 
+10 192 236 116 75 234 154 54 119 93 113 213 39 14 178 187 59 114 4 162 223 123 
+120 217 113 16 181 117 131 92 98 243 73 7 133 204 79 152 186 138 184 223 61 232 
+239 175 107 6 77 81 114 207 9 1 185 232 42 73 210 224 226 141 20 11 98 155 22 
+191 221 146 109 227 88 71 139 152 51 189 21 135 119 202 164 29 195 51 148 112 
+157 181 49 233 233 145 94 13 122 64 94 169 71 4 203 111 101 58 105 44 56 231 74 
+22 82 170 86 197 169 118 146 41 85 6 118 234 92 145 141 149 ^
+484 1 219 32 243 208 200 48 48 21 178 13 40 115 178 232 197 196 218 61 14 4 183 
+60 23 93 136 50 202 229 99 120 245 143 5 134 128 151 130 32 236 34 124 68 215 
+182 82 112 46 126 229 92 192 169 163 159 49 19 17 136 43 28 140 119 28 160 47 
+104 140 126 202 236 27 196 225 235 90 230 16 158 132 240 130 39 164 123 104 147 
+54 32 216 119 35 75 123 97 232 224 52 137 21 185 187 129 95 24 71 47 97 212 50 
+222 144 188 100 91 228 101 35 122 153 92 172 241 74 179 203 180 167 2 36 39 191 
+225 23 120 238 215 175 154 36 66 34 131 242 45 162 161 210 142 14 223 81 141 63 
+168 199 104 167 228 121 209 198 133 184 24 91 221 173 192 142 61 7 76 94 80 190 
+8 40 162 208 227 150 213 240 103 196 245 150 179 223 108 243 228 128 124 41 113 
+17 109 187 109 180 194 91 201 12 116 149 215 155 226 206 86 201 46 133 157 168 
+172 2 2 9 183 26 6 98 183 33 180 174 163 125 19 24 64 119 8 232 204 124 48 41 
+106 89 33 207 30 82 85 203 207 10 154 9 210 115 171 58 108 216 126 209 164 103 
+176 71 74 199 131 10 147 81 134 135 79 219 12 69 132 220 202 209 171 31 19 51 
+166 38 227 157 141 70 83 29 84 67 217 97 205 122 133 164 96 2 241 94 107 33 160 
+87 145 186 185 214 231 14 243 9 230 43 1 38 200 55 222 110 158 105 138 211 79 
+226 186 158 112 66 54 59 72 25 8 13 60 43 21 212 30 48 68 195 8 239 132 213 28 
+133 191 198 167 201 19 44 238 208 1 65 56 220 195 35 95 51 173 212 57 137 233 
+168 192 176 78 2 29 111 102 232 177 22 129 68 168 165 74 172 29 104 174 156 197 
+189 44 218 34 158 85 210 135 99 147 101 62 224 59 52 110 178 20 214 204 171 78 
+36 46 106 55 3 212 77 65 63 148 25 15 187 136 23 100 64 139 182 62 197 216 146 
+137 240 96 22 156 170 87 125 12 96 234 139 175 134 108 236 54 52 144 195 28 167 
+221 193 120 218 41 86 174 190 227 184 243 235 56 213 21 205 115 205 71 ^
+506 0 110 165 141 238 206 37 169 45 187 134 142 124 66 5 36 71 79 235 231 5 105 
+22 239 166 101 49 86 83 65 224 21 31 102 221 3 190 147 231 79 56 182 165 36 140 
+30 147 157 128 149 3 47 245 159 217 68 99 203 167 235 157 54 193 91 116 122 120 
+236 7 20 145 242 5 141 164 7 125 238 175 143 153 81 45 8 85 54 50 189 49 17 127 
+153 45 151 240 121 160 177 132 227 1 63 166 244 204 158 188 53 59 231 148 12 94 
+96 154 184 11 208 236 186 69 233 63 135 97 183 194 51 180 2 161 132 191 107 42 
+207 102 78 101 118 37 243 244 94 60 12 163 47 66 110 129 247 217 247 148 43 236 
+117 118 73 137 12 58 202 138 220 117 82 179 116 53 164 76 81 150 101 13 192 62 
+106 87 143 222 32 205 187 203 93 31 245 123 75 52 135 66 41 178 87 38 129 104 
+62 175 38 55 153 155 244 168 16 172 94 170 105 91 190 78 27 167 130 64 126 55 
+79 199 84 237 146 128 113 109 31 33 17 96 11 29 187 98 103 107 116 158 14 9 219 
+162 18 51 75 157 233 242 179 190 4 76 7 199 194 82 74 23 125 26 69 164 112 223 
+171 65 155 70 119 176 103 212 209 86 152 16 136 200 149 146 202 64 21 210 151 
+61 77 72 108 2 18 230 119 245 54 124 140 209 196 2 197 26 212 66 184 80 159 148 
+117 187 24 44 191 176 246 119 33 196 140 99 98 69 54 19 42 28 53 238 32 241 81 
+224 57 173 123 180 145 68 204 53 95 125 169 219 231 222 211 1 27 24 223 240 16 
+67 1 237 215 84 25 40 149 72 3 152 90 87 112 80 16 241 45 77 36 214 229 59 88 
+246 188 232 108 71 222 142 50 115 93 105 201 35 6 170 179 47 102 4 150 211 111 
+120 205 113 4 181 105 127 84 94 239 61 3 121 196 71 148 186 138 184 223 61 220 
+227 175 107 6 65 81 114 207 245 233 173 228 30 73 206 216 218 133 8 11 98 143 
+10 179 221 146 97 219 88 67 139 144 39 189 13 123 111 194 156 25 183 51 144 108 
+145 173 49 229 233 137 86 9 114 64 90 161 63 240 195 111 89 58 97 40 44 227 70 
+14 78 170 74 197 169 114 138 41 73 242 110 234 177 ^
+491 0 145 135 155 207 20 243 208 200 40 48 21 170 5 40 111 178 228 189 196 210 
+49 6 246 171 56 23 85 128 46 198 217 95 108 241 135 247 130 116 151 130 24 228 
+34 116 56 207 178 70 112 42 118 221 80 184 157 151 159 37 19 5 132 31 24 136 
+111 20 148 35 104 132 126 194 232 19 192 225 223 90 230 12 146 120 228 126 39 
+152 115 100 147 50 28 216 107 35 75 119 85 220 216 44 125 17 185 179 121 95 16 
+71 39 89 208 42 210 144 176 92 79 228 97 23 114 141 84 172 233 70 175 199 176 
+155 236 36 31 179 213 15 112 226 211 163 146 28 58 30 131 230 41 162 161 202 
+142 14 219 73 141 55 156 195 96 159 224 109 197 198 125 172 12 83 213 173 192 
+130 53 241 72 90 72 182 242 28 150 200 227 138 213 236 99 188 237 150 171 211 
+100 239 220 124 124 29 109 13 105 183 109 168 182 87 201 246 108 149 215 151 
+222 194 74 189 38 133 145 164 168 248 244 9 183 14 248 86 179 29 172 170 163 
+117 15 20 56 115 8 224 204 120 44 33 94 89 21 199 18 78 85 191 203 6 154 1 210 
+115 163 54 108 212 122 209 156 103 176 63 66 187 123 10 139 77 126 131 75 211 8 
+69 124 216 202 205 171 27 7 47 154 30 223 153 137 70 83 29 80 67 209 93 193 118 
+129 160 88 2 229 82 99 33 160 246 79 133 174 177 206 219 10 231 247 222 39 247 
+38 196 55 222 102 154 93 130 211 71 226 182 150 108 54 42 55 64 25 1 52 35 9 
+212 30 36 60 195 4 239 128 201 28 121 187 186 167 197 11 32 230 196 239 65 44 
+220 187 31 87 43 169 204 57 137 225 160 180 172 78 240 21 107 98 232 177 22 129 
+68 168 153 74 160 25 92 174 148 193 181 36 218 22 158 81 206 127 87 135 89 50 
+212 59 52 98 166 20 214 192 159 66 32 46 106 47 249 200 69 61 59 144 21 15 175 
+136 19 100 52 127 182 58 185 208 134 133 240 84 14 156 166 83 121 96 222 131 
+167 134 104 224 46 40 140 191 16 163 209 185 116 214 37 82 162 190 215 180 235 
+235 48 205 13 197 103 205 76 104 161 139 232 146 ^
+516 0 33 165 33 175 122 134 112 66 1 24 59 67 231 219 5 101 14 227 158 89 41 82 
+71 61 224 13 23 102 213 3 186 143 223 71 56 174 165 28 136 22 139 157 116 137 
+247 43 233 155 217 64 91 203 155 227 153 50 193 87 116 122 108 236 7 16 137 242 
+245 133 160 251 125 238 163 139 141 77 37 77 42 50 177 37 5 127 153 45 143 228 
+121 156 169 120 219 241 51 166 232 192 150 188 53 55 227 148 82 92 150 172 3 
+196 232 182 61 229 63 123 97 179 194 39 172 250 157 132 187 95 38 199 94 70 93 
+118 37 231 240 94 60 4 159 47 58 110 125 243 213 239 136 43 228 105 106 69 125 
+12 50 198 126 216 117 74 175 112 45 164 76 69 146 101 9 188 58 94 75 143 218 32 
+197 179 199 89 31 245 123 71 40 135 54 33 170 83 34 117 100 62 171 30 51 145 
+143 244 160 4 164 86 158 105 91 182 66 27 163 118 52 118 47 79 199 84 233 134 
+128 105 101 19 25 17 84 7 21 187 90 240 99 99 104 154 2 249 215 154 18 47 63 
+149 225 238 179 178 72 3 191 182 82 66 11 113 18 57 152 108 215 159 57 147 58 
+115 164 91 208 205 86 148 16 132 192 145 138 194 60 9 198 147 53 65 64 96 242 
+14 222 119 241 46 116 132 197 184 238 189 26 200 62 176 80 151 140 109 183 24 
+44 191 172 234 107 21 192 140 99 94 65 54 7 42 24 49 230 20 229 73 212 45 169 
+115 180 141 56 200 41 87 121 161 219 231 214 207 1 19 20 219 236 12 55 237 237 
+211 72 13 28 141 72 239 152 82 87 100 72 8 241 41 77 32 202 229 47 84 238 184 
+228 100 67 210 130 46 111 93 97 189 31 250 162 171 35 90 4 138 199 99 120 193 
+113 244 181 93 123 76 90 235 49 251 109 188 63 144 186 138 184 223 61 208 215 
+175 107 6 53 81 114 207 237 221 161 224 18 73 202 208 210 125 248 11 98 131 250 
+167 221 146 85 211 88 63 139 136 27 189 5 111 103 186 148 21 171 51 140 104 133 
+165 49 225 233 129 78 5 106 64 86 153 55 232 187 111 77 58 89 36 32 223 66 6 74 
+170 62 197 169 110 130 41 61 234 102 234 92 145 133 155 201 14 243 208 200 36 
+48 21 166 1 40 109 178 147 ^
+522 0 179 196 200 34 251 241 156 51 23 75 118 41 193 202 90 93 236 125 242 125 
+101 151 130 14 218 34 106 41 197 173 55 112 37 108 211 65 174 142 136 159 22 19 
+245 127 16 19 131 101 10 133 20 104 122 126 184 227 9 187 225 208 90 230 7 131 
+105 213 121 39 137 105 95 147 45 23 216 92 35 75 114 70 205 206 34 110 12 185 
+169 111 95 6 71 29 79 203 32 195 144 161 82 64 228 92 8 104 126 74 172 223 65 
+170 194 171 140 221 36 21 164 198 5 102 211 206 148 136 18 48 25 131 215 36 162 
+161 192 142 14 214 63 141 45 141 190 86 149 219 94 182 198 115 157 252 73 203 
+173 192 115 43 226 67 85 62 172 227 13 135 190 227 123 213 231 94 178 227 150 
+161 196 90 234 210 119 124 14 104 8 100 178 109 153 167 82 201 231 98 149 215 
+146 217 179 59 174 28 133 130 159 163 248 239 9 183 254 243 71 174 24 162 165 
+163 107 10 15 46 110 8 214 204 115 39 23 79 89 6 189 3 73 85 176 198 1 154 246 
+210 115 153 49 108 207 117 209 146 103 176 53 56 172 113 10 129 72 116 126 70 
+201 3 69 114 211 202 200 171 22 247 42 139 20 218 148 132 70 83 29 75 67 199 88 
+178 113 124 155 78 2 214 67 89 33 160 246 69 118 159 167 196 204 5 216 237 212 
+34 247 38 191 55 222 92 149 78 120 211 61 226 177 140 103 39 27 50 54 25 245 
+241 42 25 249 212 30 21 50 195 254 239 123 186 28 106 182 171 167 192 1 17 220 
+181 229 65 29 220 177 26 77 33 164 194 57 137 215 150 165 167 78 230 11 102 93 
+232 177 22 129 68 168 138 74 145 20 77 174 138 188 171 26 218 7 158 76 201 117 
+72 120 74 35 197 59 52 83 151 20 214 177 144 51 27 46 106 37 249 185 59 56 54 
+139 16 15 160 136 14 100 37 112 182 53 170 198 119 128 240 69 4 156 161 78 116 
+240 96 207 121 157 134 99 209 36 25 135 186 1 158 194 175 111 209 32 77 147 190 
+200 175 225 235 38 195 3 187 88 205 61 89 151 134 217 206 30 162 24 166 113 128 
+103 66 253 15 50 58 228 210 5 98 8 218 152 80 35 79 62 58 224 7 17 102 207 3 
+183 140 217 65 56 168 165 22 133 16 133 157 107 128 244 12 ^
+517 1 218 150 217 59 81 203 140 217 148 45 193 82 116 122 93 236 7 11 127 242 
+235 123 155 246 125 238 148 134 126 72 27 247 67 27 50 162 22 247 127 153 45 
+133 213 121 151 159 105 209 231 36 166 217 177 140 188 53 50 222 148 242 67 87 
+145 157 250 181 227 177 51 224 63 108 97 174 194 24 162 250 152 132 182 80 33 
+189 84 60 83 118 37 216 235 94 60 251 154 47 48 110 120 238 208 229 121 43 218 
+90 91 64 110 12 40 193 111 211 117 64 170 107 35 164 76 54 141 101 4 183 53 79 
+60 143 213 32 187 169 194 84 31 245 123 66 25 135 39 23 160 78 29 102 95 62 166 
+20 46 135 128 244 150 246 154 76 143 105 91 172 51 27 158 103 37 108 37 79 199 
+84 228 119 128 95 91 4 15 17 69 2 11 187 80 230 94 89 89 149 244 239 210 144 18 
+42 48 139 215 233 179 163 252 67 255 181 167 82 56 253 98 8 42 137 103 205 144 
+47 137 43 110 149 76 203 200 86 143 16 127 182 140 128 184 55 251 183 142 43 50 
+54 81 232 9 212 119 236 36 106 122 182 169 223 179 26 185 57 166 80 141 130 99 
+178 24 44 191 167 219 92 6 187 140 99 89 60 54 249 42 19 44 220 5 214 63 197 30 
+164 105 180 136 41 195 26 77 116 151 219 231 204 202 1 9 15 214 231 7 40 222 
+237 206 57 255 13 131 72 224 152 72 87 85 62 255 241 36 77 27 187 229 32 79 228 
+179 223 90 62 195 115 41 106 93 87 174 26 245 152 161 20 75 4 123 184 84 120 
+178 113 234 181 78 118 66 85 230 34 251 94 178 53 139 186 138 184 223 61 193 
+200 175 107 6 38 81 114 207 227 206 146 219 3 73 197 198 200 115 238 11 98 116 
+240 152 221 146 70 201 88 58 139 126 12 189 252 96 93 176 138 16 156 51 135 99 
+118 155 49 220 233 119 68 96 64 81 143 45 222 177 111 62 58 79 31 17 218 61 253 
+69 170 47 197 169 105 120 41 46 224 92 234 92 145 128 155 186 256 243 208 200 
+26 48 21 156 248 40 104 178 221 175 196 196 28 249 239 150 49 23 71 114 39 191 
+196 88 87 234 121 240 123 95 151 130 10 214 34 102 35 193 171 49 112 35 104 207 
+59 170 136 130 159 16 19 241 125 213 ^
+529 1 15 127 93 2 121 8 104 114 126 176 223 1 183 225 196 90 230 3 119 93 201 
+117 39 125 97 91 147 41 19 216 80 35 75 110 58 193 198 26 98 8 185 161 103 95 
+257 71 21 71 199 24 183 144 149 74 52 228 88 255 96 114 66 172 215 61 166 190 
+167 128 209 36 13 152 186 256 94 199 202 136 128 10 40 21 131 203 32 162 161 
+184 142 14 210 55 141 37 129 186 78 141 215 82 170 198 107 145 244 65 195 173 
+192 103 35 214 63 81 54 164 215 1 123 182 227 111 213 227 90 170 219 150 153 
+184 82 230 202 115 124 2 100 4 96 174 109 141 155 78 201 219 90 149 215 142 213 
+167 47 162 20 133 118 155 159 248 235 9 183 246 239 59 170 20 154 161 163 99 6 
+11 38 106 8 206 204 111 35 15 67 89 253 181 250 69 85 164 194 256 154 242 210 
+115 145 45 108 203 113 209 138 103 176 45 48 160 105 10 121 68 108 122 66 193 
+258 69 106 207 202 196 171 18 239 38 127 12 214 144 128 70 83 29 71 67 191 84 
+166 109 120 151 70 2 202 55 81 33 160 246 61 106 147 159 188 192 1 204 229 204 
+30 247 38 187 55 222 84 145 66 112 211 53 226 173 132 99 27 15 46 46 25 241 233 
+34 17 241 212 30 9 42 195 254 239 119 174 28 94 178 159 167 188 252 5 212 169 
+221 65 17 220 169 22 69 25 160 186 57 137 207 142 153 163 78 222 3 98 89 232 
+177 22 129 68 168 126 74 133 16 65 174 130 184 163 18 218 254 158 72 197 109 60 
+108 62 23 185 59 52 71 139 20 214 165 132 39 23 46 106 29 249 173 51 52 50 135 
+12 15 148 136 10 100 25 100 182 49 158 190 107 124 240 57 255 156 157 74 112 
+232 96 195 113 149 134 95 197 28 13 131 182 248 154 182 167 107 205 28 73 135 
+190 188 171 217 235 30 187 254 179 76 205 49 77 143 130 205 206 26 158 12 154 
+101 120 91 66 253 3 38 46 224 198 5 94 206 144 68 27 75 50 54 224 258 9 102 199 
+3 179 136 209 57 56 160 165 14 129 8 125 157 95 116 240 36 212 148 217 57 77 
+203 134 213 146 43 193 80 116 122 87 236 7 9 123 242 231 119 153 244 125 238 
+142 132 120 70 23 245 63 21 50 156 16 243 127 153 45 129 207 121 149 155 99 205 
+227 30 166 211 57 ^
+548 0 134 188 53 47 219 148 236 58 84 142 148 247 172 224 174 45 221 63 99 97 
+171 194 15 156 250 149 132 179 71 30 183 78 54 77 118 37 207 232 94 60 248 151 
+47 42 110 117 235 205 223 112 43 212 81 82 61 101 12 34 190 102 208 117 58 167 
+104 29 164 76 45 138 101 1 180 50 70 51 143 210 32 181 163 191 81 31 245 123 63 
+16 135 30 17 154 75 26 93 92 62 163 14 43 129 119 244 144 240 148 70 134 105 91 
+166 42 27 155 94 28 102 31 79 199 84 225 110 128 89 85 255 9 17 60 259 5 187 74 
+224 91 83 80 146 238 233 207 138 18 39 39 133 209 230 179 154 252 64 255 175 
+158 82 50 247 89 2 33 128 100 199 135 41 131 34 107 140 67 200 197 86 140 16 
+124 176 137 122 178 52 245 174 139 37 41 48 72 226 6 206 119 233 30 100 116 173 
+160 214 173 26 176 54 160 80 135 124 93 175 24 44 191 164 210 83 257 184 140 99 
+86 57 54 243 42 16 41 214 256 205 57 188 21 161 99 180 133 32 192 17 71 113 145 
+219 231 198 199 1 3 12 211 228 4 31 213 237 203 48 249 4 125 72 215 152 66 87 
+76 56 252 241 33 77 24 178 229 23 76 222 176 220 84 59 186 106 38 103 93 81 165 
+23 242 146 155 11 66 4 114 175 75 120 169 113 228 181 69 115 60 82 227 25 251 
+85 172 47 136 186 138 184 223 61 184 191 175 107 6 29 81 114 207 221 197 137 
+216 254 73 194 192 194 109 232 11 98 107 234 143 221 146 61 195 88 55 139 120 3 
+189 249 87 87 170 132 13 147 51 132 96 109 149 49 217 233 113 62 257 90 64 78 
+137 39 216 171 111 53 58 73 28 8 215 58 250 66 170 38 197 169 102 114 41 37 218 
+86 234 92 145 125 155 177 250 243 208 200 20 48 21 150 245 40 101 178 218 169 
+196 190 19 246 236 141 46 23 65 108 36 188 187 85 78 231 115 237 120 86 151 130 
+4 208 34 96 26 187 168 40 112 32 98 201 50 164 127 121 159 7 19 235 122 1 14 
+126 91 118 5 104 112 126 174 222 259 182 225 193 90 230 2 116 90 198 116 39 122 
+95 90 147 40 18 216 77 35 75 109 55 190 196 24 95 7 185 159 101 95 256 71 19 69 
+198 22 180 144 146 72 49 228 87 253 94 111 64 172 213 60 165 189 166 125 206 36 
+11 149 183 255 92 196 201 133 126 8 38 20 131 213 ^
+547 0 29 162 161 178 142 14 207 49 141 31 120 183 72 135 212 73 161 198 101 136 
+238 59 189 173 192 94 29 205 60 78 48 158 206 254 114 176 227 102 213 224 87 
+164 213 150 147 175 76 227 196 112 124 255 97 1 93 171 109 132 146 75 201 210 
+84 149 215 139 210 158 38 153 14 133 109 152 156 248 232 9 183 240 236 50 167 
+17 148 158 163 93 3 8 32 103 8 200 204 108 32 9 58 89 247 175 244 66 85 155 191 
+256 154 239 210 115 139 42 108 200 110 209 132 103 176 39 42 151 99 10 115 65 
+102 119 63 187 258 69 100 204 202 193 171 15 233 35 118 6 211 141 125 70 83 29 
+68 67 185 81 157 106 117 148 64 2 193 46 75 33 160 246 55 97 138 153 182 183 
+260 195 223 198 27 247 38 184 55 222 78 142 57 106 211 47 226 170 126 96 18 6 
+43 40 25 238 227 28 11 235 212 30 36 195 254 239 116 165 28 85 175 150 167 185 
+249 258 206 160 215 65 8 220 163 19 63 19 157 180 57 137 201 136 144 160 78 216 
+259 95 86 232 177 22 129 68 168 117 74 124 13 56 174 124 181 157 12 218 248 158 
+69 194 103 51 99 53 14 176 59 52 62 130 20 214 156 123 30 20 46 106 23 249 164 
+45 49 47 132 9 15 139 136 7 100 16 91 182 46 149 184 98 121 240 48 252 156 154 
+71 109 226 96 186 107 143 134 92 188 22 4 128 179 242 151 173 161 104 202 25 70 
+126 190 179 168 211 235 24 181 251 173 67 205 40 68 137 127 196 206 23 155 3 
+145 92 114 82 66 253 256 29 37 221 189 5 91 256 197 138 59 21 72 41 51 224 255 
+3 102 193 3 176 133 203 51 56 154 165 8 126 2 119 157 86 107 237 33 203 145 217 
+54 71 203 125 207 143 40 193 77 116 122 78 236 7 6 117 242 225 113 150 241 125 
+238 133 129 111 67 17 242 57 12 50 147 7 237 127 153 45 123 198 121 146 149 90 
+199 221 21 166 202 162 130 188 53 45 217 148 232 52 82 140 142 245 166 222 172 
+41 219 63 93 97 169 194 9 152 250 147 132 177 65 28 179 74 50 73 118 37 201 230 
+94 60 246 149 47 38 110 115 233 203 219 106 43 208 75 76 59 95 12 30 188 96 206 
+117 54 165 102 25 164 76 39 136 101 261 178 48 64 45 143 208 32 177 159 189 79 
+31 245 123 61 10 135 24 13 150 73 24 87 90 62 161 10 41 125 209 ^
+542 1 244 136 232 140 62 122 105 91 158 30 27 151 82 16 94 23 79 199 84 221 98 
+128 81 77 247 1 17 48 259 261 187 66 216 87 75 68 142 230 225 203 130 18 35 27 
+125 201 226 179 142 252 60 255 167 146 82 42 239 77 258 21 116 96 191 123 33 
+123 22 103 128 55 196 193 86 136 16 120 168 133 114 170 48 237 162 135 29 29 40 
+60 218 2 198 119 229 22 92 108 161 148 202 165 26 164 50 152 80 127 116 85 171 
+24 44 191 160 198 71 249 180 140 99 82 53 54 235 42 12 37 206 248 193 49 176 9 
+157 91 180 129 20 188 5 63 109 137 219 231 190 195 1 259 8 207 224 19 201 237 
+199 36 241 256 117 72 203 152 58 87 64 48 248 241 29 77 20 166 229 11 72 214 
+172 216 76 55 174 94 34 99 93 73 153 19 238 138 147 263 54 4 102 163 63 120 157 
+113 220 181 57 111 52 78 223 13 251 73 164 39 132 186 138 184 223 61 172 179 
+175 107 6 17 81 114 207 213 185 125 212 246 73 190 184 186 101 224 11 98 95 226 
+131 221 146 49 187 88 51 139 112 255 189 245 75 79 162 124 9 135 51 128 92 97 
+141 49 213 233 105 54 257 82 64 74 129 31 208 163 111 41 58 65 24 260 211 54 
+246 62 170 26 197 169 98 106 41 25 210 78 234 92 145 121 155 165 242 243 208 
+200 12 48 21 142 241 40 97 178 214 161 196 182 7 242 232 129 42 23 57 100 32 
+184 175 81 66 227 107 233 116 74 151 130 260 200 34 88 14 179 164 28 112 28 90 
+193 38 156 115 109 159 259 19 227 118 253 10 122 83 256 106 257 104 104 126 166 
+218 255 178 225 181 90 230 262 104 78 186 112 39 110 87 86 147 36 14 216 65 35 
+75 105 43 178 188 16 83 3 185 151 93 95 252 71 11 61 194 14 168 144 134 64 37 
+228 83 245 86 99 56 172 205 56 161 185 162 113 194 36 3 137 171 251 84 184 197 
+121 118 30 16 131 188 27 162 161 174 142 14 205 45 141 27 114 181 68 131 210 67 
+155 198 97 130 234 55 185 173 192 88 25 199 58 76 44 154 200 250 108 172 227 96 
+213 222 85 160 209 150 143 169 72 225 192 110 124 251 95 263 91 169 109 126 140 
+73 201 204 80 149 215 137 208 152 32 147 10 133 103 150 154 248 230 9 183 236 
+234 44 165 15 144 156 163 89 1 6 28 101 8 196 204 106 164 ^
+567 0 1 46 89 239 167 236 62 85 143 187 256 154 235 210 115 131 38 108 196 106 
+209 124 103 176 31 34 139 91 10 107 61 94 115 59 179 258 69 92 200 202 189 171 
+11 225 31 106 264 207 137 121 70 83 29 64 67 177 77 145 102 113 144 56 2 181 34 
+67 33 160 246 47 85 126 145 174 171 260 183 215 190 23 247 38 180 55 222 70 138 
+45 98 211 39 226 166 118 92 6 260 39 32 25 234 219 20 3 227 212 30 254 28 195 
+254 239 112 153 28 73 171 138 167 181 245 250 198 148 207 65 262 220 155 15 55 
+11 153 172 57 137 193 128 132 156 78 208 255 91 82 232 177 22 129 68 168 105 74 
+112 9 44 174 116 177 149 4 218 240 158 65 190 95 39 87 41 2 164 59 52 50 118 20 
+214 144 111 18 16 46 106 15 249 152 37 45 43 128 5 15 127 136 3 100 4 79 182 42 
+137 176 86 117 240 36 248 156 150 67 105 218 96 174 99 135 134 88 176 14 258 
+124 175 234 147 161 153 100 198 21 66 114 190 167 164 203 235 16 173 247 165 55 
+205 28 56 129 123 184 206 19 151 257 133 80 106 70 66 253 248 17 25 217 177 5 
+87 252 185 130 47 13 68 29 47 224 251 261 102 185 3 172 129 195 43 56 146 165 
+122 260 111 157 74 95 233 29 191 141 217 50 63 203 113 199 139 36 193 73 116 
+122 66 236 7 2 109 242 217 105 146 237 125 238 121 125 99 63 9 238 49 50 135 
+261 229 127 153 45 115 186 121 142 141 78 191 213 9 166 190 150 122 188 53 41 
+213 148 224 40 78 136 130 241 154 218 168 33 215 63 81 97 165 194 263 144 250 
+143 132 173 53 24 171 66 42 65 118 37 189 226 94 60 242 145 47 30 110 111 229 
+199 211 94 43 200 63 64 55 83 12 22 184 84 202 117 46 161 98 17 164 76 27 132 
+101 261 174 44 52 33 143 204 32 169 151 185 75 31 245 123 57 264 135 12 5 142 
+69 20 75 86 62 157 2 37 117 101 244 132 228 136 58 116 105 91 154 24 27 149 76 
+10 90 19 79 199 84 219 92 128 77 73 243 263 17 42 259 259 187 62 212 85 71 62 
+140 226 221 201 126 18 33 21 121 197 224 179 136 252 58 255 163 140 82 38 235 
+71 256 15 110 94 187 117 29 119 16 101 122 49 194 191 86 134 16 118 164 131 110 
+166 46 233 156 133 25 23 36 54 214 194 119 227 18 88 104 155 142 196 161 26 158 
+48 148 80 123 112 81 169 24 44 191 158 192 65 245 178 140 223 ^
+551 1 78 49 54 227 42 8 33 198 240 181 41 164 265 153 83 180 125 8 184 261 55 
+105 129 219 231 182 191 1 255 4 203 220 264 7 189 237 195 24 233 248 109 72 191 
+152 50 87 52 40 244 241 25 77 16 154 229 267 68 206 168 212 68 51 162 82 30 95 
+93 65 141 15 234 130 139 255 42 4 90 151 51 120 145 113 212 181 45 107 44 74 
+219 1 251 61 156 31 128 186 138 184 223 61 160 167 175 107 6 5 81 114 207 205 
+173 113 208 238 73 186 176 178 93 216 11 98 83 218 119 221 146 37 179 88 47 139 
+104 247 189 241 63 71 154 116 5 123 51 124 88 85 133 49 209 233 97 46 257 74 64 
+70 121 23 200 155 111 29 58 57 20 252 207 50 242 58 170 14 197 169 94 98 41 13 
+202 70 234 92 145 117 155 153 234 243 208 200 4 48 21 134 237 40 93 178 210 153 
+196 174 263 238 228 117 38 23 49 92 28 180 163 77 54 223 99 229 112 62 151 130 
+256 192 34 80 2 171 160 16 112 24 82 185 26 148 103 97 159 251 19 219 114 245 6 
+118 75 252 94 249 104 96 126 158 214 251 174 225 169 90 230 262 92 66 174 108 
+39 98 79 82 147 32 10 216 53 35 75 101 31 166 180 8 71 267 185 143 85 95 248 71 
+3 53 190 6 156 144 122 56 25 228 79 237 78 87 48 172 197 52 157 181 158 101 182 
+36 263 125 159 247 76 172 193 109 110 260 22 12 131 176 23 162 161 166 142 14 
+201 37 141 19 102 177 60 123 206 55 143 198 89 118 226 47 177 173 192 76 17 187 
+54 72 36 146 188 242 96 164 227 84 213 218 81 152 201 150 135 157 64 221 184 
+106 124 243 91 263 87 165 109 114 128 69 201 192 72 149 215 133 204 140 20 135 
+2 133 91 146 150 248 226 9 183 228 230 32 161 11 136 152 163 81 265 2 20 97 8 
+188 204 102 26 265 40 89 235 163 232 60 85 137 185 256 154 233 210 115 127 36 
+108 194 104 209 120 103 176 27 30 133 87 10 103 59 90 113 57 175 258 69 88 198 
+202 187 171 9 221 29 100 262 205 135 119 70 83 29 62 67 173 75 139 100 111 142 
+52 2 175 28 63 33 160 246 43 79 120 141 170 165 260 177 211 186 21 247 38 178 
+55 222 66 136 39 94 211 35 226 164 114 90 256 37 28 25 232 215 16 267 223 212 
+30 250 24 195 254 239 110 147 28 67 169 132 167 179 243 246 194 142 203 65 263 ^
+578 0 220 147 11 47 3 149 164 57 137 185 120 120 152 78 200 251 87 78 232 177 
+22 129 68 168 93 74 100 5 32 174 108 173 141 266 218 232 158 61 186 87 27 75 29 
+260 152 59 52 38 106 20 214 132 99 6 12 46 106 7 249 140 29 41 39 124 1 15 115 
+136 269 100 262 67 182 38 125 168 74 113 240 24 244 156 146 63 101 210 96 162 
+91 127 134 84 164 6 250 120 171 226 143 149 145 96 194 17 62 102 190 155 160 
+195 235 8 165 243 157 43 205 16 44 121 119 172 206 15 147 249 121 68 98 58 66 
+253 240 5 13 213 165 5 83 248 173 122 35 5 64 17 43 224 247 257 102 177 3 168 
+125 187 35 56 138 165 262 118 256 103 157 62 83 229 25 179 137 217 46 55 203 
+101 191 135 32 193 69 116 122 54 236 7 268 101 242 209 97 142 233 125 238 109 
+121 87 59 1 234 41 258 50 123 253 221 127 153 45 107 174 121 138 133 66 183 205 
+267 166 178 138 114 188 53 37 209 148 216 28 74 132 118 237 142 214 164 25 211 
+63 69 97 161 194 255 136 250 139 132 169 41 20 163 58 34 57 118 37 177 222 94 
+60 238 141 47 22 110 107 225 195 203 82 43 192 51 52 51 71 12 14 180 72 198 117 
+38 157 94 9 164 76 15 128 101 261 170 40 40 21 143 200 32 161 143 181 71 31 245 
+123 53 256 135 267 134 65 16 63 82 62 153 264 33 109 89 244 124 220 128 50 104 
+105 91 146 12 27 145 64 268 82 11 79 199 84 215 80 128 69 65 235 259 17 30 259 
+255 187 54 204 81 63 50 136 218 213 197 118 18 29 9 113 189 220 179 124 252 54 
+255 155 128 82 30 227 59 252 3 98 90 179 105 21 111 4 97 110 37 190 187 86 130 
+16 114 156 127 102 158 42 225 144 129 17 11 28 42 206 266 186 119 223 10 80 96 
+143 130 184 153 26 146 44 140 80 115 104 73 165 24 44 191 154 180 53 237 174 
+140 99 76 47 54 223 42 6 31 194 236 175 37 158 261 151 79 180 123 2 182 257 51 
+103 125 219 231 178 189 1 253 2 201 218 264 1 183 237 193 18 229 244 105 72 185 
+152 46 87 46 36 242 241 23 77 14 148 229 263 66 202 166 210 64 49 156 76 28 93 
+93 61 135 13 232 126 135 251 36 4 84 145 45 120 139 113 208 181 39 105 40 72 
+217 265 251 55 152 27 126 186 138 184 223 61 154 161 175 107 6 269 81 114 207 
+201 167 107 206 234 73 184 172 174 89 212 11 98 77 214 113 221 146 31 175 88 45 
+139 100 243 189 213 ^
+578 1 51 63 146 108 1 111 51 120 84 73 125 49 205 233 89 38 257 66 64 66 113 15 
+192 147 111 17 58 49 16 244 203 46 238 54 170 2 197 169 90 90 41 1 194 62 234 
+92 145 113 155 141 226 243 208 200 268 48 21 126 233 40 89 178 206 145 196 166 
+255 234 224 105 34 23 41 84 24 176 151 73 42 219 91 225 108 50 151 130 252 184 
+34 72 262 163 156 4 112 20 74 177 14 140 91 85 159 243 19 211 110 237 2 114 67 
+248 82 241 104 88 126 150 210 247 170 225 157 90 230 262 80 54 162 104 39 86 71 
+78 147 28 6 216 41 35 75 97 19 154 172 59 267 185 135 77 95 244 71 267 45 186 
+270 144 144 110 48 13 228 75 229 70 75 40 172 189 48 153 177 154 89 170 36 259 
+113 147 243 68 160 189 97 102 256 14 8 131 164 19 162 161 158 142 14 197 29 141 
+11 90 173 52 115 202 43 131 198 81 106 218 39 169 173 192 64 9 175 50 68 28 138 
+176 234 84 156 227 72 213 214 77 144 193 150 127 145 56 217 176 102 124 235 87 
+263 83 161 109 102 116 65 201 180 64 149 215 129 200 128 8 123 266 133 79 142 
+146 248 222 9 183 220 226 20 157 7 128 148 163 73 265 270 12 93 8 180 204 98 22 
+261 28 89 227 155 224 56 85 125 181 256 154 229 210 115 119 32 108 190 100 209 
+112 103 176 19 22 121 79 10 95 55 82 109 53 167 258 69 80 194 202 183 171 5 213 
+25 88 258 201 131 115 70 83 29 58 67 165 71 127 96 107 138 44 2 163 16 55 33 
+160 246 35 67 108 133 162 153 260 165 203 178 17 247 38 174 55 222 58 132 27 86 
+211 27 226 160 106 86 260 248 33 20 25 228 207 8 263 215 212 30 242 16 195 254 
+239 106 135 28 55 165 120 167 175 239 238 186 130 195 65 250 220 143 9 43 271 
+147 160 57 137 181 116 114 150 78 196 249 85 76 232 177 22 129 68 168 87 74 94 
+3 26 174 104 171 137 264 218 228 158 59 184 83 21 69 23 256 146 59 52 32 100 20 
+214 126 93 10 46 106 3 249 134 25 39 37 122 271 15 109 136 269 100 258 61 182 
+36 119 164 68 111 240 18 242 156 144 61 99 206 96 156 87 123 134 82 158 2 246 
+118 169 222 141 143 141 94 192 15 60 96 190 149 158 191 235 4 161 241 153 37 
+205 10 38 117 117 166 206 13 145 245 115 62 94 52 66 253 236 271 7 211 159 5 81 
+246 167 118 29 1 62 11 41 224 245 255 102 173 3 166 123 183 31 56 134 165 260 
+116 254 81 ^
+583 1 157 50 71 225 21 167 133 217 42 47 203 89 183 131 28 193 65 116 122 42 
+236 7 268 93 242 201 89 138 229 125 238 97 117 75 55 267 230 33 250 50 111 245 
+213 127 153 45 99 162 121 134 125 54 175 197 259 166 166 126 106 188 53 33 205 
+148 208 16 70 128 106 233 130 210 160 17 207 63 57 97 157 194 247 128 250 135 
+132 165 29 16 155 50 26 49 118 37 165 218 94 60 234 137 47 14 110 103 221 191 
+195 70 43 184 39 40 47 59 12 6 176 60 194 117 30 153 90 1 164 76 3 124 101 261 
+166 36 28 9 143 196 32 153 135 177 67 31 245 123 49 248 135 262 263 126 61 12 
+51 78 62 149 260 29 101 77 244 116 212 120 42 92 105 91 138 27 141 52 260 74 3 
+79 199 84 211 68 128 61 57 227 255 17 18 259 251 187 46 196 77 55 38 132 210 
+205 193 110 18 25 271 105 181 216 179 112 252 50 255 147 116 82 22 219 47 248 
+265 86 86 171 93 13 103 266 93 98 25 186 183 86 126 16 110 148 123 94 150 38 
+217 132 125 9 273 20 30 198 266 178 119 219 2 72 88 131 118 172 145 26 134 40 
+132 80 107 96 65 161 24 44 191 150 168 41 229 170 140 99 72 43 54 215 42 2 27 
+186 228 163 29 146 253 147 71 180 119 264 178 249 43 99 117 219 231 170 185 1 
+249 272 197 214 264 263 171 237 189 6 221 236 97 72 173 152 38 87 34 28 238 241 
+19 77 10 136 229 255 62 194 162 206 56 45 144 64 24 89 93 53 123 9 228 118 127 
+243 24 4 72 133 33 120 127 113 200 181 27 101 32 68 213 257 251 43 144 19 122 
+186 138 184 223 61 142 149 175 107 6 261 81 114 207 193 155 95 202 226 73 180 
+164 166 81 204 11 98 65 206 101 221 146 19 167 88 41 139 92 235 189 235 45 59 
+142 104 273 105 51 118 82 67 121 49 203 233 85 34 257 62 64 64 109 11 188 143 
+111 11 58 45 14 240 201 44 236 52 170 270 197 169 88 86 41 269 190 58 234 92 
+145 111 155 135 222 243 208 200 266 48 21 122 231 40 87 178 204 141 196 162 251 
+232 222 99 32 23 37 80 22 174 145 71 36 217 87 223 106 44 151 130 250 180 34 68 
+258 159 154 272 112 18 70 173 8 136 85 79 159 239 19 207 108 233 112 63 246 76 
+237 104 84 126 146 208 245 168 225 151 90 230 262 74 48 156 102 39 80 67 76 147 
+26 4 216 35 35 75 95 13 148 168 270 53 267 185 131 73 95 242 71 265 41 184 268 
+138 144 104 44 7 228 73 225 66 69 36 272 ^
+588 0 181 44 149 173 150 77 158 36 255 101 135 239 60 148 185 85 94 252 6 4 131 
+152 15 162 161 150 142 14 193 21 141 3 78 169 44 107 198 31 119 198 73 94 210 
+31 161 173 192 52 1 163 46 64 20 130 164 226 72 148 227 60 213 210 73 136 185 
+150 119 133 48 213 168 98 124 227 83 263 79 157 109 90 104 61 201 168 56 149 
+215 125 196 116 272 111 262 133 67 138 142 248 218 9 183 212 222 8 153 3 120 
+144 163 65 265 270 4 89 8 172 204 94 18 257 16 89 219 147 216 52 85 113 177 256 
+154 225 210 115 111 28 108 186 96 209 104 103 176 11 14 109 71 10 87 51 74 105 
+49 159 258 69 72 190 202 179 171 1 205 21 76 254 197 127 111 70 83 29 54 67 157 
+67 115 92 103 134 36 2 151 4 47 33 160 246 27 55 96 125 154 141 260 153 195 170 
+13 247 38 170 55 222 50 128 15 78 211 19 226 156 98 82 252 240 29 12 25 224 199 
+259 207 212 30 234 8 195 254 239 102 123 28 43 161 108 167 171 235 230 178 118 
+187 65 242 220 135 5 35 267 143 152 57 137 173 108 102 146 78 188 245 81 72 232 
+177 22 129 68 168 75 74 82 275 14 174 96 167 129 260 218 220 158 55 180 75 9 57 
+11 248 134 59 52 20 88 20 214 114 81 264 6 46 106 271 249 122 17 35 33 118 271 
+15 97 136 269 100 250 49 182 32 107 156 56 107 240 6 238 156 140 57 95 198 96 
+144 79 115 134 78 146 270 238 114 165 214 137 131 133 90 188 11 56 84 190 137 
+154 183 235 272 153 237 145 25 205 274 26 109 113 154 206 9 141 237 103 50 86 
+40 66 253 228 263 271 207 147 5 77 242 155 110 17 269 58 275 37 224 241 251 102 
+165 3 162 119 175 23 56 126 165 256 112 250 91 157 44 65 223 19 161 131 217 40 
+43 203 83 179 129 26 193 63 116 122 36 236 7 268 89 242 197 85 136 227 125 238 
+91 115 69 53 265 228 29 246 50 105 241 209 127 153 45 95 156 121 132 121 48 171 
+193 255 166 160 120 102 188 53 31 203 148 204 10 68 126 100 231 124 208 158 13 
+205 63 51 97 155 194 243 124 250 133 132 163 23 14 151 46 22 45 118 37 159 216 
+94 60 232 135 47 10 110 101 219 189 191 64 43 180 33 34 45 53 12 2 174 54 192 
+117 26 151 88 273 164 76 273 122 101 261 164 34 22 3 143 194 32 149 131 175 65 
+31 245 123 47 244 135 258 261 122 59 10 45 76 62 147 258 27 97 71 244 112 208 
+116 38 86 105 91 134 270 27 139 46 256 70 275 79 199 160 ^
+594 0 207 56 128 53 49 219 251 17 6 259 247 187 38 188 73 47 26 128 202 197 189 
+102 18 21 263 97 173 212 179 100 252 46 255 139 104 82 14 211 35 244 257 74 82 
+163 81 5 95 258 89 86 13 182 179 86 122 16 106 140 119 86 142 34 209 120 121 1 
+265 12 18 190 266 170 119 215 272 64 80 119 106 160 137 26 122 36 124 80 99 88 
+57 157 24 44 191 146 156 29 221 166 140 99 68 39 54 207 42 276 23 178 220 151 
+21 134 245 143 63 180 115 256 174 241 35 95 109 219 231 162 181 1 245 272 193 
+210 264 255 159 237 185 272 213 228 89 72 161 152 30 87 22 20 234 241 15 77 6 
+124 229 247 58 186 158 202 48 41 132 52 20 85 93 45 111 5 224 110 119 235 12 4 
+60 121 21 120 115 113 192 181 15 97 24 64 209 249 251 31 136 11 118 186 138 184 
+223 61 130 137 175 107 6 253 81 114 207 185 143 83 198 218 73 176 156 158 73 
+196 11 98 53 198 89 221 146 7 159 88 37 139 84 227 189 231 33 51 134 96 273 93 
+51 114 78 55 113 49 199 233 77 26 257 54 64 60 101 3 180 135 111 277 58 37 10 
+232 197 40 232 48 170 262 197 169 84 78 41 261 182 50 234 92 145 107 155 123 
+214 243 208 200 262 48 21 114 227 40 83 178 200 133 196 154 243 228 218 87 28 
+23 29 72 18 170 133 67 24 213 79 219 102 32 151 130 246 172 34 60 250 151 150 
+264 112 14 62 165 274 128 73 67 159 231 19 199 104 225 274 108 55 242 64 229 
+104 76 126 138 204 241 164 225 139 90 230 262 62 36 144 98 39 68 59 72 147 22 
+216 23 35 75 91 1 136 160 266 41 267 185 123 65 95 238 71 261 33 180 264 126 
+144 92 36 273 228 69 217 58 57 28 172 177 42 147 171 148 71 152 36 253 95 129 
+237 56 142 183 79 90 250 2 2 131 146 13 162 161 146 142 14 191 17 141 277 72 
+167 40 103 196 25 113 198 69 88 206 27 157 173 192 46 275 157 44 62 16 126 158 
+222 66 144 227 54 213 208 71 132 181 150 115 127 44 211 164 96 124 223 81 263 
+77 155 109 84 98 59 201 162 52 149 215 123 194 110 268 105 260 133 61 136 140 
+248 216 9 183 208 220 2 151 1 116 142 163 61 265 270 87 8 168 204 92 16 255 10 
+89 215 143 212 50 85 107 175 256 154 223 210 115 107 26 108 184 94 209 100 103 
+176 7 10 103 67 10 83 49 70 103 47 155 258 69 68 188 202 177 171 277 201 19 70 
+252 195 125 109 70 83 29 52 67 153 65 109 90 101 132 32 2 145 276 43 33 160 246 
+23 259 ^
+600 1 87 119 148 132 260 144 189 164 10 247 38 167 55 222 44 125 6 72 211 13 
+226 153 92 79 246 234 26 6 25 221 193 273 256 201 212 30 228 2 195 254 239 99 
+114 28 34 158 99 167 168 232 224 172 109 181 65 236 220 129 2 29 264 140 146 57 
+137 167 102 93 143 78 182 242 78 69 232 177 22 129 68 168 66 74 73 275 5 174 90 
+164 123 257 218 214 158 52 177 69 48 2 242 125 59 52 11 79 20 214 105 72 258 3 
+46 106 268 249 113 11 32 30 115 271 15 88 136 269 100 244 40 182 29 98 150 47 
+104 240 276 235 156 137 54 92 192 96 135 73 109 134 75 137 267 232 111 162 208 
+134 122 127 87 185 8 53 75 190 128 151 177 235 269 147 234 139 16 205 268 17 
+103 110 145 206 6 138 231 94 41 80 31 66 253 222 257 265 204 138 5 74 239 146 
+104 8 266 55 269 34 224 238 248 102 159 3 159 116 169 17 56 120 165 253 109 247 
+85 157 35 56 220 16 152 128 217 37 37 203 74 173 126 23 193 60 116 122 27 236 7 
+268 83 242 191 79 133 224 125 238 82 112 60 50 262 225 23 240 50 96 235 203 127 
+153 45 89 147 121 129 115 39 165 187 249 166 151 111 96 188 53 28 200 148 198 1 
+65 123 91 228 115 205 155 7 202 63 42 97 152 194 237 118 250 130 132 160 14 11 
+145 40 16 39 118 37 150 213 94 60 229 132 47 4 110 98 216 186 185 55 43 174 24 
+25 42 44 12 275 171 45 189 117 20 148 85 270 164 76 267 119 101 261 161 31 13 
+273 143 191 32 143 125 172 62 31 245 123 44 238 135 252 258 116 56 7 36 73 62 
+144 255 24 91 62 244 106 202 110 32 77 105 91 128 264 27 136 37 250 64 272 79 
+199 84 206 53 128 51 47 217 250 17 3 259 246 187 36 186 72 45 23 127 200 195 
+188 100 18 20 261 95 171 211 179 97 252 45 255 137 101 82 12 209 32 243 255 71 
+81 161 78 3 93 256 88 83 10 181 178 86 121 16 105 138 118 84 140 33 207 117 120 
+278 263 10 15 188 266 168 119 214 271 62 78 116 103 157 135 26 119 35 122 80 97 
+86 55 156 24 44 191 145 153 26 219 165 140 99 67 38 54 205 42 276 22 176 218 
+148 19 131 243 142 61 180 114 254 173 239 33 94 107 219 231 160 180 1 244 272 
+192 209 264 253 156 237 184 270 211 226 87 72 158 152 28 87 19 18 233 241 14 77 
+5 121 229 245 57 184 157 201 46 40 129 49 19 84 93 43 108 4 223 108 117 233 9 4 
+57 118 18 120 112 113 190 181 12 96 22 63 208 247 251 28 134 9 117 186 138 184 
+223 61 127 216 ^
+590 1 175 107 6 247 81 114 207 179 134 74 195 212 73 173 150 152 67 190 11 98 
+44 192 80 221 146 279 153 88 34 139 78 221 189 228 24 45 128 90 273 84 51 111 
+75 46 107 49 196 233 71 20 257 48 64 57 95 278 174 129 111 271 58 31 7 226 194 
+37 229 45 170 256 197 169 81 72 41 255 176 44 234 92 145 104 155 114 208 243 
+208 200 259 48 21 108 224 40 80 178 197 127 196 148 237 225 215 78 25 23 23 66 
+15 167 124 64 15 210 73 216 99 23 151 130 243 166 34 54 244 145 147 258 112 11 
+56 159 268 122 64 58 159 225 19 193 101 219 274 105 49 239 55 223 104 70 126 
+132 201 238 161 225 130 90 230 262 53 27 135 95 39 59 53 69 147 19 278 216 14 
+35 75 88 273 127 154 263 32 267 185 117 59 95 235 71 258 27 177 261 117 144 83 
+30 267 228 66 211 52 48 22 172 171 39 144 168 145 62 143 36 250 86 120 234 50 
+133 180 70 84 247 277 280 131 137 10 162 161 140 142 14 188 11 141 274 63 164 
+34 97 193 16 104 198 63 79 200 21 151 173 192 37 272 148 41 59 10 120 149 216 
+57 138 227 45 213 205 68 126 175 150 109 118 38 208 158 93 124 217 78 263 74 
+152 109 75 89 56 201 153 46 149 215 120 191 101 262 96 257 133 52 133 137 248 
+213 9 183 202 217 274 148 279 110 139 163 55 265 270 275 84 8 162 204 89 13 252 
+1 89 209 137 206 47 85 98 172 256 154 220 210 115 101 23 108 181 91 209 94 103 
+176 1 4 94 61 10 77 46 64 100 44 149 258 69 62 185 202 174 171 277 195 16 61 
+249 192 122 106 70 83 29 49 67 147 62 100 87 98 129 26 2 136 270 37 33 160 246 
+17 40 81 115 144 126 260 138 185 160 8 247 38 165 55 222 40 123 68 211 9 226 
+151 88 77 242 230 24 2 25 219 189 271 254 197 212 30 224 279 195 254 239 97 108 
+28 28 156 93 167 166 230 220 168 103 177 65 232 220 125 25 262 138 142 57 137 
+163 98 87 141 78 178 240 76 67 232 177 22 129 68 168 60 74 67 275 280 174 86 
+162 119 255 218 210 158 50 175 65 275 42 277 238 119 59 52 5 73 20 214 99 66 
+254 1 46 106 266 249 107 7 30 28 113 271 15 82 136 269 100 240 34 182 27 92 146 
+41 102 240 272 233 156 135 52 90 188 96 129 69 105 134 73 131 265 228 109 160 
+204 132 116 123 85 183 6 51 69 190 122 149 173 235 267 143 232 135 10 205 264 
+11 99 108 139 206 4 136 227 88 35 76 25 66 253 218 253 261 202 132 5 72 237 140 
+203 ^
+620 0 279 262 51 261 30 224 234 244 102 151 3 155 112 161 9 56 112 165 249 105 
+243 77 157 23 44 216 12 140 124 217 33 29 203 62 165 122 19 193 56 116 122 15 
+236 7 268 75 242 183 71 129 220 125 238 70 108 48 46 258 221 15 232 50 84 227 
+195 127 153 45 81 135 121 125 107 27 157 179 241 166 139 99 88 188 53 24 196 
+148 190 272 61 119 79 224 103 201 151 282 198 63 30 97 148 194 229 110 250 126 
+132 156 2 7 137 32 8 31 118 37 138 209 94 60 225 128 47 279 110 94 212 182 177 
+43 43 166 12 13 38 32 12 271 167 33 185 117 12 144 81 266 164 76 259 115 101 
+261 157 27 1 265 143 187 32 135 117 168 58 31 245 123 40 230 135 244 254 108 52 
+3 24 69 62 140 251 20 83 50 244 98 194 102 24 65 105 91 120 256 27 132 25 242 
+56 268 79 199 84 202 41 128 43 39 209 246 17 274 259 242 187 28 178 68 37 11 
+123 192 187 184 92 18 16 253 87 163 207 179 85 252 41 255 129 89 82 4 201 20 
+239 247 59 77 153 66 278 85 248 84 71 281 177 174 86 117 16 101 130 114 76 132 
+29 199 105 116 274 255 2 3 180 266 160 119 210 267 54 70 104 91 145 127 26 107 
+31 114 80 89 78 47 152 24 44 191 141 141 14 211 161 140 99 63 34 54 197 42 276 
+18 168 210 136 11 119 235 138 53 180 110 246 169 231 25 90 99 219 231 152 176 1 
+240 272 188 205 264 245 144 237 180 262 203 218 79 72 146 152 20 87 7 10 229 
+241 10 77 1 109 229 237 53 176 153 197 38 36 117 37 15 80 93 35 96 219 100 109 
+225 280 4 45 106 6 120 100 113 182 181 92 14 59 204 239 251 16 126 1 113 186 
+138 184 223 61 115 122 175 107 6 243 81 114 207 175 128 68 193 208 73 171 146 
+148 63 186 11 98 38 188 74 221 146 275 149 88 32 139 74 217 189 226 18 41 124 
+86 273 78 51 109 73 40 103 49 194 233 67 16 257 44 64 55 91 276 170 125 111 267 
+58 27 5 222 192 35 227 43 170 252 197 169 79 68 41 251 172 40 234 92 145 102 
+155 108 204 243 208 200 257 48 21 104 222 40 78 178 195 123 196 144 233 223 213 
+72 23 23 19 62 13 165 118 62 9 208 69 214 97 17 151 130 241 162 34 50 240 141 
+145 254 112 9 52 155 264 118 58 52 159 221 19 189 99 215 274 103 45 237 49 219 
+104 66 126 128 199 236 159 225 124 90 230 262 47 21 129 93 39 53 49 67 147 17 
+278 216 8 35 75 86 269 121 150 261 26 267 185 113 55 95 233 71 256 23 175 259 
+111 144 77 26 263 228 64 207 48 42 18 172 167 37 142 166 143 56 137 36 248 80 
+114 232 46 127 257 ^
+605 1 58 76 243 273 280 131 125 6 162 161 132 142 14 184 3 141 270 51 160 26 89 
+189 4 92 198 55 67 192 13 143 173 192 25 268 136 37 55 2 112 137 208 45 130 227 
+33 213 201 64 118 167 150 101 106 30 204 150 89 124 209 74 263 70 148 109 63 77 
+52 201 141 38 149 215 116 187 89 254 84 253 133 40 129 133 248 209 9 183 194 
+213 266 144 279 102 135 163 47 265 270 271 80 8 154 204 85 9 248 274 89 201 129 
+198 43 85 86 168 256 154 216 210 115 93 19 108 177 87 209 86 103 176 278 281 82 
+53 10 69 42 56 96 40 141 258 69 54 181 202 170 171 277 187 12 49 245 188 118 
+102 70 83 29 45 67 139 58 88 83 94 125 18 2 124 262 29 33 160 246 9 28 69 107 
+136 114 260 126 177 152 4 247 38 161 55 222 32 119 273 60 211 1 226 147 80 73 
+234 222 20 279 25 215 181 267 250 189 212 30 216 275 195 254 239 93 96 28 16 
+152 81 167 162 226 212 160 91 169 65 224 220 117 281 17 258 134 134 57 137 155 
+90 75 137 78 170 236 72 63 232 177 22 129 68 168 48 74 55 275 272 174 78 158 
+111 251 218 202 158 46 171 57 267 30 269 230 107 59 52 278 61 20 214 87 54 246 
+282 46 106 262 249 95 284 26 24 109 271 15 70 136 269 100 232 22 182 23 80 138 
+29 98 240 264 229 156 131 48 86 180 96 117 61 97 134 69 119 261 220 105 156 196 
+128 104 115 81 179 2 47 57 190 110 145 165 235 263 135 228 127 283 205 256 284 
+91 104 127 206 132 219 76 23 68 13 66 253 210 245 253 198 120 5 68 233 128 92 
+275 260 49 257 28 224 232 242 102 147 3 153 110 157 5 56 108 165 247 103 241 73 
+157 17 38 214 10 134 122 217 31 25 203 56 161 120 17 193 54 116 122 9 236 7 268 
+71 242 179 67 127 218 125 238 64 106 42 44 256 219 11 228 50 78 223 191 127 153 
+45 77 129 121 123 103 21 153 175 237 166 133 93 84 188 53 22 194 148 186 268 59 
+117 73 222 97 199 149 280 196 63 24 97 146 194 225 106 250 124 132 154 281 5 
+133 28 4 27 118 37 132 207 94 60 223 126 47 277 110 92 210 180 173 37 43 162 6 
+7 36 26 12 269 165 27 183 117 8 142 79 264 164 76 255 113 101 261 155 25 280 
+261 143 185 32 131 113 166 56 31 245 123 38 226 135 240 252 104 50 1 18 67 62 
+138 249 18 79 44 244 94 190 98 20 59 105 91 116 252 27 130 19 238 52 266 79 199 
+84 200 35 128 39 35 205 244 17 270 259 240 187 24 174 66 33 5 121 188 183 182 
+88 18 14 249 83 159 205 179 79 252 186 ^
+615 0 255 121 77 82 283 193 8 235 239 47 73 145 54 274 77 240 80 59 273 173 170 
+86 113 16 97 122 110 68 124 25 191 93 112 270 247 281 278 172 266 152 119 206 
+263 46 62 92 79 133 119 26 95 27 106 80 81 70 39 148 24 44 191 137 129 2 203 
+157 140 99 59 30 54 189 42 276 14 160 202 124 3 107 227 134 45 180 106 238 165 
+223 17 86 91 219 231 144 172 1 236 272 184 201 264 237 132 237 176 254 195 210 
+71 72 134 152 12 87 282 2 225 241 6 77 284 97 229 229 49 168 149 193 30 32 105 
+25 11 76 93 27 84 283 215 92 101 217 272 4 33 94 281 120 88 113 174 181 275 88 
+6 55 200 231 251 4 118 280 109 186 138 184 223 61 103 110 175 107 6 235 81 114 
+207 167 116 56 189 200 73 167 138 140 55 178 11 98 26 180 62 221 146 267 141 88 
+28 139 66 209 189 222 6 33 116 78 273 66 51 105 69 28 95 49 190 233 59 8 257 36 
+64 51 83 272 162 117 111 259 58 19 1 214 188 31 223 39 170 244 197 169 75 60 41 
+243 164 32 234 92 145 98 155 96 196 243 208 200 253 48 21 96 218 40 74 178 191 
+115 196 136 225 219 209 60 19 23 11 54 9 161 106 58 284 204 61 210 93 5 151 130 
+237 154 34 42 232 133 141 246 112 5 44 147 256 110 46 40 159 213 19 181 95 207 
+274 99 37 233 37 211 104 58 126 120 195 232 155 225 112 90 230 262 35 9 117 89 
+39 41 41 63 147 13 278 216 283 35 75 82 261 109 142 257 14 267 185 105 47 95 
+229 71 252 15 171 255 99 144 65 18 255 228 60 199 40 30 10 172 159 33 138 162 
+139 44 125 36 244 68 102 228 38 115 174 52 72 241 271 280 131 119 4 162 161 128 
+142 14 182 286 141 268 45 158 22 85 187 285 86 198 51 61 188 9 139 173 192 19 
+266 130 35 53 285 108 131 204 39 126 227 27 213 199 62 114 163 150 97 100 26 
+202 146 87 124 205 72 263 68 146 109 57 71 50 201 135 34 149 215 114 185 83 250 
+78 251 133 34 127 131 248 207 9 183 190 211 262 142 279 98 133 163 43 265 270 
+269 78 8 150 204 83 7 246 270 89 197 125 194 41 85 80 166 256 154 214 210 115 
+89 17 108 175 85 209 82 103 176 276 279 76 49 10 65 40 52 94 38 137 258 69 50 
+179 202 168 171 277 183 10 43 243 186 116 100 70 83 29 43 67 135 56 82 81 92 
+123 14 2 118 258 25 33 160 246 5 22 63 103 132 108 260 120 173 148 2 247 38 159 
+55 222 28 117 269 56 211 284 226 145 76 71 230 218 18 277 25 213 177 265 248 
+185 212 30 212 273 195 254 239 91 90 28 10 150 75 167 160 224 175 ^
+613 0 152 79 161 65 216 220 109 281 9 254 130 126 57 137 147 82 63 133 78 162 
+232 68 59 232 177 22 129 68 168 36 74 43 275 264 174 70 154 103 247 218 194 158 
+42 167 49 259 18 261 222 95 59 52 270 49 20 214 75 42 238 282 46 106 258 249 83 
+280 22 20 105 271 15 58 136 269 100 224 10 182 19 68 130 17 94 240 256 225 156 
+127 44 82 172 96 105 53 89 134 65 107 257 212 101 152 188 124 92 107 77 175 287 
+43 45 190 98 141 157 235 259 127 224 119 275 205 248 276 83 100 115 206 285 128 
+211 64 11 60 1 66 253 202 237 245 194 108 5 64 229 116 84 267 256 45 249 24 224 
+228 238 102 139 3 149 106 149 286 56 100 165 243 99 237 65 157 5 26 210 6 122 
+118 217 27 17 203 44 153 116 13 193 50 116 122 286 236 7 268 63 242 171 59 123 
+214 125 238 52 102 30 40 252 215 3 220 50 66 215 183 127 153 45 69 117 121 119 
+95 9 145 167 229 166 121 81 76 188 53 18 190 148 178 260 55 113 61 218 85 195 
+145 276 192 63 12 97 142 194 217 98 250 120 132 150 273 1 125 20 285 19 118 37 
+120 203 94 60 219 122 47 273 110 88 206 176 165 25 43 154 283 284 32 14 12 265 
+161 15 179 117 138 75 260 164 76 247 109 101 261 151 21 272 253 143 181 32 123 
+105 162 52 31 245 123 34 218 135 232 248 96 46 286 6 63 62 134 245 14 71 32 244 
+86 182 90 12 47 105 91 108 244 27 126 7 230 44 262 79 199 84 196 23 128 31 27 
+197 240 17 262 259 236 187 16 166 62 25 282 117 180 175 178 80 18 10 241 75 151 
+201 179 67 252 35 255 117 71 82 281 189 2 233 235 41 71 141 48 272 73 236 78 53 
+269 171 168 86 111 16 95 118 108 64 120 23 187 87 110 268 243 279 274 168 266 
+148 119 204 261 42 58 86 73 127 115 26 89 25 102 80 77 66 35 146 24 44 191 135 
+123 285 199 155 140 99 57 28 54 185 42 276 12 156 198 118 288 101 223 132 41 
+180 104 234 163 219 13 84 87 219 231 140 170 1 234 272 182 199 264 233 126 237 
+174 250 191 206 67 72 128 152 8 87 278 287 223 241 4 77 284 91 229 225 47 164 
+147 191 26 30 99 19 9 74 93 23 78 283 213 88 97 213 268 4 27 88 277 120 82 113 
+170 181 271 86 2 53 198 227 251 287 114 278 107 186 138 184 223 61 97 104 175 
+107 6 231 81 114 207 163 110 50 187 196 73 165 134 136 51 174 11 98 20 176 56 
+221 146 263 137 88 26 139 62 205 189 220 29 112 74 273 60 51 103 67 22 91 49 
+188 233 55 4 257 32 64 49 79 270 158 113 111 255 58 15 288 210 213 ^
+624 1 28 220 36 170 238 197 169 72 54 41 237 158 26 234 92 145 95 155 87 190 
+243 208 200 250 48 21 90 215 40 71 178 188 109 196 130 219 216 206 51 16 23 5 
+48 6 158 97 55 278 201 55 207 90 286 151 130 234 148 34 36 226 127 138 240 112 
+2 38 141 250 104 37 31 159 207 19 175 92 201 274 96 31 230 28 205 104 52 126 
+114 192 229 152 225 103 90 230 262 26 108 86 39 32 35 60 147 10 278 216 277 35 
+75 79 255 100 136 254 5 267 185 99 41 95 226 71 249 9 168 252 90 144 56 12 249 
+228 57 193 34 21 4 172 153 30 135 159 136 35 116 36 241 59 93 225 32 106 171 43 
+66 238 268 280 131 110 1 162 161 122 142 14 179 283 141 265 36 155 16 79 184 
+279 77 198 45 52 182 3 133 173 192 10 263 121 32 50 282 102 122 198 30 120 227 
+18 213 196 59 108 157 150 91 91 20 199 140 84 124 199 69 263 65 143 109 48 62 
+47 201 126 28 149 215 111 182 74 244 69 248 133 25 124 128 248 204 9 183 184 
+208 256 139 279 92 130 163 37 265 270 266 75 8 144 204 80 4 243 264 89 191 119 
+188 38 85 71 163 256 154 211 210 115 83 14 108 172 82 209 76 103 176 273 276 67 
+43 10 59 37 46 91 35 131 258 69 44 176 202 165 171 277 177 7 34 240 183 113 97 
+70 83 29 40 67 129 53 73 78 89 120 8 2 109 252 19 33 160 246 289 13 54 97 126 
+99 260 111 167 142 289 247 38 156 55 222 22 114 263 50 211 281 226 142 70 68 
+224 212 15 274 25 210 171 262 245 179 212 30 206 270 195 254 239 88 81 28 1 147 
+66 167 157 221 202 150 76 159 65 214 220 107 281 7 253 129 124 57 137 145 80 60 
+132 78 160 231 67 58 232 177 22 129 68 168 33 74 40 275 262 174 68 153 101 246 
+218 192 158 41 166 47 257 15 259 220 92 59 52 268 46 20 214 72 39 236 282 46 
+106 257 249 80 279 21 19 104 271 15 55 136 269 100 222 7 182 18 65 128 14 93 
+240 254 224 156 126 43 81 170 96 102 51 87 134 64 104 256 210 100 151 186 123 
+89 105 76 174 287 42 42 190 95 140 155 235 258 125 223 117 273 205 246 274 81 
+99 112 206 285 127 209 61 8 58 288 66 253 200 235 243 193 105 5 63 228 113 82 
+265 255 44 247 23 224 227 237 102 137 3 148 105 147 285 56 98 165 242 98 236 63 
+157 2 23 209 5 119 117 217 26 15 203 41 151 115 12 193 49 116 122 284 236 7 268 
+61 242 169 57 122 213 125 238 49 101 27 39 251 214 1 218 50 63 213 181 127 153 
+45 67 114 121 118 93 6 143 165 227 166 118 78 74 188 53 17 189 148 176 258 54 
+112 58 217 82 194 144 275 191 141 ^
+628 1 3 97 139 194 211 92 250 117 132 147 267 290 119 14 282 13 118 37 111 200 
+94 60 216 119 47 270 110 85 203 173 159 16 43 148 277 278 29 5 12 262 158 6 176 
+117 286 135 72 257 164 76 241 106 101 261 148 18 266 247 143 178 32 117 99 159 
+49 31 245 123 31 212 135 226 245 90 43 286 289 60 62 131 242 11 65 23 244 80 
+176 84 6 38 105 91 102 238 27 123 290 224 38 259 79 199 84 193 14 128 25 21 191 
+237 17 256 259 233 187 10 160 59 19 276 114 174 169 175 74 18 7 235 69 145 198 
+179 58 252 32 255 111 62 82 278 183 285 230 229 32 68 135 39 269 67 230 75 44 
+263 168 165 86 108 16 92 112 105 58 114 20 181 78 107 265 237 276 268 162 266 
+142 119 201 258 36 52 77 64 118 109 26 80 22 96 80 71 60 29 143 24 44 191 132 
+114 279 193 152 140 99 54 25 54 179 42 276 9 150 192 109 285 92 217 129 35 180 
+101 228 160 213 7 81 81 219 231 134 167 1 231 272 179 196 264 227 117 237 171 
+244 185 200 61 72 119 152 2 87 272 284 220 241 1 77 284 82 229 219 44 158 144 
+188 20 27 90 10 6 71 93 17 69 283 210 82 91 207 262 4 18 79 271 120 73 113 164 
+181 265 83 288 50 195 221 251 281 108 275 104 186 138 184 223 61 88 95 175 107 
+6 225 81 114 207 157 101 41 184 190 73 162 128 130 45 168 11 98 11 170 47 221 
+146 257 131 88 23 139 56 199 189 217 283 23 106 68 273 51 51 100 64 13 85 49 
+185 233 49 290 257 26 64 46 73 267 152 107 111 249 58 9 288 204 183 26 218 34 
+170 234 197 169 70 50 41 233 154 22 234 92 145 93 155 81 186 243 208 200 248 48 
+21 86 213 40 69 178 186 105 196 126 215 214 204 45 14 23 1 44 4 156 91 53 274 
+199 51 205 88 282 151 130 232 144 34 32 222 123 136 236 112 34 137 246 100 31 
+25 159 203 19 171 90 197 274 94 27 228 22 201 104 48 126 110 190 227 150 225 97 
+90 230 262 20 286 102 84 39 26 31 58 147 8 278 216 273 35 75 77 251 94 132 252 
+291 267 185 95 37 95 224 71 247 5 166 250 84 144 50 8 245 228 55 189 30 15 172 
+149 28 133 157 134 29 110 36 239 53 87 223 28 100 169 37 62 236 266 280 131 104 
+291 162 161 118 142 14 177 281 141 263 30 153 12 75 182 275 71 198 41 46 178 
+291 129 173 192 4 261 115 30 48 280 98 116 194 24 116 227 12 213 194 57 104 153 
+150 87 85 16 197 136 82 124 195 67 263 63 141 109 42 56 45 201 120 24 149 215 
+109 180 68 240 63 246 133 19 122 126 248 202 9 183 180 206 252 137 279 88 128 
+163 33 265 270 264 73 8 140 204 78 2 241 76 ^
+622 0 89 183 111 180 34 85 59 159 256 154 207 210 115 75 10 108 168 78 209 68 
+103 176 269 272 55 35 10 51 33 38 87 31 123 258 69 36 172 202 161 171 277 169 3 
+22 236 179 109 93 70 83 29 36 67 121 49 61 74 85 116 2 97 244 11 33 160 246 285 
+1 42 89 118 87 260 99 159 134 289 247 38 152 55 222 14 110 255 42 211 277 226 
+138 62 64 216 204 11 270 25 206 163 258 241 171 212 30 198 266 195 254 239 84 
+69 28 283 143 54 167 153 217 194 142 64 151 65 206 220 99 281 293 249 125 116 
+57 137 137 72 48 128 78 152 227 63 54 232 177 22 129 68 168 21 74 28 275 254 
+174 60 149 93 242 218 184 158 37 162 39 249 3 251 212 80 59 52 260 34 20 214 60 
+27 228 282 46 106 253 249 68 275 17 15 100 271 15 43 136 269 100 214 289 182 14 
+53 120 2 89 240 246 220 156 122 39 77 162 96 90 43 79 134 60 92 252 202 96 147 
+178 119 77 97 72 170 287 38 30 190 83 136 147 235 254 117 219 109 265 205 238 
+266 73 95 100 206 285 123 201 49 290 50 280 66 253 192 227 235 189 93 5 59 224 
+101 74 257 251 40 239 19 224 223 233 102 129 3 144 101 139 281 56 90 165 238 94 
+232 55 157 284 11 205 1 107 113 217 22 7 203 29 143 111 8 193 45 116 122 276 
+236 7 268 53 242 161 49 118 209 125 238 37 97 15 35 247 210 287 210 50 51 205 
+173 127 153 45 59 102 121 114 85 288 135 157 219 166 106 66 66 188 53 13 185 
+148 168 250 50 108 46 213 70 190 140 271 187 63 291 97 137 194 207 88 250 115 
+132 145 263 290 115 10 280 9 118 37 105 198 94 60 214 117 47 268 110 83 201 171 
+155 10 43 144 273 274 27 293 12 260 156 174 117 284 133 70 255 164 76 237 104 
+101 261 146 16 262 243 143 176 32 113 95 157 47 31 245 123 29 208 135 222 243 
+86 41 286 285 58 62 129 240 9 61 17 244 76 172 80 2 32 105 91 98 234 27 121 286 
+220 34 257 79 199 84 191 8 128 21 17 187 235 17 252 259 231 187 6 156 57 15 272 
+112 170 165 173 70 18 5 231 65 141 196 179 52 252 30 255 107 56 82 276 179 281 
+228 225 26 66 131 33 267 63 226 73 38 259 166 163 86 106 16 90 108 103 54 110 
+18 177 72 105 263 233 274 264 158 266 138 119 199 256 32 48 71 58 112 105 26 74 
+20 92 80 67 56 25 141 24 44 191 130 108 275 189 150 140 99 52 23 54 175 42 276 
+7 146 188 103 283 86 213 127 31 180 99 224 158 209 3 79 77 219 231 130 165 1 
+229 272 177 194 264 223 111 237 169 240 181 196 57 72 113 152 292 87 268 282 
+218 241 293 77 284 76 229 80 ^
+635 1 40 150 140 184 12 23 78 294 2 67 93 9 57 283 206 74 83 199 254 4 6 67 263 
+120 61 113 156 181 257 79 284 46 191 213 251 273 100 271 100 186 138 184 223 61 
+76 83 175 107 6 217 81 114 207 149 89 29 180 182 73 158 120 122 37 160 11 98 
+295 162 35 221 146 249 123 88 19 139 48 191 189 213 275 15 98 60 273 39 51 96 
+60 1 77 49 181 233 41 286 257 18 64 42 65 263 144 99 111 241 58 1 288 196 179 
+22 214 30 170 226 197 169 66 42 41 225 146 14 234 92 145 89 155 69 178 243 208 
+200 244 48 21 78 209 40 65 178 182 97 196 118 207 210 200 33 10 23 289 36 152 
+79 49 266 195 43 201 84 274 151 130 228 136 34 24 214 115 132 228 112 292 26 
+129 238 92 19 13 159 195 19 163 86 189 274 90 19 224 10 193 104 40 126 102 186 
+223 146 225 85 90 230 262 8 278 90 80 39 14 23 54 147 4 278 216 265 35 75 73 
+243 82 124 248 283 267 185 87 29 95 220 71 243 293 162 246 72 144 38 237 228 51 
+181 22 3 288 172 141 24 129 153 130 17 98 36 235 41 75 219 20 88 165 25 54 232 
+262 280 131 92 291 162 161 110 142 14 173 277 141 259 18 149 4 67 178 267 59 
+198 33 34 170 287 121 173 192 288 257 103 26 44 276 90 104 186 12 108 227 213 
+190 53 96 145 150 79 73 8 193 128 78 124 187 63 263 59 137 109 30 44 41 201 108 
+16 149 215 105 176 56 232 51 242 133 7 118 122 248 198 9 183 172 202 244 133 
+279 80 124 163 25 265 270 260 69 8 132 204 74 294 237 252 89 179 107 176 32 85 
+53 157 256 154 205 210 115 71 8 108 166 76 209 64 103 176 267 270 49 31 10 47 
+31 34 85 29 119 258 69 32 170 202 159 171 277 165 1 16 234 177 107 91 70 83 29 
+34 67 117 47 55 72 83 114 292 2 91 240 7 33 160 246 283 291 36 85 114 81 260 93 
+155 130 289 247 38 150 55 222 10 108 251 38 211 275 226 136 58 62 212 200 9 268 
+25 204 159 256 239 167 212 30 194 264 195 254 239 82 63 28 279 141 48 167 151 
+215 190 138 58 147 65 202 220 95 281 291 247 123 112 57 137 133 68 42 126 78 
+148 225 61 52 232 177 22 129 68 168 15 74 22 275 250 174 56 147 89 240 218 180 
+158 35 160 35 245 293 247 208 74 59 52 256 28 20 214 54 21 224 282 46 106 251 
+249 62 273 15 13 98 271 15 37 136 269 100 210 285 182 12 47 116 292 87 240 242 
+218 156 120 37 75 158 96 84 39 75 134 58 86 250 198 94 145 174 117 71 93 70 168 
+287 36 24 190 77 134 143 235 252 113 217 105 261 205 234 262 69 93 94 206 285 
+121 197 43 286 46 276 66 253 188 223 231 187 87 5 57 222 95 285 ^
+636 0 251 248 37 233 16 224 220 230 102 123 3 141 98 133 278 56 84 165 235 91 
+229 49 157 278 2 202 295 98 110 217 19 1 203 20 137 108 5 193 42 116 122 270 
+236 7 268 47 242 155 43 115 206 125 238 28 94 6 32 244 207 284 204 50 42 199 
+167 127 153 45 53 93 121 111 79 282 129 151 213 166 97 57 60 188 53 10 182 148 
+162 244 47 105 37 210 61 187 137 268 184 63 285 97 134 194 201 82 250 112 132 
+142 257 290 109 4 277 3 118 37 96 195 94 60 211 114 47 265 110 80 198 168 149 1 
+43 138 267 268 24 287 12 257 153 288 171 117 281 130 67 252 164 76 231 101 101 
+261 143 13 256 237 143 173 32 107 89 154 44 31 245 123 26 202 135 216 240 80 38 
+286 279 55 62 126 237 6 55 8 244 70 166 74 293 23 105 91 92 228 27 118 280 214 
+28 254 79 199 84 188 296 128 15 11 181 232 17 246 259 228 187 150 54 9 266 109 
+164 159 170 64 18 2 225 59 135 193 179 43 252 27 255 101 47 82 273 173 275 225 
+219 17 63 125 24 264 57 220 70 29 253 163 160 86 103 16 87 102 100 48 104 15 
+171 63 102 260 227 271 258 152 266 132 119 196 253 26 42 62 49 103 99 26 65 17 
+86 80 61 50 19 138 24 44 191 127 99 269 183 147 140 99 49 20 54 169 42 276 4 
+140 182 94 280 77 207 124 25 180 96 218 155 203 294 76 71 219 231 124 162 1 226 
+272 174 191 264 217 102 237 166 234 175 190 51 72 104 152 289 87 262 279 215 
+241 293 77 284 67 229 209 39 148 139 183 10 22 75 292 1 66 93 7 54 283 205 72 
+81 197 252 4 3 64 261 120 58 113 154 181 255 78 283 45 190 211 251 271 98 270 
+99 186 138 184 223 61 73 80 175 107 6 215 81 114 207 147 86 26 179 180 73 157 
+118 120 35 158 11 98 293 160 32 221 146 247 121 88 18 139 46 189 189 212 273 13 
+96 58 273 36 51 95 59 295 75 49 180 233 39 285 257 16 64 41 63 262 142 97 111 
+239 58 296 288 194 178 21 213 29 170 224 197 169 65 40 41 223 144 12 234 92 145 
+88 155 66 176 243 208 200 243 48 21 76 208 40 64 178 181 95 196 116 205 209 199 
+30 9 23 288 34 296 151 76 48 264 194 41 200 83 272 151 130 227 134 34 22 212 
+113 131 226 112 292 24 127 236 90 16 10 159 193 19 161 85 187 274 89 17 223 7 
+191 104 38 126 100 185 222 145 225 82 90 230 262 5 276 87 79 39 11 21 53 147 3 
+278 216 263 35 75 72 241 79 122 247 281 267 185 85 27 95 219 71 242 292 161 245 
+69 144 35 295 235 228 50 179 20 287 172 139 23 128 152 129 14 95 36 234 38 72 
+218 18 85 164 22 52 231 261 280 131 89 291 162 161 108 142 14 172 276 91 ^
+635 1 256 9 146 297 61 175 261 50 198 27 25 164 284 115 173 192 282 254 94 23 
+41 273 84 95 180 3 102 227 290 213 187 50 90 139 150 73 64 2 190 122 75 124 181 
+60 263 56 134 109 21 35 38 201 99 10 149 215 102 173 47 226 42 239 133 297 115 
+119 248 195 9 183 166 199 238 130 279 74 121 163 19 265 270 257 66 8 126 204 71 
+294 234 246 89 173 101 170 29 85 44 154 256 154 202 210 115 65 5 108 163 73 209 
+58 103 176 264 267 40 25 10 41 28 28 82 26 113 258 69 26 167 202 156 171 277 
+159 297 7 231 174 104 88 70 83 29 31 67 111 44 46 69 80 111 289 2 82 234 1 33 
+160 246 280 285 27 79 108 72 260 84 149 124 289 247 38 147 55 222 4 105 245 32 
+211 272 226 133 52 59 206 194 6 265 25 201 153 253 236 161 212 30 188 261 195 
+254 239 79 54 28 273 138 39 167 148 212 184 132 49 141 65 196 220 89 281 288 
+244 120 106 57 137 127 62 33 123 78 142 222 58 49 232 177 22 129 68 168 6 74 13 
+275 244 174 50 144 83 237 218 174 158 32 157 29 239 287 241 202 65 59 52 250 19 
+20 214 45 12 218 282 46 106 248 249 53 270 12 10 95 271 15 28 136 269 100 204 
+279 182 9 38 110 286 84 240 236 215 156 117 34 72 152 96 75 33 69 134 55 77 247 
+192 91 142 168 114 62 87 67 165 287 33 15 190 68 131 137 235 249 107 214 99 255 
+205 228 256 63 90 85 206 285 118 191 34 280 40 270 66 253 182 217 225 184 78 5 
+54 219 86 64 247 246 35 229 14 224 218 228 102 119 3 139 96 129 276 56 80 165 
+233 89 227 45 157 274 295 200 295 92 108 217 17 296 203 14 133 106 3 193 40 116 
+122 266 236 7 268 43 242 151 39 113 204 125 238 22 92 30 242 205 282 200 50 36 
+195 163 127 153 45 49 87 121 109 75 278 125 147 209 166 91 51 56 188 53 8 180 
+148 158 240 45 103 31 208 55 185 135 266 182 63 281 97 132 194 197 78 250 110 
+132 140 253 290 105 275 298 118 37 90 193 94 60 209 112 47 263 110 78 196 166 
+145 294 43 134 263 264 22 283 12 255 151 284 169 117 279 128 65 250 164 76 227 
+99 101 261 141 11 252 233 143 171 32 103 85 152 42 31 245 123 24 198 135 212 
+238 76 36 286 275 53 62 124 235 4 51 2 244 66 162 70 291 17 105 91 88 224 27 
+116 276 210 24 252 79 199 84 186 292 128 11 7 177 230 17 242 259 226 187 295 
+146 52 5 262 107 160 155 168 60 18 221 55 131 191 179 37 252 25 255 97 41 82 
+271 169 271 223 215 11 61 121 18 262 53 216 68 23 249 161 158 86 101 16 85 98 
+98 44 100 13 167 57 100 258 223 269 254 148 266 128 119 194 251 22 38 56 43 275 
+^
+642 0 91 26 53 13 78 80 53 42 11 134 24 44 191 123 87 261 175 143 140 99 45 16 
+54 161 42 276 132 174 82 276 65 199 120 17 180 92 210 151 195 290 72 63 219 231 
+116 158 1 222 272 170 187 264 209 90 237 162 226 167 182 43 72 92 152 285 87 
+254 275 211 241 293 77 284 55 229 201 35 140 135 179 2 18 63 284 298 62 93 300 
+42 283 201 64 73 189 244 4 292 52 253 120 46 113 146 181 247 74 279 41 186 203 
+251 263 90 266 95 186 138 184 223 61 61 68 175 107 6 207 81 114 207 139 74 14 
+175 172 73 153 110 112 27 150 11 98 285 152 20 221 146 239 113 88 14 139 38 181 
+189 208 265 5 88 50 273 24 51 91 55 287 67 49 176 233 31 281 257 8 64 37 55 258 
+134 89 111 231 58 292 288 186 174 17 209 25 170 216 197 169 61 32 41 215 136 4 
+234 92 145 84 155 54 168 243 208 200 239 48 21 68 204 40 60 178 177 87 196 108 
+197 205 195 18 5 23 284 26 296 147 64 44 256 190 33 196 79 264 151 130 223 126 
+34 14 204 105 127 218 112 292 16 119 228 82 4 299 159 185 19 153 81 179 274 85 
+9 219 296 183 104 30 126 92 181 218 141 225 70 90 230 262 294 268 75 75 39 300 
+13 49 147 300 278 216 255 35 75 68 233 67 114 243 273 267 185 77 19 95 215 71 
+238 288 157 241 57 144 23 291 227 228 46 171 12 289 283 172 131 19 124 148 125 
+2 83 36 230 26 60 214 10 73 160 10 44 227 257 280 131 77 291 162 161 100 142 14 
+168 272 141 254 3 144 295 57 173 257 44 198 23 19 160 282 111 173 192 278 252 
+88 21 39 271 80 89 176 298 98 227 286 213 185 48 86 135 150 69 58 299 188 118 
+73 124 177 58 263 54 132 109 15 29 36 201 93 6 149 215 100 171 41 222 36 237 
+133 293 113 117 248 193 9 183 162 197 234 128 279 70 119 163 15 265 270 255 64 
+8 122 204 69 294 232 242 89 169 97 166 27 85 38 152 256 154 200 210 115 61 3 
+108 161 71 209 54 103 176 262 265 34 21 10 37 26 24 80 24 109 258 69 22 165 202 
+154 171 277 155 297 1 229 172 102 86 70 83 29 29 67 107 42 40 67 78 109 287 2 
+76 230 298 33 160 246 278 281 21 75 104 66 260 78 145 120 289 247 38 145 55 222 
+103 241 28 211 270 226 131 48 57 202 190 4 263 25 199 149 251 234 157 212 30 
+184 259 195 254 239 77 48 28 269 136 33 167 146 210 180 128 43 137 65 192 220 
+85 281 286 242 118 102 57 137 123 58 27 121 78 138 220 56 47 232 177 22 129 68 
+168 74 7 275 240 174 46 142 79 235 218 170 158 30 155 25 235 283 237 198 59 59 
+52 246 13 20 214 39 6 214 282 46 106 246 249 47 268 10 8 93 271 15 22 136 269 
+100 200 275 42 ^
+644 0 6 29 104 280 81 240 230 212 156 114 31 69 146 96 66 27 63 134 52 68 244 
+186 88 139 162 111 53 81 64 162 287 30 6 190 59 128 131 235 246 101 211 93 249 
+205 222 250 57 87 76 206 285 115 185 25 274 34 264 66 253 176 211 219 181 69 5 
+51 216 77 58 241 243 32 223 11 224 215 225 102 113 3 136 93 123 273 56 74 165 
+230 86 224 39 157 268 289 197 295 83 105 217 14 293 203 5 127 103 193 37 116 
+122 260 236 7 268 37 242 145 33 110 201 125 238 13 89 293 27 239 202 279 194 50 
+27 189 157 127 153 45 43 78 121 106 69 272 119 141 203 166 82 42 50 188 53 5 
+177 148 152 234 42 100 22 205 46 182 132 263 179 63 275 97 129 194 191 72 250 
+107 132 137 247 290 99 296 272 295 118 37 81 190 94 60 206 109 47 260 110 75 
+193 163 139 288 43 128 257 258 19 277 12 252 148 278 166 117 276 125 62 247 164 
+76 221 96 101 261 138 8 246 227 143 168 32 97 79 149 39 31 245 123 21 192 135 
+206 235 70 33 286 269 50 62 121 232 1 45 295 244 60 156 64 288 8 105 91 82 218 
+27 113 270 204 18 249 79 199 84 183 286 128 5 1 171 227 17 236 259 223 187 292 
+140 49 301 256 104 154 149 165 54 18 299 215 49 125 188 179 28 252 22 255 91 32 
+82 268 163 265 220 209 2 58 115 9 259 47 210 65 14 243 158 155 86 98 16 82 92 
+95 38 94 10 161 48 97 255 217 266 248 142 266 122 119 191 248 16 32 47 34 88 89 
+26 50 12 76 80 51 40 9 133 24 44 191 122 84 259 173 142 140 99 44 15 54 159 42 
+276 301 130 172 79 275 62 197 119 15 180 91 208 150 193 289 71 61 219 231 114 
+157 1 221 272 169 186 264 207 87 237 161 224 165 180 41 72 89 152 284 87 252 
+274 210 241 293 77 284 52 229 199 34 138 134 178 17 60 282 298 61 93 299 39 283 
+200 62 71 187 242 4 290 49 251 120 43 113 144 181 245 73 278 40 185 201 251 261 
+88 265 94 186 138 184 223 61 58 65 175 107 6 205 81 114 207 137 71 11 174 170 
+73 152 108 110 25 148 11 98 283 150 17 221 146 237 111 88 13 139 36 179 189 207 
+263 3 86 48 273 21 51 90 54 285 65 49 175 233 29 280 257 6 64 36 53 257 132 87 
+111 229 58 291 288 184 173 16 208 24 170 214 197 169 60 30 41 213 134 2 234 92 
+145 83 155 51 166 243 208 200 238 48 21 66 203 40 59 178 176 85 196 106 195 204 
+194 15 4 23 283 24 296 146 61 43 254 189 31 195 78 262 151 130 222 124 34 12 
+202 103 126 216 112 292 14 117 226 80 1 297 159 183 19 151 80 177 274 84 7 218 
+294 181 104 28 126 90 180 217 140 225 67 90 230 262 292 266 72 74 39 298 11 48 
+147 300 278 216 253 265 ^
+638 1 75 65 227 58 108 240 267 267 185 71 13 95 212 71 235 285 154 238 48 144 
+14 288 221 228 43 165 6 283 280 172 125 16 121 145 122 297 74 36 227 17 51 211 
+4 64 157 1 38 224 254 280 131 68 291 162 161 94 142 14 165 269 141 251 298 141 
+292 51 170 251 35 198 17 10 154 279 105 173 192 272 249 79 18 36 268 74 80 170 
+292 92 227 280 213 182 45 80 129 150 63 49 296 185 112 70 124 171 55 263 51 129 
+109 6 20 33 201 84 149 215 97 168 32 216 27 234 133 287 110 114 248 190 9 183 
+156 194 228 125 279 64 116 163 9 265 270 252 61 8 116 204 66 294 229 236 89 163 
+91 160 24 85 29 149 256 154 197 210 115 55 108 158 68 209 48 103 176 259 262 25 
+15 10 31 23 18 77 21 103 258 69 16 162 202 151 171 277 149 297 296 226 169 99 
+83 70 83 29 26 67 101 39 31 64 75 106 284 2 67 224 295 33 160 246 275 275 12 69 
+98 57 260 69 139 114 289 247 38 142 55 222 298 100 235 22 211 267 226 128 42 54 
+196 184 1 260 25 196 143 248 231 151 212 30 178 256 195 254 239 74 39 28 263 
+133 24 167 143 207 174 122 34 131 65 186 220 79 281 283 239 115 96 57 137 117 
+52 18 118 78 132 217 53 44 232 177 22 129 68 168 295 74 302 275 234 174 40 139 
+73 232 218 164 158 27 152 19 229 277 231 192 50 59 52 240 4 20 214 30 301 208 
+282 46 106 243 249 38 265 7 5 90 271 15 13 136 269 100 194 269 182 4 23 100 276 
+79 240 226 210 156 112 29 67 142 96 60 23 59 134 50 62 242 182 86 137 158 109 
+47 77 62 160 287 28 190 53 126 127 235 244 97 209 89 245 205 218 246 53 85 70 
+206 285 113 181 19 270 30 260 66 253 172 207 215 179 63 5 49 214 71 54 237 241 
+30 219 9 224 213 223 102 109 3 134 91 119 271 56 70 165 228 84 222 35 157 264 
+285 195 295 77 103 217 12 291 203 303 123 101 302 193 35 116 122 256 236 7 268 
+33 242 141 29 108 199 125 238 7 87 289 25 237 200 277 190 50 21 185 153 127 153 
+45 39 72 121 104 65 268 115 137 199 166 76 36 46 188 53 3 175 148 148 230 40 98 
+16 203 40 180 130 261 177 63 271 97 127 194 187 68 250 105 132 135 243 290 95 
+294 270 293 118 37 75 188 94 60 204 107 47 258 110 73 191 161 135 284 43 124 
+253 254 17 273 12 250 146 274 164 117 274 123 60 245 164 76 217 94 101 261 136 
+6 242 223 143 166 32 93 75 147 37 31 245 123 19 188 135 202 233 66 31 286 265 
+48 62 119 230 303 41 291 244 56 152 60 286 2 105 91 78 214 27 111 266 200 14 
+247 79 199 84 181 282 128 1 301 167 225 17 232 259 221 187 290 136 47 299 252 
+102 150 145 163 157 ^
+653 0 18 299 207 41 117 184 179 16 252 18 255 83 20 82 264 155 257 216 201 296 
+54 107 303 255 39 202 61 2 235 154 151 86 94 16 78 84 91 30 86 6 153 36 93 251 
+209 262 240 134 266 114 119 187 244 8 24 35 22 76 81 26 38 8 68 80 43 32 1 129 
+24 44 191 118 72 251 165 138 140 99 40 11 54 151 42 276 301 122 164 67 271 50 
+189 115 7 180 87 200 146 185 285 67 53 219 231 106 153 1 217 272 165 182 264 
+199 75 237 157 216 157 172 33 72 77 152 280 87 244 270 206 241 293 77 284 40 
+229 191 30 130 130 174 298 13 48 274 298 57 93 295 27 283 196 54 63 179 234 4 
+282 37 243 120 31 113 136 181 237 69 274 36 181 193 251 253 80 261 90 186 138 
+184 223 61 46 53 175 107 6 197 81 114 207 129 59 305 170 162 73 148 100 102 17 
+140 11 98 275 142 5 221 146 229 103 88 9 139 28 171 189 203 255 301 78 40 273 9 
+51 86 50 277 57 49 171 233 21 276 257 304 64 32 45 253 124 79 111 221 58 287 
+288 176 169 12 204 20 170 206 197 169 56 22 41 205 126 300 234 92 145 79 155 39 
+158 243 208 200 234 48 21 58 199 40 55 178 172 77 196 98 187 200 190 3 23 279 
+16 296 142 49 39 246 185 23 191 74 254 151 130 218 116 34 4 194 95 122 208 112 
+292 6 109 218 72 295 289 159 175 19 143 76 169 274 80 305 214 286 173 104 20 
+126 82 176 213 136 225 55 90 230 262 284 258 60 70 39 290 3 44 147 300 278 216 
+245 35 75 63 223 52 104 238 263 267 185 67 9 95 210 71 233 283 152 236 42 144 8 
+286 217 228 41 161 2 279 278 172 121 14 119 143 120 293 68 36 225 11 45 209 58 
+155 301 34 222 252 280 131 62 291 162 161 90 142 14 163 267 141 249 294 139 290 
+47 168 247 29 198 13 4 150 277 101 173 192 268 247 73 16 34 266 70 74 166 288 
+88 227 276 213 180 43 76 125 150 59 43 294 183 108 68 124 167 53 263 49 127 109 
+14 31 201 78 302 149 215 95 166 26 212 21 232 133 283 108 112 248 188 9 183 152 
+192 224 123 279 60 114 163 5 265 270 250 59 8 112 204 64 294 227 232 89 159 87 
+156 22 85 23 147 256 154 195 210 115 51 304 108 156 66 209 44 103 176 257 260 
+19 11 10 27 21 14 75 19 99 258 69 12 160 202 149 171 277 145 297 292 224 167 97 
+81 70 83 29 24 67 97 37 25 62 73 104 282 2 61 220 293 33 160 246 273 271 6 65 
+94 51 260 63 135 110 289 247 38 140 55 222 296 98 231 18 211 265 226 126 38 52 
+192 180 305 258 25 194 139 246 229 147 212 30 174 254 195 254 239 72 33 28 259 
+131 18 167 141 205 170 118 28 127 65 182 220 75 281 281 237 113 92 57 137 113 
+48 12 116 78 128 215 51 42 232 177 22 129 68 168 291 161 ^
+653 0 296 275 228 174 34 136 67 229 218 158 158 24 149 13 223 271 225 186 41 59 
+52 234 302 20 214 21 295 202 282 46 106 240 249 29 262 4 2 87 271 15 4 136 269 
+100 188 263 182 1 14 94 270 76 240 220 207 156 109 26 64 136 96 51 17 53 134 47 
+53 239 176 83 134 152 106 38 71 59 157 287 25 298 190 44 123 121 235 241 91 206 
+83 239 205 212 240 47 82 61 206 285 110 175 10 264 24 254 66 253 166 201 209 
+176 54 5 46 211 62 48 231 238 27 213 6 224 210 220 102 103 3 131 88 113 268 56 
+64 165 225 81 219 29 157 258 279 192 295 68 100 217 9 288 203 297 117 98 302 
+193 32 116 122 250 236 7 268 27 242 135 23 105 196 125 238 305 84 283 22 234 
+197 274 184 50 12 179 147 127 153 45 33 63 121 101 59 262 109 131 193 166 67 27 
+40 188 53 172 148 142 224 37 95 7 200 31 177 127 258 174 63 265 97 124 194 181 
+62 250 102 132 132 237 290 89 291 267 290 118 37 66 185 94 60 201 104 47 255 
+110 70 188 158 129 278 43 118 247 248 14 267 12 247 143 268 161 117 271 120 57 
+242 164 76 211 91 101 261 133 3 236 217 143 163 32 87 69 144 34 31 245 123 16 
+182 135 196 230 60 28 286 259 45 62 116 227 303 35 285 244 50 146 54 283 300 
+105 91 72 208 27 108 260 194 8 244 79 199 84 178 276 128 302 298 161 222 17 226 
+259 218 187 287 130 44 296 246 99 144 139 160 44 18 299 205 39 115 183 179 13 
+252 17 255 81 17 82 263 153 255 215 199 294 53 105 301 254 37 200 60 306 233 
+153 150 86 93 16 77 82 90 28 84 5 151 33 92 250 207 261 238 132 266 112 119 186 
+243 6 22 32 19 73 79 26 35 7 66 80 41 30 306 128 24 44 191 117 69 249 163 137 
+140 99 39 10 54 149 42 276 301 120 162 64 270 47 187 114 5 180 86 198 145 183 
+284 66 51 219 231 104 152 1 216 272 164 181 264 197 72 237 156 214 155 170 31 
+72 74 152 279 87 242 269 205 241 293 77 284 37 229 189 29 128 129 173 297 12 45 
+272 298 56 93 294 24 283 195 52 61 177 232 4 280 34 241 120 28 113 134 181 235 
+68 273 35 180 191 251 251 78 260 89 186 138 184 223 61 43 50 175 107 6 195 81 
+114 207 127 56 303 169 160 73 147 98 100 15 138 11 98 273 140 2 221 146 227 101 
+88 8 139 26 169 189 202 253 300 76 38 273 6 51 85 49 275 55 49 170 233 19 275 
+257 303 64 31 43 252 122 77 111 219 58 286 288 174 168 11 203 19 170 204 197 
+169 55 20 41 203 124 299 234 92 145 78 155 36 156 243 208 200 233 48 21 56 198 
+40 54 178 171 75 196 96 185 199 189 306 23 278 14 296 141 46 38 244 184 21 190 
+73 252 151 130 217 114 34 2 192 93 121 206 112 292 4 107 216 70 293 112 ^
+646 1 159 169 19 137 73 163 274 77 302 211 280 167 104 14 126 76 173 210 133 
+225 46 90 230 262 278 252 51 67 39 284 306 41 147 300 278 216 239 35 75 60 217 
+43 98 235 257 267 185 61 3 95 207 71 230 280 149 233 33 144 308 283 211 228 38 
+155 305 273 275 172 115 11 116 140 117 287 59 36 222 2 36 206 303 49 152 295 28 
+219 249 280 131 53 291 162 161 84 142 14 160 264 141 246 288 136 287 41 165 241 
+20 198 7 304 144 274 95 173 192 262 244 64 13 31 263 64 65 160 282 82 227 270 
+213 177 40 70 119 150 53 34 291 180 102 65 124 161 50 263 46 124 109 300 5 28 
+201 69 299 149 215 92 163 17 206 12 229 133 277 105 109 248 185 9 183 146 189 
+218 120 279 54 111 163 308 265 270 247 56 8 106 204 61 294 224 226 89 153 81 
+150 19 85 14 144 256 154 192 210 115 45 304 108 153 63 209 38 103 176 254 257 
+10 5 10 21 18 8 72 16 93 258 69 6 157 202 146 171 277 139 297 286 221 164 94 78 
+70 83 29 21 67 91 34 16 59 70 101 279 2 52 214 290 33 160 246 270 265 306 59 88 
+42 260 54 129 104 289 247 38 137 55 222 293 95 225 12 211 262 226 123 32 49 186 
+174 305 255 25 191 133 243 226 141 212 30 168 251 195 254 239 69 24 28 253 128 
+9 167 138 202 164 112 19 121 65 176 220 69 281 278 234 110 86 57 137 107 42 3 
+113 78 122 212 48 39 232 177 22 129 68 168 285 74 292 275 224 174 30 134 63 227 
+218 154 158 22 147 9 219 267 221 182 35 59 52 230 298 20 214 15 291 198 282 46 
+106 238 249 23 260 2 85 271 15 307 136 269 100 184 259 182 308 8 90 266 74 240 
+216 205 156 107 24 62 132 96 45 13 49 134 45 47 237 172 81 132 148 104 32 67 57 
+155 287 23 294 190 38 121 117 235 239 87 204 79 235 205 208 236 43 80 55 206 
+285 108 171 4 260 20 250 66 253 162 197 205 174 48 5 44 209 56 44 227 236 25 
+209 4 224 208 218 102 99 3 129 86 109 266 56 60 165 223 79 217 25 157 254 275 
+190 295 62 98 217 7 286 203 293 113 96 302 193 30 116 122 246 236 7 268 23 242 
+131 19 103 194 125 238 301 82 279 20 232 195 272 180 50 6 175 143 127 153 45 29 
+57 121 99 55 258 105 127 189 166 61 21 36 188 53 307 170 148 138 220 35 93 1 
+198 25 175 125 256 172 63 261 97 122 194 177 58 250 100 132 130 233 290 85 289 
+265 288 118 37 60 183 94 60 199 102 47 253 110 68 186 156 125 274 43 114 243 
+244 12 263 12 245 141 264 159 117 269 118 55 240 164 76 207 89 101 261 131 1 
+232 213 143 161 32 83 65 142 32 31 245 123 14 178 135 192 228 56 26 286 255 43 
+62 114 225 303 31 281 244 46 142 50 281 296 105 91 238 ^
+647 0 200 27 104 252 186 240 79 199 84 174 268 128 298 294 153 218 17 218 259 
+214 187 283 122 40 292 238 95 136 131 156 36 18 299 197 31 107 179 179 1 252 13 
+255 73 5 82 259 145 247 211 191 286 49 97 293 250 29 192 56 298 225 149 146 86 
+89 16 73 74 86 20 76 1 143 21 88 246 199 257 230 124 266 104 119 182 239 309 14 
+20 7 61 71 26 23 3 58 80 33 22 302 124 24 44 191 113 57 241 155 133 140 99 35 6 
+54 141 42 276 301 112 154 52 266 35 179 110 308 180 82 190 141 175 280 62 43 
+219 231 96 148 1 212 272 160 177 264 189 60 237 152 206 147 162 23 72 62 152 
+275 87 234 265 201 241 293 77 284 25 229 181 25 120 125 169 293 8 33 264 298 52 
+93 290 12 283 191 44 53 169 224 4 272 22 233 120 16 113 126 181 227 64 269 31 
+176 183 251 243 70 256 85 186 138 184 223 61 31 38 175 107 6 187 81 114 207 119 
+44 295 165 152 73 143 90 92 7 130 11 98 265 132 301 221 146 219 93 88 4 139 18 
+161 189 198 245 296 68 30 273 305 51 81 45 267 47 49 166 233 11 271 257 299 64 
+27 35 248 114 69 111 211 58 282 288 166 164 7 199 15 170 196 197 169 51 12 41 
+195 116 295 234 92 145 74 155 24 148 243 208 200 229 48 21 48 194 40 50 178 167 
+67 196 88 177 195 185 299 306 23 274 6 296 137 34 34 236 180 13 186 69 244 151 
+130 213 106 34 305 184 85 117 198 112 292 307 99 208 62 285 279 159 165 19 133 
+71 159 274 75 300 209 276 163 104 10 126 72 171 208 131 225 40 90 230 262 274 
+248 45 65 39 280 304 39 147 300 278 216 235 35 75 58 213 37 94 233 253 267 185 
+57 310 95 205 71 228 278 147 231 27 144 304 281 207 228 36 151 303 269 273 172 
+111 9 114 138 115 283 53 36 220 307 30 204 301 43 150 291 24 217 247 280 131 47 
+291 162 161 80 142 14 158 262 141 244 284 134 285 37 163 237 14 198 3 300 140 
+272 91 173 192 258 242 58 11 29 261 60 59 156 278 78 227 266 213 175 38 66 115 
+150 49 28 289 178 98 63 124 157 48 263 44 122 109 296 310 26 201 63 297 149 215 
+90 161 11 202 6 227 133 273 103 107 248 183 9 183 142 187 214 118 279 50 109 
+163 306 265 270 245 54 8 102 204 59 294 222 222 89 149 77 146 17 85 8 142 256 
+154 190 210 115 41 304 108 151 61 209 34 103 176 252 255 4 1 10 17 16 4 70 14 
+89 258 69 2 155 202 144 171 277 135 297 282 219 162 92 76 70 83 29 19 67 87 32 
+10 57 68 99 277 2 46 210 288 33 160 246 268 261 302 55 84 36 260 48 125 100 289 
+247 38 135 55 222 291 93 221 8 211 260 226 121 28 47 182 170 305 253 25 189 129 
+241 224 137 212 30 164 249 195 254 239 86 ^
+665 0 15 28 247 125 167 135 199 158 106 10 115 65 170 220 63 281 275 231 107 80 
+57 137 101 36 306 110 78 116 209 45 36 232 177 22 129 68 168 279 74 286 275 218 
+174 24 131 57 224 218 148 158 19 144 3 213 261 215 176 26 59 52 224 292 20 214 
+6 285 192 282 46 106 235 249 14 257 311 309 82 271 15 301 136 269 100 178 253 
+182 308 311 84 260 71 240 210 202 156 104 21 59 126 96 36 7 43 134 42 38 234 
+166 78 129 142 101 23 61 54 152 287 20 288 190 29 118 111 235 236 81 201 73 229 
+205 202 230 37 77 46 206 285 105 165 307 254 14 244 66 253 156 191 199 171 39 5 
+41 206 47 38 221 233 22 203 1 224 205 215 102 93 3 126 83 103 263 56 54 165 220 
+76 214 19 157 248 269 187 295 53 95 217 4 283 203 287 107 93 302 193 27 116 122 
+240 236 7 268 17 242 125 13 100 191 125 238 295 79 273 17 229 192 269 174 50 
+309 169 137 127 153 45 23 48 121 96 49 252 99 121 183 166 52 12 30 188 53 307 
+167 148 132 214 32 90 304 195 16 172 122 253 169 63 255 97 119 194 171 52 250 
+97 132 127 227 290 79 286 262 285 118 37 51 180 94 60 196 99 47 250 110 65 183 
+153 119 268 43 108 237 238 9 257 12 242 138 258 156 117 266 115 52 237 164 76 
+201 86 101 261 128 310 226 207 143 158 32 77 59 139 29 31 245 123 11 172 135 
+186 225 50 23 286 249 40 62 111 222 303 25 275 244 40 136 44 278 290 105 91 62 
+198 27 103 250 184 310 239 79 199 84 173 266 128 297 293 151 217 17 216 259 213 
+187 282 120 39 291 236 94 134 129 155 34 18 299 195 29 105 178 179 310 252 12 
+255 71 2 82 258 143 245 210 189 284 48 95 291 249 27 190 55 296 223 148 145 86 
+88 16 72 72 85 18 74 141 18 87 245 197 256 228 122 266 102 119 181 238 308 12 
+17 4 58 69 26 20 2 56 80 31 20 301 123 24 44 191 112 54 239 153 132 140 99 34 5 
+54 139 42 276 301 110 152 49 265 32 177 109 307 180 81 188 140 173 279 61 41 
+219 231 94 147 1 211 272 159 176 264 187 57 237 151 204 145 160 21 72 59 152 
+274 87 232 264 200 241 293 77 284 22 229 179 24 118 124 168 292 7 30 262 298 51 
+93 289 9 283 190 42 51 167 222 4 270 19 231 120 13 113 124 181 225 63 268 30 
+175 181 251 241 68 255 84 186 138 184 223 61 28 35 175 107 6 185 81 114 207 117 
+41 293 164 150 73 142 88 90 5 128 11 98 263 130 299 221 146 217 91 88 3 139 16 
+159 189 197 243 295 66 28 273 303 51 80 44 265 45 49 165 233 9 270 257 298 64 
+26 33 247 112 67 111 209 58 281 288 164 163 6 198 14 170 194 197 169 50 10 41 
+193 114 294 234 92 145 73 155 21 146 243 208 200 228 48 21 46 193 40 49 178 166 
+65 196 86 175 194 184 297 306 23 273 206 ^
+641 0 296 134 25 31 230 177 7 183 66 238 151 130 210 100 34 302 178 79 114 192 
+112 292 304 93 202 56 279 273 159 159 19 127 68 153 274 72 297 206 270 157 104 
+4 126 66 168 205 128 225 31 90 230 262 268 242 36 62 39 274 301 36 147 300 278 
+216 229 35 75 55 207 28 88 230 247 267 185 51 307 95 202 71 225 275 144 228 18 
+144 298 278 201 228 33 145 300 263 270 172 105 6 111 135 112 277 44 36 217 301 
+21 201 298 34 147 285 18 214 244 280 131 38 291 162 161 74 142 14 155 259 141 
+241 278 131 282 31 160 231 5 198 311 294 134 269 85 173 192 252 239 49 8 26 258 
+54 50 150 272 72 227 260 213 172 35 60 109 150 43 19 286 175 92 60 124 151 45 
+263 41 119 109 290 304 23 201 54 294 149 215 87 158 2 196 311 224 133 267 100 
+104 248 180 9 183 136 184 208 115 279 44 106 163 303 265 270 242 51 8 96 204 56 
+294 219 216 89 143 71 140 14 85 313 139 256 154 187 210 115 35 304 108 148 58 
+209 28 103 176 249 252 309 309 10 11 13 312 67 11 83 258 69 310 152 202 141 171 
+277 129 297 276 216 159 89 73 70 83 29 16 67 81 29 1 54 65 96 274 2 37 204 285 
+33 160 246 265 255 296 49 78 27 260 39 119 94 289 247 38 132 55 222 288 90 215 
+2 211 257 226 118 22 44 176 164 305 250 25 186 123 238 221 131 212 30 158 246 
+195 254 239 64 9 28 243 123 308 167 133 197 154 102 4 111 65 166 220 59 281 273 
+229 105 76 57 137 97 32 302 108 78 112 207 43 34 232 177 22 129 68 168 275 74 
+282 275 214 174 20 129 53 222 218 144 158 17 142 313 209 257 211 172 20 59 52 
+220 288 20 214 281 188 282 46 106 233 249 8 255 311 309 80 271 15 297 136 269 
+100 174 249 182 308 307 80 256 69 240 206 200 156 102 19 57 122 96 30 3 39 134 
+40 32 232 162 76 127 138 99 17 57 52 150 287 18 284 190 23 116 107 235 234 77 
+199 69 225 205 198 226 33 75 40 206 285 103 161 303 250 10 240 66 253 152 187 
+195 169 33 5 39 204 41 34 217 231 20 199 313 224 203 213 102 89 3 124 81 99 261 
+56 50 165 218 74 212 15 157 244 265 185 295 47 93 217 2 281 203 283 103 91 302 
+193 25 116 122 236 236 7 268 13 242 121 9 98 189 125 238 291 77 269 15 227 190 
+267 170 50 305 165 133 127 153 45 19 42 121 94 45 248 95 117 179 166 46 6 26 
+188 53 307 165 148 128 210 30 88 300 193 10 170 120 251 167 63 251 97 117 194 
+167 48 250 95 132 125 223 290 75 284 260 283 118 37 45 178 94 60 194 97 47 248 
+110 63 181 151 115 264 43 104 233 234 7 253 12 240 136 254 154 117 264 113 50 
+235 164 76 197 84 101 261 126 310 222 203 143 276 ^
+656 0 32 69 51 135 25 31 245 123 7 164 135 178 221 42 19 286 241 36 62 107 218 
+303 17 267 244 32 128 36 274 282 105 91 54 190 27 99 242 176 306 235 79 199 84 
+169 258 128 293 289 143 213 17 208 259 209 187 278 112 35 287 228 90 126 121 
+151 26 18 299 187 21 97 174 179 302 252 8 255 63 306 82 254 135 237 206 181 276 
+44 87 283 245 19 182 51 288 215 144 141 86 84 16 68 64 81 10 66 312 133 6 83 
+241 189 252 220 114 266 94 119 177 234 304 4 5 308 46 61 26 8 314 48 80 23 12 
+297 119 24 44 191 108 42 231 145 128 140 99 30 1 54 131 42 276 301 102 144 37 
+261 20 169 105 303 180 77 180 136 165 275 57 33 219 231 86 143 1 207 272 155 
+172 264 179 45 237 147 196 137 152 13 72 47 152 270 87 224 260 196 241 293 77 
+284 10 229 171 20 110 120 164 288 3 18 254 298 47 93 285 313 283 186 34 43 159 
+214 4 262 7 223 120 1 113 116 181 217 59 264 26 171 173 251 233 60 251 80 186 
+138 184 223 61 16 23 175 107 6 177 81 114 207 109 29 285 160 142 73 138 80 82 
+313 120 11 98 255 122 291 221 146 209 83 88 315 139 8 151 189 193 235 291 58 20 
+273 295 51 76 40 257 37 49 161 233 1 266 257 294 64 22 25 243 104 59 111 201 58 
+277 288 156 159 2 194 10 170 186 197 169 46 2 41 185 106 290 234 92 145 69 155 
+9 138 243 208 200 224 48 21 38 189 40 45 178 162 57 196 78 167 190 180 289 306 
+23 269 312 296 132 19 29 226 175 3 181 64 234 151 130 208 96 34 300 174 75 112 
+188 112 292 302 89 198 52 275 269 159 155 19 123 66 149 274 70 295 204 266 153 
+104 126 62 166 203 126 225 25 90 230 262 264 238 30 60 39 270 299 34 147 300 
+278 216 225 35 75 53 203 22 84 228 243 267 185 47 305 95 200 71 223 273 142 226 
+12 144 294 276 197 228 31 141 298 259 268 172 101 4 109 133 110 273 38 36 215 
+297 15 199 296 28 145 281 14 212 242 280 131 32 291 162 161 70 142 14 153 257 
+141 239 274 129 280 27 158 227 315 198 309 290 130 267 81 173 192 248 237 43 6 
+24 256 50 44 146 268 68 227 256 213 170 33 56 105 150 39 13 284 173 88 58 124 
+147 43 263 39 117 109 286 300 21 201 48 292 149 215 85 156 312 192 307 222 133 
+263 98 102 248 178 9 183 132 182 204 113 279 40 104 163 301 265 270 240 49 8 92 
+204 54 294 217 212 89 139 67 136 12 85 309 137 256 154 185 210 115 31 304 108 
+146 56 209 24 103 176 247 250 305 307 10 7 11 310 65 9 79 258 69 308 150 202 
+139 171 277 125 297 272 214 157 87 71 70 83 29 14 67 77 27 311 52 63 94 272 2 
+31 200 283 33 160 246 263 251 292 45 74 21 260 33 115 90 289 247 38 130 55 222 
+286 88 211 227 ^
+668 0 211 254 226 115 16 41 170 158 305 247 25 183 117 235 218 125 212 30 152 
+243 195 254 239 61 28 237 120 302 167 130 194 148 96 312 105 65 160 220 53 281 
+270 226 102 70 57 137 91 26 296 105 78 106 204 40 31 232 177 22 129 68 168 269 
+74 276 275 208 174 14 126 47 219 218 138 158 14 139 310 203 251 205 166 11 59 
+52 214 282 20 214 308 275 182 282 46 106 230 249 316 252 311 309 77 271 15 291 
+136 269 100 168 243 182 308 301 74 250 66 240 200 197 156 99 16 54 116 96 21 
+314 33 134 37 23 229 156 73 124 132 96 8 51 49 147 287 15 278 190 14 113 101 
+235 231 71 196 63 219 205 192 220 27 72 31 206 285 100 155 297 244 4 234 66 253 
+146 181 189 166 24 5 36 201 32 28 211 228 17 193 313 224 200 210 102 83 3 121 
+78 93 258 56 44 165 215 71 209 9 157 238 259 182 295 38 90 217 316 278 203 277 
+97 88 302 193 22 116 122 230 236 7 268 7 242 115 3 95 186 125 238 285 74 263 12 
+224 187 264 164 50 299 159 127 127 153 45 13 33 121 91 39 242 89 111 173 166 37 
+314 20 188 53 307 162 148 122 204 27 85 294 190 1 167 117 248 164 63 245 97 114 
+194 161 42 250 92 132 122 217 290 69 281 257 280 118 37 36 175 94 60 191 94 47 
+245 110 60 178 148 109 258 43 98 227 228 4 247 12 237 133 248 151 117 261 110 
+47 232 164 76 191 81 101 261 123 310 216 197 143 153 32 67 49 134 24 31 245 123 
+6 162 135 176 220 40 18 286 239 35 62 106 217 303 15 265 244 30 126 34 273 280 
+105 91 52 188 27 98 240 174 305 234 79 199 84 168 256 128 292 288 141 212 17 
+206 259 208 187 277 110 34 286 226 89 124 119 150 24 18 299 185 19 95 173 179 
+300 252 7 255 61 304 82 253 133 235 205 179 274 43 85 281 244 17 180 50 286 213 
+143 140 86 83 16 67 62 80 8 64 312 131 3 82 240 187 251 218 112 266 92 119 176 
+233 303 2 2 306 43 59 26 5 314 46 80 21 10 296 118 24 44 191 107 39 229 143 127 
+140 99 29 54 129 42 276 301 100 142 34 260 17 167 104 302 180 76 178 135 163 
+274 56 31 219 231 84 142 1 206 272 154 171 264 177 42 237 146 194 135 150 11 72 
+44 152 269 87 222 259 195 241 293 77 284 7 229 169 19 108 119 163 287 2 15 252 
+298 46 93 284 311 283 185 32 41 157 212 4 260 4 221 120 315 113 114 181 215 58 
+263 25 170 171 251 231 58 250 79 186 138 184 223 61 13 20 175 107 6 175 81 114 
+207 107 26 283 159 140 73 137 78 80 312 118 11 98 253 120 289 221 146 207 81 88 
+315 139 6 149 189 192 233 290 56 18 273 293 51 75 39 255 35 49 160 233 316 265 
+257 293 64 21 23 242 102 57 111 199 58 276 288 154 158 1 193 9 170 184 197 169 
+45 41 183 104 289 234 92 145 68 155 6 136 243 208 203 ^
+656 0 221 48 21 32 186 40 42 178 159 51 196 72 161 187 177 283 306 23 266 309 
+296 129 10 26 220 172 316 178 61 228 151 130 205 90 34 297 168 69 109 182 112 
+292 299 83 192 46 269 263 159 149 19 117 63 143 274 67 292 201 260 147 104 313 
+126 56 163 200 123 225 16 90 230 262 258 232 21 57 39 264 296 31 147 300 278 
+216 219 35 75 50 197 13 78 225 237 267 185 41 302 95 197 71 220 270 139 223 3 
+144 288 273 191 228 28 135 295 253 265 172 95 1 106 130 107 267 29 36 212 291 6 
+196 293 19 142 275 8 209 239 280 131 23 291 162 161 64 142 14 150 254 141 236 
+268 126 277 21 155 221 309 198 306 284 124 264 75 173 192 242 234 34 3 21 253 
+44 35 140 262 62 227 250 213 167 30 50 99 150 33 4 281 170 82 55 124 141 40 263 
+36 114 109 280 294 18 201 39 289 149 215 82 153 306 186 301 219 133 257 95 99 
+248 175 9 183 126 179 198 110 279 34 101 163 298 265 270 237 46 8 86 204 51 294 
+214 206 89 133 61 130 9 85 303 134 256 154 182 210 115 25 304 108 143 53 209 18 
+103 176 244 247 299 304 10 1 8 307 62 6 73 258 69 305 147 202 136 171 277 119 
+297 266 211 154 84 68 70 83 29 11 67 71 24 305 49 60 91 269 2 22 194 280 33 160 
+246 260 245 286 39 68 12 260 24 109 84 289 247 38 127 55 222 283 85 205 311 211 
+252 226 113 12 39 166 154 305 245 25 181 113 233 216 121 212 30 148 241 195 254 
+239 59 313 28 233 118 298 167 128 192 144 92 308 101 65 156 220 49 281 268 224 
+100 66 57 137 87 22 292 103 78 102 202 38 29 232 177 22 129 68 168 265 74 272 
+275 204 174 10 124 43 217 218 134 158 12 137 308 199 247 201 162 5 59 52 210 
+278 20 214 304 271 178 282 46 106 228 249 312 250 311 309 75 271 15 287 136 269 
+100 164 239 182 308 297 70 246 64 240 196 195 156 97 14 52 112 96 15 312 29 134 
+35 17 227 152 71 122 128 94 2 47 47 145 287 13 274 190 8 111 97 235 229 67 194 
+59 215 205 188 216 23 70 25 206 285 98 151 293 240 230 66 253 142 177 185 164 
+18 5 34 199 26 24 207 226 15 189 313 224 198 208 102 79 3 119 76 89 256 56 40 
+165 213 69 207 5 157 234 255 180 295 32 88 217 316 276 203 273 93 86 302 193 20 
+116 122 226 236 7 268 3 242 111 318 93 184 125 238 281 72 259 10 222 185 262 
+160 50 295 155 123 127 153 45 9 27 121 89 35 238 85 107 169 166 31 310 16 188 
+53 307 160 148 118 200 25 83 290 188 314 165 115 246 162 63 241 97 112 194 157 
+38 250 90 132 120 213 290 65 279 255 278 118 37 30 173 94 60 189 92 47 243 110 
+58 176 146 105 254 43 94 223 224 2 243 12 235 131 244 149 117 259 108 45 230 
+164 76 187 79 101 261 109 ^
+656 0 310 208 189 143 149 32 59 41 130 20 31 245 123 2 154 135 168 216 32 14 
+286 231 31 62 102 213 303 7 257 244 22 118 26 269 272 105 91 44 180 27 94 232 
+166 301 230 79 199 84 164 248 128 288 284 133 208 17 198 259 204 187 273 102 30 
+282 218 85 116 111 146 16 18 299 177 11 87 169 179 292 252 3 255 53 296 82 249 
+125 227 201 171 266 39 77 273 240 9 172 46 278 205 139 136 86 79 16 63 54 76 56 
+312 123 312 78 236 179 247 210 104 266 84 119 172 229 299 315 311 298 31 51 26 
+314 314 38 80 13 2 292 114 24 44 191 103 27 221 135 123 140 99 25 317 54 121 42 
+276 301 92 134 22 256 5 159 100 298 180 72 170 131 155 270 52 23 219 231 76 138 
+1 202 272 150 167 264 169 30 237 142 186 127 142 3 72 32 152 265 87 214 255 191 
+241 293 77 284 316 229 161 15 100 115 159 283 319 3 244 298 42 93 280 303 283 
+181 24 33 149 204 4 252 313 213 120 307 113 106 181 207 54 259 21 166 163 251 
+223 50 246 75 186 138 184 223 61 1 8 175 107 6 167 81 114 207 99 14 275 155 132 
+73 133 70 72 308 110 11 98 245 112 281 221 146 199 73 88 315 139 319 141 189 
+188 225 286 48 10 273 285 51 71 35 247 27 49 156 233 312 261 257 289 64 17 15 
+238 94 49 111 191 58 272 288 146 154 318 189 5 170 176 197 169 41 313 41 175 96 
+285 234 92 145 64 155 315 128 243 208 200 219 48 21 28 184 40 40 178 157 47 196 
+68 157 185 175 279 306 23 264 307 296 127 4 24 216 170 314 176 59 224 151 130 
+203 86 34 295 164 65 107 178 112 292 297 79 188 42 265 259 159 145 19 113 61 
+139 274 65 290 199 256 143 104 311 126 52 161 198 121 225 10 90 230 262 254 228 
+15 55 39 260 294 29 147 300 278 216 215 35 75 48 193 7 74 223 233 267 185 37 
+300 95 195 71 218 268 137 221 318 144 284 271 187 228 26 131 293 249 263 172 91 
+320 104 128 105 263 23 36 210 287 194 291 13 140 271 4 207 237 280 131 17 291 
+162 161 60 142 14 148 252 141 234 264 124 275 17 153 217 305 198 304 280 120 
+262 71 173 192 238 232 28 1 19 251 40 29 136 258 58 227 246 213 165 28 46 95 
+150 29 319 279 168 78 53 124 137 38 263 34 112 109 276 290 16 201 33 287 149 
+215 80 151 302 182 297 217 133 253 93 97 248 173 9 183 122 177 194 108 279 30 
+99 163 296 265 270 235 44 8 82 204 49 294 212 202 89 129 57 126 7 85 299 132 
+256 154 180 210 115 21 304 108 141 51 209 14 103 176 242 245 295 302 10 318 6 
+305 60 4 69 258 69 303 145 202 134 171 277 115 297 262 209 152 82 66 70 83 29 9 
+67 67 22 301 47 58 89 267 2 16 190 278 33 160 246 258 241 282 35 64 6 260 18 
+105 80 289 247 38 125 55 292 ^
+<D
+
+H>SHS Type 3 Strings<H
+D>
+45 0 14 5 3 1 4 16 12 20 1 6 15 11 18 4 17 16 6 10 3 2 9 9 14 6 2 8 6 7 10 17 
+12 20 6 7 5 16 1 4 2 17 10 15 8 20 1 ^
+<D
+
diff --git a/dbus/test/data/valid-config-files-system/debug-allow-all-fail.conf.in b/dbus/test/data/valid-config-files-system/debug-allow-all-fail.conf.in
new file mode 100644
index 0000000..bab178f
--- /dev/null
+++ b/dbus/test/data/valid-config-files-system/debug-allow-all-fail.conf.in
@@ -0,0 +1,17 @@
+<!-- Bus that listens on a debug pipe and doesn't create any restrictions -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <listen>debug-pipe:name=test-server</listen>
+  <listen>@TEST_LISTEN@</listen>
+  <type>system</type>
+  <servicehelper>@TEST_LAUNCH_HELPER_BINARY@</servicehelper>
+  <servicedir>@DBUS_TEST_DATA@/invalid-service-files-system</servicedir>
+  <policy context="default">
+    <allow send_interface="*"/>
+    <allow receive_interface="*"/>
+    <allow own="*"/>
+    <allow user="*"/>
+  </policy>
+</busconfig>
diff --git a/dbus/test/data/valid-config-files-system/debug-allow-all-pass.conf.in b/dbus/test/data/valid-config-files-system/debug-allow-all-pass.conf.in
new file mode 100644
index 0000000..3836673
--- /dev/null
+++ b/dbus/test/data/valid-config-files-system/debug-allow-all-pass.conf.in
@@ -0,0 +1,17 @@
+<!-- Bus that listens on a debug pipe and doesn't create any restrictions -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <listen>debug-pipe:name=test-server</listen>
+  <listen>@TEST_LISTEN@</listen>
+  <type>system</type>
+  <servicehelper>@TEST_LAUNCH_HELPER_BINARY@</servicehelper>
+  <servicedir>@DBUS_TEST_DATA@/valid-service-files-system</servicedir>
+  <policy context="default">
+    <allow send_interface="*"/>
+    <allow receive_interface="*"/>
+    <allow own="*"/>
+    <allow user="*"/>
+  </policy>
+</busconfig>
diff --git a/dbus/test/data/valid-config-files/basic.conf b/dbus/test/data/valid-config-files/basic.conf
new file mode 100644
index 0000000..5297097
--- /dev/null
+++ b/dbus/test/data/valid-config-files/basic.conf
@@ -0,0 +1,32 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/bar</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.d</includedir>
+  <servicedir>/usr/share/foo</servicedir>
+  <include ignore_missing="yes">nonexistent.conf</include>
+  <policy context="default">
+    <allow user="*"/>
+  </policy>
+
+  <limit name="max_incoming_bytes">5000</limit>   
+  <limit name="max_outgoing_bytes">5000</limit>
+  <limit name="max_message_size">300</limit>
+  <limit name="service_start_timeout">5000</limit>
+  <limit name="auth_timeout">6000</limit>
+  <limit name="max_completed_connections">50</limit>  
+  <limit name="max_incomplete_connections">80</limit>
+  <limit name="max_connections_per_user">64</limit>
+  <limit name="max_pending_service_starts">64</limit>
+  <limit name="max_names_per_connection">256</limit>
+
+  <selinux>
+        <associate own="org.freedesktop.FrobationaryMeasures"
+         context="my_selinux_context_t"/>
+        <associate own="org.freedesktop.BlahBlahBlah"
+         context="foo_t"/>
+  </selinux>
+
+</busconfig>
diff --git a/dbus/test/data/valid-config-files/basic.d/basic.conf b/dbus/test/data/valid-config-files/basic.d/basic.conf
new file mode 100644
index 0000000..d109d71
--- /dev/null
+++ b/dbus/test/data/valid-config-files/basic.d/basic.conf
@@ -0,0 +1,13 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/bar</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.d</includedir>
+  <servicedir>/usr/share/foo</servicedir>
+  <include ignore_missing="yes">nonexistent.conf</include>
+  <policy context="default">
+    <allow user="*"/>
+  </policy>
+</busconfig>
diff --git a/dbus/test/data/valid-config-files/check-own-rules.conf b/dbus/test/data/valid-config-files/check-own-rules.conf
new file mode 100644
index 0000000..bc2f415
--- /dev/null
+++ b/dbus/test/data/valid-config-files/check-own-rules.conf
@@ -0,0 +1,14 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/bar</listen>
+  <listen>tcp:port=1234</listen>
+  <servicedir>/usr/share/foo</servicedir>
+  <policy context="default">
+    <allow user="*"/>
+    <deny own="*"/>
+    <allow own_prefix="org.freedesktop.ManySystems"/>
+  </policy>
+
+</busconfig>
diff --git a/dbus/test/data/valid-config-files/debug-allow-all-sha1.conf.in b/dbus/test/data/valid-config-files/debug-allow-all-sha1.conf.in
new file mode 100644
index 0000000..8baee7d
--- /dev/null
+++ b/dbus/test/data/valid-config-files/debug-allow-all-sha1.conf.in
@@ -0,0 +1,16 @@
+<!-- Bus that listens on a debug pipe and requires SHA1 auth, used to test SHA1 -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <listen>debug-pipe:name=test-server</listen>
+  <listen>@TEST_LISTEN@</listen>
+  <servicedir>@DBUS_TEST_DATA@/valid-service-files</servicedir>
+  <auth>DBUS_COOKIE_SHA1</auth>
+  <policy context="default">
+    <allow send_interface="*"/>
+    <allow receive_interface="*"/>
+    <allow own="*"/>
+    <allow user="*"/>
+  </policy>
+</busconfig>
diff --git a/dbus/test/data/valid-config-files/debug-allow-all.conf.in b/dbus/test/data/valid-config-files/debug-allow-all.conf.in
new file mode 100644
index 0000000..00df20d
--- /dev/null
+++ b/dbus/test/data/valid-config-files/debug-allow-all.conf.in
@@ -0,0 +1,15 @@
+<!-- Bus that listens on a debug pipe and doesn't create any restrictions -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <listen>debug-pipe:name=test-server</listen>
+  <listen>@TEST_LISTEN@</listen>
+  <servicedir>@DBUS_TEST_DATA@/valid-service-files</servicedir>
+  <policy context="default">
+    <allow send_interface="*"/>
+    <allow receive_interface="*"/>
+    <allow own="*"/>
+    <allow user="*"/>
+  </policy>
+</busconfig>
diff --git a/dbus/test/data/valid-config-files/entities.conf b/dbus/test/data/valid-config-files/entities.conf
new file mode 100644
index 0000000..3d3cea7
--- /dev/null
+++ b/dbus/test/data/valid-config-files/entities.conf
@@ -0,0 +1,14 @@
+<!-- This config file contains XML entities -->
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/&lt;bar&gt;</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.&#100;</includedir>
+  <servicedir>/usr/&amp;share/foo</servicedir>
+  <include ignore_missing="ye&#115;">nonexistent.conf&#110;</include>
+  <policy context="&#100;efault">
+    <allow user="*"/>
+  </policy>
+</busconfig>
diff --git a/dbus/test/data/valid-config-files/incoming-limit.conf b/dbus/test/data/valid-config-files/incoming-limit.conf
new file mode 100644
index 0000000..abfab3f
--- /dev/null
+++ b/dbus/test/data/valid-config-files/incoming-limit.conf
@@ -0,0 +1,18 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <!-- Our well-known bus type, don't change this -->
+  <type>session</type>
+  <listen>unix:tmpdir=/tmp</listen>
+
+  <policy context="default">
+    <!-- Allow everything to be sent -->
+    <allow send_destination="*" eavesdrop="true"/>
+    <!-- Allow everything to be received -->
+    <allow eavesdrop="true"/>
+    <!-- Allow anyone to own anything -->
+    <allow own="*"/>
+  </policy>
+
+  <limit name="max_incoming_bytes">1</limit>
+</busconfig>
diff --git a/dbus/test/data/valid-config-files/many-rules.conf b/dbus/test/data/valid-config-files/many-rules.conf
new file mode 100644
index 0000000..2393162
--- /dev/null
+++ b/dbus/test/data/valid-config-files/many-rules.conf
@@ -0,0 +1,61 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <user>mybususer</user>
+  <listen>unix:path=/foo/bar</listen>
+  <listen>tcp:port=1234</listen>
+  <includedir>basic.d</includedir>
+  <standard_session_servicedirs />
+  <servicedir>/usr/share/foo</servicedir>
+  <include ignore_missing="yes">nonexistent.conf</include>
+  <policy context="default">
+    <allow user="*"/>
+    <deny send_interface="org.freedesktop.System" send_member="Reboot"/> 
+    <deny receive_interface="org.freedesktop.System" receive_member="Reboot"/>
+    <deny send_path="/foo/bar/SystemObjectThing" send_member="Reboot"/> 
+    <deny own="org.freedesktop.System"/>
+    <deny own_prefix="org.freedesktop.ManySystems"/>
+    <deny send_destination="org.freedesktop.System"/>
+    <deny receive_sender="org.freedesktop.System"/>
+    <deny user="root"/>
+    <deny group="bin"/>
+    <allow send_type="error"/>
+    <allow send_type="method_call"/>
+    <allow send_type="method_return"/>
+    <allow send_type="signal"/>
+    <deny send_destination="org.freedesktop.Bar" send_interface="org.freedesktop.Foo"/>
+    <deny send_destination="org.freedesktop.Bar" send_interface="org.freedesktop.Foo" send_type="method_call"/>
+  </policy>
+
+  <policy context="mandatory">
+    <allow user="*"/>
+    <deny send_interface="org.freedesktop.System" send_member="Reboot"/> 
+    <deny receive_interface="org.freedesktop.System" receive_member="Reboot"/>
+    <deny send_path="/foo/bar/SystemObjectThing" send_member="Reboot"/> 
+    <deny own="org.freedesktop.System"/>
+    <deny own_prefix="org.freedesktop.ManySystems"/>
+    <deny send_destination="org.freedesktop.System"/>
+    <deny receive_sender="org.freedesktop.System"/>
+    <deny user="root"/>
+    <deny group="bin"/>
+    <allow send_type="error"/>
+    <allow send_type="method_call"/>
+    <allow send_type="method_return"/>
+    <allow send_type="signal"/>
+    <deny send_destination="org.freedesktop.Bar" send_interface="org.freedesktop.Foo"/>
+    <deny send_destination="org.freedesktop.Bar" send_interface="org.freedesktop.Foo" send_type="method_call"/>
+  </policy>
+
+  <limit name="max_incoming_bytes">5000</limit>   
+  <limit name="max_outgoing_bytes">5000</limit>
+  <limit name="max_message_size">300</limit>
+  <limit name="service_start_timeout">5000</limit>
+  <limit name="auth_timeout">6000</limit>
+  <limit name="max_completed_connections">50</limit>  
+  <limit name="max_incomplete_connections">80</limit>
+  <limit name="max_connections_per_user">64</limit>
+  <limit name="max_pending_service_starts">64</limit>
+  <limit name="max_names_per_connection">256</limit>
+  <limit name="max_match_rules_per_connection">512</limit>
+                                   
+</busconfig>
diff --git a/dbus/test/data/valid-config-files/system.d/test.conf b/dbus/test/data/valid-config-files/system.d/test.conf
new file mode 100644
index 0000000..5b60a1f
--- /dev/null
+++ b/dbus/test/data/valid-config-files/system.d/test.conf
@@ -0,0 +1,20 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <!-- The following demonstrates how to punch holes in a default deny-all 
+       policy so that a particular user can own a service, and other 
+       connections can get messages from it -->
+
+  <!-- Only root can own the FooService service, and 
+       this user can only send the one kind of message -->
+  <policy user="root">
+    <allow own="org.foo.FooService"/>
+    <allow send_interface="org.foo.FooBroadcastInterface"/>
+  </policy>
+
+  <!-- Allow any connection to receive the message, but 
+       only if the message is sent by the owner of FooService -->
+  <policy context="default">
+    <allow receive_interface="org.foo.FooBroadcastInterface" receive_sender="org.foo.FooService"/>
+  </policy>
+</busconfig>
diff --git a/dbus/test/data/valid-introspection-files/lots-of-types.xml b/dbus/test/data/valid-introspection-files/lots-of-types.xml
new file mode 100644
index 0000000..8e0e605
--- /dev/null
+++ b/dbus/test/data/valid-introspection-files/lots-of-types.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Introspection 0.1//EN"
+ "http://www.freedesktop.org/software/dbus/introspection.dtd">
+<node>
+
+  <interface name="org.freedesktop.LotsOfTypesInterface">
+
+    <method name="SetInt32Value">
+      <arg name="theInt32" type="int32"/>
+    </method>
+    <method name="GetInt32Value">
+      <arg name="theInt32" type="int32" direction="out"/>
+    </method>
+    <signal name="Int32ValueChanged">
+      <arg name="newInt32Value" type="int32"/>
+    </signal>
+
+    <method name="SetUint32Value">
+      <arg name="theUint32" type="uint32"/>
+    </method>
+    <method name="GetUint32Value">
+      <arg name="theUint32" type="uint32" direction="out"/>
+    </method>
+    <signal name="Uint32ValueChanged">
+      <arg name="newUint32Value" type="uint32"/>
+    </signal>
+
+    <method name="SetInt64Value">
+      <arg name="theInt64" type="int64"/>
+    </method>
+    <method name="GetInt64Value">
+      <arg name="theInt64" type="int64" direction="out"/>
+    </method>
+    <signal name="Int64ValueChanged">
+      <arg name="newInt64Value" type="int64"/>
+    </signal>
+
+    <method name="SetUint64Value">
+      <arg name="theUint64" type="uint64"/>
+    </method>
+    <method name="GetUint64Value">
+      <arg name="theUint64" type="uint64" direction="out"/>
+    </method>
+    <signal name="Uint64ValueChanged">
+      <arg name="newUint64Value" type="uint64"/>
+    </signal>
+
+    <method name="SetBooleanValue">
+      <arg name="theBoolean" type="boolean"/>
+    </method>
+    <method name="GetBooleanValue">
+      <arg name="theBoolean" type="boolean" direction="out"/>
+    </method>
+    <signal name="BooleanValueChanged">
+      <arg name="newBooleanValue" type="boolean"/>
+    </signal>
+
+    <method name="SetStringValue">
+      <arg name="theString" type="string"/>
+    </method>
+    <method name="GetStringValue">
+      <arg name="theString" type="string" direction="out"/>
+    </method>
+    <signal name="StringValueChanged">
+      <arg name="newStringValue" type="string"/>
+    </signal>
+
+    <method name="SetDoubleValue">
+      <arg name="theDouble" type="double"/>
+    </method>
+    <method name="GetDoubleValue">
+      <arg name="theDouble" type="double" direction="out"/>
+    </method>
+    <signal name="DoubleValueChanged">
+      <arg name="newDoubleValue" type="double"/>
+    </signal>
+
+  </interface>
+
+  <interface name="org.freedesktop.ASecondInterface">
+    <method name="RandomFrobate">
+      <arg type="boolean" direction="in"/>
+      <arg type="string" direction="out"/>
+      <arg type="string" direction="out"/>
+      <arg type="int64"/> <!-- direction defaults to "in" -->
+      <arg type="string" direction="out"/>
+      <arg type="string" direction="out"/>
+      <arg type="int32" direction="in"/>
+    </method>
+  </interface>
+
+</node>
+
diff --git a/dbus/test/data/valid-messages/array-of-array-of-uint32.message b/dbus/test/data/valid-messages/array-of-array-of-uint32.message
new file mode 100644
index 0000000..e12186b
--- /dev/null
+++ b/dbus/test/data/valid-messages/array-of-array-of-uint32.message
@@ -0,0 +1,33 @@
+# Message with an array of array of uint32
+
+VALID_HEADER method_call
+REQUIRED_FIELDS
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+
+TYPE ARRAY
+TYPE ARRAY
+TYPE UINT32
+
+LENGTH Array
+START_LENGTH Array
+
+## array of uint32
+LENGTH SubArray1
+START_LENGTH SubArray1
+UINT32 1
+UINT32 2
+UINT32 3
+END_LENGTH SubArray1
+
+## array of uint32
+LENGTH SubArray2
+START_LENGTH SubArray2
+UINT32 4
+UINT32 5
+END_LENGTH SubArray2
+
+END_LENGTH Array
+
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/dict-simple.message b/dbus/test/data/valid-messages/dict-simple.message
new file mode 100644
index 0000000..fa6927d
--- /dev/null
+++ b/dbus/test/data/valid-messages/dict-simple.message
@@ -0,0 +1,15 @@
+# A simple dict
+
+VALID_HEADER method_call
+REQUIRED_FIELDS
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+TYPE DICT
+LENGTH Dict
+START_LENGTH Dict
+STRING 'int32'
+TYPE INT32
+INT32 0x12345678
+END_LENGTH Dict
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/dict.message b/dbus/test/data/valid-messages/dict.message
new file mode 100644
index 0000000..0f997b1
--- /dev/null
+++ b/dbus/test/data/valid-messages/dict.message
@@ -0,0 +1,47 @@
+# Dict with different values
+
+VALID_HEADER method_call
+REQUIRED_FIELDS
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+TYPE DICT
+LENGTH Dict
+START_LENGTH Dict
+STRING 'boolean'
+TYPE BOOLEAN
+BYTE 1
+STRING 'int32'
+TYPE INT32
+INT32 0x12345678
+STRING 'uint32'
+TYPE UINT32
+UINT32 0x8765432
+STRING 'double'
+TYPE DOUBLE
+DOUBLE 3.141592653589
+STRING 'string'
+TYPE STRING
+STRING 'This is a string'
+STRING 'boolean_array'
+TYPE ARRAY
+TYPE BOOLEAN
+BOOLEAN_ARRAY { true, false, false, true, false }
+STRING 'int32_array'
+TYPE ARRAY
+TYPE INT32
+INT32_ARRAY { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10 }
+STRING 'uint32_array'
+TYPE ARRAY
+TYPE UINT32
+UINT32_ARRAY { 11, 12, 314, 1911, 57692, 1237, 2834 }
+STRING 'double_array'
+TYPE ARRAY
+TYPE DOUBLE
+DOUBLE_ARRAY { 0.1, 0.2, 3.1415926, 2.7183, 10.0, 9.99 }
+STRING 'string_array'
+TYPE ARRAY
+TYPE STRING
+STRING_ARRAY { 'Hello', 'This', 'Is', 'A', 'String', 'Array!' }
+END_LENGTH Dict
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/emptiness.message b/dbus/test/data/valid-messages/emptiness.message
new file mode 100644
index 0000000..32042c0
--- /dev/null
+++ b/dbus/test/data/valid-messages/emptiness.message
@@ -0,0 +1,63 @@
+# Empty arrays and strings
+
+VALID_HEADER method_call
+REQUIRED_FIELDS
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+TYPE STRING
+INT32 0
+BYTE 0 # Strings need to be NULL-terminated
+TYPE ARRAY
+TYPE BOOLEAN
+INT32 0
+TYPE ARRAY
+TYPE INT32
+INT32 0
+TYPE ARRAY
+TYPE UINT32
+INT32 0
+TYPE ARRAY
+TYPE DOUBLE
+INT32 0
+TYPE ARRAY
+TYPE BYTE
+INT32 0
+TYPE ARRAY
+TYPE STRING
+INT32 0
+TYPE DICT
+INT32 0
+
+# A dict with empty arrays
+TYPE DICT
+LENGTH Dict
+START_LENGTH Dict
+STRING 'boolean_array'
+TYPE ARRAY
+TYPE BOOLEAN
+INT32 0
+STRING 'int32_array'
+TYPE ARRAY
+TYPE INT32
+INT32 0
+STRING 'uint32_array'
+TYPE ARRAY
+TYPE UINT32
+INT32 0
+STRING 'double_array'
+TYPE ARRAY
+TYPE DOUBLE
+INT32 0
+STRING 'byte_array'
+TYPE ARRAY 
+TYPE BYTE
+INT32 0
+STRING 'string_array' }
+TYPE ARRAY
+TYPE STRING
+INT32 0
+END_LENGTH Dict
+
+END_LENGTH Body
+
diff --git a/dbus/test/data/valid-messages/lots-of-arguments.message b/dbus/test/data/valid-messages/lots-of-arguments.message
new file mode 100644
index 0000000..bdaae0f
--- /dev/null
+++ b/dbus/test/data/valid-messages/lots-of-arguments.message
@@ -0,0 +1,65 @@
+# Message with lots of different argument types
+
+VALID_HEADER method_call
+REQUIRED_FIELDS
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+TYPE NIL
+TYPE BYTE
+BYTE 42
+TYPE INT32
+INT32 0x12345678
+TYPE UINT32
+UINT32 0x8765432
+TYPE DOUBLE
+DOUBLE 3.141592653589
+TYPE STRING
+STRING 'This is a string'
+TYPE ARRAY
+TYPE BOOLEAN
+BOOLEAN_ARRAY { true, false, false, true, false }
+TYPE ARRAY
+TYPE INT32
+INT32_ARRAY { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10 }
+TYPE ARRAY
+TYPE UINT32
+UINT32_ARRAY { 11, 12, 314, 1911, 57692, 1237, 2834 }
+TYPE ARRAY
+TYPE DOUBLE
+DOUBLE_ARRAY { 0.1, 0.2, 3.1415926, 2.7183, 10.0, 9.99 }
+TYPE ARRAY
+TYPE STRING
+STRING_ARRAY { 'Hello', 'This', 'Is', 'A', 'String', 'Array!' }
+TYPE CUSTOM
+STRING 'named type'
+BYTE_ARRAY { 'b', 'i', 'n', 'a', 'r', 'y', 'd', 'a', 't', 'a' }
+
+TYPE ARRAY
+TYPE DICT
+LENGTH Array
+START_LENGTH Array
+
+LENGTH Dict1
+START_LENGTH Dict1
+STRING 'key1'
+TYPE INT32
+INT32 0x12345678
+STRING 'key2'
+TYPE UINT32
+UINT32 0x8765432
+END_LENGTH Dict1
+
+LENGTH Dict2
+START_LENGTH Dict2
+STRING 'key1'
+TYPE INT32
+INT32 0x12345678
+STRING 'key2'
+TYPE UINT32
+UINT32 0x8765432
+END_LENGTH Dict2
+
+END_LENGTH Array
+
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/no-padding.message b/dbus/test/data/valid-messages/no-padding.message
new file mode 100644
index 0000000..94df4d4
--- /dev/null
+++ b/dbus/test/data/valid-messages/no-padding.message
@@ -0,0 +1,22 @@
+## Message with no header padding
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+REQUIRED_FIELDS
+
+## this byte array is filled with zeros to the natural length 
+## of the header
+HEADER_FIELD UNKNOWN
+TYPE ARRAY
+TYPE BYTE
+ALIGN 4
+LENGTH ThisByteArray
+START_LENGTH ThisByteArray
+BYTE 1
+ALIGN 8 1
+END_LENGTH ThisByteArray
+
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/opposite-endian.message b/dbus/test/data/valid-messages/opposite-endian.message
new file mode 100644
index 0000000..90949dd
--- /dev/null
+++ b/dbus/test/data/valid-messages/opposite-endian.message
@@ -0,0 +1,30 @@
+## Message of opposite endianness, with lots of random fields in it
+
+OPPOSITE_ENDIAN
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+REQUIRED_FIELDS
+
+HEADER_FIELD UNKNOWN
+TYPE INT32
+INT32 0xfeeb
+
+ALIGN 8
+END_LENGTH Header
+
+START_LENGTH Body
+
+TYPE INT32
+INT32 89765432
+TYPE UINT32
+UINT32 0xfffffff
+TYPE STRING
+STRING 'Hello this is a string'
+TYPE DOUBLE
+DOUBLE 3.14159
+
+TYPE NIL
+
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/recursive-types.message b/dbus/test/data/valid-messages/recursive-types.message
new file mode 100644
index 0000000..e306fd1
--- /dev/null
+++ b/dbus/test/data/valid-messages/recursive-types.message
@@ -0,0 +1,99 @@
+## Message with recursive types
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+
+REQUIRED_FIELDS
+
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+
+# Everything is inside a dict
+TYPE DICT
+LENGTH Dict1
+START_LENGTH Dict1
+
+# first dict entry is an array of array of uint32
+STRING 'mega-uint-array'
+TYPE ARRAY
+TYPE ARRAY
+TYPE ARRAY
+TYPE UINT32
+LENGTH Array1
+START_LENGTH Array1
+
+LENGTH Array1_1
+START_LENGTH Array1_1
+UINT32_ARRAY { 1, 2, 3, 4, 5}
+UINT32_ARRAY { 2, 3, 4, 5, 1}
+UINT32_ARRAY { 3, 4, 5, 1, 2}
+END_LENGTH Array1_1
+
+LENGTH Array1_2
+START_LENGTH Array1_2
+UINT32_ARRAY { 4, 5, 6, 7, 8}
+UINT32_ARRAY { 5, 6, 7, 8, 4}
+END_LENGTH Array1_2
+
+END_LENGTH Array1
+
+# second dict entry is an array of strings
+STRING 'string-array'
+TYPE ARRAY
+TYPE STRING
+STRING_ARRAY { 'a', 'string', 'array'}
+
+# third dict entry is another dict
+STRING 'nested-dict'
+TYPE DICT
+LENGTH Dict2
+START_LENGTH Dict2
+
+STRING 'string'
+TYPE STRING
+STRING 'a deeply nested string'     
+
+STRING 'super-nested-dict'
+TYPE DICT
+LENGTH Dict3
+START_LENGTH Dict3
+
+STRING 'double-array'
+TYPE ARRAY
+TYPE DOUBLE
+DOUBLE_ARRAY {1.0, 2.0, 3.0}
+
+STRING 'dict-array'
+TYPE ARRAY
+TYPE DICT
+LENGTH Array2
+START_LENGTH Array2
+
+LENGTH Dict4
+START_LENGTH Dict4
+STRING 'key4'
+TYPE BYTE
+BYTE '4'
+END_LENGTH Dict4
+
+LENGTH Dict5
+START_LENGTH Dict5
+STRING 'key5'
+TYPE BYTE
+BYTE '5'
+END_LENGTH Dict5
+
+END_LENGTH Array2
+
+STRING 'boolean'
+TYPE BOOLEAN
+BOOLEAN false
+
+END_LENGTH Dict3
+
+END_LENGTH Dict2
+
+END_LENGTH Dict1
+
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/simplest-manual.message b/dbus/test/data/valid-messages/simplest-manual.message
new file mode 100644
index 0000000..d6a960d
--- /dev/null
+++ b/dbus/test/data/valid-messages/simplest-manual.message
@@ -0,0 +1,30 @@
+## like simplest.message, but doesn't use VALID_HEADER
+## convenience command. mostly to test the test framework.
+
+LITTLE_ENDIAN
+BYTE 'l'
+BYTE 1
+BYTE 0
+BYTE 0
+LENGTH Header
+LENGTH Body
+## client serial
+INT32 7
+
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/foo'
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Bar'
+HEADER_FIELD SIGNATURE
+TYPE STRING
+STRING ''
+
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/simplest.message b/dbus/test/data/valid-messages/simplest.message
new file mode 100644
index 0000000..b9ddaf6
--- /dev/null
+++ b/dbus/test/data/valid-messages/simplest.message
@@ -0,0 +1,10 @@
+## simplest possible valid message
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+REQUIRED_FIELDS
+
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/standard-acquire-service.message b/dbus/test/data/valid-messages/standard-acquire-service.message
new file mode 100644
index 0000000..459f3bb
--- /dev/null
+++ b/dbus/test/data/valid-messages/standard-acquire-service.message
@@ -0,0 +1,26 @@
+# Standard org.freedesktop.DBus.AcquireService message
+
+VALID_HEADER method_call
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/org/freedesktop/DBus'
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.DBus'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'AcquireService'
+HEADER_FIELD DESTINATION
+TYPE STRING
+STRING 'org.freedesktop.DBus'
+HEADER_FIELD SIGNATURE
+TYPE STRING
+STRING 'su'
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+TYPE STRING
+STRING 'org.freedesktop.DBus.Sample'
+TYPE UINT32
+UINT32 0
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/standard-hello.message b/dbus/test/data/valid-messages/standard-hello.message
new file mode 100644
index 0000000..a08835e
--- /dev/null
+++ b/dbus/test/data/valid-messages/standard-hello.message
@@ -0,0 +1,22 @@
+# Standard org.freedesktop.DBus.Hello message
+
+VALID_HEADER method_call
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/org/freedesktop/DBus'
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.DBus'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'Hello'
+HEADER_FIELD DESTINATION
+TYPE STRING
+STRING 'org.freedesktop.DBus'
+HEADER_FIELD SIGNATURE
+TYPE STRING
+STRING ''
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/standard-list-services.message b/dbus/test/data/valid-messages/standard-list-services.message
new file mode 100644
index 0000000..3e10aeb
--- /dev/null
+++ b/dbus/test/data/valid-messages/standard-list-services.message
@@ -0,0 +1,22 @@
+# Standard org.freedesktop.DBus.ListServices message
+
+VALID_HEADER method_call
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/org/freedesktop/DBus'
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.DBus'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'ListServices'
+HEADER_FIELD DESTINATION
+TYPE STRING
+STRING 'org.freedesktop.DBus'
+HEADER_FIELD SIGNATURE
+TYPE STRING
+STRING ''
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/standard-service-exists.message b/dbus/test/data/valid-messages/standard-service-exists.message
new file mode 100644
index 0000000..6b57eb5
--- /dev/null
+++ b/dbus/test/data/valid-messages/standard-service-exists.message
@@ -0,0 +1,24 @@
+# Standard org.freedesktop.DBus.ServiceExists message
+
+VALID_HEADER method_call
+HEADER_FIELD PATH
+TYPE OBJECT_PATH
+OBJECT_PATH '/org/freedesktop/DBus'
+HEADER_FIELD INTERFACE
+TYPE STRING
+STRING 'org.freedesktop.DBus'
+HEADER_FIELD MEMBER
+TYPE STRING
+STRING 'ServiceExists'
+HEADER_FIELD DESTINATION
+TYPE STRING
+STRING 'org.freedesktop.DBus'
+HEADER_FIELD SIGNATURE
+TYPE STRING
+STRING 's'
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+TYPE STRING
+STRING 'org.freedesktop.DBus.Sample'
+END_LENGTH Body
diff --git a/dbus/test/data/valid-messages/unknown-header-field.message b/dbus/test/data/valid-messages/unknown-header-field.message
new file mode 100644
index 0000000..ac7d624
--- /dev/null
+++ b/dbus/test/data/valid-messages/unknown-header-field.message
@@ -0,0 +1,19 @@
+## message with a 'name' header field and unknown 'unkn' field
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER method_call
+REQUIRED_FIELDS
+
+HEADER_FIELD UNKNOWN
+TYPE DICT
+LENGTH Dict
+START_LENGTH Dict
+STRING 'int32'
+TYPE INT32
+INT32 0x12345678
+END_LENGTH Dict
+
+ALIGN 8
+END_LENGTH Header
+START_LENGTH Body
+END_LENGTH Body
diff --git a/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteEchoService.service.in b/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteEchoService.service.in
new file mode 100644
index 0000000..3076f3b
--- /dev/null
+++ b/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteEchoService.service.in
@@ -0,0 +1,5 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteEchoService
+Exec=@DBUS_TEST_EXEC@/test-service@EXEEXT@
+User=anyrandomuser
+
diff --git a/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteSegfaultService.service.in b/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteSegfaultService.service.in
new file mode 100644
index 0000000..705d714
--- /dev/null
+++ b/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteSegfaultService.service.in
@@ -0,0 +1,5 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteSegfaultService
+Exec=@DBUS_TEST_EXEC@/test-segfault@EXEEXT@
+User=anyrandomuser
+
diff --git a/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service.in b/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service.in
new file mode 100644
index 0000000..870835e
--- /dev/null
+++ b/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service.in
@@ -0,0 +1,5 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteShellEchoServiceFail
+Exec=@DBUS_TEST_EXEC@/test-shell-service@EXEEXT@ "this should 'fail' because of an unterminated quote
+User=anyrandomuser
+
diff --git a/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service.in b/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service.in
new file mode 100644
index 0000000..6647261
--- /dev/null
+++ b/dbus/test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service.in
@@ -0,0 +1,5 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess
+Exec=@DBUS_TEST_EXEC@/test-shell-service@EXEEXT@ -test "that" 'we get' back --what "we put in"
+User=anyrandomuser
+
diff --git a/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service.in b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service.in
new file mode 100644
index 0000000..0fdfead
--- /dev/null
+++ b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuite.PrivServer
+Exec=@DBUS_TEST_EXEC@/name-test/test-privserver@EXEEXT@
+
diff --git a/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteEchoService.service.in b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteEchoService.service.in
new file mode 100644
index 0000000..a22a77d
--- /dev/null
+++ b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteEchoService.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteEchoService
+Exec=@DBUS_TEST_EXEC@/test-service@EXEEXT@
diff --git a/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service.in b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service.in
new file mode 100644
index 0000000..633862c
--- /dev/null
+++ b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteForkingEchoService
+Exec=@DBUS_TEST_EXEC@/test-service@EXEEXT@ org.freedesktop.DBus.TestSuiteForkingEchoService fork
diff --git a/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteSegfaultService.service.in b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteSegfaultService.service.in
new file mode 100644
index 0000000..7625427
--- /dev/null
+++ b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteSegfaultService.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteSegfaultService
+Exec=@DBUS_TEST_EXEC@/test-segfault@EXEEXT@
+
diff --git a/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service.in b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service.in
new file mode 100644
index 0000000..8f5964a
--- /dev/null
+++ b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteShellEchoServiceFail
+Exec=@DBUS_TEST_EXEC@/test-shell-service@EXEEXT@ "this should 'fail' because of an unterminated quote
diff --git a/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service.in b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service.in
new file mode 100644
index 0000000..a52887e
--- /dev/null
+++ b/dbus/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service.in
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess
+Exec=@DBUS_TEST_EXEC@/test-shell-service@EXEEXT@ -test "that" 'we get' back --what "we put in"
+
diff --git a/dbus/test/dbus-daemon-eavesdrop.c b/dbus/test/dbus-daemon-eavesdrop.c
new file mode 100644
index 0000000..0bd923d
--- /dev/null
+++ b/dbus/test/dbus-daemon-eavesdrop.c
@@ -0,0 +1,555 @@
+/* Integration tests for the eavesdrop=true|false keyword in DBusMatchRule
+ *
+ * Author: Cosimo Alfarano <cosimo.alfarano@collabora.co.uk>
+ * Based on: tests/dbus-daemon.c by Simon McVittie
+ * Copyright © 2010-2011 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <string.h>
+
+#ifdef DBUS_WIN
+# include <io.h>
+# include <windows.h>
+#else
+# include <signal.h>
+# include <unistd.h>
+#endif
+
+#define SENDER_NAME "test.eavesdrop.sender"
+#define SENDER_PATH "/test/eavesdrop/sender"
+#define SENDER_IFACE SENDER_NAME
+#define SENDER_SIGNAL_NAME "Signal"
+#define SENDER_STOPPER_NAME "Stopper"
+
+/* This rule is equivalent to the one added to a proxy connecting to
+ * SENDER_NAME+SENDER_IFACE, plus restricting on signal name.
+ * Being more restrictive, if the connection receives what we need, for sure
+ * the original proxy rule will match it */
+#define RECEIVER_RULE "sender='" SENDER_NAME "'," \
+  "interface='" SENDER_IFACE "'," \
+  "type='signal'," \
+  "member='" SENDER_SIGNAL_NAME "'"
+#define POLITELISTENER_RULE RECEIVER_RULE
+#define EAVESDROPPER_RULE RECEIVER_RULE ",eavesdrop=true"
+
+#define STOPPER_RULE "sender='" SENDER_NAME \
+  "',interface='" SENDER_IFACE "',type='signal',member='" SENDER_STOPPER_NAME "'"
+
+/* a connection received a signal to whom? */
+typedef enum {
+  NONE_YET = 0,
+  TO_ME,
+  TO_OTHER,
+  BROADCAST,
+} SignalDst;
+
+typedef struct {
+    DBusError e;
+    GError *ge;
+
+    GPid daemon_pid;
+
+    /* eavedrop keyword tests */
+    DBusConnection *sender;
+    DBusConnection *receiver;
+    SignalDst receiver_dst;
+    dbus_bool_t receiver_got_stopper;
+    DBusConnection *eavesdropper;
+    SignalDst eavesdropper_dst;
+    dbus_bool_t eavesdropper_got_stopper;
+    DBusConnection *politelistener;
+    SignalDst politelistener_dst;
+    dbus_bool_t politelistener_got_stopper;
+} Fixture;
+
+#define assert_no_error(e) _assert_no_error (e, __FILE__, __LINE__)
+static void
+_assert_no_error (const DBusError *e,
+    const char *file,
+    int line)
+{
+  if (G_UNLIKELY (dbus_error_is_set (e)))
+    g_error ("%s:%d: expected success but got error: %s: %s",
+        file, line, e->name, e->message);
+}
+
+static gchar *
+spawn_dbus_daemon (gchar *binary,
+    gchar *configuration,
+    GPid *daemon_pid)
+{
+  GError *error = NULL;
+  GString *address;
+  gint address_fd;
+  gchar *argv[] = {
+      binary,
+      configuration,
+      "--nofork",
+      "--print-address=1", /* stdout */
+      NULL
+  };
+
+  g_spawn_async_with_pipes (NULL, /* working directory */
+      argv,
+      NULL, /* envp */
+      G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+      NULL, /* child_setup */
+      NULL, /* user data */
+      daemon_pid,
+      NULL, /* child's stdin = /dev/null */
+      &address_fd,
+      NULL, /* child's stderr = our stderr */
+      &error);
+  g_assert_no_error (error);
+
+  address = g_string_new (NULL);
+
+  /* polling until the dbus-daemon writes out its address is a bit stupid,
+   * but at least it's simple, unlike dbus-launch... in principle we could
+   * use select() here, but life's too short */
+  while (1)
+    {
+      gssize bytes;
+      gchar buf[4096];
+      gchar *newline;
+
+      bytes = read (address_fd, buf, sizeof (buf));
+
+      if (bytes > 0)
+        g_string_append_len (address, buf, bytes);
+
+      newline = strchr (address->str, '\n');
+
+      if (newline != NULL)
+        {
+          g_string_truncate (address, newline - address->str);
+          break;
+        }
+
+      g_usleep (G_USEC_PER_SEC / 10);
+    }
+
+  return g_string_free (address, FALSE);
+}
+
+static DBusConnection *
+connect_to_bus (const gchar *address)
+{
+  DBusConnection *conn;
+  DBusError error = DBUS_ERROR_INIT;
+  dbus_bool_t ok;
+
+  conn = dbus_connection_open_private (address, &error);
+  assert_no_error (&error);
+  g_assert (conn != NULL);
+
+  ok = dbus_bus_register (conn, &error);
+  assert_no_error (&error);
+  g_assert (ok);
+  g_assert (dbus_bus_get_unique_name (conn) != NULL);
+
+  dbus_connection_setup_with_g_main (conn, NULL);
+  return conn;
+}
+
+/* send a unicast signal to <self> to ensure that no other connection
+ * listening is the actual recipient for the signal */
+static DBusHandlerResult
+sender_send_unicast_to_sender (Fixture *f)
+{
+  DBusMessage *signal;
+
+  signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE,
+      SENDER_SIGNAL_NAME);
+  dbus_message_set_destination (signal, dbus_bus_get_unique_name (f->sender));
+
+  if (signal == NULL)
+    g_error ("OOM");
+
+  if (!dbus_connection_send (f->sender, signal, NULL))
+    g_error ("OOM");
+
+  dbus_message_unref (signal);
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* send a unicast signal to <receiver>, making <politelistener> and
+ * <eavesdropper> not a actual recipient for it */
+static DBusHandlerResult
+sender_send_unicast_to_receiver (Fixture *f)
+{
+  DBusMessage *signal;
+
+  signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE, SENDER_SIGNAL_NAME);
+  dbus_message_set_destination (signal, dbus_bus_get_unique_name (f->receiver));
+
+  if (signal == NULL)
+    g_error ("OOM");
+
+  if (!dbus_connection_send (f->sender, signal, NULL))
+    g_error ("OOM");
+
+  dbus_message_unref (signal);
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+sender_send_broadcast (Fixture *f)
+{
+  DBusMessage *signal;
+
+  signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE, SENDER_SIGNAL_NAME);
+  dbus_message_set_destination (signal, NULL);
+
+  if (signal == NULL)
+    g_error ("OOM");
+
+  if (!dbus_connection_send (f->sender, signal, NULL))
+    g_error ("OOM");
+
+  dbus_message_unref (signal);
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* Send special broadcast signal to indicate that the connections can "stop"
+ * listening and check their results.
+ * DBus does not re-order messages, so when the three connections have received
+ * this signal, we are sure that any message sent before it has also been
+ * dispatched. */
+static DBusHandlerResult
+sender_send_stopper (Fixture *f)
+{
+  DBusMessage *signal;
+
+  signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE, SENDER_STOPPER_NAME);
+  dbus_message_set_destination (signal, NULL);
+
+  if (signal == NULL)
+    g_error ("OOM");
+
+  if (!dbus_connection_send (f->sender, signal, NULL))
+    g_error ("OOM");
+
+  dbus_message_unref (signal);
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* Ignore NameAcquired, then depending on the signal received:
+ * - updates f-><conn>_dst based on the destination of the message
+ * - asserts that <conn> received the stop signal
+ */
+static DBusHandlerResult
+signal_filter (DBusConnection *connection,
+    DBusMessage *message,
+    void *user_data)
+{
+  Fixture *f = user_data;
+  SignalDst *dst = NULL;
+  DBusConnection **conn;
+  dbus_bool_t *got_stopper;
+
+  if (0 == strcmp (dbus_message_get_member (message), "NameAcquired"))
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+  if (connection == f->receiver)
+    {
+      dst = &(f->receiver_dst);
+      conn = &(f->receiver);
+      got_stopper = &(f->receiver_got_stopper);
+    }
+  else if (connection == f->eavesdropper)
+    {
+      dst = &(f->eavesdropper_dst);
+      conn = &(f->eavesdropper);
+      got_stopper = &(f->eavesdropper_got_stopper);
+    }
+  else if (connection == f->politelistener)
+    {
+      dst = &(f->politelistener_dst);
+      conn = &(f->politelistener);
+      got_stopper = &(f->politelistener_got_stopper);
+    }
+  else
+    {
+      g_error ("connection not matching");
+    }
+
+  if (0 == strcmp (dbus_message_get_member (message), SENDER_SIGNAL_NAME))
+    {
+      if (dbus_message_get_destination (message) == NULL)
+        *dst = BROADCAST;
+      else if (0 == strcmp (dbus_message_get_destination (message), dbus_bus_get_unique_name (*conn)))
+        *dst = TO_ME;
+      else /* if (dbus_message_get_destination (message) != NULL) */
+        *dst = TO_OTHER;
+    }
+  else if (0 == strcmp (dbus_message_get_member (message), SENDER_STOPPER_NAME))
+    {
+      *got_stopper = TRUE;
+    }
+  else
+    {
+      g_error ("got unknown member from message: %s",
+          dbus_message_get_member (message));
+    }
+
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+add_receiver_filter (Fixture *f)
+{
+  DBusError e = DBUS_ERROR_INIT;
+
+  dbus_bus_add_match (f->receiver, RECEIVER_RULE, &e);
+  assert_no_error (&e);
+  dbus_bus_add_match (f->receiver, STOPPER_RULE, &e);
+  assert_no_error (&e);
+
+  if (!dbus_connection_add_filter (f->receiver,
+        signal_filter, f, NULL))
+    g_error ("OOM");
+}
+
+static void
+add_eavesdropper_filter (Fixture *f)
+{
+  DBusError e = DBUS_ERROR_INIT;
+
+  dbus_bus_add_match (f->eavesdropper, EAVESDROPPER_RULE, &e);
+  assert_no_error (&e);
+  dbus_bus_add_match (f->eavesdropper, STOPPER_RULE, &e);
+  assert_no_error (&e);
+
+  if (!dbus_connection_add_filter (f->eavesdropper,
+        signal_filter, f, NULL))
+    g_error ("OOM");
+}
+
+static void
+add_politelistener_filter (Fixture *f)
+{
+  DBusError e = DBUS_ERROR_INIT;
+
+  dbus_bus_add_match (f->politelistener, POLITELISTENER_RULE, &e);
+  assert_no_error (&e);
+  dbus_bus_add_match (f->politelistener, STOPPER_RULE, &e);
+  assert_no_error (&e);
+
+  if (!dbus_connection_add_filter (f->politelistener,
+        signal_filter, f, NULL))
+    g_error ("OOM");
+}
+
+static void
+setup (Fixture *f,
+    gconstpointer context G_GNUC_UNUSED)
+{
+  gchar *dbus_daemon;
+  gchar *config;
+  gchar *address;
+
+  f->ge = NULL;
+  dbus_error_init (&f->e);
+
+  dbus_daemon = g_strdup (g_getenv ("DBUS_TEST_DAEMON"));
+
+  if (dbus_daemon == NULL)
+    dbus_daemon = g_strdup ("dbus-daemon");
+
+  if (g_getenv ("DBUS_TEST_SYSCONFDIR") != NULL)
+    {
+      config = g_strdup_printf ("--config-file=%s/dbus-1/session.conf",
+          g_getenv ("DBUS_TEST_SYSCONFDIR"));
+    }
+  else if (g_getenv ("DBUS_TEST_DATA") != NULL)
+    {
+      config = g_strdup_printf (
+          "--config-file=%s/valid-config-files/session.conf",
+          g_getenv ("DBUS_TEST_DATA"));
+    }
+  else
+    {
+      config = g_strdup ("--session");
+    }
+
+  address = spawn_dbus_daemon (dbus_daemon, config, &f->daemon_pid);
+
+  g_free (dbus_daemon);
+  g_free (config);
+
+  f->sender = connect_to_bus (address);
+  dbus_bus_request_name (f->sender, SENDER_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE,
+      &(f->e));
+  f->receiver = connect_to_bus (address);
+  f->eavesdropper = connect_to_bus (address);
+  f->politelistener = connect_to_bus (address);
+  add_receiver_filter (f);
+  add_politelistener_filter (f);
+  add_eavesdropper_filter (f);
+
+  g_free (address);
+}
+
+static void
+test_eavesdrop_broadcast (Fixture *f,
+    gconstpointer context G_GNUC_UNUSED)
+{
+  sender_send_broadcast (f);
+  sender_send_stopper (f);
+
+  while (!f->receiver_got_stopper ||
+      !f->politelistener_got_stopper ||
+      !f->eavesdropper_got_stopper)
+    g_main_context_iteration (NULL, TRUE);
+
+  /* all the three connection can receive a broadcast */
+  g_assert_cmpint (f->receiver_dst, ==, BROADCAST);
+  g_assert_cmpint (f->politelistener_dst, ==, BROADCAST);
+  g_assert_cmpint (f->eavesdropper_dst, ==, BROADCAST);
+}
+
+/* a way to say that none of the listening connection are destination of the
+ * signal */
+static void
+test_eavesdrop_unicast_to_sender (Fixture *f,
+    gconstpointer context G_GNUC_UNUSED)
+{
+  sender_send_unicast_to_sender (f);
+  sender_send_stopper (f);
+
+  while (!f->receiver_got_stopper ||
+      !f->politelistener_got_stopper ||
+      !f->eavesdropper_got_stopper)
+    g_main_context_iteration (NULL, TRUE);
+
+  /* not directed to it and not broadcasted, they cannot receive it */
+  g_assert_cmpint (f->receiver_dst, ==, NONE_YET);
+  g_assert_cmpint (f->politelistener_dst, ==, NONE_YET);
+  /* eavesdrop=true, it will receive the signal even though it's not directed
+   * to it */
+  g_assert_cmpint (f->eavesdropper_dst, ==, TO_OTHER);
+}
+
+static void
+test_eavesdrop_unicast_to_receiver (Fixture *f,
+    gconstpointer context G_GNUC_UNUSED)
+{
+  sender_send_unicast_to_receiver (f);
+  sender_send_stopper (f);
+
+  while (!f->receiver_got_stopper ||
+      !f->politelistener_got_stopper ||
+      !f->eavesdropper_got_stopper)
+    g_main_context_iteration (NULL, TRUE);
+
+  /* direct to him */
+  g_assert_cmpint (f->receiver_dst, ==, TO_ME);
+  /* not directed to it and not broadcasted, it cannot receive it */
+  g_assert_cmpint (f->politelistener_dst, ==, NONE_YET);
+  /* eavesdrop=true, it will receive the signal even though it's not directed
+   * to it */
+  g_assert_cmpint (f->eavesdropper_dst, ==, TO_OTHER);
+}
+
+static void
+teardown (Fixture *f,
+    gconstpointer context G_GNUC_UNUSED)
+{
+  dbus_error_free (&f->e);
+  g_clear_error (&f->ge);
+
+  if (f->sender != NULL)
+    {
+      dbus_connection_close (f->sender);
+      dbus_connection_unref (f->sender);
+      f->sender = NULL;
+    }
+
+  if (f->receiver != NULL)
+    {
+      dbus_connection_remove_filter (f->receiver,
+          signal_filter, f);
+
+      dbus_connection_close (f->receiver);
+      dbus_connection_unref (f->receiver);
+      f->receiver = NULL;
+    }
+
+  if (f->politelistener != NULL)
+    {
+      dbus_connection_remove_filter (f->politelistener,
+          signal_filter, f);
+
+      dbus_connection_close (f->politelistener);
+      dbus_connection_unref (f->politelistener);
+      f->politelistener = NULL;
+    }
+
+  if (f->eavesdropper != NULL)
+    {
+      dbus_connection_remove_filter (f->eavesdropper,
+          signal_filter, f);
+
+      dbus_connection_close (f->eavesdropper);
+      dbus_connection_unref (f->eavesdropper);
+      f->eavesdropper = NULL;
+    }
+
+#ifdef DBUS_WIN
+  TerminateProcess (f->daemon_pid, 1);
+#else
+  kill (f->daemon_pid, SIGTERM);
+#endif
+
+  g_spawn_close_pid (f->daemon_pid);
+}
+
+int
+main (int argc,
+    char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+  g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
+
+  g_test_add ("/eavedrop/match_keyword/broadcast", Fixture, NULL,
+      setup, test_eavesdrop_broadcast, teardown);
+  g_test_add ("/eavedrop/match_keyword/unicast_to_receiver", Fixture, NULL,
+      setup, test_eavesdrop_unicast_to_receiver,
+      teardown);
+  g_test_add ("/eavedrop/match_keyword/unicast_to_sender", Fixture, NULL,
+      setup, test_eavesdrop_unicast_to_sender, teardown);
+
+  return g_test_run ();
+}
diff --git a/dbus/test/dbus-daemon.c b/dbus/test/dbus-daemon.c
new file mode 100644
index 0000000..cc87153
--- /dev/null
+++ b/dbus/test/dbus-daemon.c
@@ -0,0 +1,368 @@
+/* Integration tests for the dbus-daemon
+ *
+ * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
+ * Copyright © 2010-2011 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <string.h>
+
+#ifdef DBUS_WIN
+# include <io.h>
+# include <windows.h>
+#else
+# include <signal.h>
+# include <unistd.h>
+#endif
+
+typedef struct {
+    gboolean skip;
+
+    DBusError e;
+    GError *ge;
+
+    GPid daemon_pid;
+
+    DBusConnection *left_conn;
+
+    DBusConnection *right_conn;
+    gboolean right_conn_echo;
+} Fixture;
+
+#define assert_no_error(e) _assert_no_error (e, __FILE__, __LINE__)
+static void
+_assert_no_error (const DBusError *e,
+    const char *file,
+    int line)
+{
+  if (G_UNLIKELY (dbus_error_is_set (e)))
+    g_error ("%s:%d: expected success but got error: %s: %s",
+        file, line, e->name, e->message);
+}
+
+static gchar *
+spawn_dbus_daemon (gchar *binary,
+    gchar *configuration,
+    GPid *daemon_pid)
+{
+  GError *error = NULL;
+  GString *address;
+  gint address_fd;
+  gchar *argv[] = {
+      binary,
+      configuration,
+      "--nofork",
+      "--print-address=1", /* stdout */
+      NULL
+  };
+
+  g_spawn_async_with_pipes (NULL, /* working directory */
+      argv,
+      NULL, /* envp */
+      G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+      NULL, /* child_setup */
+      NULL, /* user data */
+      daemon_pid,
+      NULL, /* child's stdin = /dev/null */
+      &address_fd,
+      NULL, /* child's stderr = our stderr */
+      &error);
+  g_assert_no_error (error);
+
+  address = g_string_new (NULL);
+
+  /* polling until the dbus-daemon writes out its address is a bit stupid,
+   * but at least it's simple, unlike dbus-launch... in principle we could
+   * use select() here, but life's too short */
+  while (1)
+    {
+      gssize bytes;
+      gchar buf[4096];
+      gchar *newline;
+
+      bytes = read (address_fd, buf, sizeof (buf));
+
+      if (bytes > 0)
+        g_string_append_len (address, buf, bytes);
+
+      newline = strchr (address->str, '\n');
+
+      if (newline != NULL)
+        {
+          g_string_truncate (address, newline - address->str);
+          break;
+        }
+
+      g_usleep (G_USEC_PER_SEC / 10);
+    }
+
+  return g_string_free (address, FALSE);
+}
+
+static DBusConnection *
+connect_to_bus (const gchar *address)
+{
+  DBusConnection *conn;
+  DBusError error = DBUS_ERROR_INIT;
+  dbus_bool_t ok;
+
+  conn = dbus_connection_open_private (address, &error);
+  assert_no_error (&error);
+  g_assert (conn != NULL);
+
+  ok = dbus_bus_register (conn, &error);
+  assert_no_error (&error);
+  g_assert (ok);
+  g_assert (dbus_bus_get_unique_name (conn) != NULL);
+
+  dbus_connection_setup_with_g_main (conn, NULL);
+  return conn;
+}
+
+static DBusHandlerResult
+echo_filter (DBusConnection *connection,
+    DBusMessage *message,
+    void *user_data)
+{
+  DBusMessage *reply;
+
+  if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+  reply = dbus_message_new_method_return (message);
+
+  if (reply == NULL)
+    g_error ("OOM");
+
+  if (!dbus_connection_send (connection, reply, NULL))
+    g_error ("OOM");
+
+  dbus_message_unref (reply);
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+typedef struct {
+    const char *bug_ref;
+    guint min_messages;
+    const char *config_file;
+} Config;
+
+static void
+setup (Fixture *f,
+    gconstpointer context)
+{
+  const Config *config = context;
+  gchar *dbus_daemon;
+  gchar *arg;
+  gchar *address;
+
+  f->ge = NULL;
+  dbus_error_init (&f->e);
+
+  if (config != NULL && config->config_file != NULL)
+    {
+      if (g_getenv ("DBUS_TEST_DATA") == NULL)
+        {
+          g_message ("SKIP: set DBUS_TEST_DATA to a directory containing %s",
+              config->config_file);
+          f->skip = TRUE;
+          return;
+        }
+
+      arg = g_strdup_printf (
+          "--config-file=%s/%s",
+          g_getenv ("DBUS_TEST_DATA"), config->config_file);
+    }
+  else if (g_getenv ("DBUS_TEST_SYSCONFDIR") != NULL)
+    {
+      arg = g_strdup_printf ("--config-file=%s/dbus-1/session.conf",
+          g_getenv ("DBUS_TEST_SYSCONFDIR"));
+    }
+  else if (g_getenv ("DBUS_TEST_DATA") != NULL)
+    {
+      arg = g_strdup_printf (
+          "--config-file=%s/valid-config-files/session.conf",
+          g_getenv ("DBUS_TEST_DATA"));
+    }
+  else
+    {
+      arg = g_strdup ("--session");
+    }
+
+  dbus_daemon = g_strdup (g_getenv ("DBUS_TEST_DAEMON"));
+
+  if (dbus_daemon == NULL)
+    dbus_daemon = g_strdup ("dbus-daemon");
+
+  address = spawn_dbus_daemon (dbus_daemon, arg, &f->daemon_pid);
+
+  g_free (dbus_daemon);
+  g_free (arg);
+
+  f->left_conn = connect_to_bus (address);
+  f->right_conn = connect_to_bus (address);
+  g_free (address);
+}
+
+static void
+add_echo_filter (Fixture *f)
+{
+  if (!dbus_connection_add_filter (f->right_conn, echo_filter, NULL, NULL))
+    g_error ("OOM");
+
+  f->right_conn_echo = TRUE;
+}
+
+static void
+pc_count (DBusPendingCall *pc,
+    void *data)
+{
+  guint *received_p = data;
+
+  (*received_p)++;
+}
+
+static void
+test_echo (Fixture *f,
+    gconstpointer context)
+{
+  const Config *config = context;
+  guint count = 2000;
+  guint sent;
+  guint received = 0;
+  double elapsed;
+
+  if (f->skip)
+    return;
+
+  if (config != NULL && config->bug_ref != NULL)
+    g_test_bug (config->bug_ref);
+
+  if (g_test_perf ())
+    count = 100000;
+
+  if (config != NULL)
+    count = MAX (config->min_messages, count);
+
+  add_echo_filter (f);
+
+  g_test_timer_start ();
+
+  for (sent = 0; sent < count; sent++)
+    {
+      DBusMessage *m = dbus_message_new_method_call (
+          dbus_bus_get_unique_name (f->right_conn), "/",
+          "com.example", "Spam");
+      DBusPendingCall *pc;
+
+      if (m == NULL)
+        g_error ("OOM");
+
+      if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
+                                            DBUS_TIMEOUT_INFINITE) ||
+          pc == NULL)
+        g_error ("OOM");
+
+      if (dbus_pending_call_get_completed (pc))
+        pc_count (pc, &received);
+      else if (!dbus_pending_call_set_notify (pc, pc_count, &received,
+            NULL))
+        g_error ("OOM");
+
+      dbus_pending_call_unref (pc);
+      dbus_message_unref (m);
+    }
+
+  while (received < count)
+    g_main_context_iteration (NULL, TRUE);
+
+  elapsed = g_test_timer_elapsed ();
+
+  g_test_maximized_result (count / elapsed, "%u messages / %f seconds",
+      count, elapsed);
+}
+
+static void
+teardown (Fixture *f,
+    gconstpointer context G_GNUC_UNUSED)
+{
+  dbus_error_free (&f->e);
+  g_clear_error (&f->ge);
+
+  if (f->left_conn != NULL)
+    {
+      dbus_connection_close (f->left_conn);
+      dbus_connection_unref (f->left_conn);
+      f->left_conn = NULL;
+    }
+
+  if (f->right_conn != NULL)
+    {
+      if (f->right_conn_echo)
+        {
+          dbus_connection_remove_filter (f->right_conn, echo_filter, NULL);
+          f->right_conn_echo = FALSE;
+        }
+
+      dbus_connection_close (f->right_conn);
+      dbus_connection_unref (f->right_conn);
+      f->right_conn = NULL;
+    }
+
+  if (f->daemon_pid != 0)
+    {
+#ifdef DBUS_WIN
+      TerminateProcess (f->daemon_pid, 1);
+#else
+      kill (f->daemon_pid, SIGTERM);
+#endif
+
+      g_spawn_close_pid (f->daemon_pid);
+      f->daemon_pid = 0;
+    }
+}
+
+static Config limited_config = {
+    "34393", 10000, "valid-config-files/incoming-limit.conf"
+};
+
+int
+main (int argc,
+    char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+  g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
+
+  g_test_add ("/echo/session", Fixture, NULL, setup, test_echo, teardown);
+  g_test_add ("/echo/limited", Fixture, &limited_config,
+      setup, test_echo, teardown);
+
+  return g_test_run ();
+}
diff --git a/dbus/test/dbus-test-runner b/dbus/test/dbus-test-runner
new file mode 100644
index 0000000..a3dc396
--- /dev/null
+++ b/dbus/test/dbus-test-runner
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+set -e
+
+dir="$1"
+shift
+
+if ! test -d "$dir"; then
+  echo "Usage: dbus-test-runner directory [executable...]"
+  exit 0
+fi
+
+passed=0
+failed=0
+skipped=0
+
+for prog in "$@"; do
+  e=0
+  "$dir/$prog" || e=$?
+  case $e in
+    (0)
+      echo "PASS: $prog"
+      passed=`expr $passed + 1`
+      ;;
+    (77)
+      echo "SKIP: $prog"
+      skipped=`expr $skipped + 1`
+      ;;
+    (*)
+      echo "FAIL: $prog"
+      failed=`expr $failed + 1`
+      ;;
+  esac
+done
+
+if test $failed = 0; then
+  # avoid saying "FAIL", to make it easy to grep results!
+  echo "PASSED $passed / SKIPPED $skipped"
+  exit 0
+else
+  echo "PASSED $passed / FAILED $failed / SKIPPED $skipped"
+  exit 1
+fi
diff --git a/dbus/test/internals/refs.c b/dbus/test/internals/refs.c
new file mode 100644
index 0000000..db43a4d
--- /dev/null
+++ b/dbus/test/internals/refs.c
@@ -0,0 +1,608 @@
+/* Regression test for thread-safe reference-counting
+ *
+ * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
+ * Copyright © 2011 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#define DBUS_COMPILATION    /* this test uses libdbus-internal */
+#include <dbus/dbus.h>
+#include <dbus/dbus-connection-internal.h>
+#include <dbus/dbus-mainloop.h>
+#include <dbus/dbus-message-internal.h>
+#include <dbus/dbus-pending-call-internal.h>
+#include <dbus/dbus-server-protected.h>
+#include "test-utils.h"
+
+static void
+assert_no_error (const DBusError *e)
+{
+  if (G_UNLIKELY (dbus_error_is_set (e)))
+    g_error ("expected success but got error: %s: %s", e->name, e->message);
+}
+
+#define N_THREADS 200
+#define N_REFS 10000
+G_STATIC_ASSERT (((unsigned) N_THREADS * (unsigned) N_REFS) < G_MAXINT32);
+
+static dbus_int32_t connection_slot = -1;
+static dbus_int32_t server_slot = -1;
+static dbus_int32_t message_slot = -1;
+static dbus_int32_t pending_call_slot = -1;
+
+typedef struct {
+  DBusError e;
+  DBusLoop *loop;
+  DBusServer *server;
+  DBusConnection *connection;
+  DBusConnection *server_connection;
+  DBusMessage *message;
+  GThread *threads[N_THREADS];
+  gboolean last_unref;
+} Fixture;
+
+typedef void *(*RefFunc) (void *);
+typedef void (*VoidFunc) (void *);
+
+typedef struct {
+  void *thing;
+  RefFunc ref;
+  VoidFunc ref_void;
+  VoidFunc unref;
+  void *mutex;
+  VoidFunc lock;
+  VoidFunc unlock;
+} Thread;
+
+/* provide backwards compatibility shim when building with a glib <= 2.30.x */
+#if !GLIB_CHECK_VERSION(2,31,0)
+#define g_thread_new(name,func,data) g_thread_create(func,data,TRUE,NULL)
+#endif
+
+static gpointer
+ref_thread (gpointer data)
+{
+  Thread *thread = data;
+  int i;
+
+  for (i = 0; i < N_REFS; i++)
+    {
+      if (thread->lock != NULL)
+        (thread->lock) (thread->mutex);
+
+      if (thread->ref != NULL)
+        {
+          gpointer ret = (thread->ref) (thread->thing);
+
+          g_assert (ret == thread->thing);
+        }
+      else
+        {
+          (thread->ref_void) (thread->thing);
+        }
+
+      if (thread->unlock != NULL)
+        (thread->unlock) (thread->mutex);
+    }
+
+  return NULL;
+}
+
+static gpointer
+cycle_thread (gpointer data)
+{
+  Thread *thread = data;
+  int i;
+
+  for (i = 0; i < N_REFS; i++)
+    {
+      if (thread->lock != NULL)
+        (thread->lock) (thread->mutex);
+
+      if (thread->ref != NULL)
+        {
+          gpointer ret = (thread->ref) (thread->thing);
+
+          g_assert (ret == thread->thing);
+        }
+      else
+        {
+          (thread->ref_void) (thread->thing);
+        }
+
+      (thread->unref) (thread->thing);
+
+      if (thread->unlock != NULL)
+        (thread->unlock) (thread->mutex);
+    }
+
+  return NULL;
+}
+
+static gpointer
+unref_thread (gpointer data)
+{
+  Thread *thread = data;
+  int i;
+
+  for (i = 0; i < N_REFS; i++)
+    {
+      if (thread->lock != NULL)
+        (thread->lock) (thread->mutex);
+
+      (thread->unref) (thread->thing);
+
+      if (thread->unlock != NULL)
+        (thread->unlock) (thread->mutex);
+    }
+
+  return NULL;
+}
+
+static void
+last_unref (void *data)
+{
+  Fixture *f = data;
+
+  g_assert (!f->last_unref);
+  f->last_unref = TRUE;
+}
+
+static void
+wait_for_all_threads (Fixture *f)
+{
+  int i;
+
+  for (i = 0; i < N_THREADS; i++)
+    g_thread_join (f->threads[i]);
+}
+
+static void
+new_conn_cb (DBusServer *server,
+    DBusConnection *server_connection,
+    void *data)
+{
+  Fixture *f = data;
+
+  g_assert (f->server_connection == NULL);
+  f->server_connection = dbus_connection_ref (server_connection);
+
+  test_connection_setup (f->loop, f->server_connection);
+}
+
+static void
+setup (Fixture *f,
+    gconstpointer data)
+{
+  if (!dbus_threads_init_default ())
+    g_error ("OOM");
+
+  f->loop = _dbus_loop_new ();
+  g_assert (f->loop != NULL);
+
+  dbus_error_init (&f->e);
+
+  f->server = dbus_server_listen ("tcp:host=127.0.0.1", &f->e);
+  assert_no_error (&f->e);
+  g_assert (f->server != NULL);
+
+  if (!dbus_connection_allocate_data_slot (&connection_slot))
+    g_error ("OOM");
+
+  if (!dbus_server_allocate_data_slot (&server_slot))
+    g_error ("OOM");
+
+  if (!dbus_message_allocate_data_slot (&message_slot))
+    g_error ("OOM");
+
+  if (!dbus_pending_call_allocate_data_slot (&pending_call_slot))
+    g_error ("OOM");
+}
+
+static void
+setup_connection (Fixture *f,
+    gconstpointer data)
+{
+  char *address;
+
+  setup (f, data);
+
+  dbus_server_set_new_connection_function (f->server,
+      new_conn_cb, f, NULL);
+
+  if (!test_server_setup (f->loop, f->server))
+    g_error ("failed to set up server");
+
+  address = dbus_server_get_address (f->server);
+  g_assert (address != NULL);
+  f->connection = dbus_connection_open_private (address, &f->e);
+  assert_no_error (&f->e);
+  g_assert (f->connection != NULL);
+  dbus_free (address);
+
+  if (!test_connection_setup (f->loop, f->connection))
+    g_error ("failed to set up connection");
+
+  while (f->server_connection == NULL)
+    _dbus_loop_iterate (f->loop, TRUE);
+
+  test_connection_shutdown (f->loop, f->connection);
+  test_server_shutdown (f->loop, f->server);
+}
+
+static void
+test_connection (Fixture *f,
+    gconstpointer data)
+{
+  Thread public_api = { f->connection,
+    (RefFunc) dbus_connection_ref,
+    NULL,
+    (VoidFunc) dbus_connection_unref,
+    NULL,
+    NULL,
+    NULL };
+  Thread internal_api = { f->connection,
+    (RefFunc) _dbus_connection_ref_unlocked,
+    NULL,
+    (VoidFunc) _dbus_connection_unref_unlocked,
+    f->connection,
+    (VoidFunc) _dbus_connection_lock,
+    (VoidFunc) _dbus_connection_unlock };
+  int i;
+
+  /* Use a slot as a pseudo-weakref */
+  if (!dbus_connection_set_data (f->connection, connection_slot, f,
+        last_unref))
+    g_error ("OOM");
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      if ((i % 2) == 0)
+        f->threads[i] = g_thread_new (NULL, ref_thread, &public_api);
+      else
+        f->threads[i] = g_thread_new (NULL, ref_thread, &internal_api);
+
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      if ((i % 2) == 0)
+        f->threads[i] = g_thread_new (NULL, cycle_thread, &public_api);
+      else
+        f->threads[i] = g_thread_new (NULL, cycle_thread, &internal_api);
+
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      if ((i % 2) == 0)
+        f->threads[i] = g_thread_new (NULL, unref_thread, &public_api);
+      else
+        f->threads[i] = g_thread_new (NULL, unref_thread, &internal_api);
+
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  /* Destroy the connection. This should be the last-unref. */
+  g_assert (!f->last_unref);
+  dbus_connection_close (f->connection);
+  dbus_connection_unref (f->connection);
+  f->connection = NULL;
+  g_assert (f->last_unref);
+}
+
+static void
+server_lock (void *server)
+{
+  SERVER_LOCK (((DBusServer *) server));
+}
+
+static void
+server_unlock (void *server)
+{
+  SERVER_UNLOCK (((DBusServer *) server));
+}
+
+static void
+test_server (Fixture *f,
+    gconstpointer data)
+{
+  Thread public_api = { f->server,
+    (RefFunc) dbus_server_ref,
+    NULL,
+    (VoidFunc) dbus_server_unref,
+    NULL,
+    NULL,
+    NULL };
+  Thread internal_api = { f->server,
+    NULL,
+    (VoidFunc) _dbus_server_ref_unlocked,
+    (VoidFunc) _dbus_server_unref_unlocked,
+    f->server,
+    server_lock,
+    server_unlock };
+  int i;
+
+  if (!dbus_server_set_data (f->server, server_slot, f, last_unref))
+    g_error ("OOM");
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      if ((i % 2) == 0)
+        f->threads[i] = g_thread_new (NULL, ref_thread, &public_api);
+      else
+        f->threads[i] = g_thread_new (NULL, ref_thread, &internal_api);
+
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      if ((i % 2) == 0)
+        f->threads[i] = g_thread_new (NULL, cycle_thread, &public_api);
+      else
+        f->threads[i] = g_thread_new (NULL, cycle_thread, &internal_api);
+
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      if ((i % 2) == 0)
+        f->threads[i] = g_thread_new (NULL, unref_thread, &public_api);
+      else
+        f->threads[i] = g_thread_new (NULL, unref_thread, &internal_api);
+
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  /* Destroy the server. This should be the last-unref. */
+  g_assert (!f->last_unref);
+  dbus_server_disconnect (f->server);
+  dbus_server_unref (f->server);
+  f->server = NULL;
+  g_assert (f->last_unref);
+}
+
+static void
+test_message (Fixture *f,
+    gconstpointer data)
+{
+  DBusMessage *message = dbus_message_new_signal ("/foo", "foo.bar.baz",
+      "Foo");
+  Thread public_api = { message,
+    (RefFunc) dbus_message_ref,
+    NULL,
+    (VoidFunc) dbus_message_unref,
+    NULL,
+    NULL,
+    NULL };
+  int i;
+
+  if (!dbus_message_set_data (message, message_slot, f, last_unref))
+    g_error ("OOM");
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      f->threads[i] = g_thread_new (NULL, ref_thread, &public_api);
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      f->threads[i] = g_thread_new (NULL, cycle_thread, &public_api);
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      f->threads[i] = g_thread_new (NULL, unref_thread, &public_api);
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  /* Destroy the server. This should be the last-unref. */
+  g_assert (!f->last_unref);
+  dbus_message_unref (message);
+  g_assert (f->last_unref);
+}
+
+static void
+test_pending_call (Fixture *f,
+    gconstpointer data)
+{
+  Thread public_api = { NULL,
+    (RefFunc) dbus_pending_call_ref,
+    NULL,
+    (VoidFunc) dbus_pending_call_unref,
+    NULL,
+    NULL,
+    NULL };
+  Thread internal_api = { NULL,
+    (RefFunc) _dbus_pending_call_ref_unlocked,
+    NULL,
+    (VoidFunc) dbus_pending_call_unref,
+    f->connection,
+    (VoidFunc) _dbus_connection_lock,
+    (VoidFunc) _dbus_connection_unlock };
+  /* This one can't be used to ref, only to cycle or unref. */
+  Thread unref_and_unlock_api = { NULL,
+    (RefFunc) _dbus_pending_call_ref_unlocked,
+    NULL,
+    (VoidFunc) _dbus_pending_call_unref_and_unlock,
+    f->connection,
+    (VoidFunc) _dbus_connection_lock,
+    NULL };
+  int i;
+  DBusPendingCall *pending_call;
+
+  _dbus_connection_lock (f->connection);
+  pending_call = _dbus_pending_call_new_unlocked (f->connection,
+      DBUS_TIMEOUT_INFINITE, NULL);
+  g_assert (pending_call != NULL);
+  _dbus_connection_unlock (f->connection);
+
+  public_api.thing = pending_call;
+  internal_api.thing = pending_call;
+  unref_and_unlock_api.thing = pending_call;
+
+  if (!dbus_pending_call_set_data (pending_call, pending_call_slot, f,
+        last_unref))
+    g_error ("OOM");
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      if ((i % 2) == 0)
+        f->threads[i] = g_thread_new (NULL, ref_thread, &public_api);
+      else
+        f->threads[i] = g_thread_new (NULL, ref_thread, &internal_api);
+
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      switch (i % 3)
+        {
+          case 0:
+            f->threads[i] = g_thread_new (NULL, cycle_thread, &public_api);
+            break;
+          case 1:
+            f->threads[i] = g_thread_new (NULL, cycle_thread, &internal_api);
+            break;
+          default:
+            f->threads[i] = g_thread_new (NULL, cycle_thread,
+                &unref_and_unlock_api);
+        }
+
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  for (i = 0; i < N_THREADS; i++)
+    {
+      switch (i % 3)
+        {
+          case 0:
+            f->threads[i] = g_thread_new (NULL, unref_thread, &public_api);
+            break;
+          case 1:
+            f->threads[i] = g_thread_new (NULL, unref_thread, &internal_api);
+            break;
+          default:
+            f->threads[i] = g_thread_new (NULL, unref_thread,
+                &unref_and_unlock_api);
+        }
+
+      g_assert (f->threads[i] != NULL);
+    }
+
+  wait_for_all_threads (f);
+
+  /* Destroy the pending call. This should be the last-unref. */
+  g_assert (!f->last_unref);
+  dbus_pending_call_unref (pending_call);
+  g_assert (f->last_unref);
+}
+
+static void
+teardown (Fixture *f,
+    gconstpointer data)
+{
+  if (f->server_connection != NULL)
+    {
+      dbus_connection_close (f->server_connection);
+      dbus_connection_unref (f->server_connection);
+    }
+
+  if (f->connection != NULL)
+    {
+      dbus_connection_close (f->connection);
+      dbus_connection_unref (f->connection);
+    }
+
+  if (f->server != NULL)
+    {
+      dbus_server_disconnect (f->server);
+      dbus_server_unref (f->server);
+    }
+
+  dbus_connection_free_data_slot (&connection_slot);
+  dbus_server_free_data_slot (&server_slot);
+  dbus_message_free_data_slot (&message_slot);
+  dbus_pending_call_free_data_slot (&pending_call_slot);
+
+  _dbus_loop_unref (f->loop);
+  dbus_error_free (&f->e);
+}
+
+int
+main (int argc,
+    char **argv)
+{
+  /* In GLib >= 2.24, < 2.31 this acts like g_thread_init() but avoids
+   * the deprecation of that function. In GLib >= 2.32 this is not
+   * necessary at all.
+   */
+  g_type_init ();
+
+  g_test_init (&argc, &argv, NULL);
+  g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
+
+  g_test_add ("/refs/connection", Fixture, NULL, setup_connection,
+      test_connection, teardown);
+  g_test_add ("/refs/message", Fixture, NULL, setup,
+      test_message, teardown);
+  g_test_add ("/refs/pending-call", Fixture, NULL, setup_connection,
+      test_pending_call, teardown);
+  g_test_add ("/refs/server", Fixture, NULL, setup,
+      test_server, teardown);
+
+  return g_test_run ();
+}
diff --git a/dbus/test/internals/syslog.c b/dbus/test/internals/syslog.c
new file mode 100644
index 0000000..4f6b7c2
--- /dev/null
+++ b/dbus/test/internals/syslog.c
@@ -0,0 +1,100 @@
+/* Manual regression test for syslog support
+ *
+ * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
+ * Copyright © 2011 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <glib.h>
+
+#define DBUS_COMPILATION    /* this test uses libdbus-internal */
+#include <dbus/dbus.h>
+#include <dbus/dbus-sysdeps.h>
+
+typedef struct {
+    int dummy;
+} Fixture;
+
+static void
+setup (Fixture *f,
+    gconstpointer data)
+{
+}
+
+/* hopefully clear enough that people don't think these messages in syslog
+ * are a bug */
+#define MESSAGE "regression test for _dbus_system_log(): "
+
+static void
+test_syslog (Fixture *f,
+    gconstpointer data)
+{
+  if (g_test_trap_fork (0, 0))
+    {
+      _dbus_init_system_log ();
+      _dbus_system_log (DBUS_SYSTEM_LOG_FATAL, MESSAGE "%d", 23);
+      /* should not be reached: exit 0 so the assertion in the main process
+       * will fail */
+      exit (0);
+    }
+
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*" MESSAGE "23\n*");
+
+  if (g_test_trap_fork (0, 0))
+    {
+      _dbus_init_system_log ();
+      _dbus_system_log (DBUS_SYSTEM_LOG_INFO, MESSAGE "%d", 42);
+      _dbus_system_log (DBUS_SYSTEM_LOG_SECURITY, MESSAGE "%d", 666);
+      exit (0);
+    }
+
+  g_test_trap_assert_passed ();
+  g_test_trap_assert_stderr ("*" MESSAGE "42\n*" MESSAGE "666\n*");
+
+  /* manual test (this is the best we can do on Windows) */
+  _dbus_init_system_log ();
+  _dbus_system_log (DBUS_SYSTEM_LOG_INFO, MESSAGE "%d", 42);
+  _dbus_system_log (DBUS_SYSTEM_LOG_SECURITY, MESSAGE "%d", 666);
+}
+
+static void
+teardown (Fixture *f,
+    gconstpointer data)
+{
+}
+
+int
+main (int argc,
+    char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+  g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
+
+  g_test_add ("/syslog", Fixture, NULL, setup, test_syslog, teardown);
+
+  return g_test_run ();
+}
diff --git a/dbus/test/loopback.c b/dbus/test/loopback.c
new file mode 100644
index 0000000..d0d69c8
--- /dev/null
+++ b/dbus/test/loopback.c
@@ -0,0 +1,211 @@
+/* Simple sanity-check for loopback through TCP and Unix sockets.
+ *
+ * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
+ * Copyright © 2010-2011 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+typedef struct {
+    DBusError e;
+
+    DBusServer *server;
+    DBusConnection *server_conn;
+    /* queue of DBusMessage */
+    GQueue server_messages;
+
+    DBusConnection *client_conn;
+} Fixture;
+
+static void
+assert_no_error (const DBusError *e)
+{
+  if (G_UNLIKELY (dbus_error_is_set (e)))
+    g_error ("expected success but got error: %s: %s", e->name, e->message);
+}
+
+static DBusHandlerResult
+server_message_cb (DBusConnection *server_conn,
+    DBusMessage *message,
+    void *data)
+{
+  Fixture *f = data;
+
+  g_assert (server_conn == f->server_conn);
+  g_queue_push_tail (&f->server_messages, dbus_message_ref (message));
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+new_conn_cb (DBusServer *server,
+    DBusConnection *server_conn,
+    void *data)
+{
+  Fixture *f = data;
+  dbus_bool_t have_mem;
+
+  g_assert (f->server_conn == NULL);
+  f->server_conn = dbus_connection_ref (server_conn);
+  dbus_connection_setup_with_g_main (server_conn, NULL);
+
+  have_mem = dbus_connection_add_filter (server_conn,
+      server_message_cb, f, NULL);
+  g_assert (have_mem);
+}
+
+static void
+setup (Fixture *f,
+    gconstpointer addr)
+{
+  dbus_error_init (&f->e);
+  g_queue_init (&f->server_messages);
+
+  f->server = dbus_server_listen (addr, &f->e);
+  assert_no_error (&f->e);
+  g_assert (f->server != NULL);
+
+  dbus_server_set_new_connection_function (f->server,
+      new_conn_cb, f, NULL);
+  dbus_server_setup_with_g_main (f->server, NULL);
+}
+
+static void
+test_connect (Fixture *f,
+    gconstpointer addr G_GNUC_UNUSED)
+{
+  g_assert (f->server_conn == NULL);
+
+  f->client_conn = dbus_connection_open_private (
+      dbus_server_get_address (f->server), &f->e);
+  assert_no_error (&f->e);
+  g_assert (f->client_conn != NULL);
+  dbus_connection_setup_with_g_main (f->client_conn, NULL);
+
+  while (f->server_conn == NULL)
+    {
+      g_print (".");
+      g_main_context_iteration (NULL, TRUE);
+    }
+}
+
+static void
+test_message (Fixture *f,
+    gconstpointer addr)
+{
+  dbus_bool_t have_mem;
+  dbus_uint32_t serial;
+  DBusMessage *outgoing, *incoming;
+
+  test_connect (f, addr);
+
+  outgoing = dbus_message_new_signal ("/com/example/Hello",
+      "com.example.Hello", "Greeting");
+  g_assert (outgoing != NULL);
+
+  have_mem = dbus_connection_send (f->client_conn, outgoing, &serial);
+  g_assert (have_mem);
+  g_assert (serial != 0);
+
+  while (g_queue_is_empty (&f->server_messages))
+    {
+      g_print (".");
+      g_main_context_iteration (NULL, TRUE);
+    }
+
+  g_assert_cmpuint (g_queue_get_length (&f->server_messages), ==, 1);
+
+  incoming = g_queue_pop_head (&f->server_messages);
+
+  g_assert (!dbus_message_contains_unix_fds (incoming));
+  g_assert_cmpstr (dbus_message_get_destination (incoming), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_error_name (incoming), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_interface (incoming), ==,
+      "com.example.Hello");
+  g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Greeting");
+  g_assert_cmpstr (dbus_message_get_sender (incoming), ==, NULL);
+  g_assert_cmpstr (dbus_message_get_signature (incoming), ==, "");
+  g_assert_cmpstr (dbus_message_get_path (incoming), ==, "/com/example/Hello");
+  g_assert_cmpuint (dbus_message_get_serial (incoming), ==, serial);
+
+  dbus_message_unref (incoming);
+
+  dbus_message_unref (outgoing);
+}
+
+static void
+teardown (Fixture *f,
+    gconstpointer addr G_GNUC_UNUSED)
+{
+  if (f->client_conn != NULL)
+    {
+      dbus_connection_close (f->client_conn);
+      dbus_connection_unref (f->client_conn);
+      f->client_conn = NULL;
+    }
+
+  if (f->server_conn != NULL)
+    {
+      dbus_connection_close (f->server_conn);
+      dbus_connection_unref (f->server_conn);
+      f->server_conn = NULL;
+    }
+
+  if (f->server != NULL)
+    {
+      dbus_server_disconnect (f->server);
+      dbus_server_unref (f->server);
+      f->server = NULL;
+    }
+}
+
+int
+main (int argc,
+    char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_test_add ("/connect/tcp", Fixture, "tcp:host=127.0.0.1", setup,
+      test_connect, teardown);
+  g_test_add ("/message/tcp", Fixture, "tcp:host=127.0.0.1", setup,
+      test_message, teardown);
+
+  g_test_add ("/connect/nonce-tcp", Fixture, "nonce-tcp:host=127.0.0.1", setup,
+      test_connect, teardown);
+  g_test_add ("/message/nonce-tcp", Fixture, "nonce-tcp:host=127.0.0.1", setup,
+      test_message, teardown);
+
+#ifdef DBUS_UNIX
+  g_test_add ("/connect/unix", Fixture, "unix:tmpdir=/tmp", setup,
+      test_connect, teardown);
+  g_test_add ("/message/unix", Fixture, "unix:tmpdir=/tmp", setup,
+      test_message, teardown);
+#endif
+
+  return g_test_run ();
+}
diff --git a/dbus/test/marshal.c b/dbus/test/marshal.c
new file mode 100644
index 0000000..e9ac7e3
--- /dev/null
+++ b/dbus/test/marshal.c
@@ -0,0 +1,257 @@
+/* Simple sanity-check for D-Bus message serialization.
+ *
+ * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
+ * Copyright © 2010-2011 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+typedef struct {
+    DBusError e;
+} Fixture;
+
+static void
+assert_no_error (const DBusError *e)
+{
+  if (G_UNLIKELY (dbus_error_is_set (e)))
+    g_error ("expected success but got error: %s: %s", e->name, e->message);
+}
+
+static void
+setup (Fixture *f,
+    gconstpointer arg G_GNUC_UNUSED)
+{
+  dbus_error_init (&f->e);
+}
+
+/* this is meant to be obviously correct, not efficient! */
+static guint32
+get_uint32 (const gchar *blob,
+    gsize offset,
+    char endian)
+{
+  if (endian == 'l')
+    {
+      return
+        blob[offset] |
+        (blob[offset + 1] << 8) |
+        (blob[offset + 2] << 16) |
+        (blob[offset + 3] << 24);
+    }
+  else if (endian == 'B')
+    {
+      return
+        (blob[offset] << 24) |
+        (blob[offset + 1] << 16) |
+        (blob[offset + 2] << 8) |
+        blob[offset + 3];
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+}
+
+#define BLOB_LENGTH (sizeof (le_blob) - 1)
+#define OFFSET_BODY_LENGTH (4)
+#define OFFSET_SERIAL (8)
+
+const gchar le_blob[] =
+    /* byte 0 */
+    /* yyyyuu fixed headers */
+    "l"                     /* little-endian */
+    "\2"                    /* reply (which is the simplest message) */
+    "\2"                    /* no auto-starting */
+    "\1"                    /* D-Bus version = 1 */
+    /* byte 4 */
+    "\4\0\0\0"              /* bytes in body = 4 */
+    /* byte 8 */
+    "\x78\x56\x34\x12"      /* serial number = 0x12345678 */
+    /* byte 12 */
+    /* a(uv) variable headers start here */
+    "\x0f\0\0\0"            /* bytes in array of variable headers = 15 */
+                            /* pad to 8-byte boundary = nothing */
+    /* byte 16 */
+    "\5"                    /* in reply to: */
+        "\1u\0"             /* variant signature = u */
+                            /* pad to 4-byte boundary = nothing */
+        "\x12\xef\xcd\xab"  /* 0xabcdef12 */
+                            /* pad to 8-byte boundary = nothing */
+    /* byte 24 */
+    "\x08"                  /* signature: */
+        "\1g\0"             /* variant signature = g */
+        "\1u\0"             /* 1 byte, u, NUL (no alignment needed) */
+        "\0"                /* pad to 8-byte boundary for body */
+    /* body; byte 32 */
+    "\xef\xbe\xad\xde"      /* 0xdeadbeef */
+    ;
+
+const gchar be_blob[] =
+    /* byte 0 */
+    /* yyyyuu fixed headers */
+    "B"                     /* big-endian */
+    "\2"                    /* reply (which is the simplest message) */
+    "\2"                    /* no auto-starting */
+    "\1"                    /* D-Bus version = 1 */
+    /* byte 4 */
+    "\0\0\0\4"              /* bytes in body = 4 */
+    /* byte 8 */
+    "\x12\x34\x56\x78"      /* serial number = 0x12345678 */
+    /* byte 12 */
+    /* a(uv) variable headers start here */
+    "\0\0\0\x0f"            /* bytes in array of variable headers = 15 */
+                            /* pad to 8-byte boundary = nothing */
+    /* byte 16 */
+    "\5"                    /* in reply to: */
+        "\1u\0"             /* variant signature = u */
+                            /* pad to 4-byte boundary = nothing */
+        "\xab\xcd\xef\x12"  /* 0xabcdef12 */
+                            /* pad to 8-byte boundary = nothing */
+    /* byte 24 */
+    "\x08"                  /* signature: */
+        "\1g\0"             /* variant signature = g */
+        "\1u\0"             /* 1 byte, u, NUL (no alignment needed) */
+        "\0"                /* pad to 8-byte boundary for body */
+    /* body; byte 32 */
+    "\xde\xad\xbe\xef"      /* 0xdeadbeef */
+    ;
+
+static void
+test_endian (Fixture *f,
+    gconstpointer arg)
+{
+  const gchar *blob = arg;
+  char *output;
+  DBusMessage *m;
+  int len;
+  dbus_uint32_t u;
+  dbus_bool_t ok;
+
+  g_assert_cmpuint ((guint) sizeof (le_blob), ==, (guint) sizeof (be_blob));
+
+  g_assert_cmpuint (get_uint32 (blob, OFFSET_BODY_LENGTH, blob[0]), ==, 4);
+  g_assert_cmpuint (get_uint32 (blob, OFFSET_SERIAL, blob[0]), ==,
+      0x12345678u);
+
+  len = dbus_message_demarshal_bytes_needed (blob, sizeof (le_blob));
+  /* everything in the string except the implicit "\0" at the end is part of
+   * the message */
+  g_assert_cmpint (len, ==, BLOB_LENGTH);
+
+  m = dbus_message_demarshal (blob, sizeof (le_blob), &f->e);
+  assert_no_error (&f->e);
+  g_assert (m != NULL);
+
+  g_assert_cmpuint (dbus_message_get_serial (m), ==, 0x12345678u);
+  g_assert_cmpuint (dbus_message_get_reply_serial (m), ==, 0xabcdef12u);
+  g_assert_cmpstr (dbus_message_get_signature (m), ==, "u");
+
+  /* Implementation detail: appending to the message results in it being
+   * byteswapped into compiler byte order, which exposed a bug in libdbus,
+   * fd.o #38120. (If that changes, this test might not exercise that
+   * particular bug but will still be valid.) */
+  u = 0xdecafbadu;
+  ok = dbus_message_append_args (m,
+      DBUS_TYPE_UINT32, &u,
+      DBUS_TYPE_INVALID);
+  g_assert (ok);
+
+  dbus_message_marshal (m, &output, &len);
+
+  g_assert (output[0] == 'l' || output[0] == 'B');
+  /* the single-byte fields are unaffected, even if the endianness was
+   * swapped */
+  g_assert_cmpint (output[1], ==, blob[1]);
+  g_assert_cmpint (output[2], ==, blob[2]);
+  g_assert_cmpint (output[3], ==, blob[3]);
+  /* the length and serial are in the new endianness, the length has expanded
+   * to 8, and the serial is correct */
+  g_assert_cmpuint (get_uint32 (output, OFFSET_BODY_LENGTH, output[0]), ==, 8);
+  g_assert_cmpuint (get_uint32 (output, OFFSET_SERIAL, output[0]), ==,
+      0x12345678u);
+  /* the second "u" in the signature replaced a padding byte, so only
+   * the length of the body changed */
+  g_assert_cmpint (len, ==, BLOB_LENGTH + 4);
+}
+
+static void
+test_needed (Fixture *f,
+    gconstpointer arg)
+{
+  const gchar *blob = arg;
+
+  /* We need at least 16 bytes to know how long the message is - that's just
+   * a fact of the D-Bus protocol. */
+  g_assert_cmpint (
+      dbus_message_demarshal_bytes_needed (blob, 0), ==, 0);
+  g_assert_cmpint (
+      dbus_message_demarshal_bytes_needed (blob, 15), ==, 0);
+  /* This is enough that we should be able to tell how much we need. */
+  g_assert_cmpint (
+      dbus_message_demarshal_bytes_needed (blob, 16), ==, BLOB_LENGTH);
+  /* The header is 32 bytes long (here), so that's another interesting
+   * boundary. */
+  g_assert_cmpint (
+      dbus_message_demarshal_bytes_needed (blob, 31), ==, BLOB_LENGTH);
+  g_assert_cmpint (
+      dbus_message_demarshal_bytes_needed (blob, 32), ==, BLOB_LENGTH);
+  g_assert_cmpint (
+      dbus_message_demarshal_bytes_needed (blob, 33), ==, BLOB_LENGTH);
+  g_assert_cmpint (
+      dbus_message_demarshal_bytes_needed (blob, BLOB_LENGTH - 1), ==,
+      BLOB_LENGTH);
+  g_assert_cmpint (
+      dbus_message_demarshal_bytes_needed (blob, BLOB_LENGTH), ==,
+      BLOB_LENGTH);
+  g_assert_cmpint (
+      dbus_message_demarshal_bytes_needed (blob, sizeof (be_blob)), ==,
+      BLOB_LENGTH);
+}
+
+static void
+teardown (Fixture *f,
+    gconstpointer arg G_GNUC_UNUSED)
+{
+  dbus_error_free (&f->e);
+}
+
+int
+main (int argc,
+    char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_test_add ("/demarshal/le", Fixture, le_blob, setup, test_endian, teardown);
+  g_test_add ("/demarshal/be", Fixture, be_blob, setup, test_endian, teardown);
+  g_test_add ("/demarshal/needed/le", Fixture, le_blob, setup, test_needed,
+      teardown);
+  g_test_add ("/demarshal/needed/be", Fixture, be_blob, setup, test_needed,
+      teardown);
+
+  return g_test_run ();
+}
diff --git a/dbus/test/name-test/Makefile.am b/dbus/test/name-test/Makefile.am
new file mode 100644
index 0000000..6aaf178
--- /dev/null
+++ b/dbus/test/name-test/Makefile.am
@@ -0,0 +1,39 @@
+# Everything in this directory is statically-linked to libdbus-internal
+AM_CPPFLAGS = \
+	-I$(top_srcdir) \
+	-DDBUS_COMPILATION \
+	-DDBUS_STATIC_BUILD \
+	$(NULL)
+
+# if assertions are enabled, improve backtraces
+AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
+
+## note that TESTS has special meaning (stuff to use in make check)
+## so if adding tests not to be run in make check, don't add them to 
+## TESTS
+if DBUS_BUILD_TESTS
+TESTS_ENVIRONMENT=DBUS_TOP_BUILDDIR=@abs_top_builddir@ DBUS_TOP_SRCDIR=@abs_top_srcdir@ PYTHON=@PYTHON@
+TESTS=run-test.sh run-test-systemserver.sh
+else
+TESTS=
+endif
+
+EXTRA_DIST=run-test.sh run-test-systemserver.sh test-wait-for-echo.py test-activation-forking.py
+
+if DBUS_BUILD_TESTS
+
+## we use noinst_PROGRAMS not check_PROGRAMS for TESTS so that we
+## build even when not doing "make check"
+noinst_PROGRAMS=test-pending-call-dispatch test-pending-call-timeout test-threads-init test-ids test-shutdown test-privserver test-privserver-client test-autolaunch
+
+test_pending_call_dispatch_LDADD=$(top_builddir)/dbus/libdbus-internal.la
+test_pending_call_timeout_LDADD=$(top_builddir)/dbus/libdbus-internal.la
+test_threads_init_LDADD=$(top_builddir)/dbus/libdbus-internal.la
+test_ids_LDADD=$(top_builddir)/dbus/libdbus-internal.la
+
+test_shutdown_LDADD=../libdbus-testutils.la
+test_privserver_LDADD=../libdbus-testutils.la
+test_privserver_client_LDADD=../libdbus-testutils.la
+test_autolaunch_LDADD=../libdbus-testutils.la
+
+endif
diff --git a/dbus/test/name-test/run-test-systemserver.sh b/dbus/test/name-test/run-test-systemserver.sh
new file mode 100755
index 0000000..afd1f04
--- /dev/null
+++ b/dbus/test/name-test/run-test-systemserver.sh
@@ -0,0 +1,51 @@
+#! /bin/sh
+die()
+{
+    if ! test -z "$DBUS_SESSION_BUS_PID" ; then
+        echo "killing message bus "$DBUS_SESSION_BUS_PID >&2
+        kill -9 $DBUS_SESSION_BUS_PID
+    fi
+    echo $SCRIPTNAME: $* >&2
+
+    exit 1
+}
+
+SCRIPTNAME=$0
+MODE=$1
+
+## so the tests can complain if you fail to use the script to launch them
+DBUS_TEST_NAME_RUN_TEST_SCRIPT=1
+export DBUS_TEST_NAME_RUN_TEST_SCRIPT
+
+SOURCE_CONFIG_FILE=$DBUS_TOP_SRCDIR/test/name-test/tmp-session-like-system.conf
+export SOURCE_CONFIG_FILE
+# Rerun ourselves with tmp session bus if we're not already
+if test -z "$DBUS_TEST_NAME_IN_SYS_RUN_TEST"; then
+  DBUS_TEST_NAME_IN_SYS_RUN_TEST=1
+  export DBUS_TEST_NAME_IN_SYS_RUN_TEST
+  exec $DBUS_TOP_SRCDIR/tools/run-with-tmp-session-bus.sh $SCRIPTNAME $MODE
+fi 
+
+if test -n "$DBUS_TEST_MONITOR"; then
+  dbus-monitor --session &
+fi
+
+echo "running test-expected-echo-fail"
+${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/tools/dbus-send --print-reply --dest=org.freedesktop.DBus.TestSuiteEchoService /org/freedesktop/TestSuite org.freedesktop.TestSuite.Echo string:hi >echo-error-output.tmp 2>&1
+if ! grep -q 'DBus.Error' echo-error-output.tmp; then
+  echo "Didn't get expected failure; output was:"
+  echo "====="
+  cat echo-error-output.tmp
+  echo "====="
+  exit 1
+fi
+
+echo "running test echo signal"
+if test "x$PYTHON" = "x:"; then
+  echo "Skipped test-echo-signal: Python interpreter not found"
+elif ! $PYTHON $DBUS_TOP_SRCDIR/test/name-test/test-wait-for-echo.py; then
+  echo "Failed test-wait-for-echo"
+  exit 1
+fi
+
+exit 0
diff --git a/dbus/test/name-test/run-test.sh b/dbus/test/name-test/run-test.sh
new file mode 100644
index 0000000..cad5937
--- /dev/null
+++ b/dbus/test/name-test/run-test.sh
@@ -0,0 +1,60 @@
+#! /bin/sh
+
+die()
+{
+    if ! test -z "$DBUS_SESSION_BUS_PID" ; then
+        echo "killing message bus "$DBUS_SESSION_BUS_PID >&2
+        kill -9 $DBUS_SESSION_BUS_PID
+    fi
+    echo $SCRIPTNAME: $* >&2
+
+    exit 1
+}
+
+
+SCRIPTNAME=$0
+MODE=$1
+
+## so the tests can complain if you fail to use the script to launch them
+DBUS_TEST_NAME_RUN_TEST_SCRIPT=1
+export DBUS_TEST_NAME_RUN_TEST_SCRIPT
+
+# Rerun ourselves with tmp session bus if we're not already
+if test -z "$DBUS_TEST_NAME_IN_RUN_TEST"; then
+  DBUS_TEST_NAME_IN_RUN_TEST=1
+  export DBUS_TEST_NAME_IN_RUN_TEST
+  exec $DBUS_TOP_SRCDIR/tools/run-with-tmp-session-bus.sh $SCRIPTNAME $MODE
+fi 
+
+if test -n "$DBUS_TEST_MONITOR"; then
+  dbus-monitor --session &
+fi
+
+echo "running test-ids"
+${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-ids || die "test-ids failed"
+
+echo "running test-pending-call-dispatch"
+${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-pending-call-dispatch || die "test-pending-call-dispatch failed"
+
+echo "running test-pending-call-timeout"
+${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-pending-call-timeout || die "test-pending-call-timeout failed"
+
+echo "running test-threads-init"
+${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-threads-init || die "test-threads-init failed"
+
+echo "running test-privserver-client"
+${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-privserver-client || die "test-privserver-client failed"
+
+echo "running test-shutdown"
+${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-shutdown || die "test-shutdown failed"
+
+echo "running test activation forking"
+if test "x$PYTHON" = "x:"; then
+  echo "Skipped test-activation-forking: Python interpreter not found"
+elif ! $PYTHON $DBUS_TOP_SRCDIR/test/name-test/test-activation-forking.py; then
+  echo "Failed test-activation-forking"
+  exit 1
+fi
+
+echo "running test-autolaunch"
+${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-autolaunch || die "test-autolaunch failed"
diff --git a/dbus/test/name-test/test-activation-forking.py b/dbus/test/name-test/test-activation-forking.py
new file mode 100644
index 0000000..0d82075
--- /dev/null
+++ b/dbus/test/name-test/test-activation-forking.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+
+import os,sys
+
+try:
+    import gobject
+    import dbus
+    import dbus.mainloop.glib
+except:
+    print "Failed import, aborting test"
+    sys.exit(0)
+
+dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+loop = gobject.MainLoop()
+
+exitcode = 0
+
+bus = dbus.SessionBus()
+bus_iface = dbus.Interface(bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus'), 'org.freedesktop.DBus')
+
+o = bus.get_object('org.freedesktop.DBus.TestSuiteForkingEchoService', '/org/freedesktop/TestSuite')
+i = dbus.Interface(o, 'org.freedesktop.TestSuite')
+
+# Start it up
+reply = i.Echo("hello world")
+print "TestSuiteForkingEchoService initial reply OK"
+
+def ignore(*args, **kwargs):
+    pass
+
+# Now monitor for exits, when that happens, start it up again.
+# The goal here is to try to hit any race conditions in activation.
+counter = 0
+def on_forking_echo_owner_changed(name, old, new):
+    global counter
+    global o
+    global i
+    if counter > 10:
+        print "Activated 10 times OK, TestSuiteForkingEchoService pass"
+        loop.quit()
+        return
+    counter += 1
+    if new == '':
+        o = bus.get_object('org.freedesktop.DBus.TestSuiteForkingEchoService', '/org/freedesktop/TestSuite')
+        i = dbus.Interface(o, 'org.freedesktop.TestSuite')
+        i.Echo("counter %r" % counter)
+        i.Exit(reply_handler=ignore, error_handler=ignore)
+
+bus_iface.connect_to_signal('NameOwnerChanged', on_forking_echo_owner_changed, arg0='org.freedesktop.DBus.TestSuiteForkingEchoService')
+
+i.Exit(reply_handler=ignore, error_handler=ignore)
+
+def check_counter():
+    if counter == 0:
+        print "Failed to get NameOwnerChanged for TestSuiteForkingEchoService"
+        sys.exit(1)
+gobject.timeout_add(15000, check_counter)
+
+loop.run()
+sys.exit(0)
diff --git a/dbus/test/name-test/test-autolaunch.c b/dbus/test/name-test/test-autolaunch.c
new file mode 100644
index 0000000..5e51989
--- /dev/null
+++ b/dbus/test/name-test/test-autolaunch.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <dbus/dbus.h>
+#include "dbus/dbus-sysdeps.h"
+
+int
+main (int argc, char *argv[])
+{
+  DBusConnection *conn = NULL;
+  DBusError error;
+
+  _dbus_setenv ("DBUS_SESSION_BUS_ADDRESS", NULL);
+
+  dbus_error_init (&error);
+
+  conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
+
+#ifdef DBUS_ENABLE_X11_AUTOLAUNCH
+  if (dbus_error_is_set (&error))
+    {
+      fprintf (stderr, "*** Failed to autolaunch session bus: %s\n",
+               error.message);
+      dbus_error_free (&error);
+      return 1;
+    }
+#else
+  /* We don't necessarily expect it to *work* without X (although it might -
+   * for instance on Mac OS it might have used launchd). Just check that the
+   * results are consistent. */
+
+  if (dbus_error_is_set (&error) && conn != NULL)
+    {
+      fprintf (stderr, "*** Autolaunched session bus, but an error was set!\n");
+      return 1;
+    }
+#endif
+
+  if (!dbus_error_is_set (&error) && conn == NULL)
+    {
+      fprintf (stderr, "*** Failed to autolaunch session bus but no error was set\n");
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/dbus/test/name-test/test-ids.c b/dbus/test/name-test/test-ids.c
new file mode 100644
index 0000000..8f63d04
--- /dev/null
+++ b/dbus/test/name-test/test-ids.c
@@ -0,0 +1,56 @@
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-connection-internal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+static void
+die (const char *message)
+{
+  fprintf (stderr, "*** test-ids: %s", message);
+  exit (1);
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  DBusError error;
+  DBusConnection *connection;
+  char *id;
+  char *server_id;
+  
+  dbus_error_init (&error);
+  connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
+  if (connection == NULL)
+    {
+      fprintf (stderr, "*** Failed to open connection to system bus: %s\n",
+               error.message);
+      dbus_error_free (&error);
+      return 1;
+    }
+
+  server_id = dbus_connection_get_server_id (connection);
+  if (server_id == NULL)
+    die ("No bus server ID retrieved\n");
+  /* printf("'%s'\n", server_id); */
+  if (strlen (server_id) != 32)
+    die ("Bus server id should have length 32\n");
+  dbus_free (server_id);
+
+  id = dbus_bus_get_id (connection, NULL);
+  if (id == NULL)
+    die ("No bus ID retrieved\n");
+  /* printf("'%s'\n", id); */
+  if (strlen (id) != 32)
+    die ("Bus ID should have length 32\n");
+  dbus_free (id);  
+  
+  _dbus_verbose ("*** Test IDs exiting\n");
+  
+  return 0;
+}
diff --git a/dbus/test/name-test/test-pending-call-dispatch.c b/dbus/test/name-test/test-pending-call-dispatch.c
new file mode 100644
index 0000000..c8b5a46
--- /dev/null
+++ b/dbus/test/name-test/test-pending-call-dispatch.c
@@ -0,0 +1,124 @@
+/**
+* Test to make sure we don't get stuck polling a dbus connection
+* which has no data on the socket.  This was an issue where
+* one pending call would read all the data off the bus
+* and the second pending call would not check to see
+* if its data had already been read before polling the connection
+* and blocking.
+**/
+
+#include <config.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-sysdeps.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void
+_run_iteration (DBusConnection *conn)
+{
+  DBusPendingCall *echo_pending;
+  DBusPendingCall *dbus_pending;
+  DBusMessage *method;
+  DBusMessage *reply;
+  char *echo = "echo";
+
+  /* send the first message */
+  method = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
+                                         "/org/freedesktop/TestSuite",
+                                         "org.freedesktop.TestSuite",
+                                         "Echo");
+
+  dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL);
+  dbus_connection_send_with_reply (conn, method, &echo_pending, -1);
+  dbus_message_unref (method);
+  
+  /* send the second message */
+  method = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                         DBUS_PATH_DBUS,
+                                         "org.freedesktop.Introspectable",
+                                         "Introspect");
+
+  dbus_connection_send_with_reply (conn, method, &dbus_pending, -1);
+  dbus_message_unref (method);
+
+  /* block on the second message (should return immediately) */
+  dbus_pending_call_block (dbus_pending);
+
+  /* block on the first message */
+  /* if it does not return immediately chances 
+     are we hit the block in poll bug */
+  dbus_pending_call_block (echo_pending);
+
+  /* check the reply only to make sure we
+     are not getting errors unrelated
+     to the block in poll bug */
+  reply = dbus_pending_call_steal_reply (echo_pending);
+
+  if (reply == NULL)
+    {
+      printf ("Failed: Reply is NULL ***\n");
+      exit (1);
+    }
+
+  if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      printf ("Failed: Reply is error: %s ***\n", dbus_message_get_error_name (reply));
+      exit (1);
+    } 
+
+  dbus_message_unref (reply);
+  dbus_pending_call_unref (dbus_pending);
+  dbus_pending_call_unref (echo_pending);
+  
+}
+
+int
+main (int argc, char *argv[])
+{
+  long start_tv_sec, start_tv_usec;
+  long end_tv_sec, end_tv_usec;
+  int i;
+  DBusMessage *method;
+  DBusConnection *conn;
+  DBusError error;
+
+  /* Time each iteration and make sure it doesn't take more than 5 seconds
+     to complete.  Outside influences may cause connections to take longer
+     but if it does and we are stuck in a poll call then we know the 
+     stuck in poll bug has come back to haunt us */
+
+  printf ("*** Testing stuck in poll\n");
+
+  dbus_error_init (&error);
+
+  conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
+
+  /* run 100 times to make sure */
+  for (i = 0; i < 100; i++)
+    {
+      long delta;
+      
+      _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
+      _run_iteration (conn);
+      _dbus_get_monotonic_time (&end_tv_sec, &end_tv_usec);
+
+      /* we just care about seconds */
+      delta = end_tv_sec - start_tv_sec;
+      printf ("Iter %i: %lis\n", i, delta);
+      if (delta >= 5)
+        {
+	  printf ("Failed: looks like we might have been be stuck in poll ***\n");
+	  exit (1);
+	}
+    }
+ 
+  method = dbus_message_new_method_call ("org.freedesktop.TestSuiteEchoService",
+                                         "/org/freedesktop/TestSuite",
+                                         "org.freedesktop.TestSuite",
+                                         "Exit");
+  dbus_connection_send (conn, method, NULL);
+  dbus_message_unref (method);
+
+  printf ("Success ***\n");
+  exit (0);
+}
diff --git a/dbus/test/name-test/test-pending-call-timeout.c b/dbus/test/name-test/test-pending-call-timeout.c
new file mode 100644
index 0000000..d051fab
--- /dev/null
+++ b/dbus/test/name-test/test-pending-call-timeout.c
@@ -0,0 +1,103 @@
+/**
+* Test to make sure that pending calls succeed when given a default,
+* specific and infinite timeout.
+**/
+
+#include <config.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-sysdeps.h>
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+
+static void
+_method_call (DBusConnection *conn,
+	      int             timeout_milliseconds)
+{
+  DBusPendingCall *pending;
+  DBusMessage *method;
+  DBusMessage *reply;
+  char *echo = "echo";
+
+  /* send the message */
+  method = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
+                                         "/org/freedesktop/TestSuite",
+                                         "org.freedesktop.TestSuite",
+                                         "DelayEcho");
+
+  dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL);
+  dbus_connection_send_with_reply (conn, method, &pending, timeout_milliseconds);
+  dbus_message_unref (method);
+  
+  /* block on the message */
+  dbus_pending_call_block (pending);
+
+  /* check the reply only to make sure we
+     are not getting errors unrelated
+     to the block in poll bug */
+  reply = dbus_pending_call_steal_reply (pending);
+
+  if (reply == NULL)
+    {
+      printf ("Failed: Reply is NULL ***\n");
+      exit (1);
+    }
+
+  if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      printf ("Failed: Reply is error: %s ***\n", dbus_message_get_error_name (reply));
+      exit (1);
+    } 
+
+  dbus_message_unref (reply);
+  dbus_pending_call_unref (pending);
+}
+
+static void
+_run_iteration (DBusConnection *conn)
+{
+  _method_call (conn, -1);
+  _method_call (conn, 10000);
+  _method_call (conn, INT_MAX);
+}
+
+int
+main (int argc, char *argv[])
+{
+  long start_tv_sec, start_tv_usec;
+  long end_tv_sec, end_tv_usec;
+  int i;
+  DBusMessage *method;
+  DBusConnection *conn;
+  DBusError error;
+
+  printf ("*** Testing pending call timeouts\n");
+
+  dbus_error_init (&error);
+
+  conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
+
+  /* run 100 times to make sure */
+  for (i = 0; i < 100; i++)
+    {
+      long delta;
+      
+      _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
+      _run_iteration (conn);
+      _dbus_get_monotonic_time (&end_tv_sec, &end_tv_usec);
+
+      /* we just care about seconds */
+      delta = end_tv_sec - start_tv_sec;
+      printf ("Iter %i: %lis\n", i, delta);
+    }
+ 
+  method = dbus_message_new_method_call ("org.freedesktop.TestSuiteEchoService",
+                                         "/org/freedesktop/TestSuite",
+                                         "org.freedesktop.TestSuite",
+                                         "Exit");
+  dbus_connection_send (conn, method, NULL);
+  dbus_message_unref (method);
+
+  printf ("Success ***\n");
+  exit (0);
+}
diff --git a/dbus/test/name-test/test-privserver-client.c b/dbus/test/name-test/test-privserver-client.c
new file mode 100644
index 0000000..e7f4896
--- /dev/null
+++ b/dbus/test/name-test/test-privserver-client.c
@@ -0,0 +1,168 @@
+#include <config.h>
+#include "../test-utils.h"
+
+static void
+die (const char *message, ...)
+{
+  va_list args;
+  va_start (args, message);
+  vfprintf (stderr, message, args);
+  va_end (args);
+  exit (1);
+}
+
+#define PRIVSERVER_SERVICE "org.freedesktop.DBus.TestSuite.PrivServer"
+#define PRIVSERVER_INTERFACE PRIVSERVER_SERVICE
+#define PRIVSERVER_DIED_RULE \
+      "type='signal',sender='" DBUS_SERVICE_DBUS "'," \
+      "interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged'," \
+      "arg0='" PRIVSERVER_SERVICE "',arg2=''"
+
+static DBusHandlerResult
+filter_session_message (DBusConnection     *connection,
+                        DBusMessage        *message,
+                        void               *user_data)
+{
+  dbus_bool_t *service_died_p = user_data;
+  const char *name, *old_owner, *new_owner;
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_DBUS,
+                              "NameOwnerChanged") &&
+      dbus_message_has_sender (message, DBUS_SERVICE_DBUS) &&
+      dbus_message_get_args (message, NULL,
+                             DBUS_TYPE_STRING, &name,
+                             DBUS_TYPE_STRING, &old_owner,
+                             DBUS_TYPE_STRING, &new_owner,
+                             DBUS_TYPE_INVALID) &&
+      strcmp (name, PRIVSERVER_SERVICE) == 0 &&
+      old_owner[0] != '\0' &&
+      new_owner[0] == '\0')
+    {
+      *service_died_p = TRUE;
+    }
+
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult 
+filter_private_message (DBusConnection     *connection,
+                        DBusMessage        *message,
+                        void               *user_data)
+{
+  dbus_bool_t *private_conn_lost_p = user_data;
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_LOCAL,
+                              "Disconnected"))
+    {
+      *private_conn_lost_p = TRUE;
+    }
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+open_shutdown_private_connection (dbus_bool_t use_guid)
+{
+  DBusError error;
+  DBusLoop *loop;
+  DBusConnection *session;
+  DBusMessage *msg;
+  DBusMessage *reply;
+  DBusConnection *privconn;
+  char *addr;
+  dbus_bool_t service_died;
+  dbus_bool_t private_conn_lost;
+
+  dbus_error_init (&error);
+  service_died = FALSE;
+  private_conn_lost = FALSE;
+
+  loop = _dbus_loop_new ();
+
+  session = dbus_bus_get (DBUS_BUS_SESSION, &error);
+  if (!session)
+    die ("couldn't access session bus\n");
+  dbus_connection_set_exit_on_disconnect (session, FALSE);
+  test_connection_setup (loop, session);
+
+  dbus_bus_add_match (session, PRIVSERVER_DIED_RULE, &error);
+  if (dbus_error_is_set (&error))
+    die ("couldn't add match rule \"%s\": %s: %s", PRIVSERVER_DIED_RULE,
+         error.name, error.message);
+
+  if (!dbus_connection_add_filter (session, filter_session_message,
+                                   &service_died, NULL))
+    die ("couldn't add filter to session bus\n");
+
+  msg = dbus_message_new_method_call (PRIVSERVER_SERVICE, "/",
+                                      PRIVSERVER_INTERFACE, "GetPrivateAddress");
+  if (!(reply = dbus_connection_send_with_reply_and_block (session, msg, -1, &error)))
+    die ("couldn't send message: %s\n", error.message);
+  dbus_message_unref (msg);
+  if (!dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &addr, DBUS_TYPE_INVALID))
+    die ("couldn't parse message replym\n");
+  printf ("got private temp address %s\n", addr);
+  addr = strdup (addr);
+  if (!use_guid)
+    {
+      char *comma = strrchr (addr, ',');
+      if (comma)
+        *comma = '\0';
+    }
+  privconn = dbus_connection_open (addr, &error);
+  free (addr);
+  if (!privconn)
+    die ("couldn't connect to server direct connection: %s\n", error.message);
+  dbus_message_unref (reply);
+
+  dbus_connection_set_exit_on_disconnect (privconn, FALSE);
+  if (!dbus_connection_add_filter (privconn, filter_private_message,
+                                   &private_conn_lost, NULL))
+    die ("couldn't add filter to private connection\n");
+  test_connection_setup (loop, privconn);
+
+  msg = dbus_message_new_method_call (PRIVSERVER_SERVICE, "/",
+                                      PRIVSERVER_INTERFACE, "Quit");
+  if (!dbus_connection_send (session, msg, NULL))
+    die ("couldn't send Quit message\n");
+  dbus_message_unref (msg);
+
+  while (!service_died || !private_conn_lost)
+    _dbus_loop_iterate (loop, TRUE);
+
+  dbus_connection_remove_filter (session, filter_session_message,
+                                 &service_died);
+  dbus_bus_remove_match (session, PRIVSERVER_DIED_RULE, NULL);
+  test_connection_shutdown (loop, session);
+  dbus_connection_unref (session);
+
+  test_connection_shutdown (loop, privconn);
+  dbus_connection_remove_filter (privconn, filter_private_message,
+                                 &private_conn_lost);
+  dbus_connection_unref (privconn);
+
+  _dbus_loop_unref (loop);
+}
+
+int
+main (int argc, char *argv[])
+{
+  open_shutdown_private_connection (TRUE);
+
+  dbus_shutdown ();
+
+  open_shutdown_private_connection (TRUE);
+
+  dbus_shutdown ();
+
+  open_shutdown_private_connection (FALSE);
+
+  dbus_shutdown ();
+
+  open_shutdown_private_connection (FALSE);
+
+  dbus_shutdown ();
+
+  return 0;
+}
diff --git a/dbus/test/name-test/test-privserver.c b/dbus/test/name-test/test-privserver.c
new file mode 100644
index 0000000..39a98b7
--- /dev/null
+++ b/dbus/test/name-test/test-privserver.c
@@ -0,0 +1,123 @@
+#include <config.h>
+#include "../test-utils.h"
+
+static void
+die (const char *message, ...)
+{
+  va_list args;
+  va_start (args, message);
+  vfprintf (stderr, message, args);
+  va_end (args);
+  exit (1);
+}
+
+typedef struct TestServiceData TestServiceData;
+
+struct TestServiceData
+{
+  DBusLoop *loop;
+  char *private_addr;
+};
+
+static void
+new_connection_callback (DBusServer     *server,
+                         DBusConnection *new_connection,
+                         void           *data)
+{
+  TestServiceData *testdata = data;
+
+  if (!test_connection_setup (testdata->loop, new_connection))
+    dbus_connection_close (new_connection);
+}
+
+static DBusHandlerResult 
+filter_session_message (DBusConnection     *connection,
+                        DBusMessage        *message,
+                        void               *user_data)
+{
+  TestServiceData *testdata = user_data;
+
+  if (dbus_message_is_method_call (message,
+                                   "org.freedesktop.DBus.TestSuite.PrivServer",
+                                   "GetPrivateAddress"))
+    {
+       DBusMessage *reply;
+       reply = dbus_message_new_method_return (message);
+       dbus_message_append_args (reply, DBUS_TYPE_STRING, 
+                                 &(testdata->private_addr), DBUS_TYPE_INVALID);
+       dbus_connection_send (connection, reply, NULL);
+       dbus_message_unref (reply);
+       return DBUS_HANDLER_RESULT_HANDLED;
+    }
+  else if (dbus_message_is_method_call (message,
+                                   "org.freedesktop.DBus.TestSuite.PrivServer",
+                                   "Quit"))
+    {
+      fprintf (stderr, "server exiting loop\n");
+      _dbus_loop_quit (testdata->loop);
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+int
+main (int argc, char *argv[])
+{
+  DBusServer *server;
+  DBusError error;
+  DBusLoop *loop;
+  DBusConnection *session;
+  TestServiceData *testdata;
+
+  dbus_error_init (&error);
+
+  loop = _dbus_loop_new ();
+
+  testdata = dbus_new (TestServiceData, 1);
+  testdata->loop = loop;
+
+  session = dbus_bus_get (DBUS_BUS_SESSION, &error);
+  if (!session)
+    die ("couldn't access session bus");
+
+  test_connection_setup (loop, session);
+
+  dbus_bus_request_name (session, "org.freedesktop.DBus.TestSuite.PrivServer", 0, &error);
+  if (dbus_error_is_set (&error))
+    die ("couldn't request name: %s", error.message);
+
+  if (!dbus_connection_add_filter (session, filter_session_message, testdata, NULL))
+    die ("couldn't add filter");
+
+#ifdef DBUS_CMAKE
+  server = dbus_server_listen (TEST_LISTEN, &error);
+#else
+  server = dbus_server_listen ("unix:tmpdir=/tmp", &error);
+#endif
+  if (!server)
+    die (error.message);
+  testdata->private_addr = dbus_server_get_address (server);
+  printf ("test server listening on %s\n", testdata->private_addr);
+
+  dbus_server_set_new_connection_function (server, new_connection_callback,
+                                           testdata, NULL);
+
+  if (!test_server_setup (loop, server))
+    die ("server setup failed");
+
+  fprintf (stderr, "server running mainloop\n");
+  _dbus_loop_run (loop);
+  fprintf (stderr, "server mainloop quit\n");
+
+  test_server_shutdown (loop, server);
+
+  test_connection_shutdown (loop, session);
+
+  dbus_connection_unref (session);
+
+  _dbus_loop_unref (loop);
+
+  dbus_free (testdata);
+
+  return 0;
+}
diff --git a/dbus/test/name-test/test-shutdown.c b/dbus/test/name-test/test-shutdown.c
new file mode 100644
index 0000000..526c1cb
--- /dev/null
+++ b/dbus/test/name-test/test-shutdown.c
@@ -0,0 +1,68 @@
+
+#include <config.h>
+#include "../test-utils.h"
+
+static DBusLoop *loop;
+
+static void
+die (const char *message)
+{
+  fprintf (stderr, "*** test-shutdown: %s", message);
+  exit (1);
+}
+
+static void
+open_destroy_shared_session_bus_connection (void)
+{
+  DBusError error;
+  DBusConnection *connection;
+  char *session_addr_no_guid;
+  char *comma;
+  
+  dbus_error_init (&error);
+
+  session_addr_no_guid = strdup (getenv ("DBUS_SESSION_BUS_ADDRESS"));
+  comma = strchr (session_addr_no_guid, ',');
+  if (comma == NULL)
+    die ("Couldn't find GUID in session bus address");
+  *comma = '\0';
+    
+  connection = dbus_connection_open (session_addr_no_guid, &error);
+  free (session_addr_no_guid);
+  if (connection == NULL)
+    die ("Failed to open connection to temp session bus\n");
+
+  loop = _dbus_loop_new ();
+  if (loop == NULL)
+    die ("No memory\n");
+  
+  if (!test_connection_setup (loop, connection))
+    die ("No memory\n");
+
+  test_connection_shutdown (loop, connection);
+ 
+  _dbus_loop_unref (loop);
+
+  dbus_connection_unref (connection); 
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  open_destroy_shared_session_bus_connection ();
+
+  dbus_shutdown ();
+
+  open_destroy_shared_session_bus_connection ();
+
+  dbus_shutdown ();
+
+  open_destroy_shared_session_bus_connection ();
+
+  dbus_shutdown ();
+
+  _dbus_verbose ("*** Test shutdown exiting\n");
+  
+  return 0;
+}
diff --git a/dbus/test/name-test/test-threads-init.c b/dbus/test/name-test/test-threads-init.c
new file mode 100644
index 0000000..5e22852
--- /dev/null
+++ b/dbus/test/name-test/test-threads-init.c
@@ -0,0 +1,180 @@
+/**
+ * Test to make sure late thread initialization works
+ */
+
+#include <config.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-sysdeps.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-connection-internal.h>
+
+static void
+_run_iteration (DBusConnection *conn)
+{
+  DBusPendingCall *echo_pending;
+  DBusPendingCall *dbus_pending;
+  DBusMessage *method;
+  DBusMessage *reply;
+  char *echo = "echo";
+
+  /* send the first message */
+  method = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
+                                         "/org/freedesktop/TestSuite",
+                                         "org.freedesktop.TestSuite",
+                                         "Echo");
+
+  dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL);
+  dbus_connection_send_with_reply (conn, method, &echo_pending, -1);
+  dbus_message_unref (method);
+  
+  /* send the second message */
+  method = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                         DBUS_PATH_DBUS,
+                                         "org.freedesktop.Introspectable",
+                                         "Introspect");
+
+  dbus_connection_send_with_reply (conn, method, &dbus_pending, -1);
+  dbus_message_unref (method);
+
+  /* block on the second message (should return immediately) */
+  dbus_pending_call_block (dbus_pending);
+
+  /* block on the first message */
+  /* if it does not return immediately chances 
+     are we hit the block in poll bug */
+  dbus_pending_call_block (echo_pending);
+
+  /* check the reply only to make sure we
+     are not getting errors unrelated
+     to the block in poll bug */
+  reply = dbus_pending_call_steal_reply (echo_pending);
+
+  if (reply == NULL)
+    {
+      printf ("Failed: Reply is NULL ***\n");
+      exit (1);
+    }
+
+  if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      printf ("Failed: Reply is error: %s ***\n", dbus_message_get_error_name (reply));
+      exit (1);
+    } 
+
+  dbus_message_unref (reply);
+  dbus_pending_call_unref (dbus_pending);
+  dbus_pending_call_unref (echo_pending);
+  
+}
+static void
+check_mutex_lock (DBusMutex *mutex1, 
+                  DBusMutex *mutex2, 
+                  dbus_bool_t is_same)
+{
+  _dbus_assert (mutex1 != NULL);
+  _dbus_assert (mutex2 != NULL);
+  
+  if (is_same)
+    {
+      _dbus_assert (mutex1 == mutex2);
+    }
+  else
+    {
+      _dbus_assert (mutex1 != mutex2);
+    }
+}
+
+static void
+check_condvar_lock (DBusCondVar *condvar1,  
+                    DBusCondVar *condvar2,   
+                    dbus_bool_t is_same)
+{
+  _dbus_assert (condvar1 != NULL);
+  _dbus_assert (condvar2 != NULL);
+
+  if (is_same)
+    {
+      _dbus_assert (condvar1 == condvar2);
+    }
+  else
+    {
+      _dbus_assert (condvar1 != condvar2);
+    }
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  DBusMessage *method;
+  DBusConnection *conn;
+  DBusError error;
+  DBusMutex *mutex1, *dispatch_mutex1, *io_path_mutex1;
+  DBusCondVar *dispatch_cond1, *io_path_cond1;
+  DBusMutex *mutex2, *dispatch_mutex2, *io_path_mutex2;
+  DBusCondVar *dispatch_cond2, *io_path_cond2;
+
+  printf ("*** Testing late thread init\n");
+
+  dbus_error_init (&error);
+
+  conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
+
+  _dbus_connection_test_get_locks (conn, &mutex1, 
+                                         &dispatch_mutex1, 
+                                         &io_path_mutex1,
+                                         &dispatch_cond1,
+                                         &io_path_cond1);
+  _run_iteration (conn);
+  _dbus_connection_test_get_locks (conn, &mutex2,
+                                         &dispatch_mutex2,
+                                         &io_path_mutex2,
+                                         &dispatch_cond2,
+                                         &io_path_cond2);
+
+  check_mutex_lock (mutex1, mutex2, TRUE);
+  check_mutex_lock (dispatch_mutex1, dispatch_mutex2, TRUE);
+  check_mutex_lock (io_path_mutex1, io_path_mutex2, TRUE);
+  check_condvar_lock (dispatch_cond1, dispatch_cond2, TRUE);
+  check_condvar_lock (io_path_cond1, io_path_cond2, TRUE);
+
+  dbus_threads_init_default ();
+
+  _dbus_connection_test_get_locks (conn, &mutex1,
+                                         &dispatch_mutex1,
+                                         &io_path_mutex1,
+                                         &dispatch_cond1,
+                                         &io_path_cond1);
+
+  check_mutex_lock (mutex1, mutex2, FALSE);
+  check_mutex_lock (dispatch_mutex1, dispatch_mutex2, FALSE);
+  check_mutex_lock (io_path_mutex1, io_path_mutex2, FALSE);
+  check_condvar_lock (dispatch_cond1, dispatch_cond2, FALSE);
+  check_condvar_lock (io_path_cond1, io_path_cond2, FALSE);
+
+  _run_iteration (conn);
+  _dbus_connection_test_get_locks (conn, &mutex2,
+                                         &dispatch_mutex2,
+                                         &io_path_mutex2,
+                                         &dispatch_cond2,
+                                         &io_path_cond2);
+
+  check_mutex_lock (mutex1, mutex2, TRUE);
+  check_mutex_lock (dispatch_mutex1, dispatch_mutex2, TRUE);
+  check_mutex_lock (io_path_mutex1, io_path_mutex2, TRUE);
+  check_condvar_lock (dispatch_cond1, dispatch_cond2, TRUE);
+  check_condvar_lock (io_path_cond1, io_path_cond2, TRUE);
+
+  method = dbus_message_new_method_call ("org.freedesktop.TestSuiteEchoService",
+                                         "/org/freedesktop/TestSuite",
+                                         "org.freedesktop.TestSuite",
+                                         "Exit");
+  dbus_connection_send (conn, method, NULL);
+  dbus_message_unref (method);
+
+  printf ("Success ***\n");
+  exit (0);
+}
diff --git a/dbus/test/name-test/test-wait-for-echo.py b/dbus/test/name-test/test-wait-for-echo.py
new file mode 100755
index 0000000..bd09e45
--- /dev/null
+++ b/dbus/test/name-test/test-wait-for-echo.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+
+import os,sys
+
+try:
+    import gobject
+    import dbus
+    import dbus.mainloop.glib
+except:
+    print "Failed import, aborting test"
+    sys.exit(0)
+
+dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+loop = gobject.MainLoop()
+
+exitcode = 0
+
+def handle_noreceipt():
+    print "Failed to get signal"
+    global exitcode
+    exitcode = 1
+    loop.quit()
+
+gobject.timeout_add(7000, handle_noreceipt)
+
+bus = dbus.SessionBus()
+
+def sighandler(*args, **kwargs):
+    print "got signal"
+    loop.quit()   
+
+bus.add_signal_receiver(sighandler, dbus_interface='org.freedesktop.TestSuite', signal_name='Foo')
+
+o = bus.get_object('org.freedesktop.DBus.TestSuiteEchoService', '/org/freedesktop/TestSuite')
+i = dbus.Interface(o, 'org.freedesktop.TestSuite')
+def nullhandler(*args, **kwargs):
+    pass
+i.EmitFoo(reply_handler=nullhandler, error_handler=nullhandler)
+
+loop.run()
+sys.exit(exitcode)
diff --git a/dbus/test/name-test/tmp-session-like-system.conf b/dbus/test/name-test/tmp-session-like-system.conf
new file mode 100644
index 0000000..29ab115
--- /dev/null
+++ b/dbus/test/name-test/tmp-session-like-system.conf
@@ -0,0 +1,91 @@
+<!-- This configuration file controls the per-user-login-session message bus.
+     Add a session-local.conf and edit that rather than changing this 
+     file directly. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <!-- Our well-known bus type, don't change this -->
+  <type>session</type>
+
+  <!-- If we fork, keep the user's original umask to avoid affecting
+       the behavior of child processes. -->
+  <keep_umask/>
+
+  <syslog/>
+
+  <listen>unix:tmpdir=/tmp</listen>
+
+  <standard_session_servicedirs />
+
+  <!-- intended to match system bus -->
+  <policy context="default">
+    <!-- All users can connect to system bus -->
+    <allow user="*"/>
+
+    <!-- Holes must be punched in service configuration files for
+         name ownership and sending method calls -->
+    <deny own="*"/>
+    <deny send_type="method_call"/>
+
+    <!-- Signals and reply messages (method returns, errors) are allowed
+         by default -->
+    <allow send_type="signal"/>
+    <allow send_requested_reply="true" send_type="method_return"/>
+    <allow send_requested_reply="true" send_type="error"/>
+
+    <!-- All messages may be received by default -->
+    <allow receive_type="method_call"/>
+    <allow receive_type="method_return"/>
+    <allow receive_type="error"/>
+    <allow receive_type="signal"/>
+
+    <!-- Allow anyone to talk to the message bus -->
+    <allow send_destination="org.freedesktop.DBus"/>
+    <!-- But disallow some specific bus services -->
+    <deny send_destination="org.freedesktop.DBus"
+          send_interface="org.freedesktop.DBus"
+          send_member="UpdateActivationEnvironment"/>
+
+    <!-- Specific to the test suite -->
+    <allow own="org.freedesktop.DBus.TestSuiteEchoService"/>
+    <allow send_destination="org.freedesktop.DBus.TestSuiteEchoService"
+           send_interface="org.freedesktop.DBus.Introspectable"/>
+    <allow send_destination="org.freedesktop.DBus.TestSuiteEchoService"
+           send_interface="org.freedesktop.TestSuite"
+           send_member="EmitFoo"/>
+  </policy>
+
+  <policy context="default">
+     <allow own="org.freedesktop.DBus.TestSuiteEchoService"/>
+     <allow send_destination="org.freedesktop.DBus.TestSuiteEchoService"
+            send_interface="org.freedesktop.DBus.Introspectable"/>
+     <allow send_destination="org.freedesktop.DBus.TestSuiteEchoService"
+            send_interface="org.freedesktop.TestSuite"
+            send_member="EmitFoo"/>
+  </policy>
+
+  <!-- For the session bus, override the default relatively-low limits 
+       with essentially infinite limits, since the bus is just running 
+       as the user anyway, using up bus resources is not something we need 
+       to worry about. In some cases, we do set the limits lower than 
+       "all available memory" if exceeding the limit is almost certainly a bug, 
+       having the bus enforce a limit is nicer than a huge memory leak. But the 
+       intent is that these limits should never be hit. -->
+
+  <!-- the memory limits are 1G instead of say 4G because they can't exceed 32-bit signed int max -->
+  <limit name="max_incoming_bytes">1000000000</limit>
+  <limit name="max_outgoing_bytes">1000000000</limit>
+  <limit name="max_message_size">1000000000</limit>
+  <limit name="service_start_timeout">120000</limit>  
+  <limit name="auth_timeout">240000</limit>
+  <limit name="max_completed_connections">100000</limit>  
+  <limit name="max_incomplete_connections">10000</limit>
+  <limit name="max_connections_per_user">100000</limit>
+  <limit name="max_pending_service_starts">10000</limit>
+  <limit name="max_names_per_connection">50000</limit>
+  <limit name="max_match_rules_per_connection">50000</limit>
+  <limit name="max_replies_per_connection">50000</limit>
+  <limit name="reply_timeout">300000</limit>
+
+</busconfig>
diff --git a/dbus/test/relay.c b/dbus/test/relay.c
new file mode 100644
index 0000000..f4129d0
--- /dev/null
+++ b/dbus/test/relay.c
@@ -0,0 +1,322 @@
+/* Regression test for passing unmodified messages between connections
+ *
+ * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
+ * Copyright © 2010-2011 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+/* This is basically a miniature dbus-daemon. We relay messages from the client
+ * on the left to the client on the right.
+ *
+ * left      socket     left      dispatch     right    socket     right
+ * client ===========>  server --------------> server ===========> client
+ * conn                 conn                   conn                conn
+ *
+ * In the real dbus-daemon, the client connections would be out-of-process,
+ * but here we're cheating and doing everything in-process.
+ */
+
+typedef struct {
+    DBusError e;
+
+    DBusServer *server;
+
+    DBusConnection *left_client_conn;
+    DBusConnection *left_server_conn;
+
+    DBusConnection *right_server_conn;
+    DBusConnection *right_client_conn;
+    /* queue of DBusMessage received by right_client_conn */
+    GQueue messages;
+} Fixture;
+
+static void
+assert_no_error (const DBusError *e)
+{
+  if (G_UNLIKELY (dbus_error_is_set (e)))
+    g_error ("expected success but got error: %s: %s", e->name, e->message);
+}
+
+static DBusHandlerResult
+server_message_cb (DBusConnection *server_conn,
+    DBusMessage *message,
+    void *data)
+{
+  Fixture *f = data;
+
+  g_assert (server_conn == f->left_server_conn);
+  g_assert (f->right_server_conn != NULL);
+
+  dbus_connection_send (f->right_server_conn, message, NULL);
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+right_client_message_cb (DBusConnection *client_conn,
+    DBusMessage *message,
+    void *data)
+{
+  Fixture *f = data;
+
+  g_assert (client_conn == f->right_client_conn);
+  g_queue_push_tail (&f->messages, dbus_message_ref (message));
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+new_conn_cb (DBusServer *server,
+    DBusConnection *server_conn,
+    void *data)
+{
+  Fixture *f = data;
+  dbus_bool_t have_mem;
+
+  if (f->left_server_conn == NULL)
+    {
+      f->left_server_conn = dbus_connection_ref (server_conn);
+
+      have_mem = dbus_connection_add_filter (server_conn,
+          server_message_cb, f, NULL);
+      g_assert (have_mem);
+    }
+  else
+    {
+      g_assert (f->right_server_conn == NULL);
+      f->right_server_conn = dbus_connection_ref (server_conn);
+    }
+
+  dbus_connection_setup_with_g_main (server_conn, NULL);
+}
+
+static void
+setup (Fixture *f,
+    gconstpointer data G_GNUC_UNUSED)
+{
+  dbus_error_init (&f->e);
+  g_queue_init (&f->messages);
+
+  f->server = dbus_server_listen ("tcp:host=127.0.0.1", &f->e);
+  assert_no_error (&f->e);
+  g_assert (f->server != NULL);
+
+  dbus_server_set_new_connection_function (f->server,
+      new_conn_cb, f, NULL);
+  dbus_server_setup_with_g_main (f->server, NULL);
+}
+
+static void
+test_connect (Fixture *f,
+    gconstpointer data G_GNUC_UNUSED)
+{
+  dbus_bool_t have_mem;
+  char *address;
+
+  g_assert (f->left_server_conn == NULL);
+  g_assert (f->right_server_conn == NULL);
+
+  address = dbus_server_get_address (f->server);
+  g_assert (address != NULL);
+
+  f->left_client_conn = dbus_connection_open_private (address, &f->e);
+  assert_no_error (&f->e);
+  g_assert (f->left_client_conn != NULL);
+  dbus_connection_setup_with_g_main (f->left_client_conn, NULL);
+
+  while (f->left_server_conn == NULL)
+    {
+      g_print (".");
+      g_main_context_iteration (NULL, TRUE);
+    }
+
+  f->right_client_conn = dbus_connection_open_private (address, &f->e);
+  assert_no_error (&f->e);
+  g_assert (f->right_client_conn != NULL);
+  dbus_connection_setup_with_g_main (f->right_client_conn, NULL);
+
+  dbus_free (address);
+
+  while (f->right_server_conn == NULL)
+    {
+      g_print (".");
+      g_main_context_iteration (NULL, TRUE);
+    }
+
+  have_mem = dbus_connection_add_filter (f->right_client_conn,
+      right_client_message_cb, f, NULL);
+  g_assert (have_mem);
+}
+
+static dbus_uint32_t
+send_one (Fixture *f,
+    const char *member)
+{
+  dbus_bool_t have_mem;
+  dbus_uint32_t serial;
+  DBusMessage *outgoing;
+
+  outgoing = dbus_message_new_signal ("/com/example/Hello",
+      "com.example.Hello", member);
+  g_assert (outgoing != NULL);
+
+  have_mem = dbus_connection_send (f->left_client_conn, outgoing, &serial);
+  g_assert (have_mem);
+  g_assert (serial != 0);
+
+  dbus_message_unref (outgoing);
+  return serial;
+}
+
+static void
+test_relay (Fixture *f,
+    gconstpointer data)
+{
+  DBusMessage *incoming;
+
+  test_connect (f, data);
+
+  send_one (f, "First");
+  send_one (f, "Second");
+
+  while (g_queue_get_length (&f->messages) < 2)
+    {
+      g_print (".");
+      g_main_context_iteration (NULL, TRUE);
+    }
+
+  g_assert_cmpuint (g_queue_get_length (&f->messages), ==, 2);
+
+  incoming = g_queue_pop_head (&f->messages);
+  g_assert_cmpstr (dbus_message_get_member (incoming), ==, "First");
+  dbus_message_unref (incoming);
+
+  incoming = g_queue_pop_head (&f->messages);
+  g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Second");
+  dbus_message_unref (incoming);
+}
+
+/* An arbitrary number of messages */
+#define MANY 8192
+
+static void
+test_limit (Fixture *f,
+    gconstpointer data)
+{
+  DBusMessage *incoming;
+  guint i;
+
+  test_connect (f, data);
+
+  /* This was an attempt to reproduce fd.o #34393. It didn't work. */
+  g_test_bug ("34393");
+  dbus_connection_set_max_received_size (f->left_server_conn, 1);
+  g_main_context_iteration (NULL, TRUE);
+
+  for (i = 0; i < MANY; i++)
+    {
+      gchar *buf = g_strdup_printf ("Message%u", i);
+
+      send_one (f, buf);
+      g_free (buf);
+    }
+
+  i = 0;
+
+  while (i < MANY)
+    {
+      while (g_queue_is_empty (&f->messages))
+        {
+          g_main_context_iteration (NULL, TRUE);
+        }
+
+      while ((incoming = g_queue_pop_head (&f->messages)) != NULL)
+        {
+          i++;
+          dbus_message_unref (incoming);
+        }
+    }
+}
+
+static void
+teardown (Fixture *f,
+    gconstpointer data G_GNUC_UNUSED)
+{
+  if (f->left_client_conn != NULL)
+    {
+      dbus_connection_close (f->left_client_conn);
+      dbus_connection_unref (f->left_client_conn);
+      f->left_client_conn = NULL;
+    }
+
+  if (f->right_client_conn != NULL)
+    {
+      dbus_connection_close (f->right_client_conn);
+      dbus_connection_unref (f->right_client_conn);
+      f->right_client_conn = NULL;
+    }
+
+  if (f->left_server_conn != NULL)
+    {
+      dbus_connection_close (f->left_server_conn);
+      dbus_connection_unref (f->left_server_conn);
+      f->left_server_conn = NULL;
+    }
+
+  if (f->right_server_conn != NULL)
+    {
+      dbus_connection_close (f->right_server_conn);
+      dbus_connection_unref (f->right_server_conn);
+      f->right_server_conn = NULL;
+    }
+
+  if (f->server != NULL)
+    {
+      dbus_server_disconnect (f->server);
+      dbus_server_unref (f->server);
+      f->server = NULL;
+    }
+}
+
+int
+main (int argc,
+    char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+  g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
+
+  g_test_add ("/connect", Fixture, NULL, setup,
+      test_connect, teardown);
+  g_test_add ("/relay", Fixture, NULL, setup,
+      test_relay, teardown);
+  g_test_add ("/limit", Fixture, NULL, setup,
+      test_limit, teardown);
+
+  return g_test_run ();
+}
diff --git a/dbus/test/shell-test.c b/dbus/test/shell-test.c
new file mode 100644
index 0000000..b479a9c
--- /dev/null
+++ b/dbus/test/shell-test.c
@@ -0,0 +1,109 @@
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#define DBUS_COMPILATION
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-list.h>
+#include <dbus/dbus-memory.h>
+#include <dbus/dbus-shell.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-sysdeps.h>
+
+static dbus_bool_t
+test_command_line (const char *arg1, ...)
+{
+  int i, original_argc, shell_argc;
+  char **shell_argv;
+  char **original_argv;
+  char *command_line, *tmp;
+  DBusString str;
+  DBusList *list = NULL, *node;
+  va_list var_args;
+  DBusError error;
+
+  va_start (var_args, arg1);
+  _dbus_list_append (&list, (char *)arg1);
+  do
+    {
+      tmp = va_arg (var_args, char *);
+      if (!tmp)
+        break;
+      _dbus_list_append (&list, tmp);
+    } while (tmp);
+  va_end (var_args);
+
+  original_argc = _dbus_list_get_length (&list);
+  original_argv = dbus_new (char *, original_argc);
+  _dbus_string_init (&str);
+  for (i = 0, node = _dbus_list_get_first_link (&list); i < original_argc && node;
+       i++, node = _dbus_list_get_next_link (&list, node))
+    {
+      original_argv[i] = node->data;
+      if (i > 0)
+        _dbus_string_append_byte (&str, ' ');
+      _dbus_string_append (&str, original_argv[i]);
+    }
+  
+  _dbus_list_clear (&list);
+  command_line = _dbus_string_get_data (&str);
+  printf ("\n\nTesting command line '%s'\n", command_line);
+
+  dbus_error_init (&error);
+  if (!_dbus_shell_parse_argv (command_line, &shell_argc, &shell_argv, &error))
+    {
+      fprintf (stderr, "Error parsing command line: %s\n", error.message ? error.message : "");
+      return FALSE;
+    }
+  else
+    {
+      if (shell_argc != original_argc)
+        {
+          printf ("Number of arguments returned (%d) don't match original (%d)\n",
+                  shell_argc, original_argc);
+          return FALSE;
+        } 
+      printf ("Number of arguments: %d\n", shell_argc);
+      for (i = 0; i < shell_argc; i++)
+        {
+          char *unquoted;
+          
+          unquoted = _dbus_shell_unquote (original_argv[i]);
+          if (strcmp (unquoted ? unquoted : "",
+                      shell_argv[i] ? shell_argv[i] : ""))
+            {
+              printf ("Position %d, returned argument (%s) does not match original (%s)\n",
+                      i, shell_argv[i], unquoted);
+              dbus_free (unquoted);
+              return FALSE;
+            }
+          dbus_free (unquoted);
+          if (shell_argv[i])
+            printf ("Argument %d = %s\n", i, shell_argv[i]);
+        }
+      
+      dbus_free_string_array (shell_argv);
+    }
+  
+  _dbus_string_free (&str);
+  
+  return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+  if (!test_command_line ("command", "-s", "--force-shutdown", "\"a string\"", "123", NULL)
+      || !test_command_line ("command", "-s", NULL)
+      || !test_command_line ("/opt/gnome/bin/service-start", NULL)
+      || !test_command_line ("grep", "-l", "-r", "-i", "'whatever'", "files*.c", NULL)
+      || !test_command_line ("/home/boston/johnp/devel-local/dbus/test/test-segfault", NULL)
+      || !test_command_line ("ls", "-l", "-a", "--colors", _dbus_get_tmpdir(), NULL)
+      || !test_command_line ("rsync-to-server", NULL)
+      || !test_command_line ("test-segfault", "--no-segfault", NULL)
+      || !test_command_line ("evolution", "mailto:pepe@cuco.com", NULL)
+      || !test_command_line ("run", "\"a \n multiline\"", NULL)
+      || test_command_line ("ls", "\"a wrong string'", NULL) /* invalid command line */ )
+    return -1;
+  
+  return 0;
+}
diff --git a/dbus/test/spawn-test.c b/dbus/test/spawn-test.c
new file mode 100644
index 0000000..f1a5505
--- /dev/null
+++ b/dbus/test/spawn-test.c
@@ -0,0 +1,44 @@
+#include <config.h>
+#include <dbus/dbus.h>
+
+#define DBUS_COMPILATION /* cheat and use dbus-sysdeps */
+#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-spawn.h>
+#undef DBUS_COMPILATION
+#include <stdio.h>
+
+static void
+setup_func (void *data)
+{
+  printf ("entering setup func.\n");
+}
+
+int
+main (int argc, char **argv)
+{
+  char **argv_copy;
+  int i;
+  DBusError error;
+  
+  if (argc < 2)
+    {
+      fprintf (stderr, "You need to specify a program to launch.\n");
+
+      return -1;
+    }
+
+  argv_copy = dbus_new (char *, argc);
+  for (i = 0; i < argc - 1; i++)
+    argv_copy [i] = argv[i + 1];
+  argv_copy[argc - 1] = NULL;
+  
+  if (!_dbus_spawn_async_with_babysitter (NULL, argv_copy, NULL, setup_func, NULL, &error))
+    {
+      fprintf (stderr, "Could not launch application: \"%s\"\n",
+	       error.message);
+    }
+
+  dbus_free(argv_copy);
+ 
+  return 0;
+}
diff --git a/dbus/test/syntax.c b/dbus/test/syntax.c
new file mode 100644
index 0000000..88db963
--- /dev/null
+++ b/dbus/test/syntax.c
@@ -0,0 +1,289 @@
+/* Simple sanity-check for D-Bus syntax validation.
+ *
+ * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
+ * Copyright © 2010-2011 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+
+typedef struct {
+    DBusError e;
+} Fixture;
+
+typedef struct {
+    dbus_bool_t (*function) (const char *, DBusError *);
+    const char * const * valid;
+    const char * const * invalid;
+} Test;
+
+Test paths, interfaces, members, errors, bus_names, signatures,
+     single_signatures, strings;
+
+const char * const valid_paths[] = {
+    "/",
+    "/a",
+    "/_",
+    "/a/b/c",
+    "/com/example/123",
+    "/org/freedesktop/DBus",
+    "/org/freedesktop/Telepathy/AccountManager",
+    NULL
+};
+
+const char * const invalid_paths[] = {
+    "",
+    ".",
+    "//",
+    "/a/",
+    "/-",
+    "/com//example/MyApp",
+    "/$",
+    "/\xa9",      /* © in latin-1 */
+    "/\xc2\xa9",  /* © in UTF-8 */
+    NULL
+};
+
+const char * const valid_interfaces[] = {
+    "com.example",
+    "com.example.a0",
+    "org.freedesktop.DBus",
+    NULL
+};
+
+const char * const invalid_interfaces[] = {
+   "",
+    "com",
+    "com.example.",
+    "com.example..a0",
+    "com.example.0a",
+    "com.example.a$",
+    "com.example.a\xa9",
+    "com.example.a\xc2\xa9",
+    NULL
+};
+
+const char * const valid_members[] = {
+    "_",
+    "a",
+    "a0",
+    "GetAll",
+    "BadgerMushroomSnake",
+    NULL
+};
+
+const char * const invalid_members[] = {
+    "",
+    "-",
+    "a-",
+    "0",
+    "0_",
+    "Badger.Mushroom",
+    "a$",
+    "a\xa9",
+    "a\xc2\xa9",
+    NULL
+};
+
+const char * const valid_errors[] = {
+    "com.example",
+    "com.example.a0",
+    "org.freedesktop.DBus.NameHasNoOwner",
+    NULL
+};
+
+const char * const invalid_errors[] = {
+   "",
+    "com",
+    "com.example.",
+    "com.example..a0",
+    "com.example.0a",
+    "com.example.a$",
+    "com.example.a\xa9",
+    "com.example.a\xc2\xa9",
+    NULL
+};
+
+const char * const valid_bus_names[] = {
+    "com.example",
+    "com.example.a0",
+    "com.example._",
+    ":1.42",
+    ":1.2.3.4.5",
+    ":com.example",
+    "org.freedesktop.DBus",
+    NULL
+};
+
+const char * const invalid_bus_names[] = {
+   "",
+    "com",
+    "com.example.",
+    "com.example..a0",
+    "com.example.0a",
+    "com.example.a:b",
+    "com.example.a\xa9",
+    "com.example.a\xc2\xa9",
+    NULL
+};
+
+const char * const valid_signatures[] = {
+    "",
+    "a{sv}",
+    NULL
+};
+
+const char * const invalid_signatures[] = {
+    "a",
+    "a{s_}",
+    NULL
+};
+
+const char * const valid_single_signatures[] = {
+    "s",
+    "a{sv}",
+    NULL
+};
+
+const char * const invalid_single_signatures[] = {
+    "",
+    "a",
+    "sv",
+    "a{sv}as",
+    NULL
+};
+
+const char * const valid_strings[] = {
+    "",
+    "\xc2\xa9",
+    NULL
+};
+
+const char * const invalid_strings[] = {
+    "\xa9",
+    NULL
+};
+
+static void
+setup (Fixture *f,
+    gconstpointer arg G_GNUC_UNUSED)
+{
+  dbus_error_init (&f->e);
+
+#define FILL_TEST(name, func) \
+  do { \
+    (name).function = (func); \
+    (name).valid = valid_ ## name; \
+    (name).invalid = invalid_ ## name; \
+  } while (0)
+
+  FILL_TEST (paths, dbus_validate_path);
+  FILL_TEST (interfaces, dbus_validate_interface);
+  FILL_TEST (members, dbus_validate_member);
+  FILL_TEST (errors, dbus_validate_error_name);
+  FILL_TEST (bus_names, dbus_validate_bus_name);
+  FILL_TEST (signatures, dbus_signature_validate);
+  FILL_TEST (single_signatures, dbus_signature_validate_single);
+  FILL_TEST (strings, dbus_validate_utf8);
+}
+
+static void
+test_syntax (Fixture *f,
+    gconstpointer arg)
+{
+  const Test *test = arg;
+  int i;
+
+  g_assert (test != NULL);
+  g_assert (test->function != NULL);
+  g_assert (test->valid != NULL);
+  g_assert (test->invalid != NULL);
+
+  for (i = 0; test->valid[i] != NULL; i++)
+    {
+      dbus_bool_t ok = test->function (test->valid[i], &f->e);
+
+      if (dbus_error_is_set (&f->e))
+        g_error ("%s was considered invalid: %s: %s", test->valid[i],
+            f->e.name, f->e.message);
+
+      if (!ok)
+        g_error ("%s was considered invalid without an error", test->valid[i]);
+    }
+
+  for (i = 0; test->invalid[i] != NULL; i++)
+    {
+      dbus_bool_t ok = test->function (test->invalid[i], &f->e);
+
+      if (ok)
+        g_error ("%s should have been considered invalid", test->invalid[i]);
+
+      if (!dbus_error_is_set (&f->e))
+        g_error ("%s should have an error set", test->invalid[i]);
+
+      if (!dbus_validate_error_name (f->e.name, NULL))
+        g_error ("%s produced an invalid error name: %s",
+            test->invalid[i], f->e.name);
+
+      if (!dbus_validate_utf8 (f->e.message, NULL))
+        g_error ("%s produced an invalid error message: %s",
+            test->invalid[i], f->e.message);
+
+      dbus_error_free (&f->e);
+    }
+}
+
+static void
+teardown (Fixture *f,
+    gconstpointer arg G_GNUC_UNUSED)
+{
+  dbus_error_free (&f->e);
+}
+
+int
+main (int argc,
+    char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+
+  g_test_add ("/syntax/path", Fixture, &paths, setup, test_syntax, teardown);
+  g_test_add ("/syntax/interface", Fixture, &interfaces,
+      setup, test_syntax, teardown);
+  g_test_add ("/syntax/error", Fixture, &errors,
+      setup, test_syntax, teardown);
+  g_test_add ("/syntax/member", Fixture, &members,
+      setup, test_syntax, teardown);
+  g_test_add ("/syntax/bus-name", Fixture, &bus_names,
+      setup, test_syntax, teardown);
+  g_test_add ("/syntax/signature", Fixture, &signatures,
+      setup, test_syntax, teardown);
+  g_test_add ("/syntax/single-signature", Fixture, &single_signatures,
+      setup, test_syntax, teardown);
+  g_test_add ("/syntax/utf8", Fixture, &strings,
+      setup, test_syntax, teardown);
+
+  return g_test_run ();
+}
diff --git a/dbus/test/test-exit.c b/dbus/test/test-exit.c
new file mode 100644
index 0000000..f335818
--- /dev/null
+++ b/dbus/test/test-exit.c
@@ -0,0 +1,7 @@
+/* This is a process that just exits with a failure code */
+int
+main (int argc, char **argv)
+{
+
+  return 1;
+}
diff --git a/dbus/test/test-names.c b/dbus/test/test-names.c
new file mode 100644
index 0000000..2736635
--- /dev/null
+++ b/dbus/test/test-names.c
@@ -0,0 +1,78 @@
+#include <config.h>
+#include "test-utils.h"
+
+static DBusLoop *loop;
+
+static void
+die (const char *message)
+{
+  fprintf (stderr, "*** test-names: %s", message);
+  exit (1);
+}
+
+static void
+TestName(DBusConnection *connection, const char *name, int expectedSuccess)
+{
+  DBusError error;
+  dbus_error_init (&error);
+
+  (void) dbus_bus_request_name (connection, name, 0, &error);
+  if (dbus_error_is_set (&error))
+    {
+      if (expectedSuccess)
+        fprintf (stderr, "Error acquiring name '%s': %s\n", name, error.message);
+      else
+        fprintf (stdout, "Expected Error acquiring name '%s': %s\n", name, error.message);
+      _dbus_verbose ("*** Failed to acquire name '%s': %s\n", name,
+                     error.message);
+      dbus_error_free (&error);
+      if (expectedSuccess)
+        exit (1);
+    }
+  else 
+    {
+      if (!expectedSuccess)
+        fprintf (stderr, "Unexpected Success acquiring name '%s'\n", name);
+      else
+        fprintf (stdout, "Successfully acquired name '%s'\n", name);
+      _dbus_verbose ("*** Managed to acquire name '%s'\n", name);
+      if (!expectedSuccess)
+        exit (1);
+    }
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  DBusError error;
+  DBusConnection *connection;
+  
+  dbus_error_init (&error);
+  connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
+  if (connection == NULL)
+    {
+      fprintf (stderr, "*** Failed to open connection to system bus: %s\n",
+               error.message);
+      dbus_error_free (&error);
+      return 1;
+    }
+
+  loop = _dbus_loop_new ();
+  if (loop == NULL)
+    die ("No memory\n");
+  
+  if (!test_connection_setup (loop, connection))
+    die ("No memory\n");
+
+  TestName(connection, "org.freedesktop.DBus.Test", TRUE);
+  TestName(connection, "org.freedesktop.DBus.Test-2", TRUE);
+  TestName(connection, "org.freedesktop.DBus.Test_2", TRUE);
+#if 0
+  TestName(connection, "Test_2", TRUE);
+#endif
+
+  _dbus_verbose ("*** Test service name exiting\n");
+  
+  return 0;
+}
diff --git a/dbus/test/test-segfault.c b/dbus/test/test-segfault.c
new file mode 100644
index 0000000..329a21f
--- /dev/null
+++ b/dbus/test/test-segfault.c
@@ -0,0 +1,30 @@
+/* This is simply a process that segfaults */
+#include <config.h>
+#include <stdlib.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef HAVE_SETRLIMIT
+#include <sys/resource.h>
+#endif
+
+int
+main (int argc, char **argv)
+{
+  char *p;  
+
+#if HAVE_SETRLIMIT
+  struct rlimit r = { 0, };
+  
+  getrlimit (RLIMIT_CORE, &r);
+  r.rlim_cur = 0;
+  setrlimit (RLIMIT_CORE, &r);
+  
+  raise (SIGSEGV);
+#endif
+  p = NULL;
+  *p = 'a';
+  
+  return 0;
+}
diff --git a/dbus/test/test-service.c b/dbus/test/test-service.c
new file mode 100644
index 0000000..7181fa3
--- /dev/null
+++ b/dbus/test/test-service.c
@@ -0,0 +1,505 @@
+#include <config.h>
+
+#include "test-utils.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+static DBusLoop *loop;
+static dbus_bool_t already_quit = FALSE;
+static dbus_bool_t hello_from_self_reply_received = FALSE;
+
+static void
+quit (void)
+{
+  if (!already_quit)
+    {
+      _dbus_loop_quit (loop);
+      already_quit = TRUE;
+    }
+}
+
+static void
+die (const char *message)
+{
+  fprintf (stderr, "*** test-service: %s", message);
+  exit (1);
+}
+
+static void
+check_hello_from_self_reply (DBusPendingCall *pcall, 
+                             void *user_data)
+{
+  DBusMessage *reply;
+  DBusMessage *echo_message, *echo_reply = NULL;
+  DBusError error;
+  DBusConnection *connection;
+  
+  int type;
+  
+  dbus_error_init (&error);
+ 
+  connection = dbus_bus_get (DBUS_BUS_STARTER, &error);
+  if (connection == NULL)
+    {
+      fprintf (stderr, "*** Failed to open connection to activating message bus: %s\n",
+               error.message);
+      dbus_error_free (&error);
+      die("no memory");
+    }
+
+  
+  echo_message = (DBusMessage *)user_data;
+    
+  reply = dbus_pending_call_steal_reply (pcall);
+    
+  type = dbus_message_get_type (reply);
+    
+  if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+    {
+      const char *s;
+      printf ("Reply from HelloFromSelf received\n");
+     
+      if (!dbus_message_get_args (echo_message,
+                              &error,
+                              DBUS_TYPE_STRING, &s,
+                              DBUS_TYPE_INVALID))
+        {
+            echo_reply = dbus_message_new_error (echo_message,
+                                      error.name,
+                                      error.message);
+
+            if (echo_reply == NULL)
+              die ("No memory\n");
+
+        } 
+      else
+        {  
+          echo_reply = dbus_message_new_method_return (echo_message);
+          if (echo_reply == NULL)
+            die ("No memory\n");
+  
+          if (!dbus_message_append_args (echo_reply,
+                                 DBUS_TYPE_STRING, &s,
+                                 DBUS_TYPE_INVALID))
+            die ("No memory");
+        }
+        
+      if (!dbus_connection_send (connection, echo_reply, NULL))
+        die ("No memory\n");
+      
+      dbus_message_unref (echo_reply);
+    }
+  else if (type == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      dbus_set_error_from_message (&error, reply);
+      printf ("Error type in reply: %s\n", error.message);
+
+      if (strcmp (error.name, DBUS_ERROR_NO_MEMORY) != 0)
+        {
+            echo_reply = dbus_message_new_error (echo_reply,
+                                      error.name,
+                                      error.message);
+
+            if (echo_reply == NULL)
+              die ("No memory\n");
+
+            if (!dbus_connection_send (connection, echo_reply, NULL))
+              die ("No memory\n");
+
+            dbus_message_unref (echo_reply);
+        }
+      dbus_error_free (&error);
+    }
+  else
+     _dbus_assert_not_reached ("Unexpected message received\n");
+
+  hello_from_self_reply_received = TRUE;
+  
+  dbus_message_unref (reply);
+  dbus_message_unref (echo_message);
+  dbus_pending_call_unref (pcall);
+  dbus_connection_unref (connection);
+}
+
+static DBusHandlerResult
+handle_run_hello_from_self (DBusConnection     *connection,
+                                               DBusMessage        *message)
+{
+  DBusError error;
+  DBusMessage *reply, *self_message;
+  DBusPendingCall *pcall;
+  char *s;
+
+  _dbus_verbose ("sending reply to Echo method\n");
+  
+  dbus_error_init (&error);
+  
+  if (!dbus_message_get_args (message,
+                              &error,
+                              DBUS_TYPE_STRING, &s,
+                              DBUS_TYPE_INVALID))
+    {
+      reply = dbus_message_new_error (message,
+                                      error.name,
+                                      error.message);
+
+      if (reply == NULL)
+        die ("No memory\n");
+
+      if (!dbus_connection_send (connection, reply, NULL))
+        die ("No memory\n");
+
+      dbus_message_unref (reply);
+
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+    printf ("Sending HelloFromSelf\n");
+
+ _dbus_verbose ("*** Sending message to self\n");
+ self_message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
+                                          "/org/freedesktop/TestSuite",
+                                          "org.freedesktop.TestSuite",
+                                          "HelloFromSelf");
+  
+  if (self_message == NULL)
+    die ("No memory");
+  
+  if (!dbus_connection_send_with_reply (connection, self_message, &pcall, -1))
+    die("No memory");
+  
+  dbus_message_ref (message);
+  if (!dbus_pending_call_set_notify (pcall, check_hello_from_self_reply, (void *)message, NULL))
+    die("No memory");
+    
+  printf ("Sent HelloFromSelf\n");
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+handle_echo (DBusConnection     *connection,
+             DBusMessage        *message)
+{
+  DBusError error;
+  DBusMessage *reply;
+  char *s;
+
+  _dbus_verbose ("sending reply to Echo method\n");
+  
+  dbus_error_init (&error);
+  
+  if (!dbus_message_get_args (message,
+                              &error,
+                              DBUS_TYPE_STRING, &s,
+                              DBUS_TYPE_INVALID))
+    {
+      reply = dbus_message_new_error (message,
+                                      error.name,
+                                      error.message);
+
+      if (reply == NULL)
+        die ("No memory\n");
+
+      if (!dbus_connection_send (connection, reply, NULL))
+        die ("No memory\n");
+
+      dbus_message_unref (reply);
+
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    die ("No memory\n");
+  
+  if (!dbus_message_append_args (reply,
+                                 DBUS_TYPE_STRING, &s,
+                                 DBUS_TYPE_INVALID))
+    die ("No memory");
+  
+  if (!dbus_connection_send (connection, reply, NULL))
+    die ("No memory\n");
+
+  fprintf (stderr, "Echo service echoed string: \"%s\"\n", s);
+  
+  dbus_message_unref (reply);
+    
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+handle_delay_echo (DBusConnection     *connection,
+                   DBusMessage        *message)
+{
+  DBusError error;
+  DBusMessage *reply;
+  char *s;
+
+  _dbus_verbose ("sleeping for a short time\n");
+
+  _dbus_sleep_milliseconds (50);
+
+  _dbus_verbose ("sending reply to DelayEcho method\n");
+  
+  dbus_error_init (&error);
+  
+  if (!dbus_message_get_args (message,
+                              &error,
+                              DBUS_TYPE_STRING, &s,
+                              DBUS_TYPE_INVALID))
+    {
+      reply = dbus_message_new_error (message,
+                                      error.name,
+                                      error.message);
+
+      if (reply == NULL)
+        die ("No memory\n");
+
+      if (!dbus_connection_send (connection, reply, NULL))
+        die ("No memory\n");
+
+      dbus_message_unref (reply);
+
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    die ("No memory\n");
+  
+  if (!dbus_message_append_args (reply,
+                                 DBUS_TYPE_STRING, &s,
+                                 DBUS_TYPE_INVALID))
+    die ("No memory");
+  
+  if (!dbus_connection_send (connection, reply, NULL))
+    die ("No memory\n");
+
+  fprintf (stderr, "DelayEcho service echoed string: \"%s\"\n", s);
+  
+  dbus_message_unref (reply);
+    
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+
+static void
+path_unregistered_func (DBusConnection  *connection,
+                        void            *user_data)
+{
+  /* connection was finalized */
+}
+
+static DBusHandlerResult
+path_message_func (DBusConnection  *connection,
+                   DBusMessage     *message,
+                   void            *user_data)
+{
+  if (dbus_message_is_method_call (message,
+                                   "org.freedesktop.TestSuite",
+                                   "Echo"))
+    return handle_echo (connection, message);
+  else if (dbus_message_is_method_call (message,
+                                        "org.freedesktop.TestSuite",
+                                        "DelayEcho"))
+    return handle_delay_echo (connection, message);
+  else if (dbus_message_is_method_call (message,
+                                        "org.freedesktop.TestSuite",
+                                        "Exit"))
+    {
+      quit ();
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
+  else if (dbus_message_is_method_call (message,
+                                        "org.freedesktop.TestSuite",
+                                        "EmitFoo"))
+    {
+      /* Emit the Foo signal */
+      DBusMessage *signal;
+      double v_DOUBLE;
+
+      _dbus_verbose ("emitting signal Foo\n");
+      
+      signal = dbus_message_new_signal ("/org/freedesktop/TestSuite",
+                                        "org.freedesktop.TestSuite",
+                                        "Foo");
+      if (signal == NULL)
+        die ("No memory\n");
+
+      v_DOUBLE = 42.6;
+      if (!dbus_message_append_args (signal,
+                                     DBUS_TYPE_DOUBLE, &v_DOUBLE,
+                                     DBUS_TYPE_INVALID))
+        die ("No memory");
+  
+      if (!dbus_connection_send (connection, signal, NULL))
+        die ("No memory\n");
+      
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
+    
+  else if (dbus_message_is_method_call (message,
+                                   "org.freedesktop.TestSuite",
+                                   "RunHelloFromSelf"))
+    {
+      return handle_run_hello_from_self (connection, message);
+    }
+  else if (dbus_message_is_method_call (message,
+                                        "org.freedesktop.TestSuite",
+                                        "HelloFromSelf"))
+    {
+        DBusMessage *reply;
+        printf ("Received the HelloFromSelf message\n");
+        
+        reply = dbus_message_new_method_return (message);
+        if (reply == NULL)
+          die ("No memory");
+        
+        if (!dbus_connection_send (connection, reply, NULL))
+          die ("No memory");
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+    }
+  else
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusObjectPathVTable
+echo_vtable = {
+  path_unregistered_func,
+  path_message_func,
+  NULL,
+};
+
+
+static const char* echo_path = "/org/freedesktop/TestSuite" ;
+
+static DBusHandlerResult
+filter_func (DBusConnection     *connection,
+             DBusMessage        *message,
+             void               *user_data)
+{
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_LOCAL,
+                              "Disconnected"))
+    {
+      quit ();
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
+  else
+    {
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  DBusError error;
+  int result;
+  DBusConnection *connection;
+  const char *name;
+  dbus_bool_t do_fork;
+
+  if (argc != 3)
+    {
+      name = "org.freedesktop.DBus.TestSuiteEchoService";
+      do_fork = FALSE;
+    }
+  else
+    {
+      name = argv[1];
+#ifndef DBUS_WIN
+      do_fork = strcmp (argv[2], "fork") == 0;
+#else
+      do_fork = FALSE;
+#endif
+    }
+
+  /* The bare minimum for simulating a program "daemonizing"; the intent
+   * is to test services which move from being legacy init scripts to
+   * activated services.
+   * https://bugzilla.redhat.com/show_bug.cgi?id=545267
+   */
+#ifndef DBUS_WIN
+   if (do_fork)
+    {
+      pid_t pid = fork ();
+      if (pid != 0)
+        exit (0);
+      sleep (1);
+    }
+#endif
+
+  dbus_error_init (&error);
+  connection = dbus_bus_get (DBUS_BUS_STARTER, &error);
+  if (connection == NULL)
+    {
+      fprintf (stderr, "*** Failed to open connection to activating message bus: %s\n",
+               error.message);
+      dbus_error_free (&error);
+      return 1;
+    }
+
+  loop = _dbus_loop_new ();
+  if (loop == NULL)
+    die ("No memory\n");
+  
+  if (!test_connection_setup (loop, connection))
+    die ("No memory\n");
+
+  if (!dbus_connection_add_filter (connection,
+                                   filter_func, NULL, NULL))
+    die ("No memory");
+
+  if (!dbus_connection_register_object_path (connection,
+                                             echo_path,
+                                             &echo_vtable,
+                                             (void*) 0xdeadbeef))
+    die ("No memory");
+
+  {
+    void *d;
+    if (!dbus_connection_get_object_path_data (connection, echo_path, &d))
+      die ("No memory");
+    if (d != (void*) 0xdeadbeef)
+      die ("dbus_connection_get_object_path_data() doesn't seem to work right\n");
+  }
+
+  result = dbus_bus_request_name (connection, name,
+                                  0, &error);
+  if (dbus_error_is_set (&error))
+    {
+      fprintf (stderr, "Error %s\n", error.message);
+      _dbus_verbose ("*** Failed to acquire service: %s\n",
+                     error.message);
+      dbus_error_free (&error);
+      exit (1);
+    }
+
+  if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+    {
+      fprintf (stderr, "Unable to acquire service: code %d\n", result);
+      _dbus_verbose ("*** Failed to acquire service: %d\n", result);
+      exit (1);
+    }
+
+  _dbus_verbose ("*** Test service entering main loop\n");
+  _dbus_loop_run (loop);
+  
+  test_connection_shutdown (loop, connection);
+
+  dbus_connection_remove_filter (connection, filter_func, NULL);
+  
+  dbus_connection_unref (connection);
+
+  _dbus_loop_unref (loop);
+  loop = NULL;
+  
+  dbus_shutdown ();
+
+  _dbus_verbose ("*** Test service exiting\n");
+  
+  return 0;
+}
diff --git a/dbus/test/test-shell-service.c b/dbus/test/test-shell-service.c
new file mode 100644
index 0000000..32a8832
--- /dev/null
+++ b/dbus/test/test-shell-service.c
@@ -0,0 +1,203 @@
+#include <config.h>
+
+#include "test-utils.h"
+
+static DBusLoop *loop;
+static dbus_bool_t already_quit = FALSE;
+static const char* echo_path = "/org/freedesktop/TestSuite";
+
+typedef struct
+{
+  int argc;
+  char **argv;
+} EchoData;
+
+static void
+quit (void)
+{
+  if (!already_quit)
+    {
+      _dbus_loop_quit (loop);
+      already_quit = TRUE;
+    }
+}
+
+static void
+die (const char *message)
+{
+  fprintf (stderr, "*** test-service: %s", message);
+  exit (1);
+}
+
+static DBusHandlerResult
+handle_echo (DBusConnection     *connection,
+             DBusMessage        *message)
+{
+  DBusError error;
+  DBusMessage *reply;
+  DBusMessageIter iter;
+  int i;
+  EchoData *d;
+
+  _dbus_verbose ("sending reply to Echo method\n");
+
+  if (!dbus_connection_get_object_path_data (connection, echo_path, (void **)&d))
+      die ("No memory");
+
+
+  dbus_error_init (&error);
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    die ("No memory\n");
+  
+  dbus_message_iter_init_append (reply, &iter);
+  for (i = 0; i < d->argc; ++i)
+    if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &(d->argv[i])))
+      die ("No memory\n");
+
+  if (!dbus_connection_send (connection, reply, NULL))
+    die ("No memory\n");
+
+  fprintf (stderr, "Shell echo service echoed the command line\n");
+  
+  dbus_message_unref (reply);
+    
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+path_unregistered_func (DBusConnection  *connection,
+                        void            *user_data)
+{
+  /* connection was finalized */
+}
+
+static DBusHandlerResult
+path_message_func (DBusConnection  *connection,
+                   DBusMessage     *message,
+                   void            *user_data)
+{
+  if (dbus_message_is_method_call (message,
+                                   "org.freedesktop.TestSuite",
+                                   "Echo"))
+    return handle_echo (connection, message);
+  else if (dbus_message_is_method_call (message,
+                                        "org.freedesktop.TestSuite",
+                                        "Exit"))
+    {
+      quit ();
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
+  else
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusObjectPathVTable
+echo_vtable = {
+  path_unregistered_func,
+  path_message_func,
+  NULL,
+};
+
+static DBusHandlerResult
+filter_func (DBusConnection     *connection,
+             DBusMessage        *message,
+             void               *user_data)
+{
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_LOCAL,
+                              "Disconnected"))
+    {
+      quit ();
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
+  else
+    {
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  DBusConnection *connection;
+  DBusError error;
+  EchoData echo_data;
+  int result;
+  
+  echo_data.argc = argc;
+  echo_data.argv = argv;
+  
+  dbus_error_init (&error);
+  connection = dbus_bus_get (DBUS_BUS_STARTER, &error);
+  if (connection == NULL)
+    {
+      fprintf (stderr, "*** Failed to open connection to activating message bus: %s\n",
+               error.message);
+      dbus_error_free (&error);
+      return 1;
+    }
+
+  loop = _dbus_loop_new ();
+  if (loop == NULL)
+    die ("No memory\n");
+  
+  if (!test_connection_setup (loop, connection))
+    die ("No memory\n");
+
+  if (!dbus_connection_add_filter (connection,
+                                   filter_func, NULL, NULL))
+    die ("No memory");
+
+  if (!dbus_connection_register_object_path (connection,
+                                             echo_path,
+                                             &echo_vtable,
+                                             (void*) &echo_data))
+    die ("No memory");
+
+  {
+    void *d;
+    if (!dbus_connection_get_object_path_data (connection, echo_path, &d))
+      die ("No memory");
+    if (d != (void*) &echo_data)
+      die ("dbus_connection_get_object_path_data() doesn't seem to work right\n");
+  }
+  
+  result = dbus_bus_request_name (connection, "org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess",
+                                  0, &error);
+  if (dbus_error_is_set (&error))
+    {
+      fprintf (stderr, "Error %s\n", error.message);
+      _dbus_verbose ("*** Failed to acquire service: %s\n",
+                     error.message);
+      dbus_error_free (&error);
+      exit (1);
+    }
+
+  if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+    {
+      fprintf (stderr, "Unable to acquire service: code %d\n", result);
+      _dbus_verbose ("*** Failed to acquire service: %d\n", result);
+      exit (1);
+    }
+
+  _dbus_verbose ("*** Test service entering main loop\n");
+  _dbus_loop_run (loop);
+
+  test_connection_shutdown (loop, connection);
+
+  dbus_connection_remove_filter (connection, filter_func, NULL);
+  
+  dbus_connection_unref (connection);
+
+  _dbus_loop_unref (loop);
+  loop = NULL;
+  
+  dbus_shutdown ();
+
+  _dbus_verbose ("*** Test service exiting\n");
+  
+  return 0;
+}
diff --git a/dbus/test/test-sleep-forever.c b/dbus/test/test-sleep-forever.c
new file mode 100644
index 0000000..d54769a
--- /dev/null
+++ b/dbus/test/test-sleep-forever.c
@@ -0,0 +1,22 @@
+/* This is a process that just sleeps infinitely. */
+
+#include <config.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef DBUS_WIN
+# include <windows.h>
+# define sleep Sleep
+#endif
+
+
+int
+main (int argc, char **argv)
+{
+  while (1)
+    sleep (10000000);
+
+  return 1;
+}
diff --git a/dbus/test/test-utils.c b/dbus/test/test-utils.c
new file mode 100644
index 0000000..c3c3ed3
--- /dev/null
+++ b/dbus/test/test-utils.c
@@ -0,0 +1,315 @@
+#include <config.h>
+#include "test-utils.h"
+
+typedef struct
+{
+  DBusLoop *loop;
+  DBusConnection *connection;
+
+} CData;
+
+static dbus_bool_t
+add_watch (DBusWatch *watch,
+	   void      *data)
+{
+  CData *cd = data;
+
+  return _dbus_loop_add_watch (cd->loop, watch);
+}
+
+static void
+remove_watch (DBusWatch *watch,
+	      void      *data)
+{
+  CData *cd = data;
+  
+  _dbus_loop_remove_watch (cd->loop, watch);
+}
+
+static void
+toggle_watch (DBusWatch  *watch,
+              void       *data)
+{
+  CData *cd = data;
+
+  _dbus_loop_toggle_watch (cd->loop, watch);
+}
+
+static dbus_bool_t
+add_timeout (DBusTimeout *timeout,
+	     void        *data)
+{
+  CData *cd = data;
+
+  return _dbus_loop_add_timeout (cd->loop, timeout);
+}
+
+static void
+remove_timeout (DBusTimeout *timeout,
+		void        *data)
+{
+  CData *cd = data;
+
+  _dbus_loop_remove_timeout (cd->loop, timeout);
+}
+
+static void
+dispatch_status_function (DBusConnection    *connection,
+                          DBusDispatchStatus new_status,
+                          void              *data)
+{
+  DBusLoop *loop = data;
+  
+  if (new_status != DBUS_DISPATCH_COMPLETE)
+    {
+      while (!_dbus_loop_queue_dispatch (loop, connection))
+        _dbus_wait_for_memory ();
+    }
+}
+
+static void
+cdata_free (void *data)
+{
+  CData *cd = data;
+
+  dbus_connection_unref (cd->connection);
+  _dbus_loop_unref (cd->loop);
+  
+  dbus_free (cd);
+}
+
+static CData*
+cdata_new (DBusLoop       *loop,
+           DBusConnection *connection)
+{
+  CData *cd;
+
+  cd = dbus_new0 (CData, 1);
+  if (cd == NULL)
+    return NULL;
+
+  cd->loop = loop;
+  cd->connection = connection;
+
+  dbus_connection_ref (cd->connection);
+  _dbus_loop_ref (cd->loop);
+
+  return cd;
+}
+
+dbus_bool_t
+test_connection_setup (DBusLoop       *loop,
+                       DBusConnection *connection)
+{
+  CData *cd;
+
+  cd = NULL;
+  
+  dbus_connection_set_dispatch_status_function (connection, dispatch_status_function,
+                                                loop, NULL);
+  
+  cd = cdata_new (loop, connection);
+  if (cd == NULL)
+    goto nomem;
+
+  if (!dbus_connection_set_watch_functions (connection,
+                                            add_watch,
+                                            remove_watch,
+                                            toggle_watch,
+                                            cd, cdata_free))
+    goto nomem;
+
+
+  cd = cdata_new (loop, connection);
+  if (cd == NULL)
+    goto nomem;
+  
+  if (!dbus_connection_set_timeout_functions (connection,
+                                              add_timeout,
+                                              remove_timeout,
+                                              NULL,
+                                              cd, cdata_free))
+    goto nomem;
+
+  if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
+    {
+      if (!_dbus_loop_queue_dispatch (loop, connection))
+        goto nomem;
+    }
+  
+  return TRUE;
+  
+ nomem:
+  if (cd)
+    cdata_free (cd);
+  
+  dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
+  dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
+  dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
+  
+  return FALSE;
+}
+
+void
+test_connection_shutdown (DBusLoop       *loop,
+                          DBusConnection *connection)
+{
+  if (!dbus_connection_set_watch_functions (connection,
+                                            NULL,
+                                            NULL,
+                                            NULL,
+                                            NULL, NULL))
+    _dbus_assert_not_reached ("setting watch functions to NULL failed");
+  
+  if (!dbus_connection_set_timeout_functions (connection,
+                                              NULL,
+                                              NULL,
+                                              NULL,
+                                              NULL, NULL))
+    _dbus_assert_not_reached ("setting timeout functions to NULL failed");
+
+  dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
+}
+
+typedef struct
+{
+  DBusLoop *loop;
+  DBusServer *server;
+} ServerData;
+
+static void
+serverdata_free (void *data)
+{
+  ServerData *sd = data;
+
+  dbus_server_unref (sd->server);
+  _dbus_loop_unref (sd->loop);
+  
+  dbus_free (sd);
+}
+
+static ServerData*
+serverdata_new (DBusLoop       *loop,
+                DBusServer     *server)
+{
+  ServerData *sd;
+
+  sd = dbus_new0 (ServerData, 1);
+  if (sd == NULL)
+    return NULL;
+
+  sd->loop = loop;
+  sd->server = server;
+
+  dbus_server_ref (sd->server);
+  _dbus_loop_ref (sd->loop);
+
+  return sd;
+}
+
+static dbus_bool_t
+add_server_watch (DBusWatch  *watch,
+                  void       *data)
+{
+  ServerData *context = data;
+
+  return _dbus_loop_add_watch (context->loop, watch);
+}
+
+static void
+toggle_server_watch (DBusWatch  *watch,
+                     void       *data)
+{
+  ServerData *context = data;
+
+  _dbus_loop_toggle_watch (context->loop, watch);
+}
+
+static void
+remove_server_watch (DBusWatch  *watch,
+                     void       *data)
+{
+  ServerData *context = data;
+  
+  _dbus_loop_remove_watch (context->loop, watch);
+}
+
+static dbus_bool_t
+add_server_timeout (DBusTimeout *timeout,
+                    void        *data)
+{
+  ServerData *context = data;
+
+  return _dbus_loop_add_timeout (context->loop, timeout);
+}
+
+static void
+remove_server_timeout (DBusTimeout *timeout,
+                       void        *data)
+{
+  ServerData *context = data;
+  
+  _dbus_loop_remove_timeout (context->loop, timeout);
+}
+
+dbus_bool_t
+test_server_setup (DBusLoop      *loop,
+                   DBusServer    *server)
+{
+  ServerData *sd;
+
+  sd = serverdata_new (loop, server);
+  if (sd == NULL)
+    goto nomem;
+
+  if (!dbus_server_set_watch_functions (server,
+                                        add_server_watch,
+                                        remove_server_watch,
+                                        toggle_server_watch,
+                                        sd,
+                                        serverdata_free))
+    {
+      goto nomem;
+    }
+
+  sd = serverdata_new (loop, server);
+  if (sd == NULL)
+    goto nomem;
+
+  if (!dbus_server_set_timeout_functions (server,
+                                          add_server_timeout,
+                                          remove_server_timeout,
+                                          NULL,
+                                          sd, serverdata_free))
+    {
+      goto nomem;
+    }   
+  return TRUE;
+
+ nomem:
+  if (sd)
+    serverdata_free (sd);
+  
+  test_server_shutdown (loop, server);
+  
+  return FALSE;
+}
+
+void
+test_server_shutdown (DBusLoop         *loop,
+                      DBusServer       *server)
+{
+  dbus_server_disconnect (server);
+
+  if (!dbus_server_set_watch_functions (server,
+                                        NULL, NULL, NULL,
+                                        NULL,
+                                        NULL))
+    _dbus_assert_not_reached ("setting watch functions to NULL failed");
+  
+  if (!dbus_server_set_timeout_functions (server,
+                                          NULL, NULL, NULL,
+                                          NULL,
+                                          NULL))
+    _dbus_assert_not_reached ("setting timeout functions to NULL failed");  
+}
diff --git a/dbus/test/test-utils.h b/dbus/test/test-utils.h
new file mode 100644
index 0000000..3e1e55e
--- /dev/null
+++ b/dbus/test/test-utils.h
@@ -0,0 +1,25 @@
+#ifndef TEST_UTILS_H
+#define TEST_UTILS_H
+#ifndef DBUS_COMPILATION
+#define DBUS_COMPILATION /* Cheat and use private stuff */
+#endif
+#include <dbus/dbus.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dbus/dbus-mainloop.h>
+#include <dbus/dbus-internals.h>
+#undef DBUS_COMPILATION
+
+dbus_bool_t test_connection_setup                 (DBusLoop       *loop,
+                                                   DBusConnection *connection);
+void        test_connection_shutdown              (DBusLoop       *loop,
+                                                   DBusConnection *connection);
+void        test_connection_dispatch_all_messages (DBusConnection *connection);
+dbus_bool_t test_connection_dispatch_one_message  (DBusConnection *connection);
+
+dbus_bool_t test_server_setup                     (DBusLoop      *loop,
+                                                   DBusServer    *server);
+void        test_server_shutdown                  (DBusLoop      *loop,
+                                                   DBusServer    *server);
+
+#endif
diff --git a/dbus/test/unused-code-gc.py b/dbus/test/unused-code-gc.py
new file mode 100755
index 0000000..a58597f
--- /dev/null
+++ b/dbus/test/unused-code-gc.py
@@ -0,0 +1,242 @@
+#! /usr/bin/python
+
+import os
+import sys
+import string
+import re
+
+## hash from symbol name to list of symbols with that name,
+## where the list of symbols contains a list representing each symbol
+symbols = {}
+roots = {}
+
+def createBacklinks(name, syms):
+    for s in syms:
+        refs = s[2]
+        for r in refs:
+            ## for each ref, add ourselves as a referencer
+            if symbols.has_key(r):
+                targets = symbols[r]
+                for t in targets:
+                    if name not in t[5]:
+                        t[5].append(name)
+
+def markSymbol(frm, name):
+    if not symbols.has_key(name):
+        print "%s referenced but was not in the objdump"
+    syms = symbols[name]
+    ## print ambiguous references unless they are internal noise like ".L129"
+    if len(syms) > 1 and name[0] != '.':
+        print "Reference to symbol '%s' from '%s' is ambiguous, marking all '%s'" % (name, frm, name)
+        print syms
+    for s in syms:
+        if s[4]:
+            pass ## already marked
+        else:
+            s[4] = 1
+            refs = s[2]
+            for r in refs:
+                markSymbol(s[0], r)
+
+def cmpFilename(a, b):
+    v = cmp(a[1], b[1])
+    if v == 0:
+        v = cmp(a[0], b[0])
+    return v
+
+def sizeAsString(bytes):
+    if bytes < 1024:
+        return "%d bytes" % bytes
+    elif bytes < 1024*1024:
+        return "%.2gK" % (bytes / 1024.0)
+    else:
+        return "%.2gM" % (bytes / 1024.0 / 1024.0)
+
+def printLost():
+    list = []
+    filename = None
+    for (name, syms) in symbols.items():
+        s = syms[0] ## we always mark all or none for now
+        if not s[4] and name[0] != '.': ## skip .L129 type symbols
+            filename = s[3]
+            if not filename:
+                filename = "unknown file"
+            list.append ((name, filename, s[5], s[7]))
+
+    file_summaries = []
+    total_unused = 0
+    total_this_file = 0
+    filename = None
+    list.sort(cmpFilename)
+    for l in list:
+        next_filename = l[1]
+        if next_filename != filename:
+            if total_this_file > 0:
+                file_summaries.append ("  %s may be unused in %s" % (sizeAsString(total_this_file), filename))
+            print "%s has these symbols not reachable from exported symbols:" % next_filename
+            filename = next_filename
+            total_this_file = 0
+        print "    %s %s" % (l[0], sizeAsString(l[3]))
+        total_unused = total_unused + l[3]
+        total_this_file = total_this_file + l[3]
+        for trace in l[2]:
+            print "       referenced from %s" % trace
+
+    for fs in file_summaries:
+        print fs
+    print "%s total may be unused" % sizeAsString(total_unused)
+
+def main():
+
+    ## 0001aa44 <_dbus_message_get_network_data>:
+    sym_re = re.compile ('([0-9a-f]+) <([^>]+)>:')
+    ## 1aa49:       e8 00 00 00 00          call   1aa4e <_dbus_message_get_network_data+0xa>
+    ref_re = re.compile (' <([^>]+)> *$')
+    ## /home/hp/dbus-cvs/dbus/dbus/dbus-message.c:139
+    file_re = re.compile ('^(\/[^:].*):[0-9]+$')
+    ## _dbus_message_get_network_data+0xa
+    funcname_re = re.compile ('([^+]+)\+[0-9a-fx]+')
+    ## 00005410 T dbus_address_entries_free
+    dynsym_re = re.compile ('T ([^ \n]+)$')
+    
+    filename = sys.argv[1]
+
+    command = """
+    objdump -D --demangle -l %s
+    """ % filename
+
+    command = string.strip (command)
+
+    print "Running: %s" % command
+    
+    f = os.popen(command)    
+
+    ## first we find which functions reference which other functions
+    current_sym = None
+    lines = f.readlines()
+    for l in lines:
+        addr = None
+        name = None
+        target = None
+        file = None
+        
+        match = sym_re.match(l)
+        if match:
+            addr = match.group(1)
+            name = match.group(2)
+        else:
+            match = ref_re.search(l)
+            if match:
+                target = match.group(1)
+            else:
+                match = file_re.match(l)
+                if match:
+                    file = match.group(1)
+
+        if name:
+            ## 0 symname, 1 address, 2 references, 3 filename, 4 reached, 5 referenced-by 6 backlinked 7 approx size
+            item = [name, addr, [], None, 0, [], 0, 0]
+            if symbols.has_key(name):
+                symbols[name].append(item)
+            else:
+                symbols[name] = [item]
+
+            if current_sym:
+                prev_addr = long(current_sym[1], 16)
+                our_addr = long(item[1], 16)
+                item[7] = our_addr - prev_addr
+                if item[7] < 0:
+                    print "Computed negative size %d for %s" % (item[7], item[0])
+                    item[7] = 0
+                                  
+            current_sym = item
+            
+        elif target and current_sym:
+            match = funcname_re.match(target)
+            if match:
+                ## dump the "+address"
+                target = match.group(1)
+            if target == current_sym[0]:
+                pass ## skip self-references
+            else:
+                current_sym[2].append (target)
+
+        elif file and current_sym:
+            if file.startswith('/usr/include'):
+                ## inlined libc thingy
+                pass
+            elif current_sym[0].startswith('.debug'):
+                ## debug info
+                pass
+            elif current_sym[3] and current_sym[3] != file:
+                raise Exception ("%s in both %s and %s" % (current_sym[0], current_sym[3], file))
+            else:
+                current_sym[3] = file
+
+    ## now we need to find the roots (exported symbols)
+    command = "nm -D %s" % filename
+    print "Running: %s" % command
+    f = os.popen(command)
+    lines = f.readlines ()
+    for l in lines:
+        match = dynsym_re.search(l)
+        if match:
+            name = match.group(1)
+            if roots.has_key(name):
+                raise Exception("symbol %s exported twice?" % name)
+            else:
+                roots[name] = 1
+
+    print "%d symbols exported from this object" % len(roots)
+
+    ## these functions are used only indirectly, so we don't
+    ## notice they are used. Manually add them as roots...
+    vtable_roots = ['unix_finalize',
+                    'unix_handle_watch',
+                    'unix_disconnect',
+                    'unix_connection_set',
+                    'unix_do_iteration',
+                    'unix_live_messages_changed',
+                    'unix_get_unix_fd',
+                    'handle_client_data_cookie_sha1_mech',
+                    'handle_client_data_external_mech',
+                    'handle_server_data_cookie_sha1_mech',
+                    'handle_server_data_external_mech',
+                    'handle_client_initial_response_cookie_sha1_mech',                  
+                    'handle_client_initial_response_external_mech',
+                    'handle_client_shutdown_cookie_sha1_mech',
+                    'handle_client_shutdown_external_mech',
+                    'handle_server_shutdown_cookie_sha1_mech',
+                    'handle_server_shutdown_external_mech'
+                    ]
+
+    for vr in vtable_roots:
+        if roots.has_key(vr):
+            raise Exception("%s is already a root" % vr)
+        roots[vr] = 1
+
+    for k in roots.keys():
+        markSymbol("root", k)
+
+    for (k, v) in symbols.items():
+        createBacklinks(k, v)
+
+    print """
+
+The symbols mentioned below don't appear to be reachable starting from
+the dynamic exports of the library. However, this program is pretty
+dumb; a limitation that creates false positives is that it can only
+trace 'reachable' through hardcoded function calls, if a function is
+called only through a vtable, it won't be marked reachable (and
+neither will its children in the call graph).
+
+Also, the sizes mentioned are more or less completely bogus.
+
+"""
+    
+    print "The following are hardcoded in as vtable roots: %s" % vtable_roots
+    
+    printLost()
+        
+if __name__ == "__main__":
+    main()
diff --git a/dbus/tools/Android.mk b/dbus/tools/Android.mk
new file mode 100644
index 0000000..a5d33f7
--- /dev/null
+++ b/dbus/tools/Android.mk
@@ -0,0 +1,39 @@
+LOCAL_PATH := $(call my-dir)
+
+dbusToolsCommonCFlags := \
+	-DDBUS_COMPILATION \
+	-DDBUS_MACHINE_UUID_FILE=\"/etc/machine-id\" \
+	-Wno-unused-parameter
+
+# common
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := dbus-print-message.c
+LOCAL_SHARED_LIBRARIES += libdbus
+LOCAL_CFLAGS += $(dbusToolsCommonCFlags)
+LOCAL_MODULE := libdbus-tools-common
+include $(BUILD_STATIC_LIBRARY)
+
+# dbus-monitor
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := dbus-monitor.c
+LOCAL_SHARED_LIBRARIES += libdbus
+LOCAL_STATIC_LIBRARIES += libdbus-tools-common
+LOCAL_CFLAGS += $(dbusToolsCommonCFlags)
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE := dbus-monitor
+include $(BUILD_EXECUTABLE)
+
+# dbus-send
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := dbus-send.c
+LOCAL_SHARED_LIBRARIES += libdbus
+LOCAL_STATIC_LIBRARIES += libdbus-tools-common
+LOCAL_CFLAGS += $(dbusToolsCommonCFlags)
+LOCAL_MODULE := dbus-send
+include $(BUILD_EXECUTABLE)
diff --git a/dbus/tools/Makefile.am b/dbus/tools/Makefile.am
new file mode 100644
index 0000000..cfd54b8
--- /dev/null
+++ b/dbus/tools/Makefile.am
@@ -0,0 +1,80 @@
+configdir=$(sysconfdir)/dbus-1
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir) \
+	$(DBUS_STATIC_BUILD_CPPFLAGS) \
+	$(DBUS_X_CFLAGS) \
+	-DDBUS_COMPILATION \
+	-DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" \
+	$(NULL)
+
+# if assertions are enabled, improve backtraces
+AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
+
+bin_PROGRAMS = \
+	dbus-launch \
+	dbus-monitor \
+	dbus-send \
+	$(NULL)
+
+if DBUS_UNIX
+bin_PROGRAMS += \
+	dbus-cleanup-sockets \
+	dbus-uuidgen \
+	$(NULL)
+endif
+
+dbus_send_SOURCES=				\
+	dbus-print-message.c			\
+	dbus-print-message.h			\
+	dbus-send.c
+
+dbus_monitor_SOURCES=				\
+	dbus-monitor.c				\
+	dbus-print-message.c			\
+	dbus-print-message.h
+
+if DBUS_WIN
+dbus_launch_SOURCES=				\
+	dbus-launch-win.c			\
+	dbus-launch.h
+else
+dbus_launch_SOURCES=				\
+	dbus-launch.c				\
+	dbus-launch-x11.c			\
+	dbus-launch.h
+endif
+
+dbus_cleanup_sockets_SOURCES=			\
+	dbus-cleanup-sockets.c
+
+dbus_uuidgen_SOURCES=				\
+	dbus-uuidgen.c
+
+dbus_send_LDADD = \
+	$(top_builddir)/dbus/libdbus-1.la \
+	$(NULL)
+
+dbus_monitor_LDADD = \
+	$(top_builddir)/dbus/libdbus-1.la \
+	$(NETWORK_libs) \
+	$(NULL)
+
+dbus_uuidgen_LDADD = \
+	$(top_builddir)/dbus/libdbus-1.la \
+	$(NULL)
+
+dbus_launch_LDADD = \
+	$(DBUS_X_LIBS) \
+	$(NULL)
+
+EXTRA_DIST = run-with-tmp-session-bus.sh strtoll.c strtoull.c
+CLEANFILES = 				\
+	run-with-tmp-session-bus.conf
+
+# create the /var/lib/dbus directory for dbus-uuidgen
+install-data-local:
+	$(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/dbus
+
+installcheck-local:
+	test -d $(DESTDIR)$(localstatedir)/lib/dbus
diff --git a/dbus/tools/NOTICE b/dbus/tools/NOTICE
new file mode 100644
index 0000000..a91ca1d
--- /dev/null
+++ b/dbus/tools/NOTICE
@@ -0,0 +1,551 @@
+D-Bus is licensed to you under your choice of the Academic Free
+License version 2.1, or the GNU General Public License version 2.
+Both licenses are included here. Some of the standalone binaries are
+under the GPL only; in particular, but not limited to,
+tools/dbus-cleanup-sockets.c and test/decode-gcov.c. Each source code
+file is marked with the proper copyright information - if you find a
+file that isn't marked please bring it to our attention.
+
+
+The Academic Free License
+v. 2.1
+
+This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work:
+
+Licensed under the Academic Free License version 2.1
+
+1) Grant of Copyright License. Licensor hereby grants You a
+world-wide, royalty-free, non-exclusive, perpetual, sublicenseable
+license to do the following:
+
+a) to reproduce the Original Work in copies;
+
+b) to prepare derivative works ("Derivative Works") based upon the Original Work;
+
+c) to distribute copies of the Original Work and Derivative Works to the public;
+
+d) to perform the Original Work publicly; and
+
+e) to display the Original Work publicly.
+
+2) Grant of Patent License. Licensor hereby grants You a world-wide,
+royalty-free, non-exclusive, perpetual, sublicenseable license, under
+patent claims owned or controlled by the Licensor that are embodied in
+the Original Work as furnished by the Licensor, to make, use, sell and
+offer for sale the Original Work and Derivative Works.
+
+3) Grant of Source Code License. The term "Source Code" means the
+preferred form of the Original Work for making modifications to it and
+all available documentation describing how to modify the Original
+Work. Licensor hereby agrees to provide a machine-readable copy of the
+Source Code of the Original Work along with each copy of the Original
+Work that Licensor distributes. Licensor reserves the right to satisfy
+this obligation by placing a machine-readable copy of the Source Code
+in an information repository reasonably calculated to permit
+inexpensive and convenient access by You for as long as Licensor
+continues to distribute the Original Work, and by publishing the
+address of that information repository in a notice immediately
+following the copyright notice that applies to the Original Work.
+
+4) Exclusions From License Grant. Neither the names of Licensor, nor
+the names of any contributors to the Original Work, nor any of their
+trademarks or service marks, may be used to endorse or promote
+products derived from this Original Work without express prior written
+permission of the Licensor. Nothing in this License shall be deemed to
+grant any rights to trademarks, copyrights, patents, trade secrets or
+any other intellectual property of Licensor except as expressly stated
+herein. No patent license is granted to make, use, sell or offer to
+sell embodiments of any patent claims other than the licensed claims
+defined in Section 2. No right is granted to the trademarks of
+Licensor even if such marks are included in the Original Work. Nothing
+in this License shall be interpreted to prohibit Licensor from
+licensing under different terms from this License any Original Work
+that Licensor otherwise would have a right to license.
+
+5) This section intentionally omitted.
+
+6) Attribution Rights. You must retain, in the Source Code of any
+Derivative Works that You create, all copyright, patent or trademark
+notices from the Source Code of the Original Work, as well as any
+notices of licensing and any descriptive text identified therein as an
+"Attribution Notice." You must cause the Source Code for any
+Derivative Works that You create to carry a prominent Attribution
+Notice reasonably calculated to inform recipients that You have
+modified the Original Work.
+
+7) Warranty of Provenance and Disclaimer of Warranty. Licensor
+warrants that the copyright in and to the Original Work and the patent
+rights granted herein by Licensor are owned by the Licensor or are
+sublicensed to You under the terms of this License with the permission
+of the contributor(s) of those copyrights and patent rights. Except as
+expressly stated in the immediately proceeding sentence, the Original
+Work is provided under this License on an "AS IS" BASIS and WITHOUT
+WARRANTY, either express or implied, including, without limitation,
+the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL
+WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential
+part of this License. No license to Original Work is granted hereunder
+except under this disclaimer.
+
+8) Limitation of Liability. Under no circumstances and under no legal
+theory, whether in tort (including negligence), contract, or
+otherwise, shall the Licensor be liable to any person for any direct,
+indirect, special, incidental, or consequential damages of any
+character arising as a result of this License or the use of the
+Original Work including, without limitation, damages for loss of
+goodwill, work stoppage, computer failure or malfunction, or any and
+all other commercial damages or losses. This limitation of liability
+shall not apply to liability for death or personal injury resulting
+from Licensor's negligence to the extent applicable law prohibits such
+limitation. Some jurisdictions do not allow the exclusion or
+limitation of incidental or consequential damages, so this exclusion
+and limitation may not apply to You.
+
+9) Acceptance and Termination. If You distribute copies of the
+Original Work or a Derivative Work, You must make a reasonable effort
+under the circumstances to obtain the express assent of recipients to
+the terms of this License. Nothing else but this License (or another
+written agreement between Licensor and You) grants You permission to
+create Derivative Works based upon the Original Work or to exercise
+any of the rights granted in Section 1 herein, and any attempt to do
+so except under the terms of this License (or another written
+agreement between Licensor and You) is expressly prohibited by
+U.S. copyright law, the equivalent laws of other countries, and by
+international treaty. Therefore, by exercising any of the rights
+granted to You in Section 1 herein, You indicate Your acceptance of
+this License and all of its terms and conditions.
+
+10) Termination for Patent Action. This License shall terminate
+automatically and You may no longer exercise any of the rights granted
+to You by this License as of the date You commence an action,
+including a cross-claim or counterclaim, against Licensor or any
+licensee alleging that the Original Work infringes a patent. This
+termination provision shall not apply for an action alleging patent
+infringement by combinations of the Original Work with other software
+or hardware.
+
+11) Jurisdiction, Venue and Governing Law. Any action or suit relating
+to this License may be brought only in the courts of a jurisdiction
+wherein the Licensor resides or in which Licensor conducts its primary
+business, and under the laws of that jurisdiction excluding its
+conflict-of-law provisions. The application of the United Nations
+Convention on Contracts for the International Sale of Goods is
+expressly excluded. Any use of the Original Work outside the scope of
+this License or after its termination shall be subject to the
+requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101
+et seq., the equivalent laws of other countries, and international
+treaty. This section shall survive the termination of this License.
+
+12) Attorneys Fees. In any action to enforce the terms of this License
+or seeking damages relating thereto, the prevailing party shall be
+entitled to recover its costs and expenses, including, without
+limitation, reasonable attorneys' fees and costs incurred in
+connection with such action, including any appeal of such action. This
+section shall survive the termination of this License.
+
+13) Miscellaneous. This License represents the complete agreement
+concerning the subject matter hereof. If any provision of this License
+is held to be unenforceable, such provision shall be reformed only to
+the extent necessary to make it enforceable.
+
+14) Definition of "You" in This License. "You" throughout this
+License, whether in upper or lower case, means an individual or a
+legal entity exercising rights under, and complying with all of the
+terms of, this License. For legal entities, "You" includes any entity
+that controls, is controlled by, or is under common control with
+you. For purposes of this definition, "control" means (i) the power,
+direct or indirect, to cause the direction or management of such
+entity, whether by contract or otherwise, or (ii) ownership of fifty
+percent (50%) or more of the outstanding shares, or (iii) beneficial
+ownership of such entity.
+
+15) Right to Use. You may use the Original Work in all ways not
+otherwise restricted or conditioned by this License or by law, and
+Licensor promises not to interfere with or be responsible for such
+uses by You.
+
+This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights
+reserved. Permission is hereby granted to copy and distribute this
+license without modification. This license may not be modified without
+the express written permission of its copyright owner.
+
+
+-- 
+END OF ACADEMIC FREE LICENSE. The following is intended to describe the essential 
+differences between the Academic Free License (AFL) version 1.0 and other 
+open source licenses:
+
+The Academic Free License is similar to the BSD, MIT, UoI/NCSA and Apache 
+licenses in many respects but it is intended to solve a few problems with 
+those licenses.
+    
+* The AFL is written so as to make it clear what software is being 
+licensed (by the inclusion of a statement following the copyright notice 
+in the software). This way, the license functions better than a template 
+license. The BSD, MIT and UoI/NCSA licenses apply to unidentified software.
+    
+* The AFL contains a complete copyright grant to the software. The BSD 
+and Apache licenses are vague and incomplete in that respect.
+    
+* The AFL contains a complete patent grant to the software. The BSD, MIT, 
+UoI/NCSA and Apache licenses rely on an implied patent license and contain 
+no explicit patent grant.
+    
+* The AFL makes it clear that no trademark rights are granted to the 
+licensor's trademarks. The Apache license contains such a provision, but the 
+BSD, MIT and UoI/NCSA licenses do not.
+    
+* The AFL includes the warranty by the licensor that it either owns the 
+copyright or that it is distributing the software under a license. None of 
+the other licenses contain that warranty. All other warranties are disclaimed, 
+as is the case for the other licenses.
+
+* The AFL is itself copyrighted (with the right granted to copy and distribute 
+without modification). This ensures that the owner of the copyright to the 
+license will control changes. The Apache license contains a copyright notice, 
+but the BSD, MIT and UoI/NCSA licenses do not. 
+--
+START OF GNU GENERAL PUBLIC LICENSE
+--
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/dbus/tools/dbus-cleanup-sockets.c b/dbus/tools/dbus-cleanup-sockets.c
new file mode 100644
index 0000000..1b6709a
--- /dev/null
+++ b/dbus/tools/dbus-cleanup-sockets.c
@@ -0,0 +1,448 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-cleanup-sockets.c  dbus-cleanup-sockets utility
+ *
+ * Copyright (C) 2003 Red Hat, Inc.
+ * Copyright (C) 2002 Michael Meeks
+ *
+ * Note that this file is NOT licensed under the Academic Free License,
+ * as it is based on linc-cleanup-sockets which is LGPL.
+ *
+ * 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
+ *
+ */
+#include <config.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+static void*
+xmalloc (size_t bytes)
+{
+  void *mem;
+
+  if (bytes == 0)
+    return NULL;
+
+  mem = malloc (bytes);
+
+  if (mem == NULL)
+    {
+      fprintf (stderr, "Allocation of %d bytes failed\n",
+               (int) bytes);
+      exit (1);
+    }
+
+  return mem;
+}
+
+static void*
+xrealloc (void *old, size_t bytes)
+{
+  void *mem;
+
+  if (bytes == 0)
+    {
+      free (old);
+      return NULL;
+    }
+
+  mem = realloc (old, bytes);
+
+  if (mem == NULL)
+    {
+      fprintf (stderr, "Reallocation of %d bytes failed\n",
+               (int) bytes);
+      exit (1);
+    }
+
+  return mem;
+}
+
+#ifdef AF_UNIX
+
+typedef enum
+  {
+    SOCKET_UNKNOWN,
+    SOCKET_FAILED_TO_HANDLE,
+    SOCKET_DEAD,
+    SOCKET_ALIVE,
+    SOCKET_UNLINKED
+  } SocketStatus;
+
+static int alive_count = 0;
+static int cleaned_count = 0;
+static int unhandled_count = 0;
+
+typedef struct
+{
+  char *name;
+  int   fd;
+  SocketStatus status;
+  int   n_retries;
+} SocketEntry;
+
+static SocketEntry*
+socket_entry_new (const char *dir,
+                  const char *fname)
+{
+  SocketEntry *se;
+  int len;
+
+  se = xmalloc (sizeof (SocketEntry));
+
+  len = strlen (dir) + strlen (fname) + 2; /* 2 = nul and '/' */
+  se->name = xmalloc (len);
+
+  strcpy (se->name, dir);
+  strcat (se->name, "/");
+  strcat (se->name, fname);
+
+  se->fd = -1;
+
+  se->status = SOCKET_UNKNOWN;
+
+  se->n_retries = 0;
+
+  return se;
+}
+
+static void
+free_socket_entry (SocketEntry *se)
+{
+  if (se)
+    {
+      free (se->name);
+      if (se->fd >= 0)
+        close (se->fd);
+      free (se);
+    }
+}
+
+static void
+free_socket_entries (SocketEntry** entries,
+                     int           n_entries)
+{
+  int i;
+
+  if (entries)
+    {
+      for (i = 0; i < n_entries; ++i)
+        free_socket_entry (entries[i]);
+      free (entries);
+    }
+}
+
+static void
+read_sockets (const char    *dir,
+              SocketEntry ***entries_p,
+              int           *n_entries_p)
+{
+  DIR   *dirh;
+  struct dirent *dent;
+  SocketEntry **entries;
+  int n_entries;
+  int allocated;
+
+  n_entries = 0;
+  allocated = 2;
+  entries = xmalloc (sizeof (SocketEntry*) * allocated);
+
+  dirh = opendir (dir);
+  if (dirh == NULL)
+    {
+      fprintf (stderr, "Failed to open directory %s: %s\n",
+               dir, strerror (errno));
+      exit (1);
+    }
+
+  while ((dent = readdir (dirh)))
+    {
+      SocketEntry *se;
+
+      if (strncmp (dent->d_name, "dbus-", 5) != 0)
+        continue;
+
+      se = socket_entry_new (dir, dent->d_name);
+
+      if (n_entries == allocated)
+        {
+          allocated *= 2;
+          entries = xrealloc (entries, sizeof (SocketEntry*) * allocated);
+        }
+
+      entries[n_entries] = se;
+      n_entries += 1;
+    }
+
+  closedir (dirh);
+
+  *entries_p = entries;
+  *n_entries_p = n_entries;
+}
+
+static SocketStatus
+open_socket (SocketEntry *se)
+{
+  int ret;
+  struct sockaddr_un saddr;
+
+  if (se->n_retries > 5)
+    {
+      fprintf (stderr, "Warning: giving up on socket %s after several retries; unable to determine socket's status\n",
+               se->name);
+      return SOCKET_FAILED_TO_HANDLE;
+    }
+
+  se->n_retries += 1;
+
+  se->fd = socket (AF_UNIX, SOCK_STREAM, 0);
+  if (se->fd < 0)
+    {
+      fprintf (stderr, "Warning: failed to open a socket to use for connecting: %s\n",
+               strerror (errno));
+      return SOCKET_UNKNOWN;
+    }
+
+  if (fcntl (se->fd, F_SETFL, O_NONBLOCK) < 0)
+    {
+      fprintf (stderr, "Warning: failed set socket %s nonblocking: %s\n",
+               se->name, strerror (errno));
+      return SOCKET_UNKNOWN;
+    }
+
+
+  memset (&saddr, '\0', sizeof (saddr)); /* nul-terminates the sun_path */
+
+  saddr.sun_family = AF_UNIX;
+  strncpy (saddr.sun_path, se->name, sizeof (saddr.sun_path) - 1);
+
+  do
+    {
+      ret = connect (se->fd, (struct sockaddr*) &saddr, sizeof (saddr));
+    }
+  while (ret < 0 && errno == EINTR);
+
+  if (ret >= 0)
+    return SOCKET_ALIVE;
+  else
+    {
+      switch (errno)
+        {
+        case EINPROGRESS:
+        case EAGAIN:
+          return SOCKET_UNKNOWN;
+        case ECONNREFUSED:
+          return SOCKET_DEAD;
+        default:
+          fprintf (stderr, "Warning: unexpected error connecting to socket %s: %s\n",
+                   se->name, strerror (errno));
+          return SOCKET_FAILED_TO_HANDLE;
+        }
+    }
+}
+
+static int
+handle_sockets (SocketEntry **entries,
+                int           n_entries)
+{
+  int i;
+  int n_unknown;
+
+  n_unknown = 0;
+
+  i = 0;
+  while (i < n_entries)
+    {
+      SocketEntry *se;
+      SocketStatus status;
+
+      se = entries[i];
+      ++i;
+
+      if (se->fd >= 0)
+        {
+          fprintf (stderr, "Internal error, socket has fd  kept open while status = %d\n",
+                   se->status);
+          exit (1);
+        }
+
+      if (se->status != SOCKET_UNKNOWN)
+        continue;
+
+      status = open_socket (se);
+
+      switch (status)
+        {
+        case SOCKET_DEAD:
+          cleaned_count += 1;
+          if (unlink (se->name) < 0)
+            {
+              fprintf (stderr, "Warning: Failed to delete %s: %s\n",
+                       se->name, strerror (errno));
+
+              se->status = SOCKET_FAILED_TO_HANDLE;
+            }
+          else
+            se->status = SOCKET_UNLINKED;
+          break;
+
+        case SOCKET_ALIVE:
+          alive_count += 1;
+          /* FALL THRU */
+
+        case SOCKET_FAILED_TO_HANDLE:
+        case SOCKET_UNKNOWN:
+          se->status = status;
+          break;
+
+        case SOCKET_UNLINKED:
+          fprintf (stderr, "Bad status from open_socket(), should not happen\n");
+          exit (1);
+          break;
+        }
+
+      if (se->fd >= 0)
+        {
+          close (se->fd);
+          se->fd = -1;
+        }
+
+      if (se->status == SOCKET_UNKNOWN)
+        n_unknown += 1;
+    }
+
+  return n_unknown == 0;
+}
+
+static void
+clean_dir (const char *dir)
+{
+  SocketEntry **entries;
+  int n_entries;
+
+  read_sockets (dir, &entries, &n_entries);
+
+  /* open_socket() will fail conclusively after
+   * several retries, so this loop is guaranteed
+   * to terminate eventually
+   */
+  while (!handle_sockets (entries, n_entries))
+    {
+      fprintf (stderr, "Unable to determine state of some sockets, retrying in 2 seconds\n");
+      sleep (2);
+    }
+
+  unhandled_count += (n_entries - alive_count - cleaned_count);
+
+  free_socket_entries (entries, n_entries);
+}
+
+#endif /* AF_UNIX */
+
+static void
+usage (int ecode)
+{
+  fprintf (stderr, "dbus-cleanup-sockets [--version] [--help] <socketdir>\n");
+  exit (ecode);
+}
+
+static void
+version (void)
+{
+  printf ("D-Bus Socket Cleanup Utility %s\n"
+          "Copyright (C) 2003 Red Hat, Inc.\n"
+          "Copyright (C) 2002 Michael Meeks\n"
+          "This is free software; see the source for copying conditions.\n"
+          "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
+          VERSION);
+  exit (0);
+}
+
+int
+main (int argc, char **argv)
+{
+  int i;
+  int saw_doubledash;
+  const char *dirname;
+
+  saw_doubledash = FALSE;
+  dirname = NULL;
+  i = 1;
+  while (i < argc)
+    {
+      const char *arg = argv[i];
+
+      if (strcmp (arg, "--help") == 0 ||
+          strcmp (arg, "-h") == 0 ||
+          strcmp (arg, "-?") == 0)
+        usage (0);
+      else if (strcmp (arg, "--version") == 0)
+        version ();
+      else if (!saw_doubledash)
+	{
+          if (strcmp (arg, "--") == 0)
+            saw_doubledash = TRUE;
+          else if (*arg == '-')
+            usage (1);
+	}
+      else
+        {
+          if (dirname != NULL)
+            {
+              fprintf (stderr, "dbus-cleanup-sockets only supports a single directory name\n");
+              exit (1);
+            }
+
+          dirname = arg;
+        }
+
+      ++i;
+    }
+
+  /* Default to session socket dir, usually /tmp */
+  if (dirname == NULL)
+    dirname = DBUS_SESSION_SOCKET_DIR;
+
+#ifdef AF_UNIX
+  clean_dir (dirname);
+
+  printf ("Cleaned up %d sockets in %s; %d sockets are still in use; %d in unknown state\n",
+          cleaned_count, dirname, alive_count, unhandled_count);
+#else
+  printf ("This system does not support UNIX domain sockets, so dbus-cleanup-sockets does nothing\n");
+#endif
+
+  return 0;
+}
diff --git a/dbus/tools/dbus-launch-win.c b/dbus/tools/dbus-launch-win.c
new file mode 100644
index 0000000..215fac3
--- /dev/null
+++ b/dbus/tools/dbus-launch-win.c
@@ -0,0 +1,171 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-launch-win.c  dbus-launch utility
+ *
+ * Copyright (C) 2007 Ralf Habacker <ralf.habacker@freenet.de>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#ifndef UNICODE
+#define UNICODE 1
+#endif
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+/* Save string functions.  Instead of figuring out the exact _MSC_VER
+   that work, override for everybody.  */
+
+#define errno_t int
+#define wcscat_s my_wcscat_s
+#define wcscpy_s my_wcscpy_s
+
+static errno_t
+wcscat_s (wchar_t *dest, size_t size, wchar_t *src) 
+{
+  assert (sizeof (wchar_t) * (wcslen (dest) + wcslen (src) + 1) <= size);
+  wcscat (dest, src);
+  return 0;
+}
+
+
+static errno_t
+wcscpy_s (wchar_t *dest, size_t size, wchar_t *src)
+{
+  assert (sizeof (wchar_t) * (wcslen (src) + 1) <= size);
+  wcscpy (dest, src);
+  return 0;
+}
+
+/* TODO (tl): This Windows version of dbus-launch is curretly rather
+ * pointless as it doesn't take the same command-line options as the
+ * UNIX dbus-launch does. A main point of the dbus-launch command is
+ * to pass it for instance a --config-file option to make the started
+ * dbus-daemon use that config file.
+ * 
+ * This version also doesn't print out any information, which is a
+ * main point of the UNIX one. It should at least support the
+ * --sh-syntax option, and maybe also a --cmd-syntax to print out the
+ * variable settings in cmd.exe syntax?
+ * 
+ * NOTE (rh): The main task of dbus-launch is (from the man page) to start 
+ * a session bus and this is archieved by the current implemention. 
+ * 
+ * Additional on windows the session bus starting in not integrated 
+ * into the logon process, so there is no need for any --syntax option. 
+ * In fact (at least for kde on windows) the session bus is autostarted 
+ * with the first application requesting a session bus. 
+ *
+ */
+
+#define AUTO_ACTIVATE_CONSOLE_WHEN_VERBOSE_MODE 1
+
+#define DIM(x) (sizeof(x) / sizeof(x[0]))
+#define WCSTRINGIFY_(x) L ## x
+#define WCSTRINGIFY(x) WCSTRINGIFY_(x)
+
+int
+main (int argc, char **argv)
+{
+  wchar_t dbusDaemonPath[MAX_PATH * 2 + 1];
+  wchar_t command[MAX_PATH * 2 + 1];
+  wchar_t *p;
+  wchar_t *daemon_name;
+  int result;
+  int showConsole = 0;
+#ifdef DBUS_WINCE
+  char *s = NULL;
+#else
+  char *s = getenv("DBUS_VERBOSE");
+#endif
+  int verbose = s && *s != '\0' ? 1 : 0;
+
+  PROCESS_INFORMATION pi;
+  STARTUPINFOW si;
+  BOOL inherit = TRUE;
+  DWORD flags = 0;
+
+#ifdef AUTO_ACTIVATE_CONSOLE_WHEN_VERBOSE_MODE
+  if (verbose)
+      showConsole = 1; 
+#endif
+  GetModuleFileNameW (NULL, dbusDaemonPath, DIM (dbusDaemonPath));
+  
+  daemon_name = WCSTRINGIFY(DBUS_DAEMON_NAME) L".exe";
+  
+  if ((p = wcsrchr (dbusDaemonPath, L'\\'))) 
+    {
+      p[1] = L'\0';
+      wcscat_s (dbusDaemonPath, sizeof (dbusDaemonPath), daemon_name);
+    }
+  else 
+    {
+      if (verbose)
+          fprintf (stderr, "error: could not extract path from current "
+                   "applications module filename\n");
+      return 1;
+    } 
+
+#ifdef DBUS_WINCE
+   /* Windows CE has a different interpretation of cmdline: Start with argv[1].  */
+   wcscpy_s (command, sizeof (command), L"--session");
+   if (verbose)
+     fprintf (stderr, "%ls %ls\n", dbusDaemonPath, command);
+#else
+   command[0] = L'\0';
+   /* Windows cmdline starts with path, which can contain spaces.  */
+   wcscpy_s (command, sizeof (command), L"\"");
+   wcscat_s (command, sizeof (command), dbusDaemonPath);
+   wcscat_s (command, sizeof (command), L"\" --session");
+   if (verbose)
+     fprintf (stderr, "%ls\n", command);
+#endif
+  
+  memset (&si, 0, sizeof (si));
+  memset (&pi, 0, sizeof (pi));
+  si.cb = sizeof (si);
+  
+  if (verbose)
+    flags |= CREATE_NEW_CONSOLE;
+
+#ifdef DBUS_WINCE
+  inherit = FALSE;
+#else
+  flags |= NORMAL_PRIORITY_CLASS;
+  if (!verbose)
+    flags |= DETACHED_PROCESS;
+#endif
+
+  result = CreateProcessW (dbusDaemonPath, command, 0, 0,
+                           inherit, flags, 0, 0, &si, &pi);
+
+  if (result == 0) 
+    {
+      if (verbose)
+        fprintf (stderr, "Could not start " DBUS_DAEMON_NAME ". error=%d\n",
+                 GetLastError ());
+      return 4;
+    }
+   
+  CloseHandle (pi.hProcess);
+  CloseHandle (pi.hThread);
+
+  return 0;
+}
diff --git a/dbus/tools/dbus-launch-x11.c b/dbus/tools/dbus-launch-x11.c
new file mode 100644
index 0000000..c7e3330
--- /dev/null
+++ b/dbus/tools/dbus-launch-x11.c
@@ -0,0 +1,468 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-launch.h  dbus-launch utility
+ *
+ * Copyright (C) 2006 Thiago Macieira <thiago@kde.org>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-launch.h"
+
+#ifdef DBUS_BUILD_X11
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+Display *xdisplay = NULL;
+static Atom selection_atom;
+static Atom address_atom;
+static Atom pid_atom;
+
+static int
+x_io_error_handler (Display *xdisplay)
+{
+  verbose ("X IO error\n");
+  kill_bus_and_exit (0);
+  return 0;
+}
+
+static void
+remove_prefix (char *s,
+               char *prefix)
+{
+  int plen;
+
+  plen = strlen (prefix);
+
+  if (strncmp (s, prefix, plen) == 0)
+    {
+      memmove (s, s + plen, strlen (s) - plen + 1);
+    }
+}
+
+static const char*
+get_homedir (void)
+{
+  const char *home;
+  
+  home = getenv ("HOME");
+  if (home == NULL)
+    {
+      /* try from the user database */
+      struct passwd *user = getpwuid (getuid());
+      if (user != NULL)
+        home = user->pw_dir;
+    }
+
+  if (home == NULL)
+    {
+      fprintf (stderr, "Can't get user home directory\n");
+      exit (1);
+    }
+
+  return home;
+}
+
+#define DBUS_DIR ".dbus"
+#define DBUS_SESSION_BUS_DIR "session-bus"
+
+static char *
+get_session_file (void)
+{
+  static const char prefix[] = "/" DBUS_DIR "/" DBUS_SESSION_BUS_DIR "/";
+  const char *machine;
+  const char *home;
+  char *display;
+  char *result;
+  char *p;
+
+  machine = get_machine_uuid ();
+  if (machine == NULL)
+    return NULL;
+
+  display = xstrdup (getenv ("DISPLAY"));
+  if (display == NULL)
+    {
+      verbose ("X11 integration disabled because X11 is not running\n");
+      return NULL;
+    }
+
+  /* remove the screen part of the display name */
+  p = strrchr (display, ':');
+  if (p != NULL)
+    {
+      for ( ; *p; ++p)
+        {
+          if (*p == '.')
+            {
+              *p = '\0';
+              break;
+            }
+        }
+    }
+
+  /* Note that we leave the hostname in the display most of the
+   * time. The idea is that we want to be per-(machine,display,user)
+   * triplet to be extra-sure we get a bus we can connect to. Ideally
+   * we'd recognize when the hostname matches the machine we're on in
+   * all cases; we do try to drop localhost and localhost.localdomain
+   * as a special common case so that alternate spellings of DISPLAY
+   * don't result in extra bus instances.
+   *
+   * We also kill the ":" if there's nothing in front of it. This
+   * avoids an ugly double underscore in the filename.
+   */
+  remove_prefix (display, "localhost.localdomain:");
+  remove_prefix (display, "localhost:");
+  remove_prefix (display, ":");
+
+  /* replace the : in the display with _ if the : is still there.
+   * use _ instead of - since it can't be in hostnames.
+   */
+  for (p = display; *p; ++p)
+    {
+      if (*p == ':')
+        *p = '_';
+    }
+  
+  home = get_homedir ();
+  
+  result = malloc (strlen (home) + strlen (prefix) + strlen (machine) +
+                   strlen (display) + 2);
+  if (result == NULL)
+    {
+      /* out of memory */
+      free (display);
+      return NULL;
+    }
+
+  strcpy (result, home);
+  strcat (result, prefix);
+  strcat (result, machine);
+  strcat (result, "-");
+  strcat (result, display);
+  free (display);
+
+  verbose ("session file: %s\n", result);
+  return result;
+}
+
+static void
+ensure_session_directory (void)
+{
+  const char *home;
+  char *dir;
+  
+  home = get_homedir ();
+
+  /* be sure we have space for / and nul */
+  dir = malloc (strlen (home) + strlen (DBUS_DIR) + strlen (DBUS_SESSION_BUS_DIR) + 3);
+  if (dir == NULL)
+    {
+      fprintf (stderr, "no memory\n");
+      exit (1);
+    }
+  
+  strcpy (dir, home);
+  strcat (dir, "/");
+  strcat (dir, DBUS_DIR);
+
+  if (mkdir (dir, 0700) < 0)
+    {
+      /* only print a warning here, writing the session file itself will fail later */
+      if (errno != EEXIST)
+        fprintf (stderr, "Unable to create %s\n", dir);
+    }
+
+  strcat (dir, "/");
+  strcat (dir, DBUS_SESSION_BUS_DIR);
+
+  if (mkdir (dir, 0700) < 0)
+    {
+      /* only print a warning here, writing the session file itself will fail later */
+      if (errno != EEXIST)
+        fprintf (stderr, "Unable to create %s\n", dir);
+    }
+  
+  free (dir);
+}
+
+static Display *
+open_x11 (void)
+{
+  if (xdisplay != NULL)
+    return xdisplay;
+
+  xdisplay = XOpenDisplay (NULL);
+  if (xdisplay != NULL)
+    {
+      verbose ("Connected to X11 display '%s'\n", DisplayString (xdisplay));
+      XSetIOErrorHandler (x_io_error_handler);
+    }
+  return xdisplay;
+}
+
+static int
+init_x_atoms (Display *display)
+{
+  static const char selection_prefix[] = "_DBUS_SESSION_BUS_SELECTION_";
+  static const char address_prefix[] = "_DBUS_SESSION_BUS_ADDRESS";
+  static const char pid_prefix[] = "_DBUS_SESSION_BUS_PID";
+  static int init = FALSE;
+  char *atom_name;
+  const char *machine;
+  char *user_name;
+  struct passwd *user;
+
+  if (init)
+    return TRUE;
+
+  machine = get_machine_uuid ();
+  if (machine == NULL)
+    return FALSE;
+
+  user = getpwuid (getuid ());
+  if (user == NULL)
+    {
+      verbose ("Could not determine user information; aborting X11 integration.\n");
+      return FALSE;
+    }
+  user_name = xstrdup(user->pw_name);
+
+  atom_name = malloc (strlen (machine) + strlen (user_name) + 2 +
+                      MAX (strlen (selection_prefix),
+                           MAX (strlen (address_prefix),
+                                strlen (pid_prefix))));
+  if (atom_name == NULL)
+    {
+      verbose ("Could not create X11 atoms; aborting X11 integration.\n");
+      free (user_name);
+      return FALSE;
+    }
+
+  /* create the selection atom */
+  strcpy (atom_name, selection_prefix);
+  strcat (atom_name, user_name);
+  strcat (atom_name, "_");
+  strcat (atom_name, machine);
+  selection_atom = XInternAtom (display, atom_name, FALSE);
+
+  /* create the address property atom */
+  strcpy (atom_name, address_prefix);
+  address_atom = XInternAtom (display, atom_name, FALSE);
+
+  /* create the PID property atom */
+  strcpy (atom_name, pid_prefix);
+  pid_atom = XInternAtom (display, atom_name, FALSE);
+
+  free (atom_name);
+  free (user_name);
+  init = TRUE;
+  return TRUE;
+}
+
+/*
+ * Gets the daemon address from the X11 display.
+ * Returns FALSE if there was an error. Returning
+ * TRUE does not mean the address exists.
+ */
+int
+x11_get_address (char **paddress, pid_t *pid, long *wid)
+{
+  int result;
+  Atom type;
+  Window owner;
+  int format;
+  unsigned long items;
+  unsigned long after;
+  char *data;
+
+  *paddress = NULL;
+
+  /* locate the selection owner */
+  owner = XGetSelectionOwner (xdisplay, selection_atom);
+  if (owner == None)
+    return TRUE;                /* no owner */
+  if (wid != NULL)
+    *wid = (long) owner;
+
+  /* get the bus address */
+  result = XGetWindowProperty (xdisplay, owner, address_atom, 0, 1024, False,
+                              XA_STRING, &type, &format, &items, &after,
+                              (unsigned char **) &data);
+  if (result != Success || type == None || after != 0 || data == NULL || format != 8)
+    return FALSE;               /* error */
+
+  *paddress = xstrdup (data);
+  XFree (data);
+
+  /* get the PID */
+  if (pid != NULL)
+    {
+      *pid = 0;
+      result = XGetWindowProperty (xdisplay, owner, pid_atom, 0, sizeof pid, False,
+                                   XA_CARDINAL, &type, &format, &items, &after,
+                                   (unsigned char **) &data);
+      if (result == Success && type != None && after == 0 && data != NULL && format == 32)
+        *pid = (pid_t) *(long*) data;
+      XFree (data);
+    }
+
+  return TRUE;                  /* success */
+}
+
+/*
+ * Saves the address in the X11 display. Returns 0 on success.
+ * If an error occurs, returns -1. If the selection already exists,
+ * returns 1. (i.e. another daemon is already running)
+ */
+static Window
+set_address_in_x11(char *address, pid_t pid)
+{
+  char *current_address;
+  Window wid = None;
+  unsigned long pid32; /* Xlib property functions want _long_ not 32-bit for format "32" */
+  
+  /* lock the X11 display to make sure we're doing this atomically */
+  XGrabServer (xdisplay);
+
+  if (!x11_get_address (&current_address, NULL, NULL))
+    {
+      /* error! */
+      goto out;
+    }
+
+  if (current_address != NULL)
+    {
+      /* someone saved the address in the meantime */
+      free (current_address);
+      goto out;
+    }
+
+  /* Create our window */
+  wid = XCreateWindow (xdisplay, RootWindow (xdisplay, 0), -20, -20, 10, 10,
+                       0, CopyFromParent, InputOnly, CopyFromParent,
+                       0, NULL);
+  verbose ("Created window %d\n", wid);
+
+  /* Save the property in the window */
+  XChangeProperty (xdisplay, wid, address_atom, XA_STRING, 8, PropModeReplace,
+                   (unsigned char *)address, strlen (address));
+  pid32 = pid;
+  XChangeProperty (xdisplay, wid, pid_atom, XA_CARDINAL, 32, PropModeReplace,
+                   (unsigned char *)&pid32, 1);
+
+  /* Now grab the selection */
+  XSetSelectionOwner (xdisplay, selection_atom, wid, CurrentTime);
+
+ out:
+  /* Ungrab the server to let other people use it too */
+  XUngrabServer (xdisplay);
+
+  /* And make sure that the ungrab gets sent to X11 */
+  XFlush (xdisplay);
+
+  return wid;
+}
+
+/*
+ * Saves the session address in session file. Returns TRUE on
+ * success, FALSE if an error occurs.
+ */
+static int
+set_address_in_file (char *address, pid_t pid, Window wid)
+{
+  char *session_file;
+  FILE *f;
+
+  ensure_session_directory ();
+  session_file = get_session_file();
+  if (session_file == NULL)
+    return FALSE;
+
+  f = fopen (session_file, "w");
+  free (session_file);
+  if (f == NULL)
+    return FALSE;               /* some kind of error */
+  fprintf (f,
+           "# This file allows processes on the machine with id %s using \n"
+           "# display %s to find the D-Bus session bus with the below address.\n"
+           "# If the DBUS_SESSION_BUS_ADDRESS environment variable is set, it will\n"
+           "# be used rather than this file.\n"
+           "# See \"man dbus-launch\" for more details.\n"
+           "DBUS_SESSION_BUS_ADDRESS=%s\n"
+           "DBUS_SESSION_BUS_PID=%ld\n"
+           "DBUS_SESSION_BUS_WINDOWID=%ld\n",
+           get_machine_uuid (),
+           getenv ("DISPLAY"),
+           address, (long)pid, (long)wid);
+
+  fclose (f);
+
+  return TRUE;
+}
+
+int
+x11_save_address (char *address, pid_t pid, long *wid)
+{
+  Window id = set_address_in_x11 (address, pid);
+  if (id != None)
+    {
+      if (!set_address_in_file (address, pid, id))
+        return FALSE;
+
+      if (wid != NULL)
+        *wid = (long) id;
+      return TRUE;
+    }
+  return FALSE;
+}
+
+int
+x11_init (void)
+{
+  return open_x11 () != NULL && init_x_atoms (xdisplay);
+}
+
+void
+x11_handle_event (void)
+{
+  if (xdisplay != NULL)
+    {      
+      while (XPending (xdisplay))
+        {
+          XEvent ignored;
+          XNextEvent (xdisplay, &ignored);
+        }
+    }
+}  
+
+#else
+void dummy_dbus_launch_x11 (void);
+
+void dummy_dbus_launch_x11 (void) { }
+#endif
diff --git a/dbus/tools/dbus-launch.c b/dbus/tools/dbus-launch.c
new file mode 100644
index 0000000..1ec9ae5
--- /dev/null
+++ b/dbus/tools/dbus-launch.c
@@ -0,0 +1,1278 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-launch.c  dbus-launch utility
+ *
+ * Copyright (C) 2003, 2006 Red Hat, Inc.
+ * Copyright (C) 2006 Thiago Macieira <thiago@kde.org>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-launch.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <sys/select.h>
+#include <time.h>
+
+#ifdef DBUS_BUILD_X11
+#include <X11/Xlib.h>
+extern Display *xdisplay;
+#endif
+
+/* PROCESSES
+ *
+ * If you are in a shell and run "dbus-launch myapp", here is what happens:
+ *
+ * shell [*]
+ *   \- main()               --exec--> myapp[*]
+ *      \- "intermediate parent"
+ *         \- bus-runner     --exec--> dbus-daemon --fork
+ *         \- babysitter[*]            \- final dbus-daemon[*]
+ *
+ * Processes marked [*] survive the initial flurry of activity.
+ *
+ * If you run "dbus-launch --sh-syntax" then the diagram is the same, except
+ * that main() prints variables and exits 0 instead of exec'ing myapp.
+ *
+ * PIPES
+ *
+ * dbus-daemon --print-pid     -> bus_pid_to_launcher_pipe     -> main
+ * dbus-daemon --print-address -> bus_address_to_launcher_pipe -> main
+ * main                        -> bus_pid_to_babysitter_pipe   -> babysitter
+ *
+ * The intermediate parent looks pretty useless at first glance. Its purpose
+ * is to avoid the bus-runner becoming a zombie: when the intermediate parent
+ * terminates, the bus-runner and babysitter are reparented to init, which
+ * reaps them if they have finished. We can't rely on main() to reap arbitrary
+ * children because it might exec myapp, after which it can't be relied on to
+ * reap its children. We *can* rely on main() to reap the intermediate parent,
+ * because that happens before it execs myapp.
+ *
+ * It's unclear why dbus-daemon needs to fork, but we explicitly tell it to
+ * for some reason, then wait for it. If we left it undefined, a forking
+ * dbus-daemon would get the parent process reparented to init and reaped
+ * when the intermediate parent terminated, and a non-forking dbus-daemon
+ * would get reparented to init and carry on there.
+ *
+ * myapp is exec'd by the process that initially ran main() so that it's
+ * the shell's child, so the shell knows how to do job control and stuff.
+ * This is desirable for the "dbus-launch an application" use-case, less so
+ * for the "dbus-launch a test suite in an isolated session" use-case.
+ */
+
+static char* machine_uuid = NULL;
+
+const char*
+get_machine_uuid (void)
+{
+  return machine_uuid;
+}
+
+static void
+save_machine_uuid (const char *uuid_arg)
+{
+  if (strlen (uuid_arg) != 32)
+    {
+      fprintf (stderr, "machine ID '%s' looks like it's the wrong length, should be 32 hex digits",
+               uuid_arg);
+      exit (1);
+    }
+
+  machine_uuid = xstrdup (uuid_arg);
+}
+
+#define UUID_MAXLEN 40
+/* Read the machine uuid from file if needed. Returns TRUE if machine_uuid is
+ * set after this function */
+static int
+read_machine_uuid_if_needed (void)
+{
+  FILE *f;
+  char uuid[UUID_MAXLEN];
+  size_t len;
+  int ret = FALSE;
+
+  if (machine_uuid != NULL)
+    return TRUE;
+
+  f = fopen (DBUS_MACHINE_UUID_FILE, "r");
+  if (f == NULL)
+    return FALSE;
+
+  if (fgets (uuid, UUID_MAXLEN, f) == NULL)
+    goto out;
+
+  len = strlen (uuid);
+  if (len < 32)
+    goto out;
+
+  /* rstrip the read uuid */
+  while (len > 31 && isspace(uuid[len - 1]))
+    len--;
+
+  if (len != 32)
+    goto out;
+
+  uuid[len] = '\0';
+  machine_uuid = xstrdup (uuid);
+  verbose ("UID: %s\n", machine_uuid);
+  ret = TRUE;
+
+out:
+  fclose(f);
+  return ret;
+}
+
+
+void
+verbose (const char *format,
+         ...)
+{
+  va_list args;
+  static int verbose = TRUE;
+  static int verbose_initted = FALSE;
+  
+  /* things are written a bit oddly here so that
+   * in the non-verbose case we just have the one
+   * conditional and return immediately.
+   */
+  if (!verbose)
+    return;
+  
+  if (!verbose_initted)
+    {
+      verbose = getenv ("DBUS_VERBOSE") != NULL;
+      verbose_initted = TRUE;
+      if (!verbose)
+        return;
+    }
+
+  fprintf (stderr, "%lu: ", (unsigned long) getpid ());
+  
+  va_start (args, format);
+  vfprintf (stderr, format, args);
+  va_end (args);
+}
+
+static void
+usage (int ecode)
+{
+  fprintf (stderr, "dbus-launch [--version] [--help] [--sh-syntax] [--csh-syntax] [--auto-syntax] [--exit-with-session]\n");
+  exit (ecode);
+}
+
+static void
+version (void)
+{
+  printf ("D-Bus Message Bus Launcher %s\n"
+          "Copyright (C) 2003 Red Hat, Inc.\n"
+          "This is free software; see the source for copying conditions.\n"
+          "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
+          VERSION);
+  exit (0);
+}
+
+char *
+xstrdup (const char *str)
+{
+  int len;
+  char *copy;
+  
+  if (str == NULL)
+    return NULL;
+  
+  len = strlen (str);
+
+  copy = malloc (len + 1);
+  if (copy == NULL)
+    return NULL;
+
+  memcpy (copy, str, len + 1);
+  
+  return copy;
+}
+
+typedef enum
+{
+  READ_STATUS_OK,    /**< Read succeeded */
+  READ_STATUS_ERROR, /**< Some kind of error */
+  READ_STATUS_EOF    /**< EOF returned */
+} ReadStatus;
+
+static ReadStatus
+read_line (int        fd,
+           char      *buf,
+           size_t     maxlen)
+{
+  size_t bytes = 0;
+  ReadStatus retval;
+
+  memset (buf, '\0', maxlen);
+  maxlen -= 1; /* ensure nul term */
+  
+  retval = READ_STATUS_OK;
+  
+  while (TRUE)
+    {
+      ssize_t chunk;    
+      size_t to_read;
+      
+    again:
+      to_read = maxlen - bytes;
+
+      if (to_read == 0)
+        break;
+      
+      chunk = read (fd,
+                    buf + bytes,
+                    to_read);
+      if (chunk < 0 && errno == EINTR)
+        goto again;
+          
+      if (chunk < 0)
+        {
+          retval = READ_STATUS_ERROR;
+          break;
+        }
+      else if (chunk == 0)
+        {
+          retval = READ_STATUS_EOF;
+          break; /* EOF */
+        }
+      else /* chunk > 0 */
+	bytes += chunk;
+    }
+
+  if (retval == READ_STATUS_EOF &&
+      bytes > 0)
+    retval = READ_STATUS_OK;
+  
+  /* whack newline */
+  if (retval != READ_STATUS_ERROR &&
+      bytes > 0 &&
+      buf[bytes-1] == '\n')
+    buf[bytes-1] = '\0';
+  
+  return retval;
+}
+
+static ReadStatus
+read_pid (int        fd,
+          pid_t     *buf)
+{
+  size_t bytes = 0;
+  ReadStatus retval;
+
+  retval = READ_STATUS_OK;
+  
+  while (TRUE)
+    {
+      ssize_t chunk;    
+      size_t to_read;
+      
+    again:
+      to_read = sizeof (pid_t) - bytes;
+
+      if (to_read == 0)
+        break;
+      
+      chunk = read (fd,
+                    ((char*)buf) + bytes,
+                    to_read);
+      if (chunk < 0 && errno == EINTR)
+        goto again;
+          
+      if (chunk < 0)
+        {
+          retval = READ_STATUS_ERROR;
+          break;
+        }
+      else if (chunk == 0)
+        {
+          retval = READ_STATUS_EOF;
+          break; /* EOF */
+        }
+      else /* chunk > 0 */
+	bytes += chunk;
+    }
+
+  return retval;
+}
+
+static void
+do_write (int fd, const void *buf, size_t count)
+{
+  size_t bytes_written;
+  int ret;
+  
+  bytes_written = 0;
+  
+ again:
+  
+  ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
+
+  if (ret < 0)
+    {
+      if (errno == EINTR)
+        goto again;
+      else
+        {
+          fprintf (stderr, "Failed to write data to pipe! %s\n",
+                   strerror (errno));
+          exit (1); /* give up, we suck */
+        }
+    }
+  else
+    bytes_written += ret;
+  
+  if (bytes_written < count)
+    goto again;
+}
+
+static void
+write_pid (int   fd,
+           pid_t pid)
+{
+  do_write (fd, &pid, sizeof (pid));
+}
+
+static int
+do_waitpid (pid_t pid)
+{
+  int ret;
+  
+ again:
+  ret = waitpid (pid, NULL, 0);
+
+  if (ret < 0 &&
+      errno == EINTR)
+    goto again;
+
+  return ret;
+}
+
+static pid_t bus_pid_to_kill = -1;
+
+static void
+kill_bus(void)
+{
+  verbose ("Killing message bus and exiting babysitter\n");
+  kill (bus_pid_to_kill, SIGTERM);
+  sleep (3);
+  kill (bus_pid_to_kill, SIGKILL);
+}
+
+void
+kill_bus_and_exit (int exitcode)
+{
+  /* in case these point to any NFS mounts, get rid of them immediately */
+  close (0);
+  close (1);
+  close (2);
+
+  kill_bus();
+
+  exit (exitcode);
+}
+
+static void
+print_variables (const char *bus_address, pid_t bus_pid, long bus_wid,
+		 int c_shell_syntax, int bourne_shell_syntax,
+		 int binary_syntax)
+{
+  if (binary_syntax)
+    {
+      do_write (1, bus_address, strlen (bus_address) + 1);
+      do_write (1, &bus_pid, sizeof bus_pid);
+      do_write (1, &bus_wid, sizeof bus_wid);
+      return;
+    }
+  else if (c_shell_syntax)
+    {
+      printf ("setenv DBUS_SESSION_BUS_ADDRESS '%s';\n", bus_address);	
+      printf ("set DBUS_SESSION_BUS_PID=%ld;\n", (long) bus_pid);
+      if (bus_wid)
+        printf ("set DBUS_SESSION_BUS_WINDOWID=%ld;\n", (long) bus_wid);
+      fflush (stdout);
+    }
+  else if (bourne_shell_syntax)
+    {
+      printf ("DBUS_SESSION_BUS_ADDRESS='%s';\n", bus_address);
+      printf ("export DBUS_SESSION_BUS_ADDRESS;\n");
+      printf ("DBUS_SESSION_BUS_PID=%ld;\n", (long) bus_pid);
+      if (bus_wid)
+        printf ("DBUS_SESSION_BUS_WINDOWID=%ld;\n", (long) bus_wid);
+      fflush (stdout);
+    }
+  else
+    {
+      printf ("DBUS_SESSION_BUS_ADDRESS=%s\n", bus_address);
+      printf ("DBUS_SESSION_BUS_PID=%ld\n", (long) bus_pid);
+      if (bus_wid)
+	printf ("DBUS_SESSION_BUS_WINDOWID=%ld\n", (long) bus_wid);
+      fflush (stdout);
+    }
+}
+
+static int got_sighup = FALSE;
+
+static void
+signal_handler (int sig)
+{
+  switch (sig)
+    {
+#ifdef SIGHUP
+    case SIGHUP:
+#endif
+    case SIGINT:
+    case SIGTERM:
+      got_sighup = TRUE;
+      break;
+    }
+}
+
+static void
+kill_bus_when_session_ends (void)
+{
+  int tty_fd;
+  int x_fd;
+  fd_set read_set;
+  fd_set err_set;
+  struct sigaction act;
+  sigset_t empty_mask;
+  
+  /* install SIGHUP handler */
+  got_sighup = FALSE;
+  sigemptyset (&empty_mask);
+  act.sa_handler = signal_handler;
+  act.sa_mask    = empty_mask;
+  act.sa_flags   = 0;
+  sigaction (SIGHUP,  &act, NULL);
+  sigaction (SIGTERM,  &act, NULL);
+  sigaction (SIGINT,  &act, NULL);
+  
+#ifdef DBUS_BUILD_X11
+  x11_init();
+  if (xdisplay != NULL)
+    {
+      x_fd = ConnectionNumber (xdisplay);
+    }
+  else
+    x_fd = -1;
+#else
+  x_fd = -1;
+#endif
+
+  if (isatty (0))
+    tty_fd = 0;
+  else
+    tty_fd = -1;
+
+  if (x_fd >= 0)
+    {
+      verbose ("session lifetime is defined by X, not monitoring stdin\n");
+      tty_fd = -1;
+    }
+  else if (tty_fd >= 0)
+    {
+      verbose ("stdin isatty(), monitoring it\n");
+    }
+  else
+    {
+      verbose ("stdin was not a TTY, not monitoring it\n");
+    }
+
+  if (tty_fd < 0 && x_fd < 0)
+    {
+      fprintf (stderr, "No terminal on standard input and no X display; cannot attach message bus to session lifetime\n");
+      exit (1);
+    }
+  
+  while (TRUE)
+    {
+#ifdef DBUS_BUILD_X11
+      /* Dump events on the floor, and let
+       * IO error handler run if we lose
+       * the X connection. It's important to
+       * run this before going into select() since
+       * we might have queued outgoing messages or
+       * events.
+       */
+      x11_handle_event ();
+#endif
+      
+      FD_ZERO (&read_set);
+      FD_ZERO (&err_set);
+
+      if (tty_fd >= 0)
+        {
+          FD_SET (tty_fd, &read_set);
+          FD_SET (tty_fd, &err_set);
+        }
+
+      if (x_fd >= 0)
+        {
+          FD_SET (x_fd, &read_set);
+          FD_SET (x_fd, &err_set);
+        }
+
+      select (MAX (tty_fd, x_fd) + 1,
+              &read_set, NULL, &err_set, NULL);
+
+      if (got_sighup)
+        {
+          verbose ("Got SIGHUP, exiting\n");
+          kill_bus_and_exit (0);
+        }
+      
+#ifdef DBUS_BUILD_X11
+      /* Events will be processed before we select again
+       */
+      if (x_fd >= 0)
+        verbose ("X fd condition reading = %d error = %d\n",
+                 FD_ISSET (x_fd, &read_set),
+                 FD_ISSET (x_fd, &err_set));
+#endif
+
+      if (tty_fd >= 0)
+        {
+          if (FD_ISSET (tty_fd, &read_set))
+            {
+              int bytes_read;
+              char discard[512];
+
+              verbose ("TTY ready for reading\n");
+              
+              bytes_read = read (tty_fd, discard, sizeof (discard));
+
+              verbose ("Read %d bytes from TTY errno = %d\n",
+                       bytes_read, errno);
+              
+              if (bytes_read == 0)
+                kill_bus_and_exit (0); /* EOF */
+              else if (bytes_read < 0 && errno != EINTR)
+                {
+                  /* This shouldn't happen I don't think; to avoid
+                   * spinning on the fd forever we exit.
+                   */
+                  fprintf (stderr, "dbus-launch: error reading from stdin: %s\n",
+                           strerror (errno));
+                  kill_bus_and_exit (0);
+                }
+            }
+          else if (FD_ISSET (tty_fd, &err_set))
+            {
+              verbose ("TTY has error condition\n");
+              
+              kill_bus_and_exit (0);
+            }
+        }
+    }
+}
+
+static void
+babysit (int   exit_with_session,
+         pid_t child_pid,
+         int   read_bus_pid_fd)  /* read pid from here */
+{
+  int ret;
+  int dev_null_fd;
+  const char *s;
+
+  verbose ("babysitting, exit_with_session = %d, child_pid = %ld, read_bus_pid_fd = %d\n",
+           exit_with_session, (long) child_pid, read_bus_pid_fd);
+  
+  /* We chdir ("/") since we are persistent and daemon-like, and fork
+   * again so dbus-launch can reap the parent.  However, we don't
+   * setsid() or close fd 0 because the idea is to remain attached
+   * to the tty and the X server in order to kill the message bus
+   * when the session ends.
+   */
+
+  if (chdir ("/") < 0)
+    {
+      fprintf (stderr, "Could not change to root directory: %s\n",
+               strerror (errno));
+      exit (1);
+    }
+
+  /* Close stdout/stderr so we don't block an "eval" or otherwise
+   * lock up. stdout is still chaining through to dbus-launch
+   * and in turn to the parent shell.
+   */
+  dev_null_fd = open ("/dev/null", O_RDWR);
+  if (dev_null_fd >= 0)
+    {
+      if (!exit_with_session)
+        dup2 (dev_null_fd, 0);
+      dup2 (dev_null_fd, 1);
+      s = getenv ("DBUS_DEBUG_OUTPUT");
+      if (s == NULL || *s == '\0')
+        dup2 (dev_null_fd, 2);
+    }
+  else
+    {
+      fprintf (stderr, "Failed to open /dev/null: %s\n",
+               strerror (errno));
+      /* continue, why not */
+    }
+  
+  ret = fork ();
+
+  if (ret < 0)
+    {
+      fprintf (stderr, "fork() failed in babysitter: %s\n",
+               strerror (errno));
+      exit (1);
+    }
+
+  if (ret > 0)
+    {
+      /* Parent reaps pre-fork part of bus daemon, then exits and is
+       * reaped so the babysitter isn't a zombie
+       */
+
+      verbose ("=== Babysitter's intermediate parent continues again\n");
+      
+      if (do_waitpid (child_pid) < 0)
+        {
+          /* shouldn't happen */
+          fprintf (stderr, "Failed waitpid() waiting for bus daemon's parent\n");
+          exit (1);
+        }
+
+      verbose ("Babysitter's intermediate parent exiting\n");
+      
+      exit (0);
+    }
+
+  /* Child continues */
+  verbose ("=== Babysitter process created\n");
+
+  verbose ("Reading PID from bus\n");
+      
+  switch (read_pid (read_bus_pid_fd, &bus_pid_to_kill))
+    {
+    case READ_STATUS_OK:
+      break;
+    case READ_STATUS_EOF:
+      fprintf (stderr, "EOF in dbus-launch reading PID from bus daemon\n");
+      exit (1);
+      break;
+    case READ_STATUS_ERROR:
+      fprintf (stderr, "Error in dbus-launch reading PID from bus daemon: %s\n",
+	       strerror (errno));
+      exit (1);
+      break;
+    }
+
+  verbose ("Got PID %ld from daemon\n",
+           (long) bus_pid_to_kill);
+  
+  if (exit_with_session)
+    {
+      /* Bus is now started and launcher has needed info;
+       * we connect to X display and tty and wait to
+       * kill bus if requested.
+       */
+      
+      kill_bus_when_session_ends ();
+    }
+
+  verbose ("Babysitter exiting\n");
+  
+  exit (0);
+}
+
+static void
+do_close_stderr (void)
+{
+  int fd;
+
+  fflush (stderr);
+
+  /* dbus-launch is a Unix-only program, so we can rely on /dev/null being there.
+   * We're including unistd.h and we're dealing with sh/csh launch sequences...
+   */
+  fd = open ("/dev/null", O_RDWR);
+  if (fd == -1)
+    {
+      fprintf (stderr, "Internal error: cannot open /dev/null: %s", strerror (errno));
+      exit (1);
+    }
+
+  close (2);
+  if (dup2 (fd, 2) == -1)
+    {
+      /* error; we can't report an error anymore... */
+      exit (1);
+    }
+  close (fd);
+}
+
+static void
+pass_info (const char *runprog, const char *bus_address, pid_t bus_pid,
+           long bus_wid, int c_shell_syntax, int bourne_shell_syntax,
+           int binary_syntax,
+           int argc, char **argv, int remaining_args)
+{
+  char *envvar = NULL;
+  char **args = NULL;
+
+  if (runprog)
+    {
+      int i;
+
+      envvar = malloc (strlen ("DBUS_SESSION_BUS_ADDRESS=") +
+          strlen (bus_address) + 1);
+      args = malloc (sizeof (char *) * ((argc-remaining_args)+2));
+
+      if (envvar == NULL || args == NULL)
+        goto oom;
+
+     args[0] = xstrdup (runprog);
+      if (!args[0])
+        goto oom;
+     for (i = 1; i <= (argc-remaining_args); i++)
+      {
+        size_t len = strlen (argv[remaining_args+i-1])+1;
+        args[i] = malloc (len);
+        if (!args[i])
+          goto oom;
+        strncpy (args[i], argv[remaining_args+i-1], len);
+       }
+     args[i] = NULL;
+
+     strcpy (envvar, "DBUS_SESSION_BUS_ADDRESS=");
+     strcat (envvar, bus_address);
+     putenv (envvar);
+
+     execvp (runprog, args);
+     fprintf (stderr, "Couldn't exec %s: %s\n", runprog, strerror (errno));
+     exit (1);
+    }
+   else
+    {
+      print_variables (bus_address, bus_pid, bus_wid, c_shell_syntax,
+         bourne_shell_syntax, binary_syntax);
+    }
+  verbose ("dbus-launch exiting\n");
+
+  fflush (stdout);
+  fflush (stderr);
+  close (1);
+  close (2);
+  exit (0);
+oom:
+  if (envvar)
+    free (envvar);
+
+  if (args)
+    free (args);
+
+  fprintf (stderr, "Out of memory!");
+  exit (1);
+}
+
+#define READ_END  0
+#define WRITE_END 1
+
+int
+main (int argc, char **argv)
+{
+  const char *prev_arg;
+  const char *shname;
+  const char *runprog = NULL;
+  int remaining_args = 0;
+  int exit_with_session;
+  int binary_syntax = FALSE;
+  int c_shell_syntax = FALSE;
+  int bourne_shell_syntax = FALSE;
+  int auto_shell_syntax = FALSE;
+  int autolaunch = FALSE;
+  int requires_arg = FALSE;
+  int close_stderr = FALSE;
+  int i;
+  int ret;
+  int bus_pid_to_launcher_pipe[2];
+  int bus_pid_to_babysitter_pipe[2];
+  int bus_address_to_launcher_pipe[2];
+  char *config_file;
+  
+  exit_with_session = FALSE;
+  config_file = NULL;
+  
+  prev_arg = NULL;
+  i = 1;
+  while (i < argc)
+    {
+      const char *arg = argv[i];
+ 
+      if (strcmp (arg, "--help") == 0 ||
+          strcmp (arg, "-h") == 0 ||
+          strcmp (arg, "-?") == 0)
+        usage (0);
+      else if (strcmp (arg, "--auto-syntax") == 0)
+        auto_shell_syntax = TRUE;
+      else if (strcmp (arg, "-c") == 0 ||
+               strcmp (arg, "--csh-syntax") == 0)
+        c_shell_syntax = TRUE;
+      else if (strcmp (arg, "-s") == 0 ||
+               strcmp (arg, "--sh-syntax") == 0)
+        bourne_shell_syntax = TRUE;
+      else if (strcmp (arg, "--binary-syntax") == 0)
+        binary_syntax = TRUE;
+      else if (strcmp (arg, "--version") == 0)
+        version ();
+      else if (strcmp (arg, "--exit-with-session") == 0)
+        exit_with_session = TRUE;
+      else if (strcmp (arg, "--close-stderr") == 0)
+        close_stderr = TRUE;
+      else if (strstr (arg, "--autolaunch=") == arg)
+        {
+          const char *s;
+
+          if (autolaunch)
+            {
+              fprintf (stderr, "--autolaunch given twice\n");
+              exit (1);
+            }
+          
+          autolaunch = TRUE;
+
+          s = strchr (arg, '=');
+          ++s;
+
+          save_machine_uuid (s);
+        }
+      else if (prev_arg &&
+               strcmp (prev_arg, "--autolaunch") == 0)
+        {
+          if (autolaunch)
+            {
+              fprintf (stderr, "--autolaunch given twice\n");
+              exit (1);
+            }
+          
+          autolaunch = TRUE;
+
+          save_machine_uuid (arg);
+	  requires_arg = FALSE;
+        }
+      else if (strcmp (arg, "--autolaunch") == 0)
+	requires_arg = TRUE;
+      else if (strstr (arg, "--config-file=") == arg)
+        {
+          const char *file;
+
+          if (config_file != NULL)
+            {
+              fprintf (stderr, "--config-file given twice\n");
+              exit (1);
+            }
+          
+          file = strchr (arg, '=');
+          ++file;
+
+          config_file = xstrdup (file);
+        }
+      else if (prev_arg &&
+               strcmp (prev_arg, "--config-file") == 0)
+        {
+          if (config_file != NULL)
+            {
+              fprintf (stderr, "--config-file given twice\n");
+              exit (1);
+            }
+
+          config_file = xstrdup (arg);
+	  requires_arg = FALSE;
+        }
+      else if (strcmp (arg, "--config-file") == 0)
+	requires_arg = TRUE;
+      else if (arg[0] == '-')
+        {
+          if (strcmp (arg, "--") != 0)
+            {
+              fprintf (stderr, "Option `%s' is unknown.\n", arg);
+              exit (1);
+            }
+          else
+            {
+              runprog = argv[i+1];
+              remaining_args = i+2;
+              break;
+            }
+        }
+      else
+	{
+	  runprog = arg;
+	  remaining_args = i+1;
+	  break;
+	}
+      
+      prev_arg = arg;
+      
+      ++i;
+    }
+  if (requires_arg)
+    {
+      fprintf (stderr, "Option `%s' requires an argument.\n", prev_arg);
+      exit (1);
+    }
+
+  if (auto_shell_syntax)
+    {
+      if ((shname = getenv ("SHELL")) != NULL)
+       {
+         if (!strncmp (shname + strlen (shname) - 3, "csh", 3))
+           c_shell_syntax = TRUE;
+         else
+           bourne_shell_syntax = TRUE;
+       }
+      else
+       bourne_shell_syntax = TRUE;
+    }  
+
+  if (exit_with_session)
+    verbose ("--exit-with-session enabled\n");
+
+  if (autolaunch)
+    {      
+#ifndef DBUS_BUILD_X11
+      fprintf (stderr, "Autolaunch requested, but X11 support not compiled in.\n"
+	       "Cannot continue.\n");
+      exit (1);
+#else /* DBUS_BUILD_X11 */
+#ifndef DBUS_ENABLE_X11_AUTOLAUNCH
+      fprintf (stderr, "X11 autolaunch support disabled at compile time.\n");
+      exit (1);
+#else /* DBUS_ENABLE_X11_AUTOLAUNCH */
+      char *address;
+      pid_t pid;
+      long wid;
+      
+      if (get_machine_uuid () == NULL)
+        {
+          fprintf (stderr, "Machine UUID not provided as arg to --autolaunch\n");
+          exit (1);
+        }
+
+      verbose ("Autolaunch enabled (using X11).\n");
+      if (!exit_with_session)
+	{
+	  verbose ("--exit-with-session automatically enabled\n");
+	  exit_with_session = TRUE;
+	}
+
+      if (!x11_init ())
+	{
+	  fprintf (stderr, "Autolaunch error: X11 initialization failed.\n");
+	  exit (1);
+	}
+
+      if (!x11_get_address (&address, &pid, &wid))
+	{
+	  fprintf (stderr, "Autolaunch error: X11 communication error.\n");
+	  exit (1);
+	}
+
+      if (address != NULL)
+	{
+	  verbose ("dbus-daemon is already running. Returning existing parameters.\n");
+	  pass_info (runprog, address, pid, wid, c_shell_syntax,
+			   bourne_shell_syntax, binary_syntax, argc, argv, remaining_args);
+	  exit (0);
+	}
+#endif /* DBUS_ENABLE_X11_AUTOLAUNCH */
+    }
+  else if (read_machine_uuid_if_needed())
+    {
+      x11_init();
+#endif /* DBUS_BUILD_X11 */
+    }
+
+
+  if (pipe (bus_pid_to_launcher_pipe) < 0 ||
+      pipe (bus_address_to_launcher_pipe) < 0 ||
+      pipe (bus_pid_to_babysitter_pipe) < 0)
+    {
+      fprintf (stderr,
+               "Failed to create pipe: %s\n",
+               strerror (errno));
+      exit (1);
+    }
+
+  ret = fork ();
+  if (ret < 0)
+    {
+      fprintf (stderr, "Failed to fork: %s\n",
+               strerror (errno));
+      exit (1);
+    }
+
+  if (ret == 0)
+    {
+      /* Child */
+#define MAX_FD_LEN 64
+      char write_pid_fd_as_string[MAX_FD_LEN];
+      char write_address_fd_as_string[MAX_FD_LEN];
+
+#ifdef DBUS_BUILD_X11
+      xdisplay = NULL;
+#endif
+
+      if (close_stderr)
+	do_close_stderr ();
+
+      verbose ("=== Babysitter's intermediate parent created\n");
+
+      /* Fork once more to create babysitter */
+      
+      ret = fork ();
+      if (ret < 0)
+        {
+          fprintf (stderr, "Failed to fork: %s\n",
+                   strerror (errno));
+          exit (1);
+        }
+      
+      if (ret > 0)
+        {
+          /* In babysitter */
+          verbose ("=== Babysitter's intermediate parent continues\n");
+          
+          close (bus_pid_to_launcher_pipe[READ_END]);
+	  close (bus_pid_to_launcher_pipe[WRITE_END]);
+          close (bus_address_to_launcher_pipe[READ_END]);
+          close (bus_address_to_launcher_pipe[WRITE_END]);
+          close (bus_pid_to_babysitter_pipe[WRITE_END]);
+
+          /* babysit() will fork *again*
+           * and will also reap the pre-forked bus
+           * daemon
+           */
+          babysit (exit_with_session, ret,
+                   bus_pid_to_babysitter_pipe[READ_END]);
+          exit (0);
+        }
+
+      verbose ("=== Bus exec process created\n");
+      
+      /* Now we are the bus process (well, almost;
+       * dbus-daemon itself forks again)
+       */
+      close (bus_pid_to_launcher_pipe[READ_END]);
+      close (bus_address_to_launcher_pipe[READ_END]);
+      close (bus_pid_to_babysitter_pipe[READ_END]);
+      close (bus_pid_to_babysitter_pipe[WRITE_END]);
+
+      sprintf (write_pid_fd_as_string,
+               "%d", bus_pid_to_launcher_pipe[WRITE_END]);
+
+      sprintf (write_address_fd_as_string,
+               "%d", bus_address_to_launcher_pipe[WRITE_END]);
+
+      verbose ("Calling exec()\n");
+ 
+#ifdef DBUS_BUILD_TESTS 
+      /* exec from testdir */
+      if (getenv("DBUS_USE_TEST_BINARY") != NULL)
+        {
+          execl (TEST_BUS_BINARY,
+                 TEST_BUS_BINARY,
+                 "--fork",
+                 "--print-pid", write_pid_fd_as_string,
+                 "--print-address", write_address_fd_as_string,
+                 config_file ? "--config-file" : "--session",
+                 config_file, /* has to be last in this varargs list */
+                 NULL); 
+
+          fprintf (stderr,
+                   "Failed to execute test message bus daemon %s: %s. Will try again with the system path.\n",
+                   TEST_BUS_BINARY, strerror (errno));
+        }
+ #endif /* DBUS_BUILD_TESTS */
+
+      execl (DBUS_DAEMONDIR"/dbus-daemon",
+             DBUS_DAEMONDIR"/dbus-daemon",
+             "--fork",
+             "--print-pid", write_pid_fd_as_string,
+             "--print-address", write_address_fd_as_string,
+             config_file ? "--config-file" : "--session",
+             config_file, /* has to be last in this varargs list */
+             NULL);
+
+      fprintf (stderr,
+               "Failed to execute message bus daemon %s: %s.  Will try again without full path.\n",
+               DBUS_DAEMONDIR"/dbus-daemon", strerror (errno));
+      
+      /*
+       * If it failed, try running without full PATH.  Note this is needed
+       * because the build process builds the run-with-tmp-session-bus.conf
+       * file and the dbus-daemon will not be in the install location during
+       * build time.
+       */
+      execlp ("dbus-daemon",
+              "dbus-daemon",
+              "--fork",
+              "--print-pid", write_pid_fd_as_string,
+              "--print-address", write_address_fd_as_string,
+              config_file ? "--config-file" : "--session",
+              config_file, /* has to be last in this varargs list */
+              NULL);
+
+      fprintf (stderr,
+               "Failed to execute message bus daemon: %s\n",
+               strerror (errno));
+      exit (1);
+    }
+  else
+    {
+      /* Parent */
+#define MAX_PID_LEN 64
+      pid_t bus_pid;  
+      char bus_address[MAX_ADDR_LEN];
+      char buf[MAX_PID_LEN];
+      char *end;
+      long wid = 0;
+      long val;
+      int ret2;
+
+      verbose ("=== Parent dbus-launch continues\n");
+      
+      close (bus_pid_to_launcher_pipe[WRITE_END]);
+      close (bus_address_to_launcher_pipe[WRITE_END]);
+      close (bus_pid_to_babysitter_pipe[READ_END]);
+
+      verbose ("Waiting for babysitter's intermediate parent\n");
+      
+      /* Immediately reap parent of babysitter
+       * (which was created just for us to reap)
+       */
+      if (do_waitpid (ret) < 0)
+        {
+          fprintf (stderr, "Failed to waitpid() for babysitter intermediate process: %s\n",
+                   strerror (errno));
+          exit (1);
+        }
+
+      verbose ("Reading address from bus\n");
+      
+      /* Read the pipe data, print, and exit */
+      switch (read_line (bus_address_to_launcher_pipe[READ_END],
+                         bus_address, MAX_ADDR_LEN))
+        {
+        case READ_STATUS_OK:
+          break;
+        case READ_STATUS_EOF:
+          fprintf (stderr, "EOF in dbus-launch reading address from bus daemon\n");
+          exit (1);
+          break;
+        case READ_STATUS_ERROR:
+          fprintf (stderr, "Error in dbus-launch reading address from bus daemon: %s\n",
+                   strerror (errno));
+          exit (1);
+          break;
+        }
+        
+      close (bus_address_to_launcher_pipe[READ_END]);
+
+      verbose ("Reading PID from daemon\n");
+      /* Now read data */
+      switch (read_line (bus_pid_to_launcher_pipe[READ_END], buf, MAX_PID_LEN))
+	{
+	case READ_STATUS_OK:
+	  break;
+	case READ_STATUS_EOF:
+	  fprintf (stderr, "EOF reading PID from bus daemon\n");
+	  exit (1);
+	  break;
+	case READ_STATUS_ERROR:
+	  fprintf (stderr, "Error reading PID from bus daemon: %s\n",
+		   strerror (errno));
+	  exit (1);
+	  break;
+	}
+
+      end = NULL;
+      val = strtol (buf, &end, 0);
+      if (buf == end || end == NULL)
+	{
+	  fprintf (stderr, "Failed to parse bus PID \"%s\": %s\n",
+		   buf, strerror (errno));
+	  exit (1);
+	}
+
+      bus_pid = val;
+
+      close (bus_pid_to_launcher_pipe[READ_END]);
+
+#ifdef DBUS_ENABLE_X11_AUTOLAUNCH
+      if (xdisplay != NULL)
+        {
+          verbose("Saving x11 address\n");
+          ret2 = x11_save_address (bus_address, bus_pid, &wid);
+          /* Only get an existing dbus session when autolaunching */
+          if (autolaunch)
+            {
+              if (ret2 == 0)
+                {
+                  char *address = NULL;
+                  /* another window got added. Return its address */
+                  bus_pid_to_kill = bus_pid;
+                  if (x11_get_address (&address, &bus_pid, &wid)
+                       && address != NULL)
+                    {
+                      verbose ("dbus-daemon is already running. Returning existing parameters.\n");
+                      /* Kill the old bus */
+                      kill_bus();
+                      pass_info (runprog, address, bus_pid, wid,
+                         c_shell_syntax, bourne_shell_syntax, binary_syntax,
+                         argc, argv, remaining_args);
+                    }
+                  }
+              if (ret2 < 0)
+                {
+                  fprintf (stderr, "Error saving bus information.\n");
+                  bus_pid_to_kill = bus_pid;
+                  kill_bus_and_exit (1);
+                }
+            }
+        }
+#endif
+
+      /* Forward the pid to the babysitter */
+      write_pid (bus_pid_to_babysitter_pipe[WRITE_END], bus_pid);
+      close (bus_pid_to_babysitter_pipe[WRITE_END]);
+
+       pass_info (runprog, bus_address, bus_pid, wid, c_shell_syntax,
+              bourne_shell_syntax, binary_syntax, argc, argv, remaining_args);
+    }
+
+  return 0;
+}
diff --git a/dbus/tools/dbus-launch.h b/dbus/tools/dbus-launch.h
new file mode 100644
index 0000000..8220bb8
--- /dev/null
+++ b/dbus/tools/dbus-launch.h
@@ -0,0 +1,57 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-launch.h  dbus-launch utility
+ *
+ * Copyright (C) 2006 Thiago Macieira <thiago@kde.org>
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * 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
+ *
+ */
+
+#ifndef DBUS_LAUNCH_H
+#define DBUS_LAUNCH_H
+
+#include <sys/types.h>
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#undef  MAX
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
+
+#define MAX_ADDR_LEN 512
+
+/* defined in dbus-launch.c */
+void verbose (const char *format, ...);
+char *xstrdup (const char *str);
+void kill_bus_and_exit (int exitcode);
+
+const char* get_machine_uuid (void);
+
+#ifdef DBUS_BUILD_X11
+/* defined in dbus-launch-x11.c */
+int x11_init (void);
+int x11_get_address (char **paddress, pid_t *pid, long *wid);
+int x11_save_address (char *address, pid_t pid, long *wid);
+void x11_handle_event (void);
+#endif
+
+#endif
diff --git a/dbus/tools/dbus-monitor.c b/dbus/tools/dbus-monitor.c
new file mode 100644
index 0000000..a4b5478
--- /dev/null
+++ b/dbus/tools/dbus-monitor.c
@@ -0,0 +1,416 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-monitor.c  Utility program to monitor messages on the bus
+ *
+ * Copyright (C) 2003 Philip Blundell <philb@gnu.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DBUS_WIN
+#include <winsock2.h>
+#undef interface
+#else
+#include <sys/time.h>
+#endif
+
+#include <time.h>
+
+#include "dbus-print-message.h"
+
+#define EAVESDROPPING_RULE "eavesdrop=true"
+
+#ifdef DBUS_WIN
+
+/* gettimeofday is not defined on windows */
+#define DBUS_SECONDS_SINCE_1601 11644473600LL
+#define DBUS_USEC_IN_SEC        1000000LL
+
+#ifdef DBUS_WINCE
+
+#ifndef _IOLBF
+#define _IOLBF 0x40
+#endif
+#ifndef _IONBF
+#define _IONBF 0x04
+#endif
+
+void
+GetSystemTimeAsFileTime (LPFILETIME ftp)
+{
+  SYSTEMTIME st;
+  GetSystemTime (&st);
+  SystemTimeToFileTime (&st, ftp);
+}
+#endif
+
+static int
+gettimeofday (struct timeval *__p,
+	      void *__t)
+{
+  union {
+      unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
+      FILETIME           ft;
+    } now;
+
+  GetSystemTimeAsFileTime (&now.ft);
+  __p->tv_usec = (long) ((now.ns100 / 10LL) % DBUS_USEC_IN_SEC);
+  __p->tv_sec  = (long)(((now.ns100 / 10LL) / DBUS_SECONDS_SINCE_1601) - DBUS_SECONDS_SINCE_1601);
+
+  return 0;
+}
+#endif
+
+inline static void
+oom (const char *doing)
+{
+  fprintf (stderr, "OOM while %s\n", doing);
+  exit (1);
+}
+
+static DBusHandlerResult
+monitor_filter_func (DBusConnection     *connection,
+		     DBusMessage        *message,
+		     void               *user_data)
+{
+  print_message (message, FALSE);
+  
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_LOCAL,
+                              "Disconnected"))
+    exit (0);
+  
+  /* Conceptually we want this to be
+   * DBUS_HANDLER_RESULT_NOT_YET_HANDLED, but this raises
+   * some problems.  See bug 1719.
+   */
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+#ifdef __APPLE__
+#define PROFILE_TIMED_FORMAT "%s\t%lu\t%d"
+#else
+#define PROFILE_TIMED_FORMAT "%s\t%lu\t%lu"
+#endif
+#define TRAP_NULL_STRING(str) ((str) ? (str) : "<none>")
+
+typedef enum
+{
+  PROFILE_ATTRIBUTE_FLAG_SERIAL = 1,
+  PROFILE_ATTRIBUTE_FLAG_REPLY_SERIAL = 2,
+  PROFILE_ATTRIBUTE_FLAG_SENDER = 4,
+  PROFILE_ATTRIBUTE_FLAG_DESTINATION = 8,
+  PROFILE_ATTRIBUTE_FLAG_PATH = 16,
+  PROFILE_ATTRIBUTE_FLAG_INTERFACE = 32,
+  PROFILE_ATTRIBUTE_FLAG_MEMBER = 64,
+  PROFILE_ATTRIBUTE_FLAG_ERROR_NAME = 128
+} ProfileAttributeFlags;
+
+static void
+profile_print_with_attrs (const char *type, DBusMessage *message,
+  struct timeval *t, ProfileAttributeFlags attrs)
+{
+  printf (PROFILE_TIMED_FORMAT, type, t->tv_sec, t->tv_usec);
+
+  if (attrs & PROFILE_ATTRIBUTE_FLAG_SERIAL)
+    printf ("\t%u", dbus_message_get_serial (message));
+
+  if (attrs & PROFILE_ATTRIBUTE_FLAG_REPLY_SERIAL)
+    printf ("\t%u", dbus_message_get_reply_serial (message));
+
+  if (attrs & PROFILE_ATTRIBUTE_FLAG_SENDER)
+    printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_sender (message)));
+
+  if (attrs & PROFILE_ATTRIBUTE_FLAG_DESTINATION)
+    printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_destination (message)));
+
+  if (attrs & PROFILE_ATTRIBUTE_FLAG_PATH)
+    printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_path (message)));
+
+  if (attrs & PROFILE_ATTRIBUTE_FLAG_INTERFACE)
+    printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_interface (message)));
+
+  if (attrs & PROFILE_ATTRIBUTE_FLAG_MEMBER)
+    printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_member (message)));
+
+  if (attrs & PROFILE_ATTRIBUTE_FLAG_ERROR_NAME)
+    printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_error_name (message)));
+
+  printf ("\n");
+}
+
+static void
+print_message_profile (DBusMessage *message)
+{
+  struct timeval t;
+
+  if (gettimeofday (&t, NULL) < 0)
+    {
+      printf ("un\n");
+      return;
+    }
+
+  switch (dbus_message_get_type (message))
+    {
+      case DBUS_MESSAGE_TYPE_METHOD_CALL:
+	profile_print_with_attrs ("mc", message, &t,
+	  PROFILE_ATTRIBUTE_FLAG_SERIAL |
+	  PROFILE_ATTRIBUTE_FLAG_SENDER |
+	  PROFILE_ATTRIBUTE_FLAG_PATH |
+	  PROFILE_ATTRIBUTE_FLAG_INTERFACE |
+	  PROFILE_ATTRIBUTE_FLAG_MEMBER);
+	break;
+      case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+	profile_print_with_attrs ("mr", message, &t,
+	  PROFILE_ATTRIBUTE_FLAG_SERIAL |
+	  PROFILE_ATTRIBUTE_FLAG_DESTINATION |
+	  PROFILE_ATTRIBUTE_FLAG_REPLY_SERIAL);
+	break;
+      case DBUS_MESSAGE_TYPE_ERROR:
+	profile_print_with_attrs ("err", message, &t,
+	  PROFILE_ATTRIBUTE_FLAG_SERIAL |
+	  PROFILE_ATTRIBUTE_FLAG_DESTINATION |
+	  PROFILE_ATTRIBUTE_FLAG_REPLY_SERIAL);
+	break;
+      case DBUS_MESSAGE_TYPE_SIGNAL:
+	profile_print_with_attrs ("sig", message, &t,
+	  PROFILE_ATTRIBUTE_FLAG_SERIAL |
+	  PROFILE_ATTRIBUTE_FLAG_PATH |
+	  PROFILE_ATTRIBUTE_FLAG_INTERFACE |
+	  PROFILE_ATTRIBUTE_FLAG_MEMBER);
+	break;
+      default:
+	printf (PROFILE_TIMED_FORMAT "\n", "tun", t.tv_sec, t.tv_usec);
+	break;
+    }
+}
+
+static DBusHandlerResult
+profile_filter_func (DBusConnection	*connection,
+		     DBusMessage	*message,
+		     void		*user_data)
+{
+  print_message_profile (message);
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_LOCAL,
+                              "Disconnected"))
+    exit (0);
+
+  return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+usage (char *name, int ecode)
+{
+  fprintf (stderr, "Usage: %s [--system | --session | --address ADDRESS] [--monitor | --profile ] [watch expressions]\n", name);
+  exit (ecode);
+}
+
+static void
+only_one_type (dbus_bool_t *seen_bus_type,
+               char        *name)
+{
+  if (*seen_bus_type)
+    {
+      fprintf (stderr, "I only support monitoring one bus at a time!\n");
+      usage (name, 1);
+    }
+  else
+    {
+      *seen_bus_type = TRUE;
+    }
+}
+
+int
+main (int argc, char *argv[])
+{
+  DBusConnection *connection;
+  DBusError error;
+  DBusBusType type = DBUS_BUS_SESSION;
+  DBusHandleMessageFunction filter_func = monitor_filter_func;
+  char *address = NULL;
+  dbus_bool_t seen_bus_type = FALSE;
+  
+  int i = 0, j = 0, numFilters = 0;
+  char **filters = NULL;
+
+  /* Set stdout to be unbuffered; this is basically so that if people
+   * do dbus-monitor > file, then send SIGINT via Control-C, they
+   * don't lose the last chunk of messages.
+   */
+
+#ifdef DBUS_WIN
+  setvbuf (stdout, NULL, _IONBF, 0);
+#else
+  setvbuf (stdout, NULL, _IOLBF, 0);
+#endif
+
+  for (i = 1; i < argc; i++)
+    {
+      char *arg = argv[i];
+
+      if (!strcmp (arg, "--system"))
+        {
+          only_one_type (&seen_bus_type, argv[0]);
+          type = DBUS_BUS_SYSTEM;
+        }
+      else if (!strcmp (arg, "--session"))
+        {
+          only_one_type (&seen_bus_type, argv[0]);
+          type = DBUS_BUS_SESSION;
+        }
+      else if (!strcmp (arg, "--address"))
+        {
+          only_one_type (&seen_bus_type, argv[0]);
+
+          if (i+1 < argc)
+            {
+              address = argv[i+1];
+              i++;
+            }
+          else
+            usage (argv[0], 1);
+        }
+      else if (!strcmp (arg, "--help"))
+	usage (argv[0], 0);
+      else if (!strcmp (arg, "--monitor"))
+	filter_func = monitor_filter_func;
+      else if (!strcmp (arg, "--profile"))
+	filter_func = profile_filter_func;
+      else if (!strcmp (arg, "--"))
+	continue;
+      else if (arg[0] == '-')
+	usage (argv[0], 1);
+      else {
+          unsigned int filter_len;
+          numFilters++;
+          /* Prepend a rule (and a comma) to enable the monitor to eavesdrop.
+           * Prepending allows the user to add eavesdrop=false at command line
+           * in order to disable eavesdropping when needed */
+          filter_len = strlen (EAVESDROPPING_RULE) + 1 + strlen (arg) + 1;
+
+          filters = (char **) realloc (filters, numFilters * sizeof (char *));
+          if (filters == NULL)
+            oom ("adding a new filter slot");
+          filters[j] = (char *) malloc (filter_len * sizeof (char *));
+          if (filters[j] == NULL)
+            oom ("adding a new filter");
+          snprintf (filters[j], filter_len, "%s,%s", EAVESDROPPING_RULE, arg);
+          j++;
+      }
+    }
+
+  dbus_error_init (&error);
+  
+  if (address != NULL)
+    {
+      connection = dbus_connection_open (address, &error);
+      if (connection)
+        {
+          if (!dbus_bus_register (connection, &error))
+      	    {
+              fprintf (stderr, "Failed to register connection to bus at %s: %s\n",
+      	               address, error.message);
+              dbus_error_free (&error);
+              exit (1);
+      	    }
+        }
+    }
+  else
+    connection = dbus_bus_get (type, &error);
+  if (connection == NULL)
+    {
+      const char *where;
+      if (address != NULL)
+        where = address;
+      else
+        {
+          switch (type)
+            {
+            case DBUS_BUS_SYSTEM:
+              where = "system bus";
+              break;
+            case DBUS_BUS_SESSION:
+              where = "session bus";
+              break;
+            default:
+              where = "";
+            }
+        }
+      fprintf (stderr, "Failed to open connection to %s: %s\n",
+               where,
+               error.message);
+      dbus_error_free (&error);
+      exit (1);
+    }
+
+  if (numFilters)
+    {
+      for (i = 0; i < j; i++)
+        {
+          dbus_bus_add_match (connection, filters[i], &error);
+          if (dbus_error_is_set (&error))
+            {
+              fprintf (stderr, "Failed to setup match \"%s\": %s\n",
+                       filters[i], error.message);
+              dbus_error_free (&error);
+              exit (1);
+            }
+	  free(filters[i]);
+        }
+    }
+  else
+    {
+      dbus_bus_add_match (connection,
+		          EAVESDROPPING_RULE ",type='signal'",
+		          &error);
+      if (dbus_error_is_set (&error))
+        goto lose;
+      dbus_bus_add_match (connection,
+		          EAVESDROPPING_RULE ",type='method_call'",
+		          &error);
+      if (dbus_error_is_set (&error))
+        goto lose;
+      dbus_bus_add_match (connection,
+		          EAVESDROPPING_RULE ",type='method_return'",
+		          &error);
+      if (dbus_error_is_set (&error))
+        goto lose;
+      dbus_bus_add_match (connection,
+		          EAVESDROPPING_RULE ",type='error'",
+		          &error);
+      if (dbus_error_is_set (&error))
+        goto lose;
+    }
+
+  if (!dbus_connection_add_filter (connection, filter_func, NULL, NULL)) {
+    fprintf (stderr, "Couldn't add filter!\n");
+    exit (1);
+  }
+
+  while (dbus_connection_read_write_dispatch(connection, -1))
+    ;
+  exit (0);
+ lose:
+  fprintf (stderr, "Error: %s\n", error.message);
+  exit (1);
+}
+
diff --git a/dbus/tools/dbus-print-message.c b/dbus/tools/dbus-print-message.c
new file mode 100644
index 0000000..75d00ac
--- /dev/null
+++ b/dbus/tools/dbus-print-message.c
@@ -0,0 +1,409 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-print-message.h  Utility function to print out a message
+ *
+ * Copyright (C) 2003 Philip Blundell <philb@gnu.org>
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-print-message.h"
+
+#include <stdlib.h>
+#include "config.h"
+
+static const char*
+type_to_name (int message_type)
+{
+  switch (message_type)
+    {
+    case DBUS_MESSAGE_TYPE_SIGNAL:
+      return "signal";
+    case DBUS_MESSAGE_TYPE_METHOD_CALL:
+      return "method call";
+    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+      return "method return";
+    case DBUS_MESSAGE_TYPE_ERROR:
+      return "error";
+    default:
+      return "(unknown message type)";
+    }
+}
+
+#define INDENT 3
+
+static void
+indent (int depth)
+{
+  while (depth-- > 0)
+    printf ("   "); /* INDENT spaces. */
+}
+
+static void
+print_hex (unsigned char *bytes, unsigned int len, int depth)
+{
+  unsigned int i, columns;
+
+  printf ("array of bytes [\n");
+
+  indent (depth + 1);
+
+  /* Each byte takes 3 cells (two hexits, and a space), except the last one. */
+  columns = (80 - ((depth + 1) * INDENT)) / 3;
+
+  if (columns < 8)
+    columns = 8;
+
+  i = 0;
+
+  while (i < len)
+    {
+      printf ("%02x", bytes[i]);
+      i++;
+
+      if (i != len)
+        {
+          if (i % columns == 0)
+            {
+              printf ("\n");
+              indent (depth + 1);
+            }
+          else
+            {
+              printf (" ");
+            }
+        }
+    }
+
+  printf ("\n");
+  indent (depth);
+  printf ("]\n");
+}
+
+#define DEFAULT_SIZE 100
+
+static void
+print_ay (DBusMessageIter *iter, int depth)
+{
+  /* Not using DBusString because it's not public API. It's 2009, and I'm
+   * manually growing a string chunk by chunk.
+   */
+  unsigned char *bytes = malloc (DEFAULT_SIZE + 1);
+  unsigned int len = 0;
+  unsigned int max = DEFAULT_SIZE;
+  dbus_bool_t all_ascii = TRUE;
+  int current_type;
+
+  while ((current_type = dbus_message_iter_get_arg_type (iter))
+          != DBUS_TYPE_INVALID)
+    {
+      unsigned char val;
+
+      dbus_message_iter_get_basic (iter, &val);
+      bytes[len] = val;
+      len++;
+
+      if (val < 32 || val > 126)
+        all_ascii = FALSE;
+
+      if (len == max)
+        {
+          max *= 2;
+          bytes = realloc (bytes, max + 1);
+        }
+
+      dbus_message_iter_next (iter);
+    }
+
+  if (all_ascii)
+    {
+      bytes[len] = '\0';
+      printf ("array of bytes \"%s\"\n", bytes);
+    }
+  else
+    {
+      print_hex (bytes, len, depth);
+    }
+
+  free (bytes);
+}
+
+static void
+print_iter (DBusMessageIter *iter, dbus_bool_t literal, int depth)
+{
+  do
+    {
+      int type = dbus_message_iter_get_arg_type (iter);
+
+      if (type == DBUS_TYPE_INVALID)
+	break;
+      
+      indent(depth);
+
+      switch (type)
+	{
+	case DBUS_TYPE_STRING:
+	  {
+	    char *val;
+	    dbus_message_iter_get_basic (iter, &val);
+	    if (!literal)
+	      printf ("string \"");
+	    printf ("%s", val);
+	    if (!literal)
+	      printf ("\"\n");
+	    break;
+	  }
+
+	case DBUS_TYPE_SIGNATURE:
+	  {
+	    char *val;
+	    dbus_message_iter_get_basic (iter, &val);
+	    if (!literal)
+	      printf ("signature \"");
+	    printf ("%s", val);
+	    if (!literal)
+	      printf ("\"\n");
+	    break;
+	  }
+
+	case DBUS_TYPE_OBJECT_PATH:
+	  {
+	    char *val;
+	    dbus_message_iter_get_basic (iter, &val);
+	    if (!literal)
+	      printf ("object path \"");
+	    printf ("%s", val);
+	    if (!literal)
+	      printf ("\"\n");
+	    break;
+	  }
+
+	case DBUS_TYPE_INT16:
+	  {
+	    dbus_int16_t val;
+	    dbus_message_iter_get_basic (iter, &val);
+	    printf ("int16 %d\n", val);
+	    break;
+	  }
+
+	case DBUS_TYPE_UINT16:
+	  {
+	    dbus_uint16_t val;
+	    dbus_message_iter_get_basic (iter, &val);
+	    printf ("uint16 %u\n", val);
+	    break;
+	  }
+
+	case DBUS_TYPE_INT32:
+	  {
+	    dbus_int32_t val;
+	    dbus_message_iter_get_basic (iter, &val);
+	    printf ("int32 %d\n", val);
+	    break;
+	  }
+
+	case DBUS_TYPE_UINT32:
+	  {
+	    dbus_uint32_t val;
+	    dbus_message_iter_get_basic (iter, &val);
+	    printf ("uint32 %u\n", val);
+	    break;
+	  }
+
+	case DBUS_TYPE_INT64:
+	  {
+	    dbus_int64_t val;
+	    dbus_message_iter_get_basic (iter, &val);
+#ifdef DBUS_INT64_PRINTF_MODIFIER
+        printf ("int64 %" DBUS_INT64_PRINTF_MODIFIER "d\n", val);
+#else
+        printf ("int64 (omitted)\n");
+#endif
+	    break;
+	  }
+
+	case DBUS_TYPE_UINT64:
+	  {
+	    dbus_uint64_t val;
+	    dbus_message_iter_get_basic (iter, &val);
+#ifdef DBUS_INT64_PRINTF_MODIFIER
+        printf ("uint64 %" DBUS_INT64_PRINTF_MODIFIER "u\n", val);
+#else
+        printf ("uint64 (omitted)\n");
+#endif
+	    break;
+	  }
+
+	case DBUS_TYPE_DOUBLE:
+	  {
+	    double val;
+	    dbus_message_iter_get_basic (iter, &val);
+	    printf ("double %g\n", val);
+	    break;
+	  }
+
+	case DBUS_TYPE_BYTE:
+	  {
+	    unsigned char val;
+	    dbus_message_iter_get_basic (iter, &val);
+	    printf ("byte %d\n", val);
+	    break;
+	  }
+
+	case DBUS_TYPE_BOOLEAN:
+	  {
+	    dbus_bool_t val;
+	    dbus_message_iter_get_basic (iter, &val);
+	    printf ("boolean %s\n", val ? "true" : "false");
+	    break;
+	  }
+
+	case DBUS_TYPE_VARIANT:
+	  {
+	    DBusMessageIter subiter;
+
+	    dbus_message_iter_recurse (iter, &subiter);
+
+	    printf ("variant ");
+	    print_iter (&subiter, literal, depth+1);
+	    break;
+	  }
+	case DBUS_TYPE_ARRAY:
+	  {
+	    int current_type;
+	    DBusMessageIter subiter;
+
+	    dbus_message_iter_recurse (iter, &subiter);
+
+	    current_type = dbus_message_iter_get_arg_type (&subiter);
+
+	    if (current_type == DBUS_TYPE_BYTE)
+	      {
+		print_ay (&subiter, depth);
+		break;
+	      }
+
+	    printf("array [\n");
+	    while (current_type != DBUS_TYPE_INVALID)
+	      {
+		print_iter (&subiter, literal, depth+1);
+
+		dbus_message_iter_next (&subiter);
+		current_type = dbus_message_iter_get_arg_type (&subiter);
+
+		if (current_type != DBUS_TYPE_INVALID)
+		  printf (",");
+	      }
+	    indent(depth);
+	    printf("]\n");
+	    break;
+	  }
+	case DBUS_TYPE_DICT_ENTRY:
+	  {
+	    DBusMessageIter subiter;
+
+	    dbus_message_iter_recurse (iter, &subiter);
+
+	    printf("dict entry(\n");
+	    print_iter (&subiter, literal, depth+1);
+	    dbus_message_iter_next (&subiter);
+	    print_iter (&subiter, literal, depth+1);
+	    indent(depth);
+	    printf(")\n");
+	    break;
+	  }
+	    
+	case DBUS_TYPE_STRUCT:
+	  {
+	    int current_type;
+	    DBusMessageIter subiter;
+
+	    dbus_message_iter_recurse (iter, &subiter);
+
+	    printf("struct {\n");
+	    while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
+	      {
+		print_iter (&subiter, literal, depth+1);
+		dbus_message_iter_next (&subiter);
+		if (dbus_message_iter_get_arg_type (&subiter) != DBUS_TYPE_INVALID)
+		  printf (",");
+	      }
+	    indent(depth);
+	    printf("}\n");
+	    break;
+	  }
+	    
+	default:
+	  printf (" (dbus-monitor too dumb to decipher arg type '%c')\n", type);
+	  break;
+	}
+    } while (dbus_message_iter_next (iter));
+}
+
+void
+print_message (DBusMessage *message, dbus_bool_t literal)
+{
+  DBusMessageIter iter;
+  const char *sender;
+  const char *destination;
+  int message_type;
+
+  message_type = dbus_message_get_type (message);
+  sender = dbus_message_get_sender (message);
+  destination = dbus_message_get_destination (message);
+  
+  if (!literal)
+    {
+      printf ("%s sender=%s -> dest=%s",
+	      type_to_name (message_type),
+	      sender ? sender : "(null sender)",
+	      destination ? destination : "(null destination)");
+  
+      switch (message_type)
+	{
+	case DBUS_MESSAGE_TYPE_METHOD_CALL:
+	case DBUS_MESSAGE_TYPE_SIGNAL:
+	  printf (" serial=%u path=%s; interface=%s; member=%s\n",
+                  dbus_message_get_serial (message),
+		  dbus_message_get_path (message),
+		  dbus_message_get_interface (message),
+		  dbus_message_get_member (message));
+	  break;
+      
+	case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+	  printf (" reply_serial=%u\n",
+          dbus_message_get_reply_serial (message));
+	  break;
+
+	case DBUS_MESSAGE_TYPE_ERROR:
+	  printf (" error_name=%s reply_serial=%u\n",
+		  dbus_message_get_error_name (message),
+          dbus_message_get_reply_serial (message));
+	  break;
+
+	default:
+	  printf ("\n");
+	  break;
+	}
+    }
+
+  dbus_message_iter_init (message, &iter);
+  print_iter (&iter, literal, 1);
+  fflush (stdout);
+  
+}
+
diff --git a/dbus/tools/dbus-print-message.h b/dbus/tools/dbus-print-message.h
new file mode 100644
index 0000000..26700d8
--- /dev/null
+++ b/dbus/tools/dbus-print-message.h
@@ -0,0 +1,31 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-print-message.h  Utility function to print out a message
+ *
+ * Copyright (C) 2003 Philip Blundell <philb@gnu.org>
+ * Copyright (C) 2003 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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
+ *
+ */
+#ifndef DBUS_PRINT_MESSAGE_H
+#define DBUS_PRINT_MESSAGE_H
+
+#include <stdio.h>
+#include <string.h>
+#include <dbus/dbus.h>
+
+void print_message (DBusMessage *message, dbus_bool_t literal);
+
+#endif /* DBUS_PRINT_MESSAGE_H */
diff --git a/dbus/tools/dbus-send.c b/dbus/tools/dbus-send.c
new file mode 100644
index 0000000..e403a58
--- /dev/null
+++ b/dbus/tools/dbus-send.c
@@ -0,0 +1,542 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-send.c  Utility program to send messages from the command line
+ *
+ * Copyright (C) 2003 Philip Blundell <philb@gnu.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dbus/dbus.h>
+
+#ifndef HAVE_STRTOLL
+#undef strtoll
+#define strtoll mystrtoll
+#include "strtoll.c"
+#endif
+
+#ifndef HAVE_STRTOULL
+#undef strtoull
+#define strtoull mystrtoull
+#include "strtoull.c"
+#endif
+
+#ifdef DBUS_WINCE
+#ifndef strdup
+#define strdup _strdup
+#endif
+#endif
+
+#include "dbus-print-message.h"
+
+static const char *appname;
+
+static void
+usage (int ecode)
+{
+  fprintf (stderr, "Usage: %s [--help] [--system | --session | --address=ADDRESS] [--dest=NAME] [--type=TYPE] [--print-reply[=literal]] [--reply-timeout=MSEC] <destination object path> <message name> [contents ...]\n", appname);
+  exit (ecode);
+}
+
+static void
+append_arg (DBusMessageIter *iter, int type, const char *value)
+{
+  dbus_uint16_t uint16;
+  dbus_int16_t int16;
+  dbus_uint32_t uint32;
+  dbus_int32_t int32;
+  dbus_uint64_t uint64;
+  dbus_int64_t int64;
+  double d;
+  unsigned char byte;
+  dbus_bool_t v_BOOLEAN;
+  
+  /* FIXME - we are ignoring OOM returns on all these functions */
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+      byte = strtoul (value, NULL, 0);
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &byte);
+      break;
+
+    case DBUS_TYPE_DOUBLE:
+      d = strtod (value, NULL);
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &d);
+      break;
+
+    case DBUS_TYPE_INT16:
+      int16 = strtol (value, NULL, 0);
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_INT16, &int16);
+      break;
+
+    case DBUS_TYPE_UINT16:
+      uint16 = strtoul (value, NULL, 0);
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT16, &uint16);
+      break;
+
+    case DBUS_TYPE_INT32:
+      int32 = strtol (value, NULL, 0);
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &int32);
+      break;
+
+    case DBUS_TYPE_UINT32:
+      uint32 = strtoul (value, NULL, 0);
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &uint32);
+      break;
+
+    case DBUS_TYPE_INT64:
+      int64 = strtoll (value, NULL, 0);
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &int64);
+      break;
+
+    case DBUS_TYPE_UINT64:
+      uint64 = strtoull (value, NULL, 0);
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &uint64);
+      break;
+
+    case DBUS_TYPE_STRING:
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value);
+      break;
+
+    case DBUS_TYPE_OBJECT_PATH:
+      dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &value);
+      break;
+
+    case DBUS_TYPE_BOOLEAN:
+      if (strcmp (value, "true") == 0)
+	{
+	  v_BOOLEAN = TRUE;
+	  dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v_BOOLEAN);
+	}
+      else if (strcmp (value, "false") == 0)
+	{
+	  v_BOOLEAN = FALSE;
+	  dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v_BOOLEAN);
+	}
+      else
+	{
+	  fprintf (stderr, "%s: Expected \"true\" or \"false\" instead of \"%s\"\n", appname, value);
+	  exit (1);
+	}
+      break;
+
+    default:
+      fprintf (stderr, "%s: Unsupported data type %c\n", appname, (char) type);
+      exit (1);
+    }
+}
+
+static void
+append_array (DBusMessageIter *iter, int type, const char *value)
+{
+  const char *val;
+  char *dupval = strdup (value);
+
+  val = strtok (dupval, ",");
+  while (val != NULL)
+    {
+      append_arg (iter, type, val);
+      val = strtok (NULL, ",");
+    }
+  free (dupval);
+}
+
+static void
+append_dict (DBusMessageIter *iter, int keytype, int valtype, const char *value)
+{
+  const char *val;
+  char *dupval = strdup (value);
+
+  val = strtok (dupval, ",");
+  while (val != NULL)
+    {
+      DBusMessageIter subiter;
+      
+      dbus_message_iter_open_container (iter,
+					DBUS_TYPE_DICT_ENTRY,
+					NULL,
+					&subiter);
+
+      append_arg (&subiter, keytype, val);
+      val = strtok (NULL, ",");
+      if (val == NULL)
+	{
+	  fprintf (stderr, "%s: Malformed dictionary\n", appname);
+	  exit (1);
+	}
+      append_arg (&subiter, valtype, val);
+
+      dbus_message_iter_close_container (iter, &subiter);
+      val = strtok (NULL, ",");
+    } 
+  free (dupval);
+}
+
+static int
+type_from_name (const char *arg)
+{
+  int type;
+  if (!strcmp (arg, "string"))
+    type = DBUS_TYPE_STRING;
+  else if (!strcmp (arg, "int16"))
+    type = DBUS_TYPE_INT16;
+  else if (!strcmp (arg, "uint16"))
+    type = DBUS_TYPE_UINT16;
+  else if (!strcmp (arg, "int32"))
+    type = DBUS_TYPE_INT32;
+  else if (!strcmp (arg, "uint32"))
+    type = DBUS_TYPE_UINT32;
+  else if (!strcmp (arg, "int64"))
+    type = DBUS_TYPE_INT64;
+  else if (!strcmp (arg, "uint64"))
+    type = DBUS_TYPE_UINT64;
+  else if (!strcmp (arg, "double"))
+    type = DBUS_TYPE_DOUBLE;
+  else if (!strcmp (arg, "byte"))
+    type = DBUS_TYPE_BYTE;
+  else if (!strcmp (arg, "boolean"))
+    type = DBUS_TYPE_BOOLEAN;
+  else if (!strcmp (arg, "objpath"))
+    type = DBUS_TYPE_OBJECT_PATH;
+  else
+    {
+      fprintf (stderr, "%s: Unknown type \"%s\"\n", appname, arg);
+      exit (1);
+    }
+  return type;
+}
+
+int
+main (int argc, char *argv[])
+{
+  DBusConnection *connection;
+  DBusError error;
+  DBusMessage *message;
+  int print_reply;
+  int print_reply_literal;
+  int reply_timeout;
+  DBusMessageIter iter;
+  int i;
+  DBusBusType type = DBUS_BUS_SESSION;
+  const char *dest = NULL;
+  const char *name = NULL;
+  const char *path = NULL;
+  int message_type = DBUS_MESSAGE_TYPE_SIGNAL;
+  const char *type_str = NULL;
+  const char *address = NULL;
+  int session_or_system = FALSE;
+
+  appname = argv[0];
+  
+  if (argc < 3)
+    usage (1);
+
+  print_reply = FALSE;
+  print_reply_literal = FALSE;
+  reply_timeout = -1;
+  
+  for (i = 1; i < argc && name == NULL; i++)
+    {
+      char *arg = argv[i];
+
+      if (strcmp (arg, "--system") == 0)
+        {
+	  type = DBUS_BUS_SYSTEM;
+          session_or_system = TRUE;
+        }
+      else if (strcmp (arg, "--session") == 0)
+        {
+	  type = DBUS_BUS_SESSION;
+          session_or_system = TRUE;
+        }
+      else if (strstr (arg, "--address") == arg)
+        {
+          address = strchr (arg, '=');
+
+          if (address == NULL) 
+            {
+              fprintf (stderr, "\"--address=\" requires an ADDRESS\n");
+              usage (1);
+            }
+          else
+            {
+              address = address + 1;
+            }
+        }
+      else if (strncmp (arg, "--print-reply", 13) == 0)
+	{
+	  print_reply = TRUE;
+	  message_type = DBUS_MESSAGE_TYPE_METHOD_CALL;
+	  if (*(arg + 13) != '\0')
+	    print_reply_literal = TRUE;
+	}
+      else if (strstr (arg, "--reply-timeout=") == arg)
+	{
+	  reply_timeout = strtol (strchr (arg, '=') + 1,
+				  NULL, 10);
+	}
+      else if (strstr (arg, "--dest=") == arg)
+	dest = strchr (arg, '=') + 1;
+      else if (strstr (arg, "--type=") == arg)
+	type_str = strchr (arg, '=') + 1;
+      else if (!strcmp(arg, "--help"))
+	usage (0);
+      else if (arg[0] == '-')
+	usage (1);
+      else if (path == NULL)
+        path = arg;
+      else /* name == NULL guaranteed by the 'while' loop */
+        name = arg;
+    }
+
+  if (name == NULL)
+    usage (1);
+
+  if (session_or_system &&
+      (address != NULL))
+    {
+      fprintf (stderr, "\"--address\" may not be used with \"--system\" or \"--session\"\n");
+      usage (1);
+    }
+
+  if (type_str != NULL)
+    {
+      message_type = dbus_message_type_from_string (type_str);
+      if (!(message_type == DBUS_MESSAGE_TYPE_METHOD_CALL ||
+            message_type == DBUS_MESSAGE_TYPE_SIGNAL))
+        {
+          fprintf (stderr, "Message type \"%s\" is not supported\n",
+                   type_str);
+          exit (1);
+        }
+    }
+  
+  dbus_error_init (&error);
+
+  if (address != NULL)
+    {
+      connection = dbus_connection_open (address, &error);
+    }
+  else
+    {
+      connection = dbus_bus_get (type, &error);
+    }
+
+  if (connection == NULL)
+    {
+      fprintf (stderr, "Failed to open connection to \"%s\" message bus: %s\n",
+               (address != NULL) ? address :
+                 ((type == DBUS_BUS_SYSTEM) ? "system" : "session"),
+               error.message);
+      dbus_error_free (&error);
+      exit (1);
+    }
+
+  if (message_type == DBUS_MESSAGE_TYPE_METHOD_CALL)
+    {
+      char *last_dot;
+
+      last_dot = strrchr (name, '.');
+      if (last_dot == NULL)
+        {
+          fprintf (stderr, "Must use org.mydomain.Interface.Method notation, no dot in \"%s\"\n",
+                   name);
+          exit (1);
+        }
+      *last_dot = '\0';
+      
+      message = dbus_message_new_method_call (NULL,
+                                              path,
+                                              name,
+                                              last_dot + 1);
+      dbus_message_set_auto_start (message, TRUE);
+    }
+  else if (message_type == DBUS_MESSAGE_TYPE_SIGNAL)
+    {
+      char *last_dot;
+
+      last_dot = strrchr (name, '.');
+      if (last_dot == NULL)
+        {
+          fprintf (stderr, "Must use org.mydomain.Interface.Signal notation, no dot in \"%s\"\n",
+                   name);
+          exit (1);
+        }
+      *last_dot = '\0';
+      
+      message = dbus_message_new_signal (path, name, last_dot + 1);
+    }
+  else
+    {
+      fprintf (stderr, "Internal error, unknown message type\n");
+      exit (1);
+    }
+
+  if (message == NULL)
+    {
+      fprintf (stderr, "Couldn't allocate D-Bus message\n");
+      exit (1);
+    }
+
+  if (dest && !dbus_message_set_destination (message, dest))
+    {
+      fprintf (stderr, "Not enough memory\n");
+      exit (1);
+    }
+  
+  dbus_message_iter_init_append (message, &iter);
+
+  while (i < argc)
+    {
+      char *arg;
+      char *c;
+      int type;
+      int secondary_type;
+      int container_type;
+      DBusMessageIter *target_iter;
+      DBusMessageIter container_iter;
+
+      type = DBUS_TYPE_INVALID;
+      arg = argv[i++];
+      c = strchr (arg, ':');
+
+      if (c == NULL)
+	{
+	  fprintf (stderr, "%s: Data item \"%s\" is badly formed\n", argv[0], arg);
+	  exit (1);
+	}
+
+      *(c++) = 0;
+
+      container_type = DBUS_TYPE_INVALID;
+
+      if (strcmp (arg, "variant") == 0)
+	container_type = DBUS_TYPE_VARIANT;
+      else if (strcmp (arg, "array") == 0)
+	container_type = DBUS_TYPE_ARRAY;
+      else if (strcmp (arg, "dict") == 0)
+	container_type = DBUS_TYPE_DICT_ENTRY;
+
+      if (container_type != DBUS_TYPE_INVALID)
+	{
+	  arg = c;
+	  c = strchr (arg, ':');
+	  if (c == NULL)
+	    {
+	      fprintf (stderr, "%s: Data item \"%s\" is badly formed\n", argv[0], arg);
+	      exit (1);
+	    }
+	  *(c++) = 0;
+	}
+
+      if (arg[0] == 0)
+	type = DBUS_TYPE_STRING;
+      else
+	type = type_from_name (arg);
+
+      if (container_type == DBUS_TYPE_DICT_ENTRY)
+	{
+	  char sig[5];
+	  arg = c;
+	  c = strchr (c, ':');
+	  if (c == NULL)
+	    {
+	      fprintf (stderr, "%s: Data item \"%s\" is badly formed\n", argv[0], arg);
+	      exit (1);
+	    }
+	  *(c++) = 0;
+	  secondary_type = type_from_name (arg);
+	  sig[0] = DBUS_DICT_ENTRY_BEGIN_CHAR;
+	  sig[1] = type;
+	  sig[2] = secondary_type;
+	  sig[3] = DBUS_DICT_ENTRY_END_CHAR;
+	  sig[4] = '\0';
+	  dbus_message_iter_open_container (&iter,
+					    DBUS_TYPE_ARRAY,
+					    sig,
+					    &container_iter);
+	  target_iter = &container_iter;
+	}
+      else if (container_type != DBUS_TYPE_INVALID)
+	{
+	  char sig[2];
+	  sig[0] = type;
+	  sig[1] = '\0';
+	  dbus_message_iter_open_container (&iter,
+					    container_type,
+					    sig,
+					    &container_iter);
+	  target_iter = &container_iter;
+	}
+      else
+	target_iter = &iter;
+
+      if (container_type == DBUS_TYPE_ARRAY)
+	{
+	  append_array (target_iter, type, c);
+	}
+      else if (container_type == DBUS_TYPE_DICT_ENTRY)
+	{
+	  append_dict (target_iter, type, secondary_type, c);
+	}
+      else
+	append_arg (target_iter, type, c);
+
+      if (container_type != DBUS_TYPE_INVALID)
+	{
+	  dbus_message_iter_close_container (&iter,
+					     &container_iter);
+	}
+    }
+
+  if (print_reply)
+    {
+      DBusMessage *reply;
+
+      dbus_error_init (&error);
+      reply = dbus_connection_send_with_reply_and_block (connection,
+                                                         message, reply_timeout,
+                                                         &error);
+      if (dbus_error_is_set (&error))
+        {
+          fprintf (stderr, "Error %s: %s\n",
+		   error.name,
+                   error.message);
+          exit (1);
+        }
+
+      if (reply)
+        {
+          print_message (reply, print_reply_literal);
+          dbus_message_unref (reply);
+        }
+    }
+  else
+    {
+      dbus_connection_send (connection, message, NULL);
+      dbus_connection_flush (connection);
+    }
+
+  dbus_message_unref (message);
+
+  dbus_connection_unref (connection);
+
+  exit (0);
+}
diff --git a/dbus/tools/dbus-uuidgen.c b/dbus/tools/dbus-uuidgen.c
new file mode 100644
index 0000000..c8ba1cf
--- /dev/null
+++ b/dbus/tools/dbus-uuidgen.c
@@ -0,0 +1,161 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* dbus-uuidgen.c  Utility program to create UUIDs
+ *
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dbus/dbus-uuidgen.h>
+#include <dbus/dbus.h>
+
+static void
+usage (char *name, int ecode)
+{
+  if (name == NULL)
+    name = "dbus-uuidgen";
+  
+  fprintf (stderr, "Usage: %s [--ensure[=FILENAME]] [--get[=FILENAME]]\n", name);
+  exit (ecode);
+}
+
+static void
+version (void)
+{
+  printf ("D-Bus UUID Generator %s\n"
+          "Copyright (C) 2006 Red Hat, Inc.\n"
+          "This is free software; see the source for copying conditions.\n"
+          "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
+          VERSION);
+  exit (0);
+}
+
+static dbus_bool_t
+get_arg (const char  *arg,
+         const char  *option,
+         const char **value_p)
+{
+  const char *fn;
+
+  if (strlen(arg) < strlen(option))
+    return FALSE;
+  
+  fn = arg + strlen(option);
+
+  if (!(*fn == '=' || *fn == ' ' || *fn == '\0'))
+    {
+      usage (NULL, 1);
+    }
+  
+  if (*fn == '=')
+    ++fn;
+  
+  while (*fn == ' ' && *fn != '\0')
+    ++fn;
+  
+  if (*fn != '\0')
+    {
+      *value_p = fn;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int i;
+  const char *filename;
+  dbus_bool_t ensure_uuid;
+  dbus_bool_t get_uuid;
+  DBusError error;
+
+  ensure_uuid = FALSE;
+  get_uuid = FALSE;
+  
+  filename = NULL;
+
+  for (i = 1; i < argc; i++)
+    {
+      char *arg = argv[i];
+
+      if (strncmp (arg, "--ensure", strlen("--ensure")) == 0)
+        {
+          get_arg (arg, "--ensure", &filename);
+          ensure_uuid = TRUE;
+        }
+      else if (strncmp (arg, "--get", strlen("--get")) == 0)
+        {
+          get_arg (arg, "--get", &filename);
+          get_uuid = TRUE;
+        }
+      else if (strcmp (arg, "--help") == 0)
+	usage (argv[0], 0);
+      else if (strcmp (arg, "--version") == 0)
+        version ();
+      else
+        usage (argv[0], 1);
+    }
+
+  if (get_uuid && ensure_uuid)
+    {
+      fprintf (stderr, "Can't specify both --get and --ensure\n");
+      exit (1);
+    }
+
+  dbus_error_init (&error);
+  
+  if (get_uuid || ensure_uuid)
+    {
+      char *uuid;
+      if (dbus_internal_do_not_use_get_uuid (filename, &uuid, ensure_uuid, &error))
+        {
+          if (get_uuid) /* print nothing on --ensure */
+            printf ("%s\n", uuid);
+          dbus_free (uuid);
+        }
+    }
+  else
+    {
+      char *uuid;
+      if (dbus_internal_do_not_use_create_uuid (&uuid))
+        {
+          printf ("%s\n", uuid);
+          dbus_free (uuid);
+        }
+      else
+        {
+          dbus_set_error (&error, DBUS_ERROR_NO_MEMORY, "No memory");
+        }
+    }
+
+  if (dbus_error_is_set (&error))
+    {
+      fprintf (stderr, "%s\n", error.message);
+      dbus_error_free (&error);
+      exit (1);
+    }
+  else
+    {
+      exit (0);
+    }
+}
diff --git a/dbus/tools/lcov.am b/dbus/tools/lcov.am
new file mode 100644
index 0000000..7ba4991
--- /dev/null
+++ b/dbus/tools/lcov.am
@@ -0,0 +1,43 @@
+# Copyright © 2008-2011 Collabora Ltd.
+# Copyright © 2008-2011 Nokia Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+lcov-reset:
+	lcov --directory @abs_top_srcdir@ --zerocounters
+
+lcov-report:
+	lcov --directory @abs_top_srcdir@ --capture \
+		--output-file @abs_top_builddir@/lcov.info
+	$(mkdir_p) @abs_top_builddir@/lcov.html
+	git_commit=`GIT_DIR=@abs_top_srcdir@/.git git log -1 --pretty=format:%h 2>/dev/null`;\
+	genhtml --title "@PACKAGE_STRING@ $$git_commit" \
+		--output-directory @abs_top_builddir@/lcov.html lcov.info
+	@echo
+	@echo 'lcov report can be found in:'
+	@echo 'file://@abs_top_builddir@/lcov.html/index.html'
+	@echo
+
+lcov-check:
+	$(MAKE) lcov-reset
+	$(MAKE) check $(LCOV_CHECK_ARGS)
+	$(MAKE) lcov-report
+
+## vim:set ft=automake:
diff --git a/dbus/tools/run-with-tmp-session-bus.sh b/dbus/tools/run-with-tmp-session-bus.sh
new file mode 100644
index 0000000..c39999f
--- /dev/null
+++ b/dbus/tools/run-with-tmp-session-bus.sh
@@ -0,0 +1,76 @@
+#! /bin/sh
+
+SCRIPTNAME=$0
+WRAPPED_SCRIPT=$1
+shift
+
+die() 
+{
+    if ! test -z "$DBUS_SESSION_BUS_PID" ; then
+        echo "killing message bus "$DBUS_SESSION_BUS_PID >&2
+        kill -9 $DBUS_SESSION_BUS_PID
+    fi
+    echo $SCRIPTNAME: $* >&2
+    exit 1
+}
+
+if test -z "$DBUS_TOP_BUILDDIR" ; then
+    die "Must set DBUS_TOP_BUILDDIR"
+fi
+
+## convenient to be able to ctrl+C without leaking the message bus process
+trap 'die "Received SIGINT"' INT
+
+CONFIG_FILE=./run-with-tmp-session-bus.conf
+SERVICE_DIR="$DBUS_TOP_BUILDDIR/test/data/valid-service-files"
+ESCAPED_SERVICE_DIR=`echo $SERVICE_DIR | sed -e 's/\//\\\\\\//g'`
+echo "escaped service dir is: $ESCAPED_SERVICE_DIR" >&2
+
+if test -z "$SOURCE_CONFIG_FILE"; then
+    SOURCE_CONFIG_FILE="$DBUS_TOP_BUILDDIR/bus/session.conf";
+fi
+## create a configuration file based on the standard session.conf
+cat $SOURCE_CONFIG_FILE |  \
+    sed -e 's/<standard_session_servicedirs.*$/<servicedir>'$ESCAPED_SERVICE_DIR'<\/servicedir>/g' |  \
+    sed -e 's/<include.*$//g'                \
+  > $CONFIG_FILE
+
+echo "Created configuration file $CONFIG_FILE" >&2
+
+if ! test -e "$DBUS_TOP_BUILDDIR"/bus/dbus-daemon ; then
+    die "$DBUS_TOP_BUILDDIR/bus/dbus-daemon does not exist"
+fi
+
+PATH="$DBUS_TOP_BUILDDIR"/bus:$PATH
+export PATH
+
+## the libtool script found by the path search should already do this, but
+LD_LIBRARY_PATH=$DBUS_TOP_BUILDDIR/dbus/.libs:$LD_LIBRARY_PATH
+export LD_LIBRARY_PATH
+unset DBUS_SESSION_BUS_ADDRESS
+unset DBUS_SESSION_BUS_PID
+
+echo "Running $DBUS_TOP_BUILDDIR/tools/dbus-launch --sh-syntax --config-file=$CONFIG_FILE" >&2
+
+DBUS_USE_TEST_BINARY=1 
+export DBUS_USE_TEST_BINARY
+eval `$DBUS_TOP_BUILDDIR/tools/dbus-launch --sh-syntax --config-file=$CONFIG_FILE`
+
+if test -z "$DBUS_SESSION_BUS_PID" ; then
+    die "Failed to launch message bus for test script to run"
+fi
+
+echo "Started bus pid $DBUS_SESSION_BUS_PID at $DBUS_SESSION_BUS_ADDRESS" >&2
+
+# Execute wrapped script
+echo "Running $WRAPPED_SCRIPT $@" >&2
+$WRAPPED_SCRIPT "$@" || die "script \"$WRAPPED_SCRIPT\" failed"
+
+kill -TERM $DBUS_SESSION_BUS_PID || die "Message bus vanished! should not have happened" && echo "Killed daemon $DBUS_SESSION_BUS_PID" >&2
+
+sleep 2
+
+## be sure it really died 
+kill -9 $DBUS_SESSION_BUS_PID > /dev/null 2>&1 || true
+
+exit 0
diff --git a/dbus/tools/strtoll.c b/dbus/tools/strtoll.c
new file mode 100644
index 0000000..e4f5770
--- /dev/null
+++ b/dbus/tools/strtoll.c
@@ -0,0 +1,166 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <limits.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdlib.h>
+#ifdef DBUS_WINCE
+#include <windows.h>
+#endif
+
+#ifndef isspace
+#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
+#endif
+
+/* Minimum and maximum values a `signed long long int' can hold.  */
+#ifndef LLONG_MAX
+#   define LLONG_MAX	9223372036854775807LL
+#endif
+
+#ifndef LLONG_MIN
+#   define LLONG_MIN	(-LLONG_MAX - 1LL)
+#endif
+/* Maximum value an `unsigned long long int' can hold.  (Minimum is 0.)  */
+#ifndef ULLONG_MAX
+#   define ULLONG_MAX	18446744073709551615ULL
+#endif
+/*
+ * Convert a string to a long long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long long strtoll (const char*, char **, int);
+
+long long
+strtoll(const char * nptr, char ** endptr, int base)
+{
+	const char *s;
+	unsigned long long acc;
+	char c;
+	unsigned long long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * Skip white space and pick up leading +/- sign if any.
+	 * If base is 0, allow 0x for hex and 0 for octal, else
+	 * assume decimal; if base is already 16, allow 0x.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X') &&
+	    ((s[1] >= '0' && s[1] <= '9') ||
+	    (s[1] >= 'A' && s[1] <= 'F') ||
+	    (s[1] >= 'a' && s[1] <= 'f'))) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	/*
+	 * Compute the cutoff value between legal numbers and illegal
+	 * numbers.  That is the largest legal value, divided by the
+	 * base.  An input number that is greater than this value, if
+	 * followed by a legal input character, is too big.  One that
+	 * is equal to this value may be valid or not; the limit
+	 * between valid and invalid numbers is then based on the last
+	 * digit.  For instance, if the range for quads is
+	 * [-9223372036854775808..9223372036854775807] and the input base
+	 * is 10, cutoff will be set to 922337203685477580 and cutlim to
+	 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
+	 * accumulated a value > 922337203685477580, or equal but the
+	 * next digit is > 7 (or 8), the number is too big, and we will
+	 * return a range error.
+	 *
+	 * Set 'any' if any `digits' consumed; make it negative to indicate
+	 * overflow.
+	 */
+	cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
+	    : LLONG_MAX;
+	cutlim = cutoff % base;
+	cutoff /= base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = neg ? LLONG_MIN : LLONG_MAX;
+#ifdef DBUS_WINCE
+		SetLastError (ERROR_ARITHMETIC_OVERFLOW);
+#else
+		errno = ERANGE;
+#endif
+	} else if (!any) {
+noconv:
+#ifdef DBUS_WINCE
+		SetLastError (ERROR_INVALID_PARAMETER);
+#else
+		errno = EINVAL;
+#endif
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}
+
diff --git a/dbus/tools/strtoull.c b/dbus/tools/strtoull.c
new file mode 100644
index 0000000..459c509
--- /dev/null
+++ b/dbus/tools/strtoull.c
@@ -0,0 +1,144 @@
+/*-
+ * Copyright (c) 1992, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <limits.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <stdlib.h>
+#ifdef DBUS_WINCE
+#include <windows.h>
+#endif
+
+#ifndef isspace
+#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
+#endif
+
+/* Minimum and maximum values a `signed long long int' can hold.  */
+#ifndef LLONG_MAX
+#   define LLONG_MAX	9223372036854775807LL
+#endif
+
+#ifndef LLONG_MIN
+#   define LLONG_MIN	(-LLONG_MAX - 1LL)
+#endif
+/* Maximum value an `unsigned long long int' can hold.  (Minimum is 0.)  */
+#ifndef ULLONG_MAX
+#   define ULLONG_MAX	18446744073709551615ULL
+#endif
+
+/*
+ * Convert a string to an unsigned long long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long long strtoull (const char *, char **, int);
+
+unsigned long long
+strtoull(const char * nptr, char ** endptr, int base)
+{
+	const char *s;
+	unsigned long long acc;
+	char c;
+	unsigned long long cutoff;
+	int neg, any, cutlim;
+
+	/*
+	 * See strtoq for comments as to the logic used.
+	 */
+	s = nptr;
+	do {
+		c = *s++;
+	} while (isspace((unsigned char)c));
+	if (c == '-') {
+		neg = 1;
+		c = *s++;
+	} else {
+		neg = 0;
+		if (c == '+')
+			c = *s++;
+	}
+	if ((base == 0 || base == 16) &&
+	    c == '0' && (*s == 'x' || *s == 'X') &&
+	    ((s[1] >= '0' && s[1] <= '9') ||
+	    (s[1] >= 'A' && s[1] <= 'F') ||
+	    (s[1] >= 'a' && s[1] <= 'f'))) {
+		c = s[1];
+		s += 2;
+		base = 16;
+	}
+	if (base == 0)
+		base = c == '0' ? 8 : 10;
+	acc = any = 0;
+	if (base < 2 || base > 36)
+		goto noconv;
+
+	cutoff = ULLONG_MAX / base;
+	cutlim = ULLONG_MAX % base;
+	for ( ; ; c = *s++) {
+		if (c >= '0' && c <= '9')
+			c -= '0';
+		else if (c >= 'A' && c <= 'Z')
+			c -= 'A' - 10;
+		else if (c >= 'a' && c <= 'z')
+			c -= 'a' - 10;
+		else
+			break;
+		if (c >= base)
+			break;
+		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+			any = -1;
+		else {
+			any = 1;
+			acc *= base;
+			acc += c;
+		}
+	}
+	if (any < 0) {
+		acc = ULLONG_MAX;
+#ifdef DBUS_WINCE
+		SetLastError (ERROR_ARITHMETIC_OVERFLOW);
+#else
+		errno = ERANGE;
+#endif
+	} else if (!any) {
+noconv:
+#ifdef DBUS_WINCE
+		SetLastError (ERROR_INVALID_PARAMETER);
+#else
+		errno = EINVAL;
+#endif
+	} else if (neg)
+		acc = -acc;
+	if (endptr != NULL)
+		*endptr = (char *)(any ? s - 1 : nptr);
+	return (acc);
+}