Merge "Force alignment of data buffer used to process netlink messages"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 8611d3b..74ec29d 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -50,3 +50,4 @@
 
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/init.rc)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/init.rc)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/reboot)
diff --git a/liblinenoise/MODULE_LICENSE_BSD_LIKE b/MODULE_LICENSE_APACHE2
similarity index 100%
copy from liblinenoise/MODULE_LICENSE_BSD_LIKE
copy to MODULE_LICENSE_APACHE2
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..152be20
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,324 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Android-specific code.                        ==
+   =========================================================================
+
+Android Code
+Copyright 2005-2008 The Android Open Source Project
+
+This product includes software developed as part of
+The Android Open Source Project (http://source.android.com).
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Apache Commons code.                              ==
+   =========================================================================
+
+Apache Commons
+Copyright 1999-2006 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Jakarta Commons Logging.                          ==
+   =========================================================================
+
+Jakarta Commons Logging (JCL)
+Copyright 2005,2006 The Apache Software Foundation.
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Nuance code.                                  ==
+   =========================================================================
+
+These files are Copyright 2007 Nuance Communications, but released under
+the Apache2 License.
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Media Codecs code.                            ==
+   =========================================================================
+
+Media Codecs
+These files are Copyright 1998 - 2009 PacketVideo, but released under
+the Apache2 License.
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the TagSoup code.                                 ==
+   =========================================================================
+
+This file is part of TagSoup and is Copyright 2002-2008 by John Cowan.
+
+TagSoup is licensed under the Apache License,
+Version 2.0.  You may obtain a copy of this license at
+http://www.apache.org/licenses/LICENSE-2.0 .  You may also have
+additional legal rights not granted by this license.
+
+TagSoup is distributed in the hope that it will be useful, but
+unless required by applicable law or agreed to in writing, TagSoup
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+OF ANY KIND, either express or implied; not even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Additional Codecs code.                           ==
+   =========================================================================
+
+Additional Codecs
+These files are Copyright 2003-2010 VisualOn, but released under
+the Apache2 License.
+
+  =========================================================================
+  ==  NOTICE file corresponding to the section 4 d of                    ==
+  ==  the Apache License, Version 2.0,                                   ==
+  ==  in this case for the Audio Effects code.                           ==
+  =========================================================================
+
+Audio Effects
+These files are Copyright (C) 2004-2010 NXP Software and
+Copyright (C) 2010 The Android Open Source Project, but released under
+the Apache2 License.
+
+
+                               Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the 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.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+
+
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+Unicode Data Files include all data files under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+and http://www.unicode.org/cldr/data/ . Unicode Software includes any
+source code published in the Unicode Standard or under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/, and
+http://www.unicode.org/cldr/data/.
+
+NOTICE TO USER: Carefully read the following legal agreement. BY
+DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA
+FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY
+ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF
+THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY,
+DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2008 Unicode, Inc. All rights reserved. Distributed
+under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation (the
+"Data Files") or Unicode software and any associated documentation (the
+"Software") to deal in the Data Files or Software without restriction,
+including without limitation the rights to use, copy, modify, merge,
+publish, distribute, and/or sell copies of the Data Files or Software,
+and to permit persons to whom the Data Files or Software are furnished to
+do so, provided that (a) the above copyright notice(s) and this permission
+notice appear with all copies of the Data Files or Software, (b) both the
+above copyright notice(s) and this permission notice appear in associated
+documentation, and (c) there is clear notice in each modified Data File
+or in the Software as well as in the documentation associated with the
+Data File(s) or Software that the data or software has been modified.
+
+THE DATA FILES AND SOFTWARE ARE 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
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
+INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
+OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in these Data Files or Software without prior written
+authorization of the copyright holder.
diff --git a/adb/Android.mk b/adb/Android.mk
index a803978..721b48d 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -64,7 +64,6 @@
 	file_sync_client.c \
 	$(EXTRA_SRCS) \
 	$(USB_SRCS) \
-	utils.c \
 	usb_vendors.c
 
 LOCAL_C_INCLUDES += external/openssl/include
@@ -116,8 +115,7 @@
 	framebuffer_service.c \
 	remount_service.c \
 	usb_linux_client.c \
-	log_service.c \
-	utils.c
+	log_service.c
 
 LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
 LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
@@ -132,7 +130,7 @@
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
 
-LOCAL_STATIC_LIBRARIES := libcutils libc libmincrypt
+LOCAL_STATIC_LIBRARIES := liblog libcutils libc libmincrypt
 include $(BUILD_EXECUTABLE)
 
 
@@ -157,7 +155,6 @@
 	file_sync_client.c \
 	get_my_path_linux.c \
 	usb_linux.c \
-	utils.c \
 	usb_vendors.c \
 	fdevent.c
 
diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT
index b53bc44..5966686 100644
--- a/adb/SERVICES.TXT
+++ b/adb/SERVICES.TXT
@@ -225,27 +225,6 @@
       If the adbd daemon doesn't have sufficient privileges to open
       the framebuffer device, the connection is simply closed immediately.
 
-dns:<server-name>
-    This service is an exception because it only runs within the ADB server.
-    It is used to implement USB networking, i.e. to provide a network connection
-    to the device through the host machine (note: this is the exact opposite of
-    network tethering).
-
-    It is used to perform a gethostbyname(<address>) on the host and return
-    the corresponding IP address as a 4-byte string.
-
-recover:<size>
-    This service is used to upload a recovery image to the device. <size>
-    must be a number corresponding to the size of the file. The service works
-    by:
-
-       - creating a file named /tmp/update
-       - reading 'size' bytes from the client and writing them to /tmp/update
-       - when everything is read successfully, create a file named /tmp/update.start
-
-    This service can only work when the device is in recovery mode. Otherwise,
-    the /tmp directory doesn't exist and the connection will be closed immediately.
-
 jdwp:<pid>
     Connects to the JDWP thread running in the VM of process <pid>.
 
diff --git a/adb/adb.c b/adb/adb.c
index ec74b49..72b7484 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -34,6 +34,7 @@
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 #if !ADB_HOST
+#include <cutils/properties.h>
 #include <private/android_filesystem_config.h>
 #include <sys/capability.h>
 #include <linux/prctl.h>
@@ -1199,7 +1200,7 @@
 #endif
     int i;
     for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
-        if ((i == CAP_SETUID) || (i == CAP_SETGID)) {
+        if (i == CAP_SETUID || i == CAP_SETGID) {
             // CAP_SETUID CAP_SETGID needed by /system/bin/run-as
             continue;
         }
@@ -1301,13 +1302,6 @@
     /* don't listen on a port (default 5037) if running in secure mode */
     /* don't run as root if we are running in secure mode */
     if (should_drop_privileges()) {
-        struct __user_cap_header_struct header;
-        struct __user_cap_data_struct cap[2];
-
-        if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
-            exit(1);
-        }
-
         drop_capabilities_bounding_set_if_needed();
 
         /* add extra groups:
@@ -1337,16 +1331,6 @@
             exit(1);
         }
 
-        memset(&header, 0, sizeof(header));
-        memset(cap, 0, sizeof(cap));
-
-        /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */
-        header.version = _LINUX_CAPABILITY_VERSION_3;
-        header.pid = 0;
-        cap[CAP_TO_INDEX(CAP_SYS_BOOT)].effective |= CAP_TO_MASK(CAP_SYS_BOOT);
-        cap[CAP_TO_INDEX(CAP_SYS_BOOT)].permitted |= CAP_TO_MASK(CAP_SYS_BOOT);
-        capset(&header, cap);
-
         D("Local port disabled\n");
     } else {
         char local_name[30];
@@ -1404,105 +1388,6 @@
     return 0;
 }
 
-#if ADB_HOST
-void connect_device(char* host, char* buffer, int buffer_size)
-{
-    int port, fd;
-    char* portstr = strchr(host, ':');
-    char hostbuf[100];
-    char serial[100];
-
-    strncpy(hostbuf, host, sizeof(hostbuf) - 1);
-    if (portstr) {
-        if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) {
-            snprintf(buffer, buffer_size, "bad host name %s", host);
-            return;
-        }
-        // zero terminate the host at the point we found the colon
-        hostbuf[portstr - host] = 0;
-        if (sscanf(portstr + 1, "%d", &port) == 0) {
-            snprintf(buffer, buffer_size, "bad port number %s", portstr);
-            return;
-        }
-    } else {
-        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
-    }
-
-    snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
-    if (find_transport(serial)) {
-        snprintf(buffer, buffer_size, "already connected to %s", serial);
-        return;
-    }
-
-    fd = socket_network_client(hostbuf, port, SOCK_STREAM);
-    if (fd < 0) {
-        snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
-        return;
-    }
-
-    D("client: connected on remote on fd %d\n", fd);
-    close_on_exec(fd);
-    disable_tcp_nagle(fd);
-    register_socket_transport(fd, serial, port, 0);
-    snprintf(buffer, buffer_size, "connected to %s", serial);
-}
-
-void connect_emulator(char* port_spec, char* buffer, int buffer_size)
-{
-    char* port_separator = strchr(port_spec, ',');
-    if (!port_separator) {
-        snprintf(buffer, buffer_size,
-                "unable to parse '%s' as <console port>,<adb port>",
-                port_spec);
-        return;
-    }
-
-    // Zero-terminate console port and make port_separator point to 2nd port.
-    *port_separator++ = 0;
-    int console_port = strtol(port_spec, NULL, 0);
-    int adb_port = strtol(port_separator, NULL, 0);
-    if (!(console_port > 0 && adb_port > 0)) {
-        *(port_separator - 1) = ',';
-        snprintf(buffer, buffer_size,
-                "Invalid port numbers: Expected positive numbers, got '%s'",
-                port_spec);
-        return;
-    }
-
-    /* Check if the emulator is already known.
-     * Note: There's a small but harmless race condition here: An emulator not
-     * present just yet could be registered by another invocation right
-     * after doing this check here. However, local_connect protects
-     * against double-registration too. From here, a better error message
-     * can be produced. In the case of the race condition, the very specific
-     * error message won't be shown, but the data doesn't get corrupted. */
-    atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
-    if (known_emulator != NULL) {
-        snprintf(buffer, buffer_size,
-                "Emulator on port %d already registered.", adb_port);
-        return;
-    }
-
-    /* Check if more emulators can be registered. Similar unproblematic
-     * race condition as above. */
-    int candidate_slot = get_available_local_transport_index();
-    if (candidate_slot < 0) {
-        snprintf(buffer, buffer_size, "Cannot accept more emulators.");
-        return;
-    }
-
-    /* Preconditions met, try to connect to the emulator. */
-    if (!local_connect_arbitrary_ports(console_port, adb_port)) {
-        snprintf(buffer, buffer_size,
-                "Connected to emulator on ports %d,%d", console_port, adb_port);
-    } else {
-        snprintf(buffer, buffer_size,
-                "Could not connect to emulator on ports %d,%d",
-                console_port, adb_port);
-    }
-}
-#endif
-
 int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
 {
     atransport *transport = NULL;
@@ -1563,21 +1448,6 @@
         }
     }
 
-    // add a new TCP transport, device or emulator
-    if (!strncmp(service, "connect:", 8)) {
-        char buffer[4096];
-        char* host = service + 8;
-        if (!strncmp(host, "emu:", 4)) {
-            connect_emulator(host + 4, buffer, sizeof(buffer));
-        } else {
-            connect_device(host, buffer, sizeof(buffer));
-        }
-        // Send response for emulator and device
-        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);
-        writex(reply_fd, buf, strlen(buf));
-        return 0;
-    }
-
     // remove TCP transport
     if (!strncmp(service, "disconnect:", 11)) {
         char buffer[4096];
diff --git a/adb/adb.h b/adb/adb.h
index a01d460..622ca70 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -128,10 +128,7 @@
         */
     void (*close)(asocket *s);
 
-        /* socket-type-specific extradata */
-    void *extra;
-
-    	/* A socket is bound to atransport */
+        /* A socket is bound to atransport */
     atransport *transport;
 };
 
@@ -292,7 +289,7 @@
 void close_usb_devices();
 
 /* cause new transports to be init'd and added to the list */
-void register_socket_transport(int s, const char *serial, int port, int local);
+int register_socket_transport(int s, const char *serial, int port, int local);
 
 /* these should only be used for the "adb disconnect" command */
 void unregister_transport(atransport *t);
diff --git a/adb/log_service.c b/adb/log_service.c
index 6e9bdee..af24356 100644
--- a/adb/log_service.c
+++ b/adb/log_service.c
@@ -22,7 +22,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <sys/socket.h>
-#include <cutils/logger.h>
+#include <log/logger.h>
 #include "sysdeps.h"
 #include "adb.h"
 
diff --git a/adb/mutex_list.h b/adb/mutex_list.h
index 652dd73..ff72751 100644
--- a/adb/mutex_list.h
+++ b/adb/mutex_list.h
@@ -6,7 +6,6 @@
 #ifndef ADB_MUTEX
 #error ADB_MUTEX not defined when including this file
 #endif
-ADB_MUTEX(dns_lock)
 ADB_MUTEX(socket_list_lock)
 ADB_MUTEX(transport_lock)
 #if ADB_HOST
diff --git a/adb/remount_service.c b/adb/remount_service.c
index 4cb41e7..ad61284 100644
--- a/adb/remount_service.c
+++ b/adb/remount_service.c
@@ -72,6 +72,8 @@
 static int remount_system()
 {
     char *dev;
+    int fd;
+    int OFF = 0;
 
     if (system_ro == 0) {
         return 0;
@@ -82,6 +84,13 @@
     if (!dev)
         return -1;
 
+    fd = unix_open(dev, O_RDONLY);
+    if (fd < 0)
+        return -1;
+
+    ioctl(fd, BLKROSET, &OFF);
+    adb_close(fd);
+
     system_ro = mount(dev, "/system", "none", MS_REMOUNT, NULL);
 
     free(dev);
diff --git a/adb/services.c b/adb/services.c
index 54d21a8..951048e 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <stddef.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -34,6 +35,7 @@
 #  endif
 #else
 #  include <cutils/android_reboot.h>
+#  include <cutils/properties.h>
 #endif
 
 typedef struct stinfo stinfo;
@@ -53,59 +55,7 @@
     return 0;
 }
 
-#if ADB_HOST
-ADB_MUTEX_DEFINE( dns_lock );
-
-static void dns_service(int fd, void *cookie)
-{
-    char *hostname = cookie;
-    struct hostent *hp;
-    unsigned zero = 0;
-
-    adb_mutex_lock(&dns_lock);
-    hp = gethostbyname(hostname);
-    free(cookie);
-    if(hp == 0) {
-        writex(fd, &zero, 4);
-    } else {
-        writex(fd, hp->h_addr, 4);
-    }
-    adb_mutex_unlock(&dns_lock);
-    adb_close(fd);
-}
-#else
-extern int recovery_mode;
-
-static void recover_service(int s, void *cookie)
-{
-    unsigned char buf[4096];
-    unsigned count = (unsigned) cookie;
-    int fd;
-
-    fd = adb_creat("/tmp/update", 0644);
-    if(fd < 0) {
-        adb_close(s);
-        return;
-    }
-
-    while(count > 0) {
-        unsigned xfer = (count > 4096) ? 4096 : count;
-        if(readx(s, buf, xfer)) break;
-        if(writex(fd, buf, xfer)) break;
-        count -= xfer;
-    }
-
-    if(count == 0) {
-        writex(s, "OKAY", 4);
-    } else {
-        writex(s, "FAIL", 4);
-    }
-    adb_close(fd);
-    adb_close(s);
-
-    fd = adb_creat("/tmp/update.begin", 0644);
-    adb_close(fd);
-}
+#if !ADB_HOST
 
 void restart_root_service(int fd, void *cookie)
 {
@@ -165,6 +115,7 @@
 void reboot_service(int fd, void *arg)
 {
     char buf[100];
+    char property_val[PROPERTY_VALUE_MAX];
     int pid, ret;
 
     sync();
@@ -182,51 +133,29 @@
         waitpid(pid, &ret, 0);
     }
 
-    ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
-    if (ret < 0) {
-        snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
+    ret = snprintf(property_val, sizeof(property_val), "reboot,%s", (char *) arg);
+    if (ret >= (int) sizeof(property_val)) {
+        snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret);
         writex(fd, buf, strlen(buf));
+        goto cleanup;
     }
+
+    ret = property_set(ANDROID_RB_PROPERTY, property_val);
+    if (ret < 0) {
+        snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret);
+        writex(fd, buf, strlen(buf));
+        goto cleanup;
+    }
+    // Don't return early. Give the reboot command time to take effect
+    // to avoid messing up scripts which do "adb reboot && adb wait-for-device"
+    while(1) { pause(); }
+cleanup:
     free(arg);
     adb_close(fd);
 }
 
 #endif
 
-#if 0
-static void echo_service(int fd, void *cookie)
-{
-    char buf[4096];
-    int r;
-    char *p;
-    int c;
-
-    for(;;) {
-        r = adb_read(fd, buf, 4096);
-        if(r == 0) goto done;
-        if(r < 0) {
-            if(errno == EINTR) continue;
-            else goto done;
-        }
-
-        c = r;
-        p = buf;
-        while(c > 0) {
-            r = write(fd, p, c);
-            if(r > 0) {
-                c -= r;
-                p += r;
-                continue;
-            }
-            if((r < 0) && (errno == EINTR)) continue;
-            goto done;
-        }
-    }
-done:
-    close(fd);
-}
-#endif
-
 static int create_service_thread(void (*func)(int, void *), void *cookie)
 {
     stinfo *sti;
@@ -413,9 +342,7 @@
                 disable_tcp_nagle(ret);
         } else {
 #if ADB_HOST
-            adb_mutex_lock(&dns_lock);
             ret = socket_network_client(name + 1, port, SOCK_STREAM);
-            adb_mutex_unlock(&dns_lock);
 #else
             return -1;
 #endif
@@ -434,18 +361,11 @@
         ret = socket_local_client(name + 16,
                 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
 #endif
-#if ADB_HOST
-    } else if(!strncmp("dns:", name, 4)){
-        char *n = strdup(name + 4);
-        if(n == 0) return -1;
-        ret = create_service_thread(dns_service, n);
-#else /* !ADB_HOST */
+#if !ADB_HOST
     } else if(!strncmp("dev:", name, 4)) {
         ret = unix_open(name + 4, O_RDWR);
     } else if(!strncmp(name, "framebuffer:", 12)) {
         ret = create_service_thread(framebuffer_service, 0);
-    } else if(recovery_mode && !strncmp(name, "recover:", 8)) {
-        ret = create_service_thread(recover_service, (void*) atoi(name + 8));
     } else if (!strncmp(name, "jdwp:", 5)) {
         ret = create_jdwp_connection_fd(atoi(name+5));
     } else if (!strncmp(name, "log:", 4)) {
@@ -481,10 +401,6 @@
     } else if(!strncmp(name, "usb:", 4)) {
         ret = create_service_thread(restart_usb_service, NULL);
 #endif
-#if 0
-    } else if(!strncmp(name, "echo:", 5)){
-        ret = create_service_thread(echo_service, 0);
-#endif
     }
     if (ret >= 0) {
         close_on_exec(ret);
@@ -519,6 +435,124 @@
     adb_close(fd);
     D("wait_for_state is done\n");
 }
+
+static void connect_device(char* host, char* buffer, int buffer_size)
+{
+    int port, fd;
+    char* portstr = strchr(host, ':');
+    char hostbuf[100];
+    char serial[100];
+    int ret;
+
+    strncpy(hostbuf, host, sizeof(hostbuf) - 1);
+    if (portstr) {
+        if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) {
+            snprintf(buffer, buffer_size, "bad host name %s", host);
+            return;
+        }
+        // zero terminate the host at the point we found the colon
+        hostbuf[portstr - host] = 0;
+        if (sscanf(portstr + 1, "%d", &port) == 0) {
+            snprintf(buffer, buffer_size, "bad port number %s", portstr);
+            return;
+        }
+    } else {
+        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+    }
+
+    snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
+
+    fd = socket_network_client(hostbuf, port, SOCK_STREAM);
+    if (fd < 0) {
+        snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
+        return;
+    }
+
+    D("client: connected on remote on fd %d\n", fd);
+    close_on_exec(fd);
+    disable_tcp_nagle(fd);
+
+    ret = register_socket_transport(fd, serial, port, 0);
+    if (ret < 0) {
+        adb_close(fd);
+        snprintf(buffer, buffer_size, "already connected to %s", serial);
+    } else {
+        snprintf(buffer, buffer_size, "connected to %s", serial);
+    }
+}
+
+void connect_emulator(char* port_spec, char* buffer, int buffer_size)
+{
+    char* port_separator = strchr(port_spec, ',');
+    if (!port_separator) {
+        snprintf(buffer, buffer_size,
+                "unable to parse '%s' as <console port>,<adb port>",
+                port_spec);
+        return;
+    }
+
+    // Zero-terminate console port and make port_separator point to 2nd port.
+    *port_separator++ = 0;
+    int console_port = strtol(port_spec, NULL, 0);
+    int adb_port = strtol(port_separator, NULL, 0);
+    if (!(console_port > 0 && adb_port > 0)) {
+        *(port_separator - 1) = ',';
+        snprintf(buffer, buffer_size,
+                "Invalid port numbers: Expected positive numbers, got '%s'",
+                port_spec);
+        return;
+    }
+
+    /* Check if the emulator is already known.
+     * Note: There's a small but harmless race condition here: An emulator not
+     * present just yet could be registered by another invocation right
+     * after doing this check here. However, local_connect protects
+     * against double-registration too. From here, a better error message
+     * can be produced. In the case of the race condition, the very specific
+     * error message won't be shown, but the data doesn't get corrupted. */
+    atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
+    if (known_emulator != NULL) {
+        snprintf(buffer, buffer_size,
+                "Emulator on port %d already registered.", adb_port);
+        return;
+    }
+
+    /* Check if more emulators can be registered. Similar unproblematic
+     * race condition as above. */
+    int candidate_slot = get_available_local_transport_index();
+    if (candidate_slot < 0) {
+        snprintf(buffer, buffer_size, "Cannot accept more emulators.");
+        return;
+    }
+
+    /* Preconditions met, try to connect to the emulator. */
+    if (!local_connect_arbitrary_ports(console_port, adb_port)) {
+        snprintf(buffer, buffer_size,
+                "Connected to emulator on ports %d,%d", console_port, adb_port);
+    } else {
+        snprintf(buffer, buffer_size,
+                "Could not connect to emulator on ports %d,%d",
+                console_port, adb_port);
+    }
+}
+
+static void connect_service(int fd, void* cookie)
+{
+    char buf[4096];
+    char resp[4096];
+    char *host = cookie;
+
+    if (!strncmp(host, "emu:", 4)) {
+        connect_emulator(host + 4, buf, sizeof(buf));
+    } else {
+        connect_device(host, buf, sizeof(buf));
+    }
+
+    // Send response for emulator and device
+    snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf);
+    writex(fd, resp, strlen(resp));
+    adb_close(fd);
+}
 #endif
 
 #if ADB_HOST
@@ -552,6 +586,10 @@
 
         int fd = create_service_thread(wait_for_state, sinfo);
         return create_local_socket(fd);
+    } else if (!strncmp(name, "connect:", 8)) {
+        const char *host = name + 8;
+        int fd = create_service_thread(connect_service, (void *)host);
+        return create_local_socket(fd);
     }
     return NULL;
 }
diff --git a/adb/sockets.c b/adb/sockets.c
index 305cb44..f17608b 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -844,7 +844,7 @@
     free(s);
 }
 
-asocket *create_smart_socket(void (*action_cb)(asocket *s, const char *act))
+static asocket *create_smart_socket(void)
 {
     D("Creating smart socket \n");
     asocket *s = calloc(1, sizeof(asocket));
@@ -852,21 +852,15 @@
     s->enqueue = smart_socket_enqueue;
     s->ready = smart_socket_ready;
     s->close = smart_socket_close;
-    s->extra = action_cb;
 
-    D("SS(%d): created %p\n", s->id, action_cb);
+    D("SS(%d)\n", s->id);
     return s;
 }
 
-void smart_socket_action(asocket *s, const char *act)
-{
-
-}
-
 void connect_to_smartsocket(asocket *s)
 {
     D("Connecting to smart socket \n");
-    asocket *ss = create_smart_socket(smart_socket_action);
+    asocket *ss = create_smart_socket();
     s->peer = ss;
     ss->peer = s;
     s->ready(s);
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 0252ef3..4033b72 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -261,7 +261,6 @@
 
 #include "fdevent.h"
 #include <cutils/sockets.h>
-#include <cutils/properties.h>
 #include <cutils/misc.h>
 #include <signal.h>
 #include <sys/wait.h>
diff --git a/adb/transport.c b/adb/transport.c
index b4abb66..224fe55 100644
--- a/adb/transport.c
+++ b/adb/transport.c
@@ -32,6 +32,11 @@
     .prev = &transport_list,
 };
 
+static atransport pending_list = {
+    .next = &pending_list,
+    .prev = &pending_list,
+};
+
 ADB_MUTEX_DEFINE( transport_lock );
 
 #if ADB_TRACE
@@ -645,8 +650,11 @@
         }
     }
 
-        /* put us on the master device list */
     adb_mutex_lock(&transport_lock);
+    /* remove from pending list */
+    t->next->prev = t->prev;
+    t->prev->next = t->next;
+    /* put us on the master device list */
     t->next = &transport_list;
     t->prev = transport_list.prev;
     t->next->prev = t;
@@ -989,9 +997,10 @@
 }
 #endif // ADB_HOST
 
-void register_socket_transport(int s, const char *serial, int port, int local)
+int register_socket_transport(int s, const char *serial, int port, int local)
 {
     atransport *t = calloc(1, sizeof(atransport));
+    atransport *n;
     char buff[32];
 
     if (!serial) {
@@ -999,15 +1008,37 @@
         serial = buff;
     }
     D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port);
-    if ( init_socket_transport(t, s, port, local) < 0 ) {
-        adb_close(s);
+    if (init_socket_transport(t, s, port, local) < 0) {
         free(t);
-        return;
+        return -1;
     }
-    if(serial) {
-        t->serial = strdup(serial);
+
+    adb_mutex_lock(&transport_lock);
+    for (n = pending_list.next; n != &pending_list; n = n->next) {
+        if (n->serial && !strcmp(serial, n->serial)) {
+            adb_mutex_unlock(&transport_lock);
+            free(t);
+            return -1;
+        }
     }
+
+    for (n = transport_list.next; n != &transport_list; n = n->next) {
+        if (n->serial && !strcmp(serial, n->serial)) {
+            adb_mutex_unlock(&transport_lock);
+            free(t);
+            return -1;
+        }
+    }
+
+    t->next = &pending_list;
+    t->prev = pending_list.prev;
+    t->next->prev = t;
+    t->prev->next = t;
+    t->serial = strdup(serial);
+    adb_mutex_unlock(&transport_lock);
+
     register_transport(t);
+    return 0;
 }
 
 #if ADB_HOST
@@ -1077,6 +1108,14 @@
     if(devpath) {
         t->devpath = strdup(devpath);
     }
+
+    adb_mutex_lock(&transport_lock);
+    t->next = &pending_list;
+    t->prev = pending_list.prev;
+    t->next->prev = t;
+    t->prev->next = t;
+    adb_mutex_unlock(&transport_lock);
+
     register_transport(t);
 }
 
diff --git a/adb/transport_local.c b/adb/transport_local.c
index 96a24ba..1cfa24d 100644
--- a/adb/transport_local.c
+++ b/adb/transport_local.c
@@ -21,6 +21,9 @@
 
 #include "sysdeps.h"
 #include <sys/types.h>
+#if !ADB_HOST
+#include <cutils/properties.h>
+#endif
 
 #define  TRACE_TAG  TRACE_TRANSPORT
 #include "adb.h"
diff --git a/adb/utils.c b/adb/utils.c
deleted file mode 100644
index 91518ba..0000000
--- a/adb/utils.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-#include "utils.h"
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-char*
-buff_addc (char*  buff, char*  buffEnd, int  c)
-{
-    int  avail = buffEnd - buff;
-
-    if (avail <= 0)  /* already in overflow mode */
-        return buff;
-
-    if (avail == 1) {  /* overflowing, the last byte is reserved for zero */
-        buff[0] = 0;
-        return buff + 1;
-    }
-
-    buff[0] = (char) c;  /* add char and terminating zero */
-    buff[1] = 0;
-    return buff + 1;
-}
-
-char*
-buff_adds (char*  buff, char*  buffEnd, const char*  s)
-{
-    int  slen = strlen(s);
-
-    return buff_addb(buff, buffEnd, s, slen);
-}
-
-char*
-buff_addb (char*  buff, char*  buffEnd, const void*  data, int  len)
-{
-    int  avail = (buffEnd - buff);
-
-    if (avail <= 0 || len <= 0)  /* already overflowing */
-        return buff;
-
-    if (len > avail)
-        len = avail;
-
-    memcpy(buff, data, len);
-
-    buff += len;
-
-    /* ensure there is a terminating zero */
-    if (buff >= buffEnd) {  /* overflow */
-        buff[-1] = 0;
-    } else
-        buff[0] = 0;
-
-    return buff;
-}
-
-char*
-buff_add  (char*  buff, char*  buffEnd, const char*  format, ... )
-{
-    int      avail;
-
-    avail = (buffEnd - buff);
-
-    if (avail > 0) {
-        va_list  args;
-        int      nn;
-
-        va_start(args, format);
-        nn = vsnprintf( buff, avail, format, args);
-        va_end(args);
-
-        if (nn < 0) {
-            /* some C libraries return -1 in case of overflow,
-             * but they will also do that if the format spec is
-             * invalid. We assume ADB is not buggy enough to
-             * trigger that last case. */
-            nn = avail;
-        }
-        else if (nn > avail) {
-            nn = avail;
-        }
-
-        buff += nn;
-
-        /* ensure that there is a terminating zero */
-        if (buff >= buffEnd)
-            buff[-1] = 0;
-        else
-            buff[0] = 0;
-    }
-    return buff;
-}
diff --git a/adb/utils.h b/adb/utils.h
deleted file mode 100644
index f70ecd2..0000000
--- a/adb/utils.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-#ifndef _ADB_UTILS_H
-#define _ADB_UTILS_H
-
-/* bounded buffer functions */
-
-/* all these functions are used to append data to a bounded buffer.
- *
- * after each operation, the buffer is guaranteed to be zero-terminated,
- * even in the case of an overflow. they all return the new buffer position
- * which allows one to use them in succession, only checking for overflows
- * at the end. For example:
- *
- *    BUFF_DECL(temp,p,end,1024);
- *    char*    p;
- *
- *    p = buff_addc(temp, end, '"');
- *    p = buff_adds(temp, end, string);
- *    p = buff_addc(temp, end, '"');
- *
- *    if (p >= end) {
- *        overflow detected. note that 'temp' is
- *        zero-terminated for safety. 
- *    }
- *    return strdup(temp);
- */
-
-/* tries to add a character to the buffer, in case of overflow
- * this will only write a terminating zero and return buffEnd.
- */
-char*   buff_addc (char*  buff, char*  buffEnd, int  c);
-
-/* tries to add a string to the buffer */
-char*   buff_adds (char*  buff, char*  buffEnd, const char*  s);
-
-/* tries to add a bytes to the buffer. the input can contain zero bytes,
- * but a terminating zero will always be appended at the end anyway
- */
-char*   buff_addb (char*  buff, char*  buffEnd, const void*  data, int  len);
-
-/* tries to add a formatted string to a bounded buffer */
-char*   buff_add  (char*  buff, char*  buffEnd, const char*  format, ... );
-
-/* convenience macro used to define a bounded buffer, as well as
- * a 'cursor' and 'end' variables all in one go.
- *
- * note: this doesn't place an initial terminating zero in the buffer,
- * you need to use one of the buff_ functions for this. or simply
- * do _cursor[0] = 0 manually.
- */
-#define  BUFF_DECL(_buff,_cursor,_end,_size)   \
-    char   _buff[_size], *_cursor=_buff, *_end = _cursor + (_size)
-
-#endif /* _ADB_UTILS_H */
diff --git a/adf/Android.mk b/adf/Android.mk
new file mode 100644
index 0000000..64d486e
--- /dev/null
+++ b/adf/Android.mk
@@ -0,0 +1,18 @@
+#
+# Copyright (C) 2013 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.
+#
+LOCAL_PATH := $(my-dir)
+
+include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/adf/libadf/Android.mk b/adf/libadf/Android.mk
new file mode 100644
index 0000000..908aa6c
--- /dev/null
+++ b/adf/libadf/Android.mk
@@ -0,0 +1,23 @@
+# Copyright (C) 2013 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := adf.c
+LOCAL_MODULE := libadf
+LOCAL_MODULE_TAGS := optional
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/adf/libadf/adf.c b/adf/libadf/adf.c
new file mode 100644
index 0000000..871629e
--- /dev/null
+++ b/adf/libadf/adf.c
@@ -0,0 +1,810 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <linux/limits.h>
+
+#include <sys/ioctl.h>
+
+#include <adf/adf.h>
+
+#define ADF_BASE_PATH "/dev/"
+
+static ssize_t adf_find_nodes(const char *pattern, adf_id_t **ids)
+{
+    DIR *dir;
+    struct dirent *dirent;
+    size_t n = 0;
+    ssize_t ret;
+    adf_id_t *ids_ret = NULL;
+
+    dir = opendir(ADF_BASE_PATH);
+    if (!dir)
+        return -errno;
+
+    errno = 0;
+    while ((dirent = readdir(dir))) {
+        adf_id_t id;
+        int matched = sscanf(dirent->d_name, pattern, &id);
+
+        if (matched < 0) {
+            ret = -errno;
+            goto done;
+        } else if (matched != 1) {
+            continue;
+        }
+
+        adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
+        if (!new_ids) {
+            ret = -ENOMEM;
+            goto done;
+        }
+
+        ids_ret = new_ids;
+        ids_ret[n] = id;
+        n++;
+    }
+    if (errno)
+        ret = -errno;
+    else
+        ret = n;
+
+done:
+    closedir(dir);
+    if (ret < 0)
+        free(ids_ret);
+    else
+        *ids = ids_ret;
+    return ret;
+}
+
+ssize_t adf_devices(adf_id_t **ids)
+{
+    return adf_find_nodes("adf%u", ids);
+}
+
+int adf_device_open(adf_id_t id, int flags, struct adf_device *dev)
+{
+    char filename[64];
+    int err;
+
+    dev->id = id;
+
+    snprintf(filename, sizeof(filename), ADF_BASE_PATH "adf%u", id);
+    dev->fd = open(filename, flags);
+    if (dev->fd < 0)
+        return -errno;
+
+    return 0;
+}
+
+void adf_device_close(struct adf_device *dev)
+{
+    if (dev->fd >= 0)
+        close(dev->fd);
+}
+
+int adf_get_device_data(struct adf_device *dev, struct adf_device_data *data)
+{
+    int err;
+    int ret = 0;
+
+    memset(data, 0, sizeof(*data));
+
+    err = ioctl(dev->fd, ADF_GET_DEVICE_DATA, data);
+    if (err < 0)
+        return -ENOMEM;
+
+    if (data->n_attachments) {
+        data->attachments = malloc(sizeof(data->attachments[0]) *
+                data->n_attachments);
+        if (!data->attachments)
+            return -ENOMEM;
+    }
+
+    if (data->n_allowed_attachments) {
+        data->allowed_attachments =
+                malloc(sizeof(data->allowed_attachments[0]) *
+                        data->n_allowed_attachments);
+        if (!data->allowed_attachments) {
+            ret = -ENOMEM;
+            goto done;
+        }
+    }
+
+    if (data->custom_data_size) {
+        data->custom_data = malloc(data->custom_data_size);
+        if (!data->custom_data) {
+            ret = -ENOMEM;
+            goto done;
+        }
+    }
+
+    err = ioctl(dev->fd, ADF_GET_DEVICE_DATA, data);
+    if (err < 0)
+        ret = -errno;
+
+done:
+    if (ret < 0)
+        adf_free_device_data(data);
+    return ret;
+}
+
+void adf_free_device_data(struct adf_device_data *data)
+{
+    free(data->attachments);
+    free(data->allowed_attachments);
+    free(data->custom_data);
+}
+
+int adf_device_post(struct adf_device *dev,
+        adf_id_t *interfaces, size_t n_interfaces,
+        struct adf_buffer_config *bufs, size_t n_bufs,
+        void *custom_data, size_t custom_data_size)
+{
+    int err;
+    struct adf_post_config data;
+
+    memset(&data, 0, sizeof(data));
+    data.interfaces = interfaces;
+    data.n_interfaces = n_interfaces;
+    data.bufs = bufs;
+    data.n_bufs = n_bufs;
+    data.custom_data = custom_data;
+    data.custom_data_size = custom_data_size;
+
+    err = ioctl(dev->fd, ADF_POST_CONFIG, &data);
+    if (err < 0)
+        return -errno;
+
+    return (int)data.complete_fence;
+}
+
+static int adf_device_attachment(struct adf_device *dev,
+        adf_id_t overlay_engine, adf_id_t interface, bool attach)
+{
+    int err;
+    struct adf_attachment_config data;
+
+    memset(&data, 0, sizeof(data));
+    data.overlay_engine = overlay_engine;
+    data.interface = interface;
+
+    err = ioctl(dev->fd, attach ? ADF_ATTACH : ADF_DETACH, &data);
+    if (err < 0)
+        return -errno;
+
+    return 0;
+}
+
+int adf_device_attach(struct adf_device *dev, adf_id_t overlay_engine,
+                      adf_id_t interface)
+{
+   return adf_device_attachment(dev, overlay_engine, interface, true);
+}
+
+int adf_device_detach(struct adf_device *dev, adf_id_t overlay_engine,
+                      adf_id_t interface)
+{
+   return adf_device_attachment(dev, overlay_engine, interface, false);
+}
+
+ssize_t adf_interfaces(struct adf_device *dev, adf_id_t **interfaces)
+{
+    char pattern[64];
+
+    snprintf(pattern, sizeof(pattern), "adf-interface%u.%%u", dev->id);
+    return adf_find_nodes(pattern, interfaces);
+}
+
+ssize_t adf_interfaces_for_overlay_engine(struct adf_device *dev,
+        adf_id_t overlay_engine, adf_id_t **interfaces)
+{
+    struct adf_device_data data;
+    ssize_t n = 0;
+    ssize_t ret;
+    adf_id_t *ids_ret = NULL;
+
+    ret = adf_get_device_data(dev, &data);
+    if (ret < 0)
+        return ret;
+
+    size_t i;
+    for (i = 0; i < data.n_allowed_attachments; i++) {
+        if (data.allowed_attachments[i].overlay_engine != overlay_engine)
+            continue;
+
+        adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
+        if (!new_ids) {
+            ret = -ENOMEM;
+            goto done;
+        }
+
+        ids_ret = new_ids;
+        ids_ret[n] = data.allowed_attachments[i].interface;
+        n++;
+    }
+
+    ret = n;
+
+done:
+    adf_free_device_data(&data);
+    if (ret < 0)
+        free(ids_ret);
+    else
+        *interfaces = ids_ret;
+    return ret;
+}
+
+static ssize_t adf_interfaces_filter(struct adf_device *dev,
+        adf_id_t *in, size_t n_in, adf_id_t **out,
+        bool (*filter)(struct adf_interface_data *data, __u32 match),
+        __u32 match)
+{
+    size_t n = 0;
+    ssize_t ret;
+    adf_id_t *ids_ret = NULL;
+
+    size_t i;
+    for (i = 0; i < n_in; i++) {
+        int fd = adf_interface_open(dev, in[i], O_RDONLY);
+        if (fd < 0) {
+            ret = fd;
+            goto done;
+        }
+
+        struct adf_interface_data data;
+        ret = adf_get_interface_data(fd, &data);
+        close(fd);
+        if (ret < 0)
+            goto done;
+
+        if (!filter(&data, match))
+            continue;
+
+        adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
+        if (!new_ids) {
+            ret = -ENOMEM;
+            goto done;
+        }
+
+        ids_ret = new_ids;
+        ids_ret[n] = in[i];
+        n++;
+    }
+
+    ret = n;
+
+done:
+    if (ret < 0)
+        free(ids_ret);
+    else
+        *out = ids_ret;
+    return ret;
+}
+
+static bool adf_interface_type_filter(struct adf_interface_data *data,
+        __u32 type)
+{
+    return data->type == (enum adf_interface_type)type;
+}
+
+ssize_t adf_interfaces_filter_by_type(struct adf_device *dev,
+        enum adf_interface_type type,
+        adf_id_t *in, size_t n_in, adf_id_t **out)
+{
+    return adf_interfaces_filter(dev, in, n_in, out, adf_interface_type_filter,
+            type);
+}
+
+static bool adf_interface_flags_filter(struct adf_interface_data *data,
+        __u32 flag)
+{
+    return !!(data->flags & flag);
+}
+
+ssize_t adf_interfaces_filter_by_flag(struct adf_device *dev, __u32 flag,
+        adf_id_t *in, size_t n_in, adf_id_t **out)
+{
+    return adf_interfaces_filter(dev, in, n_in, out, adf_interface_flags_filter,
+            flag);
+}
+
+int adf_interface_open(struct adf_device *dev, adf_id_t id, int flags)
+{
+    char filename[64];
+
+    snprintf(filename, sizeof(filename), ADF_BASE_PATH "adf-interface%u.%u",
+            dev->id, id);
+
+    int fd = open(filename, flags);
+    if (fd < 0)
+        return -errno;
+    return fd;
+}
+
+int adf_get_interface_data(int fd, struct adf_interface_data *data)
+{
+    int err;
+    int ret = 0;
+
+    memset(data, 0, sizeof(*data));
+
+    err = ioctl(fd, ADF_GET_INTERFACE_DATA, data);
+    if (err < 0)
+        return -errno;
+
+    if (data->n_available_modes) {
+        data->available_modes = malloc(sizeof(data->available_modes[0]) *
+                data->n_available_modes);
+        if (!data->available_modes)
+            return -ENOMEM;
+    }
+
+    if (data->custom_data_size) {
+        data->custom_data = malloc(data->custom_data_size);
+        if (!data->custom_data) {
+            ret = -ENOMEM;
+            goto done;
+        }
+    }
+
+    err = ioctl(fd, ADF_GET_INTERFACE_DATA, data);
+    if (err < 0)
+        ret = -errno;
+
+done:
+    if (ret < 0)
+        adf_free_interface_data(data);
+    return ret;
+}
+
+void adf_free_interface_data(struct adf_interface_data *data)
+{
+    free(data->available_modes);
+    free(data->custom_data);
+}
+
+int adf_interface_blank(int fd, __u8 mode)
+{
+    int err = ioctl(fd, ADF_BLANK, mode);
+    if (err < 0)
+        return -errno;
+    return 0;
+}
+
+int adf_interface_set_mode(int fd, struct drm_mode_modeinfo *mode)
+{
+    int err = ioctl(fd, ADF_SET_MODE, mode);
+    if (err < 0)
+        return -errno;
+    return 0;
+}
+
+int adf_interface_simple_buffer_alloc(int fd, __u32 w, __u32 h,
+        __u32 format, __u32 *offset, __u32 *pitch)
+{
+    int err;
+    struct adf_simple_buffer_alloc data;
+
+    memset(&data, 0, sizeof(data));
+    data.w = w;
+    data.h = h;
+    data.format = format;
+
+    err = ioctl(fd, ADF_SIMPLE_BUFFER_ALLOC, &data);
+    if (err < 0)
+        return -errno;
+
+    *offset = data.offset;
+    *pitch = data.pitch;
+    return (int)data.fd;
+}
+
+int adf_interface_simple_post(int fd, __u32 overlay_engine,
+        __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset,
+        __u32 pitch, int acquire_fence)
+{
+    int ret;
+    struct adf_simple_post_config data;
+
+    memset(&data, 0, sizeof(data));
+    data.buf.overlay_engine = overlay_engine;
+    data.buf.w = w;
+    data.buf.h = h;
+    data.buf.format = format;
+    data.buf.fd[0] = buf_fd;
+    data.buf.offset[0] = offset;
+    data.buf.pitch[0] = pitch;
+    data.buf.n_planes = 1;
+    data.buf.acquire_fence = acquire_fence;
+
+    ret = ioctl(fd, ADF_SIMPLE_POST_CONFIG, &data);
+    if (ret < 0)
+        return -errno;
+
+    return (int)data.complete_fence;
+}
+
+ssize_t adf_overlay_engines(struct adf_device *dev, adf_id_t **overlay_engines)
+{
+    char pattern[64];
+
+    snprintf(pattern, sizeof(pattern), "adf-overlay-engine%u.%%u", dev->id);
+    return adf_find_nodes(pattern, overlay_engines);
+}
+
+ssize_t adf_overlay_engines_for_interface(struct adf_device *dev,
+        adf_id_t interface, adf_id_t **overlay_engines)
+{
+    struct adf_device_data data;
+    ssize_t n = 0;
+    ssize_t ret;
+    adf_id_t *ids_ret = NULL;
+
+    ret = adf_get_device_data(dev, &data);
+    if (ret < 0)
+        return ret;
+
+    size_t i;
+    for (i = 0; i < data.n_allowed_attachments; i++) {
+        if (data.allowed_attachments[i].interface != interface)
+            continue;
+
+        adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
+        if (!new_ids) {
+            ret = -ENOMEM;
+            goto done;
+        }
+
+        ids_ret = new_ids;
+        ids_ret[n] = data.allowed_attachments[i].overlay_engine;
+        n++;
+    }
+
+    ret = n;
+
+done:
+    adf_free_device_data(&data);
+    if (ret < 0)
+        free(ids_ret);
+    else
+        *overlay_engines = ids_ret;
+    return ret;
+}
+
+static ssize_t adf_overlay_engines_filter(struct adf_device *dev,
+        adf_id_t *in, size_t n_in, adf_id_t **out,
+        bool (*filter)(struct adf_overlay_engine_data *data, void *cookie),
+        void *cookie)
+{
+    size_t n = 0;
+    ssize_t ret;
+    adf_id_t *ids_ret = NULL;
+
+    size_t i;
+    for (i = 0; i < n_in; i++) {
+        int fd = adf_overlay_engine_open(dev, in[i], O_RDONLY);
+        if (fd < 0) {
+            ret = fd;
+            goto done;
+        }
+
+        struct adf_overlay_engine_data data;
+        ret = adf_get_overlay_engine_data(fd, &data);
+        close(fd);
+        if (ret < 0)
+            goto done;
+
+        if (!filter(&data, cookie))
+            continue;
+
+        adf_id_t *new_ids = realloc(ids_ret, (n + 1) * sizeof(ids_ret[0]));
+        if (!new_ids) {
+            ret = -ENOMEM;
+            goto done;
+        }
+
+        ids_ret = new_ids;
+        ids_ret[n] = in[i];
+        n++;
+    }
+
+    ret = n;
+
+done:
+    if (ret < 0)
+        free(ids_ret);
+    else
+        *out = ids_ret;
+    return ret;
+}
+
+struct format_filter_cookie {
+    const __u32 *formats;
+    size_t n_formats;
+};
+
+static bool adf_overlay_engine_format_filter(
+        struct adf_overlay_engine_data *data, void *cookie)
+{
+    struct format_filter_cookie *c = cookie;
+    size_t i;
+    for (i = 0; i < data->n_supported_formats; i++) {
+        size_t j;
+        for (j = 0; j < c->n_formats; j++)
+            if (data->supported_formats[i] == c->formats[j])
+                return true;
+    }
+    return false;
+}
+
+ssize_t adf_overlay_engines_filter_by_format(struct adf_device *dev,
+        const __u32 *formats, size_t n_formats, adf_id_t *in, size_t n_in,
+        adf_id_t **out)
+{
+    struct format_filter_cookie cookie = { formats, n_formats };
+    return adf_overlay_engines_filter(dev, in, n_in, out,
+            adf_overlay_engine_format_filter, &cookie);
+}
+
+int adf_overlay_engine_open(struct adf_device *dev, adf_id_t id, int flags)
+{
+    char filename[64];
+
+    snprintf(filename, sizeof(filename),
+            ADF_BASE_PATH "adf-overlay-engine%u.%u", dev->id, id);
+
+    int fd = open(filename, flags);
+    if (fd < 0)
+        return -errno;
+    return fd;
+}
+
+int adf_get_overlay_engine_data(int fd, struct adf_overlay_engine_data *data)
+{
+    int err;
+    int ret = 0;
+
+    memset(data, 0, sizeof(*data));
+
+    err = ioctl(fd, ADF_GET_OVERLAY_ENGINE_DATA, data);
+    if (err < 0)
+        return -errno;
+
+    if (data->n_supported_formats) {
+        data->supported_formats = malloc(sizeof(data->supported_formats[0]) *
+              data->n_supported_formats);
+        if (!data->supported_formats)
+            return -ENOMEM;
+    }
+
+    if (data->custom_data_size) {
+      data->custom_data = malloc(data->custom_data_size);
+      if (!data->custom_data) {
+          ret = -ENOMEM;
+          goto done;
+      }
+    }
+
+    err = ioctl(fd, ADF_GET_OVERLAY_ENGINE_DATA, data);
+    if (err < 0)
+        ret = -errno;
+
+done:
+    if (ret < 0)
+        adf_free_overlay_engine_data(data);
+    return ret;
+}
+
+void adf_free_overlay_engine_data(struct adf_overlay_engine_data *data)
+{
+    free(data->supported_formats);
+    free(data->custom_data);
+}
+
+bool adf_overlay_engine_supports_format(int fd, __u32 format)
+{
+    struct adf_overlay_engine_data data;
+    bool ret = false;
+    size_t i;
+
+    int err = adf_get_overlay_engine_data(fd, &data);
+    if (err < 0)
+        return false;
+
+    for (i = 0; i < data.n_supported_formats; i++) {
+        if (data.supported_formats[i] == format) {
+            ret = true;
+            break;
+        }
+    }
+
+    adf_free_overlay_engine_data(&data);
+    return ret;
+}
+
+int adf_set_event(int fd, enum adf_event_type type, bool enabled)
+{
+    struct adf_set_event data;
+
+    data.type = type;
+    data.enabled = enabled;
+
+    int err = ioctl(fd, ADF_SET_EVENT, &data);
+    if (err < 0)
+        return -errno;
+    return 0;
+}
+
+int adf_read_event(int fd, struct adf_event **event)
+{
+    struct adf_event header;
+    struct {
+        struct adf_event base;
+        uint8_t data[0];
+    } *event_ret;
+    size_t data_size;
+    int ret = 0;
+
+    int err = read(fd, &header, sizeof(header));
+    if (err < 0)
+        return -errno;
+    if ((size_t)err < sizeof(header))
+        return -EIO;
+    if (header.length < sizeof(header))
+        return -EIO;
+
+    event_ret = malloc(header.length);
+    if (!event_ret)
+        return -ENOMEM;
+    data_size = header.length - sizeof(header);
+
+    memcpy(event_ret, &header, sizeof(header));
+    ssize_t read_size = read(fd, &event_ret->data, data_size);
+    if (read_size < 0) {
+        ret = -errno;
+        goto done;
+    }
+    if ((size_t)read_size < data_size) {
+        ret = -EIO;
+        goto done;
+    }
+
+    *event = &event_ret->base;
+
+done:
+    if (ret < 0)
+        free(event_ret);
+    return ret;
+}
+
+void adf_format_str(__u32 format, char buf[ADF_FORMAT_STR_SIZE])
+{
+    buf[0] = format & 0xFF;
+    buf[1] = (format >> 8) & 0xFF;
+    buf[2] = (format >> 16) & 0xFF;
+    buf[3] = (format >> 24) & 0xFF;
+    buf[4] = '\0';
+}
+
+static bool adf_find_simple_post_overlay_engine(struct adf_device *dev,
+        const __u32 *formats, size_t n_formats,
+        adf_id_t interface, adf_id_t *overlay_engine)
+{
+    adf_id_t *engs;
+    ssize_t n_engs = adf_overlay_engines_for_interface(dev, interface, &engs);
+
+    if (n_engs <= 0)
+        return false;
+
+    adf_id_t *filtered_engs;
+    ssize_t n_filtered_engs = adf_overlay_engines_filter_by_format(dev,
+            formats, n_formats, engs, n_engs, &filtered_engs);
+    free(engs);
+
+    if (n_filtered_engs <= 0)
+        return false;
+
+    *overlay_engine = filtered_engs[0];
+    free(filtered_engs);
+    return true;
+}
+
+static const __u32 any_rgb_format[] = {
+    DRM_FORMAT_C8,
+    DRM_FORMAT_RGB332,
+    DRM_FORMAT_BGR233,
+    DRM_FORMAT_XRGB1555,
+    DRM_FORMAT_XBGR1555,
+    DRM_FORMAT_RGBX5551,
+    DRM_FORMAT_BGRX5551,
+    DRM_FORMAT_ARGB1555,
+    DRM_FORMAT_ABGR1555,
+    DRM_FORMAT_RGBA5551,
+    DRM_FORMAT_BGRA5551,
+    DRM_FORMAT_RGB565,
+    DRM_FORMAT_BGR565,
+    DRM_FORMAT_RGB888,
+    DRM_FORMAT_BGR888,
+    DRM_FORMAT_XRGB8888,
+    DRM_FORMAT_XBGR8888,
+    DRM_FORMAT_RGBX8888,
+    DRM_FORMAT_BGRX8888,
+    DRM_FORMAT_XRGB2101010,
+    DRM_FORMAT_XBGR2101010,
+    DRM_FORMAT_RGBX1010102,
+    DRM_FORMAT_BGRX1010102,
+    DRM_FORMAT_ARGB2101010,
+    DRM_FORMAT_ABGR2101010,
+    DRM_FORMAT_RGBA1010102,
+    DRM_FORMAT_BGRA1010102,
+    DRM_FORMAT_ARGB8888,
+    DRM_FORMAT_ABGR8888,
+    DRM_FORMAT_RGBA8888,
+    DRM_FORMAT_BGRA8888,
+};
+
+int adf_find_simple_post_configuration(struct adf_device *dev,
+        const __u32 *formats, size_t n_formats,
+        adf_id_t *interface, adf_id_t *overlay_engine)
+{
+    adf_id_t *intfs;
+    ssize_t n_intfs = adf_interfaces(dev, &intfs);
+
+    if (n_intfs < 0)
+        return n_intfs;
+    else if (!n_intfs)
+        return -ENODEV;
+
+    adf_id_t *primary_intfs;
+    ssize_t n_primary_intfs = adf_interfaces_filter_by_flag(dev,
+            ADF_INTF_FLAG_PRIMARY, intfs, n_intfs, &primary_intfs);
+    free(intfs);
+
+    if (n_primary_intfs < 0)
+        return n_primary_intfs;
+    else if (!n_primary_intfs)
+        return -ENODEV;
+
+    if (!formats) {
+        formats = any_rgb_format;
+        n_formats = sizeof(any_rgb_format) / sizeof(any_rgb_format[0]);
+    }
+
+    bool found = false;
+    ssize_t i = 0;
+    for (i = 0; i < n_primary_intfs; i++) {
+        found = adf_find_simple_post_overlay_engine(dev, formats, n_formats,
+                primary_intfs[i], overlay_engine);
+        if (found) {
+            *interface = primary_intfs[i];
+            break;
+        }
+    }
+    free(primary_intfs);
+
+    if (!found)
+        return -ENODEV;
+
+    return 0;
+}
diff --git a/adf/libadf/include/adf/adf.h b/adf/libadf/include/adf/adf.h
new file mode 100644
index 0000000..b6bda34
--- /dev/null
+++ b/adf/libadf/include/adf/adf.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _LIBADF_ADF_H_
+#define _LIBADF_ADF_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <video/adf.h>
+
+typedef __u32 adf_id_t;
+
+struct adf_device {
+    adf_id_t id;
+    int fd;
+};
+
+__BEGIN_DECLS
+
+/**
+ * Enumerates all ADF devices.
+ *
+ * Returns the number of ADF devices, and sets ids to a list of device IDs.
+ * The caller must free() the returned list of device IDs.
+ *
+ * On error, returns -errno.
+ */
+ssize_t adf_devices(adf_id_t **ids);
+
+/**
+ * Opens an ADF device.
+ *
+ * On error, returns -errno.
+ */
+int adf_device_open(adf_id_t id, int flags, struct adf_device *dev);
+/**
+ * Closes an ADF device.
+ */
+void adf_device_close(struct adf_device *dev);
+/**
+ * Reads the ADF device data.
+ *
+ * adf_get_device_data() allocates buffers inside data, which the caller
+ * must free by calling adf_free_device_data().  On error, returns -errno.
+ */
+int adf_get_device_data(struct adf_device *dev, struct adf_device_data *data);
+/**
+ * Frees the device data returned by adf_get_device_data().
+ */
+void adf_free_device_data(struct adf_device_data *data);
+
+/**
+ * Atomically posts a new display configuration to the specified interfaces.
+ *
+ * Returns a sync fence fd that will fire when the configuration is removed
+ * from the screen.  On error, returns -errno.
+ */
+int adf_device_post(struct adf_device *dev,
+        adf_id_t *interfaces, size_t n_interfaces,
+        struct adf_buffer_config *bufs, size_t n_bufs,
+        void *custom_data, size_t custom_data_size);
+/**
+ * Attaches the specified interface and overlay engine.
+ */
+int adf_device_attach(struct adf_device *dev, adf_id_t overlay_engine,
+                      adf_id_t interface);
+/**
+ * Detaches the specified interface and overlay engine.
+ */
+int adf_device_detach(struct adf_device *dev, adf_id_t overlay_engine,
+                      adf_id_t interface);
+
+/**
+ * Enumerates all interfaces belonging to an ADF device.
+ *
+ * The caller must free() the returned list of interface IDs.
+ */
+ssize_t adf_interfaces(struct adf_device *dev, adf_id_t **interfaces);
+
+/**
+ * Enumerates all interfaces which can be attached to the specified overlay
+ * engine.
+ *
+ * The caller must free() the returned list of interface IDs.
+ */
+ssize_t adf_interfaces_for_overlay_engine(struct adf_device *dev,
+        adf_id_t overlay_engine, adf_id_t **interfaces);
+/**
+ * Filters a list of interfaces by type.
+ *
+ * Returns the number of matching interfaces, and sets out to a list of matching
+ * interface IDs.  The caller must free() the returned list of interface IDs.
+ *
+ * On error, returns -errno.
+ */
+ssize_t adf_interfaces_filter_by_type(struct adf_device *dev,
+        enum adf_interface_type type,
+        adf_id_t *in, size_t n_in, adf_id_t **out);
+/**
+ * Filters a list of interfaces by flag.
+ *
+ * The caller must free() the returned list of interface IDs.
+ */
+ssize_t adf_interfaces_filter_by_flag(struct adf_device *dev, __u32 flag,
+        adf_id_t *in, size_t n_in, adf_id_t **out);
+
+/**
+ * Opens an ADF interface.
+ *
+ * Returns a file descriptor.  The caller must close() the fd when done.
+ * On error, returns -errno.
+ */
+int adf_interface_open(struct adf_device *dev, adf_id_t id, int flags);
+/**
+ * Reads the interface data.
+ *
+ * adf_get_interface_data() allocates buffers inside data, which the caller
+ * must free by calling adf_free_interface_data().  On error, returns -errno.
+ */
+int adf_get_interface_data(int fd, struct adf_interface_data *data);
+/**
+ * Frees the interface data returned by adf_get_interface_data().
+ */
+void adf_free_interface_data(struct adf_interface_data *data);
+
+/**
+ * Sets the interface's DPMS mode.
+ */
+int adf_interface_blank(int fd, __u8 mode);
+/**
+ * Sets the interface's display mode.
+ */
+int adf_interface_set_mode(int fd, struct drm_mode_modeinfo *mode);
+/**
+ * Allocates a single-plane RGB buffer of the specified size and format.
+ *
+ * Returns a dma-buf fd.  On error, returns -errno.
+ */
+int adf_interface_simple_buffer_alloc(int fd, __u32 w, __u32 h,
+        __u32 format, __u32 *offset, __u32 *pitch);
+/**
+ * Posts a single-plane RGB buffer to the display using the specified
+ * overlay engine.
+ *
+ * Returns a sync fence fd that will fire when the buffer is removed
+ * from the screen.  On error, returns -errno.
+ */
+int adf_interface_simple_post(int fd, adf_id_t overlay_engine,
+        __u32 w, __u32 h, __u32 format, int buf_fd, __u32 offset,
+        __u32 pitch, int acquire_fence);
+
+/**
+ * Enumerates all overlay engines belonging to an ADF device.
+ *
+ * The caller must free() the returned list of overlay engine IDs.
+ */
+ssize_t adf_overlay_engines(struct adf_device *dev, adf_id_t **overlay_engines);
+
+/**
+ * Enumerates all overlay engines which can be attached to the specified
+ * interface.
+ *
+ * The caller must free() the returned list of overlay engine IDs.
+ */
+ssize_t adf_overlay_engines_for_interface(struct adf_device *dev,
+        adf_id_t interface, adf_id_t **overlay_engines);
+/**
+ * Filters a list of overlay engines by supported buffer format.
+ *
+ * Returns the overlay engines which support at least one of the specified
+ * formats.  The caller must free() the returned list of overlay engine IDs.
+ */
+ssize_t adf_overlay_engines_filter_by_format(struct adf_device *dev,
+        const __u32 *formats, size_t n_formats, adf_id_t *in, size_t n_in,
+        adf_id_t **out);
+
+/**
+ * Opens an ADF overlay engine.
+ *
+ * Returns a file descriptor.  The caller must close() the fd when done.
+ * On error, returns -errno.
+ */
+int adf_overlay_engine_open(struct adf_device *dev, adf_id_t id, int flags);
+/**
+ * Reads the overlay engine data.
+ *
+ * adf_get_overlay_engine_data() allocates buffers inside data, which the caller
+ * must free by calling adf_free_overlay_engine_data().  On error, returns
+ * -errno.
+ */
+int adf_get_overlay_engine_data(int fd, struct adf_overlay_engine_data *data);
+/**
+ * Frees the overlay engine data returned by adf_get_overlay_engine_data().
+ */
+void adf_free_overlay_engine_data(struct adf_overlay_engine_data *data);
+
+/**
+ * Returns whether the overlay engine supports the specified format.
+ */
+bool adf_overlay_engine_supports_format(int fd, __u32 format);
+
+/**
+ * Subscribes or unsubscribes from the specified hardware event.
+ */
+int adf_set_event(int fd, enum adf_event_type type, bool enabled);
+/**
+ * Reads one event from the fd, blocking if needed.
+ *
+ * The caller must free() the returned buffer.  On error, returns -errno.
+ */
+int adf_read_event(int fd, struct adf_event **event);
+
+#define ADF_FORMAT_STR_SIZE 5
+/**
+ * Converts an ADF/DRM fourcc format to its string representation.
+ */
+void adf_format_str(__u32 format, char buf[ADF_FORMAT_STR_SIZE]);
+
+/**
+ * Finds an appropriate interface and overlay engine for a simple post.
+ *
+ * Specifically, finds the primary interface, and an overlay engine
+ * that can be attached to the primary interface and supports one of the
+ * specified formats.  The caller may pass a NULL formats list, to indicate that
+ * any RGB format is acceptable.
+ *
+ * On error, returns -errno.
+ */
+int adf_find_simple_post_configuration(struct adf_device *dev,
+        const __u32 *formats, size_t n_formats,
+        adf_id_t *interface, adf_id_t *overlay_engine);
+
+__END_DECLS
+
+#endif /* _LIBADF_ADF_H_ */
diff --git a/adf/libadfhwc/Android.mk b/adf/libadfhwc/Android.mk
new file mode 100644
index 0000000..acea322
--- /dev/null
+++ b/adf/libadfhwc/Android.mk
@@ -0,0 +1,25 @@
+# Copyright (C) 2013 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := adfhwc.cpp
+LOCAL_MODULE := libadfhwc
+LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_LIBRARIES := libadf liblog libutils
+LOCAL_CFLAGS += -DLOG_TAG=\"adfhwc\"
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/adf/libadfhwc/adfhwc.cpp b/adf/libadfhwc/adfhwc.cpp
new file mode 100644
index 0000000..dee3cae
--- /dev/null
+++ b/adf/libadfhwc/adfhwc.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
+#include <sys/resource.h>
+
+#include <adf/adf.h>
+#include <adfhwc/adfhwc.h>
+
+#include <cutils/log.h>
+#include <utils/Vector.h>
+
+struct adf_hwc_helper {
+    adf_hwc_event_callbacks const *event_cb;
+    void *event_cb_data;
+
+    pthread_t event_thread;
+
+    android::Vector<int> intf_fds;
+    android::Vector<drm_mode_modeinfo> display_configs;
+};
+
+template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
+
+int adf_eventControl(struct adf_hwc_helper *dev, int disp, int event,
+        int enabled)
+{
+    if (enabled != !!enabled)
+        return -EINVAL;
+
+    if ((size_t)disp >= dev->intf_fds.size())
+        return -EINVAL;
+
+    switch (event) {
+    case HWC_EVENT_VSYNC:
+        return adf_set_event(dev->intf_fds[disp], ADF_EVENT_VSYNC, enabled);
+    }
+
+    return -EINVAL;
+}
+
+static inline int32_t dpi(uint16_t res, uint16_t size_mm)
+{
+    if (size_mm)
+        return 1000 * (res * 25.4f) / size_mm;
+    return 0;
+}
+
+int adf_blank(struct adf_hwc_helper *dev, int disp, int blank)
+{
+    if ((size_t)disp >= dev->intf_fds.size())
+        return -EINVAL;
+
+    uint8_t dpms_mode = blank ? DRM_MODE_DPMS_OFF : DRM_MODE_DPMS_ON;
+    return adf_interface_blank(dev->intf_fds[disp], dpms_mode);
+}
+
+int adf_query_display_types_supported(struct adf_hwc_helper *dev, int *value)
+{
+    *value = 0;
+    if (dev->intf_fds.size() > 0)
+        *value |= HWC_DISPLAY_PRIMARY_BIT;
+    if (dev->intf_fds.size() > 1)
+        *value |= HWC_DISPLAY_EXTERNAL_BIT;
+
+    return 0;
+}
+
+int adf_getDisplayConfigs(struct adf_hwc_helper *dev, int disp,
+        uint32_t *configs, size_t *numConfigs)
+{
+    if ((size_t)disp >= dev->intf_fds.size())
+        return -EINVAL;
+
+    adf_interface_data data;
+    int err = adf_get_interface_data(dev->intf_fds[disp], &data);
+    if (err < 0) {
+        ALOGE("failed to get ADF interface data: %s", strerror(err));
+        return err;
+    }
+
+    if (!data.hotplug_detect)
+        return -ENODEV;
+
+    android::Vector<drm_mode_modeinfo *> unique_configs;
+    unique_configs.push_back(&data.current_mode);
+    for (size_t i = 0; i < data.n_available_modes; i++)
+        if (memcmp(&data.available_modes[i], &data.current_mode,
+                sizeof(data.current_mode)))
+            unique_configs.push_back(&data.available_modes[i]);
+
+    for (size_t i = 0; i < min(*numConfigs, unique_configs.size()); i++) {
+        configs[i] = dev->display_configs.size();
+        dev->display_configs.push_back(*unique_configs[i]);
+    }
+    *numConfigs = unique_configs.size();
+
+    adf_free_interface_data(&data);
+    return 0;
+}
+
+static int32_t adf_display_attribute(const adf_interface_data &data,
+        const drm_mode_modeinfo &mode, const uint32_t attribute)
+{
+    switch (attribute) {
+    case HWC_DISPLAY_VSYNC_PERIOD:
+        if (mode.vrefresh)
+            return 1000000000 / mode.vrefresh;
+        return 0;
+
+    case HWC_DISPLAY_WIDTH:
+        return mode.hdisplay;
+
+    case HWC_DISPLAY_HEIGHT:
+        return mode.vdisplay;
+
+    case HWC_DISPLAY_DPI_X:
+        return dpi(mode.hdisplay, data.width_mm);
+
+    case HWC_DISPLAY_DPI_Y:
+        return dpi(mode.vdisplay, data.height_mm);
+
+    default:
+        ALOGE("unknown display attribute %u", attribute);
+        return -EINVAL;
+    }
+}
+
+int adf_getDisplayAttributes(struct adf_hwc_helper *dev, int disp,
+        uint32_t config, const uint32_t *attributes, int32_t *values)
+{
+    if ((size_t)disp >= dev->intf_fds.size())
+        return -EINVAL;
+
+    if (config >= dev->display_configs.size())
+        return -EINVAL;
+
+    adf_interface_data data;
+    int err = adf_get_interface_data(dev->intf_fds[disp], &data);
+    if (err < 0) {
+        ALOGE("failed to get ADF interface data: %s", strerror(err));
+        return err;
+    }
+
+    for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++)
+        values[i] = adf_display_attribute(data, dev->display_configs[config],
+                attributes[i]);
+
+    adf_free_interface_data(&data);
+    return 0;
+}
+
+static void handle_adf_event(struct adf_hwc_helper *dev, int disp)
+{
+    adf_event *event;
+    int err = adf_read_event(dev->intf_fds[disp], &event);
+    if (err < 0) {
+        ALOGE("error reading event from display %d: %s", disp, strerror(err));
+        return;
+    }
+
+    void *vsync_temp;
+    adf_vsync_event *vsync;
+    adf_hotplug_event *hotplug;
+
+    switch (event->type) {
+    case ADF_EVENT_VSYNC:
+        vsync_temp = event;
+        vsync = static_cast<adf_vsync_event *>(vsync_temp);
+        // casting directly to adf_vsync_event * makes g++ warn about
+        // potential alignment issues that don't apply here
+        dev->event_cb->vsync(dev->event_cb_data, disp, vsync->timestamp);
+        break;
+    case ADF_EVENT_HOTPLUG:
+        hotplug = reinterpret_cast<adf_hotplug_event *>(event);
+        dev->event_cb->hotplug(dev->event_cb_data, disp, hotplug->connected);
+        break;
+    default:
+        if (event->type < ADF_EVENT_DEVICE_CUSTOM)
+            ALOGW("unrecognized event type %u", event->type);
+        else if (!dev->event_cb || !dev->event_cb->custom_event)
+            ALOGW("unhandled event type %u", event->type);
+        else
+            dev->event_cb->custom_event(dev->event_cb_data, disp, event);
+    }
+    free(event);
+}
+
+static void *adf_event_thread(void *data)
+{
+    adf_hwc_helper *dev = static_cast<adf_hwc_helper *>(data);
+
+    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+
+    pollfd *fds = new pollfd[dev->intf_fds.size()];
+    for (size_t i = 0; i < dev->intf_fds.size(); i++) {
+        fds[i].fd = dev->intf_fds[i];
+        fds[i].events = POLLIN | POLLPRI;
+    }
+
+    while (true) {
+        int err = poll(fds, dev->intf_fds.size(), -1);
+
+        if (err > 0) {
+            for (size_t i = 0; i < dev->intf_fds.size(); i++)
+                if (fds[i].revents & (POLLIN | POLLPRI))
+                    handle_adf_event(dev, i);
+        }
+        else if (err == -1) {
+            if (errno == EINTR)
+                break;
+            ALOGE("error in event thread: %s", strerror(errno));
+        }
+    }
+
+    delete [] fds;
+    return NULL;
+}
+
+int adf_hwc_open(int *intf_fds, size_t n_intfs,
+        const struct adf_hwc_event_callbacks *event_cb, void *event_cb_data,
+        struct adf_hwc_helper **dev)
+{
+    if (!n_intfs)
+        return -EINVAL;
+
+    adf_hwc_helper *dev_ret = new adf_hwc_helper;
+    dev_ret->event_cb = event_cb;
+    dev_ret->event_cb_data = event_cb_data;
+
+    int ret;
+
+    for (size_t i = 0; i < n_intfs; i++) {
+        int dup_intf_fd = dup(intf_fds[i]);
+        if (dup_intf_fd < 0) {
+            ALOGE("failed to dup interface fd: %s", strerror(errno));
+            ret = -errno;
+            goto err;
+        }
+
+        dev_ret->intf_fds.push_back(dup_intf_fd);
+
+        ret = adf_set_event(dup_intf_fd, ADF_EVENT_HOTPLUG, 1);
+        if (ret < 0 && ret != -EINVAL) {
+            ALOGE("failed to enable hotplug event on display %u: %s",
+                    i, strerror(errno));
+            goto err;
+        }
+    }
+
+    ret = pthread_create(&dev_ret->event_thread, NULL, adf_event_thread,
+            dev_ret);
+    if (ret) {
+        ALOGE("failed to create event thread: %s", strerror(ret));
+        goto err;
+    }
+
+    *dev = dev_ret;
+    return 0;
+
+err:
+    for (size_t i = 0; i < dev_ret->intf_fds.size(); i++)
+        close(dev_ret->intf_fds[i]);
+
+    delete dev_ret;
+    return ret;
+}
+
+void adf_hwc_close(struct adf_hwc_helper *dev)
+{
+    pthread_kill(dev->event_thread, SIGTERM);
+    pthread_join(dev->event_thread, NULL);
+
+    for (size_t i = 0; i < dev->intf_fds.size(); i++)
+        close(dev->intf_fds[i]);
+
+    delete dev;
+}
diff --git a/adf/libadfhwc/include/adfhwc/adfhwc.h b/adf/libadfhwc/include/adfhwc/adfhwc.h
new file mode 100644
index 0000000..71e7624
--- /dev/null
+++ b/adf/libadfhwc/include/adfhwc/adfhwc.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _LIBADFHWC_ADFHWC_H_
+#define _LIBADFHWC_ADFHWC_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <video/adf.h>
+
+#include <hardware/hwcomposer.h>
+
+struct adf_hwc_helper;
+
+struct adf_hwc_event_callbacks {
+    /**
+     * Called on vsync (required)
+     */
+    void (*vsync)(void *data, int disp, uint64_t timestamp);
+    /**
+     * Called on hotplug (required)
+     */
+    void (*hotplug)(void *data, int disp, bool connected);
+    /**
+     * Called on hardware-custom ADF events (optional)
+     */
+    void (*custom_event)(void *data, int disp, struct adf_event *event);
+};
+
+/**
+ * Converts HAL pixel formats to equivalent ADF/DRM format FourCCs.
+ */
+static inline uint32_t adf_fourcc_for_hal_pixel_format(int format)
+{
+    switch (format) {
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+        return DRM_FORMAT_RGBA8888;
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+        return DRM_FORMAT_RGBX8888;
+    case HAL_PIXEL_FORMAT_RGB_888:
+        return DRM_FORMAT_RGB888;
+    case HAL_PIXEL_FORMAT_RGB_565:
+        return DRM_FORMAT_RGB565;
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+        return DRM_FORMAT_BGRA8888;
+    case HAL_PIXEL_FORMAT_YV12:
+        return DRM_FORMAT_YVU420;
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        return DRM_FORMAT_NV16;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        return DRM_FORMAT_NV21;
+    case HAL_PIXEL_FORMAT_YCbCr_422_I:
+        return DRM_FORMAT_YUYV;
+    default:
+        return 0;
+    }
+}
+
+/**
+ * Converts HAL display types to equivalent ADF interface flags.
+ */
+static inline uint32_t adf_hwc_interface_flag_for_disp(int disp)
+{
+    switch (disp) {
+    case HWC_DISPLAY_PRIMARY:
+        return ADF_INTF_FLAG_PRIMARY;
+    case HWC_DISPLAY_EXTERNAL:
+        return ADF_INTF_FLAG_EXTERNAL;
+    default:
+        return 0;
+    }
+}
+
+__BEGIN_DECLS
+
+/**
+ * Create a HWC helper for the specified ADF interfaces.
+ *
+ * intf_fds must be indexed by HWC display type: e.g.,
+ * intf_fds[HWC_DISPLAY_PRIMARY] is the fd for the primary display
+ * interface.  n_intfs must be >= 1.
+ *
+ * The caller retains ownership of the fds in intf_fds and must close()
+ * them when they are no longer needed.
+ *
+ * On error, returns -errno.
+ */
+int adf_hwc_open(int *intf_fds, size_t n_intfs,
+        const struct adf_hwc_event_callbacks *event_cb, void *event_cb_data,
+        struct adf_hwc_helper **dev);
+
+/**
+ * Destroys a HWC helper.
+ */
+void adf_hwc_close(struct adf_hwc_helper *dev);
+
+/**
+ * Generic implementations of common HWC ops.
+ *
+ * The HWC should not point its ops directly at these helpers.  Instead, the HWC
+ * should provide stub ops which call these helpers after converting the
+ * hwc_composer_device_1* to a struct adf_hwc_helper*.
+ */
+int adf_eventControl(struct adf_hwc_helper *dev, int disp, int event,
+        int enabled);
+int adf_blank(struct adf_hwc_helper *dev, int disp, int blank);
+int adf_query_display_types_supported(struct adf_hwc_helper *dev, int *value);
+int adf_getDisplayConfigs(struct adf_hwc_helper *dev, int disp,
+        uint32_t *configs, size_t *numConfigs);
+int adf_getDisplayAttributes(struct adf_hwc_helper *dev, int disp,
+        uint32_t config, const uint32_t *attributes, int32_t *values);
+
+__END_DECLS
+
+#endif /* _LIBADFHWC_ADFHWC_H_ */
diff --git a/debuggerd/arm/machine.c b/debuggerd/arm/machine.c
index 6bcd07e..4ab6026 100644
--- a/debuggerd/arm/machine.c
+++ b/debuggerd/arm/machine.c
@@ -15,18 +15,15 @@
 ** limitations under the License.
 */
 
-#include <stddef.h>
+#include <errno.h>
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
 #include <sys/ptrace.h>
-
-#include <corkscrew/ptrace.h>
-
-#include <linux/user.h>
+#include <sys/types.h>
+#include <sys/user.h>
 
 #include "../utility.h"
 #include "../machine.h"
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index da2e9b0..756f7bb 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -31,9 +31,10 @@
 #include <sys/stat.h>
 #include <sys/poll.h>
 
+#include <log/logd.h>
+#include <log/logger.h>
+
 #include <cutils/sockets.h>
-#include <cutils/logd.h>
-#include <cutils/logger.h>
 #include <cutils/properties.h>
 #include <cutils/debugger.h>
 
@@ -435,11 +436,13 @@
     signal(SIGBUS, SIG_DFL);
     signal(SIGFPE, SIG_DFL);
     signal(SIGSEGV, SIG_DFL);
-    signal(SIGPIPE, SIG_DFL);
 #ifdef SIGSTKFLT
     signal(SIGSTKFLT, SIG_DFL);
 #endif
 
+    // Ignore failed writes to closed sockets
+    signal(SIGPIPE, SIG_IGN);
+
     logsocket = socket_local_client("logd",
             ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM);
     if(logsocket < 0) {
diff --git a/debuggerd/mips/machine.c b/debuggerd/mips/machine.c
index e06a50c..489f3c5 100644
--- a/debuggerd/mips/machine.c
+++ b/debuggerd/mips/machine.c
@@ -26,7 +26,7 @@
 
 #include <corkscrew/ptrace.h>
 
-#include <linux/user.h>
+#include <sys/user.h>
 
 #include "../utility.h"
 #include "../machine.h"
diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c
index 48d7aa9..aa63547 100644
--- a/debuggerd/tombstone.c
+++ b/debuggerd/tombstone.c
@@ -29,7 +29,7 @@
 
 #include <private/android_filesystem_config.h>
 
-#include <cutils/logger.h>
+#include <log/logger.h>
 #include <cutils/properties.h>
 
 #include <backtrace/backtrace.h>
diff --git a/debuggerd/utility.c b/debuggerd/utility.c
index 9bf3c18..41be982 100644
--- a/debuggerd/utility.c
+++ b/debuggerd/utility.c
@@ -22,7 +22,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <signal.h>
-#include <cutils/logd.h>
+#include <log/logd.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <arpa/inet.h>
diff --git a/debuggerd/x86/machine.c b/debuggerd/x86/machine.c
index e00208d..db44b11 100644
--- a/debuggerd/x86/machine.c
+++ b/debuggerd/x86/machine.c
@@ -1,5 +1,4 @@
-/* system/debuggerd/debuggerd.c
-**
+/*
 ** Copyright 2006, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,10 +23,6 @@
 #include <sys/types.h>
 #include <sys/ptrace.h>
 
-#include <corkscrew/ptrace.h>
-
-#include <linux/user.h>
-
 #include "../utility.h"
 #include "../machine.h"
 
@@ -35,20 +30,17 @@
 }
 
 void dump_registers(log_t* log, pid_t tid, int scope_flags) {
-    struct pt_regs_x86 r;
-    if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
+    struct pt_regs r;
+    if (ptrace(PTRACE_GETREGS, tid, 0, &r) == -1) {
         _LOG(log, scope_flags, "cannot get registers: %s\n", strerror(errno));
         return;
     }
-    //if there is no stack, no print just like arm
-    if(!r.ebp)
-        return;
-    _LOG(log, scope_flags, "    eax %08x  ebx %08x  ecx %08x  edx %08x\n",
+    _LOG(log, scope_flags, "    eax %08lx  ebx %08lx  ecx %08lx  edx %08lx\n",
          r.eax, r.ebx, r.ecx, r.edx);
-    _LOG(log, scope_flags, "    esi %08x  edi %08x\n",
+    _LOG(log, scope_flags, "    esi %08lx  edi %08lx\n",
          r.esi, r.edi);
     _LOG(log, scope_flags, "    xcs %08x  xds %08x  xes %08x  xfs %08x  xss %08x\n",
          r.xcs, r.xds, r.xes, r.xfs, r.xss);
-    _LOG(log, scope_flags, "    eip %08x  ebp %08x  esp %08x  flags %08x\n",
+    _LOG(log, scope_flags, "    eip %08lx  ebp %08lx  esp %08lx  flags %08lx\n",
          r.eip, r.ebp, r.esp, r.eflags);
 }
diff --git a/fastboot/engine.c b/fastboot/engine.c
index 84ea984..972c4ed 100644
--- a/fastboot/engine.c
+++ b/fastboot/engine.c
@@ -264,21 +264,7 @@
     int fd;
     struct stat st;
 
-#ifdef USE_MINGW
-    /* Ideally we should use tmpfile() here, the same as with unix version.
-     * But unfortunately it is not portable as it is not clear whether this
-     * function opens file in TEXT or BINARY mode.
-     *
-     * There are also some reports it is buggy:
-     *    http://pdplab.it.uom.gr/teaching/gcc_manuals/gnulib.html#tmpfile
-     *    http://www.mega-nerd.com/erikd/Blog/Windiots/tmpfile.html
-     */
-    char *filename = tempnam(getenv("TEMP"), "fastboot-format.img");
-    fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644);
-    unlink(filename);
-#else
     fd = fileno(tmpfile());
-#endif
     make_ext4fs_sparse_fd(fd, image->partition_size, NULL, NULL);
 
     fstat(fd, &st);
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index da2af41..73a6e56 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -42,6 +42,7 @@
 
 #include <sys/time.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 
 #include <bootimg.h>
 #include <sparse/sparse.h>
@@ -53,6 +54,8 @@
 #define O_BINARY 0
 #endif
 
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
+
 char cur_product[FB_RESPONSE_SZ + 1];
 
 void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
@@ -80,6 +83,27 @@
 unsigned second_offset  = 0x00f00000;
 unsigned tags_offset    = 0x00000100;
 
+enum fb_buffer_type {
+    FB_BUFFER,
+    FB_BUFFER_SPARSE,
+};
+
+struct fastboot_buffer {
+    enum fb_buffer_type type;
+    void *data;
+    unsigned int sz;
+};
+
+static struct {
+    char img_name[13];
+    char sig_name[13];
+    char part_name[9];
+    bool is_optional;
+} images[3] = {
+    {"boot.img", "boot.sig", "boot", false},
+    {"recovery.img", "recovery.sig", "recovery", true},
+    {"system.img", "system.sig", "system", false},
+};
 
 void get_my_path(char *path);
 
@@ -123,44 +147,28 @@
     return strdup(path);
 }
 
-#ifdef _WIN32
-void *load_file(const char *fn, unsigned *_sz);
-int64_t file_size(const char *fn);
-#else
-#if defined(__APPLE__) && defined(__MACH__)
-#define lseek64 lseek
-#define off64_t off_t
-#endif
-
-int64_t file_size(const char *fn)
+static int64_t file_size(int fd)
 {
-    off64_t off;
-    int fd;
+    struct stat st;
+    int ret;
 
-    fd = open(fn, O_RDONLY);
-    if (fd < 0) return -1;
+    ret = fstat(fd, &st);
 
-    off = lseek64(fd, 0, SEEK_END);
-    close(fd);
-
-    return off;
+    return ret ? -1 : st.st_size;
 }
 
-void *load_file(const char *fn, unsigned *_sz)
+static void *load_fd(int fd, unsigned *_sz)
 {
     char *data;
     int sz;
-    int fd;
     int errno_tmp;
 
     data = 0;
-    fd = open(fn, O_RDONLY);
-    if(fd < 0) return 0;
 
-    sz = lseek(fd, 0, SEEK_END);
-    if(sz < 0) goto oops;
-
-    if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
+    sz = file_size(fd);
+    if (sz < 0) {
+        goto oops;
+    }
 
     data = (char*) malloc(sz);
     if(data == 0) goto oops;
@@ -178,7 +186,16 @@
     errno = errno_tmp;
     return 0;
 }
-#endif
+
+static void *load_file(const char *fn, unsigned *_sz)
+{
+    int fd;
+
+    fd = open(fn, O_RDONLY | O_BINARY);
+    if(fd < 0) return 0;
+
+    return load_fd(fd, _sz);
+}
 
 int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial)
 {
@@ -385,6 +402,31 @@
     return data;
 }
 
+static int unzip_to_file(zipfile_t zip, char *name)
+{
+    int fd;
+    char *data;
+    unsigned sz;
+
+    fd = fileno(tmpfile());
+    if (fd < 0) {
+        return -1;
+    }
+
+    data = unzip_file(zip, name, &sz);
+    if (data == 0) {
+        return -1;
+    }
+
+    if (write(fd, data, sz) != sz) {
+        fd = -1;
+    }
+
+    free(data);
+    lseek(fd, 0, SEEK_SET);
+    return fd;
+}
+
 static char *strip(char *s)
 {
     int n;
@@ -489,27 +531,20 @@
     fb_queue_notice("--------------------------------------------");
 }
 
-
-struct sparse_file **load_sparse_files(const char *fname, int max_size)
+static struct sparse_file **load_sparse_files(int fd, int max_size)
 {
-    int fd;
     struct sparse_file *s;
     int files;
     struct sparse_file **out_s;
 
-    fd = open(fname, O_RDONLY | O_BINARY);
-    if (fd < 0) {
-        die("cannot open '%s'\n", fname);
-    }
-
     s = sparse_file_import_auto(fd, false);
     if (!s) {
-        die("cannot sparse read file '%s'\n", fname);
+        die("cannot sparse read file\n");
     }
 
     files = sparse_file_resparse(s, max_size, NULL, 0);
     if (files < 0) {
-        die("Failed to resparse '%s'\n", fname);
+        die("Failed to resparse\n");
     }
 
     out_s = calloc(sizeof(struct sparse_file *), files + 1);
@@ -519,7 +554,7 @@
 
     files = sparse_file_resparse(s, max_size, out_s, files);
     if (files < 0) {
-        die("Failed to resparse '%s'\n", fname);
+        die("Failed to resparse\n");
     }
 
     return out_s;
@@ -580,29 +615,78 @@
      return fb_format_supported(usb, part);
 }
 
-void do_flash(usb_handle *usb, const char *pname, const char *fname)
+static int load_buf_fd(usb_handle *usb, int fd,
+        struct fastboot_buffer *buf)
 {
     int64_t sz64;
     void *data;
     int64_t limit;
 
-    sz64 = file_size(fname);
+    sz64 = file_size(fd);
+    if (sz64 < 0) {
+        return -1;
+    }
     limit = get_sparse_limit(usb, sz64);
     if (limit) {
-        struct sparse_file **s = load_sparse_files(fname, limit);
+        struct sparse_file **s = load_sparse_files(fd, limit);
         if (s == NULL) {
-            die("cannot sparse load '%s'\n", fname);
+            return -1;
         }
-        while (*s) {
-            sz64 = sparse_file_len(*s, true, false);
-            fb_queue_flash_sparse(pname, *s++, sz64);
-        }
+        buf->type = FB_BUFFER_SPARSE;
+        buf->data = s;
     } else {
         unsigned int sz;
-        data = load_file(fname, &sz);
-        if (data == 0) die("cannot load '%s': %s\n", fname, strerror(errno));
-        fb_queue_flash(pname, data, sz);
+        data = load_fd(fd, &sz);
+        if (data == 0) return -1;
+        buf->type = FB_BUFFER;
+        buf->data = data;
+        buf->sz = sz;
     }
+
+    return 0;
+}
+
+static int load_buf(usb_handle *usb, const char *fname,
+        struct fastboot_buffer *buf)
+{
+    int fd;
+
+    fd = open(fname, O_RDONLY | O_BINARY);
+    if (fd < 0) {
+        die("cannot open '%s'\n", fname);
+    }
+
+    return load_buf_fd(usb, fd, buf);
+}
+
+static void flash_buf(const char *pname, struct fastboot_buffer *buf)
+{
+    struct sparse_file **s;
+
+    switch (buf->type) {
+        case FB_BUFFER_SPARSE:
+            s = buf->data;
+            while (*s) {
+                int64_t sz64 = sparse_file_len(*s, true, false);
+                fb_queue_flash_sparse(pname, *s++, sz64);
+            }
+            break;
+        case FB_BUFFER:
+            fb_queue_flash(pname, buf->data, buf->sz);
+            break;
+        default:
+            die("unknown buffer type: %d", buf->type);
+    }
+}
+
+void do_flash(usb_handle *usb, const char *pname, const char *fname)
+{
+    struct fastboot_buffer buf;
+
+    if (load_buf(usb, fname, &buf)) {
+        die("cannot load '%s'", fname);
+    }
+    flash_buf(pname, &buf);
 }
 
 void do_update_signature(zipfile_t zip, char *fn)
@@ -615,13 +699,17 @@
     fb_queue_command("signature", "installing signature");
 }
 
-void do_update(char *fn, int erase_first)
+void do_update(usb_handle *usb, char *fn, int erase_first)
 {
     void *zdata;
     unsigned zsize;
     void *data;
     unsigned sz;
     zipfile_t zip;
+    int fd;
+    int rc;
+    struct fastboot_buffer buf;
+    int i;
 
     queue_info_dump();
 
@@ -650,30 +738,25 @@
 
     setup_requirements(data, sz);
 
-    data = unzip_file(zip, "boot.img", &sz);
-    if (data == 0) die("update package missing boot.img");
-    do_update_signature(zip, "boot.sig");
-    if (erase_first && needs_erase("boot")) {
-        fb_queue_erase("boot");
-    }
-    fb_queue_flash("boot", data, sz);
-
-    data = unzip_file(zip, "recovery.img", &sz);
-    if (data != 0) {
-        do_update_signature(zip, "recovery.sig");
-        if (erase_first && needs_erase("recovery")) {
-            fb_queue_erase("recovery");
+    for (i = 0; i < ARRAY_SIZE(images); i++) {
+        fd = unzip_to_file(zip, images[i].img_name);
+        if (fd < 0) {
+            if (images[i].is_optional)
+                continue;
+            die("update package missing %s", images[i].img_name);
         }
-        fb_queue_flash("recovery", data, sz);
+        rc = load_buf_fd(usb, fd, &buf);
+        if (rc) die("cannot load %s from flash", images[i].img_name);
+        do_update_signature(zip, images[i].sig_name);
+        if (erase_first && needs_erase(images[i].part_name)) {
+            fb_queue_erase(images[i].part_name);
+        }
+        flash_buf(images[i].part_name, &buf);
+        /* not closing the fd here since the sparse code keeps the fd around
+         * but hasn't mmaped data yet. The tmpfile will get cleaned up when the
+         * program exits.
+         */
     }
-
-    data = unzip_file(zip, "system.img", &sz);
-    if (data == 0) die("update package missing system.img");
-    do_update_signature(zip, "system.sig");
-    if (erase_first && needs_erase("system")) {
-        fb_queue_erase("system");
-    }
-    fb_queue_flash("system", data, sz);
 }
 
 void do_send_signature(char *fn)
@@ -694,11 +777,13 @@
     fb_queue_command("signature", "installing signature");
 }
 
-void do_flashall(int erase_first)
+void do_flashall(usb_handle *usb, int erase_first)
 {
     char *fname;
     void *data;
     unsigned sz;
+    struct fastboot_buffer buf;
+    int i;
 
     queue_info_dump();
 
@@ -710,33 +795,19 @@
     if (data == 0) die("could not load android-info.txt: %s", strerror(errno));
     setup_requirements(data, sz);
 
-    fname = find_item("boot", product);
-    data = load_file(fname, &sz);
-    if (data == 0) die("could not load boot.img: %s", strerror(errno));
-    do_send_signature(fname);
-    if (erase_first && needs_erase("boot")) {
-        fb_queue_erase("boot");
-    }
-    fb_queue_flash("boot", data, sz);
-
-    fname = find_item("recovery", product);
-    data = load_file(fname, &sz);
-    if (data != 0) {
-        do_send_signature(fname);
-        if (erase_first && needs_erase("recovery")) {
-            fb_queue_erase("recovery");
+    for (i = 0; i < ARRAY_SIZE(images); i++) {
+        fname = find_item(images[i].part_name, product);
+        if (load_buf(usb, fname, &buf)) {
+            if (images[i].is_optional)
+                continue;
+            die("could not load %s\n", images[i].img_name);
         }
-        fb_queue_flash("recovery", data, sz);
+        do_send_signature(fname);
+        if (erase_first && needs_erase(images[i].part_name)) {
+            fb_queue_erase(images[i].part_name);
+        }
+        flash_buf(images[i].part_name, &buf);
     }
-
-    fname = find_item("system", product);
-    data = load_file(fname, &sz);
-    if (data == 0) die("could not load system.img: %s", strerror(errno));
-    do_send_signature(fname);
-    if (erase_first && needs_erase("system")) {
-        fb_queue_erase("system");
-    }
-    fb_queue_flash("system", data, sz);
 }
 
 #define skip(n) do { argc -= (n); argv += (n); } while (0)
@@ -996,14 +1067,14 @@
             fb_queue_flash(pname, data, sz);
         } else if(!strcmp(*argv, "flashall")) {
             skip(1);
-            do_flashall(erase_first);
+            do_flashall(usb, erase_first);
             wants_reboot = 1;
         } else if(!strcmp(*argv, "update")) {
             if (argc > 1) {
-                do_update(argv[1], erase_first);
+                do_update(usb, argv[1], erase_first);
                 skip(2);
             } else {
-                do_update("update.zip", erase_first);
+                do_update(usb, "update.zip", erase_first);
                 skip(1);
             }
             wants_reboot = 1;
diff --git a/fastboot/util_windows.c b/fastboot/util_windows.c
index 9e029fd..74a5c27 100644
--- a/fastboot/util_windows.c
+++ b/fastboot/util_windows.c
@@ -36,29 +36,6 @@
 
 #include <windows.h>
 
-int64_t file_size(const char *fn)
-{
-    HANDLE    file;
-    char     *data;
-    DWORD     sz;
-
-    file = CreateFile( fn,
-                       GENERIC_READ,
-                       FILE_SHARE_READ,
-                       NULL,
-                       OPEN_EXISTING,
-                       0,
-                       NULL );
-
-    if (file == INVALID_HANDLE_VALUE)
-        return -1;
-
-    sz = GetFileSize( file, NULL );
-    CloseHandle( file );
-
-    return sz;
-}
-
 void get_my_path(char exe[PATH_MAX])
 {
 	char*  r;
@@ -70,47 +47,3 @@
 		*r = 0;
 }
 
-
-void *load_file(const char *fn, unsigned *_sz)
-{
-    HANDLE    file;
-    char     *data;
-    DWORD     sz;
-
-    file = CreateFile( fn,
-                       GENERIC_READ,
-                       FILE_SHARE_READ,
-                       NULL,
-                       OPEN_EXISTING,
-                       0,
-                       NULL );
-
-    if (file == INVALID_HANDLE_VALUE)
-        return NULL;
-
-    sz = GetFileSize( file, NULL );
-    data      = NULL;
-
-    if (sz > 0) {
-        data = (char*) malloc( sz );
-        if (data == NULL) {
-            fprintf(stderr, "load_file: could not allocate %ld bytes\n", sz );
-            sz = 0;
-        } else {
-            DWORD  out_bytes;
-
-            if ( !ReadFile( file, data, sz, &out_bytes, NULL ) ||
-                 out_bytes != sz )
-            {
-                fprintf(stderr, "load_file: could not read %ld bytes from '%s'\n", sz, fn);
-                free(data);
-                data      = NULL;
-                sz = 0;
-            }
-        }
-    }
-    CloseHandle( file );
-
-    *_sz = (unsigned) sz;
-    return  data;
-}
diff --git a/fastbootd/Android.mk b/fastbootd/Android.mk
new file mode 100644
index 0000000..0f32dbf
--- /dev/null
+++ b/fastbootd/Android.mk
@@ -0,0 +1,104 @@
+# Copyright (C) 2013 Google Inc.
+#
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := \
+    external/openssl/include \
+    external/mdnsresponder/mDNSShared \
+    $(LOCAL_PATH)/include \
+    external/zlib/ \
+
+LOCAL_SRC_FILES := \
+    config.c \
+    commands.c \
+    commands/boot.c \
+    commands/flash.c \
+    commands/partitions.c \
+    commands/virtual_partitions.c \
+    fastbootd.c \
+    protocol.c \
+    network_discovery.c \
+    socket_client.c \
+    secure.c \
+    transport.c \
+    transport_socket.c \
+    trigger.c \
+    usb_linux_client.c \
+    utils.c \
+
+LOCAL_MODULE := fastbootd
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter -DFLASH_CERT
+LOCAL_LDFLAGS := -ldl
+
+LOCAL_SHARED_LIBRARIES := \
+    libhardware \
+    libcrypto \
+    libhardware_legacy \
+    libmdnssd
+
+LOCAL_STATIC_LIBRARIES := \
+    libsparse_static \
+    libc \
+    libcutils \
+    libz
+
+#LOCAL_FORCE_STATIC_EXECUTABLE := true
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_C_INCLUDES := \
+    external/zlib/
+
+LOCAL_SRC_FILES := \
+    commands/partitions.c \
+    other/gptedit.c \
+    utils.c
+
+LOCAL_MODULE := gptedit
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+
+LOCAL_STATIC_LIBRARIES := \
+    libsparse_static \
+    libc \
+    libcutils \
+    libz
+
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := \
+    $(LOCAL_PATH)/include \
+
+LOCAL_STATIC_LIBRARIES := \
+    $(EXTRA_STATIC_LIBS) \
+    libcutils
+
+LOCAL_SRC_FILES := \
+    other/vendor_trigger.c
+
+LOCAL_MODULE := libvendortrigger.default
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/fastbootd/bootimg.h b/fastbootd/bootimg.h
new file mode 100644
index 0000000..44fde92
--- /dev/null
+++ b/fastbootd/bootimg.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the 
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef _BOOT_IMAGE_H_
+#define _BOOT_IMAGE_H_
+
+typedef struct boot_img_hdr boot_img_hdr;
+
+#define BOOT_MAGIC "ANDROID!"
+#define BOOT_MAGIC_SIZE 8
+#define BOOT_NAME_SIZE 16
+#define BOOT_ARGS_SIZE 512
+
+struct boot_img_hdr
+{
+    unsigned char magic[BOOT_MAGIC_SIZE];
+
+    unsigned kernel_size;  /* size in bytes */
+    unsigned kernel_addr;  /* physical load addr */
+
+    unsigned ramdisk_size; /* size in bytes */
+    unsigned ramdisk_addr; /* physical load addr */
+
+    unsigned second_size;  /* size in bytes */
+    unsigned second_addr;  /* physical load addr */
+
+    unsigned tags_addr;    /* physical addr for kernel tags */
+    unsigned page_size;    /* flash page size we assume */
+    unsigned unused[2];    /* future expansion: should be 0 */
+
+    unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
+    
+    unsigned char cmdline[BOOT_ARGS_SIZE];
+
+    unsigned id[8]; /* timestamp / checksum / sha1 / etc */
+};
+
+/*
+** +-----------------+ 
+** | boot header     | 1 page
+** +-----------------+
+** | kernel          | n pages  
+** +-----------------+
+** | ramdisk         | m pages  
+** +-----------------+
+** | second stage    | o pages
+** +-----------------+
+**
+** n = (kernel_size + page_size - 1) / page_size
+** m = (ramdisk_size + page_size - 1) / page_size
+** o = (second_size + page_size - 1) / page_size
+**
+** 0. all entities are page_size aligned in flash
+** 1. kernel and ramdisk are required (size != 0)
+** 2. second is optional (second_size == 0 -> no second)
+** 3. load each element (kernel, ramdisk, second) at
+**    the specified physical address (kernel_addr, etc)
+** 4. prepare tags at tag_addr.  kernel_args[] is
+**    appended to the kernel commandline in the tags.
+** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
+** 6. if second_size != 0: jump to second_addr
+**    else: jump to kernel_addr
+*/
+
+boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
+                        void *ramdisk, unsigned ramdisk_size,
+                        void *second, unsigned second_size,
+                        unsigned page_size,
+                        unsigned *bootimg_size);
+
+void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline);                
+#endif
diff --git a/fastbootd/commands.c b/fastbootd/commands.c
new file mode 100644
index 0000000..d8a601f
--- /dev/null
+++ b/fastbootd/commands.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/reboot.h>
+#include <fcntl.h>
+
+#include "bootimg.h"
+#include "commands/boot.h"
+#include "commands/flash.h"
+#include "commands/partitions.h"
+#include "commands/virtual_partitions.h"
+#include "debug.h"
+#include "protocol.h"
+#include "trigger.h"
+#include "utils.h"
+
+#define ATAGS_LOCATION "/proc/atags"
+
+static void cmd_boot(struct protocol_handle *phandle, const char *arg)
+{
+    int sz, atags_sz, new_atags_sz;
+    int rv;
+    unsigned kernel_actual;
+    unsigned ramdisk_actual;
+    unsigned second_actual;
+    void *kernel_ptr;
+    void *ramdisk_ptr;
+    void *second_ptr;
+    struct boot_img_hdr *hdr;
+    char *ptr = NULL;
+    char *atags_ptr = NULL;
+    char *new_atags = NULL;
+    int data_fd = 0;
+
+    D(DEBUG, "cmd_boot %s\n", arg);
+
+    if (phandle->download_fd < 0) {
+        fastboot_fail(phandle, "no kernel file");
+        return;
+    }
+
+    atags_ptr = read_atags(ATAGS_LOCATION, &atags_sz);
+    if (atags_ptr == NULL) {
+        fastboot_fail(phandle, "atags read error");
+        goto error;
+    }
+
+    // TODO: With cms we can also verify partition name included as
+    // cms signed attribute
+    if (flash_validate_certificate(phandle->download_fd, &data_fd) != 1) {
+        fastboot_fail(phandle, "Access forbiden you need the certificate");
+        return;
+    }
+
+    sz = get_file_size(data_fd);
+
+    ptr = (char *) mmap(NULL, sz, PROT_READ,
+                        MAP_POPULATE | MAP_PRIVATE, data_fd, 0);
+
+    hdr = (struct boot_img_hdr *) ptr;
+
+    if (ptr == MAP_FAILED) {
+        fastboot_fail(phandle, "internal fastbootd error");
+        goto error;
+    }
+
+    if ((size_t) sz < sizeof(*hdr)) {
+        fastboot_fail(phandle, "invalid bootimage header");
+        goto error;
+    }
+
+    kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, hdr->page_size);
+    ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, hdr->page_size);
+    second_actual = ROUND_TO_PAGE(hdr->second_size, hdr->page_size);
+
+    new_atags = (char *) create_atags((unsigned *) atags_ptr, atags_sz, hdr, &new_atags_sz);
+
+    if (new_atags == NULL) {
+        fastboot_fail(phandle, "atags generate error");
+        goto error;
+    }
+    if (new_atags_sz > 0x4000) {
+        fastboot_fail(phandle, "atags file to large");
+        goto error;
+    }
+
+    if ((int) (hdr->page_size + kernel_actual + ramdisk_actual) < sz) {
+        fastboot_fail(phandle, "incomplete bootimage");
+        goto error;
+    }
+
+    kernel_ptr = (void *)((unsigned) ptr + hdr->page_size);
+    ramdisk_ptr = (void *)((unsigned) kernel_ptr + kernel_actual);
+    second_ptr = (void *)((unsigned) ramdisk_ptr + ramdisk_actual);
+
+    D(INFO, "preparing to boot");
+    // Prepares boot physical address. Addresses from header are ignored
+    rv = prepare_boot_linux(hdr->kernel_addr, kernel_ptr, kernel_actual,
+                            hdr->ramdisk_addr, ramdisk_ptr, ramdisk_actual,
+                            hdr->second_addr, second_ptr, second_actual,
+                            hdr->tags_addr, new_atags, ROUND_TO_PAGE(new_atags_sz, hdr->page_size));
+    if (rv < 0) {
+        fastboot_fail(phandle, "kexec prepare failed");
+        goto error;
+    }
+
+    fastboot_okay(phandle, "");
+
+    free(atags_ptr);
+    munmap(ptr, sz);
+    free(new_atags);
+    close(data_fd);
+
+    D(INFO, "Kexec going to reboot");
+    reboot(LINUX_REBOOT_CMD_KEXEC);
+
+    fastboot_fail(phandle, "reboot error");
+
+    return;
+
+error:
+
+    if (atags_ptr != NULL)
+        free(atags_ptr);
+    if (ptr != NULL)
+        munmap(ptr, sz);
+
+}
+
+static void cmd_erase(struct protocol_handle *phandle, const char *arg)
+{
+    int partition_fd;
+    char path[PATH_MAX];
+    D(DEBUG, "cmd_erase %s\n", arg);
+
+    if (flash_find_entry(arg, path, PATH_MAX)) {
+        fastboot_fail(phandle, "partition table doesn't exist");
+        return;
+    }
+
+    if (path == NULL) {
+        fastboot_fail(phandle, "Couldn't find partition");
+        return;
+    }
+
+    partition_fd = flash_get_partiton(path);
+    if (partition_fd < 0) {
+        fastboot_fail(phandle, "partiton file does not exists");
+    }
+
+    if (flash_erase(partition_fd)) {
+        fastboot_fail(phandle, "failed to erase partition");
+        flash_close(partition_fd);
+        return;
+    }
+
+    if (flash_close(partition_fd) < 0) {
+        D(ERR, "could not close device %s", strerror(errno));
+        fastboot_fail(phandle, "failed to erase partition");
+        return;
+    }
+    fastboot_okay(phandle, "");
+}
+
+static int GPT_header_location() {
+    const char *location_str = fastboot_getvar("gpt_sector");
+    char *str;
+    int location;
+
+    if (!strcmp("", location_str)) {
+        D(INFO, "GPT location not specified using second sector");
+        return 1;
+    }
+    else {
+        location = strtoul(location_str, &str, 10);
+        D(INFO, "GPT location specified as %d", location);
+
+        if (*str != '\0')
+            return -1;
+
+        return location - 1;
+    }
+}
+
+static void cmd_gpt_layout(struct protocol_handle *phandle, const char *arg) {
+    struct GPT_entry_table *oldtable;
+    int location;
+    struct GPT_content content;
+    const char *device;
+    device = fastboot_getvar("blockdev");
+
+    if (!strcmp(device, "")) {
+        fastboot_fail(phandle, "blockdev not defined in config file");
+        return;
+    }
+
+    //TODO: add same verification as in cmd_flash
+    if (phandle->download_fd < 0) {
+        fastboot_fail(phandle, "no layout file");
+        return;
+    }
+
+    location = GPT_header_location();
+    oldtable = GPT_get_device(device, location);
+
+    GPT_default_content(&content, oldtable);
+    if (oldtable == NULL)
+        D(WARN, "Could not get old gpt table");
+    else
+        GPT_release_device(oldtable);
+
+    if (!GPT_parse_file(phandle->download_fd, &content)) {
+        fastboot_fail(phandle, "Could not parse partition config file");
+        return;
+    }
+
+    if (trigger_gpt_layout(&content)) {
+        fastboot_fail(phandle, "Vendor forbids this opperation");
+        GPT_release_content(&content);
+        return;
+    }
+
+    if (!GPT_write_content(device, &content)) {
+        fastboot_fail(phandle, "Unable to write gpt file");
+        GPT_release_content(&content);
+        return;
+    }
+
+    GPT_release_content(&content);
+    fastboot_okay(phandle, "");
+}
+
+static void cmd_flash(struct protocol_handle *phandle, const char *arg)
+{
+    int partition;
+    uint64_t sz;
+    char data[BOOT_MAGIC_SIZE];
+    char path[PATH_MAX];
+    ssize_t header_sz = 0;
+    int data_fd = 0;
+
+    D(DEBUG, "cmd_flash %s\n", arg);
+
+    if (try_handle_virtual_partition(phandle, arg)) {
+        return;
+    }
+
+    if (phandle->download_fd < 0) {
+        fastboot_fail(phandle, "no kernel file");
+        return;
+    }
+
+    if (flash_find_entry(arg, path, PATH_MAX)) {
+        fastboot_fail(phandle, "partition table doesn't exist");
+        return;
+    }
+
+    if (flash_validate_certificate(phandle->download_fd, &data_fd) != 1) {
+        fastboot_fail(phandle, "Access forbiden you need certificate");
+        return;
+    }
+
+    // TODO: Maybe its goot idea to check whether the partition is bootable
+    if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
+        if (read_data_once(data_fd, data, BOOT_MAGIC_SIZE) < BOOT_MAGIC_SIZE) {
+            fastboot_fail(phandle, "incoming data read error, cannot read boot header");
+            return;
+        }
+        if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
+            fastboot_fail(phandle, "image is not a boot image");
+            return;
+        }
+    }
+
+    partition = flash_get_partiton(path);
+
+    sz = get_file_size64(data_fd);
+
+    sz -= header_sz;
+
+    if (sz > get_file_size64(partition)) {
+        flash_close(partition);
+        D(WARN, "size of file too large");
+        fastboot_fail(phandle, "size of file too large");
+        return;
+    }
+
+    D(INFO, "writing %lld bytes to '%s'\n", sz, arg);
+
+    if (flash_write(partition, phandle->download_fd, sz, header_sz)) {
+        fastboot_fail(phandle, "flash write failure");
+        return;
+    }
+    D(INFO, "partition '%s' updated\n", arg);
+
+    flash_close(partition);
+    close(data_fd);
+
+    fastboot_okay(phandle, "");
+}
+
+static void cmd_continue(struct protocol_handle *phandle, const char *arg)
+{
+    fastboot_okay(phandle, "");
+#if 0
+    udc_stop();
+
+    boot_linux_from_flash();
+#endif
+}
+
+static void cmd_getvar(struct protocol_handle *phandle, const char *arg)
+{
+    const char *value;
+    D(DEBUG, "cmd_getvar %s\n", arg);
+
+    value = fastboot_getvar(arg);
+
+    fastboot_okay(phandle, value);
+}
+
+static void cmd_download(struct protocol_handle *phandle, const char *arg)
+{
+    unsigned len = strtoul(arg, NULL, 16);
+    int old_fd;
+
+    if (len > 256 * 1024 * 1024) {
+        fastboot_fail(phandle, "data too large");
+        return;
+    }
+
+    fastboot_data(phandle, len);
+
+    old_fd = protocol_get_download(phandle);
+    if (old_fd >= 0) {
+        off_t len = lseek(old_fd, 0, SEEK_END);
+        D(INFO, "disposing of unused fd %d, size %ld", old_fd, len);
+        close(old_fd);
+    }
+
+    phandle->download_fd = protocol_handle_download(phandle, len);
+    if (phandle->download_fd < 0) {
+        fastboot_fail(phandle, "download failed");
+        return;
+    }
+
+    fastboot_okay(phandle, "");
+}
+
+static void cmd_oem(struct protocol_handle *phandle, const char *arg) {
+    const char *response = "";
+
+    //TODO: Maybe it should get download descriptor also
+    if (trigger_oem_cmd(arg, &response))
+        fastboot_fail(phandle, response);
+    else
+        fastboot_okay(phandle, response);
+}
+
+void commands_init()
+{
+    virtual_partition_register("partition-table", cmd_gpt_layout);
+
+    fastboot_register("boot", cmd_boot);
+    fastboot_register("erase:", cmd_erase);
+    fastboot_register("flash:", cmd_flash);
+    fastboot_register("continue", cmd_continue);
+    fastboot_register("getvar:", cmd_getvar);
+    fastboot_register("download:", cmd_download);
+    fastboot_register("oem", cmd_oem);
+    //fastboot_publish("version", "0.5");
+    //fastboot_publish("product", "swordfish");
+    //fastboot_publish("kernel", "lk");
+}
diff --git a/fastbootd/commands/boot.c b/fastbootd/commands/boot.c
new file mode 100644
index 0000000..8da9a28
--- /dev/null
+++ b/fastbootd/commands/boot.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <sys/syscall.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "boot.h"
+#include "debug.h"
+#include "utils.h"
+#include "bootimg.h"
+
+
+#define KEXEC_ARM_ATAGS_OFFSET  0x1000
+#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
+
+#define MEMORY_SIZE 0x0800000
+#define START_ADDRESS 0x44000000
+#define KERNEL_START (START_ADDRESS + KEXEC_ARM_ZIMAGE_OFFSET)
+
+#define ATAG_NONE_TYPE      0x00000000
+#define ATAG_CORE_TYPE      0x54410001
+#define ATAG_RAMDISK_TYPE   0x54410004
+#define ATAG_INITRD2_TYPE   0x54420005
+#define ATAG_CMDLINE_TYPE   0x54410009
+
+#define MAX_ATAG_SIZE 0x4000
+
+struct atag_info {
+    unsigned size;
+    unsigned type;
+};
+
+struct atag_initrd2 {
+    unsigned start;
+    unsigned size;
+};
+
+struct atag_cmdline {
+    char cmdline[0];
+};
+
+struct atag {
+    struct atag_info info;
+    union {
+        struct atag_initrd2 initrd2;
+        struct atag_cmdline cmdline;
+    } data;
+};
+
+
+long kexec_load(unsigned int entry, unsigned long nr_segments,
+                struct kexec_segment *segment, unsigned long flags) {
+   return syscall(__NR_kexec_load, entry, nr_segments, segment, flags);
+}
+
+/*
+ * Prepares arguments for kexec
+ * Kernel address is not set into kernel_phys
+ * Ramdisk is set to position relative to kernel
+ */
+int prepare_boot_linux(unsigned kernel_phys, void *kernel_addr, int kernel_size,
+                       unsigned ramdisk_phys, void *ramdisk_addr, int ramdisk_size,
+                       unsigned second_phys, void *second_addr, int second_size,
+                       unsigned atags_phys, void *atags_addr, int atags_size) {
+    struct kexec_segment segment[4];
+    int segment_count = 2;
+    unsigned entry = START_ADDRESS + KEXEC_ARM_ZIMAGE_OFFSET;
+    int rv;
+    int page_size = getpagesize();
+
+    segment[0].buf = kernel_addr;
+    segment[0].bufsz = kernel_size;
+    segment[0].mem = (void *) KERNEL_START;
+    segment[0].memsz = ROUND_TO_PAGE(kernel_size, page_size);
+
+    if (kernel_size > MEMORY_SIZE - KEXEC_ARM_ZIMAGE_OFFSET) {
+        D(INFO, "Kernel image too big");
+        return -1;
+    }
+
+    segment[1].buf = atags_addr;
+    segment[1].bufsz = atags_size;
+    segment[1].mem = (void *) (START_ADDRESS + KEXEC_ARM_ATAGS_OFFSET);
+    segment[1].memsz = ROUND_TO_PAGE(atags_size, page_size);
+
+    D(INFO, "Ramdisk size is %d", ramdisk_size);
+
+    if (ramdisk_size != 0) {
+        segment[segment_count].buf = ramdisk_addr;
+        segment[segment_count].bufsz = ramdisk_size;
+        segment[segment_count].mem = (void *) (KERNEL_START + ramdisk_phys - kernel_phys);
+        segment[segment_count].memsz = ROUND_TO_PAGE(ramdisk_phys, page_size);
+        ++segment_count;
+    }
+
+    D(INFO, "Ramdisk size is %d", ramdisk_size);
+    if (second_size != 0) {
+        segment[segment_count].buf = second_addr;
+        segment[segment_count].bufsz = second_size;
+        segment[segment_count].mem = (void *) (KERNEL_START + second_phys - kernel_phys);
+        segment[segment_count].memsz = ROUND_TO_PAGE(second_size, page_size);
+        entry = second_phys;
+        ++segment_count;
+    }
+
+    rv = kexec_load(entry, segment_count, segment, KEXEC_ARCH_DEFAULT);
+
+    if (rv != 0) {
+        D(INFO, "Kexec_load returned non-zero exit code: %s\n", strerror(errno));
+        return -1;
+    }
+
+    return 1;
+
+}
+
+unsigned *create_atags(unsigned *atags_position, int atag_size, const struct boot_img_hdr *hdr, int *size) {
+    struct atag *current_tag = (struct atag *) atags_position;
+    unsigned *current_tag_raw = atags_position;
+    unsigned *new_atags = malloc(ROUND_TO_PAGE(atag_size + BOOT_ARGS_SIZE * sizeof(char),
+                                               hdr->page_size));
+    //This pointer will point into the beggining of buffer free space
+    unsigned *natags_raw_buff = new_atags;
+    int new_atags_size = 0;
+    int current_size;
+    int cmdl_length;
+
+    // copy tags from current atag file
+    while (current_tag->info.type != ATAG_NONE_TYPE) {
+        switch (current_tag->info.type) {
+            case ATAG_CMDLINE_TYPE:
+            case ATAG_RAMDISK_TYPE:
+            case ATAG_INITRD2_TYPE: break;
+            default:
+                memcpy((void *)natags_raw_buff, (void *)current_tag_raw, current_tag->info.size * sizeof(unsigned));
+                natags_raw_buff += current_tag->info.size;
+                new_atags_size += current_tag->info.size;
+        }
+
+        current_tag_raw += current_tag->info.size;
+        current_tag = (struct atag *) current_tag_raw;
+
+        if (current_tag_raw >= atags_position + atag_size) {
+            D(ERR, "Critical error in atags");
+            return NULL;
+        }
+    }
+
+    // set INITRD2 tag
+    if (hdr->ramdisk_size > 0) {
+        current_size = (sizeof(struct atag_info) + sizeof(struct atag_initrd2)) / sizeof(unsigned);
+        *((struct atag *) natags_raw_buff) = (struct atag) {
+            .info = {
+                .size = current_size,
+                .type = ATAG_INITRD2_TYPE
+            },
+            .data = {
+                .initrd2 = (struct atag_initrd2) {
+                    .start = hdr->ramdisk_addr,
+                    .size = hdr->ramdisk_size
+                }
+            }
+        };
+
+        new_atags_size += current_size;
+        natags_raw_buff += current_size;
+    }
+
+    // set ATAG_CMDLINE
+    cmdl_length = strnlen((char *) hdr->cmdline, BOOT_ARGS_SIZE - 1);
+    current_size = sizeof(struct atag_info) + (1 + cmdl_length);
+    current_size = (current_size + sizeof(unsigned) - 1) / sizeof(unsigned);
+    *((struct atag *) natags_raw_buff) = (struct atag) {
+        .info = {
+            .size = current_size,
+            .type = ATAG_CMDLINE_TYPE
+        },
+    };
+
+    //copy cmdline and ensure that there is null character
+    memcpy(((struct atag *) natags_raw_buff)->data.cmdline.cmdline,
+           (char *) hdr->cmdline, cmdl_length);
+    ((struct atag *) natags_raw_buff)->data.cmdline.cmdline[cmdl_length] = '\0';
+
+    new_atags_size += current_size;
+    natags_raw_buff += current_size;
+
+    // set ATAG_NONE
+    *((struct atag *) natags_raw_buff) = (struct atag) {
+        .info = {
+            .size = 0,
+            .type = ATAG_NONE_TYPE
+        },
+    };
+    new_atags_size += sizeof(struct atag_info) / sizeof(unsigned);
+    natags_raw_buff += sizeof(struct atag_info) / sizeof(unsigned);
+
+    *size = new_atags_size * sizeof(unsigned);
+    return new_atags;
+}
+
+char *read_atags(const char * path, int *atags_sz) {
+    int afd = -1;
+    char *atags_ptr = NULL;
+
+    afd = open(path, O_RDONLY);
+    if (afd < 0) {
+        D(ERR, "wrong atags file");
+        return 0;
+    }
+
+    atags_ptr = (char *) malloc(MAX_ATAG_SIZE);
+    if (atags_ptr == NULL) {
+        D(ERR, "insufficient memory");
+        return 0;
+    }
+
+    *atags_sz = read(afd, atags_ptr, MAX_ATAG_SIZE);
+
+    close(afd);
+    return atags_ptr;
+}
+
diff --git a/fastbootd/commands/boot.h b/fastbootd/commands/boot.h
new file mode 100644
index 0000000..901c38a
--- /dev/null
+++ b/fastbootd/commands/boot.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef __FASTBOOT_BOOT_H
+#define __FASTBOOT_BOOT_H
+
+#include <sys/cdefs.h>
+#include <linux/kexec.h>
+
+#include "bootimg.h"
+
+#define KEXEC_TYPE_DEFAULT 0
+#define KEXEC_TYPE_CRASH   1
+
+int prepare_boot_linux(unsigned, void *, int, unsigned, void *, int,
+                       unsigned, void *, int, unsigned, void *, int);
+unsigned *create_atags(unsigned *, int, const struct boot_img_hdr *, int *);
+long kexec_load(unsigned int, unsigned long, struct kexec_segment *, unsigned long);
+char *read_atags(const char *, int *);
+
+#endif /* _SYS_KEXEC_H */
+
diff --git a/fastbootd/commands/flash.c b/fastbootd/commands/flash.c
new file mode 100644
index 0000000..0954217
--- /dev/null
+++ b/fastbootd/commands/flash.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "flash.h"
+#include "protocol.h"
+#include "debug.h"
+#include "utils.h"
+#include "commands/partitions.h"
+
+#ifdef FLASH_CERT
+#include "secure.h"
+#endif
+
+#define ALLOWED_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-."
+#define BUFFER_SIZE 1024 * 1024
+#define MIN(a, b) (a > b ? b : a)
+
+
+int flash_find_entry(const char *name, char *out, size_t outlen)
+{
+//TODO: Assumption: All the partitions has they unique name
+
+    const char *path = fastboot_getvar("device-directory");
+    size_t length;
+    if (strcmp(path, "") == 0) {
+        D(ERR, "device-directory: not defined in config file");
+        return -1;
+    }
+
+    length = strspn(name, ALLOWED_CHARS);
+    if (length != strlen(name)) {
+        D(ERR, "Not allowed char in name: %c", name[length]);
+        return -1;
+    }
+
+    if (snprintf(out, outlen, "%s%s", path, name) >= (int) outlen) {
+        D(ERR, "Too long path to partition file");
+        return -1;
+    }
+
+    if (access(out, F_OK ) == -1) {
+        D(ERR, "could not find partition file %s", name);
+        return -1;
+    }
+
+    return 0;
+}
+
+int flash_erase(int fd)
+{
+    int64_t size;
+    size = get_block_device_size(fd);
+    D(DEBUG, "erase %llu data from %d\n", size, fd);
+
+    return wipe_block_device(fd, size);
+}
+
+int flash_write(int partition_fd, int data_fd, ssize_t size, ssize_t skip)
+{
+    ssize_t written = 0;
+    struct GPT_mapping input;
+    struct GPT_mapping output;
+
+    while (written < size) {
+        int current_size = MIN(size - written, BUFFER_SIZE);
+
+        if (gpt_mmap(&input, written + skip, current_size, data_fd)) {
+            D(ERR, "Error in writing data, unable to map data file %d at %d size %d", size, skip, current_size);
+            return -1;
+        }
+        if (gpt_mmap(&output, written, current_size, partition_fd)) {
+            D(ERR, "Error in writing data, unable to map output partition");
+            return -1;
+        }
+
+        memcpy(output.ptr, input.ptr, current_size);
+
+        gpt_unmap(&input);
+        gpt_unmap(&output);
+
+        written += current_size;
+    }
+
+    return 0;
+}
+
+#ifdef FLASH_CERT
+
+int flash_validate_certificate(int signed_fd, int *data_fd) {
+    int ret = 0;
+    const char *cert_path;
+    X509_STORE *store = NULL;
+    CMS_ContentInfo *content_info;
+    BIO *content;
+
+    cert_path = fastboot_getvar("certificate-path");
+    if (!strcmp(cert_path, "")) {
+        D(ERR, "could not find cert-key value in config file");
+        goto finish;
+    }
+
+    store = cert_store_from_path(cert_path);
+    if (store == NULL) {
+        D(ERR, "unable to create certification store");
+        goto finish;
+    }
+
+    if (cert_read(signed_fd, &content_info, &content)) {
+        D(ERR, "reading data failed");
+        goto finish;
+    }
+
+    ret = cert_verify(content, content_info, store, data_fd);
+    cert_release(content, content_info);
+
+    return ret;
+
+finish:
+    if (store != NULL)
+        cert_release_store(store);
+
+    return ret;
+}
+
+#else
+int flash_validate_certificate(int signed_fd, int *data_fd) {
+    return 1;
+}
+#endif
diff --git a/fastbootd/commands/flash.h b/fastbootd/commands/flash.h
new file mode 100644
index 0000000..5a64cab
--- /dev/null
+++ b/fastbootd/commands/flash.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef _FASTBOOTD_ERASE_H
+#define _FASTBOOTD_ERASE_H
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include "debug.h"
+
+int flash_find_entry(const char *, char *, size_t);
+int flash_erase(int fd);
+
+static inline int flash_get_partiton(const char *path) {
+    return open(path, O_RDWR);
+}
+
+static inline int flash_close(int fd) {
+    return close(fd);
+}
+
+int flash_write(int partition, int data, ssize_t size, ssize_t skip);
+
+static inline ssize_t read_data_once(int fd, char *buffer, ssize_t size) {
+    ssize_t readcount = 0;
+    ssize_t len;
+
+    while ((len = TEMP_FAILURE_RETRY(read(fd, (void *) &buffer[readcount], size - readcount))) > 0) {
+        readcount += len;
+    }
+    if (len < 0) {
+        D(ERR, "Read error:%s", strerror(errno));
+        return len;
+    }
+
+    return readcount;
+}
+
+int flash_validate_certificate(int signed_fd, int *data_fd);
+
+#endif
+
diff --git a/fastbootd/commands/partitions.c b/fastbootd/commands/partitions.c
new file mode 100644
index 0000000..de80ea3
--- /dev/null
+++ b/fastbootd/commands/partitions.c
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <endian.h>
+#include <zlib.h>
+#include <linux/hdreg.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <cutils/config_utils.h>
+
+#include "partitions.h"
+#include "debug.h"
+#include "utils.h"
+#include "protocol.h"
+
+#define BLKRRPART  _IO(0x12,95) /* re-read partition table */
+#define BLKSSZGET  _IO(0x12,104)
+
+#define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y))
+#define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y)))
+#define ALIGN_DOWN(x, y) ((y) * ((x) / (y)))
+
+
+const uint8_t partition_type_uuid[16] = {
+    0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
+    0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7,
+};
+
+//TODO: There is assumption that we are using little endian
+
+static void GPT_entry_clear(struct GPT_entry_raw *entry)
+{
+    memset(entry, 0, sizeof(*entry));
+}
+
+/*
+ * returns mapped location to choosen area
+ * mapped_ptr is pointer to whole area mapped (it can be bigger then requested)
+ */
+int gpt_mmap(struct GPT_mapping *mapping, uint64_t location, int size, int fd)
+{
+    unsigned int location_diff = location & ~PAGE_MASK;
+
+    mapping->size = ALIGN(size + location_diff, PAGE_SIZE);
+
+    uint64_t sz = get_file_size64(fd);
+    if (sz < size + location) {
+        D(ERR, "the location of mapping area is outside of the device size %lld", sz);
+        return 1;
+    }
+    location = ALIGN_DOWN(location, PAGE_SIZE);
+
+    mapping->map_ptr = mmap64(NULL, mapping->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, location);
+
+    if (mapping->map_ptr == MAP_FAILED) {
+        mapping->ptr = MAP_FAILED;
+        D(ERR, "map failed %d", (int) mapping->map_ptr);
+        return 1;
+    }
+
+    mapping->ptr = (void *)((char *) mapping->map_ptr + location_diff);
+    return 0;
+}
+
+void gpt_unmap(struct GPT_mapping *mapping) {
+    munmap(mapping->map_ptr, mapping->size);
+}
+
+
+#define LBA_ADDR(table, value)   ((uint64_t) (table)->sector_size * (value))
+
+int GPT_map_from_content(struct GPT_entry_table *table, const struct GPT_content *content)
+{
+
+    // Mapping header
+    if (gpt_mmap(&table->header_map, LBA_ADDR(table, content->header.current_lba),
+                 table->sector_size, table->fd)) {
+        D(ERR, "unable to map header:%s\n", strerror(errno));
+        goto error_header;
+    }
+
+    table->header = (struct GPT_header *) table->header_map.ptr;
+
+    table->partition_table_size = ROUND_UP(content->header.entries_count * sizeof(*table->entries),
+                                           table->sector_size);
+
+    // Mapping entry table
+    if (gpt_mmap(&table->entries_map, LBA_ADDR(table, content->header.entries_lba),
+                 table->partition_table_size, table->fd)) {
+        D(ERR, "unable to map entries");
+        goto error_signature;
+    }
+
+    table->entries = (struct GPT_entry_raw *) table->entries_map.ptr;
+
+    // Mapping secondary header
+    if (gpt_mmap(&table->sec_header_map, LBA_ADDR(table, content->header.backup_lba),
+                 table->sector_size, table->fd)) {
+        D(ERR, "unable to map backup gpt header");
+        goto error_sec_header;
+    }
+
+    // Mapping secondary entries table
+    if (gpt_mmap(&table->sec_entries_map,
+                 LBA_ADDR(table, content->header.backup_lba) - table->partition_table_size,
+                 table->partition_table_size, table->fd)) {
+        D(ERR, "unable to map secondary gpt table");
+        goto error_sec_entries;
+    }
+
+    table->second_header = (struct GPT_header *) table->sec_header_map.ptr;
+    table->second_entries = (struct GPT_entry_raw *) table->sec_entries_map.ptr;
+    table->second_valid = strcmp("EFI PART", (char *) table->second_header->signature) == 0;
+
+    return 0;
+
+error_sec_entries:
+    gpt_unmap(&table->sec_header_map);
+error_sec_header:
+    gpt_unmap(&table->entries_map);
+error_signature:
+    gpt_unmap(&table->header_map);
+error_header:
+    return 1;
+}
+
+int GPT_map(struct GPT_entry_table *table, unsigned header_lba)
+{
+    struct GPT_content content;
+    struct GPT_mapping mapping;
+    struct GPT_header *header;
+
+    if (gpt_mmap(&mapping, LBA_ADDR(table, header_lba), table->sector_size, table->fd)) {
+        D(ERR, "unable to map header: %s", strerror(errno));
+        goto error_header;
+    }
+
+    header = (struct GPT_header *) mapping.ptr;
+
+    if (strcmp("EFI PART", (char *) header->signature)) {
+        D(ERR, "GPT entry not valid");
+        goto error_signature;
+    }
+
+    content.header = *header;
+
+    gpt_unmap(&mapping);
+
+    return GPT_map_from_content(table, &content);
+
+error_signature:
+    gpt_unmap(&table->header_map);
+error_header:
+    return 1;
+}
+
+struct GPT_entry_table* GPT_get_device(const char *path, unsigned header_lba)
+{
+    struct GPT_entry_table *table;
+    size_t sector_bytes;
+
+    table = (struct GPT_entry_table *) malloc(sizeof(*table));
+    table->fd = open(path, O_RDWR);
+
+    if (table->fd < 0) {
+        D(ERR, "unable to open file %s:%s\n", path, strerror(errno));
+        return NULL;
+    }
+
+    if (!ioctl(table->fd, BLKSSZGET, &sector_bytes)) {
+        table->sector_size = (unsigned) sector_bytes;
+        D(INFO, "Got sector size %d", table->sector_size);
+    } else {
+        D(WARN, "unable to get sector size, assuming 512");
+        table->sector_size = 512;
+    }
+
+    if (GPT_map(table, header_lba)) {
+        D(ERR, "Could not map gpt");
+        return NULL;
+    }
+
+    return table;
+}
+
+static struct GPT_entry_table* GPT_get_from_content(const char *path, const struct GPT_content *content)
+{
+    struct GPT_entry_table *table;
+    size_t sector_bytes;
+
+    table = (struct GPT_entry_table *) malloc(sizeof(*table));
+    table->fd = open(path, O_RDWR);
+
+    if (table->fd < 0) {
+        D(ERR, "unable to open file %s:%s\n", path, strerror(errno));
+        return NULL;
+    }
+
+    if (!ioctl(table->fd, BLKSSZGET, &sector_bytes)) {
+        table->sector_size = (unsigned) sector_bytes;
+        D(INFO, "Got sector size %d", table->sector_size);
+    } else {
+        D(WARN, "unable to get sector size %s, assuming 512", strerror(errno));
+        table->sector_size = 512;
+    }
+
+    if (GPT_map_from_content(table, content)) {
+        D(ERR, "Could not map gpt");
+        return NULL;
+    }
+
+    return table;
+}
+
+
+void GPT_release_device(struct GPT_entry_table *table)
+{
+    gpt_unmap(&table->header_map);
+    gpt_unmap(&table->entries_map);
+    gpt_unmap(&table->sec_header_map);
+    gpt_unmap(&table->sec_entries_map);
+    close(table->fd);
+    free(table);
+}
+
+static int GPT_check_overlap(struct GPT_entry_table *table, struct GPT_entry_raw *entry);
+static int GPT_check_overlap_except(struct GPT_entry_table *table,
+                                    struct GPT_entry_raw *entry,
+                                    struct GPT_entry_raw *exclude);
+
+void GPT_edit_entry(struct GPT_entry_table *table,
+                    struct GPT_entry_raw *old_entry,
+                    struct GPT_entry_raw *new_entry)
+{
+    struct GPT_entry_raw *current_entry = GPT_get_pointer(table, old_entry);
+
+    if (GPT_check_overlap_except(table, new_entry, current_entry)) {
+        D(ERR, "Couldn't add overlaping partition");
+        return;
+    }
+
+    if (current_entry == NULL) {
+        D(ERR, "Couldn't find entry");
+        return;
+    }
+
+    *current_entry = *new_entry;
+}
+
+int GPT_delete_entry(struct GPT_entry_table *table, struct GPT_entry_raw *entry)
+{
+    struct GPT_entry_raw *raw = GPT_get_pointer(table, entry);
+
+    if (raw == NULL) {
+        D(ERR, "could not find entry");
+        return 1;
+    }
+    D(DEBUG, "Deleting gpt entry '%s'\n", raw->partition_guid);
+
+    // Entry in the middle of table may become empty
+    GPT_entry_clear(raw);
+
+    return 0;
+}
+
+void GPT_add_entry(struct GPT_entry_table *table, struct GPT_entry_raw *entry)
+{
+    unsigned i;
+    int inserted = 0;
+    if (GPT_check_overlap(table, entry)) {
+        D(ERR, "Couldn't add overlaping partition");
+        return;
+    }
+
+    if (GPT_get_pointer(table, entry) != NULL) {
+        D(WARN, "Add entry fault, this entry already exists");
+        return;
+    }
+
+    struct GPT_entry_raw *entries = table->entries;
+
+    for (i = 0; i < table->header->entries_count; ++i) {
+        if (!entries[i].type_guid[0]) {
+            inserted = 1;
+            D(DEBUG, "inserting");
+            memcpy(&entries[i], entry, sizeof(entries[i]));
+            break;
+        }
+    }
+
+    if (!inserted) {
+        D(ERR, "Unable to find empty partion entry");
+    }
+}
+
+struct GPT_entry_raw *GPT_get_pointer_by_UTFname(struct GPT_entry_table *table, const uint16_t *name);
+
+struct GPT_entry_raw *GPT_get_pointer(struct GPT_entry_table *table, struct GPT_entry_raw *entry)
+{
+    if (entry->partition_guid[0] != 0)
+        return GPT_get_pointer_by_guid(table, (const char *) entry->partition_guid);
+    else if (entry->name[0] != 0)
+        return GPT_get_pointer_by_UTFname(table, entry->name);
+
+    D(WARN, "Name or guid needed to find entry");
+    return NULL;
+}
+
+struct GPT_entry_raw *GPT_get_pointer_by_guid(struct GPT_entry_table *table, const char *name)
+{
+    int current = (int) table->header->entries_count;
+
+    for (current = current - 1; current >= 0; --current) {
+        if (strncmp((char *) name,
+                    (char *) table->entries[current].partition_guid, 16) == 0) {
+                return &table->entries[current];
+        }
+    }
+
+    return NULL;
+}
+
+int strncmp_UTF16_char(const uint16_t *s1, const char *s2, size_t n)
+{
+    if (n == 0)
+        return (0);
+    do {
+        if (((*s1) & 127) != *s2++)
+            return (((unsigned char) ((*s1) & 127)) - *(unsigned char *)--s2);
+        if (*s1++ == 0)
+            break;
+    } while (--n != 0);
+    return (0);
+}
+
+int strncmp_UTF16(const uint16_t *s1, const uint16_t *s2, size_t n)
+{
+    if (n == 0)
+        return (0);
+    do {
+        if ((*s1) != *s2++)
+            return (*s1 - *--s2);
+        if (*s1++ == 0)
+            break;
+    } while (--n != 0);
+    return (0);
+}
+
+struct GPT_entry_raw *GPT_get_pointer_by_name(struct GPT_entry_table *table, const char *name)
+{
+    int count = (int) table->header->entries_count;
+    int current;
+
+    for (current = 0; current < count; ++current) {
+        if (strncmp_UTF16_char(table->entries[current].name,
+                         (char *) name, 16) == 0) {
+                    return &table->entries[current];
+        }
+    }
+
+    return NULL;
+}
+
+struct GPT_entry_raw *GPT_get_pointer_by_UTFname(struct GPT_entry_table *table, const uint16_t *name)
+{
+    int count = (int) table->header->entries_count;
+    int current;
+
+    for (current = 0; current < count; ++current) {
+        if (strncmp_UTF16(table->entries[current].name,
+                          name, GPT_NAMELEN) == 0) {
+                return &table->entries[current];
+        }
+    }
+
+    return NULL;
+}
+
+void GPT_sync(struct GPT_entry_table *table)
+{
+    uint32_t crc;
+
+    //calculate crc32
+    crc = crc32(0, Z_NULL, 0);
+    crc = crc32(crc, (void*) table->entries, table->header->entries_count * sizeof(*table->entries));
+    table->header->partition_array_checksum = crc;
+
+    table->header->header_checksum = 0;
+    crc = crc32(0, Z_NULL, 0);
+    crc = crc32(crc, (void*) table->header, table->header->header_size);
+    table->header->header_checksum = crc;
+
+    //sync secondary partion
+    if (table->second_valid) {
+        memcpy((void *)table->second_entries, (void *) table->entries, table->partition_table_size);
+        memcpy((void *)table->second_header, (void *)table->header, sizeof(*table->header));
+    }
+
+    if(!ioctl(table->fd, BLKRRPART, NULL)) {
+        D(WARN, "Unable to force kernel to refresh partition table");
+    }
+}
+
+void GPT_to_UTF16(uint16_t *to, const char *from, int n)
+{
+    int i;
+    for (i = 0; i < (n - 1) && (to[i] = from[i]) != '\0'; ++i);
+    to[i] = '\0';
+}
+
+void GPT_from_UTF16(char *to, const uint16_t *from, int n)
+{
+    int i;
+    for (i = 0; i < (n - 1) && (to[i] = from[i] & 127) != '\0'; ++i);
+    to[i] = '\0';
+}
+
+static int GPT_check_overlap_except(struct GPT_entry_table *table,
+                                    struct GPT_entry_raw *entry,
+                                    struct GPT_entry_raw *exclude) {
+    int current = (int) table->header->entries_count;
+    int dontcheck;
+    struct GPT_entry_raw *current_entry;
+    if (entry->last_lba < entry->first_lba) {
+        D(WARN, "Start address have to be less than end address");
+        return 1;
+    }
+
+    for (current = current - 1; current >= 0; --current) {
+        current_entry = &table->entries[current];
+        dontcheck = strncmp((char *) entry->partition_guid,
+                           (char *) current_entry->partition_guid , 16) == 0;
+        dontcheck |= current_entry->type_guid[0] == 0;
+        dontcheck |= current_entry == exclude;
+
+        if (!dontcheck && ((entry->last_lba >= current_entry->first_lba &&
+                            entry->first_lba < current_entry->last_lba ))) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static int GPT_check_overlap(struct GPT_entry_table *table, struct GPT_entry_raw *entry)
+{
+    return GPT_check_overlap_except(table, entry, NULL);
+}
+
+static char *get_key_value(char *ptr, char **key, char **value)
+{
+    *key = ptr;
+    ptr = strchr(ptr, '=');
+
+    if (ptr == NULL)
+        return NULL;
+
+    *ptr++ = '\0';
+    *value = ptr;
+    ptr = strchr(ptr, ';');
+
+    if (ptr == NULL)
+        ptr = *value + strlen(*value);
+    else
+        *ptr = '\0';
+
+    *key = strip(*key);
+    *value = strip(*value);
+
+    return ptr;
+}
+
+//TODO: little endian?
+static int add_key_value(const char *key, const char *value, struct GPT_entry_raw *entry)
+{
+    char *endptr;
+    if (!strcmp(key, "type")) {
+        strncpy((char *) entry->type_guid, value, 16);
+        entry->type_guid[15] = 0;
+    }
+    else if (!strcmp(key, "guid")) {
+        strncpy((char *) entry->partition_guid, value, 16);
+        entry->type_guid[15] = 0;
+    }
+    else if (!strcmp(key, "firstlba")) {
+        entry->first_lba = strtoul(value, &endptr, 10);
+        if (*endptr != '\0') goto error;
+    }
+    else if (!strcmp(key, "lastlba")) {
+        entry->last_lba = strtoul(value, &endptr, 10);
+        if (*endptr != '\0') goto error;
+    }
+    else if (!strcmp(key, "flags")) {
+        entry->flags = strtoul(value, &endptr, 16);
+        if (*endptr != '\0') goto error;
+    }
+    else if (!strcmp(key, "name")) {
+        GPT_to_UTF16(entry->name, value, GPT_NAMELEN);
+    }
+    else {
+        goto error;
+    }
+
+    return 0;
+
+error:
+    D(ERR, "Could not find key or parse value: %s,%s", key, value);
+    return 1;
+}
+
+int GPT_parse_entry(char *string, struct GPT_entry_raw *entry)
+{
+    char *ptr = string;
+    char *key, *value;
+
+    while ((ptr = get_key_value(ptr, &key, &value)) != NULL) {
+        if (add_key_value(key, value, entry)) {
+            D(WARN, "key or value not valid: %s %s", key, value);
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+void entry_set_guid(int n, uint8_t *guid)
+{
+    int fd;
+    fd = open("/dev/urandom", O_RDONLY);
+    read(fd, guid, 16);
+    close(fd);
+
+    //rfc4122
+    guid[8] = (guid[8] & 0x3F) | 0x80;
+    guid[7] = (guid[7] & 0x0F) | 0x40;
+}
+
+void GPT_default_content(struct GPT_content *content, struct GPT_entry_table *table)
+{
+    if (table != NULL) {
+        memcpy(&content->header, table->header, sizeof(content->header));
+        content->header.header_size = sizeof(content->header);
+        content->header.entry_size = sizeof(struct GPT_entry_raw);
+    }
+    else {
+        D(WARN, "Could not locate old gpt table, using default values");
+        memset(&content->header, 0, sizeof(content->header) / sizeof(int));
+        content->header = (struct GPT_header) {
+            .revision = 0x10000,
+            .header_size = sizeof(content->header),
+            .header_checksum = 0,
+            .reserved_zeros = 0,
+            .current_lba = 1,
+            .backup_lba = 1,
+            .entry_size = sizeof(struct GPT_entry_raw),
+            .partition_array_checksum = 0
+        };
+        strncpy((char *)content->header.signature, "EFI PART", 8);
+        strncpy((char *)content->header.disk_guid, "ANDROID MMC DISK", 16);
+    }
+}
+
+static int get_config_uint64(cnode *node, uint64_t *ptr, const char *name)
+{
+    const char *tmp;
+    uint64_t val;
+    char *endptr;
+    if ((tmp = config_str(node, name, NULL))) {
+        val = strtoull(tmp, &endptr, 10);
+        if (*endptr != '\0') {
+            D(WARN, "Value for %s is not a number: %s", name, tmp);
+            return 1;
+        }
+        *ptr = val;
+        return 0;
+    }
+    return 1;
+}
+
+static int get_config_string(cnode *node, char *ptr, int max_len, const char *name)
+{
+    size_t begin, end;
+    const char *value = config_str(node, name, NULL);
+    if (!value)
+        return -1;
+
+    begin = strcspn(value, "\"") + 1;
+    end = strcspn(&value[begin], "\"");
+
+    if ((int) end > max_len) {
+        D(WARN, "Identifier \"%s\" too long", value);
+        return -1;
+    }
+
+    strncpy(ptr, &value[begin], end);
+    if((int) end < max_len)
+        ptr[end] = 0;
+    return 0;
+}
+
+static void GPT_parse_header(cnode *node, struct GPT_content *content)
+{
+    get_config_uint64(node, &content->header.current_lba, "header_lba");
+    get_config_uint64(node, &content->header.backup_lba, "backup_lba");
+    get_config_uint64(node, &content->header.first_usable_lba, "first_lba");
+    get_config_uint64(node, &content->header.last_usable_lba, "last_lba");
+    get_config_uint64(node, &content->header.entries_lba, "entries_lba");
+    get_config_string(node, (char *) content->header.disk_guid, 16, "guid");
+}
+
+static int GPT_parse_partitions(cnode *node, struct GPT_content *content)
+{
+    cnode *current;
+    int i;
+    uint64_t partition_size;
+    struct GPT_entry_raw *entry;
+    for (i = 0, current = node->first_child; current; current = current->next, ++i) {
+        entry = &content->entries[i];
+        entry_set_guid(i, content->entries[i].partition_guid);
+        memcpy(&content->entries[i].type_guid, partition_type_uuid, 16);
+        if (get_config_uint64(current, &entry->first_lba, "first_lba")) {
+            D(ERR, "first_lba not specified");
+            return 1;
+        }
+        if (get_config_uint64(current, &partition_size, "partition_size")) {
+            D(ERR, "partition_size not specified");
+            return 1;
+        }
+        if (config_str(current, "system", NULL)) {
+            entry->flags |= GPT_FLAG_SYSTEM;
+        }
+        if (config_str(current, "bootable", NULL)) {
+            entry->flags |= GPT_FLAG_BOOTABLE;
+        }
+        if (config_str(current, "readonly", NULL)) {
+            entry->flags |= GPT_FLAG_READONLY;
+        }
+        if (config_str(current, "automount", NULL)) {
+            entry->flags |= GPT_FLAG_DOAUTOMOUNT;
+        }
+
+        get_config_uint64(current, &content->entries[i].flags, "flags");
+        content->entries[i].last_lba = content->entries[i].first_lba + partition_size - 1;
+        GPT_to_UTF16(content->entries[i].name, current->name, 16);
+    }
+    return 0;
+}
+
+static inline int cnode_count(cnode *node)
+{
+    int i;
+    cnode *current;
+    for (i = 0, current = node->first_child; current; current = current->next, ++i)
+        ;
+    return i;
+}
+
+
+static int GPT_parse_cnode(cnode *root, struct GPT_content *content)
+{
+    cnode *partnode;
+
+    if (!(partnode = config_find(root, "partitions"))) {
+        D(ERR, "Could not find partition table");
+        return 0;
+    }
+
+    GPT_parse_header(root, content);
+
+    content->header.entries_count = cnode_count(partnode);
+    content->entries = malloc(content->header.entries_count * sizeof(struct GPT_entry_raw));
+
+    if (GPT_parse_partitions(partnode, content)) {
+        D(ERR, "Could not parse partitions");
+        return 0;
+    }
+
+    return 1;
+}
+
+int GPT_parse_file(int fd, struct GPT_content *content)
+{
+    char *data;
+    int size;
+    int ret;
+    cnode *root = config_node("", "");
+
+    size = get_file_size(fd);
+    data = (char *) mmap(NULL, size + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+
+    if (data == NULL) {
+        if (size == 0)
+            D(ERR, "config file empty");
+        else
+            D(ERR, "Out of memory");
+        return 0;
+    }
+
+    data[size - 1] = 0;
+    config_load(root, data);
+
+    if (root->first_child == NULL) {
+        D(ERR, "Could not read config file");
+        return 0;
+    }
+
+    ret = GPT_parse_cnode(root, content);
+    munmap(data, size);
+    return ret;
+}
+
+void GPT_release_content(struct GPT_content *content)
+{
+    free(content->entries);
+}
+
+int GPT_write_content(const char *device, struct GPT_content *content)
+{
+    struct GPT_entry_table *maptable;
+
+    maptable = GPT_get_from_content(device, content);
+    if (maptable == NULL) {
+        D(ERR, "could not map device");
+        return 0;
+    }
+
+    memcpy(maptable->header, &content->header, sizeof(*maptable->header));
+    memcpy(maptable->entries, content->entries,
+           content->header.entries_count * sizeof(*maptable->entries));
+
+    GPT_sync(maptable);
+    GPT_release_device(maptable);
+
+    return 1;
+}
+
diff --git a/fastbootd/commands/partitions.h b/fastbootd/commands/partitions.h
new file mode 100644
index 0000000..9a6a88d
--- /dev/null
+++ b/fastbootd/commands/partitions.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+
+#ifndef __FASTBOOTD_PATITIONS_
+#define __FASTBOOTD_PATITIONS_
+
+#include <stdint.h>
+
+#define GPT_ENTRIES 128
+#define GPT_NAMELEN 36
+
+#define GPT_FLAG_SYSTEM (1ULL << 0)
+#define GPT_FLAG_BOOTABLE (1ULL << 2)
+#define GPT_FLAG_READONLY (1ULL << 60)
+#define GPT_FLAG_DOAUTOMOUNT (1ULL << 63)
+
+// it should be passed in little endian order
+struct GPT_entry_raw {
+    uint8_t type_guid[16];
+    uint8_t partition_guid[16];
+    uint64_t first_lba; // little endian
+    uint64_t last_lba;
+    uint64_t flags;
+    uint16_t name[GPT_NAMELEN]; // UTF-16 LE
+};
+
+struct GPT_mapping {
+    void *map_ptr;
+    void *ptr;
+    unsigned size;
+};
+
+struct GPT_entry_table {
+    int fd;
+
+    struct GPT_mapping header_map;
+    struct GPT_mapping entries_map;
+    struct GPT_mapping sec_header_map;
+    struct GPT_mapping sec_entries_map;
+
+    struct GPT_header *header;
+    struct GPT_entry_raw *entries;
+    struct GPT_header *second_header;
+    struct GPT_entry_raw *second_entries;
+
+    unsigned sector_size;
+    unsigned partition_table_size;
+    int second_valid;
+};
+
+struct GPT_header {
+    uint8_t signature[8];
+    uint32_t revision;
+    uint32_t header_size;
+    uint32_t header_checksum;
+    uint32_t reserved_zeros;
+    uint64_t current_lba;
+    uint64_t backup_lba;
+    uint64_t first_usable_lba;
+    uint64_t last_usable_lba;
+    uint8_t disk_guid[16];
+    uint64_t entries_lba;
+    uint32_t entries_count;
+    uint32_t entry_size;
+    uint32_t partition_array_checksum;
+    // the rest should be filled with zeros
+} __attribute__((packed));
+
+struct GPT_content {
+    struct GPT_header header;
+    struct GPT_entry_raw *entries;
+};
+
+
+struct GPT_entry_table* GPT_get_device(const char *, unsigned lba);
+
+void GPT_release_device(struct GPT_entry_table *);
+
+void GPT_edit_entry(struct GPT_entry_table *table,
+                    struct GPT_entry_raw *old_entry,
+                    struct GPT_entry_raw *new_entry);
+
+int GPT_delete_entry(struct GPT_entry_table *table, struct GPT_entry_raw *entry);
+
+void GPT_add_entry(struct GPT_entry_table *table, struct GPT_entry_raw *entry);
+
+struct GPT_entry_raw *GPT_get_pointer(struct GPT_entry_table *table, struct GPT_entry_raw *entry);
+struct GPT_entry_raw *GPT_get_pointer_by_guid(struct GPT_entry_table *, const char *);
+struct GPT_entry_raw *GPT_get_pointer_by_name(struct GPT_entry_table *, const char *);
+
+//Use after every edit operation
+void GPT_sync();
+
+void GPT_to_UTF16(uint16_t *, const char *, int );
+void GPT_from_UTF16(char *, const uint16_t *, int);
+
+int GPT_parse_entry(char *string, struct GPT_entry_raw *entry);
+
+void GPT_default_content(struct GPT_content *content, struct GPT_entry_table *table);
+
+void GPT_release_content(struct GPT_content *content);
+
+int GPT_parse_file(int fd, struct GPT_content *content);
+
+int GPT_write_content(const char *device, struct GPT_content *content);
+
+int gpt_mmap(struct GPT_mapping *mapping, uint64_t location, int size, int fd);
+
+void gpt_unmap(struct GPT_mapping *mapping);
+
+#endif
diff --git a/fastbootd/commands/virtual_partitions.c b/fastbootd/commands/virtual_partitions.c
new file mode 100644
index 0000000..813f485
--- /dev/null
+++ b/fastbootd/commands/virtual_partitions.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 "commands/virtual_partitions.h"
+#include "debug.h"
+
+static struct virtual_partition *partitions = NULL;
+
+int try_handle_virtual_partition(struct protocol_handle *handle, const char *arg)
+{
+    struct virtual_partition *current;
+
+    for (current = partitions; current != NULL; current = current->next) {
+        if (!strcmp(current->name, arg)) {
+            current->handler(handle, arg);
+        }
+    }
+
+    return 0;
+}
+
+void virtual_partition_register(
+        const char * name,
+        void (*handler)(struct protocol_handle *phandle, const char *arg))
+{
+    struct virtual_partition *new;
+    new = malloc(sizeof(*new));
+    if (new) {
+        new->name = name;
+        new->handler = handler;
+        new->next = partitions;
+        partitions = new;
+    }
+    else {
+        D(ERR, "Out of memory");
+    }
+}
diff --git a/fastbootd/commands/virtual_partitions.h b/fastbootd/commands/virtual_partitions.h
new file mode 100644
index 0000000..88df71e
--- /dev/null
+++ b/fastbootd/commands/virtual_partitions.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef FASTBOOTD_VIRTUAL_PARTITIONS_H
+#define FASTBOOTD_VIRTUAL_PARTITIONS_H
+
+#include "protocol.h"
+
+struct virtual_partition {
+    struct virtual_partition *next;
+    const char *name;
+    void (*handler)(struct protocol_handle *phandle, const char *arg);
+};
+
+int try_handle_virtual_partition(struct protocol_handle *handle, const char *arg);
+
+void virtual_partition_register(
+        const char * name,
+        void (*handler)(struct protocol_handle *phandle, const char *arg));
+
+#endif
diff --git a/fastbootd/config.c b/fastbootd/config.c
new file mode 100644
index 0000000..fe6da69
--- /dev/null
+++ b/fastbootd/config.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "protocol.h"
+#include "utils.h"
+
+#include "debug.h"
+
+// TODO: change config path
+#define CONFIG_PATH "/data/fastboot.cfg"
+
+static int config_parse_line(char *line)
+{
+    char *c;
+    char *key;
+    char *value;
+
+    c = strchr(line, '#');
+    if (c)
+        *c = '\0';
+
+    if (strspn(line, " \t") == strlen(line))
+        return 0;
+
+    c = strchr(line, '=');
+    if (c == NULL)
+        return -1;
+
+    key = line;
+    *c = '\0';
+    value = c + 1;
+
+    key = strip(key);
+    value = strip(value);
+
+    key = strdup(key);
+    value = strdup(value);
+
+    fastboot_publish(key, value);
+
+    return 0;
+}
+
+static void config_parse(char *buffer)
+{
+    char *saveptr;
+    char *str = buffer;
+    char *line = buffer;
+    int c;
+    int ret;
+
+    for (c = 1; line != NULL; c++) {
+        line = strtok_r(str, "\r\n", &saveptr);
+        if (line != NULL) {
+            D(VERBOSE, "'%s'", line);
+            ret = config_parse_line(line);
+            if (ret < 0) {
+                D(WARN, "error parsing " CONFIG_PATH " line %d", c);
+            }
+        }
+        str = NULL;
+    }
+}
+
+void config_init()
+{
+    int fd;
+    off_t len;
+    ssize_t ret;
+    size_t count = 0;
+    char *buffer;
+
+    fd = open(CONFIG_PATH, O_RDONLY);
+    if (fd < 0) {
+        D(ERR, "failed to open " CONFIG_PATH);
+        return;
+    }
+
+    len = lseek(fd, 0, SEEK_END);
+    if (len < 0) {
+        D(ERR, "failed to seek to end of " CONFIG_PATH);
+        return;
+    }
+
+    lseek(fd, 0, SEEK_SET);
+
+    buffer = malloc(len + 1);
+    if (buffer == NULL) {
+        D(ERR, "failed to allocate %ld bytes", len);
+        return;
+    }
+
+    while (count < (size_t)len) {
+        ret = read(fd, buffer + count, len - count);
+        if (ret < 0 && errno != EINTR) {
+            D(ERR, "failed to read " CONFIG_PATH ": %d %s", errno, strerror(errno));
+            return;
+        }
+        if (ret == 0) {
+            D(ERR, "early EOF reading " CONFIG_PATH);
+            return;
+        }
+
+        count += ret;
+    }
+
+    buffer[len] = '\0';
+
+    config_parse(buffer);
+
+    free(buffer);
+}
diff --git a/fastbootd/debug.h b/fastbootd/debug.h
new file mode 100644
index 0000000..74620b8
--- /dev/null
+++ b/fastbootd/debug.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _FASTBOOTD_DEBUG_H_
+#define _FASTBOOTD_DEBUG_H_
+
+#include <stdio.h>
+
+#include <cutils/klog.h>
+
+#define ERR 0
+#define WARN 1
+#define INFO 2
+#define VERBOSE 3
+#define DEBUG 4
+
+extern unsigned int debug_level;
+
+//#define DLOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
+#define DLOG(fmt, ...) KLOG_INFO("fastbootd", fmt, ##__VA_ARGS__)
+
+#define D(level, fmt, ...) \
+    do { \
+        if (debug_level == level || debug_level > level) { \
+            DLOG("%s:%d " fmt "\n", __BASE_FILE__, __LINE__, ##__VA_ARGS__); \
+        } \
+    } while (0)
+
+#endif
diff --git a/fastbootd/fastbootd.c b/fastbootd/fastbootd.c
new file mode 100644
index 0000000..2b51b33
--- /dev/null
+++ b/fastbootd/fastbootd.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <cutils/klog.h>
+#include <getopt.h>
+#include <stdlib.h>
+
+#include "debug.h"
+#include "trigger.h"
+#include "socket_client.h"
+#include "secure.h"
+
+unsigned int debug_level = DEBUG;
+
+void commands_init();
+void usb_init();
+void config_init();
+int transport_socket_init();
+int network_discovery_init();
+void ssh_server_start();
+
+int main(int argc, char **argv)
+{
+    int socket_client = 0;
+    int c;
+    int network = 1;
+
+    klog_init();
+    klog_set_level(6);
+
+    const struct option longopts[] = {
+        {"socket", no_argument, 0, 'S'},
+        {"nonetwork", no_argument, 0, 'n'},
+        {0, 0, 0, 0}
+    };
+
+    while (1) {
+        c = getopt_long(argc, argv, "Sn", longopts, NULL);
+        /* Alphabetical cases */
+        if (c < 0)
+            break;
+        switch (c) {
+        case 'S':
+            socket_client = 1;
+            break;
+        case 'n':
+            network = 0;
+            break;
+        case '?':
+            return 1;
+        default:
+            return 0;
+        }
+    }
+
+    (void)argc;
+    (void)argv;
+
+    klog_init();
+    klog_set_level(6);
+
+    if (socket_client) {
+        //TODO: Shouldn't we change current tty into raw mode?
+        run_socket_client();
+    }
+    else {
+        cert_init_crypto();
+        config_init();
+        load_trigger();
+        commands_init();
+        usb_init();
+
+        if (network) {
+            if (!transport_socket_init())
+                exit(1);
+            ssh_server_start();
+            network_discovery_init();
+        }
+
+        while (1) {
+            sleep(1);
+        }
+    }
+    return 0;
+}
diff --git a/fastbootd/include/vendor_trigger.h b/fastbootd/include/vendor_trigger.h
new file mode 100644
index 0000000..51204fa
--- /dev/null
+++ b/fastbootd/include/vendor_trigger.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef __VENDOR_TRIGGER_H_
+#define __VENDOR_TRIGGER_H_
+
+#define TRIGGER_MODULE_ID "fastbootd"
+#include <hardware/hardware.h>
+
+__BEGIN_DECLS
+
+struct GPT_entry_raw;
+struct GPT_content;
+
+/*
+ * Structer with function pointers may become longer in the future
+ */
+
+struct vendor_trigger_t {
+    struct hw_device_t common;
+
+    /*
+     * This function runs at the beggining and shoud never be changed
+     *
+     * version is number parameter indicating version on the fastbootd side
+     * libversion is version indicateing version of the library version
+     *
+     * returns 0 if it can cooperate with the current version and 1 in opposite
+     */
+    int (*check_version)(const int version, int *libversion);
+
+
+    /*
+     * Return value -1 forbid the action from the vendor site and sets errno
+     */
+    int (* gpt_layout)(struct GPT_content *);
+    int (* oem_cmd)(const char *arg, const char **response);
+};
+
+__END_DECLS
+
+#endif
diff --git a/fastbootd/network_discovery.c b/fastbootd/network_discovery.c
new file mode 100644
index 0000000..1cd3e48
--- /dev/null
+++ b/fastbootd/network_discovery.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <stdio.h>
+#include <string.h>
+#include <dns_sd.h>
+#include <cutils/properties.h>
+#include <unistd.h>
+
+#include "debug.h"
+#include "network_discovery.h"
+#include "utils.h"
+
+#define MDNS_SERVICE_NAME "mdnsd"
+#define MDNS_SERVICE_STATUS "init.svc.mdnsd"
+#define FASTBOOTD_TYPE "_fastbootd._tcp"
+#define FASTBOOTD_DOMAIN "local."
+#define FASTBOOTD_NAME "fastbootd"
+
+
+static void reg_reply(DNSServiceRef sdref, const DNSServiceFlags flags, DNSServiceErrorType errorCode,
+    const char *name, const char *regtype, const char *domain, void *context)
+{
+    (void)sdref;    // Unused
+    (void)flags;    // Unused
+    (void)context;  // Unused
+    if (errorCode == kDNSServiceErr_ServiceNotRunning) {
+        fprintf(stderr, "Error code %d\n", errorCode);
+    }
+
+
+    printf("Got a reply for service %s.%s%s: ", name, regtype, domain);
+
+    if (errorCode == kDNSServiceErr_NoError)
+    {
+        if (flags & kDNSServiceFlagsAdd)
+            printf("Name now registered and active\n");
+        else
+            printf("Name registration removed\n");
+        if (errorCode == kDNSServiceErr_NameConflict)
+            printf("Name in use, please choose another\n");
+        else
+            printf("Error %d\n", errorCode);
+
+        if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
+    }
+}
+
+static int register_service() {
+    DNSServiceRef sdref = NULL;
+    const char *domain = FASTBOOTD_DOMAIN;
+    const char *type = FASTBOOTD_TYPE;
+    const char *host = NULL;
+    char name[PROP_VALUE_MAX];
+    uint16_t port = 22;
+    int flags = 0;
+    DNSServiceErrorType result;
+    property_get("ro.serialno", name, "");
+    if (!strcmp(name, "")) {
+        D(ERR, "No property serialno");
+        return -1;
+    }
+
+    result = DNSServiceRegister(&sdref, flags, kDNSServiceInterfaceIndexAny,
+                       name, type, domain, host, port,
+                       0, NULL, reg_reply, NULL);
+    if (result != kDNSServiceErr_NoError) {
+        D(ERR, "Unable to register service");
+        return -1;
+    }
+    return 0;
+}
+
+
+int network_discovery_init()
+{
+    D(INFO, "Starting discovery");
+    if (service_start(MDNS_SERVICE_NAME)) {
+        D(ERR, "Unable to start discovery");
+        return -1;
+    }
+
+    if (register_service()) {
+        D(ERR, "Unable to register service");
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/fastbootd/network_discovery.h b/fastbootd/network_discovery.h
new file mode 100644
index 0000000..75fda63
--- /dev/null
+++ b/fastbootd/network_discovery.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef _FASTBOOTD_NETWORK_DISCOVERY_H
+#define _FASTBOOTD_NETWORK_DISCOVERY_H
+
+int network_discovery_init();
+
+#endif
diff --git a/fastbootd/other/gptedit.c b/fastbootd/other/gptedit.c
new file mode 100644
index 0000000..16d34a5
--- /dev/null
+++ b/fastbootd/other/gptedit.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <cutils/klog.h>
+
+#include "commands/partitions.h"
+#include "debug.h"
+
+unsigned int debug_level = DEBUG;
+//TODO: add tool to generate config file
+
+void usage() {
+    fprintf(stderr,
+            "usage: test_gpt [ <option> ] <file>\n"
+            "\n"
+            "options:\n"
+            "  -p                                       print partitions\n"
+            "  -c                                       print config file\n"
+            "  -a                                       adds new partition\n"
+            "  -d                                       deletes partition (-o needed)\n"
+            "\n"
+            "  -n name@startlba,endlba                  new partition detail\n"
+            "  -o                                       old partition name\n"
+            "  -t                                       type guid\n"
+            "  -g                                       partition guid\n"
+            "  -l gpt_location                          specyfies gpt secto\n"
+    );
+
+}
+
+void printGPT(struct GPT_entry_table *table);
+void addGPT(struct GPT_entry_table *table, const char *arg, const char *guid, const char *tguid);
+void deleteGPT(struct GPT_entry_table *table, const char *name);
+void configPrintGPT(struct GPT_entry_table *table);
+
+int main(int argc, char *argv[]) {
+    int print_cmd = 0;
+    int config_cmd = 0;
+    int add_cmd = 0;
+    int del_cmd = 0;
+    int sync_cmd = 0;
+    int c;
+    const char *new_partition = NULL;
+    const char *old_partition = NULL;
+    const char *type_guid = NULL;
+    const char *partition_guid = NULL;
+    unsigned gpt_location = 1;
+
+    klog_init();
+    klog_set_level(6);
+
+    const struct option longopts[] = {
+        {"print", no_argument, 0, 'p'},
+        {"config-print", no_argument, 0, 'c'},
+        {"add", no_argument, 0, 'a'},
+        {"del", no_argument, 0, 'd'},
+        {"new", required_argument, 0, 'n'},
+        {"old", required_argument, 0, 'o'},
+        {"type", required_argument, 0, 't'},
+        {"sync", required_argument, 0, 's'},
+        {"guid", required_argument, 0, 'g'},
+        {"location", required_argument, 0, 'l'},
+        {0, 0, 0, 0}
+    };
+
+    while (1) {
+        c = getopt_long(argc, argv, "pcadt:g:n:o:sl:", longopts, NULL);
+        /* Alphabetical cases */
+        if (c < 0)
+            break;
+        switch (c) {
+        case 'p':
+            print_cmd = 1;
+            break;
+        case 'c':
+            config_cmd = 1;
+            break;
+        case 'a':
+            add_cmd = 1;
+            break;
+        case 'd':
+            del_cmd = 1;
+            break;
+        case 'n':
+            new_partition = optarg;
+            break;
+        case 'o':
+            old_partition = optarg;
+            break;
+        case 't':
+            type_guid = optarg;
+        case 'g':
+            partition_guid = optarg;
+            break;
+        case 's':
+            sync_cmd = 1;
+            break;
+        case 'l':
+            gpt_location = strtoul(optarg, NULL, 10);
+            fprintf(stderr, "Got offset as %d", gpt_location);
+            break;
+        case '?':
+            return 1;
+        default:
+            abort();
+        }
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc < 1) {
+        usage();
+        return 1;
+    }
+
+    const char *path = argv[0];
+    struct GPT_entry_table *table = GPT_get_device(path, gpt_location);
+    if (table == NULL) {
+        fprintf(stderr, "unable to get GPT table from %s\n", path);
+        return 1;
+    }
+
+    if (add_cmd)
+        addGPT(table, new_partition, partition_guid, type_guid);
+    if (del_cmd)
+        deleteGPT(table, old_partition);
+    if (print_cmd)
+        printGPT(table);
+    if (config_cmd)
+        configPrintGPT(table);
+    if (sync_cmd)
+        GPT_sync(table);
+
+    GPT_release_device(table);
+
+    return 0;
+}
+
+void printGPT(struct GPT_entry_table *table) {
+    struct GPT_entry_raw *entry = table->entries;
+    unsigned n, m;
+    char name[GPT_NAMELEN + 1];
+
+    printf("ptn  start block   end block     name\n");
+    printf("---- ------------- -------------\n");
+
+    for (n = 0; n < table->header->entries_count; n++, entry++) {
+        if (entry->type_guid[0] == 0)
+            continue;
+        for (m = 0; m < GPT_NAMELEN; m++) {
+            name[m] = entry->name[m] & 127;
+        }
+        name[m] = 0;
+        printf("#%03d %13lld %13lld %s\n",
+            n + 1, entry->first_lba, entry->last_lba, name);
+    }
+}
+
+void configPrintGPT(struct GPT_entry_table *table) {
+    struct GPT_entry_raw *entry = table->entries;
+    unsigned n, m;
+    char name[GPT_NAMELEN + 1];
+    char temp_guid[17];
+    temp_guid[16] = 0;
+
+    printf("header_lba %lld\n", table->header->current_lba);
+    printf("backup_lba %lld\n", table->header->backup_lba);
+    printf("first_lba %lld\n", table->header->first_usable_lba);
+    printf("last_lba %lld\n", table->header->last_usable_lba);
+    printf("entries_lba %lld\n", table->header->entries_lba);
+    snprintf(temp_guid, 17, "%s", table->header->disk_guid);
+    printf("guid \"%s\"", temp_guid);
+
+    printf("\npartitions {\n");
+
+    for (n = 0; n < table->header->entries_count; n++, entry++) {
+        uint64_t size = entry->last_lba - entry->first_lba + 1;
+
+        if (entry->type_guid[0] == 0)
+            continue;
+        for (m = 0; m < GPT_NAMELEN; m++) {
+            name[m] = entry->name[m] & 127;
+        }
+        name[m] = 0;
+
+        printf("    %s {\n", name);
+        snprintf(temp_guid, 17, "%s", entry->partition_guid);
+        printf("        guid \"%s\"\n", temp_guid);
+        printf("        first_lba %lld\n", entry->first_lba);
+        printf("        partition_size %lld\n", size);
+        if (entry->flags & GPT_FLAG_SYSTEM)
+            printf("        system\n");
+        if (entry->flags & GPT_FLAG_BOOTABLE)
+            printf("        bootable\n");
+        if (entry->flags & GPT_FLAG_READONLY)
+            printf("        readonly\n");
+        if (entry->flags & GPT_FLAG_DOAUTOMOUNT)
+            printf("        automount\n");
+        printf("    }\n\n");
+    }
+    printf("}\n");
+}
+
+void addGPT(struct GPT_entry_table *table, const char *str  , const char *guid, const char *tguid) {
+    char *c, *c2;
+    char *arg = malloc(strlen(str));
+    char *name = arg;
+    unsigned start, end;
+    strcpy(arg, str);
+    if (guid == NULL || tguid == NULL) {
+        fprintf(stderr, "Type guid and partion guid needed");
+        free(arg);
+        return;
+    }
+
+    c = strchr(arg, '@');
+
+    if (c == NULL) {
+        fprintf(stderr, "Wrong entry format");
+        free(arg);
+        return;
+    }
+
+    *c++ = '\0';
+
+    c2 = strchr(c, ',');
+
+    if (c2 == NULL) {
+        fprintf(stderr, "Wrong entry format");
+        free(arg);
+        return;
+    }
+
+    start = strtoul(c, NULL, 10);
+    *c2++ = '\0';
+    end = strtoul(c2, NULL, 10);
+
+    struct GPT_entry_raw data;
+    strncpy((char *)data.partition_guid, guid, 15);
+    data.partition_guid[15] = '\0';
+    strncpy((char *)data.type_guid, tguid, 15);
+    data.type_guid[15] = '\0';
+    GPT_to_UTF16(data.name, name, GPT_NAMELEN);
+    data.first_lba = start;
+    data.last_lba = end;
+
+    fprintf(stderr, "Adding (%d,%d) %s as, [%s, %s]", start, end, name, (char *) data.type_guid, (char *) data.partition_guid);
+    GPT_add_entry(table, &data);
+    free(arg);
+}
+
+void deleteGPT(struct GPT_entry_table *table, const char *name) {
+    struct GPT_entry_raw *entry;
+
+    if (name == NULL) {
+        fprintf(stderr, "Need partition name");
+        return;
+    }
+
+    entry = GPT_get_pointer_by_name(table, name);
+
+    if (!entry) {
+        fprintf(stderr, "Unable to find partition: %s", name);
+        return;
+    }
+    GPT_delete_entry(table, entry);
+}
+
diff --git a/fastbootd/other/partitions.sample.cfg b/fastbootd/other/partitions.sample.cfg
new file mode 100644
index 0000000..49562cf
--- /dev/null
+++ b/fastbootd/other/partitions.sample.cfg
@@ -0,0 +1,60 @@
+
+header_lba 1
+backup_lba 101
+first_lba 43
+last_lba 100
+entries_lba 2
+
+partitions {
+    #You can generate this as output from gptedit -c
+    SOS {
+        first_lba 28672
+        partition_size 16384
+    }
+
+    DTB {
+        first_lba 45056
+        partition_size 8192
+    }
+
+    LNX {
+        first_lba 53248
+        partition_size 16384
+    }
+
+    APP {
+        first_lba 69632
+        partition_size 1048576
+    }
+
+    CAC {
+        first_lba 1118208
+        partition_size 1572864
+    }
+
+    MSC {
+        first_lba 2691072
+        partition_size 4096
+    }
+
+    USP {
+        first_lba 2695168
+        partition_size 65536
+    }
+
+    MDA {
+        first_lba 2760704
+        partition_size 4096
+    }
+
+    FCT {
+        first_lba 2764800
+        partition_size 32768
+    }
+
+    UDA {
+        first_lba 2797568
+        partition_size 27975680
+    }
+}
+
diff --git a/fastbootd/other/sign/src/SignImg.java b/fastbootd/other/sign/src/SignImg.java
new file mode 100644
index 0000000..338d427
--- /dev/null
+++ b/fastbootd/other/sign/src/SignImg.java
@@ -0,0 +1,181 @@
+package signtool;
+
+import java.io.*;
+import java.util.Properties;
+import java.util.ArrayList;
+
+import javax.mail.internet.*;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.activation.MailcapCommandMap;
+import javax.activation.CommandMap;
+
+import java.security.PrivateKey;
+import java.security.Security;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateEncodingException;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
+import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.cms.CMSProcessableByteArray;
+import org.bouncycastle.cms.CMSSignedGenerator;
+import org.bouncycastle.cms.CMSSignedDataGenerator;
+import org.bouncycastle.cms.CMSSignedGenerator;
+import org.bouncycastle.cms.CMSProcessable;
+import org.bouncycastle.cms.CMSSignedData;
+import org.bouncycastle.cms.CMSTypedData;
+import org.bouncycastle.cert.jcajce.JcaCertStore;
+import org.bouncycastle.util.Store;
+import org.bouncycastle.asn1.ASN1InputStream;    
+import org.bouncycastle.asn1.DEROutputStream;
+import org.bouncycastle.asn1.ASN1Object;
+
+
+public class SignImg {
+
+    /* It reads private key in pkcs#8 formate
+     * Conversion:
+     * openssl pkcs8 -topk8 -nocrypt -outform DER < inkey.pem > outkey.pk8
+     */
+    private static PrivateKey getPrivateKey(String path) throws IOException, FileNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException {
+        File file = new File(path);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int)file.length()];
+        fis.read(data);
+        fis.close();
+
+        PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(data);
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        PrivateKey privateKey = kf.generatePrivate(kspec);
+
+        return privateKey;
+    }
+
+    private static MimeBodyPart getContent(String path) throws IOException, FileNotFoundException, MessagingException {
+        MimeBodyPart body = new MimeBodyPart();
+
+        File file = new File(path);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int)file.length()];
+        fis.read(data);
+        fis.close();
+
+        body.setContent(data, "application/octet-stream");
+
+        return body;
+    }
+
+    private static CMSProcessableByteArray getCMSContent(String path) throws IOException, FileNotFoundException, MessagingException {
+        File file = new File(path);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int)file.length()];
+        fis.read(data);
+        fis.close();
+        CMSProcessableByteArray cms = new CMSProcessableByteArray(data);
+
+        return cms;
+    }
+
+    private static X509Certificate readCert(String path) throws IOException, FileNotFoundException, CertificateException {
+        File file = new File(path);
+        FileInputStream is = new FileInputStream(file);
+
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        Certificate cert = cf.generateCertificate(is);
+        is.close();
+
+        return (X509Certificate) cert;
+    }
+
+    private static void save(MimeBodyPart content, String path) throws IOException, FileNotFoundException, MessagingException {
+        File file = new File(path);
+        FileOutputStream os = new FileOutputStream(file);
+
+        content.writeTo(os);
+
+        os.close();
+    }
+
+    private static Store certToStore(X509Certificate certificate) throws CertificateEncodingException {
+        ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>();
+        certList.add(certificate);
+        return new JcaCertStore(certList);
+    }
+
+    public static void setDefaultMailcap()
+    {
+        MailcapCommandMap _mailcap =
+            (MailcapCommandMap)CommandMap.getDefaultCommandMap();
+
+        _mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
+        _mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
+        _mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
+        _mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
+        _mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
+
+        CommandMap.setDefaultCommandMap(_mailcap);
+    } 
+
+    public static void main(String[] args) {
+        try {
+            if (args.length < 4) {
+                System.out.println("Usage: signimg data private_key certificate output");
+                return;
+            }
+            System.out.println("Signing the image");
+            setDefaultMailcap();
+
+            Security.addProvider(new BouncyCastleProvider());
+
+            PrivateKey key = getPrivateKey(args[1]);
+            System.out.println("File read sucessfully");
+
+            CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
+
+            CMSTypedData body = getCMSContent(args[0]);
+            System.out.println("Content read sucessfully");
+
+            X509Certificate cert = (X509Certificate) readCert(args[2]);
+            System.out.println("Certificate read sucessfully");
+
+            ContentSigner sha256Signer = new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").build(key);
+
+            Store certs = certToStore(cert);
+
+            generator.addCertificates(certs);
+            generator.addSignerInfoGenerator(
+                          new JcaSignerInfoGeneratorBuilder(
+                                new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
+                          .build(sha256Signer, cert));
+
+            CMSSignedData signed = generator.generate(body, true);
+            System.out.println("Signed");
+
+            Properties props = System.getProperties();
+            Session session = Session.getDefaultInstance(props, null);
+            
+            File file = new File(args[3]);
+            FileOutputStream os = new FileOutputStream(file);
+
+            ASN1InputStream asn1 = new ASN1InputStream(signed.getEncoded());
+            ByteArrayOutputStream out = new ByteArrayOutputStream(); 
+            DEROutputStream dOut = new DEROutputStream(os); 
+            dOut.writeObject(ASN1Object.fromByteArray(signed.getEncoded()));
+
+        }
+        catch (Exception ex) {
+            System.out.println("Exception during programm execution: " + ex.getMessage());
+        }
+    }
+}
diff --git a/fastbootd/other/vendor_trigger.c b/fastbootd/other/vendor_trigger.c
new file mode 100644
index 0000000..101959b
--- /dev/null
+++ b/fastbootd/other/vendor_trigger.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <stdlib.h>
+
+#include "vendor_trigger.h"
+#include "debug.h"
+
+unsigned int debug_level = DEBUG;
+
+static const int version = 1;
+
+int check_version(const int fastboot_version, int *libversion) {
+    *libversion = version;
+    return !(fastboot_version == version);
+}
+
+int gpt_layout(struct GPT_content *table) {
+    D(DEBUG, "message from libvendor");
+    return 0;
+}
+
+int oem_cmd(const char *arg, const char **response) {
+    D(DEBUG, "message from libvendor, oem catched request %s", arg);
+    return 0;
+}
+
+static int close_triggers(struct vendor_trigger_t *dev)
+{
+    if (dev)
+        free(dev);
+
+    return 0;
+}
+
+static int open_triggers(const struct hw_module_t *module, char const *name,
+                         struct hw_device_t **device) {
+    struct vendor_trigger_t *dev = malloc(sizeof(struct vendor_trigger_t));
+    klog_init();
+    klog_set_level(6);
+
+    memset(dev, 0, sizeof(*dev));
+    dev->common.module = (struct hw_module_t *) module;
+    dev->common.close  = (int (*)(struct hw_device_t *)) close_triggers;
+
+    dev->gpt_layout = gpt_layout;
+    dev->oem_cmd = oem_cmd;
+
+    *device = (struct hw_device_t *) dev;
+
+    return 0;
+}
+
+
+static struct hw_module_methods_t trigger_module_methods = {
+    .open = open_triggers,
+};
+
+struct hw_module_t HAL_MODULE_INFO_SYM = {
+    .tag = HARDWARE_MODULE_TAG,
+    .version_major = 1,
+    .version_minor = 0,
+    .id = TRIGGER_MODULE_ID,
+    .name = "vendor trigger library for fastbootd",
+    .author = "Google, Inc.",
+    .methods = &trigger_module_methods,
+};
+
diff --git a/fastbootd/protocol.c b/fastbootd/protocol.c
new file mode 100644
index 0000000..0086b4a
--- /dev/null
+++ b/fastbootd/protocol.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "debug.h"
+#include "protocol.h"
+#include "transport.h"
+
+#define STATE_OFFLINE   0
+#define STATE_COMMAND   1
+#define STATE_COMPLETE  2
+#define STATE_ERROR     3
+
+struct fastboot_cmd {
+    struct fastboot_cmd *next;
+    const char *prefix;
+    unsigned prefix_len;
+    void (*execute)(struct protocol_handle *phandle, const char *arg);
+};
+
+struct fastboot_var {
+    struct fastboot_var *next;
+    const char *name;
+    const char *value;
+};
+
+static struct fastboot_cmd *cmdlist;
+
+void fastboot_register(const char *prefix,
+        void (*phandle)(struct protocol_handle *phandle, const char *arg))
+{
+    struct fastboot_cmd *cmd;
+    cmd = malloc(sizeof(*cmd));
+    if (cmd) {
+        cmd->prefix = prefix;
+        cmd->prefix_len = strlen(prefix);
+        cmd->execute = phandle;
+        cmd->next = cmdlist;
+        cmdlist = cmd;
+    }
+}
+
+static struct fastboot_var *varlist;
+
+void fastboot_publish(const char *name, const char *value)
+{
+    struct fastboot_var *var;
+    var = malloc(sizeof(*var));
+    if (var) {
+        var->name = name;
+        var->value = value;
+        var->next = varlist;
+        varlist = var;
+    }
+}
+
+const char *fastboot_getvar(const char *name)
+{
+    struct fastboot_var *var;
+
+    for (var = varlist; var; var = var->next) {
+        if (!strcmp(var->name, name)) {
+            return var->value;
+        }
+    }
+
+    return "";
+}
+
+int protocol_handle_download(struct protocol_handle *phandle, size_t len)
+{
+    return transport_handle_download(phandle->transport_handle, len);
+}
+
+static ssize_t protocol_handle_write(struct protocol_handle *phandle,
+        char *buffer, size_t len)
+{
+    return transport_handle_write(phandle->transport_handle, buffer, len);
+}
+
+static void fastboot_ack(struct protocol_handle *phandle, const char *code,
+        const char *reason)
+{
+    char response[64];
+
+    if (phandle->state != STATE_COMMAND)
+        return;
+
+    if (reason == 0)
+        reason = "";
+
+    snprintf(response, 64, "%s%s", code, reason);
+    phandle->state = STATE_COMPLETE;
+
+    protocol_handle_write(phandle, response, strlen(response));
+}
+
+void fastboot_fail(struct protocol_handle *phandle, const char *reason)
+{
+    fastboot_ack(phandle, "FAIL", reason);
+}
+
+void fastboot_okay(struct protocol_handle *phandle, const char *info)
+{
+    fastboot_ack(phandle, "OKAY", info);
+}
+
+void fastboot_data(struct protocol_handle *phandle, size_t len)
+{
+    char response[64];
+    ssize_t ret;
+
+    snprintf(response, 64, "DATA%08x", len);
+    ret = protocol_handle_write(phandle, response, strlen(response));
+    if (ret < 0)
+        return;
+}
+
+void protocol_handle_command(struct protocol_handle *phandle, char *buffer)
+{
+    D(INFO,"fastboot: %s\n", buffer);
+
+    struct fastboot_cmd *cmd;
+
+    for (cmd = cmdlist; cmd; cmd = cmd->next) {
+        if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
+            continue;
+        phandle->state = STATE_COMMAND;
+        cmd->execute(phandle, buffer + cmd->prefix_len);
+        if (phandle->state == STATE_COMMAND)
+            fastboot_fail(phandle, "unknown reason");
+        return;
+    }
+
+    fastboot_fail(phandle, "unknown command");
+}
+
+struct protocol_handle *create_protocol_handle(struct transport_handle *thandle)
+{
+    struct protocol_handle *phandle;
+
+    phandle = calloc(sizeof(struct protocol_handle), 1);
+
+    phandle->transport_handle = thandle;
+    phandle->state = STATE_OFFLINE;
+    phandle->download_fd = -1;
+
+    pthread_mutex_init(&phandle->lock, NULL);
+
+    return phandle;
+}
+
+int protocol_get_download(struct protocol_handle *phandle)
+{
+    int fd;
+
+    pthread_mutex_lock(&phandle->lock);
+    fd = phandle->download_fd;
+    phandle->download_fd = -1;
+    pthread_mutex_unlock(&phandle->lock);
+
+    return fd;
+}
diff --git a/fastbootd/protocol.h b/fastbootd/protocol.h
new file mode 100644
index 0000000..ea2a8df
--- /dev/null
+++ b/fastbootd/protocol.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef _FASTBOOTD_PROTOCOL_H_
+#define _FASTBOOTD_PROTOCOL_H_
+
+#include <pthread.h>
+#include <stddef.h>
+
+struct protocol_handle {
+    struct transport_handle *transport_handle;
+    unsigned int state;
+    int download_fd;
+
+    pthread_mutex_t lock;
+};
+
+void fastboot_register(const char *prefix,
+               void (*handle)(struct protocol_handle *handle, const char *arg));
+
+void fastboot_publish(const char *name, const char *value);
+const char *fastboot_getvar(const char *name);
+
+struct protocol_handle *create_protocol_handle(struct transport_handle *t);
+void protocol_handle_command(struct protocol_handle *handle, char *buffer);
+int protocol_handle_download(struct protocol_handle *phandle, size_t len);
+int protocol_get_download(struct protocol_handle *phandle);
+
+void fastboot_fail(struct protocol_handle *handle, const char *reason);
+void fastboot_okay(struct protocol_handle *handle, const char *reason);
+void fastboot_data(struct protocol_handle *handle, size_t len);
+
+#endif
diff --git a/fastbootd/secure.c b/fastbootd/secure.c
new file mode 100644
index 0000000..a657ad4
--- /dev/null
+++ b/fastbootd/secure.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <openssl/pem.h>
+#include <openssl/engine.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+#include <openssl/cms.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "secure.h"
+#include "debug.h"
+#include "utils.h"
+
+
+void cert_init_crypto() {
+    CRYPTO_malloc_init();
+    ERR_load_crypto_strings();
+    OpenSSL_add_all_algorithms();
+    ENGINE_load_builtin_engines();
+}
+
+X509_STORE *cert_store_from_path(const char *path) {
+
+    X509_STORE *store;
+    struct stat st;
+    X509_LOOKUP *lookup;
+
+    if (stat(path, &st)) {
+        D(ERR, "Unable to stat cert path");
+        goto error;
+    }
+
+    if (!(store = X509_STORE_new())) {
+        goto error;
+    }
+
+    if (S_ISDIR(st.st_mode)) {
+        lookup = X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
+        if (lookup == NULL)
+            goto error;
+        if (!X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM)) {
+            D(ERR, "Error loading cert directory %s", path);
+            goto error;
+        }
+    }
+    else if(S_ISREG(st.st_mode)) {
+        lookup = X509_STORE_add_lookup(store,X509_LOOKUP_file());
+        if (lookup == NULL)
+            goto error;
+        if (!X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM)) {
+            D(ERR, "Error loading cert directory %s", path);
+            goto error;
+        }
+    }
+    else {
+        D(ERR, "cert path is not directory or regular file");
+        goto error;
+    }
+
+    return store;
+
+error:
+    return NULL;
+}
+
+
+int cert_read(int fd, CMS_ContentInfo **content, BIO **output) {
+    BIO *input;
+    *output = NULL;
+
+
+    input = BIO_new_fd(fd, BIO_NOCLOSE);
+    if (input == NULL) {
+        D(ERR, "Unable to open input");
+        goto error;
+    }
+
+    //TODO:
+    // read with d2i_CMS_bio to support DER
+    // with java or just encode data with base64
+    *content = SMIME_read_CMS(input, output);
+    if (*content == NULL) {
+        unsigned long err = ERR_peek_last_error();
+        D(ERR, "Unable to parse input file: %s", ERR_lib_error_string(err));
+        goto error_read;
+    }
+
+    BIO_free(input);
+
+    return 0;
+
+error_read:
+    BIO_free(input);
+error:
+    return 1;
+}
+
+int cert_verify(BIO *content, CMS_ContentInfo *content_info, X509_STORE *store, int *out_fd) {
+    BIO *output_temp;
+    int ret;
+
+    *out_fd = create_temp_file();
+    if (*out_fd < 0) {
+        D(ERR, "unable to create temporary file");
+        return -1;
+    }
+
+    output_temp = BIO_new_fd(*out_fd, BIO_NOCLOSE);
+    if (output_temp == NULL) {
+        D(ERR, "unable to create temporary bio");
+        close(*out_fd);
+        return -1;
+    }
+
+    ret = CMS_verify(content_info, NULL ,store, content, output_temp, 0);
+
+    if (ret == 0) {
+        char buf[256];
+        unsigned long err = ERR_peek_last_error();
+        D(ERR, "Verification failed with reason: %s, %s", ERR_lib_error_string(err),  ERR_error_string(err, buf));
+        D(ERR, "Data used: content %d", (int) content);
+    }
+
+    ERR_clear_error();
+    ERR_remove_state(0);
+
+    BIO_free(output_temp);
+
+    return ret;
+}
+
+void cert_release(BIO *content, CMS_ContentInfo *info) {
+    BIO_free(content);
+    CMS_ContentInfo_free(info);
+}
+
diff --git a/fastbootd/secure.h b/fastbootd/secure.h
new file mode 100644
index 0000000..878a643
--- /dev/null
+++ b/fastbootd/secure.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef _FASTBOOTD_SECURE_H
+#define _FASTBOOTD_SECURE_H
+
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/pem.h>
+#include <openssl/cms.h>
+
+void cert_init_crypto();
+
+X509_STORE *cert_store_from_path(const char*stream);
+
+static inline void cert_release_store(X509_STORE *store) {
+    X509_STORE_free(store);
+}
+
+int cert_read(int fd, CMS_ContentInfo **content, BIO **output);
+int cert_verify(BIO *content, CMS_ContentInfo *content_info, X509_STORE *store, int *out_fd);
+void cert_release(BIO *content, CMS_ContentInfo *info);
+
+#endif
diff --git a/fastbootd/socket_client.c b/fastbootd/socket_client.c
new file mode 100644
index 0000000..da636db
--- /dev/null
+++ b/fastbootd/socket_client.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <stdio.h>
+#include <cutils/sockets.h>
+#include <poll.h>
+#include <unistd.h>
+
+#include "utils.h"
+
+#define BUFFER_SIZE 256
+
+#define STDIN_FD 0
+#define STDOUT_FD 1
+#define STDERR_FD 2
+
+void run_socket_client() {
+    int fd;
+    char buffer[BUFFER_SIZE];
+    int n;
+    struct pollfd fds[2];
+
+    fd = socket_local_client("fastbootd",
+                         ANDROID_SOCKET_NAMESPACE_RESERVED,
+                         SOCK_STREAM);
+
+    if (fd < 0) {
+        fprintf(stderr, "ERROR: Unable to open fastbootd socket\n");
+        return;
+    }
+
+    fds[0].fd = STDIN_FD;
+    fds[0].events = POLLIN;
+    fds[1].fd = fd;
+    fds[1].events = POLLIN;
+
+    while(true) {
+        if (poll(fds, 2, -1) <= 0) {
+            fprintf(stderr, "ERROR: socket error");
+            return;
+        }
+
+        if (fds[0].revents & POLLIN) {
+            if ((n = read(STDIN_FD, buffer, BUFFER_SIZE)) < 0) {
+                goto error;
+            }
+
+            if (bulk_write(fd, buffer, n) < 0) {
+                goto error;
+            }
+        }
+
+        if (fds[1].revents & POLLIN) {
+            if ((n = read(fd, buffer, BUFFER_SIZE)) < 0) {
+                goto error;
+            }
+
+            if (bulk_write(STDOUT_FD, buffer, n) < 0) {
+                goto error;
+            }
+        }
+    }
+
+error:
+    fprintf(stderr, "Transport error\n");
+}
diff --git a/fastbootd/socket_client.h b/fastbootd/socket_client.h
new file mode 100644
index 0000000..4481ff2
--- /dev/null
+++ b/fastbootd/socket_client.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef _FASTBOOTD_SOCKET_CLIENT_H
+#define _FASTBOOTD_SOCKET_CLIENT_H
+
+void run_socket_client();
+
+#endif
diff --git a/fastbootd/transport.c b/fastbootd/transport.c
new file mode 100644
index 0000000..19a705c
--- /dev/null
+++ b/fastbootd/transport.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include "debug.h"
+#include "protocol.h"
+#include "transport.h"
+
+#define COMMAND_BUF_SIZE 64
+
+ssize_t transport_handle_write(struct transport_handle *thandle, char *buffer, size_t len)
+{
+    return thandle->transport->write(thandle, buffer, len);
+}
+
+void transport_handle_close(struct transport_handle *thandle)
+{
+    thandle->transport->close(thandle);
+}
+
+int transport_handle_download(struct transport_handle *thandle, size_t len)
+{
+    ssize_t ret;
+    size_t n = 0;
+    int fd;
+    // TODO: move out of /dev
+    char tempname[] = "/dev/fastboot_download_XXXXXX";
+    char *buffer;
+
+    fd = mkstemp(tempname);
+    if (fd < 0)
+        return -1;
+
+    unlink(tempname);
+
+    ftruncate(fd, len);
+
+    buffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+    if (buffer == NULL) {
+        D(ERR, "mmap(%u) failed: %d %s", len, errno, strerror(errno));
+        goto err;
+    }
+
+    while (n < len) {
+        ret = thandle->transport->read(thandle, buffer + n, len - n);
+        if (ret <= 0) {
+            D(WARN, "transport read failed, ret=%d %s", ret, strerror(-ret));
+            break;
+        }
+        n += ret;
+    }
+
+    munmap(buffer, len);
+
+    if (n != len)
+        goto err;
+
+    return fd;
+
+err:
+    close(fd);
+    transport_handle_close(thandle);
+    return -1;
+}
+
+static void *transport_data_thread(void *arg)
+{
+    struct transport_handle *thandle = arg;
+    struct protocol_handle *phandle = create_protocol_handle(thandle);
+
+    while (!thandle->stopped) {
+        int ret;
+        char buffer[COMMAND_BUF_SIZE + 1];
+        D(VERBOSE, "transport_data_thread\n");
+
+        ret = thandle->transport->read(thandle, buffer, COMMAND_BUF_SIZE);
+        if (ret <= 0) {
+            D(DEBUG, "ret = %d\n", ret);
+            break;
+        }
+        if (ret > 0) {
+            buffer[ret] = 0;
+            //TODO: multiple threads
+            protocol_handle_command(phandle, buffer);
+        }
+    }
+
+    transport_handle_close(thandle);
+    free(thandle);
+
+    return NULL;
+}
+
+static void *transport_connect_thread(void *arg)
+{
+    struct transport *transport = arg;
+    while (!transport->stopped) {
+        struct transport_handle *thandle;
+        pthread_t thread;
+        pthread_attr_t attr;
+
+        D(VERBOSE, "transport_connect_thread\n");
+        thandle = transport->connect(transport);
+        if (thandle == NULL) {
+            D(ERR, "transport connect failed\n");
+            sleep(1);
+            continue;
+        }
+        thandle->transport = transport;
+
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+        pthread_create(&thread, &attr, transport_data_thread, thandle);
+
+        sleep(1);
+    }
+
+    return NULL;
+}
+
+void transport_register(struct transport *transport)
+{
+    pthread_t thread;
+    pthread_attr_t attr;
+
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+    pthread_create(&thread, &attr, transport_connect_thread, transport);
+}
diff --git a/fastbootd/transport.h b/fastbootd/transport.h
new file mode 100644
index 0000000..209340d
--- /dev/null
+++ b/fastbootd/transport.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _FASTBOOTD_TRANSPORT_H_
+#define _FASTBOOTD_TRANSPORT_H_
+
+#include <stdbool.h>
+
+struct transport_handle {
+    struct transport *transport;
+
+    bool stopped;
+};
+
+struct transport {
+    void (*init)();
+    void (*close)(struct transport_handle *thandle);
+    ssize_t (*read)(struct transport_handle *thandle, void *data, size_t len);
+    ssize_t (*write)(struct transport_handle *thandle, const void *data, size_t len);
+    struct transport_handle *(*connect)(struct transport *transport);
+    bool stopped;
+};
+
+void transport_register(struct transport *transport);
+ssize_t transport_handle_write(struct transport_handle *handle, char *buffer, size_t len);
+int transport_handle_download(struct transport_handle *handle, size_t len);
+
+#endif
diff --git a/fastbootd/transport_socket.c b/fastbootd/transport_socket.c
new file mode 100644
index 0000000..ff0f3bd
--- /dev/null
+++ b/fastbootd/transport_socket.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <cutils/sockets.h>
+
+#include "debug.h"
+#include "transport.h"
+#include "utils.h"
+
+
+#define container_of(ptr, type, member) \
+    ((type*)((char*)(ptr) - offsetof(type, member)))
+
+#define SOCKET_WORKING 0
+#define SOCKET_STOPPED -1
+
+
+struct socket_transport {
+    struct transport transport;
+
+    int fd;
+};
+
+struct socket_handle {
+    struct transport_handle handle;
+
+    int fd;
+};
+
+void socket_close(struct transport_handle *thandle)
+{
+    struct socket_handle * handle = container_of(thandle, struct socket_handle, handle);
+    close(handle->fd);
+}
+
+struct transport_handle *socket_connect(struct transport *transport)
+{
+    struct socket_handle *handle = calloc(sizeof(struct socket_handle), 1);
+    struct socket_transport *socket_transport = container_of(transport, struct socket_transport, transport);
+    struct sockaddr addr;
+    socklen_t alen = sizeof(addr);
+
+    handle->fd = accept(socket_transport->fd, &addr, &alen);
+
+    if (handle->fd < 0) {
+        D(WARN, "socket connect error");
+        return NULL;
+    }
+
+    D(DEBUG, "[ socket_thread - registering device ]");
+    return &handle->handle;
+}
+
+ssize_t socket_write(struct transport_handle *thandle, const void *data, size_t len)
+{
+    ssize_t ret;
+    struct socket_handle *handle = container_of(thandle, struct socket_handle, handle);
+
+    D(DEBUG, "about to write (fd=%d, len=%d)", handle->fd, len);
+    ret = bulk_write(handle->fd, data, len);
+    if (ret < 0) {
+        D(ERR, "ERROR: fd = %d, ret = %zd", handle->fd, ret);
+        return -1;
+    }
+    D(DEBUG, "[ socket_write done fd=%d ]", handle->fd);
+    return ret;
+}
+
+ssize_t socket_read(struct transport_handle *thandle, void *data, size_t len)
+{
+    ssize_t ret;
+    struct socket_handle *handle = container_of(thandle, struct socket_handle, handle);
+
+    D(DEBUG, "about to read (fd=%d, len=%d)", handle->fd, len);
+    ret = bulk_read(handle->fd, data, len);
+    if (ret < 0) {
+        D(ERR, "ERROR: fd = %d, ret = %zd", handle->fd, ret);
+        return -1;
+    }
+    D(DEBUG, "[ socket_read done fd=%d ret=%zd]", handle->fd, ret);
+    return ret;
+}
+
+static int listen_socket_init(struct socket_transport *socket_transport)
+{
+    int s = android_get_control_socket("fastbootd");
+
+    if (s < 0) {
+        D(WARN, "android_get_control_socket(fastbootd): %s\n", strerror(errno));
+        return 0;
+    }
+
+    if (listen(s, 4) < 0) {
+        D(WARN, "listen(control socket): %s\n", strerror(errno));
+        return 0;
+    }
+
+    socket_transport->fd = s;
+
+    return 1;
+}
+
+
+int transport_socket_init()
+{
+    struct socket_transport *socket_transport = malloc(sizeof(struct socket_transport));
+
+    socket_transport->transport.connect = socket_connect;
+    socket_transport->transport.close = socket_close;
+    socket_transport->transport.read = socket_read;
+    socket_transport->transport.write = socket_write;
+
+    if (!listen_socket_init(socket_transport)) {
+        D(ERR, "socket transport init failed");
+        free(socket_transport);
+        return 0;
+    }
+
+    transport_register(&socket_transport->transport);
+    return 1;
+}
+
diff --git a/fastbootd/trigger.c b/fastbootd/trigger.c
new file mode 100644
index 0000000..e63e64d
--- /dev/null
+++ b/fastbootd/trigger.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <dlfcn.h>
+
+#include <hardware/hardware.h>
+#include "debug.h"
+#include "trigger.h"
+#include "protocol.h"
+#include "vendor_trigger.h"
+
+static const int version = 1;
+
+static struct vendor_trigger_t *triggers = NULL;
+
+int load_trigger() {
+    int err;
+    hw_module_t* module;
+    hw_device_t* device;
+    int libversion;
+
+    err = hw_get_module(TRIGGER_MODULE_ID, (hw_module_t const**)&module);
+
+    if (err == 0) {
+        err = module->methods->open(module, NULL, &device);
+
+        if (err == 0) {
+            triggers = (struct vendor_trigger_t *) device;
+        } else {
+            D(WARN, "Libvendor load error");
+            return 1;
+        }
+    }
+    else {
+        D(WARN, "Libvendor not load: %s", strerror(-err));
+        return 0;
+    }
+
+    if (triggers->check_version != NULL &&
+        triggers->check_version(version, &libversion)) {
+
+        triggers = NULL;
+        D(ERR, "Library report incompability");
+        return 1;
+    }
+    D(INFO, "libvendortrigger loaded");
+
+    return 0;
+}
+
+int trigger_oem_cmd(const char *arg, const char **response) {
+    if (triggers != NULL && triggers->oem_cmd != NULL)
+        return triggers->oem_cmd(arg, response);
+    return 0;
+}
+
+int trigger_gpt_layout(struct GPT_content *table) {
+    if (triggers != NULL && triggers->gpt_layout != NULL)
+        return triggers->gpt_layout(table);
+    return 0;
+}
+
diff --git a/fastbootd/trigger.h b/fastbootd/trigger.h
new file mode 100644
index 0000000..404acb4
--- /dev/null
+++ b/fastbootd/trigger.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef __FASTBOOTD_TRIGGER_H_
+#define __FASTBOOTD_TRIGGER_H_
+
+#include "commands/partitions.h"
+#include "vendor_trigger.h"
+
+int load_trigger();
+
+/* same as in struct triggers */
+
+int trigger_gpt_layout(struct GPT_content *table);
+int trigger_oem_cmd(const char *arg, const char **response);
+
+#endif
diff --git a/fastbootd/usb_linux_client.c b/fastbootd/usb_linux_client.c
new file mode 100644
index 0000000..7a8e46f
--- /dev/null
+++ b/fastbootd/usb_linux_client.c
@@ -0,0 +1,308 @@
+/*
+ * 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.
+ */
+
+#include <endian.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/functionfs.h>
+
+#include "debug.h"
+#include "transport.h"
+#include "utils.h"
+
+#define   TRACE_TAG  TRACE_USB
+
+#define MAX_PACKET_SIZE_FS     64
+#define MAX_PACKET_SIZE_HS     512
+
+#define cpu_to_le16(x)  htole16(x)
+#define cpu_to_le32(x)  htole32(x)
+
+#define FASTBOOT_CLASS         0xff
+#define FASTBOOT_SUBCLASS      0x42
+#define FASTBOOT_PROTOCOL      0x3
+
+#define USB_FFS_FASTBOOT_PATH  "/dev/usb-ffs/adb/"
+#define USB_FFS_FASTBOOT_EP(x) USB_FFS_FASTBOOT_PATH#x
+
+#define USB_FFS_FASTBOOT_EP0   USB_FFS_FASTBOOT_EP(ep0)
+#define USB_FFS_FASTBOOT_OUT   USB_FFS_FASTBOOT_EP(ep1)
+#define USB_FFS_FASTBOOT_IN    USB_FFS_FASTBOOT_EP(ep2)
+
+#define container_of(ptr, type, member) \
+    ((type*)((char*)(ptr) - offsetof(type, member)))
+
+struct usb_transport {
+    struct transport transport;
+
+    pthread_cond_t notify;
+    pthread_mutex_t lock;
+
+    int control;
+    int bulk_out; /* "out" from the host's perspective => source for fastbootd */
+    int bulk_in;  /* "in" from the host's perspective => sink for fastbootd */
+};
+
+struct usb_handle {
+    struct transport_handle handle;
+};
+
+static const struct {
+    struct usb_functionfs_descs_head header;
+    struct {
+        struct usb_interface_descriptor intf;
+        struct usb_endpoint_descriptor_no_audio source;
+        struct usb_endpoint_descriptor_no_audio sink;
+    } __attribute__((packed)) fs_descs, hs_descs;
+} __attribute__((packed)) descriptors = {
+    .header = {
+        .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC),
+        .length = cpu_to_le32(sizeof(descriptors)),
+        .fs_count = 3,
+        .hs_count = 3,
+    },
+    .fs_descs = {
+        .intf = {
+            .bLength = sizeof(descriptors.fs_descs.intf),
+            .bDescriptorType = USB_DT_INTERFACE,
+            .bInterfaceNumber = 0,
+            .bNumEndpoints = 2,
+            .bInterfaceClass = FASTBOOT_CLASS,
+            .bInterfaceSubClass = FASTBOOT_SUBCLASS,
+            .bInterfaceProtocol = FASTBOOT_PROTOCOL,
+            .iInterface = 1, /* first string from the provided table */
+        },
+        .source = {
+            .bLength = sizeof(descriptors.fs_descs.source),
+            .bDescriptorType = USB_DT_ENDPOINT,
+            .bEndpointAddress = 1 | USB_DIR_OUT,
+            .bmAttributes = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize = MAX_PACKET_SIZE_FS,
+        },
+        .sink = {
+            .bLength = sizeof(descriptors.fs_descs.sink),
+            .bDescriptorType = USB_DT_ENDPOINT,
+            .bEndpointAddress = 2 | USB_DIR_IN,
+            .bmAttributes = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize = MAX_PACKET_SIZE_FS,
+        },
+    },
+    .hs_descs = {
+        .intf = {
+            .bLength = sizeof(descriptors.hs_descs.intf),
+            .bDescriptorType = USB_DT_INTERFACE,
+            .bInterfaceNumber = 0,
+            .bNumEndpoints = 2,
+            .bInterfaceClass = FASTBOOT_CLASS,
+            .bInterfaceSubClass = FASTBOOT_SUBCLASS,
+            .bInterfaceProtocol = FASTBOOT_PROTOCOL,
+            .iInterface = 1, /* first string from the provided table */
+        },
+        .source = {
+            .bLength = sizeof(descriptors.hs_descs.source),
+            .bDescriptorType = USB_DT_ENDPOINT,
+            .bEndpointAddress = 1 | USB_DIR_OUT,
+            .bmAttributes = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize = MAX_PACKET_SIZE_HS,
+        },
+        .sink = {
+            .bLength = sizeof(descriptors.hs_descs.sink),
+            .bDescriptorType = USB_DT_ENDPOINT,
+            .bEndpointAddress = 2 | USB_DIR_IN,
+            .bmAttributes = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize = MAX_PACKET_SIZE_HS,
+        },
+    },
+};
+
+#define STR_INTERFACE_ "Fastboot Interface"
+
+static const struct {
+    struct usb_functionfs_strings_head header;
+    struct {
+        __le16 code;
+        const char str1[sizeof(STR_INTERFACE_)];
+    } __attribute__((packed)) lang0;
+} __attribute__((packed)) strings = {
+    .header = {
+        .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
+        .length = cpu_to_le32(sizeof(strings)),
+        .str_count = cpu_to_le32(1),
+        .lang_count = cpu_to_le32(1),
+    },
+    .lang0 = {
+        cpu_to_le16(0x0409), /* en-us */
+        STR_INTERFACE_,
+    },
+};
+
+static int init_functionfs(struct usb_transport *usb_transport)
+{
+    ssize_t ret;
+
+    D(VERBOSE, "OPENING %s", USB_FFS_FASTBOOT_EP0);
+    usb_transport->control = open(USB_FFS_FASTBOOT_EP0, O_RDWR);
+    if (usb_transport->control < 0) {
+        D(ERR, "[ %s: cannot open control endpoint: errno=%d]", USB_FFS_FASTBOOT_EP0, errno);
+        goto err;
+    }
+
+    ret = write(usb_transport->control, &descriptors, sizeof(descriptors));
+    if (ret < 0) {
+        D(ERR, "[ %s: write descriptors failed: errno=%d ]", USB_FFS_FASTBOOT_EP0, errno);
+        goto err;
+    }
+
+    ret = write(usb_transport->control, &strings, sizeof(strings));
+    if (ret < 0) {
+        D(ERR, "[ %s: writing strings failed: errno=%d]", USB_FFS_FASTBOOT_EP0, errno);
+        goto err;
+    }
+
+    usb_transport->bulk_out = open(USB_FFS_FASTBOOT_OUT, O_RDWR);
+    if (usb_transport->bulk_out < 0) {
+        D(ERR, "[ %s: cannot open bulk-out ep: errno=%d ]", USB_FFS_FASTBOOT_OUT, errno);
+        goto err;
+    }
+
+    usb_transport->bulk_in = open(USB_FFS_FASTBOOT_IN, O_RDWR);
+    if (usb_transport->bulk_in < 0) {
+        D(ERR, "[ %s: cannot open bulk-in ep: errno=%d ]", USB_FFS_FASTBOOT_IN, errno);
+        goto err;
+    }
+
+    return 0;
+
+err:
+    if (usb_transport->bulk_in > 0) {
+        close(usb_transport->bulk_in);
+        usb_transport->bulk_in = -1;
+    }
+    if (usb_transport->bulk_out > 0) {
+        close(usb_transport->bulk_out);
+        usb_transport->bulk_out = -1;
+    }
+    if (usb_transport->control > 0) {
+        close(usb_transport->control);
+        usb_transport->control = -1;
+    }
+    return -1;
+}
+
+static ssize_t usb_write(struct transport_handle *thandle, const void *data, size_t len)
+{
+    ssize_t ret;
+    struct transport *t = thandle->transport;
+    struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport);
+
+    D(DEBUG, "about to write (fd=%d, len=%d)", usb_transport->bulk_in, len);
+    ret = bulk_write(usb_transport->bulk_in, data, len);
+    if (ret < 0) {
+        D(ERR, "ERROR: fd = %d, ret = %zd", usb_transport->bulk_in, ret);
+        return -1;
+    }
+    D(DEBUG, "[ usb_write done fd=%d ]", usb_transport->bulk_in);
+    return ret;
+}
+
+ssize_t usb_read(struct transport_handle *thandle, void *data, size_t len)
+{
+    ssize_t ret;
+    struct transport *t = thandle->transport;
+    struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport);
+
+    D(DEBUG, "about to read (fd=%d, len=%d)", usb_transport->bulk_out, len);
+    ret = bulk_read(usb_transport->bulk_out, data, len);
+    if (ret < 0) {
+        D(ERR, "ERROR: fd = %d, ret = %zd", usb_transport->bulk_out, ret);
+        return -1;
+    }
+    D(DEBUG, "[ usb_read done fd=%d ret=%zd]", usb_transport->bulk_out, ret);
+    return ret;
+}
+
+void usb_close(struct transport_handle *thandle)
+{
+    int err;
+    struct transport *t = thandle->transport;
+    struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport);
+
+    err = ioctl(usb_transport->bulk_in, FUNCTIONFS_CLEAR_HALT);
+    if (err < 0)
+        D(WARN, "[ kick: source (fd=%d) clear halt failed (%d) ]", usb_transport->bulk_in, errno);
+
+    err = ioctl(usb_transport->bulk_out, FUNCTIONFS_CLEAR_HALT);
+    if (err < 0)
+        D(WARN, "[ kick: sink (fd=%d) clear halt failed (%d) ]", usb_transport->bulk_out, errno);
+
+    pthread_mutex_lock(&usb_transport->lock);
+    close(usb_transport->control);
+    close(usb_transport->bulk_out);
+    close(usb_transport->bulk_in);
+    usb_transport->control = usb_transport->bulk_out = usb_transport->bulk_in = -1;
+
+    pthread_cond_signal(&usb_transport->notify);
+    pthread_mutex_unlock(&usb_transport->lock);
+}
+
+struct transport_handle *usb_connect(struct transport *transport)
+{
+    int ret;
+    struct usb_handle *usb_handle = calloc(sizeof(struct usb_handle), 1);
+    struct usb_transport *usb_transport = container_of(transport, struct usb_transport, transport);
+
+    pthread_mutex_lock(&usb_transport->lock);
+    while (usb_transport->control != -1)
+        pthread_cond_wait(&usb_transport->notify, &usb_transport->lock);
+    pthread_mutex_unlock(&usb_transport->lock);
+
+    ret = init_functionfs(usb_transport);
+    if (ret < 0) {
+        D(ERR, "usb connect: failed to initialize usb transport");
+        return NULL;
+    }
+
+    D(DEBUG, "[ usb_thread - registering device ]");
+    return &usb_handle->handle;
+}
+
+void usb_init()
+{
+    struct usb_transport *usb_transport = calloc(1, sizeof(struct usb_transport));
+
+    usb_transport->transport.connect = usb_connect;
+    usb_transport->transport.close = usb_close;
+    usb_transport->transport.read = usb_read;
+    usb_transport->transport.write = usb_write;
+    usb_transport->control  = -1;
+    usb_transport->bulk_out = -1;
+    usb_transport->bulk_out = -1;
+
+    pthread_cond_init(&usb_transport->notify, NULL);
+    pthread_mutex_init(&usb_transport->lock, NULL);
+
+    transport_register(&usb_transport->transport);
+}
+
diff --git a/fastbootd/utils.c b/fastbootd/utils.c
new file mode 100644
index 0000000..fe3f0f8
--- /dev/null
+++ b/fastbootd/utils.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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 <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <stdlib.h>
+#include <cutils/properties.h>
+
+#include "utils.h"
+#include "debug.h"
+
+#ifndef BLKDISCARD
+#define BLKDISCARD _IO(0x12,119)
+#endif
+
+#ifndef BLKSECDISCARD
+#define BLKSECDISCARD _IO(0x12,125)
+#endif
+
+#define READ_BUF_SIZE (16*1024)
+
+int get_stream_size(FILE *stream) {
+    int size;
+    fseek(stream, 0, SEEK_END);
+    size = ftell(stream);
+    fseek(stream, 0, SEEK_SET);
+    return size;
+}
+
+uint64_t get_block_device_size(int fd)
+{
+    uint64_t size = 0;
+    int ret;
+
+    ret = ioctl(fd, BLKGETSIZE64, &size);
+
+    if (ret)
+        return 0;
+
+    return size;
+}
+
+uint64_t get_file_size(int fd)
+{
+    struct stat buf;
+    int ret;
+    int64_t computed_size;
+
+    ret = fstat(fd, &buf);
+    if (ret)
+        return 0;
+
+    if (S_ISREG(buf.st_mode))
+        computed_size = buf.st_size;
+    else if (S_ISBLK(buf.st_mode))
+        computed_size = get_block_device_size(fd);
+    else
+        computed_size = 0;
+
+    return computed_size;
+}
+
+uint64_t get_file_size64(int fd)
+{
+    struct stat64 buf;
+    int ret;
+    uint64_t computed_size;
+
+    ret = fstat64(fd, &buf);
+    if (ret)
+        return 0;
+
+    if (S_ISREG(buf.st_mode))
+        computed_size = buf.st_size;
+    else if (S_ISBLK(buf.st_mode))
+        computed_size = get_block_device_size(fd);
+    else
+        computed_size = 0;
+
+    return computed_size;
+}
+
+
+char *strip(char *str)
+{
+    int n;
+
+    n = strspn(str, " \t");
+    str += n;
+    n = strcspn(str, " \t");
+    str[n] = '\0';
+
+    return str;
+}
+
+int wipe_block_device(int fd, int64_t len)
+{
+    uint64_t range[2];
+    int ret;
+
+    range[0] = 0;
+    range[1] = len;
+    ret = ioctl(fd, BLKSECDISCARD, &range);
+    if (ret < 0) {
+        range[0] = 0;
+        range[1] = len;
+        ret = ioctl(fd, BLKDISCARD, &range);
+        if (ret < 0) {
+            D(WARN, "Discard failed\n");
+            return 1;
+        } else {
+            D(WARN, "Wipe via secure discard failed, used discard instead\n");
+            return 0;
+        }
+    }
+
+    return 0;
+}
+
+int create_temp_file() {
+    char tempname[] = "/dev/fastboot_data_XXXXXX";
+    int fd;
+
+    fd = mkstemp(tempname);
+    if (fd < 0)
+        return -1;
+
+    unlink(tempname);
+
+    return fd;
+}
+
+ssize_t bulk_write(int bulk_in, const char *buf, size_t length)
+{
+    size_t count = 0;
+    ssize_t ret;
+
+    do {
+        ret = TEMP_FAILURE_RETRY(write(bulk_in, buf + count, length - count));
+        if (ret < 0) {
+            D(WARN, "[ bulk_write failed fd=%d length=%d errno=%d %s ]",
+                    bulk_in, length, errno, strerror(errno));
+            return -1;
+        } else {
+            count += ret;
+        }
+    } while (count < length);
+
+    D(VERBOSE, "[ bulk_write done fd=%d ]", bulk_in);
+    return count;
+}
+
+ssize_t bulk_read(int bulk_out, char *buf, size_t length)
+{
+    ssize_t ret;
+    size_t n = 0;
+
+    while (n < length) {
+        size_t to_read = (length - n > READ_BUF_SIZE) ? READ_BUF_SIZE : length - n;
+        ret = TEMP_FAILURE_RETRY(read(bulk_out, buf + n, to_read));
+        if (ret < 0) {
+            D(WARN, "[ bulk_read failed fd=%d length=%d errno=%d %s ]",
+                    bulk_out, length, errno, strerror(errno));
+            return ret;
+        }
+        n += ret;
+        if (ret < (ssize_t)to_read) {
+            D(VERBOSE, "bulk_read short read, ret=%zd to_read=%u n=%u length=%u",
+                    ret, to_read, n, length);
+            break;
+        }
+    }
+
+    return n;
+}
+
+#define NAP_TIME 200  // 200 ms between polls
+static int wait_for_property(const char *name, const char *desired_value, int maxwait)
+{
+    char value[PROPERTY_VALUE_MAX] = {'\0'};
+    int maxnaps = (maxwait * 1000) / NAP_TIME;
+
+    if (maxnaps < 1) {
+        maxnaps = 1;
+    }
+
+    while (maxnaps-- > 0) {
+        usleep(NAP_TIME * 1000);
+        if (property_get(name, value, NULL)) {
+            if (desired_value == NULL || strcmp(value, desired_value) == 0) {
+                return 0;
+            }
+        }
+    }
+    return -1; /* failure */
+}
+
+int service_start(const char *service_name)
+{
+    int result = 0;
+    char property_value[PROPERTY_VALUE_MAX];
+
+    property_get(service_name, property_value, "");
+    if (strcmp("running", property_value) != 0) {
+        D(INFO, "Starting %s", service_name);
+        property_set("ctl.start", service_name);
+        if (wait_for_property(service_name, "running", 5))
+            result = -1;
+    }
+
+    return result;
+}
+
+int service_stop(const char *service_name)
+{
+    int result = 0;
+
+    D(INFO, "Stopping MDNSD");
+    property_set("ctl.stop", service_name);
+    if (wait_for_property(service_name, "stopped", 5))
+        result = -1;
+
+    return result;
+}
+
+int ssh_server_start()
+{
+    return service_start("sshd");
+}
diff --git a/fastbootd/utils.h b/fastbootd/utils.h
new file mode 100644
index 0000000..3d98699
--- /dev/null
+++ b/fastbootd/utils.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009-2013, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef _FASTBOOT_UTLIS_H
+#define _FASTBOOT_UTILS_H
+
+#include <stdio.h>
+
+int get_stream_size(FILE *);
+
+char *strip(char *str);
+
+uint64_t get_file_size64(int fd);
+uint64_t get_file_size(int fd);
+uint64_t get_block_device_size(int fd);
+int wipe_block_device(int fd, int64_t len);
+int create_temp_file();
+ssize_t bulk_read(int bulk_out, char *buf, size_t length);
+ssize_t bulk_write(int bulk_in, const char *buf, size_t length);
+int service_start(const char *service_name);
+int service_stop(const char *service_name);
+int ssh_server_start();
+
+#define ROUND_TO_PAGE(address,pagesize) ((address + pagesize - 1) & (~(pagesize - 1)))
+
+#define ROUND_UP(number,size) (((number + size - 1) / size) * size)
+
+#endif
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 782ae99..790598a 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -3,12 +3,13 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= fs_mgr.c
+LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c
 
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 
 LOCAL_MODULE:= libfs_mgr
-LOCAL_STATIC_LIBRARIES := liblogwrap
+LOCAL_STATIC_LIBRARIES := liblogwrap libmincrypt libext4_utils_static
+LOCAL_C_INCLUDES += system/extras/ext4_utils
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 
 include $(BUILD_STATIC_LIBRARY)
@@ -28,7 +29,7 @@
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
 
-LOCAL_STATIC_LIBRARIES := libfs_mgr liblogwrap libcutils liblog libc
+LOCAL_STATIC_LIBRARIES := libfs_mgr liblogwrap libcutils liblog libc libmincrypt libext4_utils_static
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 4f11fbb..13b71ee 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -27,18 +27,35 @@
 #include <sys/wait.h>
 #include <libgen.h>
 #include <time.h>
+#include <sys/swap.h>
+/* XXX These need to be obtained from kernel headers. See b/9336527 */
+#define SWAP_FLAG_PREFER        0x8000
+#define SWAP_FLAG_PRIO_MASK     0x7fff
+#define SWAP_FLAG_PRIO_SHIFT    0
+#define SWAP_FLAG_DISCARD       0x10000
 
+#include <linux/loop.h>
 #include <private/android_filesystem_config.h>
 #include <cutils/partition_utils.h>
 #include <cutils/properties.h>
 #include <logwrap/logwrap.h>
 
+#include "mincrypt/rsa.h"
+#include "mincrypt/sha.h"
+#include "mincrypt/sha256.h"
+
 #include "fs_mgr_priv.h"
+#include "fs_mgr_priv_verity.h"
 
 #define KEY_LOC_PROP   "ro.crypto.keyfile.userdata"
 #define KEY_IN_FOOTER  "footer"
 
 #define E2FSCK_BIN      "/system/bin/e2fsck"
+#define MKSWAP_BIN      "/system/bin/mkswap"
+
+#define FSCK_LOG_FILE   "/dev/fscklogs/log"
+
+#define ZRAM_CONF_DEV   "/sys/block/zram0/disksize"
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
@@ -74,10 +91,23 @@
     { "voldmanaged=",MF_VOLDMANAGED},
     { "length=",     MF_LENGTH },
     { "recoveryonly",MF_RECOVERYONLY },
+    { "swapprio=",   MF_SWAPPRIO },
+    { "zramsize=",   MF_ZRAMSIZE },
+    { "verify",      MF_VERIFY },
+    { "noemulatedsd", MF_NOEMULATEDSD },
     { "defaults",    0 },
     { 0,             0 },
 };
 
+struct fs_mgr_flag_values {
+    char *key_loc;
+    long long part_length;
+    char *label;
+    int partnum;
+    int swap_prio;
+    unsigned int zram_size;
+};
+
 /*
  * gettime() - returns the time in seconds of the system's monotonic clock or
  * zero on error.
@@ -109,7 +139,7 @@
 }
 
 static int parse_flags(char *flags, struct flag_list *fl,
-                       char **key_loc, long long *part_length, char **label, int *partnum,
+                       struct fs_mgr_flag_values *flag_vals,
                        char *fs_options, int fs_options_len)
 {
     int f = 0;
@@ -117,21 +147,12 @@
     char *p;
     char *savep;
 
-    /* initialize key_loc to null, if we find an MF_CRYPT flag,
-     * then we'll set key_loc to the proper value */
-    if (key_loc) {
-        *key_loc = NULL;
-    }
-    /* initialize part_length to 0, if we find an MF_LENGTH flag,
-     * then we'll set part_length to the proper value */
-    if (part_length) {
-        *part_length = 0;
-    }
-    if (partnum) {
-        *partnum = -1;
-    }
-    if (label) {
-        *label = NULL;
+    /* initialize flag values.  If we find a relevant flag, we'll
+     * update the value */
+    if (flag_vals) {
+        memset(flag_vals, 0, sizeof(*flag_vals));
+        flag_vals->partnum = -1;
+        flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
     }
 
     /* initialize fs_options to the null string */
@@ -147,17 +168,17 @@
         for (i = 0; fl[i].name; i++) {
             if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
                 f |= fl[i].flag;
-                if ((fl[i].flag == MF_CRYPT) && key_loc) {
+                if ((fl[i].flag == MF_CRYPT) && flag_vals) {
                     /* The encryptable flag is followed by an = and the
                      * location of the keys.  Get it and return it.
                      */
-                    *key_loc = strdup(strchr(p, '=') + 1);
-                } else if ((fl[i].flag == MF_LENGTH) && part_length) {
+                    flag_vals->key_loc = strdup(strchr(p, '=') + 1);
+                } else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
                     /* The length flag is followed by an = and the
                      * size of the partition.  Get it and return it.
                      */
-                    *part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
-                } else if ((fl[i].flag == MF_VOLDMANAGED) && label && partnum) {
+                    flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
+                } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
                     /* The voldmanaged flag is followed by an = and the
                      * label, a colon and the partition number or the
                      * word "auto", e.g.
@@ -171,17 +192,21 @@
                     label_start = strchr(p, '=') + 1;
                     label_end = strchr(p, ':');
                     if (label_end) {
-                        *label = strndup(label_start,
-                                         (int) (label_end - label_start));
+                        flag_vals->label = strndup(label_start,
+                                                   (int) (label_end - label_start));
                         part_start = strchr(p, ':') + 1;
                         if (!strcmp(part_start, "auto")) {
-                            *partnum = -1;
+                            flag_vals->partnum = -1;
                         } else {
-                            *partnum = strtol(part_start, NULL, 0);
+                            flag_vals->partnum = strtol(part_start, NULL, 0);
                         }
                     } else {
                         ERROR("Warning: voldmanaged= flag malformed\n");
                     }
+                } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
+                    flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
+                } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
+                    flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0);
                 }
                 break;
             }
@@ -224,10 +249,7 @@
     char *save_ptr, *p;
     struct fstab *fstab = NULL;
     struct fstab_rec *recs;
-    char *key_loc;
-    long long part_length;
-    char *label;
-    int partnum;
+    struct fs_mgr_flag_values flag_vals;
 #define FS_OPTIONS_LEN 1024
     char tmp_fs_options[FS_OPTIONS_LEN];
 
@@ -315,8 +337,7 @@
             goto err;
         }
         tmp_fs_options[0] = '\0';
-        fstab->recs[cnt].flags = parse_flags(p, mount_flags,
-                                       NULL, NULL, NULL, NULL,
+        fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
                                        tmp_fs_options, FS_OPTIONS_LEN);
 
         /* fs_options are optional */
@@ -331,13 +352,13 @@
             goto err;
         }
         fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
-                                              &key_loc, &part_length,
-                                              &label, &partnum,
-                                              NULL, 0);
-        fstab->recs[cnt].key_loc = key_loc;
-        fstab->recs[cnt].length = part_length;
-        fstab->recs[cnt].label = label;
-        fstab->recs[cnt].partnum = partnum;
+                                                    &flag_vals, NULL, 0);
+        fstab->recs[cnt].key_loc = flag_vals.key_loc;
+        fstab->recs[cnt].length = flag_vals.part_length;
+        fstab->recs[cnt].label = flag_vals.label;
+        fstab->recs[cnt].partnum = flag_vals.partnum;
+        fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
+        fstab->recs[cnt].zram_size = flag_vals.zram_size;
         cnt++;
     }
     fclose(fstab_file);
@@ -356,6 +377,10 @@
 {
     int i;
 
+    if (!fstab) {
+        return;
+    }
+
     for (i = 0; i < fstab->num_entries; i++) {
         /* Free the pointers return by strdup(3) */
         free(fstab->recs[i].blk_device);
@@ -411,7 +436,8 @@
         INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);
 
         ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
-                                      &status, true, LOG_KLOG, true);
+                                      &status, true, LOG_KLOG | LOG_FILE,
+                                      true, FSCK_LOG_FILE);
 
         if (ret < 0) {
             /* No need to check for error in fork, we can't really handle it now */
@@ -433,6 +459,43 @@
     }
 }
 
+/*
+ * Mark the given block device as read-only, using the BLKROSET ioctl.
+ * Return 0 on success, and -1 on error.
+ */
+static void fs_set_blk_ro(const char *blockdev)
+{
+    int fd;
+    int ON = 1;
+
+    fd = open(blockdev, O_RDONLY);
+    if (fd < 0) {
+        // should never happen
+        return;
+    }
+
+    ioctl(fd, BLKROSET, &ON);
+    close(fd);
+}
+
+/*
+ * __mount(): wrapper around the mount() system call which also
+ * sets the underlying block device to read-only if the mount is read-only.
+ * See "man 2 mount" for return values.
+ */
+static int __mount(const char *source, const char *target,
+                   const char *filesystemtype, unsigned long mountflags,
+                   const void *data)
+{
+    int ret = mount(source, target, filesystemtype, mountflags, data);
+
+    if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
+        fs_set_blk_ro(source);
+    }
+
+    return ret;
+}
+
 static int fs_match(char *in1, char *in2)
 {
     char *n1;
@@ -470,8 +533,9 @@
             continue;
         }
 
-        /* Skip raw partition entries such as boot, recovery, etc */
-        if (!strcmp(fstab->recs[i].fs_type, "emmc") ||
+        /* Skip swap and raw partition entries such as boot, recovery, etc */
+        if (!strcmp(fstab->recs[i].fs_type, "swap") ||
+            !strcmp(fstab->recs[i].fs_type, "emmc") ||
             !strcmp(fstab->recs[i].fs_type, "mtd")) {
             continue;
         }
@@ -485,9 +549,17 @@
                      fstab->recs[i].mount_point);
         }
 
-        mret = mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point,
+        if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) {
+            if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
+                ERROR("Could not set up verified partition, skipping!");
+                continue;
+            }
+        }
+
+        mret = __mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point,
                      fstab->recs[i].fs_type, fstab->recs[i].flags,
                      fstab->recs[i].fs_options);
+
         if (!mret) {
             /* Success!  Go get the next one */
             continue;
@@ -543,8 +615,9 @@
         }
 
         /* We found our match */
-        /* If this is a raw partition, report an error */
-        if (!strcmp(fstab->recs[i].fs_type, "emmc") ||
+        /* If this swap or a raw partition, report an error */
+        if (!strcmp(fstab->recs[i].fs_type, "swap") ||
+            !strcmp(fstab->recs[i].fs_type, "emmc") ||
             !strcmp(fstab->recs[i].fs_type, "mtd")) {
             ERROR("Cannot mount filesystem of type %s on %s\n",
                   fstab->recs[i].fs_type, n_blk_device);
@@ -561,14 +634,21 @@
                      fstab->recs[i].mount_point);
         }
 
+        if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) {
+            if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
+                ERROR("Could not set up verified partition, skipping!");
+                continue;
+            }
+        }
+
         /* Now mount it where requested */
         if (tmp_mount_point) {
             m = tmp_mount_point;
         } else {
             m = fstab->recs[i].mount_point;
         }
-        if (mount(n_blk_device, m, fstab->recs[i].fs_type,
-                  fstab->recs[i].flags, fstab->recs[i].fs_options)) {
+        if (__mount(n_blk_device, m, fstab->recs[i].fs_type,
+                    fstab->recs[i].flags, fstab->recs[i].fs_options)) {
             ERROR("Cannot mount filesystem on %s at %s\n",
                     n_blk_device, m);
             goto out;
@@ -623,6 +703,83 @@
 
     return ret;
 }
+
+/* This must be called after mount_all, because the mkswap command needs to be
+ * available.
+ */
+int fs_mgr_swapon_all(struct fstab *fstab)
+{
+    int i = 0;
+    int flags = 0;
+    int err = 0;
+    int ret = 0;
+    int status;
+    char *mkswap_argv[2] = {
+        MKSWAP_BIN,
+        NULL
+    };
+
+    if (!fstab) {
+        return -1;
+    }
+
+    for (i = 0; i < fstab->num_entries; i++) {
+        /* Skip non-swap entries */
+        if (strcmp(fstab->recs[i].fs_type, "swap")) {
+            continue;
+        }
+
+        if (fstab->recs[i].zram_size > 0) {
+            /* A zram_size was specified, so we need to configure the
+             * device.  There is no point in having multiple zram devices
+             * on a system (all the memory comes from the same pool) so
+             * we can assume the device number is 0.
+             */
+            FILE *zram_fp;
+
+            zram_fp = fopen(ZRAM_CONF_DEV, "r+");
+            if (zram_fp == NULL) {
+                ERROR("Unable to open zram conf device " ZRAM_CONF_DEV);
+                ret = -1;
+                continue;
+            }
+            fprintf(zram_fp, "%d\n", fstab->recs[i].zram_size);
+            fclose(zram_fp);
+        }
+
+        if (fstab->recs[i].fs_mgr_flags & MF_WAIT) {
+            wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
+        }
+
+        /* Initialize the swap area */
+        mkswap_argv[1] = fstab->recs[i].blk_device;
+        err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv,
+                                      &status, true, LOG_KLOG, false, NULL);
+        if (err) {
+            ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device);
+            ret = -1;
+            continue;
+        }
+
+        /* If -1, then no priority was specified in fstab, so don't set
+         * SWAP_FLAG_PREFER or encode the priority */
+        if (fstab->recs[i].swap_prio >= 0) {
+            flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) &
+                    SWAP_FLAG_PRIO_MASK;
+            flags |= SWAP_FLAG_PREFER;
+        } else {
+            flags = 0;
+        }
+        err = swapon(fstab->recs[i].blk_device, flags);
+        if (err) {
+            ERROR("swapon failed for %s\n", fstab->recs[i].blk_device);
+            ret = -1;
+        }
+    }
+
+    return ret;
+}
+
 /*
  * key_loc must be at least PROPERTY_VALUE_MAX bytes long
  *
@@ -729,3 +886,7 @@
     return fstab->fs_mgr_flags & MF_CRYPT;
 }
 
+int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
+}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index f961b39..59ffd78 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -69,6 +69,17 @@
 #define MF_VOLDMANAGED  0x10
 #define MF_LENGTH       0x20
 #define MF_RECOVERYONLY 0x40
+#define MF_SWAPPRIO     0x80
+#define MF_ZRAMSIZE     0x100
+#define MF_VERIFY       0x200
+/*
+ * There is no emulated sdcard daemon running on /data/media on this device,
+ * so treat the physical SD card as the only external storage device,
+ * a la the Nexus One.
+ */
+#define MF_NOEMULATEDSD 0x400
+
+#define DM_BUF_SIZE 4096
 
 #endif /* __CORE_FS_MGR_PRIV_H */
 
diff --git a/include/cutils/zygote.h b/fs_mgr/fs_mgr_priv_verity.h
similarity index 63%
copy from include/cutils/zygote.h
copy to fs_mgr/fs_mgr_priv_verity.h
index a7480d3..6193784 100644
--- a/include/cutils/zygote.h
+++ b/fs_mgr/fs_mgr_priv_verity.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -14,18 +14,4 @@
  * limitations under the License.
  */
 
-#ifndef __CUTILS_ZYGOTE_H
-#define __CUTILS_ZYGOTE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
-int zygote_run(int argc, const char **argv);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CUTILS_ZYGOTE_H */
+int fs_mgr_setup_verity(struct fstab_rec *fstab);
\ No newline at end of file
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c
new file mode 100644
index 0000000..969eab2
--- /dev/null
+++ b/fs_mgr/fs_mgr_verity.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <libgen.h>
+#include <time.h>
+
+#include <private/android_filesystem_config.h>
+#include <logwrap/logwrap.h>
+
+#include "mincrypt/rsa.h"
+#include "mincrypt/sha.h"
+#include "mincrypt/sha256.h"
+
+#include "ext4_utils.h"
+#include "ext4.h"
+
+#include "fs_mgr_priv.h"
+#include "fs_mgr_priv_verity.h"
+
+#define VERITY_METADATA_SIZE 32768
+#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
+#define VERITY_TABLE_RSA_KEY "/verity_key"
+
+extern struct fs_info info;
+
+static RSAPublicKey *load_key(char *path)
+{
+    FILE *f;
+    RSAPublicKey *key;
+
+    key = malloc(sizeof(RSAPublicKey));
+    if (!key) {
+        ERROR("Can't malloc key\n");
+        return NULL;
+    }
+
+    f = fopen(path, "r");
+    if (!f) {
+        ERROR("Can't open '%s'\n", path);
+        free(key);
+        return NULL;
+    }
+
+    if (!fread(key, sizeof(*key), 1, f)) {
+        ERROR("Could not read key!");
+        fclose(f);
+        free(key);
+        return NULL;
+    }
+
+    if (key->len != RSANUMWORDS) {
+        ERROR("Invalid key length %d\n", key->len);
+        fclose(f);
+        free(key);
+        return NULL;
+    }
+
+    fclose(f);
+    return key;
+}
+
+static int verify_table(char *signature, char *table, int table_length)
+{
+    int fd;
+    RSAPublicKey *key;
+    uint8_t hash_buf[SHA_DIGEST_SIZE];
+    int retval = -1;
+
+    // Hash the table
+    SHA_hash((uint8_t*)table, table_length, hash_buf);
+
+    // Now get the public key from the keyfile
+    key = load_key(VERITY_TABLE_RSA_KEY);
+    if (!key) {
+        ERROR("Couldn't load verity keys");
+        goto out;
+    }
+
+    // verify the result
+    if (!RSA_verify(key,
+                    (uint8_t*) signature,
+                    RSANUMBYTES,
+                    (uint8_t*) hash_buf,
+                    SHA_DIGEST_SIZE)) {
+        ERROR("Couldn't verify table.");
+        goto out;
+    }
+
+    retval = 0;
+
+out:
+    free(key);
+    return retval;
+}
+
+static int get_target_device_size(char *blk_device, uint64_t *device_size)
+{
+    int data_device;
+    struct ext4_super_block sb;
+
+    data_device = open(blk_device, O_RDONLY);
+    if (data_device < 0) {
+        ERROR("Error opening block device (%s)", strerror(errno));
+        return -1;
+    }
+
+    if (lseek64(data_device, 1024, SEEK_SET) < 0) {
+        ERROR("Error seeking to superblock");
+        close(data_device);
+        return -1;
+    }
+
+    if (read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
+        ERROR("Error reading superblock");
+        close(data_device);
+        return -1;
+    }
+
+    ext4_parse_sb(&sb);
+    *device_size = info.len;
+
+    close(data_device);
+    return 0;
+}
+
+static int read_verity_metadata(char *block_device, char **signature, char **table)
+{
+    unsigned magic_number;
+    unsigned table_length;
+    uint64_t device_length;
+    int protocol_version;
+    FILE *device;
+    int retval = -1;
+
+    device = fopen(block_device, "r");
+    if (!device) {
+        ERROR("Could not open block device %s (%s).\n", block_device, strerror(errno));
+        goto out;
+    }
+
+    // find the start of the verity metadata
+    if (get_target_device_size(block_device, &device_length) < 0) {
+        ERROR("Could not get target device size.\n");
+        goto out;
+    }
+    if (fseek(device, device_length, SEEK_SET) < 0) {
+        ERROR("Could not seek to start of verity metadata block.\n");
+        goto out;
+    }
+
+    // check the magic number
+    if (!fread(&magic_number, sizeof(int), 1, device)) {
+        ERROR("Couldn't read magic number!\n");
+        goto out;
+    }
+    if (magic_number != VERITY_METADATA_MAGIC_NUMBER) {
+        ERROR("Couldn't find verity metadata at offset %llu!\n", device_length);
+        goto out;
+    }
+
+    // check the protocol version
+    if (!fread(&protocol_version, sizeof(int), 1, device)) {
+        ERROR("Couldn't read verity metadata protocol version!\n");
+        goto out;
+    }
+    if (protocol_version != 0) {
+        ERROR("Got unknown verity metadata protocol version %d!\n", protocol_version);
+        goto out;
+    }
+
+    // get the signature
+    *signature = (char*) malloc(RSANUMBYTES * sizeof(char));
+    if (!*signature) {
+        ERROR("Couldn't allocate memory for signature!\n");
+        goto out;
+    }
+    if (!fread(*signature, RSANUMBYTES, 1, device)) {
+        ERROR("Couldn't read signature from verity metadata!\n");
+        free(*signature);
+        goto out;
+    }
+
+    // get the size of the table
+    if (!fread(&table_length, sizeof(int), 1, device)) {
+        ERROR("Couldn't get the size of the verity table from metadata!\n");
+        free(*signature);
+        goto out;
+    }
+
+    // get the table + null terminator
+    table_length += 1;
+    *table = malloc(table_length);
+    if(!*table) {
+        ERROR("Couldn't allocate memory for verity table!\n");
+        goto out;
+    }
+    if (!fgets(*table, table_length, device)) {
+        ERROR("Couldn't read the verity table from metadata!\n");
+        free(*table);
+        free(*signature);
+        goto out;
+    }
+
+    retval = 0;
+
+out:
+    if (device)
+        fclose(device);
+    return retval;
+}
+
+static void verity_ioctl_init(struct dm_ioctl *io, char *name, unsigned flags)
+{
+    memset(io, 0, DM_BUF_SIZE);
+    io->data_size = DM_BUF_SIZE;
+    io->data_start = sizeof(struct dm_ioctl);
+    io->version[0] = 4;
+    io->version[1] = 0;
+    io->version[2] = 0;
+    io->flags = flags | DM_READONLY_FLAG;
+    if (name) {
+        strlcpy(io->name, name, sizeof(io->name));
+    }
+}
+
+static int create_verity_device(struct dm_ioctl *io, char *name, int fd)
+{
+    verity_ioctl_init(io, name, 1);
+    if (ioctl(fd, DM_DEV_CREATE, io)) {
+        ERROR("Error creating device mapping (%s)", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+static int get_verity_device_name(struct dm_ioctl *io, char *name, int fd, char **dev_name)
+{
+    verity_ioctl_init(io, name, 0);
+    if (ioctl(fd, DM_DEV_STATUS, io)) {
+        ERROR("Error fetching verity device number (%s)", strerror(errno));
+        return -1;
+    }
+    int dev_num = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
+    if (asprintf(dev_name, "/dev/block/dm-%u", dev_num) < 0) {
+        ERROR("Error getting verity block device name (%s)", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table)
+{
+    char *verity_params;
+    char *buffer = (char*) io;
+    uint64_t device_size = 0;
+
+    if (get_target_device_size(blockdev, &device_size) < 0) {
+        return -1;
+    }
+
+    verity_ioctl_init(io, name, DM_STATUS_TABLE_FLAG);
+
+    struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
+
+    // set tgt arguments here
+    io->target_count = 1;
+    tgt->status=0;
+    tgt->sector_start=0;
+    tgt->length=device_size/512;
+    strcpy(tgt->target_type, "verity");
+
+    // build the verity params here
+    verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
+    if (sprintf(verity_params, "%s", table) < 0) {
+        return -1;
+    }
+
+    // set next target boundary
+    verity_params += strlen(verity_params) + 1;
+    verity_params = (char*) (((unsigned long)verity_params + 7) & ~8);
+    tgt->next = verity_params - buffer;
+
+    // send the ioctl to load the verity table
+    if (ioctl(fd, DM_TABLE_LOAD, io)) {
+        ERROR("Error loading verity table (%s)", strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int resume_verity_table(struct dm_ioctl *io, char *name, int fd)
+{
+    verity_ioctl_init(io, name, 0);
+    if (ioctl(fd, DM_DEV_SUSPEND, io)) {
+        ERROR("Error activating verity device (%s)", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+static int test_access(char *device) {
+    int tries = 25;
+    while (tries--) {
+        if (!access(device, F_OK) || errno != ENOENT) {
+            return 0;
+        }
+        usleep(40 * 1000);
+    }
+    return -1;
+}
+
+int fs_mgr_setup_verity(struct fstab_rec *fstab) {
+
+    int retval = -1;
+
+    char *verity_blk_name;
+    char *verity_table;
+    char *verity_table_signature;
+
+    char buffer[DM_BUF_SIZE];
+    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
+    char *mount_point = basename(fstab->mount_point);
+
+    // set the dm_ioctl flags
+    io->flags |= 1;
+    io->target_count = 1;
+
+    // get the device mapper fd
+    int fd;
+    if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
+        ERROR("Error opening device mapper (%s)", strerror(errno));
+        return retval;
+    }
+
+    // create the device
+    if (create_verity_device(io, mount_point, fd) < 0) {
+        ERROR("Couldn't create verity device!");
+        goto out;
+    }
+
+    // get the name of the device file
+    if (get_verity_device_name(io, mount_point, fd, &verity_blk_name) < 0) {
+        ERROR("Couldn't get verity device number!");
+        goto out;
+    }
+
+    // read the verity block at the end of the block device
+    if (read_verity_metadata(fstab->blk_device,
+                                    &verity_table_signature,
+                                    &verity_table) < 0) {
+        goto out;
+    }
+
+    // verify the signature on the table
+    if (verify_table(verity_table_signature,
+                            verity_table,
+                            strlen(verity_table)) < 0) {
+        goto out;
+    }
+
+    // load the verity mapping table
+    if (load_verity_table(io, mount_point, fstab->blk_device, fd, verity_table) < 0) {
+        goto out;
+    }
+
+    // activate the device
+    if (resume_verity_table(io, mount_point, fd) < 0) {
+        goto out;
+    }
+
+    // assign the new verity block device as the block device
+    free(fstab->blk_device);
+    fstab->blk_device = verity_blk_name;
+
+    // make sure we've set everything up properly
+    if (test_access(fstab->blk_device) < 0) {
+        goto out;
+    }
+
+    retval = 0;
+
+out:
+    close(fd);
+    return retval;
+}
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 05bcc1b..0f90c32 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -17,6 +17,9 @@
 #ifndef __CORE_FS_MGR_H
 #define __CORE_FS_MGR_H
 
+#include <stdint.h>
+#include <linux/dm-ioctl.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -35,9 +38,12 @@
     char *fs_options;
     int fs_mgr_flags;
     char *key_loc;
+    char *verity_loc;
     long long length;
     char *label;
     int partnum;
+    int swap_prio;
+    unsigned int zram_size;
 };
 
 struct fstab *fs_mgr_read_fstab(const char *fstab_path);
@@ -56,6 +62,8 @@
 int fs_mgr_is_voldmanaged(struct fstab_rec *fstab);
 int fs_mgr_is_nonremovable(struct fstab_rec *fstab);
 int fs_mgr_is_encryptable(struct fstab_rec *fstab);
+int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab);
+int fs_mgr_swapon_all(struct fstab *fstab);
 #ifdef __cplusplus
 }
 #endif
diff --git a/healthd/Android.mk b/healthd/Android.mk
new file mode 100644
index 0000000..473d375
--- /dev/null
+++ b/healthd/Android.mk
@@ -0,0 +1,30 @@
+# Copyright 2013 The Android Open Source Project
+
+ifneq ($(BUILD_TINY_ANDROID),true)
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := healthd_board_default.cpp
+LOCAL_MODULE := libhealthd.default
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	healthd.cpp \
+	BatteryMonitor.cpp \
+	BatteryPropertiesRegistrar.cpp
+
+LOCAL_MODULE := healthd
+LOCAL_MODULE_TAGS := optional
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
+LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
+
+LOCAL_STATIC_LIBRARIES :=  libbatteryservice libbinder libz libutils libstdc++ libcutils liblog libm libc
+LOCAL_HAL_STATIC_LIBRARIES := libhealthd
+
+include $(BUILD_EXECUTABLE)
+
+endif
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
new file mode 100644
index 0000000..688c7ff
--- /dev/null
+++ b/healthd/BatteryMonitor.cpp
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define LOG_TAG "healthd"
+
+#include "healthd.h"
+#include "BatteryMonitor.h"
+#include "BatteryPropertiesRegistrar.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <batteryservice/BatteryService.h>
+#include <cutils/klog.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#define POWER_SUPPLY_SUBSYSTEM "power_supply"
+#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM
+
+namespace android {
+
+struct sysfsStringEnumMap {
+    char* s;
+    int val;
+};
+
+static int mapSysfsString(const char* str,
+                          struct sysfsStringEnumMap map[]) {
+    for (int i = 0; map[i].s; i++)
+        if (!strcmp(str, map[i].s))
+            return map[i].val;
+
+    return -1;
+}
+
+int BatteryMonitor::getBatteryStatus(const char* status) {
+    int ret;
+    struct sysfsStringEnumMap batteryStatusMap[] = {
+        { "Unknown", BATTERY_STATUS_UNKNOWN },
+        { "Charging", BATTERY_STATUS_CHARGING },
+        { "Discharging", BATTERY_STATUS_DISCHARGING },
+        { "Not charging", BATTERY_STATUS_NOT_CHARGING },
+        { "Full", BATTERY_STATUS_FULL },
+        { NULL, 0 },
+    };
+
+    ret = mapSysfsString(status, batteryStatusMap);
+    if (ret < 0) {
+        KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
+        ret = BATTERY_STATUS_UNKNOWN;
+    }
+
+    return ret;
+}
+
+int BatteryMonitor::getBatteryHealth(const char* status) {
+    int ret;
+    struct sysfsStringEnumMap batteryHealthMap[] = {
+        { "Unknown", BATTERY_HEALTH_UNKNOWN },
+        { "Good", BATTERY_HEALTH_GOOD },
+        { "Overheat", BATTERY_HEALTH_OVERHEAT },
+        { "Dead", BATTERY_HEALTH_DEAD },
+        { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE },
+        { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE },
+        { "Cold", BATTERY_HEALTH_COLD },
+        { NULL, 0 },
+    };
+
+    ret = mapSysfsString(status, batteryHealthMap);
+    if (ret < 0) {
+        KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
+        ret = BATTERY_HEALTH_UNKNOWN;
+    }
+
+    return ret;
+}
+
+int BatteryMonitor::readFromFile(const String8& path, char* buf, size_t size) {
+    char *cp = NULL;
+
+    if (path.isEmpty())
+        return -1;
+    int fd = open(path.string(), O_RDONLY, 0);
+    if (fd == -1) {
+        KLOG_ERROR(LOG_TAG, "Could not open '%s'\n", path.string());
+        return -1;
+    }
+
+    ssize_t count = TEMP_FAILURE_RETRY(read(fd, buf, size));
+    if (count > 0)
+            cp = (char *)memrchr(buf, '\n', count);
+
+    if (cp)
+        *cp = '\0';
+    else
+        buf[0] = '\0';
+
+    close(fd);
+    return count;
+}
+
+BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
+    const int SIZE = 128;
+    char buf[SIZE];
+    int length = readFromFile(path, buf, SIZE);
+    BatteryMonitor::PowerSupplyType ret;
+    struct sysfsStringEnumMap supplyTypeMap[] = {
+            { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
+            { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
+            { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC },
+            { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC },
+            { "USB", ANDROID_POWER_SUPPLY_TYPE_USB },
+            { "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC },
+            { "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC },
+            { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC },
+            { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
+            { NULL, 0 },
+    };
+
+    if (length <= 0)
+        return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
+
+    ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf, supplyTypeMap);
+    if (ret < 0)
+        ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
+
+    return ret;
+}
+
+bool BatteryMonitor::getBooleanField(const String8& path) {
+    const int SIZE = 16;
+    char buf[SIZE];
+
+    bool value = false;
+    if (readFromFile(path, buf, SIZE) > 0) {
+        if (buf[0] != '0') {
+            value = true;
+        }
+    }
+
+    return value;
+}
+
+int BatteryMonitor::getIntField(const String8& path) {
+    const int SIZE = 128;
+    char buf[SIZE];
+
+    int value = 0;
+    if (readFromFile(path, buf, SIZE) > 0) {
+        value = strtol(buf, NULL, 0);
+    }
+    return value;
+}
+
+bool BatteryMonitor::update(void) {
+    struct BatteryProperties props;
+    bool logthis;
+
+    props.chargerAcOnline = false;
+    props.chargerUsbOnline = false;
+    props.chargerWirelessOnline = false;
+    props.batteryStatus = BATTERY_STATUS_UNKNOWN;
+    props.batteryHealth = BATTERY_HEALTH_UNKNOWN;
+    props.batteryCurrentNow = INT_MIN;
+    props.batteryChargeCounter = INT_MIN;
+
+    if (!mHealthdConfig->batteryPresentPath.isEmpty())
+        props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
+    else
+        props.batteryPresent = true;
+
+    props.batteryLevel = getIntField(mHealthdConfig->batteryCapacityPath);
+    props.batteryVoltage = getIntField(mHealthdConfig->batteryVoltagePath) / 1000;
+
+    if (!mHealthdConfig->batteryCurrentNowPath.isEmpty())
+        props.batteryCurrentNow = getIntField(mHealthdConfig->batteryCurrentNowPath);
+
+    if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
+        props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);
+
+    props.batteryTemperature = getIntField(mHealthdConfig->batteryTemperaturePath);
+
+    const int SIZE = 128;
+    char buf[SIZE];
+    String8 btech;
+
+    if (readFromFile(mHealthdConfig->batteryStatusPath, buf, SIZE) > 0)
+        props.batteryStatus = getBatteryStatus(buf);
+
+    if (readFromFile(mHealthdConfig->batteryHealthPath, buf, SIZE) > 0)
+        props.batteryHealth = getBatteryHealth(buf);
+
+    if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0)
+        props.batteryTechnology = String8(buf);
+
+    unsigned int i;
+
+    for (i = 0; i < mChargerNames.size(); i++) {
+        String8 path;
+        path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
+                          mChargerNames[i].string());
+
+        if (readFromFile(path, buf, SIZE) > 0) {
+            if (buf[0] != '0') {
+                path.clear();
+                path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH,
+                                  mChargerNames[i].string());
+                switch(readPowerSupplyType(path)) {
+                case ANDROID_POWER_SUPPLY_TYPE_AC:
+                    props.chargerAcOnline = true;
+                    break;
+                case ANDROID_POWER_SUPPLY_TYPE_USB:
+                    props.chargerUsbOnline = true;
+                    break;
+                case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+                    props.chargerWirelessOnline = true;
+                    break;
+                default:
+                    KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n",
+                                 mChargerNames[i].string());
+                }
+            }
+        }
+    }
+
+    logthis = !healthd_board_battery_update(&props);
+
+    if (logthis) {
+        char dmesgline[256];
+        snprintf(dmesgline, sizeof(dmesgline),
+                 "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
+                 props.batteryLevel, props.batteryVoltage,
+                 props.batteryTemperature < 0 ? "-" : "",
+                 abs(props.batteryTemperature / 10),
+                 abs(props.batteryTemperature % 10), props.batteryHealth,
+                 props.batteryStatus);
+
+        if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+            char b[20];
+
+            snprintf(b, sizeof(b), " c=%d", props.batteryCurrentNow / 1000);
+            strlcat(dmesgline, b, sizeof(dmesgline));
+        }
+
+        KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline,
+                  props.chargerAcOnline ? "a" : "",
+                  props.chargerUsbOnline ? "u" : "",
+                  props.chargerWirelessOnline ? "w" : "");
+    }
+
+    if (mBatteryPropertiesRegistrar != NULL)
+        mBatteryPropertiesRegistrar->notifyListeners(props);
+
+    return props.chargerAcOnline | props.chargerUsbOnline |
+            props.chargerWirelessOnline;
+}
+
+void BatteryMonitor::init(struct healthd_config *hc, bool nosvcmgr) {
+    String8 path;
+
+    mHealthdConfig = hc;
+    DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);
+    if (dir == NULL) {
+        KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
+    } else {
+        struct dirent* entry;
+
+        while ((entry = readdir(dir))) {
+            const char* name = entry->d_name;
+
+            if (!strcmp(name, ".") || !strcmp(name, ".."))
+                continue;
+
+            char buf[20];
+            // Look for "type" file in each subdirectory
+            path.clear();
+            path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
+            switch(readPowerSupplyType(path)) {
+            case ANDROID_POWER_SUPPLY_TYPE_AC:
+            case ANDROID_POWER_SUPPLY_TYPE_USB:
+            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
+                path.clear();
+                path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name);
+                if (access(path.string(), R_OK) == 0)
+                    mChargerNames.add(String8(name));
+                break;
+
+            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
+                if (mHealthdConfig->batteryStatusPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH,
+                                      name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryStatusPath = path;
+                }
+
+                if (mHealthdConfig->batteryHealthPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH,
+                                      name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryHealthPath = path;
+                }
+
+                if (mHealthdConfig->batteryPresentPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH,
+                                      name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryPresentPath = path;
+                }
+
+                if (mHealthdConfig->batteryCapacityPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH,
+                                      name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryCapacityPath = path;
+                }
+
+                if (mHealthdConfig->batteryVoltagePath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/voltage_now",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0) {
+                        mHealthdConfig->batteryVoltagePath = path;
+                    } else {
+                        path.clear();
+                        path.appendFormat("%s/%s/batt_vol",
+                                          POWER_SUPPLY_SYSFS_PATH, name);
+                        if (access(path, R_OK) == 0)
+                            mHealthdConfig->batteryVoltagePath = path;
+                    }
+                }
+
+                if (mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/current_now",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryCurrentNowPath = path;
+                }
+
+                if (mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/charge_counter",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryChargeCounterPath = path;
+                }
+
+                if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH,
+                                      name);
+                    if (access(path, R_OK) == 0) {
+                        mHealthdConfig->batteryTemperaturePath = path;
+                    } else {
+                        path.clear();
+                        path.appendFormat("%s/%s/batt_temp",
+                                          POWER_SUPPLY_SYSFS_PATH, name);
+                        if (access(path, R_OK) == 0)
+                            mHealthdConfig->batteryTemperaturePath = path;
+                    }
+                }
+
+                if (mHealthdConfig->batteryTechnologyPath.isEmpty()) {
+                    path.clear();
+                    path.appendFormat("%s/%s/technology",
+                                      POWER_SUPPLY_SYSFS_PATH, name);
+                    if (access(path, R_OK) == 0)
+                        mHealthdConfig->batteryTechnologyPath = path;
+                }
+
+                break;
+
+            case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN:
+                break;
+            }
+        }
+        closedir(dir);
+    }
+
+    if (!mChargerNames.size())
+        KLOG_ERROR(LOG_TAG, "No charger supplies found\n");
+    if (mHealthdConfig->batteryStatusPath.isEmpty())
+        KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
+    if (mHealthdConfig->batteryHealthPath.isEmpty())
+        KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n");
+    if (mHealthdConfig->batteryPresentPath.isEmpty())
+        KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n");
+    if (mHealthdConfig->batteryCapacityPath.isEmpty())
+        KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n");
+    if (mHealthdConfig->batteryVoltagePath.isEmpty())
+        KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n");
+    if (mHealthdConfig->batteryTemperaturePath.isEmpty())
+        KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n");
+    if (mHealthdConfig->batteryTechnologyPath.isEmpty())
+        KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n");
+
+    if (nosvcmgr == false) {
+            mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this);
+            mBatteryPropertiesRegistrar->publish();
+    }
+}
+
+}; // namespace android
diff --git a/healthd/BatteryMonitor.h b/healthd/BatteryMonitor.h
new file mode 100644
index 0000000..ba291af
--- /dev/null
+++ b/healthd/BatteryMonitor.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef HEALTHD_BATTERYMONITOR_H
+#define HEALTHD_BATTERYMONITOR_H
+
+#include <binder/IInterface.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include "healthd.h"
+#include "BatteryPropertiesRegistrar.h"
+
+namespace android {
+
+class BatteryPropertiesRegistrar;
+
+class BatteryMonitor {
+  public:
+
+    enum PowerSupplyType {
+        ANDROID_POWER_SUPPLY_TYPE_UNKNOWN = 0,
+        ANDROID_POWER_SUPPLY_TYPE_AC,
+        ANDROID_POWER_SUPPLY_TYPE_USB,
+        ANDROID_POWER_SUPPLY_TYPE_WIRELESS,
+        ANDROID_POWER_SUPPLY_TYPE_BATTERY
+    };
+
+    void init(struct healthd_config *hc, bool nosvcmgr);
+    bool update(void);
+
+  private:
+    struct healthd_config *mHealthdConfig;
+    Vector<String8> mChargerNames;
+
+    sp<BatteryPropertiesRegistrar> mBatteryPropertiesRegistrar;
+
+    int getBatteryStatus(const char* status);
+    int getBatteryHealth(const char* status);
+    int readFromFile(const String8& path, char* buf, size_t size);
+    PowerSupplyType readPowerSupplyType(const String8& path);
+    bool getBooleanField(const String8& path);
+    int getIntField(const String8& path);
+};
+
+}; // namespace android
+
+#endif // HEALTHD_BATTERY_MONTIOR_H
diff --git a/healthd/BatteryPropertiesRegistrar.cpp b/healthd/BatteryPropertiesRegistrar.cpp
new file mode 100644
index 0000000..6a33ad8
--- /dev/null
+++ b/healthd/BatteryPropertiesRegistrar.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include "BatteryPropertiesRegistrar.h"
+#include <batteryservice/BatteryService.h>
+#include <batteryservice/IBatteryPropertiesListener.h>
+#include <batteryservice/IBatteryPropertiesRegistrar.h>
+#include <binder/IServiceManager.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/String16.h>
+
+namespace android {
+
+BatteryPropertiesRegistrar::BatteryPropertiesRegistrar(BatteryMonitor* monitor) {
+    mBatteryMonitor = monitor;
+}
+
+void BatteryPropertiesRegistrar::publish() {
+    defaultServiceManager()->addService(String16("batterypropreg"), this);
+}
+
+void BatteryPropertiesRegistrar::notifyListeners(struct BatteryProperties props) {
+    Mutex::Autolock _l(mRegistrationLock);
+    for (size_t i = 0; i < mListeners.size(); i++) {
+        mListeners[i]->batteryPropertiesChanged(props);
+    }
+}
+
+void BatteryPropertiesRegistrar::registerListener(const sp<IBatteryPropertiesListener>& listener) {
+    {
+        Mutex::Autolock _l(mRegistrationLock);
+        // check whether this is a duplicate
+        for (size_t i = 0; i < mListeners.size(); i++) {
+            if (mListeners[i]->asBinder() == listener->asBinder()) {
+                return;
+            }
+        }
+
+        mListeners.add(listener);
+        listener->asBinder()->linkToDeath(this);
+    }
+    mBatteryMonitor->update();
+}
+
+void BatteryPropertiesRegistrar::unregisterListener(const sp<IBatteryPropertiesListener>& listener) {
+    Mutex::Autolock _l(mRegistrationLock);
+    for (size_t i = 0; i < mListeners.size(); i++) {
+        if (mListeners[i]->asBinder() == listener->asBinder()) {
+            mListeners[i]->asBinder()->unlinkToDeath(this);
+            mListeners.removeAt(i);
+            break;
+        }
+    }
+}
+
+void BatteryPropertiesRegistrar::binderDied(const wp<IBinder>& who) {
+    Mutex::Autolock _l(mRegistrationLock);
+
+    for (size_t i = 0; i < mListeners.size(); i++) {
+        if (mListeners[i]->asBinder() == who) {
+            mListeners.removeAt(i);
+            break;
+        }
+    }
+}
+
+}  // namespace android
diff --git a/healthd/BatteryPropertiesRegistrar.h b/healthd/BatteryPropertiesRegistrar.h
new file mode 100644
index 0000000..793ddad
--- /dev/null
+++ b/healthd/BatteryPropertiesRegistrar.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef HEALTHD_BATTERYPROPERTIES_REGISTRAR_H
+#define HEALTHD_BATTERYPROPERTIES_REGISTRAR_H
+
+#include "BatteryMonitor.h"
+
+#include <binder/IBinder.h>
+#include <utils/Mutex.h>
+#include <utils/Vector.h>
+#include <batteryservice/BatteryService.h>
+#include <batteryservice/IBatteryPropertiesListener.h>
+#include <batteryservice/IBatteryPropertiesRegistrar.h>
+
+namespace android {
+
+class BatteryMonitor;
+
+class BatteryPropertiesRegistrar : public BnBatteryPropertiesRegistrar,
+                                   public IBinder::DeathRecipient {
+public:
+    BatteryPropertiesRegistrar(BatteryMonitor* monitor);
+    void publish();
+    void notifyListeners(struct BatteryProperties props);
+
+private:
+    BatteryMonitor* mBatteryMonitor;
+    Mutex mRegistrationLock;
+    Vector<sp<IBatteryPropertiesListener> > mListeners;
+
+    void registerListener(const sp<IBatteryPropertiesListener>& listener);
+    void unregisterListener(const sp<IBatteryPropertiesListener>& listener);
+    void binderDied(const wp<IBinder>& who);
+};
+
+};  // namespace android
+
+#endif // HEALTHD_BATTERYPROPERTIES_REGISTRAR_H
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
new file mode 100644
index 0000000..9b84c3e
--- /dev/null
+++ b/healthd/healthd.cpp
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define LOG_TAG "healthd"
+#define KLOG_LEVEL 6
+
+#include "healthd.h"
+#include "BatteryMonitor.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <batteryservice/BatteryService.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <cutils/klog.h>
+#include <cutils/uevent.h>
+#include <sys/epoll.h>
+#include <sys/timerfd.h>
+
+using namespace android;
+
+// Periodic chores intervals in seconds
+#define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
+#define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10)
+
+static struct healthd_config healthd_config = {
+    .periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST,
+    .periodic_chores_interval_slow = DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW,
+    .batteryStatusPath = String8(String8::kEmptyString),
+    .batteryHealthPath = String8(String8::kEmptyString),
+    .batteryPresentPath = String8(String8::kEmptyString),
+    .batteryCapacityPath = String8(String8::kEmptyString),
+    .batteryVoltagePath = String8(String8::kEmptyString),
+    .batteryTemperaturePath = String8(String8::kEmptyString),
+    .batteryTechnologyPath = String8(String8::kEmptyString),
+    .batteryCurrentNowPath = String8(String8::kEmptyString),
+    .batteryChargeCounterPath = String8(String8::kEmptyString),
+};
+
+#define POWER_SUPPLY_SUBSYSTEM "power_supply"
+
+// epoll events: uevent, wakealarm, binder
+#define MAX_EPOLL_EVENTS 3
+static int uevent_fd;
+static int wakealarm_fd;
+static int binder_fd;
+
+// -1 for no epoll timeout
+static int awake_poll_interval = -1;
+
+static int wakealarm_wake_interval = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST;
+
+static BatteryMonitor* gBatteryMonitor;
+
+static bool nosvcmgr;
+
+static void wakealarm_set_interval(int interval) {
+    struct itimerspec itval;
+
+    if (wakealarm_fd == -1)
+            return;
+
+    wakealarm_wake_interval = interval;
+
+    if (interval == -1)
+        interval = 0;
+
+    itval.it_interval.tv_sec = interval;
+    itval.it_interval.tv_nsec = 0;
+    itval.it_value.tv_sec = interval;
+    itval.it_value.tv_nsec = 0;
+
+    if (timerfd_settime(wakealarm_fd, 0, &itval, NULL) == -1)
+        KLOG_ERROR(LOG_TAG, "wakealarm_set_interval: timerfd_settime failed\n");
+}
+
+static void battery_update(void) {
+    // Fast wake interval when on charger (watch for overheat);
+    // slow wake interval when on battery (watch for drained battery).
+
+   int new_wake_interval = gBatteryMonitor->update() ?
+       healthd_config.periodic_chores_interval_fast :
+           healthd_config.periodic_chores_interval_slow;
+
+    if (new_wake_interval != wakealarm_wake_interval)
+            wakealarm_set_interval(new_wake_interval);
+
+    // During awake periods poll at fast rate.  If wake alarm is set at fast
+    // rate then just use the alarm; if wake alarm is set at slow rate then
+    // poll at fast rate while awake and let alarm wake up at slow rate when
+    // asleep.
+
+    if (healthd_config.periodic_chores_interval_fast == -1)
+        awake_poll_interval = -1;
+    else
+        awake_poll_interval =
+            new_wake_interval == healthd_config.periodic_chores_interval_fast ?
+                -1 : healthd_config.periodic_chores_interval_fast * 1000;
+}
+
+static void periodic_chores() {
+    battery_update();
+}
+
+static void uevent_init(void) {
+    uevent_fd = uevent_open_socket(64*1024, true);
+
+    if (uevent_fd >= 0)
+        fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
+    else
+        KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n");
+}
+
+#define UEVENT_MSG_LEN 1024
+static void uevent_event(void) {
+    char msg[UEVENT_MSG_LEN+2];
+    char *cp;
+    int n;
+
+    n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);
+    if (n <= 0)
+        return;
+    if (n >= UEVENT_MSG_LEN)   /* overflow -- discard */
+        return;
+
+    msg[n] = '\0';
+    msg[n+1] = '\0';
+    cp = msg;
+
+    while (*cp) {
+        if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {
+            battery_update();
+            break;
+        }
+
+        /* advance to after the next \0 */
+        while (*cp++)
+            ;
+    }
+}
+
+static void wakealarm_init(void) {
+    wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK);
+    if (wakealarm_fd == -1) {
+        KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n");
+        return;
+    }
+
+    wakealarm_set_interval(healthd_config.periodic_chores_interval_fast);
+}
+
+static void wakealarm_event(void) {
+    unsigned long long wakeups;
+
+    if (read(wakealarm_fd, &wakeups, sizeof(wakeups)) == -1) {
+        KLOG_ERROR(LOG_TAG, "wakealarm_event: read wakealarm_fd failed\n");
+        return;
+    }
+
+    periodic_chores();
+}
+
+static void binder_init(void) {
+    ProcessState::self()->setThreadPoolMaxThreadCount(0);
+    IPCThreadState::self()->disableBackgroundScheduling(true);
+    IPCThreadState::self()->setupPolling(&binder_fd);
+}
+
+static void binder_event(void) {
+    IPCThreadState::self()->handlePolledCommands();
+}
+
+static void healthd_mainloop(void) {
+    struct epoll_event ev;
+    int epollfd;
+    int maxevents = 0;
+
+    epollfd = epoll_create(MAX_EPOLL_EVENTS);
+    if (epollfd == -1) {
+        KLOG_ERROR(LOG_TAG,
+                   "healthd_mainloop: epoll_create failed; errno=%d\n",
+                   errno);
+        return;
+    }
+
+    if (uevent_fd >= 0) {
+        ev.events = EPOLLIN | EPOLLWAKEUP;
+        ev.data.ptr = (void *)uevent_event;
+        if (epoll_ctl(epollfd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1)
+            KLOG_ERROR(LOG_TAG,
+                       "healthd_mainloop: epoll_ctl for uevent_fd failed; errno=%d\n",
+                       errno);
+        else
+            maxevents++;
+    }
+
+    if (wakealarm_fd >= 0) {
+        ev.events = EPOLLIN | EPOLLWAKEUP;
+        ev.data.ptr = (void *)wakealarm_event;
+        if (epoll_ctl(epollfd, EPOLL_CTL_ADD, wakealarm_fd, &ev) == -1)
+            KLOG_ERROR(LOG_TAG,
+                       "healthd_mainloop: epoll_ctl for wakealarm_fd failed; errno=%d\n",
+                       errno);
+        else
+            maxevents++;
+   }
+
+    if (binder_fd >= 0) {
+        ev.events = EPOLLIN | EPOLLWAKEUP;
+        ev.data.ptr= (void *)binder_event;
+        if (epoll_ctl(epollfd, EPOLL_CTL_ADD, binder_fd, &ev) == -1)
+            KLOG_ERROR(LOG_TAG,
+                       "healthd_mainloop: epoll_ctl for binder_fd failed; errno=%d\n",
+                       errno);
+        else
+            maxevents++;
+   }
+
+    while (1) {
+        struct epoll_event events[maxevents];
+        int nevents;
+
+        IPCThreadState::self()->flushCommands();
+        nevents = epoll_wait(epollfd, events, maxevents, awake_poll_interval);
+
+        if (nevents == -1) {
+            if (errno == EINTR)
+                continue;
+            KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");
+            break;
+        }
+
+        for (int n = 0; n < nevents; ++n) {
+            if (events[n].data.ptr)
+                (*(void (*)())events[n].data.ptr)();
+        }
+
+        if (!nevents)
+            periodic_chores();
+    }
+
+    return;
+}
+
+int main(int argc, char **argv) {
+    int ch;
+
+    klog_set_level(KLOG_LEVEL);
+
+    while ((ch = getopt(argc, argv, "n")) != -1) {
+        switch (ch) {
+        case 'n':
+            nosvcmgr = true;
+            break;
+        case '?':
+        default:
+            KLOG_WARNING(LOG_TAG, "Unrecognized healthd option: %c\n", ch);
+        }
+    }
+
+    healthd_board_init(&healthd_config);
+    wakealarm_init();
+    uevent_init();
+    binder_init();
+    gBatteryMonitor = new BatteryMonitor();
+    gBatteryMonitor->init(&healthd_config, nosvcmgr);
+
+    healthd_mainloop();
+    return 0;
+}
diff --git a/healthd/healthd.h b/healthd/healthd.h
new file mode 100644
index 0000000..5374fb1
--- /dev/null
+++ b/healthd/healthd.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _HEALTHD_H_
+#define _HEALTHD_H_
+
+#include <batteryservice/BatteryService.h>
+#include <utils/String8.h>
+
+// periodic_chores_interval_fast, periodic_chores_interval_slow: intervals at
+// which healthd wakes up to poll health state and perform periodic chores,
+// in units of seconds:
+//
+//    periodic_chores_interval_fast is used while the device is not in
+//    suspend, or in suspend and connected to a charger (to watch for battery
+//    overheat due to charging).  The default value is 60 (1 minute).  Value
+//    -1 turns off periodic chores (and wakeups) in these conditions.
+//
+//    periodic_chores_interval_slow is used when the device is in suspend and
+//    not connected to a charger (to watch for a battery drained to zero
+//    remaining capacity).  The default value is 600 (10 minutes).  Value -1
+//    tuns off periodic chores (and wakeups) in these conditions.
+//
+// power_supply sysfs attribute file paths.  Set these to specific paths
+// to use for the associated battery parameters.  healthd will search for
+// appropriate power_supply attribute files to use for any paths left empty:
+//
+//    batteryStatusPath: charging status (POWER_SUPPLY_PROP_STATUS)
+//    batteryHealthPath: battery health (POWER_SUPPLY_PROP_HEALTH)
+//    batteryPresentPath: battery present (POWER_SUPPLY_PROP_PRESENT)
+//    batteryCapacityPath: remaining capacity (POWER_SUPPLY_PROP_CAPACITY)
+//    batteryVoltagePath: battery voltage (POWER_SUPPLY_PROP_VOLTAGE_NOW)
+//    batteryTemperaturePath: battery temperature (POWER_SUPPLY_PROP_TEMP)
+//    batteryTechnologyPath: battery technology (POWER_SUPPLY_PROP_TECHNOLOGY)
+//    batteryCurrentNowPath: battery current (POWER_SUPPLY_PROP_CURRENT_NOW)
+//    batteryChargeCounterPath: battery accumulated charge
+//                                         (POWER_SUPPLY_PROP_CHARGE_COUNTER)
+
+struct healthd_config {
+    int periodic_chores_interval_fast;
+    int periodic_chores_interval_slow;
+
+    android::String8 batteryStatusPath;
+    android::String8 batteryHealthPath;
+    android::String8 batteryPresentPath;
+    android::String8 batteryCapacityPath;
+    android::String8 batteryVoltagePath;
+    android::String8 batteryTemperaturePath;
+    android::String8 batteryTechnologyPath;
+    android::String8 batteryCurrentNowPath;
+    android::String8 batteryChargeCounterPath;
+};
+
+// The following are implemented in libhealthd_board to handle board-specific
+// behavior.
+//
+// healthd_board_init() is called at startup time to modify healthd's
+// configuration according to board-specific requirements.  config
+// points to the healthd configuration values described above.  To use default
+// values, this function can simply return without modifying the fields of the
+// config parameter.
+
+void healthd_board_init(struct healthd_config *config);
+
+// Process updated battery property values.  This function is called when
+// the kernel sends updated battery status via a uevent from the power_supply
+// subsystem, or when updated values are polled by healthd, as for periodic
+// poll of battery state.
+//
+// props are the battery properties read from the kernel.  These values may
+// be modified in this call, prior to sending the modified values to the
+// Android runtime.
+//
+// Return 0 to indicate the usual kernel log battery status heartbeat message
+// is to be logged, or non-zero to prevent logging this information.
+
+int healthd_board_battery_update(struct android::BatteryProperties *props);
+
+#endif /* _HEALTHD_H_ */
diff --git a/include/cutils/zygote.h b/healthd/healthd_board_default.cpp
similarity index 63%
copy from include/cutils/zygote.h
copy to healthd/healthd_board_default.cpp
index a7480d3..b2bb516 100644
--- a/include/cutils/zygote.h
+++ b/healthd/healthd_board_default.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -14,18 +14,16 @@
  * limitations under the License.
  */
 
-#ifndef __CUTILS_ZYGOTE_H
-#define __CUTILS_ZYGOTE_H
+#include <healthd.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
-int zygote_run(int argc, const char **argv);
-
-#ifdef __cplusplus
+void healthd_board_init(struct healthd_config *config)
+{
+    // use defaults
 }
-#endif
 
-#endif /* __CUTILS_ZYGOTE_H */
+
+int healthd_board_battery_update(struct android::BatteryProperties *props)
+{
+    // return 0 to log periodic polled battery status to kernel log
+    return 0;
+}
diff --git a/include/backtrace/backtrace.h b/include/backtrace/backtrace.h
index b35a6d5..8a45690 100644
--- a/include/backtrace/backtrace.h
+++ b/include/backtrace/backtrace.h
@@ -17,12 +17,20 @@
 #ifndef _BACKTRACE_H
 #define _BACKTRACE_H
 
-#include <sys/types.h>
+#include <stdint.h>
 #include <stdbool.h>
-#include <inttypes.h>
+#include <sys/types.h>
 
 __BEGIN_DECLS
 
+// When the pid to be traced is set to this value, then trace the current
+// process. If the tid value is not BACKTRACE_NO_TID, then the specified
+// thread from the current process will be traced.
+#define BACKTRACE_CURRENT_PROCESS -1
+// When the tid to be traced is set to this value, then trace the specified
+// pid.
+#define BACKTRACE_NO_TID -1
+
 #define MAX_BACKTRACE_FRAMES 64
 
 typedef struct backtrace_map_info {
diff --git a/include/cutils/abort_socket.h b/include/cutils/abort_socket.h
deleted file mode 100644
index fbb1112..0000000
--- a/include/cutils/abort_socket.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2009, 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.
- */
-
-/* Helper to perform abortable blocking operations on a socket:
- *   asocket_connect()
- *   asocket_accept()
- *   asocket_read()
- *   asocket_write()
- * These calls are similar to the regular syscalls, but can be aborted with:
- *   asocket_abort()
- *
- * Calling close() on a regular POSIX socket does not abort blocked syscalls on
- * that socket in other threads.
- *
- * After calling asocket_abort() the socket cannot be reused.
- *
- * Call asocket_destory() *after* all threads have finished with the socket to
- * finish closing the socket and free the asocket structure.
- *
- * The helper is implemented by setting the socket non-blocking to initiate
- * syscalls connect(), accept(), read(), write(), then using a blocking poll()
- * on both the primary socket and a local pipe. This makes the poll() abortable
- * by writing a byte to the local pipe in asocket_abort().
- *
- * asocket_create() sets the fd to non-blocking mode. It must not be changed to
- * blocking mode.
- *
- * Using asocket will triple the number of file descriptors required per
- * socket, due to the local pipe. It may be possible to use a global pipe per
- * process rather than per socket, but we have not been able to come up with a
- * race-free implementation yet.
- *
- * All functions except asocket_init() and asocket_destroy() are thread safe.
- */
-
-#include <stdlib.h>
-#include <sys/socket.h>
-
-#ifndef __CUTILS_ABORT_SOCKET_H__
-#define __CUTILS_ABORT_SOCKET_H__
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct asocket {
-    int fd;           /* primary socket fd */
-    int abort_fd[2];  /* pipe used to abort */
-};
-
-/* Create an asocket from fd.
- * Sets the socket to non-blocking mode.
- * Returns NULL on error with errno set.
- */
-struct asocket *asocket_init(int fd);
-
-/* Blocking socket I/O with timeout.
- * Calling asocket_abort() from another thread will cause each of these
- * functions to immediately return with value -1 and errno ECANCELED.
- * timeout is in ms, use -1 to indicate no timeout. On timeout -1 is returned
- * with errno ETIMEDOUT.
- * EINTR is handled in-call.
- * Other semantics are identical to the regular syscalls.
- */
-int asocket_connect(struct asocket *s, const struct sockaddr *addr,
-        socklen_t addrlen, int timeout);
-
-int asocket_accept(struct asocket *s, struct sockaddr *addr,
-        socklen_t *addrlen, int timeout);
-
-int asocket_read(struct asocket *s, void *buf, size_t count, int timeout);
-
-int asocket_write(struct asocket *s, const void *buf, size_t count,
-        int timeout);
-
-/* Abort above calls and shutdown socket.
- * Further I/O operations on this socket will immediately fail after this call.
- * asocket_destroy() should be used to release resources once all threads
- * have returned from blocking calls on the socket.
- */
-void asocket_abort(struct asocket *s);
-
-/* Close socket and free asocket structure.
- * Must not be called until all calls on this structure have completed.
- */
-void asocket_destroy(struct asocket *s);
-
-#ifdef __cplusplus
-}
-#endif
-#endif //__CUTILS_ABORT_SOCKET__H__
diff --git a/include/cutils/android_reboot.h b/include/cutils/android_reboot.h
index 0c79be7..8c30e8e 100644
--- a/include/cutils/android_reboot.h
+++ b/include/cutils/android_reboot.h
@@ -24,9 +24,8 @@
 #define ANDROID_RB_POWEROFF 0xDEAD0002
 #define ANDROID_RB_RESTART2 0xDEAD0003
 
-/* Flags */
-#define ANDROID_RB_FLAG_NO_SYNC       0x1
-#define ANDROID_RB_FLAG_NO_REMOUNT_RO 0x2
+/* Properties */
+#define ANDROID_RB_PROPERTY "sys.powerctl"
 
 int android_reboot(int cmd, int flags, char *arg);
 
diff --git a/include/cutils/array.h b/include/cutils/array.h
deleted file mode 100644
index c97ff34..0000000
--- a/include/cutils/array.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * A pointer array which intelligently expands its capacity ad needed.
- */
-
-#ifndef __ARRAY_H
-#define __ARRAY_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-
-/** An array. */
-typedef struct Array Array;
-
-/** Constructs a new array. Returns NULL if we ran out of memory. */
-Array* arrayCreate();
-
-/** Frees an array. Does not free elements themselves. */
-void arrayFree(Array* array);
-
-/** Adds a pointer. Returns 0 is successful, < 0 otherwise. */
-int arrayAdd(Array* array, void* pointer);
-
-/** Gets the pointer at the specified index. */
-void* arrayGet(Array* array, int index);
-
-/** Removes the pointer at the given index and returns it. */
-void* arrayRemove(Array* array, int index);
-
-/** Sets pointer at the given index. Returns old pointer. */
-void* arraySet(Array* array, int index, void* pointer);
-
-/** Sets the array size. Sets new pointers to NULL. Returns 0 if successful, < 0 otherwise . */
-int arraySetSize(Array* array, int size);
-
-/** Returns the size of the given array. */
-int arraySize(Array* array);
-
-/** 
- * Returns a pointer to a C-style array which will be valid until this array 
- * changes.
- */
-const void** arrayUnwrap(Array* array);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __ARRAY_H */ 
diff --git a/include/cutils/bitops.h b/include/cutils/bitops.h
index eb44236..c26dc54 100644
--- a/include/cutils/bitops.h
+++ b/include/cutils/bitops.h
@@ -75,6 +75,16 @@
     return -1;
 }
 
+static inline int bitmask_weight(unsigned int *bitmask, int num_bits)
+{
+    int i;
+    int weight = 0;
+
+    for (i = 0; i < BITS_TO_WORDS(num_bits); i++)
+        weight += __builtin_popcount(bitmask[i]);
+    return weight;
+}
+
 static inline void bitmask_set(unsigned int *bitmask, int bit)
 {
     bitmask[BIT_WORD(bit)] |= BIT_MASK(bit);
diff --git a/include/cutils/fs.h b/include/cutils/fs.h
index fd5296b..d1d4cf2 100644
--- a/include/cutils/fs.h
+++ b/include/cutils/fs.h
@@ -55,6 +55,14 @@
  */
 extern int fs_write_atomic_int(const char* path, int value);
 
+/*
+ * Ensure that all directories along given path exist, creating parent
+ * directories as needed.  Validates that given path is absolute and that
+ * it contains no relative "." or ".." paths or symlinks.  Last path segment
+ * is treated as filename and ignored, unless the path ends with "/".
+ */
+extern int fs_mkdirs(const char* path, mode_t mode);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/cutils/log.h b/include/cutils/log.h
index 8b045c7..0e0248e 100644
--- a/include/cutils/log.h
+++ b/include/cutils/log.h
@@ -1,563 +1 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-//
-// C/C++ logging functions.  See the logging documentation for API details.
-//
-// We'd like these to be available from C code (in case we import some from
-// somewhere), so this has a C interface.
-//
-// The output will be correct when the log file is shared between multiple
-// threads and/or multiple processes so long as the operating system
-// supports O_APPEND.  These calls have mutex-protected data structures
-// and so are NOT reentrant.  Do not use LOG in a signal handler.
-//
-#ifndef _LIBS_CUTILS_LOG_H
-#define _LIBS_CUTILS_LOG_H
-
-#include <stdio.h>
-#include <time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#ifdef HAVE_PTHREADS
-#include <pthread.h>
-#endif
-#include <stdarg.h>
-
-#include <cutils/uio.h>
-#include <cutils/logd.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Normally we strip ALOGV (VERBOSE messages) from release builds.
- * You can modify this (for example with "#define LOG_NDEBUG 0"
- * at the top of your source file) to change that behavior.
- */
-#ifndef LOG_NDEBUG
-#ifdef NDEBUG
-#define LOG_NDEBUG 1
-#else
-#define LOG_NDEBUG 0
-#endif
-#endif
-
-/*
- * This is the local tag used for the following simplified
- * logging macros.  You can change this preprocessor definition
- * before using the other macros to change the tag.
- */
-#ifndef LOG_TAG
-#define LOG_TAG NULL
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Simplified macro to send a verbose log message using the current LOG_TAG.
- */
-#ifndef ALOGV
-#if LOG_NDEBUG
-#define ALOGV(...)   ((void)0)
-#else
-#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
-#endif
-#endif
-
-#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
-
-#ifndef ALOGV_IF
-#if LOG_NDEBUG
-#define ALOGV_IF(cond, ...)   ((void)0)
-#else
-#define ALOGV_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-#endif
-
-/*
- * Simplified macro to send a debug log message using the current LOG_TAG.
- */
-#ifndef ALOGD
-#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGD_IF
-#define ALOGD_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an info log message using the current LOG_TAG.
- */
-#ifndef ALOGI
-#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGI_IF
-#define ALOGI_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send a warning log message using the current LOG_TAG.
- */
-#ifndef ALOGW
-#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGW_IF
-#define ALOGW_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an error log message using the current LOG_TAG.
- */
-#ifndef ALOGE
-#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef ALOGE_IF
-#define ALOGE_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * verbose priority.
- */
-#ifndef IF_ALOGV
-#if LOG_NDEBUG
-#define IF_ALOGV() if (false)
-#else
-#define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG)
-#endif
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * debug priority.
- */
-#ifndef IF_ALOGD
-#define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG)
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * info priority.
- */
-#ifndef IF_ALOGI
-#define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG)
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * warn priority.
- */
-#ifndef IF_ALOGW
-#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG)
-#endif
-
-/*
- * Conditional based on whether the current LOG_TAG is enabled at
- * error priority.
- */
-#ifndef IF_ALOGE
-#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG)
-#endif
-
-
-// ---------------------------------------------------------------------
-
-/*
- * Simplified macro to send a verbose system log message using the current LOG_TAG.
- */
-#ifndef SLOGV
-#if LOG_NDEBUG
-#define SLOGV(...)   ((void)0)
-#else
-#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
-#endif
-#endif
-
-#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
-
-#ifndef SLOGV_IF
-#if LOG_NDEBUG
-#define SLOGV_IF(cond, ...)   ((void)0)
-#else
-#define SLOGV_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-#endif
-
-/*
- * Simplified macro to send a debug system log message using the current LOG_TAG.
- */
-#ifndef SLOGD
-#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef SLOGD_IF
-#define SLOGD_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an info system log message using the current LOG_TAG.
- */
-#ifndef SLOGI
-#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef SLOGI_IF
-#define SLOGI_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send a warning system log message using the current LOG_TAG.
- */
-#ifndef SLOGW
-#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef SLOGW_IF
-#define SLOGW_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an error system log message using the current LOG_TAG.
- */
-#ifndef SLOGE
-#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef SLOGE_IF
-#define SLOGE_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Simplified macro to send a verbose radio log message using the current LOG_TAG.
- */
-#ifndef RLOGV
-#if LOG_NDEBUG
-#define RLOGV(...)   ((void)0)
-#else
-#define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
-#endif
-#endif
-
-#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
-
-#ifndef RLOGV_IF
-#if LOG_NDEBUG
-#define RLOGV_IF(cond, ...)   ((void)0)
-#else
-#define RLOGV_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-#endif
-
-/*
- * Simplified macro to send a debug radio log message using the current LOG_TAG.
- */
-#ifndef RLOGD
-#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGD_IF
-#define RLOGD_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an info radio log message using the current LOG_TAG.
- */
-#ifndef RLOGI
-#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGI_IF
-#define RLOGI_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send a warning radio log message using the current LOG_TAG.
- */
-#ifndef RLOGW
-#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGW_IF
-#define RLOGW_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-/*
- * Simplified macro to send an error radio log message using the current LOG_TAG.
- */
-#ifndef RLOGE
-#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
-#endif
-
-#ifndef RLOGE_IF
-#define RLOGE_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-
-// ---------------------------------------------------------------------
-
-/*
- * Log a fatal error.  If the given condition fails, this stops program
- * execution like a normal assertion, but also generating the given message.
- * It is NOT stripped from release builds.  Note that the condition test
- * is -inverted- from the normal assert() semantics.
- */
-#ifndef LOG_ALWAYS_FATAL_IF
-#define LOG_ALWAYS_FATAL_IF(cond, ...) \
-    ( (CONDITION(cond)) \
-    ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \
-    : (void)0 )
-#endif
-
-#ifndef LOG_ALWAYS_FATAL
-#define LOG_ALWAYS_FATAL(...) \
-    ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) )
-#endif
-
-/*
- * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
- * are stripped out of release builds.
- */
-#if LOG_NDEBUG
-
-#ifndef LOG_FATAL_IF
-#define LOG_FATAL_IF(cond, ...) ((void)0)
-#endif
-#ifndef LOG_FATAL
-#define LOG_FATAL(...) ((void)0)
-#endif
-
-#else
-
-#ifndef LOG_FATAL_IF
-#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__)
-#endif
-#ifndef LOG_FATAL
-#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
-#endif
-
-#endif
-
-/*
- * Assertion that generates a log message when the assertion fails.
- * Stripped out of release builds.  Uses the current LOG_TAG.
- */
-#ifndef ALOG_ASSERT
-#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
-//#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Basic log message macro.
- *
- * Example:
- *  ALOG(LOG_WARN, NULL, "Failed with error %d", errno);
- *
- * The second argument may be NULL or "" to indicate the "global" tag.
- */
-#ifndef ALOG
-#define ALOG(priority, tag, ...) \
-    LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
-#endif
-
-/*
- * Log macro that allows you to specify a number for the priority.
- */
-#ifndef LOG_PRI
-#define LOG_PRI(priority, tag, ...) \
-    android_printLog(priority, tag, __VA_ARGS__)
-#endif
-
-/*
- * Log macro that allows you to pass in a varargs ("args" is a va_list).
- */
-#ifndef LOG_PRI_VA
-#define LOG_PRI_VA(priority, tag, fmt, args) \
-    android_vprintLog(priority, NULL, tag, fmt, args)
-#endif
-
-/*
- * Conditional given a desired logging priority and tag.
- */
-#ifndef IF_ALOG
-#define IF_ALOG(priority, tag) \
-    if (android_testLog(ANDROID_##priority, tag))
-#endif
-
-// ---------------------------------------------------------------------
-
-/*
- * Event logging.
- */
-
-/*
- * Event log entry types.  These must match up with the declarations in
- * java/android/android/util/EventLog.java.
- */
-typedef enum {
-    EVENT_TYPE_INT      = 0,
-    EVENT_TYPE_LONG     = 1,
-    EVENT_TYPE_STRING   = 2,
-    EVENT_TYPE_LIST     = 3,
-} AndroidEventLogType;
-
-
-#ifndef LOG_EVENT_INT
-#define LOG_EVENT_INT(_tag, _value) {                                       \
-        int intBuf = _value;                                                \
-        (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf,            \
-            sizeof(intBuf));                                                \
-    }
-#endif
-#ifndef LOG_EVENT_LONG
-#define LOG_EVENT_LONG(_tag, _value) {                                      \
-        long long longBuf = _value;                                         \
-        (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf,          \
-            sizeof(longBuf));                                               \
-    }
-#endif
-#ifndef LOG_EVENT_STRING
-#define LOG_EVENT_STRING(_tag, _value)                                      \
-    ((void) 0)  /* not implemented -- must combine len with string */
-#endif
-/* TODO: something for LIST */
-
-/*
- * ===========================================================================
- *
- * The stuff in the rest of this file should not be used directly.
- */
-
-#define android_printLog(prio, tag, fmt...) \
-    __android_log_print(prio, tag, fmt)
-
-#define android_vprintLog(prio, cond, tag, fmt...) \
-    __android_log_vprint(prio, tag, fmt)
-
-/* XXX Macros to work around syntax errors in places where format string
- * arg is not passed to ALOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF
- * (happens only in debug builds).
- */
-
-/* Returns 2nd arg.  Used to substitute default value if caller's vararg list
- * is empty.
- */
-#define __android_second(dummy, second, ...)     second
-
-/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
- * returns nothing.
- */
-#define __android_rest(first, ...)               , ## __VA_ARGS__
-
-#define android_printAssert(cond, tag, fmt...) \
-    __android_log_assert(cond, tag, \
-        __android_second(0, ## fmt, NULL) __android_rest(fmt))
-
-#define android_writeLog(prio, tag, text) \
-    __android_log_write(prio, tag, text)
-
-#define android_bWriteLog(tag, payload, len) \
-    __android_log_bwrite(tag, payload, len)
-#define android_btWriteLog(tag, type, payload, len) \
-    __android_log_btwrite(tag, type, payload, len)
-
-// TODO: remove these prototypes and their users
-#define android_testLog(prio, tag) (1)
-#define android_writevLog(vec,num) do{}while(0)
-#define android_write1Log(str,len) do{}while (0)
-#define android_setMinPriority(tag, prio) do{}while(0)
-//#define android_logToCallback(func) do{}while(0)
-#define android_logToFile(tag, file) (0)
-#define android_logToFd(tag, fd) (0)
-
-typedef enum {
-    LOG_ID_MAIN = 0,
-    LOG_ID_RADIO = 1,
-    LOG_ID_EVENTS = 2,
-    LOG_ID_SYSTEM = 3,
-
-    LOG_ID_MAX
-} log_id_t;
-
-/*
- * Send a simple string to the log.
- */
-int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text);
-int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _LIBS_CUTILS_LOG_H
+#include <log/log.h>
diff --git a/include/cutils/mq.h b/include/cutils/mq.h
deleted file mode 100644
index b27456d..0000000
--- a/include/cutils/mq.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * IPC messaging library.
- */
-
-#ifndef __MQ_H
-#define __MQ_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** A message. */
-typedef struct MqMessage MqMessage;
-
-/** A destination to which messages can be sent. */
-typedef struct MqDestination MqDestination;
-
-/* Array of bytes. */
-typedef struct MqBytes MqBytes;
-
-/** 
- * Hears messages. 
- * 
- * @param destination to which the message was sent
- * @param message the message to hear
- */
-typedef void MqMessageListener(MqDestination* destination, MqMessage* message);
-
-/** 
- * Hears a destination close.
- * 
- * @param destination that closed
- */
-typedef void MqCloseListener(MqDestination* destination);
-
-/** Message functions. */
-
-/** 
- * Creates a new Message.
- * 
- * @param header as defined by user
- * @param body as defined by user
- * @param replyTo destination to which replies should be sent, NULL if none
- */
-MqMessage* mqCreateMessage(MqBytes header, MqBytes body, 
-        MqDestination* replyTo);
-
-/** Sends a message to a destination. */
-void mqSendMessage(MqMessage* message, MqDestination* destination);
-
-/** Destination functions. */
-
-/** 
- * Creates a new destination. Acquires a reference implicitly.
- *
- * @param messageListener function to call when a message is recieved
- * @param closeListener function to call when the destination closes
- * @param userData user-specific data to associate with the destination.
- *  Retrieve using mqGetDestinationUserData().
- */
-MqDestination* mqCreateDestination(MqMessageListener* messageListener, 
-        MqCloseListener* closeListener, void* userData);
-
-/**
- * Gets user data which was associated with the given destination at 
- * construction time. 
- * 
- * It is only valid to call this function in the same process that the 
- * given destination was created in.
- * This function returns a null pointer if you call it on a destination
- * created in a remote process.
- */
-void* mqGetUserData(MqDestination* destination);
-
-/**
- * Returns 1 if the destination was created in this process, or 0 if
- * the destination was created in a different process, in which case you have
- * a remote stub.
- */
-int mqIsDestinationLocal(MqDestination* destination);
-
-/**
- * Increments the destination's reference count.
- */
-void mqKeepDestination(MqDesintation* destination);
-
-/**
- * Decrements the destination's reference count. 
- */
-void mqFreeDestination(MqDestination* desintation);
-
-/** Registry API. */
-
-/**
- * Gets the destination bound to a name.
- */
-MqDestination* mqGetDestination(char* name);
-
-/**
- * Binds a destination to a name.
- */
-void mqPutDestination(char* name, MqDestination* desintation);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MQ_H */ 
diff --git a/include/cutils/properties.h b/include/cutils/properties.h
index 25fd67a..2c70165 100644
--- a/include/cutils/properties.h
+++ b/include/cutils/properties.h
@@ -17,6 +17,10 @@
 #ifndef __CUTILS_PROPERTIES_H
 #define __CUTILS_PROPERTIES_H
 
+#include <sys/cdefs.h>
+#include <stddef.h>
+#include <sys/system_properties.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -28,8 +32,8 @@
 ** WARNING: system/bionic/include/sys/system_properties.h also defines
 **          these, but with different names.  (TODO: fix that)
 */
-#define PROPERTY_KEY_MAX   32
-#define PROPERTY_VALUE_MAX  92
+#define PROPERTY_KEY_MAX   PROP_NAME_MAX
+#define PROPERTY_VALUE_MAX  PROP_VALUE_MAX
 
 /* property_get: returns the length of the value which will never be
 ** greater than PROPERTY_VALUE_MAX - 1 and will always be zero terminated.
@@ -46,6 +50,22 @@
     
 int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie);    
 
+#if defined(__BIONIC_FORTIFY)
+
+extern int __property_get_real(const char *, char *, const char *)
+    __asm__(__USER_LABEL_PREFIX__ "property_get");
+__errordecl(__property_get_too_small_error, "property_get() called with too small of a buffer");
+
+__BIONIC_FORTIFY_INLINE
+int property_get(const char *key, char *value, const char *default_value) {
+    size_t bos = __bos(value);
+    if (bos < PROPERTY_VALUE_MAX) {
+        __property_get_too_small_error();
+    }
+    return __property_get_real(key, value, default_value);
+}
+
+#endif
 
 #ifdef HAVE_SYSTEM_PROPERTY_SERVER
 /*
diff --git a/include/cutils/qsort_r_compat.h b/include/cutils/qsort_r_compat.h
deleted file mode 100644
index 479a1ab..0000000
--- a/include/cutils/qsort_r_compat.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-/*
- * Provides a portable version of qsort_r, called qsort_r_compat, which is a
- * reentrant variant of qsort that passes a user data pointer to its comparator.
- * This implementation follows the BSD parameter convention.
- */
-
-#ifndef _LIBS_CUTILS_QSORT_R_COMPAT_H
-#define _LIBS_CUTILS_QSORT_R_COMPAT_H
-
-#include <stdlib.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
-        int (*compar)(void*, const void* , const void* ));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _LIBS_CUTILS_QSORT_R_COMPAT_H
diff --git a/include/cutils/selector.h b/include/cutils/selector.h
deleted file mode 100644
index dfc2a9d..0000000
--- a/include/cutils/selector.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Framework for multiplexing I/O. A selector manages a set of file
- * descriptors and calls out to user-provided callback functions to read and
- * write data and handle errors.
- */
-
-#ifndef __SELECTOR_H
-#define __SELECTOR_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdbool.h>
-    
-/** 
- * Manages SelectableFds and invokes their callbacks at appropriate times. 
- */
-typedef struct Selector Selector;
-
-/** 
- * A selectable descriptor. Contains callbacks which the selector can invoke
- * before calling select(), when the descriptor is readable or writable, and 
- * when the descriptor contains out-of-band data. Simply set a callback to 
- * NULL if you're not interested in that particular event.
- *
- * A selectable descriptor can indicate that it needs to be removed from the
- * selector by setting the 'remove' flag. The selector will remove the
- * descriptor at a later time and invoke the onRemove() callback.
- * 
- * SelectableFd fields should only be modified from the selector loop.
- */
-typedef struct SelectableFd SelectableFd;
-struct SelectableFd {
-
-    /** The file descriptor itself. */
-    int fd;
-    
-    /** Pointer to user-specific data. Can be NULL. */
-    void* data;
-    
-    /** 
-     * Set this flag when you no longer wish to be selected. The selector
-     * will invoke onRemove() when the descriptor is actually removed.
-     */
-    bool remove;
-
-    /** 
-     * Invoked by the selector before calling select. You can set up other
-     * callbacks from here as necessary.
-     */
-    void (*beforeSelect)(SelectableFd* self);
-
-    /** 
-     * Invoked by the selector when the descriptor has data available. Set to
-     * NULL to indicate that you're not interested in reading.
-     */
-    void (*onReadable)(SelectableFd* self);
-
-    /** 
-     * Invoked by the selector when the descriptor can accept data. Set to
-     * NULL to indicate that you're not interested in writing.
-     */
-    void (*onWritable)(SelectableFd* self);
-
-    /** 
-     * Invoked by the selector when out-of-band (OOB) data is available. Set to
-     * NULL to indicate that you're not interested in OOB data.
-     */
-    void (*onExcept)(SelectableFd* self);
-
-    /**
-     * Invoked by the selector after the descriptor is removed from the
-     * selector but before the selector frees the SelectableFd memory.
-     */
-    void (*onRemove)(SelectableFd* self);
-
-    /**
-     * The selector which selected this fd. Set by the selector itself.
-     */
-    Selector* selector;
-};
-
-/** 
- * Creates a new selector. 
- */
-Selector* selectorCreate(void);
-
-/** 
- * Creates a new selectable fd, adds it to the given selector and returns a 
- * pointer. Outside of 'selector' and 'fd', all fields are set to 0 or NULL 
- * by default.
- * 
- * The selectable fd should only be modified from the selector loop thread.
- */
-SelectableFd* selectorAdd(Selector* selector, int fd);
-
-/**
- * Wakes up the selector even though no I/O events occurred. Use this
- * to indicate that you're ready to write to a descriptor.
- */
-void selectorWakeUp(Selector* selector);
-    
-/** 
- * Loops continuously selecting file descriptors and firing events. 
- * Does not return. 
- */
-void selectorLoop(Selector* selector);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __SELECTOR_H */ 
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index 29034ca..1c8f107 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -66,7 +66,8 @@
 #define ATRACE_TAG_APP              (1<<12)
 #define ATRACE_TAG_RESOURCES        (1<<13)
 #define ATRACE_TAG_DALVIK           (1<<14)
-#define ATRACE_TAG_LAST             ATRACE_TAG_DALVIK
+#define ATRACE_TAG_RS               (1<<15)
+#define ATRACE_TAG_LAST             ATRACE_TAG_RS
 
 // Reserved for initialization.
 #define ATRACE_TAG_NOT_READY        (1LL<<63)
@@ -258,11 +259,28 @@
     }
 }
 
+/**
+ * Traces a 64-bit integer counter value.  name is used to identify the
+ * counter. This can be used to track how a value changes over time.
+ */
+#define ATRACE_INT64(name, value) atrace_int64(ATRACE_TAG, name, value)
+static inline void atrace_int64(uint64_t tag, const char* name, int64_t value)
+{
+    if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
+        char buf[ATRACE_MESSAGE_LENGTH];
+        size_t len;
+
+        len = snprintf(buf, ATRACE_MESSAGE_LENGTH, "C|%d|%s|%lld",
+                getpid(), name, value);
+        write(atrace_marker_fd, buf, len);
+    }
+}
+
 #else // not HAVE_ANDROID_OS
 
 #define ATRACE_INIT()
 #define ATRACE_GET_ENABLED_TAGS()
-#define ATRACE_ENABLED()
+#define ATRACE_ENABLED() 0
 #define ATRACE_BEGIN(name)
 #define ATRACE_END()
 #define ATRACE_ASYNC_BEGIN(name, cookie)
diff --git a/include/ion/ion.h b/include/ion/ion.h
index 018c0a1..fbd34e2 100644
--- a/include/ion/ion.h
+++ b/include/ion/ion.h
@@ -25,6 +25,8 @@
 
 __BEGIN_DECLS
 
+struct ion_handle;
+
 int ion_open();
 int ion_close(int fd);
 int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask,
diff --git a/include/cutils/event_tag_map.h b/include/log/event_tag_map.h
similarity index 100%
rename from include/cutils/event_tag_map.h
rename to include/log/event_tag_map.h
diff --git a/include/log/log.h b/include/log/log.h
new file mode 100644
index 0000000..7faddea
--- /dev/null
+++ b/include/log/log.h
@@ -0,0 +1,563 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// C/C++ logging functions.  See the logging documentation for API details.
+//
+// We'd like these to be available from C code (in case we import some from
+// somewhere), so this has a C interface.
+//
+// The output will be correct when the log file is shared between multiple
+// threads and/or multiple processes so long as the operating system
+// supports O_APPEND.  These calls have mutex-protected data structures
+// and so are NOT reentrant.  Do not use LOG in a signal handler.
+//
+#ifndef _LIBS_LOG_LOG_H
+#define _LIBS_LOG_LOG_H
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifdef HAVE_PTHREADS
+#include <pthread.h>
+#endif
+#include <stdarg.h>
+
+#include <log/uio.h>
+#include <log/logd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Normally we strip ALOGV (VERBOSE messages) from release builds.
+ * You can modify this (for example with "#define LOG_NDEBUG 0"
+ * at the top of your source file) to change that behavior.
+ */
+#ifndef LOG_NDEBUG
+#ifdef NDEBUG
+#define LOG_NDEBUG 1
+#else
+#define LOG_NDEBUG 0
+#endif
+#endif
+
+/*
+ * This is the local tag used for the following simplified
+ * logging macros.  You can change this preprocessor definition
+ * before using the other macros to change the tag.
+ */
+#ifndef LOG_TAG
+#define LOG_TAG NULL
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose log message using the current LOG_TAG.
+ */
+#ifndef ALOGV
+#if LOG_NDEBUG
+#define ALOGV(...)   ((void)0)
+#else
+#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#endif
+#endif
+
+#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
+
+#ifndef ALOGV_IF
+#if LOG_NDEBUG
+#define ALOGV_IF(cond, ...)   ((void)0)
+#else
+#define ALOGV_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug log message using the current LOG_TAG.
+ */
+#ifndef ALOGD
+#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGD_IF
+#define ALOGD_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an info log message using the current LOG_TAG.
+ */
+#ifndef ALOGI
+#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGI_IF
+#define ALOGI_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send a warning log message using the current LOG_TAG.
+ */
+#ifndef ALOGW
+#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGW_IF
+#define ALOGW_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an error log message using the current LOG_TAG.
+ */
+#ifndef ALOGE
+#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef ALOGE_IF
+#define ALOGE_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * verbose priority.
+ */
+#ifndef IF_ALOGV
+#if LOG_NDEBUG
+#define IF_ALOGV() if (false)
+#else
+#define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG)
+#endif
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * debug priority.
+ */
+#ifndef IF_ALOGD
+#define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG)
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * info priority.
+ */
+#ifndef IF_ALOGI
+#define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG)
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * warn priority.
+ */
+#ifndef IF_ALOGW
+#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG)
+#endif
+
+/*
+ * Conditional based on whether the current LOG_TAG is enabled at
+ * error priority.
+ */
+#ifndef IF_ALOGE
+#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG)
+#endif
+
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose system log message using the current LOG_TAG.
+ */
+#ifndef SLOGV
+#if LOG_NDEBUG
+#define SLOGV(...)   ((void)0)
+#else
+#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#endif
+#endif
+
+#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
+
+#ifndef SLOGV_IF
+#if LOG_NDEBUG
+#define SLOGV_IF(cond, ...)   ((void)0)
+#else
+#define SLOGV_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug system log message using the current LOG_TAG.
+ */
+#ifndef SLOGD
+#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGD_IF
+#define SLOGD_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an info system log message using the current LOG_TAG.
+ */
+#ifndef SLOGI
+#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGI_IF
+#define SLOGI_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send a warning system log message using the current LOG_TAG.
+ */
+#ifndef SLOGW
+#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGW_IF
+#define SLOGW_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an error system log message using the current LOG_TAG.
+ */
+#ifndef SLOGE
+#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGE_IF
+#define SLOGE_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose radio log message using the current LOG_TAG.
+ */
+#ifndef RLOGV
+#if LOG_NDEBUG
+#define RLOGV(...)   ((void)0)
+#else
+#define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#endif
+#endif
+
+#define CONDITION(cond)     (__builtin_expect((cond)!=0, 0))
+
+#ifndef RLOGV_IF
+#if LOG_NDEBUG
+#define RLOGV_IF(cond, ...)   ((void)0)
+#else
+#define RLOGV_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug radio log message using the current LOG_TAG.
+ */
+#ifndef RLOGD
+#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef RLOGD_IF
+#define RLOGD_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an info radio log message using the current LOG_TAG.
+ */
+#ifndef RLOGI
+#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef RLOGI_IF
+#define RLOGI_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send a warning radio log message using the current LOG_TAG.
+ */
+#ifndef RLOGW
+#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef RLOGW_IF
+#define RLOGW_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an error radio log message using the current LOG_TAG.
+ */
+#ifndef RLOGE
+#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef RLOGE_IF
+#define RLOGE_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+
+// ---------------------------------------------------------------------
+
+/*
+ * Log a fatal error.  If the given condition fails, this stops program
+ * execution like a normal assertion, but also generating the given message.
+ * It is NOT stripped from release builds.  Note that the condition test
+ * is -inverted- from the normal assert() semantics.
+ */
+#ifndef LOG_ALWAYS_FATAL_IF
+#define LOG_ALWAYS_FATAL_IF(cond, ...) \
+    ( (CONDITION(cond)) \
+    ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \
+    : (void)0 )
+#endif
+
+#ifndef LOG_ALWAYS_FATAL
+#define LOG_ALWAYS_FATAL(...) \
+    ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) )
+#endif
+
+/*
+ * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
+ * are stripped out of release builds.
+ */
+#if LOG_NDEBUG
+
+#ifndef LOG_FATAL_IF
+#define LOG_FATAL_IF(cond, ...) ((void)0)
+#endif
+#ifndef LOG_FATAL
+#define LOG_FATAL(...) ((void)0)
+#endif
+
+#else
+
+#ifndef LOG_FATAL_IF
+#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__)
+#endif
+#ifndef LOG_FATAL
+#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
+#endif
+
+#endif
+
+/*
+ * Assertion that generates a log message when the assertion fails.
+ * Stripped out of release builds.  Uses the current LOG_TAG.
+ */
+#ifndef ALOG_ASSERT
+#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
+//#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Basic log message macro.
+ *
+ * Example:
+ *  ALOG(LOG_WARN, NULL, "Failed with error %d", errno);
+ *
+ * The second argument may be NULL or "" to indicate the "global" tag.
+ */
+#ifndef ALOG
+#define ALOG(priority, tag, ...) \
+    LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
+#endif
+
+/*
+ * Log macro that allows you to specify a number for the priority.
+ */
+#ifndef LOG_PRI
+#define LOG_PRI(priority, tag, ...) \
+    android_printLog(priority, tag, __VA_ARGS__)
+#endif
+
+/*
+ * Log macro that allows you to pass in a varargs ("args" is a va_list).
+ */
+#ifndef LOG_PRI_VA
+#define LOG_PRI_VA(priority, tag, fmt, args) \
+    android_vprintLog(priority, NULL, tag, fmt, args)
+#endif
+
+/*
+ * Conditional given a desired logging priority and tag.
+ */
+#ifndef IF_ALOG
+#define IF_ALOG(priority, tag) \
+    if (android_testLog(ANDROID_##priority, tag))
+#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Event logging.
+ */
+
+/*
+ * Event log entry types.  These must match up with the declarations in
+ * java/android/android/util/EventLog.java.
+ */
+typedef enum {
+    EVENT_TYPE_INT      = 0,
+    EVENT_TYPE_LONG     = 1,
+    EVENT_TYPE_STRING   = 2,
+    EVENT_TYPE_LIST     = 3,
+} AndroidEventLogType;
+
+
+#ifndef LOG_EVENT_INT
+#define LOG_EVENT_INT(_tag, _value) {                                       \
+        int intBuf = _value;                                                \
+        (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf,            \
+            sizeof(intBuf));                                                \
+    }
+#endif
+#ifndef LOG_EVENT_LONG
+#define LOG_EVENT_LONG(_tag, _value) {                                      \
+        long long longBuf = _value;                                         \
+        (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf,          \
+            sizeof(longBuf));                                               \
+    }
+#endif
+#ifndef LOG_EVENT_STRING
+#define LOG_EVENT_STRING(_tag, _value)                                      \
+    ((void) 0)  /* not implemented -- must combine len with string */
+#endif
+/* TODO: something for LIST */
+
+/*
+ * ===========================================================================
+ *
+ * The stuff in the rest of this file should not be used directly.
+ */
+
+#define android_printLog(prio, tag, fmt...) \
+    __android_log_print(prio, tag, fmt)
+
+#define android_vprintLog(prio, cond, tag, fmt...) \
+    __android_log_vprint(prio, tag, fmt)
+
+/* XXX Macros to work around syntax errors in places where format string
+ * arg is not passed to ALOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF
+ * (happens only in debug builds).
+ */
+
+/* Returns 2nd arg.  Used to substitute default value if caller's vararg list
+ * is empty.
+ */
+#define __android_second(dummy, second, ...)     second
+
+/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
+ * returns nothing.
+ */
+#define __android_rest(first, ...)               , ## __VA_ARGS__
+
+#define android_printAssert(cond, tag, fmt...) \
+    __android_log_assert(cond, tag, \
+        __android_second(0, ## fmt, NULL) __android_rest(fmt))
+
+#define android_writeLog(prio, tag, text) \
+    __android_log_write(prio, tag, text)
+
+#define android_bWriteLog(tag, payload, len) \
+    __android_log_bwrite(tag, payload, len)
+#define android_btWriteLog(tag, type, payload, len) \
+    __android_log_btwrite(tag, type, payload, len)
+
+// TODO: remove these prototypes and their users
+#define android_testLog(prio, tag) (1)
+#define android_writevLog(vec,num) do{}while(0)
+#define android_write1Log(str,len) do{}while (0)
+#define android_setMinPriority(tag, prio) do{}while(0)
+//#define android_logToCallback(func) do{}while(0)
+#define android_logToFile(tag, file) (0)
+#define android_logToFd(tag, fd) (0)
+
+typedef enum {
+    LOG_ID_MAIN = 0,
+    LOG_ID_RADIO = 1,
+    LOG_ID_EVENTS = 2,
+    LOG_ID_SYSTEM = 3,
+
+    LOG_ID_MAX
+} log_id_t;
+
+/*
+ * Send a simple string to the log.
+ */
+int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text);
+int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _LIBS_CUTILS_LOG_H
diff --git a/include/cutils/logd.h b/include/log/logd.h
similarity index 97%
rename from include/cutils/logd.h
rename to include/log/logd.h
index 8737639..379c373 100644
--- a/include/cutils/logd.h
+++ b/include/log/logd.h
@@ -31,7 +31,7 @@
 #ifdef HAVE_PTHREADS
 #include <pthread.h>
 #endif
-#include <cutils/uio.h>
+#include <log/uio.h>
 #include <stdarg.h>
 
 #ifdef __cplusplus
diff --git a/include/cutils/logger.h b/include/log/logger.h
similarity index 100%
rename from include/cutils/logger.h
rename to include/log/logger.h
diff --git a/include/cutils/logprint.h b/include/log/logprint.h
similarity index 97%
rename from include/cutils/logprint.h
rename to include/log/logprint.h
index 2b1e1c5..481c96e 100644
--- a/include/cutils/logprint.h
+++ b/include/log/logprint.h
@@ -17,9 +17,9 @@
 #ifndef _LOGPRINT_H
 #define _LOGPRINT_H
 
-#include <cutils/log.h>
-#include <cutils/logger.h>
-#include <cutils/event_tag_map.h>
+#include <log/log.h>
+#include <log/logger.h>
+#include <log/event_tag_map.h>
 #include <pthread.h>
 
 #ifdef __cplusplus
diff --git a/include/cutils/uio.h b/include/log/uio.h
similarity index 100%
rename from include/cutils/uio.h
rename to include/log/uio.h
diff --git a/include/memtrack/memtrack.h b/include/memtrack/memtrack.h
new file mode 100644
index 0000000..0f1f85e
--- /dev/null
+++ b/include/memtrack/memtrack.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _LIBMEMTRACK_MEMTRACK_H_
+#define _LIBMEMTRACK_MEMTRACK_H_
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <cutils/compiler.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * struct memtrack_proc
+ *
+ * an opaque handle to the memory stats on a process.
+ * Created with memtrack_proc_new, destroyed by
+ * memtrack_proc_destroy.  Can be reused multiple times with
+ * memtrack_proc_get.
+ */
+struct memtrack_proc;
+
+/**
+ * memtrack_init
+ *
+ * Must be called once before calling any other functions.  After this function
+ * is called, everything else is thread-safe.
+ *
+ * Returns 0 on success, -errno on error.
+ */
+int memtrack_init(void);
+
+/**
+ * memtrack_proc_new
+ *
+ * Return a new handle to hold process memory stats.
+ *
+ * Returns NULL on error.
+ */
+struct memtrack_proc *memtrack_proc_new(void);
+
+/**
+ * memtrack_proc_destroy
+ *
+ * Free all memory associated with a process memory stats handle.
+ */
+void memtrack_proc_destroy(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_get
+ *
+ * Fill a process memory stats handle with data about the given pid.  Can be
+ * called on a handle that was just allocated with memtrack_proc_new,
+ * or on a handle that has been previously passed to memtrack_proc_get
+ * to replace the data with new data on the same or another process.  It is
+ * expected that the second call on the same handle should not require
+ * allocating any new memory.
+ *
+ * Returns 0 on success, -errno on error.
+ */
+int memtrack_proc_get(struct memtrack_proc *p, pid_t pid);
+
+/**
+ * memtrack_proc_graphics_total
+ *
+ * Return total amount of memory that has been allocated for use as window
+ * buffers.  Does not differentiate between memory that has already been
+ * accounted for by reading /proc/pid/smaps and memory that has not been
+ * accounted for.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_graphics_total(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_graphics_pss
+ *
+ * Return total amount of memory that has been allocated for use as window
+ * buffers, but has not already been accounted for by reading /proc/pid/smaps.
+ * Memory that is shared across processes may already be divided by the
+ * number of processes that share it (preferred), or may be charged in full to
+ * every process that shares it, depending on the capabilities of the driver.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_graphics_pss(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_gl_total
+ *
+ * Same as memtrack_proc_graphics_total, but counts GL memory (which
+ * should not overlap with graphics memory) instead of graphics memory.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_gl_total(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_gl_pss
+ *
+ * Same as memtrack_proc_graphics_total, but counts GL memory (which
+ * should not overlap with graphics memory) instead of graphics memory.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_gl_pss(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_gl_total
+ *
+ * Same as memtrack_proc_graphics_total, but counts miscellaneous memory
+ * not tracked by gl or graphics calls above.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_other_total(struct memtrack_proc *p);
+
+/**
+ * memtrack_proc_gl_pss
+ *
+ * Same as memtrack_proc_graphics_total, but counts miscellaneous memory
+ * not tracked by gl or graphics calls above.
+ *
+ * Returns non-negative size in bytes on success, -errno on error.
+ */
+ssize_t memtrack_proc_other_pss(struct memtrack_proc *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netutils/dhcp.h b/include/netutils/dhcp.h
index bd2c957..de6bc82 100644
--- a/include/netutils/dhcp.h
+++ b/include/netutils/dhcp.h
@@ -30,7 +30,9 @@
                           char *dns[],
                           char *server,
                           uint32_t *lease,
-                          char *vendorInfo);
+                          char *vendorInfo,
+                          char *domain,
+                          char *mtu);
 extern int dhcp_do_request_renew(const char *ifname,
                                 char *ipaddr,
                                 char *gateway,
@@ -38,7 +40,9 @@
                                 char *dns[],
                                 char *server,
                                 uint32_t *lease,
-                                char *vendorInfo);
+                                char *vendorInfo,
+                                char *domain,
+                                char *mtu);
 extern int dhcp_stop(const char *ifname);
 extern int dhcp_release_lease(const char *ifname);
 extern char *dhcp_get_errmsg();
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 5d363a7..0ed0d78 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -34,8 +34,8 @@
 #endif
 
 /* This is the master Users and Groups config for the platform.
-** DO NOT EVER RENUMBER.
-*/
+ * DO NOT EVER RENUMBER
+ */
 
 #define AID_ROOT             0  /* traditional unix root user */
 
@@ -72,6 +72,10 @@
 #define AID_CLAT          1029  /* clat part of nat464 */
 #define AID_LOOP_RADIO    1030  /* loop radio devices */
 #define AID_MEDIA_DRM     1031  /* MediaDrm plugins */
+#define AID_PACKAGE_INFO  1032  /* access to installed package details */
+#define AID_SDCARD_PICS   1033  /* external storage photos access */
+#define AID_SDCARD_AV     1034  /* external storage audio/video access */
+#define AID_SDCARD_ALL    1035  /* access all users external storage */
 
 #define AID_SHELL         2000  /* adb and debug shell user */
 #define AID_CACHE         2001  /* cache access */
@@ -108,50 +112,61 @@
 };
 
 static const struct android_id_info android_ids[] = {
-    { "root",      AID_ROOT, },
-    { "system",    AID_SYSTEM, },
-    { "radio",     AID_RADIO, },
-    { "bluetooth", AID_BLUETOOTH, },
-    { "graphics",  AID_GRAPHICS, },
-    { "input",     AID_INPUT, },
-    { "audio",     AID_AUDIO, },
-    { "camera",    AID_CAMERA, },
-    { "log",       AID_LOG, },
-    { "compass",   AID_COMPASS, },
-    { "mount",     AID_MOUNT, },
-    { "wifi",      AID_WIFI, },
-    { "dhcp",      AID_DHCP, },
-    { "adb",       AID_ADB, },
-    { "install",   AID_INSTALL, },
-    { "media",     AID_MEDIA, },
-    { "drm",       AID_DRM, },
-    { "mdnsr",     AID_MDNSR, },
-    { "nfc",       AID_NFC, },
-    { "drmrpc",    AID_DRMRPC, },
-    { "shell",     AID_SHELL, },
-    { "cache",     AID_CACHE, },
-    { "diag",      AID_DIAG, },
-    { "net_bt_admin", AID_NET_BT_ADMIN, },
-    { "net_bt",    AID_NET_BT, },
-    { "net_bt_stack",    AID_NET_BT_STACK, },
-    { "sdcard_r",  AID_SDCARD_R, },
-    { "sdcard_rw", AID_SDCARD_RW, },
-    { "media_rw",  AID_MEDIA_RW, },
-    { "vpn",       AID_VPN, },
-    { "keystore",  AID_KEYSTORE, },
-    { "usb",       AID_USB, },
-    { "mtp",       AID_MTP, },
-    { "gps",       AID_GPS, },
-    { "inet",      AID_INET, },
-    { "net_raw",   AID_NET_RAW, },
-    { "net_admin", AID_NET_ADMIN, },
-    { "net_bw_stats", AID_NET_BW_STATS, },
-    { "net_bw_acct", AID_NET_BW_ACCT, },
-    { "loop_radio", AID_LOOP_RADIO, },
-    { "misc",      AID_MISC, },
-    { "nobody",    AID_NOBODY, },
-    { "clat",      AID_CLAT, },
-    { "mediadrm",  AID_MEDIA_DRM, },
+    { "root",          AID_ROOT, },
+
+    { "system",        AID_SYSTEM, },
+
+    { "radio",         AID_RADIO, },
+    { "bluetooth",     AID_BLUETOOTH, },
+    { "graphics",      AID_GRAPHICS, },
+    { "input",         AID_INPUT, },
+    { "audio",         AID_AUDIO, },
+    { "camera",        AID_CAMERA, },
+    { "log",           AID_LOG, },
+    { "compass",       AID_COMPASS, },
+    { "mount",         AID_MOUNT, },
+    { "wifi",          AID_WIFI, },
+    { "adb",           AID_ADB, },
+    { "install",       AID_INSTALL, },
+    { "media",         AID_MEDIA, },
+    { "dhcp",          AID_DHCP, },
+    { "sdcard_rw",     AID_SDCARD_RW, },
+    { "vpn",           AID_VPN, },
+    { "keystore",      AID_KEYSTORE, },
+    { "usb",           AID_USB, },
+    { "drm",           AID_DRM, },
+    { "mdnsr",         AID_MDNSR, },
+    { "gps",           AID_GPS, },
+    // AID_UNUSED1
+    { "media_rw",      AID_MEDIA_RW, },
+    { "mtp",           AID_MTP, },
+    // AID_UNUSED2
+    { "drmrpc",        AID_DRMRPC, },
+    { "nfc",           AID_NFC, },
+    { "sdcard_r",      AID_SDCARD_R, },
+    { "clat",          AID_CLAT, },
+    { "loop_radio",    AID_LOOP_RADIO, },
+    { "mediadrm",      AID_MEDIA_DRM, },
+    { "package_info",  AID_PACKAGE_INFO, },
+    { "sdcard_pics",   AID_SDCARD_PICS, },
+    { "sdcard_av",     AID_SDCARD_AV, },
+    { "sdcard_all",    AID_SDCARD_ALL, },
+
+    { "shell",         AID_SHELL, },
+    { "cache",         AID_CACHE, },
+    { "diag",          AID_DIAG, },
+
+    { "net_bt_admin",  AID_NET_BT_ADMIN, },
+    { "net_bt",        AID_NET_BT, },
+    { "inet",          AID_INET, },
+    { "net_raw",       AID_NET_RAW, },
+    { "net_admin",     AID_NET_ADMIN, },
+    { "net_bw_stats",  AID_NET_BW_STATS, },
+    { "net_bw_acct",   AID_NET_BW_ACCT, },
+    { "net_bt_stack",  AID_NET_BT_STACK, },
+
+    { "misc",          AID_MISC, },
+    { "nobody",        AID_NOBODY, },
 };
 
 #define android_id_count \
@@ -229,7 +244,7 @@
     { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/tcpdump" },
     { 04770, AID_ROOT,      AID_RADIO,     0, "system/bin/pppd-ril" },
 
-    /* the following file has enhanced capabilities and IS included in user builds. */
+    /* the following files have enhanced capabilities and ARE included in user builds. */
     { 00750, AID_ROOT,      AID_SHELL,     (1 << CAP_SETUID) | (1 << CAP_SETGID), "system/bin/run-as" },
 
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
diff --git a/include/private/pixelflinger/ggl_context.h b/include/private/pixelflinger/ggl_context.h
index 4864d5a..17bb3ed 100644
--- a/include/private/pixelflinger/ggl_context.h
+++ b/include/private/pixelflinger/ggl_context.h
@@ -121,7 +121,7 @@
 template<> struct CTA<true> { };
 
 #define GGL_CONTEXT(con, c)         context_t *con = static_cast<context_t *>(c)
-#define GGL_OFFSETOF(field)         int(&(((context_t*)0)->field))
+#define GGL_OFFSETOF(field)         uintptr_t(&(((context_t*)0)->field))
 #define GGL_INIT_PROC(p, f)         p.f = ggl_ ## f;
 #define GGL_BETWEEN(x, L, H)        (uint32_t((x)-(L)) <= ((H)-(L)))
 
@@ -480,7 +480,7 @@
     uint32_t    width;
     uint32_t    height;
     uint32_t    stride;
-    int32_t     data;
+    uintptr_t   data;
     int32_t     dsdx;
     int32_t     dtdx;
     int32_t     spill[2];
diff --git a/include/system/audio.h b/include/system/audio.h
index da235dd..aa7ac02 100644
--- a/include/system/audio.h
+++ b/include/system/audio.h
@@ -31,6 +31,9 @@
  * frameworks/base/include/media/AudioSystem.h
  */
 
+/* device address used to refer to the standard remote submix */
+#define AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS "0"
+
 typedef int audio_io_handle_t;
 
 /* Audio stream types */
@@ -69,6 +72,11 @@
                                           /*  play the mix captured by this audio source.      */
     AUDIO_SOURCE_CNT,
     AUDIO_SOURCE_MAX                 = AUDIO_SOURCE_CNT - 1,
+    AUDIO_SOURCE_HOTWORD             = 1999, /* A low-priority, preemptible audio source for
+                                                for background software hotword detection.
+                                                Same tuning as AUDIO_SOURCE_VOICE_RECOGNITION.
+                                                Used only internally to the framework. Not exposed
+                                                at the audio HAL. */
 } audio_source_t;
 
 /* special audio session values
@@ -383,9 +391,51 @@
                                         // controls related to voice calls.
     AUDIO_OUTPUT_FLAG_FAST = 0x4,       // output supports "fast tracks",
                                         // defined elsewhere
-    AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8 // use deep audio buffers
+    AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8, // use deep audio buffers
+    AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 0x10,  // offload playback of compressed
+                                                // streams to hardware codec
+    AUDIO_OUTPUT_FLAG_NON_BLOCKING = 0x20 // use non-blocking write
 } audio_output_flags_t;
 
+/* The audio input flags are analogous to audio output flags.
+ * Currently they are used only when an AudioRecord is created,
+ * to indicate a preference to be connected to an input stream with
+ * attributes corresponding to the specified flags.
+ */
+typedef enum {
+    AUDIO_INPUT_FLAG_NONE = 0x0,        // no attributes
+    AUDIO_INPUT_FLAG_FAST = 0x1,        // prefer an input that supports "fast tracks"
+} audio_input_flags_t;
+
+/* Additional information about compressed streams offloaded to
+ * hardware playback
+ * The version and size fields must be initialized by the caller by using
+ * one of the constants defined here.
+ */
+typedef struct {
+    uint16_t version;                   // version of the info structure
+    uint16_t size;                      // total size of the structure including version and size
+    uint32_t sample_rate;               // sample rate in Hz
+    audio_channel_mask_t channel_mask;  // channel mask
+    audio_format_t format;              // audio format
+    audio_stream_type_t stream_type;    // stream type
+    uint32_t bit_rate;                  // bit rate in bits per second
+    int64_t duration_us;                // duration in microseconds, -1 if unknown
+    bool has_video;                     // true if stream is tied to a video stream
+    bool is_streaming;                  // true if streaming, false if local playback
+} audio_offload_info_t;
+
+#define AUDIO_MAKE_OFFLOAD_INFO_VERSION(maj,min) \
+            ((((maj) & 0xff) << 8) | ((min) & 0xff))
+
+#define AUDIO_OFFLOAD_INFO_VERSION_0_1 AUDIO_MAKE_OFFLOAD_INFO_VERSION(0, 1)
+#define AUDIO_OFFLOAD_INFO_VERSION_CURRENT AUDIO_OFFLOAD_INFO_VERSION_0_1
+
+static const audio_offload_info_t AUDIO_INFO_INITIALIZER = {
+    version: AUDIO_OFFLOAD_INFO_VERSION_CURRENT,
+    size: sizeof(audio_offload_info_t),
+};
+
 static inline bool audio_is_output_device(audio_devices_t device)
 {
     if (((device & AUDIO_DEVICE_BIT_IN) == 0) &&
@@ -439,24 +489,25 @@
 
 static inline bool audio_is_remote_submix_device(audio_devices_t device)
 {
-    if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX))
+    if ((device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
+            || (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) == AUDIO_DEVICE_IN_REMOTE_SUBMIX)
         return true;
     else
         return false;
 }
 
-static inline bool audio_is_input_channel(uint32_t channel)
+static inline bool audio_is_input_channel(audio_channel_mask_t channel)
 {
     if ((channel & ~AUDIO_CHANNEL_IN_ALL) == 0)
-        return true;
+        return channel != 0;
     else
         return false;
 }
 
-static inline bool audio_is_output_channel(uint32_t channel)
+static inline bool audio_is_output_channel(audio_channel_mask_t channel)
 {
     if ((channel & ~AUDIO_CHANNEL_OUT_ALL) == 0)
-        return true;
+        return channel != 0;
     else
         return false;
 }
diff --git a/include/system/graphics.h b/include/system/graphics.h
index ed493f5..be86ae4 100644
--- a/include/system/graphics.h
+++ b/include/system/graphics.h
@@ -42,15 +42,40 @@
  */
 
 enum {
+    /*
+     * "linear" color pixel formats:
+     *
+     * The pixel formats below contain sRGB data but are otherwise treated
+     * as linear formats, i.e.: no special operation is performed when
+     * reading or writing into a buffer in one of these formats
+     */
     HAL_PIXEL_FORMAT_RGBA_8888          = 1,
     HAL_PIXEL_FORMAT_RGBX_8888          = 2,
     HAL_PIXEL_FORMAT_RGB_888            = 3,
     HAL_PIXEL_FORMAT_RGB_565            = 4,
     HAL_PIXEL_FORMAT_BGRA_8888          = 5,
-    HAL_PIXEL_FORMAT_RGBA_5551          = 6,
-    HAL_PIXEL_FORMAT_RGBA_4444          = 7,
 
-    /* 0x8 - 0xFF range unavailable */
+    /*
+     * sRGB color pixel formats:
+     *
+     * The red, green and blue components are stored in sRGB space, and converted
+     * to linear space when read, using the standard sRGB to linear equation:
+     *
+     * Clinear = Csrgb / 12.92                  for Csrgb <= 0.04045
+     *         = (Csrgb + 0.055 / 1.055)^2.4    for Csrgb >  0.04045
+     *
+     * When written the inverse transformation is performed:
+     *
+     * Csrgb = 12.92 * Clinear                  for Clinear <= 0.0031308
+     *       = 1.055 * Clinear^(1/2.4) - 0.055  for Clinear >  0.0031308
+     *
+     *
+     *  The alpha component, if present, is always stored in linear space and
+     *  is left unmodified when read or written.
+     *
+     */
+    HAL_PIXEL_FORMAT_sRGB_A_8888        = 0xC,
+    HAL_PIXEL_FORMAT_sRGB_X_8888        = 0xD,
 
     /*
      * 0x100 - 0x1FF
@@ -268,6 +293,8 @@
     HAL_TRANSFORM_ROT_180   = 0x03,
     /* rotate source image 270 degrees clockwise */
     HAL_TRANSFORM_ROT_270   = 0x07,
+    /* don't use. see system/window.h */
+    HAL_TRANSFORM_RESERVED  = 0x08,
 };
 
 #ifdef __cplusplus
diff --git a/include/system/thread_defs.h b/include/system/thread_defs.h
new file mode 100644
index 0000000..377a48c
--- /dev/null
+++ b/include/system/thread_defs.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef ANDROID_THREAD_DEFS_H
+#define ANDROID_THREAD_DEFS_H
+
+#include "graphics.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+enum {
+    /*
+     * ***********************************************
+     * ** Keep in sync with android.os.Process.java **
+     * ***********************************************
+     *
+     * This maps directly to the "nice" priorities we use in Android.
+     * A thread priority should be chosen inverse-proportionally to
+     * the amount of work the thread is expected to do. The more work
+     * a thread will do, the less favorable priority it should get so that
+     * it doesn't starve the system. Threads not behaving properly might
+     * be "punished" by the kernel.
+     * Use the levels below when appropriate. Intermediate values are
+     * acceptable, preferably use the {MORE|LESS}_FAVORABLE constants below.
+     */
+    ANDROID_PRIORITY_LOWEST         =  19,
+
+    /* use for background tasks */
+    ANDROID_PRIORITY_BACKGROUND     =  10,
+
+    /* most threads run at normal priority */
+    ANDROID_PRIORITY_NORMAL         =   0,
+
+    /* threads currently running a UI that the user is interacting with */
+    ANDROID_PRIORITY_FOREGROUND     =  -2,
+
+    /* the main UI thread has a slightly more favorable priority */
+    ANDROID_PRIORITY_DISPLAY        =  -4,
+
+    /* ui service treads might want to run at a urgent display (uncommon) */
+    ANDROID_PRIORITY_URGENT_DISPLAY =  HAL_PRIORITY_URGENT_DISPLAY,
+
+    /* all normal audio threads */
+    ANDROID_PRIORITY_AUDIO          = -16,
+
+    /* service audio threads (uncommon) */
+    ANDROID_PRIORITY_URGENT_AUDIO   = -19,
+
+    /* should never be used in practice. regular process might not
+     * be allowed to use this level */
+    ANDROID_PRIORITY_HIGHEST        = -20,
+
+    ANDROID_PRIORITY_DEFAULT        = ANDROID_PRIORITY_NORMAL,
+    ANDROID_PRIORITY_MORE_FAVORABLE = -1,
+    ANDROID_PRIORITY_LESS_FAVORABLE = +1,
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* ANDROID_THREAD_DEFS_H */
diff --git a/include/system/window.h b/include/system/window.h
index b8a19c8..649bd71 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -230,7 +230,13 @@
      * Boolean that indicates whether the consumer is running more than
      * one buffer behind the producer.
      */
-    NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND = 9
+    NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND = 9,
+
+    /*
+     * The consumer gralloc usage bits currently set by the consumer.
+     * The values are defined in hardware/libhardware/include/gralloc.h.
+     */
+    NATIVE_WINDOW_CONSUMER_USAGE_BITS = 10
 };
 
 /* Valid operations for the (*perform)() hook.
@@ -290,12 +296,15 @@
     NATIVE_WINDOW_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H ,
     /* flip source image vertically */
     NATIVE_WINDOW_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
-    /* rotate source image 90 degrees clock-wise */
+    /* rotate source image 90 degrees clock-wise, and is applied after TRANSFORM_FLIP_{H|V} */
     NATIVE_WINDOW_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
     /* rotate source image 180 degrees */
     NATIVE_WINDOW_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
     /* rotate source image 270 degrees clock-wise */
     NATIVE_WINDOW_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
+    /* transforms source by the inverse transform of the screen it is displayed onto. This
+     * transform is applied last */
+    NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY = 0x08
 };
 
 /* parameter for NATIVE_WINDOW_SET_SCALING_MODE */
diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h
index 25a56f7..c0a9418 100644
--- a/include/sysutils/NetlinkEvent.h
+++ b/include/sysutils/NetlinkEvent.h
@@ -34,6 +34,9 @@
     const static int NlActionChange;
     const static int NlActionLinkDown;
     const static int NlActionLinkUp;
+    const static int NlActionAddressUpdated;
+    const static int NlActionAddressRemoved;
+    const static int NlActionRdnss;
 
     NetlinkEvent();
     virtual ~NetlinkEvent();
@@ -49,6 +52,8 @@
  protected:
     bool parseBinaryNetlinkMessage(char *buffer, int size);
     bool parseAsciiNetlinkMessage(char *buffer, int size);
+    bool parseIfAddrMessage(int type, struct ifaddrmsg *ifaddr, int rtasize);
+    bool parseNdUserOptMessage(struct nduseroptmsg *msg, int optsize);
 };
 
 #endif
diff --git a/include/utils/AndroidThreads.h b/include/utils/AndroidThreads.h
new file mode 100644
index 0000000..4eee14d
--- /dev/null
+++ b/include/utils/AndroidThreads.h
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBS_UTILS_ANDROID_THREADS_H
+#define _LIBS_UTILS_ANDROID_THREADS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/ThreadDefs.h>
+
+// ---------------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Create and run a new thread.
+extern int androidCreateThread(android_thread_func_t, void *);
+
+// Create thread with lots of parameters
+extern int androidCreateThreadEtc(android_thread_func_t entryFunction,
+                                  void *userData,
+                                  const char* threadName,
+                                  int32_t threadPriority,
+                                  size_t threadStackSize,
+                                  android_thread_id_t *threadId);
+
+// Get some sort of unique identifier for the current thread.
+extern android_thread_id_t androidGetThreadId();
+
+// Low-level thread creation -- never creates threads that can
+// interact with the Java VM.
+extern int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
+                                     void *userData,
+                                     const char* threadName,
+                                     int32_t threadPriority,
+                                     size_t threadStackSize,
+                                     android_thread_id_t *threadId);
+
+// set the same of the running thread
+extern void androidSetThreadName(const char* name);
+
+// Used by the Java Runtime to control how threads are created, so that
+// they can be proper and lovely Java threads.
+typedef int (*android_create_thread_fn)(android_thread_func_t entryFunction,
+                                        void *userData,
+                                        const char* threadName,
+                                        int32_t threadPriority,
+                                        size_t threadStackSize,
+                                        android_thread_id_t *threadId);
+
+extern void androidSetCreateThreadFunc(android_create_thread_fn func);
+
+// ------------------------------------------------------------------
+// Extra functions working with raw pids.
+
+// Get pid for the current thread.
+extern pid_t androidGetTid();
+
+#ifdef HAVE_ANDROID_OS
+// Change the priority AND scheduling group of a particular thread.  The priority
+// should be one of the ANDROID_PRIORITY constants.  Returns INVALID_OPERATION
+// if the priority set failed, else another value if just the group set failed;
+// in either case errno is set.  Thread ID zero means current thread.
+extern int androidSetThreadPriority(pid_t tid, int prio);
+
+// Get the current priority of a particular thread. Returns one of the
+// ANDROID_PRIORITY constants or a negative result in case of error.
+extern int androidGetThreadPriority(pid_t tid);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// ----------------------------------------------------------------------------
+// C++ API
+#ifdef __cplusplus
+namespace android {
+// ----------------------------------------------------------------------------
+
+// Create and run a new thread.
+inline bool createThread(thread_func_t f, void *a) {
+    return androidCreateThread(f, a) ? true : false;
+}
+
+// Create thread with lots of parameters
+inline bool createThreadEtc(thread_func_t entryFunction,
+                            void *userData,
+                            const char* threadName = "android:unnamed_thread",
+                            int32_t threadPriority = PRIORITY_DEFAULT,
+                            size_t threadStackSize = 0,
+                            thread_id_t *threadId = 0)
+{
+    return androidCreateThreadEtc(entryFunction, userData, threadName,
+        threadPriority, threadStackSize, threadId) ? true : false;
+}
+
+// Get some sort of unique identifier for the current thread.
+inline thread_id_t getThreadId() {
+    return androidGetThreadId();
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+#endif  // __cplusplus
+// ----------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_ANDROID_THREADS_H
diff --git a/include/cutils/zygote.h b/include/utils/Atomic.h
similarity index 63%
rename from include/cutils/zygote.h
rename to include/utils/Atomic.h
index a7480d3..7eb476c 100644
--- a/include/cutils/zygote.h
+++ b/include/utils/Atomic.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2005 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.
@@ -14,18 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef __CUTILS_ZYGOTE_H
-#define __CUTILS_ZYGOTE_H
+#ifndef ANDROID_UTILS_ATOMIC_H
+#define ANDROID_UTILS_ATOMIC_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <cutils/atomic.h>
 
-int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
-int zygote_run(int argc, const char **argv);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CUTILS_ZYGOTE_H */
+#endif // ANDROID_UTILS_ATOMIC_H
diff --git a/include/utils/BasicHashtable.h b/include/utils/BasicHashtable.h
new file mode 100644
index 0000000..c235d62
--- /dev/null
+++ b/include/utils/BasicHashtable.h
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ANDROID_BASIC_HASHTABLE_H
+#define ANDROID_BASIC_HASHTABLE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/SharedBuffer.h>
+#include <utils/TypeHelpers.h>
+
+namespace android {
+
+/* Implementation type.  Nothing to see here. */
+class BasicHashtableImpl {
+protected:
+    struct Bucket {
+        // The collision flag indicates that the bucket is part of a collision chain
+        // such that at least two entries both hash to this bucket.  When true, we
+        // may need to seek further along the chain to find the entry.
+        static const uint32_t COLLISION = 0x80000000UL;
+
+        // The present flag indicates that the bucket contains an initialized entry value.
+        static const uint32_t PRESENT   = 0x40000000UL;
+
+        // Mask for 30 bits worth of the hash code that are stored within the bucket to
+        // speed up lookups and rehashing by eliminating the need to recalculate the
+        // hash code of the entry's key.
+        static const uint32_t HASH_MASK = 0x3fffffffUL;
+
+        // Combined value that stores the collision and present flags as well as
+        // a 30 bit hash code.
+        uint32_t cookie;
+
+        // Storage for the entry begins here.
+        char entry[0];
+    };
+
+    BasicHashtableImpl(size_t entrySize, bool hasTrivialDestructor,
+            size_t minimumInitialCapacity, float loadFactor);
+    BasicHashtableImpl(const BasicHashtableImpl& other);
+    virtual ~BasicHashtableImpl();
+
+    void dispose();
+
+    inline void edit() {
+        if (mBuckets && !SharedBuffer::bufferFromData(mBuckets)->onlyOwner()) {
+            clone();
+        }
+    }
+
+    void setTo(const BasicHashtableImpl& other);
+    void clear();
+
+    ssize_t next(ssize_t index) const;
+    ssize_t find(ssize_t index, hash_t hash, const void* __restrict__ key) const;
+    size_t add(hash_t hash, const void* __restrict__ entry);
+    void removeAt(size_t index);
+    void rehash(size_t minimumCapacity, float loadFactor);
+
+    const size_t mBucketSize; // number of bytes per bucket including the entry
+    const bool mHasTrivialDestructor; // true if the entry type does not require destruction
+    size_t mCapacity;         // number of buckets that can be filled before exceeding load factor
+    float mLoadFactor;        // load factor
+    size_t mSize;             // number of elements actually in the table
+    size_t mFilledBuckets;    // number of buckets for which collision or present is true
+    size_t mBucketCount;      // number of slots in the mBuckets array
+    void* mBuckets;           // array of buckets, as a SharedBuffer
+
+    inline const Bucket& bucketAt(const void* __restrict__ buckets, size_t index) const {
+        return *reinterpret_cast<const Bucket*>(
+                static_cast<const uint8_t*>(buckets) + index * mBucketSize);
+    }
+
+    inline Bucket& bucketAt(void* __restrict__ buckets, size_t index) const {
+        return *reinterpret_cast<Bucket*>(static_cast<uint8_t*>(buckets) + index * mBucketSize);
+    }
+
+    virtual bool compareBucketKey(const Bucket& bucket, const void* __restrict__ key) const = 0;
+    virtual void initializeBucketEntry(Bucket& bucket, const void* __restrict__ entry) const = 0;
+    virtual void destroyBucketEntry(Bucket& bucket) const = 0;
+
+private:
+    void clone();
+
+    // Allocates a bucket array as a SharedBuffer.
+    void* allocateBuckets(size_t count) const;
+
+    // Releases a bucket array's associated SharedBuffer.
+    void releaseBuckets(void* __restrict__ buckets, size_t count) const;
+
+    // Destroys the contents of buckets (invokes destroyBucketEntry for each
+    // populated bucket if needed).
+    void destroyBuckets(void* __restrict__ buckets, size_t count) const;
+
+    // Copies the content of buckets (copies the cookie and invokes copyBucketEntry
+    // for each populated bucket if needed).
+    void copyBuckets(const void* __restrict__ fromBuckets,
+            void* __restrict__ toBuckets, size_t count) const;
+
+    // Determines the appropriate size of a bucket array to store a certain minimum
+    // number of entries and returns its effective capacity.
+    static void determineCapacity(size_t minimumCapacity, float loadFactor,
+            size_t* __restrict__ outBucketCount, size_t* __restrict__ outCapacity);
+
+    // Trim a hash code to 30 bits to match what we store in the bucket's cookie.
+    inline static hash_t trimHash(hash_t hash) {
+        return (hash & Bucket::HASH_MASK) ^ (hash >> 30);
+    }
+
+    // Returns the index of the first bucket that is in the collision chain
+    // for the specified hash code, given the total number of buckets.
+    // (Primary hash)
+    inline static size_t chainStart(hash_t hash, size_t count) {
+        return hash % count;
+    }
+
+    // Returns the increment to add to a bucket index to seek to the next bucket
+    // in the collision chain for the specified hash code, given the total number of buckets.
+    // (Secondary hash)
+    inline static size_t chainIncrement(hash_t hash, size_t count) {
+        return ((hash >> 7) | (hash << 25)) % (count - 1) + 1;
+    }
+
+    // Returns the index of the next bucket that is in the collision chain
+    // that is defined by the specified increment, given the total number of buckets.
+    inline static size_t chainSeek(size_t index, size_t increment, size_t count) {
+        return (index + increment) % count;
+    }
+};
+
+/*
+ * A BasicHashtable stores entries that are indexed by hash code in place
+ * within an array.  The basic operations are finding entries by key,
+ * adding new entries and removing existing entries.
+ *
+ * This class provides a very limited set of operations with simple semantics.
+ * It is intended to be used as a building block to construct more complex
+ * and interesting data structures such as HashMap.  Think very hard before
+ * adding anything extra to BasicHashtable, it probably belongs at a
+ * higher level of abstraction.
+ *
+ * TKey: The key type.
+ * TEntry: The entry type which is what is actually stored in the array.
+ *
+ * TKey must support the following contract:
+ *     bool operator==(const TKey& other) const;  // return true if equal
+ *     bool operator!=(const TKey& other) const;  // return true if unequal
+ *
+ * TEntry must support the following contract:
+ *     const TKey& getKey() const;  // get the key from the entry
+ *
+ * This class supports storing entries with duplicate keys.  Of course, it can't
+ * tell them apart during removal so only the first entry will be removed.
+ * We do this because it means that operations like add() can't fail.
+ */
+template <typename TKey, typename TEntry>
+class BasicHashtable : private BasicHashtableImpl {
+public:
+    /* Creates a hashtable with the specified minimum initial capacity.
+     * The underlying array will be created when the first entry is added.
+     *
+     * minimumInitialCapacity: The minimum initial capacity for the hashtable.
+     *     Default is 0.
+     * loadFactor: The desired load factor for the hashtable, between 0 and 1.
+     *     Default is 0.75.
+     */
+    BasicHashtable(size_t minimumInitialCapacity = 0, float loadFactor = 0.75f);
+
+    /* Copies a hashtable.
+     * The underlying storage is shared copy-on-write.
+     */
+    BasicHashtable(const BasicHashtable& other);
+
+    /* Clears and destroys the hashtable.
+     */
+    virtual ~BasicHashtable();
+
+    /* Making this hashtable a copy of the other hashtable.
+     * The underlying storage is shared copy-on-write.
+     *
+     * other: The hashtable to copy.
+     */
+    inline BasicHashtable<TKey, TEntry>& operator =(const BasicHashtable<TKey, TEntry> & other) {
+        setTo(other);
+        return *this;
+    }
+
+    /* Returns the number of entries in the hashtable.
+     */
+    inline size_t size() const {
+        return mSize;
+    }
+
+    /* Returns the capacity of the hashtable, which is the number of elements that can
+     * added to the hashtable without requiring it to be grown.
+     */
+    inline size_t capacity() const {
+        return mCapacity;
+    }
+
+    /* Returns the number of buckets that the hashtable has, which is the size of its
+     * underlying array.
+     */
+    inline size_t bucketCount() const {
+        return mBucketCount;
+    }
+
+    /* Returns the load factor of the hashtable. */
+    inline float loadFactor() const {
+        return mLoadFactor;
+    };
+
+    /* Returns a const reference to the entry at the specified index.
+     *
+     * index:   The index of the entry to retrieve.  Must be a valid index within
+     *          the bounds of the hashtable.
+     */
+    inline const TEntry& entryAt(size_t index) const {
+        return entryFor(bucketAt(mBuckets, index));
+    }
+
+    /* Returns a non-const reference to the entry at the specified index.
+     *
+     * index: The index of the entry to edit.  Must be a valid index within
+     *        the bounds of the hashtable.
+     */
+    inline TEntry& editEntryAt(size_t index) {
+        edit();
+        return entryFor(bucketAt(mBuckets, index));
+    }
+
+    /* Clears the hashtable.
+     * All entries in the hashtable are destroyed immediately.
+     * If you need to do something special with the entries in the hashtable then iterate
+     * over them and do what you need before clearing the hashtable.
+     */
+    inline void clear() {
+        BasicHashtableImpl::clear();
+    }
+
+    /* Returns the index of the next entry in the hashtable given the index of a previous entry.
+     * If the given index is -1, then returns the index of the first entry in the hashtable,
+     * if there is one, or -1 otherwise.
+     * If the given index is not -1, then returns the index of the next entry in the hashtable,
+     * in strictly increasing order, or -1 if there are none left.
+     *
+     * index:   The index of the previous entry that was iterated, or -1 to begin
+     *          iteration at the beginning of the hashtable.
+     */
+    inline ssize_t next(ssize_t index) const {
+        return BasicHashtableImpl::next(index);
+    }
+
+    /* Finds the index of an entry with the specified key.
+     * If the given index is -1, then returns the index of the first matching entry,
+     * otherwise returns the index of the next matching entry.
+     * If the hashtable contains multiple entries with keys that match the requested
+     * key, then the sequence of entries returned is arbitrary.
+     * Returns -1 if no entry was found.
+     *
+     * index:   The index of the previous entry with the specified key, or -1 to
+     *          find the first matching entry.
+     * hash:    The hashcode of the key.
+     * key:     The key.
+     */
+    inline ssize_t find(ssize_t index, hash_t hash, const TKey& key) const {
+        return BasicHashtableImpl::find(index, hash, &key);
+    }
+
+    /* Adds the entry to the hashtable.
+     * Returns the index of the newly added entry.
+     * If an entry with the same key already exists, then a duplicate entry is added.
+     * If the entry will not fit, then the hashtable's capacity is increased and
+     * its contents are rehashed.  See rehash().
+     *
+     * hash:    The hashcode of the key.
+     * entry:   The entry to add.
+     */
+    inline size_t add(hash_t hash, const TEntry& entry) {
+        return BasicHashtableImpl::add(hash, &entry);
+    }
+
+    /* Removes the entry with the specified index from the hashtable.
+     * The entry is destroyed immediately.
+     * The index must be valid.
+     *
+     * The hashtable is not compacted after an item is removed, so it is legal
+     * to continue iterating over the hashtable using next() or find().
+     *
+     * index:   The index of the entry to remove.  Must be a valid index within the
+     *          bounds of the hashtable, and it must refer to an existing entry.
+     */
+    inline void removeAt(size_t index) {
+        BasicHashtableImpl::removeAt(index);
+    }
+
+    /* Rehashes the contents of the hashtable.
+     * Grows the hashtable to at least the specified minimum capacity or the
+     * current number of elements, whichever is larger.
+     *
+     * Rehashing causes all entries to be copied and the entry indices may change.
+     * Although the hash codes are cached by the hashtable, rehashing can be an
+     * expensive operation and should be avoided unless the hashtable's size
+     * needs to be changed.
+     *
+     * Rehashing is the only way to change the capacity or load factor of the
+     * hashtable once it has been created.  It can be used to compact the
+     * hashtable by choosing a minimum capacity that is smaller than the current
+     * capacity (such as 0).
+     *
+     * minimumCapacity: The desired minimum capacity after rehashing.
+     * loadFactor: The desired load factor after rehashing.
+     */
+    inline void rehash(size_t minimumCapacity, float loadFactor) {
+        BasicHashtableImpl::rehash(minimumCapacity, loadFactor);
+    }
+
+    /* Determines whether there is room to add another entry without rehashing.
+     * When this returns true, a subsequent add() operation is guaranteed to
+     * complete without performing a rehash.
+     */
+    inline bool hasMoreRoom() const {
+        return mCapacity > mFilledBuckets;
+    }
+
+protected:
+    static inline const TEntry& entryFor(const Bucket& bucket) {
+        return reinterpret_cast<const TEntry&>(bucket.entry);
+    }
+
+    static inline TEntry& entryFor(Bucket& bucket) {
+        return reinterpret_cast<TEntry&>(bucket.entry);
+    }
+
+    virtual bool compareBucketKey(const Bucket& bucket, const void* __restrict__ key) const;
+    virtual void initializeBucketEntry(Bucket& bucket, const void* __restrict__ entry) const;
+    virtual void destroyBucketEntry(Bucket& bucket) const;
+
+private:
+    // For dumping the raw contents of a hashtable during testing.
+    friend class BasicHashtableTest;
+    inline uint32_t cookieAt(size_t index) const {
+        return bucketAt(mBuckets, index).cookie;
+    }
+};
+
+template <typename TKey, typename TEntry>
+BasicHashtable<TKey, TEntry>::BasicHashtable(size_t minimumInitialCapacity, float loadFactor) :
+        BasicHashtableImpl(sizeof(TEntry), traits<TEntry>::has_trivial_dtor,
+                minimumInitialCapacity, loadFactor) {
+}
+
+template <typename TKey, typename TEntry>
+BasicHashtable<TKey, TEntry>::BasicHashtable(const BasicHashtable<TKey, TEntry>& other) :
+        BasicHashtableImpl(other) {
+}
+
+template <typename TKey, typename TEntry>
+BasicHashtable<TKey, TEntry>::~BasicHashtable() {
+    dispose();
+}
+
+template <typename TKey, typename TEntry>
+bool BasicHashtable<TKey, TEntry>::compareBucketKey(const Bucket& bucket,
+        const void* __restrict__ key) const {
+    return entryFor(bucket).getKey() == *static_cast<const TKey*>(key);
+}
+
+template <typename TKey, typename TEntry>
+void BasicHashtable<TKey, TEntry>::initializeBucketEntry(Bucket& bucket,
+        const void* __restrict__ entry) const {
+    if (!traits<TEntry>::has_trivial_copy) {
+        new (&entryFor(bucket)) TEntry(*(static_cast<const TEntry*>(entry)));
+    } else {
+        memcpy(&entryFor(bucket), entry, sizeof(TEntry));
+    }
+}
+
+template <typename TKey, typename TEntry>
+void BasicHashtable<TKey, TEntry>::destroyBucketEntry(Bucket& bucket) const {
+    if (!traits<TEntry>::has_trivial_dtor) {
+        entryFor(bucket).~TEntry();
+    }
+}
+
+}; // namespace android
+
+#endif // ANDROID_BASIC_HASHTABLE_H
diff --git a/include/utils/BitSet.h b/include/utils/BitSet.h
new file mode 100644
index 0000000..19c03d1
--- /dev/null
+++ b/include/utils/BitSet.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef UTILS_BITSET_H
+#define UTILS_BITSET_H
+
+#include <stdint.h>
+#include <utils/TypeHelpers.h>
+
+/*
+ * Contains some bit manipulation helpers.
+ */
+
+namespace android {
+
+// A simple set of 32 bits that can be individually marked or cleared.
+struct BitSet32 {
+    uint32_t value;
+
+    inline BitSet32() : value(0) { }
+    explicit inline BitSet32(uint32_t value) : value(value) { }
+
+    // Gets the value associated with a particular bit index.
+    static inline uint32_t valueForBit(uint32_t n) { return 0x80000000 >> n; }
+
+    // Clears the bit set.
+    inline void clear() { value = 0; }
+
+    // Returns the number of marked bits in the set.
+    inline uint32_t count() const { return __builtin_popcount(value); }
+
+    // Returns true if the bit set does not contain any marked bits.
+    inline bool isEmpty() const { return ! value; }
+
+    // Returns true if the bit set does not contain any unmarked bits.
+    inline bool isFull() const { return value == 0xffffffff; }
+
+    // Returns true if the specified bit is marked.
+    inline bool hasBit(uint32_t n) const { return value & valueForBit(n); }
+
+    // Marks the specified bit.
+    inline void markBit(uint32_t n) { value |= valueForBit(n); }
+
+    // Clears the specified bit.
+    inline void clearBit(uint32_t n) { value &= ~ valueForBit(n); }
+
+    // Finds the first marked bit in the set.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t firstMarkedBit() const { return __builtin_clz(value); }
+
+    // Finds the first unmarked bit in the set.
+    // Result is undefined if all bits are marked.
+    inline uint32_t firstUnmarkedBit() const { return __builtin_clz(~ value); }
+
+    // Finds the last marked bit in the set.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t lastMarkedBit() const { return 31 - __builtin_ctz(value); }
+
+    // Finds the first marked bit in the set and clears it.  Returns the bit index.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t clearFirstMarkedBit() {
+        uint32_t n = firstMarkedBit();
+        clearBit(n);
+        return n;
+    }
+
+    // Finds the first unmarked bit in the set and marks it.  Returns the bit index.
+    // Result is undefined if all bits are marked.
+    inline uint32_t markFirstUnmarkedBit() {
+        uint32_t n = firstUnmarkedBit();
+        markBit(n);
+        return n;
+    }
+
+    // Finds the last marked bit in the set and clears it.  Returns the bit index.
+    // Result is undefined if all bits are unmarked.
+    inline uint32_t clearLastMarkedBit() {
+        uint32_t n = lastMarkedBit();
+        clearBit(n);
+        return n;
+    }
+
+    // Gets the index of the specified bit in the set, which is the number of
+    // marked bits that appear before the specified bit.
+    inline uint32_t getIndexOfBit(uint32_t n) const {
+        return __builtin_popcount(value & ~(0xffffffffUL >> n));
+    }
+
+    inline bool operator== (const BitSet32& other) const { return value == other.value; }
+    inline bool operator!= (const BitSet32& other) const { return value != other.value; }
+    inline BitSet32 operator& (const BitSet32& other) const {
+        return BitSet32(value & other.value);
+    }
+    inline BitSet32& operator&= (const BitSet32& other) {
+        value &= other.value;
+        return *this;
+    }
+    inline BitSet32 operator| (const BitSet32& other) const {
+        return BitSet32(value | other.value);
+    }
+    inline BitSet32& operator|= (const BitSet32& other) {
+        value |= other.value;
+        return *this;
+    }
+};
+
+ANDROID_BASIC_TYPES_TRAITS(BitSet32)
+
+} // namespace android
+
+#endif // UTILS_BITSET_H
diff --git a/include/utils/BlobCache.h b/include/utils/BlobCache.h
new file mode 100644
index 0000000..7d621e4
--- /dev/null
+++ b/include/utils/BlobCache.h
@@ -0,0 +1,243 @@
+/*
+ ** Copyright 2011, 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.
+ */
+
+#ifndef ANDROID_BLOB_CACHE_H
+#define ANDROID_BLOB_CACHE_H
+
+#include <stddef.h>
+
+#include <utils/Flattenable.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/threads.h>
+
+namespace android {
+
+// A BlobCache is an in-memory cache for binary key/value pairs.  A BlobCache
+// does NOT provide any thread-safety guarantees.
+//
+// The cache contents can be serialized to an in-memory buffer or mmap'd file
+// and then reloaded in a subsequent execution of the program.  This
+// serialization is non-portable and the data should only be used by the device
+// that generated it.
+class BlobCache : public RefBase {
+
+public:
+
+    // Create an empty blob cache. The blob cache will cache key/value pairs
+    // with key and value sizes less than or equal to maxKeySize and
+    // maxValueSize, respectively. The total combined size of ALL cache entries
+    // (key sizes plus value sizes) will not exceed maxTotalSize.
+    BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize);
+
+    // set inserts a new binary value into the cache and associates it with the
+    // given binary key.  If the key or value are too large for the cache then
+    // the cache remains unchanged.  This includes the case where a different
+    // value was previously associated with the given key - the old value will
+    // remain in the cache.  If the given key and value are small enough to be
+    // put in the cache (based on the maxKeySize, maxValueSize, and maxTotalSize
+    // values specified to the BlobCache constructor), then the key/value pair
+    // will be in the cache after set returns.  Note, however, that a subsequent
+    // call to set may evict old key/value pairs from the cache.
+    //
+    // Preconditions:
+    //   key != NULL
+    //   0 < keySize
+    //   value != NULL
+    //   0 < valueSize
+    void set(const void* key, size_t keySize, const void* value,
+            size_t valueSize);
+
+    // get retrieves from the cache the binary value associated with a given
+    // binary key.  If the key is present in the cache then the length of the
+    // binary value associated with that key is returned.  If the value argument
+    // is non-NULL and the size of the cached value is less than valueSize bytes
+    // then the cached value is copied into the buffer pointed to by the value
+    // argument.  If the key is not present in the cache then 0 is returned and
+    // the buffer pointed to by the value argument is not modified.
+    //
+    // Note that when calling get multiple times with the same key, the later
+    // calls may fail, returning 0, even if earlier calls succeeded.  The return
+    // value must be checked for each call.
+    //
+    // Preconditions:
+    //   key != NULL
+    //   0 < keySize
+    //   0 <= valueSize
+    size_t get(const void* key, size_t keySize, void* value, size_t valueSize);
+
+
+    // getFlattenedSize returns the number of bytes needed to store the entire
+    // serialized cache.
+    size_t getFlattenedSize() const;
+
+    // flatten serializes the current contents of the cache into the memory
+    // pointed to by 'buffer'.  The serialized cache contents can later be
+    // loaded into a BlobCache object using the unflatten method.  The contents
+    // of the BlobCache object will not be modified.
+    //
+    // Preconditions:
+    //   size >= this.getFlattenedSize()
+    status_t flatten(void* buffer, size_t size) const;
+
+    // unflatten replaces the contents of the cache with the serialized cache
+    // contents in the memory pointed to by 'buffer'.  The previous contents of
+    // the BlobCache will be evicted from the cache.  If an error occurs while
+    // unflattening the serialized cache contents then the BlobCache will be
+    // left in an empty state.
+    //
+    status_t unflatten(void const* buffer, size_t size);
+
+private:
+    // Copying is disallowed.
+    BlobCache(const BlobCache&);
+    void operator=(const BlobCache&);
+
+    // A random function helper to get around MinGW not having nrand48()
+    long int blob_random();
+
+    // clean evicts a randomly chosen set of entries from the cache such that
+    // the total size of all remaining entries is less than mMaxTotalSize/2.
+    void clean();
+
+    // isCleanable returns true if the cache is full enough for the clean method
+    // to have some effect, and false otherwise.
+    bool isCleanable() const;
+
+    // A Blob is an immutable sized unstructured data blob.
+    class Blob : public RefBase {
+    public:
+        Blob(const void* data, size_t size, bool copyData);
+        ~Blob();
+
+        bool operator<(const Blob& rhs) const;
+
+        const void* getData() const;
+        size_t getSize() const;
+
+    private:
+        // Copying is not allowed.
+        Blob(const Blob&);
+        void operator=(const Blob&);
+
+        // mData points to the buffer containing the blob data.
+        const void* mData;
+
+        // mSize is the size of the blob data in bytes.
+        size_t mSize;
+
+        // mOwnsData indicates whether or not this Blob object should free the
+        // memory pointed to by mData when the Blob gets destructed.
+        bool mOwnsData;
+    };
+
+    // A CacheEntry is a single key/value pair in the cache.
+    class CacheEntry {
+    public:
+        CacheEntry();
+        CacheEntry(const sp<Blob>& key, const sp<Blob>& value);
+        CacheEntry(const CacheEntry& ce);
+
+        bool operator<(const CacheEntry& rhs) const;
+        const CacheEntry& operator=(const CacheEntry&);
+
+        sp<Blob> getKey() const;
+        sp<Blob> getValue() const;
+
+        void setValue(const sp<Blob>& value);
+
+    private:
+
+        // mKey is the key that identifies the cache entry.
+        sp<Blob> mKey;
+
+        // mValue is the cached data associated with the key.
+        sp<Blob> mValue;
+    };
+
+    // A Header is the header for the entire BlobCache serialization format. No
+    // need to make this portable, so we simply write the struct out.
+    struct Header {
+        // mMagicNumber is the magic number that identifies the data as
+        // serialized BlobCache contents.  It must always contain 'Blb$'.
+        uint32_t mMagicNumber;
+
+        // mBlobCacheVersion is the serialization format version.
+        uint32_t mBlobCacheVersion;
+
+        // mDeviceVersion is the device-specific version of the cache.  This can
+        // be used to invalidate the cache.
+        uint32_t mDeviceVersion;
+
+        // mNumEntries is number of cache entries following the header in the
+        // data.
+        size_t mNumEntries;
+    };
+
+    // An EntryHeader is the header for a serialized cache entry.  No need to
+    // make this portable, so we simply write the struct out.  Each EntryHeader
+    // is followed imediately by the key data and then the value data.
+    //
+    // The beginning of each serialized EntryHeader is 4-byte aligned, so the
+    // number of bytes that a serialized cache entry will occupy is:
+    //
+    //   ((sizeof(EntryHeader) + keySize + valueSize) + 3) & ~3
+    //
+    struct EntryHeader {
+        // mKeySize is the size of the entry key in bytes.
+        size_t mKeySize;
+
+        // mValueSize is the size of the entry value in bytes.
+        size_t mValueSize;
+
+        // mData contains both the key and value data for the cache entry.  The
+        // key comes first followed immediately by the value.
+        uint8_t mData[];
+    };
+
+    // mMaxKeySize is the maximum key size that will be cached. Calls to
+    // BlobCache::set with a keySize parameter larger than mMaxKeySize will
+    // simply not add the key/value pair to the cache.
+    const size_t mMaxKeySize;
+
+    // mMaxValueSize is the maximum value size that will be cached. Calls to
+    // BlobCache::set with a valueSize parameter larger than mMaxValueSize will
+    // simply not add the key/value pair to the cache.
+    const size_t mMaxValueSize;
+
+    // mMaxTotalSize is the maximum size that all cache entries can occupy. This
+    // includes space for both keys and values. When a call to BlobCache::set
+    // would otherwise cause this limit to be exceeded, either the key/value
+    // pair passed to BlobCache::set will not be cached or other cache entries
+    // will be evicted from the cache to make room for the new entry.
+    const size_t mMaxTotalSize;
+
+    // mTotalSize is the total combined size of all keys and values currently in
+    // the cache.
+    size_t mTotalSize;
+
+    // mRandState is the pseudo-random number generator state. It is passed to
+    // nrand48 to generate random numbers when needed.
+    unsigned short mRandState[3];
+
+    // mCacheEntries stores all the cache entries that are resident in memory.
+    // Cache entries are added to it by the 'set' method.
+    SortedVector<CacheEntry> mCacheEntries;
+};
+
+}
+
+#endif // ANDROID_BLOB_CACHE_H
diff --git a/include/utils/ByteOrder.h b/include/utils/ByteOrder.h
new file mode 100644
index 0000000..baa3a83
--- /dev/null
+++ b/include/utils/ByteOrder.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+//
+
+#ifndef _LIBS_UTILS_BYTE_ORDER_H
+#define _LIBS_UTILS_BYTE_ORDER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#ifdef HAVE_WINSOCK
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#endif
+
+/*
+ * These macros are like the hton/ntoh byte swapping macros,
+ * except they allow you to swap to and from the "device" byte
+ * order.  The device byte order is the endianness of the target
+ * device -- for the ARM CPUs we use today, this is little endian.
+ *
+ * Note that the byte swapping functions have not been optimized
+ * much; performance is currently not an issue for them since the
+ * intent is to allow us to avoid byte swapping on the device.
+ */
+
+static inline uint32_t android_swap_long(uint32_t v)
+{
+    return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
+}
+
+static inline uint16_t android_swap_short(uint16_t v)
+{
+    return (v<<8) | (v>>8);
+}
+
+#define DEVICE_BYTE_ORDER LITTLE_ENDIAN
+
+#if BYTE_ORDER == DEVICE_BYTE_ORDER
+
+#define	dtohl(x)	(x)
+#define	dtohs(x)	(x)
+#define	htodl(x)	(x)
+#define	htods(x)	(x)
+
+#else
+
+#define	dtohl(x)	(android_swap_long(x))
+#define	dtohs(x)	(android_swap_short(x))
+#define	htodl(x)	(android_swap_long(x))
+#define	htods(x)	(android_swap_short(x))
+
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define fromlel(x) (x)
+#define fromles(x) (x)
+#define tolel(x) (x)
+#define toles(x) (x)
+#else
+#define fromlel(x) (android_swap_long(x))
+#define fromles(x) (android_swap_short(x))
+#define tolel(x) (android_swap_long(x))
+#define toles(x) (android_swap_short(x))
+#endif
+
+#endif // _LIBS_UTILS_BYTE_ORDER_H
diff --git a/include/utils/CallStack.h b/include/utils/CallStack.h
new file mode 100644
index 0000000..2056751
--- /dev/null
+++ b/include/utils/CallStack.h
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_CALLSTACK_H
+#define ANDROID_CALLSTACK_H
+
+#include <android/log.h>
+#include <utils/String8.h>
+#include <corkscrew/backtrace.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+
+class Printer;
+
+// Collect/print the call stack (function, file, line) traces for a single thread.
+class CallStack {
+public:
+    enum {
+        // Prune the lowest-most stack frames until we have at most MAX_DEPTH.
+        MAX_DEPTH = 31,
+        // Placeholder for specifying the current thread when updating the stack.
+        CURRENT_THREAD = -1,
+    };
+
+    // Create an empty call stack. No-op.
+    CallStack();
+    // Create a callstack with the current thread's stack trace.
+    // Immediately dump it to logcat using the given logtag.
+    CallStack(const char* logtag, int32_t ignoreDepth=1,
+            int32_t maxDepth=MAX_DEPTH);
+    // Copy the existing callstack (no other side effects).
+    CallStack(const CallStack& rhs);
+    ~CallStack();
+
+    // Copy the existing callstack (no other side effects).
+    CallStack& operator = (const CallStack& rhs);
+
+    // Compare call stacks by their backtrace frame memory.
+    bool operator == (const CallStack& rhs) const;
+    bool operator != (const CallStack& rhs) const;
+    bool operator < (const CallStack& rhs) const;
+    bool operator >= (const CallStack& rhs) const;
+    bool operator > (const CallStack& rhs) const;
+    bool operator <= (const CallStack& rhs) const;
+
+    // Get the PC address for the stack frame specified by index.
+    const void* operator [] (int index) const;
+
+    // Reset the stack frames (same as creating an empty call stack).
+    void clear();
+
+    // Immediately collect the stack traces for the specified thread.
+    void update(int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH, pid_t tid=CURRENT_THREAD);
+
+    // Dump a stack trace to the log using the supplied logtag.
+    void log(const char* logtag,
+             android_LogPriority priority = ANDROID_LOG_DEBUG,
+             const char* prefix = 0) const;
+
+    // Dump a stack trace to the specified file descriptor.
+    void dump(int fd, int indent = 0, const char* prefix = 0) const;
+
+    // Return a string (possibly very long) containing the complete stack trace.
+    String8 toString(const char* prefix = 0) const;
+
+    // Dump a serialized representation of the stack trace to the specified printer.
+    void print(Printer& printer) const;
+
+    // Get the count of stack frames that are in this call stack.
+    size_t size() const { return mCount; }
+
+private:
+    size_t mCount;
+    backtrace_frame_t mStack[MAX_DEPTH];
+};
+
+}; // namespace android
+
+#endif // ANDROID_CALLSTACK_H
diff --git a/include/utils/Compat.h b/include/utils/Compat.h
new file mode 100644
index 0000000..fb7748e
--- /dev/null
+++ b/include/utils/Compat.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __LIB_UTILS_COMPAT_H
+#define __LIB_UTILS_COMPAT_H
+
+#include <unistd.h>
+
+/* Compatibility definitions for non-Linux (i.e., BSD-based) hosts. */
+#ifndef HAVE_OFF64_T
+#if _FILE_OFFSET_BITS < 64
+#error "_FILE_OFFSET_BITS < 64; large files are not supported on this platform"
+#endif /* _FILE_OFFSET_BITS < 64 */
+
+typedef off_t off64_t;
+
+static inline off64_t lseek64(int fd, off64_t offset, int whence) {
+    return lseek(fd, offset, whence);
+}
+
+#ifdef HAVE_PREAD
+static inline ssize_t pread64(int fd, void* buf, size_t nbytes, off64_t offset) {
+    return pread(fd, buf, nbytes, offset);
+}
+#endif
+
+#endif /* !HAVE_OFF64_T */
+
+#if HAVE_PRINTF_ZD
+#  define ZD "%zd"
+#  define ZD_TYPE ssize_t
+#else
+#  define ZD "%ld"
+#  define ZD_TYPE long
+#endif
+
+/*
+ * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
+ * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
+ * not already defined, then define it here.
+ */
+#ifndef TEMP_FAILURE_RETRY
+/* Used to retry syscalls that can return EINTR. */
+#define TEMP_FAILURE_RETRY(exp) ({         \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+#endif
+
+#endif /* __LIB_UTILS_COMPAT_H */
diff --git a/include/utils/Condition.h b/include/utils/Condition.h
new file mode 100644
index 0000000..e63ba7e
--- /dev/null
+++ b/include/utils/Condition.h
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBS_UTILS_CONDITION_H
+#define _LIBS_UTILS_CONDITION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/Timers.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+/*
+ * Condition variable class.  The implementation is system-dependent.
+ *
+ * Condition variables are paired up with mutexes.  Lock the mutex,
+ * call wait(), then either re-wait() if things aren't quite what you want,
+ * or unlock the mutex and continue.  All threads calling wait() must
+ * use the same mutex for a given Condition.
+ */
+class Condition {
+public:
+    enum {
+        PRIVATE = 0,
+        SHARED = 1
+    };
+
+    enum WakeUpType {
+        WAKE_UP_ONE = 0,
+        WAKE_UP_ALL = 1
+    };
+
+    Condition();
+    Condition(int type);
+    ~Condition();
+    // Wait on the condition variable.  Lock the mutex before calling.
+    status_t wait(Mutex& mutex);
+    // same with relative timeout
+    status_t waitRelative(Mutex& mutex, nsecs_t reltime);
+    // Signal the condition variable, allowing one thread to continue.
+    void signal();
+    // Signal the condition variable, allowing one or all threads to continue.
+    void signal(WakeUpType type) {
+        if (type == WAKE_UP_ONE) {
+            signal();
+        } else {
+            broadcast();
+        }
+    }
+    // Signal the condition variable, allowing all threads to continue.
+    void broadcast();
+
+private:
+#if defined(HAVE_PTHREADS)
+    pthread_cond_t mCond;
+#else
+    void*   mState;
+#endif
+};
+
+// ---------------------------------------------------------------------------
+
+#if defined(HAVE_PTHREADS)
+
+inline Condition::Condition() {
+    pthread_cond_init(&mCond, NULL);
+}
+inline Condition::Condition(int type) {
+    if (type == SHARED) {
+        pthread_condattr_t attr;
+        pthread_condattr_init(&attr);
+        pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+        pthread_cond_init(&mCond, &attr);
+        pthread_condattr_destroy(&attr);
+    } else {
+        pthread_cond_init(&mCond, NULL);
+    }
+}
+inline Condition::~Condition() {
+    pthread_cond_destroy(&mCond);
+}
+inline status_t Condition::wait(Mutex& mutex) {
+    return -pthread_cond_wait(&mCond, &mutex.mMutex);
+}
+inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
+#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
+    struct timespec ts;
+    ts.tv_sec  = reltime/1000000000;
+    ts.tv_nsec = reltime%1000000000;
+    return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
+#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
+    struct timespec ts;
+#if defined(HAVE_POSIX_CLOCKS)
+    clock_gettime(CLOCK_REALTIME, &ts);
+#else // HAVE_POSIX_CLOCKS
+    // we don't support the clocks here.
+    struct timeval t;
+    gettimeofday(&t, NULL);
+    ts.tv_sec = t.tv_sec;
+    ts.tv_nsec= t.tv_usec*1000;
+#endif // HAVE_POSIX_CLOCKS
+    ts.tv_sec += reltime/1000000000;
+    ts.tv_nsec+= reltime%1000000000;
+    if (ts.tv_nsec >= 1000000000) {
+        ts.tv_nsec -= 1000000000;
+        ts.tv_sec  += 1;
+    }
+    return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
+#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
+}
+inline void Condition::signal() {
+    pthread_cond_signal(&mCond);
+}
+inline void Condition::broadcast() {
+    pthread_cond_broadcast(&mCond);
+}
+
+#endif // HAVE_PTHREADS
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_CONDITON_H
diff --git a/include/utils/Debug.h b/include/utils/Debug.h
new file mode 100644
index 0000000..08893bd
--- /dev/null
+++ b/include/utils/Debug.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_UTILS_DEBUG_H
+#define ANDROID_UTILS_DEBUG_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+template<bool> struct CompileTimeAssert;
+template<> struct CompileTimeAssert<true> {};
+#define COMPILE_TIME_ASSERT(_exp) \
+    template class CompileTimeAssert< (_exp) >;
+#endif
+#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
+    CompileTimeAssert<( _exp )>();
+
+// ---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+template<bool C, typename LSH, typename RHS> struct CompileTimeIfElse;
+template<typename LHS, typename RHS> 
+struct CompileTimeIfElse<true,  LHS, RHS> { typedef LHS TYPE; };
+template<typename LHS, typename RHS> 
+struct CompileTimeIfElse<false, LHS, RHS> { typedef RHS TYPE; };
+#endif
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_UTILS_DEBUG_H
diff --git a/include/utils/Endian.h b/include/utils/Endian.h
new file mode 100644
index 0000000..19f2504
--- /dev/null
+++ b/include/utils/Endian.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Android endian-ness defines.
+//
+#ifndef _LIBS_UTILS_ENDIAN_H
+#define _LIBS_UTILS_ENDIAN_H
+
+#if defined(HAVE_ENDIAN_H)
+
+#include <endian.h>
+
+#else /*not HAVE_ENDIAN_H*/
+
+#define __BIG_ENDIAN 0x1000
+#define __LITTLE_ENDIAN 0x0001
+
+#if defined(HAVE_LITTLE_ENDIAN)
+# define __BYTE_ORDER __LITTLE_ENDIAN
+#else
+# define __BYTE_ORDER __BIG_ENDIAN
+#endif
+
+#endif /*not HAVE_ENDIAN_H*/
+
+#endif /*_LIBS_UTILS_ENDIAN_H*/
diff --git a/include/utils/Errors.h b/include/utils/Errors.h
new file mode 100644
index 0000000..0b75b19
--- /dev/null
+++ b/include/utils/Errors.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_ERRORS_H
+#define ANDROID_ERRORS_H
+
+#include <sys/types.h>
+#include <errno.h>
+
+namespace android {
+
+// use this type to return error codes
+#ifdef HAVE_MS_C_RUNTIME
+typedef int         status_t;
+#else
+typedef int32_t     status_t;
+#endif
+
+/* the MS C runtime lacks a few error codes */
+
+/*
+ * Error codes. 
+ * All error codes are negative values.
+ */
+
+// Win32 #defines NO_ERROR as well.  It has the same value, so there's no
+// real conflict, though it's a bit awkward.
+#ifdef _WIN32
+# undef NO_ERROR
+#endif
+ 
+enum {
+    OK                = 0,    // Everything's swell.
+    NO_ERROR          = 0,    // No errors.
+    
+    UNKNOWN_ERROR       = 0x80000000,
+
+    NO_MEMORY           = -ENOMEM,
+    INVALID_OPERATION   = -ENOSYS,
+    BAD_VALUE           = -EINVAL,
+    BAD_TYPE            = 0x80000001,
+    NAME_NOT_FOUND      = -ENOENT,
+    PERMISSION_DENIED   = -EPERM,
+    NO_INIT             = -ENODEV,
+    ALREADY_EXISTS      = -EEXIST,
+    DEAD_OBJECT         = -EPIPE,
+    FAILED_TRANSACTION  = 0x80000002,
+    JPARKS_BROKE_IT     = -EPIPE,
+#if !defined(HAVE_MS_C_RUNTIME)
+    BAD_INDEX           = -EOVERFLOW,
+    NOT_ENOUGH_DATA     = -ENODATA,
+    WOULD_BLOCK         = -EWOULDBLOCK, 
+    TIMED_OUT           = -ETIMEDOUT,
+    UNKNOWN_TRANSACTION = -EBADMSG,
+#else    
+    BAD_INDEX           = -E2BIG,
+    NOT_ENOUGH_DATA     = 0x80000003,
+    WOULD_BLOCK         = 0x80000004,
+    TIMED_OUT           = 0x80000005,
+    UNKNOWN_TRANSACTION = 0x80000006,
+#endif    
+    FDS_NOT_ALLOWED     = 0x80000007,
+};
+
+// Restore define; enumeration is in "android" namespace, so the value defined
+// there won't work for Win32 code in a different namespace.
+#ifdef _WIN32
+# define NO_ERROR 0L
+#endif
+
+}; // namespace android
+    
+// ---------------------------------------------------------------------------
+    
+#endif // ANDROID_ERRORS_H
diff --git a/include/utils/FileMap.h b/include/utils/FileMap.h
new file mode 100644
index 0000000..dfe6d51
--- /dev/null
+++ b/include/utils/FileMap.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+//
+// Encapsulate a shared file mapping.
+//
+#ifndef __LIBS_FILE_MAP_H
+#define __LIBS_FILE_MAP_H
+
+#include <sys/types.h>
+
+#include <utils/Compat.h>
+
+#ifdef HAVE_WIN32_FILEMAP
+#include <windows.h>
+#endif
+
+namespace android {
+
+/*
+ * This represents a memory-mapped file.  It might be the entire file or
+ * only part of it.  This requires a little bookkeeping because the mapping
+ * needs to be aligned on page boundaries, and in some cases we'd like to
+ * have multiple references to the mapped area without creating additional
+ * maps.
+ *
+ * This always uses MAP_SHARED.
+ *
+ * TODO: we should be able to create a new FileMap that is a subset of
+ * an existing FileMap and shares the underlying mapped pages.  Requires
+ * completing the refcounting stuff and possibly introducing the notion
+ * of a FileMap hierarchy.
+ */
+class FileMap {
+public:
+    FileMap(void);
+
+    /*
+     * Create a new mapping on an open file.
+     *
+     * Closing the file descriptor does not unmap the pages, so we don't
+     * claim ownership of the fd.
+     *
+     * Returns "false" on failure.
+     */
+    bool create(const char* origFileName, int fd,
+                off64_t offset, size_t length, bool readOnly);
+
+    /*
+     * Return the name of the file this map came from, if known.
+     */
+    const char* getFileName(void) const { return mFileName; }
+    
+    /*
+     * Get a pointer to the piece of the file we requested.
+     */
+    void* getDataPtr(void) const { return mDataPtr; }
+
+    /*
+     * Get the length we requested.
+     */
+    size_t getDataLength(void) const { return mDataLength; }
+
+    /*
+     * Get the data offset used to create this map.
+     */
+    off64_t getDataOffset(void) const { return mDataOffset; }
+
+    /*
+     * Get a "copy" of the object.
+     */
+    FileMap* acquire(void) { mRefCount++; return this; }
+
+    /*
+     * Call this when mapping is no longer needed.
+     */
+    void release(void) {
+        if (--mRefCount <= 0)
+            delete this;
+    }
+
+    /*
+     * This maps directly to madvise() values, but allows us to avoid
+     * including <sys/mman.h> everywhere.
+     */
+    enum MapAdvice {
+        NORMAL, RANDOM, SEQUENTIAL, WILLNEED, DONTNEED
+    };
+
+    /*
+     * Apply an madvise() call to the entire file.
+     *
+     * Returns 0 on success, -1 on failure.
+     */
+    int advise(MapAdvice advice);
+
+protected:
+    // don't delete objects; call release()
+    ~FileMap(void);
+
+private:
+    // these are not implemented
+    FileMap(const FileMap& src);
+    const FileMap& operator=(const FileMap& src);
+
+    int         mRefCount;      // reference count
+    char*       mFileName;      // original file name, if known
+    void*       mBasePtr;       // base of mmap area; page aligned
+    size_t      mBaseLength;    // length, measured from "mBasePtr"
+    off64_t     mDataOffset;    // offset used when map was created
+    void*       mDataPtr;       // start of requested data, offset from base
+    size_t      mDataLength;    // length, measured from "mDataPtr"
+#ifdef HAVE_WIN32_FILEMAP
+    HANDLE      mFileHandle;    // Win32 file handle
+    HANDLE      mFileMapping;   // Win32 file mapping handle
+#endif
+
+    static long mPageSize;
+};
+
+}; // namespace android
+
+#endif // __LIBS_FILE_MAP_H
diff --git a/include/utils/Flattenable.h b/include/utils/Flattenable.h
new file mode 100644
index 0000000..882a8b2
--- /dev/null
+++ b/include/utils/Flattenable.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef ANDROID_UTILS_FLATTENABLE_H
+#define ANDROID_UTILS_FLATTENABLE_H
+
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/Debug.h>
+
+namespace android {
+
+
+class FlattenableUtils {
+public:
+    template<int N>
+    static size_t align(size_t size) {
+        COMPILE_TIME_ASSERT_FUNCTION_SCOPE( !(N & (N-1)) );
+        return (size + (N-1)) & ~(N-1);
+    }
+
+    template<int N>
+    static size_t align(void const*& buffer) {
+        COMPILE_TIME_ASSERT_FUNCTION_SCOPE( !(N & (N-1)) );
+        intptr_t b = intptr_t(buffer);
+        buffer = (void*)((intptr_t(buffer) + (N-1)) & ~(N-1));
+        return size_t(intptr_t(buffer) - b);
+    }
+
+    template<int N>
+    static size_t align(void*& buffer) {
+        return align<N>( const_cast<void const*&>(buffer) );
+    }
+
+    static void advance(void*& buffer, size_t& size, size_t offset) {
+        buffer = reinterpret_cast<void*>( intptr_t(buffer) + offset );
+        size -= offset;
+    }
+
+    static void advance(void const*& buffer, size_t& size, size_t offset) {
+        buffer = reinterpret_cast<void const*>( intptr_t(buffer) + offset );
+        size -= offset;
+    }
+
+    // write a POD structure
+    template<typename T>
+    static void write(void*& buffer, size_t& size, const T& value) {
+        *static_cast<T*>(buffer) = value;
+        advance(buffer, size, sizeof(T));
+    }
+
+    // read a POD structure
+    template<typename T>
+    static void read(void const*& buffer, size_t& size, T& value) {
+        value = *static_cast<T const*>(buffer);
+        advance(buffer, size, sizeof(T));
+    }
+};
+
+
+/*
+ * The Flattenable protocol allows an object to serialize itself out
+ * to a byte-buffer and an array of file descriptors.
+ * Flattenable objects must implement this protocol.
+ */
+
+template <typename T>
+class Flattenable {
+public:
+    // size in bytes of the flattened object
+    inline size_t getFlattenedSize() const;
+
+    // number of file descriptors to flatten
+    inline size_t getFdCount() const;
+
+    // flattens the object into buffer.
+    // size should be at least of getFlattenedSize()
+    // file descriptors are written in the fds[] array but ownership is
+    // not transfered (ie: they must be dupped by the caller of
+    // flatten() if needed).
+    inline status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
+
+    // unflattens the object from buffer.
+    // size should be equal to the value of getFlattenedSize() when the
+    // object was flattened.
+    // unflattened file descriptors are found in the fds[] array and
+    // don't need to be dupped(). ie: the caller of unflatten doesn't
+    // keep ownership. If a fd is not retained by unflatten() it must be
+    // explicitly closed.
+    inline status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
+};
+
+template<typename T>
+inline size_t Flattenable<T>::getFlattenedSize() const {
+    return static_cast<T const*>(this)->T::getFlattenedSize();
+}
+template<typename T>
+inline size_t Flattenable<T>::getFdCount() const {
+    return static_cast<T const*>(this)->T::getFdCount();
+}
+template<typename T>
+inline status_t Flattenable<T>::flatten(
+        void*& buffer, size_t& size, int*& fds, size_t& count) const {
+    return static_cast<T const*>(this)->T::flatten(buffer, size, fds, count);
+}
+template<typename T>
+inline status_t Flattenable<T>::unflatten(
+        void const*& buffer, size_t& size, int const*& fds, size_t& count) {
+    return static_cast<T*>(this)->T::unflatten(buffer, size, fds, count);
+}
+
+/*
+ * LightFlattenable is a protocol allowing object to serialize themselves out
+ * to a byte-buffer. Because it doesn't handle file-descriptors,
+ * LightFlattenable is usually more size efficient than Flattenable.
+ * LightFlattenable objects must implement this protocol.
+ */
+template <typename T>
+class LightFlattenable {
+public:
+    // returns whether this object always flatten into the same size.
+    // for efficiency, this should always be inline.
+    inline bool isFixedSize() const;
+
+    // returns size in bytes of the flattened object. must be a constant.
+    inline size_t getFlattenedSize() const;
+
+    // flattens the object into buffer.
+    inline status_t flatten(void* buffer, size_t size) const;
+
+    // unflattens the object from buffer of given size.
+    inline status_t unflatten(void const* buffer, size_t size);
+};
+
+template <typename T>
+inline bool LightFlattenable<T>::isFixedSize() const {
+    return static_cast<T const*>(this)->T::isFixedSize();
+}
+template <typename T>
+inline size_t LightFlattenable<T>::getFlattenedSize() const {
+    return static_cast<T const*>(this)->T::getFlattenedSize();
+}
+template <typename T>
+inline status_t LightFlattenable<T>::flatten(void* buffer, size_t size) const {
+    return static_cast<T const*>(this)->T::flatten(buffer, size);
+}
+template <typename T>
+inline status_t LightFlattenable<T>::unflatten(void const* buffer, size_t size) {
+    return static_cast<T*>(this)->T::unflatten(buffer, size);
+}
+
+/*
+ * LightFlattenablePod is an implementation of the LightFlattenable protocol
+ * for POD (plain-old-data) objects.
+ * Simply derive from LightFlattenablePod<Foo> to make Foo flattenable; no
+ * need to implement any methods; obviously Foo must be a POD structure.
+ */
+template <typename T>
+class LightFlattenablePod : public LightFlattenable<T> {
+public:
+    inline bool isFixedSize() const {
+        return true;
+    }
+
+    inline size_t getFlattenedSize() const {
+        return sizeof(T);
+    }
+    inline status_t flatten(void* buffer, size_t size) const {
+        if (size < sizeof(T)) return NO_MEMORY;
+        *reinterpret_cast<T*>(buffer) = *static_cast<T const*>(this);
+        return NO_ERROR;
+    }
+    inline status_t unflatten(void const* buffer, size_t) {
+        *static_cast<T*>(this) = *reinterpret_cast<T const*>(buffer);
+        return NO_ERROR;
+    }
+};
+
+
+}; // namespace android
+
+
+#endif /* ANDROID_UTILS_FLATTENABLE_H */
diff --git a/include/cutils/zygote.h b/include/utils/Functor.h
similarity index 61%
copy from include/cutils/zygote.h
copy to include/utils/Functor.h
index a7480d3..e24ded4 100644
--- a/include/cutils/zygote.h
+++ b/include/utils/Functor.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2011 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.
@@ -14,18 +14,20 @@
  * limitations under the License.
  */
 
-#ifndef __CUTILS_ZYGOTE_H
-#define __CUTILS_ZYGOTE_H
+#ifndef ANDROID_FUNCTOR_H
+#define ANDROID_FUNCTOR_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <utils/Errors.h>
 
-int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
-int zygote_run(int argc, const char **argv);
+namespace  android {
 
-#ifdef __cplusplus
-}
-#endif
+class Functor {
+public:
+    Functor() {}
+    virtual ~Functor() {}
+    virtual status_t operator ()(int what, void* data) { return NO_ERROR; }
+};
 
-#endif /* __CUTILS_ZYGOTE_H */
+}; // namespace android
+
+#endif // ANDROID_FUNCTOR_H
diff --git a/include/utils/JenkinsHash.h b/include/utils/JenkinsHash.h
new file mode 100644
index 0000000..7da5dbd
--- /dev/null
+++ b/include/utils/JenkinsHash.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/* Implementation of Jenkins one-at-a-time hash function. These choices are
+ * optimized for code size and portability, rather than raw speed. But speed
+ * should still be quite good.
+ **/
+
+#ifndef ANDROID_JENKINS_HASH_H
+#define ANDROID_JENKINS_HASH_H
+
+#include <utils/TypeHelpers.h>
+
+namespace android {
+
+/* The Jenkins hash of a sequence of 32 bit words A, B, C is:
+ * Whiten(Mix(Mix(Mix(0, A), B), C)) */
+
+inline uint32_t JenkinsHashMix(uint32_t hash, uint32_t data) {
+    hash += data;
+    hash += (hash << 10);
+    hash ^= (hash >> 6);
+    return hash;
+}
+
+hash_t JenkinsHashWhiten(uint32_t hash);
+
+/* Helpful utility functions for hashing data in 32 bit chunks */
+uint32_t JenkinsHashMixBytes(uint32_t hash, const uint8_t* bytes, size_t size);
+
+uint32_t JenkinsHashMixShorts(uint32_t hash, const uint16_t* shorts, size_t size);
+
+}
+
+#endif // ANDROID_JENKINS_HASH_H
diff --git a/include/utils/KeyedVector.h b/include/utils/KeyedVector.h
new file mode 100644
index 0000000..c4faae0
--- /dev/null
+++ b/include/utils/KeyedVector.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_KEYED_VECTOR_H
+#define ANDROID_KEYED_VECTOR_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/log.h>
+
+#include <utils/SortedVector.h>
+#include <utils/TypeHelpers.h>
+#include <utils/Errors.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <typename KEY, typename VALUE>
+class KeyedVector
+{
+public:
+    typedef KEY    key_type;
+    typedef VALUE  value_type;
+
+    inline                  KeyedVector();
+
+    /*
+     * empty the vector
+     */
+
+    inline  void            clear()                     { mVector.clear(); }
+
+    /*! 
+     * vector stats
+     */
+
+    //! returns number of items in the vector
+    inline  size_t          size() const                { return mVector.size(); }
+    //! returns whether or not the vector is empty
+    inline  bool            isEmpty() const             { return mVector.isEmpty(); }
+    //! returns how many items can be stored without reallocating the backing store
+    inline  size_t          capacity() const            { return mVector.capacity(); }
+    //! sets the capacity. capacity can never be reduced less than size()
+    inline ssize_t          setCapacity(size_t size)    { return mVector.setCapacity(size); }
+
+    // returns true if the arguments is known to be identical to this vector
+    inline bool isIdenticalTo(const KeyedVector& rhs) const;
+
+    /*! 
+     * accessors
+     */
+            const VALUE&    valueFor(const KEY& key) const;
+            const VALUE&    valueAt(size_t index) const;
+            const KEY&      keyAt(size_t index) const;
+            ssize_t         indexOfKey(const KEY& key) const;
+            const VALUE&    operator[] (size_t index) const;
+
+    /*!
+     * modifying the array
+     */
+
+            VALUE&          editValueFor(const KEY& key);
+            VALUE&          editValueAt(size_t index);
+
+            /*! 
+             * add/insert/replace items
+             */
+             
+            ssize_t         add(const KEY& key, const VALUE& item);
+            ssize_t         replaceValueFor(const KEY& key, const VALUE& item);
+            ssize_t         replaceValueAt(size_t index, const VALUE& item);
+
+    /*!
+     * remove items
+     */
+
+            ssize_t         removeItem(const KEY& key);
+            ssize_t         removeItemsAt(size_t index, size_t count = 1);
+            
+private:
+            SortedVector< key_value_pair_t<KEY, VALUE> >    mVector;
+};
+
+// KeyedVector<KEY, VALUE> can be trivially moved using memcpy() because its
+// underlying SortedVector can be trivially moved.
+template<typename KEY, typename VALUE> struct trait_trivial_move<KeyedVector<KEY, VALUE> > {
+    enum { value = trait_trivial_move<SortedVector< key_value_pair_t<KEY, VALUE> > >::value };
+};
+
+
+// ---------------------------------------------------------------------------
+
+/**
+ * Variation of KeyedVector that holds a default value to return when
+ * valueFor() is called with a key that doesn't exist.
+ */
+template <typename KEY, typename VALUE>
+class DefaultKeyedVector : public KeyedVector<KEY, VALUE>
+{
+public:
+    inline                  DefaultKeyedVector(const VALUE& defValue = VALUE());
+            const VALUE&    valueFor(const KEY& key) const;
+
+private:
+            VALUE                                           mDefault;
+};
+
+// ---------------------------------------------------------------------------
+
+template<typename KEY, typename VALUE> inline
+KeyedVector<KEY,VALUE>::KeyedVector()
+{
+}
+
+template<typename KEY, typename VALUE> inline
+bool KeyedVector<KEY,VALUE>::isIdenticalTo(const KeyedVector<KEY,VALUE>& rhs) const {
+    return mVector.array() == rhs.mVector.array();
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::indexOfKey(const KEY& key) const {
+    return mVector.indexOf( key_value_pair_t<KEY,VALUE>(key) );
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& KeyedVector<KEY,VALUE>::valueFor(const KEY& key) const {
+    ssize_t i = this->indexOfKey(key);
+    LOG_ALWAYS_FATAL_IF(i<0, "%s: key not found", __PRETTY_FUNCTION__);
+    return mVector.itemAt(i).value;
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& KeyedVector<KEY,VALUE>::valueAt(size_t index) const {
+    return mVector.itemAt(index).value;
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& KeyedVector<KEY,VALUE>::operator[] (size_t index) const {
+    return valueAt(index);
+}
+
+template<typename KEY, typename VALUE> inline
+const KEY& KeyedVector<KEY,VALUE>::keyAt(size_t index) const {
+    return mVector.itemAt(index).key;
+}
+
+template<typename KEY, typename VALUE> inline
+VALUE& KeyedVector<KEY,VALUE>::editValueFor(const KEY& key) {
+    ssize_t i = this->indexOfKey(key);
+    LOG_ALWAYS_FATAL_IF(i<0, "%s: key not found", __PRETTY_FUNCTION__);
+    return mVector.editItemAt(i).value;
+}
+
+template<typename KEY, typename VALUE> inline
+VALUE& KeyedVector<KEY,VALUE>::editValueAt(size_t index) {
+    return mVector.editItemAt(index).value;
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::add(const KEY& key, const VALUE& value) {
+    return mVector.add( key_value_pair_t<KEY,VALUE>(key, value) );
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::replaceValueFor(const KEY& key, const VALUE& value) {
+    key_value_pair_t<KEY,VALUE> pair(key, value);
+    mVector.remove(pair);
+    return mVector.add(pair);
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::replaceValueAt(size_t index, const VALUE& item) {
+    if (index<size()) {
+        mVector.editItemAt(index).value = item;
+        return index;
+    }
+    return BAD_INDEX;
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY,VALUE>::removeItem(const KEY& key) {
+    return mVector.remove(key_value_pair_t<KEY,VALUE>(key));
+}
+
+template<typename KEY, typename VALUE> inline
+ssize_t KeyedVector<KEY, VALUE>::removeItemsAt(size_t index, size_t count) {
+    return mVector.removeItemsAt(index, count);
+}
+
+// ---------------------------------------------------------------------------
+
+template<typename KEY, typename VALUE> inline
+DefaultKeyedVector<KEY,VALUE>::DefaultKeyedVector(const VALUE& defValue)
+    : mDefault(defValue)
+{
+}
+
+template<typename KEY, typename VALUE> inline
+const VALUE& DefaultKeyedVector<KEY,VALUE>::valueFor(const KEY& key) const {
+    ssize_t i = this->indexOfKey(key);
+    return i >= 0 ? KeyedVector<KEY,VALUE>::valueAt(i) : mDefault;
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_KEYED_VECTOR_H
diff --git a/include/utils/LinearAllocator.h b/include/utils/LinearAllocator.h
new file mode 100644
index 0000000..4772bc8
--- /dev/null
+++ b/include/utils/LinearAllocator.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+#ifndef ANDROID_LINEARALLOCATOR_H
+#define ANDROID_LINEARALLOCATOR_H
+
+#include <stddef.h>
+
+namespace android {
+
+/**
+ * A memory manager that internally allocates multi-kbyte buffers for placing objects in. It avoids
+ * the overhead of malloc when many objects are allocated. It is most useful when creating many
+ * small objects with a similar lifetime, and doesn't add significant overhead for large
+ * allocations.
+ */
+class LinearAllocator {
+public:
+    LinearAllocator();
+    ~LinearAllocator();
+
+    /**
+     * Reserves and returns a region of memory of at least size 'size', aligning as needed.
+     * Typically this is used in an object's overridden new() method or as a replacement for malloc.
+     *
+     * The lifetime of the returned buffers is tied to that of the LinearAllocator. If calling
+     * delete() on an object stored in a buffer is needed, it should be overridden to use
+     * rewindIfLastAlloc()
+     */
+    void* alloc(size_t size);
+
+    /**
+     * Attempt to deallocate the given buffer, with the LinearAllocator attempting to rewind its
+     * state if possible. No destructors are called.
+     */
+    void rewindIfLastAlloc(void* ptr, size_t allocSize);
+
+    /**
+     * Dump memory usage statistics to the log (allocated and wasted space)
+     */
+    void dumpMemoryStats(const char* prefix = "");
+
+    /**
+     * The number of bytes used for buffers allocated in the LinearAllocator (does not count space
+     * wasted)
+     */
+    size_t usedSize() const { return mTotalAllocated - mWastedSpace; }
+
+private:
+    LinearAllocator(const LinearAllocator& other);
+
+    class Page;
+
+    Page* newPage(size_t pageSize);
+    bool fitsInCurrentPage(size_t size);
+    void ensureNext(size_t size);
+    void* start(Page *p);
+    void* end(Page* p);
+
+    size_t mPageSize;
+    size_t mMaxAllocSize;
+    void* mNext;
+    Page* mCurrentPage;
+    Page* mPages;
+
+    // Memory usage tracking
+    size_t mTotalAllocated;
+    size_t mWastedSpace;
+    size_t mPageCount;
+    size_t mDedicatedPageCount;
+};
+
+}; // namespace android
+
+#endif // ANDROID_LINEARALLOCATOR_H
diff --git a/include/utils/LinearTransform.h b/include/utils/LinearTransform.h
new file mode 100644
index 0000000..04cb355
--- /dev/null
+++ b/include/utils/LinearTransform.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef _LIBS_UTILS_LINEAR_TRANSFORM_H
+#define _LIBS_UTILS_LINEAR_TRANSFORM_H
+
+#include <stdint.h>
+
+namespace android {
+
+// LinearTransform defines a structure which hold the definition of a
+// transformation from single dimensional coordinate system A into coordinate
+// system B (and back again).  Values in A and in B are 64 bit, the linear
+// scale factor is expressed as a rational number using two 32 bit values.
+//
+// Specifically, let
+// f(a) = b
+// F(b) = f^-1(b) = a
+// then
+//
+// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
+//
+// and
+//
+// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
+//
+struct LinearTransform {
+  int64_t  a_zero;
+  int64_t  b_zero;
+  int32_t  a_to_b_numer;
+  uint32_t a_to_b_denom;
+
+  // Transform from A->B
+  // Returns true on success, or false in the case of a singularity or an
+  // overflow.
+  bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
+
+  // Transform from B->A
+  // Returns true on success, or false in the case of a singularity or an
+  // overflow.
+  bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
+
+  // Helpers which will reduce the fraction N/D using Euclid's method.
+  template <class T> static void reduce(T* N, T* D);
+  static void reduce(int32_t* N, uint32_t* D);
+};
+
+
+}
+
+#endif  // _LIBS_UTILS_LINEAR_TRANSFORM_H
diff --git a/include/utils/List.h b/include/utils/List.h
new file mode 100644
index 0000000..403cd7f
--- /dev/null
+++ b/include/utils/List.h
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Templated list class.  Normally we'd use STL, but we don't have that.
+// This class mimics STL's interfaces.
+//
+// Objects are copied into the list with the '=' operator or with copy-
+// construction, so if the compiler's auto-generated versions won't work for
+// you, define your own.
+//
+// The only class you want to use from here is "List".
+//
+#ifndef _LIBS_UTILS_LIST_H
+#define _LIBS_UTILS_LIST_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace android {
+
+/*
+ * Doubly-linked list.  Instantiate with "List<MyClass> myList".
+ *
+ * Objects added to the list are copied using the assignment operator,
+ * so this must be defined.
+ */
+template<typename T> 
+class List 
+{
+protected:
+    /*
+     * One element in the list.
+     */
+    class _Node {
+    public:
+        explicit _Node(const T& val) : mVal(val) {}
+        ~_Node() {}
+        inline T& getRef() { return mVal; }
+        inline const T& getRef() const { return mVal; }
+        inline _Node* getPrev() const { return mpPrev; }
+        inline _Node* getNext() const { return mpNext; }
+        inline void setVal(const T& val) { mVal = val; }
+        inline void setPrev(_Node* ptr) { mpPrev = ptr; }
+        inline void setNext(_Node* ptr) { mpNext = ptr; }
+    private:
+        friend class List;
+        friend class _ListIterator;
+        T           mVal;
+        _Node*      mpPrev;
+        _Node*      mpNext;
+    };
+
+    /*
+     * Iterator for walking through the list.
+     */
+    
+    template <typename TYPE>
+    struct CONST_ITERATOR {
+        typedef _Node const * NodePtr;
+        typedef const TYPE Type;
+    };
+    
+    template <typename TYPE>
+    struct NON_CONST_ITERATOR {
+        typedef _Node* NodePtr;
+        typedef TYPE Type;
+    };
+    
+    template<
+        typename U,
+        template <class> class Constness
+    > 
+    class _ListIterator {
+        typedef _ListIterator<U, Constness>     _Iter;
+        typedef typename Constness<U>::NodePtr  _NodePtr;
+        typedef typename Constness<U>::Type     _Type;
+
+        explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
+
+    public:
+        _ListIterator() {}
+        _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
+        ~_ListIterator() {}
+        
+        // this will handle conversions from iterator to const_iterator
+        // (and also all convertible iterators)
+        // Here, in this implementation, the iterators can be converted
+        // if the nodes can be converted
+        template<typename V> explicit 
+        _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
+        
+
+        /*
+         * Dereference operator.  Used to get at the juicy insides.
+         */
+        _Type& operator*() const { return mpNode->getRef(); }
+        _Type* operator->() const { return &(mpNode->getRef()); }
+
+        /*
+         * Iterator comparison.
+         */
+        inline bool operator==(const _Iter& right) const { 
+            return mpNode == right.mpNode; }
+        
+        inline bool operator!=(const _Iter& right) const { 
+            return mpNode != right.mpNode; }
+
+        /*
+         * handle comparisons between iterator and const_iterator
+         */
+        template<typename OTHER>
+        inline bool operator==(const OTHER& right) const { 
+            return mpNode == right.mpNode; }
+        
+        template<typename OTHER>
+        inline bool operator!=(const OTHER& right) const { 
+            return mpNode != right.mpNode; }
+
+        /*
+         * Incr/decr, used to move through the list.
+         */
+        inline _Iter& operator++() {     // pre-increment
+            mpNode = mpNode->getNext();
+            return *this;
+        }
+        const _Iter operator++(int) {    // post-increment
+            _Iter tmp(*this);
+            mpNode = mpNode->getNext();
+            return tmp;
+        }
+        inline _Iter& operator--() {     // pre-increment
+            mpNode = mpNode->getPrev();
+            return *this;
+        }
+        const _Iter operator--(int) {   // post-increment
+            _Iter tmp(*this);
+            mpNode = mpNode->getPrev();
+            return tmp;
+        }
+
+        inline _NodePtr getNode() const { return mpNode; }
+
+        _NodePtr mpNode;    /* should be private, but older gcc fails */
+    private:
+        friend class List;
+    };
+
+public:
+    List() {
+        prep();
+    }
+    List(const List<T>& src) {      // copy-constructor
+        prep();
+        insert(begin(), src.begin(), src.end());
+    }
+    virtual ~List() {
+        clear();
+        delete[] (unsigned char*) mpMiddle;
+    }
+
+    typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
+    typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
+
+    List<T>& operator=(const List<T>& right);
+
+    /* returns true if the list is empty */
+    inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
+
+    /* return #of elements in list */
+    size_t size() const {
+        return size_t(distance(begin(), end()));
+    }
+
+    /*
+     * Return the first element or one past the last element.  The
+     * _Node* we're returning is converted to an "iterator" by a
+     * constructor in _ListIterator.
+     */
+    inline iterator begin() { 
+        return iterator(mpMiddle->getNext()); 
+    }
+    inline const_iterator begin() const { 
+        return const_iterator(const_cast<_Node const*>(mpMiddle->getNext())); 
+    }
+    inline iterator end() { 
+        return iterator(mpMiddle); 
+    }
+    inline const_iterator end() const { 
+        return const_iterator(const_cast<_Node const*>(mpMiddle)); 
+    }
+
+    /* add the object to the head or tail of the list */
+    void push_front(const T& val) { insert(begin(), val); }
+    void push_back(const T& val) { insert(end(), val); }
+
+    /* insert before the current node; returns iterator at new node */
+    iterator insert(iterator posn, const T& val) 
+    {
+        _Node* newNode = new _Node(val);        // alloc & copy-construct
+        newNode->setNext(posn.getNode());
+        newNode->setPrev(posn.getNode()->getPrev());
+        posn.getNode()->getPrev()->setNext(newNode);
+        posn.getNode()->setPrev(newNode);
+        return iterator(newNode);
+    }
+
+    /* insert a range of elements before the current node */
+    void insert(iterator posn, const_iterator first, const_iterator last) {
+        for ( ; first != last; ++first)
+            insert(posn, *first);
+    }
+
+    /* remove one entry; returns iterator at next node */
+    iterator erase(iterator posn) {
+        _Node* pNext = posn.getNode()->getNext();
+        _Node* pPrev = posn.getNode()->getPrev();
+        pPrev->setNext(pNext);
+        pNext->setPrev(pPrev);
+        delete posn.getNode();
+        return iterator(pNext);
+    }
+
+    /* remove a range of elements */
+    iterator erase(iterator first, iterator last) {
+        while (first != last)
+            erase(first++);     // don't erase than incr later!
+        return iterator(last);
+    }
+
+    /* remove all contents of the list */
+    void clear() {
+        _Node* pCurrent = mpMiddle->getNext();
+        _Node* pNext;
+
+        while (pCurrent != mpMiddle) {
+            pNext = pCurrent->getNext();
+            delete pCurrent;
+            pCurrent = pNext;
+        }
+        mpMiddle->setPrev(mpMiddle);
+        mpMiddle->setNext(mpMiddle);
+    }
+
+    /*
+     * Measure the distance between two iterators.  On exist, "first"
+     * will be equal to "last".  The iterators must refer to the same
+     * list.
+     *
+     * FIXME: This is actually a generic iterator function. It should be a 
+     * template function at the top-level with specializations for things like
+     * vector<>, which can just do pointer math). Here we limit it to
+     * _ListIterator of the same type but different constness.
+     */
+    template<
+        typename U,
+        template <class> class CL,
+        template <class> class CR
+    > 
+    ptrdiff_t distance(
+            _ListIterator<U, CL> first, _ListIterator<U, CR> last) const 
+    {
+        ptrdiff_t count = 0;
+        while (first != last) {
+            ++first;
+            ++count;
+        }
+        return count;
+    }
+
+private:
+    /*
+     * I want a _Node but don't need it to hold valid data.  More
+     * to the point, I don't want T's constructor to fire, since it
+     * might have side-effects or require arguments.  So, we do this
+     * slightly uncouth storage alloc.
+     */
+    void prep() {
+        mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
+        mpMiddle->setPrev(mpMiddle);
+        mpMiddle->setNext(mpMiddle);
+    }
+
+    /*
+     * This node plays the role of "pointer to head" and "pointer to tail".
+     * It sits in the middle of a circular list of nodes.  The iterator
+     * runs around the circle until it encounters this one.
+     */
+    _Node*      mpMiddle;
+};
+
+/*
+ * Assignment operator.
+ *
+ * The simplest way to do this would be to clear out the target list and
+ * fill it with the source.  However, we can speed things along by
+ * re-using existing elements.
+ */
+template<class T>
+List<T>& List<T>::operator=(const List<T>& right)
+{
+    if (this == &right)
+        return *this;       // self-assignment
+    iterator firstDst = begin();
+    iterator lastDst = end();
+    const_iterator firstSrc = right.begin();
+    const_iterator lastSrc = right.end();
+    while (firstSrc != lastSrc && firstDst != lastDst)
+        *firstDst++ = *firstSrc++;
+    if (firstSrc == lastSrc)        // ran out of elements in source?
+        erase(firstDst, lastDst);   // yes, erase any extras
+    else
+        insert(lastDst, firstSrc, lastSrc);     // copy remaining over
+    return *this;
+}
+
+}; // namespace android
+
+#endif // _LIBS_UTILS_LIST_H
diff --git a/include/utils/Log.h b/include/utils/Log.h
new file mode 100644
index 0000000..4259c86
--- /dev/null
+++ b/include/utils/Log.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// C/C++ logging functions.  See the logging documentation for API details.
+//
+// We'd like these to be available from C code (in case we import some from
+// somewhere), so this has a C interface.
+//
+// The output will be correct when the log file is shared between multiple
+// threads and/or multiple processes so long as the operating system
+// supports O_APPEND.  These calls have mutex-protected data structures
+// and so are NOT reentrant.  Do not use LOG in a signal handler.
+//
+#ifndef _LIBS_UTILS_LOG_H
+#define _LIBS_UTILS_LOG_H
+
+#include <cutils/log.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+
+namespace android {
+
+/*
+ * A very simple utility that yells in the log when an operation takes too long.
+ */
+class LogIfSlow {
+public:
+    LogIfSlow(const char* tag, android_LogPriority priority,
+            int timeoutMillis, const char* message);
+    ~LogIfSlow();
+
+private:
+    const char* const mTag;
+    const android_LogPriority mPriority;
+    const int mTimeoutMillis;
+    const char* const mMessage;
+    const int64_t mStart;
+};
+
+/*
+ * Writes the specified debug log message if this block takes longer than the
+ * specified number of milliseconds to run.  Includes the time actually taken.
+ *
+ * {
+ *     ALOGD_IF_SLOW(50, "Excessive delay doing something.");
+ *     doSomething();
+ * }
+ */
+#define ALOGD_IF_SLOW(timeoutMillis, message) \
+    android::LogIfSlow _logIfSlow(LOG_TAG, ANDROID_LOG_DEBUG, timeoutMillis, message);
+
+} // namespace android
+
+#endif // __cplusplus
+
+#endif // _LIBS_UTILS_LOG_H
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
new file mode 100644
index 0000000..2e0651a
--- /dev/null
+++ b/include/utils/Looper.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef UTILS_LOOPER_H
+#define UTILS_LOOPER_H
+
+#include <utils/threads.h>
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/Timers.h>
+
+#include <android/looper.h>
+
+#include <sys/epoll.h>
+
+/*
+ * Declare a concrete type for the NDK's looper forward declaration.
+ */
+struct ALooper {
+};
+
+namespace android {
+
+/**
+ * A message that can be posted to a Looper.
+ */
+struct Message {
+    Message() : what(0) { }
+    Message(int what) : what(what) { }
+
+    /* The message type. (interpretation is left up to the handler) */
+    int what;
+};
+
+
+/**
+ * Interface for a Looper message handler.
+ *
+ * The Looper holds a strong reference to the message handler whenever it has
+ * a message to deliver to it.  Make sure to call Looper::removeMessages
+ * to remove any pending messages destined for the handler so that the handler
+ * can be destroyed.
+ */
+class MessageHandler : public virtual RefBase {
+protected:
+    virtual ~MessageHandler() { }
+
+public:
+    /**
+     * Handles a message.
+     */
+    virtual void handleMessage(const Message& message) = 0;
+};
+
+
+/**
+ * A simple proxy that holds a weak reference to a message handler.
+ */
+class WeakMessageHandler : public MessageHandler {
+protected:
+    virtual ~WeakMessageHandler();
+
+public:
+    WeakMessageHandler(const wp<MessageHandler>& handler);
+    virtual void handleMessage(const Message& message);
+
+private:
+    wp<MessageHandler> mHandler;
+};
+
+
+/**
+ * A looper callback.
+ */
+class LooperCallback : public virtual RefBase {
+protected:
+    virtual ~LooperCallback() { }
+
+public:
+    /**
+     * Handles a poll event for the given file descriptor.
+     * It is given the file descriptor it is associated with,
+     * a bitmask of the poll events that were triggered (typically ALOOPER_EVENT_INPUT),
+     * and the data pointer that was originally supplied.
+     *
+     * Implementations should return 1 to continue receiving callbacks, or 0
+     * to have this file descriptor and callback unregistered from the looper.
+     */
+    virtual int handleEvent(int fd, int events, void* data) = 0;
+};
+
+
+/**
+ * Wraps a ALooper_callbackFunc function pointer.
+ */
+class SimpleLooperCallback : public LooperCallback {
+protected:
+    virtual ~SimpleLooperCallback();
+
+public:
+    SimpleLooperCallback(ALooper_callbackFunc callback);
+    virtual int handleEvent(int fd, int events, void* data);
+
+private:
+    ALooper_callbackFunc mCallback;
+};
+
+
+/**
+ * A polling loop that supports monitoring file descriptor events, optionally
+ * using callbacks.  The implementation uses epoll() internally.
+ *
+ * A looper can be associated with a thread although there is no requirement that it must be.
+ */
+class Looper : public ALooper, public RefBase {
+protected:
+    virtual ~Looper();
+
+public:
+    /**
+     * Creates a looper.
+     *
+     * If allowNonCallbaks is true, the looper will allow file descriptors to be
+     * registered without associated callbacks.  This assumes that the caller of
+     * pollOnce() is prepared to handle callback-less events itself.
+     */
+    Looper(bool allowNonCallbacks);
+
+    /**
+     * Returns whether this looper instance allows the registration of file descriptors
+     * using identifiers instead of callbacks.
+     */
+    bool getAllowNonCallbacks() const;
+
+    /**
+     * Waits for events to be available, with optional timeout in milliseconds.
+     * Invokes callbacks for all file descriptors on which an event occurred.
+     *
+     * If the timeout is zero, returns immediately without blocking.
+     * If the timeout is negative, waits indefinitely until an event appears.
+     *
+     * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before
+     * the timeout expired and no callbacks were invoked and no other file
+     * descriptors were ready.
+     *
+     * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked.
+     *
+     * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given
+     * timeout expired.
+     *
+     * Returns ALOOPER_POLL_ERROR if an error occurred.
+     *
+     * Returns a value >= 0 containing an identifier if its file descriptor has data
+     * and it has no callback function (requiring the caller here to handle it).
+     * In this (and only this) case outFd, outEvents and outData will contain the poll
+     * events and data associated with the fd, otherwise they will be set to NULL.
+     *
+     * This method does not return until it has finished invoking the appropriate callbacks
+     * for all file descriptors that were signalled.
+     */
+    int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
+    inline int pollOnce(int timeoutMillis) {
+        return pollOnce(timeoutMillis, NULL, NULL, NULL);
+    }
+
+    /**
+     * Like pollOnce(), but performs all pending callbacks until all
+     * data has been consumed or a file descriptor is available with no callback.
+     * This function will never return ALOOPER_POLL_CALLBACK.
+     */
+    int pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData);
+    inline int pollAll(int timeoutMillis) {
+        return pollAll(timeoutMillis, NULL, NULL, NULL);
+    }
+
+    /**
+     * Wakes the poll asynchronously.
+     *
+     * This method can be called on any thread.
+     * This method returns immediately.
+     */
+    void wake();
+
+    /**
+     * Adds a new file descriptor to be polled by the looper.
+     * If the same file descriptor was previously added, it is replaced.
+     *
+     * "fd" is the file descriptor to be added.
+     * "ident" is an identifier for this event, which is returned from pollOnce().
+     * The identifier must be >= 0, or ALOOPER_POLL_CALLBACK if providing a non-NULL callback.
+     * "events" are the poll events to wake up on.  Typically this is ALOOPER_EVENT_INPUT.
+     * "callback" is the function to call when there is an event on the file descriptor.
+     * "data" is a private data pointer to supply to the callback.
+     *
+     * There are two main uses of this function:
+     *
+     * (1) If "callback" is non-NULL, then this function will be called when there is
+     * data on the file descriptor.  It should execute any events it has pending,
+     * appropriately reading from the file descriptor.  The 'ident' is ignored in this case.
+     *
+     * (2) If "callback" is NULL, the 'ident' will be returned by ALooper_pollOnce
+     * when its file descriptor has data available, requiring the caller to take
+     * care of processing it.
+     *
+     * Returns 1 if the file descriptor was added, 0 if the arguments were invalid.
+     *
+     * This method can be called on any thread.
+     * This method may block briefly if it needs to wake the poll.
+     *
+     * The callback may either be specified as a bare function pointer or as a smart
+     * pointer callback object.  The smart pointer should be preferred because it is
+     * easier to avoid races when the callback is removed from a different thread.
+     * See removeFd() for details.
+     */
+    int addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data);
+    int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data);
+
+    /**
+     * Removes a previously added file descriptor from the looper.
+     *
+     * When this method returns, it is safe to close the file descriptor since the looper
+     * will no longer have a reference to it.  However, it is possible for the callback to
+     * already be running or for it to run one last time if the file descriptor was already
+     * signalled.  Calling code is responsible for ensuring that this case is safely handled.
+     * For example, if the callback takes care of removing itself during its own execution either
+     * by returning 0 or by calling this method, then it can be guaranteed to not be invoked
+     * again at any later time unless registered anew.
+     *
+     * A simple way to avoid this problem is to use the version of addFd() that takes
+     * a sp<LooperCallback> instead of a bare function pointer.  The LooperCallback will
+     * be released at the appropriate time by the Looper.
+     *
+     * Returns 1 if the file descriptor was removed, 0 if none was previously registered.
+     *
+     * This method can be called on any thread.
+     * This method may block briefly if it needs to wake the poll.
+     */
+    int removeFd(int fd);
+
+    /**
+     * Enqueues a message to be processed by the specified handler.
+     *
+     * The handler must not be null.
+     * This method can be called on any thread.
+     */
+    void sendMessage(const sp<MessageHandler>& handler, const Message& message);
+
+    /**
+     * Enqueues a message to be processed by the specified handler after all pending messages
+     * after the specified delay.
+     *
+     * The time delay is specified in uptime nanoseconds.
+     * The handler must not be null.
+     * This method can be called on any thread.
+     */
+    void sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
+            const Message& message);
+
+    /**
+     * Enqueues a message to be processed by the specified handler after all pending messages
+     * at the specified time.
+     *
+     * The time is specified in uptime nanoseconds.
+     * The handler must not be null.
+     * This method can be called on any thread.
+     */
+    void sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
+            const Message& message);
+
+    /**
+     * Removes all messages for the specified handler from the queue.
+     *
+     * The handler must not be null.
+     * This method can be called on any thread.
+     */
+    void removeMessages(const sp<MessageHandler>& handler);
+
+    /**
+     * Removes all messages of a particular type for the specified handler from the queue.
+     *
+     * The handler must not be null.
+     * This method can be called on any thread.
+     */
+    void removeMessages(const sp<MessageHandler>& handler, int what);
+
+    /**
+     * Return whether this looper's thread is currently idling -- that is, whether it
+     * stopped waiting for more work to do.  Note that this is intrinsically racy, since
+     * its state can change before you get the result back.
+     */
+    bool isIdling() const;
+
+    /**
+     * Prepares a looper associated with the calling thread, and returns it.
+     * If the thread already has a looper, it is returned.  Otherwise, a new
+     * one is created, associated with the thread, and returned.
+     *
+     * The opts may be ALOOPER_PREPARE_ALLOW_NON_CALLBACKS or 0.
+     */
+    static sp<Looper> prepare(int opts);
+
+    /**
+     * Sets the given looper to be associated with the calling thread.
+     * If another looper is already associated with the thread, it is replaced.
+     *
+     * If "looper" is NULL, removes the currently associated looper.
+     */
+    static void setForThread(const sp<Looper>& looper);
+
+    /**
+     * Returns the looper associated with the calling thread, or NULL if
+     * there is not one.
+     */
+    static sp<Looper> getForThread();
+
+private:
+    struct Request {
+        int fd;
+        int ident;
+        sp<LooperCallback> callback;
+        void* data;
+    };
+
+    struct Response {
+        int events;
+        Request request;
+    };
+
+    struct MessageEnvelope {
+        MessageEnvelope() : uptime(0) { }
+
+        MessageEnvelope(nsecs_t uptime, const sp<MessageHandler> handler,
+                const Message& message) : uptime(uptime), handler(handler), message(message) {
+        }
+
+        nsecs_t uptime;
+        sp<MessageHandler> handler;
+        Message message;
+    };
+
+    const bool mAllowNonCallbacks; // immutable
+
+    int mWakeReadPipeFd;  // immutable
+    int mWakeWritePipeFd; // immutable
+    Mutex mLock;
+
+    Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
+    bool mSendingMessage; // guarded by mLock
+
+    // Whether we are currently waiting for work.  Not protected by a lock,
+    // any use of it is racy anyway.
+    volatile bool mIdling;
+
+    int mEpollFd; // immutable
+
+    // Locked list of file descriptor monitoring requests.
+    KeyedVector<int, Request> mRequests;  // guarded by mLock
+
+    // This state is only used privately by pollOnce and does not require a lock since
+    // it runs on a single thread.
+    Vector<Response> mResponses;
+    size_t mResponseIndex;
+    nsecs_t mNextMessageUptime; // set to LLONG_MAX when none
+
+    int pollInner(int timeoutMillis);
+    void awoken();
+    void pushResponse(int events, const Request& request);
+
+    static void initTLSKey();
+    static void threadDestructor(void *st);
+};
+
+} // namespace android
+
+#endif // UTILS_LOOPER_H
diff --git a/include/utils/LruCache.h b/include/utils/LruCache.h
new file mode 100644
index 0000000..053bfaf
--- /dev/null
+++ b/include/utils/LruCache.h
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef ANDROID_UTILS_LRU_CACHE_H
+#define ANDROID_UTILS_LRU_CACHE_H
+
+#include <utils/BasicHashtable.h>
+#include <utils/UniquePtr.h>
+
+namespace android {
+
+/**
+ * GenerationCache callback used when an item is removed
+ */
+template<typename EntryKey, typename EntryValue>
+class OnEntryRemoved {
+public:
+    virtual ~OnEntryRemoved() { };
+    virtual void operator()(EntryKey& key, EntryValue& value) = 0;
+}; // class OnEntryRemoved
+
+template <typename TKey, typename TValue>
+class LruCache {
+public:
+    explicit LruCache(uint32_t maxCapacity);
+
+    enum Capacity {
+        kUnlimitedCapacity,
+    };
+
+    void setOnEntryRemovedListener(OnEntryRemoved<TKey, TValue>* listener);
+    size_t size() const;
+    const TValue& get(const TKey& key);
+    bool put(const TKey& key, const TValue& value);
+    bool remove(const TKey& key);
+    bool removeOldest();
+    void clear();
+
+    class Iterator {
+    public:
+        Iterator(const LruCache<TKey, TValue>& cache): mCache(cache), mIndex(-1) {
+        }
+
+        bool next() {
+            mIndex = mCache.mTable->next(mIndex);
+            return mIndex != -1;
+        }
+
+        size_t index() const {
+            return mIndex;
+        }
+
+        const TValue& value() const {
+            return mCache.mTable->entryAt(mIndex).value;
+        }
+
+        const TKey& key() const {
+            return mCache.mTable->entryAt(mIndex).key;
+        }
+    private:
+        const LruCache<TKey, TValue>& mCache;
+        size_t mIndex;
+    };
+
+private:
+    LruCache(const LruCache& that);  // disallow copy constructor
+
+    struct Entry {
+        TKey key;
+        TValue value;
+        Entry* parent;
+        Entry* child;
+
+        Entry(TKey key_, TValue value_) : key(key_), value(value_), parent(NULL), child(NULL) {
+        }
+        const TKey& getKey() const { return key; }
+    };
+
+    void attachToCache(Entry& entry);
+    void detachFromCache(Entry& entry);
+    void rehash(size_t newCapacity);
+
+    UniquePtr<BasicHashtable<TKey, Entry> > mTable;
+    OnEntryRemoved<TKey, TValue>* mListener;
+    Entry* mOldest;
+    Entry* mYoungest;
+    uint32_t mMaxCapacity;
+    TValue mNullValue;
+};
+
+// Implementation is here, because it's fully templated
+template <typename TKey, typename TValue>
+LruCache<TKey, TValue>::LruCache(uint32_t maxCapacity): mMaxCapacity(maxCapacity),
+    mNullValue(NULL), mTable(new BasicHashtable<TKey, Entry>), mYoungest(NULL), mOldest(NULL),
+    mListener(NULL) {
+};
+
+template<typename K, typename V>
+void LruCache<K, V>::setOnEntryRemovedListener(OnEntryRemoved<K, V>* listener) {
+    mListener = listener;
+}
+
+template <typename TKey, typename TValue>
+size_t LruCache<TKey, TValue>::size() const {
+    return mTable->size();
+}
+
+template <typename TKey, typename TValue>
+const TValue& LruCache<TKey, TValue>::get(const TKey& key) {
+    hash_t hash = hash_type(key);
+    ssize_t index = mTable->find(-1, hash, key);
+    if (index == -1) {
+        return mNullValue;
+    }
+    Entry& entry = mTable->editEntryAt(index);
+    detachFromCache(entry);
+    attachToCache(entry);
+    return entry.value;
+}
+
+template <typename TKey, typename TValue>
+bool LruCache<TKey, TValue>::put(const TKey& key, const TValue& value) {
+    if (mMaxCapacity != kUnlimitedCapacity && size() >= mMaxCapacity) {
+        removeOldest();
+    }
+
+    hash_t hash = hash_type(key);
+    ssize_t index = mTable->find(-1, hash, key);
+    if (index >= 0) {
+        return false;
+    }
+    if (!mTable->hasMoreRoom()) {
+        rehash(mTable->capacity() * 2);
+    }
+
+    // Would it be better to initialize a blank entry and assign key, value?
+    Entry initEntry(key, value);
+    index = mTable->add(hash, initEntry);
+    Entry& entry = mTable->editEntryAt(index);
+    attachToCache(entry);
+    return true;
+}
+
+template <typename TKey, typename TValue>
+bool LruCache<TKey, TValue>::remove(const TKey& key) {
+    hash_t hash = hash_type(key);
+    ssize_t index = mTable->find(-1, hash, key);
+    if (index < 0) {
+        return false;
+    }
+    Entry& entry = mTable->editEntryAt(index);
+    if (mListener) {
+        (*mListener)(entry.key, entry.value);
+    }
+    detachFromCache(entry);
+    mTable->removeAt(index);
+    return true;
+}
+
+template <typename TKey, typename TValue>
+bool LruCache<TKey, TValue>::removeOldest() {
+    if (mOldest != NULL) {
+        return remove(mOldest->key);
+        // TODO: should probably abort if false
+    }
+    return false;
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::clear() {
+    if (mListener) {
+        for (Entry* p = mOldest; p != NULL; p = p->child) {
+            (*mListener)(p->key, p->value);
+        }
+    }
+    mYoungest = NULL;
+    mOldest = NULL;
+    mTable->clear();
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::attachToCache(Entry& entry) {
+    if (mYoungest == NULL) {
+        mYoungest = mOldest = &entry;
+    } else {
+        entry.parent = mYoungest;
+        mYoungest->child = &entry;
+        mYoungest = &entry;
+    }
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::detachFromCache(Entry& entry) {
+    if (entry.parent != NULL) {
+        entry.parent->child = entry.child;
+    } else {
+        mOldest = entry.child;
+    }
+    if (entry.child != NULL) {
+        entry.child->parent = entry.parent;
+    } else {
+        mYoungest = entry.parent;
+    }
+
+    entry.parent = NULL;
+    entry.child = NULL;
+}
+
+template <typename TKey, typename TValue>
+void LruCache<TKey, TValue>::rehash(size_t newCapacity) {
+    UniquePtr<BasicHashtable<TKey, Entry> > oldTable(mTable.release());
+    Entry* oldest = mOldest;
+
+    mOldest = NULL;
+    mYoungest = NULL;
+    mTable.reset(new BasicHashtable<TKey, Entry>(newCapacity));
+    for (Entry* p = oldest; p != NULL; p = p->child) {
+        put(p->key, p->value);
+    }
+}
+
+}
+
+#endif // ANDROID_UTILS_LRU_CACHE_H
diff --git a/include/utils/Mutex.h b/include/utils/Mutex.h
new file mode 100644
index 0000000..dd201c8
--- /dev/null
+++ b/include/utils/Mutex.h
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBS_UTILS_MUTEX_H
+#define _LIBS_UTILS_MUTEX_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Errors.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Condition;
+
+/*
+ * Simple mutex class.  The implementation is system-dependent.
+ *
+ * The mutex must be unlocked by the thread that locked it.  They are not
+ * recursive, i.e. the same thread can't lock it multiple times.
+ */
+class Mutex {
+public:
+    enum {
+        PRIVATE = 0,
+        SHARED = 1
+    };
+    
+                Mutex();
+                Mutex(const char* name);
+                Mutex(int type, const char* name = NULL);
+                ~Mutex();
+
+    // lock or unlock the mutex
+    status_t    lock();
+    void        unlock();
+
+    // lock if possible; returns 0 on success, error otherwise
+    status_t    tryLock();
+
+    // Manages the mutex automatically. It'll be locked when Autolock is
+    // constructed and released when Autolock goes out of scope.
+    class Autolock {
+    public:
+        inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
+        inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
+        inline ~Autolock() { mLock.unlock(); }
+    private:
+        Mutex& mLock;
+    };
+
+private:
+    friend class Condition;
+    
+    // A mutex cannot be copied
+                Mutex(const Mutex&);
+    Mutex&      operator = (const Mutex&);
+    
+#if defined(HAVE_PTHREADS)
+    pthread_mutex_t mMutex;
+#else
+    void    _init();
+    void*   mState;
+#endif
+};
+
+// ---------------------------------------------------------------------------
+
+#if defined(HAVE_PTHREADS)
+
+inline Mutex::Mutex() {
+    pthread_mutex_init(&mMutex, NULL);
+}
+inline Mutex::Mutex(__attribute__((unused)) const char* name) {
+    pthread_mutex_init(&mMutex, NULL);
+}
+inline Mutex::Mutex(int type, __attribute__((unused)) const char* name) {
+    if (type == SHARED) {
+        pthread_mutexattr_t attr;
+        pthread_mutexattr_init(&attr);
+        pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+        pthread_mutex_init(&mMutex, &attr);
+        pthread_mutexattr_destroy(&attr);
+    } else {
+        pthread_mutex_init(&mMutex, NULL);
+    }
+}
+inline Mutex::~Mutex() {
+    pthread_mutex_destroy(&mMutex);
+}
+inline status_t Mutex::lock() {
+    return -pthread_mutex_lock(&mMutex);
+}
+inline void Mutex::unlock() {
+    pthread_mutex_unlock(&mMutex);
+}
+inline status_t Mutex::tryLock() {
+    return -pthread_mutex_trylock(&mMutex);
+}
+
+#endif // HAVE_PTHREADS
+
+// ---------------------------------------------------------------------------
+
+/*
+ * Automatic mutex.  Declare one of these at the top of a function.
+ * When the function returns, it will go out of scope, and release the
+ * mutex.
+ */
+ 
+typedef Mutex::Autolock AutoMutex;
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_MUTEX_H
diff --git a/include/utils/Printer.h b/include/utils/Printer.h
new file mode 100644
index 0000000..bb66287
--- /dev/null
+++ b/include/utils/Printer.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef ANDROID_PRINTER_H
+#define ANDROID_PRINTER_H
+
+#include <android/log.h>
+
+namespace android {
+
+// Interface for printing to an arbitrary data stream
+class Printer {
+public:
+    // Print a new line specified by 'string'. \n is appended automatically.
+    // -- Assumes that the string has no new line in it.
+    virtual void printLine(const char* string = "") = 0;
+
+    // Print a new line specified by the format string. \n is appended automatically.
+    // -- Assumes that the resulting string has no new line in it.
+    virtual void printFormatLine(const char* format, ...) __attribute__((format (printf, 2, 3)));
+
+protected:
+    Printer();
+    virtual ~Printer();
+}; // class Printer
+
+// Print to logcat
+class LogPrinter : public Printer {
+public:
+    // Create a printer using the specified logcat and log priority
+    // - Unless ignoreBlankLines is false, print blank lines to logcat
+    // (Note that the default ALOG behavior is to ignore blank lines)
+    LogPrinter(const char* logtag,
+               android_LogPriority priority = ANDROID_LOG_DEBUG,
+               const char* prefix = 0,
+               bool ignoreBlankLines = false);
+
+    // Print the specified line to logcat. No \n at the end is necessary.
+    virtual void printLine(const char* string);
+
+private:
+    void printRaw(const char* string);
+
+    const char* mLogTag;
+    android_LogPriority mPriority;
+    const char* mPrefix;
+    bool mIgnoreBlankLines;
+}; // class LogPrinter
+
+// Print to a file descriptor
+class FdPrinter : public Printer {
+public:
+    // Create a printer using the specified file descriptor.
+    // - Each line will be prefixed with 'indent' number of blank spaces.
+    // - In addition, each line will be prefixed with the 'prefix' string.
+    FdPrinter(int fd, unsigned int indent = 0, const char* prefix = 0);
+
+    // Print the specified line to the file descriptor. \n is appended automatically.
+    virtual void printLine(const char* string);
+
+private:
+    enum {
+        MAX_FORMAT_STRING = 20,
+    };
+
+    int mFd;
+    unsigned int mIndent;
+    const char* mPrefix;
+    char mFormatString[MAX_FORMAT_STRING];
+}; // class FdPrinter
+
+class String8;
+
+// Print to a String8
+class String8Printer : public Printer {
+public:
+    // Create a printer using the specified String8 as the target.
+    // - In addition, each line will be prefixed with the 'prefix' string.
+    // - target's memory lifetime must be a superset of this String8Printer.
+    String8Printer(String8* target, const char* prefix = 0);
+
+    // Append the specified line to the String8. \n is appended automatically.
+    virtual void printLine(const char* string);
+
+private:
+    String8* mTarget;
+    const char* mPrefix;
+}; // class String8Printer
+
+// Print to an existing Printer by adding a prefix to each line
+class PrefixPrinter : public Printer {
+public:
+    // Create a printer using the specified printer as the target.
+    PrefixPrinter(Printer& printer, const char* prefix);
+
+    // Print the line (prefixed with prefix) using the printer.
+    virtual void printLine(const char* string);
+
+private:
+    Printer& mPrinter;
+    const char* mPrefix;
+};
+
+}; // namespace android
+
+#endif // ANDROID_PRINTER_H
diff --git a/include/utils/ProcessCallStack.h b/include/utils/ProcessCallStack.h
new file mode 100644
index 0000000..4a86869
--- /dev/null
+++ b/include/utils/ProcessCallStack.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef ANDROID_PROCESS_CALLSTACK_H
+#define ANDROID_PROCESS_CALLSTACK_H
+
+#include <utils/CallStack.h>
+#include <android/log.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+#include <time.h>
+#include <sys/types.h>
+
+namespace android {
+
+class Printer;
+
+// Collect/print the call stack (function, file, line) traces for all threads in a process.
+class ProcessCallStack {
+public:
+    // Create an empty call stack. No-op.
+    ProcessCallStack();
+    // Copy the existing process callstack (no other side effects).
+    ProcessCallStack(const ProcessCallStack& rhs);
+    ~ProcessCallStack();
+
+    // Immediately collect the stack traces for all threads.
+    void update(int32_t maxDepth = CallStack::MAX_DEPTH);
+
+    // Print all stack traces to the log using the supplied logtag.
+    void log(const char* logtag, android_LogPriority priority = ANDROID_LOG_DEBUG,
+             const char* prefix = 0) const;
+
+    // Dump all stack traces to the specified file descriptor.
+    void dump(int fd, int indent = 0, const char* prefix = 0) const;
+
+    // Return a string (possibly very long) containing all the stack traces.
+    String8 toString(const char* prefix = 0) const;
+
+    // Dump a serialized representation of all the stack traces to the specified printer.
+    void print(Printer& printer) const;
+
+    // Get the number of threads whose stack traces were collected.
+    size_t size() const;
+
+private:
+    void printInternal(Printer& printer, Printer& csPrinter) const;
+
+    // Reset the process's stack frames and metadata.
+    void clear();
+
+    struct ThreadInfo {
+        CallStack callStack;
+        String8 threadName;
+    };
+
+    // tid -> ThreadInfo
+    KeyedVector<pid_t, ThreadInfo> mThreadMap;
+    // Time that update() was last called
+    struct tm mTimeUpdated;
+};
+
+}; // namespace android
+
+#endif // ANDROID_PROCESS_CALLSTACK_H
diff --git a/include/utils/PropertyMap.h b/include/utils/PropertyMap.h
new file mode 100644
index 0000000..a9e674f
--- /dev/null
+++ b/include/utils/PropertyMap.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef _UTILS_PROPERTY_MAP_H
+#define _UTILS_PROPERTY_MAP_H
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+#include <utils/Tokenizer.h>
+
+namespace android {
+
+/*
+ * Provides a mechanism for passing around string-based property key / value pairs
+ * and loading them from property files.
+ *
+ * The property files have the following simple structure:
+ *
+ * # Comment
+ * key = value
+ *
+ * Keys and values are any sequence of printable ASCII characters.
+ * The '=' separates the key from the value.
+ * The key and value may not contain whitespace.
+ *
+ * The '\' character is reserved for escape sequences and is not currently supported.
+ * The '"" character is reserved for quoting and is not currently supported.
+ * Files that contain the '\' or '"' character will fail to parse.
+ *
+ * The file must not contain duplicate keys.
+ *
+ * TODO Support escape sequences and quoted values when needed.
+ */
+class PropertyMap {
+public:
+    /* Creates an empty property map. */
+    PropertyMap();
+    ~PropertyMap();
+
+    /* Clears the property map. */
+    void clear();
+
+    /* Adds a property.
+     * Replaces the property with the same key if it is already present.
+     */
+    void addProperty(const String8& key, const String8& value);
+
+    /* Returns true if the property map contains the specified key. */
+    bool hasProperty(const String8& key) const;
+
+    /* Gets the value of a property and parses it.
+     * Returns true and sets outValue if the key was found and its value was parsed successfully.
+     * Otherwise returns false and does not modify outValue.  (Also logs a warning.)
+     */
+    bool tryGetProperty(const String8& key, String8& outValue) const;
+    bool tryGetProperty(const String8& key, bool& outValue) const;
+    bool tryGetProperty(const String8& key, int32_t& outValue) const;
+    bool tryGetProperty(const String8& key, float& outValue) const;
+
+    /* Adds all values from the specified property map. */
+    void addAll(const PropertyMap* map);
+
+    /* Gets the underlying property map. */
+    inline const KeyedVector<String8, String8>& getProperties() const { return mProperties; }
+
+    /* Loads a property map from a file. */
+    static status_t load(const String8& filename, PropertyMap** outMap);
+
+private:
+    class Parser {
+        PropertyMap* mMap;
+        Tokenizer* mTokenizer;
+
+    public:
+        Parser(PropertyMap* map, Tokenizer* tokenizer);
+        ~Parser();
+        status_t parse();
+
+    private:
+        status_t parseType();
+        status_t parseKey();
+        status_t parseKeyProperty();
+        status_t parseModifier(const String8& token, int32_t* outMetaState);
+        status_t parseCharacterLiteral(char16_t* outCharacter);
+    };
+
+    KeyedVector<String8, String8> mProperties;
+};
+
+} // namespace android
+
+#endif // _UTILS_PROPERTY_MAP_H
diff --git a/include/utils/RWLock.h b/include/utils/RWLock.h
new file mode 100644
index 0000000..90beb5f
--- /dev/null
+++ b/include/utils/RWLock.h
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBS_UTILS_RWLOCK_H
+#define _LIBS_UTILS_RWLOCK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Errors.h>
+#include <utils/ThreadDefs.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+#if defined(HAVE_PTHREADS)
+
+/*
+ * Simple mutex class.  The implementation is system-dependent.
+ *
+ * The mutex must be unlocked by the thread that locked it.  They are not
+ * recursive, i.e. the same thread can't lock it multiple times.
+ */
+class RWLock {
+public:
+    enum {
+        PRIVATE = 0,
+        SHARED = 1
+    };
+
+                RWLock();
+                RWLock(const char* name);
+                RWLock(int type, const char* name = NULL);
+                ~RWLock();
+
+    status_t    readLock();
+    status_t    tryReadLock();
+    status_t    writeLock();
+    status_t    tryWriteLock();
+    void        unlock();
+
+    class AutoRLock {
+    public:
+        inline AutoRLock(RWLock& rwlock) : mLock(rwlock)  { mLock.readLock(); }
+        inline ~AutoRLock() { mLock.unlock(); }
+    private:
+        RWLock& mLock;
+    };
+
+    class AutoWLock {
+    public:
+        inline AutoWLock(RWLock& rwlock) : mLock(rwlock)  { mLock.writeLock(); }
+        inline ~AutoWLock() { mLock.unlock(); }
+    private:
+        RWLock& mLock;
+    };
+
+private:
+    // A RWLock cannot be copied
+                RWLock(const RWLock&);
+   RWLock&      operator = (const RWLock&);
+
+   pthread_rwlock_t mRWLock;
+};
+
+inline RWLock::RWLock() {
+    pthread_rwlock_init(&mRWLock, NULL);
+}
+inline RWLock::RWLock(__attribute__((unused)) const char* name) {
+    pthread_rwlock_init(&mRWLock, NULL);
+}
+inline RWLock::RWLock(int type, __attribute__((unused)) const char* name) {
+    if (type == SHARED) {
+        pthread_rwlockattr_t attr;
+        pthread_rwlockattr_init(&attr);
+        pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
+        pthread_rwlock_init(&mRWLock, &attr);
+        pthread_rwlockattr_destroy(&attr);
+    } else {
+        pthread_rwlock_init(&mRWLock, NULL);
+    }
+}
+inline RWLock::~RWLock() {
+    pthread_rwlock_destroy(&mRWLock);
+}
+inline status_t RWLock::readLock() {
+    return -pthread_rwlock_rdlock(&mRWLock);
+}
+inline status_t RWLock::tryReadLock() {
+    return -pthread_rwlock_tryrdlock(&mRWLock);
+}
+inline status_t RWLock::writeLock() {
+    return -pthread_rwlock_wrlock(&mRWLock);
+}
+inline status_t RWLock::tryWriteLock() {
+    return -pthread_rwlock_trywrlock(&mRWLock);
+}
+inline void RWLock::unlock() {
+    pthread_rwlock_unlock(&mRWLock);
+}
+
+#endif // HAVE_PTHREADS
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+// ---------------------------------------------------------------------------
+
+#endif // _LIBS_UTILS_RWLOCK_H
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
new file mode 100644
index 0000000..cbfe13a
--- /dev/null
+++ b/include/utils/RefBase.h
@@ -0,0 +1,546 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_REF_BASE_H
+#define ANDROID_REF_BASE_H
+
+#include <cutils/atomic.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <utils/StrongPointer.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class TextOutput;
+TextOutput& printWeakPointer(TextOutput& to, const void* val);
+
+// ---------------------------------------------------------------------------
+
+#define COMPARE_WEAK(_op_)                                      \
+inline bool operator _op_ (const sp<T>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}                                                               \
+inline bool operator _op_ (const T* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}                                                               \
+template<typename U>                                            \
+inline bool operator _op_ (const sp<U>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}                                                               \
+template<typename U>                                            \
+inline bool operator _op_ (const U* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}
+
+// ---------------------------------------------------------------------------
+
+class ReferenceRenamer {
+protected:
+    // destructor is purposedly not virtual so we avoid code overhead from
+    // subclasses; we have to make it protected to guarantee that it
+    // cannot be called from this base class (and to make strict compilers
+    // happy).
+    ~ReferenceRenamer() { }
+public:
+    virtual void operator()(size_t i) const = 0;
+};
+
+// ---------------------------------------------------------------------------
+
+class RefBase
+{
+public:
+            void            incStrong(const void* id) const;
+            void            decStrong(const void* id) const;
+    
+            void            forceIncStrong(const void* id) const;
+
+            //! DEBUGGING ONLY: Get current strong ref count.
+            int32_t         getStrongCount() const;
+
+    class weakref_type
+    {
+    public:
+        RefBase*            refBase() const;
+        
+        void                incWeak(const void* id);
+        void                decWeak(const void* id);
+        
+        // acquires a strong reference if there is already one.
+        bool                attemptIncStrong(const void* id);
+        
+        // acquires a weak reference if there is already one.
+        // This is not always safe. see ProcessState.cpp and BpBinder.cpp
+        // for proper use.
+        bool                attemptIncWeak(const void* id);
+
+        //! DEBUGGING ONLY: Get current weak ref count.
+        int32_t             getWeakCount() const;
+
+        //! DEBUGGING ONLY: Print references held on object.
+        void                printRefs() const;
+
+        //! DEBUGGING ONLY: Enable tracking for this object.
+        // enable -- enable/disable tracking
+        // retain -- when tracking is enable, if true, then we save a stack trace
+        //           for each reference and dereference; when retain == false, we
+        //           match up references and dereferences and keep only the 
+        //           outstanding ones.
+        
+        void                trackMe(bool enable, bool retain);
+    };
+    
+            weakref_type*   createWeak(const void* id) const;
+            
+            weakref_type*   getWeakRefs() const;
+
+            //! DEBUGGING ONLY: Print references held on object.
+    inline  void            printRefs() const { getWeakRefs()->printRefs(); }
+
+            //! DEBUGGING ONLY: Enable tracking of object.
+    inline  void            trackMe(bool enable, bool retain)
+    { 
+        getWeakRefs()->trackMe(enable, retain); 
+    }
+
+    typedef RefBase basetype;
+
+protected:
+                            RefBase();
+    virtual                 ~RefBase();
+    
+    //! Flags for extendObjectLifetime()
+    enum {
+        OBJECT_LIFETIME_STRONG  = 0x0000,
+        OBJECT_LIFETIME_WEAK    = 0x0001,
+        OBJECT_LIFETIME_MASK    = 0x0001
+    };
+    
+            void            extendObjectLifetime(int32_t mode);
+            
+    //! Flags for onIncStrongAttempted()
+    enum {
+        FIRST_INC_STRONG = 0x0001
+    };
+    
+    virtual void            onFirstRef();
+    virtual void            onLastStrongRef(const void* id);
+    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
+    virtual void            onLastWeakRef(const void* id);
+
+private:
+    friend class weakref_type;
+    class weakref_impl;
+    
+                            RefBase(const RefBase& o);
+            RefBase&        operator=(const RefBase& o);
+
+private:
+    friend class ReferenceMover;
+
+    static void renameRefs(size_t n, const ReferenceRenamer& renamer);
+
+    static void renameRefId(weakref_type* ref,
+            const void* old_id, const void* new_id);
+
+    static void renameRefId(RefBase* ref,
+            const void* old_id, const void* new_id);
+
+        weakref_impl* const mRefs;
+};
+
+// ---------------------------------------------------------------------------
+
+template <class T>
+class LightRefBase
+{
+public:
+    inline LightRefBase() : mCount(0) { }
+    inline void incStrong(__attribute__((unused)) const void* id) const {
+        android_atomic_inc(&mCount);
+    }
+    inline void decStrong(__attribute__((unused)) const void* id) const {
+        if (android_atomic_dec(&mCount) == 1) {
+            delete static_cast<const T*>(this);
+        }
+    }
+    //! DEBUGGING ONLY: Get current strong ref count.
+    inline int32_t getStrongCount() const {
+        return mCount;
+    }
+
+    typedef LightRefBase<T> basetype;
+
+protected:
+    inline ~LightRefBase() { }
+
+private:
+    friend class ReferenceMover;
+    inline static void renameRefs(size_t n, const ReferenceRenamer& renamer) { }
+    inline static void renameRefId(T* ref,
+            const void* old_id, const void* new_id) { }
+
+private:
+    mutable volatile int32_t mCount;
+};
+
+// ---------------------------------------------------------------------------
+
+template <typename T>
+class wp
+{
+public:
+    typedef typename RefBase::weakref_type weakref_type;
+    
+    inline wp() : m_ptr(0) { }
+
+    wp(T* other);
+    wp(const wp<T>& other);
+    wp(const sp<T>& other);
+    template<typename U> wp(U* other);
+    template<typename U> wp(const sp<U>& other);
+    template<typename U> wp(const wp<U>& other);
+
+    ~wp();
+    
+    // Assignment
+
+    wp& operator = (T* other);
+    wp& operator = (const wp<T>& other);
+    wp& operator = (const sp<T>& other);
+    
+    template<typename U> wp& operator = (U* other);
+    template<typename U> wp& operator = (const wp<U>& other);
+    template<typename U> wp& operator = (const sp<U>& other);
+    
+    void set_object_and_refs(T* other, weakref_type* refs);
+
+    // promotion to sp
+    
+    sp<T> promote() const;
+
+    // Reset
+    
+    void clear();
+
+    // Accessors
+    
+    inline  weakref_type* get_refs() const { return m_refs; }
+    
+    inline  T* unsafe_get() const { return m_ptr; }
+
+    // Operators
+
+    COMPARE_WEAK(==)
+    COMPARE_WEAK(!=)
+    COMPARE_WEAK(>)
+    COMPARE_WEAK(<)
+    COMPARE_WEAK(<=)
+    COMPARE_WEAK(>=)
+
+    inline bool operator == (const wp<T>& o) const {
+        return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
+    }
+    template<typename U>
+    inline bool operator == (const wp<U>& o) const {
+        return m_ptr == o.m_ptr;
+    }
+
+    inline bool operator > (const wp<T>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+    }
+    template<typename U>
+    inline bool operator > (const wp<U>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+    }
+
+    inline bool operator < (const wp<T>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+    }
+    template<typename U>
+    inline bool operator < (const wp<U>& o) const {
+        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+    }
+                         inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
+    template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
+                         inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
+    template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
+                         inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
+    template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
+
+private:
+    template<typename Y> friend class sp;
+    template<typename Y> friend class wp;
+
+    T*              m_ptr;
+    weakref_type*   m_refs;
+};
+
+template <typename T>
+TextOutput& operator<<(TextOutput& to, const wp<T>& val);
+
+#undef COMPARE_WEAK
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts below here.
+
+template<typename T>
+wp<T>::wp(T* other)
+    : m_ptr(other)
+{
+    if (other) m_refs = other->createWeak(this);
+}
+
+template<typename T>
+wp<T>::wp(const wp<T>& other)
+    : m_ptr(other.m_ptr), m_refs(other.m_refs)
+{
+    if (m_ptr) m_refs->incWeak(this);
+}
+
+template<typename T>
+wp<T>::wp(const sp<T>& other)
+    : m_ptr(other.m_ptr)
+{
+    if (m_ptr) {
+        m_refs = m_ptr->createWeak(this);
+    }
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(U* other)
+    : m_ptr(other)
+{
+    if (other) m_refs = other->createWeak(this);
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(const wp<U>& other)
+    : m_ptr(other.m_ptr)
+{
+    if (m_ptr) {
+        m_refs = other.m_refs;
+        m_refs->incWeak(this);
+    }
+}
+
+template<typename T> template<typename U>
+wp<T>::wp(const sp<U>& other)
+    : m_ptr(other.m_ptr)
+{
+    if (m_ptr) {
+        m_refs = m_ptr->createWeak(this);
+    }
+}
+
+template<typename T>
+wp<T>::~wp()
+{
+    if (m_ptr) m_refs->decWeak(this);
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (T* other)
+{
+    weakref_type* newRefs =
+        other ? other->createWeak(this) : 0;
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = other;
+    m_refs = newRefs;
+    return *this;
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (const wp<T>& other)
+{
+    weakref_type* otherRefs(other.m_refs);
+    T* otherPtr(other.m_ptr);
+    if (otherPtr) otherRefs->incWeak(this);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = otherRefs;
+    return *this;
+}
+
+template<typename T>
+wp<T>& wp<T>::operator = (const sp<T>& other)
+{
+    weakref_type* newRefs =
+        other != NULL ? other->createWeak(this) : 0;
+    T* otherPtr(other.m_ptr);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = newRefs;
+    return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (U* other)
+{
+    weakref_type* newRefs =
+        other ? other->createWeak(this) : 0;
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = other;
+    m_refs = newRefs;
+    return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (const wp<U>& other)
+{
+    weakref_type* otherRefs(other.m_refs);
+    U* otherPtr(other.m_ptr);
+    if (otherPtr) otherRefs->incWeak(this);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = otherRefs;
+    return *this;
+}
+
+template<typename T> template<typename U>
+wp<T>& wp<T>::operator = (const sp<U>& other)
+{
+    weakref_type* newRefs =
+        other != NULL ? other->createWeak(this) : 0;
+    U* otherPtr(other.m_ptr);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = otherPtr;
+    m_refs = newRefs;
+    return *this;
+}
+
+template<typename T>
+void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
+{
+    if (other) refs->incWeak(this);
+    if (m_ptr) m_refs->decWeak(this);
+    m_ptr = other;
+    m_refs = refs;
+}
+
+template<typename T>
+sp<T> wp<T>::promote() const
+{
+    sp<T> result;
+    if (m_ptr && m_refs->attemptIncStrong(&result)) {
+        result.set_pointer(m_ptr);
+    }
+    return result;
+}
+
+template<typename T>
+void wp<T>::clear()
+{
+    if (m_ptr) {
+        m_refs->decWeak(this);
+        m_ptr = 0;
+    }
+}
+
+template <typename T>
+inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
+{
+    return printWeakPointer(to, val.unsafe_get());
+}
+
+// ---------------------------------------------------------------------------
+
+// this class just serves as a namespace so TYPE::moveReferences can stay
+// private.
+class ReferenceMover {
+public:
+    // it would be nice if we could make sure no extra code is generated
+    // for sp<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
+    // Using a sp<RefBase> override doesn't work; it's a bit like we wanted
+    // a template<typename TYPE inherits RefBase> template...
+
+    template<typename TYPE> static inline
+    void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+
+        class Renamer : public ReferenceRenamer {
+            sp<TYPE>* d;
+            sp<TYPE> const* s;
+            virtual void operator()(size_t i) const {
+                // The id are known to be the sp<>'s this pointer
+                TYPE::renameRefId(d[i].get(), &s[i], &d[i]);
+            }
+        public:
+            Renamer(sp<TYPE>* d, sp<TYPE> const* s) : s(s), d(d) { }
+        };
+
+        memmove(d, s, n*sizeof(sp<TYPE>));
+        TYPE::renameRefs(n, Renamer(d, s));
+    }
+
+
+    template<typename TYPE> static inline
+    void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+
+        class Renamer : public ReferenceRenamer {
+            wp<TYPE>* d;
+            wp<TYPE> const* s;
+            virtual void operator()(size_t i) const {
+                // The id are known to be the wp<>'s this pointer
+                TYPE::renameRefId(d[i].get_refs(), &s[i], &d[i]);
+            }
+        public:
+            Renamer(wp<TYPE>* d, wp<TYPE> const* s) : s(s), d(d) { }
+        };
+
+        memmove(d, s, n*sizeof(wp<TYPE>));
+        TYPE::renameRefs(n, Renamer(d, s));
+    }
+};
+
+// specialization for moving sp<> and wp<> types.
+// these are used by the [Sorted|Keyed]Vector<> implementations
+// sp<> and wp<> need to be handled specially, because they do not
+// have trivial copy operation in the general case (see RefBase.cpp
+// when DEBUG ops are enabled), but can be implemented very
+// efficiently in most cases.
+
+template<typename TYPE> inline
+void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+template<typename TYPE> inline
+void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
+    ReferenceMover::move_references(d, s, n);
+}
+
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_REF_BASE_H
diff --git a/include/utils/SharedBuffer.h b/include/utils/SharedBuffer.h
new file mode 100644
index 0000000..b670953
--- /dev/null
+++ b/include/utils/SharedBuffer.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_SHARED_BUFFER_H
+#define ANDROID_SHARED_BUFFER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class SharedBuffer
+{
+public:
+
+    /* flags to use with release() */
+    enum {
+        eKeepStorage = 0x00000001
+    };
+
+    /*! allocate a buffer of size 'size' and acquire() it.
+     *  call release() to free it.
+     */
+    static          SharedBuffer*           alloc(size_t size);
+    
+    /*! free the memory associated with the SharedBuffer.
+     * Fails if there are any users associated with this SharedBuffer.
+     * In other words, the buffer must have been release by all its
+     * users.
+     */
+    static          ssize_t                 dealloc(const SharedBuffer* released);
+
+    //! access the data for read
+    inline          const void*             data() const;
+    
+    //! access the data for read/write
+    inline          void*                   data();
+
+    //! get size of the buffer
+    inline          size_t                  size() const;
+ 
+    //! get back a SharedBuffer object from its data
+    static  inline  SharedBuffer*           bufferFromData(void* data);
+    
+    //! get back a SharedBuffer object from its data
+    static  inline  const SharedBuffer*     bufferFromData(const void* data);
+
+    //! get the size of a SharedBuffer object from its data
+    static  inline  size_t                  sizeFromData(const void* data);
+    
+    //! edit the buffer (get a writtable, or non-const, version of it)
+                    SharedBuffer*           edit() const;
+
+    //! edit the buffer, resizing if needed
+                    SharedBuffer*           editResize(size_t size) const;
+
+    //! like edit() but fails if a copy is required
+                    SharedBuffer*           attemptEdit() const;
+    
+    //! resize and edit the buffer, loose it's content.
+                    SharedBuffer*           reset(size_t size) const;
+
+    //! acquire/release a reference on this buffer
+                    void                    acquire() const;
+                    
+    /*! release a reference on this buffer, with the option of not
+     * freeing the memory associated with it if it was the last reference
+     * returns the previous reference count
+     */     
+                    int32_t                 release(uint32_t flags = 0) const;
+    
+    //! returns wether or not we're the only owner
+    inline          bool                    onlyOwner() const;
+    
+
+private:
+        inline SharedBuffer() { }
+        inline ~SharedBuffer() { }
+        SharedBuffer(const SharedBuffer&);
+        SharedBuffer& operator = (const SharedBuffer&);
+ 
+        // 16 bytes. must be sized to preserve correct alignment.
+        mutable int32_t        mRefs;
+                size_t         mSize;
+                uint32_t       mReserved[2];
+};
+
+// ---------------------------------------------------------------------------
+
+const void* SharedBuffer::data() const {
+    return this + 1;
+}
+
+void* SharedBuffer::data() {
+    return this + 1;
+}
+
+size_t SharedBuffer::size() const {
+    return mSize;
+}
+
+SharedBuffer* SharedBuffer::bufferFromData(void* data) {
+    return data ? static_cast<SharedBuffer *>(data)-1 : 0;
+}
+    
+const SharedBuffer* SharedBuffer::bufferFromData(const void* data) {
+    return data ? static_cast<const SharedBuffer *>(data)-1 : 0;
+}
+
+size_t SharedBuffer::sizeFromData(const void* data) {
+    return data ? bufferFromData(data)->mSize : 0;
+}
+
+bool SharedBuffer::onlyOwner() const {
+    return (mRefs == 1);
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_H
diff --git a/include/utils/Singleton.h b/include/utils/Singleton.h
new file mode 100644
index 0000000..c60680e
--- /dev/null
+++ b/include/utils/Singleton.h
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_UTILS_SINGLETON_H
+#define ANDROID_UTILS_SINGLETON_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/threads.h>
+#include <cutils/compiler.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+template <typename TYPE>
+class ANDROID_API Singleton
+{
+public:
+    static TYPE& getInstance() {
+        Mutex::Autolock _l(sLock);
+        TYPE* instance = sInstance;
+        if (instance == 0) {
+            instance = new TYPE();
+            sInstance = instance;
+        }
+        return *instance;
+    }
+
+    static bool hasInstance() {
+        Mutex::Autolock _l(sLock);
+        return sInstance != 0;
+    }
+    
+protected:
+    ~Singleton() { };
+    Singleton() { };
+
+private:
+    Singleton(const Singleton&);
+    Singleton& operator = (const Singleton&);
+    static Mutex sLock;
+    static TYPE* sInstance;
+};
+
+/*
+ * use ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) in your implementation file
+ * (eg: <TYPE>.cpp) to create the static instance of Singleton<>'s attributes,
+ * and avoid to have a copy of them in each compilation units Singleton<TYPE>
+ * is used.
+ * NOTE: we use a version of Mutex ctor that takes a parameter, because
+ * for some unknown reason using the default ctor doesn't emit the variable!
+ */
+
+#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE)                 \
+    template<> Mutex Singleton< TYPE >::sLock(Mutex::PRIVATE);  \
+    template<> TYPE* Singleton< TYPE >::sInstance(0);           \
+    template class Singleton< TYPE >;
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_UTILS_SINGLETON_H
+
diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h
new file mode 100644
index 0000000..2d3e82a
--- /dev/null
+++ b/include/utils/SortedVector.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_SORTED_VECTOR_H
+#define ANDROID_SORTED_VECTOR_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/log.h>
+
+#include <utils/Vector.h>
+#include <utils/VectorImpl.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <class TYPE>
+class SortedVector : private SortedVectorImpl
+{
+    friend class Vector<TYPE>;
+
+public:
+            typedef TYPE    value_type;
+    
+    /*! 
+     * Constructors and destructors
+     */
+    
+                            SortedVector();
+                            SortedVector(const SortedVector<TYPE>& rhs);
+    virtual                 ~SortedVector();
+
+    /*! copy operator */
+    const SortedVector<TYPE>&   operator = (const SortedVector<TYPE>& rhs) const;    
+    SortedVector<TYPE>&         operator = (const SortedVector<TYPE>& rhs);    
+
+    /*
+     * empty the vector
+     */
+
+    inline  void            clear()             { VectorImpl::clear(); }
+
+    /*! 
+     * vector stats
+     */
+
+    //! returns number of items in the vector
+    inline  size_t          size() const                { return VectorImpl::size(); }
+    //! returns whether or not the vector is empty
+    inline  bool            isEmpty() const             { return VectorImpl::isEmpty(); }
+    //! returns how many items can be stored without reallocating the backing store
+    inline  size_t          capacity() const            { return VectorImpl::capacity(); }
+    //! sets the capacity. capacity can never be reduced less than size()
+    inline  ssize_t         setCapacity(size_t size)    { return VectorImpl::setCapacity(size); }
+
+    /*! 
+     * C-style array access
+     */
+     
+    //! read-only C-style access 
+    inline  const TYPE*     array() const;
+
+    //! read-write C-style access. BE VERY CAREFUL when modifying the array
+    //! you must keep it sorted! You usually don't use this function.
+            TYPE*           editArray();
+
+            //! finds the index of an item
+            ssize_t         indexOf(const TYPE& item) const;
+            
+            //! finds where this item should be inserted
+            size_t          orderOf(const TYPE& item) const;
+            
+    
+    /*! 
+     * accessors
+     */
+
+    //! read-only access to an item at a given index
+    inline  const TYPE&     operator [] (size_t index) const;
+    //! alternate name for operator []
+    inline  const TYPE&     itemAt(size_t index) const;
+    //! stack-usage of the vector. returns the top of the stack (last element)
+            const TYPE&     top() const;
+
+    /*!
+     * modifying the array
+     */
+
+            //! add an item in the right place (and replace the one that is there)
+            ssize_t         add(const TYPE& item);
+            
+            //! editItemAt() MUST NOT change the order of this item
+            TYPE&           editItemAt(size_t index) {
+                return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
+            }
+
+            //! merges a vector into this one
+            ssize_t         merge(const Vector<TYPE>& vector);
+            ssize_t         merge(const SortedVector<TYPE>& vector);
+            
+            //! removes an item
+            ssize_t         remove(const TYPE&);
+
+    //! remove several items
+    inline  ssize_t         removeItemsAt(size_t index, size_t count = 1);
+    //! remove one item
+    inline  ssize_t         removeAt(size_t index)  { return removeItemsAt(index); }
+            
+protected:
+    virtual void    do_construct(void* storage, size_t num) const;
+    virtual void    do_destroy(void* storage, size_t num) const;
+    virtual void    do_copy(void* dest, const void* from, size_t num) const;
+    virtual void    do_splat(void* dest, const void* item, size_t num) const;
+    virtual void    do_move_forward(void* dest, const void* from, size_t num) const;
+    virtual void    do_move_backward(void* dest, const void* from, size_t num) const;
+    virtual int     do_compare(const void* lhs, const void* rhs) const;
+};
+
+// SortedVector<T> can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+template<typename T> struct trait_trivial_move<SortedVector<T> > { enum { value = true }; };
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts from here...
+// ---------------------------------------------------------------------------
+
+template<class TYPE> inline
+SortedVector<TYPE>::SortedVector()
+    : SortedVectorImpl(sizeof(TYPE),
+                ((traits<TYPE>::has_trivial_ctor   ? HAS_TRIVIAL_CTOR   : 0)
+                |(traits<TYPE>::has_trivial_dtor   ? HAS_TRIVIAL_DTOR   : 0)
+                |(traits<TYPE>::has_trivial_copy   ? HAS_TRIVIAL_COPY   : 0))
+                )
+{
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>::SortedVector(const SortedVector<TYPE>& rhs)
+    : SortedVectorImpl(rhs) {
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>::~SortedVector() {
+    finish_vector();
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+    SortedVectorImpl::operator = (rhs);
+    return *this; 
+}
+
+template<class TYPE> inline
+const SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
+    SortedVectorImpl::operator = (rhs);
+    return *this; 
+}
+
+template<class TYPE> inline
+const TYPE* SortedVector<TYPE>::array() const {
+    return static_cast<const TYPE *>(arrayImpl());
+}
+
+template<class TYPE> inline
+TYPE* SortedVector<TYPE>::editArray() {
+    return static_cast<TYPE *>(editArrayImpl());
+}
+
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::operator[](size_t index) const {
+    LOG_FATAL_IF(index>=size(),
+            "%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
+            int(index), int(size()));
+    return *(array() + index);
+}
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::itemAt(size_t index) const {
+    return operator[](index);
+}
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::top() const {
+    return *(array() + size() - 1);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::add(const TYPE& item) {
+    return SortedVectorImpl::add(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::indexOf(const TYPE& item) const {
+    return SortedVectorImpl::indexOf(&item);
+}
+
+template<class TYPE> inline
+size_t SortedVector<TYPE>::orderOf(const TYPE& item) const {
+    return SortedVectorImpl::orderOf(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::merge(const Vector<TYPE>& vector) {
+    return SortedVectorImpl::merge(reinterpret_cast<const VectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::merge(const SortedVector<TYPE>& vector) {
+    return SortedVectorImpl::merge(reinterpret_cast<const SortedVectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::remove(const TYPE& item) {
+    return SortedVectorImpl::remove(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::removeItemsAt(size_t index, size_t count) {
+    return VectorImpl::removeItemsAt(index, count);
+}
+
+// ---------------------------------------------------------------------------
+
+template<class TYPE>
+void SortedVector<TYPE>::do_construct(void* storage, size_t num) const {
+    construct_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_destroy(void* storage, size_t num) const {
+    destroy_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+    copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+    splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+    move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+    move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+int SortedVector<TYPE>::do_compare(const void* lhs, const void* rhs) const {
+    return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
+}
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SORTED_VECTOR_H
diff --git a/include/utils/StopWatch.h b/include/utils/StopWatch.h
new file mode 100644
index 0000000..693dd3c
--- /dev/null
+++ b/include/utils/StopWatch.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_STOPWATCH_H
+#define ANDROID_STOPWATCH_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Timers.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class StopWatch
+{
+public:
+        StopWatch(  const char *name,
+                    int clock = SYSTEM_TIME_MONOTONIC,
+                    uint32_t flags = 0);
+        ~StopWatch();
+        
+        const char* name() const;
+        nsecs_t     lap();
+        nsecs_t     elapsedTime() const;
+
+        void        reset();
+        
+private:
+    const char*     mName;
+    int             mClock;
+    uint32_t        mFlags;
+    
+    struct lap_t {
+        nsecs_t     soFar;
+        nsecs_t     thisLap;
+    };
+    
+    nsecs_t         mStartTime;
+    lap_t           mLaps[8];
+    int             mNumLaps;
+};
+
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STOPWATCH_H
diff --git a/include/utils/String16.h b/include/utils/String16.h
new file mode 100644
index 0000000..d131bfc
--- /dev/null
+++ b/include/utils/String16.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_STRING16_H
+#define ANDROID_STRING16_H
+
+#include <utils/Errors.h>
+#include <utils/SharedBuffer.h>
+#include <utils/Unicode.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+
+extern "C" {
+
+}
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class String8;
+class TextOutput;
+
+//! This is a string holding UTF-16 characters.
+class String16
+{
+public:
+    /* use String16(StaticLinkage) if you're statically linking against
+     * libutils and declaring an empty static String16, e.g.:
+     *
+     *   static String16 sAStaticEmptyString(String16::kEmptyString);
+     *   static String16 sAnotherStaticEmptyString(sAStaticEmptyString);
+     */
+    enum StaticLinkage { kEmptyString };
+
+                                String16();
+    explicit                    String16(StaticLinkage);
+                                String16(const String16& o);
+                                String16(const String16& o,
+                                         size_t len,
+                                         size_t begin=0);
+    explicit                    String16(const char16_t* o);
+    explicit                    String16(const char16_t* o, size_t len);
+    explicit                    String16(const String8& o);
+    explicit                    String16(const char* o);
+    explicit                    String16(const char* o, size_t len);
+
+                                ~String16();
+    
+    inline  const char16_t*     string() const;
+    inline  size_t              size() const;
+    
+    inline  const SharedBuffer* sharedBuffer() const;
+    
+            void                setTo(const String16& other);
+            status_t            setTo(const char16_t* other);
+            status_t            setTo(const char16_t* other, size_t len);
+            status_t            setTo(const String16& other,
+                                      size_t len,
+                                      size_t begin=0);
+    
+            status_t            append(const String16& other);
+            status_t            append(const char16_t* other, size_t len);
+            
+    inline  String16&           operator=(const String16& other);
+    
+    inline  String16&           operator+=(const String16& other);
+    inline  String16            operator+(const String16& other) const;
+
+            status_t            insert(size_t pos, const char16_t* chrs);
+            status_t            insert(size_t pos,
+                                       const char16_t* chrs, size_t len);
+
+            ssize_t             findFirst(char16_t c) const;
+            ssize_t             findLast(char16_t c) const;
+
+            bool                startsWith(const String16& prefix) const;
+            bool                startsWith(const char16_t* prefix) const;
+            
+            status_t            makeLower();
+
+            status_t            replaceAll(char16_t replaceThis,
+                                           char16_t withThis);
+
+            status_t            remove(size_t len, size_t begin=0);
+
+    inline  int                 compare(const String16& other) const;
+
+    inline  bool                operator<(const String16& other) const;
+    inline  bool                operator<=(const String16& other) const;
+    inline  bool                operator==(const String16& other) const;
+    inline  bool                operator!=(const String16& other) const;
+    inline  bool                operator>=(const String16& other) const;
+    inline  bool                operator>(const String16& other) const;
+    
+    inline  bool                operator<(const char16_t* other) const;
+    inline  bool                operator<=(const char16_t* other) const;
+    inline  bool                operator==(const char16_t* other) const;
+    inline  bool                operator!=(const char16_t* other) const;
+    inline  bool                operator>=(const char16_t* other) const;
+    inline  bool                operator>(const char16_t* other) const;
+    
+    inline                      operator const char16_t*() const;
+    
+private:
+            const char16_t*     mString;
+};
+
+// String16 can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+ANDROID_TRIVIAL_MOVE_TRAIT(String16)
+
+// ---------------------------------------------------------------------------
+// No user servicable parts below.
+
+inline int compare_type(const String16& lhs, const String16& rhs)
+{
+    return lhs.compare(rhs);
+}
+
+inline int strictly_order_type(const String16& lhs, const String16& rhs)
+{
+    return compare_type(lhs, rhs) < 0;
+}
+
+inline const char16_t* String16::string() const
+{
+    return mString;
+}
+
+inline size_t String16::size() const
+{
+    return SharedBuffer::sizeFromData(mString)/sizeof(char16_t)-1;
+}
+
+inline const SharedBuffer* String16::sharedBuffer() const
+{
+    return SharedBuffer::bufferFromData(mString);
+}
+
+inline String16& String16::operator=(const String16& other)
+{
+    setTo(other);
+    return *this;
+}
+
+inline String16& String16::operator+=(const String16& other)
+{
+    append(other);
+    return *this;
+}
+
+inline String16 String16::operator+(const String16& other) const
+{
+    String16 tmp(*this);
+    tmp += other;
+    return tmp;
+}
+
+inline int String16::compare(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size());
+}
+
+inline bool String16::operator<(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) < 0;
+}
+
+inline bool String16::operator<=(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) <= 0;
+}
+
+inline bool String16::operator==(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) == 0;
+}
+
+inline bool String16::operator!=(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) != 0;
+}
+
+inline bool String16::operator>=(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) >= 0;
+}
+
+inline bool String16::operator>(const String16& other) const
+{
+    return strzcmp16(mString, size(), other.mString, other.size()) > 0;
+}
+
+inline bool String16::operator<(const char16_t* other) const
+{
+    return strcmp16(mString, other) < 0;
+}
+
+inline bool String16::operator<=(const char16_t* other) const
+{
+    return strcmp16(mString, other) <= 0;
+}
+
+inline bool String16::operator==(const char16_t* other) const
+{
+    return strcmp16(mString, other) == 0;
+}
+
+inline bool String16::operator!=(const char16_t* other) const
+{
+    return strcmp16(mString, other) != 0;
+}
+
+inline bool String16::operator>=(const char16_t* other) const
+{
+    return strcmp16(mString, other) >= 0;
+}
+
+inline bool String16::operator>(const char16_t* other) const
+{
+    return strcmp16(mString, other) > 0;
+}
+
+inline String16::operator const char16_t*() const
+{
+    return mString;
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STRING16_H
diff --git a/include/utils/String8.h b/include/utils/String8.h
new file mode 100644
index 0000000..ef59470
--- /dev/null
+++ b/include/utils/String8.h
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_STRING8_H
+#define ANDROID_STRING8_H
+
+#include <utils/Errors.h>
+#include <utils/SharedBuffer.h>
+#include <utils/Unicode.h>
+#include <utils/TypeHelpers.h>
+
+#include <string.h> // for strcmp
+#include <stdarg.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+class String16;
+class TextOutput;
+
+//! This is a string holding UTF-8 characters. Does not allow the value more
+// than 0x10FFFF, which is not valid unicode codepoint.
+class String8
+{
+public:
+    /* use String8(StaticLinkage) if you're statically linking against
+     * libutils and declaring an empty static String8, e.g.:
+     *
+     *   static String8 sAStaticEmptyString(String8::kEmptyString);
+     *   static String8 sAnotherStaticEmptyString(sAStaticEmptyString);
+     */
+    enum StaticLinkage { kEmptyString };
+
+                                String8();
+    explicit                    String8(StaticLinkage);
+                                String8(const String8& o);
+    explicit                    String8(const char* o);
+    explicit                    String8(const char* o, size_t numChars);
+    
+    explicit                    String8(const String16& o);
+    explicit                    String8(const char16_t* o);
+    explicit                    String8(const char16_t* o, size_t numChars);
+    explicit                    String8(const char32_t* o);
+    explicit                    String8(const char32_t* o, size_t numChars);
+                                ~String8();
+
+    static inline const String8 empty();
+
+    static String8              format(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
+    static String8              formatV(const char* fmt, va_list args);
+
+    inline  const char*         string() const;
+    inline  size_t              size() const;
+    inline  size_t              length() const;
+    inline  size_t              bytes() const;
+    inline  bool                isEmpty() const;
+    
+    inline  const SharedBuffer* sharedBuffer() const;
+    
+            void                clear();
+
+            void                setTo(const String8& other);
+            status_t            setTo(const char* other);
+            status_t            setTo(const char* other, size_t numChars);
+            status_t            setTo(const char16_t* other, size_t numChars);
+            status_t            setTo(const char32_t* other,
+                                      size_t length);
+
+            status_t            append(const String8& other);
+            status_t            append(const char* other);
+            status_t            append(const char* other, size_t numChars);
+
+            status_t            appendFormat(const char* fmt, ...)
+                    __attribute__((format (printf, 2, 3)));
+            status_t            appendFormatV(const char* fmt, va_list args);
+
+            // Note that this function takes O(N) time to calculate the value.
+            // No cache value is stored.
+            size_t              getUtf32Length() const;
+            int32_t             getUtf32At(size_t index,
+                                           size_t *next_index) const;
+            void                getUtf32(char32_t* dst) const;
+
+    inline  String8&            operator=(const String8& other);
+    inline  String8&            operator=(const char* other);
+    
+    inline  String8&            operator+=(const String8& other);
+    inline  String8             operator+(const String8& other) const;
+    
+    inline  String8&            operator+=(const char* other);
+    inline  String8             operator+(const char* other) const;
+
+    inline  int                 compare(const String8& other) const;
+
+    inline  bool                operator<(const String8& other) const;
+    inline  bool                operator<=(const String8& other) const;
+    inline  bool                operator==(const String8& other) const;
+    inline  bool                operator!=(const String8& other) const;
+    inline  bool                operator>=(const String8& other) const;
+    inline  bool                operator>(const String8& other) const;
+    
+    inline  bool                operator<(const char* other) const;
+    inline  bool                operator<=(const char* other) const;
+    inline  bool                operator==(const char* other) const;
+    inline  bool                operator!=(const char* other) const;
+    inline  bool                operator>=(const char* other) const;
+    inline  bool                operator>(const char* other) const;
+    
+    inline                      operator const char*() const;
+    
+            char*               lockBuffer(size_t size);
+            void                unlockBuffer();
+            status_t            unlockBuffer(size_t size);
+            
+            // return the index of the first byte of other in this at or after
+            // start, or -1 if not found
+            ssize_t             find(const char* other, size_t start = 0) const;
+
+            void                toLower();
+            void                toLower(size_t start, size_t numChars);
+            void                toUpper();
+            void                toUpper(size_t start, size_t numChars);
+
+    /*
+     * These methods operate on the string as if it were a path name.
+     */
+
+    /*
+     * Set the filename field to a specific value.
+     *
+     * Normalizes the filename, removing a trailing '/' if present.
+     */
+    void setPathName(const char* name);
+    void setPathName(const char* name, size_t numChars);
+
+    /*
+     * Get just the filename component.
+     *
+     * "/tmp/foo/bar.c" --> "bar.c"
+     */
+    String8 getPathLeaf(void) const;
+
+    /*
+     * Remove the last (file name) component, leaving just the directory
+     * name.
+     *
+     * "/tmp/foo/bar.c" --> "/tmp/foo"
+     * "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX
+     * "bar.c" --> ""
+     */
+    String8 getPathDir(void) const;
+
+    /*
+     * Retrieve the front (root dir) component.  Optionally also return the
+     * remaining components.
+     *
+     * "/tmp/foo/bar.c" --> "tmp" (remain = "foo/bar.c")
+     * "/tmp" --> "tmp" (remain = "")
+     * "bar.c" --> "bar.c" (remain = "")
+     */
+    String8 walkPath(String8* outRemains = NULL) const;
+
+    /*
+     * Return the filename extension.  This is the last '.' and any number
+     * of characters that follow it.  The '.' is included in case we
+     * decide to expand our definition of what constitutes an extension.
+     *
+     * "/tmp/foo/bar.c" --> ".c"
+     * "/tmp" --> ""
+     * "/tmp/foo.bar/baz" --> ""
+     * "foo.jpeg" --> ".jpeg"
+     * "foo." --> ""
+     */
+    String8 getPathExtension(void) const;
+
+    /*
+     * Return the path without the extension.  Rules for what constitutes
+     * an extension are described in the comment for getPathExtension().
+     *
+     * "/tmp/foo/bar.c" --> "/tmp/foo/bar"
+     */
+    String8 getBasePath(void) const;
+
+    /*
+     * Add a component to the pathname.  We guarantee that there is
+     * exactly one path separator between the old path and the new.
+     * If there is no existing name, we just copy the new name in.
+     *
+     * If leaf is a fully qualified path (i.e. starts with '/', it
+     * replaces whatever was there before.
+     */
+    String8& appendPath(const char* leaf);
+    String8& appendPath(const String8& leaf)  { return appendPath(leaf.string()); }
+
+    /*
+     * Like appendPath(), but does not affect this string.  Returns a new one instead.
+     */
+    String8 appendPathCopy(const char* leaf) const
+                                             { String8 p(*this); p.appendPath(leaf); return p; }
+    String8 appendPathCopy(const String8& leaf) const { return appendPathCopy(leaf.string()); }
+
+    /*
+     * Converts all separators in this string to /, the default path separator.
+     *
+     * If the default OS separator is backslash, this converts all
+     * backslashes to slashes, in-place. Otherwise it does nothing.
+     * Returns self.
+     */
+    String8& convertToResPath();
+
+private:
+            status_t            real_append(const char* other, size_t numChars);
+            char*               find_extension(void) const;
+
+            const char* mString;
+};
+
+// String8 can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+ANDROID_TRIVIAL_MOVE_TRAIT(String8)
+
+// ---------------------------------------------------------------------------
+// No user servicable parts below.
+
+inline int compare_type(const String8& lhs, const String8& rhs)
+{
+    return lhs.compare(rhs);
+}
+
+inline int strictly_order_type(const String8& lhs, const String8& rhs)
+{
+    return compare_type(lhs, rhs) < 0;
+}
+
+inline const String8 String8::empty() {
+    return String8();
+}
+
+inline const char* String8::string() const
+{
+    return mString;
+}
+
+inline size_t String8::length() const
+{
+    return SharedBuffer::sizeFromData(mString)-1;
+}
+
+inline size_t String8::size() const
+{
+    return length();
+}
+
+inline bool String8::isEmpty() const
+{
+    return length() == 0;
+}
+
+inline size_t String8::bytes() const
+{
+    return SharedBuffer::sizeFromData(mString)-1;
+}
+
+inline const SharedBuffer* String8::sharedBuffer() const
+{
+    return SharedBuffer::bufferFromData(mString);
+}
+
+inline String8& String8::operator=(const String8& other)
+{
+    setTo(other);
+    return *this;
+}
+
+inline String8& String8::operator=(const char* other)
+{
+    setTo(other);
+    return *this;
+}
+
+inline String8& String8::operator+=(const String8& other)
+{
+    append(other);
+    return *this;
+}
+
+inline String8 String8::operator+(const String8& other) const
+{
+    String8 tmp(*this);
+    tmp += other;
+    return tmp;
+}
+
+inline String8& String8::operator+=(const char* other)
+{
+    append(other);
+    return *this;
+}
+
+inline String8 String8::operator+(const char* other) const
+{
+    String8 tmp(*this);
+    tmp += other;
+    return tmp;
+}
+
+inline int String8::compare(const String8& other) const
+{
+    return strcmp(mString, other.mString);
+}
+
+inline bool String8::operator<(const String8& other) const
+{
+    return strcmp(mString, other.mString) < 0;
+}
+
+inline bool String8::operator<=(const String8& other) const
+{
+    return strcmp(mString, other.mString) <= 0;
+}
+
+inline bool String8::operator==(const String8& other) const
+{
+    return strcmp(mString, other.mString) == 0;
+}
+
+inline bool String8::operator!=(const String8& other) const
+{
+    return strcmp(mString, other.mString) != 0;
+}
+
+inline bool String8::operator>=(const String8& other) const
+{
+    return strcmp(mString, other.mString) >= 0;
+}
+
+inline bool String8::operator>(const String8& other) const
+{
+    return strcmp(mString, other.mString) > 0;
+}
+
+inline bool String8::operator<(const char* other) const
+{
+    return strcmp(mString, other) < 0;
+}
+
+inline bool String8::operator<=(const char* other) const
+{
+    return strcmp(mString, other) <= 0;
+}
+
+inline bool String8::operator==(const char* other) const
+{
+    return strcmp(mString, other) == 0;
+}
+
+inline bool String8::operator!=(const char* other) const
+{
+    return strcmp(mString, other) != 0;
+}
+
+inline bool String8::operator>=(const char* other) const
+{
+    return strcmp(mString, other) >= 0;
+}
+
+inline bool String8::operator>(const char* other) const
+{
+    return strcmp(mString, other) > 0;
+}
+
+inline String8::operator const char*() const
+{
+    return mString;
+}
+
+}  // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STRING8_H
diff --git a/include/utils/StrongPointer.h b/include/utils/StrongPointer.h
new file mode 100644
index 0000000..aba9577
--- /dev/null
+++ b/include/utils/StrongPointer.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_STRONG_POINTER_H
+#define ANDROID_STRONG_POINTER_H
+
+#include <cutils/atomic.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+template<typename T> class wp;
+
+// ---------------------------------------------------------------------------
+
+#define COMPARE(_op_)                                           \
+inline bool operator _op_ (const sp<T>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}                                                               \
+inline bool operator _op_ (const T* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}                                                               \
+template<typename U>                                            \
+inline bool operator _op_ (const sp<U>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}                                                               \
+template<typename U>                                            \
+inline bool operator _op_ (const U* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}                                                               \
+inline bool operator _op_ (const wp<T>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}                                                               \
+template<typename U>                                            \
+inline bool operator _op_ (const wp<U>& o) const {              \
+    return m_ptr _op_ o.m_ptr;                                  \
+}
+
+// ---------------------------------------------------------------------------
+
+template<typename T>
+class sp {
+public:
+    inline sp() : m_ptr(0) { }
+
+    sp(T* other);
+    sp(const sp<T>& other);
+    template<typename U> sp(U* other);
+    template<typename U> sp(const sp<U>& other);
+
+    ~sp();
+
+    // Assignment
+
+    sp& operator = (T* other);
+    sp& operator = (const sp<T>& other);
+
+    template<typename U> sp& operator = (const sp<U>& other);
+    template<typename U> sp& operator = (U* other);
+
+    //! Special optimization for use by ProcessState (and nobody else).
+    void force_set(T* other);
+
+    // Reset
+
+    void clear();
+
+    // Accessors
+
+    inline  T&      operator* () const  { return *m_ptr; }
+    inline  T*      operator-> () const { return m_ptr;  }
+    inline  T*      get() const         { return m_ptr; }
+
+    // Operators
+
+    COMPARE(==)
+    COMPARE(!=)
+    COMPARE(>)
+    COMPARE(<)
+    COMPARE(<=)
+    COMPARE(>=)
+
+private:    
+    template<typename Y> friend class sp;
+    template<typename Y> friend class wp;
+    void set_pointer(T* ptr);
+    T* m_ptr;
+};
+
+#undef COMPARE
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts below here.
+
+template<typename T>
+sp<T>::sp(T* other)
+        : m_ptr(other) {
+    if (other)
+        other->incStrong(this);
+}
+
+template<typename T>
+sp<T>::sp(const sp<T>& other)
+        : m_ptr(other.m_ptr) {
+    if (m_ptr)
+        m_ptr->incStrong(this);
+}
+
+template<typename T> template<typename U>
+sp<T>::sp(U* other)
+        : m_ptr(other) {
+    if (other)
+        ((T*) other)->incStrong(this);
+}
+
+template<typename T> template<typename U>
+sp<T>::sp(const sp<U>& other)
+        : m_ptr(other.m_ptr) {
+    if (m_ptr)
+        m_ptr->incStrong(this);
+}
+
+template<typename T>
+sp<T>::~sp() {
+    if (m_ptr)
+        m_ptr->decStrong(this);
+}
+
+template<typename T>
+sp<T>& sp<T>::operator =(const sp<T>& other) {
+    T* otherPtr(other.m_ptr);
+    if (otherPtr)
+        otherPtr->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
+    m_ptr = otherPtr;
+    return *this;
+}
+
+template<typename T>
+sp<T>& sp<T>::operator =(T* other) {
+    if (other)
+        other->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
+    m_ptr = other;
+    return *this;
+}
+
+template<typename T> template<typename U>
+sp<T>& sp<T>::operator =(const sp<U>& other) {
+    T* otherPtr(other.m_ptr);
+    if (otherPtr)
+        otherPtr->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
+    m_ptr = otherPtr;
+    return *this;
+}
+
+template<typename T> template<typename U>
+sp<T>& sp<T>::operator =(U* other) {
+    if (other)
+        ((T*) other)->incStrong(this);
+    if (m_ptr)
+        m_ptr->decStrong(this);
+    m_ptr = other;
+    return *this;
+}
+
+template<typename T>
+void sp<T>::force_set(T* other) {
+    other->forceIncStrong(this);
+    m_ptr = other;
+}
+
+template<typename T>
+void sp<T>::clear() {
+    if (m_ptr) {
+        m_ptr->decStrong(this);
+        m_ptr = 0;
+    }
+}
+
+template<typename T>
+void sp<T>::set_pointer(T* ptr) {
+    m_ptr = ptr;
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_STRONG_POINTER_H
diff --git a/include/cutils/zygote.h b/include/utils/SystemClock.h
similarity index 62%
copy from include/cutils/zygote.h
copy to include/utils/SystemClock.h
index a7480d3..01db340 100644
--- a/include/cutils/zygote.h
+++ b/include/utils/SystemClock.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2008 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.
@@ -14,18 +14,19 @@
  * limitations under the License.
  */
 
-#ifndef __CUTILS_ZYGOTE_H
-#define __CUTILS_ZYGOTE_H
+#ifndef ANDROID_UTILS_SYSTEMCLOCK_H
+#define ANDROID_UTILS_SYSTEMCLOCK_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <stdint.h>
+#include <sys/types.h>
 
-int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
-int zygote_run(int argc, const char **argv);
+namespace android {
 
-#ifdef __cplusplus
-}
-#endif
+int64_t uptimeMillis();
+int64_t elapsedRealtime();
+int64_t elapsedRealtimeNano();
 
-#endif /* __CUTILS_ZYGOTE_H */
+}; // namespace android
+
+#endif // ANDROID_UTILS_SYSTEMCLOCK_H
+
diff --git a/include/utils/Thread.h b/include/utils/Thread.h
new file mode 100644
index 0000000..df30611
--- /dev/null
+++ b/include/utils/Thread.h
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBS_UTILS_THREAD_H
+#define _LIBS_UTILS_THREAD_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Condition.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/ThreadDefs.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Thread : virtual public RefBase
+{
+public:
+    // Create a Thread object, but doesn't create or start the associated
+    // thread. See the run() method.
+                        Thread(bool canCallJava = true);
+    virtual             ~Thread();
+
+    // Start the thread in threadLoop() which needs to be implemented.
+    virtual status_t    run(    const char* name = 0,
+                                int32_t priority = PRIORITY_DEFAULT,
+                                size_t stack = 0);
+    
+    // Ask this object's thread to exit. This function is asynchronous, when the
+    // function returns the thread might still be running. Of course, this
+    // function can be called from a different thread.
+    virtual void        requestExit();
+
+    // Good place to do one-time initializations
+    virtual status_t    readyToRun();
+    
+    // Call requestExit() and wait until this object's thread exits.
+    // BE VERY CAREFUL of deadlocks. In particular, it would be silly to call
+    // this function from this object's thread. Will return WOULD_BLOCK in
+    // that case.
+            status_t    requestExitAndWait();
+
+    // Wait until this object's thread exits. Returns immediately if not yet running.
+    // Do not call from this object's thread; will return WOULD_BLOCK in that case.
+            status_t    join();
+
+    // Indicates whether this thread is running or not.
+            bool        isRunning() const;
+
+#ifdef HAVE_ANDROID_OS
+    // Return the thread's kernel ID, same as the thread itself calling gettid() or
+    // androidGetTid(), or -1 if the thread is not running.
+            pid_t       getTid() const;
+#endif
+
+protected:
+    // exitPending() returns true if requestExit() has been called.
+            bool        exitPending() const;
+    
+private:
+    // Derived class must implement threadLoop(). The thread starts its life
+    // here. There are two ways of using the Thread object:
+    // 1) loop: if threadLoop() returns true, it will be called again if
+    //          requestExit() wasn't called.
+    // 2) once: if threadLoop() returns false, the thread will exit upon return.
+    virtual bool        threadLoop() = 0;
+
+private:
+    Thread& operator=(const Thread&);
+    static  int             _threadLoop(void* user);
+    const   bool            mCanCallJava;
+    // always hold mLock when reading or writing
+            thread_id_t     mThread;
+    mutable Mutex           mLock;
+            Condition       mThreadExitedCondition;
+            status_t        mStatus;
+    // note that all accesses of mExitPending and mRunning need to hold mLock
+    volatile bool           mExitPending;
+    volatile bool           mRunning;
+            sp<Thread>      mHoldSelf;
+#ifdef HAVE_ANDROID_OS
+    // legacy for debugging, not used by getTid() as it is set by the child thread
+    // and so is not initialized until the child reaches that point
+            pid_t           mTid;
+#endif
+};
+
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+#endif // _LIBS_UTILS_THREAD_H
+// ---------------------------------------------------------------------------
diff --git a/include/utils/ThreadDefs.h b/include/utils/ThreadDefs.h
new file mode 100644
index 0000000..9711c13
--- /dev/null
+++ b/include/utils/ThreadDefs.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBS_UTILS_THREAD_DEFS_H
+#define _LIBS_UTILS_THREAD_DEFS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <system/graphics.h>
+#include <system/thread_defs.h>
+
+// ---------------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* android_thread_id_t;
+
+typedef int (*android_thread_func_t)(void*);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+// ---------------------------------------------------------------------------
+// C++ API
+#ifdef __cplusplus
+namespace android {
+// ---------------------------------------------------------------------------
+
+typedef android_thread_id_t thread_id_t;
+typedef android_thread_func_t thread_func_t;
+
+enum {
+    PRIORITY_LOWEST         = ANDROID_PRIORITY_LOWEST,
+    PRIORITY_BACKGROUND     = ANDROID_PRIORITY_BACKGROUND,
+    PRIORITY_NORMAL         = ANDROID_PRIORITY_NORMAL,
+    PRIORITY_FOREGROUND     = ANDROID_PRIORITY_FOREGROUND,
+    PRIORITY_DISPLAY        = ANDROID_PRIORITY_DISPLAY,
+    PRIORITY_URGENT_DISPLAY = ANDROID_PRIORITY_URGENT_DISPLAY,
+    PRIORITY_AUDIO          = ANDROID_PRIORITY_AUDIO,
+    PRIORITY_URGENT_AUDIO   = ANDROID_PRIORITY_URGENT_AUDIO,
+    PRIORITY_HIGHEST        = ANDROID_PRIORITY_HIGHEST,
+    PRIORITY_DEFAULT        = ANDROID_PRIORITY_DEFAULT,
+    PRIORITY_MORE_FAVORABLE = ANDROID_PRIORITY_MORE_FAVORABLE,
+    PRIORITY_LESS_FAVORABLE = ANDROID_PRIORITY_LESS_FAVORABLE,
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+#endif  // __cplusplus
+// ---------------------------------------------------------------------------
+
+
+#endif // _LIBS_UTILS_THREAD_DEFS_H
diff --git a/include/utils/Timers.h b/include/utils/Timers.h
new file mode 100644
index 0000000..d015421
--- /dev/null
+++ b/include/utils/Timers.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Timer functions.
+//
+#ifndef _LIBS_UTILS_TIMERS_H
+#define _LIBS_UTILS_TIMERS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+// ------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int64_t nsecs_t;       // nano-seconds
+
+static inline nsecs_t seconds_to_nanoseconds(nsecs_t secs)
+{
+    return secs*1000000000;
+}
+
+static inline nsecs_t milliseconds_to_nanoseconds(nsecs_t secs)
+{
+    return secs*1000000;
+}
+
+static inline nsecs_t microseconds_to_nanoseconds(nsecs_t secs)
+{
+    return secs*1000;
+}
+
+static inline nsecs_t nanoseconds_to_seconds(nsecs_t secs)
+{
+    return secs/1000000000;
+}
+
+static inline nsecs_t nanoseconds_to_milliseconds(nsecs_t secs)
+{
+    return secs/1000000;
+}
+
+static inline nsecs_t nanoseconds_to_microseconds(nsecs_t secs)
+{
+    return secs/1000;
+}
+
+static inline nsecs_t s2ns(nsecs_t v)  {return seconds_to_nanoseconds(v);}
+static inline nsecs_t ms2ns(nsecs_t v) {return milliseconds_to_nanoseconds(v);}
+static inline nsecs_t us2ns(nsecs_t v) {return microseconds_to_nanoseconds(v);}
+static inline nsecs_t ns2s(nsecs_t v)  {return nanoseconds_to_seconds(v);}
+static inline nsecs_t ns2ms(nsecs_t v) {return nanoseconds_to_milliseconds(v);}
+static inline nsecs_t ns2us(nsecs_t v) {return nanoseconds_to_microseconds(v);}
+
+static inline nsecs_t seconds(nsecs_t v)      { return s2ns(v); }
+static inline nsecs_t milliseconds(nsecs_t v) { return ms2ns(v); }
+static inline nsecs_t microseconds(nsecs_t v) { return us2ns(v); }
+
+enum {
+    SYSTEM_TIME_REALTIME = 0,  // system-wide realtime clock
+    SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point
+    SYSTEM_TIME_PROCESS = 2,   // high-resolution per-process clock
+    SYSTEM_TIME_THREAD = 3,    // high-resolution per-thread clock
+    SYSTEM_TIME_BOOTTIME = 4   // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time
+};
+
+// return the system-time according to the specified clock
+#ifdef __cplusplus
+nsecs_t systemTime(int clock = SYSTEM_TIME_MONOTONIC);
+#else
+nsecs_t systemTime(int clock);
+#endif // def __cplusplus
+
+/**
+ * Returns the number of milliseconds to wait between the reference time and the timeout time.
+ * If the timeout is in the past relative to the reference time, returns 0.
+ * If the timeout is more than INT_MAX milliseconds in the future relative to the reference time,
+ * such as when timeoutTime == LLONG_MAX, returns -1 to indicate an infinite timeout delay.
+ * Otherwise, returns the difference between the reference time and timeout time
+ * rounded up to the next millisecond.
+ */
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _LIBS_UTILS_TIMERS_H
diff --git a/include/utils/Tokenizer.h b/include/utils/Tokenizer.h
new file mode 100644
index 0000000..bb25f37
--- /dev/null
+++ b/include/utils/Tokenizer.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef _UTILS_TOKENIZER_H
+#define _UTILS_TOKENIZER_H
+
+#include <assert.h>
+#include <utils/Errors.h>
+#include <utils/FileMap.h>
+#include <utils/String8.h>
+
+namespace android {
+
+/**
+ * A simple tokenizer for loading and parsing ASCII text files line by line.
+ */
+class Tokenizer {
+    Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
+            bool ownBuffer, size_t length);
+
+public:
+    ~Tokenizer();
+
+    /**
+     * Opens a file and maps it into memory.
+     *
+     * Returns NO_ERROR and a tokenizer for the file, if successful.
+     * Otherwise returns an error and sets outTokenizer to NULL.
+     */
+    static status_t open(const String8& filename, Tokenizer** outTokenizer);
+
+    /**
+     * Prepares to tokenize the contents of a string.
+     *
+     * Returns NO_ERROR and a tokenizer for the string, if successful.
+     * Otherwise returns an error and sets outTokenizer to NULL.
+     */
+    static status_t fromContents(const String8& filename,
+            const char* contents, Tokenizer** outTokenizer);
+
+    /**
+     * Returns true if at the end of the file.
+     */
+    inline bool isEof() const { return mCurrent == getEnd(); }
+
+    /**
+     * Returns true if at the end of the line or end of the file.
+     */
+    inline bool isEol() const { return isEof() || *mCurrent == '\n'; }
+
+    /**
+     * Gets the name of the file.
+     */
+    inline String8 getFilename() const { return mFilename; }
+
+    /**
+     * Gets a 1-based line number index for the current position.
+     */
+    inline int32_t getLineNumber() const { return mLineNumber; }
+
+    /**
+     * Formats a location string consisting of the filename and current line number.
+     * Returns a string like "MyFile.txt:33".
+     */
+    String8 getLocation() const;
+
+    /**
+     * Gets the character at the current position.
+     * Returns null at end of file.
+     */
+    inline char peekChar() const { return isEof() ? '\0' : *mCurrent; }
+
+    /**
+     * Gets the remainder of the current line as a string, excluding the newline character.
+     */
+    String8 peekRemainderOfLine() const;
+
+    /**
+     * Gets the character at the current position and advances past it.
+     * Returns null at end of file.
+     */
+    inline char nextChar() { return isEof() ? '\0' : *(mCurrent++); }
+
+    /**
+     * Gets the next token on this line stopping at the specified delimiters
+     * or the end of the line whichever comes first and advances past it.
+     * Also stops at embedded nulls.
+     * Returns the token or an empty string if the current character is a delimiter
+     * or is at the end of the line.
+     */
+    String8 nextToken(const char* delimiters);
+
+    /**
+     * Advances to the next line.
+     * Does nothing if already at the end of the file.
+     */
+    void nextLine();
+
+    /**
+     * Skips over the specified delimiters in the line.
+     * Also skips embedded nulls.
+     */
+    void skipDelimiters(const char* delimiters);
+
+private:
+    Tokenizer(const Tokenizer& other); // not copyable
+
+    String8 mFilename;
+    FileMap* mFileMap;
+    char* mBuffer;
+    bool mOwnBuffer;
+    size_t mLength;
+
+    const char* mCurrent;
+    int32_t mLineNumber;
+
+    inline const char* getEnd() const { return mBuffer + mLength; }
+
+};
+
+} // namespace android
+
+#endif // _UTILS_TOKENIZER_H
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
new file mode 100644
index 0000000..6ee343d
--- /dev/null
+++ b/include/utils/Trace.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef ANDROID_TRACE_H
+#define ANDROID_TRACE_H
+
+#ifdef HAVE_ANDROID_OS
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/compiler.h>
+#include <utils/threads.h>
+#include <cutils/trace.h>
+
+// See <cutils/trace.h> for more ATRACE_* macros.
+
+// ATRACE_NAME traces the beginning and end of the current scope.  To trace
+// the correct start and end times this macro should be declared first in the
+// scope body.
+#define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name)
+// ATRACE_CALL is an ATRACE_NAME that uses the current function name.
+#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
+
+namespace android {
+
+class ScopedTrace {
+public:
+inline ScopedTrace(uint64_t tag, const char* name)
+    : mTag(tag) {
+    atrace_begin(mTag,name);
+}
+
+inline ~ScopedTrace() {
+    atrace_end(mTag);
+}
+
+private:
+    uint64_t mTag;
+};
+
+}; // namespace android
+
+#else // HAVE_ANDROID_OS
+
+#define ATRACE_NAME(...)
+#define ATRACE_CALL()
+
+#endif // HAVE_ANDROID_OS
+
+#endif // ANDROID_TRACE_H
diff --git a/include/utils/TypeHelpers.h b/include/utils/TypeHelpers.h
new file mode 100644
index 0000000..13c9081
--- /dev/null
+++ b/include/utils/TypeHelpers.h
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_TYPE_HELPERS_H
+#define ANDROID_TYPE_HELPERS_H
+
+#include <new>
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+/*
+ * Types traits
+ */
+
+template <typename T> struct trait_trivial_ctor { enum { value = false }; };
+template <typename T> struct trait_trivial_dtor { enum { value = false }; };
+template <typename T> struct trait_trivial_copy { enum { value = false }; };
+template <typename T> struct trait_trivial_move { enum { value = false }; };
+template <typename T> struct trait_pointer      { enum { value = false }; };    
+template <typename T> struct trait_pointer<T*>  { enum { value = true }; };
+
+template <typename TYPE>
+struct traits {
+    enum {
+        // whether this type is a pointer
+        is_pointer          = trait_pointer<TYPE>::value,
+        // whether this type's constructor is a no-op
+        has_trivial_ctor    = is_pointer || trait_trivial_ctor<TYPE>::value,
+        // whether this type's destructor is a no-op
+        has_trivial_dtor    = is_pointer || trait_trivial_dtor<TYPE>::value,
+        // whether this type type can be copy-constructed with memcpy
+        has_trivial_copy    = is_pointer || trait_trivial_copy<TYPE>::value,
+        // whether this type can be moved with memmove
+        has_trivial_move    = is_pointer || trait_trivial_move<TYPE>::value
+    };
+};
+
+template <typename T, typename U>
+struct aggregate_traits {
+    enum {
+        is_pointer          = false,
+        has_trivial_ctor    = 
+            traits<T>::has_trivial_ctor && traits<U>::has_trivial_ctor,
+        has_trivial_dtor    = 
+            traits<T>::has_trivial_dtor && traits<U>::has_trivial_dtor,
+        has_trivial_copy    = 
+            traits<T>::has_trivial_copy && traits<U>::has_trivial_copy,
+        has_trivial_move    = 
+            traits<T>::has_trivial_move && traits<U>::has_trivial_move
+    };
+};
+
+#define ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
+    template<> struct trait_trivial_ctor< T >   { enum { value = true }; };
+
+#define ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
+    template<> struct trait_trivial_dtor< T >   { enum { value = true }; };
+
+#define ANDROID_TRIVIAL_COPY_TRAIT( T ) \
+    template<> struct trait_trivial_copy< T >   { enum { value = true }; };
+
+#define ANDROID_TRIVIAL_MOVE_TRAIT( T ) \
+    template<> struct trait_trivial_move< T >   { enum { value = true }; };
+
+#define ANDROID_BASIC_TYPES_TRAITS( T ) \
+    ANDROID_TRIVIAL_CTOR_TRAIT( T ) \
+    ANDROID_TRIVIAL_DTOR_TRAIT( T ) \
+    ANDROID_TRIVIAL_COPY_TRAIT( T ) \
+    ANDROID_TRIVIAL_MOVE_TRAIT( T )
+
+// ---------------------------------------------------------------------------
+
+/*
+ * basic types traits
+ */
+
+ANDROID_BASIC_TYPES_TRAITS( void )
+ANDROID_BASIC_TYPES_TRAITS( bool )
+ANDROID_BASIC_TYPES_TRAITS( char )
+ANDROID_BASIC_TYPES_TRAITS( unsigned char )
+ANDROID_BASIC_TYPES_TRAITS( short )
+ANDROID_BASIC_TYPES_TRAITS( unsigned short )
+ANDROID_BASIC_TYPES_TRAITS( int )
+ANDROID_BASIC_TYPES_TRAITS( unsigned int )
+ANDROID_BASIC_TYPES_TRAITS( long )
+ANDROID_BASIC_TYPES_TRAITS( unsigned long )
+ANDROID_BASIC_TYPES_TRAITS( long long )
+ANDROID_BASIC_TYPES_TRAITS( unsigned long long )
+ANDROID_BASIC_TYPES_TRAITS( float )
+ANDROID_BASIC_TYPES_TRAITS( double )
+
+// ---------------------------------------------------------------------------
+
+
+/*
+ * compare and order types
+ */
+
+template<typename TYPE> inline
+int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
+    return (lhs < rhs) ? 1 : 0;
+}
+
+template<typename TYPE> inline
+int compare_type(const TYPE& lhs, const TYPE& rhs) {
+    return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
+}
+
+/*
+ * create, destroy, copy and move types...
+ */
+
+template<typename TYPE> inline
+void construct_type(TYPE* p, size_t n) {
+    if (!traits<TYPE>::has_trivial_ctor) {
+        while (n--) {
+            new(p++) TYPE;
+        }
+    }
+}
+
+template<typename TYPE> inline
+void destroy_type(TYPE* p, size_t n) {
+    if (!traits<TYPE>::has_trivial_dtor) {
+        while (n--) {
+            p->~TYPE();
+            p++;
+        }
+    }
+}
+
+template<typename TYPE> inline
+void copy_type(TYPE* d, const TYPE* s, size_t n) {
+    if (!traits<TYPE>::has_trivial_copy) {
+        while (n--) {
+            new(d) TYPE(*s);
+            d++, s++;
+        }
+    } else {
+        memcpy(d,s,n*sizeof(TYPE));
+    }
+}
+
+template<typename TYPE> inline
+void splat_type(TYPE* where, const TYPE* what, size_t n) {
+    if (!traits<TYPE>::has_trivial_copy) {
+        while (n--) {
+            new(where) TYPE(*what);
+            where++;
+        }
+    } else {
+        while (n--) {
+            *where++ = *what;
+        }
+    }
+}
+
+template<typename TYPE> inline
+void move_forward_type(TYPE* d, const TYPE* s, size_t n = 1) {
+    if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 
+            || traits<TYPE>::has_trivial_move) 
+    {
+        memmove(d,s,n*sizeof(TYPE));
+    } else {
+        d += n;
+        s += n;
+        while (n--) {
+            --d, --s;
+            if (!traits<TYPE>::has_trivial_copy) {
+                new(d) TYPE(*s);
+            } else {
+                *d = *s;   
+            }
+            if (!traits<TYPE>::has_trivial_dtor) {
+                s->~TYPE();
+            }
+        }
+    }
+}
+
+template<typename TYPE> inline
+void move_backward_type(TYPE* d, const TYPE* s, size_t n = 1) {
+    if ((traits<TYPE>::has_trivial_dtor && traits<TYPE>::has_trivial_copy) 
+            || traits<TYPE>::has_trivial_move) 
+    {
+        memmove(d,s,n*sizeof(TYPE));
+    } else {
+        while (n--) {
+            if (!traits<TYPE>::has_trivial_copy) {
+                new(d) TYPE(*s);
+            } else {
+                *d = *s;   
+            }
+            if (!traits<TYPE>::has_trivial_dtor) {
+                s->~TYPE();
+            }
+            d++, s++;
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+/*
+ * a key/value pair
+ */
+
+template <typename KEY, typename VALUE>
+struct key_value_pair_t {
+    typedef KEY key_t;
+    typedef VALUE value_t;
+
+    KEY     key;
+    VALUE   value;
+    key_value_pair_t() { }
+    key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
+    key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
+    key_value_pair_t(const KEY& k) : key(k) { }
+    inline bool operator < (const key_value_pair_t& o) const {
+        return strictly_order_type(key, o.key);
+    }
+    inline const KEY& getKey() const {
+        return key;
+    }
+    inline const VALUE& getValue() const {
+        return value;
+    }
+};
+
+template <typename K, typename V>
+struct trait_trivial_ctor< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_ctor }; };
+template <typename K, typename V>
+struct trait_trivial_dtor< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_dtor }; };
+template <typename K, typename V>
+struct trait_trivial_copy< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_copy }; };
+template <typename K, typename V>
+struct trait_trivial_move< key_value_pair_t<K, V> >
+{ enum { value = aggregate_traits<K,V>::has_trivial_move }; };
+
+// ---------------------------------------------------------------------------
+
+/*
+ * Hash codes.
+ */
+typedef uint32_t hash_t;
+
+template <typename TKey>
+hash_t hash_type(const TKey& key);
+
+/* Built-in hash code specializations.
+ * Assumes pointers are 32bit. */
+#define ANDROID_INT32_HASH(T) \
+        template <> inline hash_t hash_type(const T& value) { return hash_t(value); }
+#define ANDROID_INT64_HASH(T) \
+        template <> inline hash_t hash_type(const T& value) { \
+                return hash_t((value >> 32) ^ value); }
+#define ANDROID_REINTERPRET_HASH(T, R) \
+        template <> inline hash_t hash_type(const T& value) { \
+                return hash_type(*reinterpret_cast<const R*>(&value)); }
+
+ANDROID_INT32_HASH(bool)
+ANDROID_INT32_HASH(int8_t)
+ANDROID_INT32_HASH(uint8_t)
+ANDROID_INT32_HASH(int16_t)
+ANDROID_INT32_HASH(uint16_t)
+ANDROID_INT32_HASH(int32_t)
+ANDROID_INT32_HASH(uint32_t)
+ANDROID_INT64_HASH(int64_t)
+ANDROID_INT64_HASH(uint64_t)
+ANDROID_REINTERPRET_HASH(float, uint32_t)
+ANDROID_REINTERPRET_HASH(double, uint64_t)
+
+template <typename T> inline hash_t hash_type(T* const & value) {
+    return hash_type(uintptr_t(value));
+}
+
+}; // namespace android
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_TYPE_HELPERS_H
diff --git a/include/utils/Unicode.h b/include/utils/Unicode.h
new file mode 100644
index 0000000..c8c87c3
--- /dev/null
+++ b/include/utils/Unicode.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_UNICODE_H
+#define ANDROID_UNICODE_H
+
+#include <sys/types.h>
+#include <stdint.h>
+
+extern "C" {
+
+typedef uint32_t char32_t;
+typedef uint16_t char16_t;
+
+// Standard string functions on char16_t strings.
+int strcmp16(const char16_t *, const char16_t *);
+int strncmp16(const char16_t *s1, const char16_t *s2, size_t n);
+size_t strlen16(const char16_t *);
+size_t strnlen16(const char16_t *, size_t);
+char16_t *strcpy16(char16_t *, const char16_t *);
+char16_t *strncpy16(char16_t *, const char16_t *, size_t);
+
+// Version of comparison that supports embedded nulls.
+// This is different than strncmp() because we don't stop
+// at a nul character and consider the strings to be different
+// if the lengths are different (thus we need to supply the
+// lengths of both strings).  This can also be used when
+// your string is not nul-terminated as it will have the
+// equivalent result as strcmp16 (unlike strncmp16).
+int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2);
+
+// Version of strzcmp16 for comparing strings in different endianness.
+int strzcmp16_h_n(const char16_t *s1H, size_t n1, const char16_t *s2N, size_t n2);
+
+// Standard string functions on char32_t strings.
+size_t strlen32(const char32_t *);
+size_t strnlen32(const char32_t *, size_t);
+
+/**
+ * Measure the length of a UTF-32 string in UTF-8. If the string is invalid
+ * such as containing a surrogate character, -1 will be returned.
+ */
+ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len);
+
+/**
+ * Stores a UTF-8 string converted from "src" in "dst", if "dst_length" is not
+ * large enough to store the string, the part of the "src" string is stored
+ * into "dst" as much as possible. See the examples for more detail.
+ * Returns the size actually used for storing the string.
+ * dst" is not null-terminated when dst_len is fully used (like strncpy).
+ *
+ * Example 1
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" >= 7
+ * ->
+ * Returned value == 6
+ * "dst" becomes \xE3\x81\x82\xE3\x81\x84\0
+ * (note that "dst" is null-terminated)
+ *
+ * Example 2
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" == 5
+ * ->
+ * Returned value == 3
+ * "dst" becomes \xE3\x81\x82\0
+ * (note that "dst" is null-terminated, but \u3044 is not stored in "dst"
+ * since "dst" does not have enough size to store the character)
+ *
+ * Example 3
+ * "src" == \u3042\u3044 (\xE3\x81\x82\xE3\x81\x84)
+ * "src_len" == 2
+ * "dst_len" == 6
+ * ->
+ * Returned value == 6
+ * "dst" becomes \xE3\x81\x82\xE3\x81\x84
+ * (note that "dst" is NOT null-terminated, like strncpy)
+ */
+void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst);
+
+/**
+ * Returns the unicode value at "index".
+ * Returns -1 when the index is invalid (equals to or more than "src_len").
+ * If returned value is positive, it is able to be converted to char32_t, which
+ * is unsigned. Then, if "next_index" is not NULL, the next index to be used is
+ * stored in "next_index". "next_index" can be NULL.
+ */
+int32_t utf32_from_utf8_at(const char *src, size_t src_len, size_t index, size_t *next_index);
+
+
+/**
+ * Returns the UTF-8 length of UTF-16 string "src".
+ */
+ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len);
+
+/**
+ * Converts a UTF-16 string to UTF-8. The destination buffer must be large
+ * enough to fit the UTF-16 as measured by utf16_to_utf8_length with an added
+ * NULL terminator.
+ */
+void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst);
+
+/**
+ * Returns the length of "src" when "src" is valid UTF-8 string.
+ * Returns 0 if src is NULL or 0-length string. Returns -1 when the source
+ * is an invalid string.
+ *
+ * This function should be used to determine whether "src" is valid UTF-8
+ * characters with valid unicode codepoints. "src" must be null-terminated.
+ *
+ * If you are going to use other utf8_to_... functions defined in this header
+ * with string which may not be valid UTF-8 with valid codepoint (form 0 to
+ * 0x10FFFF), you should use this function before calling others, since the
+ * other functions do not check whether the string is valid UTF-8 or not.
+ *
+ * If you do not care whether "src" is valid UTF-8 or not, you should use
+ * strlen() as usual, which should be much faster.
+ */
+ssize_t utf8_length(const char *src);
+
+/**
+ * Measure the length of a UTF-32 string.
+ */
+size_t utf8_to_utf32_length(const char *src, size_t src_len);
+
+/**
+ * Stores a UTF-32 string converted from "src" in "dst". "dst" must be large
+ * enough to store the entire converted string as measured by
+ * utf8_to_utf32_length plus space for a NULL terminator.
+ */
+void utf8_to_utf32(const char* src, size_t src_len, char32_t* dst);
+
+/**
+ * Returns the UTF-16 length of UTF-8 string "src".
+ */
+ssize_t utf8_to_utf16_length(const uint8_t* src, size_t srcLen);
+
+/**
+ * Convert UTF-8 to UTF-16 including surrogate pairs.
+ * Returns a pointer to the end of the string (where a null terminator might go
+ * if you wanted to add one).
+ */
+char16_t* utf8_to_utf16_no_null_terminator(const uint8_t* src, size_t srcLen, char16_t* dst);
+
+/**
+ * Convert UTF-8 to UTF-16 including surrogate pairs. The destination buffer
+ * must be large enough to hold the result as measured by utf8_to_utf16_length
+ * plus an added NULL terminator.
+ */
+void utf8_to_utf16(const uint8_t* src, size_t srcLen, char16_t* dst);
+
+/**
+ * Like utf8_to_utf16_no_null_terminator, but you can supply a maximum length of the
+ * decoded string.  The decoded string will fill up to that length; if it is longer
+ * the returned pointer will be to the character after dstLen.
+ */
+char16_t* utf8_to_utf16_n(const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen);
+
+}
+
+#endif
diff --git a/include/utils/UniquePtr.h b/include/utils/UniquePtr.h
new file mode 100644
index 0000000..bc62fe6
--- /dev/null
+++ b/include/utils/UniquePtr.h
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+/* === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE ===
+ *
+ * THIS IS A COPY OF libcore/include/UniquePtr.h AND AS SUCH THAT IS THE
+ * CANONICAL SOURCE OF THIS FILE. PLEASE KEEP THEM IN SYNC.
+ *
+ * === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE === NOTE ===
+ */
+
+#ifndef UNIQUE_PTR_H_included
+#define UNIQUE_PTR_H_included
+
+#include <cstdlib> // For NULL.
+
+// Default deleter for pointer types.
+template <typename T>
+struct DefaultDelete {
+    enum { type_must_be_complete = sizeof(T) };
+    DefaultDelete() {}
+    void operator()(T* p) const {
+        delete p;
+    }
+};
+
+// Default deleter for array types.
+template <typename T>
+struct DefaultDelete<T[]> {
+    enum { type_must_be_complete = sizeof(T) };
+    void operator()(T* p) const {
+        delete[] p;
+    }
+};
+
+// A smart pointer that deletes the given pointer on destruction.
+// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
+// and boost::scoped_array).
+// Named to be in keeping with Android style but also to avoid
+// collision with any other implementation, until we can switch over
+// to unique_ptr.
+// Use thus:
+//   UniquePtr<C> c(new C);
+template <typename T, typename D = DefaultDelete<T> >
+class UniquePtr {
+public:
+    // Construct a new UniquePtr, taking ownership of the given raw pointer.
+    explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
+    }
+
+    ~UniquePtr() {
+        reset();
+    }
+
+    // Accessors.
+    T& operator*() const { return *mPtr; }
+    T* operator->() const { return mPtr; }
+    T* get() const { return mPtr; }
+
+    // Returns the raw pointer and hands over ownership to the caller.
+    // The pointer will not be deleted by UniquePtr.
+    T* release() __attribute__((warn_unused_result)) {
+        T* result = mPtr;
+        mPtr = NULL;
+        return result;
+    }
+
+    // Takes ownership of the given raw pointer.
+    // If this smart pointer previously owned a different raw pointer, that
+    // raw pointer will be freed.
+    void reset(T* ptr = NULL) {
+        if (ptr != mPtr) {
+            D()(mPtr);
+            mPtr = ptr;
+        }
+    }
+
+private:
+    // The raw pointer.
+    T* mPtr;
+
+    // Comparing unique pointers is probably a mistake, since they're unique.
+    template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
+    template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
+
+    // Disallow copy and assignment.
+    UniquePtr(const UniquePtr&);
+    void operator=(const UniquePtr&);
+};
+
+// Partial specialization for array types. Like std::unique_ptr, this removes
+// operator* and operator-> but adds operator[].
+template <typename T, typename D>
+class UniquePtr<T[], D> {
+public:
+    explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
+    }
+
+    ~UniquePtr() {
+        reset();
+    }
+
+    T& operator[](size_t i) const {
+        return mPtr[i];
+    }
+    T* get() const { return mPtr; }
+
+    T* release() __attribute__((warn_unused_result)) {
+        T* result = mPtr;
+        mPtr = NULL;
+        return result;
+    }
+
+    void reset(T* ptr = NULL) {
+        if (ptr != mPtr) {
+            D()(mPtr);
+            mPtr = ptr;
+        }
+    }
+
+private:
+    T* mPtr;
+
+    // Disallow copy and assignment.
+    UniquePtr(const UniquePtr&);
+    void operator=(const UniquePtr&);
+};
+
+#if UNIQUE_PTR_TESTS
+
+// Run these tests with:
+// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
+
+#include <stdio.h>
+
+static void assert(bool b) {
+    if (!b) {
+        fprintf(stderr, "FAIL\n");
+        abort();
+    }
+    fprintf(stderr, "OK\n");
+}
+static int cCount = 0;
+struct C {
+    C() { ++cCount; }
+    ~C() { --cCount; }
+};
+static bool freed = false;
+struct Freer {
+    void operator()(int* p) {
+        assert(*p == 123);
+        free(p);
+        freed = true;
+    }
+};
+
+int main(int argc, char* argv[]) {
+    //
+    // UniquePtr<T> tests...
+    //
+
+    // Can we free a single object?
+    {
+        UniquePtr<C> c(new C);
+        assert(cCount == 1);
+    }
+    assert(cCount == 0);
+    // Does release work?
+    C* rawC;
+    {
+        UniquePtr<C> c(new C);
+        assert(cCount == 1);
+        rawC = c.release();
+    }
+    assert(cCount == 1);
+    delete rawC;
+    // Does reset work?
+    {
+        UniquePtr<C> c(new C);
+        assert(cCount == 1);
+        c.reset(new C);
+        assert(cCount == 1);
+    }
+    assert(cCount == 0);
+
+    //
+    // UniquePtr<T[]> tests...
+    //
+
+    // Can we free an array?
+    {
+        UniquePtr<C[]> cs(new C[4]);
+        assert(cCount == 4);
+    }
+    assert(cCount == 0);
+    // Does release work?
+    {
+        UniquePtr<C[]> c(new C[4]);
+        assert(cCount == 4);
+        rawC = c.release();
+    }
+    assert(cCount == 4);
+    delete[] rawC;
+    // Does reset work?
+    {
+        UniquePtr<C[]> c(new C[4]);
+        assert(cCount == 4);
+        c.reset(new C[2]);
+        assert(cCount == 2);
+    }
+    assert(cCount == 0);
+
+    //
+    // Custom deleter tests...
+    //
+    assert(!freed);
+    {
+        UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
+        *i = 123;
+    }
+    assert(freed);
+    return 0;
+}
+#endif
+
+#endif  // UNIQUE_PTR_H_included
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
new file mode 100644
index 0000000..ed7b725
--- /dev/null
+++ b/include/utils/Vector.h
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_VECTOR_H
+#define ANDROID_VECTOR_H
+
+#include <new>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <cutils/log.h>
+
+#include <utils/VectorImpl.h>
+#include <utils/TypeHelpers.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <typename TYPE>
+class SortedVector;
+
+/*!
+ * The main templated vector class ensuring type safety
+ * while making use of VectorImpl.
+ * This is the class users want to use.
+ */
+
+template <class TYPE>
+class Vector : private VectorImpl
+{
+public:
+            typedef TYPE    value_type;
+    
+    /*! 
+     * Constructors and destructors
+     */
+    
+                            Vector();
+                            Vector(const Vector<TYPE>& rhs);
+    explicit                Vector(const SortedVector<TYPE>& rhs);
+    virtual                 ~Vector();
+
+    /*! copy operator */
+            const Vector<TYPE>&     operator = (const Vector<TYPE>& rhs) const;
+            Vector<TYPE>&           operator = (const Vector<TYPE>& rhs);    
+
+            const Vector<TYPE>&     operator = (const SortedVector<TYPE>& rhs) const;
+            Vector<TYPE>&           operator = (const SortedVector<TYPE>& rhs);
+
+            /*
+     * empty the vector
+     */
+
+    inline  void            clear()             { VectorImpl::clear(); }
+
+    /*! 
+     * vector stats
+     */
+
+    //! returns number of items in the vector
+    inline  size_t          size() const                { return VectorImpl::size(); }
+    //! returns whether or not the vector is empty
+    inline  bool            isEmpty() const             { return VectorImpl::isEmpty(); }
+    //! returns how many items can be stored without reallocating the backing store
+    inline  size_t          capacity() const            { return VectorImpl::capacity(); }
+    //! sets the capacity. capacity can never be reduced less than size()
+    inline  ssize_t         setCapacity(size_t size)    { return VectorImpl::setCapacity(size); }
+
+    /*!
+     * set the size of the vector. items are appended with the default
+     * constructor, or removed from the end as needed.
+     */
+    inline  ssize_t         resize(size_t size)         { return VectorImpl::resize(size); }
+
+    /*!
+     * C-style array access
+     */
+     
+    //! read-only C-style access 
+    inline  const TYPE*     array() const;
+    //! read-write C-style access
+            TYPE*           editArray();
+    
+    /*! 
+     * accessors
+     */
+
+    //! read-only access to an item at a given index
+    inline  const TYPE&     operator [] (size_t index) const;
+    //! alternate name for operator []
+    inline  const TYPE&     itemAt(size_t index) const;
+    //! stack-usage of the vector. returns the top of the stack (last element)
+            const TYPE&     top() const;
+
+    /*!
+     * modifying the array
+     */
+
+    //! copy-on write support, grants write access to an item
+            TYPE&           editItemAt(size_t index);
+    //! grants right access to the top of the stack (last element)
+            TYPE&           editTop();
+
+            /*! 
+             * append/insert another vector
+             */
+            
+    //! insert another vector at a given index
+            ssize_t         insertVectorAt(const Vector<TYPE>& vector, size_t index);
+
+    //! append another vector at the end of this one
+            ssize_t         appendVector(const Vector<TYPE>& vector);
+
+
+    //! insert an array at a given index
+            ssize_t         insertArrayAt(const TYPE* array, size_t index, size_t length);
+
+    //! append an array at the end of this vector
+            ssize_t         appendArray(const TYPE* array, size_t length);
+
+            /*! 
+             * add/insert/replace items
+             */
+             
+    //! insert one or several items initialized with their default constructor
+    inline  ssize_t         insertAt(size_t index, size_t numItems = 1);
+    //! insert one or several items initialized from a prototype item
+            ssize_t         insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
+    //! pop the top of the stack (removes the last element). No-op if the stack's empty
+    inline  void            pop();
+    //! pushes an item initialized with its default constructor
+    inline  void            push();
+    //! pushes an item on the top of the stack
+            void            push(const TYPE& item);
+    //! same as push() but returns the index the item was added at (or an error)
+    inline  ssize_t         add();
+    //! same as push() but returns the index the item was added at (or an error)
+            ssize_t         add(const TYPE& item);            
+    //! replace an item with a new one initialized with its default constructor
+    inline  ssize_t         replaceAt(size_t index);
+    //! replace an item with a new one
+            ssize_t         replaceAt(const TYPE& item, size_t index);
+
+    /*!
+     * remove items
+     */
+
+    //! remove several items
+    inline  ssize_t         removeItemsAt(size_t index, size_t count = 1);
+    //! remove one item
+    inline  ssize_t         removeAt(size_t index)  { return removeItemsAt(index); }
+
+    /*!
+     * sort (stable) the array
+     */
+     
+     typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs);
+     typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state);
+     
+     inline status_t        sort(compar_t cmp);
+     inline status_t        sort(compar_r_t cmp, void* state);
+
+     // for debugging only
+     inline size_t getItemSize() const { return itemSize(); }
+
+
+     /*
+      * these inlines add some level of compatibility with STL. eventually
+      * we should probably turn things around.
+      */
+     typedef TYPE* iterator;
+     typedef TYPE const* const_iterator;
+
+     inline iterator begin() { return editArray(); }
+     inline iterator end()   { return editArray() + size(); }
+     inline const_iterator begin() const { return array(); }
+     inline const_iterator end() const   { return array() + size(); }
+     inline void reserve(size_t n) { setCapacity(n); }
+     inline bool empty() const{ return isEmpty(); }
+     inline void push_back(const TYPE& item)  { insertAt(item, size(), 1); }
+     inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
+     inline iterator erase(iterator pos) {
+         ssize_t index = removeItemsAt(pos-array());
+         return begin() + index;
+     }
+
+protected:
+    virtual void    do_construct(void* storage, size_t num) const;
+    virtual void    do_destroy(void* storage, size_t num) const;
+    virtual void    do_copy(void* dest, const void* from, size_t num) const;
+    virtual void    do_splat(void* dest, const void* item, size_t num) const;
+    virtual void    do_move_forward(void* dest, const void* from, size_t num) const;
+    virtual void    do_move_backward(void* dest, const void* from, size_t num) const;
+};
+
+// Vector<T> can be trivially moved using memcpy() because moving does not
+// require any change to the underlying SharedBuffer contents or reference count.
+template<typename T> struct trait_trivial_move<Vector<T> > { enum { value = true }; };
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts from here...
+// ---------------------------------------------------------------------------
+
+template<class TYPE> inline
+Vector<TYPE>::Vector()
+    : VectorImpl(sizeof(TYPE),
+                ((traits<TYPE>::has_trivial_ctor   ? HAS_TRIVIAL_CTOR   : 0)
+                |(traits<TYPE>::has_trivial_dtor   ? HAS_TRIVIAL_DTOR   : 0)
+                |(traits<TYPE>::has_trivial_copy   ? HAS_TRIVIAL_COPY   : 0))
+                )
+{
+}
+
+template<class TYPE> inline
+Vector<TYPE>::Vector(const Vector<TYPE>& rhs)
+    : VectorImpl(rhs) {
+}
+
+template<class TYPE> inline
+Vector<TYPE>::Vector(const SortedVector<TYPE>& rhs)
+    : VectorImpl(static_cast<const VectorImpl&>(rhs)) {
+}
+
+template<class TYPE> inline
+Vector<TYPE>::~Vector() {
+    finish_vector();
+}
+
+template<class TYPE> inline
+Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) {
+    VectorImpl::operator = (rhs);
+    return *this; 
+}
+
+template<class TYPE> inline
+const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
+    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+    return *this;
+}
+
+template<class TYPE> inline
+Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
+    return *this;
+}
+
+template<class TYPE> inline
+const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
+    VectorImpl::operator = (rhs);
+    return *this; 
+}
+
+template<class TYPE> inline
+const TYPE* Vector<TYPE>::array() const {
+    return static_cast<const TYPE *>(arrayImpl());
+}
+
+template<class TYPE> inline
+TYPE* Vector<TYPE>::editArray() {
+    return static_cast<TYPE *>(editArrayImpl());
+}
+
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::operator[](size_t index) const {
+    LOG_FATAL_IF(index>=size(),
+            "%s: index=%u out of range (%u)", __PRETTY_FUNCTION__,
+            int(index), int(size()));
+    return *(array() + index);
+}
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::itemAt(size_t index) const {
+    return operator[](index);
+}
+
+template<class TYPE> inline
+const TYPE& Vector<TYPE>::top() const {
+    return *(array() + size() - 1);
+}
+
+template<class TYPE> inline
+TYPE& Vector<TYPE>::editItemAt(size_t index) {
+    return *( static_cast<TYPE *>(editItemLocation(index)) );
+}
+
+template<class TYPE> inline
+TYPE& Vector<TYPE>::editTop() {
+    return *( static_cast<TYPE *>(editItemLocation(size()-1)) );
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertVectorAt(const Vector<TYPE>& vector, size_t index) {
+    return VectorImpl::insertVectorAt(reinterpret_cast<const VectorImpl&>(vector), index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
+    return VectorImpl::appendVector(reinterpret_cast<const VectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t length) {
+    return VectorImpl::insertArrayAt(array, index, length);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t length) {
+    return VectorImpl::appendArray(array, length);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertAt(const TYPE& item, size_t index, size_t numItems) {
+    return VectorImpl::insertAt(&item, index, numItems);
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::push(const TYPE& item) {
+    return VectorImpl::push(&item);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::add(const TYPE& item) {
+    return VectorImpl::add(&item);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::replaceAt(const TYPE& item, size_t index) {
+    return VectorImpl::replaceAt(&item, index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::insertAt(size_t index, size_t numItems) {
+    return VectorImpl::insertAt(index, numItems);
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::pop() {
+    VectorImpl::pop();
+}
+
+template<class TYPE> inline
+void Vector<TYPE>::push() {
+    VectorImpl::push();
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::add() {
+    return VectorImpl::add();
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::replaceAt(size_t index) {
+    return VectorImpl::replaceAt(index);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::removeItemsAt(size_t index, size_t count) {
+    return VectorImpl::removeItemsAt(index, count);
+}
+
+template<class TYPE> inline
+status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
+    return VectorImpl::sort((VectorImpl::compar_t)cmp);
+}
+
+template<class TYPE> inline
+status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
+    return VectorImpl::sort((VectorImpl::compar_r_t)cmp, state);
+}
+
+// ---------------------------------------------------------------------------
+
+template<class TYPE>
+void Vector<TYPE>::do_construct(void* storage, size_t num) const {
+    construct_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
+    destroy_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+    copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+    splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+    move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+    move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_H
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
new file mode 100644
index 0000000..21ad71c
--- /dev/null
+++ b/include/utils/VectorImpl.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef ANDROID_VECTOR_IMPL_H
+#define ANDROID_VECTOR_IMPL_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts in here...
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+/*!
+ * Implementation of the guts of the vector<> class
+ * this ensures backward binary compatibility and
+ * reduces code size.
+ * For performance reasons, we expose mStorage and mCount
+ * so these fields are set in stone.
+ *
+ */
+
+class VectorImpl
+{
+public:
+    enum { // flags passed to the ctor
+        HAS_TRIVIAL_CTOR    = 0x00000001,
+        HAS_TRIVIAL_DTOR    = 0x00000002,
+        HAS_TRIVIAL_COPY    = 0x00000004,
+    };
+
+                            VectorImpl(size_t itemSize, uint32_t flags);
+                            VectorImpl(const VectorImpl& rhs);
+    virtual                 ~VectorImpl();
+
+    /*! must be called from subclasses destructor */
+            void            finish_vector();
+
+            VectorImpl&     operator = (const VectorImpl& rhs);    
+            
+    /*! C-style array access */
+    inline  const void*     arrayImpl() const       { return mStorage; }
+            void*           editArrayImpl();
+            
+    /*! vector stats */
+    inline  size_t          size() const        { return mCount; }
+    inline  bool            isEmpty() const     { return mCount == 0; }
+            size_t          capacity() const;
+            ssize_t         setCapacity(size_t size);
+            ssize_t         resize(size_t size);
+
+            /*! append/insert another vector or array */
+            ssize_t         insertVectorAt(const VectorImpl& vector, size_t index);
+            ssize_t         appendVector(const VectorImpl& vector);
+            ssize_t         insertArrayAt(const void* array, size_t index, size_t length);
+            ssize_t         appendArray(const void* array, size_t length);
+            
+            /*! add/insert/replace items */
+            ssize_t         insertAt(size_t where, size_t numItems = 1);
+            ssize_t         insertAt(const void* item, size_t where, size_t numItems = 1);
+            void            pop();
+            void            push();
+            void            push(const void* item);
+            ssize_t         add();
+            ssize_t         add(const void* item);
+            ssize_t         replaceAt(size_t index);
+            ssize_t         replaceAt(const void* item, size_t index);
+
+            /*! remove items */
+            ssize_t         removeItemsAt(size_t index, size_t count = 1);
+            void            clear();
+
+            const void*     itemLocation(size_t index) const;
+            void*           editItemLocation(size_t index);
+
+            typedef int (*compar_t)(const void* lhs, const void* rhs);
+            typedef int (*compar_r_t)(const void* lhs, const void* rhs, void* state);
+            status_t        sort(compar_t cmp);
+            status_t        sort(compar_r_t cmp, void* state);
+
+protected:
+            size_t          itemSize() const;
+            void            release_storage();
+
+    virtual void            do_construct(void* storage, size_t num) const = 0;
+    virtual void            do_destroy(void* storage, size_t num) const = 0;
+    virtual void            do_copy(void* dest, const void* from, size_t num) const = 0;
+    virtual void            do_splat(void* dest, const void* item, size_t num) const = 0;
+    virtual void            do_move_forward(void* dest, const void* from, size_t num) const = 0;
+    virtual void            do_move_backward(void* dest, const void* from, size_t num) const = 0;
+    
+private:
+        void* _grow(size_t where, size_t amount);
+        void  _shrink(size_t where, size_t amount);
+
+        inline void _do_construct(void* storage, size_t num) const;
+        inline void _do_destroy(void* storage, size_t num) const;
+        inline void _do_copy(void* dest, const void* from, size_t num) const;
+        inline void _do_splat(void* dest, const void* item, size_t num) const;
+        inline void _do_move_forward(void* dest, const void* from, size_t num) const;
+        inline void _do_move_backward(void* dest, const void* from, size_t num) const;
+
+            // These 2 fields are exposed in the inlines below,
+            // so they're set in stone.
+            void *      mStorage;   // base address of the vector
+            size_t      mCount;     // number of items
+
+    const   uint32_t    mFlags;
+    const   size_t      mItemSize;
+};
+
+
+
+class SortedVectorImpl : public VectorImpl
+{
+public:
+                            SortedVectorImpl(size_t itemSize, uint32_t flags);
+                            SortedVectorImpl(const VectorImpl& rhs);
+    virtual                 ~SortedVectorImpl();
+    
+    SortedVectorImpl&     operator = (const SortedVectorImpl& rhs);    
+
+    //! finds the index of an item
+            ssize_t         indexOf(const void* item) const;
+
+    //! finds where this item should be inserted
+            size_t          orderOf(const void* item) const;
+
+    //! add an item in the right place (or replaces it if there is one)
+            ssize_t         add(const void* item);
+
+    //! merges a vector into this one
+            ssize_t         merge(const VectorImpl& vector);
+            ssize_t         merge(const SortedVectorImpl& vector);
+             
+    //! removes an item
+            ssize_t         remove(const void* item);
+        
+protected:
+    virtual int             do_compare(const void* lhs, const void* rhs) const = 0;
+
+private:
+            ssize_t         _indexOrderOf(const void* item, size_t* order = 0) const;
+
+            // these are made private, because they can't be used on a SortedVector
+            // (they don't have an implementation either)
+            ssize_t         add();
+            void            pop();
+            void            push();
+            void            push(const void* item);
+            ssize_t         insertVectorAt(const VectorImpl& vector, size_t index);
+            ssize_t         appendVector(const VectorImpl& vector);
+            ssize_t         insertArrayAt(const void* array, size_t index, size_t length);
+            ssize_t         appendArray(const void* array, size_t length);
+            ssize_t         insertAt(size_t where, size_t numItems = 1);
+            ssize_t         insertAt(const void* item, size_t where, size_t numItems = 1);
+            ssize_t         replaceAt(size_t index);
+            ssize_t         replaceAt(const void* item, size_t index);
+};
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_VECTOR_IMPL_H
diff --git a/include/utils/ashmem.h b/include/utils/ashmem.h
new file mode 100644
index 0000000..0854775
--- /dev/null
+++ b/include/utils/ashmem.h
@@ -0,0 +1,41 @@
+/* utils/ashmem.h
+ **
+ ** Copyright 2008 The Android Open Source Project
+ **
+ ** This file is dual licensed.  It may be redistributed and/or modified
+ ** under the terms of the Apache 2.0 License OR version 2 of the GNU
+ ** General Public License.
+ */
+
+#ifndef _UTILS_ASHMEM_H
+#define _UTILS_ASHMEM_H
+
+#include <linux/limits.h>
+#include <linux/ioctl.h>
+
+#define ASHMEM_NAME_LEN		256
+
+#define ASHMEM_NAME_DEF		"dev/ashmem"
+
+/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
+#define ASHMEM_NOT_REAPED	0
+#define ASHMEM_WAS_REAPED	1
+
+/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
+#define ASHMEM_NOW_UNPINNED	0
+#define ASHMEM_NOW_PINNED	1
+
+#define __ASHMEMIOC		0x77
+
+#define ASHMEM_SET_NAME		_IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
+#define ASHMEM_GET_NAME		_IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
+#define ASHMEM_SET_SIZE		_IOW(__ASHMEMIOC, 3, size_t)
+#define ASHMEM_GET_SIZE		_IO(__ASHMEMIOC, 4)
+#define ASHMEM_SET_PROT_MASK	_IOW(__ASHMEMIOC, 5, unsigned long)
+#define ASHMEM_GET_PROT_MASK	_IO(__ASHMEMIOC, 6)
+#define ASHMEM_PIN		_IO(__ASHMEMIOC, 7)
+#define ASHMEM_UNPIN		_IO(__ASHMEMIOC, 8)
+#define ASHMEM_ISPINNED		_IO(__ASHMEMIOC, 9)
+#define ASHMEM_PURGE_ALL_CACHES	_IO(__ASHMEMIOC, 10)
+
+#endif	/* _UTILS_ASHMEM_H */
diff --git a/include/utils/misc.h b/include/utils/misc.h
new file mode 100644
index 0000000..6cccec3
--- /dev/null
+++ b/include/utils/misc.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Handy utility functions and portability code.
+//
+#ifndef _LIBS_UTILS_MISC_H
+#define _LIBS_UTILS_MISC_H
+
+#include <utils/Endian.h>
+
+/* get #of elements in a static array */
+#ifndef NELEM
+# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
+#endif
+
+namespace android {
+
+typedef void (*sysprop_change_callback)(void);
+void add_sysprop_change_callback(sysprop_change_callback cb, int priority);
+void report_sysprop_change();
+
+}; // namespace android
+
+#endif // _LIBS_UTILS_MISC_H
diff --git a/include/cutils/zygote.h b/include/utils/threads.h
similarity index 61%
copy from include/cutils/zygote.h
copy to include/utils/threads.h
index a7480d3..9de3382 100644
--- a/include/cutils/zygote.h
+++ b/include/utils/threads.h
@@ -14,18 +14,25 @@
  * limitations under the License.
  */
 
-#ifndef __CUTILS_ZYGOTE_H
-#define __CUTILS_ZYGOTE_H
+#ifndef _LIBS_UTILS_THREADS_H
+#define _LIBS_UTILS_THREADS_H
+
+/*
+ * Please, DO NOT USE!
+ *
+ * This file is here only for legacy reasons. Instead, include directly
+ * the headers you need below.
+ *
+ */
+
+#include <utils/AndroidThreads.h>
 
 #ifdef __cplusplus
-extern "C" {
+#include <utils/Condition.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/RWLock.h>
+#include <utils/Thread.h>
 #endif
 
-int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
-int zygote_run(int argc, const char **argv);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CUTILS_ZYGOTE_H */
+#endif // _LIBS_UTILS_THREADS_H
diff --git a/include/ziparchive/zip_archive.h b/include/ziparchive/zip_archive.h
new file mode 100644
index 0000000..1877494
--- /dev/null
+++ b/include/ziparchive/zip_archive.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+/*
+ * Read-only access to Zip archives, with minimal heap allocation.
+ */
+#ifndef LIBZIPARCHIVE_ZIPARCHIVE_H_
+#define LIBZIPARCHIVE_ZIPARCHIVE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Compat.h>
+
+__BEGIN_DECLS
+
+/* Zip compression methods we support */
+enum {
+  kCompressStored     = 0,        // no compression
+  kCompressDeflated   = 8,        // standard deflate
+};
+
+struct ZipEntryName {
+  const char* name;
+  uint16_t name_length;
+};
+
+/*
+ * Represents information about a zip entry in a zip file.
+ */
+struct ZipEntry {
+  // Compression method: One of kCompressStored or
+  // kCompressDeflated.
+  uint16_t method;
+
+  // Modification time. The zipfile format specifies
+  // that the first two little endian bytes contain the time
+  // and the last two little endian bytes contain the date.
+  uint32_t mod_time;
+
+  // 1 if this entry contains a data descriptor segment, 0
+  // otherwise.
+  uint8_t has_data_descriptor;
+
+  // Crc32 value of this ZipEntry. This information might
+  // either be stored in the local file header or in a special
+  // Data descriptor footer at the end of the file entry.
+  uint32_t crc32;
+
+  // Compressed length of this ZipEntry. Might be present
+  // either in the local file header or in the data descriptor
+  // footer.
+  uint32_t compressed_length;
+
+  // Uncompressed length of this ZipEntry. Might be present
+  // either in the local file header or in the data descriptor
+  // footer.
+  uint32_t uncompressed_length;
+
+  // The offset to the start of data for this ZipEntry.
+  off64_t offset;
+};
+
+typedef void* ZipArchiveHandle;
+
+/*
+ * Open a Zip archive, and sets handle to the value of the opaque
+ * handle for the file. This handle must be released by calling
+ * CloseArchive with this handle.
+ *
+ * Returns 0 on success, and negative values on failure.
+ */
+int32_t OpenArchive(const char* fileName, ZipArchiveHandle* handle);
+
+/*
+ * Like OpenArchive, but takes a file descriptor open for reading
+ * at the start of the file.  The descriptor must be mappable (this does
+ * not allow access to a stream).
+ *
+ * Sets handle to the value of the opaque handle for this file descriptor.
+ * This handle must be released by calling CloseArchive with this handle.
+ *
+ * This function maps and scans the central directory and builds a table
+ * of entries for future lookups.
+ *
+ * "debugFileName" will appear in error messages, but is not otherwise used.
+ *
+ * Returns 0 on success, and negative values on failure.
+ */
+int32_t OpenArchiveFd(const int fd, const char* debugFileName,
+                      ZipArchiveHandle *handle);
+
+/*
+ * Close archive, releasing resources associated with it. This will
+ * unmap the central directory of the zipfile and free all internal
+ * data structures associated with the file. It is an error to use
+ * this handle for any further operations without an intervening
+ * call to one of the OpenArchive variants.
+ */
+void CloseArchive(ZipArchiveHandle handle);
+
+/*
+ * Find an entry in the Zip archive, by name. |entryName| must be a null
+ * terminated string, and |data| must point to a writeable memory location.
+ *
+ * Returns 0 if an entry is found, and populates |data| with information
+ * about this entry. Returns negative values otherwise.
+ *
+ * It's important to note that |data->crc32|, |data->compLen| and
+ * |data->uncompLen| might be set to values from the central directory
+ * if this file entry contains a data descriptor footer. To verify crc32s
+ * and length, a call to VerifyCrcAndLengths must be made after entry data
+ * has been processed.
+ */
+int32_t FindEntry(const ZipArchiveHandle handle, const char* entryName,
+                  ZipEntry* data);
+
+/*
+ * Start iterating over all entries of a zip file. The order of iteration
+ * is not guaranteed to be the same as the order of elements
+ * in the central directory but is stable for a given zip file. |cookie|
+ * must point to a writeable memory location, and will be set to the value
+ * of an opaque cookie which can be used to make one or more calls to
+ * Next.
+ *
+ * This method also accepts an optional prefix to restrict iteration to
+ * entry names that start with |prefix|.
+ *
+ * Returns 0 on success and negative values on failure.
+ */
+int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr,
+                       const char* prefix);
+
+/*
+ * Advance to the next element in the zipfile in iteration order.
+ *
+ * Returns 0 on success, -1 if there are no more elements in this
+ * archive and lower negative values on failure.
+ */
+int32_t Next(void* cookie, ZipEntry* data, ZipEntryName *name);
+
+/*
+ * Uncompress and write an entry to an open file identified by |fd|.
+ * |entry->uncompressed_length| bytes will be written to the file at
+ * its current offset, and the file will be truncated at the end of
+ * the uncompressed data.
+ *
+ * Returns 0 on success and negative values on failure.
+ */
+int32_t ExtractEntryToFile(ZipArchiveHandle handle, ZipEntry* entry, int fd);
+
+/**
+ * Uncompress a given zip entry to the memory region at |begin| and of
+ * size |size|. This size is expected to be the same as the *declared*
+ * uncompressed length of the zip entry. It is an error if the *actual*
+ * number of uncompressed bytes differs from this number.
+ *
+ * Returns 0 on success and negative values on failure.
+ */
+int32_t ExtractToMemory(ZipArchiveHandle handle, ZipEntry* entry,
+                        uint8_t* begin, uint32_t size);
+
+int GetFileDescriptor(const ZipArchiveHandle handle);
+
+const char* ErrorCodeString(int32_t error_code);
+
+__END_DECLS
+
+#endif  // LIBZIPARCHIVE_ZIPARCHIVE_H_
diff --git a/init/Android.mk b/init/Android.mk
index 8b436db..1f43ba6 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -38,7 +38,9 @@
 	libcutils \
 	liblog \
 	libc \
-	libselinux
+	libselinux \
+	libmincrypt \
+	libext4_utils_static
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/init/builtins.c b/init/builtins.c
index 33fc6c6..e2932d5 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -32,6 +32,7 @@
 #include <sys/wait.h>
 #include <linux/loop.h>
 #include <cutils/partition_utils.h>
+#include <cutils/android_reboot.h>
 #include <sys/system_properties.h>
 #include <fs_mgr.h>
 
@@ -56,7 +57,7 @@
 {
     int fd, ret, len;
 
-    fd = open(path, O_WRONLY|O_CREAT, 0622);
+    fd = open(path, O_WRONLY|O_CREAT|O_NOFOLLOW, 0600);
 
     if (fd < 0)
         return -errno;
@@ -515,6 +516,18 @@
     return ret;
 }
 
+int do_swapon_all(int nargs, char **args)
+{
+    struct fstab *fstab;
+    int ret;
+
+    fstab = fs_mgr_read_fstab(args[1]);
+    ret = fs_mgr_swapon_all(fstab);
+    fs_mgr_free_fstab(fstab);
+
+    return ret;
+}
+
 int do_setcon(int nargs, char **args) {
     if (is_selinux_enabled() <= 0)
         return 0;
@@ -598,6 +611,43 @@
     return 0;
 }
 
+int do_powerctl(int nargs, char **args)
+{
+    char command[PROP_VALUE_MAX];
+    int res;
+    int len = 0;
+    int cmd = 0;
+    char *reboot_target;
+
+    res = expand_props(command, args[1], sizeof(command));
+    if (res) {
+        ERROR("powerctl: cannot expand '%s'\n", args[1]);
+        return -EINVAL;
+    }
+
+    if (strncmp(command, "shutdown", 8) == 0) {
+        cmd = ANDROID_RB_POWEROFF;
+        len = 8;
+    } else if (strncmp(command, "reboot", 6) == 0) {
+        cmd = ANDROID_RB_RESTART2;
+        len = 6;
+    } else {
+        ERROR("powerctl: unrecognized command '%s'\n", command);
+        return -EINVAL;
+    }
+
+    if (command[len] == ',') {
+        reboot_target = &command[len + 1];
+    } else if (command[len] == '\0') {
+        reboot_target = "";
+    } else {
+        ERROR("powerctl: unrecognized reboot target '%s'\n", &command[len]);
+        return -EINVAL;
+    }
+
+    return android_reboot(cmd, 0, reboot_target);
+}
+
 int do_trigger(int nargs, char **args)
 {
     action_for_each_trigger(args[1], action_add_queue_tail);
diff --git a/init/devices.c b/init/devices.c
index af88c5f..f7df453 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -44,6 +44,7 @@
 #include <cutils/uevent.h>
 
 #include "devices.h"
+#include "ueventd_parser.h"
 #include "util.h"
 #include "log.h"
 
@@ -530,8 +531,11 @@
     name++;
 
     /* too-long names would overrun our buffer */
-    if(strlen(name) > len)
+    if(strlen(name) > len) {
+        ERROR("DEVPATH=%s exceeds %u-character limit on filename; ignoring event\n",
+                name, len);
         return NULL;
+    }
 
     return name;
 }
@@ -557,37 +561,76 @@
             uevent->major, uevent->minor, links);
 }
 
+#define DEVPATH_LEN 96
+
+static bool assemble_devpath(char *devpath, const char *dirname,
+        const char *devname)
+{
+    int s = snprintf(devpath, DEVPATH_LEN, "%s/%s", dirname, devname);
+    if (s < 0) {
+        ERROR("failed to assemble device path (%s); ignoring event\n",
+                strerror(errno));
+        return false;
+    } else if (s >= DEVPATH_LEN) {
+        ERROR("%s/%s exceeds %u-character limit on path; ignoring event\n",
+                dirname, devname, DEVPATH_LEN);
+        return false;
+    }
+    return true;
+}
+
+static void mkdir_recursive_for_devpath(const char *devpath)
+{
+    char dir[DEVPATH_LEN];
+    char *slash;
+
+    strcpy(dir, devpath);
+    slash = strrchr(dir, '/');
+    *slash = '\0';
+    mkdir_recursive(dir, 0755);
+}
+
 static void handle_generic_device_event(struct uevent *uevent)
 {
     char *base;
     const char *name;
-    char devpath[96] = {0};
+    char devpath[DEVPATH_LEN] = {0};
     char **links = NULL;
 
     name = parse_device_name(uevent, 64);
     if (!name)
         return;
 
-    if (!strncmp(uevent->subsystem, "usb", 3)) {
+    struct ueventd_subsystem *subsystem =
+            ueventd_subsystem_find_by_name(uevent->subsystem);
+
+    if (subsystem) {
+        const char *devname;
+
+        switch (subsystem->devname_src) {
+        case DEVNAME_UEVENT_DEVNAME:
+            devname = uevent->device_name;
+            break;
+
+        case DEVNAME_UEVENT_DEVPATH:
+            devname = name;
+            break;
+
+        default:
+            ERROR("%s subsystem's devpath option is not set; ignoring event\n",
+                    uevent->subsystem);
+            return;
+        }
+
+        if (!assemble_devpath(devpath, subsystem->dirname, devname))
+            return;
+        mkdir_recursive_for_devpath(devpath);
+    } else if (!strncmp(uevent->subsystem, "usb", 3)) {
          if (!strcmp(uevent->subsystem, "usb")) {
             if (uevent->device_name) {
-                /*
-                 * create device node provided by kernel if present
-                 * see drivers/base/core.c
-                 */
-                char *p = devpath;
-                snprintf(devpath, sizeof(devpath), "/dev/%s", uevent->device_name);
-                /* skip leading /dev/ */
-                p += 5;
-                /* build directories */
-                while (*p) {
-                    if (*p == '/') {
-                        *p = 0;
-                        make_dir(devpath, 0755);
-                        *p = '/';
-                    }
-                    p++;
-                }
+                if (!assemble_devpath(devpath, "/dev", uevent->device_name))
+                    return;
+                mkdir_recursive_for_devpath(devpath);
              }
              else {
                  /* This imitates the file system that would be created
diff --git a/init/init.c b/init/init.c
index 525b69f..365726c 100644
--- a/init/init.c
+++ b/init/init.c
@@ -42,6 +42,7 @@
 #include <cutils/android_reboot.h>
 #include <cutils/sockets.h>
 #include <cutils/iosched_policy.h>
+#include <cutils/fs.h>
 #include <private/android_filesystem_config.h>
 #include <termios.h>
 
@@ -220,6 +221,9 @@
             }
 
             rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
+            if (rc == 0 && !strcmp(scon, mycon)) {
+                ERROR("Warning!  Service %s needs a SELinux domain defined; please fix!\n", svc->name);
+            }
             freecon(mycon);
             freecon(fcon);
             if (rc < 0) {
@@ -556,6 +560,84 @@
     return ret;
 }
 
+/*
+ * Writes 512 bytes of output from Hardware RNG (/dev/hw_random, backed
+ * by Linux kernel's hw_random framework) into Linux RNG's via /dev/urandom.
+ * Does nothing if Hardware RNG is not present.
+ *
+ * Since we don't yet trust the quality of Hardware RNG, these bytes are not
+ * mixed into the primary pool of Linux RNG and the entropy estimate is left
+ * unmodified.
+ *
+ * If the HW RNG device /dev/hw_random is present, we require that at least
+ * 512 bytes read from it are written into Linux RNG. QA is expected to catch
+ * devices/configurations where these I/O operations are blocking for a long
+ * time. We do not reboot or halt on failures, as this is a best-effort
+ * attempt.
+ */
+static int mix_hwrng_into_linux_rng_action(int nargs, char **args)
+{
+    int result = -1;
+    int hwrandom_fd = -1;
+    int urandom_fd = -1;
+    char buf[512];
+    ssize_t chunk_size;
+    size_t total_bytes_written = 0;
+
+    hwrandom_fd = TEMP_FAILURE_RETRY(
+            open("/dev/hw_random", O_RDONLY | O_NOFOLLOW));
+    if (hwrandom_fd == -1) {
+        if (errno == ENOENT) {
+          ERROR("/dev/hw_random not found\n");
+          /* It's not an error to not have a Hardware RNG. */
+          result = 0;
+        } else {
+          ERROR("Failed to open /dev/hw_random: %s\n", strerror(errno));
+        }
+        goto ret;
+    }
+
+    urandom_fd = TEMP_FAILURE_RETRY(
+            open("/dev/urandom", O_WRONLY | O_NOFOLLOW));
+    if (urandom_fd == -1) {
+        ERROR("Failed to open /dev/urandom: %s\n", strerror(errno));
+        goto ret;
+    }
+
+    while (total_bytes_written < sizeof(buf)) {
+        chunk_size = TEMP_FAILURE_RETRY(
+                read(hwrandom_fd, buf, sizeof(buf) - total_bytes_written));
+        if (chunk_size == -1) {
+            ERROR("Failed to read from /dev/hw_random: %s\n", strerror(errno));
+            goto ret;
+        } else if (chunk_size == 0) {
+            ERROR("Failed to read from /dev/hw_random: EOF\n");
+            goto ret;
+        }
+
+        chunk_size = TEMP_FAILURE_RETRY(write(urandom_fd, buf, chunk_size));
+        if (chunk_size == -1) {
+            ERROR("Failed to write to /dev/urandom: %s\n", strerror(errno));
+            goto ret;
+        }
+        total_bytes_written += chunk_size;
+    }
+
+    INFO("Mixed %d bytes from /dev/hw_random into /dev/urandom",
+                total_bytes_written);
+    result = 0;
+
+ret:
+    if (hwrandom_fd != -1) {
+        close(hwrandom_fd);
+    }
+    if (urandom_fd != -1) {
+        close(urandom_fd);
+    }
+    memset(buf, 0, sizeof(buf));
+    return result;
+}
+
 static int keychord_init_action(int nargs, char **args)
 {
     keychord_init();
@@ -958,6 +1040,7 @@
     action_for_each_trigger("early-init", action_add_queue_tail);
 
     queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
+    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
     queue_builtin_action(keychord_init_action, "keychord_init");
     queue_builtin_action(console_init_action, "console_init");
 
@@ -972,6 +1055,11 @@
         action_for_each_trigger("post-fs-data", action_add_queue_tail);
     }
 
+    /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
+     * wasn't ready immediately after wait_for_coldboot_done
+     */
+    queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
+
     queue_builtin_action(property_service_init_action, "property_service_init");
     queue_builtin_action(signal_init_action, "signal_init");
     queue_builtin_action(check_startup_action, "check_startup");
diff --git a/init/init_parser.c b/init/init_parser.c
index 38582f5..f49e698 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -60,7 +60,7 @@
 #define KEYWORD(symbol, flags, nargs, func) \
     [ K_##symbol ] = { #symbol, func, nargs + 1, flags, },
 
-struct {
+static struct {
     const char *name;
     int (*func)(int nargs, char **args);
     unsigned char nargs;
@@ -76,7 +76,7 @@
 #define kw_func(kw) (keyword_info[kw].func)
 #define kw_nargs(kw) (keyword_info[kw].nargs)
 
-int lookup_keyword(const char *s)
+static int lookup_keyword(const char *s)
 {
     switch (*s++) {
     case 'c':
@@ -130,6 +130,8 @@
         if (!strcmp(s, "neshot")) return K_oneshot;
         if (!strcmp(s, "nrestart")) return K_onrestart;
         break;
+    case 'p':
+        if (!strcmp(s, "owerctl")) return K_powerctl;
     case 'r':
         if (!strcmp(s, "estart")) return K_restart;
         if (!strcmp(s, "estorecon")) return K_restorecon;
@@ -150,6 +152,7 @@
         if (!strcmp(s, "ocket")) return K_socket;
         if (!strcmp(s, "tart")) return K_start;
         if (!strcmp(s, "top")) return K_stop;
+        if (!strcmp(s, "wapon_all")) return K_swapon_all;
         if (!strcmp(s, "ymlink")) return K_symlink;
         if (!strcmp(s, "ysclktz")) return K_sysclktz;
         break;
@@ -167,7 +170,7 @@
     return K_UNKNOWN;
 }
 
-void parse_line_no_op(struct parse_state *state, int nargs, char **args)
+static void parse_line_no_op(struct parse_state *state, int nargs, char **args)
 {
 }
 
@@ -290,7 +293,7 @@
     return -1;
 }
 
-void parse_import(struct parse_state *state, int nargs, char **args)
+static void parse_import(struct parse_state *state, int nargs, char **args)
 {
     struct listnode *import_list = state->priv;
     struct import *import;
@@ -315,7 +318,7 @@
     INFO("found import '%s', adding to import list", import->filename);
 }
 
-void parse_new_section(struct parse_state *state, int kw,
+static void parse_new_section(struct parse_state *state, int kw,
                        int nargs, char **args)
 {
     printf("[ %s %s ]\n", args[0],
diff --git a/init/keywords.h b/init/keywords.h
index 414db08..97fe50c 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -14,6 +14,7 @@
 int do_mkdir(int nargs, char **args);
 int do_mount_all(int nargs, char **args);
 int do_mount(int nargs, char **args);
+int do_powerctl(int nargs, char **args);
 int do_restart(int nargs, char **args);
 int do_restorecon(int nargs, char **args);
 int do_restorecon_recursive(int nargs, char **args);
@@ -27,6 +28,7 @@
 int do_setsebool(int nargs, char **args);
 int do_start(int nargs, char **args);
 int do_stop(int nargs, char **args);
+int do_swapon_all(int nargs, char **args);
 int do_trigger(int nargs, char **args);
 int do_symlink(int nargs, char **args);
 int do_sysclktz(int nargs, char **args);
@@ -67,6 +69,7 @@
     KEYWORD(on,          SECTION, 0, 0)
     KEYWORD(oneshot,     OPTION,  0, 0)
     KEYWORD(onrestart,   OPTION,  0, 0)
+    KEYWORD(powerctl,    COMMAND, 1, do_powerctl)
     KEYWORD(restart,     COMMAND, 1, do_restart)
     KEYWORD(restorecon,  COMMAND, 1, do_restorecon)
     KEYWORD(restorecon_recursive,  COMMAND, 1, do_restorecon_recursive)
@@ -84,6 +87,7 @@
     KEYWORD(socket,      OPTION,  0, 0)
     KEYWORD(start,       COMMAND, 1, do_start)
     KEYWORD(stop,        COMMAND, 1, do_stop)
+    KEYWORD(swapon_all,  COMMAND, 1, do_swapon_all)
     KEYWORD(trigger,     COMMAND, 1, do_trigger)
     KEYWORD(symlink,     COMMAND, 1, do_symlink)
     KEYWORD(sysclktz,    COMMAND, 1, do_sysclktz)
diff --git a/init/parser.h b/init/parser.h
index 0a5802a..a58272a 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -33,7 +33,6 @@
     void *priv;
 };
 
-int lookup_keyword(const char *s);
 void DUMP(void);
 int next_token(struct parse_state *state);
 void parse_error(struct parse_state *state, const char *fmt, ...);
diff --git a/init/property_service.c b/init/property_service.c
old mode 100755
new mode 100644
index f5f5457..c370769
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -78,6 +78,7 @@
     { "runtime.",         AID_SYSTEM,   0 },
     { "hw.",              AID_SYSTEM,   0 },
     { "sys.",             AID_SYSTEM,   0 },
+    { "sys.powerctl",     AID_SHELL,    0 },
     { "service.",         AID_SYSTEM,   0 },
     { "wlan.",            AID_SYSTEM,   0 },
     { "gps.",             AID_GPS,      0 },
@@ -277,6 +278,34 @@
     }
 }
 
+static bool is_legal_property_name(const char* name, size_t namelen)
+{
+    size_t i;
+    bool previous_was_dot = false;
+    if (namelen >= PROP_NAME_MAX) return false;
+    if (namelen < 1) return false;
+    if (name[0] == '.') return false;
+    if (name[namelen - 1] == '.') return false;
+
+    /* Only allow alphanumeric, plus '.', '-', or '_' */
+    /* Don't allow ".." to appear in a property name */
+    for (i = 0; i < namelen; i++) {
+        if (name[i] == '.') {
+            if (previous_was_dot == true) return false;
+            previous_was_dot = true;
+            continue;
+        }
+        previous_was_dot = false;
+        if (name[i] == '_' || name[i] == '-') continue;
+        if (name[i] >= 'a' && name[i] <= 'z') continue;
+        if (name[i] >= 'A' && name[i] <= 'Z') continue;
+        if (name[i] >= '0' && name[i] <= '9') continue;
+        return false;
+    }
+
+    return true;
+}
+
 int property_set(const char *name, const char *value)
 {
     prop_info *pi;
@@ -285,9 +314,8 @@
     size_t namelen = strlen(name);
     size_t valuelen = strlen(value);
 
-    if(namelen >= PROP_NAME_MAX) return -1;
-    if(valuelen >= PROP_VALUE_MAX) return -1;
-    if(namelen < 1) return -1;
+    if (!is_legal_property_name(name, namelen)) return -1;
+    if (valuelen >= PROP_VALUE_MAX) return -1;
 
     pi = (prop_info*) __system_property_find(name);
 
@@ -299,7 +327,7 @@
     } else {
         ret = __system_property_add(name, namelen, value, valuelen);
         if (ret < 0) {
-            ERROR("Failed to set '%s'='%s'", name, value);
+            ERROR("Failed to set '%s'='%s'\n", name, value);
             return ret;
         }
     }
@@ -365,6 +393,12 @@
         msg.name[PROP_NAME_MAX-1] = 0;
         msg.value[PROP_VALUE_MAX-1] = 0;
 
+        if (!is_legal_property_name(msg.name, strlen(msg.name))) {
+            ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name);
+            close(s);
+            return;
+        }
+
         getpeercon(s, &source_ctx);
 
         if(memcmp(msg.name,"ctl.",4) == 0) {
diff --git a/init/signal_handler.c b/init/signal_handler.c
index d31ad63..7e8e1a7 100644
--- a/init/signal_handler.c
+++ b/init/signal_handler.c
@@ -57,7 +57,15 @@
 
     svc = service_find_by_pid(pid);
     if (!svc) {
-        ERROR("untracked pid %d exited\n", pid);
+        if (WIFEXITED(status)) {
+            ERROR("untracked pid %d exited with status %d\n", pid, WEXITSTATUS(status));
+        } else if (WIFSIGNALED(status)) {
+            ERROR("untracked pid %d killed by signal %d\n", pid, WTERMSIG(status));
+        } else if (WIFSTOPPED(status)) {
+            ERROR("untracked pid %d stopped by signal %d\n", pid, WSTOPSIG(status));
+        } else {
+            ERROR("untracked pid %d state changed\n", pid);
+        }
         return 0;
     }
 
diff --git a/init/ueventd.h b/init/ueventd.h
index 9066e47..0a454c5 100644
--- a/init/ueventd.h
+++ b/init/ueventd.h
@@ -17,6 +17,21 @@
 #ifndef _INIT_UEVENTD_H_
 #define _INIT_UEVENTD_H_
 
+#include <cutils/list.h>
+#include <sys/types.h>
+
+struct ueventd_subsystem {
+    struct listnode slist;
+
+    const char *name;
+    enum {
+        DEVNAME_UNKNOWN = 0,
+        DEVNAME_UEVENT_DEVNAME,
+        DEVNAME_UEVENT_DEVPATH,
+    } devname_src;
+    const char *dirname;
+};
+
 int ueventd_main(int argc, char **argv);
 
 #endif
diff --git a/init/ueventd_keywords.h b/init/ueventd_keywords.h
new file mode 100644
index 0000000..88e8f01
--- /dev/null
+++ b/init/ueventd_keywords.h
@@ -0,0 +1,15 @@
+#ifndef KEYWORD
+#define __MAKE_KEYWORD_ENUM__
+#define KEYWORD(symbol, flags, nargs) K_##symbol,
+enum {
+    K_UNKNOWN,
+#endif
+    KEYWORD(subsystem,      SECTION,    1)
+    KEYWORD(devname,        OPTION,     1)
+    KEYWORD(dirname,        OPTION,     1)
+#ifdef __MAKE_KEYWORD_ENUM__
+    KEYWORD_COUNT,
+};
+#undef __MAKE_KEYWORD_ENUM__
+#undef KEYWORD
+#endif
diff --git a/init/ueventd_parser.c b/init/ueventd_parser.c
index 3e60df5..e447006 100644
--- a/init/ueventd_parser.c
+++ b/init/ueventd_parser.c
@@ -14,18 +14,189 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
+#include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #include <string.h>
 
+#include "ueventd.h"
 #include "ueventd_parser.h"
 #include "parser.h"
 #include "log.h"
 #include "util.h"
 
+static list_declare(subsystem_list);
+
 static void parse_line_device(struct parse_state *state, int nargs, char **args);
 
+#define SECTION 0x01
+#define OPTION  0x02
+
+#include "ueventd_keywords.h"
+
+#define KEYWORD(symbol, flags, nargs) \
+    [ K_##symbol ] = { #symbol, nargs + 1, flags, },
+
+static struct {
+    const char *name;
+    unsigned char nargs;
+    unsigned char flags;
+} keyword_info[KEYWORD_COUNT] = {
+    [ K_UNKNOWN ] = { "unknown", 0, 0 },
+#include "ueventd_keywords.h"
+};
+#undef KEYWORD
+
+#define kw_is(kw, type) (keyword_info[kw].flags & (type))
+#define kw_nargs(kw) (keyword_info[kw].nargs)
+
+static int lookup_keyword(const char *s)
+{
+    switch (*s++) {
+    case 'd':
+        if (!strcmp(s, "evname")) return K_devname;
+        if (!strcmp(s, "irname")) return K_dirname;
+        break;
+    case 's':
+        if (!strcmp(s, "ubsystem")) return K_subsystem;
+        break;
+    }
+    return K_UNKNOWN;
+}
+
+static void parse_line_no_op(struct parse_state *state __attribute__((unused)),
+        int nargs __attribute__((unused)), char **args  __attribute__((unused)))
+{
+}
+
+static int valid_name(const char *name)
+{
+    while (*name) {
+        if (!isalnum(*name) && (*name != '_') && (*name != '-')) {
+            return 0;
+        }
+        name++;
+    }
+    return 1;
+}
+
+struct ueventd_subsystem *ueventd_subsystem_find_by_name(const char *name)
+{
+    struct listnode *node;
+    struct ueventd_subsystem *s;
+
+    list_for_each(node, &subsystem_list) {
+        s = node_to_item(node, struct ueventd_subsystem, slist);
+        if (!strcmp(s->name, name)) {
+            return s;
+        }
+    }
+    return 0;
+}
+
+static void *parse_subsystem(struct parse_state *state,
+        int nargs __attribute__((unused)), char **args)
+{
+    struct ueventd_subsystem *s;
+
+    if (!valid_name(args[1])) {
+        parse_error(state, "invalid subsystem name '%s'\n", args[1]);
+        return 0;
+    }
+
+    s = ueventd_subsystem_find_by_name(args[1]);
+    if (s) {
+        parse_error(state, "ignored duplicate definition of subsystem '%s'\n",
+                args[1]);
+        return 0;
+    }
+
+    s = calloc(1, sizeof(*s));
+    if (!s) {
+        parse_error(state, "out of memory\n");
+        return 0;
+    }
+    s->name = args[1];
+    s->dirname = "/dev";
+    list_add_tail(&subsystem_list, &s->slist);
+    return s;
+}
+
+static void parse_line_subsystem(struct parse_state *state, int nargs,
+        char **args)
+{
+    struct ueventd_subsystem *s = state->context;
+    int kw;
+
+    if (nargs == 0) {
+        return;
+    }
+
+    kw = lookup_keyword(args[0]);
+    switch (kw) {
+    case K_devname:
+        if (!strcmp(args[1], "uevent_devname"))
+            s->devname_src = DEVNAME_UEVENT_DEVNAME;
+        else if (!strcmp(args[1], "uevent_devpath"))
+            s->devname_src = DEVNAME_UEVENT_DEVPATH;
+        else
+            parse_error(state, "invalid devname '%s'\n", args[1]);
+        break;
+
+    case K_dirname:
+        if (args[1][0] == '/')
+            s->dirname = args[1];
+        else
+            parse_error(state, "dirname '%s' does not start with '/'\n",
+                    args[1]);
+        break;
+
+    default:
+        parse_error(state, "invalid option '%s'\n", args[0]);
+    }
+}
+
+static void parse_new_section(struct parse_state *state, int kw,
+                       int nargs, char **args)
+{
+    printf("[ %s %s ]\n", args[0],
+           nargs > 1 ? args[1] : "");
+
+    switch(kw) {
+    case K_subsystem:
+        state->context = parse_subsystem(state, nargs, args);
+        if (state->context) {
+            state->parse_line = parse_line_subsystem;
+            return;
+        }
+        break;
+    }
+    state->parse_line = parse_line_no_op;
+}
+
+static void parse_line(struct parse_state *state, char **args, int nargs)
+{
+    int kw = lookup_keyword(args[0]);
+    int kw_nargs = kw_nargs(kw);
+
+    if (nargs < kw_nargs) {
+        parse_error(state, "%s requires %d %s\n", args[0], kw_nargs - 1,
+            kw_nargs > 2 ? "arguments" : "argument");
+        return;
+    }
+
+    if (kw_is(kw, SECTION)) {
+        parse_new_section(state, kw, nargs, args);
+    } else if (kw_is(kw, OPTION)) {
+        state->parse_line(state, nargs, args);
+    } else {
+        parse_line_device(state, nargs, args);
+    }
+}
+
 static void parse_config(const char *fn, char *s)
 {
     struct parse_state state;
@@ -36,18 +207,19 @@
     state.line = 1;
     state.ptr = s;
     state.nexttoken = 0;
-    state.parse_line = parse_line_device;
+    state.parse_line = parse_line_no_op;
     for (;;) {
         int token = next_token(&state);
         switch (token) {
         case T_EOF:
-            state.parse_line(&state, 0, 0);
+            parse_line(&state, args, nargs);
             return;
         case T_NEWLINE:
             if (nargs) {
-                state.parse_line(&state, nargs, args);
+                parse_line(&state, args, nargs);
                 nargs = 0;
             }
+            state.line++;
             break;
         case T_TEXT:
             if (nargs < UEVENTD_PARSER_MAXARGS) {
@@ -69,7 +241,8 @@
     return 0;
 }
 
-static void parse_line_device(struct parse_state* state, int nargs, char **args)
+static void parse_line_device(struct parse_state *state __attribute__((unused)),
+        int nargs, char **args)
 {
     set_device_permission(nargs, args);
 }
diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h
index 3684285..907cc49 100644
--- a/init/ueventd_parser.h
+++ b/init/ueventd_parser.h
@@ -17,9 +17,12 @@
 #ifndef _INIT_UEVENTD_PARSER_H_
 #define _INIT_UEVENTD_PARSER_H_
 
+#include "ueventd.h"
+
 #define UEVENTD_PARSER_MAXARGS 5
 
 int ueventd_parse_config_file(const char *fn);
 void set_device_permission(int nargs, char **args);
+struct ueventd_subsystem *ueventd_subsystem_find_by_name(const char *name);
 
 #endif
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index 66d7e62..eb55b47 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -23,7 +23,7 @@
 	liblog \
 
 # To enable using libunwind on each arch, add it to the list below.
-ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),))
+ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),arm))
 
 #----------------------------------------------------------------------------
 # The native libbacktrace library with libunwind.
@@ -137,6 +137,7 @@
 	thread_utils.c \
 
 LOCAL_CFLAGS += \
+	$(common_cflags) \
 	-fno-builtin \
 	-fstack-protector-all \
 	-O0 \
@@ -149,7 +150,6 @@
 
 LOCAL_CPPFLAGS += \
 	$(common_cppflags) \
-	-fpermissive \
 
 LOCAL_SHARED_LIBRARIES += \
 	libcutils \
@@ -241,6 +241,7 @@
 	thread_utils.c \
 
 LOCAL_CFLAGS += \
+	$(common_cflags) \
 	-fno-builtin \
 	-fstack-protector-all \
 	-O0 \
@@ -251,9 +252,6 @@
 	libbacktrace_test \
 	libbacktrace \
 
-LOCAL_CPPFLAGS += \
-	-fpermissive \
-
 LOCAL_LDLIBS := \
 	-lpthread \
 
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 17d9e1d..b22d301 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -213,13 +213,13 @@
 }
 
 Backtrace* Backtrace::Create(pid_t pid, pid_t tid) {
-  if (pid < 0 || pid == getpid()) {
-    if (tid < 0 || tid == gettid()) {
+  if (pid == BACKTRACE_CURRENT_PROCESS || pid == getpid()) {
+    if (tid == BACKTRACE_NO_TID || tid == gettid()) {
       return CreateCurrentObj();
     } else {
       return CreateThreadObj(tid);
     }
-  } else if (tid < 0) {
+  } else if (tid == BACKTRACE_NO_TID) {
     return CreatePtraceObj(pid, pid);
   } else {
     return CreatePtraceObj(pid, tid);
diff --git a/libbacktrace/Corkscrew.cpp b/libbacktrace/Corkscrew.cpp
index 9daa752..2be5930 100644
--- a/libbacktrace/Corkscrew.cpp
+++ b/libbacktrace/Corkscrew.cpp
@@ -86,15 +86,33 @@
 std::string CorkscrewCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
   *offset = 0;
 
-  // Get information about the current thread.
   Dl_info info;
   const backtrace_map_info_t* map_info = backtrace_obj_->FindMapInfo(pc);
-  const char* symbol_name = NULL;
-  if (map_info && dladdr((const void*)pc, &info) && info.dli_sname) {
-    *offset = pc - map_info->start - (uintptr_t)info.dli_saddr + (uintptr_t)info.dli_fbase;
-    symbol_name = info.dli_sname;
-
-    return symbol_name;
+  if (map_info) {
+    if (dladdr((const void*)pc, &info)) {
+      if (info.dli_sname) {
+        *offset = pc - map_info->start - (uintptr_t)info.dli_saddr + (uintptr_t)info.dli_fbase;
+        return info.dli_sname;
+      }
+    } else {
+      // dladdr(3) didn't find a symbol; maybe it's static? Look in the ELF file...
+      symbol_table_t* symbol_table = load_symbol_table(map_info->name);
+      if (symbol_table) {
+        // First check if we can find the symbol using a relative pc.
+        std::string name;
+        const symbol_t* elf_symbol = find_symbol(symbol_table, pc - map_info->start);
+        if (elf_symbol) {
+          name = elf_symbol->name;
+          *offset = pc - map_info->start - elf_symbol->start;
+        } else if ((elf_symbol = find_symbol(symbol_table, pc)) != NULL) {
+          // Found the symbol using the absolute pc.
+          name = elf_symbol->name;
+          *offset = pc - elf_symbol->start;
+        }
+        free_symbol_table(symbol_table);
+        return name;
+      }
+    }
   }
   return "";
 }
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 48e2bdc..2603e1f 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -143,7 +143,7 @@
 void VerifyLevelBacktrace(void*) {
   backtrace_context_t context;
 
-  ASSERT_TRUE(backtrace_create_context(&context, -1, -1, 0));
+  ASSERT_TRUE(backtrace_create_context(&context, BACKTRACE_CURRENT_PROCESS, BACKTRACE_NO_TID, 0));
 
   VerifyLevelDump(context.backtrace);
 
@@ -165,7 +165,7 @@
 void VerifyMaxBacktrace(void*) {
   backtrace_context_t context;
 
-  ASSERT_TRUE(backtrace_create_context(&context, -1, -1, 0));
+  ASSERT_TRUE(backtrace_create_context(&context, BACKTRACE_CURRENT_PROCESS, BACKTRACE_NO_TID, 0));
 
   VerifyMaxDump(context.backtrace);
 
@@ -232,15 +232,15 @@
 
 void VerifyLevelIgnoreFrames(void*) {
   backtrace_context_t all;
-  ASSERT_TRUE(backtrace_create_context(&all, -1, -1, 0));
+  ASSERT_TRUE(backtrace_create_context(&all, BACKTRACE_CURRENT_PROCESS, BACKTRACE_NO_TID, 0));
   ASSERT_TRUE(all.backtrace != NULL);
 
   backtrace_context_t ign1;
-  ASSERT_TRUE(backtrace_create_context(&ign1, -1, -1, 1));
+  ASSERT_TRUE(backtrace_create_context(&ign1, BACKTRACE_CURRENT_PROCESS, BACKTRACE_NO_TID, 1));
   ASSERT_TRUE(ign1.backtrace != NULL);
 
   backtrace_context_t ign2;
-  ASSERT_TRUE(backtrace_create_context(&ign2, -1, -1, 2));
+  ASSERT_TRUE(backtrace_create_context(&ign2, BACKTRACE_CURRENT_PROCESS, BACKTRACE_NO_TID, 2));
   ASSERT_TRUE(ign2.backtrace != NULL);
 
   VerifyIgnoreFrames(all.backtrace, ign1.backtrace, ign2.backtrace,
@@ -296,7 +296,7 @@
     ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
     exit(1);
   }
-  VerifyProcTest(pid, -1, ReadyLevelBacktrace, VerifyLevelDump);
+  VerifyProcTest(pid, BACKTRACE_NO_TID, ReadyLevelBacktrace, VerifyLevelDump);
 
   kill(pid, SIGKILL);
   int status;
@@ -309,7 +309,7 @@
     ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, NULL, NULL), 0);
     exit(1);
   }
-  VerifyProcTest(pid, -1, ReadyMaxBacktrace, VerifyMaxDump);
+  VerifyProcTest(pid, BACKTRACE_NO_TID, ReadyMaxBacktrace, VerifyMaxDump);
 
   kill(pid, SIGKILL);
   int status;
@@ -320,11 +320,11 @@
   pid_t pid = bt_all->pid;
 
   backtrace_context_t ign1;
-  ASSERT_TRUE(backtrace_create_context(&ign1, pid, -1, 1));
+  ASSERT_TRUE(backtrace_create_context(&ign1, pid, BACKTRACE_NO_TID, 1));
   ASSERT_TRUE(ign1.backtrace != NULL);
 
   backtrace_context_t ign2;
-  ASSERT_TRUE(backtrace_create_context(&ign2, pid, -1, 2));
+  ASSERT_TRUE(backtrace_create_context(&ign2, pid, BACKTRACE_NO_TID, 2));
   ASSERT_TRUE(ign2.backtrace != NULL);
 
   VerifyIgnoreFrames(bt_all, ign1.backtrace, ign2.backtrace, NULL);
@@ -339,7 +339,7 @@
     ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0);
     exit(1);
   }
-  VerifyProcTest(pid, -1, ReadyLevelBacktrace, VerifyProcessIgnoreFrames);
+  VerifyProcTest(pid, BACKTRACE_NO_TID, ReadyLevelBacktrace, VerifyProcessIgnoreFrames);
 
   kill(pid, SIGKILL);
   int status;
@@ -614,10 +614,10 @@
 TEST(libbacktrace, format_test) {
   backtrace_context_t context;
 
-  ASSERT_TRUE(backtrace_create_context(&context, -1, -1, 0));
+  ASSERT_TRUE(backtrace_create_context(&context, BACKTRACE_CURRENT_PROCESS, BACKTRACE_NO_TID, 0));
   ASSERT_TRUE(context.backtrace != NULL);
 
-  backtrace_frame_data_t* frame = &context.backtrace->frames[1];
+  backtrace_frame_data_t* frame = const_cast<backtrace_frame_data_t*>(&context.backtrace->frames[1]);
   backtrace_frame_data_t save_frame = *frame;
 
   memset(frame, 0, sizeof(backtrace_frame_data_t));
@@ -638,7 +638,7 @@
   EXPECT_STREQ(buf, "#01 pc 12345678  MapFake");
 #endif
 
-  frame->func_name = "ProcFake";
+  frame->func_name = const_cast<char*>("ProcFake");
   backtrace_format_frame_data(&context, 1, buf, sizeof(buf));
 #if defined(__LP64__)
   EXPECT_STREQ(buf, "#01 pc 0000000012345678  MapFake (ProcFake)");
diff --git a/libcorkscrew/backtrace.c b/libcorkscrew/backtrace.c
index b365e5b..f1dd61d 100644
--- a/libcorkscrew/backtrace.c
+++ b/libcorkscrew/backtrace.c
@@ -319,16 +319,17 @@
     if (symbolName) {
         uint32_t pc_offset = symbol->relative_pc - symbol->relative_symbol_addr;
         if (pc_offset) {
-            snprintf(buffer, bufferSize, "#%02u  pc %p  %.*s (%.*s+%u)",
-                    frameNumber, (void*) symbol->relative_pc, fieldWidth, mapName,
-                    fieldWidth, symbolName, pc_offset);
+            snprintf(buffer, bufferSize, "#%02u  pc %08x  %.*s (%.*s+%u)",
+                    frameNumber, (unsigned int) symbol->relative_pc,
+                    fieldWidth, mapName, fieldWidth, symbolName, pc_offset);
         } else {
-            snprintf(buffer, bufferSize, "#%02u  pc %p  %.*s (%.*s)",
-                    frameNumber, (void*) symbol->relative_pc, fieldWidth, mapName,
-                    fieldWidth, symbolName);
+            snprintf(buffer, bufferSize, "#%02u  pc %08x  %.*s (%.*s)",
+                    frameNumber, (unsigned int) symbol->relative_pc,
+                    fieldWidth, mapName, fieldWidth, symbolName);
         }
     } else {
-        snprintf(buffer, bufferSize, "#%02u  pc %p  %.*s",
-                frameNumber, (void*) symbol->relative_pc, fieldWidth, mapName);
+        snprintf(buffer, bufferSize, "#%02u  pc %08x  %.*s",
+                frameNumber, (unsigned int) symbol->relative_pc,
+                fieldWidth, mapName);
     }
 }
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 6207f1f..f8dda36 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -24,11 +24,9 @@
 hostSmpFlag := -DANDROID_SMP=0
 
 commonSources := \
-	array.c \
 	hashmap.c \
 	atomic.c.arm \
 	native_handle.c \
-	buffer.c \
 	socket_inaddr_any_server.c \
 	socket_local_client.c \
 	socket_local_server.c \
@@ -45,8 +43,6 @@
 	strdup8to16.c \
 	record_stream.c \
 	process_name.c \
-	properties.c \
-	qsort_r_compat.c \
 	threads.c \
 	sched_policy.c \
 	iosched_policy.c \
@@ -69,16 +65,10 @@
     WINDOWS_HOST_ONLY := 1
 endif
 
-ifeq ($(WINDOWS_HOST_ONLY),1)
+ifneq ($(WINDOWS_HOST_ONLY),1)
     commonSources += \
-        uio.c
-else
-    commonSources += \
-        abort_socket.c \
         fs.c \
-        selector.c \
-        multiuser.c \
-        zygote.c
+        multiuser.c
 endif
 
 
@@ -113,8 +103,8 @@
         ashmem-dev.c \
         debugger.c \
         klog.c \
-        mq.c \
         partition_utils.c \
+        properties.c \
         qtaguid.c \
         trace.c \
         uevent.c
diff --git a/libcutils/abort_socket.c b/libcutils/abort_socket.c
deleted file mode 100644
index 6a5e5e4..0000000
--- a/libcutils/abort_socket.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright 2009, 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.
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/poll.h>
-
-#include "cutils/abort_socket.h"
-
-struct asocket *asocket_init(int fd) {
-    int abort_fd[2];
-    int flags;
-    struct asocket *s;
-
-    /* set primary socket to non-blocking */
-    flags = fcntl(fd, F_GETFL);
-    if (flags == -1)
-        return NULL;
-    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK))
-        return NULL;
-
-    /* create pipe with non-blocking write, so that asocket_close() cannot
-       block */
-    if (pipe(abort_fd))
-        return NULL;
-    flags = fcntl(abort_fd[1], F_GETFL);
-    if (flags == -1)
-        return NULL;
-    if (fcntl(abort_fd[1], F_SETFL, flags | O_NONBLOCK))
-        return NULL;
-
-    s = malloc(sizeof(struct asocket));
-    if (!s)
-        return NULL;
-
-    s->fd = fd;
-    s->abort_fd[0] = abort_fd[0];
-    s->abort_fd[1] = abort_fd[1];
-
-    return s;
-}
-
-int asocket_connect(struct asocket *s, const struct sockaddr *addr,
-        socklen_t addrlen, int timeout) {
-
-    int ret;
-
-    do {
-        ret = connect(s->fd, addr, addrlen);
-    } while (ret && errno == EINTR);
-
-    if (ret && errno == EINPROGRESS) {
-        /* ready to poll() */
-        socklen_t retlen;
-        struct pollfd pfd[2];
-
-        pfd[0].fd = s->fd;
-        pfd[0].events = POLLOUT;
-        pfd[0].revents = 0;
-        pfd[1].fd = s->abort_fd[0];
-        pfd[1].events = POLLIN;
-        pfd[1].revents = 0;
-
-        do {
-            ret = poll(pfd, 2, timeout);
-        } while (ret < 0 && errno == EINTR);
-
-        if (ret < 0)
-            return -1;
-        else if (ret == 0) {
-            /* timeout */
-            errno = ETIMEDOUT;
-            return -1;
-        }
-
-        if (pfd[1].revents) {
-            /* abort due to asocket_abort() */
-            errno = ECANCELED;
-            return -1;
-        }
-
-        if (pfd[0].revents) {
-            if (pfd[0].revents & POLLOUT) {
-                /* connect call complete, read return code */
-                retlen = sizeof(ret);
-                if (getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &ret, &retlen))
-                    return -1;
-                /* got connect() return code */
-                if (ret) {
-                    errno = ret;
-                }
-            } else {
-                /* some error event on this fd */
-                errno = ECONNABORTED;
-                return -1;
-            }
-        }
-    }
-
-    return ret;
-}
-
-int asocket_accept(struct asocket *s, struct sockaddr *addr,
-        socklen_t *addrlen, int timeout) {
-
-    int ret;
-    struct pollfd pfd[2];
-
-    pfd[0].fd = s->fd;
-    pfd[0].events = POLLIN;
-    pfd[0].revents = 0;
-    pfd[1].fd = s->abort_fd[0];
-    pfd[1].events = POLLIN;
-    pfd[1].revents = 0;
-
-    do {
-        ret = poll(pfd, 2, timeout);
-    } while (ret < 0 && errno == EINTR);
-
-    if (ret < 0)
-        return -1;
-    else if (ret == 0) {
-        /* timeout */
-        errno = ETIMEDOUT;
-        return -1;
-    }
-
-    if (pfd[1].revents) {
-        /* abort due to asocket_abort() */
-        errno = ECANCELED;
-        return -1;
-    }
-
-    if (pfd[0].revents) {
-        if (pfd[0].revents & POLLIN) {
-            /* ready to accept() without blocking */
-            do {
-                ret = accept(s->fd, addr, addrlen);
-            } while (ret < 0 && errno == EINTR);
-        } else {
-            /* some error event on this fd */
-            errno = ECONNABORTED;
-            return -1;
-        }
-    }
-
-    return ret;
-}
-
-int asocket_read(struct asocket *s, void *buf, size_t count, int timeout) {
-    int ret;
-    struct pollfd pfd[2];
-
-    pfd[0].fd = s->fd;
-    pfd[0].events = POLLIN;
-    pfd[0].revents = 0;
-    pfd[1].fd = s->abort_fd[0];
-    pfd[1].events = POLLIN;
-    pfd[1].revents = 0;
-
-    do {
-        ret = poll(pfd, 2, timeout);
-    } while (ret < 0 && errno == EINTR);
-
-    if (ret < 0)
-        return -1;
-    else if (ret == 0) {
-        /* timeout */
-        errno = ETIMEDOUT;
-        return -1;
-    }
-
-    if (pfd[1].revents) {
-        /* abort due to asocket_abort() */
-        errno = ECANCELED;
-        return -1;
-    }
-
-    if (pfd[0].revents) {
-        if (pfd[0].revents & POLLIN) {
-            /* ready to read() without blocking */
-            do {
-                ret = read(s->fd, buf, count);
-            } while (ret < 0 && errno == EINTR);
-        } else {
-            /* some error event on this fd */
-            errno = ECONNABORTED;
-            return -1;
-        }
-    }
-
-    return ret;
-}
-
-int asocket_write(struct asocket *s, const void *buf, size_t count,
-        int timeout) {
-    int ret;
-    struct pollfd pfd[2];
-
-    pfd[0].fd = s->fd;
-    pfd[0].events = POLLOUT;
-    pfd[0].revents = 0;
-    pfd[1].fd = s->abort_fd[0];
-    pfd[1].events = POLLIN;
-    pfd[1].revents = 0;
-
-    do {
-        ret = poll(pfd, 2, timeout);
-    } while (ret < 0 && errno == EINTR);
-
-    if (ret < 0)
-        return -1;
-    else if (ret == 0) {
-        /* timeout */
-        errno = ETIMEDOUT;
-        return -1;
-    }
-
-    if (pfd[1].revents) {
-        /* abort due to asocket_abort() */
-        errno = ECANCELED;
-        return -1;
-    }
-
-    if (pfd[0].revents) {
-        if (pfd[0].revents & POLLOUT) {
-            /* ready to write() without blocking */
-            do {
-                ret = write(s->fd, buf, count);
-            } while (ret < 0 && errno == EINTR);
-        } else {
-            /* some error event on this fd */
-            errno = ECONNABORTED;
-            return -1;
-        }
-    }
-
-    return ret;
-}
-
-void asocket_abort(struct asocket *s) {
-    int ret;
-    char buf = 0;
-
-    /* Prevent further use of fd, without yet releasing the fd */
-    shutdown(s->fd, SHUT_RDWR);
-
-    /* wake up calls blocked at poll() */
-    do {
-        ret = write(s->abort_fd[1], &buf, 1);
-    } while (ret < 0 && errno == EINTR);
-}
-
-void asocket_destroy(struct asocket *s) {
-    struct asocket s_copy = *s;
-
-    /* Clients should *not* be using these fd's after calling
-       asocket_destroy(), but in case they do, set to -1 so they cannot use a
-       stale fd */
-    s->fd = -1;
-    s->abort_fd[0] = -1;
-    s->abort_fd[1] = -1;
-
-    /* Call asocket_abort() in case there are still threads blocked on this
-       socket. Clients should not rely on this behavior - it is racy because we
-       are about to close() these sockets - clients should instead make sure
-       all threads are done with the socket before calling asocket_destory().
-     */
-    asocket_abort(&s_copy);
-
-    /* enough safety checks, close and release memory */
-    close(s_copy.abort_fd[1]);
-    close(s_copy.abort_fd[0]);
-    close(s_copy.fd);
-
-    free(s);
-}
diff --git a/libcutils/android_reboot.c b/libcutils/android_reboot.c
index 33a7358..aef3054 100644
--- a/libcutils/android_reboot.c
+++ b/libcutils/android_reboot.c
@@ -16,6 +16,7 @@
 
 #include <unistd.h>
 #include <sys/reboot.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -105,11 +106,8 @@
 {
     int ret;
 
-    if (!(flags & ANDROID_RB_FLAG_NO_SYNC))
-        sync();
-
-    if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))
-        remount_ro();
+    sync();
+    remount_ro();
 
     switch (cmd) {
         case ANDROID_RB_RESTART:
@@ -121,7 +119,7 @@
             break;
 
         case ANDROID_RB_RESTART2:
-            ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+            ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                            LINUX_REBOOT_CMD_RESTART2, arg);
             break;
 
diff --git a/libcutils/array.c b/libcutils/array.c
deleted file mode 100644
index 55ec055..0000000
--- a/libcutils/array.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.
- */
-
-#include <cutils/array.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#define INITIAL_CAPACITY (4)
-#define MAX_CAPACITY     ((int)(UINT_MAX/sizeof(void*)))
-
-struct Array {
-    void** contents;
-    int size;
-    int capacity;
-};
-
-Array* arrayCreate() {
-    return calloc(1, sizeof(struct Array));
-}
-
-void arrayFree(Array* array) {
-    assert(array != NULL);
-
-    // Free internal array.
-    free(array->contents);
-
-    // Free the Array itself.
-    free(array);
-}
-
-/** Returns 0 if successful, < 0 otherwise.. */
-static int ensureCapacity(Array* array, int capacity) {
-    int oldCapacity = array->capacity;
-    if (capacity > oldCapacity) {
-        int newCapacity = (oldCapacity == 0) ? INITIAL_CAPACITY : oldCapacity;
-
-        // Ensure we're not doing something nasty
-        if (capacity > MAX_CAPACITY)
-            return -1;
-
-        // Keep doubling capacity until we surpass necessary capacity.
-        while (newCapacity < capacity) {
-            int  newCap = newCapacity*2;
-            // Handle integer overflows
-            if (newCap < newCapacity || newCap > MAX_CAPACITY) {
-                newCap = MAX_CAPACITY;
-            }
-            newCapacity = newCap;
-        }
-
-        // Should not happen, but better be safe than sorry
-        if (newCapacity < 0 || newCapacity > MAX_CAPACITY)
-            return -1;
-
-        void** newContents;
-        if (array->contents == NULL) {
-            // Allocate new array.
-            newContents = malloc(newCapacity * sizeof(void*));
-            if (newContents == NULL) {
-                return -1;
-            }
-        } else {
-            // Expand existing array.
-            newContents = realloc(array->contents, sizeof(void*) * newCapacity);
-            if (newContents == NULL) {
-                return -1;
-            }
-        }
-
-        array->capacity = newCapacity;
-        array->contents = newContents;
-    }
-
-    return 0;
-}
-
-int arrayAdd(Array* array, void* pointer) {
-    assert(array != NULL);
-    int size = array->size;
-    int result = ensureCapacity(array, size + 1);
-    if (result < 0) {
-        return result;
-    }
-    array->contents[size] = pointer;
-    array->size++;
-    return 0;
-}
-
-static inline void checkBounds(Array* array, int index) {
-    assert(array != NULL);
-    assert(index < array->size);
-    assert(index >= 0);
-}
-
-void* arrayGet(Array* array, int index) {
-    checkBounds(array, index);
-    return array->contents[index];
-}
-
-void* arrayRemove(Array* array, int index) {
-    checkBounds(array, index);
-
-    void* pointer = array->contents[index];
-    
-    int newSize = array->size - 1;
-    
-    // Shift entries left.
-    if (index != newSize) {
-        memmove(array->contents + index, array->contents + index + 1, 
-                (sizeof(void*)) * (newSize - index));
-    }
-
-    array->size = newSize;
-
-    return pointer;
-}
-
-void* arraySet(Array* array, int index, void* pointer) {
-    checkBounds(array, index);
-    void* old = array->contents[index];
-    array->contents[index] = pointer;
-    return old;
-}
-
-int arraySetSize(Array* array, int newSize) {
-    assert(array != NULL);
-    assert(newSize >= 0);
-   
-    int oldSize = array->size;
-    
-    if (newSize > oldSize) {
-        // Expand.
-        int result = ensureCapacity(array, newSize);
-        if (result < 0) {
-            return result;
-        }
-
-        // Zero out new entries.
-        memset(array->contents + sizeof(void*) * oldSize, 0,
-                sizeof(void*) * (newSize - oldSize));
-    }
-
-    array->size = newSize;
-
-    return 0;
-}
-
-int arraySize(Array* array) {
-    assert(array != NULL);
-    return array->size;
-}
-
-const void** arrayUnwrap(Array* array) {
-    return (const void**)array->contents;
-}
diff --git a/libcutils/buffer.c b/libcutils/buffer.c
deleted file mode 100644
index af99bd7..0000000
--- a/libcutils/buffer.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "buffer"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "buffer.h"
-#include "loghack.h"
-
-Buffer* bufferCreate(size_t capacity) {
-    Buffer* buffer = malloc(sizeof(Buffer));
-    if (buffer == NULL) {
-        return NULL;
-    }
-    buffer->capacity = capacity;
-    buffer->expected = 0;
-    buffer->data = malloc(capacity);
-    if (buffer->data == NULL) {
-        free(buffer);
-        return NULL;
-    }
-    return buffer;
-}
-
-void bufferFree(Buffer* buffer) {
-    free(buffer->data);
-    free(buffer);
-}
-
-Buffer* bufferWrap(char* data, size_t capacity, size_t size) {
-    Buffer* buffer = malloc(sizeof(Buffer));
-    if (buffer == NULL) {
-        return NULL;
-    }
-
-    buffer->data = data;
-    buffer->capacity = capacity;
-    buffer->size = size;
-    buffer->expected = 0;
-    return buffer;
-}
-
-int bufferPrepareForRead(Buffer* buffer, size_t expected) {
-    if (expected > buffer->capacity) {
-        // Expand buffer.
-        char* expanded = realloc(buffer->data, expected);
-        if (expanded == NULL) {
-            errno = ENOMEM;
-            return -1;
-        }
-        buffer->capacity = expected;
-        buffer->data = expanded;
-    }
-
-    buffer->size = 0;
-    buffer->expected = expected;
-    return 0;
-}
-
-ssize_t bufferRead(Buffer* buffer, int fd) {
-    assert(buffer->size < buffer->expected);
-    
-    ssize_t bytesRead = read(fd, 
-            buffer->data + buffer->size, 
-            buffer->expected - buffer->size);
-
-    if (bytesRead > 0) {
-        buffer->size += bytesRead;
-        return buffer->size;        
-    }
-
-    return bytesRead;
-}
-
-void bufferPrepareForWrite(Buffer* buffer) {
-    buffer->remaining = buffer->size;
-}
-
-ssize_t bufferWrite(Buffer* buffer, int fd) {
-    assert(buffer->remaining > 0);
-    assert(buffer->remaining <= buffer->size);
-
-    ssize_t bytesWritten = write(fd, 
-            buffer->data + buffer->size - buffer->remaining,
-            buffer->remaining);
-
-    if (bytesWritten >= 0) {
-        buffer->remaining -= bytesWritten;
-
-        ALOGD("Buffer bytes written: %d", (int) bytesWritten);
-        ALOGD("Buffer size: %d", (int) buffer->size);
-        ALOGD("Buffer remaining: %d", (int) buffer->remaining);
-
-        return buffer->remaining;
-    }
-
-    return bytesWritten;
-}
-
diff --git a/libcutils/buffer.h b/libcutils/buffer.h
deleted file mode 100644
index d8bc108..0000000
--- a/libcutils/buffer.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Byte buffer utilities.
- */
-
-#ifndef __BUFFER_H
-#define __BUFFER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdlib.h>
-
-/** 
- * Byte buffer of known size. Keeps track of how much data has been read
- * into or written out of the buffer.
- */
-typedef struct {
-    /** Buffered data. */
-    char* data;
-
-    union {
-        /** For reading. # of bytes we expect. */
-        size_t expected;
-
-        /** For writing. # of bytes to write. */
-        size_t remaining;
-    };
-
-    /** Actual # of bytes in the buffer. */
-    size_t size;
-
-    /** Amount of memory allocated for this buffer. */
-    size_t capacity;
-} Buffer;
-
-/**
- * Returns true if all data has been read into the buffer.
- */
-#define bufferReadComplete(buffer) (buffer->expected == buffer->size)
-
-/**
- * Returns true if the buffer has been completely written.
- */
-#define bufferWriteComplete(buffer) (buffer->remaining == 0)
-
-/**
- * Creates a new buffer with the given initial capacity.
- */
-Buffer* bufferCreate(size_t initialCapacity);
-
-/**
- * Wraps an existing byte array.
- */
-Buffer* bufferWrap(char* data, size_t capacity, size_t size);
-
-/**
- * Frees and its data.
- */
-void bufferFree(Buffer* buffer);
-
-/**
- * Prepares buffer to read 'expected' number of bytes. Expands capacity if
- * necessary. Returns 0 if successful or -1 if an error occurs allocating
- * memory.
- */
-int bufferPrepareForRead(Buffer* buffer, size_t expected);
-
-/**
- * Reads some data into a buffer. Returns -1 in case of an error and sets 
- * errno (see read()). Returns 0 for EOF. Updates buffer->size and returns
- * the new size after a succesful read. 
- *
- * Precondition: buffer->size < buffer->expected
- */
-ssize_t bufferRead(Buffer* buffer, int fd);
-
-/**
- * Prepares a buffer to be written out.
- */
-void bufferPrepareForWrite(Buffer* buffer);
-
-/**
- * Writes data from buffer to the given fd. Returns -1 and sets errno in case
- * of an error. Updates buffer->remaining and returns the number of remaining
- * bytes to be written after a successful write. 
- *
- * Precondition: buffer->remaining > 0
- */
-ssize_t bufferWrite(Buffer* buffer, int fd);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __BUFFER_H */ 
diff --git a/libcutils/fs.c b/libcutils/fs.c
index 116526d..286a8eb 100644
--- a/libcutils/fs.c
+++ b/libcutils/fs.c
@@ -16,6 +16,11 @@
 
 #define LOG_TAG "cutils"
 
+/* These defines are only needed because prebuilt headers are out of date */
+#define __USE_XOPEN2K8 1
+#define _ATFILE_SOURCE 1
+#define _GNU_SOURCE 1
+
 #include <cutils/fs.h>
 #include <cutils/log.h>
 
@@ -27,6 +32,7 @@
 #include <string.h>
 #include <limits.h>
 #include <stdlib.h>
+#include <dirent.h>
 
 #define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
 #define BUF_SIZE 64
@@ -141,3 +147,91 @@
     unlink(temp);
     return -1;
 }
+
+#ifndef __APPLE__
+
+int fs_mkdirs(const char* path, mode_t mode) {
+    int res = 0;
+    int fd = 0;
+    struct stat sb;
+    char* buf = strdup(path);
+
+    if (*buf != '/') {
+        ALOGE("Relative paths are not allowed: %s", buf);
+        res = -EINVAL;
+        goto done;
+    }
+
+    if ((fd = open("/", 0)) == -1) {
+        ALOGE("Failed to open(/): %s", strerror(errno));
+        res = -errno;
+        goto done;
+    }
+
+    char* segment = buf + 1;
+    char* p = segment;
+    while (*p != '\0') {
+        if (*p == '/') {
+            *p = '\0';
+
+            if (!strcmp(segment, "..") || !strcmp(segment, ".") || !strcmp(segment, "")) {
+                ALOGE("Invalid path: %s", buf);
+                res = -EINVAL;
+                goto done_close;
+            }
+
+            if (fstatat(fd, segment, &sb, AT_SYMLINK_NOFOLLOW) != 0) {
+                if (errno == ENOENT) {
+                    /* Nothing there yet; let's create it! */
+                    if (mkdirat(fd, segment, mode) != 0) {
+                        if (errno == EEXIST) {
+                            /* We raced with someone; ignore */
+                        } else {
+                            ALOGE("Failed to mkdirat(%s): %s", buf, strerror(errno));
+                            res = -errno;
+                            goto done_close;
+                        }
+                    }
+                } else {
+                    ALOGE("Failed to fstatat(%s): %s", buf, strerror(errno));
+                    res = -errno;
+                    goto done_close;
+                }
+            } else {
+                if (S_ISLNK(sb.st_mode)) {
+                    ALOGE("Symbolic links are not allowed: %s", buf);
+                    res = -ELOOP;
+                    goto done_close;
+                }
+                if (!S_ISDIR(sb.st_mode)) {
+                    ALOGE("Existing segment not a directory: %s", buf);
+                    res = -ENOTDIR;
+                    goto done_close;
+                }
+            }
+
+            /* Yay, segment is ready for us to step into */
+            int next_fd;
+            if ((next_fd = openat(fd, segment, 0)) == -1) {
+                ALOGE("Failed to openat(%s): %s", buf, strerror(errno));
+                res = -errno;
+                goto done_close;
+            }
+
+            close(fd);
+            fd = next_fd;
+
+            *p = '/';
+            segment = p + 1;
+        }
+        p++;
+    }
+
+done_close:
+    close(fd);
+done:
+    free(buf);
+    return res;
+}
+
+#endif
diff --git a/libcutils/klog.c b/libcutils/klog.c
index 812af3b..d69fb10 100644
--- a/libcutils/klog.c
+++ b/libcutils/klog.c
@@ -40,6 +40,8 @@
 
     if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {
         klog_fd = open(name, O_WRONLY);
+        if (klog_fd < 0)
+                return;
         fcntl(klog_fd, F_SETFD, FD_CLOEXEC);
         unlink(name);
     }
@@ -54,6 +56,7 @@
 
     if (level > klog_level) return;
     if (klog_fd < 0) klog_init();
+    if (klog_fd < 0) return;
 
     va_start(ap, fmt);
     vsnprintf(buf, LOG_BUF_MAX, fmt, ap);
diff --git a/libcutils/mq.c b/libcutils/mq.c
deleted file mode 100644
index 899b1bc..0000000
--- a/libcutils/mq.c
+++ /dev/null
@@ -1,1357 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "mq"
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <sys/uio.h>
-
-#include <cutils/array.h>
-#include <cutils/hashmap.h>
-#include <cutils/selector.h>
-
-#include "loghack.h"
-#include "buffer.h"
-
-/** Number of dead peers to remember. */
-#define PEER_HISTORY (16)
-
-typedef struct sockaddr SocketAddress;
-typedef struct sockaddr_un UnixAddress;
-
-/** 
- * Process/user/group ID. We don't use ucred directly because it's only 
- * available on Linux.
- */
-typedef struct {
-    pid_t pid;
-    uid_t uid;
-    gid_t gid;
-} Credentials;
-
-/** Listens for bytes coming from remote peers. */
-typedef void BytesListener(Credentials credentials, char* bytes, size_t size);
-
-/** Listens for the deaths of remote peers. */
-typedef void DeathListener(pid_t pid);
-
-/** Types of packets. */
-typedef enum {
-    /** Request for a connection to another peer. */
-    CONNECTION_REQUEST, 
-
-    /** A connection to another peer. */
-    CONNECTION, 
-
-    /** Reports a failed connection attempt. */
-    CONNECTION_ERROR, 
-
-    /** A generic packet of bytes. */
-    BYTES,
-} PacketType;
-
-typedef enum {
-    /** Reading a packet header. */
-    READING_HEADER,
-
-    /** Waiting for a connection from the master. */
-    ACCEPTING_CONNECTION,
-
-    /** Reading bytes. */
-    READING_BYTES,
-} InputState;
-
-/** A packet header. */
-// TODO: Use custom headers for master->peer, peer->master, peer->peer.
-typedef struct {
-    PacketType type;
-    union {
-        /** Packet size. Used for BYTES. */
-        size_t size;
-
-        /** Credentials. Used for CONNECTION and CONNECTION_REQUEST. */
-        Credentials credentials; 
-    };
-} Header;
-
-/** A packet which will be sent to a peer. */
-typedef struct OutgoingPacket OutgoingPacket;
-struct OutgoingPacket {
-    /** Packet header. */
-    Header header; 
-    
-    union {
-        /** Connection to peer. Used with CONNECTION. */
-        int socket;
-        
-        /** Buffer of bytes. Used with BYTES. */
-        Buffer* bytes;
-    };
-
-    /** Frees all resources associated with this packet. */
-    void (*free)(OutgoingPacket* packet);
-   
-    /** Optional context. */
-    void* context;
-    
-    /** Next packet in the queue. */
-    OutgoingPacket* nextPacket;
-};
-
-/** Represents a remote peer. */
-typedef struct PeerProxy PeerProxy;
-
-/** Local peer state. You typically have one peer per process. */
-typedef struct {
-    /** This peer's PID. */
-    pid_t pid;
-    
-    /** 
-     * Map from pid to peer proxy. The peer has a peer proxy for each remote
-     * peer it's connected to. 
-     *
-     * Acquire mutex before use.
-     */
-    Hashmap* peerProxies;
-
-    /** Manages I/O. */
-    Selector* selector;
-   
-    /** Used to synchronize operations with the selector thread. */
-    pthread_mutex_t mutex; 
-
-    /** Is this peer the master? */
-    bool master;
-
-    /** Peer proxy for the master. */
-    PeerProxy* masterProxy;
-    
-    /** Listens for packets from remote peers. */
-    BytesListener* onBytes;
-    
-    /** Listens for deaths of remote peers. */
-    DeathListener* onDeath;
-    
-    /** Keeps track of recently dead peers. Requires mutex. */
-    pid_t deadPeers[PEER_HISTORY];
-    size_t deadPeerCursor;
-} Peer;
-
-struct PeerProxy {
-    /** Credentials of the remote process. */
-    Credentials credentials;
-
-    /** Keeps track of data coming in from the remote peer. */
-    InputState inputState;
-    Buffer* inputBuffer;
-    PeerProxy* connecting;
-
-    /** File descriptor for this peer. */
-    SelectableFd* fd;
-
-    /** 
-     * Queue of packets to be written out to the remote peer.
-     *
-     * Requires mutex.
-     */
-    // TODO: Limit queue length.
-    OutgoingPacket* currentPacket;
-    OutgoingPacket* lastPacket;
-    
-    /** Used to write outgoing header. */
-    Buffer outgoingHeader;
-    
-    /** True if this is the master's proxy. */
-    bool master;
-
-    /** Reference back to the local peer. */
-    Peer* peer;
-
-    /**
-     * Used in master only. Maps this peer proxy to other peer proxies to
-     * which the peer has been connected to. Maps pid to PeerProxy. Helps
-     * keep track of which connections we've sent to whom.
-     */
-    Hashmap* connections;
-};
-
-/** Server socket path. */
-static const char* MASTER_PATH = "/master.peer";
-
-/** Credentials of the master peer. */
-static const Credentials MASTER_CREDENTIALS = {0, 0, 0};
-
-/** Creates a peer proxy and adds it to the peer proxy map. */
-static PeerProxy* peerProxyCreate(Peer* peer, Credentials credentials);
-
-/** Sets the non-blocking flag on a descriptor. */
-static void setNonBlocking(int fd) {
-    int flags;
-    if ((flags = fcntl(fd, F_GETFL, 0)) < 0) { 
-        LOG_ALWAYS_FATAL("fcntl() error: %s", strerror(errno));
-    } 
-    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { 
-        LOG_ALWAYS_FATAL("fcntl() error: %s", strerror(errno));
-    } 
-}
-
-/** Closes a fd and logs a warning if the close fails. */
-static void closeWithWarning(int fd) {
-    int result = close(fd);
-    if (result == -1) {
-        ALOGW("close() error: %s", strerror(errno));
-    }
-}
-
-/** Hashes pid_t keys. */
-static int pidHash(void* key) {
-    pid_t* pid = (pid_t*) key;
-    return (int) (*pid);
-}
-
-/** Compares pid_t keys. */
-static bool pidEquals(void* keyA, void* keyB) {
-    pid_t* a = (pid_t*) keyA;
-    pid_t* b = (pid_t*) keyB;
-    return *a == *b;
-}
-
-/** Gets the master address. Not thread safe. */
-static UnixAddress* getMasterAddress() {
-    static UnixAddress masterAddress;
-    static bool initialized = false;
-    if (initialized == false) {
-        masterAddress.sun_family = AF_LOCAL;
-        strcpy(masterAddress.sun_path, MASTER_PATH); 
-        initialized = true;
-    }
-    return &masterAddress;
-}
-
-/** Gets exclusive access to the peer for this thread. */
-static void peerLock(Peer* peer) {
-    pthread_mutex_lock(&peer->mutex);
-}
-
-/** Releases exclusive access to the peer. */
-static void peerUnlock(Peer* peer) {
-    pthread_mutex_unlock(&peer->mutex);
-}
-
-/** Frees a simple, i.e. header-only, outgoing packet. */
-static void outgoingPacketFree(OutgoingPacket* packet) {
-    ALOGD("Freeing outgoing packet.");
-	free(packet);
-}
-
-/**
- * Prepare to read a new packet from the peer.
- */
-static void peerProxyExpectHeader(PeerProxy* peerProxy) {
-    peerProxy->inputState = READING_HEADER;
-    bufferPrepareForRead(peerProxy->inputBuffer, sizeof(Header));
-}
-
-/** Sets up the buffer for the outgoing header. */
-static void peerProxyPrepareOutgoingHeader(PeerProxy* peerProxy) {
-    peerProxy->outgoingHeader.data 
-        = (char*) &(peerProxy->currentPacket->header);
-    peerProxy->outgoingHeader.size = sizeof(Header);
-    bufferPrepareForWrite(&peerProxy->outgoingHeader);
-}
-
-/** Adds a packet to the end of the queue. Callers must have the mutex. */
-static void peerProxyEnqueueOutgoingPacket(PeerProxy* peerProxy,
-        OutgoingPacket* newPacket) {
-    newPacket->nextPacket = NULL; // Just in case.
-    if (peerProxy->currentPacket == NULL) {
-        // The queue is empty.
-        peerProxy->currentPacket = newPacket;
-        peerProxy->lastPacket = newPacket;
-        
-        peerProxyPrepareOutgoingHeader(peerProxy); 
-    } else {
-        peerProxy->lastPacket->nextPacket = newPacket;
-    }
-}
-
-/** Takes the peer lock and enqueues the given packet. */
-static void peerProxyLockAndEnqueueOutgoingPacket(PeerProxy* peerProxy,
-        OutgoingPacket* newPacket) {
-    Peer* peer = peerProxy->peer;
-    peerLock(peer);
-    peerProxyEnqueueOutgoingPacket(peerProxy, newPacket);
-    peerUnlock(peer);
-}
-
-/** 
- * Frees current packet and moves to the next one. Returns true if there is
- * a next packet or false if the queue is empty.
- */
-static bool peerProxyNextPacket(PeerProxy* peerProxy) {
-    Peer* peer = peerProxy->peer;
-    peerLock(peer);
-    
-    OutgoingPacket* current = peerProxy->currentPacket;
-    
-    if (current == NULL) {
-    	// The queue is already empty.
-        peerUnlock(peer);
-        return false;
-    }
-    
-    OutgoingPacket* next = current->nextPacket;
-    peerProxy->currentPacket = next;
-    current->nextPacket = NULL;
-    current->free(current);
-    if (next == NULL) {
-        // The queue is empty.
-        peerProxy->lastPacket = NULL;
-        peerUnlock(peer);
-        return false;
-    } else {
-        peerUnlock(peer);
-        peerProxyPrepareOutgoingHeader(peerProxy); 
-
-        // TODO: Start writing next packet? It would reduce the number of
-        // system calls, but we could also starve other peers.
-        return true;
-    }
-}
-
-/**
- * Checks whether a peer died recently.
- */
-static bool peerIsDead(Peer* peer, pid_t pid) {
-    size_t i;
-    for (i = 0; i < PEER_HISTORY; i++) {
-        pid_t deadPeer = peer->deadPeers[i];
-        if (deadPeer == 0) {
-            return false;
-        }
-        if (deadPeer == pid) {
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * Cleans up connection information.
- */
-static bool peerProxyRemoveConnection(void* key, void* value, void* context) {
-    PeerProxy* deadPeer = (PeerProxy*) context;
-    PeerProxy* otherPeer = (PeerProxy*) value;
-    hashmapRemove(otherPeer->connections, &(deadPeer->credentials.pid));
-    return true;
-}
-
-/**
- * Called when the peer dies.
- */
-static void peerProxyKill(PeerProxy* peerProxy, bool errnoIsSet) {
-    if (errnoIsSet) {
-        ALOGI("Peer %d died. errno: %s", peerProxy->credentials.pid, 
-                strerror(errno));
-    } else {
-        ALOGI("Peer %d died.", peerProxy->credentials.pid);
-    }
-    
-    // If we lost the master, we're up a creek. We can't let this happen.
-    if (peerProxy->master) {    
-        LOG_ALWAYS_FATAL("Lost connection to master.");
-    }
-
-    Peer* localPeer = peerProxy->peer;
-    pid_t pid = peerProxy->credentials.pid;
-    
-    peerLock(localPeer);
-    
-    // Remember for awhile that the peer died.
-    localPeer->deadPeers[localPeer->deadPeerCursor] 
-        = peerProxy->credentials.pid;
-    localPeer->deadPeerCursor++;
-    if (localPeer->deadPeerCursor == PEER_HISTORY) {
-        localPeer->deadPeerCursor = 0;
-    }
-  
-    // Remove from peer map.
-    hashmapRemove(localPeer->peerProxies, &pid);
-    
-    // External threads can no longer get to this peer proxy, so we don't 
-    // need the lock anymore.
-    peerUnlock(localPeer);
-    
-    // Remove the fd from the selector.
-    if (peerProxy->fd != NULL) {
-        peerProxy->fd->remove = true;
-    }
-
-    // Clear outgoing packet queue.
-    while (peerProxyNextPacket(peerProxy)) {}
-
-    bufferFree(peerProxy->inputBuffer);
-
-    // This only applies to the master.
-    if (peerProxy->connections != NULL) {
-        // We can't leave these other maps pointing to freed memory.
-        hashmapForEach(peerProxy->connections, &peerProxyRemoveConnection, 
-                peerProxy);
-        hashmapFree(peerProxy->connections);
-    }
-
-    // Invoke death listener.
-    localPeer->onDeath(pid);
-
-    // Free the peer proxy itself.
-    free(peerProxy);
-}
-
-static void peerProxyHandleError(PeerProxy* peerProxy, char* functionName) {
-    if (errno == EINTR) {
-        // Log interruptions but otherwise ignore them.
-        ALOGW("%s() interrupted.", functionName);
-    } else if (errno == EAGAIN) {
-        ALOGD("EWOULDBLOCK");
-        // Ignore.
-    } else {
-        ALOGW("Error returned by %s().", functionName);
-        peerProxyKill(peerProxy, true);
-    }
-}
-
-/**
- * Buffers output sent to a peer. May be called multiple times until the entire
- * buffer is filled. Returns true when the buffer is empty.
- */
-static bool peerProxyWriteFromBuffer(PeerProxy* peerProxy, Buffer* outgoing) {
-    ssize_t size = bufferWrite(outgoing, peerProxy->fd->fd);
-    if (size < 0) {
-        peerProxyHandleError(peerProxy, "write");
-        return false;
-    } else {
-        return bufferWriteComplete(outgoing);
-    }
-}
-
-/** Writes packet bytes to peer. */
-static void peerProxyWriteBytes(PeerProxy* peerProxy) {	
-	Buffer* buffer = peerProxy->currentPacket->bytes;
-	if (peerProxyWriteFromBuffer(peerProxy, buffer)) {
-        ALOGD("Bytes written.");
-        peerProxyNextPacket(peerProxy);
-    }    
-}
-
-/** Sends a socket to the peer. */
-static void peerProxyWriteConnection(PeerProxy* peerProxy) {
-    int socket = peerProxy->currentPacket->socket;
-
-    // Why does sending and receiving fds have to be such a PITA?
-    struct msghdr msg;
-    struct iovec iov[1];
-    
-    union {
-        struct cmsghdr cm;
-        char control[CMSG_SPACE(sizeof(int))];
-    } control_un;
-   
-    struct cmsghdr *cmptr;
-    
-    msg.msg_control = control_un.control;
-    msg.msg_controllen = sizeof(control_un.control);
-    cmptr = CMSG_FIRSTHDR(&msg);
-    cmptr->cmsg_len = CMSG_LEN(sizeof(int));
-    cmptr->cmsg_level = SOL_SOCKET;
-    cmptr->cmsg_type = SCM_RIGHTS;
-   
-    // Store the socket in the message.
-    *((int *) CMSG_DATA(cmptr)) = peerProxy->currentPacket->socket;
-
-    msg.msg_name = NULL;
-    msg.msg_namelen = 0;
-    iov[0].iov_base = "";
-    iov[0].iov_len = 1;
-    msg.msg_iov = iov;
-    msg.msg_iovlen = 1;
-
-    ssize_t result = sendmsg(peerProxy->fd->fd, &msg, 0);
-    
-    if (result < 0) {
-        peerProxyHandleError(peerProxy, "sendmsg");
-    } else {
-        // Success. Queue up the next packet.
-        peerProxyNextPacket(peerProxy);
-        
-    }
-}
-
-/**
- * Writes some outgoing data.
- */
-static void peerProxyWrite(SelectableFd* fd) {
-    // TODO: Try to write header and body with one system call.
-
-    PeerProxy* peerProxy = (PeerProxy*) fd->data;
-    OutgoingPacket* current = peerProxy->currentPacket;
-    
-    if (current == NULL) {
-        // We have nothing left to write.
-        return;
-    }
-
-    // Write the header.
-    Buffer* outgoingHeader = &peerProxy->outgoingHeader;
-    bool headerWritten = bufferWriteComplete(outgoingHeader);
-    if (!headerWritten) {
-        ALOGD("Writing header...");
-        headerWritten = peerProxyWriteFromBuffer(peerProxy, outgoingHeader);
-        if (headerWritten) {
-            ALOGD("Header written.");
-        }
-    }    
-
-    // Write body.
-    if (headerWritten) {
-        PacketType type = current->header.type;
-        switch (type) {
-            case CONNECTION:
-                peerProxyWriteConnection(peerProxy);
-                break;
-            case BYTES:
-                peerProxyWriteBytes(peerProxy);
-                break;
-            case CONNECTION_REQUEST:
-            case CONNECTION_ERROR:
-                // These packets consist solely of a header.
-                peerProxyNextPacket(peerProxy);
-                break;
-            default:
-                LOG_ALWAYS_FATAL("Unknown packet type: %d", type); 
-        }
-    }
-}
-
-/**
- * Sets up a peer proxy's fd before we try to select() it.
- */
-static void peerProxyBeforeSelect(SelectableFd* fd) {
-    ALOGD("Before select...");
-
-    PeerProxy* peerProxy = (PeerProxy*) fd->data;
-  
-    peerLock(peerProxy->peer);
-    bool hasPackets = peerProxy->currentPacket != NULL;
-    peerUnlock(peerProxy->peer);
-    
-    if (hasPackets) {
-        ALOGD("Packets found. Setting onWritable().");
-            
-        fd->onWritable = &peerProxyWrite;
-    } else {
-        // We have nothing to write.
-        fd->onWritable = NULL;
-    }
-}
-
-/** Prepare to read bytes from the peer. */
-static void peerProxyExpectBytes(PeerProxy* peerProxy, Header* header) {
-    ALOGD("Expecting %zd bytes.", header->size);
-
-    peerProxy->inputState = READING_BYTES;
-    if (bufferPrepareForRead(peerProxy->inputBuffer, header->size) == -1) {
-        ALOGW("Couldn't allocate memory for incoming data. Size: %u",
-                (unsigned int) header->size);    
-        
-        // TODO: Ignore the packet and log a warning?
-        peerProxyKill(peerProxy, false);
-    }
-}
-
-/**
- * Gets a peer proxy for the given ID. Creates a peer proxy if necessary.
- * Sends a connection request to the master if desired.
- *
- * Returns NULL if an error occurs. Sets errno to EHOSTDOWN if the peer died
- * or ENOMEM if memory couldn't be allocated.
- */
-static PeerProxy* peerProxyGetOrCreate(Peer* peer, pid_t pid, 
-        bool requestConnection) {
-    if (pid == peer->pid) {
-        errno = EINVAL;
-        return NULL;
-    }
-    
-    if (peerIsDead(peer, pid)) {
-        errno = EHOSTDOWN;
-        return NULL;
-    }
-    
-    PeerProxy* peerProxy = hashmapGet(peer->peerProxies, &pid);
-    if (peerProxy != NULL) {
-        return peerProxy;
-    }
-
-    // If this is the master peer, we already know about all peers.
-    if (peer->master) {
-        errno = EHOSTDOWN;
-        return NULL;
-    }
-
-    // Try to create a peer proxy.
-    Credentials credentials;
-    credentials.pid = pid;
-
-    // Fake gid and uid until we have the real thing. The real creds are
-    // filled in by masterProxyExpectConnection(). These fake creds will
-    // never be exposed to the user.
-    credentials.uid = 0;
-    credentials.gid = 0;
-
-    // Make sure we can allocate the connection request packet.
-    OutgoingPacket* packet = NULL;
-    if (requestConnection) {
-        packet = calloc(1, sizeof(OutgoingPacket));
-        if (packet == NULL) {
-            errno = ENOMEM;
-            return NULL;
-        }
-
-        packet->header.type = CONNECTION_REQUEST;
-        packet->header.credentials = credentials;
-        packet->free = &outgoingPacketFree;
-    }
-    
-    peerProxy = peerProxyCreate(peer, credentials);
-    if (peerProxy == NULL) {
-        free(packet);
-        errno = ENOMEM;
-        return NULL;
-    } else {
-        // Send a connection request to the master.
-        if (requestConnection) {
-            PeerProxy* masterProxy = peer->masterProxy;
-            peerProxyEnqueueOutgoingPacket(masterProxy, packet);
-        }
-        
-        return peerProxy;
-    }
-}
-
-/**
- * Switches the master peer proxy into a state where it's waiting for a
- * connection from the master.
- */
-static void masterProxyExpectConnection(PeerProxy* masterProxy,
-        Header* header) {
-    // TODO: Restructure things so we don't need this check.
-    // Verify that this really is the master.
-    if (!masterProxy->master) {
-        ALOGW("Non-master process %d tried to send us a connection.", 
-            masterProxy->credentials.pid);
-        // Kill off the evil peer.
-        peerProxyKill(masterProxy, false);
-        return;
-    }
-    
-    masterProxy->inputState = ACCEPTING_CONNECTION;
-    Peer* localPeer = masterProxy->peer;
-   
-    // Create a peer proxy so we have somewhere to stash the creds.
-    // See if we already have a proxy set up.
-    pid_t pid = header->credentials.pid;
-    peerLock(localPeer);
-    PeerProxy* peerProxy = peerProxyGetOrCreate(localPeer, pid, false);
-    if (peerProxy == NULL) {
-        ALOGW("Peer proxy creation failed: %s", strerror(errno));
-    } else {
-        // Fill in full credentials.
-        peerProxy->credentials = header->credentials;
-    }
-    peerUnlock(localPeer);
-    
-    // Keep track of which peer proxy we're accepting a connection for.
-    masterProxy->connecting = peerProxy;
-}
-
-/**
- * Reads input from a peer process.
- */
-static void peerProxyRead(SelectableFd* fd);
-
-/** Sets up fd callbacks. */
-static void peerProxySetFd(PeerProxy* peerProxy, SelectableFd* fd) {
-    peerProxy->fd = fd;
-    fd->data = peerProxy;
-    fd->onReadable = &peerProxyRead;
-    fd->beforeSelect = &peerProxyBeforeSelect;
-    
-    // Make the socket non-blocking.
-    setNonBlocking(fd->fd);
-}
-
-/**
- * Accepts a connection sent by the master proxy.
- */
-static void masterProxyAcceptConnection(PeerProxy* masterProxy) {
-    struct msghdr msg;
-    struct iovec iov[1];
-    ssize_t size;
-    char ignored;
-    int incomingFd;
-    
-    // TODO: Reuse code which writes the connection. Who the heck designed
-    // this API anyway?
-    union {
-        struct cmsghdr cm;
-        char control[CMSG_SPACE(sizeof(int))];
-    } control_un;
-    struct cmsghdr *cmptr;
-    msg.msg_control = control_un.control;
-    msg.msg_controllen = sizeof(control_un.control);
-
-    msg.msg_name = NULL;
-    msg.msg_namelen = 0;
-
-    // We sent 1 byte of data so we can detect EOF.
-    iov[0].iov_base = &ignored;
-    iov[0].iov_len = 1;
-    msg.msg_iov = iov;
-    msg.msg_iovlen = 1;
-
-    size = recvmsg(masterProxy->fd->fd, &msg, 0);
-    if (size < 0) {
-        if (errno == EINTR) {
-            // Log interruptions but otherwise ignore them.
-            ALOGW("recvmsg() interrupted.");
-            return;
-        } else if (errno == EAGAIN) {
-            // Keep waiting for the connection.
-            return;
-        } else {
-            LOG_ALWAYS_FATAL("Error reading connection from master: %s",
-                    strerror(errno));
-        }
-    } else if (size == 0) {
-        // EOF.
-        LOG_ALWAYS_FATAL("Received EOF from master.");
-    }
-
-    // Extract fd from message.
-    if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL 
-            && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
-        if (cmptr->cmsg_level != SOL_SOCKET) {
-            LOG_ALWAYS_FATAL("Expected SOL_SOCKET.");
-        }
-        if (cmptr->cmsg_type != SCM_RIGHTS) {
-            LOG_ALWAYS_FATAL("Expected SCM_RIGHTS.");
-        }
-        incomingFd = *((int*) CMSG_DATA(cmptr));
-    } else {
-        LOG_ALWAYS_FATAL("Expected fd.");
-    }
-    
-    // The peer proxy this connection is for.
-    PeerProxy* peerProxy = masterProxy->connecting;
-    if (peerProxy == NULL) {
-        ALOGW("Received connection for unknown peer.");
-        closeWithWarning(incomingFd);
-    } else {
-        Peer* peer = masterProxy->peer;
-        
-        SelectableFd* selectableFd = selectorAdd(peer->selector, incomingFd);
-        if (selectableFd == NULL) {
-            ALOGW("Error adding fd to selector for %d.",
-                    peerProxy->credentials.pid);
-            closeWithWarning(incomingFd);
-            peerProxyKill(peerProxy, false);
-        }
-
-        peerProxySetFd(peerProxy, selectableFd);
-    }
-    
-    peerProxyExpectHeader(masterProxy);
-}
-
-/**
- * Frees an outgoing packet containing a connection.
- */
-static void outgoingPacketFreeSocket(OutgoingPacket* packet) {
-    closeWithWarning(packet->socket);
-    outgoingPacketFree(packet);
-}
-
-/**
- * Connects two known peers.
- */
-static void masterConnectPeers(PeerProxy* peerA, PeerProxy* peerB) {
-    int sockets[2];
-    int result = socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets);
-    if (result == -1) {
-        ALOGW("socketpair() error: %s", strerror(errno));
-        // TODO: Send CONNECTION_FAILED packets to peers.
-        return;
-    }
-
-    OutgoingPacket* packetA = calloc(1, sizeof(OutgoingPacket));
-    OutgoingPacket* packetB = calloc(1, sizeof(OutgoingPacket));
-    if (packetA == NULL || packetB == NULL) {
-        free(packetA);
-        free(packetB);
-        ALOGW("malloc() error. Failed to tell process %d that process %d is"
-                " dead.", peerA->credentials.pid, peerB->credentials.pid);
-        return;
-    }
-   
-    packetA->header.type = CONNECTION;
-    packetB->header.type = CONNECTION;
-    
-    packetA->header.credentials = peerB->credentials;
-    packetB->header.credentials = peerA->credentials;
-
-    packetA->socket = sockets[0];
-    packetB->socket = sockets[1];
-
-    packetA->free = &outgoingPacketFreeSocket;
-    packetB->free = &outgoingPacketFreeSocket;
-   
-    peerLock(peerA->peer);
-    peerProxyEnqueueOutgoingPacket(peerA, packetA);   
-    peerProxyEnqueueOutgoingPacket(peerB, packetB);   
-    peerUnlock(peerA->peer);
-}
-
-/**
- * Informs a peer that the peer they're trying to connect to couldn't be
- * found.
- */
-static void masterReportConnectionError(PeerProxy* peerProxy,
-        Credentials credentials) {
-    OutgoingPacket* packet = calloc(1, sizeof(OutgoingPacket));
-    if (packet == NULL) {
-        ALOGW("malloc() error. Failed to tell process %d that process %d is"
-                " dead.", peerProxy->credentials.pid, credentials.pid);
-        return;
-    }
-   
-    packet->header.type = CONNECTION_ERROR;
-    packet->header.credentials = credentials;
-    packet->free = &outgoingPacketFree;
-    
-    peerProxyLockAndEnqueueOutgoingPacket(peerProxy, packet);   
-}
-
-/**
- * Handles a request to be connected to another peer.
- */
-static void masterHandleConnectionRequest(PeerProxy* peerProxy, 
-        Header* header) {
-    Peer* master = peerProxy->peer;
-    pid_t targetPid = header->credentials.pid;
-    if (!hashmapContainsKey(peerProxy->connections, &targetPid)) {
-        // We haven't connected these peers yet.
-        PeerProxy* targetPeer 
-            = (PeerProxy*) hashmapGet(master->peerProxies, &targetPid);
-        if (targetPeer == NULL) {
-            // Unknown process.
-            masterReportConnectionError(peerProxy, header->credentials);
-        } else {
-            masterConnectPeers(peerProxy, targetPeer);
-        }
-    }
-    
-    // This packet is complete. Get ready for the next one.
-    peerProxyExpectHeader(peerProxy);
-}
-
-/**
- * The master told us this peer is dead.
- */
-static void masterProxyHandleConnectionError(PeerProxy* masterProxy,
-        Header* header) {
-    Peer* peer = masterProxy->peer;
-    
-    // Look up the peer proxy.
-    pid_t pid = header->credentials.pid;
-    PeerProxy* peerProxy = NULL;
-    peerLock(peer);
-    peerProxy = hashmapGet(peer->peerProxies, &pid);
-    peerUnlock(peer);
-
-    if (peerProxy != NULL) {
-        ALOGI("Couldn't connect to %d.", pid);
-        peerProxyKill(peerProxy, false);
-    } else {
-        ALOGW("Peer proxy for %d not found. This shouldn't happen.", pid);
-    }
-    
-    peerProxyExpectHeader(masterProxy);
-}
-
-/**
- * Handles a packet header.
- */
-static void peerProxyHandleHeader(PeerProxy* peerProxy, Header* header) {
-    switch (header->type) {
-        case CONNECTION_REQUEST:
-            masterHandleConnectionRequest(peerProxy, header);
-            break;
-        case CONNECTION:
-            masterProxyExpectConnection(peerProxy, header);
-            break;
-        case CONNECTION_ERROR:
-            masterProxyHandleConnectionError(peerProxy, header);
-            break;
-        case BYTES:    
-            peerProxyExpectBytes(peerProxy, header);
-            break;
-        default:
-            ALOGW("Invalid packet type from %d: %d", peerProxy->credentials.pid, 
-                    header->type);
-            peerProxyKill(peerProxy, false);
-    }
-}
-
-/**
- * Buffers input sent by peer. May be called multiple times until the entire
- * buffer is filled. Returns true when the buffer is full.
- */
-static bool peerProxyBufferInput(PeerProxy* peerProxy) {
-    Buffer* in = peerProxy->inputBuffer;
-    ssize_t size = bufferRead(in, peerProxy->fd->fd);
-    if (size < 0) {
-        peerProxyHandleError(peerProxy, "read");
-        return false;
-    } else if (size == 0) {
-        // EOF.
-    	ALOGI("EOF");
-        peerProxyKill(peerProxy, false);
-        return false;
-    } else if (bufferReadComplete(in)) {
-        // We're done!
-        return true;
-    } else {
-        // Continue reading.
-        return false;
-    }
-}
-
-/**
- * Reads input from a peer process.
- */
-static void peerProxyRead(SelectableFd* fd) {
-    ALOGD("Reading...");
-    PeerProxy* peerProxy = (PeerProxy*) fd->data;
-    int state = peerProxy->inputState;
-    Buffer* in = peerProxy->inputBuffer;
-    switch (state) {
-        case READING_HEADER:
-            if (peerProxyBufferInput(peerProxy)) {
-                ALOGD("Header read.");
-                // We've read the complete header.
-                Header* header = (Header*) in->data;
-                peerProxyHandleHeader(peerProxy, header);
-            }
-            break;
-        case READING_BYTES:
-            ALOGD("Reading bytes...");
-            if (peerProxyBufferInput(peerProxy)) {
-                ALOGD("Bytes read.");
-                // We have the complete packet. Notify bytes listener.
-                peerProxy->peer->onBytes(peerProxy->credentials,
-                    in->data, in->size);
-                        
-                // Get ready for the next packet.
-                peerProxyExpectHeader(peerProxy);
-            }
-            break;
-        case ACCEPTING_CONNECTION:
-            masterProxyAcceptConnection(peerProxy);
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Unknown state: %d", state);
-    }
-}
-
-static PeerProxy* peerProxyCreate(Peer* peer, Credentials credentials) {
-    PeerProxy* peerProxy = calloc(1, sizeof(PeerProxy));
-    if (peerProxy == NULL) {
-        return NULL;
-    }
-   
-    peerProxy->inputBuffer = bufferCreate(sizeof(Header));
-    if (peerProxy->inputBuffer == NULL) {
-        free(peerProxy);
-        return NULL;
-    }
-
-    peerProxy->peer = peer;
-    peerProxy->credentials = credentials;
-
-    // Initial state == expecting a header.
-    peerProxyExpectHeader(peerProxy); 
-  
-    // Add this proxy to the map. Make sure the key points to the stable memory
-    // inside of the peer proxy itself.
-    pid_t* pid = &(peerProxy->credentials.pid);
-    hashmapPut(peer->peerProxies, pid, peerProxy);
-    return peerProxy;
-}
-
-/** Accepts a connection to the master peer. */
-static void masterAcceptConnection(SelectableFd* listenerFd) {
-    // Accept connection.
-    int socket = accept(listenerFd->fd, NULL, NULL);
-    if (socket == -1) {
-        ALOGW("accept() error: %s", strerror(errno));
-        return;
-    }
-    
-    ALOGD("Accepted connection as fd %d.", socket);
-    
-    // Get credentials.
-    Credentials credentials;
-    struct ucred ucredentials;
-    socklen_t credentialsSize = sizeof(struct ucred);
-    int result = getsockopt(socket, SOL_SOCKET, SO_PEERCRED, 
-                &ucredentials, &credentialsSize);
-    // We might want to verify credentialsSize.
-    if (result == -1) {
-        ALOGW("getsockopt() error: %s", strerror(errno));
-        closeWithWarning(socket);
-        return;
-    }
-
-    // Copy values into our own structure so we know we have the types right.
-    credentials.pid = ucredentials.pid;
-    credentials.uid = ucredentials.uid;
-    credentials.gid = ucredentials.gid;
-    
-    ALOGI("Accepted connection from process %d.", credentials.pid);
-   
-    Peer* masterPeer = (Peer*) listenerFd->data;
-    
-    peerLock(masterPeer);
-    
-    // Make sure we don't already have a connection from that process.
-    PeerProxy* peerProxy 
-        = hashmapGet(masterPeer->peerProxies, &credentials.pid);
-    if (peerProxy != NULL) {
-        peerUnlock(masterPeer);
-        ALOGW("Alread connected to process %d.", credentials.pid);
-        closeWithWarning(socket);
-        return;
-    }
-   
-    // Add connection to the selector.
-    SelectableFd* socketFd = selectorAdd(masterPeer->selector, socket);
-    if (socketFd == NULL) {
-        peerUnlock(masterPeer);
-        ALOGW("malloc() failed.");
-        closeWithWarning(socket);
-        return;
-    }
-
-    // Create a peer proxy.
-    peerProxy = peerProxyCreate(masterPeer, credentials);
-    peerUnlock(masterPeer);
-    if (peerProxy == NULL) {
-        ALOGW("malloc() failed.");
-        socketFd->remove = true;
-        closeWithWarning(socket);
-    }
-    peerProxy->connections = hashmapCreate(10, &pidHash, &pidEquals);
-    peerProxySetFd(peerProxy, socketFd);
-}
-
-/**
- * Creates the local peer.
- */
-static Peer* peerCreate() {
-    Peer* peer = calloc(1, sizeof(Peer));
-    if (peer == NULL) {
-        LOG_ALWAYS_FATAL("malloc() error.");
-    }
-    peer->peerProxies = hashmapCreate(10, &pidHash, &pidEquals);
-    peer->selector = selectorCreate();
-    
-    pthread_mutexattr_t attributes;
-    if (pthread_mutexattr_init(&attributes) != 0) {
-        LOG_ALWAYS_FATAL("pthread_mutexattr_init() error.");
-    }
-    if (pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE) != 0) {
-        LOG_ALWAYS_FATAL("pthread_mutexattr_settype() error.");
-    }
-    if (pthread_mutex_init(&peer->mutex, &attributes) != 0) {
-        LOG_ALWAYS_FATAL("pthread_mutex_init() error.");
-    }
-    
-    peer->pid = getpid();
-    return peer;
-}
-
-/** The local peer. */
-static Peer* localPeer;
-
-/** Frees a packet of bytes. */
-static void outgoingPacketFreeBytes(OutgoingPacket* packet) {
-    ALOGD("Freeing outgoing packet.");
-    bufferFree(packet->bytes);
-    free(packet);
-}
-
-/**
- * Sends a packet of bytes to a remote peer. Returns 0 on success.
- *
- * Returns -1 if an error occurs. Sets errno to ENOMEM if memory couldn't be
- * allocated. Sets errno to EHOSTDOWN if the peer died recently. Sets errno
- * to EINVAL if pid is the same as the local pid.
- */
-int peerSendBytes(pid_t pid, const char* bytes, size_t size) {
-	Peer* peer = localPeer;
-    assert(peer != NULL);
-
-    OutgoingPacket* packet = calloc(1, sizeof(OutgoingPacket));
-    if (packet == NULL) {
-        errno = ENOMEM;
-        return -1;
-    }
-
-    Buffer* copy = bufferCreate(size); 
-    if (copy == NULL) {
-        free(packet);
-        errno = ENOMEM;
-        return -1;
-    }
-
-    // Copy data.
-    memcpy(copy->data, bytes, size);
-    copy->size = size;
-    
-    packet->bytes = copy;
-    packet->header.type = BYTES;
-    packet->header.size = size;
-    packet->free = outgoingPacketFreeBytes;
-    bufferPrepareForWrite(packet->bytes);
-    
-    peerLock(peer);
-    
-    PeerProxy* peerProxy = peerProxyGetOrCreate(peer, pid, true);
-    if (peerProxy == NULL) {
-        // The peer is already dead or we couldn't alloc memory. Either way,
-        // errno is set.
-        peerUnlock(peer);
-        packet->free(packet); 
-        return -1;
-    } else {
-        peerProxyEnqueueOutgoingPacket(peerProxy, packet);
-        peerUnlock(peer);
-        selectorWakeUp(peer->selector);
-        return 0; 
-    }
-}
-
-/** Keeps track of how to free shared bytes. */
-typedef struct {
-    void (*free)(void* context);
-    void* context;
-} SharedBytesFreer;
-
-/** Frees shared bytes. */
-static void outgoingPacketFreeSharedBytes(OutgoingPacket* packet) {
-    SharedBytesFreer* sharedBytesFreer 
-        = (SharedBytesFreer*) packet->context;
-    sharedBytesFreer->free(sharedBytesFreer->context);
-    free(sharedBytesFreer);
-    free(packet);
-}
-
-/**
- * Sends a packet of bytes to a remote peer without copying the bytes. Calls
- * free() with context after the bytes have been sent.
- *
- * Returns -1 if an error occurs. Sets errno to ENOMEM if memory couldn't be
- * allocated. Sets errno to EHOSTDOWN if the peer died recently. Sets errno
- * to EINVAL if pid is the same as the local pid.
- */
-int peerSendSharedBytes(pid_t pid, char* bytes, size_t size,
-        void (*free)(void* context), void* context) {
-    Peer* peer = localPeer;
-    assert(peer != NULL);
-
-    OutgoingPacket* packet = calloc(1, sizeof(OutgoingPacket));
-    if (packet == NULL) {
-        errno = ENOMEM;
-        return -1;
-    }
-
-    Buffer* wrapper = bufferWrap(bytes, size, size);
-    if (wrapper == NULL) {
-        free(packet);
-        errno = ENOMEM;
-        return -1;
-    }
-
-    SharedBytesFreer* sharedBytesFreer = malloc(sizeof(SharedBytesFreer));
-    if (sharedBytesFreer == NULL) {
-        free(packet);
-        free(wrapper);
-        errno = ENOMEM;
-        return -1;
-    }
-    sharedBytesFreer->free = free;
-    sharedBytesFreer->context = context;
-    
-    packet->bytes = wrapper;
-    packet->context = sharedBytesFreer;
-    packet->header.type = BYTES;
-    packet->header.size = size;
-    packet->free = &outgoingPacketFreeSharedBytes;
-    bufferPrepareForWrite(packet->bytes);
-    
-    peerLock(peer);
-    
-    PeerProxy* peerProxy = peerProxyGetOrCreate(peer, pid, true);
-    if (peerProxy == NULL) {
-        // The peer is already dead or we couldn't alloc memory. Either way,
-        // errno is set.
-        peerUnlock(peer);
-        packet->free(packet); 
-        return -1;
-    } else {
-        peerProxyEnqueueOutgoingPacket(peerProxy, packet);
-        peerUnlock(peer);
-        selectorWakeUp(peer->selector);
-        return 0; 
-    }
-}
-
-/**
- * Starts the master peer. The master peer differs from other peers in that
- * it is responsible for connecting the other peers. You can only have one
- * master peer.
- *
- * Goes into an I/O loop and does not return.
- */
-void masterPeerInitialize(BytesListener* bytesListener, 
-        DeathListener* deathListener) {
-    // Create and bind socket.
-    int listenerSocket = socket(AF_LOCAL, SOCK_STREAM, 0);
-    if (listenerSocket == -1) {
-        LOG_ALWAYS_FATAL("socket() error: %s", strerror(errno));
-    }
-    unlink(MASTER_PATH);
-    int result = bind(listenerSocket, (SocketAddress*) getMasterAddress(), 
-            sizeof(UnixAddress));
-    if (result == -1) {
-        LOG_ALWAYS_FATAL("bind() error: %s", strerror(errno));
-    }
-
-    ALOGD("Listener socket: %d",  listenerSocket);
-    
-    // Queue up to 16 connections.
-    result = listen(listenerSocket, 16);
-    if (result != 0) {
-        LOG_ALWAYS_FATAL("listen() error: %s", strerror(errno));
-    }
-
-    // Make socket non-blocking.
-    setNonBlocking(listenerSocket);
-
-    // Create the peer for this process. Fail if we already have one.
-    if (localPeer != NULL) {
-        LOG_ALWAYS_FATAL("Peer is already initialized.");
-    }
-    localPeer = peerCreate();
-    if (localPeer == NULL) {
-        LOG_ALWAYS_FATAL("malloc() failed.");
-    }
-    localPeer->master = true;
-    localPeer->onBytes = bytesListener;
-    localPeer->onDeath = deathListener;
-    
-    // Make listener socket selectable.
-    SelectableFd* listenerFd = selectorAdd(localPeer->selector, listenerSocket);
-    if (listenerFd == NULL) {
-        LOG_ALWAYS_FATAL("malloc() error.");
-    }
-    listenerFd->data = localPeer;
-    listenerFd->onReadable = &masterAcceptConnection;
-}
-
-/**
- * Starts a local peer.
- *
- * Goes into an I/O loop and does not return.
- */
-void peerInitialize(BytesListener* bytesListener, 
-        DeathListener* deathListener) {
-    // Connect to master peer.
-    int masterSocket = socket(AF_LOCAL, SOCK_STREAM, 0);
-    if (masterSocket == -1) {
-        LOG_ALWAYS_FATAL("socket() error: %s", strerror(errno));
-    }
-    int result = connect(masterSocket, (SocketAddress*) getMasterAddress(),
-            sizeof(UnixAddress));
-    if (result != 0) {
-        LOG_ALWAYS_FATAL("connect() error: %s", strerror(errno));
-    }
-
-    // Create the peer for this process. Fail if we already have one.
-    if (localPeer != NULL) {
-        LOG_ALWAYS_FATAL("Peer is already initialized.");
-    }
-    localPeer = peerCreate();
-    if (localPeer == NULL) {
-        LOG_ALWAYS_FATAL("malloc() failed.");
-    }
-    localPeer->onBytes = bytesListener;
-    localPeer->onDeath = deathListener;
-    
-    // Make connection selectable.
-    SelectableFd* masterFd = selectorAdd(localPeer->selector, masterSocket);
-    if (masterFd == NULL) {
-        LOG_ALWAYS_FATAL("malloc() error.");
-    }
-
-    // Create a peer proxy for the master peer.
-    PeerProxy* masterProxy = peerProxyCreate(localPeer, MASTER_CREDENTIALS);
-    if (masterProxy == NULL) {
-        LOG_ALWAYS_FATAL("malloc() error.");
-    }
-    peerProxySetFd(masterProxy, masterFd);
-    masterProxy->master = true;
-    localPeer->masterProxy = masterProxy;
-}
-
-/** Starts the master peer I/O loop. Doesn't return. */
-void peerLoop() {
-    assert(localPeer != NULL);
-    
-    // Start selector.
-    selectorLoop(localPeer->selector);
-}
-
diff --git a/libcutils/process_name.c b/libcutils/process_name.c
index bda9d08..a6ab951 100644
--- a/libcutils/process_name.c
+++ b/libcutils/process_name.c
@@ -17,7 +17,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <cutils/process_name.h>
+#ifdef HAVE_ANDROID_OS
 #include <cutils/properties.h>
+#endif
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -33,7 +35,9 @@
 static int running_in_emulator = -1;
 
 void set_process_name(const char* new_name) {
+#ifdef HAVE_ANDROID_OS
     char  propBuf[PROPERTY_VALUE_MAX];
+#endif
 
     if (new_name == NULL) {
         return;
@@ -53,6 +57,7 @@
     }
 #endif
 
+#ifdef HAVE_ANDROID_OS
     // If we know we are not running in the emulator, then return.
     if (running_in_emulator == 0) {
         return;
@@ -82,6 +87,7 @@
         return;
     write(fd, process_name, strlen(process_name) + 1);
     close(fd);
+#endif
 }
 
 const char* get_process_name(void) {
diff --git a/libcutils/qsort_r_compat.c b/libcutils/qsort_r_compat.c
deleted file mode 100644
index 8971cb5..0000000
--- a/libcutils/qsort_r_compat.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#include <stdlib.h>
-#include <cutils/qsort_r_compat.h>
-
-#if HAVE_BSD_QSORT_R
-
-/*
- * BSD qsort_r parameter order is as we have defined here.
- */
-
-void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
-        int (*compar)(void*, const void* , const void*)) {
-    qsort_r(base, nel, width, thunk, compar);
-}
-
-#elif HAVE_GNU_QSORT_R
-
-/*
- * GNU qsort_r parameter order places the thunk parameter last.
- */
-
-struct compar_data {
-    void* thunk;
-    int (*compar)(void*, const void* , const void*);
-};
-
-static int compar_wrapper(const void* a, const void* b, void* data) {
-    struct compar_data* compar_data = (struct compar_data*)data;
-    return compar_data->compar(compar_data->thunk, a, b);
-}
-
-void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
-        int (*compar)(void*, const void* , const void*)) {
-    struct compar_data compar_data;
-    compar_data.thunk = thunk;
-    compar_data.compar = compar;
-    qsort_r(base, nel, width, compar_wrapper, &compar_data);
-}
-
-#else
-
-/*
- * Emulate qsort_r using thread local storage to access the thunk data.
- */
-
-#include <cutils/threads.h>
-
-static thread_store_t compar_data_key = THREAD_STORE_INITIALIZER;
-
-struct compar_data {
-    void* thunk;
-    int (*compar)(void*, const void* , const void*);
-};
-
-static int compar_wrapper(const void* a, const void* b) {
-    struct compar_data* compar_data = (struct compar_data*)thread_store_get(&compar_data_key);
-    return compar_data->compar(compar_data->thunk, a, b);
-}
-
-void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
-        int (*compar)(void*, const void* , const void*)) {
-    struct compar_data compar_data;
-    compar_data.thunk = thunk;
-    compar_data.compar = compar;
-    thread_store_set(&compar_data_key, &compar_data, NULL);
-    qsort(base, nel, width, compar_wrapper);
-}
-
-#endif
diff --git a/libcutils/selector.c b/libcutils/selector.c
deleted file mode 100644
index 3776bbb..0000000
--- a/libcutils/selector.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "selector"
-
-#include <assert.h>
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cutils/array.h>
-#include <cutils/selector.h>
-
-#include "loghack.h"
-
-struct Selector {
-    Array* selectableFds;
-    bool looping;
-    fd_set readFds;
-    fd_set writeFds;
-    fd_set exceptFds;
-    int maxFd;
-    int wakeupPipe[2];
-    SelectableFd* wakeupFd;
-
-    bool inSelect;
-    pthread_mutex_t inSelectLock; 
-};
-
-/** Reads and ignores wake up data. */ 
-static void eatWakeupData(SelectableFd* wakeupFd) {
-    static char garbage[64];
-    if (read(wakeupFd->fd, garbage, sizeof(garbage)) < 0) {
-        if (errno == EINTR) {
-            ALOGI("read() interrupted.");    
-        } else {
-            LOG_ALWAYS_FATAL("This should never happen: %s", strerror(errno));
-        }
-    }
-}
-
-static void setInSelect(Selector* selector, bool inSelect) {
-    pthread_mutex_lock(&selector->inSelectLock);
-    selector->inSelect = inSelect;
-    pthread_mutex_unlock(&selector->inSelectLock);
-}
-
-static bool isInSelect(Selector* selector) {
-    pthread_mutex_lock(&selector->inSelectLock);
-    bool inSelect = selector->inSelect;
-    pthread_mutex_unlock(&selector->inSelectLock);
-    return inSelect;
-}
-
-void selectorWakeUp(Selector* selector) {
-    if (!isInSelect(selector)) {
-        // We only need to write wake-up data if we're blocked in select().
-        return;
-    }
-    
-    static char garbage[1];
-    if (write(selector->wakeupPipe[1], garbage, sizeof(garbage)) < 0) {
-        if (errno == EINTR) {
-            ALOGI("read() interrupted.");    
-        } else {
-            LOG_ALWAYS_FATAL("This should never happen: %s", strerror(errno));
-        }
-    }
-}
-
-Selector* selectorCreate(void) {
-    Selector* selector = calloc(1, sizeof(Selector));
-    if (selector == NULL) {
-        LOG_ALWAYS_FATAL("malloc() error.");
-    }
-    selector->selectableFds = arrayCreate();
-    
-    // Set up wake-up pipe.
-    if (pipe(selector->wakeupPipe) < 0) {
-        LOG_ALWAYS_FATAL("pipe() error: %s", strerror(errno));
-    }
-    
-    ALOGD("Wakeup fd: %d", selector->wakeupPipe[0]);
-    
-    SelectableFd* wakeupFd = selectorAdd(selector, selector->wakeupPipe[0]);
-    if (wakeupFd == NULL) {
-        LOG_ALWAYS_FATAL("malloc() error.");
-    }
-    wakeupFd->onReadable = &eatWakeupData; 
-    
-    pthread_mutex_init(&selector->inSelectLock, NULL);
-
-    return selector;
-}
-
-SelectableFd* selectorAdd(Selector* selector, int fd) {
-    assert(selector != NULL);
-
-    SelectableFd* selectableFd = calloc(1, sizeof(SelectableFd));
-    if (selectableFd != NULL) {
-        selectableFd->selector = selector;
-        selectableFd->fd = fd;
-    
-        arrayAdd(selector->selectableFds, selectableFd);
-    }
-
-    return selectableFd;
-}
-
-/**
- * Adds an fd to the given set if the callback is non-null. Returns true
- * if the fd was added.
- */
-static inline bool maybeAdd(SelectableFd* selectableFd,
-        void (*callback)(SelectableFd*), fd_set* fdSet) {
-    if (callback != NULL) {
-        FD_SET(selectableFd->fd, fdSet);
-        return true;
-    }
-    return false;
-}
-
-/**
- * Removes stale file descriptors and initializes file descriptor sets.
- */
-static void prepareForSelect(Selector* selector) {
-    fd_set* exceptFds = &selector->exceptFds;
-    fd_set* readFds = &selector->readFds;
-    fd_set* writeFds = &selector->writeFds;
-    
-    FD_ZERO(exceptFds);
-    FD_ZERO(readFds);
-    FD_ZERO(writeFds);
-
-    Array* selectableFds = selector->selectableFds;
-    int i = 0;
-    selector->maxFd = 0;
-    int size = arraySize(selectableFds);
-    while (i < size) {
-        SelectableFd* selectableFd = arrayGet(selectableFds, i);
-        if (selectableFd->remove) {
-            // This descriptor should be removed.
-            arrayRemove(selectableFds, i);
-            size--;
-            if (selectableFd->onRemove != NULL) {
-                selectableFd->onRemove(selectableFd);
-            }
-            free(selectableFd);
-        } else {
-            if (selectableFd->beforeSelect != NULL) {
-                selectableFd->beforeSelect(selectableFd);
-            }
-            
-            bool inSet = false;
-            if (maybeAdd(selectableFd, selectableFd->onExcept, exceptFds)) {
-                ALOGD("Selecting fd %d for writing...", selectableFd->fd);
-                inSet = true;
-            }
-            if (maybeAdd(selectableFd, selectableFd->onReadable, readFds)) {
-                ALOGD("Selecting fd %d for reading...", selectableFd->fd);
-                inSet = true;
-            }
-            if (maybeAdd(selectableFd, selectableFd->onWritable, writeFds)) {
-                inSet = true;
-            }
-
-            if (inSet) {
-                // If the fd is in a set, check it against max.
-                int fd = selectableFd->fd;
-                if (fd > selector->maxFd) {
-                    selector->maxFd = fd;
-                }
-            }
-            
-            // Move to next descriptor.
-            i++;
-        }
-    }
-}
-
-/**
- * Invokes a callback if the callback is non-null and the fd is in the given
- * set.
- */
-static inline void maybeInvoke(SelectableFd* selectableFd,
-        void (*callback)(SelectableFd*), fd_set* fdSet) {
-    if (callback != NULL && !selectableFd->remove && 
-            FD_ISSET(selectableFd->fd, fdSet)) {
-        ALOGD("Selected fd %d.", selectableFd->fd);
-        callback(selectableFd);
-    }
-}
-
-/**
- * Notifies user if file descriptors are readable or writable, or if
- * out-of-band data is present.
- */
-static void fireEvents(Selector* selector) {
-    Array* selectableFds = selector->selectableFds;
-    int size = arraySize(selectableFds);
-    int i;
-    for (i = 0; i < size; i++) {
-        SelectableFd* selectableFd = arrayGet(selectableFds, i);
-        maybeInvoke(selectableFd, selectableFd->onExcept,
-                &selector->exceptFds);
-        maybeInvoke(selectableFd, selectableFd->onReadable,
-                &selector->readFds);
-        maybeInvoke(selectableFd, selectableFd->onWritable,
-                &selector->writeFds);
-    }
-}
-
-void selectorLoop(Selector* selector) {
-    // Make sure we're not already looping.
-    if (selector->looping) {
-        LOG_ALWAYS_FATAL("Already looping.");
-    }
-    selector->looping = true;
-    
-    while (true) {
-        setInSelect(selector, true);
-        
-        prepareForSelect(selector);
-
-        ALOGD("Entering select().");
-        
-        // Select file descriptors.
-        int result = select(selector->maxFd + 1, &selector->readFds, 
-                &selector->writeFds, &selector->exceptFds, NULL);
-        
-        ALOGD("Exiting select().");
-        
-        setInSelect(selector, false);
-        
-        if (result == -1) {
-            // Abort on everything except EINTR.
-            if (errno == EINTR) {
-                ALOGI("select() interrupted.");    
-            } else {
-                LOG_ALWAYS_FATAL("select() error: %s", 
-                        strerror(errno));
-            }
-        } else if (result > 0) {
-            fireEvents(selector);
-        }
-    }
-}
diff --git a/libcutils/zygote.c b/libcutils/zygote.c
deleted file mode 100644
index 37236e8..0000000
--- a/libcutils/zygote.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "Zygote"
-
-#include <cutils/sockets.h>
-#include <cutils/zygote.h>
-#include <cutils/log.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#define ZYGOTE_SOCKET "zygote"
-
-#define ZYGOTE_RETRY_COUNT 1000
-#define ZYGOTE_RETRY_MILLIS 500
-
-static void replace_nl(char *str);
-
-/*
- * If sendStdio is non-zero, the current process's stdio file descriptors
- * will be sent and inherited by the spawned process.
- */
-static int send_request(int fd, int sendStdio, int argc, const char **argv)
-{
-#ifndef HAVE_ANDROID_OS
-    // not supported on simulator targets
-    //ALOGE("zygote_* not supported on simulator targets");
-    return -1;
-#else /* HAVE_ANDROID_OS */
-    uint32_t pid;
-    int i;
-    struct iovec ivs[2];
-    struct msghdr msg;
-    char argc_buffer[12];
-    const char *newline_string = "\n";
-    struct cmsghdr *cmsg;
-    char msgbuf[CMSG_SPACE(sizeof(int) * 3)];
-    int *cmsg_payload;
-    ssize_t ret;
-
-    memset(&msg, 0, sizeof(msg));
-    memset(&ivs, 0, sizeof(ivs));
-
-    // First line is arg count 
-    snprintf(argc_buffer, sizeof(argc_buffer), "%d\n", argc);
-
-    ivs[0].iov_base = argc_buffer;
-    ivs[0].iov_len = strlen(argc_buffer);
-
-    msg.msg_iov = ivs;
-    msg.msg_iovlen = 1;
-
-    if (sendStdio != 0) {
-        // Pass the file descriptors with the first write
-        msg.msg_control = msgbuf;
-        msg.msg_controllen = sizeof msgbuf;
-
-        cmsg = CMSG_FIRSTHDR(&msg);
-
-        cmsg->cmsg_len = CMSG_LEN(3 * sizeof(int));
-        cmsg->cmsg_level = SOL_SOCKET;
-        cmsg->cmsg_type = SCM_RIGHTS;
-
-        cmsg_payload = (int *)CMSG_DATA(cmsg);
-        cmsg_payload[0] = STDIN_FILENO;
-        cmsg_payload[1] = STDOUT_FILENO;
-        cmsg_payload[2] = STDERR_FILENO;
-    }
-
-    do {
-        ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
-    } while (ret < 0 && errno == EINTR);
-
-    if (ret < 0) {
-        return -1;
-    }
-
-    // Only send the fd's once
-    msg.msg_control = NULL;
-    msg.msg_controllen = 0;
-
-    // replace any newlines with spaces and send the args
-    for (i = 0; i < argc; i++) {
-        char *tofree = NULL;
-        const char *toprint;
-
-        toprint = argv[i];
-
-        if (strchr(toprint, '\n') != NULL) {
-            tofree = strdup(toprint);
-            toprint = tofree;
-            replace_nl(tofree);
-        }
-
-        ivs[0].iov_base = (char *)toprint;
-        ivs[0].iov_len = strlen(toprint);
-        ivs[1].iov_base = (char *)newline_string;
-        ivs[1].iov_len = 1;
-
-        msg.msg_iovlen = 2;
-
-        do {
-            ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
-        } while (ret < 0 && errno == EINTR);
-
-        if (tofree != NULL) {
-            free(tofree);
-        }
-
-        if (ret < 0) {
-            return -1;
-        }
-    }
-
-    // Read the pid, as a 4-byte network-order integer
-
-    ivs[0].iov_base = &pid;
-    ivs[0].iov_len = sizeof(pid);
-    msg.msg_iovlen = 1;
-
-    do {
-        do {
-            ret = recvmsg(fd, &msg, MSG_NOSIGNAL | MSG_WAITALL);
-        } while (ret < 0 && errno == EINTR);
-
-        if (ret < 0) {
-            return -1;
-        }
-
-        ivs[0].iov_len -= ret;
-        ivs[0].iov_base += ret;
-    } while (ivs[0].iov_len > 0);
-
-    pid = ntohl(pid);
-
-    return pid;
-#endif /* HAVE_ANDROID_OS */
-}
-
-/**
- * Spawns a new dalvik instance via the Zygote process. The non-zygote
- * arguments are passed to com.android.internal.os.RuntimeInit(). The
- * first non-option argument should be a class name in the system class path.
- *
- * The arg list  may start with zygote params such as --set-uid.
- *
- * If sendStdio is non-zero, the current process's stdio file descriptors
- * will be sent and inherited by the spawned process.
- *
- * The pid of the child process is returned, or -1 if an error was 
- * encountered.
- *
- * zygote_run_oneshot waits up to ZYGOTE_RETRY_COUNT * 
- * ZYGOTE_RETRY_MILLIS for the zygote socket to be available.
- */
-int zygote_run_oneshot(int sendStdio, int argc, const char **argv) 
-{
-    int fd = -1;
-    int err;
-    int i;
-    int retries;
-    int pid;
-    const char **newargv = argv;
-    const int newargc = argc;
-
-    for (retries = 0; (fd < 0) && (retries < ZYGOTE_RETRY_COUNT); retries++) {
-        if (retries > 0) { 
-            struct timespec ts;
-
-            memset(&ts, 0, sizeof(ts));
-            ts.tv_nsec = ZYGOTE_RETRY_MILLIS * 1000 * 1000;
-
-            do {
-                err = nanosleep (&ts, &ts);
-            } while (err < 0 && errno == EINTR);
-        }
-        fd = socket_local_client(ZYGOTE_SOCKET, AF_LOCAL, 
-                ANDROID_SOCKET_NAMESPACE_RESERVED);
-    }
-
-    if (fd < 0) {
-        return -1;
-    }
-
-    pid = send_request(fd, 0, newargc, newargv);
-
-    do {
-        err = close(fd);
-    } while (err < 0 && errno == EINTR);
-
-    return pid;
-}
-
-/**
- * Replaces all occurrances of newline with space.
- */
-static void replace_nl(char *str)
-{
-    for(; *str; str++) {
-        if (*str == '\n') {
-            *str = ' ';
-        }
-    }
-}
-
-
-
diff --git a/libion/ion_test.c b/libion/ion_test.c
index 0caaa2a..8179b57 100644
--- a/libion/ion_test.c
+++ b/libion/ion_test.c
@@ -13,7 +13,6 @@
 
 #include <ion/ion.h>
 #include <linux/ion.h>
-#include <linux/omap_ion.h>
 
 size_t len = 1024*1024, align = 0;
 int prot = PROT_READ | PROT_WRITE;
@@ -74,7 +73,7 @@
 	}
 	for (i = 0; i < len; i++)
 		if (ptr[i] != (unsigned char)i)
-			printf("%s failed wrote %d read %d from mapped "
+			printf("%s failed wrote %zu read %d from mapped "
 			       "memory\n", __func__, i, ptr[i]);
 	/* clean up properly */
 	ret = ion_free(fd, handle);
@@ -258,7 +257,7 @@
 			break;
 		}
 	}
-	printf("test %d, len %u, align %u, map_flags %d, prot %d, heap_mask %d,"
+	printf("test %d, len %zu, align %zu, map_flags %d, prot %d, heap_mask %d,"
 	       " alloc_flags %d\n", test, len, align, map_flags, prot,
 	       heap_mask, alloc_flags);
 	switch (test) {
diff --git a/liblinenoise/Android.mk b/liblinenoise/Android.mk
deleted file mode 100644
index b32a5f1..0000000
--- a/liblinenoise/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# Static library
-# ========================================================
-
-include $(CLEAR_VARS)
-LOCAL_MODULE:= liblinenoise
-LOCAL_SRC_FILES := linenoise.c
-
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/liblinenoise/NOTICE b/liblinenoise/NOTICE
deleted file mode 100644
index f61419e..0000000
--- a/liblinenoise/NOTICE
+++ /dev/null
@@ -1,28 +0,0 @@
-Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-  * Redistributions of source code must retain the above copyright notice,
-    this list of conditions and the following disclaimer.
-    
-  * 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.
-    
-  * Neither the name of Redis 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
\ No newline at end of file
diff --git a/liblinenoise/linenoise.c b/liblinenoise/linenoise.c
deleted file mode 100644
index 4f6775c..0000000
--- a/liblinenoise/linenoise.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/* linenoise.c -- guerrilla line editing library against the idea that a
- * line editing lib needs to be 20,000 lines of C code.
- *
- * You can find the latest source code at:
- * 
- *   http://github.com/antirez/linenoise
- *
- * Does a number of crazy assumptions that happen to be true in 99.9999% of
- * the 2010 UNIX computers around.
- *
- * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   * Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- *   * 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.
- *   * Neither the name of Redis 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
- *
- * References:
- * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
- * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
- *
- * Todo list:
- * - Switch to gets() if $TERM is something we can't support.
- * - Filter bogus Ctrl+<char> combinations.
- * - Win32 support
- *
- * Bloat:
- * - Completion?
- * - History search like Ctrl+r in readline?
- *
- * List of escape sequences used by this program, we do everything just
- * with three sequences. In order to be so cheap we may have some
- * flickering effect with some slow terminal, but the lesser sequences
- * the more compatible.
- *
- * CHA (Cursor Horizontal Absolute)
- *    Sequence: ESC [ n G
- *    Effect: moves cursor to column n
- *
- * EL (Erase Line)
- *    Sequence: ESC [ n K
- *    Effect: if n is 0 or missing, clear from cursor to end of line
- *    Effect: if n is 1, clear from beginning of line to cursor
- *    Effect: if n is 2, clear entire line
- *
- * CUF (CUrsor Forward)
- *    Sequence: ESC [ n C
- *    Effect: moves cursor forward of n chars
- * 
- */
-
-#include <termios.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#define LINENOISE_MAX_LINE 4096
-static char *unsupported_term[] = {"dumb","cons25",NULL};
-
-static struct termios orig_termios; /* in order to restore at exit */
-static int rawmode = 0; /* for atexit() function to check if restore is needed*/
-static int atexit_registered = 0; /* register atexit just 1 time */
-static int history_max_len = 100;
-static int history_len = 0;
-char **history = NULL;
-
-static void linenoiseAtExit(void);
-int linenoiseHistoryAdd(const char *line);
-
-static int isUnsupportedTerm(void) {
-    char *term = getenv("TERM");
-    int j;
-
-    if (term == NULL) return 0;
-    for (j = 0; unsupported_term[j]; j++)
-        if (!strcasecmp(term,unsupported_term[j])) return 1;
-    return 0;
-}
-
-static void freeHistory(void) {
-    if (history) {
-        int j;
-
-        for (j = 0; j < history_len; j++)
-            free(history[j]);
-        free(history);
-    }
-}
-
-static int enableRawMode(int fd) {
-    struct termios raw;
-
-    if (!isatty(STDIN_FILENO)) goto fatal;
-    if (!atexit_registered) {
-        atexit(linenoiseAtExit);
-        atexit_registered = 1;
-    }
-    if (tcgetattr(fd,&orig_termios) == -1) goto fatal;
-
-    raw = orig_termios;  /* modify the original mode */
-    /* input modes: no break, no CR to NL, no parity check, no strip char,
-     * no start/stop output control. */
-    raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
-    /* output modes - disable post processing */
-    raw.c_oflag &= ~(OPOST);
-    /* control modes - set 8 bit chars */
-    raw.c_cflag |= (CS8);
-    /* local modes - choing off, canonical off, no extended functions,
-     * no signal chars (^Z,^C) */
-    raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
-    /* control chars - set return condition: min number of bytes and timer.
-     * We want read to return every single byte, without timeout. */
-    raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
-
-    /* put terminal in raw mode */
-    if (tcsetattr(fd,TCSADRAIN,&raw) < 0) goto fatal;
-    rawmode = 1;
-    return 0;
-
-fatal:
-    errno = ENOTTY;
-    return -1;
-}
-
-static void disableRawMode(int fd) {
-    /* Don't even check the return value as it's too late. */
-    if (rawmode && tcsetattr(fd,TCSADRAIN,&orig_termios) != -1)
-        rawmode = 0;
-}
-
-/* At exit we'll try to fix the terminal to the initial conditions. */
-static void linenoiseAtExit(void) {
-    disableRawMode(STDIN_FILENO);
-    freeHistory();
-}
-
-static int getColumns(void) {
-    struct winsize ws;
-
-    if (ioctl(1, TIOCGWINSZ, &ws) == -1) return 4096;
-    if (ws.ws_col == 0) {
-        return 4096;
-    }
-    return ws.ws_col;
-}
-
-static int effectiveLen(const char* prompt) {
-    int col = 0;
-    char c;
-    // TODO: Handle escape sequences.
-    while ( (c = *prompt++) != 0 ) {
-        if (c == '\n') {
-            col = 0;
-        } else {
-            col++;
-        }
-    }
-    return col;
-}
-
-static void refreshLine(int fd, const char *prompt, char *buf, size_t len, size_t pos, size_t cols) {
-    char seq[64];
-    size_t plen = effectiveLen(prompt);
-    
-    while((plen+pos) >= cols) {
-        buf++;
-        len--;
-        pos--;
-    }
-    while (plen+len > cols) {
-        len--;
-    }
-
-    /* Cursor to left edge */
-    snprintf(seq,64,"\x1b[0G");
-    if (write(fd,seq,strlen(seq)) == -1) return;
-    /* Write the prompt and the current buffer content */
-    if (write(fd,prompt,strlen(prompt)) == -1) return;
-    if (write(fd,buf,len) == -1) return;
-    /* Erase to right */
-    snprintf(seq,64,"\x1b[0K");
-    if (write(fd,seq,strlen(seq)) == -1) return;
-    /* Move cursor to original position. */
-    snprintf(seq,64,"\x1b[0G\x1b[%dC", (int)(pos+plen));
-    if (write(fd,seq,strlen(seq)) == -1) return;
-}
-
-static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) {
-    size_t plen = strlen(prompt);
-    size_t pos = 0;
-    size_t len = 0;
-    size_t cols = getColumns();
-    int history_index = 0;
-
-    buf[0] = '\0';
-    buflen--; /* Make sure there is always space for the nulterm */
-
-    /* The latest history entry is always our current buffer, that
-     * initially is just an empty string. */
-    linenoiseHistoryAdd("");
-    
-    if (write(fd,prompt,plen) == -1) return -1;
-    while(1) {
-        char c;
-        int nread;
-        char seq[2];
-
-        nread = read(fd,&c,1);
-        if (nread <= 0) return len;
-        switch(c) {
-        case 10:    /* line feed. */
-        case 13:    /* enter */
-            history_len--;
-            return len;
-        case 4:     /* ctrl-d */
-            history_len--;
-            return (len == 0) ? -1 : (int)len;
-        case 3:     /* ctrl-c */
-            errno = EAGAIN;
-            return -1;
-        case 127:   /* backspace */
-        case 8:     /* ctrl-h */
-            if (pos > 0 && len > 0) {
-                memmove(buf+pos-1,buf+pos,len-pos);
-                pos--;
-                len--;
-                buf[len] = '\0';
-                refreshLine(fd,prompt,buf,len,pos,cols);
-            }
-            break;
-        case 20:    /* ctrl-t */
-            if (pos > 0 && pos < len) {
-                int aux = buf[pos-1];
-                buf[pos-1] = buf[pos];
-                buf[pos] = aux;
-                if (pos != len-1) pos++;
-                refreshLine(fd,prompt,buf,len,pos,cols);
-            }
-            break;
-        case 2:     /* ctrl-b */
-            goto left_arrow;
-        case 6:     /* ctrl-f */
-            goto right_arrow;
-        case 16:    /* ctrl-p */
-            seq[1] = 65;
-            goto up_down_arrow;
-        case 14:    /* ctrl-n */
-            seq[1] = 66;
-            goto up_down_arrow;
-            break;
-        case 27:    /* escape sequence */
-            if (read(fd,seq,2) == -1) break;
-            if (seq[0] == 91 && seq[1] == 68) {
-left_arrow:
-                /* left arrow */
-                if (pos > 0) {
-                    pos--;
-                    refreshLine(fd,prompt,buf,len,pos,cols);
-                }
-            } else if (seq[0] == 91 && seq[1] == 67) {
-right_arrow:
-                /* right arrow */
-                if (pos != len) {
-                    pos++;
-                    refreshLine(fd,prompt,buf,len,pos,cols);
-                }
-            } else if (seq[0] == 91 && (seq[1] == 65 || seq[1] == 66)) {
-up_down_arrow:
-                /* up and down arrow: history */
-                if (history_len > 1) {
-                    /* Update the current history entry before to
-                     * overwrite it with tne next one. */
-                    free(history[history_len-1-history_index]);
-                    history[history_len-1-history_index] = strdup(buf);
-                    /* Show the new entry */
-                    history_index += (seq[1] == 65) ? 1 : -1;
-                    if (history_index < 0) {
-                        history_index = 0;
-                        break;
-                    } else if (history_index >= history_len) {
-                        history_index = history_len-1;
-                        break;
-                    }
-                    strncpy(buf,history[history_len-1-history_index],buflen);
-                    buf[buflen] = '\0';
-                    len = pos = strlen(buf);
-                    refreshLine(fd,prompt,buf,len,pos,cols);
-                }
-            }
-            break;
-        default:
-            if (len < buflen) {
-                if (len == pos) {
-                    buf[pos] = c;
-                    pos++;
-                    len++;
-                    buf[len] = '\0';
-                    if (plen+len < cols) {
-                        /* Avoid a full update of the line in the
-                         * trivial case. */
-                        if (write(fd,&c,1) == -1) return -1;
-                    } else {
-                        refreshLine(fd,prompt,buf,len,pos,cols);
-                    }
-                } else {
-                    memmove(buf+pos+1,buf+pos,len-pos);
-                    buf[pos] = c;
-                    len++;
-                    pos++;
-                    buf[len] = '\0';
-                    refreshLine(fd,prompt,buf,len,pos,cols);
-                }
-            }
-            break;
-        case 21: /* Ctrl+u, delete the whole line. */
-            buf[0] = '\0';
-            pos = len = 0;
-            refreshLine(fd,prompt,buf,len,pos,cols);
-            break;
-        case 11: /* Ctrl+k, delete from current to end of line. */
-            buf[pos] = '\0';
-            len = pos;
-            refreshLine(fd,prompt,buf,len,pos,cols);
-            break;
-        case 1: /* Ctrl+a, go to the start of the line */
-            pos = 0;
-            refreshLine(fd,prompt,buf,len,pos,cols);
-            break;
-        case 5: /* ctrl+e, go to the end of the line */
-            pos = len;
-            refreshLine(fd,prompt,buf,len,pos,cols);
-            break;
-        }
-    }
-    return len;
-}
-
-static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
-    int fd = STDIN_FILENO;
-    int count;
-
-    if (buflen == 0) {
-        errno = EINVAL;
-        return -1;
-    }
-    if (!isatty(STDIN_FILENO)) {
-        if (fgets(buf, buflen, stdin) == NULL) return -1;
-        count = strlen(buf);
-        if (count && buf[count-1] == '\n') {
-            count--;
-            buf[count] = '\0';
-        }
-    } else {
-        if (enableRawMode(fd) == -1) return -1;
-        count = linenoisePrompt(fd, buf, buflen, prompt);        
-        disableRawMode(fd);
-    }
-    return count;
-}
-
-char *linenoise(const char *prompt) {
-    char buf[LINENOISE_MAX_LINE];
-    int count;
-
-    if (isUnsupportedTerm()) {
-        size_t len;
-
-        printf("%s",prompt);
-        fflush(stdout);
-        if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;
-        len = strlen(buf);
-        while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) {
-            len--;
-            buf[len] = '\0';
-        }
-        return strdup(buf);
-    } else {
-        count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);
-        if (count == -1) return NULL;
-        return strdup(buf);
-    }
-}
-
-/* Using a circular buffer is smarter, but a bit more complex to handle. */
-int linenoiseHistoryAdd(const char *line) {
-    char *linecopy;
-
-    if (history_max_len == 0) return 0;
-    if (history == 0) {
-        history = malloc(sizeof(char*)*history_max_len);
-        if (history == NULL) return 0;
-        memset(history,0,(sizeof(char*)*history_max_len));
-    }
-    linecopy = strdup(line);
-    if (!linecopy) return 0;
-    if (history_len == history_max_len) {
-        memmove(history,history+1,sizeof(char*)*(history_max_len-1));
-        history_len--;
-    }
-    history[history_len] = linecopy;
-    history_len++;
-    return 1;
-}
-
-int linenoiseHistorySetMaxLen(int len) {
-    char **new;
-
-    if (len < 1) return 0;
-    if (history) {
-        int tocopy = history_len;
-
-        new = malloc(sizeof(char*)*len);
-        if (new == NULL) return 0;
-        if (len < tocopy) tocopy = len;
-        memcpy(new,history+(history_max_len-tocopy), sizeof(char*)*tocopy);
-        free(history);
-        history = new;
-    }
-    history_max_len = len;
-    if (history_len > history_max_len)
-        history_len = history_max_len;
-    return 1;
-}
diff --git a/liblinenoise/linenoise.h b/liblinenoise/linenoise.h
deleted file mode 100644
index 57bf9d1..0000000
--- a/liblinenoise/linenoise.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* linenoise.h -- guerrilla line editing library against the idea that a
- * line editing lib needs to be 20,000 lines of C code.
- *
- * See linenoise.c for more information.
- *
- * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   * Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- *   * 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.
- *   * Neither the name of Redis 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
- */
-
-#ifndef __LINENOISE_H
-#define __LINENOISE_H
-
-char *linenoise(const char *prompt);
-int linenoiseHistoryAdd(const char *line);
-int linenoiseHistorySetMaxLen(int len);
-
-#endif /* __LINENOISE_H */
diff --git a/liblog/Android.mk b/liblog/Android.mk
index be5cec2..6bfb119 100644
--- a/liblog/Android.mk
+++ b/liblog/Android.mk
@@ -36,6 +36,9 @@
     liblog_sources += \
         logprint.c \
         event_tag_map.c
+else
+    liblog_sources += \
+        uio.c
 endif
 
 liblog_host_sources := $(liblog_sources) fake_log_device.c
diff --git a/liblog/event_tag_map.c b/liblog/event_tag_map.c
index e70754e..f3d1e2f 100644
--- a/liblog/event_tag_map.c
+++ b/liblog/event_tag_map.c
@@ -13,8 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "cutils/event_tag_map.h"
-#include "cutils/log.h"
+#include <log/event_tag_map.h>
+#include <log/log.h>
 
 #include <stdlib.h>
 #include <string.h>
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c
index df43299..5283619 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.c
@@ -19,7 +19,7 @@
  * passed on to the underlying (fake) log device.  When not in the
  * simulator, messages are printed to stderr.
  */
-#include "cutils/logd.h"
+#include <log/logd.h>
 
 #include <stdlib.h>
 #include <string.h>
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 3613d25..fff7cc4 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -27,9 +27,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
-#include <cutils/logger.h>
-#include <cutils/logd.h>
-#include <cutils/log.h>
+#include <log/logger.h>
+#include <log/logd.h>
+#include <log/log.h>
 
 #define LOG_BUF_SIZE	1024
 
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 6fac84b..508c825 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -26,8 +26,8 @@
 #include <assert.h>
 #include <arpa/inet.h>
 
-#include <cutils/logd.h>
-#include <cutils/logprint.h>
+#include <log/logd.h>
+#include <log/logprint.h>
 
 typedef struct FilterInfo_t {
     char *mTag;
diff --git a/libcutils/uio.c b/liblog/uio.c
similarity index 98%
rename from libcutils/uio.c
rename to liblog/uio.c
index baa8051..cfa4cb1 100644
--- a/libcutils/uio.c
+++ b/liblog/uio.c
@@ -16,7 +16,7 @@
 
 #ifndef HAVE_SYS_UIO_H
 
-#include <cutils/uio.h>
+#include <log/uio.h>
 #include <unistd.h>
 
 int  readv( int  fd, struct iovec*  vecs, int  count )
diff --git a/libmemtrack/Android.mk b/libmemtrack/Android.mk
new file mode 100644
index 0000000..a8fb3eb
--- /dev/null
+++ b/libmemtrack/Android.mk
@@ -0,0 +1,19 @@
+# Copyright 2013 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := memtrack.c
+LOCAL_MODULE := libmemtrack
+LOCAL_C_INCLUDES += hardware/libhardware/include
+LOCAL_SHARED_LIBRARIES := libhardware liblog
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := memtrack_test.c
+LOCAL_MODULE := memtrack_test
+LOCAL_C_INCLUDES := $(call include-path-for, libpagemap)
+LOCAL_SHARED_LIBRARIES := libmemtrack libpagemap
+LOCAL_CFLAGS := -Wall -Werror
+include $(BUILD_EXECUTABLE)
diff --git a/libmemtrack/memtrack.c b/libmemtrack/memtrack.c
new file mode 100644
index 0000000..9a656df
--- /dev/null
+++ b/libmemtrack/memtrack.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include <memtrack/memtrack.h>
+
+#define LOG_TAG "memtrack"
+
+#include <log/log.h>
+
+#include <hardware/memtrack.h>
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+static const memtrack_module_t *module;
+
+struct memtrack_proc {
+    pid_t pid;
+    struct memtrack_proc_type {
+        enum memtrack_type type;
+        size_t num_records;
+        size_t allocated_records;
+        struct memtrack_record *records;
+    } types[MEMTRACK_NUM_TYPES];
+};
+
+int memtrack_init(void)
+{
+    int err;
+
+    if (module) {
+        return 0;
+    }
+
+    err = hw_get_module(MEMTRACK_HARDWARE_MODULE_ID,
+            (hw_module_t const**)&module);
+    if (err) {
+        ALOGE("Couldn't load %s module (%s)", MEMTRACK_HARDWARE_MODULE_ID,
+                strerror(-err));
+        return err;
+    }
+
+    return module->init(module);
+}
+
+struct memtrack_proc *memtrack_proc_new(void)
+{
+    if (!module) {
+        return NULL;
+    }
+
+    return calloc(sizeof(struct memtrack_proc), 1);
+}
+
+void memtrack_proc_destroy(struct memtrack_proc *p)
+{
+    enum memtrack_type i;
+
+    if (p) {
+        for (i = 0; i < MEMTRACK_NUM_TYPES; i++) {
+            free(p->types[i].records);
+        }
+    }
+    free(p);
+}
+
+static int memtrack_proc_get_type(struct memtrack_proc_type *t,
+            pid_t pid, enum memtrack_type type)
+{
+    size_t num_records = t->num_records;
+    int ret;
+
+retry:
+    ret = module->getMemory(module, pid, type, t->records, &num_records);
+    if (ret) {
+        t->num_records = 0;
+        return ret;
+    }
+    if (num_records > t->allocated_records) {
+        /* Need more records than allocated */
+        free(t->records);
+        t->records = calloc(sizeof(*t->records), num_records);
+        if (!t->records) {
+            return -ENOMEM;
+        }
+        t->allocated_records = num_records;
+        goto retry;
+    }
+    t->num_records = num_records;
+
+    return 0;
+}
+
+/* TODO: sanity checks on return values from HALs:
+ *   make sure no records have invalid flags set
+ *    - unknown flags
+ *    - too many flags of a single category
+ *    - missing ACCOUNTED/UNACCOUNTED
+ *   make sure there are not overlapping SHARED and SHARED_PSS records
+ */
+static int memtrack_proc_sanity_check(struct memtrack_proc *p)
+{
+    (void)p;
+    return 0;
+}
+
+int memtrack_proc_get(struct memtrack_proc *p, pid_t pid)
+{
+    enum memtrack_type i;
+
+    if (!module) {
+        return -EINVAL;
+    }
+
+    if (!p) {
+        return -EINVAL;
+    }
+
+    p->pid = pid;
+    for (i = 0; i < MEMTRACK_NUM_TYPES; i++) {
+        memtrack_proc_get_type(&p->types[i], pid, i);
+    }
+
+    return memtrack_proc_sanity_check(p);
+}
+
+static ssize_t memtrack_proc_sum(struct memtrack_proc *p,
+            enum memtrack_type types[], size_t num_types,
+            unsigned int flags)
+{
+    ssize_t sum = 0;
+    size_t i;
+    size_t j;
+
+    for (i = 0; i < num_types; i++) {
+        enum memtrack_type type = types[i];
+        for (j = 0; j < p->types[type].num_records; j++) {
+            if ((p->types[type].records[j].flags & flags) == flags) {
+                sum += p->types[type].records[j].size_in_bytes;
+            }
+        }
+    }
+
+    return sum;
+}
+
+ssize_t memtrack_proc_graphics_total(struct memtrack_proc *p)
+{
+    enum memtrack_type types[] = { MEMTRACK_TYPE_GRAPHICS };
+    return memtrack_proc_sum(p, types, ARRAY_SIZE(types), 0);
+}
+
+ssize_t memtrack_proc_graphics_pss(struct memtrack_proc *p)
+{
+    enum memtrack_type types[] = { MEMTRACK_TYPE_GRAPHICS };
+    return memtrack_proc_sum(p, types, ARRAY_SIZE(types),
+                MEMTRACK_FLAG_SMAPS_UNACCOUNTED);
+}
+
+ssize_t memtrack_proc_gl_total(struct memtrack_proc *p)
+{
+    enum memtrack_type types[] = { MEMTRACK_TYPE_GL };
+    return memtrack_proc_sum(p, types, ARRAY_SIZE(types), 0);
+}
+
+ssize_t memtrack_proc_gl_pss(struct memtrack_proc *p)
+{
+    enum memtrack_type types[] = { MEMTRACK_TYPE_GL };
+    return memtrack_proc_sum(p, types, ARRAY_SIZE(types),
+                MEMTRACK_FLAG_SMAPS_UNACCOUNTED);
+}
+
+ssize_t memtrack_proc_other_total(struct memtrack_proc *p)
+{
+    enum memtrack_type types[] = { MEMTRACK_TYPE_MULTIMEDIA,
+                                        MEMTRACK_TYPE_CAMERA,
+                                        MEMTRACK_TYPE_OTHER };
+    return memtrack_proc_sum(p, types, ARRAY_SIZE(types), 0);
+}
+
+ssize_t memtrack_proc_other_pss(struct memtrack_proc *p)
+{
+    enum memtrack_type types[] = { MEMTRACK_TYPE_MULTIMEDIA,
+                                        MEMTRACK_TYPE_CAMERA,
+                                        MEMTRACK_TYPE_OTHER };
+    return memtrack_proc_sum(p, types, ARRAY_SIZE(types),
+                MEMTRACK_FLAG_SMAPS_UNACCOUNTED);
+}
diff --git a/libmemtrack/memtrack_test.c b/libmemtrack/memtrack_test.c
new file mode 100644
index 0000000..cd94bc5
--- /dev/null
+++ b/libmemtrack/memtrack_test.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <memtrack/memtrack.h>
+
+#include <pagemap/pagemap.h>
+
+#define DIV_ROUND_UP(x,y) (((x) + (y) - 1) / (y))
+
+static int getprocname(pid_t pid, char *buf, int len) {
+    char *filename;
+    FILE *f;
+    int rc = 0;
+    static const char* unknown_cmdline = "<unknown>";
+
+    if (len <= 0) {
+        return -1;
+    }
+
+    if (asprintf(&filename, "/proc/%zd/cmdline", pid) < 0) {
+        rc = 1;
+        goto exit;
+    }
+
+    f = fopen(filename, "r");
+    if (f == NULL) {
+        rc = 2;
+        goto releasefilename;
+    }
+
+    if (fgets(buf, len, f) == NULL) {
+        rc = 3;
+        goto closefile;
+    }
+
+closefile:
+    (void) fclose(f);
+releasefilename:
+    free(filename);
+exit:
+    if (rc != 0) {
+        /*
+         * The process went away before we could read its process name. Try
+         * to give the user "<unknown>" here, but otherwise they get to look
+         * at a blank.
+         */
+        if (strlcpy(buf, unknown_cmdline, (size_t)len) >= (size_t)len) {
+            rc = 4;
+        }
+    }
+
+    return rc;
+}
+
+int main(int argc, char *argv[])
+{
+    int ret;
+    pm_kernel_t *ker;
+    size_t num_procs;
+    pid_t *pids;
+    struct memtrack_proc *p;
+    size_t i;
+
+    (void)argc;
+    (void)argv;
+
+    ret = memtrack_init();
+    if (ret < 0) {
+        fprintf(stderr, "failed to initialize HAL: %s (%d)\n", strerror(-ret), ret);
+        exit(EXIT_FAILURE);
+    }
+
+    ret = pm_kernel_create(&ker);
+    if (ret) {
+        fprintf(stderr, "Error creating kernel interface -- "
+                        "does this kernel have pagemap?\n");
+        exit(EXIT_FAILURE);
+    }
+
+    ret = pm_kernel_pids(ker, &pids, &num_procs);
+    if (ret) {
+        fprintf(stderr, "Error listing processes.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    p = memtrack_proc_new();
+    if (ret) {
+        fprintf(stderr, "failed to create memtrack process handle\n");
+        exit(EXIT_FAILURE);
+    }
+
+    for (i = 0; i < num_procs; i++) {
+        pid_t pid = pids[i];
+        char cmdline[256];
+        size_t v1;
+        size_t v2;
+        size_t v3;
+        size_t v4;
+        size_t v5;
+        size_t v6;
+
+        getprocname(pid, cmdline, (int)sizeof(cmdline));
+
+        ret = memtrack_proc_get(p, pid);
+        if (ret) {
+            fprintf(stderr, "failed to get memory info for pid %d: %s (%d)\n",
+                    pid, strerror(-ret), ret);
+            continue;
+        }
+
+        v1 = DIV_ROUND_UP(memtrack_proc_graphics_total(p), 1024);
+        v2 = DIV_ROUND_UP(memtrack_proc_graphics_pss(p), 1024);
+        v3 = DIV_ROUND_UP(memtrack_proc_gl_total(p), 1024);
+        v4 = DIV_ROUND_UP(memtrack_proc_gl_pss(p), 1024);
+        v5 = DIV_ROUND_UP(memtrack_proc_other_total(p), 1024);
+        v6 = DIV_ROUND_UP(memtrack_proc_other_pss(p), 1024);
+
+        if (v1 | v2 | v3 | v4 | v5 | v6) {
+            printf("%5d %6zu %6zu %6zu %6zu %6zu %6zu %s\n", pid,
+                   v1, v2, v3, v4, v5, v6, cmdline);
+        }
+    }
+
+    memtrack_proc_destroy(p);
+
+    return 0;
+}
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index da00f74..e1df874 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -92,7 +92,8 @@
                      char *server,
                      uint32_t *lease,
                      char *vendorInfo,
-                     char *domain)
+                     char *domain,
+                     char *mtu)
 {
     char prop_name[PROPERTY_KEY_MAX];
     char prop_value[PROPERTY_VALUE_MAX];
@@ -158,6 +159,10 @@
             p2p_interface);
     property_get(prop_name, domain, NULL);
 
+    snprintf(prop_name, sizeof(prop_name), "%s.%s.mtu", DHCP_PROP_NAME_PREFIX,
+            p2p_interface);
+    property_get(prop_name, mtu, NULL);
+
     return 0;
 }
 
@@ -186,7 +191,8 @@
                     char *server,
                     uint32_t *lease,
                     char *vendorInfo,
-                    char *domain)
+                    char *domain,
+                    char *mtu)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char daemon_prop_name[PROPERTY_KEY_MAX];
@@ -238,7 +244,7 @@
     if (strcmp(prop_value, "ok") == 0) {
         char dns_prop_name[PROPERTY_KEY_MAX];
         if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
-                server, lease, vendorInfo, domain) == -1) {
+                server, lease, vendorInfo, domain, mtu) == -1) {
             return -1;
         }
         return 0;
@@ -329,7 +335,8 @@
                     char *server,
                     uint32_t *lease,
                     char *vendorInfo,
-                    char *domain)
+                    char *domain,
+                    char *mtu)
 {
     char result_prop_name[PROPERTY_KEY_MAX];
     char prop_value[PROPERTY_VALUE_MAX] = {'\0'};
@@ -366,7 +373,7 @@
     }
     if (strcmp(prop_value, "ok") == 0) {
         return fill_ip_info(interface, ipaddr, gateway, prefixLength, dns,
-                server, lease, vendorInfo, domain);
+                server, lease, vendorInfo, domain, mtu);
     } else {
         snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value);
         return -1;
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index eb33d06..4d004f6 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -50,6 +50,11 @@
 #define ALOGW printf
 #endif
 
+#ifdef HAVE_ANDROID_OS
+/* SIOCKILLADDR is an Android extension. */
+#define SIOCKILLADDR 0x8939
+#endif
+
 static int ifc_ctl_sock = -1;
 static int ifc_ctl_sock6 = -1;
 void printerr(char *fmt, ...);
diff --git a/libpixelflinger/buffer.cpp b/libpixelflinger/buffer.cpp
index af7356b..cbdab5a 100644
--- a/libpixelflinger/buffer.cpp
+++ b/libpixelflinger/buffer.cpp
@@ -93,7 +93,7 @@
         gen.width   = s.width;
         gen.height  = s.height;
         gen.stride  = s.stride;
-        gen.data    = int32_t(s.data);
+        gen.data    = uintptr_t(s.data);
     }
 }
 
diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index 607ed3c..92243da 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.cpp
+++ b/libpixelflinger/codeflinger/ARMAssembler.cpp
@@ -99,8 +99,8 @@
         if (comment >= 0) {
             printf("; %s\n", mComments.valueAt(comment));
         }
-        printf("%08x:    %08x    ", int(i), int(i[0]));
-        ::disassemble((u_int)i);
+        printf("%08x:    %08x    ", uintptr_t(i), int(i[0]));
+        ::disassemble((uintptr_t)i);
         i++;
     }
 }
@@ -186,7 +186,7 @@
 
 #if defined(WITH_LIB_HARDWARE)
     if (__builtin_expect(mQemuTracing, 0)) {
-        int err = qemu_add_mapping(int(base()), name);
+        int err = qemu_add_mapping(uintptr_t(base()), name);
         mQemuTracing = (err >= 0);
     }
 #endif
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index a5d28b2..96a71f3 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -1717,7 +1717,7 @@
             gen.width   = t.surface.width;
             gen.height  = t.surface.height;
             gen.stride  = t.surface.stride;
-            gen.data    = int32_t(t.surface.data);
+            gen.data    = uintptr_t(t.surface.data);
             gen.dsdx = ti.dsdx;
             gen.dtdx = ti.dtdx;
         }
@@ -1877,7 +1877,7 @@
             struct {
                 int32_t s, sq;
                 int32_t t, tq;
-            };
+            } sqtq;
             struct {
                 int32_t v, q;
             } st[2];
@@ -1916,10 +1916,10 @@
         int32_t t =   tmu.shade.it0 +
                      (tmu.shade.idtdy * ys) + (tmu.shade.idtdx * xs) +
                      ((tmu.shade.idtdx + tmu.shade.idtdy)>>1);
-        tc[i].s  = s;
-        tc[i].t  = t;
-        tc[i].sq = gglMulx(s, q0, iwscale);
-        tc[i].tq = gglMulx(t, q0, iwscale);
+        tc[i].sqtq.s  = s;
+        tc[i].sqtq.t  = t;
+        tc[i].sqtq.sq = gglMulx(s, q0, iwscale);
+        tc[i].sqtq.tq = gglMulx(t, q0, iwscale);
     }
 
     int32_t span = 0;
@@ -2125,7 +2125,7 @@
     int sR, sG, sB;
     uint32_t s, d;
 
-    if (ct==1 || uint32_t(dst)&2) {
+    if (ct==1 || uintptr_t(dst)&2) {
 last_one:
         s = GGL_RGBA_TO_HOST( *src++ );
         *dst++ = convertAbgr8888ToRgb565(s);
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 4beebb7..34f2016 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -23,6 +23,11 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+
 #include <linux/if.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter_ipv4/ipt_ULOG.h>
@@ -38,6 +43,9 @@
 const int NetlinkEvent::NlActionChange = 3;
 const int NetlinkEvent::NlActionLinkUp = 4;
 const int NetlinkEvent::NlActionLinkDown = 5;
+const int NetlinkEvent::NlActionAddressUpdated = 6;
+const int NetlinkEvent::NlActionAddressRemoved = 7;
+const int NetlinkEvent::NlActionRdnss = 8;
 
 NetlinkEvent::NetlinkEvent() {
     mAction = NlActionUnknown;
@@ -70,13 +78,209 @@
 }
 
 /*
- * Parse an binary message from a NETLINK_ROUTE netlink socket.
+ * Parse a RTM_NEWADDR or RTM_DELADDR message.
+ */
+bool NetlinkEvent::parseIfAddrMessage(int type, struct ifaddrmsg *ifaddr,
+                                      int rtasize) {
+    struct rtattr *rta;
+    struct ifa_cacheinfo *cacheinfo = NULL;
+    char addrstr[INET6_ADDRSTRLEN] = "";
+
+    // Sanity check.
+    if (type != RTM_NEWADDR && type != RTM_DELADDR) {
+        SLOGE("parseIfAddrMessage on incorrect message type 0x%x\n", type);
+        return false;
+    }
+
+    // For log messages.
+    const char *msgtype = (type == RTM_NEWADDR) ? "RTM_NEWADDR" : "RTM_DELADDR";
+
+    for (rta = IFA_RTA(ifaddr); RTA_OK(rta, rtasize);
+         rta = RTA_NEXT(rta, rtasize)) {
+        if (rta->rta_type == IFA_ADDRESS) {
+            // Only look at the first address, because we only support notifying
+            // one change at a time.
+            if (*addrstr != '\0') {
+                SLOGE("Multiple IFA_ADDRESSes in %s, ignoring\n", msgtype);
+                continue;
+            }
+
+            // Convert the IP address to a string.
+            if (ifaddr->ifa_family == AF_INET) {
+                struct in_addr *addr4 = (struct in_addr *) RTA_DATA(rta);
+                if (RTA_PAYLOAD(rta) < sizeof(*addr4)) {
+                    SLOGE("Short IPv4 address (%d bytes) in %s",
+                          RTA_PAYLOAD(rta), msgtype);
+                    continue;
+                }
+                inet_ntop(AF_INET, addr4, addrstr, sizeof(addrstr));
+            } else if (ifaddr->ifa_family == AF_INET6) {
+                struct in6_addr *addr6 = (struct in6_addr *) RTA_DATA(rta);
+                if (RTA_PAYLOAD(rta) < sizeof(*addr6)) {
+                    SLOGE("Short IPv6 address (%d bytes) in %s",
+                          RTA_PAYLOAD(rta), msgtype);
+                    continue;
+                }
+                inet_ntop(AF_INET6, addr6, addrstr, sizeof(addrstr));
+            } else {
+                SLOGE("Unknown address family %d\n", ifaddr->ifa_family);
+                continue;
+            }
+
+            // Find the interface name.
+            char ifname[IFNAMSIZ + 1];
+            if (!if_indextoname(ifaddr->ifa_index, ifname)) {
+                SLOGE("Unknown ifindex %d in %s", ifaddr->ifa_index, msgtype);
+                return false;
+            }
+
+            // Fill in interface information.
+            mAction = (type == RTM_NEWADDR) ? NlActionAddressUpdated :
+                                              NlActionAddressRemoved;
+            mSubsystem = strdup("net");
+            asprintf(&mParams[0], "ADDRESS=%s/%d", addrstr,
+                     ifaddr->ifa_prefixlen);
+            asprintf(&mParams[1], "INTERFACE=%s", ifname);
+            asprintf(&mParams[2], "FLAGS=%u", ifaddr->ifa_flags);
+            asprintf(&mParams[3], "SCOPE=%u", ifaddr->ifa_scope);
+        } else if (rta->rta_type == IFA_CACHEINFO) {
+            // Address lifetime information.
+            if (cacheinfo) {
+                // We only support one address.
+                SLOGE("Multiple IFA_CACHEINFOs in %s, ignoring\n", msgtype);
+                continue;
+            }
+
+            if (RTA_PAYLOAD(rta) < sizeof(*cacheinfo)) {
+                SLOGE("Short IFA_CACHEINFO (%d vs. %d bytes) in %s",
+                      RTA_PAYLOAD(rta), sizeof(cacheinfo), msgtype);
+                continue;
+            }
+
+            cacheinfo = (struct ifa_cacheinfo *) RTA_DATA(rta);
+            asprintf(&mParams[4], "PREFERRED=%u", cacheinfo->ifa_prefered);
+            asprintf(&mParams[5], "VALID=%u", cacheinfo->ifa_valid);
+            asprintf(&mParams[6], "CSTAMP=%u", cacheinfo->cstamp);
+            asprintf(&mParams[7], "TSTAMP=%u", cacheinfo->tstamp);
+        }
+    }
+
+    if (addrstr[0] == '\0') {
+        SLOGE("No IFA_ADDRESS in %s\n", msgtype);
+        return false;
+    }
+
+    return true;
+}
+
+/*
+<<<<<<< HEAD
+ * Parse a RTM_NEWNDUSEROPT message.
+ */
+bool NetlinkEvent::parseNdUserOptMessage(struct nduseroptmsg *msg, int len) {
+    // Check the length is valid.
+    if (msg->nduseropt_opts_len > len) {
+        SLOGE("RTM_NEWNDUSEROPT invalid length %d > %d\n",
+              msg->nduseropt_opts_len, len);
+        return false;
+    }
+    len = msg->nduseropt_opts_len;
+
+    // Check address family and packet type.
+    if (msg->nduseropt_family != AF_INET6) {
+        SLOGE("RTM_NEWNDUSEROPT message for unknown family %d\n",
+              msg->nduseropt_family);
+        return false;
+    }
+
+    if (msg->nduseropt_icmp_type != ND_ROUTER_ADVERT ||
+        msg->nduseropt_icmp_code != 0) {
+        SLOGE("RTM_NEWNDUSEROPT message for unknown ICMPv6 type/code %d/%d\n",
+              msg->nduseropt_icmp_type, msg->nduseropt_icmp_code);
+        return false;
+    }
+
+    // Find the interface name.
+    char ifname[IFNAMSIZ + 1];
+    if (!if_indextoname(msg->nduseropt_ifindex, ifname)) {
+        SLOGE("RTM_NEWNDUSEROPT on unknown ifindex %d\n",
+              msg->nduseropt_ifindex);
+        return false;
+    }
+
+    // The kernel sends a separate netlink message for each ND option in the RA.
+    // So only parse the first ND option in the message.
+    struct nd_opt_hdr *opthdr = (struct nd_opt_hdr *) (msg + 1);
+
+    // The length is in multiples of 8 octets.
+    uint16_t optlen = opthdr->nd_opt_len;
+    if (optlen * 8 > len) {
+        SLOGE("Invalid option length %d > %d for ND option %d\n",
+              optlen * 8, len, opthdr->nd_opt_type);
+        return false;
+    }
+
+    if (opthdr->nd_opt_type == ND_OPT_RDNSS) {
+        // DNS Servers (RFC 6106).
+        // Each address takes up 2*8 octets, and the header takes up 8 octets.
+        // So for a valid option with one or more addresses, optlen must be
+        // odd and greater than 1.
+        if ((optlen < 3) || !(optlen & 0x1)) {
+            SLOGE("Invalid optlen %d for RDNSS option\n", optlen);
+            return false;
+        }
+        int numaddrs = (optlen - 1) / 2;
+
+        // Find the lifetime.
+        struct nd_opt_rdnss *rndss_opt = (struct nd_opt_rdnss *) opthdr;
+        uint32_t lifetime = ntohl(rndss_opt->nd_opt_rdnss_lifetime);
+
+        // Construct "SERVERS=<comma-separated string of DNS addresses>".
+        // Reserve (INET6_ADDRSTRLEN + 1) chars for each address: all but the
+        // the last address are followed by ','; the last is followed by '\0'.
+        static const char kServerTag[] = "SERVERS=";
+        static const int kTagLength = sizeof(kServerTag) - 1;
+        int bufsize = kTagLength + numaddrs * (INET6_ADDRSTRLEN + 1);
+        char *buf = (char *) malloc(bufsize);
+        if (!buf) {
+            SLOGE("RDNSS option: out of memory\n");
+            return false;
+        }
+        strcpy(buf, kServerTag);
+        int pos = kTagLength;
+
+        struct in6_addr *addrs = (struct in6_addr *) (rndss_opt + 1);
+        for (int i = 0; i < numaddrs; i++) {
+            if (i > 0) {
+                buf[pos++] = ',';
+            }
+            inet_ntop(AF_INET6, addrs + i, buf + pos, bufsize - pos);
+            pos += strlen(buf + pos);
+        }
+        buf[pos] = '\0';
+
+        mAction = NlActionRdnss;
+        mSubsystem = strdup("net");
+        asprintf(&mParams[0], "INTERFACE=%s", ifname);
+        asprintf(&mParams[1], "LIFETIME=%u", lifetime);
+        mParams[2] = buf;
+    } else {
+        SLOGD("Unknown ND option type %d\n", opthdr->nd_opt_type);
+        return false;
+    }
+
+    return true;
+}
+
+/*
+ * Parse a binary message from a NETLINK_ROUTE netlink socket.
  */
 bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) {
-    size_t sz = size;
-    const struct nlmsghdr *nh = (struct nlmsghdr *) buffer;
+    const struct nlmsghdr *nh;
 
-    while (NLMSG_OK(nh, sz) && (nh->nlmsg_type != NLMSG_DONE)) {
+    for (nh = (struct nlmsghdr *) buffer;
+         NLMSG_OK(nh, (unsigned) size) && (nh->nlmsg_type != NLMSG_DONE);
+         nh = NLMSG_NEXT(nh, size)) {
 
         if (nh->nlmsg_type == RTM_NEWLINK) {
             int len = nh->nlmsg_len - sizeof(*nh);
@@ -127,10 +331,41 @@
             mSubsystem = strdup("qlog");
             mAction = NlActionChange;
 
+        } else if (nh->nlmsg_type == RTM_NEWADDR ||
+                   nh->nlmsg_type == RTM_DELADDR) {
+            int len = nh->nlmsg_len - sizeof(*nh);
+            struct ifaddrmsg *ifa;
+
+            if (sizeof(*ifa) > (size_t) len) {
+                SLOGE("Got a short RTM_xxxADDR message\n");
+                continue;
+            }
+
+            ifa = (ifaddrmsg *)NLMSG_DATA(nh);
+            size_t rtasize = IFA_PAYLOAD(nh);
+            if (!parseIfAddrMessage(nh->nlmsg_type, ifa, rtasize)) {
+                continue;
+            }
+
+        } else if (nh->nlmsg_type == RTM_NEWNDUSEROPT) {
+            int len = nh->nlmsg_len - sizeof(*nh);
+            struct nduseroptmsg *ndmsg = (struct nduseroptmsg *) NLMSG_DATA(nh);
+
+            if (sizeof(*ndmsg) > (size_t) len) {
+                SLOGE("Got a short RTM_NEWNDUSEROPT message\n");
+                continue;
+            }
+
+            size_t optsize = NLMSG_PAYLOAD(nh, sizeof(*ndmsg));
+            if (!parseNdUserOptMessage(ndmsg, optsize)) {
+                continue;
+            }
+
+
         } else {
-                SLOGD("Unexpected netlink message. type=0x%x\n", nh->nlmsg_type);
+                SLOGD("Unexpected netlink message. type=0x%x\n",
+                      nh->nlmsg_type);
         }
-        nh = NLMSG_NEXT(nh, size);
     }
 
     return true;
diff --git a/libutils/Android.mk b/libutils/Android.mk
new file mode 100644
index 0000000..720443e
--- /dev/null
+++ b/libutils/Android.mk
@@ -0,0 +1,146 @@
+# Copyright (C) 2008 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+# libutils is a little unique: It's built twice, once for the host
+# and once for the device.
+
+commonSources:= \
+	BasicHashtable.cpp \
+	BlobCache.cpp \
+	CallStack.cpp \
+	FileMap.cpp \
+	JenkinsHash.cpp \
+	LinearAllocator.cpp \
+	LinearTransform.cpp \
+	Log.cpp \
+	Printer.cpp \
+	ProcessCallStack.cpp \
+	PropertyMap.cpp \
+	RefBase.cpp \
+	SharedBuffer.cpp \
+	Static.cpp \
+	StopWatch.cpp \
+	String8.cpp \
+	String16.cpp \
+	SystemClock.cpp \
+	Threads.cpp \
+	Timers.cpp \
+	Tokenizer.cpp \
+	Unicode.cpp \
+	VectorImpl.cpp \
+	misc.cpp
+
+host_commonCflags := -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)
+
+ifeq ($(HOST_OS),windows)
+ifeq ($(strip $(USE_CYGWIN),),)
+# Under MinGW, ctype.h doesn't need multi-byte support
+host_commonCflags += -DMB_CUR_MAX=1
+endif
+endif
+
+host_commonLdlibs :=
+
+ifeq ($(TARGET_OS),linux)
+host_commonLdlibs += -lrt -ldl
+endif
+
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= $(commonSources)
+ifeq ($(HOST_OS), linux)
+LOCAL_SRC_FILES += Looper.cpp
+endif
+LOCAL_MODULE:= libutils
+LOCAL_STATIC_LIBRARIES := liblog
+LOCAL_CFLAGS += $(host_commonCflags)
+LOCAL_LDLIBS += $(host_commonLdlibs)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+
+# For the host, 64-bit
+# =====================================================
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= $(commonSources)
+ifeq ($(HOST_OS), linux)
+LOCAL_SRC_FILES += Looper.cpp
+endif
+LOCAL_MODULE:= lib64utils
+LOCAL_STATIC_LIBRARIES := liblog
+LOCAL_CFLAGS += $(host_commonCflags) -m64
+LOCAL_LDLIBS += $(host_commonLdlibs)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+
+# For the device, static
+# =====================================================
+include $(CLEAR_VARS)
+
+
+# we have the common sources, plus some device-specific stuff
+LOCAL_SRC_FILES:= \
+	$(commonSources) \
+	Looper.cpp \
+	Trace.cpp
+
+ifeq ($(TARGET_OS),linux)
+LOCAL_LDLIBS += -lrt -ldl
+endif
+
+ifeq ($(TARGET_ARCH),mips)
+LOCAL_CFLAGS += -DALIGN_DOUBLE
+endif
+
+LOCAL_C_INCLUDES += \
+		bionic/libc/private \
+		external/zlib
+
+LOCAL_LDLIBS += -lpthread
+
+LOCAL_STATIC_LIBRARIES := \
+	libcutils
+
+LOCAL_SHARED_LIBRARIES := \
+        libcorkscrew \
+        liblog \
+        libdl
+
+LOCAL_MODULE:= libutils
+include $(BUILD_STATIC_LIBRARY)
+
+# For the device, shared
+# =====================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE:= libutils
+LOCAL_WHOLE_STATIC_LIBRARIES := libutils
+LOCAL_SHARED_LIBRARIES := \
+        liblog \
+        libcutils \
+        libdl \
+        libcorkscrew
+
+include $(BUILD_SHARED_LIBRARY)
+
+# Include subdirectory makefiles
+# ============================================================
+
+# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
+# team really wants is to build the stuff defined by this makefile.
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/libutils/BasicHashtable.cpp b/libutils/BasicHashtable.cpp
new file mode 100644
index 0000000..491d9e9
--- /dev/null
+++ b/libutils/BasicHashtable.cpp
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define LOG_TAG "BasicHashtable"
+
+#include <math.h>
+
+#include <utils/Log.h>
+#include <utils/BasicHashtable.h>
+#include <utils/misc.h>
+
+namespace android {
+
+BasicHashtableImpl::BasicHashtableImpl(size_t entrySize, bool hasTrivialDestructor,
+        size_t minimumInitialCapacity, float loadFactor) :
+        mBucketSize(entrySize + sizeof(Bucket)), mHasTrivialDestructor(hasTrivialDestructor),
+        mLoadFactor(loadFactor), mSize(0),
+        mFilledBuckets(0), mBuckets(NULL) {
+    determineCapacity(minimumInitialCapacity, mLoadFactor, &mBucketCount, &mCapacity);
+}
+
+BasicHashtableImpl::BasicHashtableImpl(const BasicHashtableImpl& other) :
+        mBucketSize(other.mBucketSize), mHasTrivialDestructor(other.mHasTrivialDestructor),
+        mCapacity(other.mCapacity), mLoadFactor(other.mLoadFactor),
+        mSize(other.mSize), mFilledBuckets(other.mFilledBuckets),
+        mBucketCount(other.mBucketCount), mBuckets(other.mBuckets) {
+    if (mBuckets) {
+        SharedBuffer::bufferFromData(mBuckets)->acquire();
+    }
+}
+
+BasicHashtableImpl::~BasicHashtableImpl()
+{
+}
+
+void BasicHashtableImpl::dispose() {
+    if (mBuckets) {
+        releaseBuckets(mBuckets, mBucketCount);
+    }
+}
+
+void BasicHashtableImpl::clone() {
+    if (mBuckets) {
+        void* newBuckets = allocateBuckets(mBucketCount);
+        copyBuckets(mBuckets, newBuckets, mBucketCount);
+        releaseBuckets(mBuckets, mBucketCount);
+        mBuckets = newBuckets;
+    }
+}
+
+void BasicHashtableImpl::setTo(const BasicHashtableImpl& other) {
+    if (mBuckets) {
+        releaseBuckets(mBuckets, mBucketCount);
+    }
+
+    mCapacity = other.mCapacity;
+    mLoadFactor = other.mLoadFactor;
+    mSize = other.mSize;
+    mFilledBuckets = other.mFilledBuckets;
+    mBucketCount = other.mBucketCount;
+    mBuckets = other.mBuckets;
+
+    if (mBuckets) {
+        SharedBuffer::bufferFromData(mBuckets)->acquire();
+    }
+}
+
+void BasicHashtableImpl::clear() {
+    if (mBuckets) {
+        if (mFilledBuckets) {
+            SharedBuffer* sb = SharedBuffer::bufferFromData(mBuckets);
+            if (sb->onlyOwner()) {
+                destroyBuckets(mBuckets, mBucketCount);
+                for (size_t i = 0; i < mBucketCount; i++) {
+                    Bucket& bucket = bucketAt(mBuckets, i);
+                    bucket.cookie = 0;
+                }
+            } else {
+                releaseBuckets(mBuckets, mBucketCount);
+                mBuckets = NULL;
+            }
+            mFilledBuckets = 0;
+        }
+        mSize = 0;
+    }
+}
+
+ssize_t BasicHashtableImpl::next(ssize_t index) const {
+    if (mSize) {
+        while (size_t(++index) < mBucketCount) {
+            const Bucket& bucket = bucketAt(mBuckets, index);
+            if (bucket.cookie & Bucket::PRESENT) {
+                return index;
+            }
+        }
+    }
+    return -1;
+}
+
+ssize_t BasicHashtableImpl::find(ssize_t index, hash_t hash,
+        const void* __restrict__ key) const {
+    if (!mSize) {
+        return -1;
+    }
+
+    hash = trimHash(hash);
+    if (index < 0) {
+        index = chainStart(hash, mBucketCount);
+
+        const Bucket& bucket = bucketAt(mBuckets, size_t(index));
+        if (bucket.cookie & Bucket::PRESENT) {
+            if (compareBucketKey(bucket, key)) {
+                return index;
+            }
+        } else {
+            if (!(bucket.cookie & Bucket::COLLISION)) {
+                return -1;
+            }
+        }
+    }
+
+    size_t inc = chainIncrement(hash, mBucketCount);
+    for (;;) {
+        index = chainSeek(index, inc, mBucketCount);
+
+        const Bucket& bucket = bucketAt(mBuckets, size_t(index));
+        if (bucket.cookie & Bucket::PRESENT) {
+            if ((bucket.cookie & Bucket::HASH_MASK) == hash
+                    && compareBucketKey(bucket, key)) {
+                return index;
+            }
+        }
+        if (!(bucket.cookie & Bucket::COLLISION)) {
+            return -1;
+        }
+    }
+}
+
+size_t BasicHashtableImpl::add(hash_t hash, const void* entry) {
+    if (!mBuckets) {
+        mBuckets = allocateBuckets(mBucketCount);
+    } else {
+        edit();
+    }
+
+    hash = trimHash(hash);
+    for (;;) {
+        size_t index = chainStart(hash, mBucketCount);
+        Bucket* bucket = &bucketAt(mBuckets, size_t(index));
+        if (bucket->cookie & Bucket::PRESENT) {
+            size_t inc = chainIncrement(hash, mBucketCount);
+            do {
+                bucket->cookie |= Bucket::COLLISION;
+                index = chainSeek(index, inc, mBucketCount);
+                bucket = &bucketAt(mBuckets, size_t(index));
+            } while (bucket->cookie & Bucket::PRESENT);
+        }
+
+        uint32_t collision = bucket->cookie & Bucket::COLLISION;
+        if (!collision) {
+            if (mFilledBuckets >= mCapacity) {
+                rehash(mCapacity * 2, mLoadFactor);
+                continue;
+            }
+            mFilledBuckets += 1;
+        }
+
+        bucket->cookie = collision | Bucket::PRESENT | hash;
+        mSize += 1;
+        initializeBucketEntry(*bucket, entry);
+        return index;
+    }
+}
+
+void BasicHashtableImpl::removeAt(size_t index) {
+    edit();
+
+    Bucket& bucket = bucketAt(mBuckets, index);
+    bucket.cookie &= ~Bucket::PRESENT;
+    if (!(bucket.cookie & Bucket::COLLISION)) {
+        mFilledBuckets -= 1;
+    }
+    mSize -= 1;
+    if (!mHasTrivialDestructor) {
+        destroyBucketEntry(bucket);
+    }
+}
+
+void BasicHashtableImpl::rehash(size_t minimumCapacity, float loadFactor) {
+    if (minimumCapacity < mSize) {
+        minimumCapacity = mSize;
+    }
+    size_t newBucketCount, newCapacity;
+    determineCapacity(minimumCapacity, loadFactor, &newBucketCount, &newCapacity);
+
+    if (newBucketCount != mBucketCount || newCapacity != mCapacity) {
+        if (mBuckets) {
+            void* newBuckets;
+            if (mSize) {
+                newBuckets = allocateBuckets(newBucketCount);
+                for (size_t i = 0; i < mBucketCount; i++) {
+                    const Bucket& fromBucket = bucketAt(mBuckets, i);
+                    if (fromBucket.cookie & Bucket::PRESENT) {
+                        hash_t hash = fromBucket.cookie & Bucket::HASH_MASK;
+                        size_t index = chainStart(hash, newBucketCount);
+                        Bucket* toBucket = &bucketAt(newBuckets, size_t(index));
+                        if (toBucket->cookie & Bucket::PRESENT) {
+                            size_t inc = chainIncrement(hash, newBucketCount);
+                            do {
+                                toBucket->cookie |= Bucket::COLLISION;
+                                index = chainSeek(index, inc, newBucketCount);
+                                toBucket = &bucketAt(newBuckets, size_t(index));
+                            } while (toBucket->cookie & Bucket::PRESENT);
+                        }
+                        toBucket->cookie = Bucket::PRESENT | hash;
+                        initializeBucketEntry(*toBucket, fromBucket.entry);
+                    }
+                }
+            } else {
+                newBuckets = NULL;
+            }
+            releaseBuckets(mBuckets, mBucketCount);
+            mBuckets = newBuckets;
+            mFilledBuckets = mSize;
+        }
+        mBucketCount = newBucketCount;
+        mCapacity = newCapacity;
+    }
+    mLoadFactor = loadFactor;
+}
+
+void* BasicHashtableImpl::allocateBuckets(size_t count) const {
+    size_t bytes = count * mBucketSize;
+    SharedBuffer* sb = SharedBuffer::alloc(bytes);
+    LOG_ALWAYS_FATAL_IF(!sb, "Could not allocate %u bytes for hashtable with %u buckets.",
+            uint32_t(bytes), uint32_t(count));
+    void* buckets = sb->data();
+    for (size_t i = 0; i < count; i++) {
+        Bucket& bucket = bucketAt(buckets, i);
+        bucket.cookie = 0;
+    }
+    return buckets;
+}
+
+void BasicHashtableImpl::releaseBuckets(void* __restrict__ buckets, size_t count) const {
+    SharedBuffer* sb = SharedBuffer::bufferFromData(buckets);
+    if (sb->release(SharedBuffer::eKeepStorage) == 1) {
+        destroyBuckets(buckets, count);
+        SharedBuffer::dealloc(sb);
+    }
+}
+
+void BasicHashtableImpl::destroyBuckets(void* __restrict__ buckets, size_t count) const {
+    if (!mHasTrivialDestructor) {
+        for (size_t i = 0; i < count; i++) {
+            Bucket& bucket = bucketAt(buckets, i);
+            if (bucket.cookie & Bucket::PRESENT) {
+                destroyBucketEntry(bucket);
+            }
+        }
+    }
+}
+
+void BasicHashtableImpl::copyBuckets(const void* __restrict__ fromBuckets,
+        void* __restrict__ toBuckets, size_t count) const {
+    for (size_t i = 0; i < count; i++) {
+        const Bucket& fromBucket = bucketAt(fromBuckets, i);
+        Bucket& toBucket = bucketAt(toBuckets, i);
+        toBucket.cookie = fromBucket.cookie;
+        if (fromBucket.cookie & Bucket::PRESENT) {
+            initializeBucketEntry(toBucket, fromBucket.entry);
+        }
+    }
+}
+
+// Table of 31-bit primes where each prime is no less than twice as large
+// as the previous one.  Generated by "primes.py".
+static size_t PRIMES[] = {
+    5,
+    11,
+    23,
+    47,
+    97,
+    197,
+    397,
+    797,
+    1597,
+    3203,
+    6421,
+    12853,
+    25717,
+    51437,
+    102877,
+    205759,
+    411527,
+    823117,
+    1646237,
+    3292489,
+    6584983,
+    13169977,
+    26339969,
+    52679969,
+    105359939,
+    210719881,
+    421439783,
+    842879579,
+    1685759167,
+    0,
+};
+
+void BasicHashtableImpl::determineCapacity(size_t minimumCapacity, float loadFactor,
+        size_t* __restrict__ outBucketCount, size_t* __restrict__ outCapacity) {
+    LOG_ALWAYS_FATAL_IF(loadFactor <= 0.0f || loadFactor > 1.0f,
+            "Invalid load factor %0.3f.  Must be in the range (0, 1].", loadFactor);
+
+    size_t count = ceilf(minimumCapacity / loadFactor) + 1;
+    size_t i = 0;
+    while (count > PRIMES[i] && i < NELEM(PRIMES)) {
+        i++;
+    }
+    count = PRIMES[i];
+    LOG_ALWAYS_FATAL_IF(!count, "Could not determine required number of buckets for "
+            "hashtable with minimum capacity %u and load factor %0.3f.",
+            uint32_t(minimumCapacity), loadFactor);
+    *outBucketCount = count;
+    *outCapacity = ceilf((count - 1) * loadFactor);
+}
+
+}; // namespace android
diff --git a/libutils/BlobCache.cpp b/libutils/BlobCache.cpp
new file mode 100644
index 0000000..0fb1d8e
--- /dev/null
+++ b/libutils/BlobCache.cpp
@@ -0,0 +1,362 @@
+/*
+ ** Copyright 2011, 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.
+ */
+
+#define LOG_TAG "BlobCache"
+//#define LOG_NDEBUG 0
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <utils/BlobCache.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+namespace android {
+
+// BlobCache::Header::mMagicNumber value
+static const uint32_t blobCacheMagic = '_Bb$';
+
+// BlobCache::Header::mBlobCacheVersion value
+static const uint32_t blobCacheVersion = 1;
+
+// BlobCache::Header::mDeviceVersion value
+static const uint32_t blobCacheDeviceVersion = 1;
+
+BlobCache::BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize):
+        mMaxKeySize(maxKeySize),
+        mMaxValueSize(maxValueSize),
+        mMaxTotalSize(maxTotalSize),
+        mTotalSize(0) {
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+#ifdef _WIN32
+    srand(now);
+#else
+    mRandState[0] = (now >> 0) & 0xFFFF;
+    mRandState[1] = (now >> 16) & 0xFFFF;
+    mRandState[2] = (now >> 32) & 0xFFFF;
+#endif
+    ALOGV("initializing random seed using %lld", now);
+}
+
+void BlobCache::set(const void* key, size_t keySize, const void* value,
+        size_t valueSize) {
+    if (mMaxKeySize < keySize) {
+        ALOGV("set: not caching because the key is too large: %d (limit: %d)",
+                keySize, mMaxKeySize);
+        return;
+    }
+    if (mMaxValueSize < valueSize) {
+        ALOGV("set: not caching because the value is too large: %d (limit: %d)",
+                valueSize, mMaxValueSize);
+        return;
+    }
+    if (mMaxTotalSize < keySize + valueSize) {
+        ALOGV("set: not caching because the combined key/value size is too "
+                "large: %d (limit: %d)", keySize + valueSize, mMaxTotalSize);
+        return;
+    }
+    if (keySize == 0) {
+        ALOGW("set: not caching because keySize is 0");
+        return;
+    }
+    if (valueSize <= 0) {
+        ALOGW("set: not caching because valueSize is 0");
+        return;
+    }
+
+    sp<Blob> dummyKey(new Blob(key, keySize, false));
+    CacheEntry dummyEntry(dummyKey, NULL);
+
+    while (true) {
+        ssize_t index = mCacheEntries.indexOf(dummyEntry);
+        if (index < 0) {
+            // Create a new cache entry.
+            sp<Blob> keyBlob(new Blob(key, keySize, true));
+            sp<Blob> valueBlob(new Blob(value, valueSize, true));
+            size_t newTotalSize = mTotalSize + keySize + valueSize;
+            if (mMaxTotalSize < newTotalSize) {
+                if (isCleanable()) {
+                    // Clean the cache and try again.
+                    clean();
+                    continue;
+                } else {
+                    ALOGV("set: not caching new key/value pair because the "
+                            "total cache size limit would be exceeded: %d "
+                            "(limit: %d)",
+                            keySize + valueSize, mMaxTotalSize);
+                    break;
+                }
+            }
+            mCacheEntries.add(CacheEntry(keyBlob, valueBlob));
+            mTotalSize = newTotalSize;
+            ALOGV("set: created new cache entry with %d byte key and %d byte value",
+                    keySize, valueSize);
+        } else {
+            // Update the existing cache entry.
+            sp<Blob> valueBlob(new Blob(value, valueSize, true));
+            sp<Blob> oldValueBlob(mCacheEntries[index].getValue());
+            size_t newTotalSize = mTotalSize + valueSize - oldValueBlob->getSize();
+            if (mMaxTotalSize < newTotalSize) {
+                if (isCleanable()) {
+                    // Clean the cache and try again.
+                    clean();
+                    continue;
+                } else {
+                    ALOGV("set: not caching new value because the total cache "
+                            "size limit would be exceeded: %d (limit: %d)",
+                            keySize + valueSize, mMaxTotalSize);
+                    break;
+                }
+            }
+            mCacheEntries.editItemAt(index).setValue(valueBlob);
+            mTotalSize = newTotalSize;
+            ALOGV("set: updated existing cache entry with %d byte key and %d byte "
+                    "value", keySize, valueSize);
+        }
+        break;
+    }
+}
+
+size_t BlobCache::get(const void* key, size_t keySize, void* value,
+        size_t valueSize) {
+    if (mMaxKeySize < keySize) {
+        ALOGV("get: not searching because the key is too large: %d (limit %d)",
+                keySize, mMaxKeySize);
+        return 0;
+    }
+    sp<Blob> dummyKey(new Blob(key, keySize, false));
+    CacheEntry dummyEntry(dummyKey, NULL);
+    ssize_t index = mCacheEntries.indexOf(dummyEntry);
+    if (index < 0) {
+        ALOGV("get: no cache entry found for key of size %d", keySize);
+        return 0;
+    }
+
+    // The key was found. Return the value if the caller's buffer is large
+    // enough.
+    sp<Blob> valueBlob(mCacheEntries[index].getValue());
+    size_t valueBlobSize = valueBlob->getSize();
+    if (valueBlobSize <= valueSize) {
+        ALOGV("get: copying %d bytes to caller's buffer", valueBlobSize);
+        memcpy(value, valueBlob->getData(), valueBlobSize);
+    } else {
+        ALOGV("get: caller's buffer is too small for value: %d (needs %d)",
+                valueSize, valueBlobSize);
+    }
+    return valueBlobSize;
+}
+
+static inline size_t align4(size_t size) {
+    return (size + 3) & ~3;
+}
+
+size_t BlobCache::getFlattenedSize() const {
+    size_t size = sizeof(Header);
+    for (size_t i = 0; i < mCacheEntries.size(); i++) {
+        const CacheEntry& e(mCacheEntries[i]);
+        sp<Blob> keyBlob = e.getKey();
+        sp<Blob> valueBlob = e.getValue();
+        size = align4(size);
+        size += sizeof(EntryHeader) + keyBlob->getSize() +
+                valueBlob->getSize();
+    }
+    return size;
+}
+
+status_t BlobCache::flatten(void* buffer, size_t size) const {
+    // Write the cache header
+    if (size < sizeof(Header)) {
+        ALOGE("flatten: not enough room for cache header");
+        return BAD_VALUE;
+    }
+    Header* header = reinterpret_cast<Header*>(buffer);
+    header->mMagicNumber = blobCacheMagic;
+    header->mBlobCacheVersion = blobCacheVersion;
+    header->mDeviceVersion = blobCacheDeviceVersion;
+    header->mNumEntries = mCacheEntries.size();
+
+    // Write cache entries
+    uint8_t* byteBuffer = reinterpret_cast<uint8_t*>(buffer);
+    off_t byteOffset = align4(sizeof(Header));
+    for (size_t i = 0; i < mCacheEntries.size(); i++) {
+        const CacheEntry& e(mCacheEntries[i]);
+        sp<Blob> keyBlob = e.getKey();
+        sp<Blob> valueBlob = e.getValue();
+        size_t keySize = keyBlob->getSize();
+        size_t valueSize = valueBlob->getSize();
+
+        size_t entrySize = sizeof(EntryHeader) + keySize + valueSize;
+        if (byteOffset + entrySize > size) {
+            ALOGE("flatten: not enough room for cache entries");
+            return BAD_VALUE;
+        }
+
+        EntryHeader* eheader = reinterpret_cast<EntryHeader*>(
+            &byteBuffer[byteOffset]);
+        eheader->mKeySize = keySize;
+        eheader->mValueSize = valueSize;
+
+        memcpy(eheader->mData, keyBlob->getData(), keySize);
+        memcpy(eheader->mData + keySize, valueBlob->getData(), valueSize);
+
+        byteOffset += align4(entrySize);
+    }
+
+    return OK;
+}
+
+status_t BlobCache::unflatten(void const* buffer, size_t size) {
+    // All errors should result in the BlobCache being in an empty state.
+    mCacheEntries.clear();
+
+    // Read the cache header
+    if (size < sizeof(Header)) {
+        ALOGE("unflatten: not enough room for cache header");
+        return BAD_VALUE;
+    }
+    const Header* header = reinterpret_cast<const Header*>(buffer);
+    if (header->mMagicNumber != blobCacheMagic) {
+        ALOGE("unflatten: bad magic number: %d", header->mMagicNumber);
+        return BAD_VALUE;
+    }
+    if (header->mBlobCacheVersion != blobCacheVersion ||
+            header->mDeviceVersion != blobCacheDeviceVersion) {
+        // We treat version mismatches as an empty cache.
+        return OK;
+    }
+
+    // Read cache entries
+    const uint8_t* byteBuffer = reinterpret_cast<const uint8_t*>(buffer);
+    off_t byteOffset = align4(sizeof(Header));
+    size_t numEntries = header->mNumEntries;
+    for (size_t i = 0; i < numEntries; i++) {
+        if (byteOffset + sizeof(EntryHeader) > size) {
+            mCacheEntries.clear();
+            ALOGE("unflatten: not enough room for cache entry headers");
+            return BAD_VALUE;
+        }
+
+        const EntryHeader* eheader = reinterpret_cast<const EntryHeader*>(
+                &byteBuffer[byteOffset]);
+        size_t keySize = eheader->mKeySize;
+        size_t valueSize = eheader->mValueSize;
+        size_t entrySize = sizeof(EntryHeader) + keySize + valueSize;
+
+        if (byteOffset + entrySize > size) {
+            mCacheEntries.clear();
+            ALOGE("unflatten: not enough room for cache entry headers");
+            return BAD_VALUE;
+        }
+
+        const uint8_t* data = eheader->mData;
+        set(data, keySize, data + keySize, valueSize);
+
+        byteOffset += align4(entrySize);
+    }
+
+    return OK;
+}
+
+long int BlobCache::blob_random() {
+#ifdef _WIN32
+    return rand();
+#else
+    return nrand48(mRandState);
+#endif
+}
+
+void BlobCache::clean() {
+    // Remove a random cache entry until the total cache size gets below half
+    // the maximum total cache size.
+    while (mTotalSize > mMaxTotalSize / 2) {
+        size_t i = size_t(blob_random() % (mCacheEntries.size()));
+        const CacheEntry& entry(mCacheEntries[i]);
+        mTotalSize -= entry.getKey()->getSize() + entry.getValue()->getSize();
+        mCacheEntries.removeAt(i);
+    }
+}
+
+bool BlobCache::isCleanable() const {
+    return mTotalSize > mMaxTotalSize / 2;
+}
+
+BlobCache::Blob::Blob(const void* data, size_t size, bool copyData):
+        mData(copyData ? malloc(size) : data),
+        mSize(size),
+        mOwnsData(copyData) {
+    if (data != NULL && copyData) {
+        memcpy(const_cast<void*>(mData), data, size);
+    }
+}
+
+BlobCache::Blob::~Blob() {
+    if (mOwnsData) {
+        free(const_cast<void*>(mData));
+    }
+}
+
+bool BlobCache::Blob::operator<(const Blob& rhs) const {
+    if (mSize == rhs.mSize) {
+        return memcmp(mData, rhs.mData, mSize) < 0;
+    } else {
+        return mSize < rhs.mSize;
+    }
+}
+
+const void* BlobCache::Blob::getData() const {
+    return mData;
+}
+
+size_t BlobCache::Blob::getSize() const {
+    return mSize;
+}
+
+BlobCache::CacheEntry::CacheEntry() {
+}
+
+BlobCache::CacheEntry::CacheEntry(const sp<Blob>& key, const sp<Blob>& value):
+        mKey(key),
+        mValue(value) {
+}
+
+BlobCache::CacheEntry::CacheEntry(const CacheEntry& ce):
+        mKey(ce.mKey),
+        mValue(ce.mValue) {
+}
+
+bool BlobCache::CacheEntry::operator<(const CacheEntry& rhs) const {
+    return *mKey < *rhs.mKey;
+}
+
+const BlobCache::CacheEntry& BlobCache::CacheEntry::operator=(const CacheEntry& rhs) {
+    mKey = rhs.mKey;
+    mValue = rhs.mValue;
+    return *this;
+}
+
+sp<BlobCache::Blob> BlobCache::CacheEntry::getKey() const {
+    return mKey;
+}
+
+sp<BlobCache::Blob> BlobCache::CacheEntry::getValue() const {
+    return mValue;
+}
+
+void BlobCache::CacheEntry::setValue(const sp<Blob>& value) {
+    mValue = value;
+}
+
+} // namespace android
diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
new file mode 100644
index 0000000..4ceaa7c
--- /dev/null
+++ b/libutils/CallStack.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "CallStack"
+
+#include <utils/CallStack.h>
+#include <utils/Printer.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <corkscrew/backtrace.h>
+
+namespace android {
+
+CallStack::CallStack() :
+        mCount(0) {
+}
+
+CallStack::CallStack(const char* logtag, int32_t ignoreDepth, int32_t maxDepth) {
+    this->update(ignoreDepth+1, maxDepth, CURRENT_THREAD);
+    this->log(logtag);
+}
+
+CallStack::CallStack(const CallStack& rhs) :
+        mCount(rhs.mCount) {
+    if (mCount) {
+        memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t));
+    }
+}
+
+CallStack::~CallStack() {
+}
+
+CallStack& CallStack::operator = (const CallStack& rhs) {
+    mCount = rhs.mCount;
+    if (mCount) {
+        memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t));
+    }
+    return *this;
+}
+
+bool CallStack::operator == (const CallStack& rhs) const {
+    if (mCount != rhs.mCount)
+        return false;
+    return !mCount || memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) == 0;
+}
+
+bool CallStack::operator != (const CallStack& rhs) const {
+    return !operator == (rhs);
+}
+
+bool CallStack::operator < (const CallStack& rhs) const {
+    if (mCount != rhs.mCount)
+        return mCount < rhs.mCount;
+    return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) < 0;
+}
+
+bool CallStack::operator >= (const CallStack& rhs) const {
+    return !operator < (rhs);
+}
+
+bool CallStack::operator > (const CallStack& rhs) const {
+    if (mCount != rhs.mCount)
+        return mCount > rhs.mCount;
+    return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) > 0;
+}
+
+bool CallStack::operator <= (const CallStack& rhs) const {
+    return !operator > (rhs);
+}
+
+const void* CallStack::operator [] (int index) const {
+    if (index >= int(mCount))
+        return 0;
+    return reinterpret_cast<const void*>(mStack[index].absolute_pc);
+}
+
+void CallStack::clear() {
+    mCount = 0;
+}
+
+void CallStack::update(int32_t ignoreDepth, int32_t maxDepth, pid_t tid) {
+    if (maxDepth > MAX_DEPTH) {
+        maxDepth = MAX_DEPTH;
+    }
+    ssize_t count;
+
+    if (tid >= 0) {
+        count = unwind_backtrace_thread(tid, mStack, ignoreDepth + 1, maxDepth);
+    } else if (tid == CURRENT_THREAD) {
+        count = unwind_backtrace(mStack, ignoreDepth + 1, maxDepth);
+    } else {
+        ALOGE("%s: Invalid tid specified (%d)", __FUNCTION__, tid);
+        count = 0;
+    }
+
+    mCount = count > 0 ? count : 0;
+}
+
+void CallStack::log(const char* logtag, android_LogPriority priority, const char* prefix) const {
+    LogPrinter printer(logtag, priority, prefix, /*ignoreBlankLines*/false);
+    print(printer);
+}
+
+void CallStack::dump(int fd, int indent, const char* prefix) const {
+    FdPrinter printer(fd, indent, prefix);
+    print(printer);
+}
+
+String8 CallStack::toString(const char* prefix) const {
+    String8 str;
+
+    String8Printer printer(&str, prefix);
+    print(printer);
+
+    return str;
+}
+
+void CallStack::print(Printer& printer) const {
+    backtrace_symbol_t symbols[mCount];
+
+    get_backtrace_symbols(mStack, mCount, symbols);
+    for (size_t i = 0; i < mCount; i++) {
+        char line[MAX_BACKTRACE_LINE_LENGTH];
+        format_backtrace_line(i, &mStack[i], &symbols[i],
+                line, MAX_BACKTRACE_LINE_LENGTH);
+        printer.printLine(line);
+    }
+    free_backtrace_symbols(symbols, mCount);
+}
+
+}; // namespace android
diff --git a/libutils/CleanSpec.mk b/libutils/CleanSpec.mk
new file mode 100644
index 0000000..c3c5651
--- /dev/null
+++ b/libutils/CleanSpec.mk
@@ -0,0 +1,51 @@
+# Copyright (C) 2012 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
+# ************************************************
+$(call add-clean-step, rm -rf $(HOST_OUT)/obj/STATIC_LIBRARIES/libutils_intermediates/import_includes)
+$(call add-clean-step, rm -rf $(HOST_OUT)/obj/STATIC_LIBRARIES/lib64utils_intermediates/import_includes)
diff --git a/libutils/FileMap.cpp b/libutils/FileMap.cpp
new file mode 100644
index 0000000..9ce370e
--- /dev/null
+++ b/libutils/FileMap.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+//
+// Shared file mapping class.
+//
+
+#define LOG_TAG "filemap"
+
+#include <utils/FileMap.h>
+#include <utils/Log.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_POSIX_FILEMAP
+#include <sys/mman.h>
+#endif
+
+#include <string.h>
+#include <memory.h>
+#include <errno.h>
+#include <assert.h>
+
+using namespace android;
+
+/*static*/ long FileMap::mPageSize = -1;
+
+
+/*
+ * Constructor.  Create an empty object.
+ */
+FileMap::FileMap(void)
+    : mRefCount(1), mFileName(NULL), mBasePtr(NULL), mBaseLength(0),
+      mDataPtr(NULL), mDataLength(0)
+{
+}
+
+/*
+ * Destructor.
+ */
+FileMap::~FileMap(void)
+{
+    assert(mRefCount == 0);
+
+    //printf("+++ removing FileMap %p %u\n", mDataPtr, mDataLength);
+
+    mRefCount = -100;       // help catch double-free
+    if (mFileName != NULL) {
+        free(mFileName);
+    }
+#ifdef HAVE_POSIX_FILEMAP    
+    if (mBasePtr && munmap(mBasePtr, mBaseLength) != 0) {
+        ALOGD("munmap(%p, %d) failed\n", mBasePtr, (int) mBaseLength);
+    }
+#endif
+#ifdef HAVE_WIN32_FILEMAP
+    if (mBasePtr && UnmapViewOfFile(mBasePtr) == 0) {
+        ALOGD("UnmapViewOfFile(%p) failed, error = %ld\n", mBasePtr,
+              GetLastError() );
+    }
+    if (mFileMapping != INVALID_HANDLE_VALUE) {
+        CloseHandle(mFileMapping);
+    }
+    CloseHandle(mFileHandle);
+#endif
+}
+
+
+/*
+ * Create a new mapping on an open file.
+ *
+ * Closing the file descriptor does not unmap the pages, so we don't
+ * claim ownership of the fd.
+ *
+ * Returns "false" on failure.
+ */
+bool FileMap::create(const char* origFileName, int fd, off64_t offset, size_t length,
+        bool readOnly)
+{
+#ifdef HAVE_WIN32_FILEMAP
+    int     adjust;
+    off64_t adjOffset;
+    size_t  adjLength;
+
+    if (mPageSize == -1) {
+        SYSTEM_INFO  si;
+        
+        GetSystemInfo( &si );
+        mPageSize = si.dwAllocationGranularity;
+    }
+
+    DWORD  protect = readOnly ? PAGE_READONLY : PAGE_READWRITE;
+    
+    mFileHandle  = (HANDLE) _get_osfhandle(fd);
+    mFileMapping = CreateFileMapping( mFileHandle, NULL, protect, 0, 0, NULL);
+    if (mFileMapping == NULL) {
+        ALOGE("CreateFileMapping(%p, %lx) failed with error %ld\n",
+              mFileHandle, protect, GetLastError() );
+        return false;
+    }
+    
+    adjust    = offset % mPageSize;
+    adjOffset = offset - adjust;
+    adjLength = length + adjust;
+    
+    mBasePtr = MapViewOfFile( mFileMapping, 
+                              readOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
+                              0,
+                              (DWORD)(adjOffset),
+                              adjLength );
+    if (mBasePtr == NULL) {
+        ALOGE("MapViewOfFile(%ld, %ld) failed with error %ld\n",
+              adjOffset, adjLength, GetLastError() );
+        CloseHandle(mFileMapping);
+        mFileMapping = INVALID_HANDLE_VALUE;
+        return false;
+    }
+#endif
+#ifdef HAVE_POSIX_FILEMAP
+    int     prot, flags, adjust;
+    off64_t adjOffset;
+    size_t  adjLength;
+
+    void* ptr;
+
+    assert(mRefCount == 1);
+    assert(fd >= 0);
+    assert(offset >= 0);
+    assert(length > 0);
+
+    /* init on first use */
+    if (mPageSize == -1) {
+#if NOT_USING_KLIBC
+        mPageSize = sysconf(_SC_PAGESIZE);
+        if (mPageSize == -1) {
+            ALOGE("could not get _SC_PAGESIZE\n");
+            return false;
+        }
+#else
+        /* this holds for Linux, Darwin, Cygwin, and doesn't pain the ARM */
+        mPageSize = 4096;
+#endif
+    }
+
+    adjust   = offset % mPageSize;
+try_again:
+    adjOffset = offset - adjust;
+    adjLength = length + adjust;
+
+    flags = MAP_SHARED;
+    prot = PROT_READ;
+    if (!readOnly)
+        prot |= PROT_WRITE;
+
+    ptr = mmap(NULL, adjLength, prot, flags, fd, adjOffset);
+    if (ptr == MAP_FAILED) {
+    	// Cygwin does not seem to like file mapping files from an offset.
+    	// So if we fail, try again with offset zero
+    	if (adjOffset > 0) {
+    		adjust = offset;
+    		goto try_again;
+    	}
+    
+        ALOGE("mmap(%ld,%ld) failed: %s\n",
+            (long) adjOffset, (long) adjLength, strerror(errno));
+        return false;
+    }
+    mBasePtr = ptr;
+#endif /* HAVE_POSIX_FILEMAP */
+
+    mFileName = origFileName != NULL ? strdup(origFileName) : NULL;
+    mBaseLength = adjLength;
+    mDataOffset = offset;
+    mDataPtr = (char*) mBasePtr + adjust;
+    mDataLength = length;
+
+    assert(mBasePtr != NULL);
+
+    ALOGV("MAP: base %p/%d data %p/%d\n",
+        mBasePtr, (int) mBaseLength, mDataPtr, (int) mDataLength);
+
+    return true;
+}
+
+/*
+ * Provide guidance to the system.
+ */
+int FileMap::advise(MapAdvice advice)
+{
+#if HAVE_MADVISE
+    int cc, sysAdvice;
+
+    switch (advice) {
+        case NORMAL:        sysAdvice = MADV_NORMAL;        break;
+        case RANDOM:        sysAdvice = MADV_RANDOM;        break;
+        case SEQUENTIAL:    sysAdvice = MADV_SEQUENTIAL;    break;
+        case WILLNEED:      sysAdvice = MADV_WILLNEED;      break;
+        case DONTNEED:      sysAdvice = MADV_DONTNEED;      break;
+        default:
+                            assert(false);
+                            return -1;
+    }
+
+    cc = madvise(mBasePtr, mBaseLength, sysAdvice);
+    if (cc != 0)
+        ALOGW("madvise(%d) failed: %s\n", sysAdvice, strerror(errno));
+    return cc;
+#else
+	return -1;
+#endif // HAVE_MADVISE
+}
diff --git a/libutils/JenkinsHash.cpp b/libutils/JenkinsHash.cpp
new file mode 100644
index 0000000..52c9bb7
--- /dev/null
+++ b/libutils/JenkinsHash.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+/* Implementation of Jenkins one-at-a-time hash function. These choices are
+ * optimized for code size and portability, rather than raw speed. But speed
+ * should still be quite good.
+ **/
+
+#include <utils/JenkinsHash.h>
+
+namespace android {
+
+hash_t JenkinsHashWhiten(uint32_t hash) {
+    hash += (hash << 3);
+    hash ^= (hash >> 11);
+    hash += (hash << 15);
+    return hash;
+}
+
+uint32_t JenkinsHashMixBytes(uint32_t hash, const uint8_t* bytes, size_t size) {
+    hash = JenkinsHashMix(hash, (uint32_t)size);
+    size_t i;
+    for (i = 0; i < (size & -4); i += 4) {
+        uint32_t data = bytes[i] | (bytes[i+1] << 8) | (bytes[i+2] << 16) | (bytes[i+3] << 24);
+        hash = JenkinsHashMix(hash, data);
+    }
+    if (size & 3) {
+        uint32_t data = bytes[i];
+        data |= ((size & 3) > 1) ? (bytes[i+1] << 8) : 0;
+        data |= ((size & 3) > 2) ? (bytes[i+2] << 16) : 0;
+        hash = JenkinsHashMix(hash, data);
+    }
+    return hash;
+}
+
+uint32_t JenkinsHashMixShorts(uint32_t hash, const uint16_t* shorts, size_t size) {
+    hash = JenkinsHashMix(hash, (uint32_t)size);
+    size_t i;
+    for (i = 0; i < (size & -2); i += 2) {
+        uint32_t data = shorts[i] | (shorts[i+1] << 16);
+        hash = JenkinsHashMix(hash, data);
+    }
+    if (size & 1) {
+        uint32_t data = shorts[i];
+        hash = JenkinsHashMix(hash, data);
+    }
+    return hash;
+}
+
+}
+
diff --git a/libutils/LinearAllocator.cpp b/libutils/LinearAllocator.cpp
new file mode 100644
index 0000000..a07a291
--- /dev/null
+++ b/libutils/LinearAllocator.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+#define LOG_TAG "LinearAllocator"
+#define LOG_NDEBUG 1
+
+#include <stdlib.h>
+#include <utils/LinearAllocator.h>
+#include <utils/Log.h>
+
+
+// The ideal size of a page allocation (these need to be multiples of 8)
+#define INITIAL_PAGE_SIZE ((size_t)4096) // 4kb
+#define MAX_PAGE_SIZE ((size_t)131072) // 128kb
+
+// The maximum amount of wasted space we can have per page
+// Allocations exceeding this will have their own dedicated page
+// If this is too low, we will malloc too much
+// Too high, and we may waste too much space
+// Must be smaller than INITIAL_PAGE_SIZE
+#define MAX_WASTE_SIZE ((size_t)1024)
+
+#if ALIGN_DOUBLE
+#define ALIGN_SZ (sizeof(double))
+#else
+#define ALIGN_SZ (sizeof(int))
+#endif
+
+#define ALIGN(x) ((x + ALIGN_SZ - 1 ) & ~(ALIGN_SZ - 1))
+#define ALIGN_PTR(p) ((void*)(ALIGN((size_t)p)))
+
+#if LOG_NDEBUG
+#define ADD_ALLOCATION(size)
+#define RM_ALLOCATION(size)
+#else
+#include <utils/Thread.h>
+#include <utils/Timers.h>
+static size_t s_totalAllocations = 0;
+static nsecs_t s_nextLog = 0;
+static android::Mutex s_mutex;
+
+static void _logUsageLocked() {
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    if (now > s_nextLog) {
+        s_nextLog = now + milliseconds_to_nanoseconds(10);
+        ALOGV("Total memory usage: %zu kb", s_totalAllocations / 1024);
+    }
+}
+
+static void _addAllocation(size_t size) {
+    android::AutoMutex lock(s_mutex);
+    s_totalAllocations += size;
+    _logUsageLocked();
+}
+
+#define ADD_ALLOCATION(size) _addAllocation(size);
+#define RM_ALLOCATION(size) _addAllocation(-size);
+#endif
+
+#define min(x,y) (((x) < (y)) ? (x) : (y))
+
+namespace android {
+
+class LinearAllocator::Page {
+public:
+    Page* next() { return mNextPage; }
+    void setNext(Page* next) { mNextPage = next; }
+
+    Page()
+        : mNextPage(0)
+    {}
+
+    void* operator new(size_t size, void* buf) { return buf; }
+
+    void* start() {
+        return (void*) (((size_t)this) + sizeof(Page));
+    }
+
+    void* end(int pageSize) {
+        return (void*) (((size_t)start()) + pageSize);
+    }
+
+private:
+    Page(const Page& other) {}
+    Page* mNextPage;
+};
+
+LinearAllocator::LinearAllocator()
+    : mPageSize(INITIAL_PAGE_SIZE)
+    , mMaxAllocSize(MAX_WASTE_SIZE)
+    , mNext(0)
+    , mCurrentPage(0)
+    , mPages(0)
+    , mTotalAllocated(0)
+    , mWastedSpace(0)
+    , mPageCount(0)
+    , mDedicatedPageCount(0) {}
+
+LinearAllocator::~LinearAllocator(void) {
+    Page* p = mPages;
+    while (p) {
+        Page* next = p->next();
+        p->~Page();
+        free(p);
+        RM_ALLOCATION(mPageSize);
+        p = next;
+    }
+}
+
+void* LinearAllocator::start(Page* p) {
+    return ALIGN_PTR(((size_t*)p) + sizeof(Page));
+}
+
+void* LinearAllocator::end(Page* p) {
+    return ((char*)p) + mPageSize;
+}
+
+bool LinearAllocator::fitsInCurrentPage(size_t size) {
+    return mNext && ((char*)mNext + size) <= end(mCurrentPage);
+}
+
+void LinearAllocator::ensureNext(size_t size) {
+    if (fitsInCurrentPage(size)) return;
+
+    if (mCurrentPage && mPageSize < MAX_PAGE_SIZE) {
+        mPageSize = min(MAX_PAGE_SIZE, mPageSize * 2);
+        mPageSize = ALIGN(mPageSize);
+    }
+    mWastedSpace += mPageSize;
+    Page* p = newPage(mPageSize);
+    if (mCurrentPage) {
+        mCurrentPage->setNext(p);
+    }
+    mCurrentPage = p;
+    if (!mPages) {
+        mPages = mCurrentPage;
+    }
+    mNext = start(mCurrentPage);
+}
+
+void* LinearAllocator::alloc(size_t size) {
+    size = ALIGN(size);
+    if (size > mMaxAllocSize && !fitsInCurrentPage(size)) {
+        ALOGV("Exceeded max size %zu > %zu", size, mMaxAllocSize);
+        // Allocation is too large, create a dedicated page for the allocation
+        Page* page = newPage(size);
+        mDedicatedPageCount++;
+        page->setNext(mPages);
+        mPages = page;
+        if (!mCurrentPage)
+            mCurrentPage = mPages;
+        return start(page);
+    }
+    ensureNext(size);
+    void* ptr = mNext;
+    mNext = ((char*)mNext) + size;
+    mWastedSpace -= size;
+    return ptr;
+}
+
+void LinearAllocator::rewindIfLastAlloc(void* ptr, size_t allocSize) {
+    // Don't bother rewinding across pages
+    allocSize = ALIGN(allocSize);
+    if (ptr >= start(mCurrentPage) && ptr < end(mCurrentPage)
+            && ptr == ((char*)mNext - allocSize)) {
+        mTotalAllocated -= allocSize;
+        mWastedSpace += allocSize;
+        mNext = ptr;
+    }
+}
+
+LinearAllocator::Page* LinearAllocator::newPage(size_t pageSize) {
+    pageSize = ALIGN(pageSize + sizeof(LinearAllocator::Page));
+    ADD_ALLOCATION(pageSize);
+    mTotalAllocated += pageSize;
+    mPageCount++;
+    void* buf = malloc(pageSize);
+    return new (buf) Page();
+}
+
+static const char* toSize(size_t value, float& result) {
+    if (value < 2000) {
+        result = value;
+        return "B";
+    }
+    if (value < 2000000) {
+        result = value / 1024.0f;
+        return "KB";
+    }
+    result = value / 1048576.0f;
+    return "MB";
+}
+
+void LinearAllocator::dumpMemoryStats(const char* prefix) {
+    float prettySize;
+    const char* prettySuffix;
+    prettySuffix = toSize(mTotalAllocated, prettySize);
+    ALOGD("%sTotal allocated: %.2f%s", prefix, prettySize, prettySuffix);
+    prettySuffix = toSize(mWastedSpace, prettySize);
+    ALOGD("%sWasted space: %.2f%s (%.1f%%)", prefix, prettySize, prettySuffix,
+          (float) mWastedSpace / (float) mTotalAllocated * 100.0f);
+    ALOGD("%sPages %zu (dedicated %zu)", prefix, mPageCount, mDedicatedPageCount);
+}
+
+}; // namespace android
diff --git a/libutils/LinearTransform.cpp b/libutils/LinearTransform.cpp
new file mode 100644
index 0000000..b7d28d4
--- /dev/null
+++ b/libutils/LinearTransform.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define __STDC_LIMIT_MACROS
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <utils/LinearTransform.h>
+
+namespace android {
+
+template<class T> static inline T ABS(T x) { return (x < 0) ? -x : x; }
+
+// Static math methods involving linear transformations
+static bool scale_u64_to_u64(
+        uint64_t val,
+        uint32_t N,
+        uint32_t D,
+        uint64_t* res,
+        bool round_up_not_down) {
+    uint64_t tmp1, tmp2;
+    uint32_t r;
+
+    assert(res);
+    assert(D);
+
+    // Let U32(X) denote a uint32_t containing the upper 32 bits of a 64 bit
+    // integer X.
+    // Let L32(X) denote a uint32_t containing the lower 32 bits of a 64 bit
+    // integer X.
+    // Let X[A, B] with A <= B denote bits A through B of the integer X.
+    // Let (A | B) denote the concatination of two 32 bit ints, A and B.
+    // IOW X = (A | B) => U32(X) == A && L32(X) == B
+    //
+    // compute M = val * N (a 96 bit int)
+    // ---------------------------------
+    // tmp2 = U32(val) * N (a 64 bit int)
+    // tmp1 = L32(val) * N (a 64 bit int)
+    // which means
+    // M = val * N = (tmp2 << 32) + tmp1
+    tmp2 = (val >> 32) * N;
+    tmp1 = (val & UINT32_MAX) * N;
+
+    // compute M[32, 95]
+    // tmp2 = tmp2 + U32(tmp1)
+    //      = (U32(val) * N) + U32(L32(val) * N)
+    //      = M[32, 95]
+    tmp2 += tmp1 >> 32;
+
+    // if M[64, 95] >= D, then M/D has bits > 63 set and we have
+    // an overflow.
+    if ((tmp2 >> 32) >= D) {
+        *res = UINT64_MAX;
+        return false;
+    }
+
+    // Divide.  Going in we know
+    // tmp2 = M[32, 95]
+    // U32(tmp2) < D
+    r = tmp2 % D;
+    tmp2 /= D;
+
+    // At this point
+    // tmp1      = L32(val) * N
+    // tmp2      = M[32, 95] / D
+    //           = (M / D)[32, 95]
+    // r         = M[32, 95] % D
+    // U32(tmp2) = 0
+    //
+    // compute tmp1 = (r | M[0, 31])
+    tmp1 = (tmp1 & UINT32_MAX) | ((uint64_t)r << 32);
+
+    // Divide again.  Keep the remainder around in order to round properly.
+    r = tmp1 % D;
+    tmp1 /= D;
+
+    // At this point
+    // tmp2      = (M / D)[32, 95]
+    // tmp1      = (M / D)[ 0, 31]
+    // r         =  M % D
+    // U32(tmp1) = 0
+    // U32(tmp2) = 0
+
+    // Pack the result and deal with the round-up case (As well as the
+    // remote possiblility over overflow in such a case).
+    *res = (tmp2 << 32) | tmp1;
+    if (r && round_up_not_down) {
+        ++(*res);
+        if (!(*res)) {
+            *res = UINT64_MAX;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+static bool linear_transform_s64_to_s64(
+        int64_t  val,
+        int64_t  basis1,
+        int32_t  N,
+        uint32_t D,
+        bool     invert_frac,
+        int64_t  basis2,
+        int64_t* out) {
+    uint64_t scaled, res;
+    uint64_t abs_val;
+    bool is_neg;
+
+    if (!out)
+        return false;
+
+    // Compute abs(val - basis_64). Keep track of whether or not this delta
+    // will be negative after the scale opertaion.
+    if (val < basis1) {
+        is_neg = true;
+        abs_val = basis1 - val;
+    } else {
+        is_neg = false;
+        abs_val = val - basis1;
+    }
+
+    if (N < 0)
+        is_neg = !is_neg;
+
+    if (!scale_u64_to_u64(abs_val,
+                          invert_frac ? D : ABS(N),
+                          invert_frac ? ABS(N) : D,
+                          &scaled,
+                          is_neg))
+        return false; // overflow/undeflow
+
+    // if scaled is >= 0x8000<etc>, then we are going to overflow or
+    // underflow unless ABS(basis2) is large enough to pull us back into the
+    // non-overflow/underflow region.
+    if (scaled & INT64_MIN) {
+        if (is_neg && (basis2 < 0))
+            return false; // certain underflow
+
+        if (!is_neg && (basis2 >= 0))
+            return false; // certain overflow
+
+        if (ABS(basis2) <= static_cast<int64_t>(scaled & INT64_MAX))
+            return false; // not enough
+
+        // Looks like we are OK
+        *out = (is_neg ? (-scaled) : scaled) + basis2;
+    } else {
+        // Scaled fits within signed bounds, so we just need to check for
+        // over/underflow for two signed integers.  Basically, if both scaled
+        // and basis2 have the same sign bit, and the result has a different
+        // sign bit, then we have under/overflow.  An easy way to compute this
+        // is
+        // (scaled_signbit XNOR basis_signbit) &&
+        // (scaled_signbit XOR res_signbit)
+        // ==
+        // (scaled_signbit XOR basis_signbit XOR 1) &&
+        // (scaled_signbit XOR res_signbit)
+
+        if (is_neg)
+            scaled = -scaled;
+        res = scaled + basis2;
+
+        if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
+            return false;
+
+        *out = res;
+    }
+
+    return true;
+}
+
+bool LinearTransform::doForwardTransform(int64_t a_in, int64_t* b_out) const {
+    if (0 == a_to_b_denom)
+        return false;
+
+    return linear_transform_s64_to_s64(a_in,
+                                       a_zero,
+                                       a_to_b_numer,
+                                       a_to_b_denom,
+                                       false,
+                                       b_zero,
+                                       b_out);
+}
+
+bool LinearTransform::doReverseTransform(int64_t b_in, int64_t* a_out) const {
+    if (0 == a_to_b_numer)
+        return false;
+
+    return linear_transform_s64_to_s64(b_in,
+                                       b_zero,
+                                       a_to_b_numer,
+                                       a_to_b_denom,
+                                       true,
+                                       a_zero,
+                                       a_out);
+}
+
+template <class T> void LinearTransform::reduce(T* N, T* D) {
+    T a, b;
+    if (!N || !D || !(*D)) {
+        assert(false);
+        return;
+    }
+
+    a = *N;
+    b = *D;
+
+    if (a == 0) {
+        *D = 1;
+        return;
+    }
+
+    // This implements Euclid's method to find GCD.
+    if (a < b) {
+        T tmp = a;
+        a = b;
+        b = tmp;
+    }
+
+    while (1) {
+        // a is now the greater of the two.
+        const T remainder = a % b;
+        if (remainder == 0) {
+            *N /= b;
+            *D /= b;
+            return;
+        }
+        // by swapping remainder and b, we are guaranteeing that a is
+        // still the greater of the two upon entrance to the loop.
+        a = b;
+        b = remainder;
+    }
+};
+
+template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
+template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
+
+void LinearTransform::reduce(int32_t* N, uint32_t* D) {
+    if (N && D && *D) {
+        if (*N < 0) {
+            *N = -(*N);
+            reduce(reinterpret_cast<uint32_t*>(N), D);
+            *N = -(*N);
+        } else {
+            reduce(reinterpret_cast<uint32_t*>(N), D);
+        }
+    }
+}
+
+}  // namespace android
diff --git a/libutils/Log.cpp b/libutils/Log.cpp
new file mode 100644
index 0000000..bffb56e
--- /dev/null
+++ b/libutils/Log.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#define LOG_TAG "Log"
+
+#include <utils/Log.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+LogIfSlow::LogIfSlow(const char* tag, android_LogPriority priority,
+        int timeoutMillis, const char* message) :
+        mTag(tag), mPriority(priority), mTimeoutMillis(timeoutMillis), mMessage(message),
+        mStart(systemTime(SYSTEM_TIME_BOOTTIME)) {
+}
+
+LogIfSlow::~LogIfSlow() {
+    int durationMillis = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_BOOTTIME) - mStart);
+    if (durationMillis > mTimeoutMillis) {
+        LOG_PRI(mPriority, mTag, "%s: %dms", mMessage, durationMillis);
+    }
+}
+
+} // namespace android
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
new file mode 100644
index 0000000..c51df2d
--- /dev/null
+++ b/libutils/Looper.cpp
@@ -0,0 +1,573 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+// A looper implementation based on epoll().
+//
+#define LOG_TAG "Looper"
+
+//#define LOG_NDEBUG 0
+
+// Debugs poll and wake interactions.
+#define DEBUG_POLL_AND_WAKE 0
+
+// Debugs callback registration and invocation.
+#define DEBUG_CALLBACKS 0
+
+#include <cutils/log.h>
+#include <utils/Looper.h>
+#include <utils/Timers.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+
+
+namespace android {
+
+// --- WeakMessageHandler ---
+
+WeakMessageHandler::WeakMessageHandler(const wp<MessageHandler>& handler) :
+        mHandler(handler) {
+}
+
+WeakMessageHandler::~WeakMessageHandler() {
+}
+
+void WeakMessageHandler::handleMessage(const Message& message) {
+    sp<MessageHandler> handler = mHandler.promote();
+    if (handler != NULL) {
+        handler->handleMessage(message);
+    }
+}
+
+
+// --- SimpleLooperCallback ---
+
+SimpleLooperCallback::SimpleLooperCallback(ALooper_callbackFunc callback) :
+        mCallback(callback) {
+}
+
+SimpleLooperCallback::~SimpleLooperCallback() {
+}
+
+int SimpleLooperCallback::handleEvent(int fd, int events, void* data) {
+    return mCallback(fd, events, data);
+}
+
+
+// --- Looper ---
+
+// Hint for number of file descriptors to be associated with the epoll instance.
+static const int EPOLL_SIZE_HINT = 8;
+
+// Maximum number of file descriptors for which to retrieve poll events each iteration.
+static const int EPOLL_MAX_EVENTS = 16;
+
+static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
+static pthread_key_t gTLSKey = 0;
+
+Looper::Looper(bool allowNonCallbacks) :
+        mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
+        mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
+    int wakeFds[2];
+    int result = pipe(wakeFds);
+    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
+
+    mWakeReadPipeFd = wakeFds[0];
+    mWakeWritePipeFd = wakeFds[1];
+
+    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
+    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
+            errno);
+
+    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
+    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
+            errno);
+
+    mIdling = false;
+
+    // Allocate the epoll instance and register the wake pipe.
+    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
+    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
+
+    struct epoll_event eventItem;
+    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
+    eventItem.events = EPOLLIN;
+    eventItem.data.fd = mWakeReadPipeFd;
+    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
+    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
+            errno);
+}
+
+Looper::~Looper() {
+    close(mWakeReadPipeFd);
+    close(mWakeWritePipeFd);
+    close(mEpollFd);
+}
+
+void Looper::initTLSKey() {
+    int result = pthread_key_create(& gTLSKey, threadDestructor);
+    LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
+}
+
+void Looper::threadDestructor(void *st) {
+    Looper* const self = static_cast<Looper*>(st);
+    if (self != NULL) {
+        self->decStrong((void*)threadDestructor);
+    }
+}
+
+void Looper::setForThread(const sp<Looper>& looper) {
+    sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
+
+    if (looper != NULL) {
+        looper->incStrong((void*)threadDestructor);
+    }
+
+    pthread_setspecific(gTLSKey, looper.get());
+
+    if (old != NULL) {
+        old->decStrong((void*)threadDestructor);
+    }
+}
+
+sp<Looper> Looper::getForThread() {
+    int result = pthread_once(& gTLSOnce, initTLSKey);
+    LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
+
+    return (Looper*)pthread_getspecific(gTLSKey);
+}
+
+sp<Looper> Looper::prepare(int opts) {
+    bool allowNonCallbacks = opts & ALOOPER_PREPARE_ALLOW_NON_CALLBACKS;
+    sp<Looper> looper = Looper::getForThread();
+    if (looper == NULL) {
+        looper = new Looper(allowNonCallbacks);
+        Looper::setForThread(looper);
+    }
+    if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
+        ALOGW("Looper already prepared for this thread with a different value for the "
+                "ALOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
+    }
+    return looper;
+}
+
+bool Looper::getAllowNonCallbacks() const {
+    return mAllowNonCallbacks;
+}
+
+int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
+    int result = 0;
+    for (;;) {
+        while (mResponseIndex < mResponses.size()) {
+            const Response& response = mResponses.itemAt(mResponseIndex++);
+            int ident = response.request.ident;
+            if (ident >= 0) {
+                int fd = response.request.fd;
+                int events = response.events;
+                void* data = response.request.data;
+#if DEBUG_POLL_AND_WAKE
+                ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
+                        "fd=%d, events=0x%x, data=%p",
+                        this, ident, fd, events, data);
+#endif
+                if (outFd != NULL) *outFd = fd;
+                if (outEvents != NULL) *outEvents = events;
+                if (outData != NULL) *outData = data;
+                return ident;
+            }
+        }
+
+        if (result != 0) {
+#if DEBUG_POLL_AND_WAKE
+            ALOGD("%p ~ pollOnce - returning result %d", this, result);
+#endif
+            if (outFd != NULL) *outFd = 0;
+            if (outEvents != NULL) *outEvents = 0;
+            if (outData != NULL) *outData = NULL;
+            return result;
+        }
+
+        result = pollInner(timeoutMillis);
+    }
+}
+
+int Looper::pollInner(int timeoutMillis) {
+#if DEBUG_POLL_AND_WAKE
+    ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
+#endif
+
+    // Adjust the timeout based on when the next message is due.
+    if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
+        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+        int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
+        if (messageTimeoutMillis >= 0
+                && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
+            timeoutMillis = messageTimeoutMillis;
+        }
+#if DEBUG_POLL_AND_WAKE
+        ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
+                this, mNextMessageUptime - now, timeoutMillis);
+#endif
+    }
+
+    // Poll.
+    int result = ALOOPER_POLL_WAKE;
+    mResponses.clear();
+    mResponseIndex = 0;
+
+    // We are about to idle.
+    mIdling = true;
+
+    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
+    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
+
+    // No longer idling.
+    mIdling = false;
+
+    // Acquire lock.
+    mLock.lock();
+
+    // Check for poll error.
+    if (eventCount < 0) {
+        if (errno == EINTR) {
+            goto Done;
+        }
+        ALOGW("Poll failed with an unexpected error, errno=%d", errno);
+        result = ALOOPER_POLL_ERROR;
+        goto Done;
+    }
+
+    // Check for poll timeout.
+    if (eventCount == 0) {
+#if DEBUG_POLL_AND_WAKE
+        ALOGD("%p ~ pollOnce - timeout", this);
+#endif
+        result = ALOOPER_POLL_TIMEOUT;
+        goto Done;
+    }
+
+    // Handle all events.
+#if DEBUG_POLL_AND_WAKE
+    ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
+#endif
+
+    for (int i = 0; i < eventCount; i++) {
+        int fd = eventItems[i].data.fd;
+        uint32_t epollEvents = eventItems[i].events;
+        if (fd == mWakeReadPipeFd) {
+            if (epollEvents & EPOLLIN) {
+                awoken();
+            } else {
+                ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
+            }
+        } else {
+            ssize_t requestIndex = mRequests.indexOfKey(fd);
+            if (requestIndex >= 0) {
+                int events = 0;
+                if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
+                if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
+                if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
+                if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
+                pushResponse(events, mRequests.valueAt(requestIndex));
+            } else {
+                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
+                        "no longer registered.", epollEvents, fd);
+            }
+        }
+    }
+Done: ;
+
+    // Invoke pending message callbacks.
+    mNextMessageUptime = LLONG_MAX;
+    while (mMessageEnvelopes.size() != 0) {
+        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+        const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
+        if (messageEnvelope.uptime <= now) {
+            // Remove the envelope from the list.
+            // We keep a strong reference to the handler until the call to handleMessage
+            // finishes.  Then we drop it so that the handler can be deleted *before*
+            // we reacquire our lock.
+            { // obtain handler
+                sp<MessageHandler> handler = messageEnvelope.handler;
+                Message message = messageEnvelope.message;
+                mMessageEnvelopes.removeAt(0);
+                mSendingMessage = true;
+                mLock.unlock();
+
+#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
+                ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
+                        this, handler.get(), message.what);
+#endif
+                handler->handleMessage(message);
+            } // release handler
+
+            mLock.lock();
+            mSendingMessage = false;
+            result = ALOOPER_POLL_CALLBACK;
+        } else {
+            // The last message left at the head of the queue determines the next wakeup time.
+            mNextMessageUptime = messageEnvelope.uptime;
+            break;
+        }
+    }
+
+    // Release lock.
+    mLock.unlock();
+
+    // Invoke all response callbacks.
+    for (size_t i = 0; i < mResponses.size(); i++) {
+        Response& response = mResponses.editItemAt(i);
+        if (response.request.ident == ALOOPER_POLL_CALLBACK) {
+            int fd = response.request.fd;
+            int events = response.events;
+            void* data = response.request.data;
+#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
+            ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
+                    this, response.request.callback.get(), fd, events, data);
+#endif
+            int callbackResult = response.request.callback->handleEvent(fd, events, data);
+            if (callbackResult == 0) {
+                removeFd(fd);
+            }
+            // Clear the callback reference in the response structure promptly because we
+            // will not clear the response vector itself until the next poll.
+            response.request.callback.clear();
+            result = ALOOPER_POLL_CALLBACK;
+        }
+    }
+    return result;
+}
+
+int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
+    if (timeoutMillis <= 0) {
+        int result;
+        do {
+            result = pollOnce(timeoutMillis, outFd, outEvents, outData);
+        } while (result == ALOOPER_POLL_CALLBACK);
+        return result;
+    } else {
+        nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
+                + milliseconds_to_nanoseconds(timeoutMillis);
+
+        for (;;) {
+            int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
+            if (result != ALOOPER_POLL_CALLBACK) {
+                return result;
+            }
+
+            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+            timeoutMillis = toMillisecondTimeoutDelay(now, endTime);
+            if (timeoutMillis == 0) {
+                return ALOOPER_POLL_TIMEOUT;
+            }
+        }
+    }
+}
+
+void Looper::wake() {
+#if DEBUG_POLL_AND_WAKE
+    ALOGD("%p ~ wake", this);
+#endif
+
+    ssize_t nWrite;
+    do {
+        nWrite = write(mWakeWritePipeFd, "W", 1);
+    } while (nWrite == -1 && errno == EINTR);
+
+    if (nWrite != 1) {
+        if (errno != EAGAIN) {
+            ALOGW("Could not write wake signal, errno=%d", errno);
+        }
+    }
+}
+
+void Looper::awoken() {
+#if DEBUG_POLL_AND_WAKE
+    ALOGD("%p ~ awoken", this);
+#endif
+
+    char buffer[16];
+    ssize_t nRead;
+    do {
+        nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
+    } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
+}
+
+void Looper::pushResponse(int events, const Request& request) {
+    Response response;
+    response.events = events;
+    response.request = request;
+    mResponses.push(response);
+}
+
+int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data) {
+    return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);
+}
+
+int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
+#if DEBUG_CALLBACKS
+    ALOGD("%p ~ addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident,
+            events, callback.get(), data);
+#endif
+
+    if (!callback.get()) {
+        if (! mAllowNonCallbacks) {
+            ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
+            return -1;
+        }
+
+        if (ident < 0) {
+            ALOGE("Invalid attempt to set NULL callback with ident < 0.");
+            return -1;
+        }
+    } else {
+        ident = ALOOPER_POLL_CALLBACK;
+    }
+
+    int epollEvents = 0;
+    if (events & ALOOPER_EVENT_INPUT) epollEvents |= EPOLLIN;
+    if (events & ALOOPER_EVENT_OUTPUT) epollEvents |= EPOLLOUT;
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        Request request;
+        request.fd = fd;
+        request.ident = ident;
+        request.callback = callback;
+        request.data = data;
+
+        struct epoll_event eventItem;
+        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
+        eventItem.events = epollEvents;
+        eventItem.data.fd = fd;
+
+        ssize_t requestIndex = mRequests.indexOfKey(fd);
+        if (requestIndex < 0) {
+            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
+            if (epollResult < 0) {
+                ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
+                return -1;
+            }
+            mRequests.add(fd, request);
+        } else {
+            int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
+            if (epollResult < 0) {
+                ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
+                return -1;
+            }
+            mRequests.replaceValueAt(requestIndex, request);
+        }
+    } // release lock
+    return 1;
+}
+
+int Looper::removeFd(int fd) {
+#if DEBUG_CALLBACKS
+    ALOGD("%p ~ removeFd - fd=%d", this, fd);
+#endif
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+        ssize_t requestIndex = mRequests.indexOfKey(fd);
+        if (requestIndex < 0) {
+            return 0;
+        }
+
+        int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
+        if (epollResult < 0) {
+            ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno);
+            return -1;
+        }
+
+        mRequests.removeItemsAt(requestIndex);
+    } // release lock
+    return 1;
+}
+
+void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    sendMessageAtTime(now, handler, message);
+}
+
+void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& handler,
+        const Message& message) {
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    sendMessageAtTime(now + uptimeDelay, handler, message);
+}
+
+void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
+        const Message& message) {
+#if DEBUG_CALLBACKS
+    ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d",
+            this, uptime, handler.get(), message.what);
+#endif
+
+    size_t i = 0;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        size_t messageCount = mMessageEnvelopes.size();
+        while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {
+            i += 1;
+        }
+
+        MessageEnvelope messageEnvelope(uptime, handler, message);
+        mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
+
+        // Optimization: If the Looper is currently sending a message, then we can skip
+        // the call to wake() because the next thing the Looper will do after processing
+        // messages is to decide when the next wakeup time should be.  In fact, it does
+        // not even matter whether this code is running on the Looper thread.
+        if (mSendingMessage) {
+            return;
+        }
+    } // release lock
+
+    // Wake the poll loop only when we enqueue a new message at the head.
+    if (i == 0) {
+        wake();
+    }
+}
+
+void Looper::removeMessages(const sp<MessageHandler>& handler) {
+#if DEBUG_CALLBACKS
+    ALOGD("%p ~ removeMessages - handler=%p", this, handler.get());
+#endif
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
+            const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
+            if (messageEnvelope.handler == handler) {
+                mMessageEnvelopes.removeAt(i);
+            }
+        }
+    } // release lock
+}
+
+void Looper::removeMessages(const sp<MessageHandler>& handler, int what) {
+#if DEBUG_CALLBACKS
+    ALOGD("%p ~ removeMessages - handler=%p, what=%d", this, handler.get(), what);
+#endif
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        for (size_t i = mMessageEnvelopes.size(); i != 0; ) {
+            const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(--i);
+            if (messageEnvelope.handler == handler
+                    && messageEnvelope.message.what == what) {
+                mMessageEnvelopes.removeAt(i);
+            }
+        }
+    } // release lock
+}
+
+bool Looper::isIdling() const {
+    return mIdling;
+}
+
+} // namespace android
diff --git a/liblinenoise/MODULE_LICENSE_BSD_LIKE b/libutils/MODULE_LICENSE_APACHE2
similarity index 100%
rename from liblinenoise/MODULE_LICENSE_BSD_LIKE
rename to libutils/MODULE_LICENSE_APACHE2
diff --git a/libutils/NOTICE b/libutils/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/libutils/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the 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.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/libutils/Printer.cpp b/libutils/Printer.cpp
new file mode 100644
index 0000000..ac729e0
--- /dev/null
+++ b/libutils/Printer.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define LOG_TAG "Printer"
+// #define LOG_NDEBUG 0
+
+#include <utils/Printer.h>
+#include <utils/String8.h>
+#include <utils/Log.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef __BIONIC__
+#define fdprintf dprintf
+#endif
+
+namespace android {
+
+/*
+ * Implementation of Printer
+ */
+Printer::Printer() {
+    // Intentionally left empty
+}
+
+Printer::~Printer() {
+    // Intentionally left empty
+}
+
+void Printer::printFormatLine(const char* format, ...) {
+    va_list arglist;
+    va_start(arglist, format);
+
+    char* formattedString;
+
+#ifndef USE_MINGW
+    if (vasprintf(&formattedString, format, arglist) < 0) { // returns -1 on error
+        ALOGE("%s: Failed to format string", __FUNCTION__);
+        return;
+    }
+#else
+    return;
+#endif
+
+    va_end(arglist);
+
+    printLine(formattedString);
+    free(formattedString);
+}
+
+/*
+ * Implementation of LogPrinter
+ */
+LogPrinter::LogPrinter(const char* logtag,
+                       android_LogPriority priority,
+                       const char* prefix,
+                       bool ignoreBlankLines) :
+        mLogTag(logtag),
+        mPriority(priority),
+        mPrefix(prefix ?: ""),
+        mIgnoreBlankLines(ignoreBlankLines) {
+}
+
+void LogPrinter::printLine(const char* string) {
+    if (string == NULL) {
+        ALOGW("%s: NULL string passed in", __FUNCTION__);
+        return;
+    }
+
+    if (mIgnoreBlankLines || (*string)) {
+        // Simple case: Line is not blank, or we don't care about printing blank lines
+        printRaw(string);
+    } else {
+        // Force logcat to print empty lines by adding prefixing with a space
+        printRaw(" ");
+    }
+}
+
+void LogPrinter::printRaw(const char* string) {
+    __android_log_print(mPriority, mLogTag, "%s%s", mPrefix, string);
+}
+
+
+/*
+ * Implementation of FdPrinter
+ */
+FdPrinter::FdPrinter(int fd, unsigned int indent, const char* prefix) :
+        mFd(fd), mIndent(indent), mPrefix(prefix ?: "") {
+
+    if (fd < 0) {
+        ALOGW("%s: File descriptor out of range (%d)", __FUNCTION__, fd);
+    }
+
+    // <indent><prefix><line> -- e.g. '%-4s%s\n' for indent=4
+    snprintf(mFormatString, sizeof(mFormatString), "%%-%us%%s\n", mIndent);
+}
+
+void FdPrinter::printLine(const char* string) {
+    if (string == NULL) {
+        ALOGW("%s: NULL string passed in", __FUNCTION__);
+        return;
+    } else if (mFd < 0) {
+        ALOGW("%s: File descriptor out of range (%d)", __FUNCTION__, mFd);
+        return;
+    }
+
+#ifndef USE_MINGW
+    fdprintf(mFd, mFormatString, mPrefix, string);
+#endif
+}
+
+/*
+ * Implementation of String8Printer
+ */
+String8Printer::String8Printer(String8* target, const char* prefix) :
+        mTarget(target),
+        mPrefix(prefix ?: "") {
+
+    if (target == NULL) {
+        ALOGW("%s: Target string was NULL", __FUNCTION__);
+    }
+}
+
+void String8Printer::printLine(const char* string) {
+    if (string == NULL) {
+        ALOGW("%s: NULL string passed in", __FUNCTION__);
+        return;
+    } else if (mTarget == NULL) {
+        ALOGW("%s: Target string was NULL", __FUNCTION__);
+        return;
+    }
+
+    mTarget->append(string);
+    mTarget->append("\n");
+}
+
+/*
+ * Implementation of PrefixPrinter
+ */
+PrefixPrinter::PrefixPrinter(Printer& printer, const char* prefix) :
+        mPrinter(printer), mPrefix(prefix ?: "") {
+}
+
+void PrefixPrinter::printLine(const char* string) {
+    mPrinter.printFormatLine("%s%s", mPrefix, string);
+}
+
+}; //namespace android
diff --git a/libutils/ProcessCallStack.cpp b/libutils/ProcessCallStack.cpp
new file mode 100644
index 0000000..f9340c5
--- /dev/null
+++ b/libutils/ProcessCallStack.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define LOG_TAG "ProcessCallStack"
+// #define LOG_NDEBUG 0
+
+#include <string.h>
+#include <stdio.h>
+#include <dirent.h>
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <utils/ProcessCallStack.h>
+#include <utils/Printer.h>
+
+#include <limits.h>
+
+namespace android {
+
+enum {
+    // Max sizes for various dynamically generated strings
+    MAX_TIME_STRING = 64,
+    MAX_PROC_PATH = 1024,
+
+    // Dump related prettiness constants
+    IGNORE_DEPTH_CURRENT_THREAD = 2,
+};
+
+static const char* CALL_STACK_PREFIX = "  ";
+static const char* PATH_THREAD_NAME = "/proc/self/task/%d/comm";
+static const char* PATH_SELF_TASK = "/proc/self/task";
+
+static void dumpProcessHeader(Printer& printer, pid_t pid, const char* timeStr) {
+    if (timeStr == NULL) {
+        ALOGW("%s: timeStr was NULL", __FUNCTION__);
+        return;
+    }
+
+    char path[PATH_MAX];
+    char procNameBuf[MAX_PROC_PATH];
+    char* procName = NULL;
+    FILE* fp;
+
+    snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
+    if ((fp = fopen(path, "r"))) {
+        procName = fgets(procNameBuf, sizeof(procNameBuf), fp);
+        fclose(fp);
+    }
+
+    if (!procName) {
+        procName = const_cast<char*>("<unknown>");
+    }
+
+    printer.printLine();
+    printer.printLine();
+    printer.printFormatLine("----- pid %d at %s -----", pid, timeStr);
+    printer.printFormatLine("Cmd line: %s", procName);
+}
+
+static void dumpProcessFooter(Printer& printer, pid_t pid) {
+    printer.printLine();
+    printer.printFormatLine("----- end %d -----", pid);
+    printer.printLine();
+}
+
+static String8 getThreadName(pid_t tid) {
+    char path[PATH_MAX];
+    char* procName = NULL;
+    char procNameBuf[MAX_PROC_PATH];
+    FILE* fp;
+
+    snprintf(path, sizeof(path), PATH_THREAD_NAME, tid);
+    if ((fp = fopen(path, "r"))) {
+        procName = fgets(procNameBuf, sizeof(procNameBuf), fp);
+        fclose(fp);
+    } else {
+        ALOGE("%s: Failed to open %s", __FUNCTION__, path);
+    }
+
+    // Strip ending newline
+    strtok(procName, "\n");
+
+    return String8(procName);
+}
+
+static String8 getTimeString(struct tm tm) {
+    char timestr[MAX_TIME_STRING];
+    // i.e. '2013-10-22 14:42:05'
+    strftime(timestr, sizeof(timestr), "%F %T", &tm);
+
+    return String8(timestr);
+}
+
+/*
+ * Implementation of ProcessCallStack
+ */
+ProcessCallStack::ProcessCallStack() {
+}
+
+ProcessCallStack::ProcessCallStack(const ProcessCallStack& rhs) :
+        mThreadMap(rhs.mThreadMap),
+        mTimeUpdated(rhs.mTimeUpdated) {
+}
+
+ProcessCallStack::~ProcessCallStack() {
+}
+
+void ProcessCallStack::clear() {
+    mThreadMap.clear();
+    mTimeUpdated = tm();
+}
+
+void ProcessCallStack::update(int32_t maxDepth) {
+    DIR *dp;
+    struct dirent *ep;
+    struct dirent entry;
+
+    dp = opendir(PATH_SELF_TASK);
+    if (dp == NULL) {
+        ALOGE("%s: Failed to update the process's call stacks (errno = %d, '%s')",
+              __FUNCTION__, errno, strerror(errno));
+        return;
+    }
+
+    pid_t selfPid = getpid();
+
+    clear();
+
+    // Get current time.
+#ifndef USE_MINGW
+    {
+        time_t t = time(NULL);
+        struct tm tm;
+        localtime_r(&t, &tm);
+
+        mTimeUpdated = tm;
+    }
+
+    /*
+     * Each tid is a directory inside of /proc/self/task
+     * - Read every file in directory => get every tid
+     */
+    int code;
+    while ((code = readdir_r(dp, &entry, &ep)) == 0 && ep != NULL) {
+        pid_t tid = -1;
+        sscanf(ep->d_name, "%d", &tid);
+
+        if (tid < 0) {
+            // Ignore '.' and '..'
+            ALOGV("%s: Failed to read tid from %s/%s",
+                  __FUNCTION__, PATH_SELF_TASK, ep->d_name);
+            continue;
+        }
+
+        ssize_t idx = mThreadMap.add(tid, ThreadInfo());
+        if (idx < 0) { // returns negative error value on error
+            ALOGE("%s: Failed to add new ThreadInfo (errno = %zd, '%s')",
+                  __FUNCTION__, idx, strerror(-idx));
+            continue;
+        }
+
+        ThreadInfo& threadInfo = mThreadMap.editValueAt(static_cast<size_t>(idx));
+
+        /*
+         * Ignore CallStack::update and ProcessCallStack::update for current thread
+         * - Every other thread doesn't need this since we call update off-thread
+         */
+        int ignoreDepth = (selfPid == tid) ? IGNORE_DEPTH_CURRENT_THREAD : 0;
+
+        // Update thread's call stacks
+        CallStack& cs = threadInfo.callStack;
+        cs.update(ignoreDepth, maxDepth, tid);
+
+        // Read/save thread name
+        threadInfo.threadName = getThreadName(tid);
+
+        ALOGV("%s: Got call stack for tid %d (size %zu)",
+              __FUNCTION__, tid, cs.size());
+    }
+    if (code != 0) { // returns positive error value on error
+        ALOGE("%s: Failed to readdir from %s (errno = %d, '%s')",
+              __FUNCTION__, PATH_SELF_TASK, -code, strerror(code));
+    }
+#endif
+
+    closedir(dp);
+}
+
+void ProcessCallStack::log(const char* logtag, android_LogPriority priority,
+                           const char* prefix) const {
+    LogPrinter printer(logtag, priority, prefix, /*ignoreBlankLines*/false);
+    print(printer);
+}
+
+void ProcessCallStack::print(Printer& printer) const {
+    /*
+     * Print the header/footer with the regular printer.
+     * Print the callstack with an additional two spaces as the prefix for legibility.
+     */
+    PrefixPrinter csPrinter(printer, CALL_STACK_PREFIX);
+    printInternal(printer, csPrinter);
+}
+
+void ProcessCallStack::printInternal(Printer& printer, Printer& csPrinter) const {
+    dumpProcessHeader(printer, getpid(),
+                      getTimeString(mTimeUpdated).string());
+
+    for (size_t i = 0; i < mThreadMap.size(); ++i) {
+        pid_t tid = mThreadMap.keyAt(i);
+        const ThreadInfo& threadInfo = mThreadMap.valueAt(i);
+        const CallStack& cs = threadInfo.callStack;
+        const String8& threadName = threadInfo.threadName;
+
+        printer.printLine("");
+        printer.printFormatLine("\"%s\" sysTid=%d", threadName.string(), tid);
+
+        cs.print(csPrinter);
+    }
+
+    dumpProcessFooter(printer, getpid());
+}
+
+void ProcessCallStack::dump(int fd, int indent, const char* prefix) const {
+
+    if (indent < 0) {
+        ALOGW("%s: Bad indent (%d)", __FUNCTION__, indent);
+        return;
+    }
+
+    FdPrinter printer(fd, static_cast<unsigned int>(indent), prefix);
+    print(printer);
+}
+
+String8 ProcessCallStack::toString(const char* prefix) const {
+
+    String8 dest;
+    String8Printer printer(&dest, prefix);
+    print(printer);
+
+    return dest;
+}
+
+size_t ProcessCallStack::size() const {
+    return mThreadMap.size();
+}
+
+}; //namespace android
diff --git a/libutils/PropertyMap.cpp b/libutils/PropertyMap.cpp
new file mode 100644
index 0000000..5520702
--- /dev/null
+++ b/libutils/PropertyMap.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#define LOG_TAG "PropertyMap"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <utils/PropertyMap.h>
+#include <utils/Log.h>
+
+// Enables debug output for the parser.
+#define DEBUG_PARSER 0
+
+// Enables debug output for parser performance.
+#define DEBUG_PARSER_PERFORMANCE 0
+
+
+namespace android {
+
+static const char* WHITESPACE = " \t\r";
+static const char* WHITESPACE_OR_PROPERTY_DELIMITER = " \t\r=";
+
+
+// --- PropertyMap ---
+
+PropertyMap::PropertyMap() {
+}
+
+PropertyMap::~PropertyMap() {
+}
+
+void PropertyMap::clear() {
+    mProperties.clear();
+}
+
+void PropertyMap::addProperty(const String8& key, const String8& value) {
+    mProperties.add(key, value);
+}
+
+bool PropertyMap::hasProperty(const String8& key) const {
+    return mProperties.indexOfKey(key) >= 0;
+}
+
+bool PropertyMap::tryGetProperty(const String8& key, String8& outValue) const {
+    ssize_t index = mProperties.indexOfKey(key);
+    if (index < 0) {
+        return false;
+    }
+
+    outValue = mProperties.valueAt(index);
+    return true;
+}
+
+bool PropertyMap::tryGetProperty(const String8& key, bool& outValue) const {
+    int32_t intValue;
+    if (!tryGetProperty(key, intValue)) {
+        return false;
+    }
+
+    outValue = intValue;
+    return true;
+}
+
+bool PropertyMap::tryGetProperty(const String8& key, int32_t& outValue) const {
+    String8 stringValue;
+    if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
+        return false;
+    }
+
+    char* end;
+    int value = strtol(stringValue.string(), & end, 10);
+    if (*end != '\0') {
+        ALOGW("Property key '%s' has invalid value '%s'.  Expected an integer.",
+                key.string(), stringValue.string());
+        return false;
+    }
+    outValue = value;
+    return true;
+}
+
+bool PropertyMap::tryGetProperty(const String8& key, float& outValue) const {
+    String8 stringValue;
+    if (! tryGetProperty(key, stringValue) || stringValue.length() == 0) {
+        return false;
+    }
+
+    char* end;
+    float value = strtof(stringValue.string(), & end);
+    if (*end != '\0') {
+        ALOGW("Property key '%s' has invalid value '%s'.  Expected a float.",
+                key.string(), stringValue.string());
+        return false;
+    }
+    outValue = value;
+    return true;
+}
+
+void PropertyMap::addAll(const PropertyMap* map) {
+    for (size_t i = 0; i < map->mProperties.size(); i++) {
+        mProperties.add(map->mProperties.keyAt(i), map->mProperties.valueAt(i));
+    }
+}
+
+status_t PropertyMap::load(const String8& filename, PropertyMap** outMap) {
+    *outMap = NULL;
+
+    Tokenizer* tokenizer;
+    status_t status = Tokenizer::open(filename, &tokenizer);
+    if (status) {
+        ALOGE("Error %d opening property file %s.", status, filename.string());
+    } else {
+        PropertyMap* map = new PropertyMap();
+        if (!map) {
+            ALOGE("Error allocating property map.");
+            status = NO_MEMORY;
+        } else {
+#if DEBUG_PARSER_PERFORMANCE
+            nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
+#endif
+            Parser parser(map, tokenizer);
+            status = parser.parse();
+#if DEBUG_PARSER_PERFORMANCE
+            nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
+            ALOGD("Parsed property file '%s' %d lines in %0.3fms.",
+                    tokenizer->getFilename().string(), tokenizer->getLineNumber(),
+                    elapsedTime / 1000000.0);
+#endif
+            if (status) {
+                delete map;
+            } else {
+                *outMap = map;
+            }
+        }
+        delete tokenizer;
+    }
+    return status;
+}
+
+
+// --- PropertyMap::Parser ---
+
+PropertyMap::Parser::Parser(PropertyMap* map, Tokenizer* tokenizer) :
+        mMap(map), mTokenizer(tokenizer) {
+}
+
+PropertyMap::Parser::~Parser() {
+}
+
+status_t PropertyMap::Parser::parse() {
+    while (!mTokenizer->isEof()) {
+#if DEBUG_PARSER
+        ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
+                mTokenizer->peekRemainderOfLine().string());
+#endif
+
+        mTokenizer->skipDelimiters(WHITESPACE);
+
+        if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
+            String8 keyToken = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
+            if (keyToken.isEmpty()) {
+                ALOGE("%s: Expected non-empty property key.", mTokenizer->getLocation().string());
+                return BAD_VALUE;
+            }
+
+            mTokenizer->skipDelimiters(WHITESPACE);
+
+            if (mTokenizer->nextChar() != '=') {
+                ALOGE("%s: Expected '=' between property key and value.",
+                        mTokenizer->getLocation().string());
+                return BAD_VALUE;
+            }
+
+            mTokenizer->skipDelimiters(WHITESPACE);
+
+            String8 valueToken = mTokenizer->nextToken(WHITESPACE);
+            if (valueToken.find("\\", 0) >= 0 || valueToken.find("\"", 0) >= 0) {
+                ALOGE("%s: Found reserved character '\\' or '\"' in property value.",
+                        mTokenizer->getLocation().string());
+                return BAD_VALUE;
+            }
+
+            mTokenizer->skipDelimiters(WHITESPACE);
+            if (!mTokenizer->isEol()) {
+                ALOGE("%s: Expected end of line, got '%s'.",
+                        mTokenizer->getLocation().string(),
+                        mTokenizer->peekRemainderOfLine().string());
+                return BAD_VALUE;
+            }
+
+            if (mMap->hasProperty(keyToken)) {
+                ALOGE("%s: Duplicate property value for key '%s'.",
+                        mTokenizer->getLocation().string(), keyToken.string());
+                return BAD_VALUE;
+            }
+
+            mMap->addProperty(keyToken, valueToken);
+        }
+
+        mTokenizer->nextLine();
+    }
+    return NO_ERROR;
+}
+
+} // namespace android
diff --git a/libutils/README b/libutils/README
new file mode 100644
index 0000000..01741e0
--- /dev/null
+++ b/libutils/README
@@ -0,0 +1,289 @@
+Android Utility Function Library
+================================
+
+
+If you need a feature that is native to Linux but not present on other
+platforms, construct a platform-dependent implementation that shares
+the Linux interface.  That way the actual device runs as "light" as
+possible.
+
+If that isn't feasible, create a system-independent interface and hide
+the details.
+
+The ultimate goal is *not* to create a super-duper platform abstraction
+layer.  The goal is to provide an optimized solution for Linux with
+reasonable implementations for other platforms.
+
+
+
+Resource overlay
+================
+
+
+Introduction
+------------
+
+Overlay packages are special .apk files which provide no code but
+additional resource values (and possibly new configurations) for
+resources in other packages. When an application requests resources,
+the system will return values from either the application's original
+package or any associated overlay package. Any redirection is completely
+transparent to the calling application.
+
+Resource values have the following precedence table, listed in
+descending precedence.
+
+ * overlay package, matching config (eg res/values-en-land)
+
+ * original package, matching config
+
+ * overlay package, no config (eg res/values)
+
+ * original package, no config
+
+During compilation, overlay packages are differentiated from regular
+packages by passing the -o flag to aapt.
+
+
+Background
+----------
+
+This section provides generic background material on resources in
+Android.
+
+
+How resources are bundled in .apk files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Android .apk files are .zip files, usually housing .dex code,
+certificates and resources, though packages containing resources but
+no code are possible. Resources can be divided into the following
+categories; a `configuration' indicates a set of phone language, display
+density, network operator, etc.
+
+ * assets: uncompressed, raw files packaged as part of an .apk and
+           explicitly referenced by filename. These files are
+           independent of configuration.
+
+ * res/drawable: bitmap or xml graphics. Each file may have different
+                 values depending on configuration.
+
+ * res/values: integers, strings, etc. Each resource may have different
+               values depending on configuration.
+
+Resource meta information and information proper is stored in a binary
+format in a named file resources.arsc, bundled as part of the .apk.
+
+Resource IDs and lookup
+~~~~~~~~~~~~~~~~~~~~~~~
+During compilation, the aapt tool gathers application resources and
+generates a resources.arsc file. Each resource name is assigned an
+integer ID 0xppttiii (translated to a symbolic name via R.java), where
+
+ * pp: corresponds to the package namespace (details below).
+
+ * tt: corresponds to the resource type (string, int, etc). Every
+       resource of the same type within the same package has the same
+       tt value, but depending on available types, the actual numerical
+       value may be different between packages.
+
+ * iiii: sequential number, assigned in the order resources are found.
+
+Resource values are specified paired with a set of configuration
+constraints (the default being the empty set), eg res/values-sv-port
+which imposes restrictions on language (Swedish) and display orientation
+(portrait). During lookup, every constraint set is matched against the
+current configuration, and the value corresponding to the best matching
+constraint set is returned (ResourceTypes.{h,cpp}).
+
+Parsing of resources.arsc is handled by ResourceTypes.cpp; this utility
+is governed by AssetManager.cpp, which tracks loaded resources per
+process.
+
+Assets are looked up by path and filename in AssetManager.cpp. The path
+to resources in res/drawable are located by ResourceTypes.cpp and then
+handled like assets by AssetManager.cpp. Other resources are handled
+solely by ResourceTypes.cpp.
+
+Package ID as namespace
+~~~~~~~~~~~~~~~~~~~~~~~
+The pp part of a resource ID defines a namespace. Android currently
+defines two namespaces:
+
+ * 0x01: system resources (pre-installed in framework-res.apk)
+
+ * 0x7f: application resources (bundled in the application .apk)
+
+ResourceTypes.cpp supports package IDs between 0x01 and 0x7f
+(inclusive); values outside this range are invalid.
+
+Each running (Dalvik) process is assigned a unique instance of
+AssetManager, which in turn keeps a forest structure of loaded
+resource.arsc files. Normally, this forest is structured as follows,
+where mPackageMap is the internal vector employed in ResourceTypes.cpp.
+
+mPackageMap[0x00] -> system package
+mPackageMap[0x01] -> NULL
+mPackageMap[0x02] -> NULL
+...
+mPackageMap[0x7f - 2] -> NULL
+mPackageMap[0x7f - 1] -> application package
+
+
+
+The resource overlay extension
+------------------------------
+
+The resource overlay mechanism aims to (partly) shadow and extend
+existing resources with new values for defined and new configurations.
+Technically, this is achieved by adding resource-only packages (called
+overlay packages) to existing resource namespaces, like so:
+
+mPackageMap[0x00] -> system package -> system overlay package
+mPackageMap[0x01] -> NULL
+mPackageMap[0x02] -> NULL
+...
+mPackageMap[0x7f - 2] -> NULL
+mPackageMap[0x7f - 1] -> application package -> overlay 1 -> overlay 2
+
+The use of overlay resources is completely transparent to
+applications; no additional resource identifiers are introduced, only
+configuration/value pairs. Any number of overlay packages may be loaded
+at a time; overlay packages are agnostic to what they target -- both
+system and application resources are fair game.
+
+The package targeted by an overlay package is called the target or
+original package.
+
+Resource overlay operates on symbolic resources names. Hence, to
+override the string/str1 resources in a package, the overlay package
+would include a resource also named string/str1. The end user does not
+have to worry about the numeric resources IDs assigned by aapt, as this
+is resolved automatically by the system.
+
+As of this writing, the use of resource overlay has not been fully
+explored. Until it has, only OEMs are trusted to use resource overlay.
+For this reason, overlay packages must reside in /system/overlay.
+
+
+Resource ID mapping
+~~~~~~~~~~~~~~~~~~~
+Resource identifiers must be coherent within the same namespace (ie
+PackageGroup in ResourceTypes.cpp). Calling applications will refer to
+resources using the IDs defined in the original package, but there is no
+guarantee aapt has assigned the same ID to the corresponding resource in
+an overlay package. To translate between the two, a resource ID mapping
+{original ID -> overlay ID} is created during package installation
+(PackageManagerService.java) and used during resource lookup. The
+mapping is stored in /data/resource-cache, with a @idmap file name
+suffix.
+
+The idmap file format is documented in a separate section, below.
+
+
+Package management
+~~~~~~~~~~~~~~~~~~
+Packages are managed by the PackageManagerService. Addition and removal
+of packages are monitored via the inotify framework, exposed via
+android.os.FileObserver.
+
+During initialization of a Dalvik process, ActivityThread.java requests
+the process' AssetManager (by proxy, via AssetManager.java and JNI)
+to load a list of packages. This list includes overlay packages, if
+present.
+
+When a target package or a corresponding overlay package is installed,
+the target package's process is stopped and a new idmap is generated.
+This is similar to how applications are stopped when their packages are
+upgraded.
+
+
+Creating overlay packages
+-------------------------
+
+Overlay packages should contain no code, define (some) resources with
+the same type and name as in the original package, and be compiled with
+the -o flag passed to aapt.
+
+The aapt -o flag instructs aapt to create an overlay package.
+Technically, this means the package will be assigned package id 0x00.
+
+There are no restrictions on overlay packages names, though the naming
+convention <original.package.name>.overlay.<name> is recommended.
+
+
+Example overlay package
+~~~~~~~~~~~~~~~~~~~~~~~
+
+To overlay the resource bool/b in package com.foo.bar, to be applied
+when the display is in landscape mode, create a new package with
+no source code and a single .xml file under res/values-land, with
+an entry for bool/b. Compile with aapt -o and place the results in
+/system/overlay by adding the following to Android.mk:
+
+LOCAL_AAPT_FLAGS := -o com.foo.bar
+LOCAL_MODULE_PATH := $(TARGET_OUT)/overlay
+
+
+The ID map (idmap) file format
+------------------------------
+
+The idmap format is designed for lookup performance. However, leading
+and trailing undefined overlay values are discarded to reduce the memory
+footprint.
+
+
+idmap grammar
+~~~~~~~~~~~~~
+All atoms (names in square brackets) are uint32_t integers. The
+idmap-magic constant spells "idmp" in ASCII. Offsets are given relative
+to the data_header, not to the beginning of the file.
+
+map          := header data
+header       := idmap-magic <crc32-original-pkg> <crc32-overlay-pkg>
+idmap-magic  := <0x706d6469>
+data         := data_header type_block+
+data_header  := <m> header_block{m}
+header_block := <0> | <type_block_offset>
+type_block   := <n> <id_offset> entry{n}
+entry        := <resource_id_in_target_package>
+
+
+idmap example
+~~~~~~~~~~~~~
+Given a pair of target and overlay packages with CRC sums 0x216a8fe2
+and 0x6b9beaec, each defining the following resources
+
+Name          Target package  Overlay package
+string/str0   0x7f010000      -
+string/str1   0x7f010001      0x7f010000
+string/str2   0x7f010002      -
+string/str3   0x7f010003      0x7f010001
+string/str4   0x7f010004      -
+bool/bool0    0x7f020000      -
+integer/int0  0x7f030000      0x7f020000
+integer/int1  0x7f030001      -
+
+the corresponding resource map is
+
+0x706d6469 0x216a8fe2 0x6b9beaec 0x00000003 \
+0x00000004 0x00000000 0x00000009 0x00000003 \
+0x00000001 0x7f010000 0x00000000 0x7f010001 \
+0x00000001 0x00000000 0x7f020000
+
+or, formatted differently
+
+0x706d6469  # magic: all idmap files begin with this constant
+0x216a8fe2  # CRC32 of the resources.arsc file in the original package
+0x6b9beaec  # CRC32 of the resources.arsc file in the overlay package
+0x00000003  # header; three types (string, bool, integer) in the target package
+0x00000004  #   header_block for type 0 (string) is located at offset 4
+0x00000000  #   no bool type exists in overlay package -> no header_block
+0x00000009  #   header_block for type 2 (integer) is located at offset 9
+0x00000003  # header_block for string; overlay IDs span 3 elements
+0x00000001  #   the first string in target package is entry 1 == offset
+0x7f010000  #   target 0x7f01001 -> overlay 0x7f010000
+0x00000000  #   str2 not defined in overlay package
+0x7f010001  #   target 0x7f010003 -> overlay 0x7f010001
+0x00000001  # header_block for integer; overlay IDs span 1 element
+0x00000000  #   offset == 0
+0x7f020000  #   target 0x7f030000 -> overlay 0x7f020000
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
new file mode 100644
index 0000000..f398a82
--- /dev/null
+++ b/libutils/RefBase.cpp
@@ -0,0 +1,650 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "RefBase"
+// #define LOG_NDEBUG 0
+
+#include <utils/RefBase.h>
+
+#include <utils/Atomic.h>
+#include <utils/CallStack.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <typeinfo>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+// compile with refcounting debugging enabled
+#define DEBUG_REFS                      0
+
+// whether ref-tracking is enabled by default, if not, trackMe(true, false)
+// needs to be called explicitly
+#define DEBUG_REFS_ENABLED_BY_DEFAULT   0
+
+// whether callstack are collected (significantly slows things down)
+#define DEBUG_REFS_CALLSTACK_ENABLED    1
+
+// folder where stack traces are saved when DEBUG_REFS is enabled
+// this folder needs to exist and be writable
+#define DEBUG_REFS_CALLSTACK_PATH       "/data/debug"
+
+// log all reference counting operations
+#define PRINT_REFS                      0
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+#define INITIAL_STRONG_VALUE (1<<28)
+
+// ---------------------------------------------------------------------------
+
+class RefBase::weakref_impl : public RefBase::weakref_type
+{
+public:
+    volatile int32_t    mStrong;
+    volatile int32_t    mWeak;
+    RefBase* const      mBase;
+    volatile int32_t    mFlags;
+
+#if !DEBUG_REFS
+
+    weakref_impl(RefBase* base)
+        : mStrong(INITIAL_STRONG_VALUE)
+        , mWeak(0)
+        , mBase(base)
+        , mFlags(0)
+    {
+    }
+
+    void addStrongRef(const void* /*id*/) { }
+    void removeStrongRef(const void* /*id*/) { }
+    void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
+    void addWeakRef(const void* /*id*/) { }
+    void removeWeakRef(const void* /*id*/) { }
+    void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
+    void printRefs() const { }
+    void trackMe(bool, bool) { }
+
+#else
+
+    weakref_impl(RefBase* base)
+        : mStrong(INITIAL_STRONG_VALUE)
+        , mWeak(0)
+        , mBase(base)
+        , mFlags(0)
+        , mStrongRefs(NULL)
+        , mWeakRefs(NULL)
+        , mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
+        , mRetain(false)
+    {
+    }
+    
+    ~weakref_impl()
+    {
+        bool dumpStack = false;
+        if (!mRetain && mStrongRefs != NULL) {
+            dumpStack = true;
+            ALOGE("Strong references remain:");
+            ref_entry* refs = mStrongRefs;
+            while (refs) {
+                char inc = refs->ref >= 0 ? '+' : '-';
+                ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+                refs->stack.dump(LOG_TAG);
+#endif
+                refs = refs->next;
+            }
+        }
+
+        if (!mRetain && mWeakRefs != NULL) {
+            dumpStack = true;
+            ALOGE("Weak references remain!");
+            ref_entry* refs = mWeakRefs;
+            while (refs) {
+                char inc = refs->ref >= 0 ? '+' : '-';
+                ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+                refs->stack.dump(LOG_TAG);
+#endif
+                refs = refs->next;
+            }
+        }
+        if (dumpStack) {
+            ALOGE("above errors at:");
+            CallStack stack(LOG_TAG);
+        }
+    }
+
+    void addStrongRef(const void* id) {
+        //ALOGD_IF(mTrackEnabled,
+        //        "addStrongRef: RefBase=%p, id=%p", mBase, id);
+        addRef(&mStrongRefs, id, mStrong);
+    }
+
+    void removeStrongRef(const void* id) {
+        //ALOGD_IF(mTrackEnabled,
+        //        "removeStrongRef: RefBase=%p, id=%p", mBase, id);
+        if (!mRetain) {
+            removeRef(&mStrongRefs, id);
+        } else {
+            addRef(&mStrongRefs, id, -mStrong);
+        }
+    }
+
+    void renameStrongRefId(const void* old_id, const void* new_id) {
+        //ALOGD_IF(mTrackEnabled,
+        //        "renameStrongRefId: RefBase=%p, oid=%p, nid=%p",
+        //        mBase, old_id, new_id);
+        renameRefsId(mStrongRefs, old_id, new_id);
+    }
+
+    void addWeakRef(const void* id) {
+        addRef(&mWeakRefs, id, mWeak);
+    }
+
+    void removeWeakRef(const void* id) {
+        if (!mRetain) {
+            removeRef(&mWeakRefs, id);
+        } else {
+            addRef(&mWeakRefs, id, -mWeak);
+        }
+    }
+
+    void renameWeakRefId(const void* old_id, const void* new_id) {
+        renameRefsId(mWeakRefs, old_id, new_id);
+    }
+
+    void trackMe(bool track, bool retain)
+    { 
+        mTrackEnabled = track;
+        mRetain = retain;
+    }
+
+    void printRefs() const
+    {
+        String8 text;
+
+        {
+            Mutex::Autolock _l(mMutex);
+            char buf[128];
+            sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
+            text.append(buf);
+            printRefsLocked(&text, mStrongRefs);
+            sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this);
+            text.append(buf);
+            printRefsLocked(&text, mWeakRefs);
+        }
+
+        {
+            char name[100];
+            snprintf(name, 100, DEBUG_REFS_CALLSTACK_PATH "/%p.stack", this);
+            int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644);
+            if (rc >= 0) {
+                write(rc, text.string(), text.length());
+                close(rc);
+                ALOGD("STACK TRACE for %p saved in %s", this, name);
+            }
+            else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
+                      name, strerror(errno));
+        }
+    }
+
+private:
+    struct ref_entry
+    {
+        ref_entry* next;
+        const void* id;
+#if DEBUG_REFS_CALLSTACK_ENABLED
+        CallStack stack;
+#endif
+        int32_t ref;
+    };
+
+    void addRef(ref_entry** refs, const void* id, int32_t mRef)
+    {
+        if (mTrackEnabled) {
+            AutoMutex _l(mMutex);
+
+            ref_entry* ref = new ref_entry;
+            // Reference count at the time of the snapshot, but before the
+            // update.  Positive value means we increment, negative--we
+            // decrement the reference count.
+            ref->ref = mRef;
+            ref->id = id;
+#if DEBUG_REFS_CALLSTACK_ENABLED
+            ref->stack.update(2);
+#endif
+            ref->next = *refs;
+            *refs = ref;
+        }
+    }
+
+    void removeRef(ref_entry** refs, const void* id)
+    {
+        if (mTrackEnabled) {
+            AutoMutex _l(mMutex);
+            
+            ref_entry* const head = *refs;
+            ref_entry* ref = head;
+            while (ref != NULL) {
+                if (ref->id == id) {
+                    *refs = ref->next;
+                    delete ref;
+                    return;
+                }
+                refs = &ref->next;
+                ref = *refs;
+            }
+
+            ALOGE("RefBase: removing id %p on RefBase %p"
+                    "(weakref_type %p) that doesn't exist!",
+                    id, mBase, this);
+
+            ref = head;
+            while (ref) {
+                char inc = ref->ref >= 0 ? '+' : '-';
+                ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
+                ref = ref->next;
+            }
+
+            CallStack stack(LOG_TAG);
+        }
+    }
+
+    void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
+    {
+        if (mTrackEnabled) {
+            AutoMutex _l(mMutex);
+            ref_entry* ref = r;
+            while (ref != NULL) {
+                if (ref->id == old_id) {
+                    ref->id = new_id;
+                }
+                ref = ref->next;
+            }
+        }
+    }
+
+    void printRefsLocked(String8* out, const ref_entry* refs) const
+    {
+        char buf[128];
+        while (refs) {
+            char inc = refs->ref >= 0 ? '+' : '-';
+            sprintf(buf, "\t%c ID %p (ref %d):\n", 
+                    inc, refs->id, refs->ref);
+            out->append(buf);
+#if DEBUG_REFS_CALLSTACK_ENABLED
+            out->append(refs->stack.toString("\t\t"));
+#else
+            out->append("\t\t(call stacks disabled)");
+#endif
+            refs = refs->next;
+        }
+    }
+
+    mutable Mutex mMutex;
+    ref_entry* mStrongRefs;
+    ref_entry* mWeakRefs;
+
+    bool mTrackEnabled;
+    // Collect stack traces on addref and removeref, instead of deleting the stack references
+    // on removeref that match the address ones.
+    bool mRetain;
+
+#endif
+};
+
+// ---------------------------------------------------------------------------
+
+void RefBase::incStrong(const void* id) const
+{
+    weakref_impl* const refs = mRefs;
+    refs->incWeak(id);
+    
+    refs->addStrongRef(id);
+    const int32_t c = android_atomic_inc(&refs->mStrong);
+    ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
+#if PRINT_REFS
+    ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+    if (c != INITIAL_STRONG_VALUE)  {
+        return;
+    }
+
+    android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
+    refs->mBase->onFirstRef();
+}
+
+void RefBase::decStrong(const void* id) const
+{
+    weakref_impl* const refs = mRefs;
+    refs->removeStrongRef(id);
+    const int32_t c = android_atomic_dec(&refs->mStrong);
+#if PRINT_REFS
+    ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+    ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
+    if (c == 1) {
+        refs->mBase->onLastStrongRef(id);
+        if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) {
+            delete this;
+        }
+    }
+    refs->decWeak(id);
+}
+
+void RefBase::forceIncStrong(const void* id) const
+{
+    weakref_impl* const refs = mRefs;
+    refs->incWeak(id);
+    
+    refs->addStrongRef(id);
+    const int32_t c = android_atomic_inc(&refs->mStrong);
+    ALOG_ASSERT(c >= 0, "forceIncStrong called on %p after ref count underflow",
+               refs);
+#if PRINT_REFS
+    ALOGD("forceIncStrong of %p from %p: cnt=%d\n", this, id, c);
+#endif
+
+    switch (c) {
+    case INITIAL_STRONG_VALUE:
+        android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
+        // fall through...
+    case 0:
+        refs->mBase->onFirstRef();
+    }
+}
+
+int32_t RefBase::getStrongCount() const
+{
+    return mRefs->mStrong;
+}
+
+RefBase* RefBase::weakref_type::refBase() const
+{
+    return static_cast<const weakref_impl*>(this)->mBase;
+}
+
+void RefBase::weakref_type::incWeak(const void* id)
+{
+    weakref_impl* const impl = static_cast<weakref_impl*>(this);
+    impl->addWeakRef(id);
+    const int32_t c = android_atomic_inc(&impl->mWeak);
+    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
+}
+
+
+void RefBase::weakref_type::decWeak(const void* id)
+{
+    weakref_impl* const impl = static_cast<weakref_impl*>(this);
+    impl->removeWeakRef(id);
+    const int32_t c = android_atomic_dec(&impl->mWeak);
+    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
+    if (c != 1) return;
+
+    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
+        // This is the regular lifetime case. The object is destroyed
+        // when the last strong reference goes away. Since weakref_impl
+        // outlive the object, it is not destroyed in the dtor, and
+        // we'll have to do it here.
+        if (impl->mStrong == INITIAL_STRONG_VALUE) {
+            // Special case: we never had a strong reference, so we need to
+            // destroy the object now.
+            delete impl->mBase;
+        } else {
+            // ALOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
+            delete impl;
+        }
+    } else {
+        // less common case: lifetime is OBJECT_LIFETIME_{WEAK|FOREVER}
+        impl->mBase->onLastWeakRef(id);
+        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) {
+            // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
+            // is gone, we can destroy the object.
+            delete impl->mBase;
+        }
+    }
+}
+
+bool RefBase::weakref_type::attemptIncStrong(const void* id)
+{
+    incWeak(id);
+    
+    weakref_impl* const impl = static_cast<weakref_impl*>(this);
+    int32_t curCount = impl->mStrong;
+
+    ALOG_ASSERT(curCount >= 0,
+            "attemptIncStrong called on %p after underflow", this);
+
+    while (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {
+        // we're in the easy/common case of promoting a weak-reference
+        // from an existing strong reference.
+        if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) {
+            break;
+        }
+        // the strong count has changed on us, we need to re-assert our
+        // situation.
+        curCount = impl->mStrong;
+    }
+    
+    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {
+        // we're now in the harder case of either:
+        // - there never was a strong reference on us
+        // - or, all strong references have been released
+        if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) {
+            // this object has a "normal" life-time, i.e.: it gets destroyed
+            // when the last strong reference goes away
+            if (curCount <= 0) {
+                // the last strong-reference got released, the object cannot
+                // be revived.
+                decWeak(id);
+                return false;
+            }
+
+            // here, curCount == INITIAL_STRONG_VALUE, which means
+            // there never was a strong-reference, so we can try to
+            // promote this object; we need to do that atomically.
+            while (curCount > 0) {
+                if (android_atomic_cmpxchg(curCount, curCount + 1,
+                        &impl->mStrong) == 0) {
+                    break;
+                }
+                // the strong count has changed on us, we need to re-assert our
+                // situation (e.g.: another thread has inc/decStrong'ed us)
+                curCount = impl->mStrong;
+            }
+
+            if (curCount <= 0) {
+                // promote() failed, some other thread destroyed us in the
+                // meantime (i.e.: strong count reached zero).
+                decWeak(id);
+                return false;
+            }
+        } else {
+            // this object has an "extended" life-time, i.e.: it can be
+            // revived from a weak-reference only.
+            // Ask the object's implementation if it agrees to be revived
+            if (!impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)) {
+                // it didn't so give-up.
+                decWeak(id);
+                return false;
+            }
+            // grab a strong-reference, which is always safe due to the
+            // extended life-time.
+            curCount = android_atomic_inc(&impl->mStrong);
+        }
+
+        // If the strong reference count has already been incremented by
+        // someone else, the implementor of onIncStrongAttempted() is holding
+        // an unneeded reference.  So call onLastStrongRef() here to remove it.
+        // (No, this is not pretty.)  Note that we MUST NOT do this if we
+        // are in fact acquiring the first reference.
+        if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {
+            impl->mBase->onLastStrongRef(id);
+        }
+    }
+    
+    impl->addStrongRef(id);
+
+#if PRINT_REFS
+    ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
+#endif
+
+    // now we need to fix-up the count if it was INITIAL_STRONG_VALUE
+    // this must be done safely, i.e.: handle the case where several threads
+    // were here in attemptIncStrong().
+    curCount = impl->mStrong;
+    while (curCount >= INITIAL_STRONG_VALUE) {
+        ALOG_ASSERT(curCount > INITIAL_STRONG_VALUE,
+                "attemptIncStrong in %p underflowed to INITIAL_STRONG_VALUE",
+                this);
+        if (android_atomic_cmpxchg(curCount, curCount-INITIAL_STRONG_VALUE,
+                &impl->mStrong) == 0) {
+            break;
+        }
+        // the strong-count changed on us, we need to re-assert the situation,
+        // for e.g.: it's possible the fix-up happened in another thread.
+        curCount = impl->mStrong;
+    }
+
+    return true;
+}
+
+bool RefBase::weakref_type::attemptIncWeak(const void* id)
+{
+    weakref_impl* const impl = static_cast<weakref_impl*>(this);
+
+    int32_t curCount = impl->mWeak;
+    ALOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow",
+               this);
+    while (curCount > 0) {
+        if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) {
+            break;
+        }
+        curCount = impl->mWeak;
+    }
+
+    if (curCount > 0) {
+        impl->addWeakRef(id);
+    }
+
+    return curCount > 0;
+}
+
+int32_t RefBase::weakref_type::getWeakCount() const
+{
+    return static_cast<const weakref_impl*>(this)->mWeak;
+}
+
+void RefBase::weakref_type::printRefs() const
+{
+    static_cast<const weakref_impl*>(this)->printRefs();
+}
+
+void RefBase::weakref_type::trackMe(bool enable, bool retain)
+{
+    static_cast<weakref_impl*>(this)->trackMe(enable, retain);
+}
+
+RefBase::weakref_type* RefBase::createWeak(const void* id) const
+{
+    mRefs->incWeak(id);
+    return mRefs;
+}
+
+RefBase::weakref_type* RefBase::getWeakRefs() const
+{
+    return mRefs;
+}
+
+RefBase::RefBase()
+    : mRefs(new weakref_impl(this))
+{
+}
+
+RefBase::~RefBase()
+{
+    if (mRefs->mStrong == INITIAL_STRONG_VALUE) {
+        // we never acquired a strong (and/or weak) reference on this object.
+        delete mRefs;
+    } else {
+        // life-time of this object is extended to WEAK or FOREVER, in
+        // which case weakref_impl doesn't out-live the object and we
+        // can free it now.
+        if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) {
+            // It's possible that the weak count is not 0 if the object
+            // re-acquired a weak reference in its destructor
+            if (mRefs->mWeak == 0) {
+                delete mRefs;
+            }
+        }
+    }
+    // for debugging purposes, clear this.
+    const_cast<weakref_impl*&>(mRefs) = NULL;
+}
+
+void RefBase::extendObjectLifetime(int32_t mode)
+{
+    android_atomic_or(mode, &mRefs->mFlags);
+}
+
+void RefBase::onFirstRef()
+{
+}
+
+void RefBase::onLastStrongRef(const void* /*id*/)
+{
+}
+
+bool RefBase::onIncStrongAttempted(uint32_t flags, const void* id)
+{
+    return (flags&FIRST_INC_STRONG) ? true : false;
+}
+
+void RefBase::onLastWeakRef(const void* /*id*/)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+void RefBase::renameRefs(size_t n, const ReferenceRenamer& renamer) {
+#if DEBUG_REFS
+    for (size_t i=0 ; i<n ; i++) {
+        renamer(i);
+    }
+#endif
+}
+
+void RefBase::renameRefId(weakref_type* ref,
+        const void* old_id, const void* new_id) {
+    weakref_impl* const impl = static_cast<weakref_impl*>(ref);
+    impl->renameStrongRefId(old_id, new_id);
+    impl->renameWeakRefId(old_id, new_id);
+}
+
+void RefBase::renameRefId(RefBase* ref,
+        const void* old_id, const void* new_id) {
+    ref->mRefs->renameStrongRefId(old_id, new_id);
+    ref->mRefs->renameWeakRefId(old_id, new_id);
+}
+
+}; // namespace android
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
new file mode 100644
index 0000000..3555fb7
--- /dev/null
+++ b/libutils/SharedBuffer.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <utils/SharedBuffer.h>
+#include <utils/Atomic.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+SharedBuffer* SharedBuffer::alloc(size_t size)
+{
+    SharedBuffer* sb = static_cast<SharedBuffer *>(malloc(sizeof(SharedBuffer) + size));
+    if (sb) {
+        sb->mRefs = 1;
+        sb->mSize = size;
+    }
+    return sb;
+}
+
+
+ssize_t SharedBuffer::dealloc(const SharedBuffer* released)
+{
+    if (released->mRefs != 0) return -1; // XXX: invalid operation
+    free(const_cast<SharedBuffer*>(released));
+    return 0;
+}
+
+SharedBuffer* SharedBuffer::edit() const
+{
+    if (onlyOwner()) {
+        return const_cast<SharedBuffer*>(this);
+    }
+    SharedBuffer* sb = alloc(mSize);
+    if (sb) {
+        memcpy(sb->data(), data(), size());
+        release();
+    }
+    return sb;    
+}
+
+SharedBuffer* SharedBuffer::editResize(size_t newSize) const
+{
+    if (onlyOwner()) {
+        SharedBuffer* buf = const_cast<SharedBuffer*>(this);
+        if (buf->mSize == newSize) return buf;
+        buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize);
+        if (buf != NULL) {
+            buf->mSize = newSize;
+            return buf;
+        }
+    }
+    SharedBuffer* sb = alloc(newSize);
+    if (sb) {
+        const size_t mySize = mSize;
+        memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize);
+        release();
+    }
+    return sb;    
+}
+
+SharedBuffer* SharedBuffer::attemptEdit() const
+{
+    if (onlyOwner()) {
+        return const_cast<SharedBuffer*>(this);
+    }
+    return 0;
+}
+
+SharedBuffer* SharedBuffer::reset(size_t new_size) const
+{
+    // cheap-o-reset.
+    SharedBuffer* sb = alloc(new_size);
+    if (sb) {
+        release();
+    }
+    return sb;
+}
+
+void SharedBuffer::acquire() const {
+    android_atomic_inc(&mRefs);
+}
+
+int32_t SharedBuffer::release(uint32_t flags) const
+{
+    int32_t prev = 1;
+    if (onlyOwner() || ((prev = android_atomic_dec(&mRefs)) == 1)) {
+        mRefs = 0;
+        if ((flags & eKeepStorage) == 0) {
+            free(const_cast<SharedBuffer*>(this));
+        }
+    }
+    return prev;
+}
+
+
+}; // namespace android
diff --git a/libutils/Static.cpp b/libutils/Static.cpp
new file mode 100644
index 0000000..3ed07a1
--- /dev/null
+++ b/libutils/Static.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+// All static variables go here, to control initialization and
+// destruction order in the library.
+
+namespace android {
+
+// For String8.cpp
+extern void initialize_string8();
+extern void terminate_string8();
+
+// For String16.cpp
+extern void initialize_string16();
+extern void terminate_string16();
+
+class LibUtilsFirstStatics
+{
+public:
+    LibUtilsFirstStatics()
+    {
+        initialize_string8();
+        initialize_string16();
+    }
+    
+    ~LibUtilsFirstStatics()
+    {
+        terminate_string16();
+        terminate_string8();
+    }
+};
+
+static LibUtilsFirstStatics gFirstStatics;
+int gDarwinCantLoadAllObjects = 1;
+
+}   // namespace android
diff --git a/libutils/StopWatch.cpp b/libutils/StopWatch.cpp
new file mode 100644
index 0000000..b1708d6
--- /dev/null
+++ b/libutils/StopWatch.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "StopWatch"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* for PRId64 */
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <utils/StopWatch.h>
+
+/*****************************************************************************/
+
+namespace android {
+
+
+StopWatch::StopWatch(const char *name, int clock, uint32_t flags)
+    :   mName(name), mClock(clock), mFlags(flags)
+{
+    reset();
+}
+
+StopWatch::~StopWatch()
+{
+    nsecs_t elapsed = elapsedTime();
+    const int n = mNumLaps;
+    ALOGD("StopWatch %s (us): %" PRId64 " ", mName, ns2us(elapsed));
+    for (int i=0 ; i<n ; i++) {
+        const nsecs_t soFar = mLaps[i].soFar;
+        const nsecs_t thisLap = mLaps[i].thisLap;
+        ALOGD(" [%d: %" PRId64 ", %" PRId64, i, ns2us(soFar), ns2us(thisLap));
+    }
+}
+
+const char* StopWatch::name() const
+{
+    return mName;
+}
+
+nsecs_t StopWatch::lap()
+{
+    nsecs_t elapsed = elapsedTime();
+    if (mNumLaps >= 8) {
+        elapsed = 0;
+    } else {
+        const int n = mNumLaps;
+        mLaps[n].soFar   = elapsed;
+        mLaps[n].thisLap = n ? (elapsed - mLaps[n-1].soFar) : elapsed;
+        mNumLaps = n+1;
+    }
+    return elapsed;
+}
+
+nsecs_t StopWatch::elapsedTime() const
+{
+    return systemTime(mClock) - mStartTime;
+}
+
+void StopWatch::reset()
+{
+    mNumLaps = 0;
+    mStartTime = systemTime(mClock);
+}
+
+
+/*****************************************************************************/
+
+}; // namespace android
+
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
new file mode 100644
index 0000000..b09b728
--- /dev/null
+++ b/libutils/String16.cpp
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#include <utils/String16.h>
+
+#include <utils/Debug.h>
+#include <utils/Log.h>
+#include <utils/Unicode.h>
+#include <utils/String8.h>
+#include <utils/threads.h>
+
+#include <memory.h>
+#include <stdio.h>
+#include <ctype.h>
+
+
+namespace android {
+
+static SharedBuffer* gEmptyStringBuf = NULL;
+static char16_t* gEmptyString = NULL;
+
+static inline char16_t* getEmptyString()
+{
+    gEmptyStringBuf->acquire();
+   return gEmptyString;
+}
+
+void initialize_string16()
+{
+    SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t));
+    char16_t* str = (char16_t*)buf->data();
+    *str = 0;
+    gEmptyStringBuf = buf;
+    gEmptyString = str;
+}
+
+void terminate_string16()
+{
+    SharedBuffer::bufferFromData(gEmptyString)->release();
+    gEmptyStringBuf = NULL;
+    gEmptyString = NULL;
+}
+
+// ---------------------------------------------------------------------------
+
+static char16_t* allocFromUTF8(const char* u8str, size_t u8len)
+{
+    if (u8len == 0) return getEmptyString();
+
+    const uint8_t* u8cur = (const uint8_t*) u8str;
+
+    const ssize_t u16len = utf8_to_utf16_length(u8cur, u8len);
+    if (u16len < 0) {
+        return getEmptyString();
+    }
+
+    const uint8_t* const u8end = u8cur + u8len;
+
+    SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t)*(u16len+1));
+    if (buf) {
+        u8cur = (const uint8_t*) u8str;
+        char16_t* u16str = (char16_t*)buf->data();
+
+        utf8_to_utf16(u8cur, u8len, u16str);
+
+        //printf("Created UTF-16 string from UTF-8 \"%s\":", in);
+        //printHexData(1, str, buf->size(), 16, 1);
+        //printf("\n");
+        
+        return u16str;
+    }
+
+    return getEmptyString();
+}
+
+// ---------------------------------------------------------------------------
+
+String16::String16()
+    : mString(getEmptyString())
+{
+}
+
+String16::String16(StaticLinkage)
+    : mString(0)
+{
+    // this constructor is used when we can't rely on the static-initializers
+    // having run. In this case we always allocate an empty string. It's less
+    // efficient than using getEmptyString(), but we assume it's uncommon.
+
+    char16_t* data = static_cast<char16_t*>(
+            SharedBuffer::alloc(sizeof(char16_t))->data());
+    data[0] = 0;
+    mString = data;
+}
+
+String16::String16(const String16& o)
+    : mString(o.mString)
+{
+    SharedBuffer::bufferFromData(mString)->acquire();
+}
+
+String16::String16(const String16& o, size_t len, size_t begin)
+    : mString(getEmptyString())
+{
+    setTo(o, len, begin);
+}
+
+String16::String16(const char16_t* o)
+{
+    size_t len = strlen16(o);
+    SharedBuffer* buf = SharedBuffer::alloc((len+1)*sizeof(char16_t));
+    ALOG_ASSERT(buf, "Unable to allocate shared buffer");
+    if (buf) {
+        char16_t* str = (char16_t*)buf->data();
+        strcpy16(str, o);
+        mString = str;
+        return;
+    }
+    
+    mString = getEmptyString();
+}
+
+String16::String16(const char16_t* o, size_t len)
+{
+    SharedBuffer* buf = SharedBuffer::alloc((len+1)*sizeof(char16_t));
+    ALOG_ASSERT(buf, "Unable to allocate shared buffer");
+    if (buf) {
+        char16_t* str = (char16_t*)buf->data();
+        memcpy(str, o, len*sizeof(char16_t));
+        str[len] = 0;
+        mString = str;
+        return;
+    }
+    
+    mString = getEmptyString();
+}
+
+String16::String16(const String8& o)
+    : mString(allocFromUTF8(o.string(), o.size()))
+{
+}
+
+String16::String16(const char* o)
+    : mString(allocFromUTF8(o, strlen(o)))
+{
+}
+
+String16::String16(const char* o, size_t len)
+    : mString(allocFromUTF8(o, len))
+{
+}
+
+String16::~String16()
+{
+    SharedBuffer::bufferFromData(mString)->release();
+}
+
+void String16::setTo(const String16& other)
+{
+    SharedBuffer::bufferFromData(other.mString)->acquire();
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = other.mString;
+}
+
+status_t String16::setTo(const String16& other, size_t len, size_t begin)
+{
+    const size_t N = other.size();
+    if (begin >= N) {
+        SharedBuffer::bufferFromData(mString)->release();
+        mString = getEmptyString();
+        return NO_ERROR;
+    }
+    if ((begin+len) > N) len = N-begin;
+    if (begin == 0 && len == N) {
+        setTo(other);
+        return NO_ERROR;
+    }
+
+    if (&other == this) {
+        LOG_ALWAYS_FATAL("Not implemented");
+    }
+
+    return setTo(other.string()+begin, len);
+}
+
+status_t String16::setTo(const char16_t* other)
+{
+    return setTo(other, strlen16(other));
+}
+
+status_t String16::setTo(const char16_t* other, size_t len)
+{
+    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+        ->editResize((len+1)*sizeof(char16_t));
+    if (buf) {
+        char16_t* str = (char16_t*)buf->data();
+        memmove(str, other, len*sizeof(char16_t));
+        str[len] = 0;
+        mString = str;
+        return NO_ERROR;
+    }
+    return NO_MEMORY;
+}
+
+status_t String16::append(const String16& other)
+{
+    const size_t myLen = size();
+    const size_t otherLen = other.size();
+    if (myLen == 0) {
+        setTo(other);
+        return NO_ERROR;
+    } else if (otherLen == 0) {
+        return NO_ERROR;
+    }
+    
+    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+        ->editResize((myLen+otherLen+1)*sizeof(char16_t));
+    if (buf) {
+        char16_t* str = (char16_t*)buf->data();
+        memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t));
+        mString = str;
+        return NO_ERROR;
+    }
+    return NO_MEMORY;
+}
+
+status_t String16::append(const char16_t* chrs, size_t otherLen)
+{
+    const size_t myLen = size();
+    if (myLen == 0) {
+        setTo(chrs, otherLen);
+        return NO_ERROR;
+    } else if (otherLen == 0) {
+        return NO_ERROR;
+    }
+    
+    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+        ->editResize((myLen+otherLen+1)*sizeof(char16_t));
+    if (buf) {
+        char16_t* str = (char16_t*)buf->data();
+        memcpy(str+myLen, chrs, otherLen*sizeof(char16_t));
+        str[myLen+otherLen] = 0;
+        mString = str;
+        return NO_ERROR;
+    }
+    return NO_MEMORY;
+}
+
+status_t String16::insert(size_t pos, const char16_t* chrs)
+{
+    return insert(pos, chrs, strlen16(chrs));
+}
+
+status_t String16::insert(size_t pos, const char16_t* chrs, size_t len)
+{
+    const size_t myLen = size();
+    if (myLen == 0) {
+        return setTo(chrs, len);
+        return NO_ERROR;
+    } else if (len == 0) {
+        return NO_ERROR;
+    }
+
+    if (pos > myLen) pos = myLen;
+
+    #if 0
+    printf("Insert in to %s: pos=%d, len=%d, myLen=%d, chrs=%s\n",
+           String8(*this).string(), pos,
+           len, myLen, String8(chrs, len).string());
+    #endif
+
+    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+        ->editResize((myLen+len+1)*sizeof(char16_t));
+    if (buf) {
+        char16_t* str = (char16_t*)buf->data();
+        if (pos < myLen) {
+            memmove(str+pos+len, str+pos, (myLen-pos)*sizeof(char16_t));
+        }
+        memcpy(str+pos, chrs, len*sizeof(char16_t));
+        str[myLen+len] = 0;
+        mString = str;
+        #if 0
+        printf("Result (%d chrs): %s\n", size(), String8(*this).string());
+        #endif
+        return NO_ERROR;
+    }
+    return NO_MEMORY;
+}
+
+ssize_t String16::findFirst(char16_t c) const
+{
+    const char16_t* str = string();
+    const char16_t* p = str;
+    const char16_t* e = p + size();
+    while (p < e) {
+        if (*p == c) {
+            return p-str;
+        }
+        p++;
+    }
+    return -1;
+}
+
+ssize_t String16::findLast(char16_t c) const
+{
+    const char16_t* str = string();
+    const char16_t* p = str;
+    const char16_t* e = p + size();
+    while (p < e) {
+        e--;
+        if (*e == c) {
+            return e-str;
+        }
+    }
+    return -1;
+}
+
+bool String16::startsWith(const String16& prefix) const
+{
+    const size_t ps = prefix.size();
+    if (ps > size()) return false;
+    return strzcmp16(mString, ps, prefix.string(), ps) == 0;
+}
+
+bool String16::startsWith(const char16_t* prefix) const
+{
+    const size_t ps = strlen16(prefix);
+    if (ps > size()) return false;
+    return strncmp16(mString, prefix, ps) == 0;
+}
+
+status_t String16::makeLower()
+{
+    const size_t N = size();
+    const char16_t* str = string();
+    char16_t* edit = NULL;
+    for (size_t i=0; i<N; i++) {
+        const char16_t v = str[i];
+        if (v >= 'A' && v <= 'Z') {
+            if (!edit) {
+                SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit();
+                if (!buf) {
+                    return NO_MEMORY;
+                }
+                edit = (char16_t*)buf->data();
+                mString = str = edit;
+            }
+            edit[i] = tolower((char)v);
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
+{
+    const size_t N = size();
+    const char16_t* str = string();
+    char16_t* edit = NULL;
+    for (size_t i=0; i<N; i++) {
+        if (str[i] == replaceThis) {
+            if (!edit) {
+                SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit();
+                if (!buf) {
+                    return NO_MEMORY;
+                }
+                edit = (char16_t*)buf->data();
+                mString = str = edit;
+            }
+            edit[i] = withThis;
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t String16::remove(size_t len, size_t begin)
+{
+    const size_t N = size();
+    if (begin >= N) {
+        SharedBuffer::bufferFromData(mString)->release();
+        mString = getEmptyString();
+        return NO_ERROR;
+    }
+    if ((begin+len) > N) len = N-begin;
+    if (begin == 0 && len == N) {
+        return NO_ERROR;
+    }
+
+    if (begin > 0) {
+        SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+            ->editResize((N+1)*sizeof(char16_t));
+        if (!buf) {
+            return NO_MEMORY;
+        }
+        char16_t* str = (char16_t*)buf->data();
+        memmove(str, str+begin, (N-begin+1)*sizeof(char16_t));
+        mString = str;
+    }
+    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+        ->editResize((len+1)*sizeof(char16_t));
+    if (buf) {
+        char16_t* str = (char16_t*)buf->data();
+        str[len] = 0;
+        mString = str;
+        return NO_ERROR;
+    }
+    return NO_MEMORY;
+}
+
+}; // namespace android
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
new file mode 100644
index 0000000..e852d77
--- /dev/null
+++ b/libutils/String8.cpp
@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#include <utils/String8.h>
+
+#include <utils/Log.h>
+#include <utils/Unicode.h>
+#include <utils/SharedBuffer.h>
+#include <utils/String16.h>
+#include <utils/threads.h>
+
+#include <ctype.h>
+
+/*
+ * Functions outside android is below the namespace android, since they use
+ * functions and constants in android namespace.
+ */
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+// Separator used by resource paths. This is not platform dependent contrary
+// to OS_PATH_SEPARATOR.
+#define RES_PATH_SEPARATOR '/'
+
+static SharedBuffer* gEmptyStringBuf = NULL;
+static char* gEmptyString = NULL;
+
+extern int gDarwinCantLoadAllObjects;
+int gDarwinIsReallyAnnoying;
+
+void initialize_string8();
+
+static inline char* getEmptyString()
+{
+    gEmptyStringBuf->acquire();
+    return gEmptyString;
+}
+
+void initialize_string8()
+{
+    // HACK: This dummy dependency forces linking libutils Static.cpp,
+    // which is needed to initialize String8/String16 classes.
+    // These variables are named for Darwin, but are needed elsewhere too,
+    // including static linking on any platform.
+    gDarwinIsReallyAnnoying = gDarwinCantLoadAllObjects;
+
+    SharedBuffer* buf = SharedBuffer::alloc(1);
+    char* str = (char*)buf->data();
+    *str = 0;
+    gEmptyStringBuf = buf;
+    gEmptyString = str;
+}
+
+void terminate_string8()
+{
+    SharedBuffer::bufferFromData(gEmptyString)->release();
+    gEmptyStringBuf = NULL;
+    gEmptyString = NULL;
+}
+
+// ---------------------------------------------------------------------------
+
+static char* allocFromUTF8(const char* in, size_t len)
+{
+    if (len > 0) {
+        SharedBuffer* buf = SharedBuffer::alloc(len+1);
+        ALOG_ASSERT(buf, "Unable to allocate shared buffer");
+        if (buf) {
+            char* str = (char*)buf->data();
+            memcpy(str, in, len);
+            str[len] = 0;
+            return str;
+        }
+        return NULL;
+    }
+
+    return getEmptyString();
+}
+
+static char* allocFromUTF16(const char16_t* in, size_t len)
+{
+    if (len == 0) return getEmptyString();
+
+    const ssize_t bytes = utf16_to_utf8_length(in, len);
+    if (bytes < 0) {
+        return getEmptyString();
+    }
+
+    SharedBuffer* buf = SharedBuffer::alloc(bytes+1);
+    ALOG_ASSERT(buf, "Unable to allocate shared buffer");
+    if (!buf) {
+        return getEmptyString();
+    }
+
+    char* str = (char*)buf->data();
+    utf16_to_utf8(in, len, str);
+    return str;
+}
+
+static char* allocFromUTF32(const char32_t* in, size_t len)
+{
+    if (len == 0) {
+        return getEmptyString();
+    }
+
+    const ssize_t bytes = utf32_to_utf8_length(in, len);
+    if (bytes < 0) {
+        return getEmptyString();
+    }
+
+    SharedBuffer* buf = SharedBuffer::alloc(bytes+1);
+    ALOG_ASSERT(buf, "Unable to allocate shared buffer");
+    if (!buf) {
+        return getEmptyString();
+    }
+
+    char* str = (char*) buf->data();
+    utf32_to_utf8(in, len, str);
+
+    return str;
+}
+
+// ---------------------------------------------------------------------------
+
+String8::String8()
+    : mString(getEmptyString())
+{
+}
+
+String8::String8(StaticLinkage)
+    : mString(0)
+{
+    // this constructor is used when we can't rely on the static-initializers
+    // having run. In this case we always allocate an empty string. It's less
+    // efficient than using getEmptyString(), but we assume it's uncommon.
+
+    char* data = static_cast<char*>(
+            SharedBuffer::alloc(sizeof(char))->data());
+    data[0] = 0;
+    mString = data;
+}
+
+String8::String8(const String8& o)
+    : mString(o.mString)
+{
+    SharedBuffer::bufferFromData(mString)->acquire();
+}
+
+String8::String8(const char* o)
+    : mString(allocFromUTF8(o, strlen(o)))
+{
+    if (mString == NULL) {
+        mString = getEmptyString();
+    }
+}
+
+String8::String8(const char* o, size_t len)
+    : mString(allocFromUTF8(o, len))
+{
+    if (mString == NULL) {
+        mString = getEmptyString();
+    }
+}
+
+String8::String8(const String16& o)
+    : mString(allocFromUTF16(o.string(), o.size()))
+{
+}
+
+String8::String8(const char16_t* o)
+    : mString(allocFromUTF16(o, strlen16(o)))
+{
+}
+
+String8::String8(const char16_t* o, size_t len)
+    : mString(allocFromUTF16(o, len))
+{
+}
+
+String8::String8(const char32_t* o)
+    : mString(allocFromUTF32(o, strlen32(o)))
+{
+}
+
+String8::String8(const char32_t* o, size_t len)
+    : mString(allocFromUTF32(o, len))
+{
+}
+
+String8::~String8()
+{
+    SharedBuffer::bufferFromData(mString)->release();
+}
+
+String8 String8::format(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+
+    String8 result(formatV(fmt, args));
+
+    va_end(args);
+    return result;
+}
+
+String8 String8::formatV(const char* fmt, va_list args)
+{
+    String8 result;
+    result.appendFormatV(fmt, args);
+    return result;
+}
+
+void String8::clear() {
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = getEmptyString();
+}
+
+void String8::setTo(const String8& other)
+{
+    SharedBuffer::bufferFromData(other.mString)->acquire();
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = other.mString;
+}
+
+status_t String8::setTo(const char* other)
+{
+    const char *newString = allocFromUTF8(other, strlen(other));
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = newString;
+    if (mString) return NO_ERROR;
+
+    mString = getEmptyString();
+    return NO_MEMORY;
+}
+
+status_t String8::setTo(const char* other, size_t len)
+{
+    const char *newString = allocFromUTF8(other, len);
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = newString;
+    if (mString) return NO_ERROR;
+
+    mString = getEmptyString();
+    return NO_MEMORY;
+}
+
+status_t String8::setTo(const char16_t* other, size_t len)
+{
+    const char *newString = allocFromUTF16(other, len);
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = newString;
+    if (mString) return NO_ERROR;
+
+    mString = getEmptyString();
+    return NO_MEMORY;
+}
+
+status_t String8::setTo(const char32_t* other, size_t len)
+{
+    const char *newString = allocFromUTF32(other, len);
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = newString;
+    if (mString) return NO_ERROR;
+
+    mString = getEmptyString();
+    return NO_MEMORY;
+}
+
+status_t String8::append(const String8& other)
+{
+    const size_t otherLen = other.bytes();
+    if (bytes() == 0) {
+        setTo(other);
+        return NO_ERROR;
+    } else if (otherLen == 0) {
+        return NO_ERROR;
+    }
+
+    return real_append(other.string(), otherLen);
+}
+
+status_t String8::append(const char* other)
+{
+    return append(other, strlen(other));
+}
+
+status_t String8::append(const char* other, size_t otherLen)
+{
+    if (bytes() == 0) {
+        return setTo(other, otherLen);
+    } else if (otherLen == 0) {
+        return NO_ERROR;
+    }
+
+    return real_append(other, otherLen);
+}
+
+status_t String8::appendFormat(const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+
+    status_t result = appendFormatV(fmt, args);
+
+    va_end(args);
+    return result;
+}
+
+status_t String8::appendFormatV(const char* fmt, va_list args)
+{
+    int result = NO_ERROR;
+    int n = vsnprintf(NULL, 0, fmt, args);
+    if (n != 0) {
+        size_t oldLength = length();
+        char* buf = lockBuffer(oldLength + n);
+        if (buf) {
+            vsnprintf(buf + oldLength, n + 1, fmt, args);
+        } else {
+            result = NO_MEMORY;
+        }
+    }
+    return result;
+}
+
+status_t String8::real_append(const char* other, size_t otherLen)
+{
+    const size_t myLen = bytes();
+    
+    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+        ->editResize(myLen+otherLen+1);
+    if (buf) {
+        char* str = (char*)buf->data();
+        mString = str;
+        str += myLen;
+        memcpy(str, other, otherLen);
+        str[otherLen] = '\0';
+        return NO_ERROR;
+    }
+    return NO_MEMORY;
+}
+
+char* String8::lockBuffer(size_t size)
+{
+    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+        ->editResize(size+1);
+    if (buf) {
+        char* str = (char*)buf->data();
+        mString = str;
+        return str;
+    }
+    return NULL;
+}
+
+void String8::unlockBuffer()
+{
+    unlockBuffer(strlen(mString));
+}
+
+status_t String8::unlockBuffer(size_t size)
+{
+    if (size != this->size()) {
+        SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
+            ->editResize(size+1);
+        if (! buf) {
+            return NO_MEMORY;
+        }
+
+        char* str = (char*)buf->data();
+        str[size] = 0;
+        mString = str;
+    }
+
+    return NO_ERROR;
+}
+
+ssize_t String8::find(const char* other, size_t start) const
+{
+    size_t len = size();
+    if (start >= len) {
+        return -1;
+    }
+    const char* s = mString+start;
+    const char* p = strstr(s, other);
+    return p ? p-mString : -1;
+}
+
+void String8::toLower()
+{
+    toLower(0, size());
+}
+
+void String8::toLower(size_t start, size_t length)
+{
+    const size_t len = size();
+    if (start >= len) {
+        return;
+    }
+    if (start+length > len) {
+        length = len-start;
+    }
+    char* buf = lockBuffer(len);
+    buf += start;
+    while (length > 0) {
+        *buf = tolower(*buf);
+        buf++;
+        length--;
+    }
+    unlockBuffer(len);
+}
+
+void String8::toUpper()
+{
+    toUpper(0, size());
+}
+
+void String8::toUpper(size_t start, size_t length)
+{
+    const size_t len = size();
+    if (start >= len) {
+        return;
+    }
+    if (start+length > len) {
+        length = len-start;
+    }
+    char* buf = lockBuffer(len);
+    buf += start;
+    while (length > 0) {
+        *buf = toupper(*buf);
+        buf++;
+        length--;
+    }
+    unlockBuffer(len);
+}
+
+size_t String8::getUtf32Length() const
+{
+    return utf8_to_utf32_length(mString, length());
+}
+
+int32_t String8::getUtf32At(size_t index, size_t *next_index) const
+{
+    return utf32_from_utf8_at(mString, length(), index, next_index);
+}
+
+void String8::getUtf32(char32_t* dst) const
+{
+    utf8_to_utf32(mString, length(), dst);
+}
+
+// ---------------------------------------------------------------------------
+// Path functions
+
+void String8::setPathName(const char* name)
+{
+    setPathName(name, strlen(name));
+}
+
+void String8::setPathName(const char* name, size_t len)
+{
+    char* buf = lockBuffer(len);
+
+    memcpy(buf, name, len);
+
+    // remove trailing path separator, if present
+    if (len > 0 && buf[len-1] == OS_PATH_SEPARATOR)
+        len--;
+
+    buf[len] = '\0';
+
+    unlockBuffer(len);
+}
+
+String8 String8::getPathLeaf(void) const
+{
+    const char* cp;
+    const char*const buf = mString;
+
+    cp = strrchr(buf, OS_PATH_SEPARATOR);
+    if (cp == NULL)
+        return String8(*this);
+    else
+        return String8(cp+1);
+}
+
+String8 String8::getPathDir(void) const
+{
+    const char* cp;
+    const char*const str = mString;
+
+    cp = strrchr(str, OS_PATH_SEPARATOR);
+    if (cp == NULL)
+        return String8("");
+    else
+        return String8(str, cp - str);
+}
+
+String8 String8::walkPath(String8* outRemains) const
+{
+    const char* cp;
+    const char*const str = mString;
+    const char* buf = str;
+
+    cp = strchr(buf, OS_PATH_SEPARATOR);
+    if (cp == buf) {
+        // don't include a leading '/'.
+        buf = buf+1;
+        cp = strchr(buf, OS_PATH_SEPARATOR);
+    }
+
+    if (cp == NULL) {
+        String8 res = buf != str ? String8(buf) : *this;
+        if (outRemains) *outRemains = String8("");
+        return res;
+    }
+
+    String8 res(buf, cp-buf);
+    if (outRemains) *outRemains = String8(cp+1);
+    return res;
+}
+
+/*
+ * Helper function for finding the start of an extension in a pathname.
+ *
+ * Returns a pointer inside mString, or NULL if no extension was found.
+ */
+char* String8::find_extension(void) const
+{
+    const char* lastSlash;
+    const char* lastDot;
+    int extLen;
+    const char* const str = mString;
+
+    // only look at the filename
+    lastSlash = strrchr(str, OS_PATH_SEPARATOR);
+    if (lastSlash == NULL)
+        lastSlash = str;
+    else
+        lastSlash++;
+
+    // find the last dot
+    lastDot = strrchr(lastSlash, '.');
+    if (lastDot == NULL)
+        return NULL;
+
+    // looks good, ship it
+    return const_cast<char*>(lastDot);
+}
+
+String8 String8::getPathExtension(void) const
+{
+    char* ext;
+
+    ext = find_extension();
+    if (ext != NULL)
+        return String8(ext);
+    else
+        return String8("");
+}
+
+String8 String8::getBasePath(void) const
+{
+    char* ext;
+    const char* const str = mString;
+
+    ext = find_extension();
+    if (ext == NULL)
+        return String8(*this);
+    else
+        return String8(str, ext - str);
+}
+
+String8& String8::appendPath(const char* name)
+{
+    // TODO: The test below will fail for Win32 paths. Fix later or ignore.
+    if (name[0] != OS_PATH_SEPARATOR) {
+        if (*name == '\0') {
+            // nothing to do
+            return *this;
+        }
+
+        size_t len = length();
+        if (len == 0) {
+            // no existing filename, just use the new one
+            setPathName(name);
+            return *this;
+        }
+
+        // make room for oldPath + '/' + newPath
+        int newlen = strlen(name);
+
+        char* buf = lockBuffer(len+1+newlen);
+
+        // insert a '/' if needed
+        if (buf[len-1] != OS_PATH_SEPARATOR)
+            buf[len++] = OS_PATH_SEPARATOR;
+
+        memcpy(buf+len, name, newlen+1);
+        len += newlen;
+
+        unlockBuffer(len);
+
+        return *this;
+    } else {
+        setPathName(name);
+        return *this;
+    }
+}
+
+String8& String8::convertToResPath()
+{
+#if OS_PATH_SEPARATOR != RES_PATH_SEPARATOR
+    size_t len = length();
+    if (len > 0) {
+        char * buf = lockBuffer(len);
+        for (char * end = buf + len; buf < end; ++buf) {
+            if (*buf == OS_PATH_SEPARATOR)
+                *buf = RES_PATH_SEPARATOR;
+        }
+        unlockBuffer(len);
+    }
+#endif
+    return *this;
+}
+
+}; // namespace android
diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp
new file mode 100644
index 0000000..ac8da88
--- /dev/null
+++ b/libutils/SystemClock.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+
+/*
+ * System clock functions.
+ */
+
+#ifdef HAVE_ANDROID_OS
+#include <linux/ioctl.h>
+#include <linux/rtc.h>
+#include <utils/Atomic.h>
+#include <linux/android_alarm.h>
+#endif
+
+#include <sys/time.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include <utils/SystemClock.h>
+#include <utils/Timers.h>
+
+#define LOG_TAG "SystemClock"
+#include <utils/Log.h>
+
+namespace android {
+
+/*
+ * native public static long uptimeMillis();
+ */
+int64_t uptimeMillis()
+{
+    int64_t when = systemTime(SYSTEM_TIME_MONOTONIC);
+    return (int64_t) nanoseconds_to_milliseconds(when);
+}
+
+/*
+ * native public static long elapsedRealtime();
+ */
+int64_t elapsedRealtime()
+{
+	return nanoseconds_to_milliseconds(elapsedRealtimeNano());
+}
+
+#define METHOD_CLOCK_GETTIME    0
+#define METHOD_IOCTL            1
+#define METHOD_SYSTEMTIME       2
+
+/*
+ * To debug/verify the timestamps returned by the kernel, change
+ * DEBUG_TIMESTAMP to 1 and call the timestamp routine from a single thread
+ * in the test program. b/10899829
+ */
+#define DEBUG_TIMESTAMP         0
+
+static const char *gettime_method_names[] = {
+    "clock_gettime",
+    "ioctl",
+    "systemTime",
+};
+
+#if DEBUG_TIMESTAMP
+static inline void checkTimeStamps(int64_t timestamp,
+                                   int64_t volatile *prevTimestampPtr,
+                                   int volatile *prevMethodPtr,
+                                   int curMethod)
+{
+    /*
+     * Disable the check for SDK since the prebuilt toolchain doesn't contain
+     * gettid, and int64_t is different on the ARM platform
+     * (ie long vs long long).
+     */
+#ifdef ARCH_ARM
+    int64_t prevTimestamp = *prevTimestampPtr;
+    int prevMethod = *prevMethodPtr;
+
+    if (timestamp < prevTimestamp) {
+        ALOGW("time going backwards: prev %lld(%s) vs now %lld(%s), tid=%d",
+              prevTimestamp, gettime_method_names[prevMethod],
+              timestamp, gettime_method_names[curMethod],
+              gettid());
+    }
+    // NOTE - not atomic and may generate spurious warnings if the 64-bit
+    // write is interrupted or not observed as a whole.
+    *prevTimestampPtr = timestamp;
+    *prevMethodPtr = curMethod;
+#endif
+}
+#else
+#define checkTimeStamps(timestamp, prevTimestampPtr, prevMethodPtr, curMethod)
+#endif
+
+/*
+ * native public static long elapsedRealtimeNano();
+ */
+int64_t elapsedRealtimeNano()
+{
+#ifdef HAVE_ANDROID_OS
+    struct timespec ts;
+    int result;
+    int64_t timestamp;
+#if DEBUG_TIMESTAMP
+    static volatile int64_t prevTimestamp;
+    static volatile int prevMethod;
+#endif
+
+#if 0
+    /*
+     * b/7100774
+     * clock_gettime appears to have clock skews and can sometimes return
+     * backwards values. Disable its use until we find out what's wrong.
+     */
+    result = clock_gettime(CLOCK_BOOTTIME, &ts);
+    if (result == 0) {
+        timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
+        checkTimeStamps(timestamp, &prevTimestamp, &prevMethod,
+                        METHOD_CLOCK_GETTIME);
+        return timestamp;
+    }
+#endif
+
+    // CLOCK_BOOTTIME doesn't exist, fallback to /dev/alarm
+    static int s_fd = -1;
+
+    if (s_fd == -1) {
+        int fd = open("/dev/alarm", O_RDONLY);
+        if (android_atomic_cmpxchg(-1, fd, &s_fd)) {
+            close(fd);
+        }
+    }
+
+    result = ioctl(s_fd,
+            ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts);
+
+    if (result == 0) {
+        timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
+        checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_IOCTL);
+        return timestamp;
+    }
+
+    // XXX: there was an error, probably because the driver didn't
+    // exist ... this should return
+    // a real error, like an exception!
+    timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+    checkTimeStamps(timestamp, &prevTimestamp, &prevMethod,
+                    METHOD_SYSTEMTIME);
+    return timestamp;
+#else
+    return systemTime(SYSTEM_TIME_MONOTONIC);
+#endif
+}
+
+}; // namespace android
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
new file mode 100644
index 0000000..ff74914
--- /dev/null
+++ b/libutils/Threads.cpp
@@ -0,0 +1,878 @@
+/*
+ * 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.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "libutils.threads"
+
+#include <utils/threads.h>
+#include <utils/Log.h>
+
+#include <cutils/sched_policy.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <errno.h>
+#include <assert.h>
+#include <unistd.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+# include <sched.h>
+# include <sys/resource.h>
+#ifdef HAVE_ANDROID_OS
+# include <bionic_pthread.h>
+#endif
+#elif defined(HAVE_WIN32_THREADS)
+# include <windows.h>
+# include <stdint.h>
+# include <process.h>
+# define HAVE_CREATETHREAD  // Cygwin, vs. HAVE__BEGINTHREADEX for MinGW
+#endif
+
+#if defined(HAVE_PRCTL)
+#include <sys/prctl.h>
+#endif
+
+/*
+ * ===========================================================================
+ *      Thread wrappers
+ * ===========================================================================
+ */
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+#if defined(HAVE_PTHREADS)
+// ----------------------------------------------------------------------------
+
+/*
+ * Create and run a new thread.
+ *
+ * We create it "detached", so it cleans up after itself.
+ */
+
+typedef void* (*android_pthread_entry)(void*);
+
+struct thread_data_t {
+    thread_func_t   entryFunction;
+    void*           userData;
+    int             priority;
+    char *          threadName;
+
+    // we use this trampoline when we need to set the priority with
+    // nice/setpriority, and name with prctl.
+    static int trampoline(const thread_data_t* t) {
+        thread_func_t f = t->entryFunction;
+        void* u = t->userData;
+        int prio = t->priority;
+        char * name = t->threadName;
+        delete t;
+        setpriority(PRIO_PROCESS, 0, prio);
+        if (prio >= ANDROID_PRIORITY_BACKGROUND) {
+            set_sched_policy(0, SP_BACKGROUND);
+        } else {
+            set_sched_policy(0, SP_FOREGROUND);
+        }
+        
+        if (name) {
+            androidSetThreadName(name);
+            free(name);
+        }
+        return f(u);
+    }
+};
+
+void androidSetThreadName(const char* name) {
+#if defined(HAVE_PRCTL)
+    // Mac OS doesn't have this, and we build libutil for the host too
+    int hasAt = 0;
+    int hasDot = 0;
+    const char *s = name;
+    while (*s) {
+        if (*s == '.') hasDot = 1;
+        else if (*s == '@') hasAt = 1;
+        s++;
+    }
+    int len = s - name;
+    if (len < 15 || hasAt || !hasDot) {
+        s = name;
+    } else {
+        s = name + len - 15;
+    }
+    prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0);
+#endif
+}
+
+int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
+                               void *userData,
+                               const char* threadName,
+                               int32_t threadPriority,
+                               size_t threadStackSize,
+                               android_thread_id_t *threadId)
+{
+    pthread_attr_t attr; 
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+#ifdef HAVE_ANDROID_OS  /* valgrind is rejecting RT-priority create reqs */
+    if (threadPriority != PRIORITY_DEFAULT || threadName != NULL) {
+        // Now that the pthread_t has a method to find the associated
+        // android_thread_id_t (pid) from pthread_t, it would be possible to avoid
+        // this trampoline in some cases as the parent could set the properties
+        // for the child.  However, there would be a race condition because the
+        // child becomes ready immediately, and it doesn't work for the name.
+        // prctl(PR_SET_NAME) only works for self; prctl(PR_SET_THREAD_NAME) was
+        // proposed but not yet accepted.
+        thread_data_t* t = new thread_data_t;
+        t->priority = threadPriority;
+        t->threadName = threadName ? strdup(threadName) : NULL;
+        t->entryFunction = entryFunction;
+        t->userData = userData;
+        entryFunction = (android_thread_func_t)&thread_data_t::trampoline;
+        userData = t;            
+    }
+#endif
+
+    if (threadStackSize) {
+        pthread_attr_setstacksize(&attr, threadStackSize);
+    }
+    
+    errno = 0;
+    pthread_t thread;
+    int result = pthread_create(&thread, &attr,
+                    (android_pthread_entry)entryFunction, userData);
+    pthread_attr_destroy(&attr);
+    if (result != 0) {
+        ALOGE("androidCreateRawThreadEtc failed (entry=%p, res=%d, errno=%d)\n"
+             "(android threadPriority=%d)",
+            entryFunction, result, errno, threadPriority);
+        return 0;
+    }
+
+    // Note that *threadID is directly available to the parent only, as it is
+    // assigned after the child starts.  Use memory barrier / lock if the child
+    // or other threads also need access.
+    if (threadId != NULL) {
+        *threadId = (android_thread_id_t)thread; // XXX: this is not portable
+    }
+    return 1;
+}
+
+#ifdef HAVE_ANDROID_OS
+static pthread_t android_thread_id_t_to_pthread(android_thread_id_t thread)
+{
+    return (pthread_t) thread;
+}
+#endif
+
+android_thread_id_t androidGetThreadId()
+{
+    return (android_thread_id_t)pthread_self();
+}
+
+// ----------------------------------------------------------------------------
+#elif defined(HAVE_WIN32_THREADS)
+// ----------------------------------------------------------------------------
+
+/*
+ * Trampoline to make us __stdcall-compliant.
+ *
+ * We're expected to delete "vDetails" when we're done.
+ */
+struct threadDetails {
+    int (*func)(void*);
+    void* arg;
+};
+static __stdcall unsigned int threadIntermediary(void* vDetails)
+{
+    struct threadDetails* pDetails = (struct threadDetails*) vDetails;
+    int result;
+
+    result = (*(pDetails->func))(pDetails->arg);
+
+    delete pDetails;
+
+    ALOG(LOG_VERBOSE, "thread", "thread exiting\n");
+    return (unsigned int) result;
+}
+
+/*
+ * Create and run a new thread.
+ */
+static bool doCreateThread(android_thread_func_t fn, void* arg, android_thread_id_t *id)
+{
+    HANDLE hThread;
+    struct threadDetails* pDetails = new threadDetails; // must be on heap
+    unsigned int thrdaddr;
+
+    pDetails->func = fn;
+    pDetails->arg = arg;
+
+#if defined(HAVE__BEGINTHREADEX)
+    hThread = (HANDLE) _beginthreadex(NULL, 0, threadIntermediary, pDetails, 0,
+                    &thrdaddr);
+    if (hThread == 0)
+#elif defined(HAVE_CREATETHREAD)
+    hThread = CreateThread(NULL, 0,
+                    (LPTHREAD_START_ROUTINE) threadIntermediary,
+                    (void*) pDetails, 0, (DWORD*) &thrdaddr);
+    if (hThread == NULL)
+#endif
+    {
+        ALOG(LOG_WARN, "thread", "WARNING: thread create failed\n");
+        return false;
+    }
+
+#if defined(HAVE_CREATETHREAD)
+    /* close the management handle */
+    CloseHandle(hThread);
+#endif
+
+    if (id != NULL) {
+      	*id = (android_thread_id_t)thrdaddr;
+    }
+
+    return true;
+}
+
+int androidCreateRawThreadEtc(android_thread_func_t fn,
+                               void *userData,
+                               const char* threadName,
+                               int32_t threadPriority,
+                               size_t threadStackSize,
+                               android_thread_id_t *threadId)
+{
+    return doCreateThread(  fn, userData, threadId);
+}
+
+android_thread_id_t androidGetThreadId()
+{
+    return (android_thread_id_t)GetCurrentThreadId();
+}
+
+// ----------------------------------------------------------------------------
+#else
+#error "Threads not supported"
+#endif
+
+// ----------------------------------------------------------------------------
+
+int androidCreateThread(android_thread_func_t fn, void* arg)
+{
+    return createThreadEtc(fn, arg);
+}
+
+int androidCreateThreadGetID(android_thread_func_t fn, void *arg, android_thread_id_t *id)
+{
+    return createThreadEtc(fn, arg, "android:unnamed_thread",
+                           PRIORITY_DEFAULT, 0, id);
+}
+
+static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc;
+
+int androidCreateThreadEtc(android_thread_func_t entryFunction,
+                            void *userData,
+                            const char* threadName,
+                            int32_t threadPriority,
+                            size_t threadStackSize,
+                            android_thread_id_t *threadId)
+{
+    return gCreateThreadFn(entryFunction, userData, threadName,
+        threadPriority, threadStackSize, threadId);
+}
+
+void androidSetCreateThreadFunc(android_create_thread_fn func)
+{
+    gCreateThreadFn = func;
+}
+
+pid_t androidGetTid()
+{
+#ifdef HAVE_GETTID
+    return gettid();
+#else
+    return getpid();
+#endif
+}
+
+#ifdef HAVE_ANDROID_OS
+int androidSetThreadPriority(pid_t tid, int pri)
+{
+    int rc = 0;
+    
+#if defined(HAVE_PTHREADS)
+    int lasterr = 0;
+
+    if (pri >= ANDROID_PRIORITY_BACKGROUND) {
+        rc = set_sched_policy(tid, SP_BACKGROUND);
+    } else if (getpriority(PRIO_PROCESS, tid) >= ANDROID_PRIORITY_BACKGROUND) {
+        rc = set_sched_policy(tid, SP_FOREGROUND);
+    }
+
+    if (rc) {
+        lasterr = errno;
+    }
+
+    if (setpriority(PRIO_PROCESS, tid, pri) < 0) {
+        rc = INVALID_OPERATION;
+    } else {
+        errno = lasterr;
+    }
+#endif
+    
+    return rc;
+}
+
+int androidGetThreadPriority(pid_t tid) {
+#if defined(HAVE_PTHREADS)
+    return getpriority(PRIO_PROCESS, tid);
+#else
+    return ANDROID_PRIORITY_NORMAL;
+#endif
+}
+
+#endif
+
+namespace android {
+
+/*
+ * ===========================================================================
+ *      Mutex class
+ * ===========================================================================
+ */
+
+#if defined(HAVE_PTHREADS)
+// implemented as inlines in threads.h
+#elif defined(HAVE_WIN32_THREADS)
+
+Mutex::Mutex()
+{
+    HANDLE hMutex;
+
+    assert(sizeof(hMutex) == sizeof(mState));
+
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    mState = (void*) hMutex;
+}
+
+Mutex::Mutex(const char* name)
+{
+    // XXX: name not used for now
+    HANDLE hMutex;
+
+    assert(sizeof(hMutex) == sizeof(mState));
+
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    mState = (void*) hMutex;
+}
+
+Mutex::Mutex(int type, const char* name)
+{
+    // XXX: type and name not used for now
+    HANDLE hMutex;
+
+    assert(sizeof(hMutex) == sizeof(mState));
+
+    hMutex = CreateMutex(NULL, FALSE, NULL);
+    mState = (void*) hMutex;
+}
+
+Mutex::~Mutex()
+{
+    CloseHandle((HANDLE) mState);
+}
+
+status_t Mutex::lock()
+{
+    DWORD dwWaitResult;
+    dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE);
+    return dwWaitResult != WAIT_OBJECT_0 ? -1 : NO_ERROR;
+}
+
+void Mutex::unlock()
+{
+    if (!ReleaseMutex((HANDLE) mState))
+        ALOG(LOG_WARN, "thread", "WARNING: bad result from unlocking mutex\n");
+}
+
+status_t Mutex::tryLock()
+{
+    DWORD dwWaitResult;
+
+    dwWaitResult = WaitForSingleObject((HANDLE) mState, 0);
+    if (dwWaitResult != WAIT_OBJECT_0 && dwWaitResult != WAIT_TIMEOUT)
+        ALOG(LOG_WARN, "thread", "WARNING: bad result from try-locking mutex\n");
+    return (dwWaitResult == WAIT_OBJECT_0) ? 0 : -1;
+}
+
+#else
+#error "Somebody forgot to implement threads for this platform."
+#endif
+
+
+/*
+ * ===========================================================================
+ *      Condition class
+ * ===========================================================================
+ */
+
+#if defined(HAVE_PTHREADS)
+// implemented as inlines in threads.h
+#elif defined(HAVE_WIN32_THREADS)
+
+/*
+ * Windows doesn't have a condition variable solution.  It's possible
+ * to create one, but it's easy to get it wrong.  For a discussion, and
+ * the origin of this implementation, see:
+ *
+ *  http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
+ *
+ * The implementation shown on the page does NOT follow POSIX semantics.
+ * As an optimization they require acquiring the external mutex before
+ * calling signal() and broadcast(), whereas POSIX only requires grabbing
+ * it before calling wait().  The implementation here has been un-optimized
+ * to have the correct behavior.
+ */
+typedef struct WinCondition {
+    // Number of waiting threads.
+    int                 waitersCount;
+
+    // Serialize access to waitersCount.
+    CRITICAL_SECTION    waitersCountLock;
+
+    // Semaphore used to queue up threads waiting for the condition to
+    // become signaled.
+    HANDLE              sema;
+
+    // An auto-reset event used by the broadcast/signal thread to wait
+    // for all the waiting thread(s) to wake up and be released from
+    // the semaphore.
+    HANDLE              waitersDone;
+
+    // This mutex wouldn't be necessary if we required that the caller
+    // lock the external mutex before calling signal() and broadcast().
+    // I'm trying to mimic pthread semantics though.
+    HANDLE              internalMutex;
+
+    // Keeps track of whether we were broadcasting or signaling.  This
+    // allows us to optimize the code if we're just signaling.
+    bool                wasBroadcast;
+
+    status_t wait(WinCondition* condState, HANDLE hMutex, nsecs_t* abstime)
+    {
+        // Increment the wait count, avoiding race conditions.
+        EnterCriticalSection(&condState->waitersCountLock);
+        condState->waitersCount++;
+        //printf("+++ wait: incr waitersCount to %d (tid=%ld)\n",
+        //    condState->waitersCount, getThreadId());
+        LeaveCriticalSection(&condState->waitersCountLock);
+    
+        DWORD timeout = INFINITE;
+        if (abstime) {
+            nsecs_t reltime = *abstime - systemTime();
+            if (reltime < 0)
+                reltime = 0;
+            timeout = reltime/1000000;
+        }
+        
+        // Atomically release the external mutex and wait on the semaphore.
+        DWORD res =
+            SignalObjectAndWait(hMutex, condState->sema, timeout, FALSE);
+    
+        //printf("+++ wait: awake (tid=%ld)\n", getThreadId());
+    
+        // Reacquire lock to avoid race conditions.
+        EnterCriticalSection(&condState->waitersCountLock);
+    
+        // No longer waiting.
+        condState->waitersCount--;
+    
+        // Check to see if we're the last waiter after a broadcast.
+        bool lastWaiter = (condState->wasBroadcast && condState->waitersCount == 0);
+    
+        //printf("+++ wait: lastWaiter=%d (wasBc=%d wc=%d)\n",
+        //    lastWaiter, condState->wasBroadcast, condState->waitersCount);
+    
+        LeaveCriticalSection(&condState->waitersCountLock);
+    
+        // If we're the last waiter thread during this particular broadcast
+        // then signal broadcast() that we're all awake.  It'll drop the
+        // internal mutex.
+        if (lastWaiter) {
+            // Atomically signal the "waitersDone" event and wait until we
+            // can acquire the internal mutex.  We want to do this in one step
+            // because it ensures that everybody is in the mutex FIFO before
+            // any thread has a chance to run.  Without it, another thread
+            // could wake up, do work, and hop back in ahead of us.
+            SignalObjectAndWait(condState->waitersDone, condState->internalMutex,
+                INFINITE, FALSE);
+        } else {
+            // Grab the internal mutex.
+            WaitForSingleObject(condState->internalMutex, INFINITE);
+        }
+    
+        // Release the internal and grab the external.
+        ReleaseMutex(condState->internalMutex);
+        WaitForSingleObject(hMutex, INFINITE);
+    
+        return res == WAIT_OBJECT_0 ? NO_ERROR : -1;
+    }
+} WinCondition;
+
+/*
+ * Constructor.  Set up the WinCondition stuff.
+ */
+Condition::Condition()
+{
+    WinCondition* condState = new WinCondition;
+
+    condState->waitersCount = 0;
+    condState->wasBroadcast = false;
+    // semaphore: no security, initial value of 0
+    condState->sema = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
+    InitializeCriticalSection(&condState->waitersCountLock);
+    // auto-reset event, not signaled initially
+    condState->waitersDone = CreateEvent(NULL, FALSE, FALSE, NULL);
+    // used so we don't have to lock external mutex on signal/broadcast
+    condState->internalMutex = CreateMutex(NULL, FALSE, NULL);
+
+    mState = condState;
+}
+
+/*
+ * Destructor.  Free Windows resources as well as our allocated storage.
+ */
+Condition::~Condition()
+{
+    WinCondition* condState = (WinCondition*) mState;
+    if (condState != NULL) {
+        CloseHandle(condState->sema);
+        CloseHandle(condState->waitersDone);
+        delete condState;
+    }
+}
+
+
+status_t Condition::wait(Mutex& mutex)
+{
+    WinCondition* condState = (WinCondition*) mState;
+    HANDLE hMutex = (HANDLE) mutex.mState;
+    
+    return ((WinCondition*)mState)->wait(condState, hMutex, NULL);
+}
+
+status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime)
+{
+    WinCondition* condState = (WinCondition*) mState;
+    HANDLE hMutex = (HANDLE) mutex.mState;
+    nsecs_t absTime = systemTime()+reltime;
+
+    return ((WinCondition*)mState)->wait(condState, hMutex, &absTime);
+}
+
+/*
+ * Signal the condition variable, allowing one thread to continue.
+ */
+void Condition::signal()
+{
+    WinCondition* condState = (WinCondition*) mState;
+
+    // Lock the internal mutex.  This ensures that we don't clash with
+    // broadcast().
+    WaitForSingleObject(condState->internalMutex, INFINITE);
+
+    EnterCriticalSection(&condState->waitersCountLock);
+    bool haveWaiters = (condState->waitersCount > 0);
+    LeaveCriticalSection(&condState->waitersCountLock);
+
+    // If no waiters, then this is a no-op.  Otherwise, knock the semaphore
+    // down a notch.
+    if (haveWaiters)
+        ReleaseSemaphore(condState->sema, 1, 0);
+
+    // Release internal mutex.
+    ReleaseMutex(condState->internalMutex);
+}
+
+/*
+ * Signal the condition variable, allowing all threads to continue.
+ *
+ * First we have to wake up all threads waiting on the semaphore, then
+ * we wait until all of the threads have actually been woken before
+ * releasing the internal mutex.  This ensures that all threads are woken.
+ */
+void Condition::broadcast()
+{
+    WinCondition* condState = (WinCondition*) mState;
+
+    // Lock the internal mutex.  This keeps the guys we're waking up
+    // from getting too far.
+    WaitForSingleObject(condState->internalMutex, INFINITE);
+
+    EnterCriticalSection(&condState->waitersCountLock);
+    bool haveWaiters = false;
+
+    if (condState->waitersCount > 0) {
+        haveWaiters = true;
+        condState->wasBroadcast = true;
+    }
+
+    if (haveWaiters) {
+        // Wake up all the waiters.
+        ReleaseSemaphore(condState->sema, condState->waitersCount, 0);
+
+        LeaveCriticalSection(&condState->waitersCountLock);
+
+        // Wait for all awakened threads to acquire the counting semaphore.
+        // The last guy who was waiting sets this.
+        WaitForSingleObject(condState->waitersDone, INFINITE);
+
+        // Reset wasBroadcast.  (No crit section needed because nobody
+        // else can wake up to poke at it.)
+        condState->wasBroadcast = 0;
+    } else {
+        // nothing to do
+        LeaveCriticalSection(&condState->waitersCountLock);
+    }
+
+    // Release internal mutex.
+    ReleaseMutex(condState->internalMutex);
+}
+
+#else
+#error "condition variables not supported on this platform"
+#endif
+
+// ----------------------------------------------------------------------------
+
+/*
+ * This is our thread object!
+ */
+
+Thread::Thread(bool canCallJava)
+    :   mCanCallJava(canCallJava),
+        mThread(thread_id_t(-1)),
+        mLock("Thread::mLock"),
+        mStatus(NO_ERROR),
+        mExitPending(false), mRunning(false)
+#ifdef HAVE_ANDROID_OS
+        , mTid(-1)
+#endif
+{
+}
+
+Thread::~Thread()
+{
+}
+
+status_t Thread::readyToRun()
+{
+    return NO_ERROR;
+}
+
+status_t Thread::run(const char* name, int32_t priority, size_t stack)
+{
+    Mutex::Autolock _l(mLock);
+
+    if (mRunning) {
+        // thread already started
+        return INVALID_OPERATION;
+    }
+
+    // reset status and exitPending to their default value, so we can
+    // try again after an error happened (either below, or in readyToRun())
+    mStatus = NO_ERROR;
+    mExitPending = false;
+    mThread = thread_id_t(-1);
+    
+    // hold a strong reference on ourself
+    mHoldSelf = this;
+
+    mRunning = true;
+
+    bool res;
+    if (mCanCallJava) {
+        res = createThreadEtc(_threadLoop,
+                this, name, priority, stack, &mThread);
+    } else {
+        res = androidCreateRawThreadEtc(_threadLoop,
+                this, name, priority, stack, &mThread);
+    }
+    
+    if (res == false) {
+        mStatus = UNKNOWN_ERROR;   // something happened!
+        mRunning = false;
+        mThread = thread_id_t(-1);
+        mHoldSelf.clear();  // "this" may have gone away after this.
+
+        return UNKNOWN_ERROR;
+    }
+    
+    // Do not refer to mStatus here: The thread is already running (may, in fact
+    // already have exited with a valid mStatus result). The NO_ERROR indication
+    // here merely indicates successfully starting the thread and does not
+    // imply successful termination/execution.
+    return NO_ERROR;
+
+    // Exiting scope of mLock is a memory barrier and allows new thread to run
+}
+
+int Thread::_threadLoop(void* user)
+{
+    Thread* const self = static_cast<Thread*>(user);
+
+    sp<Thread> strong(self->mHoldSelf);
+    wp<Thread> weak(strong);
+    self->mHoldSelf.clear();
+
+#ifdef HAVE_ANDROID_OS
+    // this is very useful for debugging with gdb
+    self->mTid = gettid();
+#endif
+
+    bool first = true;
+
+    do {
+        bool result;
+        if (first) {
+            first = false;
+            self->mStatus = self->readyToRun();
+            result = (self->mStatus == NO_ERROR);
+
+            if (result && !self->exitPending()) {
+                // Binder threads (and maybe others) rely on threadLoop
+                // running at least once after a successful ::readyToRun()
+                // (unless, of course, the thread has already been asked to exit
+                // at that point).
+                // This is because threads are essentially used like this:
+                //   (new ThreadSubclass())->run();
+                // The caller therefore does not retain a strong reference to
+                // the thread and the thread would simply disappear after the
+                // successful ::readyToRun() call instead of entering the
+                // threadLoop at least once.
+                result = self->threadLoop();
+            }
+        } else {
+            result = self->threadLoop();
+        }
+
+        // establish a scope for mLock
+        {
+        Mutex::Autolock _l(self->mLock);
+        if (result == false || self->mExitPending) {
+            self->mExitPending = true;
+            self->mRunning = false;
+            // clear thread ID so that requestExitAndWait() does not exit if
+            // called by a new thread using the same thread ID as this one.
+            self->mThread = thread_id_t(-1);
+            // note that interested observers blocked in requestExitAndWait are
+            // awoken by broadcast, but blocked on mLock until break exits scope
+            self->mThreadExitedCondition.broadcast();
+            break;
+        }
+        }
+        
+        // Release our strong reference, to let a chance to the thread
+        // to die a peaceful death.
+        strong.clear();
+        // And immediately, re-acquire a strong reference for the next loop
+        strong = weak.promote();
+    } while(strong != 0);
+    
+    return 0;
+}
+
+void Thread::requestExit()
+{
+    Mutex::Autolock _l(mLock);
+    mExitPending = true;
+}
+
+status_t Thread::requestExitAndWait()
+{
+    Mutex::Autolock _l(mLock);
+    if (mThread == getThreadId()) {
+        ALOGW(
+        "Thread (this=%p): don't call waitForExit() from this "
+        "Thread object's thread. It's a guaranteed deadlock!",
+        this);
+
+        return WOULD_BLOCK;
+    }
+    
+    mExitPending = true;
+
+    while (mRunning == true) {
+        mThreadExitedCondition.wait(mLock);
+    }
+    // This next line is probably not needed any more, but is being left for
+    // historical reference. Note that each interested party will clear flag.
+    mExitPending = false;
+
+    return mStatus;
+}
+
+status_t Thread::join()
+{
+    Mutex::Autolock _l(mLock);
+    if (mThread == getThreadId()) {
+        ALOGW(
+        "Thread (this=%p): don't call join() from this "
+        "Thread object's thread. It's a guaranteed deadlock!",
+        this);
+
+        return WOULD_BLOCK;
+    }
+
+    while (mRunning == true) {
+        mThreadExitedCondition.wait(mLock);
+    }
+
+    return mStatus;
+}
+
+bool Thread::isRunning() const {
+    Mutex::Autolock _l(mLock);
+    return mRunning;
+}
+
+#ifdef HAVE_ANDROID_OS
+pid_t Thread::getTid() const
+{
+    // mTid is not defined until the child initializes it, and the caller may need it earlier
+    Mutex::Autolock _l(mLock);
+    pid_t tid;
+    if (mRunning) {
+        pthread_t pthread = android_thread_id_t_to_pthread(mThread);
+        tid = __pthread_gettid(pthread);
+    } else {
+        ALOGW("Thread (this=%p): getTid() is undefined before run()", this);
+        tid = -1;
+    }
+    return tid;
+}
+#endif
+
+bool Thread::exitPending() const
+{
+    Mutex::Autolock _l(mLock);
+    return mExitPending;
+}
+
+
+
+};  // namespace android
diff --git a/libutils/Timers.cpp b/libutils/Timers.cpp
new file mode 100644
index 0000000..5293cd2
--- /dev/null
+++ b/libutils/Timers.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Timer functions.
+//
+#include <utils/Timers.h>
+#include <utils/Log.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifdef HAVE_WIN32_THREADS
+#include <windows.h>
+#endif
+
+nsecs_t systemTime(int clock)
+{
+#if defined(HAVE_POSIX_CLOCKS)
+    static const clockid_t clocks[] = {
+            CLOCK_REALTIME,
+            CLOCK_MONOTONIC,
+            CLOCK_PROCESS_CPUTIME_ID,
+            CLOCK_THREAD_CPUTIME_ID,
+            CLOCK_BOOTTIME
+    };
+    struct timespec t;
+    t.tv_sec = t.tv_nsec = 0;
+    clock_gettime(clocks[clock], &t);
+    return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec;
+#else
+    // we don't support the clocks here.
+    struct timeval t;
+    t.tv_sec = t.tv_usec = 0;
+    gettimeofday(&t, NULL);
+    return nsecs_t(t.tv_sec)*1000000000LL + nsecs_t(t.tv_usec)*1000LL;
+#endif
+}
+
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime)
+{
+    int timeoutDelayMillis;
+    if (timeoutTime > referenceTime) {
+        uint64_t timeoutDelay = uint64_t(timeoutTime - referenceTime);
+        if (timeoutDelay > uint64_t((INT_MAX - 1) * 1000000LL)) {
+            timeoutDelayMillis = -1;
+        } else {
+            timeoutDelayMillis = (timeoutDelay + 999999LL) / 1000000LL;
+        }
+    } else {
+        timeoutDelayMillis = 0;
+    }
+    return timeoutDelayMillis;
+}
diff --git a/libutils/Tokenizer.cpp b/libutils/Tokenizer.cpp
new file mode 100644
index 0000000..7067533
--- /dev/null
+++ b/libutils/Tokenizer.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#define LOG_TAG "Tokenizer"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <utils/Log.h>
+#include <utils/Tokenizer.h>
+
+// Enables debug output for the tokenizer.
+#define DEBUG_TOKENIZER 0
+
+
+namespace android {
+
+static inline bool isDelimiter(char ch, const char* delimiters) {
+    return strchr(delimiters, ch) != NULL;
+}
+
+Tokenizer::Tokenizer(const String8& filename, FileMap* fileMap, char* buffer,
+        bool ownBuffer, size_t length) :
+        mFilename(filename), mFileMap(fileMap),
+        mBuffer(buffer), mOwnBuffer(ownBuffer), mLength(length),
+        mCurrent(buffer), mLineNumber(1) {
+}
+
+Tokenizer::~Tokenizer() {
+    if (mFileMap) {
+        mFileMap->release();
+    }
+    if (mOwnBuffer) {
+        delete[] mBuffer;
+    }
+}
+
+status_t Tokenizer::open(const String8& filename, Tokenizer** outTokenizer) {
+    *outTokenizer = NULL;
+
+    int result = NO_ERROR;
+    int fd = ::open(filename.string(), O_RDONLY);
+    if (fd < 0) {
+        result = -errno;
+        ALOGE("Error opening file '%s', %s.", filename.string(), strerror(errno));
+    } else {
+        struct stat stat;
+        if (fstat(fd, &stat)) {
+            result = -errno;
+            ALOGE("Error getting size of file '%s', %s.", filename.string(), strerror(errno));
+        } else {
+            size_t length = size_t(stat.st_size);
+
+            FileMap* fileMap = new FileMap();
+            bool ownBuffer = false;
+            char* buffer;
+            if (fileMap->create(NULL, fd, 0, length, true)) {
+                fileMap->advise(FileMap::SEQUENTIAL);
+                buffer = static_cast<char*>(fileMap->getDataPtr());
+            } else {
+                fileMap->release();
+                fileMap = NULL;
+
+                // Fall back to reading into a buffer since we can't mmap files in sysfs.
+                // The length we obtained from stat is wrong too (it will always be 4096)
+                // so we must trust that read will read the entire file.
+                buffer = new char[length];
+                ownBuffer = true;
+                ssize_t nrd = read(fd, buffer, length);
+                if (nrd < 0) {
+                    result = -errno;
+                    ALOGE("Error reading file '%s', %s.", filename.string(), strerror(errno));
+                    delete[] buffer;
+                    buffer = NULL;
+                } else {
+                    length = size_t(nrd);
+                }
+            }
+
+            if (!result) {
+                *outTokenizer = new Tokenizer(filename, fileMap, buffer, ownBuffer, length);
+            }
+        }
+        close(fd);
+    }
+    return result;
+}
+
+status_t Tokenizer::fromContents(const String8& filename,
+        const char* contents, Tokenizer** outTokenizer) {
+    *outTokenizer = new Tokenizer(filename, NULL,
+            const_cast<char*>(contents), false, strlen(contents));
+    return OK;
+}
+
+String8 Tokenizer::getLocation() const {
+    String8 result;
+    result.appendFormat("%s:%d", mFilename.string(), mLineNumber);
+    return result;
+}
+
+String8 Tokenizer::peekRemainderOfLine() const {
+    const char* end = getEnd();
+    const char* eol = mCurrent;
+    while (eol != end) {
+        char ch = *eol;
+        if (ch == '\n') {
+            break;
+        }
+        eol += 1;
+    }
+    return String8(mCurrent, eol - mCurrent);
+}
+
+String8 Tokenizer::nextToken(const char* delimiters) {
+#if DEBUG_TOKENIZER
+    ALOGD("nextToken");
+#endif
+    const char* end = getEnd();
+    const char* tokenStart = mCurrent;
+    while (mCurrent != end) {
+        char ch = *mCurrent;
+        if (ch == '\n' || isDelimiter(ch, delimiters)) {
+            break;
+        }
+        mCurrent += 1;
+    }
+    return String8(tokenStart, mCurrent - tokenStart);
+}
+
+void Tokenizer::nextLine() {
+#if DEBUG_TOKENIZER
+    ALOGD("nextLine");
+#endif
+    const char* end = getEnd();
+    while (mCurrent != end) {
+        char ch = *(mCurrent++);
+        if (ch == '\n') {
+            mLineNumber += 1;
+            break;
+        }
+    }
+}
+
+void Tokenizer::skipDelimiters(const char* delimiters) {
+#if DEBUG_TOKENIZER
+    ALOGD("skipDelimiters");
+#endif
+    const char* end = getEnd();
+    while (mCurrent != end) {
+        char ch = *mCurrent;
+        if (ch == '\n' || !isDelimiter(ch, delimiters)) {
+            break;
+        }
+        mCurrent += 1;
+    }
+}
+
+} // namespace android
diff --git a/include/cutils/zygote.h b/libutils/Trace.cpp
similarity index 63%
copy from include/cutils/zygote.h
copy to libutils/Trace.cpp
index a7480d3..36fd802 100644
--- a/include/cutils/zygote.h
+++ b/libutils/Trace.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2012 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.
@@ -14,18 +14,12 @@
  * limitations under the License.
  */
 
-#ifndef __CUTILS_ZYGOTE_H
-#define __CUTILS_ZYGOTE_H
+#include <utils/misc.h>
+#include <utils/Trace.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+static void traceInit() __attribute__((constructor));
 
-int zygote_run_oneshot(int sendStdio, int argc, const char **argv);
-int zygote_run(int argc, const char **argv);
-
-#ifdef __cplusplus
+static void traceInit()
+{
+    ::android::add_sysprop_change_callback(atrace_update_tags, 0);
 }
-#endif
-
-#endif /* __CUTILS_ZYGOTE_H */
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
new file mode 100644
index 0000000..a66e3bb
--- /dev/null
+++ b/libutils/Unicode.cpp
@@ -0,0 +1,606 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#include <utils/Unicode.h>
+
+#include <stddef.h>
+
+#ifdef HAVE_WINSOCK
+# undef  nhtol
+# undef  htonl
+# undef  nhtos
+# undef  htons
+
+# ifdef HAVE_LITTLE_ENDIAN
+#  define ntohl(x)    ( ((x) << 24) | (((x) >> 24) & 255) | (((x) << 8) & 0xff0000) | (((x) >> 8) & 0xff00) )
+#  define htonl(x)    ntohl(x)
+#  define ntohs(x)    ( (((x) << 8) & 0xff00) | (((x) >> 8) & 255) )
+#  define htons(x)    ntohs(x)
+# else
+#  define ntohl(x)    (x)
+#  define htonl(x)    (x)
+#  define ntohs(x)    (x)
+#  define htons(x)    (x)
+# endif
+#else
+# include <netinet/in.h>
+#endif
+
+extern "C" {
+
+static const char32_t kByteMask = 0x000000BF;
+static const char32_t kByteMark = 0x00000080;
+
+// Surrogates aren't valid for UTF-32 characters, so define some
+// constants that will let us screen them out.
+static const char32_t kUnicodeSurrogateHighStart  = 0x0000D800;
+static const char32_t kUnicodeSurrogateHighEnd    = 0x0000DBFF;
+static const char32_t kUnicodeSurrogateLowStart   = 0x0000DC00;
+static const char32_t kUnicodeSurrogateLowEnd     = 0x0000DFFF;
+static const char32_t kUnicodeSurrogateStart      = kUnicodeSurrogateHighStart;
+static const char32_t kUnicodeSurrogateEnd        = kUnicodeSurrogateLowEnd;
+static const char32_t kUnicodeMaxCodepoint        = 0x0010FFFF;
+
+// Mask used to set appropriate bits in first byte of UTF-8 sequence,
+// indexed by number of bytes in the sequence.
+// 0xxxxxxx
+// -> (00-7f) 7bit. Bit mask for the first byte is 0x00000000
+// 110yyyyx 10xxxxxx
+// -> (c0-df)(80-bf) 11bit. Bit mask is 0x000000C0
+// 1110yyyy 10yxxxxx 10xxxxxx
+// -> (e0-ef)(80-bf)(80-bf) 16bit. Bit mask is 0x000000E0
+// 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx
+// -> (f0-f7)(80-bf)(80-bf)(80-bf) 21bit. Bit mask is 0x000000F0
+static const char32_t kFirstByteMark[] = {
+    0x00000000, 0x00000000, 0x000000C0, 0x000000E0, 0x000000F0
+};
+
+// --------------------------------------------------------------------------
+// UTF-32
+// --------------------------------------------------------------------------
+
+/**
+ * Return number of UTF-8 bytes required for the character. If the character
+ * is invalid, return size of 0.
+ */
+static inline size_t utf32_codepoint_utf8_length(char32_t srcChar)
+{
+    // Figure out how many bytes the result will require.
+    if (srcChar < 0x00000080) {
+        return 1;
+    } else if (srcChar < 0x00000800) {
+        return 2;
+    } else if (srcChar < 0x00010000) {
+        if ((srcChar < kUnicodeSurrogateStart) || (srcChar > kUnicodeSurrogateEnd)) {
+            return 3;
+        } else {
+            // Surrogates are invalid UTF-32 characters.
+            return 0;
+        }
+    }
+    // Max code point for Unicode is 0x0010FFFF.
+    else if (srcChar <= kUnicodeMaxCodepoint) {
+        return 4;
+    } else {
+        // Invalid UTF-32 character.
+        return 0;
+    }
+}
+
+// Write out the source character to <dstP>.
+
+static inline void utf32_codepoint_to_utf8(uint8_t* dstP, char32_t srcChar, size_t bytes)
+{
+    dstP += bytes;
+    switch (bytes)
+    {   /* note: everything falls through. */
+        case 4: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
+        case 3: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
+        case 2: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
+        case 1: *--dstP = (uint8_t)(srcChar | kFirstByteMark[bytes]);
+    }
+}
+
+size_t strlen32(const char32_t *s)
+{
+  const char32_t *ss = s;
+  while ( *ss )
+    ss++;
+  return ss-s;
+}
+
+size_t strnlen32(const char32_t *s, size_t maxlen)
+{
+  const char32_t *ss = s;
+  while ((maxlen > 0) && *ss) {
+    ss++;
+    maxlen--;
+  }
+  return ss-s;
+}
+
+static inline int32_t utf32_at_internal(const char* cur, size_t *num_read)
+{
+    const char first_char = *cur;
+    if ((first_char & 0x80) == 0) { // ASCII
+        *num_read = 1;
+        return *cur;
+    }
+    cur++;
+    char32_t mask, to_ignore_mask;
+    size_t num_to_read = 0;
+    char32_t utf32 = first_char;
+    for (num_to_read = 1, mask = 0x40, to_ignore_mask = 0xFFFFFF80;
+         (first_char & mask);
+         num_to_read++, to_ignore_mask |= mask, mask >>= 1) {
+        // 0x3F == 00111111
+        utf32 = (utf32 << 6) + (*cur++ & 0x3F);
+    }
+    to_ignore_mask |= mask;
+    utf32 &= ~(to_ignore_mask << (6 * (num_to_read - 1)));
+
+    *num_read = num_to_read;
+    return static_cast<int32_t>(utf32);
+}
+
+int32_t utf32_from_utf8_at(const char *src, size_t src_len, size_t index, size_t *next_index)
+{
+    if (index >= src_len) {
+        return -1;
+    }
+    size_t dummy_index;
+    if (next_index == NULL) {
+        next_index = &dummy_index;
+    }
+    size_t num_read;
+    int32_t ret = utf32_at_internal(src + index, &num_read);
+    if (ret >= 0) {
+        *next_index = index + num_read;
+    }
+
+    return ret;
+}
+
+ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len)
+{
+    if (src == NULL || src_len == 0) {
+        return -1;
+    }
+
+    size_t ret = 0;
+    const char32_t *end = src + src_len;
+    while (src < end) {
+        ret += utf32_codepoint_utf8_length(*src++);
+    }
+    return ret;
+}
+
+void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst)
+{
+    if (src == NULL || src_len == 0 || dst == NULL) {
+        return;
+    }
+
+    const char32_t *cur_utf32 = src;
+    const char32_t *end_utf32 = src + src_len;
+    char *cur = dst;
+    while (cur_utf32 < end_utf32) {
+        size_t len = utf32_codepoint_utf8_length(*cur_utf32);
+        utf32_codepoint_to_utf8((uint8_t *)cur, *cur_utf32++, len);
+        cur += len;
+    }
+    *cur = '\0';
+}
+
+// --------------------------------------------------------------------------
+// UTF-16
+// --------------------------------------------------------------------------
+
+int strcmp16(const char16_t *s1, const char16_t *s2)
+{
+  char16_t ch;
+  int d = 0;
+
+  while ( 1 ) {
+    d = (int)(ch = *s1++) - (int)*s2++;
+    if ( d || !ch )
+      break;
+  }
+
+  return d;
+}
+
+int strncmp16(const char16_t *s1, const char16_t *s2, size_t n)
+{
+  char16_t ch;
+  int d = 0;
+
+  while ( n-- ) {
+    d = (int)(ch = *s1++) - (int)*s2++;
+    if ( d || !ch )
+      break;
+  }
+
+  return d;
+}
+
+char16_t *strcpy16(char16_t *dst, const char16_t *src)
+{
+  char16_t *q = dst;
+  const char16_t *p = src;
+  char16_t ch;
+
+  do {
+    *q++ = ch = *p++;
+  } while ( ch );
+
+  return dst;
+}
+
+size_t strlen16(const char16_t *s)
+{
+  const char16_t *ss = s;
+  while ( *ss )
+    ss++;
+  return ss-s;
+}
+
+
+char16_t *strncpy16(char16_t *dst, const char16_t *src, size_t n)
+{
+  char16_t *q = dst;
+  const char16_t *p = src;
+  char ch;
+
+  while (n) {
+    n--;
+    *q++ = ch = *p++;
+    if ( !ch )
+      break;
+  }
+
+  *q = 0;
+
+  return dst;
+}
+
+size_t strnlen16(const char16_t *s, size_t maxlen)
+{
+  const char16_t *ss = s;
+
+  /* Important: the maxlen test must precede the reference through ss;
+     since the byte beyond the maximum may segfault */
+  while ((maxlen > 0) && *ss) {
+    ss++;
+    maxlen--;
+  }
+  return ss-s;
+}
+
+int strzcmp16(const char16_t *s1, size_t n1, const char16_t *s2, size_t n2)
+{
+    const char16_t* e1 = s1+n1;
+    const char16_t* e2 = s2+n2;
+
+    while (s1 < e1 && s2 < e2) {
+        const int d = (int)*s1++ - (int)*s2++;
+        if (d) {
+            return d;
+        }
+    }
+
+    return n1 < n2
+        ? (0 - (int)*s2)
+        : (n1 > n2
+           ? ((int)*s1 - 0)
+           : 0);
+}
+
+int strzcmp16_h_n(const char16_t *s1H, size_t n1, const char16_t *s2N, size_t n2)
+{
+    const char16_t* e1 = s1H+n1;
+    const char16_t* e2 = s2N+n2;
+
+    while (s1H < e1 && s2N < e2) {
+        const char16_t c2 = ntohs(*s2N);
+        const int d = (int)*s1H++ - (int)c2;
+        s2N++;
+        if (d) {
+            return d;
+        }
+    }
+
+    return n1 < n2
+        ? (0 - (int)ntohs(*s2N))
+        : (n1 > n2
+           ? ((int)*s1H - 0)
+           : 0);
+}
+
+void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst)
+{
+    if (src == NULL || src_len == 0 || dst == NULL) {
+        return;
+    }
+
+    const char16_t* cur_utf16 = src;
+    const char16_t* const end_utf16 = src + src_len;
+    char *cur = dst;
+    while (cur_utf16 < end_utf16) {
+        char32_t utf32;
+        // surrogate pairs
+        if ((*cur_utf16 & 0xFC00) == 0xD800) {
+            utf32 = (*cur_utf16++ - 0xD800) << 10;
+            utf32 |= *cur_utf16++ - 0xDC00;
+            utf32 += 0x10000;
+        } else {
+            utf32 = (char32_t) *cur_utf16++;
+        }
+        const size_t len = utf32_codepoint_utf8_length(utf32);
+        utf32_codepoint_to_utf8((uint8_t*)cur, utf32, len);
+        cur += len;
+    }
+    *cur = '\0';
+}
+
+// --------------------------------------------------------------------------
+// UTF-8
+// --------------------------------------------------------------------------
+
+ssize_t utf8_length(const char *src)
+{
+    const char *cur = src;
+    size_t ret = 0;
+    while (*cur != '\0') {
+        const char first_char = *cur++;
+        if ((first_char & 0x80) == 0) { // ASCII
+            ret += 1;
+            continue;
+        }
+        // (UTF-8's character must not be like 10xxxxxx,
+        //  but 110xxxxx, 1110xxxx, ... or 1111110x)
+        if ((first_char & 0x40) == 0) {
+            return -1;
+        }
+
+        int32_t mask, to_ignore_mask;
+        size_t num_to_read = 0;
+        char32_t utf32 = 0;
+        for (num_to_read = 1, mask = 0x40, to_ignore_mask = 0x80;
+             num_to_read < 5 && (first_char & mask);
+             num_to_read++, to_ignore_mask |= mask, mask >>= 1) {
+            if ((*cur & 0xC0) != 0x80) { // must be 10xxxxxx
+                return -1;
+            }
+            // 0x3F == 00111111
+            utf32 = (utf32 << 6) + (*cur++ & 0x3F);
+        }
+        // "first_char" must be (110xxxxx - 11110xxx)
+        if (num_to_read == 5) {
+            return -1;
+        }
+        to_ignore_mask |= mask;
+        utf32 |= ((~to_ignore_mask) & first_char) << (6 * (num_to_read - 1));
+        if (utf32 > kUnicodeMaxCodepoint) {
+            return -1;
+        }
+
+        ret += num_to_read;
+    }
+    return ret;
+}
+
+ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len)
+{
+    if (src == NULL || src_len == 0) {
+        return -1;
+    }
+
+    size_t ret = 0;
+    const char16_t* const end = src + src_len;
+    while (src < end) {
+        if ((*src & 0xFC00) == 0xD800 && (src + 1) < end
+                && (*++src & 0xFC00) == 0xDC00) {
+            // surrogate pairs are always 4 bytes.
+            ret += 4;
+            src++;
+        } else {
+            ret += utf32_codepoint_utf8_length((char32_t) *src++);
+        }
+    }
+    return ret;
+}
+
+/**
+ * Returns 1-4 based on the number of leading bits.
+ *
+ * 1111 -> 4
+ * 1110 -> 3
+ * 110x -> 2
+ * 10xx -> 1
+ * 0xxx -> 1
+ */
+static inline size_t utf8_codepoint_len(uint8_t ch)
+{
+    return ((0xe5000000 >> ((ch >> 3) & 0x1e)) & 3) + 1;
+}
+
+static inline void utf8_shift_and_mask(uint32_t* codePoint, const uint8_t byte)
+{
+    *codePoint <<= 6;
+    *codePoint |= 0x3F & byte;
+}
+
+size_t utf8_to_utf32_length(const char *src, size_t src_len)
+{
+    if (src == NULL || src_len == 0) {
+        return 0;
+    }
+    size_t ret = 0;
+    const char* cur;
+    const char* end;
+    size_t num_to_skip;
+    for (cur = src, end = src + src_len, num_to_skip = 1;
+         cur < end;
+         cur += num_to_skip, ret++) {
+        const char first_char = *cur;
+        num_to_skip = 1;
+        if ((first_char & 0x80) == 0) {  // ASCII
+            continue;
+        }
+        int32_t mask;
+
+        for (mask = 0x40; (first_char & mask); num_to_skip++, mask >>= 1) {
+        }
+    }
+    return ret;
+}
+
+void utf8_to_utf32(const char* src, size_t src_len, char32_t* dst)
+{
+    if (src == NULL || src_len == 0 || dst == NULL) {
+        return;
+    }
+
+    const char* cur = src;
+    const char* const end = src + src_len;
+    char32_t* cur_utf32 = dst;
+    while (cur < end) {
+        size_t num_read;
+        *cur_utf32++ = static_cast<char32_t>(utf32_at_internal(cur, &num_read));
+        cur += num_read;
+    }
+    *cur_utf32 = 0;
+}
+
+static inline uint32_t utf8_to_utf32_codepoint(const uint8_t *src, size_t length)
+{
+    uint32_t unicode;
+
+    switch (length)
+    {
+        case 1:
+            return src[0];
+        case 2:
+            unicode = src[0] & 0x1f;
+            utf8_shift_and_mask(&unicode, src[1]);
+            return unicode;
+        case 3:
+            unicode = src[0] & 0x0f;
+            utf8_shift_and_mask(&unicode, src[1]);
+            utf8_shift_and_mask(&unicode, src[2]);
+            return unicode;
+        case 4:
+            unicode = src[0] & 0x07;
+            utf8_shift_and_mask(&unicode, src[1]);
+            utf8_shift_and_mask(&unicode, src[2]);
+            utf8_shift_and_mask(&unicode, src[3]);
+            return unicode;
+        default:
+            return 0xffff;
+    }
+
+    //printf("Char at %p: len=%d, utf-16=%p\n", src, length, (void*)result);
+}
+
+ssize_t utf8_to_utf16_length(const uint8_t* u8str, size_t u8len)
+{
+    const uint8_t* const u8end = u8str + u8len;
+    const uint8_t* u8cur = u8str;
+
+    /* Validate that the UTF-8 is the correct len */
+    size_t u16measuredLen = 0;
+    while (u8cur < u8end) {
+        u16measuredLen++;
+        int u8charLen = utf8_codepoint_len(*u8cur);
+        uint32_t codepoint = utf8_to_utf32_codepoint(u8cur, u8charLen);
+        if (codepoint > 0xFFFF) u16measuredLen++; // this will be a surrogate pair in utf16
+        u8cur += u8charLen;
+    }
+
+    /**
+     * Make sure that we ended where we thought we would and the output UTF-16
+     * will be exactly how long we were told it would be.
+     */
+    if (u8cur != u8end) {
+        return -1;
+    }
+
+    return u16measuredLen;
+}
+
+char16_t* utf8_to_utf16_no_null_terminator(const uint8_t* u8str, size_t u8len, char16_t* u16str)
+{
+    const uint8_t* const u8end = u8str + u8len;
+    const uint8_t* u8cur = u8str;
+    char16_t* u16cur = u16str;
+
+    while (u8cur < u8end) {
+        size_t u8len = utf8_codepoint_len(*u8cur);
+        uint32_t codepoint = utf8_to_utf32_codepoint(u8cur, u8len);
+
+        // Convert the UTF32 codepoint to one or more UTF16 codepoints
+        if (codepoint <= 0xFFFF) {
+            // Single UTF16 character
+            *u16cur++ = (char16_t) codepoint;
+        } else {
+            // Multiple UTF16 characters with surrogates
+            codepoint = codepoint - 0x10000;
+            *u16cur++ = (char16_t) ((codepoint >> 10) + 0xD800);
+            *u16cur++ = (char16_t) ((codepoint & 0x3FF) + 0xDC00);
+        }
+
+        u8cur += u8len;
+    }
+    return u16cur;
+}
+
+void utf8_to_utf16(const uint8_t* u8str, size_t u8len, char16_t* u16str) {
+    char16_t* end = utf8_to_utf16_no_null_terminator(u8str, u8len, u16str);
+    *end = 0;
+}
+
+char16_t* utf8_to_utf16_n(const uint8_t* src, size_t srcLen, char16_t* dst, size_t dstLen) {
+    const uint8_t* const u8end = src + srcLen;
+    const uint8_t* u8cur = src;
+    const uint16_t* const u16end = dst + dstLen;
+    char16_t* u16cur = dst;
+
+    while (u8cur < u8end && u16cur < u16end) {
+        size_t u8len = utf8_codepoint_len(*u8cur);
+        uint32_t codepoint = utf8_to_utf32_codepoint(u8cur, u8len);
+
+        // Convert the UTF32 codepoint to one or more UTF16 codepoints
+        if (codepoint <= 0xFFFF) {
+            // Single UTF16 character
+            *u16cur++ = (char16_t) codepoint;
+        } else {
+            // Multiple UTF16 characters with surrogates
+            codepoint = codepoint - 0x10000;
+            *u16cur++ = (char16_t) ((codepoint >> 10) + 0xD800);
+            if (u16cur >= u16end) {
+                // Ooops...  not enough room for this surrogate pair.
+                return u16cur-1;
+            }
+            *u16cur++ = (char16_t) ((codepoint & 0x3FF) + 0xDC00);
+        }
+
+        u8cur += u8len;
+    }
+    return u16cur;
+}
+
+}
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
new file mode 100644
index 0000000..30ca663
--- /dev/null
+++ b/libutils/VectorImpl.cpp
@@ -0,0 +1,637 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "Vector"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <cutils/log.h>
+
+#include <utils/Errors.h>
+#include <utils/SharedBuffer.h>
+#include <utils/VectorImpl.h>
+
+/*****************************************************************************/
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+const size_t kMinVectorCapacity = 4;
+
+static inline size_t max(size_t a, size_t b) {
+    return a>b ? a : b;
+}
+
+// ----------------------------------------------------------------------------
+
+VectorImpl::VectorImpl(size_t itemSize, uint32_t flags)
+    : mStorage(0), mCount(0), mFlags(flags), mItemSize(itemSize)
+{
+}
+
+VectorImpl::VectorImpl(const VectorImpl& rhs)
+    :   mStorage(rhs.mStorage), mCount(rhs.mCount),
+        mFlags(rhs.mFlags), mItemSize(rhs.mItemSize)
+{
+    if (mStorage) {
+        SharedBuffer::bufferFromData(mStorage)->acquire();
+    }
+}
+
+VectorImpl::~VectorImpl()
+{
+    ALOGW_IF(mCount,
+        "[%p] subclasses of VectorImpl must call finish_vector()"
+        " in their destructor. Leaking %d bytes.",
+        this, (int)(mCount*mItemSize));
+    // We can't call _do_destroy() here because the vtable is already gone. 
+}
+
+VectorImpl& VectorImpl::operator = (const VectorImpl& rhs)
+{
+    LOG_ALWAYS_FATAL_IF(mItemSize != rhs.mItemSize,
+        "Vector<> have different types (this=%p, rhs=%p)", this, &rhs);
+    if (this != &rhs) {
+        release_storage();
+        if (rhs.mCount) {
+            mStorage = rhs.mStorage;
+            mCount = rhs.mCount;
+            SharedBuffer::bufferFromData(mStorage)->acquire();
+        } else {
+            mStorage = 0;
+            mCount = 0;
+        }
+    }
+    return *this;
+}
+
+void* VectorImpl::editArrayImpl()
+{
+    if (mStorage) {
+        SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage)->attemptEdit();
+        if (sb == 0) {
+            sb = SharedBuffer::alloc(capacity() * mItemSize);
+            if (sb) {
+                _do_copy(sb->data(), mStorage, mCount);
+                release_storage();
+                mStorage = sb->data();
+            }
+        }
+    }
+    return mStorage;
+}
+
+size_t VectorImpl::capacity() const
+{
+    if (mStorage) {
+        return SharedBuffer::bufferFromData(mStorage)->size() / mItemSize;
+    }
+    return 0;
+}
+
+ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
+{
+    return insertArrayAt(vector.arrayImpl(), index, vector.size());
+}
+
+ssize_t VectorImpl::appendVector(const VectorImpl& vector)
+{
+    return insertVectorAt(vector, size());
+}
+
+ssize_t VectorImpl::insertArrayAt(const void* array, size_t index, size_t length)
+{
+    if (index > size())
+        return BAD_INDEX;
+    void* where = _grow(index, length);
+    if (where) {
+        _do_copy(where, array, length);
+    }
+    return where ? index : (ssize_t)NO_MEMORY;
+}
+
+ssize_t VectorImpl::appendArray(const void* array, size_t length)
+{
+    return insertArrayAt(array, size(), length);
+}
+
+ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
+{
+    return insertAt(0, index, numItems);
+}
+
+ssize_t VectorImpl::insertAt(const void* item, size_t index, size_t numItems)
+{
+    if (index > size())
+        return BAD_INDEX;
+    void* where = _grow(index, numItems);
+    if (where) {
+        if (item) {
+            _do_splat(where, item, numItems);
+        } else {
+            _do_construct(where, numItems);
+        }
+    }
+    return where ? index : (ssize_t)NO_MEMORY;
+}
+
+static int sortProxy(const void* lhs, const void* rhs, void* func)
+{
+    return (*(VectorImpl::compar_t)func)(lhs, rhs);
+}
+
+status_t VectorImpl::sort(VectorImpl::compar_t cmp)
+{
+    return sort(sortProxy, (void*)cmp);
+}
+
+status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state)
+{
+    // the sort must be stable. we're using insertion sort which
+    // is well suited for small and already sorted arrays
+    // for big arrays, it could be better to use mergesort
+    const ssize_t count = size();
+    if (count > 1) {
+        void* array = const_cast<void*>(arrayImpl());
+        void* temp = 0;
+        ssize_t i = 1;
+        while (i < count) {
+            void* item = reinterpret_cast<char*>(array) + mItemSize*(i);
+            void* curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
+            if (cmp(curr, item, state) > 0) {
+
+                if (!temp) {
+                    // we're going to have to modify the array...
+                    array = editArrayImpl();
+                    if (!array) return NO_MEMORY;
+                    temp = malloc(mItemSize);
+                    if (!temp) return NO_MEMORY;
+                    item = reinterpret_cast<char*>(array) + mItemSize*(i);
+                    curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
+                } else {
+                    _do_destroy(temp, 1);
+                }
+
+                _do_copy(temp, item, 1);
+
+                ssize_t j = i-1;
+                void* next = reinterpret_cast<char*>(array) + mItemSize*(i);                    
+                do {
+                    _do_destroy(next, 1);
+                    _do_copy(next, curr, 1);
+                    next = curr;
+                    --j;
+                    curr = reinterpret_cast<char*>(array) + mItemSize*(j);                    
+                } while (j>=0 && (cmp(curr, temp, state) > 0));
+
+                _do_destroy(next, 1);
+                _do_copy(next, temp, 1);
+            }
+            i++;
+        }
+        
+        if (temp) {
+            _do_destroy(temp, 1);
+            free(temp);
+        }
+    }
+    return NO_ERROR;
+}
+
+void VectorImpl::pop()
+{
+    if (size())
+        removeItemsAt(size()-1, 1);
+}
+
+void VectorImpl::push()
+{
+    push(0);
+}
+
+void VectorImpl::push(const void* item)
+{
+    insertAt(item, size());
+}
+
+ssize_t VectorImpl::add()
+{
+    return add(0);
+}
+
+ssize_t VectorImpl::add(const void* item)
+{
+    return insertAt(item, size());
+}
+
+ssize_t VectorImpl::replaceAt(size_t index)
+{
+    return replaceAt(0, index);
+}
+
+ssize_t VectorImpl::replaceAt(const void* prototype, size_t index)
+{
+    ALOG_ASSERT(index<size(),
+        "[%p] replace: index=%d, size=%d", this, (int)index, (int)size());
+
+    if (index >= size()) {
+        return BAD_INDEX;
+    }
+
+    void* item = editItemLocation(index);
+    if (item != prototype) {
+        if (item == 0)
+            return NO_MEMORY;
+        _do_destroy(item, 1);
+        if (prototype == 0) {
+            _do_construct(item, 1);
+        } else {
+            _do_copy(item, prototype, 1);
+        }
+    }
+    return ssize_t(index);
+}
+
+ssize_t VectorImpl::removeItemsAt(size_t index, size_t count)
+{
+    ALOG_ASSERT((index+count)<=size(),
+        "[%p] remove: index=%d, count=%d, size=%d",
+               this, (int)index, (int)count, (int)size());
+
+    if ((index+count) > size())
+        return BAD_VALUE;
+   _shrink(index, count);
+   return index;
+}
+
+void VectorImpl::finish_vector()
+{
+    release_storage();
+    mStorage = 0;
+    mCount = 0;
+}
+
+void VectorImpl::clear()
+{
+    _shrink(0, mCount);
+}
+
+void* VectorImpl::editItemLocation(size_t index)
+{
+    ALOG_ASSERT(index<capacity(),
+        "[%p] editItemLocation: index=%d, capacity=%d, count=%d",
+        this, (int)index, (int)capacity(), (int)mCount);
+
+    if (index < capacity()) {
+        void* buffer = editArrayImpl();
+        if (buffer) {
+            return reinterpret_cast<char*>(buffer) + index*mItemSize;
+        }
+    }
+    return 0;
+}
+
+const void* VectorImpl::itemLocation(size_t index) const
+{
+    ALOG_ASSERT(index<capacity(),
+        "[%p] itemLocation: index=%d, capacity=%d, count=%d",
+        this, (int)index, (int)capacity(), (int)mCount);
+
+    if (index < capacity()) {
+        const  void* buffer = arrayImpl();
+        if (buffer) {
+            return reinterpret_cast<const char*>(buffer) + index*mItemSize;
+        }
+    }
+    return 0;
+}
+
+ssize_t VectorImpl::setCapacity(size_t new_capacity)
+{
+    size_t current_capacity = capacity();
+    ssize_t amount = new_capacity - size();
+    if (amount <= 0) {
+        // we can't reduce the capacity
+        return current_capacity;
+    } 
+    SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+    if (sb) {
+        void* array = sb->data();
+        _do_copy(array, mStorage, size());
+        release_storage();
+        mStorage = const_cast<void*>(array);
+    } else {
+        return NO_MEMORY;
+    }
+    return new_capacity;
+}
+
+ssize_t VectorImpl::resize(size_t size) {
+    ssize_t result = NO_ERROR;
+    if (size > mCount) {
+        result = insertAt(mCount, size - mCount);
+    } else if (size < mCount) {
+        result = removeItemsAt(size, mCount - size);
+    }
+    return result < 0 ? result : size;
+}
+
+void VectorImpl::release_storage()
+{
+    if (mStorage) {
+        const SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage);
+        if (sb->release(SharedBuffer::eKeepStorage) == 1) {
+            _do_destroy(mStorage, mCount);
+            SharedBuffer::dealloc(sb);
+        } 
+    }
+}
+
+void* VectorImpl::_grow(size_t where, size_t amount)
+{
+//    ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
+//        this, (int)where, (int)amount, (int)mCount, (int)capacity());
+
+    ALOG_ASSERT(where <= mCount,
+            "[%p] _grow: where=%d, amount=%d, count=%d",
+            this, (int)where, (int)amount, (int)mCount); // caller already checked
+
+    const size_t new_size = mCount + amount;
+    if (capacity() < new_size) {
+        const size_t new_capacity = max(kMinVectorCapacity, ((new_size*3)+1)/2);
+//        ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
+        if ((mStorage) &&
+            (mCount==where) &&
+            (mFlags & HAS_TRIVIAL_COPY) &&
+            (mFlags & HAS_TRIVIAL_DTOR))
+        {
+            const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
+            SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
+            if (sb) {
+                mStorage = sb->data();
+            } else {
+                return NULL;
+            }
+        } else {
+            SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+            if (sb) {
+                void* array = sb->data();
+                if (where != 0) {
+                    _do_copy(array, mStorage, where);
+                }
+                if (where != mCount) {
+                    const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize;
+                    void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+                    _do_copy(dest, from, mCount-where);
+                }
+                release_storage();
+                mStorage = const_cast<void*>(array);
+            } else {
+                return NULL;
+            }
+        }
+    } else {
+        void* array = editArrayImpl();
+        if (where != mCount) {
+            const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
+            void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+            _do_move_forward(to, from, mCount - where);
+        }
+    }
+    mCount = new_size;
+    void* free_space = const_cast<void*>(itemLocation(where));
+    return free_space;
+}
+
+void VectorImpl::_shrink(size_t where, size_t amount)
+{
+    if (!mStorage)
+        return;
+
+//    ALOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
+//        this, (int)where, (int)amount, (int)mCount, (int)capacity());
+
+    ALOG_ASSERT(where + amount <= mCount,
+            "[%p] _shrink: where=%d, amount=%d, count=%d",
+            this, (int)where, (int)amount, (int)mCount); // caller already checked
+
+    const size_t new_size = mCount - amount;
+    if (new_size*3 < capacity()) {
+        const size_t new_capacity = max(kMinVectorCapacity, new_size*2);
+//        ALOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity);
+        if ((where == new_size) &&
+            (mFlags & HAS_TRIVIAL_COPY) &&
+            (mFlags & HAS_TRIVIAL_DTOR))
+        {
+            const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
+            SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
+            if (sb) {
+                mStorage = sb->data();
+            } else {
+                return;
+            }
+        } else {
+            SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
+            if (sb) {
+                void* array = sb->data();
+                if (where != 0) {
+                    _do_copy(array, mStorage, where);
+                }
+                if (where != new_size) {
+                    const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize;
+                    void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
+                    _do_copy(dest, from, new_size - where);
+                }
+                release_storage();
+                mStorage = const_cast<void*>(array);
+            } else{
+                return;
+            }
+        }
+    } else {
+        void* array = editArrayImpl();
+        void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
+        _do_destroy(to, amount);
+        if (where != new_size) {
+            const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
+            _do_move_backward(to, from, new_size - where);
+        }
+    }
+    mCount = new_size;
+}
+
+size_t VectorImpl::itemSize() const {
+    return mItemSize;
+}
+
+void VectorImpl::_do_construct(void* storage, size_t num) const
+{
+    if (!(mFlags & HAS_TRIVIAL_CTOR)) {
+        do_construct(storage, num);
+    }
+}
+
+void VectorImpl::_do_destroy(void* storage, size_t num) const
+{
+    if (!(mFlags & HAS_TRIVIAL_DTOR)) {
+        do_destroy(storage, num);
+    }
+}
+
+void VectorImpl::_do_copy(void* dest, const void* from, size_t num) const
+{
+    if (!(mFlags & HAS_TRIVIAL_COPY)) {
+        do_copy(dest, from, num);
+    } else {
+        memcpy(dest, from, num*itemSize());
+    }
+}
+
+void VectorImpl::_do_splat(void* dest, const void* item, size_t num) const {
+    do_splat(dest, item, num);
+}
+
+void VectorImpl::_do_move_forward(void* dest, const void* from, size_t num) const {
+    do_move_forward(dest, from, num);
+}
+
+void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) const {
+    do_move_backward(dest, from, num);
+}
+
+/*****************************************************************************/
+
+SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
+    : VectorImpl(itemSize, flags)
+{
+}
+
+SortedVectorImpl::SortedVectorImpl(const VectorImpl& rhs)
+: VectorImpl(rhs)
+{
+}
+
+SortedVectorImpl::~SortedVectorImpl()
+{
+}
+
+SortedVectorImpl& SortedVectorImpl::operator = (const SortedVectorImpl& rhs)
+{
+    return static_cast<SortedVectorImpl&>( VectorImpl::operator = (static_cast<const VectorImpl&>(rhs)) );
+}
+
+ssize_t SortedVectorImpl::indexOf(const void* item) const
+{
+    return _indexOrderOf(item);
+}
+
+size_t SortedVectorImpl::orderOf(const void* item) const
+{
+    size_t o;
+    _indexOrderOf(item, &o);
+    return o;
+}
+
+ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
+{
+    // binary search
+    ssize_t err = NAME_NOT_FOUND;
+    ssize_t l = 0;
+    ssize_t h = size()-1;
+    ssize_t mid;
+    const void* a = arrayImpl();
+    const size_t s = itemSize();
+    while (l <= h) {
+        mid = l + (h - l)/2;
+        const void* const curr = reinterpret_cast<const char *>(a) + (mid*s);
+        const int c = do_compare(curr, item);
+        if (c == 0) {
+            err = l = mid;
+            break;
+        } else if (c < 0) {
+            l = mid + 1;
+        } else {
+            h = mid - 1;
+        }
+    }
+    if (order) *order = l;
+    return err;
+}
+
+ssize_t SortedVectorImpl::add(const void* item)
+{
+    size_t order;
+    ssize_t index = _indexOrderOf(item, &order);
+    if (index < 0) {
+        index = VectorImpl::insertAt(item, order, 1);
+    } else {
+        index = VectorImpl::replaceAt(item, index);
+    }
+    return index;
+}
+
+ssize_t SortedVectorImpl::merge(const VectorImpl& vector)
+{
+    // naive merge...
+    if (!vector.isEmpty()) {
+        const void* buffer = vector.arrayImpl();
+        const size_t is = itemSize();
+        size_t s = vector.size();
+        for (size_t i=0 ; i<s ; i++) {
+            ssize_t err = add( reinterpret_cast<const char*>(buffer) + i*is );
+            if (err<0) {
+                return err;
+            }
+        }
+    }
+    return NO_ERROR;
+}
+
+ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
+{
+    // we've merging a sorted vector... nice!
+    ssize_t err = NO_ERROR;
+    if (!vector.isEmpty()) {
+        // first take care of the case where the vectors are sorted together
+        if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
+            err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&>(vector), 0);
+        } else if (do_compare(vector.arrayImpl(), itemLocation(size()-1)) >= 0) {
+            err = VectorImpl::appendVector(static_cast<const VectorImpl&>(vector));
+        } else {
+            // this could be made a little better
+            err = merge(static_cast<const VectorImpl&>(vector));
+        }
+    }
+    return err;
+}
+
+ssize_t SortedVectorImpl::remove(const void* item)
+{
+    ssize_t i = indexOf(item);
+    if (i>=0) {
+        VectorImpl::removeItemsAt(i, 1);
+    }
+    return i;
+}
+
+/*****************************************************************************/
+
+}; // namespace android
+
diff --git a/libutils/misc.cpp b/libutils/misc.cpp
new file mode 100644
index 0000000..58eb499
--- /dev/null
+++ b/libutils/misc.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "misc"
+
+//
+// Miscellaneous utility functions.
+//
+#include <utils/misc.h>
+#include <utils/Log.h>
+
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+#endif
+
+#include <utils/Vector.h>
+
+using namespace android;
+
+namespace android {
+
+struct sysprop_change_callback_info {
+    sysprop_change_callback callback;
+    int priority;
+};
+
+#if defined(HAVE_PTHREADS)
+static pthread_mutex_t gSyspropMutex = PTHREAD_MUTEX_INITIALIZER;
+static Vector<sysprop_change_callback_info>* gSyspropList = NULL;
+#endif
+
+void add_sysprop_change_callback(sysprop_change_callback cb, int priority) {
+#if defined(HAVE_PTHREADS)
+    pthread_mutex_lock(&gSyspropMutex);
+    if (gSyspropList == NULL) {
+        gSyspropList = new Vector<sysprop_change_callback_info>();
+    }
+    sysprop_change_callback_info info;
+    info.callback = cb;
+    info.priority = priority;
+    bool added = false;
+    for (size_t i=0; i<gSyspropList->size(); i++) {
+        if (priority >= gSyspropList->itemAt(i).priority) {
+            gSyspropList->insertAt(info, i);
+            added = true;
+            break;
+        }
+    }
+    if (!added) {
+        gSyspropList->add(info);
+    }
+    pthread_mutex_unlock(&gSyspropMutex);
+#endif
+}
+
+void report_sysprop_change() {
+#if defined(HAVE_PTHREADS)
+    pthread_mutex_lock(&gSyspropMutex);
+    Vector<sysprop_change_callback_info> listeners;
+    if (gSyspropList != NULL) {
+        listeners = *gSyspropList;
+    }
+    pthread_mutex_unlock(&gSyspropMutex);
+
+    //ALOGI("Reporting sysprop change to %d listeners", listeners.size());
+    for (size_t i=0; i<listeners.size(); i++) {
+        listeners[i].callback();
+    }
+#endif
+}
+
+}; // namespace android
diff --git a/libutils/primes.py b/libutils/primes.py
new file mode 100755
index 0000000..e161dd8
--- /dev/null
+++ b/libutils/primes.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python2.6
+#
+# Copyright (C) 2011 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.
+#
+
+#
+# Generates a table of prime numbers for use in BasicHashtable.cpp.
+#
+# Each prime is chosen such that it is a little more than twice as large as
+# the previous prime in the table.  This makes it easier to choose a new
+# hashtable size when the underlying array is grown by as nominal factor
+# of two each time.
+#
+
+def is_odd_prime(n):
+  limit = (n - 1) / 2
+  d = 3
+  while d <= limit:
+    if n % d == 0:
+      return False
+    d += 2
+  return True
+
+print "static size_t PRIMES[] = {"
+
+n = 5
+max = 2**31 - 1
+while n < max:
+  print "    %d," % (n)
+  n = n * 2 + 1
+  while not is_odd_prime(n):
+    n += 2
+
+print "    0,"
+print "};"
diff --git a/libutils/tests/Android.mk b/libutils/tests/Android.mk
new file mode 100644
index 0000000..caedaff
--- /dev/null
+++ b/libutils/tests/Android.mk
@@ -0,0 +1,34 @@
+# Build the unit tests.
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# Build the unit tests.
+test_src_files := \
+    BasicHashtable_test.cpp \
+    BlobCache_test.cpp \
+    BitSet_test.cpp \
+    Looper_test.cpp \
+    LruCache_test.cpp \
+    String8_test.cpp \
+    Unicode_test.cpp \
+    Vector_test.cpp
+
+shared_libraries := \
+    libz \
+    liblog \
+    libcutils \
+    libutils \
+    libstlport
+
+static_libraries := \
+    libgtest \
+    libgtest_main
+
+$(foreach file,$(test_src_files), \
+    $(eval include $(CLEAR_VARS)) \
+    $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
+    $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \
+    $(eval LOCAL_SRC_FILES := $(file)) \
+    $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
+    $(eval include $(BUILD_NATIVE_TEST)) \
+)
diff --git a/libutils/tests/BasicHashtable_test.cpp b/libutils/tests/BasicHashtable_test.cpp
new file mode 100644
index 0000000..7dcf750
--- /dev/null
+++ b/libutils/tests/BasicHashtable_test.cpp
@@ -0,0 +1,577 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define LOG_TAG "BasicHashtable_test"
+
+#include <utils/BasicHashtable.h>
+#include <cutils/log.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+namespace android {
+
+typedef int SimpleKey;
+typedef int SimpleValue;
+typedef key_value_pair_t<SimpleKey, SimpleValue> SimpleEntry;
+typedef BasicHashtable<SimpleKey, SimpleEntry> SimpleHashtable;
+
+struct ComplexKey {
+    int k;
+
+    explicit ComplexKey(int k) : k(k) {
+        instanceCount += 1;
+    }
+
+    ComplexKey(const ComplexKey& other) : k(other.k) {
+        instanceCount += 1;
+    }
+
+    ~ComplexKey() {
+        instanceCount -= 1;
+    }
+
+    bool operator ==(const ComplexKey& other) const {
+        return k == other.k;
+    }
+
+    bool operator !=(const ComplexKey& other) const {
+        return k != other.k;
+    }
+
+    static ssize_t instanceCount;
+};
+
+ssize_t ComplexKey::instanceCount = 0;
+
+template<> inline hash_t hash_type(const ComplexKey& value) {
+    return hash_type(value.k);
+}
+
+struct ComplexValue {
+    int v;
+
+    explicit ComplexValue(int v) : v(v) {
+        instanceCount += 1;
+    }
+
+    ComplexValue(const ComplexValue& other) : v(other.v) {
+        instanceCount += 1;
+    }
+
+    ~ComplexValue() {
+        instanceCount -= 1;
+    }
+
+    static ssize_t instanceCount;
+};
+
+ssize_t ComplexValue::instanceCount = 0;
+
+typedef key_value_pair_t<ComplexKey, ComplexValue> ComplexEntry;
+typedef BasicHashtable<ComplexKey, ComplexEntry> ComplexHashtable;
+
+class BasicHashtableTest : public testing::Test {
+protected:
+    virtual void SetUp() {
+        ComplexKey::instanceCount = 0;
+        ComplexValue::instanceCount = 0;
+    }
+
+    virtual void TearDown() {
+        ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
+    }
+
+    void assertInstanceCount(ssize_t keys, ssize_t values) {
+        if (keys != ComplexKey::instanceCount || values != ComplexValue::instanceCount) {
+            FAIL() << "Expected " << keys << " keys and " << values << " values "
+                    "but there were actually " << ComplexKey::instanceCount << " keys and "
+                    << ComplexValue::instanceCount << " values";
+        }
+    }
+
+public:
+    template <typename TKey, typename TEntry>
+    static void cookieAt(const BasicHashtable<TKey, TEntry>& h, size_t index,
+            bool* collision, bool* present, hash_t* hash) {
+        uint32_t cookie = h.cookieAt(index);
+        *collision = cookie & BasicHashtable<TKey, TEntry>::Bucket::COLLISION;
+        *present = cookie & BasicHashtable<TKey, TEntry>::Bucket::PRESENT;
+        *hash = cookie & BasicHashtable<TKey, TEntry>::Bucket::HASH_MASK;
+    }
+
+    template <typename TKey, typename TEntry>
+    static const void* getBuckets(const BasicHashtable<TKey, TEntry>& h) {
+        return h.mBuckets;
+    }
+};
+
+template <typename TKey, typename TValue>
+static size_t add(BasicHashtable<TKey, key_value_pair_t<TKey, TValue> >& h,
+        const TKey& key, const TValue& value) {
+    return h.add(hash_type(key), key_value_pair_t<TKey, TValue>(key, value));
+}
+
+template <typename TKey, typename TValue>
+static ssize_t find(BasicHashtable<TKey, key_value_pair_t<TKey, TValue> >& h,
+        ssize_t index, const TKey& key) {
+    return h.find(index, hash_type(key), key);
+}
+
+template <typename TKey, typename TValue>
+static bool remove(BasicHashtable<TKey, key_value_pair_t<TKey, TValue> >& h,
+        const TKey& key) {
+    ssize_t index = find(h, -1, key);
+    if (index >= 0) {
+        h.removeAt(index);
+        return true;
+    }
+    return false;
+}
+
+template <typename TEntry>
+static void getKeyValue(const TEntry& entry, int* key, int* value);
+
+template <> void getKeyValue(const SimpleEntry& entry, int* key, int* value) {
+    *key = entry.key;
+    *value = entry.value;
+}
+
+template <> void getKeyValue(const ComplexEntry& entry, int* key, int* value) {
+    *key = entry.key.k;
+    *value = entry.value.v;
+}
+
+template <typename TKey, typename TValue>
+static void dump(BasicHashtable<TKey, key_value_pair_t<TKey, TValue> >& h) {
+    ALOGD("hashtable %p, size=%u, capacity=%u, bucketCount=%u",
+            &h, h.size(), h.capacity(), h.bucketCount());
+    for (size_t i = 0; i < h.bucketCount(); i++) {
+        bool collision, present;
+        hash_t hash;
+        BasicHashtableTest::cookieAt(h, i, &collision, &present, &hash);
+        if (present) {
+            int key, value;
+            getKeyValue(h.entryAt(i), &key, &value);
+            ALOGD("  [%3u] = collision=%d, present=%d, hash=0x%08x, key=%3d, value=%3d, "
+                    "hash_type(key)=0x%08x",
+                    i, collision, present, hash, key, value, hash_type(key));
+        } else {
+            ALOGD("  [%3u] = collision=%d, present=%d",
+                    i, collision, present);
+        }
+    }
+}
+
+TEST_F(BasicHashtableTest, DefaultConstructor_WithDefaultProperties) {
+    SimpleHashtable h;
+
+    EXPECT_EQ(0U, h.size());
+    EXPECT_EQ(3U, h.capacity());
+    EXPECT_EQ(5U, h.bucketCount());
+    EXPECT_EQ(0.75f, h.loadFactor());
+}
+
+TEST_F(BasicHashtableTest, Constructor_WithNonUnityLoadFactor) {
+    SimpleHashtable h(52, 0.8f);
+
+    EXPECT_EQ(0U, h.size());
+    EXPECT_EQ(77U, h.capacity());
+    EXPECT_EQ(97U, h.bucketCount());
+    EXPECT_EQ(0.8f, h.loadFactor());
+}
+
+TEST_F(BasicHashtableTest, Constructor_WithUnityLoadFactorAndExactCapacity) {
+    SimpleHashtable h(46, 1.0f);
+
+    EXPECT_EQ(0U, h.size());
+    EXPECT_EQ(46U, h.capacity()); // must be one less than bucketCount because loadFactor == 1.0f
+    EXPECT_EQ(47U, h.bucketCount());
+    EXPECT_EQ(1.0f, h.loadFactor());
+}
+
+TEST_F(BasicHashtableTest, Constructor_WithUnityLoadFactorAndInexactCapacity) {
+    SimpleHashtable h(42, 1.0f);
+
+    EXPECT_EQ(0U, h.size());
+    EXPECT_EQ(46U, h.capacity()); // must be one less than bucketCount because loadFactor == 1.0f
+    EXPECT_EQ(47U, h.bucketCount());
+    EXPECT_EQ(1.0f, h.loadFactor());
+}
+
+TEST_F(BasicHashtableTest, FindAddFindRemoveFind_OneEntry) {
+    SimpleHashtable h;
+    ssize_t index = find(h, -1, 8);
+    ASSERT_EQ(-1, index);
+
+    index = add(h, 8, 1);
+    ASSERT_EQ(1U, h.size());
+
+    ASSERT_EQ(index, find(h, -1, 8));
+    ASSERT_EQ(8, h.entryAt(index).key);
+    ASSERT_EQ(1, h.entryAt(index).value);
+
+    index = find(h, index, 8);
+    ASSERT_EQ(-1, index);
+
+    ASSERT_TRUE(remove(h, 8));
+    ASSERT_EQ(0U, h.size());
+
+    index = find(h, -1, 8);
+    ASSERT_EQ(-1, index);
+}
+
+TEST_F(BasicHashtableTest, FindAddFindRemoveFind_MultipleEntryWithUniqueKey) {
+    const size_t N = 11;
+
+    SimpleHashtable h;
+    for (size_t i = 0; i < N; i++) {
+        ssize_t index = find(h, -1, int(i));
+        ASSERT_EQ(-1, index);
+
+        index = add(h, int(i), int(i * 10));
+        ASSERT_EQ(i + 1, h.size());
+
+        ASSERT_EQ(index, find(h, -1, int(i)));
+        ASSERT_EQ(int(i), h.entryAt(index).key);
+        ASSERT_EQ(int(i * 10), h.entryAt(index).value);
+
+        index = find(h, index, int(i));
+        ASSERT_EQ(-1, index);
+    }
+
+    for (size_t i = N; --i > 0; ) {
+        ASSERT_TRUE(remove(h, int(i))) << "i = " << i;
+        ASSERT_EQ(i, h.size());
+
+        ssize_t index = find(h, -1, int(i));
+        ASSERT_EQ(-1, index);
+    }
+}
+
+TEST_F(BasicHashtableTest, FindAddFindRemoveFind_MultipleEntryWithDuplicateKey) {
+    const size_t N = 11;
+    const int K = 1;
+
+    SimpleHashtable h;
+    for (size_t i = 0; i < N; i++) {
+        ssize_t index = find(h, -1, K);
+        if (i == 0) {
+            ASSERT_EQ(-1, index);
+        } else {
+            ASSERT_NE(-1, index);
+        }
+
+        add(h, K, int(i));
+        ASSERT_EQ(i + 1, h.size());
+
+        index = -1;
+        int values = 0;
+        for (size_t j = 0; j <= i; j++) {
+            index = find(h, index, K);
+            ASSERT_GE(index, 0);
+            ASSERT_EQ(K, h.entryAt(index).key);
+            values |= 1 << h.entryAt(index).value;
+        }
+        ASSERT_EQ(values, (1 << (i + 1)) - 1);
+
+        index = find(h, index, K);
+        ASSERT_EQ(-1, index);
+    }
+
+    for (size_t i = N; --i > 0; ) {
+        ASSERT_TRUE(remove(h, K)) << "i = " << i;
+        ASSERT_EQ(i, h.size());
+
+        ssize_t index = -1;
+        for (size_t j = 0; j < i; j++) {
+            index = find(h, index, K);
+            ASSERT_GE(index, 0);
+            ASSERT_EQ(K, h.entryAt(index).key);
+        }
+
+        index = find(h, index, K);
+        ASSERT_EQ(-1, index);
+    }
+}
+
+TEST_F(BasicHashtableTest, Clear_WhenAlreadyEmpty_DoesNothing) {
+    SimpleHashtable h;
+    h.clear();
+
+    EXPECT_EQ(0U, h.size());
+    EXPECT_EQ(3U, h.capacity());
+    EXPECT_EQ(5U, h.bucketCount());
+    EXPECT_EQ(0.75f, h.loadFactor());
+}
+
+TEST_F(BasicHashtableTest, Clear_AfterElementsAdded_RemovesThem) {
+    SimpleHashtable h;
+    add(h, 0, 0);
+    add(h, 1, 0);
+    h.clear();
+
+    EXPECT_EQ(0U, h.size());
+    EXPECT_EQ(3U, h.capacity());
+    EXPECT_EQ(5U, h.bucketCount());
+    EXPECT_EQ(0.75f, h.loadFactor());
+}
+
+TEST_F(BasicHashtableTest, Clear_AfterElementsAdded_DestroysThem) {
+    ComplexHashtable h;
+    add(h, ComplexKey(0), ComplexValue(0));
+    add(h, ComplexKey(1), ComplexValue(0));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+
+    h.clear();
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
+
+    EXPECT_EQ(0U, h.size());
+    EXPECT_EQ(3U, h.capacity());
+    EXPECT_EQ(5U, h.bucketCount());
+    EXPECT_EQ(0.75f, h.loadFactor());
+}
+
+TEST_F(BasicHashtableTest, Remove_AfterElementsAdded_DestroysThem) {
+    ComplexHashtable h;
+    add(h, ComplexKey(0), ComplexValue(0));
+    add(h, ComplexKey(1), ComplexValue(0));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+
+    ASSERT_TRUE(remove(h, ComplexKey(0)));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(1, 1));
+
+    ASSERT_TRUE(remove(h, ComplexKey(1)));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
+
+    EXPECT_EQ(0U, h.size());
+    EXPECT_EQ(3U, h.capacity());
+    EXPECT_EQ(5U, h.bucketCount());
+    EXPECT_EQ(0.75f, h.loadFactor());
+}
+
+TEST_F(BasicHashtableTest, Destructor_AfterElementsAdded_DestroysThem) {
+    {
+        ComplexHashtable h;
+        add(h, ComplexKey(0), ComplexValue(0));
+        add(h, ComplexKey(1), ComplexValue(0));
+        ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+    } // h is destroyed here
+
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
+}
+
+TEST_F(BasicHashtableTest, Next_WhenEmpty_ReturnsMinusOne) {
+    SimpleHashtable h;
+
+    ASSERT_EQ(-1, h.next(-1));
+}
+
+TEST_F(BasicHashtableTest, Next_WhenNonEmpty_IteratesOverAllEntries) {
+    const int N = 88;
+
+    SimpleHashtable h;
+    for (int i = 0; i < N; i++) {
+        add(h, i, i * 10);
+    }
+
+    bool set[N];
+    memset(set, 0, sizeof(bool) * N);
+    int count = 0;
+    for (ssize_t index = -1; (index = h.next(index)) != -1; ) {
+        ASSERT_GE(index, 0);
+        ASSERT_LT(size_t(index), h.bucketCount());
+
+        const SimpleEntry& entry = h.entryAt(index);
+        ASSERT_GE(entry.key, 0);
+        ASSERT_LT(entry.key, N);
+        ASSERT_EQ(false, set[entry.key]);
+        ASSERT_EQ(entry.key * 10, entry.value);
+
+        set[entry.key] = true;
+        count += 1;
+    }
+    ASSERT_EQ(N, count);
+}
+
+TEST_F(BasicHashtableTest, Add_RehashesOnDemand) {
+    SimpleHashtable h;
+    size_t initialCapacity = h.capacity();
+    size_t initialBucketCount = h.bucketCount();
+
+    for (size_t i = 0; i < initialCapacity; i++) {
+        add(h, int(i), 0);
+    }
+
+    EXPECT_EQ(initialCapacity, h.size());
+    EXPECT_EQ(initialCapacity, h.capacity());
+    EXPECT_EQ(initialBucketCount, h.bucketCount());
+
+    add(h, -1, -1);
+
+    EXPECT_EQ(initialCapacity + 1, h.size());
+    EXPECT_GT(h.capacity(), initialCapacity);
+    EXPECT_GT(h.bucketCount(), initialBucketCount);
+    EXPECT_GT(h.bucketCount(), h.capacity());
+}
+
+TEST_F(BasicHashtableTest, Rehash_WhenCapacityAndBucketCountUnchanged_DoesNothing) {
+    ComplexHashtable h;
+    add(h, ComplexKey(0), ComplexValue(0));
+    const void* oldBuckets = getBuckets(h);
+    ASSERT_NE((void*)NULL, oldBuckets);
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(1, 1));
+
+    h.rehash(h.capacity(), h.loadFactor());
+
+    ASSERT_EQ(oldBuckets, getBuckets(h));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(1, 1));
+}
+
+TEST_F(BasicHashtableTest, Rehash_WhenEmptyAndHasNoBuckets_ButDoesNotAllocateBuckets) {
+    ComplexHashtable h;
+    ASSERT_EQ((void*)NULL, getBuckets(h));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
+
+    h.rehash(9, 1.0f);
+
+    EXPECT_EQ(0U, h.size());
+    EXPECT_EQ(10U, h.capacity());
+    EXPECT_EQ(11U, h.bucketCount());
+    EXPECT_EQ(1.0f, h.loadFactor());
+    EXPECT_EQ((void*)NULL, getBuckets(h));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
+}
+
+TEST_F(BasicHashtableTest, Rehash_WhenEmptyAndHasBuckets_ReleasesBucketsAndSetsCapacity) {
+    ComplexHashtable h(10);
+    add(h, ComplexKey(0), ComplexValue(0));
+    ASSERT_TRUE(remove(h, ComplexKey(0)));
+    ASSERT_NE((void*)NULL, getBuckets(h));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
+
+    h.rehash(0, 0.75f);
+
+    EXPECT_EQ(0U, h.size());
+    EXPECT_EQ(3U, h.capacity());
+    EXPECT_EQ(5U, h.bucketCount());
+    EXPECT_EQ(0.75f, h.loadFactor());
+    EXPECT_EQ((void*)NULL, getBuckets(h));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
+}
+
+TEST_F(BasicHashtableTest, Rehash_WhenLessThanCurrentCapacity_ShrinksBuckets) {
+    ComplexHashtable h(10);
+    add(h, ComplexKey(0), ComplexValue(0));
+    add(h, ComplexKey(1), ComplexValue(1));
+    const void* oldBuckets = getBuckets(h);
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+
+    h.rehash(0, 0.75f);
+
+    EXPECT_EQ(2U, h.size());
+    EXPECT_EQ(3U, h.capacity());
+    EXPECT_EQ(5U, h.bucketCount());
+    EXPECT_EQ(0.75f, h.loadFactor());
+    EXPECT_NE(oldBuckets, getBuckets(h));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+}
+
+TEST_F(BasicHashtableTest, CopyOnWrite) {
+    ComplexHashtable h1;
+    add(h1, ComplexKey(0), ComplexValue(0));
+    add(h1, ComplexKey(1), ComplexValue(1));
+    const void* originalBuckets = getBuckets(h1);
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+    ssize_t index0 = find(h1, -1, ComplexKey(0));
+    EXPECT_GE(index0, 0);
+
+    // copy constructor acquires shared reference
+    ComplexHashtable h2(h1);
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+    ASSERT_EQ(originalBuckets, getBuckets(h2));
+    EXPECT_EQ(h1.size(), h2.size());
+    EXPECT_EQ(h1.capacity(), h2.capacity());
+    EXPECT_EQ(h1.bucketCount(), h2.bucketCount());
+    EXPECT_EQ(h1.loadFactor(), h2.loadFactor());
+    EXPECT_EQ(index0, find(h2, -1, ComplexKey(0)));
+
+    // operator= acquires shared reference
+    ComplexHashtable h3;
+    h3 = h2;
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+    ASSERT_EQ(originalBuckets, getBuckets(h3));
+    EXPECT_EQ(h1.size(), h3.size());
+    EXPECT_EQ(h1.capacity(), h3.capacity());
+    EXPECT_EQ(h1.bucketCount(), h3.bucketCount());
+    EXPECT_EQ(h1.loadFactor(), h3.loadFactor());
+    EXPECT_EQ(index0, find(h3, -1, ComplexKey(0)));
+
+    // editEntryAt copies shared contents
+    h1.editEntryAt(index0).value.v = 42;
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(4, 4));
+    ASSERT_NE(originalBuckets, getBuckets(h1));
+    EXPECT_EQ(42, h1.entryAt(index0).value.v);
+    EXPECT_EQ(0, h2.entryAt(index0).value.v);
+    EXPECT_EQ(0, h3.entryAt(index0).value.v);
+
+    // clear releases reference to shared contents
+    h2.clear();
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(4, 4));
+    EXPECT_EQ(0U, h2.size());
+    ASSERT_NE(originalBuckets, getBuckets(h2));
+
+    // operator= acquires shared reference, destroys unshared contents
+    h1 = h3;
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+    ASSERT_EQ(originalBuckets, getBuckets(h1));
+    EXPECT_EQ(h3.size(), h1.size());
+    EXPECT_EQ(h3.capacity(), h1.capacity());
+    EXPECT_EQ(h3.bucketCount(), h1.bucketCount());
+    EXPECT_EQ(h3.loadFactor(), h1.loadFactor());
+    EXPECT_EQ(index0, find(h1, -1, ComplexKey(0)));
+
+    // add copies shared contents
+    add(h1, ComplexKey(2), ComplexValue(2));
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(5, 5));
+    ASSERT_NE(originalBuckets, getBuckets(h1));
+    EXPECT_EQ(3U, h1.size());
+    EXPECT_EQ(0U, h2.size());
+    EXPECT_EQ(2U, h3.size());
+
+    // remove copies shared contents
+    h1 = h3;
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+    ASSERT_EQ(originalBuckets, getBuckets(h1));
+    h1.removeAt(index0);
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(3, 3));
+    ASSERT_NE(originalBuckets, getBuckets(h1));
+    EXPECT_EQ(1U, h1.size());
+    EXPECT_EQ(0U, h2.size());
+    EXPECT_EQ(2U, h3.size());
+
+    // rehash copies shared contents
+    h1 = h3;
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(2, 2));
+    ASSERT_EQ(originalBuckets, getBuckets(h1));
+    h1.rehash(10, 1.0f);
+    ASSERT_NO_FATAL_FAILURE(assertInstanceCount(4, 4));
+    ASSERT_NE(originalBuckets, getBuckets(h1));
+    EXPECT_EQ(2U, h1.size());
+    EXPECT_EQ(0U, h2.size());
+    EXPECT_EQ(2U, h3.size());
+}
+
+} // namespace android
diff --git a/libutils/tests/BitSet_test.cpp b/libutils/tests/BitSet_test.cpp
new file mode 100644
index 0000000..752e56d
--- /dev/null
+++ b/libutils/tests/BitSet_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define LOG_TAG "BitSet_test"
+
+#include <utils/BitSet.h>
+#include <cutils/log.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+namespace android {
+
+class BitSetTest : public testing::Test {
+protected:
+    BitSet32 b1;
+    BitSet32 b2;
+    virtual void TearDown() {
+        b1.clear();
+        b2.clear();
+    }
+};
+
+
+TEST_F(BitSetTest, BitWiseOr) {
+    b1.markBit(2);
+    b2.markBit(4);
+
+    BitSet32 tmp = b1 | b2;
+    EXPECT_EQ(tmp.count(), 2u);
+    EXPECT_TRUE(tmp.hasBit(2) && tmp.hasBit(4));
+    // Check that the operator is symmetric
+    EXPECT_TRUE((b2 | b1) == (b1 | b2));
+
+    b1 |= b2;
+    EXPECT_EQ(b1.count(), 2u);
+    EXPECT_TRUE(b1.hasBit(2) && b1.hasBit(4));
+    EXPECT_TRUE(b2.hasBit(4) && b2.count() == 1u);
+}
+TEST_F(BitSetTest, BitWiseAnd_Disjoint) {
+    b1.markBit(2);
+    b1.markBit(4);
+    b1.markBit(6);
+
+    BitSet32 tmp = b1 & b2;
+    EXPECT_TRUE(tmp.isEmpty());
+    // Check that the operator is symmetric
+    EXPECT_TRUE((b2 & b1) == (b1 & b2));
+
+    b2 &= b1;
+    EXPECT_TRUE(b2.isEmpty());
+    EXPECT_EQ(b1.count(), 3u);
+    EXPECT_TRUE(b1.hasBit(2) && b1.hasBit(4) && b1.hasBit(6));
+}
+
+TEST_F(BitSetTest, BitWiseAnd_NonDisjoint) {
+    b1.markBit(2);
+    b1.markBit(4);
+    b1.markBit(6);
+    b2.markBit(3);
+    b2.markBit(6);
+    b2.markBit(9);
+
+    BitSet32 tmp = b1 & b2;
+    EXPECT_EQ(tmp.count(), 1u);
+    EXPECT_TRUE(tmp.hasBit(6));
+    // Check that the operator is symmetric
+    EXPECT_TRUE((b2 & b1) == (b1 & b2));
+
+    b1 &= b2;
+    EXPECT_EQ(b1.count(), 1u);
+    EXPECT_EQ(b2.count(), 3u);
+    EXPECT_TRUE(b2.hasBit(3) && b2.hasBit(6) && b2.hasBit(9));
+}
+} // namespace android
diff --git a/libutils/tests/BlobCache_test.cpp b/libutils/tests/BlobCache_test.cpp
new file mode 100644
index 0000000..7202123
--- /dev/null
+++ b/libutils/tests/BlobCache_test.cpp
@@ -0,0 +1,421 @@
+/*
+ ** Copyright 2011, 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.
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <gtest/gtest.h>
+
+#include <utils/BlobCache.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class BlobCacheTest : public ::testing::Test {
+protected:
+    enum {
+        MAX_KEY_SIZE = 6,
+        MAX_VALUE_SIZE = 8,
+        MAX_TOTAL_SIZE = 13,
+    };
+
+    virtual void SetUp() {
+        mBC = new BlobCache(MAX_KEY_SIZE, MAX_VALUE_SIZE, MAX_TOTAL_SIZE);
+    }
+
+    virtual void TearDown() {
+        mBC.clear();
+    }
+
+    sp<BlobCache> mBC;
+};
+
+TEST_F(BlobCacheTest, CacheSingleValueSucceeds) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mBC->set("abcd", 4, "efgh", 4);
+    ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
+    ASSERT_EQ('e', buf[0]);
+    ASSERT_EQ('f', buf[1]);
+    ASSERT_EQ('g', buf[2]);
+    ASSERT_EQ('h', buf[3]);
+}
+
+TEST_F(BlobCacheTest, CacheTwoValuesSucceeds) {
+    char buf[2] = { 0xee, 0xee };
+    mBC->set("ab", 2, "cd", 2);
+    mBC->set("ef", 2, "gh", 2);
+    ASSERT_EQ(size_t(2), mBC->get("ab", 2, buf, 2));
+    ASSERT_EQ('c', buf[0]);
+    ASSERT_EQ('d', buf[1]);
+    ASSERT_EQ(size_t(2), mBC->get("ef", 2, buf, 2));
+    ASSERT_EQ('g', buf[0]);
+    ASSERT_EQ('h', buf[1]);
+}
+
+TEST_F(BlobCacheTest, GetOnlyWritesInsideBounds) {
+    char buf[6] = { 0xee, 0xee, 0xee, 0xee, 0xee, 0xee };
+    mBC->set("abcd", 4, "efgh", 4);
+    ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf+1, 4));
+    ASSERT_EQ(0xee, buf[0]);
+    ASSERT_EQ('e', buf[1]);
+    ASSERT_EQ('f', buf[2]);
+    ASSERT_EQ('g', buf[3]);
+    ASSERT_EQ('h', buf[4]);
+    ASSERT_EQ(0xee, buf[5]);
+}
+
+TEST_F(BlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) {
+    char buf[3] = { 0xee, 0xee, 0xee };
+    mBC->set("abcd", 4, "efgh", 4);
+    ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 3));
+    ASSERT_EQ(0xee, buf[0]);
+    ASSERT_EQ(0xee, buf[1]);
+    ASSERT_EQ(0xee, buf[2]);
+}
+
+TEST_F(BlobCacheTest, GetDoesntAccessNullBuffer) {
+    mBC->set("abcd", 4, "efgh", 4);
+    ASSERT_EQ(size_t(4), mBC->get("abcd", 4, NULL, 0));
+}
+
+TEST_F(BlobCacheTest, MultipleSetsCacheLatestValue) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mBC->set("abcd", 4, "efgh", 4);
+    mBC->set("abcd", 4, "ijkl", 4);
+    ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
+    ASSERT_EQ('i', buf[0]);
+    ASSERT_EQ('j', buf[1]);
+    ASSERT_EQ('k', buf[2]);
+    ASSERT_EQ('l', buf[3]);
+}
+
+TEST_F(BlobCacheTest, SecondSetKeepsFirstValueIfTooLarge) {
+    char buf[MAX_VALUE_SIZE+1] = { 0xee, 0xee, 0xee, 0xee };
+    mBC->set("abcd", 4, "efgh", 4);
+    mBC->set("abcd", 4, buf, MAX_VALUE_SIZE+1);
+    ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
+    ASSERT_EQ('e', buf[0]);
+    ASSERT_EQ('f', buf[1]);
+    ASSERT_EQ('g', buf[2]);
+    ASSERT_EQ('h', buf[3]);
+}
+
+TEST_F(BlobCacheTest, DoesntCacheIfKeyIsTooBig) {
+    char key[MAX_KEY_SIZE+1];
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    for (int i = 0; i < MAX_KEY_SIZE+1; i++) {
+        key[i] = 'a';
+    }
+    mBC->set(key, MAX_KEY_SIZE+1, "bbbb", 4);
+    ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE+1, buf, 4));
+    ASSERT_EQ(0xee, buf[0]);
+    ASSERT_EQ(0xee, buf[1]);
+    ASSERT_EQ(0xee, buf[2]);
+    ASSERT_EQ(0xee, buf[3]);
+}
+
+TEST_F(BlobCacheTest, DoesntCacheIfValueIsTooBig) {
+    char buf[MAX_VALUE_SIZE+1];
+    for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
+        buf[i] = 'b';
+    }
+    mBC->set("abcd", 4, buf, MAX_VALUE_SIZE+1);
+    for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
+        buf[i] = 0xee;
+    }
+    ASSERT_EQ(size_t(0), mBC->get("abcd", 4, buf, MAX_VALUE_SIZE+1));
+    for (int i = 0; i < MAX_VALUE_SIZE+1; i++) {
+        SCOPED_TRACE(i);
+        ASSERT_EQ(0xee, buf[i]);
+    }
+}
+
+TEST_F(BlobCacheTest, DoesntCacheIfKeyValuePairIsTooBig) {
+    // Check a testing assumptions
+    ASSERT_TRUE(MAX_TOTAL_SIZE < MAX_KEY_SIZE + MAX_VALUE_SIZE);
+    ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
+
+    enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE + 1 };
+
+    char key[MAX_KEY_SIZE];
+    char buf[bufSize];
+    for (int i = 0; i < MAX_KEY_SIZE; i++) {
+        key[i] = 'a';
+    }
+    for (int i = 0; i < bufSize; i++) {
+        buf[i] = 'b';
+    }
+
+    mBC->set(key, MAX_KEY_SIZE, buf, MAX_VALUE_SIZE);
+    ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE, NULL, 0));
+}
+
+TEST_F(BlobCacheTest, CacheMaxKeySizeSucceeds) {
+    char key[MAX_KEY_SIZE];
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    for (int i = 0; i < MAX_KEY_SIZE; i++) {
+        key[i] = 'a';
+    }
+    mBC->set(key, MAX_KEY_SIZE, "wxyz", 4);
+    ASSERT_EQ(size_t(4), mBC->get(key, MAX_KEY_SIZE, buf, 4));
+    ASSERT_EQ('w', buf[0]);
+    ASSERT_EQ('x', buf[1]);
+    ASSERT_EQ('y', buf[2]);
+    ASSERT_EQ('z', buf[3]);
+}
+
+TEST_F(BlobCacheTest, CacheMaxValueSizeSucceeds) {
+    char buf[MAX_VALUE_SIZE];
+    for (int i = 0; i < MAX_VALUE_SIZE; i++) {
+        buf[i] = 'b';
+    }
+    mBC->set("abcd", 4, buf, MAX_VALUE_SIZE);
+    for (int i = 0; i < MAX_VALUE_SIZE; i++) {
+        buf[i] = 0xee;
+    }
+    ASSERT_EQ(size_t(MAX_VALUE_SIZE), mBC->get("abcd", 4, buf,
+            MAX_VALUE_SIZE));
+    for (int i = 0; i < MAX_VALUE_SIZE; i++) {
+        SCOPED_TRACE(i);
+        ASSERT_EQ('b', buf[i]);
+    }
+}
+
+TEST_F(BlobCacheTest, CacheMaxKeyValuePairSizeSucceeds) {
+    // Check a testing assumption
+    ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
+
+    enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE };
+
+    char key[MAX_KEY_SIZE];
+    char buf[bufSize];
+    for (int i = 0; i < MAX_KEY_SIZE; i++) {
+        key[i] = 'a';
+    }
+    for (int i = 0; i < bufSize; i++) {
+        buf[i] = 'b';
+    }
+
+    mBC->set(key, MAX_KEY_SIZE, buf, bufSize);
+    ASSERT_EQ(size_t(bufSize), mBC->get(key, MAX_KEY_SIZE, NULL, 0));
+}
+
+TEST_F(BlobCacheTest, CacheMinKeyAndValueSizeSucceeds) {
+    char buf[1] = { 0xee };
+    mBC->set("x", 1, "y", 1);
+    ASSERT_EQ(size_t(1), mBC->get("x", 1, buf, 1));
+    ASSERT_EQ('y', buf[0]);
+}
+
+TEST_F(BlobCacheTest, CacheSizeDoesntExceedTotalLimit) {
+    for (int i = 0; i < 256; i++) {
+        uint8_t k = i;
+        mBC->set(&k, 1, "x", 1);
+    }
+    int numCached = 0;
+    for (int i = 0; i < 256; i++) {
+        uint8_t k = i;
+        if (mBC->get(&k, 1, NULL, 0) == 1) {
+            numCached++;
+        }
+    }
+    ASSERT_GE(MAX_TOTAL_SIZE / 2, numCached);
+}
+
+TEST_F(BlobCacheTest, ExceedingTotalLimitHalvesCacheSize) {
+    // Fill up the entire cache with 1 char key/value pairs.
+    const int maxEntries = MAX_TOTAL_SIZE / 2;
+    for (int i = 0; i < maxEntries; i++) {
+        uint8_t k = i;
+        mBC->set(&k, 1, "x", 1);
+    }
+    // Insert one more entry, causing a cache overflow.
+    {
+        uint8_t k = maxEntries;
+        mBC->set(&k, 1, "x", 1);
+    }
+    // Count the number of entries in the cache.
+    int numCached = 0;
+    for (int i = 0; i < maxEntries+1; i++) {
+        uint8_t k = i;
+        if (mBC->get(&k, 1, NULL, 0) == 1) {
+            numCached++;
+        }
+    }
+    ASSERT_EQ(maxEntries/2 + 1, numCached);
+}
+
+class BlobCacheFlattenTest : public BlobCacheTest {
+protected:
+    virtual void SetUp() {
+        BlobCacheTest::SetUp();
+        mBC2 = new BlobCache(MAX_KEY_SIZE, MAX_VALUE_SIZE, MAX_TOTAL_SIZE);
+    }
+
+    virtual void TearDown() {
+        mBC2.clear();
+        BlobCacheTest::TearDown();
+    }
+
+    void roundTrip() {
+        size_t size = mBC->getFlattenedSize();
+        uint8_t* flat = new uint8_t[size];
+        ASSERT_EQ(OK, mBC->flatten(flat, size));
+        ASSERT_EQ(OK, mBC2->unflatten(flat, size));
+        delete[] flat;
+    }
+
+    sp<BlobCache> mBC2;
+};
+
+TEST_F(BlobCacheFlattenTest, FlattenOneValue) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mBC->set("abcd", 4, "efgh", 4);
+    roundTrip();
+    ASSERT_EQ(size_t(4), mBC2->get("abcd", 4, buf, 4));
+    ASSERT_EQ('e', buf[0]);
+    ASSERT_EQ('f', buf[1]);
+    ASSERT_EQ('g', buf[2]);
+    ASSERT_EQ('h', buf[3]);
+}
+
+TEST_F(BlobCacheFlattenTest, FlattenFullCache) {
+    // Fill up the entire cache with 1 char key/value pairs.
+    const int maxEntries = MAX_TOTAL_SIZE / 2;
+    for (int i = 0; i < maxEntries; i++) {
+        uint8_t k = i;
+        mBC->set(&k, 1, &k, 1);
+    }
+
+    roundTrip();
+
+    // Verify the deserialized cache
+    for (int i = 0; i < maxEntries; i++) {
+        uint8_t k = i;
+        uint8_t v = 0xee;
+        ASSERT_EQ(size_t(1), mBC2->get(&k, 1, &v, 1));
+        ASSERT_EQ(k, v);
+    }
+}
+
+TEST_F(BlobCacheFlattenTest, FlattenDoesntChangeCache) {
+    // Fill up the entire cache with 1 char key/value pairs.
+    const int maxEntries = MAX_TOTAL_SIZE / 2;
+    for (int i = 0; i < maxEntries; i++) {
+        uint8_t k = i;
+        mBC->set(&k, 1, &k, 1);
+    }
+
+    size_t size = mBC->getFlattenedSize();
+    uint8_t* flat = new uint8_t[size];
+    ASSERT_EQ(OK, mBC->flatten(flat, size));
+    delete[] flat;
+
+    // Verify the cache that we just serialized
+    for (int i = 0; i < maxEntries; i++) {
+        uint8_t k = i;
+        uint8_t v = 0xee;
+        ASSERT_EQ(size_t(1), mBC->get(&k, 1, &v, 1));
+        ASSERT_EQ(k, v);
+    }
+}
+
+TEST_F(BlobCacheFlattenTest, FlattenCatchesBufferTooSmall) {
+    // Fill up the entire cache with 1 char key/value pairs.
+    const int maxEntries = MAX_TOTAL_SIZE / 2;
+    for (int i = 0; i < maxEntries; i++) {
+        uint8_t k = i;
+        mBC->set(&k, 1, &k, 1);
+    }
+
+    size_t size = mBC->getFlattenedSize() - 1;
+    uint8_t* flat = new uint8_t[size];
+    ASSERT_EQ(BAD_VALUE, mBC->flatten(flat, size));
+    delete[] flat;
+}
+
+TEST_F(BlobCacheFlattenTest, UnflattenCatchesBadMagic) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mBC->set("abcd", 4, "efgh", 4);
+
+    size_t size = mBC->getFlattenedSize();
+    uint8_t* flat = new uint8_t[size];
+    ASSERT_EQ(OK, mBC->flatten(flat, size));
+    flat[1] = ~flat[1];
+
+    // Bad magic should cause an error.
+    ASSERT_EQ(BAD_VALUE, mBC2->unflatten(flat, size));
+    delete[] flat;
+
+    // The error should cause the unflatten to result in an empty cache
+    ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
+}
+
+TEST_F(BlobCacheFlattenTest, UnflattenCatchesBadBlobCacheVersion) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mBC->set("abcd", 4, "efgh", 4);
+
+    size_t size = mBC->getFlattenedSize();
+    uint8_t* flat = new uint8_t[size];
+    ASSERT_EQ(OK, mBC->flatten(flat, size));
+    flat[5] = ~flat[5];
+
+    // Version mismatches shouldn't cause errors, but should not use the
+    // serialized entries
+    ASSERT_EQ(OK, mBC2->unflatten(flat, size));
+    delete[] flat;
+
+    // The version mismatch should cause the unflatten to result in an empty
+    // cache
+    ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
+}
+
+TEST_F(BlobCacheFlattenTest, UnflattenCatchesBadBlobCacheDeviceVersion) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mBC->set("abcd", 4, "efgh", 4);
+
+    size_t size = mBC->getFlattenedSize();
+    uint8_t* flat = new uint8_t[size];
+    ASSERT_EQ(OK, mBC->flatten(flat, size));
+    flat[10] = ~flat[10];
+
+    // Version mismatches shouldn't cause errors, but should not use the
+    // serialized entries
+    ASSERT_EQ(OK, mBC2->unflatten(flat, size));
+    delete[] flat;
+
+    // The version mismatch should cause the unflatten to result in an empty
+    // cache
+    ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
+}
+
+TEST_F(BlobCacheFlattenTest, UnflattenCatchesBufferTooSmall) {
+    char buf[4] = { 0xee, 0xee, 0xee, 0xee };
+    mBC->set("abcd", 4, "efgh", 4);
+
+    size_t size = mBC->getFlattenedSize();
+    uint8_t* flat = new uint8_t[size];
+    ASSERT_EQ(OK, mBC->flatten(flat, size));
+
+    // A buffer truncation shouldt cause an error
+    ASSERT_EQ(BAD_VALUE, mBC2->unflatten(flat, size-1));
+    delete[] flat;
+
+    // The error should cause the unflatten to result in an empty cache
+    ASSERT_EQ(size_t(0), mBC2->get("abcd", 4, buf, 4));
+}
+
+} // namespace android
diff --git a/libutils/tests/Looper_test.cpp b/libutils/tests/Looper_test.cpp
new file mode 100644
index 0000000..8bf2ba2
--- /dev/null
+++ b/libutils/tests/Looper_test.cpp
@@ -0,0 +1,693 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+
+#include <utils/Looper.h>
+#include <utils/Timers.h>
+#include <utils/StopWatch.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "TestHelpers.h"
+
+// # of milliseconds to fudge stopwatch measurements
+#define TIMING_TOLERANCE_MS 25
+
+namespace android {
+
+enum {
+    MSG_TEST1 = 1,
+    MSG_TEST2 = 2,
+    MSG_TEST3 = 3,
+    MSG_TEST4 = 4,
+};
+
+class DelayedWake : public DelayedTask {
+    sp<Looper> mLooper;
+
+public:
+    DelayedWake(int delayMillis, const sp<Looper> looper) :
+        DelayedTask(delayMillis), mLooper(looper) {
+    }
+
+protected:
+    virtual void doTask() {
+        mLooper->wake();
+    }
+};
+
+class DelayedWriteSignal : public DelayedTask {
+    Pipe* mPipe;
+
+public:
+    DelayedWriteSignal(int delayMillis, Pipe* pipe) :
+        DelayedTask(delayMillis), mPipe(pipe) {
+    }
+
+protected:
+    virtual void doTask() {
+        mPipe->writeSignal();
+    }
+};
+
+class CallbackHandler {
+public:
+    void setCallback(const sp<Looper>& looper, int fd, int events) {
+        looper->addFd(fd, 0, events, staticHandler, this);
+    }
+
+protected:
+    virtual ~CallbackHandler() { }
+
+    virtual int handler(int fd, int events) = 0;
+
+private:
+    static int staticHandler(int fd, int events, void* data) {
+        return static_cast<CallbackHandler*>(data)->handler(fd, events);
+    }
+};
+
+class StubCallbackHandler : public CallbackHandler {
+public:
+    int nextResult;
+    int callbackCount;
+
+    int fd;
+    int events;
+
+    StubCallbackHandler(int nextResult) : nextResult(nextResult),
+            callbackCount(0), fd(-1), events(-1) {
+    }
+
+protected:
+    virtual int handler(int fd, int events) {
+        callbackCount += 1;
+        this->fd = fd;
+        this->events = events;
+        return nextResult;
+    }
+};
+
+class StubMessageHandler : public MessageHandler {
+public:
+    Vector<Message> messages;
+
+    virtual void handleMessage(const Message& message) {
+        messages.push(message);
+    }
+};
+
+class LooperTest : public testing::Test {
+protected:
+    sp<Looper> mLooper;
+
+    virtual void SetUp() {
+        mLooper = new Looper(true);
+    }
+
+    virtual void TearDown() {
+        mLooper.clear();
+    }
+};
+
+
+TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndNotAwoken_WaitsForTimeout) {
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(100);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. equal timeout";
+    EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result)
+            << "pollOnce result should be ALOOPER_POLL_TIMEOUT";
+}
+
+TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndAwokenBeforeWaiting_ImmediatelyReturns) {
+    mLooper->wake();
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(1000);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. zero because wake() was called before waiting";
+    EXPECT_EQ(ALOOPER_POLL_WAKE, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because loop was awoken";
+}
+
+TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndAwokenWhileWaiting_PromptlyReturns) {
+    sp<DelayedWake> delayedWake = new DelayedWake(100, mLooper);
+    delayedWake->run();
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(1000);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. equal wake delay";
+    EXPECT_EQ(ALOOPER_POLL_WAKE, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because loop was awoken";
+}
+
+TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndNoRegisteredFDs_ImmediatelyReturns) {
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(0);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should be approx. zero";
+    EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result)
+            << "pollOnce result should be ALOOPER_POLL_TIMEOUT";
+}
+
+TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndNoSignalledFDs_ImmediatelyReturns) {
+    Pipe pipe;
+    StubCallbackHandler handler(true);
+
+    handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT);
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(0);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should be approx. zero";
+    EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result)
+            << "pollOnce result should be ALOOPER_POLL_TIMEOUT";
+    EXPECT_EQ(0, handler.callbackCount)
+            << "callback should not have been invoked because FD was not signalled";
+}
+
+TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndSignalledFD_ImmediatelyInvokesCallbackAndReturns) {
+    Pipe pipe;
+    StubCallbackHandler handler(true);
+
+    ASSERT_EQ(OK, pipe.writeSignal());
+    handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT);
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(0);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should be approx. zero";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because FD was signalled";
+    EXPECT_EQ(1, handler.callbackCount)
+            << "callback should be invoked exactly once";
+    EXPECT_EQ(pipe.receiveFd, handler.fd)
+            << "callback should have received pipe fd as parameter";
+    EXPECT_EQ(ALOOPER_EVENT_INPUT, handler.events)
+            << "callback should have received ALOOPER_EVENT_INPUT as events";
+}
+
+TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndNoSignalledFDs_WaitsForTimeoutAndReturns) {
+    Pipe pipe;
+    StubCallbackHandler handler(true);
+
+    handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT);
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(100);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. equal timeout";
+    EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result)
+            << "pollOnce result should be ALOOPER_POLL_TIMEOUT";
+    EXPECT_EQ(0, handler.callbackCount)
+            << "callback should not have been invoked because FD was not signalled";
+}
+
+TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDBeforeWaiting_ImmediatelyInvokesCallbackAndReturns) {
+    Pipe pipe;
+    StubCallbackHandler handler(true);
+
+    pipe.writeSignal();
+    handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT);
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(100);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    ASSERT_EQ(OK, pipe.readSignal())
+            << "signal should actually have been written";
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should be approx. zero";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because FD was signalled";
+    EXPECT_EQ(1, handler.callbackCount)
+            << "callback should be invoked exactly once";
+    EXPECT_EQ(pipe.receiveFd, handler.fd)
+            << "callback should have received pipe fd as parameter";
+    EXPECT_EQ(ALOOPER_EVENT_INPUT, handler.events)
+            << "callback should have received ALOOPER_EVENT_INPUT as events";
+}
+
+TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDWhileWaiting_PromptlyInvokesCallbackAndReturns) {
+    Pipe pipe;
+    StubCallbackHandler handler(true);
+    sp<DelayedWriteSignal> delayedWriteSignal = new DelayedWriteSignal(100, & pipe);
+
+    handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT);
+    delayedWriteSignal->run();
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(1000);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    ASSERT_EQ(OK, pipe.readSignal())
+            << "signal should actually have been written";
+    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. equal signal delay";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because FD was signalled";
+    EXPECT_EQ(1, handler.callbackCount)
+            << "callback should be invoked exactly once";
+    EXPECT_EQ(pipe.receiveFd, handler.fd)
+            << "callback should have received pipe fd as parameter";
+    EXPECT_EQ(ALOOPER_EVENT_INPUT, handler.events)
+            << "callback should have received ALOOPER_EVENT_INPUT as events";
+}
+
+TEST_F(LooperTest, PollOnce_WhenCallbackAddedThenRemoved_CallbackShouldNotBeInvoked) {
+    Pipe pipe;
+    StubCallbackHandler handler(true);
+
+    handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT);
+    pipe.writeSignal(); // would cause FD to be considered signalled
+    mLooper->removeFd(pipe.receiveFd);
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(100);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    ASSERT_EQ(OK, pipe.readSignal())
+            << "signal should actually have been written";
+    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. equal timeout because FD was no longer registered";
+    EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result)
+            << "pollOnce result should be ALOOPER_POLL_TIMEOUT";
+    EXPECT_EQ(0, handler.callbackCount)
+            << "callback should not be invoked";
+}
+
+TEST_F(LooperTest, PollOnce_WhenCallbackReturnsFalse_CallbackShouldNotBeInvokedAgainLater) {
+    Pipe pipe;
+    StubCallbackHandler handler(false);
+
+    handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT);
+
+    // First loop: Callback is registered and FD is signalled.
+    pipe.writeSignal();
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(0);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    ASSERT_EQ(OK, pipe.readSignal())
+            << "signal should actually have been written";
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. equal zero because FD was already signalled";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because FD was signalled";
+    EXPECT_EQ(1, handler.callbackCount)
+            << "callback should be invoked";
+
+    // Second loop: Callback is no longer registered and FD is signalled.
+    pipe.writeSignal();
+
+    stopWatch.reset();
+    result = mLooper->pollOnce(0);
+    elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    ASSERT_EQ(OK, pipe.readSignal())
+            << "signal should actually have been written";
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. equal zero because timeout was zero";
+    EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result)
+            << "pollOnce result should be ALOOPER_POLL_TIMEOUT";
+    EXPECT_EQ(1, handler.callbackCount)
+            << "callback should not be invoked this time";
+}
+
+TEST_F(LooperTest, PollOnce_WhenNonCallbackFdIsSignalled_ReturnsIdent) {
+    const int expectedIdent = 5;
+    void* expectedData = this;
+
+    Pipe pipe;
+
+    pipe.writeSignal();
+    mLooper->addFd(pipe.receiveFd, expectedIdent, ALOOPER_EVENT_INPUT, NULL, expectedData);
+
+    StopWatch stopWatch("pollOnce");
+    int fd;
+    int events;
+    void* data;
+    int result = mLooper->pollOnce(100, &fd, &events, &data);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    ASSERT_EQ(OK, pipe.readSignal())
+            << "signal should actually have been written";
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should be approx. zero";
+    EXPECT_EQ(expectedIdent, result)
+            << "pollOnce result should be the ident of the FD that was signalled";
+    EXPECT_EQ(pipe.receiveFd, fd)
+            << "pollOnce should have returned the received pipe fd";
+    EXPECT_EQ(ALOOPER_EVENT_INPUT, events)
+            << "pollOnce should have returned ALOOPER_EVENT_INPUT as events";
+    EXPECT_EQ(expectedData, data)
+            << "pollOnce should have returned the data";
+}
+
+TEST_F(LooperTest, AddFd_WhenCallbackAdded_ReturnsOne) {
+    Pipe pipe;
+    int result = mLooper->addFd(pipe.receiveFd, 0, ALOOPER_EVENT_INPUT, NULL, NULL);
+
+    EXPECT_EQ(1, result)
+            << "addFd should return 1 because FD was added";
+}
+
+TEST_F(LooperTest, AddFd_WhenIdentIsNegativeAndCallbackIsNull_ReturnsError) {
+    Pipe pipe;
+    int result = mLooper->addFd(pipe.receiveFd, -1, ALOOPER_EVENT_INPUT, NULL, NULL);
+
+    EXPECT_EQ(-1, result)
+            << "addFd should return -1 because arguments were invalid";
+}
+
+TEST_F(LooperTest, AddFd_WhenNoCallbackAndAllowNonCallbacksIsFalse_ReturnsError) {
+    Pipe pipe;
+    sp<Looper> looper = new Looper(false /*allowNonCallbacks*/);
+    int result = looper->addFd(pipe.receiveFd, 0, 0, NULL, NULL);
+
+    EXPECT_EQ(-1, result)
+            << "addFd should return -1 because arguments were invalid";
+}
+
+TEST_F(LooperTest, RemoveFd_WhenCallbackNotAdded_ReturnsZero) {
+    int result = mLooper->removeFd(1);
+
+    EXPECT_EQ(0, result)
+            << "removeFd should return 0 because FD not registered";
+}
+
+TEST_F(LooperTest, RemoveFd_WhenCallbackAddedThenRemovedTwice_ReturnsOnceFirstTimeAndReturnsZeroSecondTime) {
+    Pipe pipe;
+    StubCallbackHandler handler(false);
+    handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT);
+
+    // First time.
+    int result = mLooper->removeFd(pipe.receiveFd);
+
+    EXPECT_EQ(1, result)
+            << "removeFd should return 1 first time because FD was registered";
+
+    // Second time.
+    result = mLooper->removeFd(pipe.receiveFd);
+
+    EXPECT_EQ(0, result)
+            << "removeFd should return 0 second time because FD was no longer registered";
+}
+
+TEST_F(LooperTest, PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeInvoked) {
+    Pipe pipe;
+    StubCallbackHandler handler1(true);
+    StubCallbackHandler handler2(true);
+
+    handler1.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT);
+    handler2.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); // replace it
+    pipe.writeSignal(); // would cause FD to be considered signalled
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(100);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    ASSERT_EQ(OK, pipe.readSignal())
+            << "signal should actually have been written";
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. zero because FD was already signalled";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because FD was signalled";
+    EXPECT_EQ(0, handler1.callbackCount)
+            << "original handler callback should not be invoked because it was replaced";
+    EXPECT_EQ(1, handler2.callbackCount)
+            << "replacement handler callback should be invoked";
+}
+
+TEST_F(LooperTest, SendMessage_WhenOneMessageIsEnqueue_ShouldInvokeHandlerDuringNextPoll) {
+    sp<StubMessageHandler> handler = new StubMessageHandler();
+    mLooper->sendMessage(handler, Message(MSG_TEST1));
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(100);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. zero because message was already sent";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent";
+    EXPECT_EQ(size_t(1), handler->messages.size())
+            << "handled message";
+    EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
+            << "handled message";
+}
+
+TEST_F(LooperTest, SendMessage_WhenMultipleMessagesAreEnqueued_ShouldInvokeHandlersInOrderDuringNextPoll) {
+    sp<StubMessageHandler> handler1 = new StubMessageHandler();
+    sp<StubMessageHandler> handler2 = new StubMessageHandler();
+    mLooper->sendMessage(handler1, Message(MSG_TEST1));
+    mLooper->sendMessage(handler2, Message(MSG_TEST2));
+    mLooper->sendMessage(handler1, Message(MSG_TEST3));
+    mLooper->sendMessage(handler1, Message(MSG_TEST4));
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(1000);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. zero because message was already sent";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent";
+    EXPECT_EQ(size_t(3), handler1->messages.size())
+            << "handled message";
+    EXPECT_EQ(MSG_TEST1, handler1->messages[0].what)
+            << "handled message";
+    EXPECT_EQ(MSG_TEST3, handler1->messages[1].what)
+            << "handled message";
+    EXPECT_EQ(MSG_TEST4, handler1->messages[2].what)
+            << "handled message";
+    EXPECT_EQ(size_t(1), handler2->messages.size())
+            << "handled message";
+    EXPECT_EQ(MSG_TEST2, handler2->messages[0].what)
+            << "handled message";
+}
+
+TEST_F(LooperTest, SendMessageDelayed_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime) {
+    sp<StubMessageHandler> handler = new StubMessageHandler();
+    mLooper->sendMessageDelayed(ms2ns(100), handler, Message(MSG_TEST1));
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(1000);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "first poll should end quickly because next message timeout was computed";
+    EXPECT_EQ(ALOOPER_POLL_WAKE, result)
+            << "pollOnce result should be ALOOPER_POLL_WAKE due to wakeup";
+    EXPECT_EQ(size_t(0), handler->messages.size())
+            << "no message handled yet";
+
+    result = mLooper->pollOnce(1000);
+    elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_EQ(size_t(1), handler->messages.size())
+            << "handled message";
+    EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
+            << "handled message";
+    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "second poll should end around the time of the delayed message dispatch";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent";
+
+    result = mLooper->pollOnce(100);
+    elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(100 + 100, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "third poll should timeout";
+    EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result)
+            << "pollOnce result should be ALOOPER_POLL_TIMEOUT because there were no messages left";
+}
+
+TEST_F(LooperTest, SendMessageDelayed_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll) {
+    sp<StubMessageHandler> handler = new StubMessageHandler();
+    mLooper->sendMessageDelayed(ms2ns(-1000), handler, Message(MSG_TEST1));
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(100);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. zero because message was already sent";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent";
+    EXPECT_EQ(size_t(1), handler->messages.size())
+            << "handled message";
+    EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
+            << "handled message";
+}
+
+TEST_F(LooperTest, SendMessageDelayed_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll) {
+    sp<StubMessageHandler> handler = new StubMessageHandler();
+    mLooper->sendMessageDelayed(0, handler, Message(MSG_TEST1));
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(100);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. zero because message was already sent";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent";
+    EXPECT_EQ(size_t(1), handler->messages.size())
+            << "handled message";
+    EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
+            << "handled message";
+}
+
+TEST_F(LooperTest, SendMessageAtTime_WhenSentToTheFuture_ShouldInvokeHandlerAfterDelayTime) {
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    sp<StubMessageHandler> handler = new StubMessageHandler();
+    mLooper->sendMessageAtTime(now + ms2ns(100), handler, Message(MSG_TEST1));
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(1000);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "first poll should end quickly because next message timeout was computed";
+    EXPECT_EQ(ALOOPER_POLL_WAKE, result)
+            << "pollOnce result should be ALOOPER_POLL_WAKE due to wakeup";
+    EXPECT_EQ(size_t(0), handler->messages.size())
+            << "no message handled yet";
+
+    result = mLooper->pollOnce(1000);
+    elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_EQ(size_t(1), handler->messages.size())
+            << "handled message";
+    EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
+            << "handled message";
+    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "second poll should end around the time of the delayed message dispatch";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent";
+
+    result = mLooper->pollOnce(100);
+    elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(100 + 100, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "third poll should timeout";
+    EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result)
+            << "pollOnce result should be ALOOPER_POLL_TIMEOUT because there were no messages left";
+}
+
+TEST_F(LooperTest, SendMessageAtTime_WhenSentToThePast_ShouldInvokeHandlerDuringNextPoll) {
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    sp<StubMessageHandler> handler = new StubMessageHandler();
+    mLooper->sendMessageAtTime(now - ms2ns(1000), handler, Message(MSG_TEST1));
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(100);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. zero because message was already sent";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent";
+    EXPECT_EQ(size_t(1), handler->messages.size())
+            << "handled message";
+    EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
+            << "handled message";
+}
+
+TEST_F(LooperTest, SendMessageAtTime_WhenSentToThePresent_ShouldInvokeHandlerDuringNextPoll) {
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    sp<StubMessageHandler> handler = new StubMessageHandler();
+    mLooper->sendMessageAtTime(now, handler, Message(MSG_TEST1));
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(100);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. zero because message was already sent";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because message was sent";
+    EXPECT_EQ(size_t(1), handler->messages.size())
+            << "handled message";
+    EXPECT_EQ(MSG_TEST1, handler->messages[0].what)
+            << "handled message";
+}
+
+TEST_F(LooperTest, RemoveMessage_WhenRemovingAllMessagesForHandler_ShouldRemoveThoseMessage) {
+    sp<StubMessageHandler> handler = new StubMessageHandler();
+    mLooper->sendMessage(handler, Message(MSG_TEST1));
+    mLooper->sendMessage(handler, Message(MSG_TEST2));
+    mLooper->sendMessage(handler, Message(MSG_TEST3));
+    mLooper->removeMessages(handler);
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(0);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. zero because message was sent so looper was awoken";
+    EXPECT_EQ(ALOOPER_POLL_WAKE, result)
+            << "pollOnce result should be ALOOPER_POLL_WAKE because looper was awoken";
+    EXPECT_EQ(size_t(0), handler->messages.size())
+            << "no messages to handle";
+
+    result = mLooper->pollOnce(0);
+
+    EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result)
+            << "pollOnce result should be ALOOPER_POLL_TIMEOUT because there was nothing to do";
+    EXPECT_EQ(size_t(0), handler->messages.size())
+            << "no messages to handle";
+}
+
+TEST_F(LooperTest, RemoveMessage_WhenRemovingSomeMessagesForHandler_ShouldRemoveThoseMessage) {
+    sp<StubMessageHandler> handler = new StubMessageHandler();
+    mLooper->sendMessage(handler, Message(MSG_TEST1));
+    mLooper->sendMessage(handler, Message(MSG_TEST2));
+    mLooper->sendMessage(handler, Message(MSG_TEST3));
+    mLooper->sendMessage(handler, Message(MSG_TEST4));
+    mLooper->removeMessages(handler, MSG_TEST3);
+    mLooper->removeMessages(handler, MSG_TEST1);
+
+    StopWatch stopWatch("pollOnce");
+    int result = mLooper->pollOnce(0);
+    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+            << "elapsed time should approx. zero because message was sent so looper was awoken";
+    EXPECT_EQ(ALOOPER_POLL_CALLBACK, result)
+            << "pollOnce result should be ALOOPER_POLL_CALLBACK because two messages were sent";
+    EXPECT_EQ(size_t(2), handler->messages.size())
+            << "no messages to handle";
+    EXPECT_EQ(MSG_TEST2, handler->messages[0].what)
+            << "handled message";
+    EXPECT_EQ(MSG_TEST4, handler->messages[1].what)
+            << "handled message";
+
+    result = mLooper->pollOnce(0);
+
+    EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result)
+            << "pollOnce result should be ALOOPER_POLL_TIMEOUT because there was nothing to do";
+    EXPECT_EQ(size_t(2), handler->messages.size())
+            << "no more messages to handle";
+}
+
+} // namespace android
diff --git a/libutils/tests/LruCache_test.cpp b/libutils/tests/LruCache_test.cpp
new file mode 100644
index 0000000..e573952
--- /dev/null
+++ b/libutils/tests/LruCache_test.cpp
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <stdlib.h>
+#include <utils/JenkinsHash.h>
+#include <utils/LruCache.h>
+#include <cutils/log.h>
+#include <gtest/gtest.h>
+
+namespace android {
+
+typedef int SimpleKey;
+typedef const char* StringValue;
+
+struct ComplexKey {
+    int k;
+
+    explicit ComplexKey(int k) : k(k) {
+        instanceCount += 1;
+    }
+
+    ComplexKey(const ComplexKey& other) : k(other.k) {
+        instanceCount += 1;
+    }
+
+    ~ComplexKey() {
+        instanceCount -= 1;
+    }
+
+    bool operator ==(const ComplexKey& other) const {
+        return k == other.k;
+    }
+
+    bool operator !=(const ComplexKey& other) const {
+        return k != other.k;
+    }
+
+    static ssize_t instanceCount;
+};
+
+ssize_t ComplexKey::instanceCount = 0;
+
+template<> inline hash_t hash_type(const ComplexKey& value) {
+    return hash_type(value.k);
+}
+
+struct ComplexValue {
+    int v;
+
+    explicit ComplexValue(int v) : v(v) {
+        instanceCount += 1;
+    }
+
+    ComplexValue(const ComplexValue& other) : v(other.v) {
+        instanceCount += 1;
+    }
+
+    ~ComplexValue() {
+        instanceCount -= 1;
+    }
+
+    static ssize_t instanceCount;
+};
+
+ssize_t ComplexValue::instanceCount = 0;
+
+typedef LruCache<ComplexKey, ComplexValue> ComplexCache;
+
+class EntryRemovedCallback : public OnEntryRemoved<SimpleKey, StringValue> {
+public:
+    EntryRemovedCallback() : callbackCount(0), lastKey(-1), lastValue(NULL) { }
+    ~EntryRemovedCallback() {}
+    void operator()(SimpleKey& k, StringValue& v) {
+        callbackCount += 1;
+        lastKey = k;
+        lastValue = v;
+    }
+    ssize_t callbackCount;
+    SimpleKey lastKey;
+    StringValue lastValue;
+};
+
+class LruCacheTest : public testing::Test {
+protected:
+    virtual void SetUp() {
+        ComplexKey::instanceCount = 0;
+        ComplexValue::instanceCount = 0;
+    }
+
+    virtual void TearDown() {
+        ASSERT_NO_FATAL_FAILURE(assertInstanceCount(0, 0));
+    }
+
+    void assertInstanceCount(ssize_t keys, ssize_t values) {
+        if (keys != ComplexKey::instanceCount || values != ComplexValue::instanceCount) {
+            FAIL() << "Expected " << keys << " keys and " << values << " values "
+                    "but there were actually " << ComplexKey::instanceCount << " keys and "
+                    << ComplexValue::instanceCount << " values";
+        }
+    }
+};
+
+TEST_F(LruCacheTest, Empty) {
+    LruCache<SimpleKey, StringValue> cache(100);
+
+    EXPECT_EQ(NULL, cache.get(0));
+    EXPECT_EQ(0u, cache.size());
+}
+
+TEST_F(LruCacheTest, Simple) {
+    LruCache<SimpleKey, StringValue> cache(100);
+
+    cache.put(1, "one");
+    cache.put(2, "two");
+    cache.put(3, "three");
+    EXPECT_STREQ("one", cache.get(1));
+    EXPECT_STREQ("two", cache.get(2));
+    EXPECT_STREQ("three", cache.get(3));
+    EXPECT_EQ(3u, cache.size());
+}
+
+TEST_F(LruCacheTest, MaxCapacity) {
+    LruCache<SimpleKey, StringValue> cache(2);
+
+    cache.put(1, "one");
+    cache.put(2, "two");
+    cache.put(3, "three");
+    EXPECT_EQ(NULL, cache.get(1));
+    EXPECT_STREQ("two", cache.get(2));
+    EXPECT_STREQ("three", cache.get(3));
+    EXPECT_EQ(2u, cache.size());
+}
+
+TEST_F(LruCacheTest, RemoveLru) {
+    LruCache<SimpleKey, StringValue> cache(100);
+
+    cache.put(1, "one");
+    cache.put(2, "two");
+    cache.put(3, "three");
+    cache.removeOldest();
+    EXPECT_EQ(NULL, cache.get(1));
+    EXPECT_STREQ("two", cache.get(2));
+    EXPECT_STREQ("three", cache.get(3));
+    EXPECT_EQ(2u, cache.size());
+}
+
+TEST_F(LruCacheTest, GetUpdatesLru) {
+    LruCache<SimpleKey, StringValue> cache(100);
+
+    cache.put(1, "one");
+    cache.put(2, "two");
+    cache.put(3, "three");
+    EXPECT_STREQ("one", cache.get(1));
+    cache.removeOldest();
+    EXPECT_STREQ("one", cache.get(1));
+    EXPECT_EQ(NULL, cache.get(2));
+    EXPECT_STREQ("three", cache.get(3));
+    EXPECT_EQ(2u, cache.size());
+}
+
+uint32_t hash_int(int x) {
+    return JenkinsHashWhiten(JenkinsHashMix(0, x));
+}
+
+TEST_F(LruCacheTest, StressTest) {
+    const size_t kCacheSize = 512;
+    LruCache<SimpleKey, StringValue> cache(512);
+    const size_t kNumKeys = 16 * 1024;
+    const size_t kNumIters = 100000;
+    char* strings[kNumKeys];
+
+    for (size_t i = 0; i < kNumKeys; i++) {
+        strings[i] = (char *)malloc(16);
+        sprintf(strings[i], "%d", i);
+    }
+
+    srandom(12345);
+    int hitCount = 0;
+    for (size_t i = 0; i < kNumIters; i++) {
+        int index = random() % kNumKeys;
+        uint32_t key = hash_int(index);
+        const char *val = cache.get(key);
+        if (val != NULL) {
+            EXPECT_EQ(strings[index], val);
+            hitCount++;
+        } else {
+            cache.put(key, strings[index]);
+        }
+    }
+    size_t expectedHitCount = kNumIters * kCacheSize / kNumKeys;
+    EXPECT_LT(int(expectedHitCount * 0.9), hitCount);
+    EXPECT_GT(int(expectedHitCount * 1.1), hitCount);
+    EXPECT_EQ(kCacheSize, cache.size());
+
+    for (size_t i = 0; i < kNumKeys; i++) {
+        free((void *)strings[i]);
+    }
+}
+
+TEST_F(LruCacheTest, NoLeak) {
+    ComplexCache cache(100);
+
+    cache.put(ComplexKey(0), ComplexValue(0));
+    cache.put(ComplexKey(1), ComplexValue(1));
+    EXPECT_EQ(2, cache.size());
+    assertInstanceCount(2, 3);  // the null value counts as an instance
+}
+
+TEST_F(LruCacheTest, Clear) {
+    ComplexCache cache(100);
+
+    cache.put(ComplexKey(0), ComplexValue(0));
+    cache.put(ComplexKey(1), ComplexValue(1));
+    EXPECT_EQ(2, cache.size());
+    assertInstanceCount(2, 3);
+    cache.clear();
+    assertInstanceCount(0, 1);
+}
+
+TEST_F(LruCacheTest, ClearNoDoubleFree) {
+    {
+        ComplexCache cache(100);
+
+        cache.put(ComplexKey(0), ComplexValue(0));
+        cache.put(ComplexKey(1), ComplexValue(1));
+        EXPECT_EQ(2, cache.size());
+        assertInstanceCount(2, 3);
+        cache.removeOldest();
+        cache.clear();
+        assertInstanceCount(0, 1);
+    }
+    assertInstanceCount(0, 0);
+}
+
+TEST_F(LruCacheTest, ClearReuseOk) {
+    ComplexCache cache(100);
+
+    cache.put(ComplexKey(0), ComplexValue(0));
+    cache.put(ComplexKey(1), ComplexValue(1));
+    EXPECT_EQ(2, cache.size());
+    assertInstanceCount(2, 3);
+    cache.clear();
+    assertInstanceCount(0, 1);
+    cache.put(ComplexKey(0), ComplexValue(0));
+    cache.put(ComplexKey(1), ComplexValue(1));
+    EXPECT_EQ(2, cache.size());
+    assertInstanceCount(2, 3);
+}
+
+TEST_F(LruCacheTest, Callback) {
+    LruCache<SimpleKey, StringValue> cache(100);
+    EntryRemovedCallback callback;
+    cache.setOnEntryRemovedListener(&callback);
+
+    cache.put(1, "one");
+    cache.put(2, "two");
+    cache.put(3, "three");
+    EXPECT_EQ(3, cache.size());
+    cache.removeOldest();
+    EXPECT_EQ(1, callback.callbackCount);
+    EXPECT_EQ(1, callback.lastKey);
+    EXPECT_STREQ("one", callback.lastValue);
+}
+
+TEST_F(LruCacheTest, CallbackOnClear) {
+    LruCache<SimpleKey, StringValue> cache(100);
+    EntryRemovedCallback callback;
+    cache.setOnEntryRemovedListener(&callback);
+
+    cache.put(1, "one");
+    cache.put(2, "two");
+    cache.put(3, "three");
+    EXPECT_EQ(3, cache.size());
+    cache.clear();
+    EXPECT_EQ(3, callback.callbackCount);
+}
+
+}
diff --git a/libutils/tests/String8_test.cpp b/libutils/tests/String8_test.cpp
new file mode 100644
index 0000000..c42c68d
--- /dev/null
+++ b/libutils/tests/String8_test.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#define LOG_TAG "String8_test"
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+
+class String8Test : public testing::Test {
+protected:
+    virtual void SetUp() {
+    }
+
+    virtual void TearDown() {
+    }
+};
+
+TEST_F(String8Test, Cstr) {
+    String8 tmp("Hello, world!");
+
+    EXPECT_STREQ(tmp.string(), "Hello, world!");
+}
+
+TEST_F(String8Test, OperatorPlus) {
+    String8 src1("Hello, ");
+
+    // Test adding String8 + const char*
+    const char* ccsrc2 = "world!";
+    String8 dst1 = src1 + ccsrc2;
+    EXPECT_STREQ(dst1.string(), "Hello, world!");
+    EXPECT_STREQ(src1.string(), "Hello, ");
+    EXPECT_STREQ(ccsrc2, "world!");
+
+    // Test adding String8 + String8
+    String8 ssrc2("world!");
+    String8 dst2 = src1 + ssrc2;
+    EXPECT_STREQ(dst2.string(), "Hello, world!");
+    EXPECT_STREQ(src1.string(), "Hello, ");
+    EXPECT_STREQ(ssrc2.string(), "world!");
+}
+
+TEST_F(String8Test, OperatorPlusEquals) {
+    String8 src1("My voice");
+
+    // Testing String8 += String8
+    String8 src2(" is my passport.");
+    src1 += src2;
+    EXPECT_STREQ(src1.string(), "My voice is my passport.");
+    EXPECT_STREQ(src2.string(), " is my passport.");
+
+    // Adding const char* to the previous string.
+    const char* src3 = " Verify me.";
+    src1 += src3;
+    EXPECT_STREQ(src1.string(), "My voice is my passport. Verify me.");
+    EXPECT_STREQ(src2.string(), " is my passport.");
+    EXPECT_STREQ(src3, " Verify me.");
+}
+
+}
diff --git a/libutils/tests/TestHelpers.h b/libutils/tests/TestHelpers.h
new file mode 100644
index 0000000..d8e985e
--- /dev/null
+++ b/libutils/tests/TestHelpers.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef TESTHELPERS_H
+#define TESTHELPERS_H
+
+#include <utils/threads.h>
+
+namespace android {
+
+class Pipe {
+public:
+    int sendFd;
+    int receiveFd;
+
+    Pipe() {
+        int fds[2];
+        ::pipe(fds);
+
+        receiveFd = fds[0];
+        sendFd = fds[1];
+    }
+
+    ~Pipe() {
+        if (sendFd != -1) {
+            ::close(sendFd);
+        }
+
+        if (receiveFd != -1) {
+            ::close(receiveFd);
+        }
+    }
+
+    status_t writeSignal() {
+        ssize_t nWritten = ::write(sendFd, "*", 1);
+        return nWritten == 1 ? 0 : -errno;
+    }
+
+    status_t readSignal() {
+        char buf[1];
+        ssize_t nRead = ::read(receiveFd, buf, 1);
+        return nRead == 1 ? 0 : nRead == 0 ? -EPIPE : -errno;
+    }
+};
+
+class DelayedTask : public Thread {
+    int mDelayMillis;
+
+public:
+    DelayedTask(int delayMillis) : mDelayMillis(delayMillis) { }
+
+protected:
+    virtual ~DelayedTask() { }
+
+    virtual void doTask() = 0;
+
+    virtual bool threadLoop() {
+        usleep(mDelayMillis * 1000);
+        doTask();
+        return false;
+    }
+};
+
+} // namespace android
+
+#endif // TESTHELPERS_H
diff --git a/libutils/tests/Unicode_test.cpp b/libutils/tests/Unicode_test.cpp
new file mode 100644
index 0000000..18c130c
--- /dev/null
+++ b/libutils/tests/Unicode_test.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#define LOG_TAG "Unicode_test"
+#include <utils/Log.h>
+#include <utils/Unicode.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+
+class UnicodeTest : public testing::Test {
+protected:
+    virtual void SetUp() {
+    }
+
+    virtual void TearDown() {
+    }
+};
+
+TEST_F(UnicodeTest, UTF8toUTF16ZeroLength) {
+    ssize_t measured;
+
+    const uint8_t str[] = { };
+
+    measured = utf8_to_utf16_length(str, 0);
+    EXPECT_EQ(0, measured)
+            << "Zero length input should return zero length output.";
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16ASCIILength) {
+    ssize_t measured;
+
+    // U+0030 or ASCII '0'
+    const uint8_t str[] = { 0x30 };
+
+    measured = utf8_to_utf16_length(str, sizeof(str));
+    EXPECT_EQ(1, measured)
+            << "ASCII glyphs should have a length of 1 char16_t";
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16Plane1Length) {
+    ssize_t measured;
+
+    // U+2323 SMILE
+    const uint8_t str[] = { 0xE2, 0x8C, 0xA3 };
+
+    measured = utf8_to_utf16_length(str, sizeof(str));
+    EXPECT_EQ(1, measured)
+            << "Plane 1 glyphs should have a length of 1 char16_t";
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16SurrogateLength) {
+    ssize_t measured;
+
+    // U+10000
+    const uint8_t str[] = { 0xF0, 0x90, 0x80, 0x80 };
+
+    measured = utf8_to_utf16_length(str, sizeof(str));
+    EXPECT_EQ(2, measured)
+            << "Surrogate pairs should have a length of 2 char16_t";
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16TruncatedUTF8) {
+    ssize_t measured;
+
+    // Truncated U+2323 SMILE
+    // U+2323 SMILE
+    const uint8_t str[] = { 0xE2, 0x8C };
+
+    measured = utf8_to_utf16_length(str, sizeof(str));
+    EXPECT_EQ(-1, measured)
+            << "Truncated UTF-8 should return -1 to indicate invalid";
+}
+
+TEST_F(UnicodeTest, UTF8toUTF16Normal) {
+    const uint8_t str[] = {
+        0x30, // U+0030, 1 UTF-16 character
+        0xC4, 0x80, // U+0100, 1 UTF-16 character
+        0xE2, 0x8C, 0xA3, // U+2323, 1 UTF-16 character
+        0xF0, 0x90, 0x80, 0x80, // U+10000, 2 UTF-16 character
+    };
+
+    char16_t output[1 + 1 + 1 + 2 + 1]; // Room for NULL
+
+    utf8_to_utf16(str, sizeof(str), output);
+
+    EXPECT_EQ(0x0030, output[0])
+            << "should be U+0030";
+    EXPECT_EQ(0x0100, output[1])
+            << "should be U+0100";
+    EXPECT_EQ(0x2323, output[2])
+            << "should be U+2323";
+    EXPECT_EQ(0xD800, output[3])
+            << "should be first half of surrogate U+10000";
+    EXPECT_EQ(0xDC00, output[4])
+            << "should be second half of surrogate U+10000";
+    EXPECT_EQ(NULL, output[5])
+            << "should be NULL terminated";
+}
+
+}
diff --git a/libutils/tests/Vector_test.cpp b/libutils/tests/Vector_test.cpp
new file mode 100644
index 0000000..d29c054
--- /dev/null
+++ b/libutils/tests/Vector_test.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#define LOG_TAG "Vector_test"
+
+#include <utils/Vector.h>
+#include <cutils/log.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+namespace android {
+
+class VectorTest : public testing::Test {
+protected:
+    virtual void SetUp() {
+    }
+
+    virtual void TearDown() {
+    }
+
+public:
+};
+
+
+TEST_F(VectorTest, CopyOnWrite_CopyAndAddElements) {
+
+    Vector<int> vector;
+    Vector<int> other;
+    vector.setCapacity(8);
+
+    vector.add(1);
+    vector.add(2);
+    vector.add(3);
+
+    EXPECT_EQ(vector.size(), 3);
+
+    // copy the vector
+    other = vector;
+
+    EXPECT_EQ(other.size(), 3);
+
+    // add an element to the first vector
+    vector.add(4);
+
+    // make sure the sizes are correct
+    EXPECT_EQ(vector.size(), 4);
+    EXPECT_EQ(other.size(), 3);
+
+    // add an element to the copy
+    other.add(5);
+
+    // make sure the sizes are correct
+    EXPECT_EQ(vector.size(), 4);
+    EXPECT_EQ(other.size(), 4);
+
+    // make sure the content of both vectors are correct
+    EXPECT_EQ(vector[3], 4);
+    EXPECT_EQ(other[3], 5);
+}
+
+
+} // namespace android
diff --git a/libziparchive/Android.mk b/libziparchive/Android.mk
new file mode 100644
index 0000000..5d836a1
--- /dev/null
+++ b/libziparchive/Android.mk
@@ -0,0 +1,69 @@
+#
+# Copyright (C) 2013 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+source_files := \
+	zip_archive.h \
+	zip_archive.cc
+
+includes := external/zlib
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_SRC_FILES := ${source_files}
+
+LOCAL_STATIC_LIBRARIES := libz
+LOCAL_SHARED_LIBRARIES := libutils
+LOCAL_MODULE:= libziparchive
+
+LOCAL_C_INCLUDES += ${includes}
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libziparchive
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_SRC_FILES := ${source_files}
+LOCAL_C_INCLUDES += ${includes}
+
+LOCAL_STATIC_LIBRARIES := libz libutils
+LOCAL_MODULE:= libziparchive-host
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := ziparchive-tests
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS += \
+    -DGTEST_OS_LINUX_ANDROID \
+    -DGTEST_HAS_STD_STRING
+LOCAL_SRC_FILES := zip_archive_test.cc
+LOCAL_LDFLAGS := -llog
+LOCAL_STATIC_LIBRARIES := libziparchive libz libgtest libgtest_main libutils
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := ziparchive-tests-host
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CFLAGS += \
+    -DGTEST_OS_LINUX \
+    -DGTEST_HAS_STD_STRING
+LOCAL_SRC_FILES := zip_archive_test.cc
+LOCAL_STATIC_LIBRARIES := libziparchive-host \
+	libz \
+	libgtest_host \
+	libgtest_main_host \
+	liblog \
+	libutils
+include $(BUILD_HOST_NATIVE_TEST)
diff --git a/libziparchive/testdata/valid.zip b/libziparchive/testdata/valid.zip
new file mode 100644
index 0000000..9e7cb78
--- /dev/null
+++ b/libziparchive/testdata/valid.zip
Binary files differ
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
new file mode 100644
index 0000000..2b827b3
--- /dev/null
+++ b/libziparchive/zip_archive.cc
@@ -0,0 +1,1048 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+/*
+ * Read-only access to Zip archives, with minimal heap allocation.
+ */
+#include "ziparchive/zip_archive.h"
+
+#include <zlib.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <log/log.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utils/FileMap.h>
+
+#include <JNIHelp.h>  // TEMP_FAILURE_RETRY may or may not be in unistd
+
+// This is for windows. If we don't open a file in binary mode, weirds
+// things will happen.
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/*
+ * Zip file constants.
+ */
+static const uint32_t kEOCDSignature    = 0x06054b50;
+static const uint32_t kEOCDLen          = 2;
+static const uint32_t kEOCDNumEntries   = 8;              // offset to #of entries in file
+static const uint32_t kEOCDSize         = 12;             // size of the central directory
+static const uint32_t kEOCDFileOffset   = 16;             // offset to central directory
+
+static const uint32_t kMaxCommentLen    = 65535;          // longest possible in ushort
+static const uint32_t kMaxEOCDSearch    = (kMaxCommentLen + kEOCDLen);
+
+static const uint32_t kLFHSignature     = 0x04034b50;
+static const uint32_t kLFHLen           = 30;             // excluding variable-len fields
+static const uint32_t kLFHGPBFlags      = 6;              // general purpose bit flags
+static const uint32_t kLFHCRC           = 14;             // offset to CRC
+static const uint32_t kLFHCompLen       = 18;             // offset to compressed length
+static const uint32_t kLFHUncompLen     = 22;             // offset to uncompressed length
+static const uint32_t kLFHNameLen       = 26;             // offset to filename length
+static const uint32_t kLFHExtraLen      = 28;             // offset to extra length
+
+static const uint32_t kCDESignature     = 0x02014b50;
+static const uint32_t kCDELen           = 46;             // excluding variable-len fields
+static const uint32_t kCDEMethod        = 10;             // offset to compression method
+static const uint32_t kCDEModWhen       = 12;             // offset to modification timestamp
+static const uint32_t kCDECRC           = 16;             // offset to entry CRC
+static const uint32_t kCDECompLen       = 20;             // offset to compressed length
+static const uint32_t kCDEUncompLen     = 24;             // offset to uncompressed length
+static const uint32_t kCDENameLen       = 28;             // offset to filename length
+static const uint32_t kCDEExtraLen      = 30;             // offset to extra length
+static const uint32_t kCDECommentLen    = 32;             // offset to comment length
+static const uint32_t kCDELocalOffset   = 42;             // offset to local hdr
+
+static const uint32_t kDDOptSignature   = 0x08074b50;     // *OPTIONAL* data descriptor signature
+static const uint32_t kDDSignatureLen   = 4;
+static const uint32_t kDDLen            = 12;
+static const uint32_t kDDMaxLen         = 16;             // max of 16 bytes with a signature, 12 bytes without
+static const uint32_t kDDCrc32          = 0;              // offset to crc32
+static const uint32_t kDDCompLen        = 4;              // offset to compressed length
+static const uint32_t kDDUncompLen      = 8;              // offset to uncompressed length
+
+static const uint32_t kGPBDDFlagMask    = 0x0008;         // mask value that signifies that the entry has a DD
+
+static const uint32_t kMaxErrorLen = 1024;
+
+static const char* kErrorMessages[] = {
+  "Unknown return code.",
+  "Iteration ended",
+  "Zlib error",
+  "Invalid file",
+  "Invalid handle",
+  "Duplicate entries in archive",
+  "Empty archive",
+  "Entry not found",
+  "Invalid offset",
+  "Inconsistent information",
+  "Invalid entry name",
+  "I/O Error",
+  "File mapping failed"
+};
+
+static const int32_t kErrorMessageUpperBound = 0;
+
+static const int32_t kIterationEnd = -1;
+
+// We encountered a Zlib error when inflating a stream from this file.
+// Usually indicates file corruption.
+static const int32_t kZlibError = -2;
+
+// The input file cannot be processed as a zip archive. Usually because
+// it's too small, too large or does not have a valid signature.
+static const int32_t kInvalidFile = -3;
+
+// An invalid iteration / ziparchive handle was passed in as an input
+// argument.
+static const int32_t kInvalidHandle = -4;
+
+// The zip archive contained two (or possibly more) entries with the same
+// name.
+static const int32_t kDuplicateEntry = -5;
+
+// The zip archive contains no entries.
+static const int32_t kEmptyArchive = -6;
+
+// The specified entry was not found in the archive.
+static const int32_t kEntryNotFound = -7;
+
+// The zip archive contained an invalid local file header pointer.
+static const int32_t kInvalidOffset = -8;
+
+// The zip archive contained inconsistent entry information. This could
+// be because the central directory & local file header did not agree, or
+// if the actual uncompressed length or crc32 do not match their declared
+// values.
+static const int32_t kInconsistentInformation = -9;
+
+// An invalid entry name was encountered.
+static const int32_t kInvalidEntryName = -10;
+
+// An I/O related system call (read, lseek, ftruncate, map) failed.
+static const int32_t kIoError = -11;
+
+// We were not able to mmap the central directory or entry contents.
+static const int32_t kMmapFailed = -12;
+
+static const int32_t kErrorMessageLowerBound = -13;
+
+static const char kTempMappingFileName[] = "zip: ExtractFileToFile";
+
+/*
+ * A Read-only Zip archive.
+ *
+ * We want "open" and "find entry by name" to be fast operations, and
+ * we want to use as little memory as possible.  We memory-map the zip
+ * central directory, and load a hash table with pointers to the filenames
+ * (which aren't null-terminated).  The other fields are at a fixed offset
+ * from the filename, so we don't need to extract those (but we do need
+ * to byte-read and endian-swap them every time we want them).
+ *
+ * It's possible that somebody has handed us a massive (~1GB) zip archive,
+ * so we can't expect to mmap the entire file.
+ *
+ * To speed comparisons when doing a lookup by name, we could make the mapping
+ * "private" (copy-on-write) and null-terminate the filenames after verifying
+ * the record structure.  However, this requires a private mapping of
+ * every page that the Central Directory touches.  Easier to tuck a copy
+ * of the string length into the hash table entry.
+ */
+struct ZipArchive {
+  /* open Zip archive */
+  int fd;
+
+  /* mapped central directory area */
+  off64_t directory_offset;
+  android::FileMap* directory_map;
+
+  /* number of entries in the Zip archive */
+  uint16_t num_entries;
+
+  /*
+   * We know how many entries are in the Zip archive, so we can have a
+   * fixed-size hash table. We define a load factor of 0.75 and overallocat
+   * so the maximum number entries can never be higher than
+   * ((4 * UINT16_MAX) / 3 + 1) which can safely fit into a uint32_t.
+   */
+  uint32_t hash_table_size;
+  ZipEntryName* hash_table;
+};
+
+// Returns 0 on success and negative values on failure.
+static android::FileMap* MapFileSegment(const int fd, const off64_t start,
+                                        const size_t length, const bool read_only,
+                                        const char* debug_file_name) {
+  android::FileMap* file_map = new android::FileMap;
+  const bool success = file_map->create(debug_file_name, fd, start, length, read_only);
+  if (!success) {
+    file_map->release();
+    return NULL;
+  }
+
+  return file_map;
+}
+
+static int32_t CopyFileToFile(int fd, uint8_t* begin, const uint32_t length, uint64_t *crc_out) {
+  static const uint32_t kBufSize = 32768;
+  uint8_t buf[kBufSize];
+
+  uint32_t count = 0;
+  uint64_t crc = 0;
+  while (count < length) {
+    uint32_t remaining = length - count;
+
+    // Safe conversion because kBufSize is narrow enough for a 32 bit signed
+    // value.
+    ssize_t get_size = (remaining > kBufSize) ? kBufSize : remaining;
+    ssize_t actual = TEMP_FAILURE_RETRY(read(fd, buf, get_size));
+
+    if (actual != get_size) {
+      ALOGW("CopyFileToFile: copy read failed (%d vs %zd)",
+          (int) actual, get_size);
+      return kIoError;
+    }
+
+    memcpy(begin + count, buf, get_size);
+    crc = crc32(crc, buf, get_size);
+    count += get_size;
+  }
+
+  *crc_out = crc;
+
+  return 0;
+}
+
+/*
+ * Round up to the next highest power of 2.
+ *
+ * Found on http://graphics.stanford.edu/~seander/bithacks.html.
+ */
+static uint32_t RoundUpPower2(uint32_t val) {
+  val--;
+  val |= val >> 1;
+  val |= val >> 2;
+  val |= val >> 4;
+  val |= val >> 8;
+  val |= val >> 16;
+  val++;
+
+  return val;
+}
+
+static uint32_t ComputeHash(const char* str, uint16_t len) {
+  uint32_t hash = 0;
+
+  while (len--) {
+    hash = hash * 31 + *str++;
+  }
+
+  return hash;
+}
+
+/*
+ * Convert a ZipEntry to a hash table index, verifying that it's in a
+ * valid range.
+ */
+static int64_t EntryToIndex(const ZipEntryName* hash_table,
+                            const uint32_t hash_table_size,
+                            const char* name, uint16_t length) {
+  const uint32_t hash = ComputeHash(name, length);
+
+  // NOTE: (hash_table_size - 1) is guaranteed to be non-negative.
+  uint32_t ent = hash & (hash_table_size - 1);
+  while (hash_table[ent].name != NULL) {
+    if (hash_table[ent].name_length == length &&
+        memcmp(hash_table[ent].name, name, length) == 0) {
+      return ent;
+    }
+
+    ent = (ent + 1) & (hash_table_size - 1);
+  }
+
+  ALOGV("Zip: Unable to find entry %.*s", name_length, name);
+  return kEntryNotFound;
+}
+
+/*
+ * Add a new entry to the hash table.
+ */
+static int32_t AddToHash(ZipEntryName *hash_table, const uint64_t hash_table_size,
+                         const char* name, uint16_t length) {
+  const uint64_t hash = ComputeHash(name, length);
+  uint32_t ent = hash & (hash_table_size - 1);
+
+  /*
+   * We over-allocated the table, so we're guaranteed to find an empty slot.
+   * Further, we guarantee that the hashtable size is not 0.
+   */
+  while (hash_table[ent].name != NULL) {
+    if (hash_table[ent].name_length == length &&
+        memcmp(hash_table[ent].name, name, length) == 0) {
+      // We've found a duplicate entry. We don't accept it
+      ALOGW("Zip: Found duplicate entry %.*s", length, name);
+      return kDuplicateEntry;
+    }
+    ent = (ent + 1) & (hash_table_size - 1);
+  }
+
+  hash_table[ent].name = name;
+  hash_table[ent].name_length = length;
+  return 0;
+}
+
+/*
+ * Get 2 little-endian bytes.
+ */
+static uint16_t get2LE(const uint8_t* src) {
+  return src[0] | (src[1] << 8);
+}
+
+/*
+ * Get 4 little-endian bytes.
+ */
+static uint32_t get4LE(const uint8_t* src) {
+  uint32_t result;
+
+  result = src[0];
+  result |= src[1] << 8;
+  result |= src[2] << 16;
+  result |= src[3] << 24;
+
+  return result;
+}
+
+static int32_t MapCentralDirectory0(int fd, const char* debug_file_name,
+                                    ZipArchive* archive, off64_t file_length,
+                                    uint32_t read_amount, uint8_t* scan_buffer) {
+  const off64_t search_start = file_length - read_amount;
+
+  if (lseek64(fd, search_start, SEEK_SET) != search_start) {
+    ALOGW("Zip: seek %lld failed: %s", search_start, strerror(errno));
+    return kIoError;
+  }
+  ssize_t actual = TEMP_FAILURE_RETRY(read(fd, scan_buffer, read_amount));
+  if (actual != (ssize_t) read_amount) {
+    ALOGW("Zip: read %zd failed: %s", read_amount, strerror(errno));
+    return kIoError;
+  }
+
+  /*
+   * Scan backward for the EOCD magic.  In an archive without a trailing
+   * comment, we'll find it on the first try.  (We may want to consider
+   * doing an initial minimal read; if we don't find it, retry with a
+   * second read as above.)
+   */
+  int i;
+  for (i = read_amount - kEOCDLen; i >= 0; i--) {
+    if (scan_buffer[i] == 0x50 && get4LE(&scan_buffer[i]) == kEOCDSignature) {
+      ALOGV("+++ Found EOCD at buf+%d", i);
+      break;
+    }
+  }
+  if (i < 0) {
+    ALOGD("Zip: EOCD not found, %s is not zip", debug_file_name);
+    return kInvalidFile;
+  }
+
+  const off64_t eocd_offset = search_start + i;
+  const uint8_t* eocd_ptr = scan_buffer + i;
+
+  assert(eocd_offset < file_length);
+
+  /*
+   * Grab the CD offset and size, and the number of entries in the
+   * archive.  Verify that they look reasonable. Widen dir_size and
+   * dir_offset to the file offset type.
+   */
+  const uint16_t num_entries = get2LE(eocd_ptr + kEOCDNumEntries);
+  const off64_t dir_size = get4LE(eocd_ptr + kEOCDSize);
+  const off64_t dir_offset = get4LE(eocd_ptr + kEOCDFileOffset);
+
+  if (dir_offset + dir_size > eocd_offset) {
+    ALOGW("Zip: bad offsets (dir %lld, size %lld, eocd %lld)",
+        dir_offset, dir_size, eocd_offset);
+    return kInvalidOffset;
+  }
+  if (num_entries == 0) {
+    ALOGW("Zip: empty archive?");
+    return kEmptyArchive;
+  }
+
+  ALOGV("+++ num_entries=%d dir_size=%d dir_offset=%d", num_entries, dir_size,
+      dir_offset);
+
+  /*
+   * It all looks good.  Create a mapping for the CD, and set the fields
+   * in archive.
+   */
+  android::FileMap* map = MapFileSegment(fd, dir_offset, dir_size,
+                                         true /* read only */, debug_file_name);
+  if (map == NULL) {
+    archive->directory_map = NULL;
+    return kMmapFailed;
+  }
+
+  archive->directory_map = map;
+  archive->num_entries = num_entries;
+  archive->directory_offset = dir_offset;
+
+  return 0;
+}
+
+/*
+ * Find the zip Central Directory and memory-map it.
+ *
+ * On success, returns 0 after populating fields from the EOCD area:
+ *   directory_offset
+ *   directory_map
+ *   num_entries
+ */
+static int32_t MapCentralDirectory(int fd, const char* debug_file_name,
+                                   ZipArchive* archive) {
+
+  // Test file length. We use lseek64 to make sure the file
+  // is small enough to be a zip file (Its size must be less than
+  // 0xffffffff bytes).
+  off64_t file_length = lseek64(fd, 0, SEEK_END);
+  if (file_length == -1) {
+    ALOGV("Zip: lseek on fd %d failed", fd);
+    return kInvalidFile;
+  }
+
+  if (file_length > (off64_t) 0xffffffff) {
+    ALOGV("Zip: zip file too long %d", file_length);
+    return kInvalidFile;
+  }
+
+  if (file_length < (int64_t) kEOCDLen) {
+    ALOGV("Zip: length %ld is too small to be zip", file_length);
+    return kInvalidFile;
+  }
+
+  /*
+   * Perform the traditional EOCD snipe hunt.
+   *
+   * We're searching for the End of Central Directory magic number,
+   * which appears at the start of the EOCD block.  It's followed by
+   * 18 bytes of EOCD stuff and up to 64KB of archive comment.  We
+   * need to read the last part of the file into a buffer, dig through
+   * it to find the magic number, parse some values out, and use those
+   * to determine the extent of the CD.
+   *
+   * We start by pulling in the last part of the file.
+   */
+  uint32_t read_amount = kMaxEOCDSearch;
+  if (file_length < (off64_t) read_amount) {
+    read_amount = file_length;
+  }
+
+  uint8_t* scan_buffer = (uint8_t*) malloc(read_amount);
+  int32_t result = MapCentralDirectory0(fd, debug_file_name, archive,
+                                        file_length, read_amount, scan_buffer);
+
+  free(scan_buffer);
+  return result;
+}
+
+/*
+ * Parses the Zip archive's Central Directory.  Allocates and populates the
+ * hash table.
+ *
+ * Returns 0 on success.
+ */
+static int32_t ParseZipArchive(ZipArchive* archive) {
+  int32_t result = -1;
+  const uint8_t* cd_ptr = (const uint8_t*) archive->directory_map->getDataPtr();
+  size_t cd_length = archive->directory_map->getDataLength();
+  uint16_t num_entries = archive->num_entries;
+
+  /*
+   * Create hash table.  We have a minimum 75% load factor, possibly as
+   * low as 50% after we round off to a power of 2.  There must be at
+   * least one unused entry to avoid an infinite loop during creation.
+   */
+  archive->hash_table_size = RoundUpPower2(1 + (num_entries * 4) / 3);
+  archive->hash_table = (ZipEntryName*) calloc(archive->hash_table_size,
+      sizeof(ZipEntryName));
+
+  /*
+   * Walk through the central directory, adding entries to the hash
+   * table and verifying values.
+   */
+  const uint8_t* ptr = cd_ptr;
+  for (uint16_t i = 0; i < num_entries; i++) {
+    if (get4LE(ptr) != kCDESignature) {
+      ALOGW("Zip: missed a central dir sig (at %d)", i);
+      goto bail;
+    }
+
+    if (ptr + kCDELen > cd_ptr + cd_length) {
+      ALOGW("Zip: ran off the end (at %d)", i);
+      goto bail;
+    }
+
+    const off64_t local_header_offset = get4LE(ptr + kCDELocalOffset);
+    if (local_header_offset >= archive->directory_offset) {
+      ALOGW("Zip: bad LFH offset %lld at entry %d", local_header_offset, i);
+      goto bail;
+    }
+
+    const uint16_t file_name_length = get2LE(ptr + kCDENameLen);
+    const uint16_t extra_length = get2LE(ptr + kCDEExtraLen);
+    const uint16_t comment_length = get2LE(ptr + kCDECommentLen);
+
+    /* add the CDE filename to the hash table */
+    const int add_result = AddToHash(archive->hash_table,
+        archive->hash_table_size, (const char*) ptr + kCDELen, file_name_length);
+    if (add_result) {
+      ALOGW("Zip: Error adding entry to hash table %d", add_result);
+      result = add_result;
+      goto bail;
+    }
+
+    ptr += kCDELen + file_name_length + extra_length + comment_length;
+    if ((size_t)(ptr - cd_ptr) > cd_length) {
+      ALOGW("Zip: bad CD advance (%d vs %zd) at entry %d",
+        (int) (ptr - cd_ptr), cd_length, i);
+      goto bail;
+    }
+  }
+  ALOGV("+++ zip good scan %d entries", num_entries);
+
+  result = 0;
+
+bail:
+  return result;
+}
+
+static int32_t OpenArchiveInternal(ZipArchive* archive,
+                                   const char* debug_file_name) {
+  int32_t result = -1;
+  if ((result = MapCentralDirectory(archive->fd, debug_file_name, archive))) {
+    return result;
+  }
+
+  if ((result = ParseZipArchive(archive))) {
+    return result;
+  }
+
+  return 0;
+}
+
+int32_t OpenArchiveFd(int fd, const char* debug_file_name,
+                      ZipArchiveHandle* handle) {
+  ZipArchive* archive = (ZipArchive*) malloc(sizeof(ZipArchive));
+  memset(archive, 0, sizeof(*archive));
+  *handle = archive;
+
+  archive->fd = fd;
+
+  return OpenArchiveInternal(archive, debug_file_name);
+}
+
+int32_t OpenArchive(const char* fileName, ZipArchiveHandle* handle) {
+  ZipArchive* archive = (ZipArchive*) malloc(sizeof(ZipArchive));
+  memset(archive, 0, sizeof(*archive));
+  *handle = archive;
+
+  const int fd = open(fileName, O_RDONLY | O_BINARY, 0);
+  if (fd < 0) {
+    ALOGW("Unable to open '%s': %s", fileName, strerror(errno));
+    return kIoError;
+  } else {
+    archive->fd = fd;
+  }
+
+  return OpenArchiveInternal(archive, fileName);
+}
+
+/*
+ * Close a ZipArchive, closing the file and freeing the contents.
+ */
+void CloseArchive(ZipArchiveHandle handle) {
+  ZipArchive* archive = (ZipArchive*) handle;
+  ALOGV("Closing archive %p", archive);
+
+  if (archive->fd >= 0) {
+    close(archive->fd);
+  }
+
+  if (archive->directory_map != NULL) {
+    archive->directory_map->release();
+  }
+  free(archive->hash_table);
+
+  /* ensure nobody tries to use the ZipArchive after it's closed */
+  archive->directory_offset = -1;
+  archive->fd = -1;
+  archive->num_entries = -1;
+  archive->hash_table_size = -1;
+  archive->hash_table = NULL;
+}
+
+static int32_t UpdateEntryFromDataDescriptor(int fd,
+                                             ZipEntry *entry) {
+  uint8_t ddBuf[kDDMaxLen];
+  ssize_t actual = TEMP_FAILURE_RETRY(read(fd, ddBuf, sizeof(ddBuf)));
+  if (actual != sizeof(ddBuf)) {
+    return kIoError;
+  }
+
+  const uint32_t ddSignature = get4LE(ddBuf);
+  uint16_t ddOffset = 0;
+  if (ddSignature == kDDOptSignature) {
+    ddOffset = 4;
+  }
+
+  entry->crc32 = get4LE(ddBuf + ddOffset + kDDCrc32);
+  entry->compressed_length = get4LE(ddBuf + ddOffset + kDDCompLen);
+  entry->uncompressed_length = get4LE(ddBuf + ddOffset + kDDUncompLen);
+
+  return 0;
+}
+
+// Attempts to read |len| bytes into |buf| at offset |off|.
+//
+// This method uses pread64 on platforms that support it and
+// lseek64 + read on platforms that don't. This implies that
+// callers should not rely on the |fd| offset being incremented
+// as a side effect of this call.
+static inline ssize_t ReadAtOffset(int fd, uint8_t* buf, size_t len,
+                                   off64_t off) {
+#ifdef HAVE_PREAD
+  return TEMP_FAILURE_RETRY(pread64(fd, buf, len, off));
+#else
+  // The only supported platform that doesn't support pread at the moment
+  // is Windows. Only recent versions of windows support unix like forks,
+  // and even there the semantics are quite different.
+  if (lseek64(fd, off, SEEK_SET) != off) {
+    ALOGW("Zip: failed seek to offset %lld", off);
+    return kIoError;
+  }
+
+  return TEMP_FAILURE_RETRY(read(fd, buf, len));
+#endif  // HAVE_PREAD
+}
+
+static int32_t FindEntry(const ZipArchive* archive, const int ent,
+                         ZipEntry* data) {
+  const uint16_t nameLen = archive->hash_table[ent].name_length;
+  const char* name = archive->hash_table[ent].name;
+
+  // Recover the start of the central directory entry from the filename
+  // pointer.  The filename is the first entry past the fixed-size data,
+  // so we can just subtract back from that.
+  const unsigned char* ptr = (const unsigned char*) name;
+  ptr -= kCDELen;
+
+  // This is the base of our mmapped region, we have to sanity check that
+  // the name that's in the hash table is a pointer to a location within
+  // this mapped region.
+  const unsigned char* base_ptr = (const unsigned char*)
+    archive->directory_map->getDataPtr();
+  if (ptr < base_ptr || ptr > base_ptr + archive->directory_map->getDataLength()) {
+    ALOGW("Zip: Invalid entry pointer");
+    return kInvalidOffset;
+  }
+
+  // The offset of the start of the central directory in the zipfile.
+  // We keep this lying around so that we can sanity check all our lengths
+  // and our per-file structures.
+  const off64_t cd_offset = archive->directory_offset;
+
+  // Fill out the compression method, modification time, crc32
+  // and other interesting attributes from the central directory. These
+  // will later be compared against values from the local file header.
+  data->method = get2LE(ptr + kCDEMethod);
+  data->mod_time = get4LE(ptr + kCDEModWhen);
+  data->crc32 = get4LE(ptr + kCDECRC);
+  data->compressed_length = get4LE(ptr + kCDECompLen);
+  data->uncompressed_length = get4LE(ptr + kCDEUncompLen);
+
+  // Figure out the local header offset from the central directory. The
+  // actual file data will begin after the local header and the name /
+  // extra comments.
+  const off64_t local_header_offset = get4LE(ptr + kCDELocalOffset);
+  if (local_header_offset + (off64_t) kLFHLen >= cd_offset) {
+    ALOGW("Zip: bad local hdr offset in zip");
+    return kInvalidOffset;
+  }
+
+  uint8_t lfh_buf[kLFHLen];
+  ssize_t actual = ReadAtOffset(archive->fd, lfh_buf, sizeof(lfh_buf),
+                                 local_header_offset);
+  if (actual != sizeof(lfh_buf)) {
+    ALOGW("Zip: failed reading lfh name from offset %lld", local_header_offset);
+    return kIoError;
+  }
+
+  if (get4LE(lfh_buf) != kLFHSignature) {
+    ALOGW("Zip: didn't find signature at start of lfh, offset=%lld",
+        local_header_offset);
+    return kInvalidOffset;
+  }
+
+  // Paranoia: Match the values specified in the local file header
+  // to those specified in the central directory.
+  const uint16_t lfhGpbFlags = get2LE(lfh_buf + kLFHGPBFlags);
+  const uint16_t lfhNameLen = get2LE(lfh_buf + kLFHNameLen);
+  const uint16_t lfhExtraLen = get2LE(lfh_buf + kLFHExtraLen);
+
+  if ((lfhGpbFlags & kGPBDDFlagMask) == 0) {
+    const uint32_t lfhCrc = get4LE(lfh_buf + kLFHCRC);
+    const uint32_t lfhCompLen = get4LE(lfh_buf + kLFHCompLen);
+    const uint32_t lfhUncompLen = get4LE(lfh_buf + kLFHUncompLen);
+
+    data->has_data_descriptor = 0;
+    if (data->compressed_length != lfhCompLen || data->uncompressed_length != lfhUncompLen
+        || data->crc32 != lfhCrc) {
+      ALOGW("Zip: size/crc32 mismatch. expected {%d, %d, %x}, was {%d, %d, %x}",
+        data->compressed_length, data->uncompressed_length, data->crc32,
+        lfhCompLen, lfhUncompLen, lfhCrc);
+      return kInconsistentInformation;
+    }
+  } else {
+    data->has_data_descriptor = 1;
+  }
+
+  // Check that the local file header name matches the declared
+  // name in the central directory.
+  if (lfhNameLen == nameLen) {
+    const off64_t name_offset = local_header_offset + kLFHLen;
+    if (name_offset + lfhNameLen >= cd_offset) {
+      ALOGW("Zip: Invalid declared length");
+      return kInvalidOffset;
+    }
+
+    uint8_t* name_buf = (uint8_t*) malloc(nameLen);
+    ssize_t actual = ReadAtOffset(archive->fd, name_buf, nameLen,
+                                  name_offset);
+
+    if (actual != nameLen) {
+      ALOGW("Zip: failed reading lfh name from offset %lld", name_offset);
+      free(name_buf);
+      return kIoError;
+    }
+
+    if (memcmp(name, name_buf, nameLen)) {
+      free(name_buf);
+      return kInconsistentInformation;
+    }
+
+    free(name_buf);
+  } else {
+    ALOGW("Zip: lfh name did not match central directory.");
+    return kInconsistentInformation;
+  }
+
+  const off64_t data_offset = local_header_offset + kLFHLen + lfhNameLen + lfhExtraLen;
+  if (data_offset >= cd_offset) {
+    ALOGW("Zip: bad data offset %lld in zip", (off64_t) data_offset);
+    return kInvalidOffset;
+  }
+
+  if ((off64_t)(data_offset + data->compressed_length) > cd_offset) {
+    ALOGW("Zip: bad compressed length in zip (%lld + %zd > %lld)",
+      data_offset, data->compressed_length, cd_offset);
+    return kInvalidOffset;
+  }
+
+  if (data->method == kCompressStored &&
+    (off64_t)(data_offset + data->uncompressed_length) > cd_offset) {
+     ALOGW("Zip: bad uncompressed length in zip (%lld + %zd > %lld)",
+       data_offset, data->uncompressed_length, cd_offset);
+     return kInvalidOffset;
+  }
+
+  data->offset = data_offset;
+  return 0;
+}
+
+struct IterationHandle {
+  uint32_t position;
+  const char* prefix;
+  uint16_t prefix_len;
+  ZipArchive* archive;
+};
+
+int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr, const char* prefix) {
+  ZipArchive* archive = (ZipArchive *) handle;
+
+  if (archive == NULL || archive->hash_table == NULL) {
+    ALOGW("Zip: Invalid ZipArchiveHandle");
+    return kInvalidHandle;
+  }
+
+  IterationHandle* cookie = (IterationHandle*) malloc(sizeof(IterationHandle));
+  cookie->position = 0;
+  cookie->prefix = prefix;
+  cookie->archive = archive;
+  if (prefix != NULL) {
+    cookie->prefix_len = strlen(prefix);
+  }
+
+  *cookie_ptr = cookie ;
+  return 0;
+}
+
+int32_t FindEntry(const ZipArchiveHandle handle, const char* entryName,
+                  ZipEntry* data) {
+  const ZipArchive* archive = (ZipArchive*) handle;
+  const int nameLen = strlen(entryName);
+  if (nameLen == 0 || nameLen > 65535) {
+    ALOGW("Zip: Invalid filename %s", entryName);
+    return kInvalidEntryName;
+  }
+
+  const int64_t ent = EntryToIndex(archive->hash_table,
+    archive->hash_table_size, entryName, nameLen);
+
+  if (ent < 0) {
+    ALOGD("Zip: Could not find entry %.*s", nameLen, entryName);
+    return ent;
+  }
+
+  return FindEntry(archive, ent, data);
+}
+
+int32_t Next(void* cookie, ZipEntry* data, ZipEntryName* name) {
+  IterationHandle* handle = (IterationHandle *) cookie;
+  if (handle == NULL) {
+    return kInvalidHandle;
+  }
+
+  ZipArchive* archive = handle->archive;
+  if (archive == NULL || archive->hash_table == NULL) {
+    ALOGW("Zip: Invalid ZipArchiveHandle");
+    return kInvalidHandle;
+  }
+
+  const uint32_t currentOffset = handle->position;
+  const uint32_t hash_table_length = archive->hash_table_size;
+  const ZipEntryName *hash_table = archive->hash_table;
+
+  for (uint32_t i = currentOffset; i < hash_table_length; ++i) {
+    if (hash_table[i].name != NULL &&
+        (handle->prefix == NULL ||
+         (memcmp(handle->prefix, hash_table[i].name, handle->prefix_len) == 0))) {
+      handle->position = (i + 1);
+      const int error = FindEntry(archive, i, data);
+      if (!error) {
+        name->name = hash_table[i].name;
+        name->name_length = hash_table[i].name_length;
+      }
+
+      return error;
+    }
+  }
+
+  handle->position = 0;
+  return kIterationEnd;
+}
+
+static int32_t InflateToFile(int fd, const ZipEntry* entry,
+                             uint8_t* begin, uint32_t length,
+                             uint64_t* crc_out) {
+  int32_t result = -1;
+  const uint32_t kBufSize = 32768;
+  uint8_t read_buf[kBufSize];
+  uint8_t write_buf[kBufSize];
+  z_stream zstream;
+  int zerr;
+
+  /*
+   * Initialize the zlib stream struct.
+   */
+  memset(&zstream, 0, sizeof(zstream));
+  zstream.zalloc = Z_NULL;
+  zstream.zfree = Z_NULL;
+  zstream.opaque = Z_NULL;
+  zstream.next_in = NULL;
+  zstream.avail_in = 0;
+  zstream.next_out = (Bytef*) write_buf;
+  zstream.avail_out = kBufSize;
+  zstream.data_type = Z_UNKNOWN;
+
+  /*
+   * Use the undocumented "negative window bits" feature to tell zlib
+   * that there's no zlib header waiting for it.
+   */
+  zerr = inflateInit2(&zstream, -MAX_WBITS);
+  if (zerr != Z_OK) {
+    if (zerr == Z_VERSION_ERROR) {
+      ALOGE("Installed zlib is not compatible with linked version (%s)",
+        ZLIB_VERSION);
+    } else {
+      ALOGW("Call to inflateInit2 failed (zerr=%d)", zerr);
+    }
+
+    return kZlibError;
+  }
+
+  const uint32_t uncompressed_length = entry->uncompressed_length;
+
+  uint32_t compressed_length = entry->compressed_length;
+  uint32_t write_count = 0;
+  do {
+    /* read as much as we can */
+    if (zstream.avail_in == 0) {
+      const ssize_t getSize = (compressed_length > kBufSize) ? kBufSize : compressed_length;
+      const ssize_t actual = TEMP_FAILURE_RETRY(read(fd, read_buf, getSize));
+      if (actual != getSize) {
+        ALOGW("Zip: inflate read failed (%d vs %zd)", actual, getSize);
+        result = kIoError;
+        goto z_bail;
+      }
+
+      compressed_length -= getSize;
+
+      zstream.next_in = read_buf;
+      zstream.avail_in = getSize;
+    }
+
+    /* uncompress the data */
+    zerr = inflate(&zstream, Z_NO_FLUSH);
+    if (zerr != Z_OK && zerr != Z_STREAM_END) {
+      ALOGW("Zip: inflate zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)",
+          zerr, zstream.next_in, zstream.avail_in,
+          zstream.next_out, zstream.avail_out);
+      result = kZlibError;
+      goto z_bail;
+    }
+
+    /* write when we're full or when we're done */
+    if (zstream.avail_out == 0 ||
+      (zerr == Z_STREAM_END && zstream.avail_out != kBufSize)) {
+      const size_t write_size = zstream.next_out - write_buf;
+      // The file might have declared a bogus length.
+      if (write_size + write_count > length) {
+        goto z_bail;
+      }
+      memcpy(begin + write_count, write_buf, write_size);
+      write_count += write_size;
+
+      zstream.next_out = write_buf;
+      zstream.avail_out = kBufSize;
+    }
+  } while (zerr == Z_OK);
+
+  assert(zerr == Z_STREAM_END);     /* other errors should've been caught */
+
+  // stream.adler holds the crc32 value for such streams.
+  *crc_out = zstream.adler;
+
+  if (zstream.total_out != uncompressed_length || compressed_length != 0) {
+    ALOGW("Zip: size mismatch on inflated file (%ld vs %zd)",
+        zstream.total_out, uncompressed_length);
+    result = kInconsistentInformation;
+    goto z_bail;
+  }
+
+  result = 0;
+
+z_bail:
+  inflateEnd(&zstream);    /* free up any allocated structures */
+
+  return result;
+}
+
+int32_t ExtractToMemory(ZipArchiveHandle handle,
+                        ZipEntry* entry, uint8_t* begin, uint32_t size) {
+  ZipArchive* archive = (ZipArchive*) handle;
+  const uint16_t method = entry->method;
+  off64_t data_offset = entry->offset;
+
+  if (lseek64(archive->fd, data_offset, SEEK_SET) != data_offset) {
+    ALOGW("Zip: lseek to data at %lld failed", (off64_t) data_offset);
+    return kIoError;
+  }
+
+  // this should default to kUnknownCompressionMethod.
+  int32_t return_value = -1;
+  uint64_t crc = 0;
+  if (method == kCompressStored) {
+    return_value = CopyFileToFile(archive->fd, begin, size, &crc);
+  } else if (method == kCompressDeflated) {
+    return_value = InflateToFile(archive->fd, entry, begin, size, &crc);
+  }
+
+  if (!return_value && entry->has_data_descriptor) {
+    return_value = UpdateEntryFromDataDescriptor(archive->fd, entry);
+    if (return_value) {
+      return return_value;
+    }
+  }
+
+  // TODO: Fix this check by passing the right flags to inflate2 so that
+  // it calculates the CRC for us.
+  if (entry->crc32 != crc && false) {
+    ALOGW("Zip: crc mismatch: expected %u, was %llu", entry->crc32, crc);
+    return kInconsistentInformation;
+  }
+
+  return return_value;
+}
+
+int32_t ExtractEntryToFile(ZipArchiveHandle handle,
+                           ZipEntry* entry, int fd) {
+  const int32_t declared_length = entry->uncompressed_length;
+
+  const off64_t current_offset = lseek64(fd, 0, SEEK_CUR);
+  if (current_offset == -1) {
+    ALOGW("Zip: unable to seek to current location on fd %d: %s", fd,
+          strerror(errno));
+    return kIoError;
+  }
+
+  int result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
+  if (result == -1) {
+    ALOGW("Zip: unable to truncate file to %lld: %s", declared_length + current_offset,
+          strerror(errno));
+    return kIoError;
+  }
+
+  android::FileMap* map  = MapFileSegment(fd, current_offset, declared_length,
+                                          false, kTempMappingFileName);
+  if (map == NULL) {
+    return kMmapFailed;
+  }
+
+  const int32_t error = ExtractToMemory(handle, entry,
+                                        reinterpret_cast<uint8_t*>(map->getDataPtr()),
+                                        map->getDataLength());
+  map->release();
+  return error;
+}
+
+const char* ErrorCodeString(int32_t error_code) {
+  if (error_code > kErrorMessageLowerBound && error_code < kErrorMessageUpperBound) {
+    return kErrorMessages[error_code * -1];
+  }
+
+  return kErrorMessages[0];
+}
+
+int GetFileDescriptor(const ZipArchiveHandle handle) {
+  return ((ZipArchive*) handle)->fd;
+}
+
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
new file mode 100644
index 0000000..022be5b
--- /dev/null
+++ b/libziparchive/zip_archive_test.cc
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include "ziparchive/zip_archive.h"
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+static std::string test_data_dir;
+
+static const std::string kValidZip = "valid.zip";
+
+static const uint8_t kATxtContents[] = {
+  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+  '\n'
+};
+
+static const uint8_t kBTxtContents[] = {
+  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+  '\n'
+};
+
+static int32_t OpenArchiveWrapper(const std::string& name,
+                                  ZipArchiveHandle* handle) {
+  const std::string abs_path = test_data_dir + "/" + name;
+  return OpenArchive(abs_path.c_str(), handle);
+}
+
+static void AssertNameEquals(const std::string& name_str,
+                             const ZipEntryName& name) {
+  ASSERT_EQ(name_str.size(), name.name_length);
+  ASSERT_EQ(0, memcmp(name_str.c_str(), name.name, name.name_length));
+}
+
+TEST(ziparchive, Open) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+
+  CloseArchive(handle);
+}
+
+TEST(ziparchive, Iteration) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+
+  void* iteration_cookie;
+  ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL));
+
+  ZipEntry data;
+  ZipEntryName name;
+
+  // b/c.txt
+  ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
+  AssertNameEquals("b/c.txt", name);
+
+  // b/d.txt
+  ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
+  AssertNameEquals("b/d.txt", name);
+
+  // a.txt
+  ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
+  AssertNameEquals("a.txt", name);
+
+  // b.txt
+  ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
+  AssertNameEquals("b.txt", name);
+
+  // b/
+  ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
+  AssertNameEquals("b/", name);
+
+  // End of iteration.
+  ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
+
+  CloseArchive(handle);
+}
+
+TEST(ziparchive, FindEntry) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+
+  ZipEntry data;
+  ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
+
+  // Known facts about a.txt, from zipinfo -v.
+  ASSERT_EQ(63, data.offset);
+  ASSERT_EQ(kCompressDeflated, data.method);
+  ASSERT_EQ(static_cast<uint32_t>(17), data.uncompressed_length);
+  ASSERT_EQ(static_cast<uint32_t>(13), data.compressed_length);
+  ASSERT_EQ(0x950821c5, data.crc32);
+
+  // An entry that doesn't exist. Should be a negative return code.
+  ASSERT_LT(FindEntry(handle, "nonexistent.txt", &data), 0);
+
+  CloseArchive(handle);
+}
+
+TEST(ziparchive, ExtractToMemory) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+
+  // An entry that's deflated.
+  ZipEntry data;
+  ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
+  const uint32_t a_size = data.uncompressed_length;
+  ASSERT_EQ(a_size, sizeof(kATxtContents));
+  uint8_t* buffer = new uint8_t[a_size];
+  ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, a_size));
+  ASSERT_EQ(0, memcmp(buffer, kATxtContents, a_size));
+  delete[] buffer;
+
+  // An entry that's stored.
+  ASSERT_EQ(0, FindEntry(handle, "b.txt", &data));
+  const uint32_t b_size = data.uncompressed_length;
+  ASSERT_EQ(b_size, sizeof(kBTxtContents));
+  buffer = new uint8_t[b_size];
+  ASSERT_EQ(0, ExtractToMemory(handle, &data, buffer, b_size));
+  ASSERT_EQ(0, memcmp(buffer, kBTxtContents, b_size));
+  delete[] buffer;
+
+  CloseArchive(handle);
+}
+
+TEST(ziparchive, ExtractToFile) {
+  char kTempFilePattern[] = "zip_archive_test_XXXXXX";
+  int fd = mkstemp(kTempFilePattern);
+  ASSERT_NE(-1, fd);
+  const uint8_t data[8] = { '1', '2', '3', '4', '5', '6', '7', '8' };
+  const ssize_t data_size = sizeof(data);
+
+  ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(write(fd, data, data_size)));
+
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+
+  ZipEntry entry;
+  ASSERT_EQ(0, FindEntry(handle, "a.txt", &entry));
+  ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, fd));
+
+
+  // Assert that the first 8 bytes of the file haven't been clobbered.
+  uint8_t read_buffer[data_size];
+  ASSERT_EQ(0, lseek64(fd, 0, SEEK_SET));
+  ASSERT_EQ(data_size, TEMP_FAILURE_RETRY(read(fd, read_buffer, data_size)));
+  ASSERT_EQ(0, memcmp(read_buffer, data, data_size));
+
+  // Assert that the remainder of the file contains the incompressed data.
+  std::vector<uint8_t> uncompressed_data(entry.uncompressed_length);
+  ASSERT_EQ(static_cast<ssize_t>(entry.uncompressed_length),
+            TEMP_FAILURE_RETRY(
+                read(fd, &uncompressed_data[0], entry.uncompressed_length)));
+  ASSERT_EQ(0, memcmp(&uncompressed_data[0], kATxtContents,
+                      sizeof(kATxtContents)));
+
+  // Assert that the total length of the file is sane
+  ASSERT_EQ(data_size + sizeof(kATxtContents), lseek64(fd, 0, SEEK_END));
+
+  close(fd);
+}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  static struct option options[] = {
+    { "test_data_dir", required_argument, NULL, 't' },
+    { NULL, 0, NULL, 0 }
+  };
+
+  while (true) {
+    int option_index;
+    const int c = getopt_long_only(argc, argv, "", options, &option_index);
+    if (c == -1) {
+      break;
+    }
+
+    if (c == 't') {
+      test_data_dir = optarg;
+    }
+  }
+
+  if (test_data_dir.size() == 0) {
+    printf("Test data flag (--test_data_dir) required\n\n");
+    return -1;
+  }
+
+  if (test_data_dir[0] != '/') {
+    printf("Test data must be an absolute path, was %s\n\n",
+           test_data_dir.c_str());
+    return -2;
+  }
+
+  return RUN_ALL_TESTS();
+}
+
diff --git a/logcat/event.logtags b/logcat/event.logtags
index 6040bd9..a325692 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -90,10 +90,6 @@
 # Logged when the supplicant switches to a new state
 50023 wifi_supplicant_state_changed (supplicant_state|1|5)
 
-# Do not change these names without updating tag in:
-#//device/dalvik/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.c
-51000 socket_stats (send|1|2),(recv|1|2),(ip|1|5),(port|1|5),(close|1|5)
-
 # Database operation samples.
 # db: the filename of the database
 # sql: the executed query (without query args)
@@ -110,22 +106,7 @@
 60003 view_use_drawing_cache (View drawn using bitmap cache|1|5)
 
 # graphics timestamp
-60100 sf_app_dequeue_before (buffer|1),(identity|1),(time|2)
-60101 sf_app_dequeue_after (buffer|1),(identity|1),(time|2)
-60102 sf_app_lock_before (buffer|1),(identity|1),(time|2)
-60103 sf_app_lock_after (buffer|1),(identity|1),(time|2)
-60104 sf_app_queue (buffer|1),(identity|1),(time|2)
-60105 sf_repaint (buffer|1),(time|2)
-60106 sf_composition_complete (buffer|1),(time|2)
-60107 sf_unlock_clients (buffer|1),(time|2)
-60108 sf_swapbuffers (buffer|1),(time|2)
-60109 sf_repaint_done (buffer|1),(time|2)
-60110 sf_fb_post_before (buffer|1),(time|2)
-60111 sf_fb_post_after (buffer|1),(time|2)
-60112 sf_fb_dequeue_before (buffer|1),(time|2)
-60113 sf_fb_dequeue_after (buffer|1),(time|2)
-60114 sf_fb_lock_before (buffer|1),(time|2)
-60115 sf_fb_lock_after (buffer|1),(time|2)
+# 60100 - 60199 reserved for surfaceflinger
 
 # 0 for screen off, 1 for screen on, 2 for key-guard done
 70000 screen_toggled (screen_state|1|5)
@@ -151,7 +132,7 @@
 80310 bionic_event_resolver_wrong_query (uid|1)
 
 # libcore failure logging
-90100 cert_pin_failure (certs|4)
+90100 exp_det_cert_pin_failure (certs|4)
 
 # NOTE - the range 1000000-2000000 is reserved for partners and others who
 # want to define their own log tags without conflicting with the core platform.
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index d3b5ed0..d44c679 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -1,10 +1,10 @@
 // Copyright 2006 The Android Open Source Project
 
-#include <cutils/logger.h>
-#include <cutils/logd.h>
+#include <log/logger.h>
+#include <log/logd.h>
+#include <log/logprint.h>
+#include <log/event_tag_map.h>
 #include <cutils/sockets.h>
-#include <cutils/logprint.h>
-#include <cutils/event_tag_map.h>
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h
index 8087f0a..4307a30 100644
--- a/logwrapper/include/logwrap/logwrap.h
+++ b/logwrapper/include/logwrap/logwrap.h
@@ -44,11 +44,15 @@
  *           send a signal twice to signal the caller (once for the child, and
  *           once for the caller)
  *   log_target: Specify where to log the output of the child, either LOG_NONE,
- *           LOG_ALOG (for the Android system log) or LOG_KLOG (for the kernel
- *           log).
+ *           LOG_ALOG (for the Android system log), LOG_KLOG (for the kernel
+ *           log), or LOG_FILE (and you need to specify a pathname in the
+ *           file_path argument, otherwise pass NULL).  These are bit fields,
+ *           and can be OR'ed together to log to multiple places.
  *   abbreviated: If true, capture up to the first 100 lines and last 4K of
  *           output from the child.  The abbreviated output is not dumped to
  *           the specified log until the child has exited.
+ *   file_path: if log_target has the LOG_FILE bit set, then this parameter
+ *           must be set to the pathname of the file to log to.
  *
  * Return value:
  *   0 when logwrap successfully run the child process and captured its status
@@ -58,13 +62,14 @@
  *
  */
 
-/* Values for the log_target parameter android_fork_exec_ext() */
+/* Values for the log_target parameter android_fork_execvp_ext() */
 #define LOG_NONE        0
 #define LOG_ALOG        1
 #define LOG_KLOG        2
+#define LOG_FILE        4
 
 int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
-        int log_target, bool abbreviated);
+        int log_target, bool abbreviated, char *file_path);
 
 /* Similar to above, except abbreviated logging is not available, and if logwrap
  * is true, logging is to the Android system log, and if false, there is no
@@ -74,10 +79,9 @@
                                      bool ignore_int_quit, bool logwrap)
 {
     return android_fork_execvp_ext(argc, argv, status, ignore_int_quit,
-                                   (logwrap ? LOG_ALOG : LOG_NONE), false);
+                                   (logwrap ? LOG_ALOG : LOG_NONE), false, NULL);
 }
 
-
 __END_DECLS
 
 #endif /* __LIBS_LOGWRAP_H */
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 01cc9a1..4ca1db4 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -93,6 +93,7 @@
     char klog_fmt[MAX_KLOG_TAG * 2];
     char *btag;
     bool abbreviated;
+    FILE *fp;
     struct abbr_buf a_buf;
 };
 
@@ -158,11 +159,15 @@
 
 /* Log directly to the specified log */
 static void do_log_line(struct log_info *log_info, char *line) {
-    if (log_info->log_target == LOG_KLOG) {
+    if (log_info->log_target & LOG_KLOG) {
         klog_write(6, log_info->klog_fmt, line);
-    } else if (log_info->log_target == LOG_ALOG) {
+    }
+    if (log_info->log_target & LOG_ALOG) {
         ALOG(LOG_INFO, log_info->btag, "%s", line);
     }
+    if (log_info->log_target & LOG_FILE) {
+        fprintf(log_info->fp, "%s\n", line);
+    }
 }
 
 /* Log to either the abbreviated buf, or directly to the specified log
@@ -290,7 +295,7 @@
 }
 
 static int parent(const char *tag, int parent_read, pid_t pid,
-        int *chld_sts, int log_target, bool abbreviated) {
+        int *chld_sts, int log_target, bool abbreviated, char *file_path) {
     int status = 0;
     char buffer[4096];
     struct pollfd poll_fds[] = {
@@ -300,6 +305,7 @@
         },
     };
     int rc = 0;
+    int fd;
 
     struct log_info log_info;
 
@@ -309,8 +315,6 @@
     bool found_child = false;
     char tmpbuf[256];
 
-    log_info.log_target = log_target;
-    log_info.abbreviated = abbreviated;
     log_info.btag = basename(tag);
     if (!log_info.btag) {
         log_info.btag = (char*) tag;
@@ -323,11 +327,30 @@
         init_abbr_buf(&log_info.a_buf);
     }
 
-    if (log_target == LOG_KLOG) {
+    if (log_target & LOG_KLOG) {
         snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt),
                  "<6>%.*s: %%s", MAX_KLOG_TAG, log_info.btag);
     }
 
+    if ((log_target & LOG_FILE) && !file_path) {
+        /* No file_path specified, clear the LOG_FILE bit */
+        log_target &= ~LOG_FILE;
+    }
+
+    if (log_target & LOG_FILE) {
+        fd = open(file_path, O_WRONLY | O_CREAT, 0664);
+        if (fd < 0) {
+            ERROR("Cannot log to file %s\n", file_path);
+            log_target &= ~LOG_FILE;
+        } else {
+            lseek(fd, 0, SEEK_END);
+            log_info.fp = fdopen(fd, "a");
+        }
+    }
+
+    log_info.log_target = log_target;
+    log_info.abbreviated = abbreviated;
+
     while (!found_child) {
         if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), -1)) < 0) {
             ERROR("poll failed\n");
@@ -432,6 +455,9 @@
 
 err_waitpid:
 err_poll:
+    if (log_target & LOG_FILE) {
+        fclose(log_info.fp); /* Also closes underlying fd */
+    }
     if (abbreviated) {
         free_abbr_buf(&log_info.a_buf);
     }
@@ -451,7 +477,7 @@
 }
 
 int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
-        int log_target, bool abbreviated) {
+        int log_target, bool abbreviated, char *file_path) {
     pid_t pid;
     int parent_ptty;
     int child_ptty;
@@ -523,7 +549,8 @@
             sigaction(SIGQUIT, &ignact, &quitact);
         }
 
-        rc = parent(argv[0], parent_ptty, pid, status, log_target, abbreviated);
+        rc = parent(argv[0], parent_ptty, pid, status, log_target,
+                    abbreviated, file_path);
     }
 
     if (ignore_int_quit) {
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index d1c6240..db6cb4c 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/wait.h>
@@ -80,7 +81,7 @@
     }
 
     rc = android_fork_execvp_ext(argc, &argv[0], &status, true,
-                                 log_target, abbreviated);
+                                 log_target, abbreviated, NULL);
     if (!rc) {
         if (WIFEXITED(status))
             rc = WEXITSTATUS(status);
diff --git a/reboot/Android.mk b/reboot/Android.mk
new file mode 100644
index 0000000..4db0c1e
--- /dev/null
+++ b/reboot/Android.mk
@@ -0,0 +1,12 @@
+# Copyright 2013 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= reboot.c
+
+LOCAL_SHARED_LIBRARIES:= libcutils
+
+LOCAL_MODULE:= reboot
+
+include $(BUILD_EXECUTABLE)
diff --git a/reboot/reboot.c b/reboot/reboot.c
new file mode 100644
index 0000000..d9a4227
--- /dev/null
+++ b/reboot/reboot.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <cutils/properties.h>
+#include <cutils/android_reboot.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+    int ret;
+    size_t prop_len;
+    char property_val[PROPERTY_VALUE_MAX];
+    const char *cmd = "reboot";
+    char *optarg = "";
+
+    opterr = 0;
+    do {
+        int c;
+
+        c = getopt(argc, argv, "p");
+
+        if (c == EOF) {
+            break;
+        }
+
+        switch (c) {
+        case 'p':
+            cmd = "shutdown";
+            break;
+        case '?':
+            fprintf(stderr, "usage: %s [-p] [rebootcommand]\n", argv[0]);
+            exit(EXIT_FAILURE);
+        }
+    } while (1);
+
+    if(argc > optind + 1) {
+        fprintf(stderr, "%s: too many arguments\n", argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    if (argc > optind)
+        optarg = argv[optind];
+
+    prop_len = snprintf(property_val, sizeof(property_val), "%s,%s", cmd, optarg);
+    if (prop_len >= sizeof(property_val)) {
+        fprintf(stderr, "reboot command too long: %s\n", optarg);
+        exit(EXIT_FAILURE);
+    }
+
+    ret = property_set(ANDROID_RB_PROPERTY, property_val);
+    if(ret < 0) {
+        perror("reboot");
+        exit(EXIT_FAILURE);
+    }
+
+    // Don't return early. Give the reboot command time to take effect
+    // to avoid messing up scripts which do "adb shell reboot && adb wait-for-device"
+    while(1) { pause(); }
+
+    fprintf(stderr, "Done\n");
+    return 0;
+}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 3417f54..2c16084 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -1,55 +1,38 @@
 LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
 
-# files that live under /system/etc/...
-
-copy_from := \
-	etc/hosts
-
-
-copy_to := $(addprefix $(TARGET_OUT)/,$(copy_from))
-copy_from := $(addprefix $(LOCAL_PATH)/,$(copy_from))
-
-$(copy_to) : PRIVATE_MODULE := system_etcdir
-$(copy_to) : $(TARGET_OUT)/% : $(LOCAL_PATH)/% | $(ACP)
-	$(transform-prebuilt-to-target)
-
-ALL_PREBUILT += $(copy_to)
-
-
-# files that live under /...
-
+#######################################
+# init.rc
 # Only copy init.rc if the target doesn't have its own.
 ifneq ($(TARGET_PROVIDES_INIT_RC),true)
-file := $(TARGET_ROOT_OUT)/init.rc
-$(file) : $(LOCAL_PATH)/init.rc | $(ACP)
-	$(transform-prebuilt-to-target)
-ALL_PREBUILT += $(file)
-$(INSTALLED_RAMDISK_TARGET): $(file)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := init.rc
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+
+include $(BUILD_PREBUILT)
 endif
+#######################################
+# init.environ.rc
 
-file := $(TARGET_ROOT_OUT)/ueventd.rc
-$(file) : $(LOCAL_PATH)/ueventd.rc | $(ACP)
-	$(transform-prebuilt-to-target)
-ALL_PREBUILT += $(file)
-$(INSTALLED_RAMDISK_TARGET): $(file)
+include $(CLEAR_VARS)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE := init.environ.rc
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
 
-# init.usb.rc is handled by build/target/product/core.rc
-
-
+# Put it here instead of in init.rc module definition,
+# because init.rc is conditionally included.
+#
 # create some directories (some are mount points)
-DIRS := $(addprefix $(TARGET_ROOT_OUT)/, \
-		sbin \
-		dev \
-		proc \
-		sys \
-		system \
-		data \
-	) \
-	$(TARGET_OUT_DATA)
+LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
+    sbin dev proc sys system data)
 
-$(DIRS):
-	@echo Directory: $@
-	@mkdir -p $@
+include $(BUILD_SYSTEM)/base_rules.mk
 
-ALL_PREBUILT += $(DIRS)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/init.environ.rc.in
+	@echo "Generate: $< -> $@"
+	@mkdir -p $(dir $@)
+	$(hide) sed -e 's?%BOOTCLASSPATH%?$(PRODUCT_BOOTCLASSPATH)?g' $< >$@
+
+#######################################
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
new file mode 100644
index 0000000..d2f74c0
--- /dev/null
+++ b/rootdir/init.environ.rc.in
@@ -0,0 +1,12 @@
+# set up the global environment
+on init
+    export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
+    export LD_LIBRARY_PATH /vendor/lib:/system/lib
+    export ANDROID_BOOTLOGO 1
+    export ANDROID_ROOT /system
+    export ANDROID_ASSETS /system/app
+    export ANDROID_DATA /data
+    export ANDROID_STORAGE /storage
+    export ASEC_MOUNTPOINT /mnt/asec
+    export LOOP_MOUNTPOINT /mnt/obb
+    export BOOTCLASSPATH %BOOTCLASSPATH%
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 0d53ae1..d1822cf 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -4,6 +4,7 @@
 # This is a common source of Android security bugs.
 #
 
+import /init.environ.rc
 import /init.usb.rc
 import /init.${ro.hardware}.rc
 import /init.trace.rc
@@ -30,18 +31,6 @@
 
 loglevel 3
 
-# setup the global environment
-    export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
-    export LD_LIBRARY_PATH /vendor/lib:/system/lib
-    export ANDROID_BOOTLOGO 1
-    export ANDROID_ROOT /system
-    export ANDROID_ASSETS /system/app
-    export ANDROID_DATA /data
-    export ANDROID_STORAGE /storage
-    export ASEC_MOUNTPOINT /mnt/asec
-    export LOOP_MOUNTPOINT /mnt/obb
-    export BOOTCLASSPATH /system/framework/core.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar
-
 # Backward compatibility
     symlink /system/etc /etc
     symlink /sys/kernel/debug /d
@@ -55,6 +44,19 @@
     mount cgroup none /acct cpuacct
     mkdir /acct/uid
 
+# Create cgroup mount point for memory
+    mount tmpfs none /sys/fs/cgroup mode=0750,uid=0,gid=1000
+    mkdir /sys/fs/cgroup/memory 0750 root system
+    mount cgroup none /sys/fs/cgroup/memory memory
+    write /sys/fs/cgroup/memory/memory.move_charge_at_immigrate 1
+    chown root system /sys/fs/cgroup/memory/tasks
+    chmod 0660 /sys/fs/cgroup/memory/tasks
+    mkdir /sys/fs/cgroup/memory/sw 0750 root system
+    write /sys/fs/cgroup/memory/sw/memory.swappiness 100
+    write /sys/fs/cgroup/memory/sw/memory.move_charge_at_immigrate 1
+    chown root system /sys/fs/cgroup/memory/sw/tasks
+    chmod 0660 /sys/fs/cgroup/memory/sw/tasks
+
     mkdir /system
     mkdir /data 0771 system system
     mkdir /cache 0770 system cache
@@ -62,12 +64,11 @@
 
     # See storage config details at http://source.android.com/tech/storage/
     mkdir /mnt/shell 0700 shell shell
-    mkdir /storage 0050 root sdcard_r
+    mkdir /mnt/media_rw 0700 media_rw media_rw
+    mkdir /storage 0751 root sdcard_r
 
     # Directory for putting things only root should see.
     mkdir /mnt/secure 0700 root root
-    # Create private mountpoint so we can MS_MOVE from staging
-    mount tmpfs tmpfs /mnt/secure mode=0700,uid=0,gid=0
 
     # Directory for staging bindmounts
     mkdir /mnt/secure/staging 0700 root root
@@ -134,12 +135,15 @@
 # This is needed by any process that uses socket tagging.
     chmod 0644 /dev/xt_qtaguid
 
+# Create location for fs_mgr to store abbreviated output from filesystem
+# checker programs.
+    mkdir /dev/fscklogs 0770 root system
+
 on post-fs
     # once everything is setup, no need to modify /
     mount rootfs rootfs / ro remount
     # mount shared so changes propagate into child namespaces
     mount rootfs rootfs / shared rec
-    mount tmpfs tmpfs /mnt/secure private rec
 
     # We chown/chmod /cache again so because mount is run as root + defaults
     chown system cache /cache
@@ -178,6 +182,9 @@
     # We restorecon /data in case the userdata partition has been reset.
     restorecon /data
 
+    # Avoid predictable entropy pool. Carry over entropy from previous boot.
+    copy /data/system/entropy.dat /dev/urandom
+
     # Create dump dir and collect dumps.
     # Do this before we mount cache so eventually we can use cache for
     # storing dumps on platforms which do not have a dedicated dump partition.
@@ -201,6 +208,7 @@
     mkdir /data/misc/bluetooth 0770 system system
     mkdir /data/misc/keystore 0700 keystore keystore
     mkdir /data/misc/keychain 0771 system system
+    mkdir /data/misc/radio 0770 system radio
     mkdir /data/misc/sms 0770 system radio
     mkdir /data/misc/zoneinfo 0775 system system
     mkdir /data/misc/vpn 0770 system vpn
@@ -348,25 +356,20 @@
     chown system system /sys/kernel/ipv4/tcp_rmem_max
     chown root radio /proc/cmdline
 
-# Set these so we can remotely update SELinux policy
-    chown system system /sys/fs/selinux/enforce
-
 # Define TCP buffer sizes for various networks
 #   ReadMin, ReadInitial, ReadMax, WriteMin, WriteInitial, WriteMax,
-    setprop net.tcp.buffersize.default 4096,87380,110208,4096,16384,110208
-    setprop net.tcp.buffersize.wifi    524288,1048576,2097152,262144,524288,1048576
-    setprop net.tcp.buffersize.lte     524288,1048576,2097152,262144,524288,1048576
-    setprop net.tcp.buffersize.umts    4094,87380,110208,4096,16384,110208
-    setprop net.tcp.buffersize.hspa    4094,87380,262144,4096,16384,262144
-    setprop net.tcp.buffersize.hsupa   4094,87380,262144,4096,16384,262144
-    setprop net.tcp.buffersize.hsdpa   4094,87380,262144,4096,16384,262144
-    setprop net.tcp.buffersize.hspap   4094,87380,1220608,4096,16384,1220608
-    setprop net.tcp.buffersize.edge    4093,26280,35040,4096,16384,35040
-    setprop net.tcp.buffersize.gprs    4092,8760,11680,4096,8760,11680
-    setprop net.tcp.buffersize.evdo    4094,87380,262144,4096,16384,262144
-
-# Set this property so surfaceflinger is not started by system_init
-    setprop system_init.startsurfaceflinger 0
+    setprop net.tcp.buffersize.default  4096,87380,110208,4096,16384,110208
+    setprop net.tcp.buffersize.wifi     524288,1048576,2097152,262144,524288,1048576
+    setprop net.tcp.buffersize.ethernet 524288,1048576,3145728,524288,1048576,2097152
+    setprop net.tcp.buffersize.lte      524288,1048576,2097152,262144,524288,1048576
+    setprop net.tcp.buffersize.umts     4094,87380,110208,4096,16384,110208
+    setprop net.tcp.buffersize.hspa     4094,87380,262144,4096,16384,262144
+    setprop net.tcp.buffersize.hsupa    4094,87380,262144,4096,16384,262144
+    setprop net.tcp.buffersize.hsdpa    4094,87380,262144,4096,16384,262144
+    setprop net.tcp.buffersize.hspap    4094,87380,1220608,4096,16384,1220608
+    setprop net.tcp.buffersize.edge     4093,26280,35040,4096,16384,35040
+    setprop net.tcp.buffersize.gprs     4092,8760,11680,4096,8760,11680
+    setprop net.tcp.buffersize.evdo     4094,87380,262144,4096,16384,262144
 
     class_start core
     class_start main
@@ -397,6 +400,13 @@
     class_reset late_start
     class_reset main
 
+on property:sys.powerctl=*
+    powerctl ${sys.powerctl}
+
+# system server cannot write to /proc/sys files, so proxy it through init
+on property:sys.sysctl.extra_free_kbytes=*
+    write /proc/sys/vm/extra_free_kbytes ${sys.sysctl.extra_free_kbytes}
+
 ## Daemon processes to be run by init.
 ##
 service ueventd /sbin/ueventd
@@ -404,6 +414,16 @@
     critical
     seclabel u:r:ueventd:s0
 
+service healthd /sbin/healthd
+    class core
+    critical
+    seclabel u:r:healthd:s0
+
+service healthd-charger /sbin/healthd -n
+    class charger
+    critical
+    seclabel u:r:healthd:s0
+
 service console /system/bin/sh
     class core
     console
@@ -430,6 +450,7 @@
     user system
     group system
     critical
+    onrestart restart healthd
     onrestart restart zygote
     onrestart restart media
     onrestart restart surfaceflinger
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index a60cfc5..ddf8753 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -1,3 +1,6 @@
+subsystem adf
+	devname uevent_devname
+
 /dev/null                 0666   root       root
 /dev/zero                 0666   root       root
 /dev/full                 0666   root       root
diff --git a/run-as/package.c b/run-as/package.c
index 27fc1eb..901e9e3 100644
--- a/run-as/package.c
+++ b/run-as/package.c
@@ -90,7 +90,7 @@
      */
 
     oldegid = getegid();
-    if (setegid(AID_SYSTEM) < 0) {
+    if (setegid(AID_PACKAGE_INFO) < 0) {
         return NULL;
     }
 
@@ -111,7 +111,7 @@
         goto EXIT;
 
     /* Ensure that the file is owned by the system user */
-    if ((st.st_uid != AID_SYSTEM) || (st.st_gid != AID_SYSTEM)) {
+    if ((st.st_uid != AID_SYSTEM) || (st.st_gid != AID_PACKAGE_INFO)) {
         goto EXIT;
     }
 
diff --git a/run-as/run-as.c b/run-as/run-as.c
index 3c0ecc4..cc05e63 100644
--- a/run-as/run-as.c
+++ b/run-as/run-as.c
@@ -36,9 +36,9 @@
 /*
  *  WARNING WARNING WARNING WARNING
  *
- *  This program runs as set-uid root on Android production devices.
- *  Be very conservative when modifying it to avoid any serious
- *  security issue. Keep in mind the following:
+ *  This program runs with CAP_SETUID and CAP_SETGID capabilities on Android
+ *  production devices. Be very conservative when modifying it to avoid any
+ *  serious security issue. Keep in mind the following:
  *
  *  - This program should only run for the 'root' or 'shell' users
  *
@@ -61,14 +61,19 @@
  *
  *   run-as <package-name> <command> <args>
  *
- *  The 'run-as' binary is setuid, but will check the following:
+ *  The 'run-as' binary is installed with CAP_SETUID and CAP_SETGID file
+ *  capabilities, but will check the following:
  *
  *  - that it is invoked from the 'shell' or 'root' user (abort otherwise)
  *  - that '<package-name>' is the name of an installed and debuggable package
  *  - that the package's data directory is well-formed (see package.c)
  *
- *  If so, it will cd to the package's data directory, drop to the application's
- *  user id / group id then run the command there.
+ *  If so, it will drop to the application's user id / group id, cd to the
+ *  package's data directory, then run the command there.
+ *
+ *  NOTE: In the future it might not be possible to cd to the package's data
+ *  directory under that package's user id / group id, in which case this
+ *  utility will need to be changed accordingly.
  *
  *  This can be useful for a number of different things on production devices:
  *
@@ -141,19 +146,6 @@
         return 1;
     }
 
-    /* then move to it */
-    {
-        int ret;
-        do {
-            ret = chdir(info.dataDir);
-        } while (ret < 0 && errno == EINTR);
-
-        if (ret < 0) {
-            panic("Could not cd to package's data directory: %s\n", strerror(errno));
-            return 1;
-        }
-    }
-
     /* Ensure that we change all real/effective/saved IDs at the
      * same time to avoid nasty surprises.
      */
@@ -168,6 +160,19 @@
         return 1;
     }
 
+    /* cd into the data directory */
+    {
+        int ret;
+        do {
+            ret = chdir(info.dataDir);
+        } while (ret < 0 && errno == EINTR);
+
+        if (ret < 0) {
+            panic("Could not cd to package's data directory: %s\n", strerror(errno));
+            return 1;
+        }
+    }
+
     /* User specified command for exec. */
     if (argc >= 3 ) {
         if (execvp(argv[2], argv+2) < 0) {
diff --git a/sdcard/Android.mk b/sdcard/Android.mk
index fb04d6d..4630db9 100644
--- a/sdcard/Android.mk
+++ b/sdcard/Android.mk
@@ -6,6 +6,6 @@
 LOCAL_MODULE:= sdcard
 LOCAL_CFLAGS := -Wall -Wno-unused-parameter
 
-LOCAL_SHARED_LIBRARIES := libc
+LOCAL_SHARED_LIBRARIES := libc libcutils
 
 include $(BUILD_EXECUTABLE)
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index bff6e67..05fbfba 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -30,6 +30,11 @@
 #include <pthread.h>
 #include <sys/time.h>
 #include <sys/resource.h>
+#include <sys/inotify.h>
+
+#include <cutils/fs.h>
+#include <cutils/hashmap.h>
+#include <cutils/multiuser.h>
 
 #include <private/android_filesystem_config.h>
 
@@ -57,6 +62,30 @@
  * - if an op that returns a fuse_entry fails writing the reply to the
  * kernel, you must rollback the refcount to reflect the reference the
  * kernel did not actually acquire
+ *
+ * This daemon can also derive custom filesystem permissions based on directory
+ * structure when requested. These custom permissions support several features:
+ *
+ * - Apps can access their own files in /Android/data/com.example/ without
+ * requiring any additional GIDs.
+ * - Separate permissions for protecting directories like Pictures and Music.
+ * - Multi-user separation on the same physical device.
+ *
+ * The derived permissions look like this:
+ *
+ * rwxrwx--x root:sdcard_rw     /
+ * rwxrwx--- root:sdcard_pics   /Pictures
+ * rwxrwx--- root:sdcard_av     /Music
+ *
+ * rwxrwx--x root:sdcard_rw     /Android
+ * rwxrwx--x root:sdcard_rw     /Android/data
+ * rwxrwx--- u0_a12:sdcard_rw   /Android/data/com.example
+ * rwxrwx--x root:sdcard_rw     /Android/obb/
+ * rwxrwx--- u0_a12:sdcard_rw   /Android/obb/com.example
+ *
+ * rwxrwx--- root:sdcard_all    /Android/user
+ * rwxrwx--x root:sdcard_rw     /Android/user/10
+ * rwxrwx--- u10_a12:sdcard_rw  /Android/user/10/Android/data/com.example
  */
 
 #define FUSE_TRACE 0
@@ -89,6 +118,39 @@
  * or that a reply has already been written. */
 #define NO_STATUS 1
 
+/* Path to system-provided mapping of package name to appIds */
+static const char* const kPackagesListFile = "/data/system/packages.list";
+
+/* Supplementary groups to execute with */
+static const gid_t kGroups[1] = { AID_PACKAGE_INFO };
+
+/* Permission mode for a specific node. Controls how file permissions
+ * are derived for children nodes. */
+typedef enum {
+    /* Nothing special; this node should just inherit from its parent. */
+    PERM_INHERIT,
+    /* This node is one level above a normal root; used for legacy layouts
+     * which use the first level to represent user_id. */
+    PERM_LEGACY_PRE_ROOT,
+    /* This node is "/" */
+    PERM_ROOT,
+    /* This node is "/Android" */
+    PERM_ANDROID,
+    /* This node is "/Android/data" */
+    PERM_ANDROID_DATA,
+    /* This node is "/Android/obb" */
+    PERM_ANDROID_OBB,
+    /* This node is "/Android/user" */
+    PERM_ANDROID_USER,
+} perm_t;
+
+/* Permissions structure to derive */
+typedef enum {
+    DERIVE_NONE,
+    DERIVE_LEGACY,
+    DERIVE_UNIFIED,
+} derive_t;
+
 struct handle {
     int fd;
 };
@@ -102,6 +164,13 @@
     __u64 nid;
     __u64 gen;
 
+    /* State derived based on current position in hierarchy. */
+    perm_t perm;
+    userid_t userid;
+    uid_t uid;
+    gid_t gid;
+    mode_t mode;
+
     struct node *next;          /* per-dir sibling list */
     struct node *child;         /* first contained file by this dir */
     struct node *parent;        /* containing directory */
@@ -114,16 +183,44 @@
      * namelen for both fields.
      */
     char *actual_name;
+
+    /* If non-null, an exact underlying path that should be grafted into this
+     * position. Used to support things like OBB. */
+    char* graft_path;
+    size_t graft_pathlen;
 };
 
+static int str_hash(void *key) {
+    return hashmapHash(key, strlen(key));
+}
+
+/** Test if two string keys are equal ignoring case */
+static bool str_icase_equals(void *keyA, void *keyB) {
+    return strcasecmp(keyA, keyB) == 0;
+}
+
+static int int_hash(void *key) {
+    return (int) key;
+}
+
+static bool int_equals(void *keyA, void *keyB) {
+    return keyA == keyB;
+}
+
 /* Global data structure shared by all fuse handlers. */
 struct fuse {
     pthread_mutex_t lock;
 
     __u64 next_generation;
     int fd;
+    derive_t derive;
+    bool split_perms;
+    gid_t write_gid;
     struct node root;
-    char rootpath[PATH_MAX];
+    char obbpath[PATH_MAX];
+
+    Hashmap* package_to_appid;
+    Hashmap* appid_with_rw;
 };
 
 /* Private data used by a single fuse handler. */
@@ -208,15 +305,26 @@
  * Populates 'buf' with the path and returns the length of the path on success,
  * or returns -1 if the path is too long for the provided buffer.
  */
-static ssize_t get_node_path_locked(struct node* node, char* buf, size_t bufsize)
-{
-    size_t namelen = node->namelen;
+static ssize_t get_node_path_locked(struct node* node, char* buf, size_t bufsize) {
+    const char* name;
+    size_t namelen;
+    if (node->graft_path) {
+        name = node->graft_path;
+        namelen = node->graft_pathlen;
+    } else if (node->actual_name) {
+        name = node->actual_name;
+        namelen = node->namelen;
+    } else {
+        name = node->name;
+        namelen = node->namelen;
+    }
+
     if (bufsize < namelen + 1) {
         return -1;
     }
 
     ssize_t pathlen = 0;
-    if (node->parent) {
+    if (node->parent && node->graft_path == NULL) {
         pathlen = get_node_path_locked(node->parent, buf, bufsize - namelen - 2);
         if (pathlen < 0) {
             return -1;
@@ -224,7 +332,6 @@
         buf[pathlen++] = '/';
     }
 
-    const char* name = node->actual_name ? node->actual_name : node->name;
     memcpy(buf + pathlen, name, namelen + 1); /* include trailing \0 */
     return pathlen + namelen;
 }
@@ -258,7 +365,7 @@
         struct dirent* entry;
         DIR* dir = opendir(path);
         if (!dir) {
-            ERROR("opendir %s failed: %s", path, strerror(errno));
+            ERROR("opendir %s failed: %s\n", path, strerror(errno));
             return actual;
         }
         while ((entry = readdir(dir))) {
@@ -273,9 +380,9 @@
     return actual;
 }
 
-static void attr_from_stat(struct fuse_attr *attr, const struct stat *s, __u64 nid)
+static void attr_from_stat(struct fuse_attr *attr, const struct stat *s, const struct node* node)
 {
-    attr->ino = nid;
+    attr->ino = node->nid;
     attr->size = s->st_size;
     attr->blocks = s->st_blocks;
     attr->atime = s->st_atime;
@@ -287,19 +394,169 @@
     attr->mode = s->st_mode;
     attr->nlink = s->st_nlink;
 
-        /* force permissions to something reasonable:
-         * world readable
-         * writable by the sdcard group
-         */
-    if (attr->mode & 0100) {
-        attr->mode = (attr->mode & (~0777)) | 0775;
-    } else {
-        attr->mode = (attr->mode & (~0777)) | 0664;
+    attr->uid = node->uid;
+    attr->gid = node->gid;
+
+    /* Filter requested mode based on underlying file, and
+     * pass through file type. */
+    int owner_mode = s->st_mode & 0700;
+    int filtered_mode = node->mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6));
+    attr->mode = (attr->mode & S_IFMT) | filtered_mode;
+}
+
+static int touch(char* path, mode_t mode) {
+    int fd = open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, mode);
+    if (fd == -1) {
+        if (errno == EEXIST) {
+            return 0;
+        } else {
+            ERROR("Failed to open(%s): %s\n", path, strerror(errno));
+            return -1;
+        }
+    }
+    close(fd);
+    return 0;
+}
+
+static void derive_permissions_locked(struct fuse* fuse, struct node *parent,
+        struct node *node) {
+    appid_t appid;
+
+    /* By default, each node inherits from its parent */
+    node->perm = PERM_INHERIT;
+    node->userid = parent->userid;
+    node->uid = parent->uid;
+    node->gid = parent->gid;
+    node->mode = parent->mode;
+
+    if (fuse->derive == DERIVE_NONE) {
+        return;
     }
 
-        /* all files owned by root.sdcard */
-    attr->uid = 0;
-    attr->gid = AID_SDCARD_RW;
+    /* Derive custom permissions based on parent and current node */
+    switch (parent->perm) {
+    case PERM_INHERIT:
+        /* Already inherited above */
+        break;
+    case PERM_LEGACY_PRE_ROOT:
+        /* Legacy internal layout places users at top level */
+        node->perm = PERM_ROOT;
+        node->userid = strtoul(node->name, NULL, 10);
+        break;
+    case PERM_ROOT:
+        /* Assume masked off by default. */
+        node->mode = 0770;
+        if (!strcasecmp(node->name, "Android")) {
+            /* App-specific directories inside; let anyone traverse */
+            node->perm = PERM_ANDROID;
+            node->mode = 0771;
+        } else if (fuse->split_perms) {
+            if (!strcasecmp(node->name, "DCIM")
+                    || !strcasecmp(node->name, "Pictures")) {
+                node->gid = AID_SDCARD_PICS;
+            } else if (!strcasecmp(node->name, "Alarms")
+                    || !strcasecmp(node->name, "Movies")
+                    || !strcasecmp(node->name, "Music")
+                    || !strcasecmp(node->name, "Notifications")
+                    || !strcasecmp(node->name, "Podcasts")
+                    || !strcasecmp(node->name, "Ringtones")) {
+                node->gid = AID_SDCARD_AV;
+            }
+        }
+        break;
+    case PERM_ANDROID:
+        if (!strcasecmp(node->name, "data")) {
+            /* App-specific directories inside; let anyone traverse */
+            node->perm = PERM_ANDROID_DATA;
+            node->mode = 0771;
+        } else if (!strcasecmp(node->name, "obb")) {
+            /* App-specific directories inside; let anyone traverse */
+            node->perm = PERM_ANDROID_OBB;
+            node->mode = 0771;
+            /* Single OBB directory is always shared */
+            node->graft_path = fuse->obbpath;
+            node->graft_pathlen = strlen(fuse->obbpath);
+        } else if (!strcasecmp(node->name, "user")) {
+            /* User directories must only be accessible to system, protected
+             * by sdcard_all. Zygote will bind mount the appropriate user-
+             * specific path. */
+            node->perm = PERM_ANDROID_USER;
+            node->gid = AID_SDCARD_ALL;
+            node->mode = 0770;
+        }
+        break;
+    case PERM_ANDROID_DATA:
+    case PERM_ANDROID_OBB:
+        appid = (appid_t) hashmapGet(fuse->package_to_appid, node->name);
+        if (appid != 0) {
+            node->uid = multiuser_get_uid(parent->userid, appid);
+        }
+        node->mode = 0770;
+        break;
+    case PERM_ANDROID_USER:
+        /* Root of a secondary user */
+        node->perm = PERM_ROOT;
+        node->userid = strtoul(node->name, NULL, 10);
+        node->gid = AID_SDCARD_R;
+        node->mode = 0771;
+        break;
+    }
+}
+
+/* Return if the calling UID holds sdcard_rw. */
+static bool get_caller_has_rw_locked(struct fuse* fuse, const struct fuse_in_header *hdr) {
+    /* No additional permissions enforcement */
+    if (fuse->derive == DERIVE_NONE) {
+        return true;
+    }
+
+    appid_t appid = multiuser_get_app_id(hdr->uid);
+    return hashmapContainsKey(fuse->appid_with_rw, (void*) appid);
+}
+
+/* Kernel has already enforced everything we returned through
+ * derive_permissions_locked(), so this is used to lock down access
+ * even further, such as enforcing that apps hold sdcard_rw. */
+static bool check_caller_access_to_name(struct fuse* fuse,
+        const struct fuse_in_header *hdr, const struct node* parent_node,
+        const char* name, int mode, bool has_rw) {
+    /* Always block security-sensitive files at root */
+    if (parent_node && parent_node->perm == PERM_ROOT) {
+        if (!strcasecmp(name, "autorun.inf")
+                || !strcasecmp(name, ".android_secure")
+                || !strcasecmp(name, "android_secure")) {
+            return false;
+        }
+    }
+
+    /* No additional permissions enforcement */
+    if (fuse->derive == DERIVE_NONE) {
+        return true;
+    }
+
+    /* Root always has access; access for any other UIDs should always
+     * be controlled through packages.list. */
+    if (hdr->uid == 0) {
+        return true;
+    }
+
+    /* If asking to write, verify that caller either owns the
+     * parent or holds sdcard_rw. */
+    if (mode & W_OK) {
+        if (parent_node && hdr->uid == parent_node->uid) {
+            return true;
+        }
+
+        return has_rw;
+    }
+
+    /* No extra permissions to enforce */
+    return true;
+}
+
+static bool check_caller_access_to_node(struct fuse* fuse,
+        const struct fuse_in_header *hdr, const struct node* node, int mode, bool has_rw) {
+    return check_caller_access_to_name(fuse, hdr, node->parent, node->name, mode, has_rw);
 }
 
 struct node *create_node_locked(struct fuse* fuse,
@@ -330,6 +587,8 @@
     node->namelen = namelen;
     node->nid = ptr_to_id(node);
     node->gen = fuse->next_generation++;
+
+    derive_permissions_locked(fuse, parent, node);
     acquire_node_locked(node);
     add_node_to_parent_locked(node, parent);
     return node;
@@ -422,18 +681,56 @@
     return child;
 }
 
-static void fuse_init(struct fuse *fuse, int fd, const char *source_path)
-{
+static void fuse_init(struct fuse *fuse, int fd, const char *source_path,
+        gid_t write_gid, derive_t derive, bool split_perms) {
     pthread_mutex_init(&fuse->lock, NULL);
 
     fuse->fd = fd;
     fuse->next_generation = 0;
+    fuse->derive = derive;
+    fuse->split_perms = split_perms;
+    fuse->write_gid = write_gid;
 
     memset(&fuse->root, 0, sizeof(fuse->root));
     fuse->root.nid = FUSE_ROOT_ID; /* 1 */
     fuse->root.refcount = 2;
     fuse->root.namelen = strlen(source_path);
     fuse->root.name = strdup(source_path);
+    fuse->root.userid = 0;
+    fuse->root.uid = AID_ROOT;
+
+    /* Set up root node for various modes of operation */
+    switch (derive) {
+    case DERIVE_NONE:
+        /* Traditional behavior that treats entire device as being accessible
+         * to sdcard_rw, and no permissions are derived. */
+        fuse->root.perm = PERM_ROOT;
+        fuse->root.mode = 0775;
+        fuse->root.gid = AID_SDCARD_RW;
+        break;
+    case DERIVE_LEGACY:
+        /* Legacy behavior used to support internal multiuser layout which
+         * places user_id at the top directory level, with the actual roots
+         * just below that. Shared OBB path is also at top level. */
+        fuse->root.perm = PERM_LEGACY_PRE_ROOT;
+        fuse->root.mode = 0771;
+        fuse->root.gid = AID_SDCARD_R;
+        fuse->package_to_appid = hashmapCreate(256, str_hash, str_icase_equals);
+        fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals);
+        snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/obb", source_path);
+        fs_prepare_dir(fuse->obbpath, 0775, getuid(), getgid());
+        break;
+    case DERIVE_UNIFIED:
+        /* Unified multiuser layout which places secondary user_id under
+         * /Android/user and shared OBB path under /Android/obb. */
+        fuse->root.perm = PERM_ROOT;
+        fuse->root.mode = 0771;
+        fuse->root.gid = AID_SDCARD_R;
+        fuse->package_to_appid = hashmapCreate(256, str_hash, str_icase_equals);
+        fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals);
+        snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/Android/obb", source_path);
+        break;
+    }
 }
 
 static void fuse_status(struct fuse *fuse, __u64 unique, int err)
@@ -485,7 +782,7 @@
         return -ENOMEM;
     }
     memset(&out, 0, sizeof(out));
-    attr_from_stat(&out.attr, &s, node->nid);
+    attr_from_stat(&out.attr, &s, node);
     out.attr_valid = 10;
     out.entry_valid = 10;
     out.nodeid = node->nid;
@@ -495,7 +792,7 @@
     return NO_STATUS;
 }
 
-static int fuse_reply_attr(struct fuse* fuse, __u64 unique, __u64 nid,
+static int fuse_reply_attr(struct fuse* fuse, __u64 unique, const struct node* node,
         const char* path)
 {
     struct fuse_attr_out out;
@@ -505,7 +802,7 @@
         return -errno;
     }
     memset(&out, 0, sizeof(out));
-    attr_from_stat(&out.attr, &s, nid);
+    attr_from_stat(&out.attr, &s, node);
     out.attr_valid = 10;
     fuse_reply(fuse, unique, &out, sizeof(out));
     return NO_STATUS;
@@ -530,6 +827,10 @@
             child_path, sizeof(child_path), 1))) {
         return -ENOENT;
     }
+    if (!check_caller_access_to_name(fuse, hdr, parent_node, name, R_OK, false)) {
+        return -EACCES;
+    }
+
     return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path);
 }
 
@@ -567,17 +868,23 @@
     if (!node) {
         return -ENOENT;
     }
-    return fuse_reply_attr(fuse, hdr->unique, hdr->nodeid, path);
+    if (!check_caller_access_to_node(fuse, hdr, node, R_OK, false)) {
+        return -EACCES;
+    }
+
+    return fuse_reply_attr(fuse, hdr->unique, node, path);
 }
 
 static int handle_setattr(struct fuse* fuse, struct fuse_handler* handler,
         const struct fuse_in_header *hdr, const struct fuse_setattr_in *req)
 {
+    bool has_rw;
     struct node* node;
     char path[PATH_MAX];
     struct timespec times[2];
 
     pthread_mutex_lock(&fuse->lock);
+    has_rw = get_caller_has_rw_locked(fuse, hdr);
     node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, path, sizeof(path));
     TRACE("[%d] SETATTR fh=%llx valid=%x @ %llx (%s)\n", handler->token,
             req->fh, req->valid, hdr->nodeid, node ? node->name : "?");
@@ -586,6 +893,9 @@
     if (!node) {
         return -ENOENT;
     }
+    if (!check_caller_access_to_node(fuse, hdr, node, W_OK, has_rw)) {
+        return -EACCES;
+    }
 
     /* XXX: incomplete implementation on purpose.
      * chmod/chown should NEVER be implemented.*/
@@ -625,18 +935,20 @@
             return -errno;
         }
     }
-    return fuse_reply_attr(fuse, hdr->unique, hdr->nodeid, path);
+    return fuse_reply_attr(fuse, hdr->unique, node, path);
 }
 
 static int handle_mknod(struct fuse* fuse, struct fuse_handler* handler,
         const struct fuse_in_header* hdr, const struct fuse_mknod_in* req, const char* name)
 {
+    bool has_rw;
     struct node* parent_node;
     char parent_path[PATH_MAX];
     char child_path[PATH_MAX];
     const char* actual_name;
 
     pthread_mutex_lock(&fuse->lock);
+    has_rw = get_caller_has_rw_locked(fuse, hdr);
     parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid,
             parent_path, sizeof(parent_path));
     TRACE("[%d] MKNOD %s 0%o @ %llx (%s)\n", handler->token,
@@ -647,6 +959,9 @@
             child_path, sizeof(child_path), 1))) {
         return -ENOENT;
     }
+    if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK, has_rw)) {
+        return -EACCES;
+    }
     __u32 mode = (req->mode & (~0777)) | 0664;
     if (mknod(child_path, mode, req->rdev) < 0) {
         return -errno;
@@ -657,12 +972,14 @@
 static int handle_mkdir(struct fuse* fuse, struct fuse_handler* handler,
         const struct fuse_in_header* hdr, const struct fuse_mkdir_in* req, const char* name)
 {
+    bool has_rw;
     struct node* parent_node;
     char parent_path[PATH_MAX];
     char child_path[PATH_MAX];
     const char* actual_name;
 
     pthread_mutex_lock(&fuse->lock);
+    has_rw = get_caller_has_rw_locked(fuse, hdr);
     parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid,
             parent_path, sizeof(parent_path));
     TRACE("[%d] MKDIR %s 0%o @ %llx (%s)\n", handler->token,
@@ -673,21 +990,45 @@
             child_path, sizeof(child_path), 1))) {
         return -ENOENT;
     }
+    if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK, has_rw)) {
+        return -EACCES;
+    }
     __u32 mode = (req->mode & (~0777)) | 0775;
     if (mkdir(child_path, mode) < 0) {
         return -errno;
     }
+
+    /* When creating /Android/data and /Android/obb, mark them as .nomedia */
+    if (parent_node->perm == PERM_ANDROID && !strcasecmp(name, "data")) {
+        char nomedia[PATH_MAX];
+        snprintf(nomedia, PATH_MAX, "%s/.nomedia", child_path);
+        if (touch(nomedia, 0664) != 0) {
+            ERROR("Failed to touch(%s): %s\n", nomedia, strerror(errno));
+            return -ENOENT;
+        }
+    }
+    if (parent_node->perm == PERM_ANDROID && !strcasecmp(name, "obb")) {
+        char nomedia[PATH_MAX];
+        snprintf(nomedia, PATH_MAX, "%s/.nomedia", fuse->obbpath);
+        if (touch(nomedia, 0664) != 0) {
+            ERROR("Failed to touch(%s): %s\n", nomedia, strerror(errno));
+            return -ENOENT;
+        }
+    }
+
     return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path);
 }
 
 static int handle_unlink(struct fuse* fuse, struct fuse_handler* handler,
         const struct fuse_in_header* hdr, const char* name)
 {
+    bool has_rw;
     struct node* parent_node;
     char parent_path[PATH_MAX];
     char child_path[PATH_MAX];
 
     pthread_mutex_lock(&fuse->lock);
+    has_rw = get_caller_has_rw_locked(fuse, hdr);
     parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid,
             parent_path, sizeof(parent_path));
     TRACE("[%d] UNLINK %s @ %llx (%s)\n", handler->token,
@@ -698,6 +1039,9 @@
             child_path, sizeof(child_path), 1)) {
         return -ENOENT;
     }
+    if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK, has_rw)) {
+        return -EACCES;
+    }
     if (unlink(child_path) < 0) {
         return -errno;
     }
@@ -707,11 +1051,13 @@
 static int handle_rmdir(struct fuse* fuse, struct fuse_handler* handler,
         const struct fuse_in_header* hdr, const char* name)
 {
+    bool has_rw;
     struct node* parent_node;
     char parent_path[PATH_MAX];
     char child_path[PATH_MAX];
 
     pthread_mutex_lock(&fuse->lock);
+    has_rw = get_caller_has_rw_locked(fuse, hdr);
     parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid,
             parent_path, sizeof(parent_path));
     TRACE("[%d] RMDIR %s @ %llx (%s)\n", handler->token,
@@ -722,6 +1068,9 @@
             child_path, sizeof(child_path), 1)) {
         return -ENOENT;
     }
+    if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK, has_rw)) {
+        return -EACCES;
+    }
     if (rmdir(child_path) < 0) {
         return -errno;
     }
@@ -732,6 +1081,7 @@
         const struct fuse_in_header* hdr, const struct fuse_rename_in* req,
         const char* old_name, const char* new_name)
 {
+    bool has_rw;
     struct node* old_parent_node;
     struct node* new_parent_node;
     struct node* child_node;
@@ -743,6 +1093,7 @@
     int res;
 
     pthread_mutex_lock(&fuse->lock);
+    has_rw = get_caller_has_rw_locked(fuse, hdr);
     old_parent_node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid,
             old_parent_path, sizeof(old_parent_path));
     new_parent_node = lookup_node_and_path_by_id_locked(fuse, req->newdir,
@@ -755,6 +1106,14 @@
         res = -ENOENT;
         goto lookup_error;
     }
+    if (!check_caller_access_to_name(fuse, hdr, old_parent_node, old_name, W_OK, has_rw)) {
+        res = -EACCES;
+        goto lookup_error;
+    }
+    if (!check_caller_access_to_name(fuse, hdr, new_parent_node, new_name, W_OK, has_rw)) {
+        res = -EACCES;
+        goto lookup_error;
+    }
     child_node = lookup_child_by_name_locked(old_parent_node, old_name);
     if (!child_node || get_node_path_locked(child_node,
             old_child_path, sizeof(old_child_path)) < 0) {
@@ -800,15 +1159,28 @@
     return res;
 }
 
+static int open_flags_to_access_mode(int open_flags) {
+    if ((open_flags & O_ACCMODE) == O_RDONLY) {
+        return R_OK;
+    } else if ((open_flags & O_ACCMODE) == O_WRONLY) {
+        return W_OK;
+    } else {
+        /* Probably O_RDRW, but treat as default to be safe */
+        return R_OK | W_OK;
+    }
+}
+
 static int handle_open(struct fuse* fuse, struct fuse_handler* handler,
         const struct fuse_in_header* hdr, const struct fuse_open_in* req)
 {
+    bool has_rw;
     struct node* node;
     char path[PATH_MAX];
     struct fuse_open_out out;
     struct handle *h;
 
     pthread_mutex_lock(&fuse->lock);
+    has_rw = get_caller_has_rw_locked(fuse, hdr);
     node = lookup_node_and_path_by_id_locked(fuse, hdr->nodeid, path, sizeof(path));
     TRACE("[%d] OPEN 0%o @ %llx (%s)\n", handler->token,
             req->flags, hdr->nodeid, node ? node->name : "?");
@@ -817,6 +1189,10 @@
     if (!node) {
         return -ENOENT;
     }
+    if (!check_caller_access_to_node(fuse, hdr, node,
+            open_flags_to_access_mode(req->flags), has_rw)) {
+        return -EACCES;
+    }
     h = malloc(sizeof(*h));
     if (!h) {
         return -ENOMEM;
@@ -961,6 +1337,9 @@
     if (!node) {
         return -ENOENT;
     }
+    if (!check_caller_access_to_node(fuse, hdr, node, R_OK, false)) {
+        return -EACCES;
+    }
     h = malloc(sizeof(*h));
     if (!h) {
         return -ENOMEM;
@@ -972,6 +1351,8 @@
         return -errno;
     }
     out.fh = ptr_to_id(h);
+    out.open_flags = 0;
+    out.padding = 0;
     fuse_reply(fuse, hdr->unique, &out, sizeof(out));
     return NO_STATUS;
 }
@@ -1206,6 +1587,123 @@
     return NULL;
 }
 
+static bool remove_str_to_int(void *key, void *value, void *context) {
+    Hashmap* map = context;
+    hashmapRemove(map, key);
+    free(key);
+    return true;
+}
+
+static bool remove_int_to_null(void *key, void *value, void *context) {
+    Hashmap* map = context;
+    hashmapRemove(map, key);
+    return true;
+}
+
+static int read_package_list(struct fuse *fuse) {
+    pthread_mutex_lock(&fuse->lock);
+
+    hashmapForEach(fuse->package_to_appid, remove_str_to_int, fuse->package_to_appid);
+    hashmapForEach(fuse->appid_with_rw, remove_int_to_null, fuse->appid_with_rw);
+
+    FILE* file = fopen(kPackagesListFile, "r");
+    if (!file) {
+        ERROR("failed to open package list: %s\n", strerror(errno));
+        pthread_mutex_unlock(&fuse->lock);
+        return -1;
+    }
+
+    char buf[512];
+    while (fgets(buf, sizeof(buf), file) != NULL) {
+        char package_name[512];
+        int appid;
+        char gids[512];
+
+        if (sscanf(buf, "%s %d %*d %*s %*s %s", package_name, &appid, gids) == 3) {
+            char* package_name_dup = strdup(package_name);
+            hashmapPut(fuse->package_to_appid, package_name_dup, (void*) appid);
+
+            char* token = strtok(gids, ",");
+            while (token != NULL) {
+                if (strtoul(token, NULL, 10) == fuse->write_gid) {
+                    hashmapPut(fuse->appid_with_rw, (void*) appid, (void*) 1);
+                    break;
+                }
+                token = strtok(NULL, ",");
+            }
+        }
+    }
+
+    TRACE("read_package_list: found %d packages, %d with write_gid\n",
+            hashmapSize(fuse->package_to_appid),
+            hashmapSize(fuse->appid_with_rw));
+    fclose(file);
+    pthread_mutex_unlock(&fuse->lock);
+    return 0;
+}
+
+static void watch_package_list(struct fuse* fuse) {
+    struct inotify_event *event;
+    char event_buf[512];
+
+    int nfd = inotify_init();
+    if (nfd < 0) {
+        ERROR("inotify_init failed: %s\n", strerror(errno));
+        return;
+    }
+
+    bool active = false;
+    while (1) {
+        if (!active) {
+            int res = inotify_add_watch(nfd, kPackagesListFile, IN_DELETE_SELF);
+            if (res == -1) {
+                if (errno == ENOENT || errno == EACCES) {
+                    /* Framework may not have created yet, sleep and retry */
+                    ERROR("missing packages.list; retrying\n");
+                    sleep(3);
+                    continue;
+                } else {
+                    ERROR("inotify_add_watch failed: %s\n", strerror(errno));
+                    return;
+                }
+            }
+
+            /* Watch above will tell us about any future changes, so
+             * read the current state. */
+            if (read_package_list(fuse) == -1) {
+                ERROR("read_package_list failed: %s\n", strerror(errno));
+                return;
+            }
+            active = true;
+        }
+
+        int event_pos = 0;
+        int res = read(nfd, event_buf, sizeof(event_buf));
+        if (res < (int) sizeof(*event)) {
+            if (errno == EINTR)
+                continue;
+            ERROR("failed to read inotify event: %s\n", strerror(errno));
+            return;
+        }
+
+        while (res >= (int) sizeof(*event)) {
+            int event_size;
+            event = (struct inotify_event *) (event_buf + event_pos);
+
+            TRACE("inotify event: %08x\n", event->mask);
+            if ((event->mask & IN_IGNORED) == IN_IGNORED) {
+                /* Previously watched file was deleted, probably due to move
+                 * that swapped in new data; re-arm the watch and read. */
+                active = false;
+            }
+
+            event_size = sizeof(*event) + event->len;
+            res -= event_size;
+            event_pos += event_size;
+        }
+    }
+}
+
 static int ignite_fuse(struct fuse* fuse, int num_threads)
 {
     struct fuse_handler* handlers;
@@ -1213,7 +1711,7 @@
 
     handlers = malloc(num_threads * sizeof(struct fuse_handler));
     if (!handlers) {
-        ERROR("cannot allocate storage for threads");
+        ERROR("cannot allocate storage for threads\n");
         return -ENOMEM;
     }
 
@@ -1222,16 +1720,25 @@
         handlers[i].token = i;
     }
 
-    for (i = 1; i < num_threads; i++) {
+    /* When deriving permissions, this thread is used to process inotify events,
+     * otherwise it becomes one of the FUSE handlers. */
+    i = (fuse->derive == DERIVE_NONE) ? 1 : 0;
+    for (; i < num_threads; i++) {
         pthread_t thread;
         int res = pthread_create(&thread, NULL, start_handler, &handlers[i]);
         if (res) {
-            ERROR("failed to start thread #%d, error=%d", i, res);
+            ERROR("failed to start thread #%d, error=%d\n", i, res);
             goto quit;
         }
     }
-    handle_fuse_requests(&handlers[0]);
-    ERROR("terminated prematurely");
+
+    if (fuse->derive == DERIVE_NONE) {
+        handle_fuse_requests(&handlers[0]);
+    } else {
+        watch_package_list(fuse);
+    }
+
+    ERROR("terminated prematurely\n");
 
     /* don't bother killing all of the other threads or freeing anything,
      * should never get here anyhow */
@@ -1241,14 +1748,21 @@
 
 static int usage()
 {
-    ERROR("usage: sdcard [-t<threads>] <source_path> <dest_path> <uid> <gid>\n"
-            "    -t<threads>: specify number of threads to use, default -t%d\n"
+    ERROR("usage: sdcard [OPTIONS] <source_path> <dest_path>\n"
+            "    -u: specify UID to run as\n"
+            "    -g: specify GID to run as\n"
+            "    -w: specify GID required to write (default sdcard_rw, requires -d or -l)\n"
+            "    -t: specify number of threads to use (default %d)\n"
+            "    -d: derive file permissions based on path\n"
+            "    -l: derive file permissions based on legacy internal layout\n"
+            "    -s: split derived permissions for pics, av\n"
             "\n", DEFAULT_NUM_THREADS);
     return 1;
 }
 
-static int run(const char* source_path, const char* dest_path, uid_t uid, gid_t gid,
-        int num_threads) {
+static int run(const char* source_path, const char* dest_path, uid_t uid,
+        gid_t gid, gid_t write_gid, int num_threads, derive_t derive,
+        bool split_perms) {
     int fd;
     char opts[256];
     int res;
@@ -1259,7 +1773,7 @@
 
     fd = open("/dev/fuse", O_RDWR);
     if (fd < 0){
-        ERROR("cannot open fuse device (error %d)\n", errno);
+        ERROR("cannot open fuse device: %s\n", strerror(errno));
         return -1;
     }
 
@@ -1269,23 +1783,29 @@
 
     res = mount("/dev/fuse", dest_path, "fuse", MS_NOSUID | MS_NODEV, opts);
     if (res < 0) {
-        ERROR("cannot mount fuse filesystem (error %d)\n", errno);
+        ERROR("cannot mount fuse filesystem: %s\n", strerror(errno));
+        goto error;
+    }
+
+    res = setgroups(sizeof(kGroups) / sizeof(kGroups[0]), kGroups);
+    if (res < 0) {
+        ERROR("cannot setgroups: %s\n", strerror(errno));
         goto error;
     }
 
     res = setgid(gid);
     if (res < 0) {
-        ERROR("cannot setgid (error %d)\n", errno);
+        ERROR("cannot setgid: %s\n", strerror(errno));
         goto error;
     }
 
     res = setuid(uid);
     if (res < 0) {
-        ERROR("cannot setuid (error %d)\n", errno);
+        ERROR("cannot setuid: %s\n", strerror(errno));
         goto error;
     }
 
-    fuse_init(&fuse, fd, source_path);
+    fuse_init(&fuse, fd, source_path, write_gid, derive, split_perms);
 
     umask(0);
     res = ignite_fuse(&fuse, num_threads);
@@ -1305,34 +1825,53 @@
     const char *dest_path = NULL;
     uid_t uid = 0;
     gid_t gid = 0;
+    gid_t write_gid = AID_SDCARD_RW;
     int num_threads = DEFAULT_NUM_THREADS;
+    derive_t derive = DERIVE_NONE;
+    bool split_perms = false;
     int i;
     struct rlimit rlim;
 
-    for (i = 1; i < argc; i++) {
+    int opt;
+    while ((opt = getopt(argc, argv, "u:g:w:t:dls")) != -1) {
+        switch (opt) {
+            case 'u':
+                uid = strtoul(optarg, NULL, 10);
+                break;
+            case 'g':
+                gid = strtoul(optarg, NULL, 10);
+                break;
+            case 'w':
+                write_gid = strtoul(optarg, NULL, 10);
+                break;
+            case 't':
+                num_threads = strtoul(optarg, NULL, 10);
+                break;
+            case 'd':
+                derive = DERIVE_UNIFIED;
+                break;
+            case 'l':
+                derive = DERIVE_LEGACY;
+                break;
+            case 's':
+                split_perms = true;
+                break;
+            case '?':
+            default:
+                return usage();
+        }
+    }
+
+    for (i = optind; i < argc; i++) {
         char* arg = argv[i];
-        if (!strncmp(arg, "-t", 2))
-            num_threads = strtoul(arg + 2, 0, 10);
-        else if (!source_path)
+        if (!source_path) {
             source_path = arg;
-        else if (!dest_path)
+        } else if (!dest_path) {
             dest_path = arg;
-        else if (!uid) {
-            char* endptr = NULL;
-            errno = 0;
-            uid = strtoul(arg, &endptr, 10);
-            if (*endptr != '\0' || errno != 0) {
-                ERROR("Invalid uid");
-                return usage();
-            }
+        } else if (!uid) {
+            uid = strtoul(arg, NULL, 10);
         } else if (!gid) {
-            char* endptr = NULL;
-            errno = 0;
-            gid = strtoul(arg, &endptr, 10);
-            if (*endptr != '\0' || errno != 0) {
-                ERROR("Invalid gid");
-                return usage();
-            }
+            gid = strtoul(arg, NULL, 10);
         } else {
             ERROR("too many arguments\n");
             return usage();
@@ -1355,6 +1894,10 @@
         ERROR("number of threads must be at least 1\n");
         return usage();
     }
+    if (split_perms && derive == DERIVE_NONE) {
+        ERROR("cannot split permissions without deriving\n");
+        return usage();
+    }
 
     rlim.rlim_cur = 8192;
     rlim.rlim_max = 8192;
@@ -1362,6 +1905,6 @@
         ERROR("Error setting RLIMIT_NOFILE, errno = %d\n", errno);
     }
 
-    res = run(source_path, dest_path, uid, gid, num_threads);
+    res = run(source_path, dest_path, uid, gid, write_gid, num_threads, derive, split_perms);
     return res < 0 ? 1 : 0;
 }
diff --git a/sh/Android.mk b/sh/Android.mk
deleted file mode 100644
index dcd13d8..0000000
--- a/sh/Android.mk
+++ /dev/null
@@ -1,70 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	alias.c \
-	arith.c \
-	arith_lex.c \
-	builtins.c \
-	cd.c \
-	error.c \
-	eval.c \
-	exec.c \
-	expand.c \
-	input.c \
-	jobs.c \
-	main.c \
-	memalloc.c \
-	miscbltin.c \
-	mystring.c \
-	nodes.c \
-	options.c \
-	parser.c \
-	redir.c \
-	show.c \
-	syntax.c \
-	trap.c \
-	output.c \
-	var.c \
-	bltin/echo.c \
-	init.c
-
-LOCAL_MODULE:= ash
-LOCAL_MODULE_TAGS:= shell_ash
-
-LOCAL_CFLAGS += -DSHELL -DWITH_LINENOISE
-
-LOCAL_STATIC_LIBRARIES := liblinenoise
-
-LOCAL_C_INCLUDES += system/core/liblinenoise
-
-make_ash_files: PRIVATE_SRC_FILES := $(SRC_FILES)
-make_ash_files: PRIVATE_CFLAGS := $(LOCAL_CFLAGS)
-make_ash_files:
-	p4 edit arith.c arith_lex.c arith.h builtins.h builtins.c 
-	p4 edit init.c nodes.c nodes.h token.h 
-	sh ./mktokens
-	bison -o arith.c arith.y
-	flex -o arith_lex.c arith_lex.l
-	perl -ne 'print if ( /^\#\s*define\s+ARITH/ );' < arith.c > arith.h
-	sh ./mkbuiltins shell.h builtins.def . -Wall -O2
-	sh ./mknodes.sh nodetypes nodes.c.pat .
-	sh ./mkinit.sh $(PRIVATE_SRC_FILES) 
-
-include $(BUILD_EXECUTABLE)
-
-
-# create /system/bin/sh symlink to $(TARGET_SHELL)
-# not the optimal place for this, but a fitting one
-
-OUTSYSTEMBINSH := $(TARGET_OUT)/bin/sh
-LOCAL_MODULE := systembinsh
-$(OUTSYSTEMBINSH): | $(TARGET_SHELL)
-$(OUTSYSTEMBINSH): LOCAL_MODULE := $(LOCAL_MODULE)
-$(OUTSYSTEMBINSH):
-	@echo "Symlink: $@ -> $(TARGET_SHELL)"
-	@rm -rf $@
-	$(hide) ln -sf $(TARGET_SHELL) $@
-
-ALL_DEFAULT_INSTALLED_MODULES += $(OUTSYSTEMBINSH)
-ALL_MODULES.$(LOCAL_MODULE).INSTALLED += $(OUTSYSTEMBINSH)
diff --git a/sh/MODULE_LICENSE_BSD b/sh/MODULE_LICENSE_BSD
deleted file mode 100644
index e69de29..0000000
--- a/sh/MODULE_LICENSE_BSD
+++ /dev/null
diff --git a/sh/NOTICE b/sh/NOTICE
deleted file mode 100644
index 49a66d2..0000000
--- a/sh/NOTICE
+++ /dev/null
@@ -1,31 +0,0 @@
-Copyright (c) 1991, 1993
-     The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Kenneth Almquist.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. 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.
-
-
diff --git a/sh/TOUR b/sh/TOUR
deleted file mode 100644
index f5c00c4..0000000
--- a/sh/TOUR
+++ /dev/null
@@ -1,357 +0,0 @@
-#	$NetBSD: TOUR,v 1.8 1996/10/16 14:24:56 christos Exp $
-#	@(#)TOUR	8.1 (Berkeley) 5/31/93
-
-NOTE -- This is the original TOUR paper distributed with ash and
-does not represent the current state of the shell.  It is provided anyway
-since it provides helpful information for how the shell is structured,
-but be warned that things have changed -- the current shell is
-still under development.
-
-================================================================
-
-                       A Tour through Ash
-
-               Copyright 1989 by Kenneth Almquist.
-
-
-DIRECTORIES:  The subdirectory bltin contains commands which can
-be compiled stand-alone.  The rest of the source is in the main
-ash directory.
-
-SOURCE CODE GENERATORS:  Files whose names begin with "mk" are
-programs that generate source code.  A complete list of these
-programs is:
-
-        program         intput files        generates
-        -------         ------------        ---------
-        mkbuiltins      builtins            builtins.h builtins.c
-        mkinit          *.c                 init.c
-        mknodes         nodetypes           nodes.h nodes.c
-        mksignames          -               signames.h signames.c
-        mksyntax            -               syntax.h syntax.c
-        mktokens            -               token.h
-        bltin/mkexpr    unary_op binary_op  operators.h operators.c
-
-There are undoubtedly too many of these.  Mkinit searches all the
-C source files for entries looking like:
-
-        INIT {
-              x = 1;    /* executed during initialization */
-        }
-
-        RESET {
-              x = 2;    /* executed when the shell does a longjmp
-                           back to the main command loop */
-        }
-
-        SHELLPROC {
-              x = 3;    /* executed when the shell runs a shell procedure */
-        }
-
-It pulls this code out into routines which are when particular
-events occur.  The intent is to improve modularity by isolating
-the information about which modules need to be explicitly
-initialized/reset within the modules themselves.
-
-Mkinit recognizes several constructs for placing declarations in
-the init.c file.
-        INCLUDE "file.h"
-includes a file.  The storage class MKINIT makes a declaration
-available in the init.c file, for example:
-        MKINIT int funcnest;    /* depth of function calls */
-MKINIT alone on a line introduces a structure or union declara-
-tion:
-        MKINIT
-        struct redirtab {
-              short renamed[10];
-        };
-Preprocessor #define statements are copied to init.c without any
-special action to request this.
-
-INDENTATION:  The ash source is indented in multiples of six
-spaces.  The only study that I have heard of on the subject con-
-cluded that the optimal amount to indent is in the range of four
-to six spaces.  I use six spaces since it is not too big a jump
-from the widely used eight spaces.  If you really hate six space
-indentation, use the adjind (source included) program to change
-it to something else.
-
-EXCEPTIONS:  Code for dealing with exceptions appears in
-exceptions.c.  The C language doesn't include exception handling,
-so I implement it using setjmp and longjmp.  The global variable
-exception contains the type of exception.  EXERROR is raised by
-calling error.  EXINT is an interrupt.  EXSHELLPROC is an excep-
-tion which is raised when a shell procedure is invoked.  The pur-
-pose of EXSHELLPROC is to perform the cleanup actions associated
-with other exceptions.  After these cleanup actions, the shell
-can interpret a shell procedure itself without exec'ing a new
-copy of the shell.
-
-INTERRUPTS:  In an interactive shell, an interrupt will cause an
-EXINT exception to return to the main command loop.  (Exception:
-EXINT is not raised if the user traps interrupts using the trap
-command.)  The INTOFF and INTON macros (defined in exception.h)
-provide uninterruptable critical sections.  Between the execution
-of INTOFF and the execution of INTON, interrupt signals will be
-held for later delivery.  INTOFF and INTON can be nested.
-
-MEMALLOC.C:  Memalloc.c defines versions of malloc and realloc
-which call error when there is no memory left.  It also defines a
-stack oriented memory allocation scheme.  Allocating off a stack
-is probably more efficient than allocation using malloc, but the
-big advantage is that when an exception occurs all we have to do
-to free up the memory in use at the time of the exception is to
-restore the stack pointer.  The stack is implemented using a
-linked list of blocks.
-
-STPUTC:  If the stack were contiguous, it would be easy to store
-strings on the stack without knowing in advance how long the
-string was going to be:
-        p = stackptr;
-        *p++ = c;       /* repeated as many times as needed */
-        stackptr = p;
-The folloing three macros (defined in memalloc.h) perform these
-operations, but grow the stack if you run off the end:
-        STARTSTACKSTR(p);
-        STPUTC(c, p);   /* repeated as many times as needed */
-        grabstackstr(p);
-
-We now start a top-down look at the code:
-
-MAIN.C:  The main routine performs some initialization, executes
-the user's profile if necessary, and calls cmdloop.  Cmdloop is
-repeatedly parses and executes commands.
-
-OPTIONS.C:  This file contains the option processing code.  It is
-called from main to parse the shell arguments when the shell is
-invoked, and it also contains the set builtin.  The -i and -j op-
-tions (the latter turns on job control) require changes in signal
-handling.  The routines setjobctl (in jobs.c) and setinteractive
-(in trap.c) are called to handle changes to these options.
-
-PARSING:  The parser code is all in parser.c.  A recursive des-
-cent parser is used.  Syntax tables (generated by mksyntax) are
-used to classify characters during lexical analysis.  There are
-three tables:  one for normal use, one for use when inside single
-quotes, and one for use when inside double quotes.  The tables
-are machine dependent because they are indexed by character vari-
-ables and the range of a char varies from machine to machine.
-
-PARSE OUTPUT:  The output of the parser consists of a tree of
-nodes.  The various types of nodes are defined in the file node-
-types.
-
-Nodes of type NARG are used to represent both words and the con-
-tents of here documents.  An early version of ash kept the con-
-tents of here documents in temporary files, but keeping here do-
-cuments in memory typically results in significantly better per-
-formance.  It would have been nice to make it an option to use
-temporary files for here documents, for the benefit of small
-machines, but the code to keep track of when to delete the tem-
-porary files was complex and I never fixed all the bugs in it.
-(AT&T has been maintaining the Bourne shell for more than ten
-years, and to the best of my knowledge they still haven't gotten
-it to handle temporary files correctly in obscure cases.)
-
-The text field of a NARG structure points to the text of the
-word.  The text consists of ordinary characters and a number of
-special codes defined in parser.h.  The special codes are:
-
-        CTLVAR              Variable substitution
-        CTLENDVAR           End of variable substitution
-        CTLBACKQ            Command substitution
-        CTLBACKQ|CTLQUOTE   Command substitution inside double quotes
-        CTLESC              Escape next character
-
-A variable substitution contains the following elements:
-
-        CTLVAR type name '=' [ alternative-text CTLENDVAR ]
-
-The type field is a single character specifying the type of sub-
-stitution.  The possible types are:
-
-        VSNORMAL            $var
-        VSMINUS             ${var-text}
-        VSMINUS|VSNUL       ${var:-text}
-        VSPLUS              ${var+text}
-        VSPLUS|VSNUL        ${var:+text}
-        VSQUESTION          ${var?text}
-        VSQUESTION|VSNUL    ${var:?text}
-        VSASSIGN            ${var=text}
-        VSASSIGN|VSNUL      ${var=text}
-
-In addition, the type field will have the VSQUOTE flag set if the
-variable is enclosed in double quotes.  The name of the variable
-comes next, terminated by an equals sign.  If the type is not
-VSNORMAL, then the text field in the substitution follows, ter-
-minated by a CTLENDVAR byte.
-
-Commands in back quotes are parsed and stored in a linked list.
-The locations of these commands in the string are indicated by
-CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether
-the back quotes were enclosed in double quotes.
-
-The character CTLESC escapes the next character, so that in case
-any of the CTL characters mentioned above appear in the input,
-they can be passed through transparently.  CTLESC is also used to
-escape '*', '?', '[', and '!' characters which were quoted by the
-user and thus should not be used for file name generation.
-
-CTLESC characters have proved to be particularly tricky to get
-right.  In the case of here documents which are not subject to
-variable and command substitution, the parser doesn't insert any
-CTLESC characters to begin with (so the contents of the text
-field can be written without any processing).  Other here docu-
-ments, and words which are not subject to splitting and file name
-generation, have the CTLESC characters removed during the vari-
-able and command substitution phase.  Words which are subject
-splitting and file name generation have the CTLESC characters re-
-moved as part of the file name phase.
-
-EXECUTION:  Command execution is handled by the following files:
-        eval.c     The top level routines.
-        redir.c    Code to handle redirection of input and output.
-        jobs.c     Code to handle forking, waiting, and job control.
-        exec.c     Code to to path searches and the actual exec sys call.
-        expand.c   Code to evaluate arguments.
-        var.c      Maintains the variable symbol table.  Called from expand.c.
-
-EVAL.C:  Evaltree recursively executes a parse tree.  The exit
-status is returned in the global variable exitstatus.  The alter-
-native entry evalbackcmd is called to evaluate commands in back
-quotes.  It saves the result in memory if the command is a buil-
-tin; otherwise it forks off a child to execute the command and
-connects the standard output of the child to a pipe.
-
-JOBS.C:  To create a process, you call makejob to return a job
-structure, and then call forkshell (passing the job structure as
-an argument) to create the process.  Waitforjob waits for a job
-to complete.  These routines take care of process groups if job
-control is defined.
-
-REDIR.C:  Ash allows file descriptors to be redirected and then
-restored without forking off a child process.  This is accom-
-plished by duplicating the original file descriptors.  The redir-
-tab structure records where the file descriptors have be dupli-
-cated to.
-
-EXEC.C:  The routine find_command locates a command, and enters
-the command in the hash table if it is not already there.  The
-third argument specifies whether it is to print an error message
-if the command is not found.  (When a pipeline is set up,
-find_command is called for all the commands in the pipeline be-
-fore any forking is done, so to get the commands into the hash
-table of the parent process.  But to make command hashing as
-transparent as possible, we silently ignore errors at that point
-and only print error messages if the command cannot be found
-later.)
-
-The routine shellexec is the interface to the exec system call.
-
-EXPAND.C:  Arguments are processed in three passes.  The first
-(performed by the routine argstr) performs variable and command
-substitution.  The second (ifsbreakup) performs word splitting
-and the third (expandmeta) performs file name generation.  If the
-"/u" directory is simulated, then when "/u/username" is replaced
-by the user's home directory, the flag "didudir" is set.  This
-tells the cd command that it should print out the directory name,
-just as it would if the "/u" directory were implemented using
-symbolic links.
-
-VAR.C:  Variables are stored in a hash table.  Probably we should
-switch to extensible hashing.  The variable name is stored in the
-same string as the value (using the format "name=value") so that
-no string copying is needed to create the environment of a com-
-mand.  Variables which the shell references internally are preal-
-located so that the shell can reference the values of these vari-
-ables without doing a lookup.
-
-When a program is run, the code in eval.c sticks any environment
-variables which precede the command (as in "PATH=xxx command") in
-the variable table as the simplest way to strip duplicates, and
-then calls "environment" to get the value of the environment.
-There are two consequences of this.  First, if an assignment to
-PATH precedes the command, the value of PATH before the assign-
-ment must be remembered and passed to shellexec.  Second, if the
-program turns out to be a shell procedure, the strings from the
-environment variables which preceded the command must be pulled
-out of the table and replaced with strings obtained from malloc,
-since the former will automatically be freed when the stack (see
-the entry on memalloc.c) is emptied.
-
-BUILTIN COMMANDS:  The procedures for handling these are scat-
-tered throughout the code, depending on which location appears
-most appropriate.  They can be recognized because their names al-
-ways end in "cmd".  The mapping from names to procedures is
-specified in the file builtins, which is processed by the mkbuil-
-tins command.
-
-A builtin command is invoked with argc and argv set up like a
-normal program.  A builtin command is allowed to overwrite its
-arguments.  Builtin routines can call nextopt to do option pars-
-ing.  This is kind of like getopt, but you don't pass argc and
-argv to it.  Builtin routines can also call error.  This routine
-normally terminates the shell (or returns to the main command
-loop if the shell is interactive), but when called from a builtin
-command it causes the builtin command to terminate with an exit
-status of 2.
-
-The directory bltins contains commands which can be compiled in-
-dependently but can also be built into the shell for efficiency
-reasons.  The makefile in this directory compiles these programs
-in the normal fashion (so that they can be run regardless of
-whether the invoker is ash), but also creates a library named
-bltinlib.a which can be linked with ash.  The header file bltin.h
-takes care of most of the differences between the ash and the
-stand-alone environment.  The user should call the main routine
-"main", and #define main to be the name of the routine to use
-when the program is linked into ash.  This #define should appear
-before bltin.h is included; bltin.h will #undef main if the pro-
-gram is to be compiled stand-alone.
-
-CD.C:  This file defines the cd and pwd builtins.  The pwd com-
-mand runs /bin/pwd the first time it is invoked (unless the user
-has already done a cd to an absolute pathname), but then
-remembers the current directory and updates it when the cd com-
-mand is run, so subsequent pwd commands run very fast.  The main
-complication in the cd command is in the docd command, which
-resolves symbolic links into actual names and informs the user
-where the user ended up if he crossed a symbolic link.
-
-SIGNALS:  Trap.c implements the trap command.  The routine set-
-signal figures out what action should be taken when a signal is
-received and invokes the signal system call to set the signal ac-
-tion appropriately.  When a signal that a user has set a trap for
-is caught, the routine "onsig" sets a flag.  The routine dotrap
-is called at appropriate points to actually handle the signal.
-When an interrupt is caught and no trap has been set for that
-signal, the routine "onint" in error.c is called.
-
-OUTPUT:  Ash uses it's own output routines.  There are three out-
-put structures allocated.  "Output" represents the standard out-
-put, "errout" the standard error, and "memout" contains output
-which is to be stored in memory.  This last is used when a buil-
-tin command appears in backquotes, to allow its output to be col-
-lected without doing any I/O through the UNIX operating system.
-The variables out1 and out2 normally point to output and errout,
-respectively, but they are set to point to memout when appropri-
-ate inside backquotes.
-
-INPUT:  The basic input routine is pgetc, which reads from the
-current input file.  There is a stack of input files; the current
-input file is the top file on this stack.  The code allows the
-input to come from a string rather than a file.  (This is for the
--c option and the "." and eval builtin commands.)  The global
-variable plinno is saved and restored when files are pushed and
-popped from the stack.  The parser routines store the number of
-the current line in this variable.
-
-DEBUGGING:  If DEBUG is defined in shell.h, then the shell will
-write debugging information to the file $HOME/trace.  Most of
-this is done using the TRACE macro, which takes a set of printf
-arguments inside two sets of parenthesis.  Example:
-"TRACE(("n=%d0, n))".  The double parenthesis are necessary be-
-cause the preprocessor can't handle functions with a variable
-number of arguments.  Defining DEBUG also causes the shell to
-generate a core dump if it is sent a quit signal.  The tracing
-code is in show.c.
diff --git a/sh/ThirdPartyProject.prop b/sh/ThirdPartyProject.prop
deleted file mode 100644
index eb9167e..0000000
--- a/sh/ThirdPartyProject.prop
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright 2010 Google Inc. All Rights Reserved.
-#Fri Jul 16 10:03:08 PDT 2010
-currentVersion=Unknown
-version=1.17
-isNative=true
-name=ash
-keywords=ash
-onDevice=true
-homepage=http\://www.in-ulm.de/~mascheck/various/ash/
diff --git a/sh/alias.c b/sh/alias.c
deleted file mode 100644
index 59a3dc1..0000000
--- a/sh/alias.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*	$NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $	*/
-
-/*-
- * Copyright (c) 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)alias.c	8.3 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: alias.c,v 1.12 2003/08/07 09:05:29 agc Exp $");
-#endif
-#endif /* not lint */
-
-#include <stdlib.h>
-#include "shell.h"
-#include "input.h"
-#include "output.h"
-#include "error.h"
-#include "memalloc.h"
-#include "mystring.h"
-#include "alias.h"
-#include "options.h"	/* XXX for argptr (should remove?) */
-#include "var.h"
-
-#define ATABSIZE 39
-
-struct alias *atab[ATABSIZE];
-
-STATIC void setalias(char *, char *);
-STATIC int unalias(char *);
-STATIC struct alias **hashalias(char *);
-
-STATIC
-void
-setalias(char *name, char *val)
-{
-	struct alias *ap, **app;
-
-	app = hashalias(name);
-	for (ap = *app; ap; ap = ap->next) {
-		if (equal(name, ap->name)) {
-			INTOFF;
-			ckfree(ap->val);
-			ap->val	= savestr(val);
-			INTON;
-			return;
-		}
-	}
-	/* not found */
-	INTOFF;
-	ap = ckmalloc(sizeof (struct alias));
-	ap->name = savestr(name);
-	/*
-	 * XXX - HACK: in order that the parser will not finish reading the
-	 * alias value off the input before processing the next alias, we
-	 * dummy up an extra space at the end of the alias.  This is a crock
-	 * and should be re-thought.  The idea (if you feel inclined to help)
-	 * is to avoid alias recursions.  The mechanism used is: when
-	 * expanding an alias, the value of the alias is pushed back on the
-	 * input as a string and a pointer to the alias is stored with the
-	 * string.  The alias is marked as being in use.  When the input
-	 * routine finishes reading the string, it markes the alias not
-	 * in use.  The problem is synchronization with the parser.  Since
-	 * it reads ahead, the alias is marked not in use before the
-	 * resulting token(s) is next checked for further alias sub.  The
-	 * H A C K is that we add a little fluff after the alias value
-	 * so that the string will not be exhausted.  This is a good
-	 * idea ------- ***NOT***
-	 */
-#ifdef notyet
-	ap->val = savestr(val);
-#else /* hack */
-	{
-	int len = strlen(val);
-	ap->val = ckmalloc(len + 2);
-	memcpy(ap->val, val, len);
-	ap->val[len] = ' ';	/* fluff */
-	ap->val[len+1] = '\0';
-	}
-#endif
-	ap->next = *app;
-	*app = ap;
-	INTON;
-}
-
-STATIC int
-unalias(char *name)
-{
-	struct alias *ap, **app;
-
-	app = hashalias(name);
-
-	for (ap = *app; ap; app = &(ap->next), ap = ap->next) {
-		if (equal(name, ap->name)) {
-			/*
-			 * if the alias is currently in use (i.e. its
-			 * buffer is being used by the input routine) we
-			 * just null out the name instead of freeing it.
-			 * We could clear it out later, but this situation
-			 * is so rare that it hardly seems worth it.
-			 */
-			if (ap->flag & ALIASINUSE)
-				*ap->name = '\0';
-			else {
-				INTOFF;
-				*app = ap->next;
-				ckfree(ap->name);
-				ckfree(ap->val);
-				ckfree(ap);
-				INTON;
-			}
-			return (0);
-		}
-	}
-
-	return (1);
-}
-
-#ifdef mkinit
-MKINIT void rmaliases(void);
-
-SHELLPROC {
-	rmaliases();
-}
-#endif
-
-void
-rmaliases(void)
-{
-	struct alias *ap, *tmp;
-	int i;
-
-	INTOFF;
-	for (i = 0; i < ATABSIZE; i++) {
-		ap = atab[i];
-		atab[i] = NULL;
-		while (ap) {
-			ckfree(ap->name);
-			ckfree(ap->val);
-			tmp = ap;
-			ap = ap->next;
-			ckfree(tmp);
-		}
-	}
-	INTON;
-}
-
-struct alias *
-lookupalias(char *name, int check)
-{
-	struct alias *ap = *hashalias(name);
-
-	for (; ap; ap = ap->next) {
-		if (equal(name, ap->name)) {
-			if (check && (ap->flag & ALIASINUSE))
-				return (NULL);
-			return (ap);
-		}
-	}
-
-	return (NULL);
-}
-
-char *
-get_alias_text(char *name)
-{
-	struct alias *ap;
-
-	ap = lookupalias(name, 0);
-	if (ap == NULL)
-		return NULL;
-	return ap->val;
-}
-
-/*
- * TODO - sort output
- */
-int
-aliascmd(int argc, char **argv)
-{
-	char *n, *v;
-	int ret = 0;
-	struct alias *ap;
-
-	if (argc == 1) {
-		int i;
-
-		for (i = 0; i < ATABSIZE; i++)
-			for (ap = atab[i]; ap; ap = ap->next) {
-				if (*ap->name != '\0') {
-					out1fmt("alias %s=", ap->name);
-					print_quoted(ap->val);
-					out1c('\n');
-				}
-			}
-		return (0);
-	}
-	while ((n = *++argv) != NULL) {
-		if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
-			if ((ap = lookupalias(n, 0)) == NULL) {
-				outfmt(out2, "alias: %s not found\n", n);
-				ret = 1;
-			} else {
-				out1fmt("alias %s=", n);
-				print_quoted(ap->val);
-				out1c('\n');
-			}
-		} else {
-			*v++ = '\0';
-			setalias(n, v);
-		}
-	}
-
-	return (ret);
-}
-
-int
-unaliascmd(int argc, char **argv)
-{
-	int i;
-
-	while ((i = nextopt("a")) != '\0') {
-		if (i == 'a') {
-			rmaliases();
-			return (0);
-		}
-	}
-	for (i = 0; *argptr; argptr++)
-		i = unalias(*argptr);
-
-	return (i);
-}
-
-STATIC struct alias **
-hashalias(char *p)
-{
-	unsigned int hashval;
-
-	hashval = *p << 4;
-	while (*p)
-		hashval+= *p++;
-	return &atab[hashval % ATABSIZE];
-}
diff --git a/sh/alias.h b/sh/alias.h
deleted file mode 100644
index 7ce25f4..0000000
--- a/sh/alias.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*	$NetBSD: alias.h,v 1.6 2003/08/07 09:05:29 agc Exp $	*/
-
-/*-
- * Copyright (c) 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)alias.h	8.2 (Berkeley) 5/4/95
- */
-
-#define ALIASINUSE	1
-
-struct alias {
-	struct alias *next;
-	char *name;
-	char *val;
-	int flag;
-};
-
-struct alias *lookupalias(char *, int);
-char *get_alias_text(char *);
-int aliascmd(int, char **);
-int unaliascmd(int, char **);
-void rmaliases(void);
diff --git a/sh/arith.c b/sh/arith.c
deleted file mode 100644
index f8f92a9..0000000
--- a/sh/arith.c
+++ /dev/null
@@ -1,1587 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875d.  */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, when this file is copied by Bison into a
-   Bison output file, you may use that output file without restriction.
-   This special exception was added by the Free Software Foundation
-   in version 1.24 of Bison.  */
-
-/* Written by Richard Stallman by simplifying the original so called
-   ``semantic'' parser.  */
-
-/* All symbols defined below should begin with yy or YY, to avoid
-   infringing on user name space.  This should be done even for local
-   variables, as they might otherwise be expanded by user macros.
-   There are some unavoidable exceptions within include files to
-   define necessary library symbols; they are noted "INFRINGES ON
-   USER NAME SPACE" below.  */
-
-/* Identify Bison output.  */
-#define YYBISON 1
-
-/* Skeleton name.  */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers.  */
-#define YYPURE 0
-
-/* Using locations.  */
-#define YYLSP_NEEDED 0
-
-
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     ARITH_NUM = 258,
-     ARITH_LPAREN = 259,
-     ARITH_RPAREN = 260,
-     ARITH_OR = 261,
-     ARITH_AND = 262,
-     ARITH_BOR = 263,
-     ARITH_BXOR = 264,
-     ARITH_BAND = 265,
-     ARITH_NE = 266,
-     ARITH_EQ = 267,
-     ARITH_LE = 268,
-     ARITH_GE = 269,
-     ARITH_GT = 270,
-     ARITH_LT = 271,
-     ARITH_RSHIFT = 272,
-     ARITH_LSHIFT = 273,
-     ARITH_SUB = 274,
-     ARITH_ADD = 275,
-     ARITH_REM = 276,
-     ARITH_DIV = 277,
-     ARITH_MUL = 278,
-     ARITH_BNOT = 279,
-     ARITH_NOT = 280,
-     ARITH_UNARYPLUS = 281,
-     ARITH_UNARYMINUS = 282
-   };
-#endif
-#define ARITH_NUM 258
-#define ARITH_LPAREN 259
-#define ARITH_RPAREN 260
-#define ARITH_OR 261
-#define ARITH_AND 262
-#define ARITH_BOR 263
-#define ARITH_BXOR 264
-#define ARITH_BAND 265
-#define ARITH_NE 266
-#define ARITH_EQ 267
-#define ARITH_LE 268
-#define ARITH_GE 269
-#define ARITH_GT 270
-#define ARITH_LT 271
-#define ARITH_RSHIFT 272
-#define ARITH_LSHIFT 273
-#define ARITH_SUB 274
-#define ARITH_ADD 275
-#define ARITH_REM 276
-#define ARITH_DIV 277
-#define ARITH_MUL 278
-#define ARITH_BNOT 279
-#define ARITH_NOT 280
-#define ARITH_UNARYPLUS 281
-#define ARITH_UNARYMINUS 282
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 1 "arith.y"
-
-/*	$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $	*/
-
-/*-
- * Copyright (c) 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)arith.y	8.3 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $");
-#endif
-#endif /* not lint */
-
-#include <stdlib.h>
-#include "expand.h"
-#include "shell.h"
-#include "error.h"
-#include "output.h"
-#include "memalloc.h"
-
-const char *arith_buf, *arith_startbuf;
-
-void yyerror(const char *);
-#ifdef TESTARITH
-int main(int , char *[]);
-int error(char *);
-#endif
-
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations.  */
-
-
-/* Line 214 of yacc.c.  */
-#line 202 "arith.c"
-
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
-
-# ifndef YYFREE
-#  define YYFREE free
-# endif
-# ifndef YYMALLOC
-#  define YYMALLOC malloc
-# endif
-
-/* The parser invokes alloca or malloc; define the necessary symbols.  */
-
-# ifdef YYSTACK_USE_ALLOCA
-#  if YYSTACK_USE_ALLOCA
-#   define YYSTACK_ALLOC alloca
-#  endif
-# else
-#  if defined (alloca) || defined (_ALLOCA_H)
-#   define YYSTACK_ALLOC alloca
-#  else
-#   ifdef __GNUC__
-#    define YYSTACK_ALLOC __builtin_alloca
-#   endif
-#  endif
-# endif
-
-# ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning. */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# else
-#  if defined (__STDC__) || defined (__cplusplus)
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   define YYSIZE_T size_t
-#  endif
-#  define YYSTACK_ALLOC YYMALLOC
-#  define YYSTACK_FREE YYFREE
-# endif
-#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
-
-
-#if (! defined (yyoverflow) \
-     && (! defined (__cplusplus) \
-	 || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member.  */
-union yyalloc
-{
-  short int yyss;
-  YYSTYPE yyvs;
-  };
-
-/* The size of the maximum gap between one aligned stack and the next.  */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
-   N elements.  */
-# define YYSTACK_BYTES(N) \
-     ((N) * (sizeof (short int) + sizeof (YYSTYPE))			\
-      + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO.  The source and destination do
-   not overlap.  */
-# ifndef YYCOPY
-#  if defined (__GNUC__) && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-#  else
-#   define YYCOPY(To, From, Count)		\
-      do					\
-	{					\
-	  register YYSIZE_T yyi;		\
-	  for (yyi = 0; yyi < (Count); yyi++)	\
-	    (To)[yyi] = (From)[yyi];		\
-	}					\
-      while (0)
-#  endif
-# endif
-
-/* Relocate STACK from its old location to the new one.  The
-   local variables YYSIZE and YYSTACKSIZE give the old and new number of
-   elements in the stack, and YYPTR gives the new location of the
-   stack.  Advance YYPTR to a properly aligned location for the next
-   stack.  */
-# define YYSTACK_RELOCATE(Stack)					\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack, Stack, yysize);				\
-	Stack = &yyptr->Stack;						\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (0)
-
-#endif
-
-#if defined (__STDC__) || defined (__cplusplus)
-   typedef signed char yysigned_char;
-#else
-   typedef short int yysigned_char;
-#endif
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL  14
-/* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   170
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  28
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS  3
-/* YYNRULES -- Number of rules. */
-#define YYNRULES  26
-/* YYNRULES -- Number of states. */
-#define YYNSTATES  52
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYUNDEFTOK  2
-#define YYMAXUTOK   282
-
-#define YYTRANSLATE(YYX) 						\
-  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
-static const unsigned char yytranslate[] =
-{
-       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     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
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const unsigned char yyprhs[] =
-{
-       0,     0,     3,     5,     9,    13,    17,    21,    25,    29,
-      33,    37,    41,    45,    49,    53,    57,    61,    65,    69,
-      73,    77,    81,    84,    87,    90,    93
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yysigned_char yyrhs[] =
-{
-      29,     0,    -1,    30,    -1,     4,    30,     5,    -1,    30,
-       6,    30,    -1,    30,     7,    30,    -1,    30,     8,    30,
-      -1,    30,     9,    30,    -1,    30,    10,    30,    -1,    30,
-      12,    30,    -1,    30,    15,    30,    -1,    30,    14,    30,
-      -1,    30,    16,    30,    -1,    30,    13,    30,    -1,    30,
-      11,    30,    -1,    30,    18,    30,    -1,    30,    17,    30,
-      -1,    30,    20,    30,    -1,    30,    19,    30,    -1,    30,
-      23,    30,    -1,    30,    22,    30,    -1,    30,    21,    30,
-      -1,    25,    30,    -1,    24,    30,    -1,    19,    30,    -1,
-      20,    30,    -1,     3,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
-static const unsigned char yyrline[] =
-{
-       0,    76,    76,    82,    83,    84,    85,    86,    87,    88,
-      89,    90,    91,    92,    93,    94,    95,    96,    97,    98,
-      99,   104,   109,   110,   111,   112,   113
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
-   First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
-  "$end", "error", "$undefined", "ARITH_NUM", "ARITH_LPAREN",
-  "ARITH_RPAREN", "ARITH_OR", "ARITH_AND", "ARITH_BOR", "ARITH_BXOR",
-  "ARITH_BAND", "ARITH_NE", "ARITH_EQ", "ARITH_LE", "ARITH_GE", "ARITH_GT",
-  "ARITH_LT", "ARITH_RSHIFT", "ARITH_LSHIFT", "ARITH_SUB", "ARITH_ADD",
-  "ARITH_REM", "ARITH_DIV", "ARITH_MUL", "ARITH_BNOT", "ARITH_NOT",
-  "ARITH_UNARYPLUS", "ARITH_UNARYMINUS", "$accept", "exp", "expr", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
-static const unsigned short int yytoknum[] =
-{
-       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const unsigned char yyr1[] =
-{
-       0,    28,    29,    30,    30,    30,    30,    30,    30,    30,
-      30,    30,    30,    30,    30,    30,    30,    30,    30,    30,
-      30,    30,    30,    30,    30,    30,    30
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const unsigned char yyr2[] =
-{
-       0,     2,     1,     3,     3,     3,     3,     3,     3,     3,
-       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
-       3,     3,     2,     2,     2,     2,     1
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const unsigned char yydefact[] =
-{
-       0,    26,     0,     0,     0,     0,     0,     0,     2,     0,
-      24,    25,    23,    22,     1,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     3,     4,     5,     6,     7,     8,    14,
-       9,    13,    11,    10,    12,    16,    15,    18,    17,    21,
-      20,    19
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yysigned_char yydefgoto[] =
-{
-      -1,     7,     8
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -13
-static const short int yypact[] =
-{
-      28,   -13,    28,    28,    28,    28,    28,    12,    67,    49,
-     -13,   -13,   -13,   -13,   -13,    28,    28,    28,    28,    28,
-      28,    28,    28,    28,    28,    28,    28,    28,    28,    28,
-      28,    28,    28,   -13,    84,   100,   115,    23,   128,   139,
-     139,   -12,   -12,   -12,   -12,   144,   144,   147,   147,   -13,
-     -13,   -13
-};
-
-/* YYPGOTO[NTERM-NUM].  */
-static const yysigned_char yypgoto[] =
-{
-     -13,   -13,    -2
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If zero, do what YYDEFACT says.
-   If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -1
-static const unsigned char yytable[] =
-{
-       9,    10,    11,    12,    13,    26,    27,    28,    29,    30,
-      31,    32,    14,    34,    35,    36,    37,    38,    39,    40,
-      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,     1,     2,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,     3,     4,     0,
-       0,     0,     5,     6,    33,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    28,    29,    30,    31,    32,    30,    31,
-      32
-};
-
-static const yysigned_char yycheck[] =
-{
-       2,     3,     4,     5,     6,    17,    18,    19,    20,    21,
-      22,    23,     0,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,     3,     4,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    19,    20,    -1,
-      -1,    -1,    24,    25,     5,     6,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,     6,     7,     8,     9,    10,    11,    12,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,     7,     8,     9,    10,    11,    12,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    19,    20,    21,    22,    23,    21,    22,
-      23
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
-static const unsigned char yystos[] =
-{
-       0,     3,     4,    19,    20,    24,    25,    29,    30,    30,
-      30,    30,    30,    30,     0,     6,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,     5,    30,    30,    30,    30,    30,    30,
-      30,    30,    30,    30,    30,    30,    30,    30,    30,    30,
-      30,    30
-};
-
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
-
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
-
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  */
-
-#define YYFAIL		goto yyerrlab
-
-#define YYRECOVERING()  (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value)					\
-do								\
-  if (yychar == YYEMPTY && yylen == 1)				\
-    {								\
-      yychar = (Token);						\
-      yylval = (Value);						\
-      yytoken = YYTRANSLATE (yychar);				\
-      YYPOPSTACK;						\
-      goto yybackup;						\
-    }								\
-  else								\
-    { 								\
-      yyerror ("syntax error: cannot back up");\
-      YYERROR;							\
-    }								\
-while (0)
-
-#define YYTERROR	1
-#define YYERRCODE	256
-
-/* YYLLOC_DEFAULT -- Compute the default location (before the actions
-   are run).  */
-
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)		\
-   ((Current).first_line   = (Rhs)[1].first_line,	\
-    (Current).first_column = (Rhs)[1].first_column,	\
-    (Current).last_line    = (Rhs)[N].last_line,	\
-    (Current).last_column  = (Rhs)[N].last_column)
-#endif
-
-/* YYLEX -- calling `yylex' with the right arguments.  */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested.  */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (0)
-
-# define YYDSYMPRINT(Args)			\
-do {						\
-  if (yydebug)					\
-    yysymprint Args;				\
-} while (0)
-
-# define YYDSYMPRINTF(Title, Token, Value, Location)		\
-do {								\
-  if (yydebug)							\
-    {								\
-      YYFPRINTF (stderr, "%s ", Title);				\
-      yysymprint (stderr, 					\
-                  Token, Value);	\
-      YYFPRINTF (stderr, "\n");					\
-    }								\
-} while (0)
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included).                                                   |
-`------------------------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_stack_print (short int *bottom, short int *top)
-#else
-static void
-yy_stack_print (bottom, top)
-    short int *bottom;
-    short int *top;
-#endif
-{
-  YYFPRINTF (stderr, "Stack now");
-  for (/* Nothing. */; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
-  YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (0)
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced.  |
-`------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_reduce_print (int yyrule)
-#else
-static void
-yy_reduce_print (yyrule)
-    int yyrule;
-#endif
-{
-  int yyi;
-  unsigned int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
-             yyrule - 1, yylno);
-  /* Print the symbols being reduced, and their result.  */
-  for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
-    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
-  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
-}
-
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (Rule);		\
-} while (0)
-
-/* Nonzero means print parse trace.  It is left uninitialized so that
-   multiple parsers can coexist.  */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YYDSYMPRINT(Args)
-# define YYDSYMPRINTF(Title, Token, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
-   if the built-in stack extension method is used).
-
-   Do not make this value too large; the results are undefined if
-   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
-   evaluated with infinite-precision integer arithmetic.  */
-
-#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
-# undef YYMAXDEPTH
-#endif
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-#  if defined (__GLIBC__) && defined (_STRING_H)
-#   define yystrlen strlen
-#  else
-/* Return the length of YYSTR.  */
-static YYSIZE_T
-#   if defined (__STDC__) || defined (__cplusplus)
-yystrlen (const char *yystr)
-#   else
-yystrlen (yystr)
-     const char *yystr;
-#   endif
-{
-  register const char *yys = yystr;
-
-  while (*yys++ != '\0')
-    continue;
-
-  return yys - yystr - 1;
-}
-#  endif
-# endif
-
-# ifndef yystpcpy
-#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
-#   define yystpcpy stpcpy
-#  else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
-   YYDEST.  */
-static char *
-#   if defined (__STDC__) || defined (__cplusplus)
-yystpcpy (char *yydest, const char *yysrc)
-#   else
-yystpcpy (yydest, yysrc)
-     char *yydest;
-     const char *yysrc;
-#   endif
-{
-  register char *yyd = yydest;
-  register const char *yys = yysrc;
-
-  while ((*yyd++ = *yys++) != '\0')
-    continue;
-
-  return yyd - 1;
-}
-#  endif
-# endif
-
-#endif /* !YYERROR_VERBOSE */
-
-
-
-#if YYDEBUG
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yysymprint (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  /* Pacify ``unused variable'' warnings.  */
-  (void) yyvaluep;
-
-  if (yytype < YYNTOKENS)
-    {
-      YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
-      YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
-    }
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
-  switch (yytype)
-    {
-      default:
-        break;
-    }
-  YYFPRINTF (yyoutput, ")");
-}
-
-#endif /* ! YYDEBUG */
-/*-----------------------------------------------.
-| Release the memory associated to this symbol.  |
-`-----------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yytype, yyvaluep)
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
-{
-  /* Pacify ``unused variable'' warnings.  */
-  (void) yyvaluep;
-
-  switch (yytype)
-    {
-
-      default:
-        break;
-    }
-}
-
-
-/* Prevent warnings from -Wmissing-prototypes.  */
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM);
-# else
-int yyparse ();
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-/* The lookahead symbol.  */
-int yychar;
-
-/* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far.  */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse.  |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM)
-# else
-int yyparse (YYPARSE_PARAM)
-  void *YYPARSE_PARAM;
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-  
-  register int yystate;
-  register int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Lookahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
-
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
-
-  /* The state stack.  */
-  short int yyssa[YYINITDEPTH];
-  short int *yyss = yyssa;
-  register short int *yyssp;
-
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  register YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK   (yyvsp--, yyssp--)
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
-
-  /* The variables used to return semantic value and location from the
-     action routines.  */
-  YYSTYPE yyval;
-
-
-  /* When reducing, the number of symbols on the RHS of the reduced
-     rule.  */
-  int yylen;
-
-  YYDPRINTF ((stderr, "Starting parse\n"));
-
-  yystate = 0;
-  yyerrstatus = 0;
-  yynerrs = 0;
-  yychar = YYEMPTY;		/* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-
-  yyssp = yyss;
-  yyvsp = yyvs;
-
-
-  goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate.  |
-`------------------------------------------------------------*/
- yynewstate:
-  /* In all cases, when you get here, the value and location stacks
-     have just been pushed. so pushing a state here evens the stacks.
-     */
-  yyssp++;
-
- yysetstate:
-  *yyssp = yystate;
-
-  if (yyss + yystacksize - 1 <= yyssp)
-    {
-      /* Get the current used size of the three stacks, in elements.  */
-      YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
-      {
-	/* Give user a chance to reallocate the stack. Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	short int *yyss1 = yyss;
-
-
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow ("parser stack overflow",
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-
-		    &yystacksize);
-
-	yyss = yyss1;
-	yyvs = yyvs1;
-      }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
-      goto yyoverflowlab;
-# else
-      /* Extend the stack our own way.  */
-      if (YYMAXDEPTH <= yystacksize)
-	goto yyoverflowlab;
-      yystacksize *= 2;
-      if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
-
-      {
-	short int *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyoverflowlab;
-	YYSTACK_RELOCATE (yyss);
-	YYSTACK_RELOCATE (yyvs);
-
-#  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
-      }
-# endif
-#endif /* no yyoverflow */
-
-      yyssp = yyss + yysize - 1;
-      yyvsp = yyvs + yysize - 1;
-
-
-      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
-
-      if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
-    }
-
-  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
-  goto yybackup;
-
-/*-----------.
-| yybackup.  |
-`-----------*/
-yybackup:
-
-/* Do appropriate processing given the current state.  */
-/* Read a lookahead token if we need one and don't already have one.  */
-/* yyresume: */
-
-  /* First try to decide what to do without reference to lookahead token.  */
-
-  yyn = yypact[yystate];
-  if (yyn == YYPACT_NINF)
-    goto yydefault;
-
-  /* Not known => get a lookahead token if don't already have one.  */
-
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
-  if (yychar == YYEMPTY)
-    {
-      YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
-    }
-
-  if (yychar <= YYEOF)
-    {
-      yychar = yytoken = YYEOF;
-      YYDPRINTF ((stderr, "Now at end of input.\n"));
-    }
-  else
-    {
-      yytoken = YYTRANSLATE (yychar);
-      YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc);
-    }
-
-  /* If the proper action on seeing token YYTOKEN is to reduce or to
-     detect an error, take that action.  */
-  yyn += yytoken;
-  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
-    goto yydefault;
-  yyn = yytable[yyn];
-  if (yyn <= 0)
-    {
-      if (yyn == 0 || yyn == YYTABLE_NINF)
-	goto yyerrlab;
-      yyn = -yyn;
-      goto yyreduce;
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  /* Shift the lookahead token.  */
-  YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
-
-  /* Discard the token being shifted unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
-
-  *++yyvsp = yylval;
-
-
-  /* Count tokens shifted since error; after three, turn off error
-     status.  */
-  if (yyerrstatus)
-    yyerrstatus--;
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state.  |
-`-----------------------------------------------------------*/
-yydefault:
-  yyn = yydefact[yystate];
-  if (yyn == 0)
-    goto yyerrlab;
-  goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction.  |
-`-----------------------------*/
-yyreduce:
-  /* yyn is the number of a rule to reduce with.  */
-  yylen = yyr2[yyn];
-
-  /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
-
-     Otherwise, the following line sets YYVAL to garbage.
-     This behavior is undocumented and Bison
-     users should not rely upon it.  Assigning to YYVAL
-     unconditionally makes the parser a bit smaller, and it avoids a
-     GCC warning that YYVAL may be used uninitialized.  */
-  yyval = yyvsp[1-yylen];
-
-
-  YY_REDUCE_PRINT (yyn);
-  switch (yyn)
-    {
-        case 2:
-#line 76 "arith.y"
-    {
-			return (yyvsp[0]);
-		;}
-    break;
-
-  case 3:
-#line 82 "arith.y"
-    { yyval = yyvsp[-1]; ;}
-    break;
-
-  case 4:
-#line 83 "arith.y"
-    { yyval = yyvsp[-2] ? yyvsp[-2] : yyvsp[0] ? yyvsp[0] : 0; ;}
-    break;
-
-  case 5:
-#line 84 "arith.y"
-    { yyval = yyvsp[-2] ? ( yyvsp[0] ? yyvsp[0] : 0 ) : 0; ;}
-    break;
-
-  case 6:
-#line 85 "arith.y"
-    { yyval = yyvsp[-2] | yyvsp[0]; ;}
-    break;
-
-  case 7:
-#line 86 "arith.y"
-    { yyval = yyvsp[-2] ^ yyvsp[0]; ;}
-    break;
-
-  case 8:
-#line 87 "arith.y"
-    { yyval = yyvsp[-2] & yyvsp[0]; ;}
-    break;
-
-  case 9:
-#line 88 "arith.y"
-    { yyval = yyvsp[-2] == yyvsp[0]; ;}
-    break;
-
-  case 10:
-#line 89 "arith.y"
-    { yyval = yyvsp[-2] > yyvsp[0]; ;}
-    break;
-
-  case 11:
-#line 90 "arith.y"
-    { yyval = yyvsp[-2] >= yyvsp[0]; ;}
-    break;
-
-  case 12:
-#line 91 "arith.y"
-    { yyval = yyvsp[-2] < yyvsp[0]; ;}
-    break;
-
-  case 13:
-#line 92 "arith.y"
-    { yyval = yyvsp[-2] <= yyvsp[0]; ;}
-    break;
-
-  case 14:
-#line 93 "arith.y"
-    { yyval = yyvsp[-2] != yyvsp[0]; ;}
-    break;
-
-  case 15:
-#line 94 "arith.y"
-    { yyval = yyvsp[-2] << yyvsp[0]; ;}
-    break;
-
-  case 16:
-#line 95 "arith.y"
-    { yyval = yyvsp[-2] >> yyvsp[0]; ;}
-    break;
-
-  case 17:
-#line 96 "arith.y"
-    { yyval = yyvsp[-2] + yyvsp[0]; ;}
-    break;
-
-  case 18:
-#line 97 "arith.y"
-    { yyval = yyvsp[-2] - yyvsp[0]; ;}
-    break;
-
-  case 19:
-#line 98 "arith.y"
-    { yyval = yyvsp[-2] * yyvsp[0]; ;}
-    break;
-
-  case 20:
-#line 99 "arith.y"
-    {
-			if (yyvsp[0] == 0)
-				yyerror("division by zero");
-			yyval = yyvsp[-2] / yyvsp[0];
-			;}
-    break;
-
-  case 21:
-#line 104 "arith.y"
-    {
-			if (yyvsp[0] == 0)
-				yyerror("division by zero");
-			yyval = yyvsp[-2] % yyvsp[0];
-			;}
-    break;
-
-  case 22:
-#line 109 "arith.y"
-    { yyval = !(yyvsp[0]); ;}
-    break;
-
-  case 23:
-#line 110 "arith.y"
-    { yyval = ~(yyvsp[0]); ;}
-    break;
-
-  case 24:
-#line 111 "arith.y"
-    { yyval = -(yyvsp[0]); ;}
-    break;
-
-  case 25:
-#line 112 "arith.y"
-    { yyval = yyvsp[0]; ;}
-    break;
-
-
-    }
-
-/* Line 1010 of yacc.c.  */
-#line 1276 "arith.c"
-
-  yyvsp -= yylen;
-  yyssp -= yylen;
-
-
-  YY_STACK_PRINT (yyss, yyssp);
-
-  *++yyvsp = yyval;
-
-
-  /* Now `shift' the result of the reduction.  Determine what state
-     that goes to, based on the state we popped back to and the rule
-     number reduced by.  */
-
-  yyn = yyr1[yyn];
-
-  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
-  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
-    yystate = yytable[yystate];
-  else
-    yystate = yydefgoto[yyn - YYNTOKENS];
-
-  goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
-  /* If not already recovering from an error, report this error.  */
-  if (!yyerrstatus)
-    {
-      ++yynerrs;
-#if YYERROR_VERBOSE
-      yyn = yypact[yystate];
-
-      if (YYPACT_NINF < yyn && yyn < YYLAST)
-	{
-	  YYSIZE_T yysize = 0;
-	  int yytype = YYTRANSLATE (yychar);
-	  const char* yyprefix;
-	  char *yymsg;
-	  int yyx;
-
-	  /* Start YYX at -YYN if negative to avoid negative indexes in
-	     YYCHECK.  */
-	  int yyxbegin = yyn < 0 ? -yyn : 0;
-
-	  /* Stay within bounds of both yycheck and yytname.  */
-	  int yychecklim = YYLAST - yyn;
-	  int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-	  int yycount = 0;
-
-	  yyprefix = ", expecting ";
-	  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-	      {
-		yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
-		yycount += 1;
-		if (yycount == 5)
-		  {
-		    yysize = 0;
-		    break;
-		  }
-	      }
-	  yysize += (sizeof ("syntax error, unexpected ")
-		     + yystrlen (yytname[yytype]));
-	  yymsg = (char *) YYSTACK_ALLOC (yysize);
-	  if (yymsg != 0)
-	    {
-	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
-	      yyp = yystpcpy (yyp, yytname[yytype]);
-
-	      if (yycount < 5)
-		{
-		  yyprefix = ", expecting ";
-		  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-		    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-		      {
-			yyp = yystpcpy (yyp, yyprefix);
-			yyp = yystpcpy (yyp, yytname[yyx]);
-			yyprefix = " or ";
-		      }
-		}
-	      yyerror (yymsg);
-	      YYSTACK_FREE (yymsg);
-	    }
-	  else
-	    yyerror ("syntax error; also virtual memory exhausted");
-	}
-      else
-#endif /* YYERROR_VERBOSE */
-	yyerror ("syntax error");
-    }
-
-
-
-  if (yyerrstatus == 3)
-    {
-      /* If just tried and failed to reuse lookahead token after an
-	 error, discard it.  */
-
-      if (yychar <= YYEOF)
-        {
-          /* If at end of input, pop the error token,
-	     then the rest of the stack, then return failure.  */
-	  if (yychar == YYEOF)
-	     for (;;)
-	       {
-		 YYPOPSTACK;
-		 if (yyssp == yyss)
-		   YYABORT;
-		 YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
-		 yydestruct (yystos[*yyssp], yyvsp);
-	       }
-        }
-      else
-	{
-	  YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
-	  yydestruct (yytoken, &yylval);
-	  yychar = YYEMPTY;
-
-	}
-    }
-
-  /* Else will try to reuse lookahead token after shifting the error
-     token.  */
-  goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR.  |
-`---------------------------------------------------*/
-yyerrorlab:
-
-#ifdef __GNUC__
-  /* Pacify GCC when the user code never invokes YYERROR and the label
-     yyerrorlab therefore never appears in user code.  */
-  if (0)
-     goto yyerrorlab;
-#endif
-
-  yyvsp -= yylen;
-  yyssp -= yylen;
-  yystate = *yyssp;
-  goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR.  |
-`-------------------------------------------------------------*/
-yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
-
-  for (;;)
-    {
-      yyn = yypact[yystate];
-      if (yyn != YYPACT_NINF)
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
-
-      /* Pop the current state because it cannot handle the error token.  */
-      if (yyssp == yyss)
-	YYABORT;
-
-      YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
-      yydestruct (yystos[yystate], yyvsp);
-      YYPOPSTACK;
-      yystate = *yyssp;
-      YY_STACK_PRINT (yyss, yyssp);
-    }
-
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
-  YYDPRINTF ((stderr, "Shifting error token, "));
-
-  *++yyvsp = yylval;
-
-
-  yystate = yyn;
-  goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here.  |
-`-------------------------------------*/
-yyacceptlab:
-  yyresult = 0;
-  goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here.  |
-`-----------------------------------*/
-yyabortlab:
-  yyresult = 1;
-  goto yyreturn;
-
-#ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here.  |
-`----------------------------------------------*/
-yyoverflowlab:
-  yyerror ("parser stack overflow");
-  yyresult = 2;
-  /* Fall through.  */
-#endif
-
-yyreturn:
-#ifndef yyoverflow
-  if (yyss != yyssa)
-    YYSTACK_FREE (yyss);
-#endif
-  return yyresult;
-}
-
-
-#line 115 "arith.y"
-
-int
-arith(s)
-	const char *s;
-{
-	long result;
-
-	arith_buf = arith_startbuf = s;
-
-	INTOFF;
-	result = yyparse();
-	arith_lex_reset();	/* reprime lex */
-	INTON;
-
-	return (result);
-}
-
-
-/*
- *  The exp(1) builtin.
- */
-int
-expcmd(argc, argv)
-	int argc;
-	char **argv;
-{
-	const char *p;
-	char *concat;
-	char **ap;
-	long i;
-
-	if (argc > 1) {
-		p = argv[1];
-		if (argc > 2) {
-			/*
-			 * concatenate arguments
-			 */
-			STARTSTACKSTR(concat);
-			ap = argv + 2;
-			for (;;) {
-				while (*p)
-					STPUTC(*p++, concat);
-				if ((p = *ap++) == NULL)
-					break;
-				STPUTC(' ', concat);
-			}
-			STPUTC('\0', concat);
-			p = grabstackstr(concat);
-		}
-	} else
-		p = "";
-
-	i = arith(p);
-
-	out1fmt("%ld\n", i);
-	return (! i);
-}
-
-/*************************/
-#ifdef TEST_ARITH
-#include <stdio.h>
-main(argc, argv)
-	char *argv[];
-{
-	printf("%d\n", exp(argv[1]));
-}
-error(s)
-	char *s;
-{
-	fprintf(stderr, "exp: %s\n", s);
-	exit(1);
-}
-#endif
-
-void
-yyerror(s)
-	const char *s;
-{
-
-//	yyerrok;
-	yyclearin;
-	arith_lex_reset();	/* reprime lex */
-	error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
-	/* NOTREACHED */
-}
-
-
diff --git a/sh/arith.h b/sh/arith.h
deleted file mode 100644
index f70c093..0000000
--- a/sh/arith.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#define ARITH_NUM 258
-#define ARITH_LPAREN 259
-#define ARITH_RPAREN 260
-#define ARITH_OR 261
-#define ARITH_AND 262
-#define ARITH_BOR 263
-#define ARITH_BXOR 264
-#define ARITH_BAND 265
-#define ARITH_NE 266
-#define ARITH_EQ 267
-#define ARITH_LE 268
-#define ARITH_GE 269
-#define ARITH_GT 270
-#define ARITH_LT 271
-#define ARITH_RSHIFT 272
-#define ARITH_LSHIFT 273
-#define ARITH_SUB 274
-#define ARITH_ADD 275
-#define ARITH_REM 276
-#define ARITH_DIV 277
-#define ARITH_MUL 278
-#define ARITH_BNOT 279
-#define ARITH_NOT 280
-#define ARITH_UNARYPLUS 281
-#define ARITH_UNARYMINUS 282
diff --git a/sh/arith.y b/sh/arith.y
deleted file mode 100644
index d51ed38..0000000
--- a/sh/arith.y
+++ /dev/null
@@ -1,199 +0,0 @@
-%{
-/*	$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $	*/
-
-/*-
- * Copyright (c) 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)arith.y	8.3 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: arith.y,v 1.17 2003/09/17 17:33:36 jmmv Exp $");
-#endif
-#endif /* not lint */
-
-#include <stdlib.h>
-#include "expand.h"
-#include "shell.h"
-#include "error.h"
-#include "output.h"
-#include "memalloc.h"
-
-const char *arith_buf, *arith_startbuf;
-
-void yyerror(const char *);
-#ifdef TESTARITH
-int main(int , char *[]);
-int error(char *);
-#endif
-
-%}
-%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
-
-%left ARITH_OR
-%left ARITH_AND
-%left ARITH_BOR
-%left ARITH_BXOR
-%left ARITH_BAND
-%left ARITH_EQ ARITH_NE
-%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE
-%left ARITH_LSHIFT ARITH_RSHIFT
-%left ARITH_ADD ARITH_SUB
-%left ARITH_MUL ARITH_DIV ARITH_REM
-%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT
-%%
-
-exp:	expr {
-			return ($1);
-		}
-	;
-
-
-expr:	ARITH_LPAREN expr ARITH_RPAREN { $$ = $2; }
-	| expr ARITH_OR expr	{ $$ = $1 ? $1 : $3 ? $3 : 0; }
-	| expr ARITH_AND expr	{ $$ = $1 ? ( $3 ? $3 : 0 ) : 0; }
-	| expr ARITH_BOR expr	{ $$ = $1 | $3; }
-	| expr ARITH_BXOR expr	{ $$ = $1 ^ $3; }
-	| expr ARITH_BAND expr	{ $$ = $1 & $3; }
-	| expr ARITH_EQ expr	{ $$ = $1 == $3; }
-	| expr ARITH_GT expr	{ $$ = $1 > $3; }
-	| expr ARITH_GE expr	{ $$ = $1 >= $3; }
-	| expr ARITH_LT expr	{ $$ = $1 < $3; }
-	| expr ARITH_LE expr	{ $$ = $1 <= $3; }
-	| expr ARITH_NE expr	{ $$ = $1 != $3; }
-	| expr ARITH_LSHIFT expr { $$ = $1 << $3; }
-	| expr ARITH_RSHIFT expr { $$ = $1 >> $3; }
-	| expr ARITH_ADD expr	{ $$ = $1 + $3; }
-	| expr ARITH_SUB expr	{ $$ = $1 - $3; }
-	| expr ARITH_MUL expr	{ $$ = $1 * $3; }
-	| expr ARITH_DIV expr	{
-			if ($3 == 0)
-				yyerror("division by zero");
-			$$ = $1 / $3;
-			}
-	| expr ARITH_REM expr   {
-			if ($3 == 0)
-				yyerror("division by zero");
-			$$ = $1 % $3;
-			}
-	| ARITH_NOT expr	{ $$ = !($2); }
-	| ARITH_BNOT expr	{ $$ = ~($2); }
-	| ARITH_SUB expr %prec ARITH_UNARYMINUS { $$ = -($2); }
-	| ARITH_ADD expr %prec ARITH_UNARYPLUS { $$ = $2; }
-	| ARITH_NUM
-	;
-%%
-int
-arith(s)
-	const char *s;
-{
-	long result;
-
-	arith_buf = arith_startbuf = s;
-
-	INTOFF;
-	result = yyparse();
-	arith_lex_reset();	/* reprime lex */
-	INTON;
-
-	return (result);
-}
-
-
-/*
- *  The exp(1) builtin.
- */
-int
-expcmd(argc, argv)
-	int argc;
-	char **argv;
-{
-	const char *p;
-	char *concat;
-	char **ap;
-	long i;
-
-	if (argc > 1) {
-		p = argv[1];
-		if (argc > 2) {
-			/*
-			 * concatenate arguments
-			 */
-			STARTSTACKSTR(concat);
-			ap = argv + 2;
-			for (;;) {
-				while (*p)
-					STPUTC(*p++, concat);
-				if ((p = *ap++) == NULL)
-					break;
-				STPUTC(' ', concat);
-			}
-			STPUTC('\0', concat);
-			p = grabstackstr(concat);
-		}
-	} else
-		p = "";
-
-	i = arith(p);
-
-	out1fmt("%ld\n", i);
-	return (! i);
-}
-
-/*************************/
-#ifdef TEST_ARITH
-#include <stdio.h>
-main(argc, argv)
-	char *argv[];
-{
-	printf("%d\n", exp(argv[1]));
-}
-error(s)
-	char *s;
-{
-	fprintf(stderr, "exp: %s\n", s);
-	exit(1);
-}
-#endif
-
-void
-yyerror(s)
-	const char *s;
-{
-
-//	yyerrok;
-	yyclearin;
-	arith_lex_reset();	/* reprime lex */
-	error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
-	/* NOTREACHED */
-}
diff --git a/sh/arith_lex.c b/sh/arith_lex.c
deleted file mode 100644
index 9a132dd..0000000
--- a/sh/arith_lex.c
+++ /dev/null
@@ -1,1890 +0,0 @@
-#line 2 "arith_lex.c"
-
-#line 4 "arith_lex.c"
-
-#define  YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 31
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with  platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t; 
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN               (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN              (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX               (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX              (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX              (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX              (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX             (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#endif
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-#if __STDC__
-
-#define YY_USE_CONST
-
-#endif	/* __STDC__ */
-#endif	/* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart(yyin  )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#endif
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int yyleng;
-
-extern FILE *yyin, *yyout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-    #define YY_LESS_LINENO(n)
-    
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		*yy_cp = (yy_hold_char); \
-		YY_RESTORE_YY_MORE_OFFSET \
-		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr)  )
-
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-    int yy_bs_lineno; /**< The line count. */
-    int yy_bs_column; /**< The column count. */
-    
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via yyrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-
-	};
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
-                          : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when yytext is formed. */
-static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int yyleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 1;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow yywrap()'s to do buffer switches
- * instead of setting up a fresh yyin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void yyrestart (FILE *input_file  );
-void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
-YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
-void yy_delete_buffer (YY_BUFFER_STATE b  );
-void yy_flush_buffer (YY_BUFFER_STATE b  );
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
-void yypop_buffer_state (void );
-
-static void yyensure_buffer_stack (void );
-static void yy_load_buffer_state (void );
-static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
-
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
-YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );
-
-void *yyalloc (yy_size_t  );
-void *yyrealloc (void *,yy_size_t  );
-void yyfree (void *  );
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){ \
-        yyensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! YY_CURRENT_BUFFER ){\
-        yyensure_buffer_stack (); \
-		YY_CURRENT_BUFFER_LVALUE =    \
-            yy_create_buffer(yyin,YY_BUF_SIZE ); \
-	} \
-	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define yywrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int yylineno;
-
-int yylineno = 1;
-
-extern char *yytext;
-#define yytext_ptr yytext
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[]  );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	(yytext_ptr) = yy_bp; \
-	yyleng = (size_t) (yy_cp - yy_bp); \
-	(yy_hold_char) = *yy_cp; \
-	*yy_cp = '\0'; \
-	(yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 29
-#define YY_END_OF_BUFFER 30
-/* This struct is not used in this scanner,
-   but its presence is necessary. */
-struct yy_trans_info
-	{
-	flex_int32_t yy_verify;
-	flex_int32_t yy_nxt;
-	};
-static yyconst flex_int16_t yy_accept[39] =
-    {   0,
-        0,    0,   30,   28,    1,    1,   27,   23,   12,    6,
-        7,   21,   24,   25,   22,    3,    4,   17,   28,   15,
-        5,   11,   10,   26,   14,    9,    3,    0,    4,   19,
-       18,   13,   16,   20,    5,    8,    2,    0
-    } ;
-
-static yyconst flex_int32_t yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    4,    1,    1,    1,    5,    6,    1,    7,
-        8,    9,   10,    1,   11,    1,   12,   13,   14,   14,
-       14,   14,   14,   14,   14,   15,   15,    1,    1,   16,
-       17,   18,    1,    1,   19,   19,   19,   19,   19,   19,
-       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-        1,    1,    1,   21,   20,    1,   19,   19,   19,   19,
-
-       19,   19,   20,   20,   20,   20,   20,   20,   20,   20,
-       20,   20,   20,   20,   20,   20,   20,   20,   20,   22,
-       20,   20,    1,   23,    1,   24,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst flex_int32_t yy_meta[25] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    2,    2,    2,    1,    1,    1,    2,    3,
-        1,    3,    1,    1
-    } ;
-
-static yyconst flex_int16_t yy_base[41] =
-    {   0,
-        0,    0,   47,   48,   48,   48,   29,   48,   39,   48,
-       48,   48,   48,   48,   48,   12,   14,   14,   27,   15,
-        0,   48,   20,   48,   48,   48,   22,    0,   24,   48,
-       48,   48,   48,   48,    0,   48,    0,   48,   38,   40
-    } ;
-
-static yyconst flex_int16_t yy_def[41] =
-    {   0,
-       38,    1,   38,   38,   38,   38,   38,   38,   38,   38,
-       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
-       39,   38,   38,   38,   38,   38,   38,   40,   38,   38,
-       38,   38,   38,   38,   39,   38,   40,    0,   38,   38
-    } ;
-
-static yyconst flex_int16_t yy_nxt[73] =
-    {   0,
-        4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
-       14,   15,   16,   17,   17,   18,   19,   20,   21,   21,
-       22,   21,   23,   24,   27,   27,   29,   29,   29,   30,
-       31,   33,   34,   28,   27,   27,   29,   29,   29,   35,
-       35,   37,   36,   32,   26,   25,   38,    3,   38,   38,
-       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
-       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
-       38,   38
-    } ;
-
-static yyconst flex_int16_t yy_chk[73] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,   16,   16,   17,   17,   17,   18,
-       18,   20,   20,   16,   27,   27,   29,   29,   29,   39,
-       39,   40,   23,   19,    9,    7,    3,   38,   38,   38,
-       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
-       38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
-       38,   38
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-extern int yy_flex_debug;
-int yy_flex_debug = 0;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *yytext;
-#line 1 "arith_lex.l"
-#line 2 "arith_lex.l"
-/*	$NetBSD: arith_lex.l,v 1.12.6.1 2005/04/07 11:38:58 tron Exp $	*/
-
-/*-
- * Copyright (c) 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)arith_lex.l	8.3 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: arith_lex.l,v 1.12.6.1 2005/04/07 11:38:58 tron Exp $");
-#endif
-#endif /* not lint */
-
-#include <unistd.h>
-#include "arith.h"
-#include "error.h"
-#include "expand.h"
-#include "var.h"
-
-extern int yylval;
-extern char *arith_buf, *arith_startbuf;
-#undef YY_INPUT
-#define YY_INPUT(buf,result,max) \
-	result = (*buf = *arith_buf++) ? 1 : YY_NULL;
-#define YY_NO_UNPUT
-#line 526 "arith_lex.c"
-
-#define INITIAL 0
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap (void );
-#else
-extern int yywrap (void );
-#endif
-#endif
-
-    static void yyunput (int c,char *buf_ptr  );
-    
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
-		{ \
-		int c = '*'; \
-		size_t n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int yylex (void);
-
-#define YY_DECL int yylex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-    
-#line 60 "arith_lex.l"
-
-#line 679 "arith_lex.c"
-
-	if ( (yy_init) )
-		{
-		(yy_init) = 0;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! (yy_start) )
-			(yy_start) = 1;	/* first start state */
-
-		if ( ! yyin )
-			yyin = stdin;
-
-		if ( ! yyout )
-			yyout = stdout;
-
-		if ( ! YY_CURRENT_BUFFER ) {
-			yyensure_buffer_stack ();
-			YY_CURRENT_BUFFER_LVALUE =
-				yy_create_buffer(yyin,YY_BUF_SIZE );
-		}
-
-		yy_load_buffer_state( );
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = (yy_c_buf_p);
-
-		/* Support of yytext. */
-		*yy_cp = (yy_hold_char);
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = (yy_start);
-yy_match:
-		do
-			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
-			if ( yy_accept[yy_current_state] )
-				{
-				(yy_last_accepting_state) = yy_current_state;
-				(yy_last_accepting_cpos) = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 39 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-			++yy_cp;
-			}
-		while ( yy_base[yy_current_state] != 48 );
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-		if ( yy_act == 0 )
-			{ /* have to back up */
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
-			yy_act = yy_accept[yy_current_state];
-			}
-
-		YY_DO_BEFORE_ACTION;
-
-do_action:	/* This label is used only to access EOF actions. */
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = (yy_hold_char);
-			yy_cp = (yy_last_accepting_cpos);
-			yy_current_state = (yy_last_accepting_state);
-			goto yy_find_action;
-
-case 1:
-/* rule 1 can match eol */
-YY_RULE_SETUP
-#line 61 "arith_lex.l"
-{ ; }
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 62 "arith_lex.l"
-{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 63 "arith_lex.l"
-{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 64 "arith_lex.l"
-{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 65 "arith_lex.l"
-{ char *v = lookupvar(yytext);
-			if (v) {
-				yylval = strtol(v, &v, 0);
-				if (*v == 0)
-					return ARITH_NUM;
-			}
-			error("arith: syntax error: \"%s\"", arith_startbuf);
-		}
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 73 "arith_lex.l"
-{ return(ARITH_LPAREN); }
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 74 "arith_lex.l"
-{ return(ARITH_RPAREN); }
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 75 "arith_lex.l"
-{ return(ARITH_OR); }
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 76 "arith_lex.l"
-{ return(ARITH_AND); }
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 77 "arith_lex.l"
-{ return(ARITH_BOR); }
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 78 "arith_lex.l"
-{ return(ARITH_BXOR); }
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 79 "arith_lex.l"
-{ return(ARITH_BAND); }
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 80 "arith_lex.l"
-{ return(ARITH_EQ); }
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 81 "arith_lex.l"
-{ return(ARITH_NE); }
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 82 "arith_lex.l"
-{ return(ARITH_GT); }
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 83 "arith_lex.l"
-{ return(ARITH_GE); }
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 84 "arith_lex.l"
-{ return(ARITH_LT); }
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 85 "arith_lex.l"
-{ return(ARITH_LE); }
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 86 "arith_lex.l"
-{ return(ARITH_LSHIFT); }
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 87 "arith_lex.l"
-{ return(ARITH_RSHIFT); }
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 88 "arith_lex.l"
-{ return(ARITH_MUL); }
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 89 "arith_lex.l"
-{ return(ARITH_DIV); }
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 90 "arith_lex.l"
-{ return(ARITH_REM); }
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 91 "arith_lex.l"
-{ return(ARITH_ADD); }
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 92 "arith_lex.l"
-{ return(ARITH_SUB); }
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 93 "arith_lex.l"
-{ return(ARITH_BNOT); }
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 94 "arith_lex.l"
-{ return(ARITH_NOT); }
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 95 "arith_lex.l"
-{ error("arith: syntax error: \"%s\"", arith_startbuf); }
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 96 "arith_lex.l"
-ECHO;
-	YY_BREAK
-#line 915 "arith_lex.c"
-case YY_STATE_EOF(INITIAL):
-	yyterminate();
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = (yy_hold_char);
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * yylex().  If so, then we have to assure
-			 * consistency between YY_CURRENT_BUFFER and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state(  );
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++(yy_c_buf_p);
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = (yy_c_buf_p);
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer(  ) )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				(yy_did_buffer_switch_on_eof) = 0;
-
-				if ( yywrap( ) )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				(yy_c_buf_p) =
-					(yytext_ptr) + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				(yy_c_buf_p) =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
-				yy_current_state = yy_get_previous_state(  );
-
-				yy_cp = (yy_c_buf_p);
-				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-} /* end of yylex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (void)
-{
-    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
-	register char *source = (yytext_ptr);
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
-	else
-		{
-			size_t num_to_read =
-			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
-			int yy_c_buf_p_offset =
-				(int) ((yy_c_buf_p) - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
-						number_to_move - 1;
-
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), num_to_read );
-
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	if ( (yy_n_chars) == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			yyrestart(yyin  );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	(yy_n_chars) += number_to_move;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
-	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
-	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
-	return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-    static yy_state_type yy_get_previous_state (void)
-{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-    
-	yy_current_state = (yy_start);
-
-	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
-		{
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			(yy_last_accepting_state) = yy_current_state;
-			(yy_last_accepting_cpos) = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 39 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-		}
-
-	return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
-{
-	register int yy_is_jam;
-    	register char *yy_cp = (yy_c_buf_p);
-
-	register YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		(yy_last_accepting_state) = yy_current_state;
-		(yy_last_accepting_cpos) = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 39 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 38);
-
-	return yy_is_jam ? 0 : yy_current_state;
-}
-
-    static void yyunput (int c, register char * yy_bp )
-{
-	register char *yy_cp;
-    
-    yy_cp = (yy_c_buf_p);
-
-	/* undo effects of setting up yytext */
-	*yy_cp = (yy_hold_char);
-
-	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
-		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
-					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
-		register char *source =
-				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
-
-		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
-			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
-
-		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-	(yytext_ptr) = yy_bp;
-	(yy_hold_char) = *yy_cp;
-	(yy_c_buf_p) = yy_cp;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-    static int yyinput (void)
-#else
-    static int input  (void)
-#endif
-
-{
-	int c;
-    
-	*(yy_c_buf_p) = (yy_hold_char);
-
-	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
-			/* This was really a NUL. */
-			*(yy_c_buf_p) = '\0';
-
-		else
-			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
-			++(yy_c_buf_p);
-
-			switch ( yy_get_next_buffer(  ) )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					yyrestart(yyin );
-
-					/*FALLTHROUGH*/
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( yywrap( ) )
-						return EOF;
-
-					if ( ! (yy_did_buffer_switch_on_eof) )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					(yy_c_buf_p) = (yytext_ptr) + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
-	*(yy_c_buf_p) = '\0';	/* preserve yytext */
-	(yy_hold_char) = *++(yy_c_buf_p);
-
-	return c;
-}
-#endif	/* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- * 
- * @note This function does not reset the start condition to @c INITIAL .
- */
-    void yyrestart  (FILE * input_file )
-{
-    
-	if ( ! YY_CURRENT_BUFFER ){
-        yyensure_buffer_stack ();
-		YY_CURRENT_BUFFER_LVALUE =
-            yy_create_buffer(yyin,YY_BUF_SIZE );
-	}
-
-	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
-	yy_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- * 
- */
-    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
-{
-    
-	/* TODO. We should be able to replace this entire function body
-	 * with
-	 *		yypop_buffer_state();
-	 *		yypush_buffer_state(new_buffer);
-     */
-	yyensure_buffer_stack ();
-	if ( YY_CURRENT_BUFFER == new_buffer )
-		return;
-
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-	yy_load_buffer_state( );
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (yywrap()) processing, but the only time this flag
-	 * is looked at is after yywrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void yy_load_buffer_state  (void)
-{
-    	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
-	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
-	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
-	(yy_hold_char) = *(yy_c_buf_p);
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- * 
- * @return the allocated buffer state.
- */
-    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
-{
-	YY_BUFFER_STATE b;
-    
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	yy_init_buffer(b,file );
-
-	return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with yy_create_buffer()
- * 
- */
-    void yy_delete_buffer (YY_BUFFER_STATE  b )
-{
-    
-	if ( ! b )
-		return;
-
-	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
-		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		yyfree((void *) b->yy_ch_buf  );
-
-	yyfree((void *) b  );
-}
-
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-    
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a yyrestart() or at EOF.
- */
-    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
-
-{
-	int oerrno = errno;
-    
-	yy_flush_buffer(b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-    /* If b is the current buffer, then yy_init_buffer was _probably_
-     * called from yyrestart() or through yy_get_next_buffer.
-     * In that case, we don't want to reset the lineno or column.
-     */
-    if (b != YY_CURRENT_BUFFER){
-        b->yy_bs_lineno = 1;
-        b->yy_bs_column = 0;
-    }
-
-        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-    
-	errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- * 
- */
-    void yy_flush_buffer (YY_BUFFER_STATE  b )
-{
-    	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == YY_CURRENT_BUFFER )
-		yy_load_buffer_state( );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- *  the current state. This function will allocate the stack
- *  if necessary.
- *  @param new_buffer The new state.
- *  
- */
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
-    	if (new_buffer == NULL)
-		return;
-
-	yyensure_buffer_stack();
-
-	/* This block is copied from yy_switch_to_buffer. */
-	if ( YY_CURRENT_BUFFER )
-		{
-		/* Flush out information for old buffer. */
-		*(yy_c_buf_p) = (yy_hold_char);
-		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
-		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
-		}
-
-	/* Only push if top exists. Otherwise, replace top. */
-	if (YY_CURRENT_BUFFER)
-		(yy_buffer_stack_top)++;
-	YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
-	/* copied from yy_switch_to_buffer. */
-	yy_load_buffer_state( );
-	(yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- *  The next element becomes the new top.
- *  
- */
-void yypop_buffer_state (void)
-{
-    	if (!YY_CURRENT_BUFFER)
-		return;
-
-	yy_delete_buffer(YY_CURRENT_BUFFER );
-	YY_CURRENT_BUFFER_LVALUE = NULL;
-	if ((yy_buffer_stack_top) > 0)
-		--(yy_buffer_stack_top);
-
-	if (YY_CURRENT_BUFFER) {
-		yy_load_buffer_state( );
-		(yy_did_buffer_switch_on_eof) = 1;
-	}
-}
-
-/* Allocates the stack if it does not exist.
- *  Guarantees space for at least one push.
- */
-static void yyensure_buffer_stack (void)
-{
-	int num_to_alloc;
-    
-	if (!(yy_buffer_stack)) {
-
-		/* First allocation is just for 2 elements, since we don't know if this
-		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
-		 * immediate realloc on the next call.
-         */
-		num_to_alloc = 1;
-		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
-								(num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-		
-		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-				
-		(yy_buffer_stack_max) = num_to_alloc;
-		(yy_buffer_stack_top) = 0;
-		return;
-	}
-
-	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
-		/* Increase the buffer to prepare for a possible push. */
-		int grow_size = 8 /* arbitrary grow size */;
-
-		num_to_alloc = (yy_buffer_stack_max) + grow_size;
-		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
-								((yy_buffer_stack),
-								num_to_alloc * sizeof(struct yy_buffer_state*)
-								);
-
-		/* zero only the new slots.*/
-		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
-		(yy_buffer_stack_max) = num_to_alloc;
-	}
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- * 
- * @return the newly allocated buffer state object. 
- */
-YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
-{
-	YY_BUFFER_STATE b;
-    
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	yy_switch_to_buffer(b  );
-
-	return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to yylex() will
- * scan from a @e copy of @a str.
- * @param str a NUL-terminated string to scan
- * 
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- *       yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE yy_scan_string (yyconst char * yy_str )
-{
-    
-	return yy_scan_bytes(yy_str,strlen(yy_str) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
- * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
- * 
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE yy_scan_bytes  (yyconst char * bytes, int  len )
-{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-    
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = len + 2;
-	buf = (char *) yyalloc(n  );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
-	for ( i = 0; i < len; ++i )
-		buf[i] = bytes[i];
-
-	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = yy_scan_buffer(buf,n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
-    	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
-        YY_LESS_LINENO(yyless_macro_arg);\
-		yytext[yyleng] = (yy_hold_char); \
-		(yy_c_buf_p) = yytext + yyless_macro_arg; \
-		(yy_hold_char) = *(yy_c_buf_p); \
-		*(yy_c_buf_p) = '\0'; \
-		yyleng = yyless_macro_arg; \
-		} \
-	while ( 0 )
-
-/* Accessor  methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- * 
- */
-int yyget_lineno  (void)
-{
-        
-    return yylineno;
-}
-
-/** Get the input stream.
- * 
- */
-FILE *yyget_in  (void)
-{
-        return yyin;
-}
-
-/** Get the output stream.
- * 
- */
-FILE *yyget_out  (void)
-{
-        return yyout;
-}
-
-/** Get the length of the current token.
- * 
- */
-int yyget_leng  (void)
-{
-        return yyleng;
-}
-
-/** Get the current token.
- * 
- */
-
-char *yyget_text  (void)
-{
-        return yytext;
-}
-
-/** Set the current line number.
- * @param line_number
- * 
- */
-void yyset_lineno (int  line_number )
-{
-    
-    yylineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- * 
- * @see yy_switch_to_buffer
- */
-void yyset_in (FILE *  in_str )
-{
-        yyin = in_str ;
-}
-
-void yyset_out (FILE *  out_str )
-{
-        yyout = out_str ;
-}
-
-int yyget_debug  (void)
-{
-        return yy_flex_debug;
-}
-
-void yyset_debug (int  bdebug )
-{
-        yy_flex_debug = bdebug ;
-}
-
-/* yylex_destroy is for both reentrant and non-reentrant scanners. */
-int yylex_destroy  (void)
-{
-    
-    /* Pop the buffer stack, destroying each element. */
-	while(YY_CURRENT_BUFFER){
-		yy_delete_buffer(YY_CURRENT_BUFFER  );
-		YY_CURRENT_BUFFER_LVALUE = NULL;
-		yypop_buffer_state();
-	}
-
-	/* Destroy the stack itself. */
-	yyfree((yy_buffer_stack) );
-	(yy_buffer_stack) = NULL;
-
-    return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
-	register int i;
-    	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
-	register int n;
-    	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-}
-#endif
-
-void *yyalloc (yy_size_t  size )
-{
-	return (void *) malloc( size );
-}
-
-void *yyrealloc  (void * ptr, yy_size_t  size )
-{
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return (void *) realloc( (char *) ptr, size );
-}
-
-void yyfree (void * ptr )
-{
-	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#undef YY_NEW_FILE
-#undef YY_FLUSH_BUFFER
-#undef yy_set_bol
-#undef yy_new_buffer
-#undef yy_set_interactive
-#undef yytext_ptr
-#undef YY_DO_BEFORE_ACTION
-
-#ifdef YY_DECL_IS_OURS
-#undef YY_DECL_IS_OURS
-#undef YY_DECL
-#endif
-#line 96 "arith_lex.l"
-
-
-
-void
-arith_lex_reset() {
-#ifdef YY_NEW_FILE
-	YY_NEW_FILE;
-#endif
-}
-
diff --git a/sh/arith_lex.l b/sh/arith_lex.l
deleted file mode 100644
index 79116fc..0000000
--- a/sh/arith_lex.l
+++ /dev/null
@@ -1,103 +0,0 @@
-%{
-/*	$NetBSD: arith_lex.l,v 1.12.6.1 2005/04/07 11:38:58 tron Exp $	*/
-
-/*-
- * Copyright (c) 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)arith_lex.l	8.3 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: arith_lex.l,v 1.12.6.1 2005/04/07 11:38:58 tron Exp $");
-#endif
-#endif /* not lint */
-
-#include <unistd.h>
-#include "arith.h"
-#include "error.h"
-#include "expand.h"
-#include "var.h"
-
-extern int yylval;
-extern char *arith_buf, *arith_startbuf;
-#undef YY_INPUT
-#define YY_INPUT(buf,result,max) \
-	result = (*buf = *arith_buf++) ? 1 : YY_NULL;
-#define YY_NO_UNPUT
-%}
-%option noyywrap
-
-%%
-[ \t\n]	{ ; }
-0x[0-9a-fA-F]+	{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
-0[0-7]*		{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
-[1-9][0-9]*	{ yylval = strtol(yytext, 0, 0); return(ARITH_NUM); }
-[A-Za-z_][A-Za-z_0-9]*	{ char *v = lookupvar(yytext);
-			if (v) {
-				yylval = strtol(v, &v, 0);
-				if (*v == 0)
-					return ARITH_NUM;
-			}
-			error("arith: syntax error: \"%s\"", arith_startbuf);
-		}
-"("	{ return(ARITH_LPAREN); }
-")"	{ return(ARITH_RPAREN); }
-"||"	{ return(ARITH_OR); }
-"&&"	{ return(ARITH_AND); }
-"|"	{ return(ARITH_BOR); }
-"^"	{ return(ARITH_BXOR); }
-"&"	{ return(ARITH_BAND); }
-"=="	{ return(ARITH_EQ); }
-"!="	{ return(ARITH_NE); }
-">"	{ return(ARITH_GT); }
-">="	{ return(ARITH_GE); }
-"<"	{ return(ARITH_LT); }
-"<="	{ return(ARITH_LE); }
-"<<"	{ return(ARITH_LSHIFT); }
-">>"	{ return(ARITH_RSHIFT); }
-"*"	{ return(ARITH_MUL); }
-"/"	{ return(ARITH_DIV); }
-"%"	{ return(ARITH_REM); }
-"+"	{ return(ARITH_ADD); }
-"-"	{ return(ARITH_SUB); }
-"~"	{ return(ARITH_BNOT); }
-"!"	{ return(ARITH_NOT); }
-.	{ error("arith: syntax error: \"%s\"", arith_startbuf); }
-%%
-
-void
-arith_lex_reset() {
-#ifdef YY_NEW_FILE
-	YY_NEW_FILE;
-#endif
-}
diff --git a/sh/bltin/bltin.h b/sh/bltin/bltin.h
deleted file mode 100644
index b8f9d75..0000000
--- a/sh/bltin/bltin.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*	$NetBSD: bltin.h,v 1.11 2003/08/07 09:05:40 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)bltin.h	8.1 (Berkeley) 5/31/93
- */
-
-/*
- * This file is included by programs which are optionally built into the
- * shell.  If SHELL is defined, we try to map the standard UNIX library
- * routines to ash routines using defines.
- */
-
-#include "../shell.h"
-#include "../mystring.h"
-#ifdef SHELL
-#include "../output.h"
-#include "../error.h"
-#undef stdout
-#undef stderr
-#undef putc
-#undef putchar
-#undef fileno
-#define stdout out1
-#define stderr out2
-#define printf out1fmt
-#define putc(c, file)	outc(c, file)
-#define putchar(c)	out1c(c)
-#define FILE struct output
-#define fprintf outfmt
-#define fputs outstr
-#define fflush flushout
-#define fileno(f) ((f)->fd)
-#define INITARGS(argv)
-#define	err sh_err
-#define	verr sh_verr
-#define	errx sh_errx
-#define	verrx sh_verrx
-#define	warn sh_warn
-#define	vwarn sh_vwarn
-#define	warnx sh_warnx
-#define	vwarnx sh_vwarnx
-#define exit sh_exit
-#define setprogname(s)
-#define getprogname() commandname
-#define setlocate(l,s) 0
-
-#define getenv(p) bltinlookup((p),0)
-
-#else
-#undef NULL
-#include <stdio.h>
-#undef main
-#define INITARGS(argv)	if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
-#endif
-
-pointer stalloc(int);
-void error(const char *, ...);
-void sh_warnx(const char *, ...);
-void sh_exit(int) __attribute__((__noreturn__));
-
-int echocmd(int, char **);
-
-
-extern const char *commandname;
diff --git a/sh/bltin/echo.1 b/sh/bltin/echo.1
deleted file mode 100644
index 7e71fa3..0000000
--- a/sh/bltin/echo.1
+++ /dev/null
@@ -1,109 +0,0 @@
-.\"	$NetBSD: echo.1,v 1.13 2003/08/07 09:05:40 agc Exp $
-.\"
-.\" Copyright (c) 1991, 1993
-.\"	The Regents of the University of California.  All rights reserved.
-.\"
-.\" This code is derived from software contributed to Berkeley by
-.\" Kenneth Almquist.
-.\" Copyright 1989 by Kenneth Almquist
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. 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.
-.\"
-.\"	@(#)echo.1	8.1 (Berkeley) 5/31/93
-.\"
-.Dd May 31, 1993
-.Dt ECHO 1
-.Os
-.Sh NAME
-.Nm echo
-.Nd produce message in a shell script
-.Sh SYNOPSIS
-.Nm
-.Op Fl n | Fl e
-.Ar args ...
-.Sh DESCRIPTION
-.Nm
-prints its arguments on the standard output, separated by spaces.
-Unless the
-.Fl n
-option is present, a newline is output following the arguments.
-The
-.Fl e
-option causes
-.Nm
-to treat the escape sequences specially, as described in the following
-paragraph.
-The
-.Fl e
-option is the default, and is provided solely for compatibility with
-other systems.
-Only one of the options
-.Fl n
-and
-.Fl e
-may be given.
-.Pp
-If any of the following sequences of characters is encountered during
-output, the sequence is not output.  Instead, the specified action is
-performed:
-.Bl -tag -width indent
-.It Li \eb
-A backspace character is output.
-.It Li \ec
-Subsequent output is suppressed.  This is normally used at the end of the
-last argument to suppress the trailing newline that
-.Nm
-would otherwise output.
-.It Li \ef
-Output a form feed.
-.It Li \en
-Output a newline character.
-.It Li \er
-Output a carriage return.
-.It Li \et
-Output a (horizontal) tab character.
-.It Li \ev
-Output a vertical tab.
-.It Li \e0 Ns Ar digits
-Output the character whose value is given by zero to three digits.
-If there are zero digits, a nul character is output.
-.It Li \e\e
-Output a backslash.
-.El
-.Sh HINTS
-Remember that backslash is special to the shell and needs to be escaped.
-To output a message to standard error, say
-.Pp
-.D1  echo message \*[Gt]\*[Am]2
-.Sh BUGS
-The octal character escape mechanism
-.Pq Li \e0 Ns Ar digits
-differs from the
-C language mechanism.
-.Pp
-There is no way to force
-.Nm
-to treat its arguments literally, rather than interpreting them as
-options and escape sequences.
diff --git a/sh/bltin/echo.c b/sh/bltin/echo.c
deleted file mode 100644
index bed7535..0000000
--- a/sh/bltin/echo.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*	$NetBSD: echo.c,v 1.12 2005/02/06 04:43:43 perry Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)echo.c	8.1 (Berkeley) 5/31/93
- */
-
-/*
- * Echo command.
- *
- * echo is steeped in tradition - several of them!
- * netbsd has supported 'echo [-n | -e] args' in spite of -e not being
- * documented anywhere.
- * Posix requires that -n be supported, output from strings containing
- * \ is implementation defined
- * The Single Unix Spec requires that \ escapes be treated as if -e
- * were set, but that -n not be treated as an option.
- * (ksh supports 'echo [-eEn] args', but not -- so that it is actually
- * impossible to actually output '-n')
- *
- * It is suggested that 'printf "%b" "string"' be used to get \ sequences
- * expanded.  printf is now a builtin of netbsd's sh and csh.
- */
-
-//#define main echocmd
-
-#include "bltin.h"
-
-int
-echocmd(int argc, char **argv)
-{
-	char **ap;
-	char *p;
-	char c;
-	int count;
-	int nflag = 0;
-	int eflag = 0;
-
-	ap = argv;
-	if (argc)
-		ap++;
-
-	if ((p = *ap) != NULL) {
-		if (equal(p, "-n")) {
-			nflag = 1;
-			ap++;
-		} else if (equal(p, "-e")) {
-			eflag = 1;
-			ap++;
-		}
-	}
-
-	while ((p = *ap++) != NULL) {
-		while ((c = *p++) != '\0') {
-			if (c == '\\' && eflag) {
-				switch (*p++) {
-				case 'a':  c = '\a';  break;	/* bell */
-				case 'b':  c = '\b';  break;
-				case 'c':  return 0;		/* exit */
-				case 'e':  c =  033;  break;	/* escape */
-				case 'f':  c = '\f';  break;
-				case 'n':  c = '\n';  break;
-				case 'r':  c = '\r';  break;
-				case 't':  c = '\t';  break;
-				case 'v':  c = '\v';  break;
-				case '\\':  break;		/* c = '\\' */
-				case '0':
-					c = 0;
-					count = 3;
-					while (--count >= 0 && (unsigned)(*p - '0') < 8)
-						c = (c << 3) + (*p++ - '0');
-					break;
-				default:
-					/* Output the '/' and char following */
-					p--;
-					break;
-				}
-			}
-			putchar(c);
-		}
-		if (*ap)
-			putchar(' ');
-	}
-	if (! nflag)
-		putchar('\n');
-	return 0;
-}
diff --git a/sh/builtins.c b/sh/builtins.c
deleted file mode 100644
index 344dbd6..0000000
--- a/sh/builtins.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * This file was generated by the mkbuiltins program.
- */
-
-#include "shell.h"
-#include "builtins.h"
-
-const struct builtincmd builtincmd[] = {
-
-	{ "command",	bltincmd },
-	{ "bg",	bgcmd },
-	{ "cd",	cdcmd },
-	{ "chdir",	cdcmd },
-	{ "echo",	echocmd },
-	{ "exp",	expcmd },
-	{ "let",	expcmd },
-	{ "false",	falsecmd },
-#if WITH_HISTORY
-	{ "fc",	histcmd },
-	{ "inputrc",	inputrc },
-#endif
-	{ "fg",	fgcmd },
-	{ "getopts",	getoptscmd },
-	{ "hash",	hashcmd },
-	{ "jobid",	jobidcmd },
-	{ "jobs",	jobscmd },
-	{ "local",	localcmd },
-#ifndef SMALL
-#endif
-	{ "pwd",	pwdcmd },
-	{ "read",	readcmd },
-	{ "setvar",	setvarcmd },
-	{ "true",	truecmd },
-	{ "type",	typecmd },
-	{ "umask",	umaskcmd },
-	{ "unalias",	unaliascmd },
-	{ "wait",	waitcmd },
-	{ "alias",	aliascmd },
-	{ "ulimit",	ulimitcmd },
-	{ "wordexp",	wordexpcmd },
-	{ 0, 0 },
-};
-
-const struct builtincmd splbltincmd[] = {
-	{ "break",	breakcmd },
-	{ "continue",	breakcmd },
-	{ ".",	dotcmd },
-	{ "eval",	evalcmd },
-	{ "exec",	execcmd },
-	{ "exit",	exitcmd },
-	{ "export",	exportcmd },
-	{ "readonly",	exportcmd },
-	{ "return",	returncmd },
-	{ "set",	setcmd },
-	{ "shift",	shiftcmd },
-	{ "times",	timescmd },
-	{ "trap",	trapcmd },
-	{ ":",	truecmd },
-	{ "unset",	unsetcmd },
-	{ 0, 0 },
-};
diff --git a/sh/builtins.def b/sh/builtins.def
deleted file mode 100644
index 18e56c6..0000000
--- a/sh/builtins.def
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/sh -
-#	$NetBSD: builtins.def,v 1.21 2004/07/13 15:05:59 seb Exp $
-#
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. 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.
-#
-#	@(#)builtins.def	8.4 (Berkeley) 5/4/95
-
-#
-# This file lists all the builtin commands.  The first column is the name
-# of a C routine.
-# The -j flag specifies that this command is to be excluded from systems
-# without job control.
-# The -h flag specifies that this command is to be excluded from systems
-# based on the SMALL compile-time symbol.
-# The -s flag specifies that this is a posix 'special builtin' command.
-# The -u flag specifies that this is a posix 'standard utility'.
-# The rest of the line specifies the command name or names used to run
-# the command.
-
-bltincmd	-u command
-bgcmd -j	-u bg
-breakcmd	-s break -s continue
-cdcmd		-u cd chdir
-dotcmd		-s .
-echocmd		echo
-evalcmd		-s eval
-execcmd		-s exec
-exitcmd		-s exit
-expcmd		exp let
-exportcmd	-s export -s readonly
-falsecmd	-u false
-#if WITH_HISTORY
-histcmd -h	-u fc
-inputrc		inputrc
-#endif
-fgcmd -j	-u fg
-getoptscmd	-u getopts
-hashcmd		hash
-jobidcmd	jobid
-jobscmd		-u jobs
-localcmd	local
-#ifndef SMALL
-##printfcmd	printf
-#endif
-pwdcmd		-u pwd
-readcmd		-u read
-returncmd	-s return
-setcmd		-s set
-setvarcmd	setvar
-shiftcmd	-s shift
-timescmd	-s times
-trapcmd		-s trap
-truecmd		-s : -u true
-typecmd		type
-umaskcmd	-u umask
-unaliascmd	-u unalias
-unsetcmd	-s unset
-waitcmd		-u wait
-aliascmd	-u alias
-ulimitcmd	ulimit
-##testcmd		test [
-##killcmd		-u kill		# mandated by posix for 'kill %job'
-wordexpcmd	wordexp
-#newgrp		-u newgrp	# optional command in posix
-
-#exprcmd	expr
diff --git a/sh/builtins.h b/sh/builtins.h
deleted file mode 100644
index 1f9e45a..0000000
--- a/sh/builtins.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This file was generated by the mkbuiltins program.
- */
-
-#include <sys/cdefs.h>
-
-struct builtincmd {
-      const char *name;
-      int (*builtin)(int, char **);
-};
-
-extern const struct builtincmd builtincmd[];
-extern const struct builtincmd splbltincmd[];
-
-
-int bltincmd(int, char **);
-int bgcmd(int, char **);
-int breakcmd(int, char **);
-int cdcmd(int, char **);
-int dotcmd(int, char **);
-int echocmd(int, char **);
-int evalcmd(int, char **);
-int execcmd(int, char **);
-int exitcmd(int, char **);
-int expcmd(int, char **);
-int exportcmd(int, char **);
-int falsecmd(int, char **);
-#if WITH_HISTORY
-int histcmd(int, char **);
-int inputrc(int, char **);
-#endif
-int fgcmd(int, char **);
-int getoptscmd(int, char **);
-int hashcmd(int, char **);
-int jobidcmd(int, char **);
-int jobscmd(int, char **);
-int localcmd(int, char **);
-#ifndef SMALL
-#endif
-int pwdcmd(int, char **);
-int readcmd(int, char **);
-int returncmd(int, char **);
-int setcmd(int, char **);
-int setvarcmd(int, char **);
-int shiftcmd(int, char **);
-int timescmd(int, char **);
-int trapcmd(int, char **);
-int truecmd(int, char **);
-int typecmd(int, char **);
-int umaskcmd(int, char **);
-int unaliascmd(int, char **);
-int unsetcmd(int, char **);
-int waitcmd(int, char **);
-int aliascmd(int, char **);
-int ulimitcmd(int, char **);
-int wordexpcmd(int, char **);
diff --git a/sh/cd.c b/sh/cd.c
deleted file mode 100644
index 4ab599b..0000000
--- a/sh/cd.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/*	$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)cd.c	8.2 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: cd.c,v 1.34 2003/11/14 20:00:28 dsl Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-/*
- * The cd and pwd commands.
- */
-
-#include "shell.h"
-#include "var.h"
-#include "nodes.h"	/* for jobs.h */
-#include "jobs.h"
-#include "options.h"
-#include "output.h"
-#include "memalloc.h"
-#include "error.h"
-#include "exec.h"
-#include "redir.h"
-#include "mystring.h"
-#include "show.h"
-#include "cd.h"
-
-STATIC int docd(char *, int);
-STATIC char *getcomponent(void);
-STATIC void updatepwd(char *);
-STATIC void find_curdir(int noerror);
-
-char *curdir = NULL;		/* current working directory */
-char *prevdir;			/* previous working directory */
-STATIC char *cdcomppath;
-
-int
-cdcmd(int argc, char **argv)
-{
-	const char *dest;
-	const char *path;
-	char *p, *d;
-	struct stat statb;
-	int print = cdprint;	/* set -cdprint to enable */
-
-	nextopt(nullstr);
-
-	/*
-	 * Try (quite hard) to have 'curdir' defined, nothing has set
-	 * it on entry to the shell, but we want 'cd fred; cd -' to work.
-	 */
-	getpwd(1);
-	dest = *argptr;
-	if (dest == NULL) {
-		dest = bltinlookup("HOME", 1);
-		if (dest == NULL)
-			error("HOME not set");
-	} else {
-		if (argptr[1]) {
-			/* Do 'ksh' style substitution */
-			if (!curdir)
-				error("PWD not set");
-			p = strstr(curdir, dest);
-			if (!p)
-				error("bad substitution");
-			d = stalloc(strlen(curdir) + strlen(argptr[1]) + 1);
-			memcpy(d, curdir, p - curdir);
-			strcpy(d + (p - curdir), argptr[1]);
-			strcat(d, p + strlen(dest));
-			dest = d;
-			print = 1;
-		}
-	}
-
-	if (dest[0] == '-' && dest[1] == '\0') {
-		dest = prevdir ? prevdir : curdir;
-		print = 1;
-	}
-	if (*dest == '\0')
-	        dest = ".";
-	if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
-		path = nullstr;
-	while ((p = padvance(&path, dest)) != NULL) {
-		if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
-			if (!print) {
-				/*
-				 * XXX - rethink
-				 */
-				if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
-					p += 2;
-				print = strcmp(p, dest);
-			}
-			if (docd(p, print) >= 0)
-				return 0;
-
-		}
-	}
-	error("can't cd to %s", dest);
-	/* NOTREACHED */
-}
-
-
-/*
- * Actually do the chdir.  In an interactive shell, print the
- * directory name if "print" is nonzero.
- */
-
-STATIC int
-docd(char *dest, int print)
-{
-	char *p;
-	char *q;
-	char *component;
-	struct stat statb;
-	int first;
-	int badstat;
-
-	TRACE(("docd(\"%s\", %d) called\n", dest, print));
-
-	/*
-	 *  Check each component of the path. If we find a symlink or
-	 *  something we can't stat, clear curdir to force a getcwd()
-	 *  next time we get the value of the current directory.
-	 */
-	badstat = 0;
-	cdcomppath = stalloc(strlen(dest) + 1);
-	scopy(dest, cdcomppath);
-	STARTSTACKSTR(p);
-	if (*dest == '/') {
-		STPUTC('/', p);
-		cdcomppath++;
-	}
-	first = 1;
-	while ((q = getcomponent()) != NULL) {
-		if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
-			continue;
-		if (! first)
-			STPUTC('/', p);
-		first = 0;
-		component = q;
-		while (*q)
-			STPUTC(*q++, p);
-		if (equal(component, ".."))
-			continue;
-		STACKSTRNUL(p);
-		if ((lstat(stackblock(), &statb) < 0)
-		    || (S_ISLNK(statb.st_mode)))  {
-			/* print = 1; */
-			badstat = 1;
-			break;
-		}
-	}
-
-	INTOFF;
-	if (chdir(dest) < 0) {
-		INTON;
-		return -1;
-	}
-	updatepwd(badstat ? NULL : dest);
-	INTON;
-	if (print && iflag && curdir)
-		out1fmt("%s\n", curdir);
-	return 0;
-}
-
-
-/*
- * Get the next component of the path name pointed to by cdcomppath.
- * This routine overwrites the string pointed to by cdcomppath.
- */
-
-STATIC char *
-getcomponent()
-{
-	char *p;
-	char *start;
-
-	if ((p = cdcomppath) == NULL)
-		return NULL;
-	start = cdcomppath;
-	while (*p != '/' && *p != '\0')
-		p++;
-	if (*p == '\0') {
-		cdcomppath = NULL;
-	} else {
-		*p++ = '\0';
-		cdcomppath = p;
-	}
-	return start;
-}
-
-
-
-/*
- * Update curdir (the name of the current directory) in response to a
- * cd command.  We also call hashcd to let the routines in exec.c know
- * that the current directory has changed.
- */
-
-STATIC void
-updatepwd(char *dir)
-{
-	char *new;
-	char *p;
-
-	hashcd();				/* update command hash table */
-
-	/*
-	 * If our argument is NULL, we don't know the current directory
-	 * any more because we traversed a symbolic link or something
-	 * we couldn't stat().
-	 */
-	if (dir == NULL || curdir == NULL)  {
-		if (prevdir)
-			ckfree(prevdir);
-		INTOFF;
-		prevdir = curdir;
-		curdir = NULL;
-		getpwd(1);
-		INTON;
-		if (curdir)
-			setvar("PWD", curdir, VEXPORT);
-		else
-			unsetvar("PWD", 0);
-		return;
-	}
-	cdcomppath = stalloc(strlen(dir) + 1);
-	scopy(dir, cdcomppath);
-	STARTSTACKSTR(new);
-	if (*dir != '/') {
-		p = curdir;
-		while (*p)
-			STPUTC(*p++, new);
-		if (p[-1] == '/')
-			STUNPUTC(new);
-	}
-	while ((p = getcomponent()) != NULL) {
-		if (equal(p, "..")) {
-			while (new > stackblock() && (STUNPUTC(new), *new) != '/');
-		} else if (*p != '\0' && ! equal(p, ".")) {
-			STPUTC('/', new);
-			while (*p)
-				STPUTC(*p++, new);
-		}
-	}
-	if (new == stackblock())
-		STPUTC('/', new);
-	STACKSTRNUL(new);
-	INTOFF;
-	if (prevdir)
-		ckfree(prevdir);
-	prevdir = curdir;
-	curdir = savestr(stackblock());
-	setvar("PWD", curdir, VEXPORT);
-	INTON;
-}
-
-/*
- * Posix says the default should be 'pwd -L' (as below), however
- * the 'cd' command (above) does something much nearer to the
- * posix 'cd -P' (not the posix default of 'cd -L').
- * If 'cd' is changed to support -P/L then the default here
- * needs to be revisited if the historic behaviour is to be kept.
- */
-
-int
-pwdcmd(int argc, char **argv)
-{
-	int i;
-	char opt = 'L';
-
-	while ((i = nextopt("LP")) != '\0')
-		opt = i;
-	if (*argptr)
-		error("unexpected argument");
-
-	if (opt == 'L')
-		getpwd(0);
-	else
-		find_curdir(0);
-
-	setvar("PWD", curdir, VEXPORT);
-	out1str(curdir);
-	out1c('\n');
-	return 0;
-}
-
-
-
-
-#define MAXPWD 256
-
-/*
- * Find out what the current directory is. If we already know the current
- * directory, this routine returns immediately.
- */
-void
-getpwd(int noerror)
-{
-	char *pwd;
-	struct stat stdot, stpwd;
-	static int first = 1;
-
-	if (curdir)
-		return;
-
-	if (first) {
-		first = 0;
-		pwd = getenv("PWD");
-		if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
-		    stat(pwd, &stpwd) != -1 &&
-		    stdot.st_dev == stpwd.st_dev &&
-		    stdot.st_ino == stpwd.st_ino) {
-			curdir = savestr(pwd);
-			return;
-		}
-	}
-
-	find_curdir(noerror);
-
-	return;
-}
-
-STATIC void
-find_curdir(int noerror)
-{
-	int i;
-	char *pwd;
-
-	/*
-	 * Things are a bit complicated here; we could have just used
-	 * getcwd, but traditionally getcwd is implemented using popen
-	 * to /bin/pwd. This creates a problem for us, since we cannot
-	 * keep track of the job if it is being ran behind our backs.
-	 * So we re-implement getcwd(), and we suppress interrupts
-	 * throughout the process. This is not completely safe, since
-	 * the user can still break out of it by killing the pwd program.
-	 * We still try to use getcwd for systems that we know have a
-	 * c implementation of getcwd, that does not open a pipe to
-	 * /bin/pwd.
-	 */
-#if defined(__NetBSD__) || defined(__SVR4) || defined(__linux__)
-	for (i = MAXPWD;; i *= 2) {
-		pwd = stalloc(i);
-		if (getcwd(pwd, i) != NULL) {
-			curdir = savestr(pwd);
-			return;
-		}
-		stunalloc(pwd);
-		if (errno == ERANGE)
-			continue;
-		if (!noerror)
-			error("getcwd() failed: %s", strerror(errno));
-		return;
-	}
-#else
-	{
-		char *p;
-		int status;
-		struct job *jp;
-		int pip[2];
-
-		pwd = stalloc(MAXPWD);
-		INTOFF;
-		if (pipe(pip) < 0)
-			error("Pipe call failed");
-		jp = makejob((union node *)NULL, 1);
-		if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
-			(void) close(pip[0]);
-			if (pip[1] != 1) {
-				close(1);
-				copyfd(pip[1], 1);
-				close(pip[1]);
-			}
-			(void) execl("/bin/pwd", "pwd", (char *)0);
-			sh_warn("Cannot exec /bin/pwd");
-			exit(1);
-		}
-		(void) close(pip[1]);
-		pip[1] = -1;
-		p = pwd;
-		while ((i = read(pip[0], p, pwd + MAXPWD - p)) > 0
-		     || (i == -1 && errno == EINTR)) {
-			if (i > 0)
-				p += i;
-		}
-		(void) close(pip[0]);
-		pip[0] = -1;
-		status = waitforjob(jp);
-		if (status != 0)
-			error((char *)0);
-		if (i < 0 || p == pwd || p[-1] != '\n') {
-			if (noerror) {
-				INTON;
-				return;
-			}
-			error("pwd command failed");
-		}
-		p[-1] = '\0';
-		INTON;
-		curdir = savestr(pwd);
-		return;
-	}
-#endif
-}
diff --git a/sh/cd.h b/sh/cd.h
deleted file mode 100644
index a4dcc01..0000000
--- a/sh/cd.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*	$NetBSD: cd.h,v 1.4 2003/08/07 09:05:30 agc Exp $	*/
-
-/*-
- * Copyright (c) 1995
- *	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.
- * 3. 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.
- *
- */
-
-void	getpwd(int);
-int	cdcmd(int, char **);
-int	pwdcmd(int, char **);
diff --git a/sh/error.c b/sh/error.c
deleted file mode 100644
index 8cbed19..0000000
--- a/sh/error.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*	$NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)error.c	8.2 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $");
-#endif
-#endif /* not lint */
-
-/*
- * Errors and exceptions.
- */
-
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "shell.h"
-#include "main.h"
-#include "options.h"
-#include "output.h"
-#include "error.h"
-#include "show.h"
-
-#define signal bsd_signal
-/*
- * Code to handle exceptions in C.
- */
-
-struct jmploc *handler;
-int exception;
-volatile int suppressint;
-volatile int intpending;
-char *commandname;
-
-
-static void exverror(int, const char *, va_list)
-    __attribute__((__noreturn__));
-
-/*
- * Called to raise an exception.  Since C doesn't include exceptions, we
- * just do a longjmp to the exception handler.  The type of exception is
- * stored in the global variable "exception".
- */
-
-void
-exraise(int e)
-{
-	if (handler == NULL)
-		abort();
-	exception = e;
-	longjmp(handler->loc, 1);
-}
-
-
-/*
- * Called from trap.c when a SIGINT is received.  (If the user specifies
- * that SIGINT is to be trapped or ignored using the trap builtin, then
- * this routine is not called.)  Suppressint is nonzero when interrupts
- * are held using the INTOFF macro.  The call to _exit is necessary because
- * there is a short period after a fork before the signal handlers are
- * set to the appropriate value for the child.  (The test for iflag is
- * just defensive programming.)
- */
-
-void
-onint(void)
-{
-	sigset_t nsigset;
-
-	if (suppressint) {
-		intpending = 1;
-		return;
-	}
-	intpending = 0;
-	sigemptyset(&nsigset);
-	sigprocmask(SIG_SETMASK, &nsigset, NULL);
-	if (rootshell && iflag)
-		exraise(EXINT);
-	else {
-		signal(SIGINT, SIG_DFL);
-		raise(SIGINT);
-	}
-	/* NOTREACHED */
-}
-
-static void
-exvwarning(int sv_errno, const char *msg, va_list ap)
-{
-	/* Partially emulate line buffered output so that:
-	 *	printf '%d\n' 1 a 2
-	 * and
-	 *	printf '%d %d %d\n' 1 a 2
-	 * both generate sensible text when stdout and stderr are merged.
-	 */
-	if (output.nextc != output.buf && output.nextc[-1] == '\n')
-		flushout(&output);
-	if (commandname)
-		outfmt(&errout, "%s: ", commandname);
-	if (msg != NULL) {
-		doformat(&errout, msg, ap);
-		if (sv_errno >= 0)
-			outfmt(&errout, ": ");
-	}
-	if (sv_errno >= 0)
-		outfmt(&errout, "%s", strerror(sv_errno));
-	out2c('\n');
-	flushout(&errout);
-}
-
-/*
- * Exverror is called to raise the error exception.  If the second argument
- * is not NULL then error prints an error message using printf style
- * formatting.  It then raises the error exception.
- */
-static void
-exverror(int cond, const char *msg, va_list ap)
-{
-	CLEAR_PENDING_INT;
-	INTOFF;
-
-#ifdef DEBUG
-	if (msg) {
-		TRACE(("exverror(%d, \"", cond));
-		TRACEV((msg, ap));
-		TRACE(("\") pid=%d\n", getpid()));
-	} else
-		TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
-#endif
-	if (msg)
-		exvwarning(-1, msg, ap);
-
-	flushall();
-	exraise(cond);
-	/* NOTREACHED */
-}
-
-
-void
-error(const char *msg, ...)
-{
-	va_list ap;
-
-	va_start(ap, msg);
-	exverror(EXERROR, msg, ap);
-	/* NOTREACHED */
-	va_end(ap);
-}
-
-
-void
-exerror(int cond, const char *msg, ...)
-{
-	va_list ap;
-
-	va_start(ap, msg);
-	exverror(cond, msg, ap);
-	/* NOTREACHED */
-	va_end(ap);
-}
-
-/*
- * error/warning routines for external builtins
- */
-
-void
-sh_exit(int rval)
-{
-	exerrno = rval & 255;
-	exraise(EXEXEC);
-}
-
-void
-sh_err(int status, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	exvwarning(errno, fmt, ap);
-	va_end(ap);
-	sh_exit(status);
-}
-
-void
-sh_verr(int status, const char *fmt, va_list ap)
-{
-	exvwarning(errno, fmt, ap);
-	sh_exit(status);
-}
-
-void
-sh_errx(int status, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	exvwarning(-1, fmt, ap);
-	va_end(ap);
-	sh_exit(status);
-}
-
-void
-sh_verrx(int status, const char *fmt, va_list ap)
-{
-	exvwarning(-1, fmt, ap);
-	sh_exit(status);
-}
-
-void
-sh_warn(const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	exvwarning(errno, fmt, ap);
-	va_end(ap);
-}
-
-void
-sh_vwarn(const char *fmt, va_list ap)
-{
-	exvwarning(errno, fmt, ap);
-}
-
-void
-sh_warnx(const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	exvwarning(-1, fmt, ap);
-	va_end(ap);
-}
-
-void
-sh_vwarnx(const char *fmt, va_list ap)
-{
-	exvwarning(-1, fmt, ap);
-}
-
-
-/*
- * Table of error messages.
- */
-
-struct errname {
-	short errcode;		/* error number */
-	short action;		/* operation which encountered the error */
-	const char *msg;	/* text describing the error */
-};
-
-
-#define ALL (E_OPEN|E_CREAT|E_EXEC)
-
-STATIC const struct errname errormsg[] = {
-	{ EINTR,	ALL,	"interrupted" },
-	{ EACCES,	ALL,	"permission denied" },
-	{ EIO,		ALL,	"I/O error" },
-	{ EEXIST,	ALL,	"file exists" },
-	{ ENOENT,	E_OPEN,	"no such file" },
-	{ ENOENT,	E_CREAT,"directory nonexistent" },
-	{ ENOENT,	E_EXEC,	"not found" },
-	{ ENOTDIR,	E_OPEN,	"no such file" },
-	{ ENOTDIR,	E_CREAT,"directory nonexistent" },
-	{ ENOTDIR,	E_EXEC,	"not found" },
-	{ EISDIR,	ALL,	"is a directory" },
-#ifdef EMFILE
-	{ EMFILE,	ALL,	"too many open files" },
-#endif
-	{ ENFILE,	ALL,	"file table overflow" },
-	{ ENOSPC,	ALL,	"file system full" },
-#ifdef EDQUOT
-	{ EDQUOT,	ALL,	"disk quota exceeded" },
-#endif
-#ifdef ENOSR
-	{ ENOSR,	ALL,	"no streams resources" },
-#endif
-	{ ENXIO,	ALL,	"no such device or address" },
-	{ EROFS,	ALL,	"read-only file system" },
-	{ ETXTBSY,	ALL,	"text busy" },
-#ifdef EAGAIN
-	{ EAGAIN,	E_EXEC,	"not enough memory" },
-#endif
-	{ ENOMEM,	ALL,	"not enough memory" },
-#ifdef ENOLINK
-	{ ENOLINK,	ALL,	"remote access failed" },
-#endif
-#ifdef EMULTIHOP
-	{ EMULTIHOP,	ALL,	"remote access failed" },
-#endif
-#ifdef ECOMM
-	{ ECOMM,	ALL,	"remote access failed" },
-#endif
-#ifdef ESTALE
-	{ ESTALE,	ALL,	"remote access failed" },
-#endif
-#ifdef ETIMEDOUT
-	{ ETIMEDOUT,	ALL,	"remote access failed" },
-#endif
-#ifdef ELOOP
-	{ ELOOP,	ALL,	"symbolic link loop" },
-#endif
-	{ E2BIG,	E_EXEC,	"argument list too long" },
-#ifdef ELIBACC
-	{ ELIBACC,	E_EXEC,	"shared library missing" },
-#endif
-	{ 0,		0,	NULL },
-};
-
-
-/*
- * Return a string describing an error.  The returned string may be a
- * pointer to a static buffer that will be overwritten on the next call.
- * Action describes the operation that got the error.
- */
-
-const char *
-errmsg(int e, int action)
-{
-	struct errname const *ep;
-	static char buf[12];
-
-	for (ep = errormsg ; ep->errcode ; ep++) {
-		if (ep->errcode == e && (ep->action & action) != 0)
-			return ep->msg;
-	}
-	fmtstr(buf, sizeof buf, "error %d", e);
-	return buf;
-}
diff --git a/sh/error.h b/sh/error.h
deleted file mode 100644
index 8e70ca4..0000000
--- a/sh/error.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*	$NetBSD: error.h,v 1.16 2003/08/07 09:05:30 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)error.h	8.2 (Berkeley) 5/4/95
- */
-
-#include <stdarg.h>
-
-/*
- * Types of operations (passed to the errmsg routine).
- */
-
-#define E_OPEN 01	/* opening a file */
-#define E_CREAT 02	/* creating a file */
-#define E_EXEC 04	/* executing a program */
-
-
-/*
- * We enclose jmp_buf in a structure so that we can declare pointers to
- * jump locations.  The global variable handler contains the location to
- * jump to when an exception occurs, and the global variable exception
- * contains a code identifying the exeception.  To implement nested
- * exception handlers, the user should save the value of handler on entry
- * to an inner scope, set handler to point to a jmploc structure for the
- * inner scope, and restore handler on exit from the scope.
- */
-
-#include <setjmp.h>
-
-struct jmploc {
-	jmp_buf loc;
-};
-
-extern struct jmploc *handler;
-extern int exception;
-extern int exerrno;	/* error for EXEXEC */
-
-/* exceptions */
-#define EXINT 0		/* SIGINT received */
-#define EXERROR 1	/* a generic error */
-#define EXSHELLPROC 2	/* execute a shell procedure */
-#define EXEXEC 3	/* command execution failed */
-
-
-/*
- * These macros allow the user to suspend the handling of interrupt signals
- * over a period of time.  This is similar to SIGHOLD to or sigblock, but
- * much more efficient and portable.  (But hacking the kernel is so much
- * more fun than worrying about efficiency and portability. :-))
- */
-
-extern volatile int suppressint;
-extern volatile int intpending;
-
-#define INTOFF suppressint++
-#define INTON { if (--suppressint == 0 && intpending) onint(); }
-#define FORCEINTON {suppressint = 0; if (intpending) onint();}
-#define CLEAR_PENDING_INT intpending = 0
-#define int_pending() intpending
-
-void exraise(int) __attribute__((__noreturn__));
-void onint(void);
-void error(const char *, ...) __attribute__((__noreturn__));
-void exerror(int, const char *, ...) __attribute__((__noreturn__));
-const char *errmsg(int, int);
-
-void sh_err(int, const char *, ...) __attribute__((__noreturn__));
-void sh_verr(int, const char *, va_list) __attribute__((__noreturn__));
-void sh_errx(int, const char *, ...) __attribute__((__noreturn__));
-void sh_verrx(int, const char *, va_list) __attribute__((__noreturn__));
-void sh_warn(const char *, ...);
-void sh_vwarn(const char *, va_list);
-void sh_warnx(const char *, ...);
-void sh_vwarnx(const char *, va_list);
-
-void sh_exit(int) __attribute__((__noreturn__));
-
-
-/*
- * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
- * so we use _setjmp instead.
- */
-
-#if defined(BSD) && !defined(__SVR4) && !defined(__linux__)
-#define setjmp(jmploc)	_setjmp(jmploc)
-#define longjmp(jmploc, val)	_longjmp(jmploc, val)
-#endif
diff --git a/sh/eval.c b/sh/eval.c
deleted file mode 100644
index 4eb7ded..0000000
--- a/sh/eval.c
+++ /dev/null
@@ -1,1257 +0,0 @@
-/*	$NetBSD: eval.c,v 1.81.2.1 2005/06/13 22:03:51 tron Exp $	*/
-
-/*-
- * Copyright (c) 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
-#else
-__RCSID("$NetBSD: eval.c,v 1.81.2.1 2005/06/13 22:03:51 tron Exp $");
-#endif
-#endif /* not lint */
-
-#include <stdlib.h>
-#include <signal.h>
-#include <stdio.h>
-#include <unistd.h>
-#ifdef __linux__
-#include <fcntl.h>
-#else
-#include <sys/fcntl.h>
-#endif
-#include <sys/times.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-/*
- * Evaluate a command.
- */
-
-#include "shell.h"
-#include "nodes.h"
-#include "syntax.h"
-#include "expand.h"
-#include "parser.h"
-#include "jobs.h"
-#include "eval.h"
-#include "builtins.h"
-#include "options.h"
-#include "exec.h"
-#include "redir.h"
-#include "input.h"
-#include "output.h"
-#include "trap.h"
-#include "var.h"
-#include "memalloc.h"
-#include "error.h"
-#include "show.h"
-#include "mystring.h"
-#include "main.h"
-#ifndef SMALL
-#include "myhistedit.h"
-#endif
-
-
-/* flags in argument to evaltree */
-#define EV_EXIT 01		/* exit after evaluating tree */
-#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
-#define EV_BACKCMD 04		/* command executing within back quotes */
-
-int evalskip;			/* set if we are skipping commands */
-STATIC int skipcount;		/* number of levels to skip */
-MKINIT int loopnest;		/* current loop nesting level */
-int funcnest;			/* depth of function calls */
-
-
-char *commandname;
-struct strlist *cmdenviron;
-int exitstatus;			/* exit status of last command */
-int back_exitstatus;		/* exit status of backquoted command */
-
-
-STATIC void evalloop(union node *, int);
-STATIC void evalfor(union node *, int);
-STATIC void evalcase(union node *, int);
-STATIC void evalsubshell(union node *, int);
-STATIC void expredir(union node *);
-STATIC void evalpipe(union node *);
-STATIC void evalcommand(union node *, int, struct backcmd *);
-STATIC void prehash(union node *);
-
-
-/*
- * Called to reset things after an exception.
- */
-
-#ifdef mkinit
-INCLUDE "eval.h"
-
-RESET {
-	evalskip = 0;
-	loopnest = 0;
-	funcnest = 0;
-}
-
-SHELLPROC {
-	exitstatus = 0;
-}
-#endif
-
-static int
-sh_pipe(int fds[2])
-{
-	int nfd;
-
-	if (pipe(fds))
-		return -1;
-
-	if (fds[0] < 3) {
-		nfd = fcntl(fds[0], F_DUPFD, 3);
-		if (nfd != -1) {
-			close(fds[0]);
-			fds[0] = nfd;
-		}
-	}
-
-	if (fds[1] < 3) {
-		nfd = fcntl(fds[1], F_DUPFD, 3);
-		if (nfd != -1) {
-			close(fds[1]);
-			fds[1] = nfd;
-		}
-	}
-	return 0;
-}
-
-
-/*
- * The eval commmand.
- */
-
-int
-evalcmd(int argc, char **argv)
-{
-        char *p;
-        char *concat;
-        char **ap;
-
-        if (argc > 1) {
-                p = argv[1];
-                if (argc > 2) {
-                        STARTSTACKSTR(concat);
-                        ap = argv + 2;
-                        for (;;) {
-                                while (*p)
-                                        STPUTC(*p++, concat);
-                                if ((p = *ap++) == NULL)
-                                        break;
-                                STPUTC(' ', concat);
-                        }
-                        STPUTC('\0', concat);
-                        p = grabstackstr(concat);
-                }
-                evalstring(p, EV_TESTED);
-        }
-        return exitstatus;
-}
-
-
-/*
- * Execute a command or commands contained in a string.
- */
-
-void
-evalstring(char *s, int flag)
-{
-	union node *n;
-	struct stackmark smark;
-
-	setstackmark(&smark);
-	setinputstring(s, 1);
-
-	while ((n = parsecmd(0)) != NEOF) {
-		evaltree(n, flag);
-		popstackmark(&smark);
-	}
-	popfile();
-	popstackmark(&smark);
-}
-
-
-
-/*
- * Evaluate a parse tree.  The value is left in the global variable
- * exitstatus.
- */
-
-void
-evaltree(union node *n, int flags)
-{
-	if (n == NULL) {
-		TRACE(("evaltree(NULL) called\n"));
-		exitstatus = 0;
-		goto out;
-	}
-#ifdef WITH_HISTORY
-	displayhist = 1;	/* show history substitutions done with fc */
-#endif
-	TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
-	    getpid(), n, n->type, flags));
-	switch (n->type) {
-	case NSEMI:
-		evaltree(n->nbinary.ch1, flags & EV_TESTED);
-		if (evalskip)
-			goto out;
-		evaltree(n->nbinary.ch2, flags);
-		break;
-	case NAND:
-		evaltree(n->nbinary.ch1, EV_TESTED);
-		if (evalskip || exitstatus != 0)
-			goto out;
-		evaltree(n->nbinary.ch2, flags);
-		break;
-	case NOR:
-		evaltree(n->nbinary.ch1, EV_TESTED);
-		if (evalskip || exitstatus == 0)
-			goto out;
-		evaltree(n->nbinary.ch2, flags);
-		break;
-	case NREDIR:
-		expredir(n->nredir.redirect);
-		redirect(n->nredir.redirect, REDIR_PUSH);
-		evaltree(n->nredir.n, flags);
-		popredir();
-		break;
-	case NSUBSHELL:
-		evalsubshell(n, flags);
-		break;
-	case NBACKGND:
-		evalsubshell(n, flags);
-		break;
-	case NIF: {
-		evaltree(n->nif.test, EV_TESTED);
-		if (evalskip)
-			goto out;
-		if (exitstatus == 0)
-			evaltree(n->nif.ifpart, flags);
-		else if (n->nif.elsepart)
-			evaltree(n->nif.elsepart, flags);
-		else
-			exitstatus = 0;
-		break;
-	}
-	case NWHILE:
-	case NUNTIL:
-		evalloop(n, flags);
-		break;
-	case NFOR:
-		evalfor(n, flags);
-		break;
-	case NCASE:
-		evalcase(n, flags);
-		break;
-	case NDEFUN:
-		defun(n->narg.text, n->narg.next);
-		exitstatus = 0;
-		break;
-	case NNOT:
-		evaltree(n->nnot.com, EV_TESTED);
-		exitstatus = !exitstatus;
-		break;
-	case NPIPE:
-		evalpipe(n);
-		break;
-	case NCMD:
-		evalcommand(n, flags, (struct backcmd *)NULL);
-		break;
-	default:
-		out1fmt("Node type = %d\n", n->type);
-		flushout(&output);
-		break;
-	}
-out:
-	if (pendingsigs)
-		dotrap();
-	if ((flags & EV_EXIT) != 0)
-		exitshell(exitstatus);
-}
-
-
-STATIC void
-evalloop(union node *n, int flags)
-{
-	int status;
-
-	loopnest++;
-	status = 0;
-	for (;;) {
-		evaltree(n->nbinary.ch1, EV_TESTED);
-		if (evalskip) {
-skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {
-				evalskip = 0;
-				continue;
-			}
-			if (evalskip == SKIPBREAK && --skipcount <= 0)
-				evalskip = 0;
-			break;
-		}
-		if (n->type == NWHILE) {
-			if (exitstatus != 0)
-				break;
-		} else {
-			if (exitstatus == 0)
-				break;
-		}
-		evaltree(n->nbinary.ch2, flags & EV_TESTED);
-		status = exitstatus;
-		if (evalskip)
-			goto skipping;
-	}
-	loopnest--;
-	exitstatus = status;
-}
-
-
-
-STATIC void
-evalfor(union node *n, int flags)
-{
-	struct arglist arglist;
-	union node *argp;
-	struct strlist *sp;
-	struct stackmark smark;
-	int status = 0;
-
-	setstackmark(&smark);
-	arglist.lastp = &arglist.list;
-	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
-		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
-		if (evalskip)
-			goto out;
-	}
-	*arglist.lastp = NULL;
-
-	loopnest++;
-	for (sp = arglist.list ; sp ; sp = sp->next) {
-		setvar(n->nfor.var, sp->text, 0);
-		evaltree(n->nfor.body, flags & EV_TESTED);
-		status = exitstatus;
-		if (evalskip) {
-			if (evalskip == SKIPCONT && --skipcount <= 0) {
-				evalskip = 0;
-				continue;
-			}
-			if (evalskip == SKIPBREAK && --skipcount <= 0)
-				evalskip = 0;
-			break;
-		}
-	}
-	loopnest--;
-	exitstatus = status;
-out:
-	popstackmark(&smark);
-}
-
-
-
-STATIC void
-evalcase(union node *n, int flags)
-{
-	union node *cp;
-	union node *patp;
-	struct arglist arglist;
-	struct stackmark smark;
-	int status = 0;
-
-	setstackmark(&smark);
-	arglist.lastp = &arglist.list;
-	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
-	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
-		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
-			if (casematch(patp, arglist.list->text)) {
-				if (evalskip == 0) {
-					evaltree(cp->nclist.body, flags);
-					status = exitstatus;
-				}
-				goto out;
-			}
-		}
-	}
-out:
-	exitstatus = status;
-	popstackmark(&smark);
-}
-
-
-
-/*
- * Kick off a subshell to evaluate a tree.
- */
-
-STATIC void
-evalsubshell(union node *n, int flags)
-{
-	struct job *jp;
-	int backgnd = (n->type == NBACKGND);
-
-	expredir(n->nredir.redirect);
-	INTOFF;
-	jp = makejob(n, 1);
-	if (forkshell(jp, n, backgnd) == 0) {
-		INTON;
-		if (backgnd)
-			flags &=~ EV_TESTED;
-		redirect(n->nredir.redirect, 0);
-		/* never returns */
-		evaltree(n->nredir.n, flags | EV_EXIT);
-	}
-	if (! backgnd)
-		exitstatus = waitforjob(jp);
-	INTON;
-}
-
-
-
-/*
- * Compute the names of the files in a redirection list.
- */
-
-STATIC void
-expredir(union node *n)
-{
-	union node *redir;
-
-	for (redir = n ; redir ; redir = redir->nfile.next) {
-		struct arglist fn;
-		fn.lastp = &fn.list;
-		switch (redir->type) {
-		case NFROMTO:
-		case NFROM:
-		case NTO:
-		case NCLOBBER:
-		case NAPPEND:
-			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
-			redir->nfile.expfname = fn.list->text;
-			break;
-		case NFROMFD:
-		case NTOFD:
-			if (redir->ndup.vname) {
-				expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
-				fixredir(redir, fn.list->text, 1);
-			}
-			break;
-		}
-	}
-}
-
-
-
-/*
- * Evaluate a pipeline.  All the processes in the pipeline are children
- * of the process creating the pipeline.  (This differs from some versions
- * of the shell, which make the last process in a pipeline the parent
- * of all the rest.)
- */
-
-STATIC void
-evalpipe(union node *n)
-{
-	struct job *jp;
-	struct nodelist *lp;
-	int pipelen;
-	int prevfd;
-	int pip[2];
-
-	TRACE(("evalpipe(0x%lx) called\n", (long)n));
-	pipelen = 0;
-	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
-		pipelen++;
-	INTOFF;
-	jp = makejob(n, pipelen);
-	prevfd = -1;
-	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
-		prehash(lp->n);
-		pip[1] = -1;
-		if (lp->next) {
-			if (sh_pipe(pip) < 0) {
-				close(prevfd);
-				error("Pipe call failed");
-			}
-		}
-		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
-			INTON;
-			if (prevfd > 0) {
-				close(0);
-				copyfd(prevfd, 0);
-				close(prevfd);
-			}
-			if (pip[1] >= 0) {
-				close(pip[0]);
-				if (pip[1] != 1) {
-					close(1);
-					copyfd(pip[1], 1);
-					close(pip[1]);
-				}
-			}
-			evaltree(lp->n, EV_EXIT);
-		}
-		if (prevfd >= 0)
-			close(prevfd);
-		prevfd = pip[0];
-		close(pip[1]);
-	}
-	if (n->npipe.backgnd == 0) {
-		exitstatus = waitforjob(jp);
-		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
-	}
-	INTON;
-}
-
-
-
-/*
- * Execute a command inside back quotes.  If it's a builtin command, we
- * want to save its output in a block obtained from malloc.  Otherwise
- * we fork off a subprocess and get the output of the command via a pipe.
- * Should be called with interrupts off.
- */
-
-void
-evalbackcmd(union node *n, struct backcmd *result)
-{
-	int pip[2];
-	struct job *jp;
-	struct stackmark smark;		/* unnecessary */
-
-	setstackmark(&smark);
-	result->fd = -1;
-	result->buf = NULL;
-	result->nleft = 0;
-	result->jp = NULL;
-	if (n == NULL) {
-		goto out;
-	}
-#ifdef notyet
-	/*
-	 * For now we disable executing builtins in the same
-	 * context as the shell, because we are not keeping
-	 * enough state to recover from changes that are
-	 * supposed only to affect subshells. eg. echo "`cd /`"
-	 */
-	if (n->type == NCMD) {
-		exitstatus = oexitstatus;
-		evalcommand(n, EV_BACKCMD, result);
-	} else
-#endif
-	{
-		INTOFF;
-		if (sh_pipe(pip) < 0)
-			error("Pipe call failed");
-		jp = makejob(n, 1);
-		if (forkshell(jp, n, FORK_NOJOB) == 0) {
-			FORCEINTON;
-			close(pip[0]);
-			if (pip[1] != 1) {
-				close(1);
-				copyfd(pip[1], 1);
-				close(pip[1]);
-			}
-			eflag = 0;
-			evaltree(n, EV_EXIT);
-			/* NOTREACHED */
-		}
-		close(pip[1]);
-		result->fd = pip[0];
-		result->jp = jp;
-		INTON;
-	}
-out:
-	popstackmark(&smark);
-	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
-		result->fd, result->buf, result->nleft, result->jp));
-}
-
-static const char *
-syspath(void)
-{
-	static char *sys_path = NULL;
-#ifndef __linux__    
-	static int mib[] = {CTL_USER, USER_CS_PATH};
-#endif
-	static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin";
-
-	if (sys_path == NULL) {
-#ifndef __linux__
-		size_t len;
-		if (sysctl(mib, 2, 0, &len, 0, 0) != -1 &&
-		    (sys_path = ckmalloc(len + 5)) != NULL &&
-		    sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) {
-			memcpy(sys_path, "PATH=", 5);
-		} else
-#endif
-		{
-			ckfree(sys_path);
-			/* something to keep things happy */
-			sys_path = def_path;
-		}
-	}
-	return sys_path;
-}
-
-static int
-parse_command_args(int argc, char **argv, int *use_syspath)
-{
-	int sv_argc = argc;
-	char *cp, c;
-
-	*use_syspath = 0;
-
-	for (;;) {
-		argv++;
-		if (--argc == 0)
-			break;
-		cp = *argv;
-		if (*cp++ != '-')
-			break;
-		if (*cp == '-' && cp[1] == 0) {
-			argv++;
-			argc--;
-			break;
-		}
-		while ((c = *cp++)) {
-			switch (c) {
-			case 'p':
-				*use_syspath = 1;
-				break;
-			default:
-				/* run 'typecmd' for other options */
-				return 0;
-			}
-		}
-	}
-	return sv_argc - argc;
-}
-
-int vforked = 0;
-
-/*
- * Execute a simple command.
- */
-
-STATIC void
-evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
-{
-	struct stackmark smark;
-	union node *argp;
-	struct arglist arglist;
-	struct arglist varlist;
-	char **argv;
-	int argc;
-	char **envp;
-	int varflag;
-	struct strlist *sp;
-	int mode;
-	int pip[2];
-	struct cmdentry cmdentry;
-	struct job *jp;
-	struct jmploc jmploc;
-	struct jmploc *volatile savehandler = 0;
-	char *volatile savecmdname;
-	volatile struct shparam saveparam;
-	struct localvar *volatile savelocalvars;
-	volatile int e;
-	char *lastarg;
-	const char *path = pathval();
-	volatile int temp_path = 0;
-#if __GNUC__
-	/* Avoid longjmp clobbering */
-	(void) &argv;
-	(void) &argc;
-	(void) &lastarg;
-	(void) &flags;
-#endif
-
-	vforked = 0;
-	/* First expand the arguments. */
-	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
-	setstackmark(&smark);
-	back_exitstatus = 0;
-
-	arglist.lastp = &arglist.list;
-	varflag = 1;
-	/* Expand arguments, ignoring the initial 'name=value' ones */
-	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
-		char *p = argp->narg.text;
-		if (varflag && is_name(*p)) {
-			do {
-				p++;
-			} while (is_in_name(*p));
-			if (*p == '=')
-				continue;
-		}
-		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
-		varflag = 0;
-	}
-	*arglist.lastp = NULL;
-
-	expredir(cmd->ncmd.redirect);
-
-	/* Now do the initial 'name=value' ones we skipped above */
-	varlist.lastp = &varlist.list;
-	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
-		char *p = argp->narg.text;
-		if (!is_name(*p))
-			break;
-		do
-			p++;
-		while (is_in_name(*p));
-		if (*p != '=')
-			break;
-		expandarg(argp, &varlist, EXP_VARTILDE);
-	}
-	*varlist.lastp = NULL;
-
-	argc = 0;
-	for (sp = arglist.list ; sp ; sp = sp->next)
-		argc++;
-	argv = stalloc(sizeof (char *) * (argc + 1));
-
-	for (sp = arglist.list ; sp ; sp = sp->next) {
-		TRACE(("evalcommand arg: %s\n", sp->text));
-		*argv++ = sp->text;
-	}
-	*argv = NULL;
-	lastarg = NULL;
-	if (iflag && funcnest == 0 && argc > 0)
-		lastarg = argv[-1];
-	argv -= argc;
-
-	/* Print the command if xflag is set. */
-	if (xflag) {
-		char sep = 0;
-		out2str(ps4val());
-		for (sp = varlist.list ; sp ; sp = sp->next) {
-			if (sep != 0)
-				outc(sep, &errout);
-			out2str(sp->text);
-			sep = ' ';
-		}
-		for (sp = arglist.list ; sp ; sp = sp->next) {
-			if (sep != 0)
-				outc(sep, &errout);
-			out2str(sp->text);
-			sep = ' ';
-		}
-		outc('\n', &errout);
-		flushout(&errout);
-	}
-
-	/* Now locate the command. */
-	if (argc == 0) {
-		cmdentry.cmdtype = CMDSPLBLTIN;
-		cmdentry.u.bltin = bltincmd;
-	} else {
-		static const char PATH[] = "PATH=";
-		int cmd_flags = DO_ERR;
-
-		/*
-		 * Modify the command lookup path, if a PATH= assignment
-		 * is present
-		 */
-		for (sp = varlist.list; sp; sp = sp->next)
-			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
-				path = sp->text + sizeof(PATH) - 1;
-
-		do {
-			int argsused, use_syspath;
-			find_command(argv[0], &cmdentry, cmd_flags, path);
-			if (cmdentry.cmdtype == CMDUNKNOWN) {
-				exitstatus = 127;
-				flushout(&errout);
-				goto out;
-			}
-
-			/* implement the 'command' builtin here */
-			if (cmdentry.cmdtype != CMDBUILTIN ||
-			    cmdentry.u.bltin != bltincmd)
-				break;
-			cmd_flags |= DO_NOFUNC;
-			argsused = parse_command_args(argc, argv, &use_syspath);
-			if (argsused == 0) {
-				/* use 'type' builting to display info */
-				cmdentry.u.bltin = typecmd;
-				break;
-			}
-			argc -= argsused;
-			argv += argsused;
-			if (use_syspath)
-				path = syspath() + 5;
-		} while (argc != 0);
-		if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC)
-			/* posix mandates that 'command <splbltin>' act as if
-			   <splbltin> was a normal builtin */
-			cmdentry.cmdtype = CMDBUILTIN;
-	}
-
-	/* Fork off a child process if necessary. */
-	if (cmd->ncmd.backgnd
-	 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
-	 || ((flags & EV_BACKCMD) != 0
-	    && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN)
-		 || cmdentry.u.bltin == dotcmd
-		 || cmdentry.u.bltin == evalcmd))) {
-		INTOFF;
-		jp = makejob(cmd, 1);
-		mode = cmd->ncmd.backgnd;
-		if (flags & EV_BACKCMD) {
-			mode = FORK_NOJOB;
-			if (sh_pipe(pip) < 0)
-				error("Pipe call failed");
-		}
-#ifdef DO_SHAREDVFORK
-		/* It is essential that if DO_SHAREDVFORK is defined that the
-		 * child's address space is actually shared with the parent as
-		 * we rely on this.
-		 */
-		if (cmdentry.cmdtype == CMDNORMAL) {
-			pid_t	pid;
-
-			savelocalvars = localvars;
-			localvars = NULL;
-			vforked = 1;
-			switch (pid = vfork()) {
-			case -1:
-				TRACE(("Vfork failed, errno=%d\n", errno));
-				INTON;
-				error("Cannot vfork");
-				break;
-			case 0:
-				/* Make sure that exceptions only unwind to
-				 * after the vfork(2)
-				 */
-				if (setjmp(jmploc.loc)) {
-					if (exception == EXSHELLPROC) {
-						/* We can't progress with the vfork,
-						 * so, set vforked = 2 so the parent
-						 * knows, and _exit();
-						 */
-						vforked = 2;
-						_exit(0);
-					} else {
-						_exit(exerrno);
-					}
-				}
-				savehandler = handler;
-				handler = &jmploc;
-				listmklocal(varlist.list, VEXPORT | VNOFUNC);
-				forkchild(jp, cmd, mode, vforked);
-				break;
-			default:
-				handler = savehandler;	/* restore from vfork(2) */
-				poplocalvars();
-				localvars = savelocalvars;
-				if (vforked == 2) {
-					vforked = 0;
-
-					(void)waitpid(pid, NULL, 0);
-					/* We need to progress in a normal fork fashion */
-					goto normal_fork;
-				}
-				vforked = 0;
-				forkparent(jp, cmd, mode, pid);
-				goto parent;
-			}
-		} else {
-normal_fork:
-#endif
-			if (forkshell(jp, cmd, mode) != 0)
-				goto parent;	/* at end of routine */
-			FORCEINTON;
-#ifdef DO_SHAREDVFORK
-		}
-#endif
-		if (flags & EV_BACKCMD) {
-			if (!vforked) {
-				FORCEINTON;
-			}
-			close(pip[0]);
-			if (pip[1] != 1) {
-				close(1);
-				copyfd(pip[1], 1);
-				close(pip[1]);
-			}
-		}
-		flags |= EV_EXIT;
-	}
-
-	/* This is the child process if a fork occurred. */
-	/* Execute the command. */
-	switch (cmdentry.cmdtype) {
-	case CMDFUNCTION:
-#ifdef DEBUG
-		trputs("Shell function:  ");  trargs(argv);
-#endif
-		redirect(cmd->ncmd.redirect, REDIR_PUSH);
-		saveparam = shellparam;
-		shellparam.malloc = 0;
-		shellparam.reset = 1;
-		shellparam.nparam = argc - 1;
-		shellparam.p = argv + 1;
-		shellparam.optnext = NULL;
-		INTOFF;
-		savelocalvars = localvars;
-		localvars = NULL;
-		INTON;
-		if (setjmp(jmploc.loc)) {
-			if (exception == EXSHELLPROC) {
-				freeparam((volatile struct shparam *)
-				    &saveparam);
-			} else {
-				freeparam(&shellparam);
-				shellparam = saveparam;
-			}
-			poplocalvars();
-			localvars = savelocalvars;
-			handler = savehandler;
-			longjmp(handler->loc, 1);
-		}
-		savehandler = handler;
-		handler = &jmploc;
-		listmklocal(varlist.list, 0);
-		/* stop shell blowing its stack */
-		if (++funcnest > 1000)
-			error("too many nested function calls");
-		evaltree(cmdentry.u.func, flags & EV_TESTED);
-		funcnest--;
-		INTOFF;
-		poplocalvars();
-		localvars = savelocalvars;
-		freeparam(&shellparam);
-		shellparam = saveparam;
-		handler = savehandler;
-		popredir();
-		INTON;
-		if (evalskip == SKIPFUNC) {
-			evalskip = 0;
-			skipcount = 0;
-		}
-		if (flags & EV_EXIT)
-			exitshell(exitstatus);
-		break;
-
-	case CMDBUILTIN:
-	case CMDSPLBLTIN:
-#ifdef DEBUG
-		trputs("builtin command:  ");  trargs(argv);
-#endif
-		mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH;
-		if (flags == EV_BACKCMD) {
-			memout.nleft = 0;
-			memout.nextc = memout.buf;
-			memout.bufsize = 64;
-			mode |= REDIR_BACKQ;
-		}
-		e = -1;
-		savehandler = handler;
-		savecmdname = commandname;
-		handler = &jmploc;
-		if (!setjmp(jmploc.loc)) {
-			/* We need to ensure the command hash table isn't
-			 * corruped by temporary PATH assignments.
-			 * However we must ensure the 'local' command works!
-			 */
-			if (path != pathval() && (cmdentry.u.bltin == hashcmd ||
-			    cmdentry.u.bltin == typecmd)) {
-				savelocalvars = localvars;
-				localvars = 0;
-				mklocal(path - 5 /* PATH= */, 0);
-				temp_path = 1;
-			} else
-				temp_path = 0;
-			redirect(cmd->ncmd.redirect, mode);
-
-			/* exec is a special builtin, but needs this list... */
-			cmdenviron = varlist.list;
-			/* we must check 'readonly' flag for all builtins */
-			listsetvar(varlist.list,
-				cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET);
-			commandname = argv[0];
-			/* initialize nextopt */
-			argptr = argv + 1;
-			optptr = NULL;
-			/* and getopt */
-#ifndef __linux__
-			optreset = 1;
-#endif
-			optind = 1;
-			exitstatus = cmdentry.u.bltin(argc, argv);
-		} else {
-			e = exception;
-			exitstatus = e == EXINT ? SIGINT + 128 :
-					e == EXEXEC ? exerrno : 2;
-		}
-		handler = savehandler;
-		flushall();
-		out1 = &output;
-		out2 = &errout;
-		freestdout();
-		if (temp_path) {
-			poplocalvars();
-			localvars = savelocalvars;
-		}
-		cmdenviron = NULL;
-		if (e != EXSHELLPROC) {
-			commandname = savecmdname;
-			if (flags & EV_EXIT)
-				exitshell(exitstatus);
-		}
-		if (e != -1) {
-			if ((e != EXERROR && e != EXEXEC)
-			    || cmdentry.cmdtype == CMDSPLBLTIN)
-				exraise(e);
-			FORCEINTON;
-		}
-		if (cmdentry.u.bltin != execcmd)
-			popredir();
-		if (flags == EV_BACKCMD) {
-			backcmd->buf = memout.buf;
-			backcmd->nleft = memout.nextc - memout.buf;
-			memout.buf = NULL;
-		}
-		break;
-
-	default:
-#ifdef DEBUG
-		trputs("normal command:  ");  trargs(argv);
-#endif
-		clearredir(vforked);
-		redirect(cmd->ncmd.redirect, vforked ? REDIR_VFORK : 0);
-		if (!vforked)
-			for (sp = varlist.list ; sp ; sp = sp->next)
-				setvareq(sp->text, VEXPORT|VSTACK);
-		envp = environment();
-		shellexec(argv, envp, path, cmdentry.u.index, vforked);
-		break;
-	}
-	goto out;
-
-parent:	/* parent process gets here (if we forked) */
-	if (mode == FORK_FG) {	/* argument to fork */
-		exitstatus = waitforjob(jp);
-	} else if (mode == FORK_NOJOB) {
-		backcmd->fd = pip[0];
-		close(pip[1]);
-		backcmd->jp = jp;
-	}
-	FORCEINTON;
-
-out:
-	if (lastarg)
-		/* dsl: I think this is intended to be used to support
-		 * '_' in 'vi' command mode during line editing...
-		 * However I implemented that within libedit itself.
-		 */
-		setvar("_", lastarg, 0);
-	popstackmark(&smark);
-
-	if (eflag && exitstatus && !(flags & EV_TESTED))
-		exitshell(exitstatus);
-}
-
-
-/*
- * Search for a command.  This is called before we fork so that the
- * location of the command will be available in the parent as well as
- * the child.  The check for "goodname" is an overly conservative
- * check that the name will not be subject to expansion.
- */
-
-STATIC void
-prehash(union node *n)
-{
-	struct cmdentry entry;
-
-	if (n->type == NCMD && n->ncmd.args)
-		if (goodname(n->ncmd.args->narg.text))
-			find_command(n->ncmd.args->narg.text, &entry, 0,
-				     pathval());
-}
-
-
-
-/*
- * Builtin commands.  Builtin commands whose functions are closely
- * tied to evaluation are implemented here.
- */
-
-/*
- * No command given.
- */
-
-int
-bltincmd(int argc, char **argv)
-{
-	/*
-	 * Preserve exitstatus of a previous possible redirection
-	 * as POSIX mandates
-	 */
-	return back_exitstatus;
-}
-
-
-/*
- * Handle break and continue commands.  Break, continue, and return are
- * all handled by setting the evalskip flag.  The evaluation routines
- * above all check this flag, and if it is set they start skipping
- * commands rather than executing them.  The variable skipcount is
- * the number of loops to break/continue, or the number of function
- * levels to return.  (The latter is always 1.)  It should probably
- * be an error to break out of more loops than exist, but it isn't
- * in the standard shell so we don't make it one here.
- */
-
-int
-breakcmd(int argc, char **argv)
-{
-	int n = argc > 1 ? number(argv[1]) : 1;
-
-	if (n > loopnest)
-		n = loopnest;
-	if (n > 0) {
-		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
-		skipcount = n;
-	}
-	return 0;
-}
-
-
-/*
- * The return command.
- */
-
-int
-returncmd(int argc, char **argv)
-{
-	int ret = argc > 1 ? number(argv[1]) : exitstatus;
-
-	if (funcnest) {
-		evalskip = SKIPFUNC;
-		skipcount = 1;
-		return ret;
-	}
-	else {
-		/* Do what ksh does; skip the rest of the file */
-		evalskip = SKIPFILE;
-		skipcount = 1;
-		return ret;
-	}
-}
-
-
-int
-falsecmd(int argc, char **argv)
-{
-	return 1;
-}
-
-
-int
-truecmd(int argc, char **argv)
-{
-	return 0;
-}
-
-
-int
-execcmd(int argc, char **argv)
-{
-	if (argc > 1) {
-		struct strlist *sp;
-
-		iflag = 0;		/* exit on error */
-		mflag = 0;
-		optschanged();
-		for (sp = cmdenviron; sp; sp = sp->next)
-			setvareq(sp->text, VEXPORT|VSTACK);
-		shellexec(argv + 1, environment(), pathval(), 0, 0);
-	}
-	return 0;
-}
-
-static int
-conv_time(clock_t ticks, char *seconds, size_t l)
-{
-	static clock_t tpm = 0;
-	clock_t mins;
-	int i;
-
-	mins = ticks / tpm;
-	snprintf(seconds, l, "%.4f", (ticks - mins * tpm) * 60.0 / tpm );
-
-	if (seconds[0] == '6' && seconds[1] == '0') {
-		/* 59.99995 got rounded up... */
-		mins++;
-		strlcpy(seconds, "0.0", l);
-		return mins;
-	}
-
-	/* suppress trailing zeros */
-	i = strlen(seconds) - 1;
-	for (; seconds[i] == '0' && seconds[i - 1] != '.'; i--)
-		seconds[i] = 0;
-	return mins;
-}
-
-int
-timescmd(int argc, char **argv)
-{
-	struct tms tms;
-	int u, s, cu, cs;
-	char us[8], ss[8], cus[8], css[8];
-
-	nextopt("");
-
-	times(&tms);
-
-	u = conv_time(tms.tms_utime, us, sizeof(us));
-	s = conv_time(tms.tms_stime, ss, sizeof(ss));
-	cu = conv_time(tms.tms_cutime, cus, sizeof(cus));
-	cs = conv_time(tms.tms_cstime, css, sizeof(css));
-
-	outfmt(out1, "%dm%ss %dm%ss\n%dm%ss %dm%ss\n",
-		u, us, s, ss, cu, cus, cs, css);
-
-	return 0;
-}
diff --git a/sh/eval.h b/sh/eval.h
deleted file mode 100644
index 155bc44..0000000
--- a/sh/eval.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*	$NetBSD: eval.h,v 1.14 2003/08/07 09:05:31 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)eval.h	8.2 (Berkeley) 5/4/95
- */
-
-extern char *commandname;	/* currently executing command */
-extern int exitstatus;		/* exit status of last command */
-extern int back_exitstatus;	/* exit status of backquoted command */
-extern struct strlist *cmdenviron;  /* environment for builtin command */
-
-
-struct backcmd {		/* result of evalbackcmd */
-	int fd;			/* file descriptor to read from */
-	char *buf;		/* buffer */
-	int nleft;		/* number of chars in buffer */
-	struct job *jp;		/* job structure for command */
-};
-
-void evalstring(char *, int);
-union node;	/* BLETCH for ansi C */
-void evaltree(union node *, int);
-void evalbackcmd(union node *, struct backcmd *);
-
-/* in_function returns nonzero if we are currently evaluating a function */
-#define in_function()	funcnest
-extern int funcnest;
-extern int evalskip;
-
-/* reasons for skipping commands (see comment on breakcmd routine) */
-#define SKIPBREAK	1
-#define SKIPCONT	2
-#define SKIPFUNC	3
-#define SKIPFILE	4
diff --git a/sh/exec.c b/sh/exec.c
deleted file mode 100644
index fe3613f..0000000
--- a/sh/exec.c
+++ /dev/null
@@ -1,1063 +0,0 @@
-/*	$NetBSD: exec.c,v 1.37 2003/08/07 09:05:31 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)exec.c	8.4 (Berkeley) 6/8/95";
-#else
-__RCSID("$NetBSD: exec.c,v 1.37 2003/08/07 09:05:31 agc Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/*
- * When commands are first encountered, they are entered in a hash table.
- * This ensures that a full path search will not have to be done for them
- * on each invocation.
- *
- * We should investigate converting to a linear search, even though that
- * would make the command name "hash" a misnomer.
- */
-
-#include "shell.h"
-#include "main.h"
-#include "nodes.h"
-#include "parser.h"
-#include "redir.h"
-#include "eval.h"
-#include "exec.h"
-#include "builtins.h"
-#include "var.h"
-#include "options.h"
-#include "input.h"
-#include "output.h"
-#include "syntax.h"
-#include "memalloc.h"
-#include "error.h"
-#include "init.h"
-#include "mystring.h"
-#include "show.h"
-#include "jobs.h"
-#include "alias.h"
-
-
-#define CMDTABLESIZE 31		/* should be prime */
-#define ARB 1			/* actual size determined at run time */
-
-
-
-struct tblentry {
-	struct tblentry *next;	/* next entry in hash chain */
-	union param param;	/* definition of builtin function */
-	short cmdtype;		/* index identifying command */
-	char rehash;		/* if set, cd done since entry created */
-	char cmdname[ARB];	/* name of command */
-};
-
-
-STATIC struct tblentry *cmdtable[CMDTABLESIZE];
-STATIC int builtinloc = -1;		/* index in path of %builtin, or -1 */
-int exerrno = 0;			/* Last exec error */
-
-
-STATIC void tryexec(char *, char **, char **, int);
-STATIC void execinterp(char **, char **);
-STATIC void printentry(struct tblentry *, int);
-STATIC void clearcmdentry(int);
-STATIC struct tblentry *cmdlookup(const char *, int);
-STATIC void delete_cmd_entry(void);
-
-
-extern char *const parsekwd[];
-
-/*
- * Exec a program.  Never returns.  If you change this routine, you may
- * have to change the find_command routine as well.
- */
-
-void
-shellexec(char **argv, char **envp, const char *path, int idx, int vforked)
-{
-	char *cmdname;
-	int e;
-
-	if (strchr(argv[0], '/') != NULL) {
-		tryexec(argv[0], argv, envp, vforked);
-		e = errno;
-	} else {
-		e = ENOENT;
-		while ((cmdname = padvance(&path, argv[0])) != NULL) {
-			if (--idx < 0 && pathopt == NULL) {
-				tryexec(cmdname, argv, envp, vforked);
-				if (errno != ENOENT && errno != ENOTDIR)
-					e = errno;
-			}
-			stunalloc(cmdname);
-		}
-	}
-
-	/* Map to POSIX errors */
-	switch (e) {
-	case EACCES:
-		exerrno = 126;
-		break;
-	case ENOENT:
-		exerrno = 127;
-		break;
-	default:
-		exerrno = 2;
-		break;
-	}
-	TRACE(("shellexec failed for %s, errno %d, vforked %d, suppressint %d\n",
-		argv[0], e, vforked, suppressint ));
-	exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
-	/* NOTREACHED */
-}
-
-
-STATIC void
-tryexec(char *cmd, char **argv, char **envp, int vforked)
-{
-	int e;
-#ifndef BSD
-	char *p;
-#endif
-
-#ifdef SYSV
-	do {
-		execve(cmd, argv, envp);
-	} while (errno == EINTR);
-#else
-	execve(cmd, argv, envp);
-#endif
-	e = errno;
-	if (e == ENOEXEC) {
-		if (vforked) {
-			/* We are currently vfork(2)ed, so raise an
-			 * exception, and evalcommand will try again
-			 * with a normal fork(2).
-			 */
-			exraise(EXSHELLPROC);
-		}
-		initshellproc();
-		setinputfile(cmd, 0);
-		commandname = arg0 = savestr(argv[0]);
-#if !defined(BSD) && !defined(__linux__)
-		pgetc(); pungetc();		/* fill up input buffer */
-		p = parsenextc;
-		if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
-			argv[0] = cmd;
-			execinterp(argv, envp);
-		}
-#endif
-		setparam(argv + 1);
-		exraise(EXSHELLPROC);
-	}
-	errno = e;
-}
-
-
-#if !defined(BSD) && !defined(__linux__)
-/*
- * Execute an interpreter introduced by "#!", for systems where this
- * feature has not been built into the kernel.  If the interpreter is
- * the shell, return (effectively ignoring the "#!").  If the execution
- * of the interpreter fails, exit.
- *
- * This code peeks inside the input buffer in order to avoid actually
- * reading any input.  It would benefit from a rewrite.
- */
-
-#define NEWARGS 5
-
-STATIC void
-execinterp(char **argv, char **envp)
-{
-	int n;
-	char *inp;
-	char *outp;
-	char c;
-	char *p;
-	char **ap;
-	char *newargs[NEWARGS];
-	int i;
-	char **ap2;
-	char **new;
-
-	n = parsenleft - 2;
-	inp = parsenextc + 2;
-	ap = newargs;
-	for (;;) {
-		while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
-			inp++;
-		if (n < 0)
-			goto bad;
-		if ((c = *inp++) == '\n')
-			break;
-		if (ap == &newargs[NEWARGS])
-bad:		  error("Bad #! line");
-		STARTSTACKSTR(outp);
-		do {
-			STPUTC(c, outp);
-		} while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
-		STPUTC('\0', outp);
-		n++, inp--;
-		*ap++ = grabstackstr(outp);
-	}
-	if (ap == newargs + 1) {	/* if no args, maybe no exec is needed */
-		p = newargs[0];
-		for (;;) {
-			if (equal(p, "sh") || equal(p, "ash")) {
-				return;
-			}
-			while (*p != '/') {
-				if (*p == '\0')
-					goto break2;
-				p++;
-			}
-			p++;
-		}
-break2:;
-	}
-	i = (char *)ap - (char *)newargs;		/* size in bytes */
-	if (i == 0)
-		error("Bad #! line");
-	for (ap2 = argv ; *ap2++ != NULL ; );
-	new = ckmalloc(i + ((char *)ap2 - (char *)argv));
-	ap = newargs, ap2 = new;
-	while ((i -= sizeof (char **)) >= 0)
-		*ap2++ = *ap++;
-	ap = argv;
-	while (*ap2++ = *ap++);
-	shellexec(new, envp, pathval(), 0);
-	/* NOTREACHED */
-}
-#endif
-
-
-
-/*
- * Do a path search.  The variable path (passed by reference) should be
- * set to the start of the path before the first call; padvance will update
- * this value as it proceeds.  Successive calls to padvance will return
- * the possible path expansions in sequence.  If an option (indicated by
- * a percent sign) appears in the path entry then the global variable
- * pathopt will be set to point to it; otherwise pathopt will be set to
- * NULL.
- */
-
-const char *pathopt;
-
-char *
-padvance(const char **path, const char *name)
-{
-	const char *p;
-	char *q;
-	const char *start;
-	int len;
-
-	if (*path == NULL)
-		return NULL;
-	start = *path;
-	for (p = start ; *p && *p != ':' && *p != '%' ; p++);
-	len = p - start + strlen(name) + 2;	/* "2" is for '/' and '\0' */
-	while (stackblocksize() < len)
-		growstackblock();
-	q = stackblock();
-	if (p != start) {
-		memcpy(q, start, p - start);
-		q += p - start;
-		*q++ = '/';
-	}
-	strcpy(q, name);
-	pathopt = NULL;
-	if (*p == '%') {
-		pathopt = ++p;
-		while (*p && *p != ':')  p++;
-	}
-	if (*p == ':')
-		*path = p + 1;
-	else
-		*path = NULL;
-	return stalloc(len);
-}
-
-
-
-/*** Command hashing code ***/
-
-
-int
-hashcmd(int argc, char **argv)
-{
-	struct tblentry **pp;
-	struct tblentry *cmdp;
-	int c;
-	int verbose;
-	struct cmdentry entry;
-	char *name;
-
-	verbose = 0;
-	while ((c = nextopt("rv")) != '\0') {
-		if (c == 'r') {
-			clearcmdentry(0);
-		} else if (c == 'v') {
-			verbose++;
-		}
-	}
-	if (*argptr == NULL) {
-		for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
-			for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
-				if (verbose || cmdp->cmdtype == CMDNORMAL)
-					printentry(cmdp, verbose);
-			}
-		}
-		return 0;
-	}
-	while ((name = *argptr) != NULL) {
-		if ((cmdp = cmdlookup(name, 0)) != NULL
-		 && (cmdp->cmdtype == CMDNORMAL
-		     || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
-			delete_cmd_entry();
-		find_command(name, &entry, DO_ERR, pathval());
-		if (verbose) {
-			if (entry.cmdtype != CMDUNKNOWN) {	/* if no error msg */
-				cmdp = cmdlookup(name, 0);
-				printentry(cmdp, verbose);
-			}
-			flushall();
-		}
-		argptr++;
-	}
-	return 0;
-}
-
-
-STATIC void
-printentry(struct tblentry *cmdp, int verbose)
-{
-	int idx;
-	const char *path;
-	char *name;
-
-	switch (cmdp->cmdtype) {
-	case CMDNORMAL:
-		idx = cmdp->param.index;
-		path = pathval();
-		do {
-			name = padvance(&path, cmdp->cmdname);
-			stunalloc(name);
-		} while (--idx >= 0);
-		out1str(name);
-		break;
-	case CMDSPLBLTIN:
-		out1fmt("special builtin %s", cmdp->cmdname);
-		break;
-	case CMDBUILTIN:
-		out1fmt("builtin %s", cmdp->cmdname);
-		break;
-	case CMDFUNCTION:
-		out1fmt("function %s", cmdp->cmdname);
-		if (verbose) {
-			struct procstat ps;
-			INTOFF;
-			commandtext(&ps, cmdp->param.func);
-			INTON;
-			out1str("() { ");
-			out1str(ps.cmd);
-			out1str("; }");
-		}
-		break;
-	default:
-		error("internal error: %s cmdtype %d", cmdp->cmdname, cmdp->cmdtype);
-	}
-	if (cmdp->rehash)
-		out1c('*');
-	out1c('\n');
-}
-
-
-
-/*
- * Resolve a command name.  If you change this routine, you may have to
- * change the shellexec routine as well.
- */
-
-void
-find_command(char *name, struct cmdentry *entry, int act, const char *path)
-{
-	struct tblentry *cmdp, loc_cmd;
-	int idx;
-	int prev;
-	char *fullname;
-	struct stat statb;
-	int e;
-	int (*bltin)(int,char **);
-
-	/* If name contains a slash, don't use PATH or hash table */
-	if (strchr(name, '/') != NULL) {
-		if (act & DO_ABS) {
-			while (stat(name, &statb) < 0) {
-#ifdef SYSV
-				if (errno == EINTR)
-					continue;
-#endif
-				if (errno != ENOENT && errno != ENOTDIR)
-					e = errno;
-				entry->cmdtype = CMDUNKNOWN;
-				entry->u.index = -1;
-				return;
-			}
-			entry->cmdtype = CMDNORMAL;
-			entry->u.index = -1;
-			return;
-		}
-		entry->cmdtype = CMDNORMAL;
-		entry->u.index = 0;
-		return;
-	}
-
-	if (path != pathval())
-		act |= DO_ALTPATH;
-
-	if (act & DO_ALTPATH && strstr(path, "%builtin") != NULL)
-		act |= DO_ALTBLTIN;
-
-	/* If name is in the table, check answer will be ok */
-	if ((cmdp = cmdlookup(name, 0)) != NULL) {
-		do {
-			switch (cmdp->cmdtype) {
-			case CMDNORMAL:
-				if (act & DO_ALTPATH) {
-					cmdp = NULL;
-					continue;
-				}
-				break;
-			case CMDFUNCTION:
-				if (act & DO_NOFUNC) {
-					cmdp = NULL;
-					continue;
-				}
-				break;
-			case CMDBUILTIN:
-				if ((act & DO_ALTBLTIN) || builtinloc >= 0) {
-					cmdp = NULL;
-					continue;
-				}
-				break;
-			}
-			/* if not invalidated by cd, we're done */
-			if (cmdp->rehash == 0)
-				goto success;
-		} while (0);
-	}
-
-	/* If %builtin not in path, check for builtin next */
-	if ((act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc < 0) &&
-	    (bltin = find_builtin(name)) != 0)
-		goto builtin_success;
-
-	/* We have to search path. */
-	prev = -1;		/* where to start */
-	if (cmdp) {		/* doing a rehash */
-		if (cmdp->cmdtype == CMDBUILTIN)
-			prev = builtinloc;
-		else
-			prev = cmdp->param.index;
-	}
-
-	e = ENOENT;
-	idx = -1;
-loop:
-	while ((fullname = padvance(&path, name)) != NULL) {
-		stunalloc(fullname);
-		idx++;
-		if (pathopt) {
-			if (prefix("builtin", pathopt)) {
-				if ((bltin = find_builtin(name)) == 0)
-					goto loop;
-				goto builtin_success;
-			} else if (prefix("func", pathopt)) {
-				/* handled below */
-			} else {
-				/* ignore unimplemented options */
-				goto loop;
-			}
-		}
-		/* if rehash, don't redo absolute path names */
-		if (fullname[0] == '/' && idx <= prev) {
-			if (idx < prev)
-				goto loop;
-			TRACE(("searchexec \"%s\": no change\n", name));
-			goto success;
-		}
-		while (stat(fullname, &statb) < 0) {
-#ifdef SYSV
-			if (errno == EINTR)
-				continue;
-#endif
-			if (errno != ENOENT && errno != ENOTDIR)
-				e = errno;
-			goto loop;
-		}
-		e = EACCES;	/* if we fail, this will be the error */
-		if (!S_ISREG(statb.st_mode))
-			goto loop;
-		if (pathopt) {		/* this is a %func directory */
-			if (act & DO_NOFUNC)
-				goto loop;
-			stalloc(strlen(fullname) + 1);
-			readcmdfile(fullname);
-			if ((cmdp = cmdlookup(name, 0)) == NULL ||
-			    cmdp->cmdtype != CMDFUNCTION)
-				error("%s not defined in %s", name, fullname);
-			stunalloc(fullname);
-			goto success;
-		}
-#ifdef notdef
-		/* XXX this code stops root executing stuff, and is buggy
-		   if you need a group from the group list. */
-		if (statb.st_uid == geteuid()) {
-			if ((statb.st_mode & 0100) == 0)
-				goto loop;
-		} else if (statb.st_gid == getegid()) {
-			if ((statb.st_mode & 010) == 0)
-				goto loop;
-		} else {
-			if ((statb.st_mode & 01) == 0)
-				goto loop;
-		}
-#endif
-		TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
-		INTOFF;
-		if (act & DO_ALTPATH) {
-			stalloc(strlen(fullname) + 1);
-			cmdp = &loc_cmd;
-		} else
-			cmdp = cmdlookup(name, 1);
-		cmdp->cmdtype = CMDNORMAL;
-		cmdp->param.index = idx;
-		INTON;
-		goto success;
-	}
-
-	/* We failed.  If there was an entry for this command, delete it */
-	if (cmdp)
-		delete_cmd_entry();
-	if (act & DO_ERR)
-		outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
-	entry->cmdtype = CMDUNKNOWN;
-	return;
-
-builtin_success:
-	INTOFF;
-	if (act & DO_ALTPATH)
-		cmdp = &loc_cmd;
-	else
-		cmdp = cmdlookup(name, 1);
-	if (cmdp->cmdtype == CMDFUNCTION)
-		/* DO_NOFUNC must have been set */
-		cmdp = &loc_cmd;
-	cmdp->cmdtype = CMDBUILTIN;
-	cmdp->param.bltin = bltin;
-	INTON;
-success:
-	cmdp->rehash = 0;
-	entry->cmdtype = cmdp->cmdtype;
-	entry->u = cmdp->param;
-}
-
-
-
-/*
- * Search the table of builtin commands.
- */
-
-int
-(*find_builtin(name))(int, char **)
-	char *name;
-{
-	const struct builtincmd *bp;
-
-	for (bp = builtincmd ; bp->name ; bp++) {
-		if (*bp->name == *name && equal(bp->name, name))
-			return bp->builtin;
-	}
-	return 0;
-}
-
-int
-(*find_splbltin(name))(int, char **)
-	char *name;
-{
-	const struct builtincmd *bp;
-
-	for (bp = splbltincmd ; bp->name ; bp++) {
-		if (*bp->name == *name && equal(bp->name, name))
-			return bp->builtin;
-	}
-	return 0;
-}
-
-/*
- * At shell startup put special builtins into hash table.
- * ensures they are executed first (see posix).
- * We stop functions being added with the same name
- * (as they are impossible to call)
- */
-
-void
-hash_special_builtins(void)
-{
-	const struct builtincmd *bp;
-	struct tblentry *cmdp;
-
-	for (bp = splbltincmd ; bp->name ; bp++) {
-		cmdp = cmdlookup(bp->name, 1);
-		cmdp->cmdtype = CMDSPLBLTIN;
-		cmdp->param.bltin = bp->builtin;
-	}
-}
-
-
-
-/*
- * Called when a cd is done.  Marks all commands so the next time they
- * are executed they will be rehashed.
- */
-
-void
-hashcd(void)
-{
-	struct tblentry **pp;
-	struct tblentry *cmdp;
-
-	for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
-		for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
-			if (cmdp->cmdtype == CMDNORMAL
-			 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
-				cmdp->rehash = 1;
-		}
-	}
-}
-
-
-
-/*
- * Fix command hash table when PATH changed.
- * Called before PATH is changed.  The argument is the new value of PATH;
- * pathval() still returns the old value at this point.
- * Called with interrupts off.
- */
-
-void
-changepath(const char *newval)
-{
-	const char *old, *new;
-	int idx;
-	int firstchange;
-	int bltin;
-
-	old = pathval();
-	new = newval;
-	firstchange = 9999;	/* assume no change */
-	idx = 0;
-	bltin = -1;
-	for (;;) {
-		if (*old != *new) {
-			firstchange = idx;
-			if ((*old == '\0' && *new == ':')
-			 || (*old == ':' && *new == '\0'))
-				firstchange++;
-			old = new;	/* ignore subsequent differences */
-		}
-		if (*new == '\0')
-			break;
-		if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
-			bltin = idx;
-		if (*new == ':') {
-			idx++;
-		}
-		new++, old++;
-	}
-	if (builtinloc < 0 && bltin >= 0)
-		builtinloc = bltin;		/* zap builtins */
-	if (builtinloc >= 0 && bltin < 0)
-		firstchange = 0;
-	clearcmdentry(firstchange);
-	builtinloc = bltin;
-}
-
-
-/*
- * Clear out command entries.  The argument specifies the first entry in
- * PATH which has changed.
- */
-
-STATIC void
-clearcmdentry(int firstchange)
-{
-	struct tblentry **tblp;
-	struct tblentry **pp;
-	struct tblentry *cmdp;
-
-	INTOFF;
-	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
-		pp = tblp;
-		while ((cmdp = *pp) != NULL) {
-			if ((cmdp->cmdtype == CMDNORMAL &&
-			     cmdp->param.index >= firstchange)
-			 || (cmdp->cmdtype == CMDBUILTIN &&
-			     builtinloc >= firstchange)) {
-				*pp = cmdp->next;
-				ckfree(cmdp);
-			} else {
-				pp = &cmdp->next;
-			}
-		}
-	}
-	INTON;
-}
-
-
-/*
- * Delete all functions.
- */
-
-#ifdef mkinit
-MKINIT void deletefuncs(void);
-MKINIT void hash_special_builtins(void);
-
-INIT {
-	hash_special_builtins();
-}
-
-SHELLPROC {
-	deletefuncs();
-}
-#endif
-
-void
-deletefuncs(void)
-{
-	struct tblentry **tblp;
-	struct tblentry **pp;
-	struct tblentry *cmdp;
-
-	INTOFF;
-	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
-		pp = tblp;
-		while ((cmdp = *pp) != NULL) {
-			if (cmdp->cmdtype == CMDFUNCTION) {
-				*pp = cmdp->next;
-				freefunc(cmdp->param.func);
-				ckfree(cmdp);
-			} else {
-				pp = &cmdp->next;
-			}
-		}
-	}
-	INTON;
-}
-
-
-
-/*
- * Locate a command in the command hash table.  If "add" is nonzero,
- * add the command to the table if it is not already present.  The
- * variable "lastcmdentry" is set to point to the address of the link
- * pointing to the entry, so that delete_cmd_entry can delete the
- * entry.
- */
-
-struct tblentry **lastcmdentry;
-
-
-STATIC struct tblentry *
-cmdlookup(const char *name, int add)
-{
-	int hashval;
-	const char *p;
-	struct tblentry *cmdp;
-	struct tblentry **pp;
-
-	p = name;
-	hashval = *p << 4;
-	while (*p)
-		hashval += *p++;
-	hashval &= 0x7FFF;
-	pp = &cmdtable[hashval % CMDTABLESIZE];
-	for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
-		if (equal(cmdp->cmdname, name))
-			break;
-		pp = &cmdp->next;
-	}
-	if (add && cmdp == NULL) {
-		INTOFF;
-		cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
-					+ strlen(name) + 1);
-		cmdp->next = NULL;
-		cmdp->cmdtype = CMDUNKNOWN;
-		cmdp->rehash = 0;
-		strcpy(cmdp->cmdname, name);
-		INTON;
-	}
-	lastcmdentry = pp;
-	return cmdp;
-}
-
-/*
- * Delete the command entry returned on the last lookup.
- */
-
-STATIC void
-delete_cmd_entry(void)
-{
-	struct tblentry *cmdp;
-
-	INTOFF;
-	cmdp = *lastcmdentry;
-	*lastcmdentry = cmdp->next;
-	ckfree(cmdp);
-	INTON;
-}
-
-
-
-#ifdef notdef
-void
-getcmdentry(char *name, struct cmdentry *entry)
-{
-	struct tblentry *cmdp = cmdlookup(name, 0);
-
-	if (cmdp) {
-		entry->u = cmdp->param;
-		entry->cmdtype = cmdp->cmdtype;
-	} else {
-		entry->cmdtype = CMDUNKNOWN;
-		entry->u.index = 0;
-	}
-}
-#endif
-
-
-/*
- * Add a new command entry, replacing any existing command entry for
- * the same name - except special builtins.
- */
-
-STATIC void
-addcmdentry(char *name, struct cmdentry *entry)
-{
-	struct tblentry *cmdp;
-
-	INTOFF;
-	cmdp = cmdlookup(name, 1);
-	if (cmdp->cmdtype != CMDSPLBLTIN) {
-		if (cmdp->cmdtype == CMDFUNCTION) {
-			freefunc(cmdp->param.func);
-		}
-		cmdp->cmdtype = entry->cmdtype;
-		cmdp->param = entry->u;
-	}
-	INTON;
-}
-
-
-/*
- * Define a shell function.
- */
-
-void
-defun(char *name, union node *func)
-{
-	struct cmdentry entry;
-
-	INTOFF;
-	entry.cmdtype = CMDFUNCTION;
-	entry.u.func = copyfunc(func);
-	addcmdentry(name, &entry);
-	INTON;
-}
-
-
-/*
- * Delete a function if it exists.
- */
-
-int
-unsetfunc(char *name)
-{
-	struct tblentry *cmdp;
-
-	if ((cmdp = cmdlookup(name, 0)) != NULL &&
-	    cmdp->cmdtype == CMDFUNCTION) {
-		freefunc(cmdp->param.func);
-		delete_cmd_entry();
-		return (0);
-	}
-	return (1);
-}
-
-/*
- * Locate and print what a word is...
- * also used for 'command -[v|V]'
- */
-
-int
-typecmd(int argc, char **argv)
-{
-	struct cmdentry entry;
-	struct tblentry *cmdp;
-	char * const *pp;
-	struct alias *ap;
-	int err = 0;
-	char *arg;
-	int c;
-	int V_flag = 0;
-	int v_flag = 0;
-	int p_flag = 0;
-
-	while ((c = nextopt("vVp")) != 0) {
-		switch (c) {
-		case 'v': v_flag = 1; break;
-		case 'V': V_flag = 1; break;
-		case 'p': p_flag = 1; break;
-		}
-	}
-
-	if (p_flag && (v_flag || V_flag))
-		error("cannot specify -p with -v or -V");
-
-	while ((arg = *argptr++)) {
-		if (!v_flag)
-			out1str(arg);
-		/* First look at the keywords */
-		for (pp = parsekwd; *pp; pp++)
-			if (**pp == *arg && equal(*pp, arg))
-				break;
-
-		if (*pp) {
-			if (v_flag)
-				err = 1;
-			else
-				out1str(" is a shell keyword\n");
-			continue;
-		}
-
-		/* Then look at the aliases */
-		if ((ap = lookupalias(arg, 1)) != NULL) {
-			if (!v_flag)
-				out1fmt(" is an alias for \n");
-			out1fmt("%s\n", ap->val);
-			continue;
-		}
-
-		/* Then check if it is a tracked alias */
-		if ((cmdp = cmdlookup(arg, 0)) != NULL) {
-			entry.cmdtype = cmdp->cmdtype;
-			entry.u = cmdp->param;
-		} else {
-			/* Finally use brute force */
-			find_command(arg, &entry, DO_ABS, pathval());
-		}
-
-		switch (entry.cmdtype) {
-		case CMDNORMAL: {
-			if (strchr(arg, '/') == NULL) {
-				const char *path = pathval();
-				char *name;
-				int j = entry.u.index;
-				do {
-					name = padvance(&path, arg);
-					stunalloc(name);
-				} while (--j >= 0);
-				if (!v_flag)
-					out1fmt(" is%s ",
-					    cmdp ? " a tracked alias for" : "");
-				out1fmt("%s\n", name);
-			} else {
-				if (access(arg, X_OK) == 0) {
-					if (!v_flag)
-						out1fmt(" is ");
-					out1fmt("%s\n", arg);
-				} else {
-					if (!v_flag)
-						out1fmt(": %s\n",
-						    strerror(errno));
-					else
-						err = 126;
-				}
-			}
- 			break;
-		}
-		case CMDFUNCTION:
-			if (!v_flag)
-				out1str(" is a shell function\n");
-			else
-				out1fmt("%s\n", arg);
-			break;
-
-		case CMDBUILTIN:
-			if (!v_flag)
-				out1str(" is a shell builtin\n");
-			else
-				out1fmt("%s\n", arg);
-			break;
-
-		case CMDSPLBLTIN:
-			if (!v_flag)
-				out1str(" is a special shell builtin\n");
-			else
-				out1fmt("%s\n", arg);
-			break;
-
-		default:
-			if (!v_flag)
-				out1str(": not found\n");
-			err = 127;
-			break;
-		}
-	}
-	return err;
-}
diff --git a/sh/exec.h b/sh/exec.h
deleted file mode 100644
index 26fd09c..0000000
--- a/sh/exec.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*	$NetBSD: exec.h,v 1.21 2003/08/07 09:05:31 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)exec.h	8.3 (Berkeley) 6/8/95
- */
-
-/* values of cmdtype */
-#define CMDUNKNOWN	-1	/* no entry in table for command */
-#define CMDNORMAL	0	/* command is an executable program */
-#define CMDFUNCTION	1	/* command is a shell function */
-#define CMDBUILTIN	2	/* command is a shell builtin */
-#define CMDSPLBLTIN	3	/* command is a special shell builtin */
-
-
-struct cmdentry {
-	int cmdtype;
-	union param {
-		int index;
-		int (*bltin)(int, char**);
-		union node *func;
-	} u;
-};
-
-
-/* action to find_command() */
-#define DO_ERR		0x01	/* prints errors */
-#define DO_ABS		0x02	/* checks absolute paths */
-#define DO_NOFUNC	0x04	/* don't return shell functions, for command */
-#define DO_ALTPATH	0x08	/* using alternate path */
-#define DO_ALTBLTIN	0x20	/* %builtin in alt. path */
-
-extern const char *pathopt;	/* set by padvance */
-
-void shellexec(char **, char **, const char *, int, int)
-    __attribute__((__noreturn__));
-char *padvance(const char **, const char *);
-int hashcmd(int, char **);
-void find_command(char *, struct cmdentry *, int, const char *);
-int (*find_builtin(char *))(int, char **);
-int (*find_splbltin(char *))(int, char **);
-void hashcd(void);
-void changepath(const char *);
-void deletefuncs(void);
-void getcmdentry(char *, struct cmdentry *);
-void addcmdentry(char *, struct cmdentry *);
-void defun(char *, union node *);
-int unsetfunc(char *);
-int typecmd(int, char **);
-void hash_special_builtins(void);
diff --git a/sh/expand.c b/sh/expand.c
deleted file mode 100644
index d3462fc..0000000
--- a/sh/expand.c
+++ /dev/null
@@ -1,1559 +0,0 @@
-/*	$NetBSD: expand.c,v 1.68.2.2 2005/04/07 11:37:39 tron Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)expand.c	8.5 (Berkeley) 5/15/95";
-#else
-__RCSID("$NetBSD: expand.c,v 1.68.2.2 2005/04/07 11:37:39 tron Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-/*
- * Routines to expand arguments to commands.  We have to deal with
- * backquotes, shell variables, and file metacharacters.
- */
-
-#include "shell.h"
-#include "main.h"
-#include "nodes.h"
-#include "eval.h"
-#include "expand.h"
-#include "syntax.h"
-#include "parser.h"
-#include "jobs.h"
-#include "options.h"
-#include "var.h"
-#include "input.h"
-#include "output.h"
-#include "memalloc.h"
-#include "error.h"
-#include "mystring.h"
-#include "show.h"
-
-/*
- * Structure specifying which parts of the string should be searched
- * for IFS characters.
- */
-
-struct ifsregion {
-	struct ifsregion *next;	/* next region in list */
-	int begoff;		/* offset of start of region */
-	int endoff;		/* offset of end of region */
-	int inquotes;		/* search for nul bytes only */
-};
-
-
-char *expdest;			/* output of current string */
-struct nodelist *argbackq;	/* list of back quote expressions */
-struct ifsregion ifsfirst;	/* first struct in list of ifs regions */
-struct ifsregion *ifslastp;	/* last struct in list */
-struct arglist exparg;		/* holds expanded arg list */
-
-STATIC void argstr(char *, int);
-STATIC char *exptilde(char *, int);
-STATIC void expbackq(union node *, int, int);
-STATIC int subevalvar(char *, char *, int, int, int, int);
-STATIC char *evalvar(char *, int);
-STATIC int varisset(char *, int);
-STATIC void varvalue(char *, int, int, int);
-STATIC void recordregion(int, int, int);
-STATIC void removerecordregions(int); 
-STATIC void ifsbreakup(char *, struct arglist *);
-STATIC void ifsfree(void);
-STATIC void expandmeta(struct strlist *, int);
-STATIC void expmeta(char *, char *);
-STATIC void addfname(char *);
-STATIC struct strlist *expsort(struct strlist *);
-STATIC struct strlist *msort(struct strlist *, int);
-STATIC int pmatch(char *, char *, int);
-STATIC char *cvtnum(int, char *);
-
-/*
- * Expand shell variables and backquotes inside a here document.
- */
-
-void
-expandhere(union node *arg, int fd)
-{
-	herefd = fd;
-	expandarg(arg, (struct arglist *)NULL, 0);
-	xwrite(fd, stackblock(), expdest - stackblock());
-}
-
-
-/*
- * Perform variable substitution and command substitution on an argument,
- * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
- * perform splitting and file name expansion.  When arglist is NULL, perform
- * here document expansion.
- */
-
-void
-expandarg(union node *arg, struct arglist *arglist, int flag)
-{
-	struct strlist *sp;
-	char *p;
-
-	argbackq = arg->narg.backquote;
-	STARTSTACKSTR(expdest);
-	ifsfirst.next = NULL;
-	ifslastp = NULL;
-	argstr(arg->narg.text, flag);
-	if (arglist == NULL) {
-		return;			/* here document expanded */
-	}
-	STPUTC('\0', expdest);
-	p = grabstackstr(expdest);
-	exparg.lastp = &exparg.list;
-	/*
-	 * TODO - EXP_REDIR
-	 */
-	if (flag & EXP_FULL) {
-		ifsbreakup(p, &exparg);
-		*exparg.lastp = NULL;
-		exparg.lastp = &exparg.list;
-		expandmeta(exparg.list, flag);
-	} else {
-		if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
-			rmescapes(p);
-		sp = (struct strlist *)stalloc(sizeof (struct strlist));
-		sp->text = p;
-		*exparg.lastp = sp;
-		exparg.lastp = &sp->next;
-	}
-	ifsfree();
-	*exparg.lastp = NULL;
-	if (exparg.list) {
-		*arglist->lastp = exparg.list;
-		arglist->lastp = exparg.lastp;
-	}
-}
-
-
-
-/*
- * Perform variable and command substitution.
- * If EXP_FULL is set, output CTLESC characters to allow for further processing.
- * Otherwise treat $@ like $* since no splitting will be performed.
- */
-
-STATIC void
-argstr(char *p, int flag)
-{
-	char c;
-	int quotes = flag & (EXP_FULL | EXP_CASE);	/* do CTLESC */
-	int firsteq = 1;
-	const char *ifs = 0;
-	int ifs_split = EXP_IFS_SPLIT;
-
-	if (flag & EXP_IFS_SPLIT)
-		ifs = ifsset() ? ifsval() : " \t\n";
-
-	if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
-		p = exptilde(p, flag);
-	for (;;) {
-		switch (c = *p++) {
-		case '\0':
-		case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */
-			return;
-		case CTLQUOTEMARK:
-			/* "$@" syntax adherence hack */
-			if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
-				break;
-			if ((flag & EXP_FULL) != 0)
-				STPUTC(c, expdest);
-			ifs_split = 0;
-			break;
-		case CTLQUOTEEND:
-			ifs_split = EXP_IFS_SPLIT;
-			break;
-		case CTLESC:
-			if (quotes)
-				STPUTC(c, expdest);
-			c = *p++;
-			STPUTC(c, expdest);
-			break;
-		case CTLVAR:
-			p = evalvar(p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split));
-			break;
-		case CTLBACKQ:
-		case CTLBACKQ|CTLQUOTE:
-			expbackq(argbackq->n, c & CTLQUOTE, flag);
-			argbackq = argbackq->next;
-			break;
-		case CTLENDARI:
-			expari(flag);
-			break;
-		case ':':
-		case '=':
-			/*
-			 * sort of a hack - expand tildes in variable
-			 * assignments (after the first '=' and after ':'s).
-			 */
-			STPUTC(c, expdest);
-			if (flag & EXP_VARTILDE && *p == '~') {
-				if (c == '=') {
-					if (firsteq)
-						firsteq = 0;
-					else
-						break;
-				}
-				p = exptilde(p, flag);
-			}
-			break;
-		default:
-			STPUTC(c, expdest);
-			if (flag & EXP_IFS_SPLIT & ifs_split && strchr(ifs, c) != NULL) {
-				/* We need to get the output split here... */
-				recordregion(expdest - stackblock() - 1,
-						expdest - stackblock(), 0);
-			}
-			break;
-		}
-	}
-}
-
-STATIC char *
-exptilde(char *p, int flag)
-{
-	char c, *startp = p;
-	const char *home;
-	int quotes = flag & (EXP_FULL | EXP_CASE);
-
-	while ((c = *p) != '\0') {
-		switch(c) {
-		case CTLESC:
-			return (startp);
-		case CTLQUOTEMARK:
-			return (startp);
-		case ':':
-			if (flag & EXP_VARTILDE)
-				goto done;
-			break;
-		case '/':
-			goto done;
-		}
-		p++;
-	}
-done:
-	*p = '\0';
-	if (*(startp+1) == '\0') {
-		if ((home = lookupvar("HOME")) == NULL)
-			goto lose;
-	} else
-        	goto lose;
-	if (*home == '\0')
-		goto lose;
-	*p = c;
-	while ((c = *home++) != '\0') {
-		if (quotes && SQSYNTAX[(int)c] == CCTL)
-			STPUTC(CTLESC, expdest);
-		STPUTC(c, expdest);
-	}
-	return (p);
-lose:
-	*p = c;
-	return (startp);
-}
-
-
-STATIC void 
-removerecordregions(int endoff)
-{
-	if (ifslastp == NULL)
-		return;
-
-	if (ifsfirst.endoff > endoff) {
-		while (ifsfirst.next != NULL) {
-			struct ifsregion *ifsp;
-			INTOFF;
-			ifsp = ifsfirst.next->next;
-			ckfree(ifsfirst.next);
-			ifsfirst.next = ifsp;
-			INTON;
-		}
-		if (ifsfirst.begoff > endoff)
-			ifslastp = NULL;
-		else {
-			ifslastp = &ifsfirst;
-			ifsfirst.endoff = endoff;
-		}
-		return;
-	}
-	
-	ifslastp = &ifsfirst;
-	while (ifslastp->next && ifslastp->next->begoff < endoff)
-		ifslastp=ifslastp->next;
-	while (ifslastp->next != NULL) {
-		struct ifsregion *ifsp;
-		INTOFF;
-		ifsp = ifslastp->next->next;
-		ckfree(ifslastp->next);
-		ifslastp->next = ifsp;
-		INTON;
-	}
-	if (ifslastp->endoff > endoff)
-		ifslastp->endoff = endoff;
-}
-
-
-/*
- * Expand arithmetic expression.  Backup to start of expression,
- * evaluate, place result in (backed up) result, adjust string position.
- */
-void
-expari(int flag)
-{
-	char *p, *start;
-	int result;
-	int begoff;
-	int quotes = flag & (EXP_FULL | EXP_CASE);
-	int quoted;
-
-	/*	ifsfree(); */
-
-	/*
-	 * This routine is slightly over-complicated for
-	 * efficiency.  First we make sure there is
-	 * enough space for the result, which may be bigger
-	 * than the expression if we add exponentation.  Next we
-	 * scan backwards looking for the start of arithmetic.  If the
-	 * next previous character is a CTLESC character, then we
-	 * have to rescan starting from the beginning since CTLESC
-	 * characters have to be processed left to right.
-	 */
-#if INT_MAX / 1000000000 >= 10 || INT_MIN / 1000000000 <= -10
-#error "integers with more than 10 digits are not supported"
-#endif
-	CHECKSTRSPACE(12 - 2, expdest);
-	USTPUTC('\0', expdest);
-	start = stackblock();
-	p = expdest - 1;
-	while (*p != CTLARI && p >= start)
-		--p;
-	if (*p != CTLARI)
-		error("missing CTLARI (shouldn't happen)");
-	if (p > start && *(p-1) == CTLESC)
-		for (p = start; *p != CTLARI; p++)
-			if (*p == CTLESC)
-				p++;
-
-	if (p[1] == '"')
-		quoted=1;
-	else
-		quoted=0;
-	begoff = p - start;
-	removerecordregions(begoff);
-	if (quotes)
-		rmescapes(p+2);
-	result = arith(p+2);
-	fmtstr(p, 12, "%d", result);
-
-	while (*p++)
-		;
-
-	if (quoted == 0)
-		recordregion(begoff, p - 1 - start, 0);
-	result = expdest - p + 1;
-	STADJUST(-result, expdest);
-}
-
-
-/*
- * Expand stuff in backwards quotes.
- */
-
-STATIC void
-expbackq(union node *cmd, int quoted, int flag)
-{
-	struct backcmd in;
-	int i;
-	char buf[128];
-	char *p;
-	char *dest = expdest;
-	struct ifsregion saveifs, *savelastp;
-	struct nodelist *saveargbackq;
-	char lastc;
-	int startloc = dest - stackblock();
-	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
-	int saveherefd;
-	int quotes = flag & (EXP_FULL | EXP_CASE);
-
-	INTOFF;
-	saveifs = ifsfirst;
-	savelastp = ifslastp;
-	saveargbackq = argbackq;
-	saveherefd = herefd;
-	herefd = -1;
-	p = grabstackstr(dest);
-	evalbackcmd(cmd, &in);
-	ungrabstackstr(p, dest);
-	ifsfirst = saveifs;
-	ifslastp = savelastp;
-	argbackq = saveargbackq;
-	herefd = saveherefd;
-
-	p = in.buf;
-	lastc = '\0';
-	for (;;) {
-		if (--in.nleft < 0) {
-			if (in.fd < 0)
-				break;
-			while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
-			TRACE(("expbackq: read returns %d\n", i));
-			if (i <= 0)
-				break;
-			p = buf;
-			in.nleft = i - 1;
-		}
-		lastc = *p++;
-		if (lastc != '\0') {
-			if (quotes && syntax[(int)lastc] == CCTL)
-				STPUTC(CTLESC, dest);
-			STPUTC(lastc, dest);
-		}
-	}
-
-	/* Eat all trailing newlines */
-	p = stackblock() + startloc;
-	while (dest > p && dest[-1] == '\n')
-		STUNPUTC(dest);
-
-	if (in.fd >= 0)
-		close(in.fd);
-	if (in.buf)
-		ckfree(in.buf);
-	if (in.jp)
-		back_exitstatus = waitforjob(in.jp);
-	if (quoted == 0)
-		recordregion(startloc, dest - stackblock(), 0);
-	TRACE(("evalbackq: size=%d: \"%.*s\"\n",
-		(dest - stackblock()) - startloc,
-		(dest - stackblock()) - startloc,
-		stackblock() + startloc));
-	expdest = dest;
-	INTON;
-}
-
-
-
-STATIC int
-subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags)
-{
-	char *startp;
-	char *loc = NULL;
-	char *q;
-	int c = 0;
-	int saveherefd = herefd;
-	struct nodelist *saveargbackq = argbackq;
-	int amount;
-
-	herefd = -1;
-	argstr(p, 0);
-	STACKSTRNUL(expdest);
-	herefd = saveherefd;
-	argbackq = saveargbackq;
-	startp = stackblock() + startloc;
-	if (str == NULL)
-	    str = stackblock() + strloc;
-
-	switch (subtype) {
-	case VSASSIGN:
-		setvar(str, startp, 0);
-		amount = startp - expdest;
-		STADJUST(amount, expdest);
-		varflags &= ~VSNUL;
-		if (c != 0)
-			*loc = c;
-		return 1;
-
-	case VSQUESTION:
-		if (*p != CTLENDVAR) {
-			outfmt(&errout, "%s\n", startp);
-			error((char *)NULL);
-		}
-		error("%.*s: parameter %snot set", p - str - 1,
-		      str, (varflags & VSNUL) ? "null or "
-					      : nullstr);
-		/* NOTREACHED */
-
-	case VSTRIMLEFT:
-		for (loc = startp; loc < str; loc++) {
-			c = *loc;
-			*loc = '\0';
-			if (patmatch(str, startp, varflags & VSQUOTE))
-				goto recordleft;
-			*loc = c;
-			if ((varflags & VSQUOTE) && *loc == CTLESC)
-			        loc++;
-		}
-		return 0;
-
-	case VSTRIMLEFTMAX:
-		for (loc = str - 1; loc >= startp;) {
-			c = *loc;
-			*loc = '\0';
-			if (patmatch(str, startp, varflags & VSQUOTE))
-				goto recordleft;
-			*loc = c;
-			loc--;
-			if ((varflags & VSQUOTE) && loc > startp &&
-			    *(loc - 1) == CTLESC) {
-				for (q = startp; q < loc; q++)
-					if (*q == CTLESC)
-						q++;
-				if (q > loc)
-					loc--;
-			}
-		}
-		return 0;
-
-	case VSTRIMRIGHT:
-	        for (loc = str - 1; loc >= startp;) {
-			if (patmatch(str, loc, varflags & VSQUOTE))
-				goto recordright;
-			loc--;
-			if ((varflags & VSQUOTE) && loc > startp &&
-			    *(loc - 1) == CTLESC) { 
-				for (q = startp; q < loc; q++)
-					if (*q == CTLESC)
-						q++;
-				if (q > loc)
-					loc--;
-			}
-		}
-		return 0;
-
-	case VSTRIMRIGHTMAX:
-		for (loc = startp; loc < str - 1; loc++) {
-			if (patmatch(str, loc, varflags & VSQUOTE))
-				goto recordright;
-			if ((varflags & VSQUOTE) && *loc == CTLESC)
-			        loc++;
-		}
-		return 0;
-
-	default:
-		abort();
-	}
-
-recordleft:
-	*loc = c;
-	amount = ((str - 1) - (loc - startp)) - expdest;
-	STADJUST(amount, expdest);
-	while (loc != str - 1)
-		*startp++ = *loc++;
-	return 1;
-
-recordright:
-	amount = loc - expdest;
-	STADJUST(amount, expdest);
-	STPUTC('\0', expdest);
-	STADJUST(-1, expdest);
-	return 1;
-}
-
-
-/*
- * Expand a variable, and return a pointer to the next character in the
- * input string.
- */
-
-STATIC char *
-evalvar(char *p, int flag)
-{
-	int subtype;
-	int varflags;
-	char *var;
-	char *val;
-	int patloc;
-	int c;
-	int set;
-	int special;
-	int startloc;
-	int varlen;
-	int apply_ifs;
-	int quotes = flag & (EXP_FULL | EXP_CASE);
-
-	varflags = (unsigned char)*p++;
-	subtype = varflags & VSTYPE;
-	var = p;
-	special = !is_name(*p);
-	p = strchr(p, '=') + 1;
-
-again: /* jump here after setting a variable with ${var=text} */
-	if (special) {
-		set = varisset(var, varflags & VSNUL);
-		val = NULL;
-	} else {
-		val = lookupvar(var);
-		if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
-			val = NULL;
-			set = 0;
-		} else
-			set = 1;
-	}
-
-	varlen = 0;
-	startloc = expdest - stackblock();
-
-	if (!set && uflag) {
-		switch (subtype) {
-		case VSNORMAL:
-		case VSTRIMLEFT:
-		case VSTRIMLEFTMAX:
-		case VSTRIMRIGHT:
-		case VSTRIMRIGHTMAX:
-		case VSLENGTH:
-			error("%.*s: parameter not set", p - var - 1, var);
-			/* NOTREACHED */
-		}
-	}
-
-	if (set && subtype != VSPLUS) {
-		/* insert the value of the variable */
-		if (special) {
-			varvalue(var, varflags & VSQUOTE, subtype, flag);
-			if (subtype == VSLENGTH) {
-				varlen = expdest - stackblock() - startloc;
-				STADJUST(-varlen, expdest);
-			}
-		} else {
-			char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
-								  : BASESYNTAX;
-
-			if (subtype == VSLENGTH) {
-				for (;*val; val++)
-					varlen++;
-			} else {
-				while (*val) {
-					if (quotes && syntax[(int)*val] == CCTL)
-						STPUTC(CTLESC, expdest);
-					STPUTC(*val++, expdest);
-				}
-
-			}
-		}
-	}
-
-
-	apply_ifs = ((varflags & VSQUOTE) == 0 ||
-		(*var == '@' && shellparam.nparam != 1));
-
-	switch (subtype) {
-	case VSLENGTH:
-		expdest = cvtnum(varlen, expdest);
-		break;
-
-	case VSNORMAL:
-		break;
-
-	case VSPLUS:
-		set = !set;
-		/* FALLTHROUGH */
-	case VSMINUS:
-		if (!set) {
-		        argstr(p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0));
-			/*
-			 * ${x-a b c} doesn't get split, but removing the
-			 * 'apply_ifs = 0' apparantly breaks ${1+"$@"}..
-			 * ${x-'a b' c} should generate 2 args.
-			 */
-			/* We should have marked stuff already */
-			apply_ifs = 0;
-		}
-		break;
-
-	case VSTRIMLEFT:
-	case VSTRIMLEFTMAX:
-	case VSTRIMRIGHT:
-	case VSTRIMRIGHTMAX:
-		if (!set)
-			break;
-		/*
-		 * Terminate the string and start recording the pattern
-		 * right after it
-		 */
-		STPUTC('\0', expdest);
-		patloc = expdest - stackblock();
-		if (subevalvar(p, NULL, patloc, subtype,
-			       startloc, varflags) == 0) {
-			int amount = (expdest - stackblock() - patloc) + 1;
-			STADJUST(-amount, expdest);
-		}
-		/* Remove any recorded regions beyond start of variable */
-		removerecordregions(startloc);
-		apply_ifs = 1;
-		break;
-
-	case VSASSIGN:
-	case VSQUESTION:
-		if (set)
-			break;
-		if (subevalvar(p, var, 0, subtype, startloc, varflags)) {
-			varflags &= ~VSNUL;
-			/* 
-			 * Remove any recorded regions beyond 
-			 * start of variable 
-			 */
-			removerecordregions(startloc);
-			goto again;
-		}
-		apply_ifs = 0;
-		break;
-
-	default:
-		abort();
-	}
-
-	if (apply_ifs)
-		recordregion(startloc, expdest - stackblock(),
-			     varflags & VSQUOTE);
-
-	if (subtype != VSNORMAL) {	/* skip to end of alternative */
-		int nesting = 1;
-		for (;;) {
-			if ((c = *p++) == CTLESC)
-				p++;
-			else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
-				if (set)
-					argbackq = argbackq->next;
-			} else if (c == CTLVAR) {
-				if ((*p++ & VSTYPE) != VSNORMAL)
-					nesting++;
-			} else if (c == CTLENDVAR) {
-				if (--nesting == 0)
-					break;
-			}
-		}
-	}
-	return p;
-}
-
-
-
-/*
- * Test whether a specialized variable is set.
- */
-
-STATIC int
-varisset(char *name, int nulok)
-{
-	if (*name == '!')
-		return backgndpid != -1;
-	else if (*name == '@' || *name == '*') {
-		if (*shellparam.p == NULL)
-			return 0;
-
-		if (nulok) {
-			char **av;
-
-			for (av = shellparam.p; *av; av++)
-				if (**av != '\0')
-					return 1;
-			return 0;
-		}
-	} else if (is_digit(*name)) {
-		char *ap;
-		int num = atoi(name);
-
-		if (num > shellparam.nparam)
-			return 0;
-
-		if (num == 0)
-			ap = arg0;
-		else
-			ap = shellparam.p[num - 1];
-
-		if (nulok && (ap == NULL || *ap == '\0'))
-			return 0;
-	}
-	return 1;
-}
-
-
-
-/*
- * Add the value of a specialized variable to the stack string.
- */
-
-STATIC void
-varvalue(char *name, int quoted, int subtype, int flag)
-{
-	int num;
-	char *p;
-	int i;
-	char sep;
-	char **ap;
-	char const *syntax;
-
-#define STRTODEST(p) \
-	do {\
-	if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \
-		syntax = quoted? DQSYNTAX : BASESYNTAX; \
-		while (*p) { \
-			if (syntax[(int)*p] == CCTL) \
-				STPUTC(CTLESC, expdest); \
-			STPUTC(*p++, expdest); \
-		} \
-	} else \
-		while (*p) \
-			STPUTC(*p++, expdest); \
-	} while (0)
-
-
-	switch (*name) {
-	case '$':
-		num = rootpid;
-		goto numvar;
-	case '?':
-		num = exitstatus;
-		goto numvar;
-	case '#':
-		num = shellparam.nparam;
-		goto numvar;
-	case '!':
-		num = backgndpid;
-numvar:
-		expdest = cvtnum(num, expdest);
-		break;
-	case '-':
-		for (i = 0; optlist[i].name; i++) {
-			if (optlist[i].val)
-				STPUTC(optlist[i].letter, expdest);
-		}
-		break;
-	case '@':
-		if (flag & EXP_FULL && quoted) {
-			for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
-				STRTODEST(p);
-				if (*ap)
-					STPUTC('\0', expdest);
-			}
-			break;
-		}
-		/* fall through */
-	case '*':
-		if (ifsset() != 0)
-			sep = ifsval()[0];
-		else
-			sep = ' ';
-		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
-			STRTODEST(p);
-			if (*ap && sep)
-				STPUTC(sep, expdest);
-		}
-		break;
-	case '0':
-		p = arg0;
-		STRTODEST(p);
-		break;
-	default:
-		if (is_digit(*name)) {
-			num = atoi(name);
-			if (num > 0 && num <= shellparam.nparam) {
-				p = shellparam.p[num - 1];
-				STRTODEST(p);
-			}
-		}
-		break;
-	}
-}
-
-
-
-/*
- * Record the fact that we have to scan this region of the
- * string for IFS characters.
- */
-
-STATIC void
-recordregion(int start, int end, int inquotes)
-{
-	struct ifsregion *ifsp;
-
-	if (ifslastp == NULL) {
-		ifsp = &ifsfirst;
-	} else {
-		if (ifslastp->endoff == start
-		    && ifslastp->inquotes == inquotes) {
-			/* extend previous area */
-			ifslastp->endoff = end;
-			return;
-		}
-		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
-		ifslastp->next = ifsp;
-	}
-	ifslastp = ifsp;
-	ifslastp->next = NULL;
-	ifslastp->begoff = start;
-	ifslastp->endoff = end;
-	ifslastp->inquotes = inquotes;
-}
-
-
-
-/*
- * Break the argument string into pieces based upon IFS and add the
- * strings to the argument list.  The regions of the string to be
- * searched for IFS characters have been stored by recordregion.
- */
-STATIC void
-ifsbreakup(char *string, struct arglist *arglist)
-{
-	struct ifsregion *ifsp;
-	struct strlist *sp;
-	char *start;
-	char *p;
-	char *q;
-	const char *ifs;
-	const char *ifsspc;
-	int inquotes;
-
-	start = string;
-	ifsspc = NULL;
-	inquotes = 0;
-
-	if (ifslastp == NULL) {
-		/* Return entire argument, IFS doesn't apply to any of it */
-		sp = (struct strlist *)stalloc(sizeof *sp);
-		sp->text = start;
-		*arglist->lastp = sp;
-		arglist->lastp = &sp->next;
-		return;
-	}
-
-	ifs = ifsset() ? ifsval() : " \t\n";
-
-	for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
-		p = string + ifsp->begoff;
-		inquotes = ifsp->inquotes;
-		ifsspc = NULL;
-		while (p < string + ifsp->endoff) {
-			q = p;
-			if (*p == CTLESC)
-				p++;
-			if (inquotes) {
-				/* Only NULs (probably from "$@") end args */
-				if (*p != 0) {
-					p++;
-					continue;
-				}
-			} else {
-				if (!strchr(ifs, *p)) {
-					p++;
-					continue;
-				}
-				ifsspc = strchr(" \t\n", *p);
-
-				/* Ignore IFS whitespace at start */
-				if (q == start && ifsspc != NULL) {
-					p++;
-					start = p;
-					continue;
-				}
-			}
-
-			/* Save this argument... */
-			*q = '\0';
-			sp = (struct strlist *)stalloc(sizeof *sp);
-			sp->text = start;
-			*arglist->lastp = sp;
-			arglist->lastp = &sp->next;
-			p++;
-
-			if (ifsspc != NULL) {
-				/* Ignore further trailing IFS whitespace */
-				for (; p < string + ifsp->endoff; p++) {
-					q = p;
-					if (*p == CTLESC)
-						p++;
-					if (strchr(ifs, *p) == NULL) {
-						p = q;
-						break;
-					}
-					if (strchr(" \t\n", *p) == NULL) {
-						p++;
-						break;
-					}
-				}
-			}
-			start = p;
-		}
-	}
-
-	/*
-	 * Save anything left as an argument.
-	 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as
-	 * generating 2 arguments, the second of which is empty.
-	 * Some recent clarification of the Posix spec say that it
-	 * should only generate one....
-	 */
-	if (*start /* || (!ifsspc && start > string) */) {
-		sp = (struct strlist *)stalloc(sizeof *sp);
-		sp->text = start;
-		*arglist->lastp = sp;
-		arglist->lastp = &sp->next;
-	}
-}
-
-STATIC void
-ifsfree(void)
-{
-	while (ifsfirst.next != NULL) {
-		struct ifsregion *ifsp;
-		INTOFF;
-		ifsp = ifsfirst.next->next;
-		ckfree(ifsfirst.next);
-		ifsfirst.next = ifsp;
-		INTON;
-	}
-	ifslastp = NULL;
-	ifsfirst.next = NULL;
-}
-
-
-
-/*
- * Expand shell metacharacters.  At this point, the only control characters
- * should be escapes.  The results are stored in the list exparg.
- */
-
-char *expdir;
-
-
-STATIC void
-expandmeta(struct strlist *str, int flag)
-{
-	char *p;
-	struct strlist **savelastp;
-	struct strlist *sp;
-	char c;
-	/* TODO - EXP_REDIR */
-
-	while (str) {
-		if (fflag)
-			goto nometa;
-		p = str->text;
-		for (;;) {			/* fast check for meta chars */
-			if ((c = *p++) == '\0')
-				goto nometa;
-			if (c == '*' || c == '?' || c == '[' || c == '!')
-				break;
-		}
-		savelastp = exparg.lastp;
-		INTOFF;
-		if (expdir == NULL) {
-			int i = strlen(str->text);
-			expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
-		}
-
-		expmeta(expdir, str->text);
-		ckfree(expdir);
-		expdir = NULL;
-		INTON;
-		if (exparg.lastp == savelastp) {
-			/*
-			 * no matches
-			 */
-nometa:
-			*exparg.lastp = str;
-			rmescapes(str->text);
-			exparg.lastp = &str->next;
-		} else {
-			*exparg.lastp = NULL;
-			*savelastp = sp = expsort(*savelastp);
-			while (sp->next != NULL)
-				sp = sp->next;
-			exparg.lastp = &sp->next;
-		}
-		str = str->next;
-	}
-}
-
-
-/*
- * Do metacharacter (i.e. *, ?, [...]) expansion.
- */
-
-STATIC void
-expmeta(char *enddir, char *name)
-{
-	char *p;
-	const char *cp;
-	char *q;
-	char *start;
-	char *endname;
-	int metaflag;
-	struct stat statb;
-	DIR *dirp;
-	struct dirent *dp;
-	int atend;
-	int matchdot;
-
-	metaflag = 0;
-	start = name;
-	for (p = name ; ; p++) {
-		if (*p == '*' || *p == '?')
-			metaflag = 1;
-		else if (*p == '[') {
-			q = p + 1;
-			if (*q == '!')
-				q++;
-			for (;;) {
-				while (*q == CTLQUOTEMARK)
-					q++;
-				if (*q == CTLESC)
-					q++;
-				if (*q == '/' || *q == '\0')
-					break;
-				if (*++q == ']') {
-					metaflag = 1;
-					break;
-				}
-			}
-		} else if (*p == '!' && p[1] == '!'	&& (p == name || p[-1] == '/')) {
-			metaflag = 1;
-		} else if (*p == '\0')
-			break;
-		else if (*p == CTLQUOTEMARK)
-			continue;
-		else if (*p == CTLESC)
-			p++;
-		if (*p == '/') {
-			if (metaflag)
-				break;
-			start = p + 1;
-		}
-	}
-	if (metaflag == 0) {	/* we've reached the end of the file name */
-		if (enddir != expdir)
-			metaflag++;
-		for (p = name ; ; p++) {
-			if (*p == CTLQUOTEMARK)
-				continue;
-			if (*p == CTLESC)
-				p++;
-			*enddir++ = *p;
-			if (*p == '\0')
-				break;
-		}
-		if (metaflag == 0 || lstat(expdir, &statb) >= 0)
-			addfname(expdir);
-		return;
-	}
-	endname = p;
-	if (start != name) {
-		p = name;
-		while (p < start) {
-			while (*p == CTLQUOTEMARK)
-				p++;
-			if (*p == CTLESC)
-				p++;
-			*enddir++ = *p++;
-		}
-	}
-	if (enddir == expdir) {
-		cp = ".";
-	} else if (enddir == expdir + 1 && *expdir == '/') {
-		cp = "/";
-	} else {
-		cp = expdir;
-		enddir[-1] = '\0';
-	}
-	if ((dirp = opendir(cp)) == NULL)
-		return;
-	if (enddir != expdir)
-		enddir[-1] = '/';
-	if (*endname == 0) {
-		atend = 1;
-	} else {
-		atend = 0;
-		*endname++ = '\0';
-	}
-	matchdot = 0;
-	p = start;
-	while (*p == CTLQUOTEMARK)
-		p++;
-	if (*p == CTLESC)
-		p++;
-	if (*p == '.')
-		matchdot++;
-	while (! int_pending() && (dp = readdir(dirp)) != NULL) {
-		if (dp->d_name[0] == '.' && ! matchdot)
-			continue;
-		if (patmatch(start, dp->d_name, 0)) {
-			if (atend) {
-				scopy(dp->d_name, enddir);
-				addfname(expdir);
-			} else {
-				for (p = enddir, cp = dp->d_name;
-				     (*p++ = *cp++) != '\0';)
-					continue;
-				p[-1] = '/';
-				expmeta(p, endname);
-			}
-		}
-	}
-	closedir(dirp);
-	if (! atend)
-		endname[-1] = '/';
-}
-
-
-/*
- * Add a file name to the list.
- */
-
-STATIC void
-addfname(char *name)
-{
-	char *p;
-	struct strlist *sp;
-
-	p = stalloc(strlen(name) + 1);
-	scopy(name, p);
-	sp = (struct strlist *)stalloc(sizeof *sp);
-	sp->text = p;
-	*exparg.lastp = sp;
-	exparg.lastp = &sp->next;
-}
-
-
-/*
- * Sort the results of file name expansion.  It calculates the number of
- * strings to sort and then calls msort (short for merge sort) to do the
- * work.
- */
-
-STATIC struct strlist *
-expsort(struct strlist *str)
-{
-	int len;
-	struct strlist *sp;
-
-	len = 0;
-	for (sp = str ; sp ; sp = sp->next)
-		len++;
-	return msort(str, len);
-}
-
-
-STATIC struct strlist *
-msort(struct strlist *list, int len)
-{
-	struct strlist *p, *q = NULL;
-	struct strlist **lpp;
-	int half;
-	int n;
-
-	if (len <= 1)
-		return list;
-	half = len >> 1;
-	p = list;
-	for (n = half ; --n >= 0 ; ) {
-		q = p;
-		p = p->next;
-	}
-	q->next = NULL;			/* terminate first half of list */
-	q = msort(list, half);		/* sort first half of list */
-	p = msort(p, len - half);		/* sort second half */
-	lpp = &list;
-	for (;;) {
-		if (strcmp(p->text, q->text) < 0) {
-			*lpp = p;
-			lpp = &p->next;
-			if ((p = *lpp) == NULL) {
-				*lpp = q;
-				break;
-			}
-		} else {
-			*lpp = q;
-			lpp = &q->next;
-			if ((q = *lpp) == NULL) {
-				*lpp = p;
-				break;
-			}
-		}
-	}
-	return list;
-}
-
-
-
-/*
- * Returns true if the pattern matches the string.
- */
-
-int
-patmatch(char *pattern, char *string, int squoted)
-{
-#ifdef notdef
-	if (pattern[0] == '!' && pattern[1] == '!')
-		return 1 - pmatch(pattern + 2, string);
-	else
-#endif
-		return pmatch(pattern, string, squoted);
-}
-
-
-STATIC int
-pmatch(char *pattern, char *string, int squoted)
-{
-	char *p, *q;
-	char c;
-
-	p = pattern;
-	q = string;
-	for (;;) {
-		switch (c = *p++) {
-		case '\0':
-			goto breakloop;
-		case CTLESC:
-			if (squoted && *q == CTLESC)
-				q++;
-			if (*q++ != *p++)
-				return 0;
-			break;
-		case CTLQUOTEMARK:
-			continue;
-		case '?':
-			if (squoted && *q == CTLESC)
-				q++;
-			if (*q++ == '\0')
-				return 0;
-			break;
-		case '*':
-			c = *p;
-			while (c == CTLQUOTEMARK || c == '*')
-				c = *++p;
-			if (c != CTLESC &&  c != CTLQUOTEMARK &&
-			    c != '?' && c != '*' && c != '[') {
-				while (*q != c) {
-					if (squoted && *q == CTLESC &&
-					    q[1] == c)
-						break;
-					if (*q == '\0')
-						return 0;
-					if (squoted && *q == CTLESC)
-						q++;
-					q++;
-				}
-			}
-			do {
-				if (pmatch(p, q, squoted))
-					return 1;
-				if (squoted && *q == CTLESC)
-					q++;
-			} while (*q++ != '\0');
-			return 0;
-		case '[': {
-			char *endp;
-			int invert, found;
-			char chr;
-
-			endp = p;
-			if (*endp == '!')
-				endp++;
-			for (;;) {
-				while (*endp == CTLQUOTEMARK)
-					endp++;
-				if (*endp == '\0')
-					goto dft;		/* no matching ] */
-				if (*endp == CTLESC)
-					endp++;
-				if (*++endp == ']')
-					break;
-			}
-			invert = 0;
-			if (*p == '!') {
-				invert++;
-				p++;
-			}
-			found = 0;
-			chr = *q++;
-			if (squoted && chr == CTLESC)
-				chr = *q++;
-			if (chr == '\0')
-				return 0;
-			c = *p++;
-			do {
-				if (c == CTLQUOTEMARK)
-					continue;
-				if (c == CTLESC)
-					c = *p++;
-				if (*p == '-' && p[1] != ']') {
-					p++;
-					while (*p == CTLQUOTEMARK)
-						p++;
-					if (*p == CTLESC)
-						p++;
-					if (chr >= c && chr <= *p)
-						found = 1;
-					p++;
-				} else {
-					if (chr == c)
-						found = 1;
-				}
-			} while ((c = *p++) != ']');
-			if (found == invert)
-				return 0;
-			break;
-		}
-dft:	        default:
-			if (squoted && *q == CTLESC)
-				q++;
-			if (*q++ != c)
-				return 0;
-			break;
-		}
-	}
-breakloop:
-	if (*q != '\0')
-		return 0;
-	return 1;
-}
-
-
-
-/*
- * Remove any CTLESC characters from a string.
- */
-
-void
-rmescapes(char *str)
-{
-	char *p, *q;
-
-	p = str;
-	while (*p != CTLESC && *p != CTLQUOTEMARK) {
-		if (*p++ == '\0')
-			return;
-	}
-	q = p;
-	while (*p) {
-		if (*p == CTLQUOTEMARK) {
-			p++;
-			continue;
-		}
-		if (*p == CTLESC)
-			p++;
-		*q++ = *p++;
-	}
-	*q = '\0';
-}
-
-
-
-/*
- * See if a pattern matches in a case statement.
- */
-
-int
-casematch(union node *pattern, char *val)
-{
-	struct stackmark smark;
-	int result;
-	char *p;
-
-	setstackmark(&smark);
-	argbackq = pattern->narg.backquote;
-	STARTSTACKSTR(expdest);
-	ifslastp = NULL;
-	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
-	STPUTC('\0', expdest);
-	p = grabstackstr(expdest);
-	result = patmatch(p, val, 0);
-	popstackmark(&smark);
-	return result;
-}
-
-/*
- * Our own itoa().
- */
-
-STATIC char *
-cvtnum(int num, char *buf)
-{
-	char temp[32];
-	int neg = num < 0;
-	char *p = temp + 31;
-
-	temp[31] = '\0';
-
-	do {
-		*--p = num % 10 + '0';
-	} while ((num /= 10) != 0);
-
-	if (neg)
-		*--p = '-';
-
-	while (*p)
-		STPUTC(*p++, buf);
-	return buf;
-}
-
-/*
- * Do most of the work for wordexp(3).
- */
-
-int
-wordexpcmd(int argc, char **argv)
-{
-	size_t len;
-	int i;
-
-	out1fmt("%d", argc - 1);
-	out1c('\0');
-	for (i = 1, len = 0; i < argc; i++)
-		len += strlen(argv[i]);
-	out1fmt("%zd", len);
-	out1c('\0');
-	for (i = 1; i < argc; i++) {
-		out1str(argv[i]);
-		out1c('\0');
-	}
-	return (0);
-}
diff --git a/sh/expand.h b/sh/expand.h
deleted file mode 100644
index 1ea876d..0000000
--- a/sh/expand.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*	$NetBSD: expand.h,v 1.16 2004/07/13 15:05:59 seb Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)expand.h	8.2 (Berkeley) 5/4/95
- */
-
-struct strlist {
-	struct strlist *next;
-	char *text;
-};
-
-
-struct arglist {
-	struct strlist *list;
-	struct strlist **lastp;
-};
-
-/*
- * expandarg() flags
- */
-#define EXP_FULL	0x1	/* perform word splitting & file globbing */
-#define EXP_TILDE	0x2	/* do normal tilde expansion */
-#define	EXP_VARTILDE	0x4	/* expand tildes in an assignment */
-#define	EXP_REDIR	0x8	/* file glob for a redirection (1 match only) */
-#define EXP_CASE	0x10	/* keeps quotes around for CASE pattern */
-#define EXP_IFS_SPLIT	0x20	/* need to record arguments for ifs breakup */
-
-
-union node;
-void expandhere(union node *, int);
-void expandarg(union node *, struct arglist *, int);
-void expari(int);
-int patmatch(char *, char *, int);
-void rmescapes(char *);
-int casematch(union node *, char *);
-int wordexpcmd(int, char **);
-
-/* From arith.y */
-int arith(const char *);
-int expcmd(int , char **);
-void arith_lex_reset(void);
-int yylex(void);
diff --git a/sh/funcs/cmv b/sh/funcs/cmv
deleted file mode 100644
index 667f846..0000000
--- a/sh/funcs/cmv
+++ /dev/null
@@ -1,50 +0,0 @@
-#	$NetBSD: cmv,v 1.7 1995/05/11 21:31:05 christos Exp $
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#	This product includes software developed by the University of
-#	California, Berkeley and its contributors.
-# 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.
-#
-#	@(#)cmv	8.2 (Berkeley) 5/4/95
-
-# Conditional move--don't replace an existing file.
-
-cmv() {
-	if test $# != 2
-	then	echo "cmv: arg count"
-		return 2
-	fi
-	if test -f "$2" -o -w "$2"
-	then	echo "$2 exists"
-		return 2
-	fi
-	/bin/mv "$1" "$2"
-}
diff --git a/sh/funcs/dirs b/sh/funcs/dirs
deleted file mode 100644
index 68bb317..0000000
--- a/sh/funcs/dirs
+++ /dev/null
@@ -1,74 +0,0 @@
-#	$NetBSD: dirs,v 1.7 1995/05/11 21:31:08 christos Exp $
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#	This product includes software developed by the University of
-#	California, Berkeley and its contributors.
-# 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.
-#
-#	@(#)dirs	8.2 (Berkeley) 5/4/95
-
-# pushd, popd, and dirs --- written by Chris Bertin
-# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
-# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
-
-pushd () {
-	SAVE=`pwd`
-	if [ "$1" = "" ] 
-	then	if [ "$DSTACK" = "" ]
-		then	echo "pushd: directory stack empty."
-			return 1
-		fi
-		set $DSTACK
-		cd $1 || return
-		shift 1
-		DSTACK="$*"
-	else	cd $1 > /dev/null || return
-	fi
-	DSTACK="$SAVE $DSTACK"
-	dirs
-}
-
-popd () {
-	if [ "$DSTACK" = "" ] 
-	then	echo "popd: directory stack empty."
-		return 1
-	fi
-	set $DSTACK
-	cd $1
-	shift
-	DSTACK=$*
-	dirs
-}
-
-dirs () {
-	echo "`pwd` $DSTACK"
-	return 0
-}
diff --git a/sh/funcs/kill b/sh/funcs/kill
deleted file mode 100644
index 75b0180..0000000
--- a/sh/funcs/kill
+++ /dev/null
@@ -1,50 +0,0 @@
-#	$NetBSD: kill,v 1.7 1995/05/11 21:31:10 christos Exp $
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#	This product includes software developed by the University of
-#	California, Berkeley and its contributors.
-# 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.
-#
-#	@(#)kill	8.2 (Berkeley) 5/4/95
-
-# Convert job names to process ids and then run /bin/kill.
-
-kill() {
-	local args x
-	args=
-	for x in "$@"
-	do	case $x in
-		%*)	x=`jobid "$x"` ;;
-		esac
-		args="$args $x"
-	done
-	/bin/kill $args
-}
diff --git a/sh/funcs/login b/sh/funcs/login
deleted file mode 100644
index 7ae08b2..0000000
--- a/sh/funcs/login
+++ /dev/null
@@ -1,39 +0,0 @@
-#	$NetBSD: login,v 1.7 1995/05/11 21:31:11 christos Exp $
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#	This product includes software developed by the University of
-#	California, Berkeley and its contributors.
-# 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.
-#
-#	@(#)login	8.2 (Berkeley) 5/4/95
-
-# replaces the login builtin in the BSD shell
-login () exec login "$@"
diff --git a/sh/funcs/newgrp b/sh/funcs/newgrp
deleted file mode 100644
index 796a4f1..0000000
--- a/sh/funcs/newgrp
+++ /dev/null
@@ -1,38 +0,0 @@
-#	$NetBSD: newgrp,v 1.7 1995/05/11 21:31:12 christos Exp $
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#	This product includes software developed by the University of
-#	California, Berkeley and its contributors.
-# 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.
-#
-#	@(#)newgrp	8.2 (Berkeley) 5/4/95
-
-newgrp() exec newgrp "$@"
diff --git a/sh/funcs/popd b/sh/funcs/popd
deleted file mode 100644
index b2b65d5..0000000
--- a/sh/funcs/popd
+++ /dev/null
@@ -1,74 +0,0 @@
-#	$NetBSD: popd,v 1.7 1995/05/11 21:31:13 christos Exp $
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#	This product includes software developed by the University of
-#	California, Berkeley and its contributors.
-# 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.
-#
-#	@(#)popd	8.2 (Berkeley) 5/4/95
-
-# pushd, popd, and dirs --- written by Chris Bertin
-# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
-# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
-
-pushd () {
-	SAVE=`pwd`
-	if [ "$1" = "" ] 
-	then	if [ "$DSTACK" = "" ]
-		then	echo "pushd: directory stack empty."
-			return 1
-		fi
-		set $DSTACK
-		cd $1 || return
-		shift 1
-		DSTACK="$*"
-	else	cd $1 > /dev/null || return
-	fi
-	DSTACK="$SAVE $DSTACK"
-	dirs
-}
-
-popd () {
-	if [ "$DSTACK" = "" ] 
-	then	echo "popd: directory stack empty."
-		return 1
-	fi
-	set $DSTACK
-	cd $1
-	shift
-	DSTACK=$*
-	dirs
-}
-
-dirs () {
-	echo "`pwd` $DSTACK"
-	return 0
-}
diff --git a/sh/funcs/pushd b/sh/funcs/pushd
deleted file mode 100644
index b393038..0000000
--- a/sh/funcs/pushd
+++ /dev/null
@@ -1,74 +0,0 @@
-#	$NetBSD: pushd,v 1.7 1995/05/11 21:31:15 christos Exp $
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#	This product includes software developed by the University of
-#	California, Berkeley and its contributors.
-# 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.
-#
-#	@(#)pushd	8.2 (Berkeley) 5/4/95
-
-# pushd, popd, and dirs --- written by Chris Bertin
-# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
-# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
-
-pushd () {
-	SAVE=`pwd`
-	if [ "$1" = "" ] 
-	then	if [ "$DSTACK" = "" ]
-		then	echo "pushd: directory stack empty."
-			return 1
-		fi
-		set $DSTACK
-		cd $1 || return
-		shift 1
-		DSTACK="$*"
-	else	cd $1 > /dev/null || return
-	fi
-	DSTACK="$SAVE $DSTACK"
-	dirs
-}
-
-popd () {
-	if [ "$DSTACK" = "" ] 
-	then	echo "popd: directory stack empty."
-		return 1
-	fi
-	set $DSTACK
-	cd $1
-	shift
-	DSTACK=$*
-	dirs
-}
-
-dirs () {
-	echo "`pwd` $DSTACK"
-	return 0
-}
diff --git a/sh/funcs/suspend b/sh/funcs/suspend
deleted file mode 100644
index 8a4197d..0000000
--- a/sh/funcs/suspend
+++ /dev/null
@@ -1,42 +0,0 @@
-#	$NetBSD: suspend,v 1.7 1995/05/11 21:31:17 christos Exp $
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-#    must display the following acknowledgement:
-#	This product includes software developed by the University of
-#	California, Berkeley and its contributors.
-# 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.
-#
-#	@(#)suspend	8.2 (Berkeley) 5/4/95
-
-suspend() {
-	local -
-	set +j
-	kill -TSTP 0
-}
diff --git a/sh/histedit.c b/sh/histedit.c
deleted file mode 100644
index 4bb2b34..0000000
--- a/sh/histedit.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/*	$NetBSD: histedit.c,v 1.34 2003/10/27 06:19:29 lukem Exp $	*/
-
-/*-
- * Copyright (c) 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)histedit.c	8.2 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: histedit.c,v 1.34 2003/10/27 06:19:29 lukem Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <paths.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-/*
- * Editline and history functions (and glue).
- */
-#include "shell.h"
-#include "parser.h"
-#include "var.h"
-#include "options.h"
-#include "main.h"
-#include "output.h"
-#include "mystring.h"
-#include "myhistedit.h"
-#include "error.h"
-#ifndef SMALL
-#include "eval.h"
-#include "memalloc.h"
-
-#define MAXHISTLOOPS	4	/* max recursions through fc */
-#define DEFEDITOR	"ed"	/* default editor *should* be $EDITOR */
-
-History *hist;	/* history cookie */
-EditLine *el;	/* editline cookie */
-int displayhist;
-static FILE *el_in, *el_out;
-
-STATIC const char *fc_replace(const char *, char *, char *);
-
-#ifdef DEBUG
-extern FILE *tracefile;
-#endif
-
-/*
- * Set history and editing status.  Called whenever the status may
- * have changed (figures out what to do).
- */
-void
-histedit(void)
-{
-	FILE *el_err;
-
-#define editing (Eflag || Vflag)
-
-	if (iflag) {
-		if (!hist) {
-			/*
-			 * turn history on
-			 */
-			INTOFF;
-			hist = history_init();
-			INTON;
-
-			if (hist != NULL)
-				sethistsize(histsizeval());
-			else
-				out2str("sh: can't initialize history\n");
-		}
-		if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
-			/*
-			 * turn editing on
-			 */
-			char *term, *shname;
-
-			INTOFF;
-			if (el_in == NULL)
-				el_in = fdopen(0, "r");
-			if (el_out == NULL)
-				el_out = fdopen(2, "w");
-			if (el_in == NULL || el_out == NULL)
-				goto bad;
-			el_err = el_out;
-#if DEBUG
-			if (tracefile)
-				el_err = tracefile;
-#endif
-			term = lookupvar("TERM");
-			if (term)
-				setenv("TERM", term, 1);
-			else
-				unsetenv("TERM");
-			shname = arg0;
-			if (shname[0] == '-')
-				shname++;
-			el = el_init(shname, el_in, el_out, el_err);
-			if (el != NULL) {
-				if (hist)
-					el_set(el, EL_HIST, history, hist);
-				el_set(el, EL_PROMPT, getprompt);
-				el_set(el, EL_SIGNAL, 1);
-			} else {
-bad:
-				out2str("sh: can't initialize editing\n");
-			}
-			INTON;
-		} else if (!editing && el) {
-			INTOFF;
-			el_end(el);
-			el = NULL;
-			INTON;
-		}
-		if (el) {
-			if (Vflag)
-				el_set(el, EL_EDITOR, "vi");
-			else if (Eflag)
-				el_set(el, EL_EDITOR, "emacs");
-			el_source(el, NULL);
-		}
-	} else {
-		INTOFF;
-		if (el) {	/* no editing if not interactive */
-			el_end(el);
-			el = NULL;
-		}
-		if (hist) {
-			history_end(hist);
-			hist = NULL;
-		}
-		INTON;
-	}
-}
-
-
-void
-sethistsize(const char *hs)
-{
-	int histsize;
-	HistEvent he;
-
-	if (hist != NULL) {
-		if (hs == NULL || *hs == '\0' ||
-		   (histsize = atoi(hs)) < 0)
-			histsize = 100;
-		history(hist, &he, H_SETSIZE, histsize);
-	}
-}
-
-void
-setterm(const char *term)
-{
-	if (el != NULL && term != NULL)
-		if (el_set(el, EL_TERMINAL, term) != 0) {
-			outfmt(out2, "sh: Can't set terminal type %s\n", term);
-			outfmt(out2, "sh: Using dumb terminal settings.\n");
-		}
-}
-
-int
-inputrc(argc, argv)
-	int argc;
-	char **argv;
-{
-	if (argc != 2) {
-		out2str("usage: inputrc file\n");
-		return 1;
-	}
-	if (el != NULL) {
-		if (el_source(el, argv[1])) {
-			out2str("inputrc: failed\n");
-			return 1;
-		} else
-			return 0;
-	} else {
-		out2str("sh: inputrc ignored, not editing\n");
-		return 1;
-	}
-}
-
-/*
- *  This command is provided since POSIX decided to standardize
- *  the Korn shell fc command.  Oh well...
- */
-int
-histcmd(int argc, char **argv)
-{
-	int ch;
-	const char *editor = NULL;
-	HistEvent he;
-	int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
-	int i, retval;
-	const char *firststr, *laststr;
-	int first, last, direction;
-	char *pat = NULL, *repl;	/* ksh "fc old=new" crap */
-	static int active = 0;
-	struct jmploc jmploc;
-	struct jmploc *volatile savehandler;
-	char editfile[MAXPATHLEN + 1];
-	FILE *efp;
-#ifdef __GNUC__
-	/* Avoid longjmp clobbering */
-	(void) &editor;
-	(void) &lflg;
-	(void) &nflg;
-	(void) &rflg;
-	(void) &sflg;
-	(void) &firststr;
-	(void) &laststr;
-	(void) &pat;
-	(void) &repl;
-	(void) &efp;
-	(void) &argc;
-	(void) &argv;
-#endif
-
-	if (hist == NULL)
-		error("history not active");
-
-	if (argc == 1)
-		error("missing history argument");
-
-	optreset = 1; optind = 1; /* initialize getopt */
-	while (not_fcnumber(argv[optind]) &&
-	      (ch = getopt(argc, argv, ":e:lnrs")) != -1)
-		switch ((char)ch) {
-		case 'e':
-			editor = optionarg;
-			break;
-		case 'l':
-			lflg = 1;
-			break;
-		case 'n':
-			nflg = 1;
-			break;
-		case 'r':
-			rflg = 1;
-			break;
-		case 's':
-			sflg = 1;
-			break;
-		case ':':
-			error("option -%c expects argument", optopt);
-			/* NOTREACHED */
-		case '?':
-		default:
-			error("unknown option: -%c", optopt);
-			/* NOTREACHED */
-		}
-	argc -= optind, argv += optind;
-
-	/*
-	 * If executing...
-	 */
-	if (lflg == 0 || editor || sflg) {
-		lflg = 0;	/* ignore */
-		editfile[0] = '\0';
-		/*
-		 * Catch interrupts to reset active counter and
-		 * cleanup temp files.
-		 */
-		if (setjmp(jmploc.loc)) {
-			active = 0;
-			if (*editfile)
-				unlink(editfile);
-			handler = savehandler;
-			longjmp(handler->loc, 1);
-		}
-		savehandler = handler;
-		handler = &jmploc;
-		if (++active > MAXHISTLOOPS) {
-			active = 0;
-			displayhist = 0;
-			error("called recursively too many times");
-		}
-		/*
-		 * Set editor.
-		 */
-		if (sflg == 0) {
-			if (editor == NULL &&
-			    (editor = bltinlookup("FCEDIT", 1)) == NULL &&
-			    (editor = bltinlookup("EDITOR", 1)) == NULL)
-				editor = DEFEDITOR;
-			if (editor[0] == '-' && editor[1] == '\0') {
-				sflg = 1;	/* no edit */
-				editor = NULL;
-			}
-		}
-	}
-
-	/*
-	 * If executing, parse [old=new] now
-	 */
-	if (lflg == 0 && argc > 0 &&
-	     ((repl = strchr(argv[0], '=')) != NULL)) {
-		pat = argv[0];
-		*repl++ = '\0';
-		argc--, argv++;
-	}
-	/*
-	 * determine [first] and [last]
-	 */
-	switch (argc) {
-	case 0:
-		firststr = lflg ? "-16" : "-1";
-		laststr = "-1";
-		break;
-	case 1:
-		firststr = argv[0];
-		laststr = lflg ? "-1" : argv[0];
-		break;
-	case 2:
-		firststr = argv[0];
-		laststr = argv[1];
-		break;
-	default:
-		error("too many args");
-		/* NOTREACHED */
-	}
-	/*
-	 * Turn into event numbers.
-	 */
-	first = str_to_event(firststr, 0);
-	last = str_to_event(laststr, 1);
-
-	if (rflg) {
-		i = last;
-		last = first;
-		first = i;
-	}
-	/*
-	 * XXX - this should not depend on the event numbers
-	 * always increasing.  Add sequence numbers or offset
-	 * to the history element in next (diskbased) release.
-	 */
-	direction = first < last ? H_PREV : H_NEXT;
-
-	/*
-	 * If editing, grab a temp file.
-	 */
-	if (editor) {
-		int fd;
-		INTOFF;		/* easier */
-		snprintf(editfile, sizeof(editfile), "%s_shXXXXXX", _PATH_TMP);
-		if ((fd = mkstemp(editfile)) < 0)
-			error("can't create temporary file %s", editfile);
-		if ((efp = fdopen(fd, "w")) == NULL) {
-			close(fd);
-			error("can't allocate stdio buffer for temp");
-		}
-	}
-
-	/*
-	 * Loop through selected history events.  If listing or executing,
-	 * do it now.  Otherwise, put into temp file and call the editor
-	 * after.
-	 *
-	 * The history interface needs rethinking, as the following
-	 * convolutions will demonstrate.
-	 */
-	history(hist, &he, H_FIRST);
-	retval = history(hist, &he, H_NEXT_EVENT, first);
-	for (;retval != -1; retval = history(hist, &he, direction)) {
-		if (lflg) {
-			if (!nflg)
-				out1fmt("%5d ", he.num);
-			out1str(he.str);
-		} else {
-			const char *s = pat ?
-			   fc_replace(he.str, pat, repl) : he.str;
-
-			if (sflg) {
-				if (displayhist) {
-					out2str(s);
-				}
-
-				evalstring(strcpy(stalloc(strlen(s) + 1), s), 0);
-				if (displayhist && hist) {
-					/*
-					 *  XXX what about recursive and
-					 *  relative histnums.
-					 */
-					history(hist, &he, H_ENTER, s);
-				}
-			} else
-				fputs(s, efp);
-		}
-		/*
-		 * At end?  (if we were to lose last, we'd sure be
-		 * messed up).
-		 */
-		if (he.num == last)
-			break;
-	}
-	if (editor) {
-		char *editcmd;
-
-		fclose(efp);
-		editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
-		sprintf(editcmd, "%s %s", editor, editfile);
-		evalstring(editcmd, 0);	/* XXX - should use no JC command */
-		INTON;
-		readcmdfile(editfile);	/* XXX - should read back - quick tst */
-		unlink(editfile);
-	}
-
-	if (lflg == 0 && active > 0)
-		--active;
-	if (displayhist)
-		displayhist = 0;
-	return 0;
-}
-
-STATIC const char *
-fc_replace(const char *s, char *p, char *r)
-{
-	char *dest;
-	int plen = strlen(p);
-
-	STARTSTACKSTR(dest);
-	while (*s) {
-		if (*s == *p && strncmp(s, p, plen) == 0) {
-			while (*r)
-				STPUTC(*r++, dest);
-			s += plen;
-			*p = '\0';	/* so no more matches */
-		} else
-			STPUTC(*s++, dest);
-	}
-	STACKSTRNUL(dest);
-	dest = grabstackstr(dest);
-
-	return (dest);
-}
-
-int
-not_fcnumber(char *s)
-{
-	if (s == NULL)
-		return 0;
-        if (*s == '-')
-                s++;
-	return (!is_number(s));
-}
-
-int
-str_to_event(const char *str, int last)
-{
-	HistEvent he;
-	const char *s = str;
-	int relative = 0;
-	int i, retval;
-
-	retval = history(hist, &he, H_FIRST);
-	switch (*s) {
-	case '-':
-		relative = 1;
-		/*FALLTHROUGH*/
-	case '+':
-		s++;
-	}
-	if (is_number(s)) {
-		i = atoi(s);
-		if (relative) {
-			while (retval != -1 && i--) {
-				retval = history(hist, &he, H_NEXT);
-			}
-			if (retval == -1)
-				retval = history(hist, &he, H_LAST);
-		} else {
-			retval = history(hist, &he, H_NEXT_EVENT, i);
-			if (retval == -1) {
-				/*
-				 * the notion of first and last is
-				 * backwards to that of the history package
-				 */
-				retval = history(hist, &he,
-						last ? H_FIRST : H_LAST);
-			}
-		}
-		if (retval == -1)
-			error("history number %s not found (internal error)",
-			       str);
-	} else {
-		/*
-		 * pattern
-		 */
-		retval = history(hist, &he, H_PREV_STR, str);
-		if (retval == -1)
-			error("history pattern not found: %s", str);
-	}
-	return (he.num);
-}
-#else
-int
-histcmd(int argc, char **argv)
-{
-	error("not compiled with history support");
-	/* NOTREACHED */
-}
-int
-inputrc(int argc, char **argv)
-{
-	error("not compiled with history support");
-	/* NOTREACHED */
-}
-#endif
diff --git a/sh/init.c b/sh/init.c
deleted file mode 100644
index 55ad172..0000000
--- a/sh/init.c
+++ /dev/null
@@ -1,1090 +0,0 @@
-/*
- * This file was generated by the mkinit program.
- */
-
-#include "shell.h"
-#include "mystring.h"
-#include "init.h"
-#include "eval.h"
-#include <stdio.h>
-#include "input.h"
-#include "error.h"
-#include <stdlib.h>
-#include "options.h"
-#include "redir.h"
-#include <signal.h>
-#include "trap.h"
-#include "output.h"
-#include "memalloc.h"
-#include "var.h"
-
-
-
-#undef  ATABSIZE
-#define ATABSIZE 39
-#undef  YYBISON
-#define YYBISON 1
-#undef  YYSKELETON_NAME
-#define YYSKELETON_NAME "yacc.c"
-#undef  YYPURE
-#define YYPURE 0
-#undef  YYLSP_NEEDED
-#define YYLSP_NEEDED 0
-#undef  ARITH_NUM
-#define ARITH_NUM 258
-#undef  ARITH_LPAREN
-#define ARITH_LPAREN 259
-#undef  ARITH_RPAREN
-#define ARITH_RPAREN 260
-#undef  ARITH_OR
-#define ARITH_OR 261
-#undef  ARITH_AND
-#define ARITH_AND 262
-#undef  ARITH_BOR
-#define ARITH_BOR 263
-#undef  ARITH_BXOR
-#define ARITH_BXOR 264
-#undef  ARITH_BAND
-#define ARITH_BAND 265
-#undef  ARITH_NE
-#define ARITH_NE 266
-#undef  ARITH_EQ
-#define ARITH_EQ 267
-#undef  ARITH_LE
-#define ARITH_LE 268
-#undef  ARITH_GE
-#define ARITH_GE 269
-#undef  ARITH_GT
-#define ARITH_GT 270
-#undef  ARITH_LT
-#define ARITH_LT 271
-#undef  ARITH_RSHIFT
-#define ARITH_RSHIFT 272
-#undef  ARITH_LSHIFT
-#define ARITH_LSHIFT 273
-#undef  ARITH_SUB
-#define ARITH_SUB 274
-#undef  ARITH_ADD
-#define ARITH_ADD 275
-#undef  ARITH_REM
-#define ARITH_REM 276
-#undef  ARITH_DIV
-#define ARITH_DIV 277
-#undef  ARITH_MUL
-#define ARITH_MUL 278
-#undef  ARITH_BNOT
-#define ARITH_BNOT 279
-#undef  ARITH_NOT
-#define ARITH_NOT 280
-#undef  ARITH_UNARYPLUS
-#define ARITH_UNARYPLUS 281
-#undef  ARITH_UNARYMINUS
-#define ARITH_UNARYMINUS 282
-#undef  YYFINAL
-#define YYFINAL  14
-#undef  YYLAST
-#define YYLAST   170
-#undef  YYNTOKENS
-#define YYNTOKENS  28
-#undef  YYNNTS
-#define YYNNTS  3
-#undef  YYNRULES
-#define YYNRULES  26
-#undef  YYNSTATES
-#define YYNSTATES  52
-#undef  YYUNDEFTOK
-#define YYUNDEFTOK  2
-#undef  YYMAXUTOK
-#define YYMAXUTOK   282
-#undef  YYPACT_NINF
-#define YYPACT_NINF -13
-#undef  YYTABLE_NINF
-#define YYTABLE_NINF -1
-#undef  yyerrok
-#define yyerrok		(yyerrstatus = 0)
-#undef  yyclearin
-#define yyclearin	(yychar = YYEMPTY)
-#undef  YYEMPTY
-#define YYEMPTY		(-2)
-#undef  YYEOF
-#define YYEOF		0
-#undef  YYACCEPT
-#define YYACCEPT	goto yyacceptlab
-#undef  YYABORT
-#define YYABORT		goto yyabortlab
-#undef  YYERROR
-#define YYERROR		goto yyerrorlab
-#undef  YYFAIL
-#define YYFAIL		goto yyerrlab
-#undef  YYTERROR
-#define YYTERROR	1
-#undef  YYERRCODE
-#define YYERRCODE	256
-#undef  YYPOPSTACK
-#define YYPOPSTACK   (yyvsp--, yyssp--)
-#undef  YY_INT_ALIGNED
-#define  YY_INT_ALIGNED short int
-#undef  FLEX_SCANNER
-#define FLEX_SCANNER
-#undef  YY_FLEX_MAJOR_VERSION
-#define YY_FLEX_MAJOR_VERSION 2
-#undef  YY_FLEX_MINOR_VERSION
-#define YY_FLEX_MINOR_VERSION 5
-#undef  YY_FLEX_SUBMINOR_VERSION
-#define YY_FLEX_SUBMINOR_VERSION 31
-#undef  FLEX_BETA
-#define FLEX_BETA
-#undef  FLEXINT_H
-#define FLEXINT_H
-#undef  INT8_MIN
-#define INT8_MIN               (-128)
-#undef  INT16_MIN
-#define INT16_MIN              (-32767-1)
-#undef  INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#undef  INT8_MAX
-#define INT8_MAX               (127)
-#undef  INT16_MAX
-#define INT16_MAX              (32767)
-#undef  INT32_MAX
-#define INT32_MAX              (2147483647)
-#undef  UINT8_MAX
-#define UINT8_MAX              (255U)
-#undef  UINT16_MAX
-#define UINT16_MAX             (65535U)
-#undef  UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#undef  YY_USE_CONST
-#define YY_USE_CONST
-#undef  YY_USE_CONST
-#define YY_USE_CONST
-#undef  yyconst
-#define yyconst const
-#undef  yyconst
-#define yyconst
-#undef  YY_NULL
-#define YY_NULL 0
-#undef  BEGIN
-#define BEGIN (yy_start) = 1 + 2 *
-#undef  YY_START
-#define YY_START (((yy_start) - 1) / 2)
-#undef  YYSTATE
-#define YYSTATE YY_START
-#undef  YY_NEW_FILE
-#define YY_NEW_FILE yyrestart(yyin  )
-#undef  YY_END_OF_BUFFER_CHAR
-#define YY_END_OF_BUFFER_CHAR 0
-#undef  YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#undef  YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-#undef  EOB_ACT_CONTINUE_SCAN
-#define EOB_ACT_CONTINUE_SCAN 0
-#undef  EOB_ACT_END_OF_FILE
-#define EOB_ACT_END_OF_FILE 1
-#undef  EOB_ACT_LAST_MATCH
-#define EOB_ACT_LAST_MATCH 2
-#undef  YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-#undef  YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-#undef  YY_BUFFER_NEW
-#define YY_BUFFER_NEW 0
-#undef  YY_BUFFER_NORMAL
-#define YY_BUFFER_NORMAL 1
-#undef  YY_BUFFER_EOF_PENDING
-#define YY_BUFFER_EOF_PENDING 2
-#undef  YY_CURRENT_BUFFER
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-#undef  YY_CURRENT_BUFFER_LVALUE
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-#undef  YY_FLUSH_BUFFER
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
-#undef  yy_new_buffer
-#define yy_new_buffer yy_create_buffer
-#undef  YY_SKIP_YYWRAP
-#define YY_SKIP_YYWRAP
-#undef  yytext_ptr
-#define yytext_ptr yytext
-#undef  YY_DO_BEFORE_ACTION
-#define YY_DO_BEFORE_ACTION \
-#undef  YY_NUM_RULES
-#define YY_NUM_RULES 29
-#undef  YY_END_OF_BUFFER
-#define YY_END_OF_BUFFER 30
-#undef  REJECT
-#define REJECT reject_used_but_not_detected
-#undef  YY_MORE_ADJ
-#define YY_MORE_ADJ 0
-#undef  YY_RESTORE_YY_MORE_OFFSET
-#define YY_RESTORE_YY_MORE_OFFSET
-#undef  YY_NO_UNPUT
-#define YY_NO_UNPUT
-#undef  INITIAL
-#define INITIAL 0
-#undef  YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#undef  YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#undef  ECHO
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
-#undef  YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#undef  YY_DECL_IS_OURS
-#define YY_DECL_IS_OURS 1
-#undef  YY_DECL
-#define YY_DECL int yylex (void)
-#undef  YY_USER_ACTION
-#define YY_USER_ACTION
-#undef  YY_BREAK
-#define YY_BREAK break;
-#undef  YY_RULE_SETUP
-#define YY_RULE_SETUP \
-#undef  YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#undef  YYTABLES_NAME
-#define YYTABLES_NAME "yytables"
-#undef  MAXPWD
-#define MAXPWD 256
-#undef  signal
-#define signal bsd_signal
-#undef  ALL
-#define ALL (E_OPEN|E_CREAT|E_EXEC)
-#undef  EV_EXIT
-#define EV_EXIT 01		/* exit after evaluating tree */
-#undef  EV_TESTED
-#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
-#undef  EV_BACKCMD
-#define EV_BACKCMD 04		/* command executing within back quotes */
-#undef  CMDTABLESIZE
-#define CMDTABLESIZE 31		/* should be prime */
-#undef  ARB
-#define ARB 1			/* actual size determined at run time */
-#undef  NEWARGS
-#define NEWARGS 5
-#undef  EOF_NLEFT
-#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
-#undef  _PATH_DEVNULL
-#define _PATH_DEVNULL "/dev/null"
-#undef  PROFILE
-#define PROFILE 0
-#undef  SIGSSIZE
-#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
-#undef  MINSIZE
-#define MINSIZE 504		/* minimum size of a block */
-#undef  DEFINE_OPTIONS
-#define DEFINE_OPTIONS
-#undef  EOFMARKLEN
-#define EOFMARKLEN 79
-#undef  OPENBRACE
-#define OPENBRACE '{'
-#undef  CLOSEBRACE
-#define CLOSEBRACE '}'
-#undef  EMPTY
-#define EMPTY -2		/* marks an unused slot in redirtab */
-#undef  signal
-#define signal bsd_signal
-#undef  sys_signame
-#define sys_signame sys_siglist
-#undef  S_DFL
-#define S_DFL 1			/* default signal handling (SIG_DFL) */
-#undef  S_CATCH
-#define S_CATCH 2		/* signal is caught */
-#undef  S_IGN
-#define S_IGN 3			/* signal is ignored (SIG_IGN) */
-#undef  S_HARD_IGN
-#define S_HARD_IGN 4		/* signal is ignored permenantly */
-#undef  S_RESET
-#define S_RESET 5		/* temporary - to reset a hard ignored sig */
-#undef  OUTBUFSIZ
-#define OUTBUFSIZ BUFSIZ
-#undef  BLOCK_OUT
-#define BLOCK_OUT -2		/* output to a fixed block of memory */
-#undef  MEM_OUT
-#define MEM_OUT -3		/* output to dynamically allocated memory */
-#undef  OUTPUT_ERR
-#define OUTPUT_ERR 01		/* error occurred on output */
-#undef  TEMPSIZE
-#define TEMPSIZE 24
-#undef  HAVE_VASPRINTF
-#define HAVE_VASPRINTF 1
-#undef  VTABSIZE
-#define VTABSIZE 39
-#undef  VTABSIZE
-#define VTABSIZE 517
-#undef  ATABSIZE
-#define ATABSIZE 39
-#undef  YYBISON
-#define YYBISON 1
-#undef  YYSKELETON_NAME
-#define YYSKELETON_NAME "yacc.c"
-#undef  YYPURE
-#define YYPURE 0
-#undef  YYLSP_NEEDED
-#define YYLSP_NEEDED 0
-#undef  ARITH_NUM
-#define ARITH_NUM 258
-#undef  ARITH_LPAREN
-#define ARITH_LPAREN 259
-#undef  ARITH_RPAREN
-#define ARITH_RPAREN 260
-#undef  ARITH_OR
-#define ARITH_OR 261
-#undef  ARITH_AND
-#define ARITH_AND 262
-#undef  ARITH_BOR
-#define ARITH_BOR 263
-#undef  ARITH_BXOR
-#define ARITH_BXOR 264
-#undef  ARITH_BAND
-#define ARITH_BAND 265
-#undef  ARITH_NE
-#define ARITH_NE 266
-#undef  ARITH_EQ
-#define ARITH_EQ 267
-#undef  ARITH_LE
-#define ARITH_LE 268
-#undef  ARITH_GE
-#define ARITH_GE 269
-#undef  ARITH_GT
-#define ARITH_GT 270
-#undef  ARITH_LT
-#define ARITH_LT 271
-#undef  ARITH_RSHIFT
-#define ARITH_RSHIFT 272
-#undef  ARITH_LSHIFT
-#define ARITH_LSHIFT 273
-#undef  ARITH_SUB
-#define ARITH_SUB 274
-#undef  ARITH_ADD
-#define ARITH_ADD 275
-#undef  ARITH_REM
-#define ARITH_REM 276
-#undef  ARITH_DIV
-#define ARITH_DIV 277
-#undef  ARITH_MUL
-#define ARITH_MUL 278
-#undef  ARITH_BNOT
-#define ARITH_BNOT 279
-#undef  ARITH_NOT
-#define ARITH_NOT 280
-#undef  ARITH_UNARYPLUS
-#define ARITH_UNARYPLUS 281
-#undef  ARITH_UNARYMINUS
-#define ARITH_UNARYMINUS 282
-#undef  YYFINAL
-#define YYFINAL  14
-#undef  YYLAST
-#define YYLAST   170
-#undef  YYNTOKENS
-#define YYNTOKENS  28
-#undef  YYNNTS
-#define YYNNTS  3
-#undef  YYNRULES
-#define YYNRULES  26
-#undef  YYNSTATES
-#define YYNSTATES  52
-#undef  YYUNDEFTOK
-#define YYUNDEFTOK  2
-#undef  YYMAXUTOK
-#define YYMAXUTOK   282
-#undef  YYPACT_NINF
-#define YYPACT_NINF -13
-#undef  YYTABLE_NINF
-#define YYTABLE_NINF -1
-#undef  yyerrok
-#define yyerrok		(yyerrstatus = 0)
-#undef  yyclearin
-#define yyclearin	(yychar = YYEMPTY)
-#undef  YYEMPTY
-#define YYEMPTY		(-2)
-#undef  YYEOF
-#define YYEOF		0
-#undef  YYACCEPT
-#define YYACCEPT	goto yyacceptlab
-#undef  YYABORT
-#define YYABORT		goto yyabortlab
-#undef  YYERROR
-#define YYERROR		goto yyerrorlab
-#undef  YYFAIL
-#define YYFAIL		goto yyerrlab
-#undef  YYTERROR
-#define YYTERROR	1
-#undef  YYERRCODE
-#define YYERRCODE	256
-#undef  YYPOPSTACK
-#define YYPOPSTACK   (yyvsp--, yyssp--)
-#undef  YY_INT_ALIGNED
-#define  YY_INT_ALIGNED short int
-#undef  FLEX_SCANNER
-#define FLEX_SCANNER
-#undef  YY_FLEX_MAJOR_VERSION
-#define YY_FLEX_MAJOR_VERSION 2
-#undef  YY_FLEX_MINOR_VERSION
-#define YY_FLEX_MINOR_VERSION 5
-#undef  YY_FLEX_SUBMINOR_VERSION
-#define YY_FLEX_SUBMINOR_VERSION 31
-#undef  FLEX_BETA
-#define FLEX_BETA
-#undef  FLEXINT_H
-#define FLEXINT_H
-#undef  INT8_MIN
-#define INT8_MIN               (-128)
-#undef  INT16_MIN
-#define INT16_MIN              (-32767-1)
-#undef  INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#undef  INT8_MAX
-#define INT8_MAX               (127)
-#undef  INT16_MAX
-#define INT16_MAX              (32767)
-#undef  INT32_MAX
-#define INT32_MAX              (2147483647)
-#undef  UINT8_MAX
-#define UINT8_MAX              (255U)
-#undef  UINT16_MAX
-#define UINT16_MAX             (65535U)
-#undef  UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#undef  YY_USE_CONST
-#define YY_USE_CONST
-#undef  YY_USE_CONST
-#define YY_USE_CONST
-#undef  yyconst
-#define yyconst const
-#undef  yyconst
-#define yyconst
-#undef  YY_NULL
-#define YY_NULL 0
-#undef  BEGIN
-#define BEGIN (yy_start) = 1 + 2 *
-#undef  YY_START
-#define YY_START (((yy_start) - 1) / 2)
-#undef  YYSTATE
-#define YYSTATE YY_START
-#undef  YY_NEW_FILE
-#define YY_NEW_FILE yyrestart(yyin  )
-#undef  YY_END_OF_BUFFER_CHAR
-#define YY_END_OF_BUFFER_CHAR 0
-#undef  YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#undef  YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-#undef  EOB_ACT_CONTINUE_SCAN
-#define EOB_ACT_CONTINUE_SCAN 0
-#undef  EOB_ACT_END_OF_FILE
-#define EOB_ACT_END_OF_FILE 1
-#undef  EOB_ACT_LAST_MATCH
-#define EOB_ACT_LAST_MATCH 2
-#undef  YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-#undef  YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-#undef  YY_BUFFER_NEW
-#define YY_BUFFER_NEW 0
-#undef  YY_BUFFER_NORMAL
-#define YY_BUFFER_NORMAL 1
-#undef  YY_BUFFER_EOF_PENDING
-#define YY_BUFFER_EOF_PENDING 2
-#undef  YY_CURRENT_BUFFER
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-#undef  YY_CURRENT_BUFFER_LVALUE
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-#undef  YY_FLUSH_BUFFER
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
-#undef  yy_new_buffer
-#define yy_new_buffer yy_create_buffer
-#undef  YY_SKIP_YYWRAP
-#define YY_SKIP_YYWRAP
-#undef  yytext_ptr
-#define yytext_ptr yytext
-#undef  YY_DO_BEFORE_ACTION
-#define YY_DO_BEFORE_ACTION \
-#undef  YY_NUM_RULES
-#define YY_NUM_RULES 29
-#undef  YY_END_OF_BUFFER
-#define YY_END_OF_BUFFER 30
-#undef  REJECT
-#define REJECT reject_used_but_not_detected
-#undef  YY_MORE_ADJ
-#define YY_MORE_ADJ 0
-#undef  YY_RESTORE_YY_MORE_OFFSET
-#define YY_RESTORE_YY_MORE_OFFSET
-#undef  YY_NO_UNPUT
-#define YY_NO_UNPUT
-#undef  INITIAL
-#define INITIAL 0
-#undef  YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#undef  YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#undef  ECHO
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
-#undef  YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#undef  YY_DECL_IS_OURS
-#define YY_DECL_IS_OURS 1
-#undef  YY_DECL
-#define YY_DECL int yylex (void)
-#undef  YY_USER_ACTION
-#define YY_USER_ACTION
-#undef  YY_BREAK
-#define YY_BREAK break;
-#undef  YY_RULE_SETUP
-#define YY_RULE_SETUP \
-#undef  YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#undef  YYTABLES_NAME
-#define YYTABLES_NAME "yytables"
-#undef  MAXPWD
-#define MAXPWD 256
-#undef  signal
-#define signal bsd_signal
-#undef  ALL
-#define ALL (E_OPEN|E_CREAT|E_EXEC)
-#undef  EV_EXIT
-#define EV_EXIT 01		/* exit after evaluating tree */
-#undef  EV_TESTED
-#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
-#undef  EV_BACKCMD
-#define EV_BACKCMD 04		/* command executing within back quotes */
-#undef  CMDTABLESIZE
-#define CMDTABLESIZE 31		/* should be prime */
-#undef  ARB
-#define ARB 1			/* actual size determined at run time */
-#undef  NEWARGS
-#define NEWARGS 5
-#undef  EOF_NLEFT
-#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
-#undef  _PATH_DEVNULL
-#define _PATH_DEVNULL "/dev/null"
-#undef  PROFILE
-#define PROFILE 0
-#undef  SIGSSIZE
-#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
-#undef  MINSIZE
-#define MINSIZE 504		/* minimum size of a block */
-#undef  DEFINE_OPTIONS
-#define DEFINE_OPTIONS
-#undef  EOFMARKLEN
-#define EOFMARKLEN 79
-#undef  OPENBRACE
-#define OPENBRACE '{'
-#undef  CLOSEBRACE
-#define CLOSEBRACE '}'
-#undef  EMPTY
-#define EMPTY -2		/* marks an unused slot in redirtab */
-#undef  signal
-#define signal bsd_signal
-#undef  sys_signame
-#define sys_signame sys_siglist
-#undef  S_DFL
-#define S_DFL 1			/* default signal handling (SIG_DFL) */
-#undef  S_CATCH
-#define S_CATCH 2		/* signal is caught */
-#undef  S_IGN
-#define S_IGN 3			/* signal is ignored (SIG_IGN) */
-#undef  S_HARD_IGN
-#define S_HARD_IGN 4		/* signal is ignored permenantly */
-#undef  S_RESET
-#define S_RESET 5		/* temporary - to reset a hard ignored sig */
-#undef  OUTBUFSIZ
-#define OUTBUFSIZ BUFSIZ
-#undef  BLOCK_OUT
-#define BLOCK_OUT -2		/* output to a fixed block of memory */
-#undef  MEM_OUT
-#define MEM_OUT -3		/* output to dynamically allocated memory */
-#undef  OUTPUT_ERR
-#define OUTPUT_ERR 01		/* error occurred on output */
-#undef  TEMPSIZE
-#define TEMPSIZE 24
-#undef  HAVE_VASPRINTF
-#define HAVE_VASPRINTF 1
-#undef  VTABSIZE
-#define VTABSIZE 39
-#undef  VTABSIZE
-#define VTABSIZE 517
-#undef  main
-#define main echocmd
-#undef  YYBISON
-#define YYBISON 1
-#undef  YYSKELETON_NAME
-#define YYSKELETON_NAME "yacc.c"
-#undef  YYPURE
-#define YYPURE 0
-#undef  YYLSP_NEEDED
-#define YYLSP_NEEDED 0
-#undef  ARITH_NUM
-#define ARITH_NUM 258
-#undef  ARITH_LPAREN
-#define ARITH_LPAREN 259
-#undef  ARITH_RPAREN
-#define ARITH_RPAREN 260
-#undef  ARITH_OR
-#define ARITH_OR 261
-#undef  ARITH_AND
-#define ARITH_AND 262
-#undef  ARITH_BOR
-#define ARITH_BOR 263
-#undef  ARITH_BXOR
-#define ARITH_BXOR 264
-#undef  ARITH_BAND
-#define ARITH_BAND 265
-#undef  ARITH_NE
-#define ARITH_NE 266
-#undef  ARITH_EQ
-#define ARITH_EQ 267
-#undef  ARITH_LE
-#define ARITH_LE 268
-#undef  ARITH_GE
-#define ARITH_GE 269
-#undef  ARITH_GT
-#define ARITH_GT 270
-#undef  ARITH_LT
-#define ARITH_LT 271
-#undef  ARITH_RSHIFT
-#define ARITH_RSHIFT 272
-#undef  ARITH_LSHIFT
-#define ARITH_LSHIFT 273
-#undef  ARITH_SUB
-#define ARITH_SUB 274
-#undef  ARITH_ADD
-#define ARITH_ADD 275
-#undef  ARITH_REM
-#define ARITH_REM 276
-#undef  ARITH_DIV
-#define ARITH_DIV 277
-#undef  ARITH_MUL
-#define ARITH_MUL 278
-#undef  ARITH_BNOT
-#define ARITH_BNOT 279
-#undef  ARITH_NOT
-#define ARITH_NOT 280
-#undef  ARITH_UNARYPLUS
-#define ARITH_UNARYPLUS 281
-#undef  ARITH_UNARYMINUS
-#define ARITH_UNARYMINUS 282
-#undef  YYFINAL
-#define YYFINAL  14
-#undef  YYLAST
-#define YYLAST   170
-#undef  YYNTOKENS
-#define YYNTOKENS  28
-#undef  YYNNTS
-#define YYNNTS  3
-#undef  YYNRULES
-#define YYNRULES  26
-#undef  YYNSTATES
-#define YYNSTATES  52
-#undef  YYUNDEFTOK
-#define YYUNDEFTOK  2
-#undef  YYMAXUTOK
-#define YYMAXUTOK   282
-#undef  YYPACT_NINF
-#define YYPACT_NINF -13
-#undef  YYTABLE_NINF
-#define YYTABLE_NINF -1
-#undef  yyerrok
-#define yyerrok		(yyerrstatus = 0)
-#undef  yyclearin
-#define yyclearin	(yychar = YYEMPTY)
-#undef  YYEMPTY
-#define YYEMPTY		(-2)
-#undef  YYEOF
-#define YYEOF		0
-#undef  YYACCEPT
-#define YYACCEPT	goto yyacceptlab
-#undef  YYABORT
-#define YYABORT		goto yyabortlab
-#undef  YYERROR
-#define YYERROR		goto yyerrorlab
-#undef  YYFAIL
-#define YYFAIL		goto yyerrlab
-#undef  YYTERROR
-#define YYTERROR	1
-#undef  YYERRCODE
-#define YYERRCODE	256
-#undef  YYPOPSTACK
-#define YYPOPSTACK   (yyvsp--, yyssp--)
-#undef  YY_INT_ALIGNED
-#define  YY_INT_ALIGNED short int
-#undef  FLEX_SCANNER
-#define FLEX_SCANNER
-#undef  YY_FLEX_MAJOR_VERSION
-#define YY_FLEX_MAJOR_VERSION 2
-#undef  YY_FLEX_MINOR_VERSION
-#define YY_FLEX_MINOR_VERSION 5
-#undef  YY_FLEX_SUBMINOR_VERSION
-#define YY_FLEX_SUBMINOR_VERSION 31
-#undef  FLEX_BETA
-#define FLEX_BETA
-#undef  FLEXINT_H
-#define FLEXINT_H
-#undef  INT8_MIN
-#define INT8_MIN               (-128)
-#undef  INT16_MIN
-#define INT16_MIN              (-32767-1)
-#undef  INT32_MIN
-#define INT32_MIN              (-2147483647-1)
-#undef  INT8_MAX
-#define INT8_MAX               (127)
-#undef  INT16_MAX
-#define INT16_MAX              (32767)
-#undef  INT32_MAX
-#define INT32_MAX              (2147483647)
-#undef  UINT8_MAX
-#define UINT8_MAX              (255U)
-#undef  UINT16_MAX
-#define UINT16_MAX             (65535U)
-#undef  UINT32_MAX
-#define UINT32_MAX             (4294967295U)
-#undef  YY_USE_CONST
-#define YY_USE_CONST
-#undef  YY_USE_CONST
-#define YY_USE_CONST
-#undef  yyconst
-#define yyconst const
-#undef  yyconst
-#define yyconst
-#undef  YY_NULL
-#define YY_NULL 0
-#undef  BEGIN
-#define BEGIN (yy_start) = 1 + 2 *
-#undef  YY_START
-#define YY_START (((yy_start) - 1) / 2)
-#undef  YYSTATE
-#define YYSTATE YY_START
-#undef  YY_NEW_FILE
-#define YY_NEW_FILE yyrestart(yyin  )
-#undef  YY_END_OF_BUFFER_CHAR
-#define YY_END_OF_BUFFER_CHAR 0
-#undef  YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#undef  YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-#undef  EOB_ACT_CONTINUE_SCAN
-#define EOB_ACT_CONTINUE_SCAN 0
-#undef  EOB_ACT_END_OF_FILE
-#define EOB_ACT_END_OF_FILE 1
-#undef  EOB_ACT_LAST_MATCH
-#define EOB_ACT_LAST_MATCH 2
-#undef  YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-#undef  YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-#undef  YY_BUFFER_NEW
-#define YY_BUFFER_NEW 0
-#undef  YY_BUFFER_NORMAL
-#define YY_BUFFER_NORMAL 1
-#undef  YY_BUFFER_EOF_PENDING
-#define YY_BUFFER_EOF_PENDING 2
-#undef  YY_CURRENT_BUFFER
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
-#undef  YY_CURRENT_BUFFER_LVALUE
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-#undef  YY_FLUSH_BUFFER
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
-#undef  yy_new_buffer
-#define yy_new_buffer yy_create_buffer
-#undef  yytext_ptr
-#define yytext_ptr yytext
-#undef  YY_DO_BEFORE_ACTION
-#define YY_DO_BEFORE_ACTION \
-#undef  YY_NUM_RULES
-#define YY_NUM_RULES 29
-#undef  YY_END_OF_BUFFER
-#define YY_END_OF_BUFFER 30
-#undef  REJECT
-#define REJECT reject_used_but_not_detected
-#undef  YY_MORE_ADJ
-#define YY_MORE_ADJ 0
-#undef  YY_RESTORE_YY_MORE_OFFSET
-#define YY_RESTORE_YY_MORE_OFFSET
-#undef  YY_NO_UNPUT
-#define YY_NO_UNPUT
-#undef  INITIAL
-#define INITIAL 0
-#undef  YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#undef  YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#undef  ECHO
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
-#undef  YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#undef  YY_DECL_IS_OURS
-#define YY_DECL_IS_OURS 1
-#undef  YY_DECL
-#define YY_DECL int yylex (void)
-#undef  YY_USER_ACTION
-#define YY_USER_ACTION
-#undef  YY_BREAK
-#define YY_BREAK break;
-#undef  YY_RULE_SETUP
-#define YY_RULE_SETUP \
-#undef  YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#undef  YYTABLES_NAME
-#define YYTABLES_NAME "yytables"
-#undef  MAXPWD
-#define MAXPWD 256
-#undef  ALL
-#define ALL (E_OPEN|E_CREAT|E_EXEC)
-#undef  EV_EXIT
-#define EV_EXIT 01		/* exit after evaluating tree */
-#undef  EV_TESTED
-#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
-#undef  EV_BACKCMD
-#define EV_BACKCMD 04		/* command executing within back quotes */
-#undef  CMDTABLESIZE
-#define CMDTABLESIZE 31		/* should be prime */
-#undef  ARB
-#define ARB 1			/* actual size determined at run time */
-#undef  NEWARGS
-#define NEWARGS 5
-#undef  EOF_NLEFT
-#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
-#undef  _PATH_DEVNULL
-#define _PATH_DEVNULL "/dev/null"
-#undef  PROFILE
-#define PROFILE 0
-#undef  SIGSSIZE
-#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
-#undef  MINSIZE
-#define MINSIZE 504		/* minimum size of a block */
-#undef  DEFINE_OPTIONS
-#define DEFINE_OPTIONS
-#undef  EOFMARKLEN
-#define EOFMARKLEN 79
-#undef  OPENBRACE
-#define OPENBRACE '{'
-#undef  CLOSEBRACE
-#define CLOSEBRACE '}'
-#undef  EMPTY
-#define EMPTY -2		/* marks an unused slot in redirtab */
-#undef  S_DFL
-#define S_DFL 1			/* default signal handling (SIG_DFL) */
-#undef  S_CATCH
-#define S_CATCH 2		/* signal is caught */
-#undef  S_IGN
-#define S_IGN 3			/* signal is ignored (SIG_IGN) */
-#undef  S_HARD_IGN
-#define S_HARD_IGN 4		/* signal is ignored permenantly */
-#undef  S_RESET
-#define S_RESET 5		/* temporary - to reset a hard ignored sig */
-#undef  OUTBUFSIZ
-#define OUTBUFSIZ BUFSIZ
-#undef  BLOCK_OUT
-#define BLOCK_OUT -2		/* output to a fixed block of memory */
-#undef  MEM_OUT
-#define MEM_OUT -3		/* output to dynamically allocated memory */
-#undef  OUTPUT_ERR
-#define OUTPUT_ERR 01		/* error occurred on output */
-#undef  TEMPSIZE
-#define TEMPSIZE 24
-#undef  HAVE_VASPRINTF
-#define HAVE_VASPRINTF 1
-#undef  VTABSIZE
-#define VTABSIZE 39
-#undef  VTABSIZE
-#define VTABSIZE 517
-#undef  main
-#define main echocmd
-
-
-
-extern void rmaliases(void);
-
-extern int loopnest;		/* current loop nesting level */
-
-extern void deletefuncs(void);
-extern void hash_special_builtins(void);
-
-struct strpush {
-	struct strpush *prev;	/* preceding string on stack */
-	char *prevstring;
-	int prevnleft;
-	int prevlleft;
-	struct alias *ap;	/* if push was associated with an alias */
-};
-
-struct parsefile {
-	struct parsefile *prev;	/* preceding file on stack */
-	int linno;		/* current line */
-	int fd;			/* file descriptor (or -1 if string) */
-	int nleft;		/* number of chars left in this line */
-	int lleft;		/* number of chars left in this buffer */
-	char *nextc;		/* next char in buffer */
-	char *buf;		/* input buffer */
-	struct strpush *strpush; /* for pushing strings at this level */
-	struct strpush basestrpush; /* so pushing one is fast */
-};
-
-extern int parselleft;		/* copy of parsefile->lleft */
-extern struct parsefile basepf;	/* top level input file */
-extern char basebuf[BUFSIZ];	/* buffer for top level input file */
-
-extern pid_t backgndpid;	/* pid of last background process */
-extern int jobctl;
-
-extern int tokpushback;		/* last token pushed back */
-extern int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
-
-struct redirtab {
-	struct redirtab *next;
-	short renamed[10];
-};
-
-extern struct redirtab *redirlist;
-
-extern char sigmode[NSIG];	/* current value of signal */
-
-extern char **environ;
-
-
-
-/*
- * Initialization code.
- */
-
-void
-init() {
-
-      /* from exec.c: */
-      {
-	      hash_special_builtins();
-      }
-
-      /* from input.c: */
-      {
-	      basepf.nextc = basepf.buf = basebuf;
-      }
-
-      /* from var.c: */
-      {
-	      char **envp;
-
-	      initvar();
-	      for (envp = environ ; *envp ; envp++) {
-		      if (strchr(*envp, '=')) {
-			      setvareq(*envp, VEXPORT|VTEXTFIXED);
-		      }
-	      }
-      }
-}
-
-
-
-/*
- * This routine is called when an error or an interrupt occurs in an
- * interactive shell and control is returned to the main command loop.
- */
-
-void
-reset() {
-
-      /* from eval.c: */
-      {
-	      evalskip = 0;
-	      loopnest = 0;
-	      funcnest = 0;
-      }
-
-      /* from input.c: */
-      {
-	      if (exception != EXSHELLPROC)
-		      parselleft = parsenleft = 0;	/* clear input buffer */
-	      popallfiles();
-      }
-
-      /* from parser.c: */
-      {
-	      tokpushback = 0;
-	      checkkwd = 0;
-      }
-
-      /* from redir.c: */
-      {
-	      while (redirlist)
-		      popredir();
-      }
-
-      /* from output.c: */
-      {
-	      out1 = &output;
-	      out2 = &errout;
-	      if (memout.buf != NULL) {
-		      ckfree(memout.buf);
-		      memout.buf = NULL;
-	      }
-      }
-}
-
-
-
-/*
- * This routine is called to initialize the shell to run a shell procedure.
- */
-
-void
-initshellproc() {
-
-      /* from alias.c: */
-      {
-	      rmaliases();
-      }
-
-      /* from eval.c: */
-      {
-	      exitstatus = 0;
-      }
-
-      /* from exec.c: */
-      {
-	      deletefuncs();
-      }
-
-      /* from input.c: */
-      {
-	      popallfiles();
-      }
-
-      /* from jobs.c: */
-      {
-	      backgndpid = -1;
-#if JOBS
-	      jobctl = 0;
-#endif
-      }
-
-      /* from options.c: */
-      {
-	      int i;
-
-	      for (i = 0; optlist[i].name; i++)
-		      optlist[i].val = 0;
-	      optschanged();
-
-      }
-
-      /* from redir.c: */
-      {
-	      clearredir(0);
-      }
-
-      /* from trap.c: */
-      {
-	      char *sm;
-
-	      clear_traps(0);
-	      for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
-		      if (*sm == S_IGN)
-			      *sm = S_HARD_IGN;
-	      }
-      }
-
-      /* from var.c: */
-      {
-	      shprocvar();
-      }
-}
diff --git a/sh/init.h b/sh/init.h
deleted file mode 100644
index 60d924e..0000000
--- a/sh/init.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*	$NetBSD: init.h,v 1.10 2003/08/07 09:05:32 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)init.h	8.2 (Berkeley) 5/4/95
- */
-
-void init(void);
-void reset(void);
-void initshellproc(void);
diff --git a/sh/input.c b/sh/input.c
deleted file mode 100644
index 056ee8b..0000000
--- a/sh/input.c
+++ /dev/null
@@ -1,577 +0,0 @@
-/*	$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)input.c	8.3 (Berkeley) 6/9/95";
-#else
-__RCSID("$NetBSD: input.c,v 1.39 2003/08/07 09:05:32 agc Exp $");
-#endif
-#endif /* not lint */
-
-#include <stdio.h>	/* defines BUFSIZ */
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * This file implements the input routines used by the parser.
- */
-
-#include "shell.h"
-#include "redir.h"
-#include "syntax.h"
-#include "input.h"
-#include "output.h"
-#include "options.h"
-#include "memalloc.h"
-#include "error.h"
-#include "alias.h"
-#include "parser.h"
-#include "myhistedit.h"
-
-#ifdef WITH_LINENOISE
-#include "linenoise.h"
-#endif
-
-#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
-
-MKINIT
-struct strpush {
-	struct strpush *prev;	/* preceding string on stack */
-	char *prevstring;
-	int prevnleft;
-	int prevlleft;
-	struct alias *ap;	/* if push was associated with an alias */
-};
-
-/*
- * The parsefile structure pointed to by the global variable parsefile
- * contains information about the current file being read.
- */
-
-MKINIT
-struct parsefile {
-	struct parsefile *prev;	/* preceding file on stack */
-	int linno;		/* current line */
-	int fd;			/* file descriptor (or -1 if string) */
-	int nleft;		/* number of chars left in this line */
-	int lleft;		/* number of chars left in this buffer */
-	char *nextc;		/* next char in buffer */
-	char *buf;		/* input buffer */
-	struct strpush *strpush; /* for pushing strings at this level */
-	struct strpush basestrpush; /* so pushing one is fast */
-};
-
-
-int plinno = 1;			/* input line number */
-int parsenleft;			/* copy of parsefile->nleft */
-MKINIT int parselleft;		/* copy of parsefile->lleft */
-char *parsenextc;		/* copy of parsefile->nextc */
-MKINIT struct parsefile basepf;	/* top level input file */
-MKINIT char basebuf[BUFSIZ];	/* buffer for top level input file */
-struct parsefile *parsefile = &basepf;	/* current input file */
-int init_editline = 0;		/* editline library initialized? */
-int whichprompt;		/* 1 == PS1, 2 == PS2 */
-
-#if WITH_HISTORY
-EditLine *el;			/* cookie for editline package */
-#endif
-
-STATIC void pushfile(void);
-static int preadfd(void);
-
-#ifdef mkinit
-INCLUDE <stdio.h>
-INCLUDE "input.h"
-INCLUDE "error.h"
-
-INIT {
-	basepf.nextc = basepf.buf = basebuf;
-}
-
-RESET {
-	if (exception != EXSHELLPROC)
-		parselleft = parsenleft = 0;	/* clear input buffer */
-	popallfiles();
-}
-
-SHELLPROC {
-	popallfiles();
-}
-#endif
-
-
-/*
- * Read a line from the script.
- */
-
-char *
-pfgets(char *line, int len)
-{
-	char *p = line;
-	int nleft = len;
-	int c;
-
-	while (--nleft > 0) {
-		c = pgetc_macro();
-		if (c == PEOF) {
-			if (p == line)
-				return NULL;
-			break;
-		}
-		*p++ = c;
-		if (c == '\n')
-			break;
-	}
-	*p = '\0';
-	return line;
-}
-
-
-
-/*
- * Read a character from the script, returning PEOF on end of file.
- * Nul characters in the input are silently discarded.
- */
-
-int
-pgetc(void)
-{
-	return pgetc_macro();
-}
-
-int in_interactive_mode() {
-    return parsefile != NULL && parsefile->fd == 0;
-}
-
-static int
-preadfd(void)
-{
-	int nr;
-	char *buf =  parsefile->buf;
-	parsenextc = buf;
-
-retry:
-#ifdef WITH_HISTORY
-	if (parsefile->fd == 0 && el) {
-		static const char *rl_cp;
-		static int el_len;
-
-		if (rl_cp == NULL)
-			rl_cp = el_gets(el, &el_len);
-		if (rl_cp == NULL)
-			nr = 0;
-		else {
-			nr = el_len;
-			if (nr > BUFSIZ - 8)
-				nr = BUFSIZ - 8;
-			memcpy(buf, rl_cp, nr);
-			if (nr != el_len) {
-				el_len -= nr;
-				rl_cp += nr;
-			} else
-				rl_cp = 0;
-		}
-
-	} else
-#endif
-#ifdef WITH_LINENOISE
-    if (parsefile->fd == 0) {
-        static char *rl_start;
-        static const char *rl_cp;
-        static int el_len;
-
-        if (rl_cp == NULL) {
-            rl_cp = rl_start = linenoise(getprompt(""));
-            if (rl_cp != NULL) {
-                el_len = strlen(rl_start);
-                if (el_len != 0) {
-                    /* Add non-blank lines to history. */
-                    linenoiseHistoryAdd(rl_start);
-                }
-                out2str("\n");
-                /* Client expects a newline at end of input, doesn't expect null */
-                rl_start[el_len++] = '\n';
-            }
-        }
-        if (rl_cp == NULL)
-            nr = 0;
-        else {
-            nr = el_len;
-            if (nr > BUFSIZ - 8)
-                nr = BUFSIZ - 8;
-            memcpy(buf, rl_cp, nr);
-            if (nr != el_len) {
-                el_len -= nr;
-                rl_cp += nr;
-            } else {
-                rl_cp = 0;
-                if (rl_start != NULL) {
-                    free(rl_start);
-                    rl_start = NULL;
-                }
-            }
-        }
-    } else
-#endif
-		nr = read(parsefile->fd, buf, BUFSIZ - 8);
-
-
-	if (nr <= 0) {
-                if (nr < 0) {
-                        if (errno == EINTR)
-                                goto retry;
-                        if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
-                                int flags = fcntl(0, F_GETFL, 0);
-                                if (flags >= 0 && flags & O_NONBLOCK) {
-                                        flags &=~ O_NONBLOCK;
-                                        if (fcntl(0, F_SETFL, flags) >= 0) {
-						out2str("sh: turning off NDELAY mode\n");
-                                                goto retry;
-                                        }
-                                }
-                        }
-                }
-                nr = -1;
-	}
-	return nr;
-}
-
-/*
- * Refill the input buffer and return the next input character:
- *
- * 1) If a string was pushed back on the input, pop it;
- * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
- *    from a string so we can't refill the buffer, return EOF.
- * 3) If the is more stuff in this buffer, use it else call read to fill it.
- * 4) Process input up to the next newline, deleting nul characters.
- */
-
-int
-preadbuffer(void)
-{
-	char *p, *q;
-	int more;
-	int something;
-	char savec;
-
-	if (parsefile->strpush) {
-		popstring();
-		if (--parsenleft >= 0)
-			return (*parsenextc++);
-	}
-	if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
-		return PEOF;
-	flushout(&output);
-	flushout(&errout);
-
-again:
-	if (parselleft <= 0) {
-		if ((parselleft = preadfd()) == -1) {
-			parselleft = parsenleft = EOF_NLEFT;
-			return PEOF;
-		}
-	}
-
-	q = p = parsenextc;
-
-	/* delete nul characters */
-	something = 0;
-	for (more = 1; more;) {
-		switch (*p) {
-		case '\0':
-			p++;	/* Skip nul */
-			goto check;
-
-		case '\t':
-		case ' ':
-			break;
-
-		case '\n':
-			parsenleft = q - parsenextc;
-			more = 0; /* Stop processing here */
-			break;
-
-		default:
-			something = 1;
-			break;
-		}
-
-		*q++ = *p++;
-check:
-		if (--parselleft <= 0) {
-			parsenleft = q - parsenextc - 1;
-			if (parsenleft < 0)
-				goto again;
-			*q = '\0';
-			more = 0;
-		}
-	}
-
-	savec = *q;
-	*q = '\0';
-
-#ifdef WITH_HISTORY
-	if (parsefile->fd == 0 && hist && something) {
-		HistEvent he;
-		INTOFF;
-		history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
-		    parsenextc);
-		INTON;
-	}
-#endif
-
-	if (vflag) {
-		out2str(parsenextc);
-		flushout(out2);
-	}
-
-	*q = savec;
-
-	return *parsenextc++;
-}
-
-/*
- * Undo the last call to pgetc.  Only one character may be pushed back.
- * PEOF may be pushed back.
- */
-
-void
-pungetc(void)
-{
-	parsenleft++;
-	parsenextc--;
-}
-
-/*
- * Push a string back onto the input at this current parsefile level.
- * We handle aliases this way.
- */
-void
-pushstring(char *s, int len, void *ap)
-{
-	struct strpush *sp;
-
-	INTOFF;
-/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
-	if (parsefile->strpush) {
-		sp = ckmalloc(sizeof (struct strpush));
-		sp->prev = parsefile->strpush;
-		parsefile->strpush = sp;
-	} else
-		sp = parsefile->strpush = &(parsefile->basestrpush);
-	sp->prevstring = parsenextc;
-	sp->prevnleft = parsenleft;
-	sp->prevlleft = parselleft;
-	sp->ap = (struct alias *)ap;
-	if (ap)
-		((struct alias *)ap)->flag |= ALIASINUSE;
-	parsenextc = s;
-	parsenleft = len;
-	INTON;
-}
-
-void
-popstring(void)
-{
-	struct strpush *sp = parsefile->strpush;
-
-	INTOFF;
-	parsenextc = sp->prevstring;
-	parsenleft = sp->prevnleft;
-	parselleft = sp->prevlleft;
-/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
-	if (sp->ap)
-		sp->ap->flag &= ~ALIASINUSE;
-	parsefile->strpush = sp->prev;
-	if (sp != &(parsefile->basestrpush))
-		ckfree(sp);
-	INTON;
-}
-
-/*
- * Set the input to take input from a file.  If push is set, push the
- * old input onto the stack first.
- */
-
-void
-setinputfile(const char *fname, int push)
-{
-	int fd;
-	int fd2;
-
-	INTOFF;
-	if ((fd = open(fname, O_RDONLY)) < 0)
-		error("Can't open %s", fname);
-	if (fd < 10) {
-		fd2 = copyfd(fd, 10);
-		close(fd);
-		if (fd2 < 0)
-			error("Out of file descriptors");
-		fd = fd2;
-	}
-	setinputfd(fd, push);
-	INTON;
-}
-
-
-/*
- * Like setinputfile, but takes an open file descriptor.  Call this with
- * interrupts off.
- */
-
-void
-setinputfd(int fd, int push)
-{
-	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
-	if (push) {
-		pushfile();
-		parsefile->buf = ckmalloc(BUFSIZ);
-	}
-	if (parsefile->fd > 0)
-		close(parsefile->fd);
-	parsefile->fd = fd;
-	if (parsefile->buf == NULL)
-		parsefile->buf = ckmalloc(BUFSIZ);
-	parselleft = parsenleft = 0;
-	plinno = 1;
-}
-
-
-/*
- * Like setinputfile, but takes input from a string.
- */
-
-void
-setinputstring(char *string, int push)
-{
-	INTOFF;
-	if (push)
-		pushfile();
-	parsenextc = string;
-	parselleft = parsenleft = strlen(string);
-	parsefile->buf = NULL;
-	plinno = 1;
-	INTON;
-}
-
-
-
-/*
- * To handle the "." command, a stack of input files is used.  Pushfile
- * adds a new entry to the stack and popfile restores the previous level.
- */
-
-STATIC void
-pushfile(void)
-{
-	struct parsefile *pf;
-
-	parsefile->nleft = parsenleft;
-	parsefile->lleft = parselleft;
-	parsefile->nextc = parsenextc;
-	parsefile->linno = plinno;
-	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
-	pf->prev = parsefile;
-	pf->fd = -1;
-	pf->strpush = NULL;
-	pf->basestrpush.prev = NULL;
-	parsefile = pf;
-}
-
-
-void
-popfile(void)
-{
-	struct parsefile *pf = parsefile;
-
-	INTOFF;
-	if (pf->fd >= 0)
-		close(pf->fd);
-	if (pf->buf)
-		ckfree(pf->buf);
-	while (pf->strpush)
-		popstring();
-	parsefile = pf->prev;
-	ckfree(pf);
-	parsenleft = parsefile->nleft;
-	parselleft = parsefile->lleft;
-	parsenextc = parsefile->nextc;
-	plinno = parsefile->linno;
-	INTON;
-}
-
-
-/*
- * Return to top level.
- */
-
-void
-popallfiles(void)
-{
-	while (parsefile != &basepf)
-		popfile();
-}
-
-
-
-/*
- * Close the file(s) that the shell is reading commands from.  Called
- * after a fork is done.
- *
- * Takes one arg, vfork, which tells it to not modify its global vars
- * as it is still running in the parent.
- *
- * This code is (probably) unnecessary as the 'close on exec' flag is
- * set and should be enough.  In the vfork case it is definitely wrong
- * to close the fds as another fork() may be done later to feed data
- * from a 'here' document into a pipe and we don't want to close the
- * pipe!
- */
-
-void
-closescript(int vforked)
-{
-	if (vforked)
-		return;
-	popallfiles();
-	if (parsefile->fd > 0) {
-		close(parsefile->fd);
-		parsefile->fd = 0;
-	}
-}
diff --git a/sh/input.h b/sh/input.h
deleted file mode 100644
index 99c1b77..0000000
--- a/sh/input.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*	$NetBSD: input.h,v 1.15 2003/08/07 09:05:33 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)input.h	8.2 (Berkeley) 5/4/95
- */
-
-/* PEOF (the end of file marker) is defined in syntax.h */
-
-/*
- * The input line number.  Input.c just defines this variable, and saves
- * and restores it when files are pushed and popped.  The user of this
- * package must set its value.
- */
-extern int plinno;
-extern int parsenleft;		/* number of characters left in input buffer */
-extern char *parsenextc;	/* next character in input buffer */
-extern int init_editline;	/* 0 == not setup, 1 == OK, -1 == failed */
-
-int in_interactive_mode();
-char *pfgets(char *, int);
-int pgetc(void);
-int preadbuffer(void);
-void pungetc(void);
-void pushstring(char *, int, void *);
-void popstring(void);
-void setinputfile(const char *, int);
-void setinputfd(int, int);
-void setinputstring(char *, int);
-void popfile(void);
-void popallfiles(void);
-void closescript(int);
-
-#define pgetc_macro()	(--parsenleft >= 0? *parsenextc++ : preadbuffer())
diff --git a/sh/jobs.c b/sh/jobs.c
deleted file mode 100644
index b9460b0..0000000
--- a/sh/jobs.c
+++ /dev/null
@@ -1,1487 +0,0 @@
-/*	$NetBSD: jobs.c,v 1.62 2003/12/18 00:56:05 christos Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: jobs.c,v 1.62 2003/12/18 00:56:05 christos Exp $");
-#endif
-#endif /* not lint */
-
-#include <fcntl.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#define _PATH_DEVNULL "/dev/null"
-#include <sys/types.h>
-#include <sys/param.h>
-#ifdef BSD
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#endif
-#include <sys/wait.h>
-#define killpg(s,i) kill(-(s),i)
-#include <sys/ioctl.h>
-
-#include "shell.h"
-#if JOBS
-#if OLD_TTY_DRIVER
-#include "sgtty.h"
-#else
-#include <termios.h>
-#endif
-#undef CEOF			/* syntax.h redefines this */
-#endif
-#include "redir.h"
-#include "show.h"
-#include "main.h"
-#include "parser.h"
-#include "nodes.h"
-#include "jobs.h"
-#include "options.h"
-#include "trap.h"
-#include "syntax.h"
-#include "input.h"
-#include "output.h"
-#include "memalloc.h"
-#include "error.h"
-#include "mystring.h"
-
-// Use of process groups is disabled to allow adb shell children to terminate when the shell dies
-#define USE_PROCESS_GROUPS
-
-
-static struct job *jobtab;		/* array of jobs */
-static int njobs;			/* size of array */
-static int jobs_invalid;		/* set in child */
-MKINIT pid_t backgndpid = -1;	/* pid of last background process */
-#if JOBS
-int initialpgrp;		/* pgrp of shell on invocation */
-static int curjob = -1;		/* current job */
-#endif
-static int ttyfd = -1;
-
-STATIC void restartjob(struct job *);
-STATIC void freejob(struct job *);
-STATIC struct job *getjob(const char *, int);
-STATIC int dowait(int, struct job *);
-STATIC int onsigchild(void);
-STATIC int waitproc(int, struct job *, int *);
-STATIC void cmdtxt(union node *);
-STATIC void cmdlist(union node *, int);
-STATIC void cmdputs(const char *);
-
-#ifdef OLD_TTY_DRIVER
-static pid_t tcgetpgrp(int fd);
-static int tcsetpgrp(int fd, pid_t pgrp);
-
-static pid_t
-tcgetpgrp(int fd)
-{
-	pid_t pgrp;
-	if (ioctl(fd, TIOCGPGRP, (char *)&pgrp) == -1)
-		return -1;
-	else
-		return pgrp;
-}
-
-static int
-tcsetpgrp(int fd, pid_tpgrp)
-{
-	return ioctl(fd, TIOCSPGRP, (char *)&pgrp);
-}
-#endif
-
-/*
- * Turn job control on and off.
- *
- * Note:  This code assumes that the third arg to ioctl is a character
- * pointer, which is true on Berkeley systems but not System V.  Since
- * System V doesn't have job control yet, this isn't a problem now.
- */
-
-MKINIT int jobctl;
-
-void
-setjobctl(int on)
-{
-#ifdef OLD_TTY_DRIVER
-	int ldisc;
-#endif
-
-	if (on == jobctl || rootshell == 0)
-		return;
-	if (on) {
-#if defined(FIOCLEX) || defined(FD_CLOEXEC)
-		int err;
-		int i;
-		if (ttyfd != -1)
-			close(ttyfd);
-		if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) {
-			for (i = 0; i < 3; i++) {
-				if (isatty(i) && (ttyfd = dup(i)) != -1)
-					break;
-			}
-			if (i == 3)
-				goto out;
-		}
-		/* Move to a high fd */
-		for (i = 10; i > 2; i--) {
-			if ((err = fcntl(ttyfd, F_DUPFD, (1 << i) - 1)) != -1)
-				break;
-		}
-		if (err != -1) {
-			close(ttyfd);
-			ttyfd = err;
-		}
-#ifdef FIOCLEX
-		err = ioctl(ttyfd, FIOCLEX, 0);
-#elif FD_CLOEXEC
-		err = fcntl(ttyfd, F_SETFD,
-		    fcntl(ttyfd, F_GETFD, 0) | FD_CLOEXEC);
-#endif
-		if (err == -1) {
-			close(ttyfd);
-			ttyfd = -1;
-			goto out;
-		}
-#else
-		out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control");
-		goto out;
-#endif
-		do { /* while we are in the background */
-			if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) {
-out:
-				out2str("sh: can't access tty; job control turned off\n");
-				mflag = 0;
-				return;
-			}
-			if (initialpgrp == -1)
-				initialpgrp = getpgrp();
-			else if (initialpgrp != getpgrp()) {
-				killpg(0, SIGTTIN);
-				continue;
-			}
-		} while (0);
-
-#ifdef OLD_TTY_DRIVER
-		if (ioctl(ttyfd, TIOCGETD, (char *)&ldisc) < 0
-		    || ldisc != NTTYDISC) {
-			out2str("sh: need new tty driver to run job control; job control turned off\n");
-			mflag = 0;
-			return;
-		}
-#endif
-		setsignal(SIGTSTP, 0);
-		setsignal(SIGTTOU, 0);
-		setsignal(SIGTTIN, 0);
-#ifdef USE_PROCESS_GROUPS
-		if (getpgid(0) != rootpid && setpgid(0, rootpid) == -1)
-			error("Cannot set process group (%s) at %d",
-			    strerror(errno), __LINE__);
-		if (tcsetpgrp(ttyfd, rootpid) == -1)
-			error("Cannot set tty process group (%s) at %d",
-			    strerror(errno), __LINE__);
-#endif
-	} else { /* turning job control off */
-#ifdef USE_PROCESS_GROUPS
-		if (getpgid(0) != initialpgrp && setpgid(0, initialpgrp) == -1)
-			error("Cannot set process group (%s) at %d",
-			    strerror(errno), __LINE__);
-		if (tcsetpgrp(ttyfd, initialpgrp) == -1)
-			error("Cannot set tty process group (%s) at %d",
-			    strerror(errno), __LINE__);
-#endif
-		close(ttyfd);
-		ttyfd = -1;
-		setsignal(SIGTSTP, 0);
-		setsignal(SIGTTOU, 0);
-		setsignal(SIGTTIN, 0);
-	}
-	jobctl = on;
-}
-
-
-#ifdef mkinit
-INCLUDE <stdlib.h>
-
-SHELLPROC {
-	backgndpid = -1;
-#if JOBS
-	jobctl = 0;
-#endif
-}
-
-#endif
-
-
-
-#if JOBS
-int
-fgcmd(int argc, char **argv)
-{
-	struct job *jp;
-	int i;
-	int status;
-
-	nextopt("");
-	jp = getjob(*argptr, 0);
-	if (jp->jobctl == 0)
-		error("job not created under job control");
-	out1fmt("%s", jp->ps[0].cmd);
-	for (i = 1; i < jp->nprocs; i++)
-		out1fmt(" | %s", jp->ps[i].cmd );
-	out1c('\n');
-	flushall();
-
-	for (i = 0; i < jp->nprocs; i++)
-	    if (tcsetpgrp(ttyfd, jp->ps[i].pid) != -1)
-		    break;
-
-	if (i >= jp->nprocs) {
-		error("Cannot set tty process group (%s) at %d",
-		    strerror(errno), __LINE__);
-	}
-	restartjob(jp);
-	INTOFF;
-	status = waitforjob(jp);
-	INTON;
-	return status;
-}
-
-static void
-set_curjob(struct job *jp, int mode)
-{
-	struct job *jp1, *jp2;
-	int i, ji;
-
-	ji = jp - jobtab;
-
-	/* first remove from list */
-	if (ji == curjob)
-		curjob = jp->prev_job;
-	else {
-		for (i = 0; i < njobs; i++) {
-			if (jobtab[i].prev_job != ji)
-				continue;
-			jobtab[i].prev_job = jp->prev_job;
-			break;
-		}
-	}
-
-	/* Then re-insert in correct position */
-	switch (mode) {
-	case 0:	/* job being deleted */
-		jp->prev_job = -1;
-		break;
-	case 1:	/* newly created job or backgrounded job,
-		   put after all stopped jobs. */
-		if (curjob != -1 && jobtab[curjob].state == JOBSTOPPED) {
-			for (jp1 = jobtab + curjob; ; jp1 = jp2) {
-				if (jp1->prev_job == -1)
-					break;
-				jp2 = jobtab + jp1->prev_job;
-				if (jp2->state != JOBSTOPPED)
-					break;
-			}
-			jp->prev_job = jp1->prev_job;
-			jp1->prev_job = ji;
-			break;
-		}
-		/* FALLTHROUGH */
-	case 2:	/* newly stopped job - becomes curjob */
-		jp->prev_job = curjob;
-		curjob = ji;
-		break;
-	}
-}
-
-int
-bgcmd(int argc, char **argv)
-{
-	struct job *jp;
-	int i;
-
-	nextopt("");
-	do {
-		jp = getjob(*argptr, 0);
-		if (jp->jobctl == 0)
-			error("job not created under job control");
-		set_curjob(jp, 1);
-		out1fmt("[%ld] %s", (long)(jp - jobtab + 1), jp->ps[0].cmd);
-		for (i = 1; i < jp->nprocs; i++)
-			out1fmt(" | %s", jp->ps[i].cmd );
-		out1c('\n');
-		flushall();
-		restartjob(jp);
-	} while (*argptr && *++argptr);
-	return 0;
-}
-
-
-STATIC void
-restartjob(struct job *jp)
-{
-	struct procstat *ps;
-	int i;
-
-	if (jp->state == JOBDONE)
-		return;
-	INTOFF;
-	for (i = 0; i < jp->nprocs; i++)
-		if (killpg(jp->ps[i].pid, SIGCONT) != -1)
-			break;
-	if (i >= jp->nprocs)
-		error("Cannot continue job (%s)", strerror(errno));
-	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
-		if (WIFSTOPPED(ps->status)) {
-			ps->status = -1;
-			jp->state = JOBRUNNING;
-		}
-	}
-	INTON;
-}
-#endif
-
-static void
-showjob(struct output *out, struct job *jp, int mode)
-{
-	int procno;
-	int st;
-	struct procstat *ps;
-	int col;
-	char s[64];
-
-#if JOBS
-	if (mode & SHOW_PGID) {
-		/* just output process (group) id of pipeline */
-		outfmt(out, "%ld\n", (long)jp->ps->pid);
-		return;
-	}
-#endif
-
-	procno = jp->nprocs;
-	if (!procno)
-		return;
-
-	if (mode & SHOW_PID)
-		mode |= SHOW_MULTILINE;
-
-	if ((procno > 1 && !(mode & SHOW_MULTILINE))
-	    || (mode & SHOW_SIGNALLED)) {
-		/* See if we have more than one status to report */
-		ps = jp->ps;
-		st = ps->status;
-		do {
-			int st1 = ps->status;
-			if (st1 != st)
-				/* yes - need multi-line output */
-				mode |= SHOW_MULTILINE;
-			if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1))
-				continue;
-			if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f)
-			    && st1 != SIGINT && st1 != SIGPIPE))
-				mode |= SHOW_ISSIG;
-
-		} while (ps++, --procno);
-		procno = jp->nprocs;
-	}
-
-	if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) {
-		if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) {
-			TRACE(("showjob: freeing job %d\n", jp - jobtab + 1));
-			freejob(jp);
-		}
-		return;
-	}
-
-	for (ps = jp->ps; --procno >= 0; ps++) {	/* for each process */
-		if (ps == jp->ps)
-			fmtstr(s, 16, "[%ld] %c ",
-				(long)(jp - jobtab + 1),
-#if JOBS
-				jp == jobtab + curjob ? '+' :
-				curjob != -1 && jp == jobtab +
-					    jobtab[curjob].prev_job ? '-' :
-#endif
-				' ');
-		else
-			fmtstr(s, 16, "      " );
-		col = strlen(s);
-		if (mode & SHOW_PID) {
-			fmtstr(s + col, 16, "%ld ", (long)ps->pid);
-			     col += strlen(s + col);
-		}
-		if (ps->status == -1) {
-			scopy("Running", s + col);
-		} else if (WIFEXITED(ps->status)) {
-			st = WEXITSTATUS(ps->status);
-			if (st)
-				fmtstr(s + col, 16, "Done(%d)", st);
-			else
-				fmtstr(s + col, 16, "Done");
-		} else {
-#if JOBS
-			if (WIFSTOPPED(ps->status)) 
-				st = WSTOPSIG(ps->status);
-			else /* WIFSIGNALED(ps->status) */
-#endif
-				st = WTERMSIG(ps->status);
-			st &= 0x7f;
-			if (st < NSIG && sys_siglist[st])
-				scopyn(sys_siglist[st], s + col, 32);
-			else
-				fmtstr(s + col, 16, "Signal %d", st);
-			if (WCOREDUMP(ps->status)) {
-				col += strlen(s + col);
-				scopyn(" (core dumped)", s + col,  64 - col);
-			}
-		}
-		col += strlen(s + col);
-		outstr(s, out);
-		do {
-			outc(' ', out);
-			col++;
-		} while (col < 30);
-		outstr(ps->cmd, out);
-		if (mode & SHOW_MULTILINE) {
-			if (procno > 0) {
-				outc(' ', out);
-				outc('|', out);
-			}
-		} else {
-			while (--procno >= 0)
-				outfmt(out, " | %s", (++ps)->cmd );
-		}
-		outc('\n', out);
-	}
-	flushout(out);
-	jp->changed = 0;
-	if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE))
-		freejob(jp);
-}
-
-
-int
-jobscmd(int argc, char **argv)
-{
-	int mode, m;
-	int sv = jobs_invalid;
-
-	jobs_invalid = 0;
-	mode = 0;
-	while ((m = nextopt("lp")))
-		if (m == 'l')
-			mode = SHOW_PID;
-		else
-			mode = SHOW_PGID;
-	if (*argptr)
-		do
-			showjob(out1, getjob(*argptr,0), mode);
-		while (*++argptr);
-	else
-		showjobs(out1, mode);
-	jobs_invalid = sv;
-	return 0;
-}
-
-
-/*
- * Print a list of jobs.  If "change" is nonzero, only print jobs whose
- * statuses have changed since the last call to showjobs.
- *
- * If the shell is interrupted in the process of creating a job, the
- * result may be a job structure containing zero processes.  Such structures
- * will be freed here.
- */
-
-void
-showjobs(struct output *out, int mode)
-{
-	int jobno;
-	struct job *jp;
-	int silent = 0, gotpid;
-
-	TRACE(("showjobs(%x) called\n", mode));
-
-	/* If not even one one job changed, there is nothing to do */
-	gotpid = dowait(0, NULL);
-	while (dowait(0, NULL) > 0)
-		continue;
-#ifdef JOBS
-	/*
-	 * Check if we are not in our foreground group, and if not
-	 * put us in it.
-	 */
-	if (mflag && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) {
-		if (tcsetpgrp(ttyfd, getpid()) == -1)
-			error("Cannot set tty process group (%s) at %d",
-			    strerror(errno), __LINE__);
-		TRACE(("repaired tty process group\n"));
-		silent = 1;
-	}
-#endif
-	if (jobs_invalid)
-		return;
-
-	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
-		if (!jp->used)
-			continue;
-		if (jp->nprocs == 0) {
-			freejob(jp);
-			continue;
-		}
-		if ((mode & SHOW_CHANGED) && !jp->changed)
-			continue;
-		if (silent && jp->changed) {
-			jp->changed = 0;
-			continue;
-		}
-		showjob(out, jp, mode);
-	}
-}
-
-/*
- * Mark a job structure as unused.
- */
-
-STATIC void
-freejob(struct job *jp)
-{
-	INTOFF;
-	if (jp->ps != &jp->ps0) {
-		ckfree(jp->ps);
-		jp->ps = &jp->ps0;
-	}
-	jp->nprocs = 0;
-	jp->used = 0;
-#if JOBS
-	set_curjob(jp, 0);
-#endif
-	INTON;
-}
-
-
-
-int
-waitcmd(int argc, char **argv)
-{
-	struct job *job;
-	int status, retval = 127;
-	struct job *jp;
-
-	nextopt("");
-
-	if (!*argptr) {
-		/* wait for all jobs */
-		jp = jobtab;
-		if (jobs_invalid)
-			return 0;
-		for (;;) {
-			if (jp >= jobtab + njobs) {
-				/* no running procs */
-				return 0;
-			}
-			if (!jp->used || jp->state != JOBRUNNING) {
-				jp++;
-				continue;
-			}
-			if (dowait(1, (struct job *)NULL) == -1)
-			       return 128 + SIGINT;
-			jp = jobtab;
-		}
-	}
-
-	for (; *argptr; argptr++) {
-		job = getjob(*argptr, 1);
-		if (!job) {
-			retval = 127;
-			continue;
-		}
-		/* loop until process terminated or stopped */
-		while (job->state == JOBRUNNING) {
-			if (dowait(1, (struct job *)NULL) == -1)
-			       return 128 + SIGINT;
-		}
-		status = job->ps[job->nprocs].status;
-		if (WIFEXITED(status))
-			retval = WEXITSTATUS(status);
-#if JOBS
-		else if (WIFSTOPPED(status))
-			retval = WSTOPSIG(status) + 128;
-#endif
-		else {
-			/* XXX: limits number of signals */
-			retval = WTERMSIG(status) + 128;
-		}
-		if (!iflag)
-			freejob(job);
-	}
-	return retval;
-}
-
-
-
-int
-jobidcmd(int argc, char **argv)
-{
-	struct job *jp;
-	int i;
-
-	nextopt("");
-	jp = getjob(*argptr, 0);
-	for (i = 0 ; i < jp->nprocs ; ) {
-		out1fmt("%ld", (long)jp->ps[i].pid);
-		out1c(++i < jp->nprocs ? ' ' : '\n');
-	}
-	return 0;
-}
-
-int
-getjobpgrp(const char *name)
-{
-	struct job *jp;
-
-	jp = getjob(name, 1);
-	if (jp == 0)
-		return 0;
-	return -jp->ps[0].pid;
-}
-
-/*
- * Convert a job name to a job structure.
- */
-
-STATIC struct job *
-getjob(const char *name, int noerror)
-{
-	int jobno = -1;
-	struct job *jp;
-	int pid;
-	int i;
-	const char *err_msg = "No such job: %s";
-		
-	if (name == NULL) {
-#if JOBS
-		jobno = curjob;
-#endif
-		err_msg = "No current job";
-	} else if (name[0] == '%') {
-		if (is_number(name + 1)) {
-			jobno = number(name + 1) - 1;
-		} else if (!name[2]) {
-			switch (name[1]) {
-#if JOBS
-			case 0:
-			case '+':
-			case '%':
-				jobno = curjob;
-				err_msg = "No current job";
-				break;
-			case '-':
-				jobno = curjob;
-				if (jobno != -1)
-					jobno = jobtab[jobno].prev_job;
-				err_msg = "No previous job";
-				break;
-#endif
-			default:
-				goto check_pattern;
-			}
-		} else {
-			struct job *found;
-    check_pattern:
-			found = NULL;
-			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
-				if (!jp->used || jp->nprocs <= 0)
-					continue;
-				if ((name[1] == '?'
-					&& strstr(jp->ps[0].cmd, name + 2))
-				    || prefix(name + 1, jp->ps[0].cmd)) {
-					if (found) {
-						err_msg = "%s: ambiguous";
-						found = 0;
-						break;
-					}
-					found = jp;
-				}
-			}
-			if (found)
-				return found;
-		}
-
-	} else if (is_number(name)) {
-		pid = number(name);
-		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
-			if (jp->used && jp->nprocs > 0
-			 && jp->ps[jp->nprocs - 1].pid == pid)
-				return jp;
-		}
-	}
-
-	if (!jobs_invalid && jobno >= 0 && jobno < njobs) {
-		jp = jobtab + jobno;
-		if (jp->used)
-			return jp;
-	}
-	if (!noerror)
-		error(err_msg, name);
-	return 0;
-}
-
-
-
-/*
- * Return a new job structure,
- */
-
-struct job *
-makejob(union node *node, int nprocs)
-{
-	int i;
-	struct job *jp;
-
-	if (jobs_invalid) {
-		for (i = njobs, jp = jobtab ; --i >= 0 ; jp++) {
-			if (jp->used)
-				freejob(jp);
-		}
-		jobs_invalid = 0;
-	}
-
-	for (i = njobs, jp = jobtab ; ; jp++) {
-		if (--i < 0) {
-			INTOFF;
-			if (njobs == 0) {
-				jobtab = ckmalloc(4 * sizeof jobtab[0]);
-			} else {
-				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
-				memcpy(jp, jobtab, njobs * sizeof jp[0]);
-				/* Relocate `ps' pointers */
-				for (i = 0; i < njobs; i++)
-					if (jp[i].ps == &jobtab[i].ps0)
-						jp[i].ps = &jp[i].ps0;
-				ckfree(jobtab);
-				jobtab = jp;
-			}
-			jp = jobtab + njobs;
-			for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
-			INTON;
-			break;
-		}
-		if (jp->used == 0)
-			break;
-	}
-	INTOFF;
-	jp->state = JOBRUNNING;
-	jp->used = 1;
-	jp->changed = 0;
-	jp->nprocs = 0;
-#if JOBS
-	jp->jobctl = jobctl;
-	set_curjob(jp, 1);
-#endif
-	if (nprocs > 1) {
-		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
-	} else {
-		jp->ps = &jp->ps0;
-	}
-	INTON;
-	TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
-	    jp - jobtab + 1));
-	return jp;
-}
-
-
-/*
- * Fork off a subshell.  If we are doing job control, give the subshell its
- * own process group.  Jp is a job structure that the job is to be added to.
- * N is the command that will be evaluated by the child.  Both jp and n may
- * be NULL.  The mode parameter can be one of the following:
- *	FORK_FG - Fork off a foreground process.
- *	FORK_BG - Fork off a background process.
- *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
- *		     process group even if job control is on.
- *
- * When job control is turned off, background processes have their standard
- * input redirected to /dev/null (except for the second and later processes
- * in a pipeline).
- */
-
-int
-forkshell(struct job *jp, union node *n, int mode)
-{
-	int pid;
-
-	TRACE(("forkshell(%%%d, %p, %d) called\n", jp - jobtab, n, mode));
-	switch ((pid = fork())) {
-	case -1:
-		TRACE(("Fork failed, errno=%d\n", errno));
-		INTON;
-		error("Cannot fork");
-		break;
-	case 0:
-		forkchild(jp, n, mode, 0);
-		return 0;
-	default:
-		return forkparent(jp, n, mode, pid);
-	}
-}
-
-int
-forkparent(struct job *jp, union node *n, int mode, pid_t pid)
-{
-	int pgrp;
-
-	if (rootshell && mode != FORK_NOJOB && mflag) {
-		if (jp == NULL || jp->nprocs == 0)
-			pgrp = pid;
-		else
-			pgrp = jp->ps[0].pid;
-#ifdef USE_PROCESS_GROUPS
-		/* This can fail because we are doing it in the child also */
-		(void)setpgid(pid, pgrp);
-#endif
-	}
-	if (mode == FORK_BG)
-		backgndpid = pid;		/* set $! */
-	if (jp) {
-		struct procstat *ps = &jp->ps[jp->nprocs++];
-		ps->pid = pid;
-		ps->status = -1;
-		ps->cmd[0] = 0;
-		if (/* iflag && rootshell && */ n)
-			commandtext(ps, n);
-	}
-	TRACE(("In parent shell:  child = %d\n", pid));
-	return pid;
-}
-
-void
-forkchild(struct job *jp, union node *n, int mode, int vforked)
-{
-	int wasroot;
-	int pgrp;
-	const char *devnull = _PATH_DEVNULL;
-	const char *nullerr = "Can't open %s";
-
-	wasroot = rootshell;
-	TRACE(("Child shell %d\n", getpid()));
-	if (!vforked)
-		rootshell = 0;
-
-	closescript(vforked);
-	clear_traps(vforked);
-#if JOBS
-	if (!vforked)
-		jobctl = 0;		/* do job control only in root shell */
-	if (wasroot && mode != FORK_NOJOB && mflag) {
-		if (jp == NULL || jp->nprocs == 0)
-			pgrp = getpid();
-		else
-			pgrp = jp->ps[0].pid;
-#ifdef USE_PROCESS_GROUPS
-		/* This can fail because we are doing it in the parent also */
-		(void)setpgid(0, pgrp);
-		if (mode == FORK_FG) {
-			if (tcsetpgrp(ttyfd, pgrp) == -1)
-				error("Cannot set tty process group (%s) at %d",
-				    strerror(errno), __LINE__);
-		}
-#endif
-		setsignal(SIGTSTP, vforked);
-		setsignal(SIGTTOU, vforked);
-	} else if (mode == FORK_BG) {
-		ignoresig(SIGINT, vforked);
-		ignoresig(SIGQUIT, vforked);
-		if ((jp == NULL || jp->nprocs == 0) &&
-		    ! fd0_redirected_p ()) {
-			close(0);
-			if (open(devnull, O_RDONLY) != 0)
-				error(nullerr, devnull);
-		}
-	}
-#else
-	if (mode == FORK_BG) {
-		ignoresig(SIGINT, vforked);
-		ignoresig(SIGQUIT, vforked);
-		if ((jp == NULL || jp->nprocs == 0) &&
-		    ! fd0_redirected_p ()) {
-			close(0);
-			if (open(devnull, O_RDONLY) != 0)
-				error(nullerr, devnull);
-		}
-	}
-#endif
-	if (wasroot && iflag) {
-		setsignal(SIGINT, vforked);
-		setsignal(SIGQUIT, vforked);
-		setsignal(SIGTERM, vforked);
-	}
-
-	if (!vforked)
-		jobs_invalid = 1;
-}
-
-/*
- * Wait for job to finish.
- *
- * Under job control we have the problem that while a child process is
- * running interrupts generated by the user are sent to the child but not
- * to the shell.  This means that an infinite loop started by an inter-
- * active user may be hard to kill.  With job control turned off, an
- * interactive user may place an interactive program inside a loop.  If
- * the interactive program catches interrupts, the user doesn't want
- * these interrupts to also abort the loop.  The approach we take here
- * is to have the shell ignore interrupt signals while waiting for a
- * forground process to terminate, and then send itself an interrupt
- * signal if the child process was terminated by an interrupt signal.
- * Unfortunately, some programs want to do a bit of cleanup and then
- * exit on interrupt; unless these processes terminate themselves by
- * sending a signal to themselves (instead of calling exit) they will
- * confuse this approach.
- */
-
-int
-waitforjob(struct job *jp)
-{
-#if JOBS
-	int mypgrp = getpgrp();
-#endif
-	int status;
-	int st;
-
-	INTOFF;
-	TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
-	while (jp->state == JOBRUNNING) {
-		dowait(1, jp);
-	}
-#if JOBS
-	if (jp->jobctl) {
-		if (tcsetpgrp(ttyfd, mypgrp) == -1)
-			error("Cannot set tty process group (%s) at %d",
-			    strerror(errno), __LINE__);
-	}
-	if (jp->state == JOBSTOPPED && curjob != jp - jobtab)
-		set_curjob(jp, 2);
-#endif
-	status = jp->ps[jp->nprocs - 1].status;
-	/* convert to 8 bits */
-	if (WIFEXITED(status))
-		st = WEXITSTATUS(status);
-#if JOBS
-	else if (WIFSTOPPED(status))
-		st = WSTOPSIG(status) + 128;
-#endif
-	else
-		st = WTERMSIG(status) + 128;
-	TRACE(("waitforjob: job %d, nproc %d, status %x, st %x\n",
-		jp - jobtab + 1, jp->nprocs, status, st ));
-#if JOBS
-	if (jp->jobctl) {
-		/*
-		 * This is truly gross.
-		 * If we're doing job control, then we did a TIOCSPGRP which
-		 * caused us (the shell) to no longer be in the controlling
-		 * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
-		 * intuit from the subprocess exit status whether a SIGINT
-		 * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
-		 */
-		if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
-			raise(SIGINT);
-	}
-#endif
-	if (! JOBS || jp->state == JOBDONE)
-		freejob(jp);
-	INTON;
-	return st;
-}
-
-
-
-/*
- * Wait for a process to terminate.
- */
-
-STATIC int
-dowait(int block, struct job *job)
-{
-	int pid;
-	int status;
-	struct procstat *sp;
-	struct job *jp;
-	struct job *thisjob;
-	int done;
-	int stopped;
-	extern volatile char gotsig[];
-
-	TRACE(("dowait(%d) called\n", block));
-	do {
-		pid = waitproc(block, job, &status);
-		TRACE(("wait returns pid %d, status %d\n", pid, status));
-	} while (pid == -1 && errno == EINTR && gotsig[SIGINT - 1] == 0);
-	if (pid <= 0)
-		return pid;
-	INTOFF;
-	thisjob = NULL;
-	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
-		if (jp->used) {
-			done = 1;
-			stopped = 1;
-			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
-				if (sp->pid == -1)
-					continue;
-				if (sp->pid == pid) {
-					TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - jobtab + 1, pid, sp->status, status));
-					sp->status = status;
-					thisjob = jp;
-				}
-				if (sp->status == -1)
-					stopped = 0;
-				else if (WIFSTOPPED(sp->status))
-					done = 0;
-			}
-			if (stopped) {		/* stopped or done */
-				int state = done ? JOBDONE : JOBSTOPPED;
-				if (jp->state != state) {
-					TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
-					jp->state = state;
-#if JOBS
-					if (done)
-						set_curjob(jp, 0);
-#endif
-				}
-			}
-		}
-	}
-
-	if (thisjob && thisjob->state != JOBRUNNING) {
-		int mode = 0;
-		if (!rootshell || !iflag)
-			mode = SHOW_SIGNALLED;
-		if (job == thisjob)
-			mode = SHOW_SIGNALLED | SHOW_NO_FREE;
-		if (mode)
-			showjob(out2, thisjob, mode);
-		else {
-			TRACE(("Not printing status, rootshell=%d, job=%p\n",
-				rootshell, job));
-			thisjob->changed = 1;
-		}
-	}
-
-	INTON;
-	return pid;
-}
-
-
-
-/*
- * Do a wait system call.  If job control is compiled in, we accept
- * stopped processes.  If block is zero, we return a value of zero
- * rather than blocking.
- *
- * System V doesn't have a non-blocking wait system call.  It does
- * have a SIGCLD signal that is sent to a process when one of it's
- * children dies.  The obvious way to use SIGCLD would be to install
- * a handler for SIGCLD which simply bumped a counter when a SIGCLD
- * was received, and have waitproc bump another counter when it got
- * the status of a process.  Waitproc would then know that a wait
- * system call would not block if the two counters were different.
- * This approach doesn't work because if a process has children that
- * have not been waited for, System V will send it a SIGCLD when it
- * installs a signal handler for SIGCLD.  What this means is that when
- * a child exits, the shell will be sent SIGCLD signals continuously
- * until is runs out of stack space, unless it does a wait call before
- * restoring the signal handler.  The code below takes advantage of
- * this (mis)feature by installing a signal handler for SIGCLD and
- * then checking to see whether it was called.  If there are any
- * children to be waited for, it will be.
- *
- * If neither SYSV nor BSD is defined, we don't implement nonblocking
- * waits at all.  In this case, the user will not be informed when
- * a background process until the next time she runs a real program
- * (as opposed to running a builtin command or just typing return),
- * and the jobs command may give out of date information.
- */
-
-#ifdef SYSV
-STATIC int gotsigchild;
-
-STATIC int onsigchild() {
-	gotsigchild = 1;
-}
-#endif
-
-
-STATIC int
-waitproc(int block, struct job *jp, int *status)
-{
-#ifdef BSD
-	int flags = 0;
-
-#if JOBS
-	if (jp != NULL && jp->jobctl)
-		flags |= WUNTRACED;
-#endif
-	if (block == 0)
-		flags |= WNOHANG;
-	return wait3(status, flags, (struct rusage *)NULL);
-#else
-#ifdef SYSV
-	int (*save)();
-
-	if (block == 0) {
-		gotsigchild = 0;
-		save = signal(SIGCLD, onsigchild);
-		signal(SIGCLD, save);
-		if (gotsigchild == 0)
-			return 0;
-	}
-	return wait(status);
-#else
-	if (block == 0)
-		return 0;
-	return wait(status);
-#endif
-#endif
-}
-
-/*
- * return 1 if there are stopped jobs, otherwise 0
- */
-int job_warning = 0;
-int
-stoppedjobs(void)
-{
-	int jobno;
-	struct job *jp;
-
-	if (job_warning || jobs_invalid)
-		return (0);
-	for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
-		if (jp->used == 0)
-			continue;
-		if (jp->state == JOBSTOPPED) {
-			out2str("You have stopped jobs.\n");
-			job_warning = 2;
-			return (1);
-		}
-	}
-
-	return (0);
-}
-
-/*
- * Return a string identifying a command (to be printed by the
- * jobs command).
- */
-
-STATIC char *cmdnextc;
-STATIC int cmdnleft;
-
-void
-commandtext(struct procstat *ps, union node *n)
-{
-	int len;
-
-	cmdnextc = ps->cmd;
-	if (iflag || mflag || sizeof ps->cmd < 100)
-		len = sizeof(ps->cmd);
-	else
-		len = sizeof(ps->cmd) / 10;
-	cmdnleft = len;
-	cmdtxt(n);
-	if (cmdnleft <= 0) {
-		char *p = ps->cmd + len - 4;
-		p[0] = '.';
-		p[1] = '.';
-		p[2] = '.';
-		p[3] = 0;
-	} else
-		*cmdnextc = '\0';
-	TRACE(("commandtext: ps->cmd %x, end %x, left %d\n\t\"%s\"\n",
-		ps->cmd, cmdnextc, cmdnleft, ps->cmd));
-}
-
-
-STATIC void
-cmdtxt(union node *n)
-{
-	union node *np;
-	struct nodelist *lp;
-	const char *p;
-	int i;
-	char s[2];
-
-	if (n == NULL || cmdnleft <= 0)
-		return;
-	switch (n->type) {
-	case NSEMI:
-		cmdtxt(n->nbinary.ch1);
-		cmdputs("; ");
-		cmdtxt(n->nbinary.ch2);
-		break;
-	case NAND:
-		cmdtxt(n->nbinary.ch1);
-		cmdputs(" && ");
-		cmdtxt(n->nbinary.ch2);
-		break;
-	case NOR:
-		cmdtxt(n->nbinary.ch1);
-		cmdputs(" || ");
-		cmdtxt(n->nbinary.ch2);
-		break;
-	case NPIPE:
-		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
-			cmdtxt(lp->n);
-			if (lp->next)
-				cmdputs(" | ");
-		}
-		break;
-	case NSUBSHELL:
-		cmdputs("(");
-		cmdtxt(n->nredir.n);
-		cmdputs(")");
-		break;
-	case NREDIR:
-	case NBACKGND:
-		cmdtxt(n->nredir.n);
-		break;
-	case NIF:
-		cmdputs("if ");
-		cmdtxt(n->nif.test);
-		cmdputs("; then ");
-		cmdtxt(n->nif.ifpart);
-		if (n->nif.elsepart) {
-			cmdputs("; else ");
-			cmdtxt(n->nif.elsepart);
-		}
-		cmdputs("; fi");
-		break;
-	case NWHILE:
-		cmdputs("while ");
-		goto until;
-	case NUNTIL:
-		cmdputs("until ");
-until:
-		cmdtxt(n->nbinary.ch1);
-		cmdputs("; do ");
-		cmdtxt(n->nbinary.ch2);
-		cmdputs("; done");
-		break;
-	case NFOR:
-		cmdputs("for ");
-		cmdputs(n->nfor.var);
-		cmdputs(" in ");
-		cmdlist(n->nfor.args, 1);
-		cmdputs("; do ");
-		cmdtxt(n->nfor.body);
-		cmdputs("; done");
-		break;
-	case NCASE:
-		cmdputs("case ");
-		cmdputs(n->ncase.expr->narg.text);
-		cmdputs(" in ");
-		for (np = n->ncase.cases; np; np = np->nclist.next) {
-			cmdtxt(np->nclist.pattern);
-			cmdputs(") ");
-			cmdtxt(np->nclist.body);
-			cmdputs(";; ");
-		}
-		cmdputs("esac");
-		break;
-	case NDEFUN:
-		cmdputs(n->narg.text);
-		cmdputs("() { ... }");
-		break;
-	case NCMD:
-		cmdlist(n->ncmd.args, 1);
-		cmdlist(n->ncmd.redirect, 0);
-		break;
-	case NARG:
-		cmdputs(n->narg.text);
-		break;
-	case NTO:
-		p = ">";  i = 1;  goto redir;
-	case NCLOBBER:
-		p = ">|";  i = 1;  goto redir;
-	case NAPPEND:
-		p = ">>";  i = 1;  goto redir;
-	case NTOFD:
-		p = ">&";  i = 1;  goto redir;
-	case NFROM:
-		p = "<";  i = 0;  goto redir;
-	case NFROMFD:
-		p = "<&";  i = 0;  goto redir;
-	case NFROMTO:
-		p = "<>";  i = 0;  goto redir;
-redir:
-		if (n->nfile.fd != i) {
-			s[0] = n->nfile.fd + '0';
-			s[1] = '\0';
-			cmdputs(s);
-		}
-		cmdputs(p);
-		if (n->type == NTOFD || n->type == NFROMFD) {
-			s[0] = n->ndup.dupfd + '0';
-			s[1] = '\0';
-			cmdputs(s);
-		} else {
-			cmdtxt(n->nfile.fname);
-		}
-		break;
-	case NHERE:
-	case NXHERE:
-		cmdputs("<<...");
-		break;
-	default:
-		cmdputs("???");
-		break;
-	}
-}
-
-STATIC void
-cmdlist(union node *np, int sep)
-{
-	for (; np; np = np->narg.next) {
-		if (!sep)
-			cmdputs(" ");
-		cmdtxt(np);
-		if (sep && np->narg.next)
-			cmdputs(" ");
-	}
-}
-
-
-STATIC void
-cmdputs(const char *s)
-{
-	const char *p, *str = 0;
-	char c, cc[2] = " ";
-	char *nextc;
-	int nleft;
-	int subtype = 0;
-	int quoted = 0;
-	static char vstype[16][4] = { "", "}", "-", "+", "?", "=",
-					"#", "##", "%", "%%" };
-
-	p = s;
-	nextc = cmdnextc;
-	nleft = cmdnleft;
-	while (nleft > 0 && (c = *p++) != 0) {
-		switch (c) {
-		case CTLESC:
-			c = *p++;
-			break;
-		case CTLVAR:
-			subtype = *p++;
-			if ((subtype & VSTYPE) == VSLENGTH)
-				str = "${#";
-			else
-				str = "${";
-			if (!(subtype & VSQUOTE) != !(quoted & 1)) {
-				quoted ^= 1;
-				c = '"';
-			} else
-				c = *str++;
-			break;
-		case CTLENDVAR:
-			if (quoted & 1) {
-				c = '"';
-				str = "}";
-			} else
-				c = '}';
-			quoted >>= 1;
-			subtype = 0;
-			break;
-		case CTLBACKQ:
-			c = '$';
-			str = "(...)";
-			break;
-		case CTLBACKQ+CTLQUOTE:
-			c = '"';
-			str = "$(...)\"";
-			break;
-		case CTLARI:
-			c = '$';
-			str = "((";
-			break;
-		case CTLENDARI:
-			c = ')';
-			str = ")";
-			break;
-		case CTLQUOTEMARK:
-			quoted ^= 1;
-			c = '"';
-			break;
-		case '=':
-			if (subtype == 0)
-				break;
-			str = vstype[subtype & VSTYPE];
-			if (subtype & VSNUL)
-				c = ':';
-			else
-				c = *str++;
-			if (c != '}')
-				quoted <<= 1;
-			break;
-		case '\'':
-		case '\\':
-		case '"':
-		case '$':
-			/* These can only happen inside quotes */
-			cc[0] = c;
-			str = cc;
-			c = '\\';
-			break;
-		default:
-			break;
-		}
-		do {
-			*nextc++ = c;
-		} while (--nleft > 0 && str && (c = *str++));
-		str = 0;
-	}
-	if ((quoted & 1) && nleft) {
-		*nextc++ = '"';
-		nleft--;
-	}
-	cmdnleft = nleft;
-	cmdnextc = nextc;
-}
diff --git a/sh/jobs.h b/sh/jobs.h
deleted file mode 100644
index 47e76c2..0000000
--- a/sh/jobs.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*	$NetBSD: jobs.h,v 1.19 2003/11/27 21:16:14 dsl Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)jobs.h	8.2 (Berkeley) 5/4/95
- */
-
-#include "output.h"
-
-/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
-#define FORK_FG 0
-#define FORK_BG 1
-#define FORK_NOJOB 2
-
-/* mode flags for showjob(s) */
-#define	SHOW_PGID	0x01	/* only show pgid - for jobs -p */
-#define	SHOW_MULTILINE	0x02	/* one line per process */
-#define	SHOW_PID	0x04	/* include process pid */
-#define	SHOW_CHANGED	0x08	/* only jobs whose state has changed */
-#define	SHOW_SIGNALLED	0x10	/* only if stopped/exited on signal */
-#define	SHOW_ISSIG	0x20	/* job was signalled */
-#define	SHOW_NO_FREE	0x40	/* do not free job */
-
-
-/*
- * A job structure contains information about a job.  A job is either a
- * single process or a set of processes contained in a pipeline.  In the
- * latter case, pidlist will be non-NULL, and will point to a -1 terminated
- * array of pids.
- */
-#define	MAXCMDTEXT	200
-
-struct procstat {
-	pid_t	pid;		/* process id */
- 	int	status;		/* last process status from wait() */
- 	char	cmd[MAXCMDTEXT];/* text of command being run */
-};
-
-struct job {
-	struct procstat ps0;	/* status of process */
-	struct procstat *ps;	/* status or processes when more than one */
-	int	nprocs;		/* number of processes */
-	pid_t	pgrp;		/* process group of this job */
-	char	state;
-#define	JOBRUNNING	0	/* at least one proc running */
-#define	JOBSTOPPED	1	/* all procs are stopped */
-#define	JOBDONE		2	/* all procs are completed */
-	char	used;		/* true if this entry is in used */
-	char	changed;	/* true if status has changed */
-#if JOBS
-	char 	jobctl;		/* job running under job control */
-	int	prev_job;	/* previous job index */
-#endif
-};
-
-extern pid_t backgndpid;	/* pid of last background process */
-extern int job_warning;		/* user was warned about stopped jobs */
-
-void setjobctl(int);
-int fgcmd(int, char **);
-int bgcmd(int, char **);
-int jobscmd(int, char **);
-void showjobs(struct output *, int);
-int waitcmd(int, char **);
-int jobidcmd(int, char **);
-struct job *makejob(union node *, int);
-int forkshell(struct job *, union node *, int);
-void forkchild(struct job *, union node *, int, int);
-int forkparent(struct job *, union node *, int, pid_t);
-int waitforjob(struct job *);
-int stoppedjobs(void);
-void commandtext(struct procstat *, union node *);
-int getjobpgrp(const char *);
-
-#if ! JOBS
-#define setjobctl(on)	/* do nothing */
-#endif
diff --git a/sh/machdep.h b/sh/machdep.h
deleted file mode 100644
index 14e803b..0000000
--- a/sh/machdep.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*	$NetBSD: machdep.h,v 1.11 2003/08/07 09:05:33 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)machdep.h	8.2 (Berkeley) 5/4/95
- */
-
-/*
- * Most machines require the value returned from malloc to be aligned
- * in some way.  The following macro will get this right on many machines.
- */
-
-#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
-/*
- * It appears that grabstackstr() will barf with such alignments
- * because stalloc() will return a string allocated in a new stackblock.
- */
-#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
diff --git a/sh/main.c b/sh/main.c
deleted file mode 100644
index 43b154f..0000000
--- a/sh/main.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/*	$NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-__COPYRIGHT("@(#) Copyright (c) 1991, 1993\n\
-	The Regents of the University of California.  All rights reserved.\n");
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)main.c	8.7 (Berkeley) 7/19/95";
-#else
-__RCSID("$NetBSD: main.c,v 1.48 2003/09/14 12:09:29 jmmv Exp $");
-#endif
-#endif /* not lint */
-
-#include <errno.h>
-#include <stdio.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-
-#include "shell.h"
-#include "main.h"
-#include "options.h"
-#include "output.h"
-#include "parser.h"
-#include "nodes.h"
-#include "expand.h"
-#include "eval.h"
-#include "jobs.h"
-#include "input.h"
-#include "trap.h"
-#include "var.h"
-#include "show.h"
-#include "memalloc.h"
-#include "error.h"
-#include "init.h"
-#include "mystring.h"
-#include "exec.h"
-#include "cd.h"
-
-#define PROFILE 0
-
-int rootpid;
-int rootshell;
-STATIC union node *curcmd;
-STATIC union node *prevcmd;
-#if PROFILE
-short profile_buf[16384];
-extern int etext();
-#endif
-
-STATIC void read_profile(const char *);
-STATIC char *find_dot_file(char *);
-int main(int, char **);
-
-/*
- * Main routine.  We initialize things, parse the arguments, execute
- * profiles if we're a login shell, and then call cmdloop to execute
- * commands.  The setjmp call sets up the location to jump to when an
- * exception occurs.  When an exception occurs the variable "state"
- * is used to figure out how far we had gotten.
- */
-
-int
-main(int argc, char **argv)
-{
-	struct jmploc jmploc;
-	struct stackmark smark;
-	volatile int state;
-	char *shinit;
-
-#if PROFILE
-	monitor(4, etext, profile_buf, sizeof profile_buf, 50);
-#endif
-	state = 0;
-	if (setjmp(jmploc.loc)) {
-		/*
-		 * When a shell procedure is executed, we raise the
-		 * exception EXSHELLPROC to clean up before executing
-		 * the shell procedure.
-		 */
-		switch (exception) {
-		case EXSHELLPROC:
-			rootpid = getpid();
-			rootshell = 1;
-			minusc = NULL;
-			state = 3;
-			break;
-
-		case EXEXEC:
-			exitstatus = exerrno;
-			break;
-
-		case EXERROR:
-			exitstatus = 2;
-			break;
-
-		default:
-			break;
-		}
-
-		if (exception != EXSHELLPROC) {
-			if (state == 0 || iflag == 0 || ! rootshell)
-				exitshell(exitstatus);
-		}
-		reset();
-		if (exception == EXINT
-#if ATTY
-		 && (! attyset() || equal(termval(), "emacs"))
-#endif
-		 ) {
-			out2c('\n');
-			flushout(&errout);
-		}
-		popstackmark(&smark);
-		FORCEINTON;				/* enable interrupts */
-		if (state == 1)
-			goto state1;
-		else if (state == 2)
-			goto state2;
-		else if (state == 3)
-			goto state3;
-		else
-			goto state4;
-	}
-	handler = &jmploc;
-#ifdef DEBUG
-#if DEBUG == 2
-	debug = 1;
-#endif
-	opentrace();
-	trputs("Shell args:  ");  trargs(argv);
-#endif
-	rootpid = getpid();
-	rootshell = 1;
-	init();
-	setstackmark(&smark);
-	procargs(argc, argv);
-	if (argv[0] && argv[0][0] == '-') {
-		state = 1;
-		read_profile("/etc/profile");
-state1:
-		state = 2;
-		read_profile(".profile");
-	}
-state2:
-	state = 3;
-	if (getuid() == geteuid() && getgid() == getegid()) {
-		if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
-			state = 3;
-			read_profile(shinit);
-		}
-	}
-state3:
-	state = 4;
-	if (sflag == 0 || minusc) {
-		static int sigs[] =  {
-		    SIGINT, SIGQUIT, SIGHUP, 
-#ifdef SIGTSTP
-		    SIGTSTP,
-#endif
-		    SIGPIPE
-		};
-#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
-		int i;
-
-		for (i = 0; i < SIGSSIZE; i++)
-		    setsignal(sigs[i], 0);
-	}
-
-	if (minusc)
-		evalstring(minusc, 0);
-
-	if (sflag || minusc == NULL) {
-state4:	/* XXX ??? - why isn't this before the "if" statement */
-		cmdloop(1);
-	}
-#if PROFILE
-	monitor(0);
-#endif
-	exitshell(exitstatus);
-	/* NOTREACHED */
-}
-
-
-/*
- * Read and execute commands.  "Top" is nonzero for the top level command
- * loop; it turns on prompting if the shell is interactive.
- */
-
-void
-cmdloop(int top)
-{
-	union node *n;
-	struct stackmark smark;
-	int inter;
-	int numeof = 0;
-
-	TRACE(("cmdloop(%d) called\n", top));
-	setstackmark(&smark);
-	for (;;) {
-		if (pendingsigs)
-			dotrap();
-		inter = 0;
-		if (iflag && top) {
-			inter = 1;
-			showjobs(out2, SHOW_CHANGED);
-			flushout(&errout);
-		}
-		n = parsecmd(inter);
-		/* showtree(n); DEBUG */
-		if (n == NEOF) {
-			if (!top || numeof >= 50)
-				break;
-			if (!stoppedjobs()) {
-				if (!Iflag)
-					break;
-				out2str("\nUse \"exit\" to leave shell.\n");
-			}
-			numeof++;
-		} else if (n != NULL && nflag == 0) {
-			job_warning = (job_warning == 2) ? 1 : 0;
-			numeof = 0;
-			evaltree(n, 0);
-		}
-		popstackmark(&smark);
-		setstackmark(&smark);
-		if (evalskip == SKIPFILE) {
-			evalskip = 0;
-			break;
-		}
-	}
-	popstackmark(&smark);
-}
-
-
-
-/*
- * Read /etc/profile or .profile.  Return on error.
- */
-
-STATIC void
-read_profile(const char *name)
-{
-	int fd;
-	int xflag_set = 0;
-	int vflag_set = 0;
-
-	INTOFF;
-	if ((fd = open(name, O_RDONLY)) >= 0)
-		setinputfd(fd, 1);
-	INTON;
-	if (fd < 0)
-		return;
-	/* -q turns off -x and -v just when executing init files */
-	if (qflag)  {
-	    if (xflag)
-		    xflag = 0, xflag_set = 1;
-	    if (vflag)
-		    vflag = 0, vflag_set = 1;
-	}
-	cmdloop(0);
-	if (qflag)  {
-	    if (xflag_set)
-		    xflag = 1;
-	    if (vflag_set)
-		    vflag = 1;
-	}
-	popfile();
-}
-
-
-
-/*
- * Read a file containing shell functions.
- */
-
-void
-readcmdfile(char *name)
-{
-	int fd;
-
-	INTOFF;
-	if ((fd = open(name, O_RDONLY)) >= 0)
-		setinputfd(fd, 1);
-	else
-		error("Can't open %s", name);
-	INTON;
-	cmdloop(0);
-	popfile();
-}
-
-
-
-/*
- * Take commands from a file.  To be compatible we should do a path
- * search for the file, which is necessary to find sub-commands.
- */
-
-
-STATIC char *
-find_dot_file(char *basename)
-{
-	char *fullname;
-	const char *path = pathval();
-	struct stat statb;
-
-	/* don't try this for absolute or relative paths */
-	if (strchr(basename, '/'))
-		return basename;
-
-	while ((fullname = padvance(&path, basename)) != NULL) {
-		if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
-			/*
-			 * Don't bother freeing here, since it will
-			 * be freed by the caller.
-			 */
-			return fullname;
-		}
-		stunalloc(fullname);
-	}
-
-	/* not found in the PATH */
-	error("%s: not found", basename);
-	/* NOTREACHED */
-}
-
-int
-dotcmd(int argc, char **argv)
-{
-	exitstatus = 0;
-
-	if (argc >= 2) {		/* That's what SVR2 does */
-		char *fullname;
-		struct stackmark smark;
-
-		setstackmark(&smark);
-		fullname = find_dot_file(argv[1]);
-		setinputfile(fullname, 1);
-		commandname = fullname;
-		cmdloop(0);
-		popfile();
-		popstackmark(&smark);
-	}
-	return exitstatus;
-}
-
-
-int
-exitcmd(int argc, char **argv)
-{
-	if (stoppedjobs())
-		return 0;
-	if (argc > 1)
-		exitstatus = number(argv[1]);
-	exitshell(exitstatus);
-	/* NOTREACHED */
-}
diff --git a/sh/main.h b/sh/main.h
deleted file mode 100644
index d198e2d..0000000
--- a/sh/main.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*	$NetBSD: main.h,v 1.10 2003/08/07 09:05:34 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)main.h	8.2 (Berkeley) 5/4/95
- */
-
-extern int rootpid;	/* pid of main shell */
-extern int rootshell;	/* true if we aren't a child of the main shell */
-
-void readcmdfile(char *);
-void cmdloop(int);
-int dotcmd(int, char **);
-int exitcmd(int, char **);
diff --git a/sh/memalloc.c b/sh/memalloc.c
deleted file mode 100644
index 07c14db..0000000
--- a/sh/memalloc.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*	$NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)memalloc.c	8.3 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: memalloc.c,v 1.28 2003/08/07 09:05:34 agc Exp $");
-#endif
-#endif /* not lint */
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "shell.h"
-#include "output.h"
-#include "memalloc.h"
-#include "error.h"
-#include "machdep.h"
-#include "mystring.h"
-
-/*
- * Like malloc, but returns an error when out of space.
- */
-
-pointer
-ckmalloc(int nbytes)
-{
-	pointer p;
-
-	p = malloc(nbytes);
-	if (p == NULL)
-		error("Out of space");
-	return p;
-}
-
-
-/*
- * Same for realloc.
- */
-
-pointer
-ckrealloc(pointer p, int nbytes)
-{
-	p = realloc(p, nbytes);
-	if (p == NULL)
-		error("Out of space");
-	return p;
-}
-
-
-/*
- * Make a copy of a string in safe storage.
- */
-
-char *
-savestr(const char *s)
-{
-	char *p;
-
-	p = ckmalloc(strlen(s) + 1);
-	scopy(s, p);
-	return p;
-}
-
-
-/*
- * Parse trees for commands are allocated in lifo order, so we use a stack
- * to make this more efficient, and also to avoid all sorts of exception
- * handling code to handle interrupts in the middle of a parse.
- *
- * The size 504 was chosen because the Ultrix malloc handles that size
- * well.
- */
-
-#define MINSIZE 504		/* minimum size of a block */
-
-struct stack_block {
-	struct stack_block *prev;
-	char space[MINSIZE];
-};
-
-struct stack_block stackbase;
-struct stack_block *stackp = &stackbase;
-struct stackmark *markp;
-char *stacknxt = stackbase.space;
-int stacknleft = MINSIZE;
-int sstrnleft;
-int herefd = -1;
-
-pointer
-stalloc(int nbytes)
-{
-	char *p;
-
-	nbytes = SHELL_ALIGN(nbytes);
-	if (nbytes > stacknleft) {
-		int blocksize;
-		struct stack_block *sp;
-
-		blocksize = nbytes;
-		if (blocksize < MINSIZE)
-			blocksize = MINSIZE;
-		INTOFF;
-		sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
-		sp->prev = stackp;
-		stacknxt = sp->space;
-		stacknleft = blocksize;
-		stackp = sp;
-		INTON;
-	}
-	p = stacknxt;
-	stacknxt += nbytes;
-	stacknleft -= nbytes;
-	return p;
-}
-
-
-void
-stunalloc(pointer p)
-{
-	if (p == NULL) {		/*DEBUG */
-		write(2, "stunalloc\n", 10);
-		abort();
-	}
-	stacknleft += stacknxt - (char *)p;
-	stacknxt = p;
-}
-
-
-
-void
-setstackmark(struct stackmark *mark)
-{
-	mark->stackp = stackp;
-	mark->stacknxt = stacknxt;
-	mark->stacknleft = stacknleft;
-	mark->marknext = markp;
-	markp = mark;
-}
-
-
-void
-popstackmark(struct stackmark *mark)
-{
-	struct stack_block *sp;
-
-	INTOFF;
-	markp = mark->marknext;
-	while (stackp != mark->stackp) {
-		sp = stackp;
-		stackp = sp->prev;
-		ckfree(sp);
-	}
-	stacknxt = mark->stacknxt;
-	stacknleft = mark->stacknleft;
-	INTON;
-}
-
-
-/*
- * When the parser reads in a string, it wants to stick the string on the
- * stack and only adjust the stack pointer when it knows how big the
- * string is.  Stackblock (defined in stack.h) returns a pointer to a block
- * of space on top of the stack and stackblocklen returns the length of
- * this block.  Growstackblock will grow this space by at least one byte,
- * possibly moving it (like realloc).  Grabstackblock actually allocates the
- * part of the block that has been used.
- */
-
-void
-growstackblock(void)
-{
-	int newlen = SHELL_ALIGN(stacknleft * 2 + 100);
-
-	if (stacknxt == stackp->space && stackp != &stackbase) {
-		struct stack_block *oldstackp;
-		struct stackmark *xmark;
-		struct stack_block *sp;
-
-		INTOFF;
-		oldstackp = stackp;
-		sp = stackp;
-		stackp = sp->prev;
-		sp = ckrealloc((pointer)sp,
-		    sizeof(struct stack_block) - MINSIZE + newlen);
-		sp->prev = stackp;
-		stackp = sp;
-		stacknxt = sp->space;
-		stacknleft = newlen;
-
-		/*
-		 * Stack marks pointing to the start of the old block
-		 * must be relocated to point to the new block 
-		 */
-		xmark = markp;
-		while (xmark != NULL && xmark->stackp == oldstackp) {
-			xmark->stackp = stackp;
-			xmark->stacknxt = stacknxt;
-			xmark->stacknleft = stacknleft;
-			xmark = xmark->marknext;
-		}
-		INTON;
-	} else {
-		char *oldspace = stacknxt;
-		int oldlen = stacknleft;
-		char *p = stalloc(newlen);
-
-		(void)memcpy(p, oldspace, oldlen);
-		stacknxt = p;			/* free the space */
-		stacknleft += newlen;		/* we just allocated */
-	}
-}
-
-void
-grabstackblock(int len)
-{
-	len = SHELL_ALIGN(len);
-	stacknxt += len;
-	stacknleft -= len;
-}
-
-/*
- * The following routines are somewhat easier to use than the above.
- * The user declares a variable of type STACKSTR, which may be declared
- * to be a register.  The macro STARTSTACKSTR initializes things.  Then
- * the user uses the macro STPUTC to add characters to the string.  In
- * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
- * grown as necessary.  When the user is done, she can just leave the
- * string there and refer to it using stackblock().  Or she can allocate
- * the space for it using grabstackstr().  If it is necessary to allow
- * someone else to use the stack temporarily and then continue to grow
- * the string, the user should use grabstack to allocate the space, and
- * then call ungrabstr(p) to return to the previous mode of operation.
- *
- * USTPUTC is like STPUTC except that it doesn't check for overflow.
- * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
- * is space for at least one character.
- */
-
-char *
-growstackstr(void)
-{
-	int len = stackblocksize();
-	if (herefd >= 0 && len >= 1024) {
-		xwrite(herefd, stackblock(), len);
-		sstrnleft = len - 1;
-		return stackblock();
-	}
-	growstackblock();
-	sstrnleft = stackblocksize() - len - 1;
-	return stackblock() + len;
-}
-
-/*
- * Called from CHECKSTRSPACE.
- */
-
-char *
-makestrspace(void)
-{
-	int len = stackblocksize() - sstrnleft;
-	growstackblock();
-	sstrnleft = stackblocksize() - len;
-	return stackblock() + len;
-}
-
-void
-ungrabstackstr(char *s, char *p)
-{
-	stacknleft += stacknxt - s;
-	stacknxt = s;
-	sstrnleft = stacknleft - (p - s);
-
-}
diff --git a/sh/memalloc.h b/sh/memalloc.h
deleted file mode 100644
index e793880..0000000
--- a/sh/memalloc.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*	$NetBSD: memalloc.h,v 1.14 2003/08/07 09:05:34 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)memalloc.h	8.2 (Berkeley) 5/4/95
- */
-
-struct stackmark {
-	struct stack_block *stackp;
-	char *stacknxt;
-	int stacknleft;
-	struct stackmark *marknext;
-};
-
-
-extern char *stacknxt;
-extern int stacknleft;
-extern int sstrnleft;
-extern int herefd;
-
-pointer ckmalloc(int);
-pointer ckrealloc(pointer, int);
-char *savestr(const char *);
-pointer stalloc(int);
-void stunalloc(pointer);
-void setstackmark(struct stackmark *);
-void popstackmark(struct stackmark *);
-void growstackblock(void);
-void grabstackblock(int);
-char *growstackstr(void);
-char *makestrspace(void);
-void ungrabstackstr(char *, char *);
-
-
-
-#define stackblock() stacknxt
-#define stackblocksize() stacknleft
-#define STARTSTACKSTR(p)	p = stackblock(), sstrnleft = stackblocksize()
-#define STPUTC(c, p)	(--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
-#define CHECKSTRSPACE(n, p)	{ if (sstrnleft < n) p = makestrspace(); }
-#define USTPUTC(c, p)	(--sstrnleft, *p++ = (c))
-#define STACKSTRNUL(p)	(sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
-#define STUNPUTC(p)	(++sstrnleft, --p)
-#define STTOPC(p)	p[-1]
-#define STADJUST(amount, p)	(p += (amount), sstrnleft -= (amount))
-#define grabstackstr(p)	stalloc(stackblocksize() - sstrnleft)
-
-#define ckfree(p)	free((pointer)(p))
diff --git a/sh/miscbltin.c b/sh/miscbltin.c
deleted file mode 100644
index d89029a..0000000
--- a/sh/miscbltin.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*	$NetBSD: miscbltin.c,v 1.34.2.1 2005/04/07 11:34:20 tron Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)miscbltin.c	8.4 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: miscbltin.c,v 1.34.2.1 2005/04/07 11:34:20 tron Exp $");
-#endif
-#endif /* not lint */
-
-/*
- * Miscelaneous builtins.
- */
-
-#include <sys/types.h>		/* quad_t */
-#include <sys/param.h>		/* BSD4_4 */
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include "shell.h"
-#include "options.h"
-#include "var.h"
-#include "output.h"
-#include "memalloc.h"
-#include "error.h"
-#include "miscbltin.h"
-#include "mystring.h"
-
-#undef rflag
-
-
-
-/*
- * The read builtin.
- * Backslahes escape the next char unless -r is specified.
- *
- * This uses unbuffered input, which may be avoidable in some cases.
- *
- * Note that if IFS=' :' then read x y should work so that:
- * 'a b'	x='a', y='b'
- * ' a b '	x='a', y='b'
- * ':b'		x='',  y='b'
- * ':'		x='',  y=''
- * '::'		x='',  y=''
- * ': :'	x='',  y=''
- * ':::'	x='',  y='::'
- * ':b c:'	x='',  y='b c:'
- */
-
-int
-readcmd(int argc, char **argv)
-{
-	char **ap;
-	char c;
-	int rflag;
-	char *prompt;
-	const char *ifs;
-	char *p;
-	int startword;
-	int status;
-	int i;
-	int is_ifs;
-	int saveall = 0;
-
-	rflag = 0;
-	prompt = NULL;
-	while ((i = nextopt("p:r")) != '\0') {
-		if (i == 'p')
-			prompt = optionarg;
-		else
-			rflag = 1;
-	}
-
-	if (prompt && isatty(0)) {
-		out2str(prompt);
-		flushall();
-	}
-
-	if (*(ap = argptr) == NULL)
-		error("arg count");
-
-	if ((ifs = bltinlookup("IFS", 1)) == NULL)
-		ifs = " \t\n";
-
-	status = 0;
-	startword = 2;
-	STARTSTACKSTR(p);
-	for (;;) {
-		if (read(0, &c, 1) != 1) {
-			status = 1;
-			break;
-		}
-		if (c == '\0')
-			continue;
-		if (c == '\\' && !rflag) {
-			if (read(0, &c, 1) != 1) {
-				status = 1;
-				break;
-			}
-			if (c != '\n')
-				STPUTC(c, p);
-			continue;
-		}
-		if (c == '\n')
-			break;
-		if (strchr(ifs, c))
-			is_ifs = strchr(" \t\n", c) ? 1 : 2;
-		else
-			is_ifs = 0;
-
-		if (startword != 0) {
-			if (is_ifs == 1) {
-				/* Ignore leading IFS whitespace */
-				if (saveall)
-					STPUTC(c, p);
-				continue;
-			}
-			if (is_ifs == 2 && startword == 1) {
-				/* Only one non-whitespace IFS per word */
-				startword = 2;
-				if (saveall)
-					STPUTC(c, p);
-				continue;
-			}
-		}
-
-		if (is_ifs == 0) {
-			/* append this character to the current variable */
-			startword = 0;
-			if (saveall)
-				/* Not just a spare terminator */
-				saveall++;
-			STPUTC(c, p);
-			continue;
-		}
-
-		/* end of variable... */
-		startword = is_ifs;
-
-		if (ap[1] == NULL) {
-			/* Last variable needs all IFS chars */
-			saveall++;
-			STPUTC(c, p);
-			continue;
-		}
-
-		STACKSTRNUL(p);
-		setvar(*ap, stackblock(), 0);
-		ap++;
-		STARTSTACKSTR(p);
-	}
-	STACKSTRNUL(p);
-
-	/* Remove trailing IFS chars */
-	for (; stackblock() <= --p; *p = 0) {
-		if (!strchr(ifs, *p))
-			break;
-		if (strchr(" \t\n", *p))
-			/* Always remove whitespace */
-			continue;
-		if (saveall > 1)
-			/* Don't remove non-whitespace unless it was naked */
-			break;
-	}
-	setvar(*ap, stackblock(), 0);
-
-	/* Set any remaining args to "" */
-	while (*++ap != NULL)
-		setvar(*ap, nullstr, 0);
-	return status;
-}
-
-
-
-int
-umaskcmd(int argc, char **argv)
-{
-	char *ap;
-	int mask;
-	int i;
-	int symbolic_mode = 0;
-
-	while ((i = nextopt("S")) != '\0') {
-		symbolic_mode = 1;
-	}
-
-	INTOFF;
-	mask = umask(0);
-	umask(mask);
-	INTON;
-
-	if ((ap = *argptr) == NULL) {
-		if (symbolic_mode) {
-			char u[4], g[4], o[4];
-
-			i = 0;
-			if ((mask & S_IRUSR) == 0)
-				u[i++] = 'r';
-			if ((mask & S_IWUSR) == 0)
-				u[i++] = 'w';
-			if ((mask & S_IXUSR) == 0)
-				u[i++] = 'x';
-			u[i] = '\0';
-
-			i = 0;
-			if ((mask & S_IRGRP) == 0)
-				g[i++] = 'r';
-			if ((mask & S_IWGRP) == 0)
-				g[i++] = 'w';
-			if ((mask & S_IXGRP) == 0)
-				g[i++] = 'x';
-			g[i] = '\0';
-
-			i = 0;
-			if ((mask & S_IROTH) == 0)
-				o[i++] = 'r';
-			if ((mask & S_IWOTH) == 0)
-				o[i++] = 'w';
-			if ((mask & S_IXOTH) == 0)
-				o[i++] = 'x';
-			o[i] = '\0';
-
-			out1fmt("u=%s,g=%s,o=%s\n", u, g, o);
-		} else {
-			out1fmt("%.4o\n", mask);
-		}
-	} else {
-		if (isdigit((unsigned char)*ap)) {
-			mask = 0;
-			do {
-				if (*ap >= '8' || *ap < '0')
-					error("Illegal number: %s", argv[1]);
-				mask = (mask << 3) + (*ap - '0');
-			} while (*++ap != '\0');
-			umask(mask);
-		} else
-			error("Illegal mode: %s", ap);
-	}
-	return 0;
-}
-
-#if 1
-/*
- * ulimit builtin
- *
- * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
- * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
- * ash by J.T. Conklin.
- *
- * Public domain.
- */
-
-struct limits {
-	const char *name;
-	int	cmd;
-	int	factor;	/* multiply by to get rlim_{cur,max} values */
-	char	option;
-};
-
-static const struct limits limits[] = {
-#ifdef RLIMIT_CPU
-	{ "time(seconds)",		RLIMIT_CPU,	   1, 't' },
-#endif
-#ifdef RLIMIT_FSIZE
-	{ "file(blocks)",		RLIMIT_FSIZE,	 512, 'f' },
-#endif
-#ifdef RLIMIT_DATA
-	{ "data(kbytes)",		RLIMIT_DATA,	1024, 'd' },
-#endif
-#ifdef RLIMIT_STACK
-	{ "stack(kbytes)",		RLIMIT_STACK,	1024, 's' },
-#endif
-#ifdef  RLIMIT_CORE
-	{ "coredump(blocks)",		RLIMIT_CORE,	 512, 'c' },
-#endif
-#ifdef RLIMIT_RSS
-	{ "memory(kbytes)",		RLIMIT_RSS,	1024, 'm' },
-#endif
-#ifdef RLIMIT_MEMLOCK
-	{ "locked memory(kbytes)",	RLIMIT_MEMLOCK, 1024, 'l' },
-#endif
-#ifdef RLIMIT_NPROC
-	{ "process(processes)",		RLIMIT_NPROC,      1, 'p' },
-#endif
-#ifdef RLIMIT_NOFILE
-	{ "nofiles(descriptors)",	RLIMIT_NOFILE,     1, 'n' },
-#endif
-#ifdef RLIMIT_VMEM
-	{ "vmemory(kbytes)",		RLIMIT_VMEM,	1024, 'v' },
-#endif
-#ifdef RLIMIT_SWAP
-	{ "swap(kbytes)",		RLIMIT_SWAP,	1024, 'w' },
-#endif
-#ifdef RLIMIT_SBSIZE
-	{ "sbsize(bytes)",		RLIMIT_SBSIZE,	   1, 'b' },
-#endif
-	{ (char *) 0,			0,		   0,  '\0' }
-};
-
-int
-ulimitcmd(int argc, char **argv)
-{
-	int	c;
-	rlim_t val = 0;
-	enum { SOFT = 0x1, HARD = 0x2 }
-			how = SOFT | HARD;
-	const struct limits	*l;
-	int		set, all = 0;
-	int		optc, what;
-	struct rlimit	limit;
-
-	what = 'f';
-	while ((optc = nextopt("HSabtfdsmcnpl")) != '\0')
-		switch (optc) {
-		case 'H':
-			how = HARD;
-			break;
-		case 'S':
-			how = SOFT;
-			break;
-		case 'a':
-			all = 1;
-			break;
-		default:
-			what = optc;
-		}
-
-	for (l = limits; l->name && l->option != what; l++)
-		;
-	if (!l->name)
-		error("internal error (%c)", what);
-
-	set = *argptr ? 1 : 0;
-	if (set) {
-		char *p = *argptr;
-
-		if (all || argptr[1])
-			error("too many arguments");
-		if (strcmp(p, "unlimited") == 0)
-			val = RLIM_INFINITY;
-		else {
-			val = (rlim_t) 0;
-
-			while ((c = *p++) >= '0' && c <= '9')
-			{
-				val = (val * 10) + (long)(c - '0');
-				if ((long)val < 0)
-					break;
-			}
-			if (c)
-				error("bad number");
-			val *= l->factor;
-		}
-	}
-	if (all) {
-		for (l = limits; l->name; l++) {
-			getrlimit(l->cmd, &limit);
-			if (how & SOFT)
-				val = limit.rlim_cur;
-			else if (how & HARD)
-				val = limit.rlim_max;
-
-			out1fmt("%-20s ", l->name);
-			if (val == RLIM_INFINITY)
-				out1fmt("unlimited\n");
-			else
-			{
-				val /= l->factor;
-#ifdef BSD4_4
-				out1fmt("%lld\n", (long long) val);
-#else
-				out1fmt("%ld\n", (long) val);
-#endif
-			}
-		}
-		return 0;
-	}
-
-	getrlimit(l->cmd, &limit);
-	if (set) {
-		if (how & HARD)
-			limit.rlim_max = val;
-		if (how & SOFT)
-			limit.rlim_cur = val;
-		if (setrlimit(l->cmd, &limit) < 0)
-			error("error setting limit (%s)", strerror(errno));
-	} else {
-		if (how & SOFT)
-			val = limit.rlim_cur;
-		else if (how & HARD)
-			val = limit.rlim_max;
-
-		if (val == RLIM_INFINITY)
-			out1fmt("unlimited\n");
-		else
-		{
-			val /= l->factor;
-#ifdef BSD4_4
-			out1fmt("%lld\n", (long long) val);
-#else
-			out1fmt("%ld\n", (long) val);
-#endif
-		}
-	}
-	return 0;
-}
-#endif
diff --git a/sh/miscbltin.h b/sh/miscbltin.h
deleted file mode 100644
index 4c12c82..0000000
--- a/sh/miscbltin.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*	$NetBSD: miscbltin.h,v 1.3 2003/08/21 17:57:53 christos Exp $	*/
-
-/*
- * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-int readcmd(int, char **);
-int umaskcmd(int, char **);
-int ulimitcmd(int, char **);
diff --git a/sh/mkbuiltins b/sh/mkbuiltins
deleted file mode 100644
index 5b19269..0000000
--- a/sh/mkbuiltins
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/bin/sh -
-#	$NetBSD: mkbuiltins,v 1.21 2004/06/06 07:03:11 christos Exp $
-#
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. 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.
-#
-#	@(#)mkbuiltins	8.2 (Berkeley) 5/4/95
-
-havehist=1
-if [ "X$1" = "X-h" ]; then
-	havehist=0
-	shift
-fi
-
-shell=$1
-builtins=$2
-objdir=$3
-
-havejobs=0
-if grep '^#define JOBS[	 ]*1' ${shell} > /dev/null
-then
-	havejobs=1
-fi
-
-exec <$builtins 3> ${objdir}/builtins.c 4> ${objdir}/builtins.h
-
-echo '/*
- * This file was generated by the mkbuiltins program.
- */
-
-#include "shell.h"
-#include "builtins.h"
-
-const struct builtincmd builtincmd[] = {
-' >&3
-
-echo '/*
- * This file was generated by the mkbuiltins program.
- */
-
-#include <sys/cdefs.h>
-
-struct builtincmd {
-      const char *name;
-      int (*builtin)(int, char **);
-};
-
-extern const struct builtincmd builtincmd[];
-extern const struct builtincmd splbltincmd[];
-
-' >&4
-
-specials=
-
-while read line
-do
-	set -- $line
-	[ -z "$1" ] && continue
-	case "$1" in
-	\#if*|\#def*|\#end*)
-		echo $line >&3
-		echo $line >&4
-		continue
-		;;
-	esac
-	l1="${line###}"
-	[ "$l1" != "$line" ] && continue
-
-
-	func=$1
-	shift
-	[ x"$1" = x'-j' ] && {
-		[ $havejobs = 0 ] && continue
-		shift
-	}
-	[ x"$1" = x'-h' ] && {
-		[ $havehist = 0 ] && continue
-		shift
-	}
-	echo 'int '"$func"'(int, char **);' >&4
-	while
-		[ $# != 0 -a "$1" != '#' ]
-	do
-		[ "$1" = '-s' ] && {
-			specials="$specials $2 $func"
-			shift 2
-			continue;
-		}
-		[ "$1" = '-u' ] && shift
-		echo '	{ "'$1'",	'"$func"' },' >&3
-		shift
-	done
-done
-
-echo '	{ 0, 0 },' >&3
-echo '};' >&3
-echo >&3
-echo 'const struct builtincmd splbltincmd[] = {' >&3
-
-set -- $specials
-while
-	[ $# != 0 ]
-do
-	echo '	{ "'$1'",	'"$2"' },' >&3
-	shift 2
-done
-
-echo '	{ 0, 0 },' >&3
-echo "};" >&3
diff --git a/sh/mkinit.sh b/sh/mkinit.sh
deleted file mode 100644
index cae27dd..0000000
--- a/sh/mkinit.sh
+++ /dev/null
@@ -1,197 +0,0 @@
-#! /bin/sh
-#	$NetBSD: mkinit.sh,v 1.2 2004/06/15 23:09:54 dsl Exp $
-
-# Copyright (c) 2003 The NetBSD Foundation, Inc.
-# All rights reserved.
-#
-# This code is derived from software contributed to The NetBSD Foundation
-# by David Laight.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
-srcs="$*"
-
-nl='
-'
-openparen='('
-backslash='\'
-
-includes=' "shell.h" "mystring.h" "init.h" '
-defines=
-decles=
-event_init=
-event_reset=
-event_shellproc=
-
-for src in $srcs; do
-	exec <$src
-	decnl="$nl"
-	while IFS=; read -r line; do
-		[ "$line" = x ]
-		case "$line " in
-		INIT["{ 	"]* ) event=init;;
-		RESET["{ 	"]* ) event=reset;;
-		SHELLPROC["{ 	"]* ) event=shellproc;;
-		INCLUDE[\ \	]* )
-			IFS=' 	'
-			set -- $line
-			# ignore duplicates
-			[ "${includes}" != "${includes%* $2 }" ] && continue
-			includes="$includes$2 "
-			continue
-			;;
-		MKINIT\  )
-			# struct declaration
-			decles="$decles$nl"
-			while
-				read -r line
-				decles="${decles}${line}${nl}"
-				[ "$line" != "};" ]
-			do
-				:
-			done
-			decnl="$nl"
-			continue
-			;;
-		MKINIT["{ 	"]* )
-			# strip initialiser
-			def=${line#MKINIT}
-			comment="${def#*;}"
-			def="${def%;$comment}"
-			def="${def%%=*}"
-			def="${def% }"
-			decles="${decles}${decnl}extern${def};${comment}${nl}"
-			decnl=
-			continue
-			;;
-		\#define[\ \	]* )
-			IFS=' 	'
-			set -- $line
-			# Ignore those with arguments
-			[ "$2" = "${2##*$openparen}" ] || continue
-			# and multiline definitions
-			[ "$line" = "${line%$backslash}" ] || continue
-			defines="${defines}#undef  $2${nl}${line}${nl}"
-			continue
-			;;
-		* ) continue;;
-		esac
-		# code for events
-		ev="${nl}      /* from $src: */${nl}      {${nl}"
-		while
-			read -r line
-			[ "$line" != "}" ]
-		do
-			# The C program indented by an extra 6 chars using
-			# tabs then spaces. I need to compare the output :-(
-			indent=6
-			while
-				l=${line#	}
-				[ "$l" != "$line" ]
-			do
-				indent=$(($indent + 8))
-				line="$l"
-			done
-			while
-				l=${line# }
-				[ "$l" != "$line" ]
-			do
-				indent=$(($indent + 1))
-				line="$l"
-			done
-			[ -z "$line" -o "$line" != "${line###}" ] && indent=0
-			while
-				[ $indent -ge 8 ]
-			do
-				ev="$ev	"
-				indent="$(($indent - 8))"
-			done
-			while
-				[ $indent -gt 0 ]
-			do
-				ev="$ev "
-				indent="$(($indent - 1))"
-			done
-			ev="${ev}${line}${nl}"
-		done
-		ev="${ev}      }${nl}"
-		eval event_$event=\"\$event_$event\$ev\"
-	done
-done
-
-exec >init.c.tmp
-
-echo "/*"
-echo " * This file was generated by the mkinit program."
-echo " */"
-echo
-
-IFS=' '
-for f in $includes; do
-	echo "#include $f"
-done
-
-echo
-echo
-echo
-echo "$defines"
-echo
-echo "$decles"
-echo
-echo
-echo "/*"
-echo " * Initialization code."
-echo " */"
-echo
-echo "void"
-echo "init() {"
-echo "${event_init%$nl}"
-echo "}"
-echo
-echo
-echo
-echo "/*"
-echo " * This routine is called when an error or an interrupt occurs in an"
-echo " * interactive shell and control is returned to the main command loop."
-echo " */"
-echo
-echo "void"
-echo "reset() {"
-echo "${event_reset%$nl}"
-echo "}"
-echo
-echo
-echo
-echo "/*"
-echo " * This routine is called to initialize the shell to run a shell procedure."
-echo " */"
-echo
-echo "void"
-echo "initshellproc() {"
-echo "${event_shellproc%$nl}"
-echo "}"
-
-exec >&-
-mv init.c.tmp init.c
diff --git a/sh/mknodes.sh b/sh/mknodes.sh
deleted file mode 100644
index 54d2e3d..0000000
--- a/sh/mknodes.sh
+++ /dev/null
@@ -1,217 +0,0 @@
-#! /bin/sh
-#	$NetBSD: mknodes.sh,v 1.1 2004/01/16 23:24:38 dsl Exp $
-
-# Copyright (c) 2003 The NetBSD Foundation, Inc.
-# All rights reserved.
-#
-# This code is derived from software contributed to The NetBSD Foundation
-# by David Laight.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
-nodetypes=$1
-nodes_pat=$2
-objdir="$3"
-
-exec <$nodetypes
-exec >$objdir/nodes.h.tmp
-
-echo "/*"
-echo " * This file was generated by mknodes.sh"
-echo " */"
-echo
-
-tagno=0
-while IFS=; read -r line; do
-	line="${line%%#*}"
-	IFS=' 	'
-	set -- $line
-	IFS=
-	[ -z "$2" ] && continue
-	case "$line" in
-	[" 	"]* )
-		IFS=' '
-		[ $field = 0 ] && struct_list="$struct_list $struct"
-		eval field_${struct}_$field=\"\$*\"
-		eval numfld_$struct=\$field
-		field=$(($field + 1))
-		;;
-	* )
-		define=$1
-		struct=$2
-		echo "#define $define $tagno"
-		tagno=$(($tagno + 1))
-		eval define_$struct=\"\$define_$struct \$define\"
-		struct_define="$struct_define $struct"
-		field=0
-		;;
-	esac
-done
-
-echo
-
-IFS=' '
-for struct in $struct_list; do
-	echo
-	echo
-	echo "struct $struct {"
-	field=0
-	while
-		eval line=\"\$field_${struct}_$field\"
-		field=$(($field + 1))
-		[ -n "$line" ]
-	do
-		IFS=' '
-		set -- $line
-		name=$1
-		case $2 in
-		nodeptr ) type="union node *";;
-		nodelist ) type="struct nodelist *";;
-		string ) type="char *";;
-		int ) type="int ";;
-		* ) name=; shift 2; type="$*";;
-		esac
-		echo "      $type$name;"
-	done
-	echo "};"
-done
-
-echo
-echo
-echo "union node {"
-echo "      int type;"
-for struct in $struct_list; do
-	echo "      struct $struct $struct;"
-done
-echo "};"
-echo
-echo
-echo "struct nodelist {"
-echo "	struct nodelist *next;"
-echo "	union node *n;"
-echo "};"
-echo
-echo
-echo "union node *copyfunc(union node *);"
-echo "void freefunc(union node *);"
-
-mv $objdir/nodes.h.tmp $objdir/nodes.h || exit 1
-
-exec <$nodes_pat
-exec >$objdir/nodes.c.tmp
-
-echo "/*"
-echo " * This file was generated by mknodes.sh"
-echo " */"
-echo
-
-while IFS=; read -r line; do
-	IFS=' 	'
-	set -- $line
-	IFS=
-	case "$1" in
-	'%SIZES' )
-		echo "static const short nodesize[$tagno] = {"
-		IFS=' '
-		for struct in $struct_define; do
-			echo "      SHELL_ALIGN(sizeof (struct $struct)),"
-		done
-		echo "};"
-		;;
-	'%CALCSIZE' )
-		echo "      if (n == NULL)"
-		echo "	    return;"
-		echo "      funcblocksize += nodesize[n->type];"
-		echo "      switch (n->type) {"
-		IFS=' '
-		for struct in $struct_list; do
-			eval defines=\"\$define_$struct\"
-			for define in $defines; do
-				echo "      case $define:"
-			done
-			eval field=\$numfld_$struct
-			while
-				[ $field != 0 ]
-			do
-				eval line=\"\$field_${struct}_$field\"
-				field=$(($field - 1))
-				IFS=' '
-				set -- $line
-				name=$1
-				cl=")"
-				case $2 in
-				nodeptr ) fn=calcsize;;
-				nodelist ) fn=sizenodelist;;
-				string ) fn="funcstringsize += strlen"
-					cl=") + 1";;
-				* ) continue;;
-				esac
-				echo "	    ${fn}(n->$struct.$name${cl};"
-			done
-			echo "	    break;"
-		done
-		echo "      };"
-		;;
-	'%COPY' )
-		echo "      if (n == NULL)"
-		echo "	    return NULL;"
-		echo "      new = funcblock;"
-		echo "      funcblock = (char *) funcblock + nodesize[n->type];"
-		echo "      switch (n->type) {"
-		IFS=' '
-		for struct in $struct_list; do
-			eval defines=\"\$define_$struct\"
-			for define in $defines; do
-				echo "      case $define:"
-			done
-			eval field=\$numfld_$struct
-			while
-				[ $field != 0 ]
-			do
-				eval line=\"\$field_${struct}_$field\"
-				field=$(($field - 1))
-				IFS=' '
-				set -- $line
-				name=$1
-				case $2 in
-				nodeptr ) fn="copynode(";;
-				nodelist ) fn="copynodelist(";;
-				string ) fn="nodesavestr(";;
-				int ) fn=;;
-				* ) continue;;
-				esac
-				f="$struct.$name"
-				echo "	    new->$f = ${fn}n->$f${fn:+)};"
-			done
-			echo "	    break;"
-		done
-		echo "      };"
-		echo "      new->type = n->type;"
-		;;
-	* ) echo "$line";;
-	esac
-done
-
-mv $objdir/nodes.c.tmp $objdir/nodes.c || exit 1
diff --git a/sh/mktokens b/sh/mktokens
deleted file mode 100644
index 25f2e6e..0000000
--- a/sh/mktokens
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/bin/sh -
-#	$NetBSD: mktokens,v 1.10 2003/08/22 11:22:23 agc Exp $
-#
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. 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.
-#
-#	@(#)mktokens	8.1 (Berkeley) 5/31/93
-
-# The following is a list of tokens.  The second column is nonzero if the
-# token marks the end of a list.  The third column is the name to print in
-# error messages.
-
-cat > /tmp/ka$$ <<\!
-TEOF	1	end of file
-TNL	0	newline
-TSEMI	0	";"
-TBACKGND 0	"&"
-TAND	0	"&&"
-TOR	0	"||"
-TPIPE	0	"|"
-TLP	0	"("
-TRP	1	")"
-TENDCASE 1	";;"
-TENDBQUOTE 1	"`"
-TREDIR	0	redirection
-TWORD	0	word
-TIF	0	"if"
-TTHEN	1	"then"
-TELSE	1	"else"
-TELIF	1	"elif"
-TFI	1	"fi"
-TWHILE	0	"while"
-TUNTIL	0	"until"
-TFOR	0	"for"
-TDO	1	"do"
-TDONE	1	"done"
-TBEGIN	0	"{"
-TEND	1	"}"
-TCASE	0	"case"
-TESAC	1	"esac"
-TNOT	0	"!"
-!
-nl=`wc -l /tmp/ka$$`
-exec > token.h
-awk '{print "#define " $1 " " NR-1}' /tmp/ka$$
-echo '
-/* Array indicating which tokens mark the end of a list */
-const char tokendlist[] = {'
-awk '{print "\t" $2 ","}' /tmp/ka$$
-echo '};
-
-const char *const tokname[] = {'
-sed -e 's/"/\\"/g' \
-    -e 's/[^	 ]*[	 ][	 ]*[^	 ]*[	 ][	 ]*\(.*\)/	"\1",/' \
-    /tmp/ka$$
-echo '};
-'
-sed 's/"//g' /tmp/ka$$ | awk '
-/TIF/{print "#define KWDOFFSET " NR-1; print ""; 
-      print "const char *const parsekwd[] = {"}
-/TIF/,/neverfound/{print "	\"" $3 "\","}'
-echo '	0
-};'
-
-rm /tmp/ka$$
diff --git a/sh/myhistedit.h b/sh/myhistedit.h
deleted file mode 100644
index 603a27b..0000000
--- a/sh/myhistedit.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*	$NetBSD: myhistedit.h,v 1.10 2003/08/07 09:05:35 agc Exp $	*/
-
-/*-
- * Copyright (c) 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.
- * 3. 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.
- *
- *	@(#)myhistedit.h	8.2 (Berkeley) 5/4/95
- */
-
-#ifdef WITH_HISTORY
-#include <histedit.h>
-
-extern History *hist;
-extern EditLine *el;
-extern int displayhist;
-
-void histedit(void);
-void sethistsize(const char *);
-void setterm(const char *);
-int histcmd(int, char **);
-int inputrc(int, char **);
-int not_fcnumber(char *);
-int str_to_event(const char *, int);
-#endif
-
diff --git a/sh/mystring.c b/sh/mystring.c
deleted file mode 100644
index aecf83e..0000000
--- a/sh/mystring.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*	$NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)mystring.c	8.2 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: mystring.c,v 1.16 2003/08/07 09:05:35 agc Exp $");
-#endif
-#endif /* not lint */
-
-/*
- * String functions.
- *
- *	equal(s1, s2)		Return true if strings are equal.
- *	scopy(from, to)		Copy a string.
- *	scopyn(from, to, n)	Like scopy, but checks for overflow.
- *	number(s)		Convert a string of digits to an integer.
- *	is_number(s)		Return true if s is a string of digits.
- */
-
-#include <stdlib.h>
-#include "shell.h"
-#include "syntax.h"
-#include "error.h"
-#include "mystring.h"
-
-
-char nullstr[1];		/* zero length string */
-
-/*
- * equal - #defined in mystring.h
- */
-
-/*
- * scopy - #defined in mystring.h
- */
-
-
-/*
- * scopyn - copy a string from "from" to "to", truncating the string
- *		if necessary.  "To" is always nul terminated, even if
- *		truncation is performed.  "Size" is the size of "to".
- */
-
-void
-scopyn(const char *from, char *to, int size)
-{
-
-	while (--size > 0) {
-		if ((*to++ = *from++) == '\0')
-			return;
-	}
-	*to = '\0';
-}
-
-
-/*
- * prefix -- see if pfx is a prefix of string.
- */
-
-int
-prefix(const char *pfx, const char *string)
-{
-	while (*pfx) {
-		if (*pfx++ != *string++)
-			return 0;
-	}
-	return 1;
-}
-
-
-/*
- * Convert a string of digits to an integer, printing an error message on
- * failure.
- */
-
-int
-number(const char *s)
-{
-
-	if (! is_number(s))
-		error("Illegal number: %s", s);
-	return atoi(s);
-}
-
-
-
-/*
- * Check for a valid number.  This should be elsewhere.
- */
-
-int
-is_number(const char *p)
-{
-	do {
-		if (! is_digit(*p))
-			return 0;
-	} while (*++p != '\0');
-	return 1;
-}
diff --git a/sh/mystring.h b/sh/mystring.h
deleted file mode 100644
index 08a73e9..0000000
--- a/sh/mystring.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*	$NetBSD: mystring.h,v 1.11 2003/08/07 09:05:35 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)mystring.h	8.2 (Berkeley) 5/4/95
- */
-
-#include <string.h>
-
-void scopyn(const char *, char *, int);
-int prefix(const char *, const char *);
-int number(const char *);
-int is_number(const char *);
-
-#define equal(s1, s2)	(strcmp(s1, s2) == 0)
-#define scopy(s1, s2)	((void)strcpy(s2, s1))
diff --git a/sh/nodes.c b/sh/nodes.c
deleted file mode 100644
index 8a2c718..0000000
--- a/sh/nodes.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * This file was generated by mknodes.sh
- */
-
-/*	$NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
- */
-
-#include <stdlib.h>
-/*
- * Routine for dealing with parsed shell commands.
- */
-
-#include "shell.h"
-#include "nodes.h"
-#include "memalloc.h"
-#include "machdep.h"
-#include "mystring.h"
-
-
-int     funcblocksize;		/* size of structures in function */
-int     funcstringsize;		/* size of strings in node */
-pointer funcblock;		/* block to allocate function from */
-char   *funcstring;		/* block to allocate strings from */
-
-static const short nodesize[26] = {
-      SHELL_ALIGN(sizeof (struct nbinary)),
-      SHELL_ALIGN(sizeof (struct ncmd)),
-      SHELL_ALIGN(sizeof (struct npipe)),
-      SHELL_ALIGN(sizeof (struct nredir)),
-      SHELL_ALIGN(sizeof (struct nredir)),
-      SHELL_ALIGN(sizeof (struct nredir)),
-      SHELL_ALIGN(sizeof (struct nbinary)),
-      SHELL_ALIGN(sizeof (struct nbinary)),
-      SHELL_ALIGN(sizeof (struct nif)),
-      SHELL_ALIGN(sizeof (struct nbinary)),
-      SHELL_ALIGN(sizeof (struct nbinary)),
-      SHELL_ALIGN(sizeof (struct nfor)),
-      SHELL_ALIGN(sizeof (struct ncase)),
-      SHELL_ALIGN(sizeof (struct nclist)),
-      SHELL_ALIGN(sizeof (struct narg)),
-      SHELL_ALIGN(sizeof (struct narg)),
-      SHELL_ALIGN(sizeof (struct nfile)),
-      SHELL_ALIGN(sizeof (struct nfile)),
-      SHELL_ALIGN(sizeof (struct nfile)),
-      SHELL_ALIGN(sizeof (struct nfile)),
-      SHELL_ALIGN(sizeof (struct nfile)),
-      SHELL_ALIGN(sizeof (struct ndup)),
-      SHELL_ALIGN(sizeof (struct ndup)),
-      SHELL_ALIGN(sizeof (struct nhere)),
-      SHELL_ALIGN(sizeof (struct nhere)),
-      SHELL_ALIGN(sizeof (struct nnot)),
-};
-
-
-STATIC void calcsize(union node *);
-STATIC void sizenodelist(struct nodelist *);
-STATIC union node *copynode(union node *);
-STATIC struct nodelist *copynodelist(struct nodelist *);
-STATIC char *nodesavestr(char *);
-
-
-
-/*
- * Make a copy of a parse tree.
- */
-
-union node *
-copyfunc(n)
-	union node *n;
-{
-	if (n == NULL)
-		return NULL;
-	funcblocksize = 0;
-	funcstringsize = 0;
-	calcsize(n);
-	funcblock = ckmalloc(funcblocksize + funcstringsize);
-	funcstring = (char *) funcblock + funcblocksize;
-	return copynode(n);
-}
-
-
-
-STATIC void
-calcsize(n)
-	union node *n;
-{
-      if (n == NULL)
-	    return;
-      funcblocksize += nodesize[n->type];
-      switch (n->type) {
-      case NSEMI:
-      case NAND:
-      case NOR:
-      case NWHILE:
-      case NUNTIL:
-	    calcsize(n->nbinary.ch2);
-	    calcsize(n->nbinary.ch1);
-	    break;
-      case NCMD:
-	    calcsize(n->ncmd.redirect);
-	    calcsize(n->ncmd.args);
-	    break;
-      case NPIPE:
-	    sizenodelist(n->npipe.cmdlist);
-	    break;
-      case NREDIR:
-      case NBACKGND:
-      case NSUBSHELL:
-	    calcsize(n->nredir.redirect);
-	    calcsize(n->nredir.n);
-	    break;
-      case NIF:
-	    calcsize(n->nif.elsepart);
-	    calcsize(n->nif.ifpart);
-	    calcsize(n->nif.test);
-	    break;
-      case NFOR:
-	    funcstringsize += strlen(n->nfor.var) + 1;
-	    calcsize(n->nfor.body);
-	    calcsize(n->nfor.args);
-	    break;
-      case NCASE:
-	    calcsize(n->ncase.cases);
-	    calcsize(n->ncase.expr);
-	    break;
-      case NCLIST:
-	    calcsize(n->nclist.body);
-	    calcsize(n->nclist.pattern);
-	    calcsize(n->nclist.next);
-	    break;
-      case NDEFUN:
-      case NARG:
-	    sizenodelist(n->narg.backquote);
-	    funcstringsize += strlen(n->narg.text) + 1;
-	    calcsize(n->narg.next);
-	    break;
-      case NTO:
-      case NCLOBBER:
-      case NFROM:
-      case NFROMTO:
-      case NAPPEND:
-	    calcsize(n->nfile.fname);
-	    calcsize(n->nfile.next);
-	    break;
-      case NTOFD:
-      case NFROMFD:
-	    calcsize(n->ndup.vname);
-	    calcsize(n->ndup.next);
-	    break;
-      case NHERE:
-      case NXHERE:
-	    calcsize(n->nhere.doc);
-	    calcsize(n->nhere.next);
-	    break;
-      case NNOT:
-	    calcsize(n->nnot.com);
-	    break;
-      };
-}
-
-
-
-STATIC void
-sizenodelist(lp)
-	struct nodelist *lp;
-{
-	while (lp) {
-		funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
-		calcsize(lp->n);
-		lp = lp->next;
-	}
-}
-
-
-
-STATIC union node *
-copynode(n)
-	union node *n;
-{
-	union node *new;
-
-      if (n == NULL)
-	    return NULL;
-      new = funcblock;
-      funcblock = (char *) funcblock + nodesize[n->type];
-      switch (n->type) {
-      case NSEMI:
-      case NAND:
-      case NOR:
-      case NWHILE:
-      case NUNTIL:
-	    new->nbinary.ch2 = copynode(n->nbinary.ch2);
-	    new->nbinary.ch1 = copynode(n->nbinary.ch1);
-	    break;
-      case NCMD:
-	    new->ncmd.redirect = copynode(n->ncmd.redirect);
-	    new->ncmd.args = copynode(n->ncmd.args);
-	    new->ncmd.backgnd = n->ncmd.backgnd;
-	    break;
-      case NPIPE:
-	    new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
-	    new->npipe.backgnd = n->npipe.backgnd;
-	    break;
-      case NREDIR:
-      case NBACKGND:
-      case NSUBSHELL:
-	    new->nredir.redirect = copynode(n->nredir.redirect);
-	    new->nredir.n = copynode(n->nredir.n);
-	    break;
-      case NIF:
-	    new->nif.elsepart = copynode(n->nif.elsepart);
-	    new->nif.ifpart = copynode(n->nif.ifpart);
-	    new->nif.test = copynode(n->nif.test);
-	    break;
-      case NFOR:
-	    new->nfor.var = nodesavestr(n->nfor.var);
-	    new->nfor.body = copynode(n->nfor.body);
-	    new->nfor.args = copynode(n->nfor.args);
-	    break;
-      case NCASE:
-	    new->ncase.cases = copynode(n->ncase.cases);
-	    new->ncase.expr = copynode(n->ncase.expr);
-	    break;
-      case NCLIST:
-	    new->nclist.body = copynode(n->nclist.body);
-	    new->nclist.pattern = copynode(n->nclist.pattern);
-	    new->nclist.next = copynode(n->nclist.next);
-	    break;
-      case NDEFUN:
-      case NARG:
-	    new->narg.backquote = copynodelist(n->narg.backquote);
-	    new->narg.text = nodesavestr(n->narg.text);
-	    new->narg.next = copynode(n->narg.next);
-	    break;
-      case NTO:
-      case NCLOBBER:
-      case NFROM:
-      case NFROMTO:
-      case NAPPEND:
-	    new->nfile.fname = copynode(n->nfile.fname);
-	    new->nfile.fd = n->nfile.fd;
-	    new->nfile.next = copynode(n->nfile.next);
-	    break;
-      case NTOFD:
-      case NFROMFD:
-	    new->ndup.vname = copynode(n->ndup.vname);
-	    new->ndup.dupfd = n->ndup.dupfd;
-	    new->ndup.fd = n->ndup.fd;
-	    new->ndup.next = copynode(n->ndup.next);
-	    break;
-      case NHERE:
-      case NXHERE:
-	    new->nhere.doc = copynode(n->nhere.doc);
-	    new->nhere.fd = n->nhere.fd;
-	    new->nhere.next = copynode(n->nhere.next);
-	    break;
-      case NNOT:
-	    new->nnot.com = copynode(n->nnot.com);
-	    break;
-      };
-      new->type = n->type;
-	return new;
-}
-
-
-STATIC struct nodelist *
-copynodelist(lp)
-	struct nodelist *lp;
-{
-	struct nodelist *start;
-	struct nodelist **lpp;
-
-	lpp = &start;
-	while (lp) {
-		*lpp = funcblock;
-		funcblock = (char *) funcblock +
-		    SHELL_ALIGN(sizeof(struct nodelist));
-		(*lpp)->n = copynode(lp->n);
-		lp = lp->next;
-		lpp = &(*lpp)->next;
-	}
-	*lpp = NULL;
-	return start;
-}
-
-
-
-STATIC char *
-nodesavestr(s)
-	char   *s;
-{
-	register char *p = s;
-	register char *q = funcstring;
-	char   *rtn = funcstring;
-
-	while ((*q++ = *p++) != 0)
-		continue;
-	funcstring = q;
-	return rtn;
-}
-
-
-
-/*
- * Free a parse tree.
- */
-
-void
-freefunc(n)
-	union node *n;
-{
-	if (n)
-		ckfree(n);
-}
diff --git a/sh/nodes.c.pat b/sh/nodes.c.pat
deleted file mode 100644
index e619a01..0000000
--- a/sh/nodes.c.pat
+++ /dev/null
@@ -1,166 +0,0 @@
-/*	$NetBSD: nodes.c.pat,v 1.12 2004/06/15 22:57:27 dsl Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
- */
-
-#include <stdlib.h>
-/*
- * Routine for dealing with parsed shell commands.
- */
-
-#include "shell.h"
-#include "nodes.h"
-#include "memalloc.h"
-#include "machdep.h"
-#include "mystring.h"
-
-
-int     funcblocksize;		/* size of structures in function */
-int     funcstringsize;		/* size of strings in node */
-pointer funcblock;		/* block to allocate function from */
-char   *funcstring;		/* block to allocate strings from */
-
-%SIZES
-
-
-STATIC void calcsize(union node *);
-STATIC void sizenodelist(struct nodelist *);
-STATIC union node *copynode(union node *);
-STATIC struct nodelist *copynodelist(struct nodelist *);
-STATIC char *nodesavestr(char *);
-
-
-
-/*
- * Make a copy of a parse tree.
- */
-
-union node *
-copyfunc(n)
-	union node *n;
-{
-	if (n == NULL)
-		return NULL;
-	funcblocksize = 0;
-	funcstringsize = 0;
-	calcsize(n);
-	funcblock = ckmalloc(funcblocksize + funcstringsize);
-	funcstring = (char *) funcblock + funcblocksize;
-	return copynode(n);
-}
-
-
-
-STATIC void
-calcsize(n)
-	union node *n;
-{
-	%CALCSIZE
-}
-
-
-
-STATIC void
-sizenodelist(lp)
-	struct nodelist *lp;
-{
-	while (lp) {
-		funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
-		calcsize(lp->n);
-		lp = lp->next;
-	}
-}
-
-
-
-STATIC union node *
-copynode(n)
-	union node *n;
-{
-	union node *new;
-
-	%COPY
-	return new;
-}
-
-
-STATIC struct nodelist *
-copynodelist(lp)
-	struct nodelist *lp;
-{
-	struct nodelist *start;
-	struct nodelist **lpp;
-
-	lpp = &start;
-	while (lp) {
-		*lpp = funcblock;
-		funcblock = (char *) funcblock +
-		    SHELL_ALIGN(sizeof(struct nodelist));
-		(*lpp)->n = copynode(lp->n);
-		lp = lp->next;
-		lpp = &(*lpp)->next;
-	}
-	*lpp = NULL;
-	return start;
-}
-
-
-
-STATIC char *
-nodesavestr(s)
-	char   *s;
-{
-	register char *p = s;
-	register char *q = funcstring;
-	char   *rtn = funcstring;
-
-	while ((*q++ = *p++) != 0)
-		continue;
-	funcstring = q;
-	return rtn;
-}
-
-
-
-/*
- * Free a parse tree.
- */
-
-void
-freefunc(n)
-	union node *n;
-{
-	if (n)
-		ckfree(n);
-}
diff --git a/sh/nodes.h b/sh/nodes.h
deleted file mode 100644
index aa750ed..0000000
--- a/sh/nodes.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * This file was generated by mknodes.sh
- */
-
-#define NSEMI 0
-#define NCMD 1
-#define NPIPE 2
-#define NREDIR 3
-#define NBACKGND 4
-#define NSUBSHELL 5
-#define NAND 6
-#define NOR 7
-#define NIF 8
-#define NWHILE 9
-#define NUNTIL 10
-#define NFOR 11
-#define NCASE 12
-#define NCLIST 13
-#define NDEFUN 14
-#define NARG 15
-#define NTO 16
-#define NCLOBBER 17
-#define NFROM 18
-#define NFROMTO 19
-#define NAPPEND 20
-#define NTOFD 21
-#define NFROMFD 22
-#define NHERE 23
-#define NXHERE 24
-#define NNOT 25
-
-
-
-struct nbinary {
-      int type;
-      union node *ch1;
-      union node *ch2;
-};
-
-
-struct ncmd {
-      int type;
-      int backgnd;
-      union node *args;
-      union node *redirect;
-};
-
-
-struct npipe {
-      int type;
-      int backgnd;
-      struct nodelist *cmdlist;
-};
-
-
-struct nredir {
-      int type;
-      union node *n;
-      union node *redirect;
-};
-
-
-struct nif {
-      int type;
-      union node *test;
-      union node *ifpart;
-      union node *elsepart;
-};
-
-
-struct nfor {
-      int type;
-      union node *args;
-      union node *body;
-      char *var;
-};
-
-
-struct ncase {
-      int type;
-      union node *expr;
-      union node *cases;
-};
-
-
-struct nclist {
-      int type;
-      union node *next;
-      union node *pattern;
-      union node *body;
-};
-
-
-struct narg {
-      int type;
-      union node *next;
-      char *text;
-      struct nodelist *backquote;
-};
-
-
-struct nfile {
-      int type;
-      union node *next;
-      int fd;
-      union node *fname;
-      char *expfname;
-};
-
-
-struct ndup {
-      int type;
-      union node *next;
-      int fd;
-      int dupfd;
-      union node *vname;
-};
-
-
-struct nhere {
-      int type;
-      union node *next;
-      int fd;
-      union node *doc;
-};
-
-
-struct nnot {
-      int type;
-      union node *com;
-};
-
-
-union node {
-      int type;
-      struct nbinary nbinary;
-      struct ncmd ncmd;
-      struct npipe npipe;
-      struct nredir nredir;
-      struct nif nif;
-      struct nfor nfor;
-      struct ncase ncase;
-      struct nclist nclist;
-      struct narg narg;
-      struct nfile nfile;
-      struct ndup ndup;
-      struct nhere nhere;
-      struct nnot nnot;
-};
-
-
-struct nodelist {
-	struct nodelist *next;
-	union node *n;
-};
-
-
-union node *copyfunc(union node *);
-void freefunc(union node *);
diff --git a/sh/nodetypes b/sh/nodetypes
deleted file mode 100644
index 4adebc0..0000000
--- a/sh/nodetypes
+++ /dev/null
@@ -1,143 +0,0 @@
-#	$NetBSD: nodetypes,v 1.12 2003/08/22 11:22:23 agc Exp $
-# Copyright (c) 1991, 1993
-#	The Regents of the University of California.  All rights reserved.
-#
-# This code is derived from software contributed to Berkeley by
-# Kenneth Almquist.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-# 3. 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.
-#
-#	@(#)nodetypes	8.2 (Berkeley) 5/4/95
-
-# This file describes the nodes used in parse trees.  Unindented lines
-# contain a node type followed by a structure tag.  Subsequent indented
-# lines specify the fields of the structure.  Several node types can share
-# the same structure, in which case the fields of the structure should be
-# specified only once.
-#
-# A field of a structure is described by the name of the field followed
-# by a type.  The currently implemented types are:
-#	nodeptr - a pointer to a node
-#	nodelist - a pointer to a list of nodes
-#	string - a pointer to a nul terminated string
-#	int - an integer
-#	other - any type that can be copied by assignment
-#	temp - a field that doesn't have to be copied when the node is copied
-# The last two types should be followed by the text of a C declaration for
-# the field.
-
-NSEMI nbinary			# two commands separated by a semicolon
-	type	  int
-	ch1	  nodeptr		# the first child
-	ch2	  nodeptr		# the second child
-
-NCMD ncmd			# a simple command
-	type	  int
-	backgnd	  int			# set to run command in background
-	args	  nodeptr		# the arguments
-	redirect  nodeptr		# list of file redirections
-
-NPIPE npipe			# a pipeline
-	type	  int
-	backgnd	  int			# set to run pipeline in background
-	cmdlist	  nodelist		# the commands in the pipeline
-
-NREDIR nredir			# redirection (of a complex command)
-	type	  int
-	n	  nodeptr		# the command
-	redirect  nodeptr		# list of file redirections
-
-NBACKGND nredir			# run command in background
-NSUBSHELL nredir		# run command in a subshell
-
-NAND nbinary			# the && operator
-NOR nbinary			# the || operator
-
-NIF nif				# the if statement.  Elif clauses are handled
-	type	  int		    # using multiple if nodes.
-	test	  nodeptr		# if test
-	ifpart	  nodeptr		# then ifpart
-	elsepart  nodeptr		# else elsepart
-
-NWHILE nbinary			# the while statement.  First child is the test
-NUNTIL nbinary			# the until statement
-
-NFOR nfor			# the for statement
-	type	  int
-	args	  nodeptr		# for var in args
-	body	  nodeptr		# do body; done
-	var	  string		# the for variable
-
-NCASE ncase			# a case statement
-	type	  int
-	expr	  nodeptr		# the word to switch on
-	cases	  nodeptr		# the list of cases (NCLIST nodes)
-
-NCLIST nclist			# a case
-	type	  int
-	next	  nodeptr		# the next case in list
-	pattern	  nodeptr		# list of patterns for this case
-	body	  nodeptr		# code to execute for this case
-
-
-NDEFUN narg			# define a function.  The "next" field contains
-				# the body of the function.
-
-NARG narg			# represents a word
-	type	  int
-	next	  nodeptr		# next word in list
-	text	  string		# the text of the word
-	backquote nodelist		# list of commands in back quotes
-
-NTO nfile			# fd> fname
-NCLOBBER nfile			# fd>| fname
-NFROM nfile			# fd< fname
-NFROMTO nfile			# fd<> fname
-NAPPEND nfile			# fd>> fname
-	type	  int
-	next	  nodeptr		# next redirection in list
-	fd	  int			# file descriptor being redirected
-	fname	  nodeptr		# file name, in a NARG node
-	expfname  temp	char *expfname	# actual file name
-
-NTOFD ndup			# fd<&dupfd
-NFROMFD ndup			# fd>&dupfd
-	type	  int
-	next	  nodeptr		# next redirection in list
-	fd	  int			# file descriptor being redirected
-	dupfd	  int			# file descriptor to duplicate
-	vname	  nodeptr		# file name if fd>&$var
-
-
-NHERE nhere			# fd<<\!
-NXHERE nhere			# fd<<!
-	type	  int
-	next	  nodeptr		# next redirection in list
-	fd	  int			# file descriptor being redirected
-	doc	  nodeptr		# input to command (NARG node)
-
-NNOT nnot			# ! command  (actually pipeline)
-	type	int
-	com	nodeptr
diff --git a/sh/options.c b/sh/options.c
deleted file mode 100644
index bc833c7..0000000
--- a/sh/options.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/*	$NetBSD: options.c,v 1.37 2004/10/30 19:29:27 christos Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)options.c	8.2 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: options.c,v 1.37 2004/10/30 19:29:27 christos Exp $");
-#endif
-#endif /* not lint */
-
-#include <signal.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include "shell.h"
-#define DEFINE_OPTIONS
-#include "options.h"
-#undef DEFINE_OPTIONS
-#include "nodes.h"	/* for other header files */
-#include "eval.h"
-#include "jobs.h"
-#include "input.h"
-#include "output.h"
-#include "trap.h"
-#include "var.h"
-#include "memalloc.h"
-#include "error.h"
-#include "mystring.h"
-#ifndef SMALL
-#include "myhistedit.h"
-#endif
-#include "show.h"
-
-char *arg0;			/* value of $0 */
-struct shparam shellparam;	/* current positional parameters */
-char **argptr;			/* argument list for builtin commands */
-char *optionarg;		/* set by nextopt (like getopt) */
-char *optptr;			/* used by nextopt */
-
-char *minusc;			/* argument to -c option */
-
-
-STATIC void options(int);
-STATIC void minus_o(char *, int);
-STATIC void setoption(int, int);
-STATIC int getopts(char *, char *, char **, char ***, char **);
-
-
-/*
- * Process the shell command line arguments.
- */
-
-void
-procargs(int argc, char **argv)
-{
-	int i;
-
-	argptr = argv;
-	if (argc > 0)
-		argptr++;
-	for (i = 0; i < NOPTS; i++)
-		optlist[i].val = 2;
-	options(1);
-	if (*argptr == NULL && minusc == NULL)
-		sflag = 1;
-	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
-		iflag = 1;
-	if (mflag == 2)
-		mflag = iflag;
-	for (i = 0; i < NOPTS; i++)
-		if (optlist[i].val == 2)
-			optlist[i].val = 0;
-#if DEBUG == 2
-	debug = 1;
-#endif
-	arg0 = argv[0];
-	if (sflag == 0 && minusc == NULL) {
-		commandname = argv[0];
-		arg0 = *argptr++;
-		setinputfile(arg0, 0);
-		commandname = arg0;
-	}
-	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
-	if (minusc != NULL) {
-		if (argptr == NULL || *argptr == NULL)
-			error("Bad -c option");
-		minusc = *argptr++;
-		if (*argptr != 0)
-			arg0 = *argptr++;
-	}
-
-	shellparam.p = argptr;
-	shellparam.reset = 1;
-	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
-	while (*argptr) {
-		shellparam.nparam++;
-		argptr++;
-	}
-	optschanged();
-}
-
-
-void
-optschanged(void)
-{
-	setinteractive(iflag);
-#ifdef WITH_HISTORY
-	histedit();
-#endif
-	setjobctl(mflag);
-}
-
-/*
- * Process shell options.  The global variable argptr contains a pointer
- * to the argument list; we advance it past the options.
- */
-
-STATIC void
-options(int cmdline)
-{
-	static char empty[] = "";
-	char *p;
-	int val;
-	int c;
-
-	if (cmdline)
-		minusc = NULL;
-	while ((p = *argptr) != NULL) {
-		argptr++;
-		if ((c = *p++) == '-') {
-			val = 1;
-                        if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
-                                if (!cmdline) {
-                                        /* "-" means turn off -x and -v */
-                                        if (p[0] == '\0')
-                                                xflag = vflag = 0;
-                                        /* "--" means reset params */
-                                        else if (*argptr == NULL)
-						setparam(argptr);
-                                }
-				break;	  /* "-" or  "--" terminates options */
-			}
-		} else if (c == '+') {
-			val = 0;
-		} else {
-			argptr--;
-			break;
-		}
-		while ((c = *p++) != '\0') {
-			if (c == 'c' && cmdline) {
-				/* command is after shell args*/
-				minusc = empty;
-			} else if (c == 'o') {
-				minus_o(*argptr, val);
-				if (*argptr)
-					argptr++;
-			} else {
-				setoption(c, val);
-			}
-		}
-	}
-}
-
-static void
-set_opt_val(int i, int val)
-{
-	int j;
-	int flag;
-
-	if (val && (flag = optlist[i].opt_set)) {
-		/* some options (eg vi/emacs) are mutually exclusive */
-		for (j = 0; j < NOPTS; j++)
-		    if (optlist[j].opt_set == flag)
-			optlist[j].val = 0;
-	}
-	optlist[i].val = val;
-#ifdef DEBUG
-	if (&optlist[i].val == &debug)
-		opentrace();
-#endif
-}
-
-STATIC void
-minus_o(char *name, int val)
-{
-	int i;
-
-	if (name == NULL) {
-		out1str("Current option settings\n");
-		for (i = 0; i < NOPTS; i++)
-			out1fmt("%-16s%s\n", optlist[i].name,
-				optlist[i].val ? "on" : "off");
-	} else {
-		for (i = 0; i < NOPTS; i++)
-			if (equal(name, optlist[i].name)) {
-				set_opt_val(i, val);
-				return;
-			}
-		error("Illegal option -o %s", name);
-	}
-}
-
-
-STATIC void
-setoption(int flag, int val)
-{
-	int i;
-
-	for (i = 0; i < NOPTS; i++)
-		if (optlist[i].letter == flag) {
-			set_opt_val( i, val );
-			return;
-		}
-	error("Illegal option -%c", flag);
-	/* NOTREACHED */
-}
-
-
-
-#ifdef mkinit
-INCLUDE "options.h"
-
-SHELLPROC {
-	int i;
-
-	for (i = 0; optlist[i].name; i++)
-		optlist[i].val = 0;
-	optschanged();
-
-}
-#endif
-
-
-/*
- * Set the shell parameters.
- */
-
-void
-setparam(char **argv)
-{
-	char **newparam;
-	char **ap;
-	int nparam;
-
-	for (nparam = 0 ; argv[nparam] ; nparam++);
-	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
-	while (*argv) {
-		*ap++ = savestr(*argv++);
-	}
-	*ap = NULL;
-	freeparam(&shellparam);
-	shellparam.malloc = 1;
-	shellparam.nparam = nparam;
-	shellparam.p = newparam;
-	shellparam.optnext = NULL;
-}
-
-
-/*
- * Free the list of positional parameters.
- */
-
-void
-freeparam(volatile struct shparam *param)
-{
-	char **ap;
-
-	if (param->malloc) {
-		for (ap = param->p ; *ap ; ap++)
-			ckfree(*ap);
-		ckfree(param->p);
-	}
-}
-
-
-
-/*
- * The shift builtin command.
- */
-
-int
-shiftcmd(int argc, char **argv)
-{
-	int n;
-	char **ap1, **ap2;
-
-	n = 1;
-	if (argc > 1)
-		n = number(argv[1]);
-	if (n > shellparam.nparam)
-		error("can't shift that many");
-	INTOFF;
-	shellparam.nparam -= n;
-	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
-		if (shellparam.malloc)
-			ckfree(*ap1);
-	}
-	ap2 = shellparam.p;
-	while ((*ap2++ = *ap1++) != NULL);
-	shellparam.optnext = NULL;
-	INTON;
-	return 0;
-}
-
-
-
-/*
- * The set command builtin.
- */
-
-int
-setcmd(int argc, char **argv)
-{
-	if (argc == 1)
-		return showvars(0, 0, 1);
-	INTOFF;
-	options(0);
-	optschanged();
-	if (*argptr != NULL) {
-		setparam(argptr);
-	}
-	INTON;
-	return 0;
-}
-
-
-void
-getoptsreset(value)
-	const char *value;
-{
-	if (number(value) == 1) {
-		shellparam.optnext = NULL;
-		shellparam.reset = 1;
-	}
-}
-
-/*
- * The getopts builtin.  Shellparam.optnext points to the next argument
- * to be processed.  Shellparam.optptr points to the next character to
- * be processed in the current argument.  If shellparam.optnext is NULL,
- * then it's the first time getopts has been called.
- */
-
-int
-getoptscmd(int argc, char **argv)
-{
-	char **optbase;
-
-	if (argc < 3)
-		error("usage: getopts optstring var [arg]");
-	else if (argc == 3)
-		optbase = shellparam.p;
-	else
-		optbase = &argv[3];
-
-	if (shellparam.reset == 1) {
-		shellparam.optnext = optbase;
-		shellparam.optptr = NULL;
-		shellparam.reset = 0;
-	}
-
-	return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
-		       &shellparam.optptr);
-}
-
-STATIC int
-getopts(char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr)
-{
-	char *p, *q;
-	char c = '?';
-	int done = 0;
-	int ind = 0;
-	int err = 0;
-	char s[12];
-
-	if ((p = *optpptr) == NULL || *p == '\0') {
-		/* Current word is done, advance */
-		if (*optnext == NULL)
-			return 1;
-		p = **optnext;
-		if (p == NULL || *p != '-' || *++p == '\0') {
-atend:
-			ind = *optnext - optfirst + 1;
-			*optnext = NULL;
-			p = NULL;
-			done = 1;
-			goto out;
-		}
-		(*optnext)++;
-		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
-			goto atend;
-	}
-
-	c = *p++;
-	for (q = optstr; *q != c; ) {
-		if (*q == '\0') {
-			if (optstr[0] == ':') {
-				s[0] = c;
-				s[1] = '\0';
-				err |= setvarsafe("OPTARG", s, 0);
-			} else {
-				outfmt(&errout, "Illegal option -%c\n", c);
-				(void) unsetvar("OPTARG", 0);
-			}
-			c = '?';
-			goto bad;
-		}
-		if (*++q == ':')
-			q++;
-	}
-
-	if (*++q == ':') {
-		if (*p == '\0' && (p = **optnext) == NULL) {
-			if (optstr[0] == ':') {
-				s[0] = c;
-				s[1] = '\0';
-				err |= setvarsafe("OPTARG", s, 0);
-				c = ':';
-			} else {
-				outfmt(&errout, "No arg for -%c option\n", c);
-				(void) unsetvar("OPTARG", 0);
-				c = '?';
-			}
-			goto bad;
-		}
-
-		if (p == **optnext)
-			(*optnext)++;
-		err |= setvarsafe("OPTARG", p, 0);
-		p = NULL;
-	} else
-		err |= setvarsafe("OPTARG", "", 0);
-	ind = *optnext - optfirst + 1;
-	goto out;
-
-bad:
-	ind = 1;
-	*optnext = NULL;
-	p = NULL;
-out:
-	*optpptr = p;
-	fmtstr(s, sizeof(s), "%d", ind);
-	err |= setvarsafe("OPTIND", s, VNOFUNC);
-	s[0] = c;
-	s[1] = '\0';
-	err |= setvarsafe(optvar, s, 0);
-	if (err) {
-		*optnext = NULL;
-		*optpptr = NULL;
-		flushall();
-		exraise(EXERROR);
-	}
-	return done;
-}
-
-/*
- * XXX - should get rid of.  have all builtins use getopt(3).  the
- * library getopt must have the BSD extension static variable "optreset"
- * otherwise it can't be used within the shell safely.
- *
- * Standard option processing (a la getopt) for builtin routines.  The
- * only argument that is passed to nextopt is the option string; the
- * other arguments are unnecessary.  It return the character, or '\0' on
- * end of input.
- */
-
-int
-nextopt(const char *optstring)
-{
-	char *p;
-	const char *q;
-	char c;
-
-	if ((p = optptr) == NULL || *p == '\0') {
-		p = *argptr;
-		if (p == NULL || *p != '-' || *++p == '\0')
-			return '\0';
-		argptr++;
-		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
-			return '\0';
-	}
-	c = *p++;
-	for (q = optstring ; *q != c ; ) {
-		if (*q == '\0')
-			error("Illegal option -%c", c);
-		if (*++q == ':')
-			q++;
-	}
-	if (*++q == ':') {
-		if (*p == '\0' && (p = *argptr++) == NULL)
-			error("No arg for -%c option", c);
-		optionarg = p;
-		p = NULL;
-	}
-	optptr = p;
-	return c;
-}
diff --git a/sh/options.h b/sh/options.h
deleted file mode 100644
index 4cc7dbe..0000000
--- a/sh/options.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*	$NetBSD: options.h,v 1.17 2003/08/07 09:05:36 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)options.h	8.2 (Berkeley) 5/4/95
- */
-
-struct shparam {
-	int nparam;		/* # of positional parameters (without $0) */
-	unsigned char malloc;	/* if parameter list dynamically allocated */
-	unsigned char reset;	/* if getopts has been reset */
-	char **p;		/* parameter list */
-	char **optnext;		/* next parameter to be processed by getopts */
-	char *optptr;		/* used by getopts */
-};
-
-
-struct optent {
-	const char *name;		/* for set -o <name> */
-	const char letter;		/* set [+/-]<letter> and $- */
-	const char opt_set;		/* mutually exclusive option set */
-	char val;			/* value of <letter>flag */
-};
-
-/* Those marked [U] are required by posix, but have no effect! */
-
-#ifdef DEFINE_OPTIONS
-#define DEF_OPTS(name, letter, opt_set) {name, letter, opt_set, 0},
-struct optent optlist[] = {
-#else
-#define DEF_OPTS(name, letter, opt_set)
-#endif
-#define DEF_OPT(name,letter) DEF_OPTS(name, letter, 0)
-
-DEF_OPT( "errexit",	'e' )	/* exit on error */
-#define eflag optlist[0].val
-DEF_OPT( "noglob",	'f' )	/* no pathname expansion */
-#define fflag optlist[1].val
-DEF_OPT( "ignoreeof",	'I' )	/* do not exit on EOF */
-#define Iflag optlist[2].val
-DEF_OPT( "interactive",'i' )	/* interactive shell */
-#define iflag optlist[3].val
-DEF_OPT( "monitor",	'm' )	/* job control */
-#define mflag optlist[4].val
-DEF_OPT( "noexec",	'n' )	/* [U] do not exec commands */
-#define nflag optlist[5].val
-DEF_OPT( "stdin",	's' )	/* read from stdin */
-#define sflag optlist[6].val
-DEF_OPT( "xtrace",	'x' )	/* trace after expansion */
-#define xflag optlist[7].val
-DEF_OPT( "verbose",	'v' )	/* trace read input */
-#define vflag optlist[8].val
-DEF_OPTS( "vi",		'V', 'V' )	/* vi style editing */
-#define Vflag optlist[9].val
-DEF_OPTS( "emacs",	'E', 'V' )	/* emacs style editing */
-#define	Eflag optlist[10].val
-DEF_OPT( "noclobber",	'C' )	/* do not overwrite files with > */
-#define	Cflag optlist[11].val
-DEF_OPT( "allexport",	'a' )	/* export all variables */
-#define	aflag optlist[12].val
-DEF_OPT( "notify",	'b' )	/* [U] report completion of background jobs */
-#define	bflag optlist[13].val
-DEF_OPT( "nounset",	'u' )	/* error expansion of unset variables */
-#define	uflag optlist[14].val
-DEF_OPT( "quietprofile", 'q' )
-#define	qflag optlist[15].val
-DEF_OPT( "nolog",	0 )	/* [U] no functon defs in command history */
-#define	nolog optlist[16].val
-DEF_OPT( "cdprint",	0 )	/* always print result of cd */
-#define	cdprint optlist[17].val
-#ifdef DEBUG
-DEF_OPT( "debug",	0 )	/* enable debug prints */
-#define	debug optlist[18].val
-#endif
-
-#ifdef DEFINE_OPTIONS
-	{ 0, 0, 0, 0 },
-};
-#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)
-int sizeof_optlist = sizeof optlist;
-#else
-extern struct optent optlist[];
-extern int sizeof_optlist;
-#endif
-
-
-extern char *minusc;		/* argument to -c option */
-extern char *arg0;		/* $0 */
-extern struct shparam shellparam;  /* $@ */
-extern char **argptr;		/* argument list for builtin commands */
-extern char *optionarg;		/* set by nextopt */
-extern char *optptr;		/* used by nextopt */
-
-void procargs(int, char **);
-void optschanged(void);
-void setparam(char **);
-void freeparam(volatile struct shparam *);
-int shiftcmd(int, char **);
-int setcmd(int, char **);
-int getoptscmd(int, char **);
-int nextopt(const char *);
-void getoptsreset(const char *);
diff --git a/sh/output.c b/sh/output.c
deleted file mode 100644
index b0e669e..0000000
--- a/sh/output.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*	$NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)output.c	8.2 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: output.c,v 1.28 2003/08/07 09:05:36 agc Exp $");
-#endif
-#endif /* not lint */
-
-/*
- * Shell output routines.  We use our own output routines because:
- *	When a builtin command is interrupted we have to discard
- *		any pending output.
- *	When a builtin command appears in back quotes, we want to
- *		save the output of the command in a region obtained
- *		via malloc, rather than doing a fork and reading the
- *		output of the command via a pipe.
- *	Our output routines may be smaller than the stdio routines.
- */
-
-#include <sys/types.h>		/* quad_t */
-#include <sys/param.h>		/* BSD4_4 */
-#include <sys/ioctl.h>
-
-#include <stdio.h>	/* defines BUFSIZ */
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include "shell.h"
-#include "syntax.h"
-#include "output.h"
-#include "memalloc.h"
-#include "error.h"
-
-
-#define OUTBUFSIZ BUFSIZ
-#define BLOCK_OUT -2		/* output to a fixed block of memory */
-#define MEM_OUT -3		/* output to dynamically allocated memory */
-#define OUTPUT_ERR 01		/* error occurred on output */
-
-
-struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
-struct output errout = {NULL, 0, NULL, 100, 2, 0};
-struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
-struct output *out1 = &output;
-struct output *out2 = &errout;
-
-
-
-#ifdef mkinit
-
-INCLUDE "output.h"
-INCLUDE "memalloc.h"
-
-RESET {
-	out1 = &output;
-	out2 = &errout;
-	if (memout.buf != NULL) {
-		ckfree(memout.buf);
-		memout.buf = NULL;
-	}
-}
-
-#endif
-
-
-#ifdef notdef	/* no longer used */
-/*
- * Set up an output file to write to memory rather than a file.
- */
-
-void
-open_mem(char *block, int length, struct output *file)
-{
-	file->nextc = block;
-	file->nleft = --length;
-	file->fd = BLOCK_OUT;
-	file->flags = 0;
-}
-#endif
-
-
-void
-out1str(const char *p)
-{
-	outstr(p, out1);
-}
-
-
-void
-out2str(const char *p)
-{
-	outstr(p, out2);
-}
-
-
-void
-outstr(const char *p, struct output *file)
-{
-	while (*p)
-		outc(*p++, file);
-	if (file == out2)
-		flushout(file);
-}
-
-
-char out_junk[16];
-
-
-void
-emptyoutbuf(struct output *dest)
-{
-	int offset;
-
-	if (dest->fd == BLOCK_OUT) {
-		dest->nextc = out_junk;
-		dest->nleft = sizeof out_junk;
-		dest->flags |= OUTPUT_ERR;
-	} else if (dest->buf == NULL) {
-		INTOFF;
-		dest->buf = ckmalloc(dest->bufsize);
-		dest->nextc = dest->buf;
-		dest->nleft = dest->bufsize;
-		INTON;
-	} else if (dest->fd == MEM_OUT) {
-		offset = dest->bufsize;
-		INTOFF;
-		dest->bufsize <<= 1;
-		dest->buf = ckrealloc(dest->buf, dest->bufsize);
-		dest->nleft = dest->bufsize - offset;
-		dest->nextc = dest->buf + offset;
-		INTON;
-	} else {
-		flushout(dest);
-	}
-	dest->nleft--;
-}
-
-
-void
-flushall(void)
-{
-	flushout(&output);
-	flushout(&errout);
-}
-
-
-void
-flushout(struct output *dest)
-{
-
-	if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0)
-		return;
-	if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0)
-		dest->flags |= OUTPUT_ERR;
-	dest->nextc = dest->buf;
-	dest->nleft = dest->bufsize;
-}
-
-
-void
-freestdout(void)
-{
-	INTOFF;
-	if (output.buf) {
-		ckfree(output.buf);
-		output.buf = NULL;
-		output.nleft = 0;
-	}
-	INTON;
-}
-
-
-void
-outfmt(struct output *file, const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	doformat(file, fmt, ap);
-	va_end(ap);
-}
-
-
-void
-out1fmt(const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	doformat(out1, fmt, ap);
-	va_end(ap);
-}
-
-void
-dprintf(const char *fmt, ...)
-{
-	va_list ap;
-
-	va_start(ap, fmt);
-	doformat(out2, fmt, ap);
-	va_end(ap);
-	flushout(out2);
-}
-
-void
-fmtstr(char *outbuf, size_t length, const char *fmt, ...)
-{
-	va_list ap;
-	struct output strout;
-
-	va_start(ap, fmt);
-	strout.nextc = outbuf;
-	strout.nleft = length;
-	strout.fd = BLOCK_OUT;
-	strout.flags = 0;
-	doformat(&strout, fmt, ap);
-	outc('\0', &strout);
-	if (strout.flags & OUTPUT_ERR)
-		outbuf[length - 1] = '\0';
-	va_end(ap);
-}
-
-/*
- * Formatted output.  This routine handles a subset of the printf formats:
- * - Formats supported: d, u, o, p, X, s, and c.
- * - The x format is also accepted but is treated like X.
- * - The l, ll and q modifiers are accepted.
- * - The - and # flags are accepted; # only works with the o format.
- * - Width and precision may be specified with any format except c.
- * - An * may be given for the width or precision.
- * - The obsolete practice of preceding the width with a zero to get
- *   zero padding is not supported; use the precision field.
- * - A % may be printed by writing %% in the format string.
- */
-
-#define TEMPSIZE 24
-
-#ifdef BSD4_4
-#define HAVE_VASPRINTF 1
-#endif
-
-void
-doformat(struct output *dest, const char *f, va_list ap)
-{
-#if	HAVE_VASPRINTF
-	char *s;
-
-	vasprintf(&s, f, ap);
-	outstr(s, dest);
-	free(s);     
-#else	/* !HAVE_VASPRINTF */
-	static const char digit[] = "0123456789ABCDEF";
-	char c;
-	char temp[TEMPSIZE];
-	int flushleft;
-	int sharp;
-	int width;
-	int prec;
-	int islong;
-	int isquad;
-	char *p;
-	int sign;
-#ifdef BSD4_4
-	quad_t l;
-	u_quad_t num;
-#else
-	long l;
-	u_long num;
-#endif
-	unsigned base;
-	int len;
-	int size;
-	int pad;
-
-	while ((c = *f++) != '\0') {
-		if (c != '%') {
-			outc(c, dest);
-			continue;
-		}
-		flushleft = 0;
-		sharp = 0;
-		width = 0;
-		prec = -1;
-		islong = 0;
-		isquad = 0;
-		for (;;) {
-			if (*f == '-')
-				flushleft++;
-			else if (*f == '#')
-				sharp++;
-			else
-				break;
-			f++;
-		}
-		if (*f == '*') {
-			width = va_arg(ap, int);
-			f++;
-		} else {
-			while (is_digit(*f)) {
-				width = 10 * width + digit_val(*f++);
-			}
-		}
-		if (*f == '.') {
-			if (*++f == '*') {
-				prec = va_arg(ap, int);
-				f++;
-			} else {
-				prec = 0;
-				while (is_digit(*f)) {
-					prec = 10 * prec + digit_val(*f++);
-				}
-			}
-		}
-		if (*f == 'l') {
-			f++;
-			if (*f == 'l') {
-				isquad++;
-				f++;
-			} else
-				islong++;
-		} else if (*f == 'q') {
-			isquad++;
-			f++;
-		}
-		switch (*f) {
-		case 'd':
-#ifdef BSD4_4
-			if (isquad)
-				l = va_arg(ap, quad_t);
-			else
-#endif
-			if (islong)
-				l = va_arg(ap, long);
-			else
-				l = va_arg(ap, int);
-			sign = 0;
-			num = l;
-			if (l < 0) {
-				num = -l;
-				sign = 1;
-			}
-			base = 10;
-			goto number;
-		case 'u':
-			base = 10;
-			goto uns_number;
-		case 'o':
-			base = 8;
-			goto uns_number;
-		case 'p':
-			outc('0', dest);
-			outc('x', dest);
-			/*FALLTHROUGH*/
-		case 'x':
-			/* we don't implement 'x'; treat like 'X' */
-		case 'X':
-			base = 16;
-uns_number:	  /* an unsigned number */
-			sign = 0;
-#ifdef BSD4_4
-			if (isquad)
-				num = va_arg(ap, u_quad_t);
-			else
-#endif
-			if (islong)
-				num = va_arg(ap, unsigned long);
-			else
-				num = va_arg(ap, unsigned int);
-number:		  /* process a number */
-			p = temp + TEMPSIZE - 1;
-			*p = '\0';
-			while (num) {
-				*--p = digit[num % base];
-				num /= base;
-			}
-			len = (temp + TEMPSIZE - 1) - p;
-			if (prec < 0)
-				prec = 1;
-			if (sharp && *f == 'o' && prec <= len)
-				prec = len + 1;
-			pad = 0;
-			if (width) {
-				size = len;
-				if (size < prec)
-					size = prec;
-				size += sign;
-				pad = width - size;
-				if (flushleft == 0) {
-					while (--pad >= 0)
-						outc(' ', dest);
-				}
-			}
-			if (sign)
-				outc('-', dest);
-			prec -= len;
-			while (--prec >= 0)
-				outc('0', dest);
-			while (*p)
-				outc(*p++, dest);
-			while (--pad >= 0)
-				outc(' ', dest);
-			break;
-		case 's':
-			p = va_arg(ap, char *);
-			pad = 0;
-			if (width) {
-				len = strlen(p);
-				if (prec >= 0 && len > prec)
-					len = prec;
-				pad = width - len;
-				if (flushleft == 0) {
-					while (--pad >= 0)
-						outc(' ', dest);
-				}
-			}
-			prec++;
-			while (--prec != 0 && *p)
-				outc(*p++, dest);
-			while (--pad >= 0)
-				outc(' ', dest);
-			break;
-		case 'c':
-			c = va_arg(ap, int);
-			outc(c, dest);
-			break;
-		default:
-			outc(*f, dest);
-			break;
-		}
-		f++;
-	}
-#endif	/* !HAVE_VASPRINTF */
-}
-
-
-
-/*
- * Version of write which resumes after a signal is caught.
- */
-
-int
-xwrite(int fd, char *buf, int nbytes)
-{
-	int ntry;
-	int i;
-	int n;
-
-	n = nbytes;
-	ntry = 0;
-	for (;;) {
-		i = write(fd, buf, n);
-		if (i > 0) {
-			if ((n -= i) <= 0)
-				return nbytes;
-			buf += i;
-			ntry = 0;
-		} else if (i == 0) {
-			if (++ntry > 10)
-				return nbytes - n;
-		} else if (errno != EINTR) {
-			return -1;
-		}
-	}
-}
-
-
-/*
- * Version of ioctl that retries after a signal is caught.
- * XXX unused function
- */
-
-int
-xioctl(int fd, unsigned long request, char *arg)
-{
-	int i;
-
-	while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
-	return i;
-}
diff --git a/sh/output.h b/sh/output.h
deleted file mode 100644
index 9a199a0..0000000
--- a/sh/output.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*	$NetBSD: output.h,v 1.17 2003/08/07 09:05:36 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)output.h	8.2 (Berkeley) 5/4/95
- */
-
-#ifndef OUTPUT_INCL
-
-#include <stdarg.h>
-
-struct output {
-	char *nextc;
-	int nleft;
-	char *buf;
-	int bufsize;
-	short fd;
-	short flags;
-};
-
-extern struct output output;
-extern struct output errout;
-extern struct output memout;
-extern struct output *out1;
-extern struct output *out2;
-
-void open_mem(char *, int, struct output *);
-void out1str(const char *);
-void out2str(const char *);
-void outstr(const char *, struct output *);
-void emptyoutbuf(struct output *);
-void flushall(void);
-void flushout(struct output *);
-void freestdout(void);
-void outfmt(struct output *, const char *, ...)
-    __attribute__((__format__(__printf__,2,3)));
-void out1fmt(const char *, ...)
-    __attribute__((__format__(__printf__,1,2)));
-void dprintf(const char *, ...)
-    __attribute__((__format__(__printf__,1,2)));
-void fmtstr(char *, size_t, const char *, ...)
-    __attribute__((__format__(__printf__,3,4)));
-void doformat(struct output *, const char *, va_list);
-int xwrite(int, char *, int);
-int xioctl(int, unsigned long, char *);
-
-#define outc(c, file)	(--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c)))
-#define out1c(c)	outc(c, out1);
-#define out2c(c)	outc(c, out2);
-
-#define OUTPUT_INCL
-#endif
diff --git a/sh/parser.c b/sh/parser.c
deleted file mode 100644
index faf0268..0000000
--- a/sh/parser.c
+++ /dev/null
@@ -1,1654 +0,0 @@
-/*	$NetBSD: parser.c,v 1.57 2004/06/27 10:27:57 dsl Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)parser.c	8.7 (Berkeley) 5/16/95";
-#else
-__RCSID("$NetBSD: parser.c,v 1.57 2004/06/27 10:27:57 dsl Exp $");
-#endif
-#endif /* not lint */
-
-#include <stdlib.h>
-
-#include "shell.h"
-#include "parser.h"
-#include "nodes.h"
-#include "expand.h"	/* defines rmescapes() */
-#include "eval.h"	/* defines commandname */
-#include "redir.h"	/* defines copyfd() */
-#include "syntax.h"
-#include "options.h"
-#include "input.h"
-#include "output.h"
-#include "var.h"
-#include "error.h"
-#include "memalloc.h"
-#include "mystring.h"
-#include "alias.h"
-#include "show.h"
-#ifndef SMALL
-#include "myhistedit.h"
-#endif
-
-/*
- * Shell command parser.
- */
-
-#define EOFMARKLEN 79
-
-/* values returned by readtoken */
-#include "token.h"
-
-#define OPENBRACE '{'
-#define CLOSEBRACE '}'
-
-
-struct heredoc {
-	struct heredoc *next;	/* next here document in list */
-	union node *here;		/* redirection node */
-	char *eofmark;		/* string indicating end of input */
-	int striptabs;		/* if set, strip leading tabs */
-};
-
-
-
-static int noalias = 0;		/* when set, don't handle aliases */
-struct heredoc *heredoclist;	/* list of here documents to read */
-int parsebackquote;		/* nonzero if we are inside backquotes */
-int doprompt;			/* if set, prompt the user */
-int needprompt;			/* true if interactive and at start of line */
-int lasttoken;			/* last token read */
-MKINIT int tokpushback;		/* last token pushed back */
-char *wordtext;			/* text of last word returned by readtoken */
-MKINIT int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
-struct nodelist *backquotelist;
-union node *redirnode;
-struct heredoc *heredoc;
-int quoteflag;			/* set if (part of) last token was quoted */
-int startlinno;			/* line # where last token started */
-
-
-STATIC union node *list(int);
-STATIC union node *andor(void);
-STATIC union node *pipeline(void);
-STATIC union node *command(void);
-STATIC union node *simplecmd(union node **, union node *);
-STATIC union node *makename(void);
-STATIC void parsefname(void);
-STATIC void parseheredoc(void);
-STATIC int peektoken(void);
-STATIC int readtoken(void);
-STATIC int xxreadtoken(void);
-STATIC int readtoken1(int, char const *, char *, int);
-STATIC int noexpand(char *);
-STATIC void synexpect(int) __attribute__((__noreturn__));
-STATIC void synerror(const char *) __attribute__((__noreturn__));
-STATIC void setprompt(int);
-
-
-/*
- * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
- * valid parse tree indicating a blank line.)
- */
-
-union node *
-parsecmd(int interact)
-{
-	int t;
-
-	tokpushback = 0;
-	doprompt = interact;
-	if (doprompt)
-		setprompt(1);
-	else
-		setprompt(0);
-	needprompt = 0;
-	t = readtoken();
-	if (t == TEOF)
-		return NEOF;
-	if (t == TNL)
-		return NULL;
-	tokpushback++;
-	return list(1);
-}
-
-
-STATIC union node *
-list(int nlflag)
-{
-	union node *n1, *n2, *n3;
-	int tok;
-
-	checkkwd = 2;
-	if (nlflag == 0 && tokendlist[peektoken()])
-		return NULL;
-	n1 = NULL;
-	for (;;) {
-		n2 = andor();
-		tok = readtoken();
-		if (tok == TBACKGND) {
-			if (n2->type == NCMD || n2->type == NPIPE) {
-				n2->ncmd.backgnd = 1;
-			} else if (n2->type == NREDIR) {
-				n2->type = NBACKGND;
-			} else {
-				n3 = (union node *)stalloc(sizeof (struct nredir));
-				n3->type = NBACKGND;
-				n3->nredir.n = n2;
-				n3->nredir.redirect = NULL;
-				n2 = n3;
-			}
-		}
-		if (n1 == NULL) {
-			n1 = n2;
-		}
-		else {
-			n3 = (union node *)stalloc(sizeof (struct nbinary));
-			n3->type = NSEMI;
-			n3->nbinary.ch1 = n1;
-			n3->nbinary.ch2 = n2;
-			n1 = n3;
-		}
-		switch (tok) {
-		case TBACKGND:
-		case TSEMI:
-			tok = readtoken();
-			/* fall through */
-		case TNL:
-			if (tok == TNL) {
-				parseheredoc();
-				if (nlflag)
-					return n1;
-			} else {
-				tokpushback++;
-			}
-			checkkwd = 2;
-			if (tokendlist[peektoken()])
-				return n1;
-			break;
-		case TEOF:
-			if (heredoclist)
-				parseheredoc();
-			else
-				pungetc();		/* push back EOF on input */
-			return n1;
-		default:
-			if (nlflag)
-				synexpect(-1);
-			tokpushback++;
-			return n1;
-		}
-	}
-}
-
-
-
-STATIC union node *
-andor(void)
-{
-	union node *n1, *n2, *n3;
-	int t;
-
-	n1 = pipeline();
-	for (;;) {
-		if ((t = readtoken()) == TAND) {
-			t = NAND;
-		} else if (t == TOR) {
-			t = NOR;
-		} else {
-			tokpushback++;
-			return n1;
-		}
-		n2 = pipeline();
-		n3 = (union node *)stalloc(sizeof (struct nbinary));
-		n3->type = t;
-		n3->nbinary.ch1 = n1;
-		n3->nbinary.ch2 = n2;
-		n1 = n3;
-	}
-}
-
-
-
-STATIC union node *
-pipeline(void)
-{
-	union node *n1, *n2, *pipenode;
-	struct nodelist *lp, *prev;
-	int negate;
-
-	negate = 0;
-	TRACE(("pipeline: entered\n"));
-	while (readtoken() == TNOT)
-		negate = !negate;
-	tokpushback++;
-	n1 = command();
-	if (readtoken() == TPIPE) {
-		pipenode = (union node *)stalloc(sizeof (struct npipe));
-		pipenode->type = NPIPE;
-		pipenode->npipe.backgnd = 0;
-		lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
-		pipenode->npipe.cmdlist = lp;
-		lp->n = n1;
-		do {
-			prev = lp;
-			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
-			lp->n = command();
-			prev->next = lp;
-		} while (readtoken() == TPIPE);
-		lp->next = NULL;
-		n1 = pipenode;
-	}
-	tokpushback++;
-	if (negate) {
-		n2 = (union node *)stalloc(sizeof (struct nnot));
-		n2->type = NNOT;
-		n2->nnot.com = n1;
-		return n2;
-	} else
-		return n1;
-}
-
-
-
-STATIC union node *
-command(void)
-{
-	union node *n1, *n2;
-	union node *ap, **app;
-	union node *cp, **cpp;
-	union node *redir, **rpp;
-	int t, negate = 0;
-
-	checkkwd = 2;
-	redir = NULL;
-	n1 = NULL;
-	rpp = &redir;
-
-	/* Check for redirection which may precede command */
-	while (readtoken() == TREDIR) {
-		*rpp = n2 = redirnode;
-		rpp = &n2->nfile.next;
-		parsefname();
-	}
-	tokpushback++;
-
-	while (readtoken() == TNOT) {
-		TRACE(("command: TNOT recognized\n"));
-		negate = !negate;
-	}
-	tokpushback++;
-
-	switch (readtoken()) {
-	case TIF:
-		n1 = (union node *)stalloc(sizeof (struct nif));
-		n1->type = NIF;
-		n1->nif.test = list(0);
-		if (readtoken() != TTHEN)
-			synexpect(TTHEN);
-		n1->nif.ifpart = list(0);
-		n2 = n1;
-		while (readtoken() == TELIF) {
-			n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
-			n2 = n2->nif.elsepart;
-			n2->type = NIF;
-			n2->nif.test = list(0);
-			if (readtoken() != TTHEN)
-				synexpect(TTHEN);
-			n2->nif.ifpart = list(0);
-		}
-		if (lasttoken == TELSE)
-			n2->nif.elsepart = list(0);
-		else {
-			n2->nif.elsepart = NULL;
-			tokpushback++;
-		}
-		if (readtoken() != TFI)
-			synexpect(TFI);
-		checkkwd = 1;
-		break;
-	case TWHILE:
-	case TUNTIL: {
-		int got;
-		n1 = (union node *)stalloc(sizeof (struct nbinary));
-		n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
-		n1->nbinary.ch1 = list(0);
-		if ((got=readtoken()) != TDO) {
-TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
-			synexpect(TDO);
-		}
-		n1->nbinary.ch2 = list(0);
-		if (readtoken() != TDONE)
-			synexpect(TDONE);
-		checkkwd = 1;
-		break;
-	}
-	case TFOR:
-		if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
-			synerror("Bad for loop variable");
-		n1 = (union node *)stalloc(sizeof (struct nfor));
-		n1->type = NFOR;
-		n1->nfor.var = wordtext;
-		if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) {
-			app = &ap;
-			while (readtoken() == TWORD) {
-				n2 = (union node *)stalloc(sizeof (struct narg));
-				n2->type = NARG;
-				n2->narg.text = wordtext;
-				n2->narg.backquote = backquotelist;
-				*app = n2;
-				app = &n2->narg.next;
-			}
-			*app = NULL;
-			n1->nfor.args = ap;
-			if (lasttoken != TNL && lasttoken != TSEMI)
-				synexpect(-1);
-		} else {
-			static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
-								   '@', '=', '\0'};
-			n2 = (union node *)stalloc(sizeof (struct narg));
-			n2->type = NARG;
-			n2->narg.text = argvars;
-			n2->narg.backquote = NULL;
-			n2->narg.next = NULL;
-			n1->nfor.args = n2;
-			/*
-			 * Newline or semicolon here is optional (but note
-			 * that the original Bourne shell only allowed NL).
-			 */
-			if (lasttoken != TNL && lasttoken != TSEMI)
-				tokpushback++;
-		}
-		checkkwd = 2;
-		if ((t = readtoken()) == TDO)
-			t = TDONE;
-		else if (t == TBEGIN)
-			t = TEND;
-		else
-			synexpect(-1);
-		n1->nfor.body = list(0);
-		if (readtoken() != t)
-			synexpect(t);
-		checkkwd = 1;
-		break;
-	case TCASE:
-		n1 = (union node *)stalloc(sizeof (struct ncase));
-		n1->type = NCASE;
-		if (readtoken() != TWORD)
-			synexpect(TWORD);
-		n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
-		n2->type = NARG;
-		n2->narg.text = wordtext;
-		n2->narg.backquote = backquotelist;
-		n2->narg.next = NULL;
-		while (readtoken() == TNL);
-		if (lasttoken != TWORD || ! equal(wordtext, "in"))
-			synerror("expecting \"in\"");
-		cpp = &n1->ncase.cases;
-		noalias = 1;
-		checkkwd = 2, readtoken();
-		do {
-			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
-			cp->type = NCLIST;
-			app = &cp->nclist.pattern;
-			for (;;) {
-				*app = ap = (union node *)stalloc(sizeof (struct narg));
-				ap->type = NARG;
-				ap->narg.text = wordtext;
-				ap->narg.backquote = backquotelist;
-				if (checkkwd = 2, readtoken() != TPIPE)
-					break;
-				app = &ap->narg.next;
-				readtoken();
-			}
-			ap->narg.next = NULL;
-			noalias = 0;
-			if (lasttoken != TRP) {
-				synexpect(TRP);
-			}
-			cp->nclist.body = list(0);
-
-			checkkwd = 2;
-			if ((t = readtoken()) != TESAC) {
-				if (t != TENDCASE) {
-					noalias = 0;
-					synexpect(TENDCASE);
-				} else {
-					noalias = 1;
-					checkkwd = 2;
-					readtoken();
-				}
-			}
-			cpp = &cp->nclist.next;
-		} while(lasttoken != TESAC);
-		noalias = 0;
-		*cpp = NULL;
-		checkkwd = 1;
-		break;
-	case TLP:
-		n1 = (union node *)stalloc(sizeof (struct nredir));
-		n1->type = NSUBSHELL;
-		n1->nredir.n = list(0);
-		n1->nredir.redirect = NULL;
-		if (readtoken() != TRP)
-			synexpect(TRP);
-		checkkwd = 1;
-		break;
-	case TBEGIN:
-		n1 = list(0);
-		if (readtoken() != TEND)
-			synexpect(TEND);
-		checkkwd = 1;
-		break;
-	/* Handle an empty command like other simple commands.  */
-	case TSEMI:
-		/*
-		 * An empty command before a ; doesn't make much sense, and
-		 * should certainly be disallowed in the case of `if ;'.
-		 */
-		if (!redir)
-			synexpect(-1);
-	case TAND:
-	case TOR:
-	case TNL:
-	case TEOF:
-	case TWORD:
-	case TRP:
-		tokpushback++;
-		n1 = simplecmd(rpp, redir);
-		goto checkneg;
-	default:
-		synexpect(-1);
-		/* NOTREACHED */
-	}
-
-	/* Now check for redirection which may follow command */
-	while (readtoken() == TREDIR) {
-		*rpp = n2 = redirnode;
-		rpp = &n2->nfile.next;
-		parsefname();
-	}
-	tokpushback++;
-	*rpp = NULL;
-	if (redir) {
-		if (n1->type != NSUBSHELL) {
-			n2 = (union node *)stalloc(sizeof (struct nredir));
-			n2->type = NREDIR;
-			n2->nredir.n = n1;
-			n1 = n2;
-		}
-		n1->nredir.redirect = redir;
-	}
-
-checkneg:
-	if (negate) {
-		n2 = (union node *)stalloc(sizeof (struct nnot));
-		n2->type = NNOT;
-		n2->nnot.com = n1;
-		return n2;
-	}
-	else
-		return n1;
-}
-
-
-STATIC union node *
-simplecmd(union node **rpp, union node *redir)
-{
-	union node *args, **app;
-	union node **orig_rpp = rpp;
-	union node *n = NULL, *n2;
-	int negate = 0;
-
-	/* If we don't have any redirections already, then we must reset */
-	/* rpp to be the address of the local redir variable.  */
-	if (redir == 0)
-		rpp = &redir;
-
-	args = NULL;
-	app = &args;
-	/*
-	 * We save the incoming value, because we need this for shell
-	 * functions.  There can not be a redirect or an argument between
-	 * the function name and the open parenthesis.
-	 */
-	orig_rpp = rpp;
-
-	while (readtoken() == TNOT) {
-		TRACE(("command: TNOT recognized\n"));
-		negate = !negate;
-	}
-	tokpushback++;
-
-	for (;;) {
-		if (readtoken() == TWORD) {
-			n = (union node *)stalloc(sizeof (struct narg));
-			n->type = NARG;
-			n->narg.text = wordtext;
-			n->narg.backquote = backquotelist;
-			*app = n;
-			app = &n->narg.next;
-		} else if (lasttoken == TREDIR) {
-			*rpp = n = redirnode;
-			rpp = &n->nfile.next;
-			parsefname();	/* read name of redirection file */
-		} else if (lasttoken == TLP && app == &args->narg.next
-					    && rpp == orig_rpp) {
-			/* We have a function */
-			if (readtoken() != TRP)
-				synexpect(TRP);
-#ifdef notdef
-			if (! goodname(n->narg.text))
-				synerror("Bad function name");
-#endif
-			n->type = NDEFUN;
-			n->narg.next = command();
-			goto checkneg;
-		} else {
-			tokpushback++;
-			break;
-		}
-	}
-	*app = NULL;
-	*rpp = NULL;
-	n = (union node *)stalloc(sizeof (struct ncmd));
-	n->type = NCMD;
-	n->ncmd.backgnd = 0;
-	n->ncmd.args = args;
-	n->ncmd.redirect = redir;
-
-checkneg:
-	if (negate) {
-		n2 = (union node *)stalloc(sizeof (struct nnot));
-		n2->type = NNOT;
-		n2->nnot.com = n;
-		return n2;
-	}
-	else
-		return n;
-}
-
-STATIC union node *
-makename(void)
-{
-	union node *n;
-
-	n = (union node *)stalloc(sizeof (struct narg));
-	n->type = NARG;
-	n->narg.next = NULL;
-	n->narg.text = wordtext;
-	n->narg.backquote = backquotelist;
-	return n;
-}
-
-void fixredir(union node *n, const char *text, int err)
-	{
-	TRACE(("Fix redir %s %d\n", text, err));
-	if (!err)
-		n->ndup.vname = NULL;
-
-	if (is_digit(text[0]) && text[1] == '\0')
-		n->ndup.dupfd = digit_val(text[0]);
-	else if (text[0] == '-' && text[1] == '\0')
-		n->ndup.dupfd = -1;
-	else {
-
-		if (err)
-			synerror("Bad fd number");
-		else
-			n->ndup.vname = makename();
-	}
-}
-
-
-STATIC void
-parsefname(void)
-{
-	union node *n = redirnode;
-
-	if (readtoken() != TWORD)
-		synexpect(-1);
-	if (n->type == NHERE) {
-		struct heredoc *here = heredoc;
-		struct heredoc *p;
-		int i;
-
-		if (quoteflag == 0)
-			n->type = NXHERE;
-		TRACE(("Here document %d\n", n->type));
-		if (here->striptabs) {
-			while (*wordtext == '\t')
-				wordtext++;
-		}
-		if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
-			synerror("Illegal eof marker for << redirection");
-		rmescapes(wordtext);
-		here->eofmark = wordtext;
-		here->next = NULL;
-		if (heredoclist == NULL)
-			heredoclist = here;
-		else {
-			for (p = heredoclist ; p->next ; p = p->next);
-			p->next = here;
-		}
-	} else if (n->type == NTOFD || n->type == NFROMFD) {
-		fixredir(n, wordtext, 0);
-	} else {
-		n->nfile.fname = makename();
-	}
-}
-
-
-/*
- * Input any here documents.
- */
-
-STATIC void
-parseheredoc(void)
-{
-	struct heredoc *here;
-	union node *n;
-
-	while (heredoclist) {
-		here = heredoclist;
-		heredoclist = here->next;
-		if (needprompt) {
-			setprompt(2);
-			needprompt = 0;
-		}
-		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
-				here->eofmark, here->striptabs);
-		n = (union node *)stalloc(sizeof (struct narg));
-		n->narg.type = NARG;
-		n->narg.next = NULL;
-		n->narg.text = wordtext;
-		n->narg.backquote = backquotelist;
-		here->here->nhere.doc = n;
-	}
-}
-
-STATIC int
-peektoken(void)
-{
-	int t;
-
-	t = readtoken();
-	tokpushback++;
-	return (t);
-}
-
-STATIC int
-readtoken(void)
-{
-	int t;
-	int savecheckkwd = checkkwd;
-#ifdef DEBUG
-	int alreadyseen = tokpushback;
-#endif
-	struct alias *ap;
-
-	top:
-	t = xxreadtoken();
-
-	if (checkkwd) {
-		/*
-		 * eat newlines
-		 */
-		if (checkkwd == 2) {
-			checkkwd = 0;
-			while (t == TNL) {
-				parseheredoc();
-				t = xxreadtoken();
-			}
-		} else
-			checkkwd = 0;
-		/*
-		 * check for keywords and aliases
-		 */
-		if (t == TWORD && !quoteflag)
-		{
-			const char *const *pp;
-
-			for (pp = parsekwd; *pp; pp++) {
-				if (**pp == *wordtext && equal(*pp, wordtext))
-				{
-					lasttoken = t = pp - 
-					    parsekwd + KWDOFFSET;
-					TRACE(("keyword %s recognized\n", tokname[t]));
-					goto out;
-				}
-			}
-			if(!noalias &&
-			    (ap = lookupalias(wordtext, 1)) != NULL) {
-				pushstring(ap->val, strlen(ap->val), ap);
-				checkkwd = savecheckkwd;
-				goto top;
-			}
-		}
-out:
-		checkkwd = (t == TNOT) ? savecheckkwd : 0;
-	}
-#ifdef DEBUG
-	if (!alreadyseen)
-	    TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
-	else
-	    TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
-#endif
-	return (t);
-}
-
-
-/*
- * Read the next input token.
- * If the token is a word, we set backquotelist to the list of cmds in
- *	backquotes.  We set quoteflag to true if any part of the word was
- *	quoted.
- * If the token is TREDIR, then we set redirnode to a structure containing
- *	the redirection.
- * In all cases, the variable startlinno is set to the number of the line
- *	on which the token starts.
- *
- * [Change comment:  here documents and internal procedures]
- * [Readtoken shouldn't have any arguments.  Perhaps we should make the
- *  word parsing code into a separate routine.  In this case, readtoken
- *  doesn't need to have any internal procedures, but parseword does.
- *  We could also make parseoperator in essence the main routine, and
- *  have parseword (readtoken1?) handle both words and redirection.]
- */
-
-#define RETURN(token)	return lasttoken = token
-
-STATIC int
-xxreadtoken(void)
-{
-	int c;
-
-	if (tokpushback) {
-		tokpushback = 0;
-		return lasttoken;
-	}
-	if (needprompt) {
-		setprompt(2);
-		needprompt = 0;
-	}
-	startlinno = plinno;
-	for (;;) {	/* until token or start of word found */
-		c = pgetc_macro();
-		if (c == ' ' || c == '\t')
-			continue;		/* quick check for white space first */
-		switch (c) {
-		case ' ': case '\t':
-			continue;
-		case '#':
-			while ((c = pgetc()) != '\n' && c != PEOF);
-			pungetc();
-			continue;
-		case '\\':
-			if (pgetc() == '\n') {
-				startlinno = ++plinno;
-				if (doprompt)
-					setprompt(2);
-				else
-					setprompt(0);
-				continue;
-			}
-			pungetc();
-			goto breakloop;
-		case '\n':
-			plinno++;
-			needprompt = doprompt;
-			RETURN(TNL);
-		case PEOF:
-			RETURN(TEOF);
-		case '&':
-			if (pgetc() == '&')
-				RETURN(TAND);
-			pungetc();
-			RETURN(TBACKGND);
-		case '|':
-			if (pgetc() == '|')
-				RETURN(TOR);
-			pungetc();
-			RETURN(TPIPE);
-		case ';':
-			if (pgetc() == ';')
-				RETURN(TENDCASE);
-			pungetc();
-			RETURN(TSEMI);
-		case '(':
-			RETURN(TLP);
-		case ')':
-			RETURN(TRP);
-		default:
-			goto breakloop;
-		}
-	}
-breakloop:
-	return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
-#undef RETURN
-}
-
-
-
-/*
- * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
- * is not NULL, read a here document.  In the latter case, eofmark is the
- * word which marks the end of the document and striptabs is true if
- * leading tabs should be stripped from the document.  The argument firstc
- * is the first character of the input token or document.
- *
- * Because C does not have internal subroutines, I have simulated them
- * using goto's to implement the subroutine linkage.  The following macros
- * will run code that appears at the end of readtoken1.
- */
-
-#define CHECKEND()	{goto checkend; checkend_return:;}
-#define PARSEREDIR()	{goto parseredir; parseredir_return:;}
-#define PARSESUB()	{goto parsesub; parsesub_return:;}
-#define PARSEBACKQOLD()	{oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
-#define PARSEBACKQNEW()	{oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
-#define	PARSEARITH()	{goto parsearith; parsearith_return:;}
-
-/*
- * Keep track of nested doublequotes in dblquote and doublequotep.
- * We use dblquote for the first 32 levels, and we expand to a malloc'ed
- * region for levels above that. Usually we never need to malloc.
- * This code assumes that an int is 32 bits. We don't use uint32_t,
- * because the rest of the code does not.
- */
-#define ISDBLQUOTE() ((varnest < 32) ? (dblquote & (1 << varnest)) : \
-    (dblquotep[(varnest / 32) - 1] & (1 << (varnest % 32))))
-
-#define SETDBLQUOTE() \
-    if (varnest < 32) \
-	dblquote |= (1 << varnest); \
-    else \
-	dblquotep[(varnest / 32) - 1] |= (1 << (varnest % 32))
-
-#define CLRDBLQUOTE() \
-    if (varnest < 32) \
-	dblquote &= ~(1 << varnest); \
-    else \
-	dblquotep[(varnest / 32) - 1] &= ~(1 << (varnest % 32))
-
-STATIC int
-readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
-{
-	int c = firstc;
-	char *out;
-	int len;
-	char line[EOFMARKLEN + 1];
-	struct nodelist *bqlist;
-	int quotef;
-	int *dblquotep = NULL;
-	size_t maxnest = 32;
-	int dblquote;
-	int varnest;	/* levels of variables expansion */
-	int arinest;	/* levels of arithmetic expansion */
-	int parenlevel;	/* levels of parens in arithmetic */
-	int oldstyle;
-	char const *prevsyntax = NULL;	/* syntax before arithmetic */
-#if __GNUC__
-	/* Avoid longjmp clobbering */
-	(void) &maxnest;
-	(void) &dblquotep;
-	(void) &out;
-	(void) &quotef;
-	(void) &dblquote;
-	(void) &varnest;
-	(void) &arinest;
-	(void) &parenlevel;
-	(void) &oldstyle;
-	(void) &prevsyntax;
-	(void) &syntax;
-#endif
-
-	startlinno = plinno;
-	dblquote = 0;
-	varnest = 0;
-	if (syntax == DQSYNTAX) {
-		SETDBLQUOTE();
-	}
-	quotef = 0;
-	bqlist = NULL;
-	arinest = 0;
-	parenlevel = 0;
-
-	STARTSTACKSTR(out);
-	loop: {	/* for each line, until end of word */
-#if ATTY
-		if (c == '\034' && doprompt
-		 && attyset() && ! equal(termval(), "emacs")) {
-			attyline();
-			if (syntax == BASESYNTAX)
-				return readtoken();
-			c = pgetc();
-			goto loop;
-		}
-#endif
-		CHECKEND();	/* set c to PEOF if at end of here document */
-		for (;;) {	/* until end of line or end of word */
-			CHECKSTRSPACE(4, out);	/* permit 4 calls to USTPUTC */
-			switch(syntax[c]) {
-			case CNL:	/* '\n' */
-				if (syntax == BASESYNTAX)
-					goto endword;	/* exit outer loop */
-				USTPUTC(c, out);
-				plinno++;
-				if (doprompt)
-					setprompt(2);
-				else
-					setprompt(0);
-				c = pgetc();
-				goto loop;		/* continue outer loop */
-			case CWORD:
-				USTPUTC(c, out);
-				break;
-			case CCTL:
-				if (eofmark == NULL || ISDBLQUOTE())
-					USTPUTC(CTLESC, out);
-				USTPUTC(c, out);
-				break;
-			case CBACK:	/* backslash */
-				c = pgetc();
-				if (c == PEOF) {
-					USTPUTC('\\', out);
-					pungetc();
-					break;
-				}
-				if (c == '\n') {
-					if (doprompt)
-						setprompt(2);
-					else
-						setprompt(0);
-					break;
-				}
-				quotef = 1;
-				if (ISDBLQUOTE() && c != '\\' &&
-				    c != '`' && c != '$' &&
-				    (c != '"' || eofmark != NULL))
-					USTPUTC('\\', out);
-				if (SQSYNTAX[c] == CCTL)
-					USTPUTC(CTLESC, out);
-				else if (eofmark == NULL) {
-					USTPUTC(CTLQUOTEMARK, out);
-					USTPUTC(c, out);
-					if (varnest != 0)
-						USTPUTC(CTLQUOTEEND, out);
-					break;
-				}
-				USTPUTC(c, out);
-				break;
-			case CSQUOTE:
-				if (syntax != SQSYNTAX) {
-					if (eofmark == NULL)
-						USTPUTC(CTLQUOTEMARK, out);
-					quotef = 1;
-					syntax = SQSYNTAX;
-					break;
-				}
-				if (eofmark != NULL && arinest == 0 &&
-				    varnest == 0) {
-					/* Ignore inside quoted here document */
-					USTPUTC(c, out);
-					break;
-				}
-				/* End of single quotes... */
-				if (arinest)
-					syntax = ARISYNTAX;
-				else {
-					syntax = BASESYNTAX;
-					if (varnest != 0)
-						USTPUTC(CTLQUOTEEND, out);
-				}
-				break;
-			case CDQUOTE:
-				if (eofmark != NULL && arinest == 0 &&
-				    varnest == 0) {
-					/* Ignore inside here document */
-					USTPUTC(c, out);
-					break;
-				}
-				quotef = 1;
-				if (arinest) {
-					if (ISDBLQUOTE()) {
-						syntax = ARISYNTAX;
-						CLRDBLQUOTE();
-					} else {
-						syntax = DQSYNTAX;
-						SETDBLQUOTE();
-						USTPUTC(CTLQUOTEMARK, out);
-					}
-					break;
-				}
-				if (eofmark != NULL)
-					break;
-				if (ISDBLQUOTE()) {
-					if (varnest != 0)
-						USTPUTC(CTLQUOTEEND, out);
-					syntax = BASESYNTAX;
-					CLRDBLQUOTE();
-				} else {
-					syntax = DQSYNTAX;
-					SETDBLQUOTE();
-					USTPUTC(CTLQUOTEMARK, out);
-				}
-				break;
-			case CVAR:	/* '$' */
-				PARSESUB();		/* parse substitution */
-				break;
-			case CENDVAR:	/* CLOSEBRACE */
-				if (varnest > 0 && !ISDBLQUOTE()) {
-					varnest--;
-					USTPUTC(CTLENDVAR, out);
-				} else {
-					USTPUTC(c, out);
-				}
-				break;
-			case CLP:	/* '(' in arithmetic */
-				parenlevel++;
-				USTPUTC(c, out);
-				break;
-			case CRP:	/* ')' in arithmetic */
-				if (parenlevel > 0) {
-					USTPUTC(c, out);
-					--parenlevel;
-				} else {
-					if (pgetc() == ')') {
-						if (--arinest == 0) {
-							USTPUTC(CTLENDARI, out);
-							syntax = prevsyntax;
-							if (syntax == DQSYNTAX)
-								SETDBLQUOTE();
-							else
-								CLRDBLQUOTE();
-						} else
-							USTPUTC(')', out);
-					} else {
-						/*
-						 * unbalanced parens
-						 *  (don't 2nd guess - no error)
-						 */
-						pungetc();
-						USTPUTC(')', out);
-					}
-				}
-				break;
-			case CBQUOTE:	/* '`' */
-				PARSEBACKQOLD();
-				break;
-			case CEOF:
-				goto endword;		/* exit outer loop */
-			default:
-				if (varnest == 0)
-					goto endword;	/* exit outer loop */
-				USTPUTC(c, out);
-			}
-			c = pgetc_macro();
-		}
-	}
-endword:
-	if (syntax == ARISYNTAX)
-		synerror("Missing '))'");
-	if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
-		synerror("Unterminated quoted string");
-	if (varnest != 0) {
-		startlinno = plinno;
-		/* { */
-		synerror("Missing '}'");
-	}
-	USTPUTC('\0', out);
-	len = out - stackblock();
-	out = stackblock();
-	if (eofmark == NULL) {
-		if ((c == '>' || c == '<')
-		 && quotef == 0
-		 && len <= 2
-		 && (*out == '\0' || is_digit(*out))) {
-			PARSEREDIR();
-			return lasttoken = TREDIR;
-		} else {
-			pungetc();
-		}
-	}
-	quoteflag = quotef;
-	backquotelist = bqlist;
-	grabstackblock(len);
-	wordtext = out;
-	if (dblquotep != NULL)
-	    ckfree(dblquotep);
-	return lasttoken = TWORD;
-/* end of readtoken routine */
-
-
-
-/*
- * Check to see whether we are at the end of the here document.  When this
- * is called, c is set to the first character of the next input line.  If
- * we are at the end of the here document, this routine sets the c to PEOF.
- */
-
-checkend: {
-	if (eofmark) {
-		if (striptabs) {
-			while (c == '\t')
-				c = pgetc();
-		}
-		if (c == *eofmark) {
-			if (pfgets(line, sizeof line) != NULL) {
-				char *p, *q;
-
-				p = line;
-				for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
-				if (*p == '\n' && *q == '\0') {
-					c = PEOF;
-					plinno++;
-					needprompt = doprompt;
-				} else {
-					pushstring(line, strlen(line), NULL);
-				}
-			}
-		}
-	}
-	goto checkend_return;
-}
-
-
-/*
- * Parse a redirection operator.  The variable "out" points to a string
- * specifying the fd to be redirected.  The variable "c" contains the
- * first character of the redirection operator.
- */
-
-parseredir: {
-	char fd = *out;
-	union node *np;
-
-	np = (union node *)stalloc(sizeof (struct nfile));
-	if (c == '>') {
-		np->nfile.fd = 1;
-		c = pgetc();
-		if (c == '>')
-			np->type = NAPPEND;
-		else if (c == '|')
-			np->type = NCLOBBER;
-		else if (c == '&')
-			np->type = NTOFD;
-		else {
-			np->type = NTO;
-			pungetc();
-		}
-	} else {	/* c == '<' */
-		np->nfile.fd = 0;
-		switch (c = pgetc()) {
-		case '<':
-			if (sizeof (struct nfile) != sizeof (struct nhere)) {
-				np = (union node *)stalloc(sizeof (struct nhere));
-				np->nfile.fd = 0;
-			}
-			np->type = NHERE;
-			heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
-			heredoc->here = np;
-			if ((c = pgetc()) == '-') {
-				heredoc->striptabs = 1;
-			} else {
-				heredoc->striptabs = 0;
-				pungetc();
-			}
-			break;
-
-		case '&':
-			np->type = NFROMFD;
-			break;
-
-		case '>':
-			np->type = NFROMTO;
-			break;
-
-		default:
-			np->type = NFROM;
-			pungetc();
-			break;
-		}
-	}
-	if (fd != '\0')
-		np->nfile.fd = digit_val(fd);
-	redirnode = np;
-	goto parseredir_return;
-}
-
-
-/*
- * Parse a substitution.  At this point, we have read the dollar sign
- * and nothing else.
- */
-
-parsesub: {
-	int subtype;
-	int typeloc;
-	int flags;
-	char *p;
-	static const char types[] = "}-+?=";
-
-	c = pgetc();
-	if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) {
-		USTPUTC('$', out);
-		pungetc();
-	} else if (c == '(') {	/* $(command) or $((arith)) */
-		if (pgetc() == '(') {
-			PARSEARITH();
-		} else {
-			pungetc();
-			PARSEBACKQNEW();
-		}
-	} else {
-		USTPUTC(CTLVAR, out);
-		typeloc = out - stackblock();
-		USTPUTC(VSNORMAL, out);
-		subtype = VSNORMAL;
-		if (c == OPENBRACE) {
-			c = pgetc();
-			if (c == '#') {
-				if ((c = pgetc()) == CLOSEBRACE)
-					c = '#';
-				else
-					subtype = VSLENGTH;
-			}
-			else
-				subtype = 0;
-		}
-		if (is_name(c)) {
-			do {
-				STPUTC(c, out);
-				c = pgetc();
-			} while (is_in_name(c));
-		} else if (is_digit(c)) {
-			do {
-				USTPUTC(c, out);
-				c = pgetc();
-			} while (is_digit(c));
-		}
-		else if (is_special(c)) {
-			USTPUTC(c, out);
-			c = pgetc();
-		}
-		else
-badsub:			synerror("Bad substitution");
-
-		STPUTC('=', out);
-		flags = 0;
-		if (subtype == 0) {
-			switch (c) {
-			case ':':
-				flags = VSNUL;
-				c = pgetc();
-				/*FALLTHROUGH*/
-			default:
-				p = strchr(types, c);
-				if (p == NULL)
-					goto badsub;
-				subtype = p - types + VSNORMAL;
-				break;
-			case '%':
-			case '#':
-				{
-					int cc = c;
-					subtype = c == '#' ? VSTRIMLEFT :
-							     VSTRIMRIGHT;
-					c = pgetc();
-					if (c == cc)
-						subtype++;
-					else
-						pungetc();
-					break;
-				}
-			}
-		} else {
-			pungetc();
-		}
-		if (ISDBLQUOTE() || arinest)
-			flags |= VSQUOTE;
-		*(stackblock() + typeloc) = subtype | flags;
-		if (subtype != VSNORMAL) {
-			varnest++;
-			if (varnest >= maxnest) {
-				dblquotep = ckrealloc(dblquotep, maxnest / 8);
-				dblquotep[(maxnest / 32) - 1] = 0;
-				maxnest += 32;
-			}
-		}
-	}
-	goto parsesub_return;
-}
-
-
-/*
- * Called to parse command substitutions.  Newstyle is set if the command
- * is enclosed inside $(...); nlpp is a pointer to the head of the linked
- * list of commands (passed by reference), and savelen is the number of
- * characters on the top of the stack which must be preserved.
- */
-
-parsebackq: {
-	struct nodelist **nlpp;
-	int savepbq;
-	union node *n;
-	char *volatile str;
-	struct jmploc jmploc;
-	struct jmploc *volatile savehandler;
-	int savelen;
-	int saveprompt;
-#ifdef __GNUC__
-	(void) &saveprompt;
-#endif
-
-	savepbq = parsebackquote;
-	if (setjmp(jmploc.loc)) {
-		if (str)
-			ckfree(str);
-		parsebackquote = 0;
-		handler = savehandler;
-		longjmp(handler->loc, 1);
-	}
-	INTOFF;
-	str = NULL;
-	savelen = out - stackblock();
-	if (savelen > 0) {
-		str = ckmalloc(savelen);
-		memcpy(str, stackblock(), savelen);
-	}
-	savehandler = handler;
-	handler = &jmploc;
-	INTON;
-        if (oldstyle) {
-                /* We must read until the closing backquote, giving special
-                   treatment to some slashes, and then push the string and
-                   reread it as input, interpreting it normally.  */
-                char *pout;
-                int pc;
-                int psavelen;
-                char *pstr;
-
-
-                STARTSTACKSTR(pout);
-		for (;;) {
-			if (needprompt) {
-				setprompt(2);
-				needprompt = 0;
-			}
-			switch (pc = pgetc()) {
-			case '`':
-				goto done;
-
-			case '\\':
-                                if ((pc = pgetc()) == '\n') {
-					plinno++;
-					if (doprompt)
-						setprompt(2);
-					else
-						setprompt(0);
-					/*
-					 * If eating a newline, avoid putting
-					 * the newline into the new character
-					 * stream (via the STPUTC after the
-					 * switch).
-					 */
-					continue;
-				}
-                                if (pc != '\\' && pc != '`' && pc != '$'
-                                    && (!ISDBLQUOTE() || pc != '"'))
-                                        STPUTC('\\', pout);
-				break;
-
-			case '\n':
-				plinno++;
-				needprompt = doprompt;
-				break;
-
-			case PEOF:
-			        startlinno = plinno;
-				synerror("EOF in backquote substitution");
- 				break;
-
-			default:
-				break;
-			}
-			STPUTC(pc, pout);
-                }
-done:
-                STPUTC('\0', pout);
-                psavelen = pout - stackblock();
-                if (psavelen > 0) {
-			pstr = grabstackstr(pout);
-			setinputstring(pstr, 1);
-                }
-        }
-	nlpp = &bqlist;
-	while (*nlpp)
-		nlpp = &(*nlpp)->next;
-	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
-	(*nlpp)->next = NULL;
-	parsebackquote = oldstyle;
-
-	if (oldstyle) {
-		saveprompt = doprompt;
-		doprompt = 0;
-	}
-
-	n = list(0);
-
-	if (oldstyle)
-		doprompt = saveprompt;
-	else {
-		if (readtoken() != TRP)
-			synexpect(TRP);
-	}
-
-	(*nlpp)->n = n;
-        if (oldstyle) {
-		/*
-		 * Start reading from old file again, ignoring any pushed back
-		 * tokens left from the backquote parsing
-		 */
-                popfile();
-		tokpushback = 0;
-	}
-	while (stackblocksize() <= savelen)
-		growstackblock();
-	STARTSTACKSTR(out);
-	if (str) {
-		memcpy(out, str, savelen);
-		STADJUST(savelen, out);
-		INTOFF;
-		ckfree(str);
-		str = NULL;
-		INTON;
-	}
-	parsebackquote = savepbq;
-	handler = savehandler;
-	if (arinest || ISDBLQUOTE())
-		USTPUTC(CTLBACKQ | CTLQUOTE, out);
-	else
-		USTPUTC(CTLBACKQ, out);
-	if (oldstyle)
-		goto parsebackq_oldreturn;
-	else
-		goto parsebackq_newreturn;
-}
-
-/*
- * Parse an arithmetic expansion (indicate start of one and set state)
- */
-parsearith: {
-
-	if (++arinest == 1) {
-		prevsyntax = syntax;
-		syntax = ARISYNTAX;
-		USTPUTC(CTLARI, out);
-		if (ISDBLQUOTE())
-			USTPUTC('"',out);
-		else
-			USTPUTC(' ',out);
-	} else {
-		/*
-		 * we collapse embedded arithmetic expansion to
-		 * parenthesis, which should be equivalent
-		 */
-		USTPUTC('(', out);
-	}
-	goto parsearith_return;
-}
-
-} /* end of readtoken */
-
-
-
-#ifdef mkinit
-RESET {
-	tokpushback = 0;
-	checkkwd = 0;
-}
-#endif
-
-/*
- * Returns true if the text contains nothing to expand (no dollar signs
- * or backquotes).
- */
-
-STATIC int
-noexpand(char *text)
-{
-	char *p;
-	char c;
-
-	p = text;
-	while ((c = *p++) != '\0') {
-		if (c == CTLQUOTEMARK)
-			continue;
-		if (c == CTLESC)
-			p++;
-		else if (BASESYNTAX[(int)c] == CCTL)
-			return 0;
-	}
-	return 1;
-}
-
-
-/*
- * Return true if the argument is a legal variable name (a letter or
- * underscore followed by zero or more letters, underscores, and digits).
- */
-
-int
-goodname(char *name)
-	{
-	char *p;
-
-	p = name;
-	if (! is_name(*p))
-		return 0;
-	while (*++p) {
-		if (! is_in_name(*p))
-			return 0;
-	}
-	return 1;
-}
-
-
-/*
- * Called when an unexpected token is read during the parse.  The argument
- * is the token that is expected, or -1 if more than one type of token can
- * occur at this point.
- */
-
-STATIC void
-synexpect(int token)
-{
-	char msg[64];
-
-	if (token >= 0) {
-		fmtstr(msg, 64, "%s unexpected (expecting %s)",
-			tokname[lasttoken], tokname[token]);
-	} else {
-		fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
-	}
-	synerror(msg);
-	/* NOTREACHED */
-}
-
-
-STATIC void
-synerror(const char *msg)
-{
-	if (commandname)
-		outfmt(&errout, "%s: %d: ", commandname, startlinno);
-	outfmt(&errout, "Syntax error: %s\n", msg);
-	error((char *)NULL);
-	/* NOTREACHED */
-}
-
-STATIC void
-setprompt(int which)
-{
-	whichprompt = which;
-
-#ifdef WITH_HISTORY
-	if (!el)
-#endif
-#ifdef WITH_LINENOISE
-        if (! in_interactive_mode() )
-#endif
-		out2str(getprompt(NULL));
-}
-
-/*
- * called by editline -- any expansions to the prompt
- *    should be added here.
- */
-const char *
-getprompt(void *unused)
-	{
-	switch (whichprompt) {
-	case 0:
-		return "";
-	case 1:
-		return ps1val();
-	case 2:
-		return ps2val();
-	default:
-		return "<internal prompt error>";
-	}
-}
diff --git a/sh/parser.h b/sh/parser.h
deleted file mode 100644
index b343c71..0000000
--- a/sh/parser.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*	$NetBSD: parser.h,v 1.17 2004/06/26 22:09:49 dsl Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)parser.h	8.3 (Berkeley) 5/4/95
- */
-
-/* control characters in argument strings */
-#define CTL_FIRST '\201'	/* first 'special' character */
-#define CTLESC '\201'		/* escape next character */
-#define CTLVAR '\202'		/* variable defn */
-#define CTLENDVAR '\203'
-#define CTLBACKQ '\204'
-#define CTLQUOTE 01		/* ored with CTLBACKQ code if in quotes */
-/*	CTLBACKQ | CTLQUOTE == '\205' */
-#define	CTLARI	'\206'		/* arithmetic expression */
-#define	CTLENDARI '\207'
-#define	CTLQUOTEMARK '\210'
-#define	CTLQUOTEEND '\211'	/* only inside ${...} */
-#define	CTL_LAST '\211'		/* last 'special' character */
-
-/* variable substitution byte (follows CTLVAR) */
-#define VSTYPE	0x0f		/* type of variable substitution */
-#define VSNUL	0x10		/* colon--treat the empty string as unset */
-#define VSQUOTE 0x80		/* inside double quotes--suppress splitting */
-
-/* values of VSTYPE field */
-#define VSNORMAL	0x1		/* normal variable:  $var or ${var} */
-#define VSMINUS		0x2		/* ${var-text} */
-#define VSPLUS		0x3		/* ${var+text} */
-#define VSQUESTION	0x4		/* ${var?message} */
-#define VSASSIGN	0x5		/* ${var=text} */
-#define VSTRIMLEFT	0x6		/* ${var#pattern} */
-#define VSTRIMLEFTMAX	0x7		/* ${var##pattern} */
-#define VSTRIMRIGHT	0x8		/* ${var%pattern} */
-#define VSTRIMRIGHTMAX 	0x9		/* ${var%%pattern} */
-#define VSLENGTH	0xa		/* ${#var} */
-
-
-/*
- * NEOF is returned by parsecmd when it encounters an end of file.  It
- * must be distinct from NULL, so we use the address of a variable that
- * happens to be handy.
- */
-extern int tokpushback;
-#define NEOF ((union node *)&tokpushback)
-extern int whichprompt;		/* 1 == PS1, 2 == PS2 */
-
-
-union node *parsecmd(int);
-void fixredir(union node *, const char *, int);
-int goodname(char *);
-const char *getprompt(void *);
diff --git a/sh/redir.c b/sh/redir.c
deleted file mode 100644
index 5c4c286..0000000
--- a/sh/redir.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/*	$NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)redir.c	8.2 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: redir.c,v 1.29 2004/07/08 03:57:33 christos Exp $");
-#endif
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/param.h>	/* PIPE_BUF */
-#include <signal.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-/*
- * Code for dealing with input/output redirection.
- */
-
-#include "main.h"
-#include "shell.h"
-#include "nodes.h"
-#include "jobs.h"
-#include "options.h"
-#include "expand.h"
-#include "redir.h"
-#include "output.h"
-#include "memalloc.h"
-#include "error.h"
-
-
-#define EMPTY -2		/* marks an unused slot in redirtab */
-#ifndef PIPE_BUF
-# define PIPESIZE 4096		/* amount of buffering in a pipe */
-#else
-# define PIPESIZE PIPE_BUF
-#endif
-
-#define signal bsd_signal
-
-MKINIT
-struct redirtab {
-	struct redirtab *next;
-	short renamed[10];
-};
-
-
-MKINIT struct redirtab *redirlist;
-
-/*
- * We keep track of whether or not fd0 has been redirected.  This is for
- * background commands, where we want to redirect fd0 to /dev/null only
- * if it hasn't already been redirected.
-*/
-int fd0_redirected = 0;
-
-STATIC void openredirect(union node *, char[10], int);
-STATIC int openhere(union node *);
-
-
-/*
- * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
- * old file descriptors are stashed away so that the redirection can be
- * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
- * standard output, and the standard error if it becomes a duplicate of
- * stdout, is saved in memory.
- */
-
-void
-redirect(union node *redir, int flags)
-{
-	union node *n;
-	struct redirtab *sv = NULL;
-	int i;
-	int fd;
-	int try;
-	char memory[10];	/* file descriptors to write to memory */
-
-	for (i = 10 ; --i >= 0 ; )
-		memory[i] = 0;
-	memory[1] = flags & REDIR_BACKQ;
-	if (flags & REDIR_PUSH) {
-		/* We don't have to worry about REDIR_VFORK here, as
-		 * flags & REDIR_PUSH is never true if REDIR_VFORK is set.
-		 */
-		sv = ckmalloc(sizeof (struct redirtab));
-		for (i = 0 ; i < 10 ; i++)
-			sv->renamed[i] = EMPTY;
-		sv->next = redirlist;
-		redirlist = sv;
-	}
-	for (n = redir ; n ; n = n->nfile.next) {
-		fd = n->nfile.fd;
-		try = 0;
-		if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
-		    n->ndup.dupfd == fd)
-			continue; /* redirect from/to same file descriptor */
-
-		if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
-			INTOFF;
-again:
-			if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
-				switch (errno) {
-				case EBADF:
-					if (!try) {
-						openredirect(n, memory, flags);
-						try++;
-						goto again;
-					}
-					/* FALLTHROUGH*/
-				default:
-					INTON;
-					error("%d: %s", fd, strerror(errno));
-					/* NOTREACHED */
-				}
-			}
-			if (!try) {
-				sv->renamed[fd] = i;
-				close(fd);
-			}
-			INTON;
-		} else {
-			close(fd);
-		}
-                if (fd == 0)
-                        fd0_redirected++;
-		if (!try)
-			openredirect(n, memory, flags);
-	}
-	if (memory[1])
-		out1 = &memout;
-	if (memory[2])
-		out2 = &memout;
-}
-
-
-STATIC void
-openredirect(union node *redir, char memory[10], int flags)
-{
-	int fd = redir->nfile.fd;
-	char *fname;
-	int f;
-	int oflags = O_WRONLY|O_CREAT|O_TRUNC, eflags;
-
-	/*
-	 * We suppress interrupts so that we won't leave open file
-	 * descriptors around.  This may not be such a good idea because
-	 * an open of a device or a fifo can block indefinitely.
-	 */
-	INTOFF;
-	memory[fd] = 0;
-	switch (redir->nfile.type) {
-	case NFROM:
-		fname = redir->nfile.expfname;
-		if (flags & REDIR_VFORK)
-			eflags = O_NONBLOCK;
-		else
-			eflags = 0;
-		if ((f = open(fname, O_RDONLY|eflags)) < 0)
-			goto eopen;
-		if (eflags)
-			(void)fcntl(f, F_SETFL, fcntl(f, F_GETFL, 0) & ~eflags);
-		break;
-	case NFROMTO:
-		fname = redir->nfile.expfname;
-		if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
-			goto ecreate;
-		break;
-	case NTO:
-		if (Cflag)
-			oflags |= O_EXCL;
-		/* FALLTHROUGH */
-	case NCLOBBER:
-		fname = redir->nfile.expfname;
-		if ((f = open(fname, oflags, 0666)) < 0)
-			goto ecreate;
-		break;
-	case NAPPEND:
-		fname = redir->nfile.expfname;
-		if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
-			goto ecreate;
-		break;
-	case NTOFD:
-	case NFROMFD:
-		if (redir->ndup.dupfd >= 0) {	/* if not ">&-" */
-			if (memory[redir->ndup.dupfd])
-				memory[fd] = 1;
-			else
-				copyfd(redir->ndup.dupfd, fd);
-		}
-		INTON;
-		return;
-	case NHERE:
-	case NXHERE:
-		f = openhere(redir);
-		break;
-	default:
-		abort();
-	}
-
-	if (f != fd) {
-		copyfd(f, fd);
-		close(f);
-	}
-	INTON;
-	return;
-ecreate:
-	error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
-eopen:
-	error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
-}
-
-
-/*
- * Handle here documents.  Normally we fork off a process to write the
- * data to a pipe.  If the document is short, we can stuff the data in
- * the pipe without forking.
- */
-
-STATIC int
-openhere(union node *redir)
-{
-	int pip[2];
-	int len = 0;
-
-	if (pipe(pip) < 0)
-		error("Pipe call failed");
-	if (redir->type == NHERE) {
-		len = strlen(redir->nhere.doc->narg.text);
-		if (len <= PIPESIZE) {
-			xwrite(pip[1], redir->nhere.doc->narg.text, len);
-			goto out;
-		}
-	}
-	if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
-		close(pip[0]);
-		signal(SIGINT, SIG_IGN);
-		signal(SIGQUIT, SIG_IGN);
-		signal(SIGHUP, SIG_IGN);
-#ifdef SIGTSTP
-		signal(SIGTSTP, SIG_IGN);
-#endif
-		signal(SIGPIPE, SIG_DFL);
-		if (redir->type == NHERE)
-			xwrite(pip[1], redir->nhere.doc->narg.text, len);
-		else
-			expandhere(redir->nhere.doc, pip[1]);
-		_exit(0);
-	}
-out:
-	close(pip[1]);
-	return pip[0];
-}
-
-
-
-/*
- * Undo the effects of the last redirection.
- */
-
-void
-popredir(void)
-{
-	struct redirtab *rp = redirlist;
-	int i;
-
-	for (i = 0 ; i < 10 ; i++) {
-		if (rp->renamed[i] != EMPTY) {
-                        if (i == 0)
-                                fd0_redirected--;
-			close(i);
-			if (rp->renamed[i] >= 0) {
-				copyfd(rp->renamed[i], i);
-				close(rp->renamed[i]);
-			}
-		}
-	}
-	INTOFF;
-	redirlist = rp->next;
-	ckfree(rp);
-	INTON;
-}
-
-/*
- * Undo all redirections.  Called on error or interrupt.
- */
-
-#ifdef mkinit
-
-INCLUDE "redir.h"
-
-RESET {
-	while (redirlist)
-		popredir();
-}
-
-SHELLPROC {
-	clearredir(0);
-}
-
-#endif
-
-/* Return true if fd 0 has already been redirected at least once.  */
-int
-fd0_redirected_p () {
-        return fd0_redirected != 0;
-}
-
-/*
- * Discard all saved file descriptors.
- */
-
-void
-clearredir(vforked)
-	int vforked;
-{
-	struct redirtab *rp;
-	int i;
-
-	for (rp = redirlist ; rp ; rp = rp->next) {
-		for (i = 0 ; i < 10 ; i++) {
-			if (rp->renamed[i] >= 0) {
-				close(rp->renamed[i]);
-			}
-			if (!vforked)
-				rp->renamed[i] = EMPTY;
-		}
-	}
-}
-
-
-
-/*
- * Copy a file descriptor to be >= to.  Returns -1
- * if the source file descriptor is closed, EMPTY if there are no unused
- * file descriptors left.
- */
-
-int
-copyfd(int from, int to)
-{
-	int newfd;
-
-	newfd = fcntl(from, F_DUPFD, to);
-	if (newfd < 0) {
-		if (errno == EMFILE)
-			return EMPTY;
-		else
-			error("%d: %s", from, strerror(errno));
-	}
-	return newfd;
-}
diff --git a/sh/redir.h b/sh/redir.h
deleted file mode 100644
index c9709e9..0000000
--- a/sh/redir.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*	$NetBSD: redir.h,v 1.15 2003/08/07 09:05:37 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)redir.h	8.2 (Berkeley) 5/4/95
- */
-
-/* flags passed to redirect */
-#define REDIR_PUSH 01		/* save previous values of file descriptors */
-#define REDIR_BACKQ 02		/* save the command output in memory */
-#define REDIR_VFORK 04		/* running under vfork(2), be careful */
-
-union node;
-void redirect(union node *, int);
-void popredir(void);
-int fd0_redirected_p(void);
-void clearredir(int);
-int copyfd(int, int);
-
diff --git a/sh/sh.1 b/sh/sh.1
deleted file mode 100644
index 3ef55b4..0000000
--- a/sh/sh.1
+++ /dev/null
@@ -1,1928 +0,0 @@
-.\"	$NetBSD: sh.1,v 1.78 2004/06/03 19:54:37 hubertf Exp $
-.\" Copyright (c) 1991, 1993
-.\"	The Regents of the University of California.  All rights reserved.
-.\"
-.\" This code is derived from software contributed to Berkeley by
-.\" Kenneth Almquist.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. 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.
-.\"
-.\"	@(#)sh.1	8.6 (Berkeley) 5/4/95
-.\"
-.Dd April 17, 2004
-.Os
-.Dt SH 1
-.Sh NAME
-.Nm sh
-.Nd command interpreter (shell)
-.Sh SYNOPSIS
-.Nm
-.Bk -words
-.Op Fl aCefnuvxIimqVEb
-.Op Cm +aCefnuvxIimqVEb
-.Ek
-.Bk -words
-.Op Fl o Ar option_name
-.Op Cm +o Ar option_name
-.Ek
-.Bk -words
-.Op Ar command_file Oo Ar argument ... Oc
-.Ek
-.Nm
-.Fl c
-.Bk -words
-.Op Fl aCefnuvxIimqVEb
-.Op Cm +aCefnuvxIimqVEb
-.Ek
-.Bk -words
-.Op Fl o Ar option_name
-.Op Cm +o Ar option_name
-.Ek
-.Bk -words
-.Ar command_string
-.Op Ar command_name Oo Ar argument ... Oc
-.Ek
-.Nm
-.Fl s
-.Bk -words
-.Op Fl aCefnuvxIimqVEb
-.Op Cm +aCefnuvxIimqVEb
-.Ek
-.Bk -words
-.Op Fl o Ar option_name
-.Op Cm +o Ar option_name
-.Ek
-.Bk -words
-.Op Ar argument ...
-.Ek
-.Sh DESCRIPTION
-.Nm
-is the standard command interpreter for the system.
-The current version of
-.Nm
-is in the process of being changed to conform with the
-.Tn POSIX
-1003.2 and 1003.2a specifications for the shell.
-This version has many
-features which make it appear similar in some respects to the Korn shell,
-but it is not a Korn shell clone (see
-.Xr ksh 1 ) .
-Only features designated by
-.Tn POSIX ,
-plus a few Berkeley extensions, are being incorporated into this shell.
-.\" We expect
-.\" .Tn POSIX
-.\" conformance by the time 4.4 BSD is released.
-This man page is not intended
-to be a tutorial or a complete specification of the shell.
-.Ss Overview
-The shell is a command that reads lines from either a file or the
-terminal, interprets them, and generally executes other commands.
-It is the program that is running when a user logs into the system
-(although a user can select a different shell with the
-.Xr chsh 1
-command).
-The shell implements a language that has flow control
-constructs, a macro facility that provides a variety of features in
-addition to data storage, along with built in history and line editing
-capabilities.
-It incorporates many features to aid interactive use and
-has the advantage that the interpretative language is common to both
-interactive and non-interactive use (shell scripts).
-That is, commands
-can be typed directly to the running shell or can be put into a file and
-the file can be executed directly by the shell.
-.Ss Invocation
-If no args are present and if the standard input of the shell
-is connected to a terminal (or if the
-.Fl i
-flag is set),
-and the
-.Fl c
-option is not present, the shell is considered an interactive shell.
-An interactive shell generally prompts before each command and handles
-programming and command errors differently (as described below).
-When first starting,
-the shell inspects argument 0, and if it begins with a dash
-.Sq - ,
-the shell is also considered
-a login shell.
-This is normally done automatically by the system
-when the user first logs in.
-A login shell first reads commands
-from the files
-.Pa /etc/profile
-and
-.Pa .profile
-if they exist.
-If the environment variable
-.Ev ENV
-is set on entry to a shell, or is set in the
-.Pa .profile
-of a login shell, the shell next reads
-commands from the file named in
-.Ev ENV .
-Therefore, a user should place commands that are to be executed only at
-login time in the
-.Pa .profile
-file, and commands that are executed for every shell inside the
-.Ev ENV
-file.
-To set the
-.Ev ENV
-variable to some file, place the following line in your
-.Pa .profile
-of your home directory
-.Pp
-.Dl ENV=$HOME/.shinit; export ENV
-.Pp
-substituting for
-.Dq .shinit
-any filename you wish.
-Since the
-.Ev ENV
-file is read for every invocation of the shell, including shell scripts
-and non-interactive shells, the following paradigm is useful for
-restricting commands in the
-.Ev ENV
-file to interactive invocations.
-Place commands within the
-.Dq case
-and
-.Dq esac
-below (these commands are described later):
-.Pp
-.Bl -item -compact -offset indent
-.It
-.Li case $- in *i*)
-.Bl -item -compact -offset indent
-.It
-.Li # commands for interactive use only
-.It
-.Li ...
-.El
-.It
-.Li esac
-.El
-.Pp
-If command line arguments besides the options have been specified, then
-the shell treats the first argument as the name of a file from which to
-read commands (a shell script), and the remaining arguments are set as the
-positional parameters of the shell ($1, $2, etc).
-Otherwise, the shell
-reads commands from its standard input.
-.Ss Argument List Processing
-All of the single letter options have a corresponding name that can be
-used as an argument to the
-.Fl o
-option.
-The set
-.Fl o
-name is provided next to the single letter option in
-the description below.
-Specifying a dash
-.Dq -
-turns the option on, while using a plus
-.Dq +
-disables the option.
-The following options can be set from the command line or
-with the
-.Ic set
-builtin (described later).
-.Bl -tag -width aaaallexportfoo -offset indent
-.It Fl a Em allexport
-Export all variables assigned to.
-.It Fl c
-Read commands from the
-.Ar command_string
-operand instead of from the standard input.
-Special parameter 0 will be set from the
-.Ar command_name
-operand and the positional parameters ($1, $2, etc.)
-set from the remaining argument operands.
-.It Fl C Em noclobber
-Don't overwrite existing files with
-.Dq \*[Gt] .
-.It Fl e Em errexit
-If not interactive, exit immediately if any untested command fails.
-The exit status of a command is considered to be
-explicitly tested if the command is used to control an
-.Ic if ,
-.Ic elif ,
-.Ic while ,
-or
-.Ic until ;
-or if the command is the left hand operand of an
-.Dq \*[Am]\*[Am]
-or
-.Dq ||
-operator.
-.It Fl f Em noglob
-Disable pathname expansion.
-.It Fl n Em noexec
-If not interactive, read commands but do not execute them.
-This is useful for checking the syntax of shell scripts.
-.It Fl u Em nounset
-Write a message to standard error when attempting to expand a variable
-that is not set, and if the shell is not interactive, exit immediately.
-.It Fl v Em verbose
-The shell writes its input to standard error as it is read.
-Useful for debugging.
-.It Fl x Em xtrace
-Write each command to standard error (preceded by a
-.Sq +\  )
-before it is executed.
-Useful for debugging.
-.It Fl q Em quietprofile
-If the
-.Fl v
-or
-.Fl x
-options have been set, do not apply them when reading
-initialization files, these being
-.Pa /etc/profile ,
-.Pa .profile ,
-and the file specified by the
-.Ev ENV
-environment variable.
-.It Fl I Em ignoreeof
-Ignore EOF's from input when interactive.
-.It Fl i Em interactive
-Force the shell to behave interactively.
-.It Fl m Em monitor
-Turn on job control (set automatically when interactive).
-.It Fl s Em stdin
-Read commands from standard input (set automatically if no file arguments
-are present).
-This option has no effect when set after the shell has
-already started running (i.e. with
-.Ic set ) .
-.It Fl V Em vi
-Enable the built-in
-.Xr vi 1
-command line editor (disables
-.Fl E
-if it has been set).
-(See the
-.Sx Command Line Editing
-section below.)
-.It Fl E Em emacs
-Enable the built-in emacs style
-command line editor (disables
-.Fl V
-if it has been set).
-(See the
-.Sx Command Line Editing
-section below.)
-.It Fl b Em notify
-Enable asynchronous notification of background job completion.
-(UNIMPLEMENTED for 4.4alpha)
-.It "\ \ " Em cdprint
-Make an interactive shell always print the new directory name when
-changed by the
-.Ic cd
-command.
-.El
-.Ss Lexical Structure
-The shell reads input in terms of lines from a file and breaks it up into
-words at whitespace (blanks and tabs), and at certain sequences of
-characters that are special to the shell called
-.Dq operators .
-There are two types of operators: control operators and redirection
-operators (their meaning is discussed later).
-Following is a list of operators:
-.Bl -ohang -offset indent
-.It "Control operators:"
-.Dl \*[Am]  \*[Am]\*[Am]  \&(  \&)  \&;  ;; | || \*[Lt]newline\*[Gt]
-.It "Redirection operators:"
-.Dl \*[Lt]  \*[Gt]  \*[Gt]|  \*[Lt]\*[Lt]  \*[Gt]\*[Gt]  \*[Lt]\*[Am]  \*[Gt]\*[Am]  \*[Lt]\*[Lt]-  \*[Lt]\*[Gt]
-.El
-.Ss Quoting
-Quoting is used to remove the special meaning of certain characters or
-words to the shell, such as operators, whitespace, or keywords.
-There are three types of quoting: matched single quotes,
-matched double quotes, and backslash.
-.Ss Backslash
-A backslash preserves the literal meaning of the following
-character, with the exception of
-.Aq newline .
-A backslash preceding a
-.Aq newline
-is treated as a line continuation.
-.Ss Single Quotes
-Enclosing characters in single quotes preserves the literal meaning of all
-the characters (except single quotes, making it impossible to put
-single-quotes in a single-quoted string).
-.Ss Double Quotes
-Enclosing characters within double quotes preserves the literal
-meaning of all characters except dollarsign
-.Pq $ ,
-backquote
-.Pq ` ,
-and backslash
-.Pq \e .
-The backslash inside double quotes is historically weird, and serves to
-quote only the following characters:
-.Dl $  `  \*q  \e  \*[Lt]newline\*[Gt] .
-Otherwise it remains literal.
-.Ss Reserved Words
-Reserved words are words that have special meaning to the
-shell and are recognized at the beginning of a line and
-after a control operator.
-The following are reserved words:
-.Bl -column while while while while while -offset indent
-.It ! Ta elif Ta fi Ta while Ta case
-.It else Ta for Ta then Ta { Ta }
-.It do Ta done Ta until Ta if Ta esac
-.El
-.Pp
-Their meaning is discussed later.
-.Ss Aliases
-An alias is a name and corresponding value set using the
-.Ic alias
-builtin command.
-Whenever a reserved word may occur (see above),
-and after checking for reserved words, the shell
-checks the word to see if it matches an alias.
-If it does, it replaces it in the input stream with its value.
-For example, if there is an alias called
-.Dq lf
-with the value
-.Dq "ls -F" ,
-then the input:
-.Pp
-.Dl lf foobar Aq return
-.Pp
-would become
-.Pp
-.Dl ls -F foobar Aq return
-.Pp
-Aliases provide a convenient way for naive users to create shorthands for
-commands without having to learn how to create functions with arguments.
-They can also be used to create lexically obscure code.
-This use is discouraged.
-.Ss Commands
-The shell interprets the words it reads according to a language, the
-specification of which is outside the scope of this man page (refer to the
-BNF in the
-.Tn POSIX
-1003.2 document).
-Essentially though, a line is read and if the first
-word of the line (or after a control operator) is not a reserved word,
-then the shell has recognized a simple command.
-Otherwise, a complex
-command or some other special construct may have been recognized.
-.Ss Simple Commands
-If a simple command has been recognized, the shell performs
-the following actions:
-.Bl -enum -offset indent
-.It
-Leading words of the form
-.Dq name=value
-are stripped off and assigned to the environment of the simple command.
-Redirection operators and their arguments (as described below) are
-stripped off and saved for processing.
-.It
-The remaining words are expanded as described in
-the section called
-.Dq Expansions ,
-and the first remaining word is considered the command name and the
-command is located.
-The remaining words are considered the arguments of the command.
-If no command name resulted, then the
-.Dq name=value
-variable assignments recognized in item 1 affect the current shell.
-.It
-Redirections are performed as described in the next section.
-.El
-.Ss Redirections
-Redirections are used to change where a command reads its input or sends
-its output.
-In general, redirections open, close, or duplicate an
-existing reference to a file.
-The overall format used for redirection is:
-.Pp
-.Dl [n] Va redir-op Ar file
-.Pp
-where
-.Va redir-op
-is one of the redirection operators mentioned previously.
-Following is a list of the possible redirections.
-The
-.Bq n
-is an optional number, as in
-.Sq 3
-(not
-.Sq Bq 3 ) ,
-that refers to a file descriptor.
-.Bl -tag -width aaabsfiles -offset indent
-.It [n] Ns \*[Gt] file
-Redirect standard output (or n) to file.
-.It [n] Ns \*[Gt]| file
-Same, but override the
-.Fl C
-option.
-.It [n] Ns \*[Gt]\*[Gt] file
-Append standard output (or n) to file.
-.It [n] Ns \*[Lt] file
-Redirect standard input (or n) from file.
-.It [n1] Ns \*[Lt]\*[Am] Ns n2
-Duplicate standard input (or n1) from file descriptor n2.
-.It [n] Ns \*[Lt]\*[Am]-
-Close standard input (or n).
-.It [n1] Ns \*[Gt]\*[Am] Ns n2
-Duplicate standard output (or n1) to n2.
-.It [n] Ns \*[Gt]\*[Am]-
-Close standard output (or n).
-.It [n] Ns \*[Lt]\*[Gt] file
-Open file for reading and writing on standard input (or n).
-.El
-.Pp
-The following redirection is often called a
-.Dq here-document .
-.Bl -item -offset indent
-.It
-.Li [n]\*[Lt]\*[Lt] delimiter
-.Dl here-doc-text ...
-.Li delimiter
-.El
-.Pp
-All the text on successive lines up to the delimiter is saved away and
-made available to the command on standard input, or file descriptor n if
-it is specified.
-If the delimiter as specified on the initial line is
-quoted, then the here-doc-text is treated literally, otherwise the text is
-subjected to parameter expansion, command substitution, and arithmetic
-expansion (as described in the section on
-.Dq Expansions ) .
-If the operator is
-.Dq \*[Lt]\*[Lt]-
-instead of
-.Dq \*[Lt]\*[Lt] ,
-then leading tabs in the here-doc-text are stripped.
-.Ss Search and Execution
-There are three types of commands: shell functions, builtin commands, and
-normal programs -- and the command is searched for (by name) in that order.
-They each are executed in a different way.
-.Pp
-When a shell function is executed, all of the shell positional parameters
-(except $0, which remains unchanged) are set to the arguments of the shell
-function.
-The variables which are explicitly placed in the environment of
-the command (by placing assignments to them before the function name) are
-made local to the function and are set to the values given.
-Then the command given in the function definition is executed.
-The positional parameters are restored to their original values
-when the command completes.
-This all occurs within the current shell.
-.Pp
-Shell builtins are executed internally to the shell, without spawning a
-new process.
-.Pp
-Otherwise, if the command name doesn't match a function or builtin, the
-command is searched for as a normal program in the file system (as
-described in the next section).
-When a normal program is executed, the shell runs the program,
-passing the arguments and the environment to the program.
-If the program is not a normal executable file (i.e., if it does
-not begin with the "magic number" whose
-.Tn ASCII
-representation is "#!", so
-.Xr execve 2
-returns
-.Er ENOEXEC
-then) the shell will interpret the program in a subshell.
-The child shell will reinitialize itself in this case,
-so that the effect will be as if a
-new shell had been invoked to handle the ad-hoc shell script, except that
-the location of hashed commands located in the parent shell will be
-remembered by the child.
-.Pp
-Note that previous versions of this document and the source code itself
-misleadingly and sporadically refer to a shell script without a magic
-number as a "shell procedure".
-.Ss Path Search
-When locating a command, the shell first looks to see if it has a shell
-function by that name.
-Then it looks for a builtin command by that name.
-If a builtin command is not found, one of two things happen:
-.Bl -enum
-.It
-Command names containing a slash are simply executed without performing
-any searches.
-.It
-The shell searches each entry in
-.Ev PATH
-in turn for the command.
-The value of the
-.Ev PATH
-variable should be a series of entries separated by colons.
-Each entry consists of a directory name.
-The current directory may be indicated
-implicitly by an empty directory name, or explicitly by a single period.
-.El
-.Ss Command Exit Status
-Each command has an exit status that can influence the behavior
-of other shell commands.
-The paradigm is that a command exits
-with zero for normal or success, and non-zero for failure,
-error, or a false indication.
-The man page for each command
-should indicate the various exit codes and what they mean.
-Additionally, the builtin commands return exit codes, as does
-an executed shell function.
-.Pp
-If a command consists entirely of variable assignments then the
-exit status of the command is that of the last command substitution
-if any, otherwise 0.
-.Ss Complex Commands
-Complex commands are combinations of simple commands with control
-operators or reserved words, together creating a larger complex command.
-More generally, a command is one of the following:
-.Bl -bullet
-.It
-simple command
-.It
-pipeline
-.It
-list or compound-list
-.It
-compound command
-.It
-function definition
-.El
-.Pp
-Unless otherwise stated, the exit status of a command is that of the last
-simple command executed by the command.
-.Ss Pipelines
-A pipeline is a sequence of one or more commands separated
-by the control operator |.
-The standard output of all but
-the last command is connected to the standard input
-of the next command.
-The standard output of the last
-command is inherited from the shell, as usual.
-.Pp
-The format for a pipeline is:
-.Pp
-.Dl [!] command1 [ | command2 ...]
-.Pp
-The standard output of command1 is connected to the standard input of
-command2.
-The standard input, standard output, or both of a command is
-considered to be assigned by the pipeline before any redirection specified
-by redirection operators that are part of the command.
-.Pp
-If the pipeline is not in the background (discussed later), the shell
-waits for all commands to complete.
-.Pp
-If the reserved word ! does not precede the pipeline, the exit status is
-the exit status of the last command specified in the pipeline.
-Otherwise, the exit status is the logical NOT of the exit status of the
-last command.
-That is, if the last command returns zero, the exit status
-is 1; if the last command returns greater than zero, the exit status is
-zero.
-.Pp
-Because pipeline assignment of standard input or standard output or both
-takes place before redirection, it can be modified by redirection.
-For example:
-.Pp
-.Dl $ command1 2\*[Gt]\*[Am]1 | command2
-.Pp
-sends both the standard output and standard error of command1
-to the standard input of command2.
-.Pp
-A ; or
-.Aq newline
-terminator causes the preceding AND-OR-list (described
-next) to be executed sequentially; a \*[Am] causes asynchronous execution of
-the preceding AND-OR-list.
-.Pp
-Note that unlike some other shells, each process in the pipeline is a
-child of the invoking shell (unless it is a shell builtin, in which case
-it executes in the current shell -- but any effect it has on the
-environment is wiped).
-.Ss Background Commands -- \*[Am]
-If a command is terminated by the control operator ampersand (\*[Am]), the
-shell executes the command asynchronously -- that is, the shell does not
-wait for the command to finish before executing the next command.
-.Pp
-The format for running a command in background is:
-.Pp
-.Dl command1 \*[Am] [command2 \*[Am] ...]
-.Pp
-If the shell is not interactive, the standard input of an asynchronous
-command is set to
-.Pa /dev/null .
-.Ss Lists -- Generally Speaking
-A list is a sequence of zero or more commands separated by newlines,
-semicolons, or ampersands, and optionally terminated by one of these three
-characters.
-The commands in a list are executed in the order they are written.
-If command is followed by an ampersand, the shell starts the
-command and immediately proceed onto the next command; otherwise it waits
-for the command to terminate before proceeding to the next one.
-.Ss Short-Circuit List Operators
-.Dq \*[Am]\*[Am]
-and
-.Dq ||
-are AND-OR list operators.
-.Dq \*[Am]\*[Am]
-executes the first command, and then executes the second command if and only
-if the exit status of the first command is zero.
-.Dq ||
-is similar, but executes the second command if and only if the exit status
-of the first command is nonzero.
-.Dq \*[Am]\*[Am]
-and
-.Dq ||
-both have the same priority.
-Note that these operators are left-associative, so
-.Dq true || echo bar && echo baz
-writes
-.Dq baz
-and nothing else.
-This is not the way it works in C.
-.Ss Flow-Control Constructs -- if, while, for, case
-The syntax of the if command is
-.Bd -literal -offset indent
-if list
-then list
-[ elif list
-then    list ] ...
-[ else list ]
-fi
-.Ed
-.Pp
-The syntax of the while command is
-.Bd -literal -offset indent
-while list
-do   list
-done
-.Ed
-.Pp
-The two lists are executed repeatedly while the exit status of the
-first list is zero.
-The until command is similar, but has the word
-until in place of while, which causes it to
-repeat until the exit status of the first list is zero.
-.Pp
-The syntax of the for command is
-.Bd -literal -offset indent
-for variable in word ...
-do   list
-done
-.Ed
-.Pp
-The words are expanded, and then the list is executed repeatedly with the
-variable set to each word in turn.
-do and done may be replaced with
-.Dq {
-and
-.Dq } .
-.Pp
-The syntax of the break and continue command is
-.Bd -literal -offset indent
-break [ num ]
-continue [ num ]
-.Ed
-.Pp
-Break terminates the num innermost for or while loops.
-Continue continues with the next iteration of the innermost loop.
-These are implemented as builtin commands.
-.Pp
-The syntax of the case command is
-.Bd -literal -offset indent
-case word in
-pattern) list ;;
-\&...
-esac
-.Ed
-.Pp
-The pattern can actually be one or more patterns (see
-.Sx Shell Patterns
-described later), separated by
-.Dq \*(Ba
-characters.
-.Ss Grouping Commands Together
-Commands may be grouped by writing either
-.Pp
-.Dl (list)
-.Pp
-or
-.Pp
-.Dl { list; }
-.Pp
-The first of these executes the commands in a subshell.
-Builtin commands grouped into a (list) will not affect the current shell.
-The second form does not fork another shell so is slightly more efficient.
-Grouping commands together this way allows you to redirect
-their output as though they were one program:
-.Pp
-.Bd -literal -offset indent
-{ echo -n \*q hello \*q ; echo \*q world" ; } \*[Gt] greeting
-.Ed
-.Pp
-Note that
-.Dq }
-must follow a control operator (here,
-.Dq \&; )
-so that it is recognized as a reserved word and not as another command argument.
-.Ss Functions
-The syntax of a function definition is
-.Pp
-.Dl name ( ) command
-.Pp
-A function definition is an executable statement; when executed it
-installs a function named name and returns an exit status of zero.
-The command is normally a list enclosed between
-.Dq {
-and
-.Dq } .
-.Pp
-Variables may be declared to be local to a function by using a local
-command.
-This should appear as the first statement of a function, and the syntax is
-.Pp
-.Dl local [ variable | - ] ...
-.Pp
-Local is implemented as a builtin command.
-.Pp
-When a variable is made local, it inherits the initial value and exported
-and readonly flags from the variable with the same name in the surrounding
-scope, if there is one.
-Otherwise, the variable is initially unset.
-The shell uses dynamic scoping, so that if you make the variable x local to
-function f, which then calls function g, references to the variable x made
-inside g will refer to the variable x declared inside f, not to the global
-variable named x.
-.Pp
-The only special parameter that can be made local is
-.Dq - .
-Making
-.Dq -
-local any shell options that are changed via the set command inside the
-function to be restored to their original values when the function
-returns.
-.Pp
-The syntax of the return command is
-.Pp
-.Dl return [ exitstatus ]
-.Pp
-It terminates the currently executing function.
-Return is implemented as a builtin command.
-.Ss Variables and Parameters
-The shell maintains a set of parameters.
-A parameter denoted by a name is called a variable.
-When starting up, the shell turns all the environment
-variables into shell variables.
-New variables can be set using the form
-.Pp
-.Dl name=value
-.Pp
-Variables set by the user must have a name consisting solely of
-alphabetics, numerics, and underscores - the first of which must not be
-numeric.
-A parameter can also be denoted by a number or a special
-character as explained below.
-.Ss Positional Parameters
-A positional parameter is a parameter denoted by a number (n \*[Gt] 0).
-The shell sets these initially to the values of its command line arguments
-that follow the name of the shell script.
-The
-.Ic set
-builtin can also be used to set or reset them.
-.Ss Special Parameters
-A special parameter is a parameter denoted by one of the following special
-characters.
-The value of the parameter is listed next to its character.
-.Bl -tag -width thinhyphena
-.It *
-Expands to the positional parameters, starting from one.
-When the
-expansion occurs within a double-quoted string it expands to a single
-field with the value of each parameter separated by the first character of
-the
-.Ev IFS
-variable, or by a
-.Aq space
-if
-.Ev IFS
-is unset.
-.It @
-Expands to the positional parameters, starting from one.
-When the expansion occurs within double-quotes, each positional
-parameter expands as a separate argument.
-If there are no positional parameters, the
-expansion of @ generates zero arguments, even when @ is
-double-quoted.
-What this basically means, for example, is
-if $1 is
-.Dq abc
-and $2 is
-.Dq def ghi ,
-then
-.Qq $@
-expands to
-the two arguments:
-.Pp
-.Sm off
-.Dl \*q abc \*q \  \*q def\ ghi \*q
-.Sm on
-.It #
-Expands to the number of positional parameters.
-.It \&?
-Expands to the exit status of the most recent pipeline.
-.It - (Hyphen.)
-Expands to the current option flags (the single-letter
-option names concatenated into a string) as specified on
-invocation, by the set builtin command, or implicitly
-by the shell.
-.It $
-Expands to the process ID of the invoked shell.
-A subshell retains the same value of $ as its parent.
-.It \&!
-Expands to the process ID of the most recent background
-command executed from the current shell.
-For a pipeline, the process ID is that of the last command in the pipeline.
-.It 0 (Zero.)
-Expands to the name of the shell or shell script.
-.El
-.Ss Word Expansions
-This clause describes the various expansions that are performed on words.
-Not all expansions are performed on every word, as explained later.
-.Pp
-Tilde expansions, parameter expansions, command substitutions, arithmetic
-expansions, and quote removals that occur within a single word expand to a
-single field.
-It is only field splitting or pathname expansion that can
-create multiple fields from a single word.
-The single exception to this
-rule is the expansion of the special parameter @ within double-quotes, as
-was described above.
-.Pp
-The order of word expansion is:
-.Bl -enum
-.It
-Tilde Expansion, Parameter Expansion, Command Substitution,
-Arithmetic Expansion (these all occur at the same time).
-.It
-Field Splitting is performed on fields
-generated by step (1) unless the
-.Ev IFS
-variable is null.
-.It
-Pathname Expansion (unless set
-.Fl f
-is in effect).
-.It
-Quote Removal.
-.El
-.Pp
-The $ character is used to introduce parameter expansion, command
-substitution, or arithmetic evaluation.
-.Ss Tilde Expansion (substituting a user's home directory)
-A word beginning with an unquoted tilde character (~) is
-subjected to tilde expansion.
-All the characters up to
-a slash (/) or the end of the word are treated as a username
-and are replaced with the user's home directory.
-If the username is missing (as in
-.Pa ~/foobar ) ,
-the tilde is replaced with the value of the
-.Va HOME
-variable (the current user's home directory).
-.Ss Parameter Expansion
-The format for parameter expansion is as follows:
-.Pp
-.Dl ${expression}
-.Pp
-where expression consists of all characters until the matching
-.Dq } .
-Any
-.Dq }
-escaped by a backslash or within a quoted string, and characters in
-embedded arithmetic expansions, command substitutions, and variable
-expansions, are not examined in determining the matching
-.Dq } .
-.Pp
-The simplest form for parameter expansion is:
-.Pp
-.Dl ${parameter}
-.Pp
-The value, if any, of parameter is substituted.
-.Pp
-The parameter name or symbol can be enclosed in braces, which are
-optional except for positional parameters with more than one digit or
-when parameter is followed by a character that could be interpreted as
-part of the name.
-If a parameter expansion occurs inside double-quotes:
-.Bl -enum
-.It
-Pathname expansion is not performed on the results of the expansion.
-.It
-Field splitting is not performed on the results of the
-expansion, with the exception of @.
-.El
-.Pp
-In addition, a parameter expansion can be modified by using one of the
-following formats.
-.Bl -tag -width aaparameterwordaaaaa
-.It ${parameter:-word}
-Use Default Values.
-If parameter is unset or null, the expansion of word
-is substituted; otherwise, the value of parameter is substituted.
-.It ${parameter:=word}
-Assign Default Values.
-If parameter is unset or null, the expansion of
-word is assigned to parameter.
-In all cases, the final value of parameter is substituted.
-Only variables, not positional parameters or special
-parameters, can be assigned in this way.
-.It ${parameter:?[word]}
-Indicate Error if Null or Unset.
-If parameter is unset or null, the
-expansion of word (or a message indicating it is unset if word is omitted)
-is written to standard error and the shell exits with a nonzero exit status.
-Otherwise, the value of parameter is substituted.
-An interactive shell need not exit.
-.It ${parameter:+word}
-Use Alternative Value.
-If parameter is unset or null, null is
-substituted; otherwise, the expansion of word is substituted.
-.El
-.Pp
-In the parameter expansions shown previously, use of the colon in the
-format results in a test for a parameter that is unset or null; omission
-of the colon results in a test for a parameter that is only unset.
-.Bl -tag -width aaparameterwordaaaaa
-.It ${#parameter}
-String Length.
-The length in characters of the value of parameter.
-.El
-.Pp
-The following four varieties of parameter expansion provide for substring
-processing.
-In each case, pattern matching notation (see
-.Sx Shell Patterns ) ,
-rather than regular expression notation, is used to evaluate the patterns.
-If parameter is * or @, the result of the expansion is unspecified.
-Enclosing the full parameter expansion string in double-quotes does not
-cause the following four varieties of pattern characters to be quoted,
-whereas quoting characters within the braces has this effect.
-.Bl -tag -width aaparameterwordaaaaa
-.It ${parameter%word}
-Remove Smallest Suffix Pattern.
-The word is expanded to produce a pattern.
-The parameter expansion then results in parameter, with the
-smallest portion of the suffix matched by the pattern deleted.
-.It ${parameter%%word}
-Remove Largest Suffix Pattern.
-The word is expanded to produce a pattern.
-The parameter expansion then results in parameter, with the largest
-portion of the suffix matched by the pattern deleted.
-.It ${parameter#word}
-Remove Smallest Prefix Pattern.
-The word is expanded to produce a pattern.
-The parameter expansion then results in parameter, with the
-smallest portion of the prefix matched by the pattern deleted.
-.It ${parameter##word}
-Remove Largest Prefix Pattern.
-The word is expanded to produce a pattern.
-The parameter expansion then results in parameter, with the largest
-portion of the prefix matched by the pattern deleted.
-.El
-.Ss Command Substitution
-Command substitution allows the output of a command to be substituted in
-place of the command name itself.
-Command substitution occurs when the command is enclosed as follows:
-.Pp
-.Dl $(command)
-.Pp
-or
-.Po
-.Dq backquoted
-version
-.Pc :
-.Pp
-.Dl `command`
-.Pp
-The shell expands the command substitution by executing command in a
-subshell environment and replacing the command substitution with the
-standard output of the command, removing sequences of one or more
-.Ao newline Ac Ns s
-at the end of the substitution.
-(Embedded
-.Ao newline Ac Ns s
-before
-the end of the output are not removed; however, during field splitting,
-they may be translated into
-.Ao space Ac Ns s ,
-depending on the value of
-.Ev IFS
-and quoting that is in effect.)
-.Ss Arithmetic Expansion
-Arithmetic expansion provides a mechanism for evaluating an arithmetic
-expression and substituting its value.
-The format for arithmetic expansion is as follows:
-.Pp
-.Dl $((expression))
-.Pp
-The expression is treated as if it were in double-quotes, except
-that a double-quote inside the expression is not treated specially.
-The shell expands all tokens in the expression for parameter expansion,
-command substitution, and quote removal.
-.Pp
-Next, the shell treats this as an arithmetic expression and
-substitutes the value of the expression.
-.Ss White Space Splitting (Field Splitting)
-After parameter expansion, command substitution, and
-arithmetic expansion the shell scans the results of
-expansions and substitutions that did not occur in double-quotes for
-field splitting and multiple fields can result.
-.Pp
-The shell treats each character of the
-.Ev IFS
-as a delimiter and use the delimiters to split the results of parameter
-expansion and command substitution into fields.
-.Ss Pathname Expansion (File Name Generation)
-Unless the
-.Fl f
-flag is set, file name generation is performed after word splitting is
-complete.
-Each word is viewed as a series of patterns, separated by slashes.
-The process of expansion replaces the word with the names of all
-existing files whose names can be formed by replacing each pattern with a
-string that matches the specified pattern.
-There are two restrictions on
-this: first, a pattern cannot match a string containing a slash, and
-second, a pattern cannot match a string starting with a period unless the
-first character of the pattern is a period.
-The next section describes the
-patterns used for both Pathname Expansion and the
-.Ic case
-command.
-.Ss Shell Patterns
-A pattern consists of normal characters, which match themselves,
-and meta-characters.
-The meta-characters are
-.Dq \&! ,
-.Dq * ,
-.Dq \&? ,
-and
-.Dq \&[ .
-These characters lose their special meanings if they are quoted.
-When command or variable substitution is performed
-and the dollar sign or back quotes are not double quoted,
-the value of the variable or the output of
-the command is scanned for these characters and they are turned into
-meta-characters.
-.Pp
-An asterisk
-.Pq Dq *
-matches any string of characters.
-A question mark matches any single character.
-A left bracket
-.Pq Dq \&[
-introduces a character class.
-The end of the character class is indicated by a
-.Pq Dq \&] ;
-if the
-.Dq \&]
-is missing then the
-.Dq \&[
-matches a
-.Dq \&[
-rather than introducing a character class.
-A character class matches any of the characters between the square brackets.
-A range of characters may be specified using a minus sign.
-The character class may be complemented
-by making an exclamation point the first character of the character class.
-.Pp
-To include a
-.Dq \&]
-in a character class, make it the first character listed (after the
-.Dq \&! ,
-if any).
-To include a minus sign, make it the first or last character listed.
-.Ss Builtins
-This section lists the builtin commands which are builtin because they
-need to perform some operation that can't be performed by a separate
-process.
-In addition to these, there are several other commands that may
-be builtin for efficiency (e.g.
-.Xr printf 1 ,
-.Xr echo 1 ,
-.Xr test 1 ,
-etc).
-.Bl -tag -width 5n
-.It :
-A null command that returns a 0 (true) exit value.
-.It \&. file
-The commands in the specified file are read and executed by the shell.
-.It alias Op Ar name Ns Op Ar "=string ..."
-If
-.Ar name=string
-is specified, the shell defines the alias
-.Ar name
-with value
-.Ar string .
-If just
-.Ar name
-is specified, the value of the alias
-.Ar name
-is printed.
-With no arguments, the
-.Ic alias
-builtin prints the
-names and values of all defined aliases (see
-.Ic unalias ) .
-.It bg [ Ar job ] ...
-Continue the specified jobs (or the current job if no
-jobs are given) in the background.
-.It Xo command
-.Op Fl p
-.Op Fl v
-.Op Fl V
-.Ar command
-.Op Ar arg ...
-.Xc
-Execute the specified command but ignore shell functions when searching
-for it.
-(This is useful when you
-have a shell function with the same name as a builtin command.)
-.Bl -tag -width 5n
-.It Fl p
-search for command using a
-.Ev PATH
-that guarantees to find all the standard utilities.
-.It Fl V
-Do not execute the command but
-search for the command and print the resolution of the
-command search.
-This is the same as the type builtin.
-.It Fl v
-Do not execute the command but
-search for the command and print the absolute pathname
-of utilities, the name for builtins or the expansion of aliases.
-.El
-.It cd Op Ar directory Op Ar replace
-Switch to the specified directory (default
-.Ev $HOME ) .
-If
-.Ar replace
-is specified, then the new directory name is generated by replacing
-the first occurrence of
-.Ar directory
-in the current directory name with
-.Ar replace .
-Otherwise if an entry for
-.Ev CDPATH
-appears in the environment of the
-.Ic cd
-command or the shell variable
-.Ev CDPATH
-is set and the directory name does not begin with a slash, then the
-directories listed in
-.Ev CDPATH
-will be searched for the specified directory.
-The format of
-.Ev CDPATH
-is the same as that of
-.Ev PATH .
-In an interactive shell, the
-.Ic cd
-command will print out the name of the
-directory that it actually switched to if this is different from the name
-that the user gave.
-These may be different either because the
-.Ev CDPATH
-mechanism was used or because a symbolic link was crossed.
-.It eval Ar string ...
-Concatenate all the arguments with spaces.
-Then re-parse and execute the command.
-.It exec Op Ar command arg ...
-Unless command is omitted, the shell process is replaced with the
-specified program (which must be a real program, not a shell builtin or
-function).
-Any redirections on the
-.Ic exec
-command are marked as permanent, so that they are not undone when the
-.Ic exec
-command finishes.
-.It exit Op Ar exitstatus
-Terminate the shell process.
-If
-.Ar exitstatus
-is given it is used as the exit status of the shell; otherwise the
-exit status of the preceding command is used.
-.It export Ar name ...
-.It export Fl p
-The specified names are exported so that they will appear in the
-environment of subsequent commands.
-The only way to un-export a variable is to unset it.
-The shell allows the value of a variable to be set at the
-same time it is exported by writing
-.Pp
-.Dl export name=value
-.Pp
-With no arguments the export command lists the names of all exported variables.
-With the
-.Fl p
-option specified the output will be formatted suitably for non-interactive use.
-.It Xo fc Op Fl e Ar editor
-.Op Ar first Op Ar last
-.Xc
-.It Xo fc Fl l
-.Op Fl nr
-.Op Ar first Op Ar last
-.Xc
-.It Xo fc Fl s Op Ar old=new
-.Op Ar first
-.Xc
-The
-.Ic fc
-builtin lists, or edits and re-executes, commands previously entered
-to an interactive shell.
-.Bl -tag -width 5n
-.It Fl e No editor
-Use the editor named by editor to edit the commands.
-The editor string is a command name, subject to search via the
-.Ev PATH
-variable.
-The value in the
-.Ev FCEDIT
-variable is used as a default when
-.Fl e
-is not specified.
-If
-.Ev FCEDIT
-is null or unset, the value of the
-.Ev EDITOR
-variable is used.
-If
-.Ev EDITOR
-is null or unset,
-.Xr ed 1
-is used as the editor.
-.It Fl l No (ell)
-List the commands rather than invoking an editor on them.
-The commands are written in the sequence indicated by
-the first and last operands, as affected by
-.Fl r ,
-with each command preceded by the command number.
-.It Fl n
-Suppress command numbers when listing with -l.
-.It Fl r
-Reverse the order of the commands listed (with
-.Fl l )
-or edited (with neither
-.Fl l
-nor
-.Fl s ) .
-.It Fl s
-Re-execute the command without invoking an editor.
-.It first
-.It last
-Select the commands to list or edit.
-The number of previous commands that
-can be accessed are determined by the value of the
-.Ev HISTSIZE
-variable.
-The value of first or last or both are one of the following:
-.Bl -tag -width 5n
-.It [+]number
-A positive number representing a command number; command numbers can be
-displayed with the
-.Fl l
-option.
-.It Fl number
-A negative decimal number representing the command that was executed
-number of commands previously.
-For example, \-1 is the immediately previous command.
-.El
-.It string
-A string indicating the most recently entered command that begins with
-that string.
-If the old=new operand is not also specified with
-.Fl s ,
-the string form of the first operand cannot contain an embedded equal sign.
-.El
-.Pp
-The following environment variables affect the execution of fc:
-.Bl -tag -width HISTSIZE
-.It Ev FCEDIT
-Name of the editor to use.
-.It Ev HISTSIZE
-The number of previous commands that are accessible.
-.El
-.It fg Op Ar job
-Move the specified job or the current job to the foreground.
-.It getopts Ar optstring var
-The
-.Tn POSIX
-.Ic getopts
-command, not to be confused with the
-.Em Bell Labs
--derived
-.Xr getopt 1 .
-.Pp
-The first argument should be a series of letters, each of which may be
-optionally followed by a colon to indicate that the option requires an
-argument.
-The variable specified is set to the parsed option.
-.Pp
-The
-.Ic getopts
-command deprecates the older
-.Xr getopt 1
-utility due to its handling of arguments containing whitespace.
-.Pp
-The
-.Ic getopts
-builtin may be used to obtain options and their arguments
-from a list of parameters.
-When invoked,
-.Ic getopts
-places the value of the next option from the option string in the list in
-the shell variable specified by
-.Va var
-and its index in the shell variable
-.Ev OPTIND .
-When the shell is invoked,
-.Ev OPTIND
-is initialized to 1.
-For each option that requires an argument, the
-.Ic getopts
-builtin will place it in the shell variable
-.Ev OPTARG .
-If an option is not allowed for in the
-.Va optstring ,
-then
-.Ev OPTARG
-will be unset.
-.Pp
-.Va optstring
-is a string of recognized option letters (see
-.Xr getopt 3 ) .
-If a letter is followed by a colon, the option is expected to have an
-argument which may or may not be separated from it by white space.
-If an option character is not found where expected,
-.Ic getopts
-will set the variable
-.Va var
-to a
-.Dq \&? ;
-.Ic getopts
-will then unset
-.Ev OPTARG
-and write output to standard error.
-By specifying a colon as the first character of
-.Va optstring
-all errors will be ignored.
-.Pp
-A nonzero value is returned when the last option is reached.
-If there are no remaining arguments,
-.Ic getopts
-will set
-.Va var
-to the special option,
-.Dq -- ,
-otherwise, it will set
-.Va var
-to
-.Dq \&? .
-.Pp
-The following code fragment shows how one might process the arguments
-for a command that can take the options
-.Op a
-and
-.Op b ,
-and the option
-.Op c ,
-which requires an argument.
-.Pp
-.Bd -literal -offset indent
-while getopts abc: f
-do
-	case $f in
-	a | b)	flag=$f;;
-	c)	carg=$OPTARG;;
-	\\?)	echo $USAGE; exit 1;;
-	esac
-done
-shift `expr $OPTIND - 1`
-.Ed
-.Pp
-This code will accept any of the following as equivalent:
-.Pp
-.Bd -literal -offset indent
-cmd \-acarg file file
-cmd \-a \-c arg file file
-cmd \-carg -a file file
-cmd \-a \-carg \-\- file file
-.Ed
-.It hash Fl rv Ar command ...
-The shell maintains a hash table which remembers the
-locations of commands.
-With no arguments whatsoever,
-the
-.Ic hash
-command prints out the contents of this table.
-Entries which have not been looked at since the last
-.Ic cd
-command are marked with an asterisk; it is possible for these entries
-to be invalid.
-.Pp
-With arguments, the
-.Ic hash
-command removes the specified commands from the hash table (unless
-they are functions) and then locates them.
-With the
-.Fl v
-option, hash prints the locations of the commands as it finds them.
-The
-.Fl r
-option causes the hash command to delete all the entries in the hash table
-except for functions.
-.It inputrc Ar file
-Read the
-.Va file
-to set keybindings as defined by
-.Xr editrc 5 .
-.It jobid Op Ar job
-Print the process id's of the processes in the job.
-If the
-.Ar job
-argument is omitted, the current job is used.
-.It jobs
-This command lists out all the background processes
-which are children of the current shell process.
-.It pwd Op Fl LP
-Print the current directory.
-If 
-.Fl L
-is specified the cached value (initially set from
-.Ev PWD )
-is checked to see if it refers to the current directory, if it does
-the value is printed.
-Otherwise the current directory name is found using
-.Xr getcwd(3) .
-The environment variable
-.Ev PWD
-is set to printed value.
-.Pp
-The default is
-.Ic pwd
-.Fl L ,
-but note that the builtin
-.Ic cd
-command doesn't currently support
-.Fl L
-or
-.Fl P
-and will cache (almost) the absolute path.
-If
-.Ic cd
-is changed,
-.Ic pwd
-may be changed to default to
-.Ic pwd
-.Fl P .
-.Pp
-If the current directory is renamed and replaced by a symlink to the
-same directory, or the initial
-.Ev PWD
-value followed a symbolic link, then the cached value may not
-be the absolute path.
-.Pp
-The builtin command may differ from the program of the same name because
-the program will use
-.Ev PWD
-and the builtin uses a separately cached value.
-.It Xo read Op Fl p Ar prompt
-.Op Fl r
-.Ar variable
-.Op Ar ...
-.Xc
-The prompt is printed if the
-.Fl p
-option is specified and the standard input is a terminal.
-Then a line is read from the standard input.
-The trailing newline is deleted from the
-line and the line is split as described in the section on word splitting
-above, and the pieces are assigned to the variables in order.
-If there are more pieces than variables, the remaining pieces
-(along with the characters in
-.Ev IFS
-that separated them) are assigned to the last variable.
-If there are more variables than pieces,
-the remaining variables are assigned the null string.
-The
-.Ic read
-builtin will indicate success unless EOF is encountered on input, in
-which case failure is returned.
-.Pp
-By default, unless the
-.Fl r
-option is specified, the backslash
-.Dq \e
-acts as an escape character, causing the following character to be treated
-literally.
-If a backslash is followed by a newline, the backslash and the
-newline will be deleted.
-.It readonly Ar name ...
-.It readonly Fl p
-The specified names are marked as read only, so that they cannot be
-subsequently modified or unset.
-The shell allows the value of a variable
-to be set at the same time it is marked read only by writing
-.Pp
-.Dl readonly name=value
-.Pp
-With no arguments the readonly command lists the names of all read only
-variables.
-With the
-.Fl p
-option specified the output will be formatted suitably for non-interactive use.
-.Pp
-.It Xo set
-.Oo {
-.Fl options | Cm +options | Cm -- }
-.Oc Ar arg ...
-.Xc
-The
-.Ic set
-command performs three different functions.
-.Pp
-With no arguments, it lists the values of all shell variables.
-.Pp
-If options are given, it sets the specified option
-flags, or clears them as described in the section called
-.Sx Argument List Processing .
-.Pp
-The third use of the set command is to set the values of the shell's
-positional parameters to the specified args.
-To change the positional
-parameters without changing any options, use
-.Dq --
-as the first argument to set.
-If no args are present, the set command
-will clear all the positional parameters (equivalent to executing
-.Dq shift $# . )
-.It setvar Ar variable Ar value
-Assigns value to variable.
-(In general it is better to write
-variable=value rather than using
-.Ic setvar .
-.Ic setvar
-is intended to be used in
-functions that assign values to variables whose names are passed as
-parameters.)
-.It shift Op Ar n
-Shift the positional parameters n times.
-A
-.Ic shift
-sets the value of
-.Va $1
-to the value of
-.Va $2 ,
-the value of
-.Va $2
-to the value of
-.Va $3 ,
-and so on, decreasing
-the value of
-.Va $#
-by one.
-If there are zero positional parameters,
-.Ic shift
-does nothing.
-.It Xo trap
-.Op Fl l
-.Xc
-.It Xo trap
-.Op Ar action
-.Ar signal ...
-.Xc
-Cause the shell to parse and execute action when any of the specified
-signals are received.
-The signals are specified by signal number or as the name of the signal.
-If
-.Ar signal
-is
-.Li 0 ,
-the action is executed when the shell exits.
-.Ar action
-may be null, which cause the specified signals to be ignored.
-With
-.Ar action
-omitted or set to `-' the specified signals are set to their default action.
-When the shell forks off a subshell, it resets trapped (but not ignored)
-signals to the default action.
-The
-.Ic trap
-command has no effect on signals that were
-ignored on entry to the shell.
-Issuing
-.Ic trap
-with option
-.Ar -l
-will print a list of valid signal names.
-.Ic trap
-without any arguments cause it to write a list of signals and their
-associated action to the standard output in a format that is suitable
-as an input to the shell that achieves the same trapping results.
-.Pp
-Examples:
-.Pp
-.Dl trap
-.Pp
-List trapped signals and their corresponding action
-.Pp
-.Dl trap -l
-.Pp
-Print a list of valid signals
-.Pp
-.Dl trap '' INT QUIT tstp 30
-.Pp
-Ignore signals INT QUIT TSTP USR1
-.Pp
-.Dl trap date INT
-.Pp
-Print date upon receiving signal INT
-.It type Op Ar name ...
-Interpret each name as a command and print the resolution of the command
-search.
-Possible resolutions are:
-shell keyword, alias, shell builtin,
-command, tracked alias and not found.
-For aliases the alias expansion is
-printed; for commands and tracked aliases the complete pathname of the
-command is printed.
-.It ulimit Xo
-.Op Fl H \*(Ba Fl S
-.Op Fl a \*(Ba Fl tfdscmlpn Op Ar value
-.Xc
-Inquire about or set the hard or soft limits on processes or set new
-limits.
-The choice between hard limit (which no process is allowed to
-violate, and which may not be raised once it has been lowered) and soft
-limit (which causes processes to be signaled but not necessarily killed,
-and which may be raised) is made with these flags:
-.Bl -tag -width Fl
-.It Fl H
-set or inquire about hard limits
-.It Fl S
-set or inquire about soft limits.
-If neither
-.Fl H
-nor
-.Fl S
-is specified, the soft limit is displayed or both limits are set.
-If both are specified, the last one wins.
-.El
-.Pp
-.Bl -tag -width Fl
-The limit to be interrogated or set, then, is chosen by specifying
-any one of these flags:
-.It Fl a
-show all the current limits
-.It Fl b
-show or set the limit on the socket buffer size of a process (in bytes)
-.It Fl t
-show or set the limit on CPU time (in seconds)
-.It Fl f
-show or set the limit on the largest file that can be created
-(in 512-byte blocks)
-.It Fl d
-show or set the limit on the data segment size of a process (in kilobytes)
-.It Fl s
-show or set the limit on the stack size of a process (in kilobytes)
-.It Fl c
-show or set the limit on the largest core dump size that can be produced
-(in 512-byte blocks)
-.It Fl m
-show or set the limit on the total physical memory that can be
-in use by a process (in kilobytes)
-.It Fl l
-show or set the limit on how much memory a process can lock with
-.Xr mlock 2
-(in kilobytes)
-.It Fl p
-show or set the limit on the number of processes this user can
-have at one time
-.It Fl n
-show or set the limit on the number of files a process can have open at once
-.El
-.Pp
-If none of these is specified, it is the limit on file size that is shown
-or set.
-If value is specified, the limit is set to that number; otherwise
-the current limit is displayed.
-.Pp
-Limits of an arbitrary process can be displayed or set using the
-.Xr sysctl 8
-utility.
-.Pp
-.It umask Op Ar mask
-Set the value of umask (see
-.Xr umask 2 )
-to the specified octal value.
-If the argument is omitted, the umask value is printed.
-.It unalias Xo
-.Op Fl a
-.Op Ar name
-.Xc
-If
-.Ar name
-is specified, the shell removes that alias.
-If
-.Fl a
-is specified, all aliases are removed.
-.It unset Ar name ...
-The specified variables and functions are unset and unexported.
-If a given name corresponds to both a variable and a function, both
-the variable and the function are unset.
-.It wait Op Ar job
-Wait for the specified job to complete and return the exit status of the
-last process in the job.
-If the argument is omitted, wait for all jobs to
-complete and then return an exit status of zero.
-.El
-.Ss Command Line Editing
-When
-.Nm
-is being used interactively from a terminal, the current command
-and the command history (see
-.Ic fc
-in
-.Sx Builtins )
-can be edited using emacs-mode or vi-mode command-line editing.
-The command
-.Ql set -o emacs
-enables emacs-mode editing.
-The command
-.Ql set -o vi
-enables vi-mode editing and places sh into vi insert mode.
-(See the
-.Sx Argument List Processing
-section above.)
-.Pp
-The vi mode uses commands similar to a subset of those described in the
-.Xr vi 1
-man page.
-With vi-mode
-enabled, sh can be switched between insert mode and command mode.
-It's similar to vi: typing
-.Aq ESC
-will throw you into command VI command mode.
-Hitting
-.Aq return
-while in command mode will pass the line to the shell.
-.Pp
-The emacs mode uses commands similar to a subset available in
-the emacs editor.
-With emacs-mode enabled, special keys can be used to modify the text
-in the buffer using the control key.
-.Pp
-.Nm
-uses the
-.Xr editline 3
-library.
-.Sh EXIT STATUS
-Errors that are detected by the shell, such as a syntax error, will cause the
-shell to exit with a non-zero exit status.
-If the shell is not an
-interactive shell, the execution of the shell file will be aborted.
-Otherwise
-the shell will return the exit status of the last command executed, or
-if the exit builtin is used with a numeric argument, it will return the
-argument.
-.Sh ENVIRONMENT
-.Bl -tag -width MAILCHECK
-.It Ev HOME
-Set automatically by
-.Xr login 1
-from the user's login directory in the password file
-.Pq Xr passwd 5 .
-This environment variable also functions as the default argument for the
-cd builtin.
-.It Ev PATH
-The default search path for executables.
-See the above section
-.Sx Path Search .
-.It Ev CDPATH
-The search path used with the cd builtin.
-.It Ev LANG
-The string used to specify localization information that allows users
-to work with different culture-specific and language conventions.
-See
-.Xr nls 7 .
-.It Ev MAIL
-The name of a mail file, that will be checked for the arrival of new mail.
-Overridden by
-.Ev MAILPATH .
-.It Ev MAILCHECK
-The frequency in seconds that the shell checks for the arrival of mail
-in the files specified by the
-.Ev MAILPATH
-or the
-.Ev MAIL
-file.
-If set to 0, the check will occur at each prompt.
-.It Ev MAILPATH
-A colon
-.Dq \&:
-separated list of file names, for the shell to check for incoming mail.
-This environment setting overrides the
-.Ev MAIL
-setting.
-There is a maximum of 10 mailboxes that can be monitored at once.
-.It Ev PS1
-The primary prompt string, which defaults to
-.Dq $ \  ,
-unless you are the superuser, in which case it defaults to
-.Dq # \  .
-.It Ev PS2
-The secondary prompt string, which defaults to
-.Dq \*[Gt] \  .
-.It Ev PS4
-Output before each line when execution trace (set -x) is enabled,
-defaults to
-.Dq + \  .
-.It Ev IFS
-Input Field Separators.
-This is normally set to
-.Aq space ,
-.Aq tab ,
-and
-.Aq newline .
-See the
-.Sx White Space Splitting
-section for more details.
-.It Ev TERM
-The default terminal setting for the shell.
-This is inherited by
-children of the shell, and is used in the history editing modes.
-.It Ev HISTSIZE
-The number of lines in the history buffer for the shell.
-.El
-.Sh FILES
-.Bl -item -width HOMEprofilexxxx
-.It
-.Pa $HOME/.profile
-.It
-.Pa /etc/profile
-.El
-.Sh SEE ALSO
-.Xr csh 1 ,
-.Xr echo 1 ,
-.Xr getopt 1 ,
-.Xr ksh 1 ,
-.Xr login 1 ,
-.Xr printf 1 ,
-.Xr test 1 ,
-.Xr editline 3 ,
-.Xr getopt 3 ,
-.\" .Xr profile 4 ,
-.Xr editrc 5 ,
-.Xr passwd 5 ,
-.Xr environ 7 ,
-.Xr nls 7 ,
-.Xr sysctl 8
-.Sh HISTORY
-A
-.Nm
-command appeared in
-.At v1 .
-It was, however, unmaintainable so we wrote this one.
-.Sh BUGS
-Setuid shell scripts should be avoided at all costs, as they are a
-significant security risk.
-.Pp
-PS1, PS2, and PS4 should be subject to parameter expansion before
-being displayed.
diff --git a/sh/shell.h b/sh/shell.h
deleted file mode 100644
index 94be27a..0000000
--- a/sh/shell.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*	$NetBSD: shell.h,v 1.17 2003/08/07 09:05:38 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)shell.h	8.2 (Berkeley) 5/4/95
- */
-
-/*
- * The follow should be set to reflect the type of system you have:
- *	JOBS -> 1 if you have Berkeley job control, 0 otherwise.
- *	SHORTNAMES -> 1 if your linker cannot handle long names.
- *	define BSD if you are running 4.2 BSD or later.
- *	define SYSV if you are running under System V.
- *	define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
- *	define DEBUG=2 to compile in and turn on debugging.
- *	define DO_SHAREDVFORK to indicate that vfork(2) shares its address
- *	       with its parent.
- *
- * When debugging is on, debugging info will be written to ./trace and
- * a quit signal will generate a core dump.
- */
-
-#include <sys/param.h>
-
-#define JOBS 1
-#ifndef BSD
-#define BSD 1
-#endif
-
-#ifndef DO_SHAREDVFORK
-#if __NetBSD_Version__ >= 104000000
-#define DO_SHAREDVFORK
-#endif
-#endif
-
-typedef void *pointer;
-#ifndef NULL
-#define NULL (void *)0
-#endif
-#define STATIC	/* empty */
-#define MKINIT	/* empty */
-
-#include <sys/cdefs.h>
-
-extern char nullstr[1];		/* null string */
-
-
-#ifdef DEBUG
-#define TRACE(param)	trace param
-#define TRACEV(param)	tracev param
-#else
-#define TRACE(param)
-#define TRACEV(param)
-#endif
diff --git a/sh/show.c b/sh/show.c
deleted file mode 100644
index e92aa51..0000000
--- a/sh/show.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/*	$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)show.c	8.3 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: show.c,v 1.26 2003/11/14 10:46:13 dsl Exp $");
-#endif
-#endif /* not lint */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-
-#include "shell.h"
-#include "parser.h"
-#include "nodes.h"
-#include "mystring.h"
-#include "show.h"
-#include "options.h"
-
-
-#ifdef DEBUG
-static void shtree(union node *, int, char *, FILE*);
-static void shcmd(union node *, FILE *);
-static void sharg(union node *, FILE *);
-static void indent(int, char *, FILE *);
-static void trstring(char *);
-
-
-void
-showtree(union node *n)
-{
-	trputs("showtree called\n");
-	shtree(n, 1, NULL, stdout);
-}
-
-
-static void
-shtree(union node *n, int ind, char *pfx, FILE *fp)
-{
-	struct nodelist *lp;
-	const char *s;
-
-	if (n == NULL)
-		return;
-
-	indent(ind, pfx, fp);
-	switch(n->type) {
-	case NSEMI:
-		s = "; ";
-		goto binop;
-	case NAND:
-		s = " && ";
-		goto binop;
-	case NOR:
-		s = " || ";
-binop:
-		shtree(n->nbinary.ch1, ind, NULL, fp);
-	   /*    if (ind < 0) */
-			fputs(s, fp);
-		shtree(n->nbinary.ch2, ind, NULL, fp);
-		break;
-	case NCMD:
-		shcmd(n, fp);
-		if (ind >= 0)
-			putc('\n', fp);
-		break;
-	case NPIPE:
-		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
-			shcmd(lp->n, fp);
-			if (lp->next)
-				fputs(" | ", fp);
-		}
-		if (n->npipe.backgnd)
-			fputs(" &", fp);
-		if (ind >= 0)
-			putc('\n', fp);
-		break;
-	default:
-		fprintf(fp, "<node type %d>", n->type);
-		if (ind >= 0)
-			putc('\n', fp);
-		break;
-	}
-}
-
-
-
-static void
-shcmd(union node *cmd, FILE *fp)
-{
-	union node *np;
-	int first;
-	const char *s;
-	int dftfd;
-
-	first = 1;
-	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
-		if (! first)
-			putchar(' ');
-		sharg(np, fp);
-		first = 0;
-	}
-	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
-		if (! first)
-			putchar(' ');
-		switch (np->nfile.type) {
-			case NTO:	s = ">";  dftfd = 1; break;
-			case NCLOBBER:	s = ">|"; dftfd = 1; break;
-			case NAPPEND:	s = ">>"; dftfd = 1; break;
-			case NTOFD:	s = ">&"; dftfd = 1; break;
-			case NFROM:	s = "<";  dftfd = 0; break;
-			case NFROMFD:	s = "<&"; dftfd = 0; break;
-			case NFROMTO:	s = "<>"; dftfd = 0; break;
-			default:  	s = "*error*"; dftfd = 0; break;
-		}
-		if (np->nfile.fd != dftfd)
-			fprintf(fp, "%d", np->nfile.fd);
-		fputs(s, fp);
-		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
-			fprintf(fp, "%d", np->ndup.dupfd);
-		} else {
-			sharg(np->nfile.fname, fp);
-		}
-		first = 0;
-	}
-}
-
-
-
-static void
-sharg(union node *arg, FILE *fp)
-{
-	char *p;
-	struct nodelist *bqlist;
-	int subtype;
-
-	if (arg->type != NARG) {
-		printf("<node type %d>\n", arg->type);
-		abort();
-	}
-	bqlist = arg->narg.backquote;
-	for (p = arg->narg.text ; *p ; p++) {
-		switch (*p) {
-		case CTLESC:
-			putc(*++p, fp);
-			break;
-		case CTLVAR:
-			putc('$', fp);
-			putc('{', fp);
-			subtype = *++p;
-			if (subtype == VSLENGTH)
-				putc('#', fp);
-
-			while (*p != '=')
-				putc(*p++, fp);
-
-			if (subtype & VSNUL)
-				putc(':', fp);
-
-			switch (subtype & VSTYPE) {
-			case VSNORMAL:
-				putc('}', fp);
-				break;
-			case VSMINUS:
-				putc('-', fp);
-				break;
-			case VSPLUS:
-				putc('+', fp);
-				break;
-			case VSQUESTION:
-				putc('?', fp);
-				break;
-			case VSASSIGN:
-				putc('=', fp);
-				break;
-			case VSTRIMLEFT:
-				putc('#', fp);
-				break;
-			case VSTRIMLEFTMAX:
-				putc('#', fp);
-				putc('#', fp);
-				break;
-			case VSTRIMRIGHT:
-				putc('%', fp);
-				break;
-			case VSTRIMRIGHTMAX:
-				putc('%', fp);
-				putc('%', fp);
-				break;
-			case VSLENGTH:
-				break;
-			default:
-				printf("<subtype %d>", subtype);
-			}
-			break;
-		case CTLENDVAR:
-		     putc('}', fp);
-		     break;
-		case CTLBACKQ:
-		case CTLBACKQ|CTLQUOTE:
-			putc('$', fp);
-			putc('(', fp);
-			shtree(bqlist->n, -1, NULL, fp);
-			putc(')', fp);
-			break;
-		default:
-			putc(*p, fp);
-			break;
-		}
-	}
-}
-
-
-static void
-indent(int amount, char *pfx, FILE *fp)
-{
-	int i;
-
-	for (i = 0 ; i < amount ; i++) {
-		if (pfx && i == amount - 1)
-			fputs(pfx, fp);
-		putc('\t', fp);
-	}
-}
-#endif
-
-
-
-/*
- * Debugging stuff.
- */
-
-
-FILE *tracefile;
-
-
-#ifdef DEBUG
-void
-trputc(int c)
-{
-	if (debug != 1)
-		return;
-	putc(c, tracefile);
-}
-#endif
-
-void
-trace(const char *fmt, ...)
-{
-#ifdef DEBUG
-	va_list va;
-
-	if (debug != 1)
-		return;
-	va_start(va, fmt);
-	(void) vfprintf(tracefile, fmt, va);
-	va_end(va);
-#endif
-}
-
-void
-tracev(const char *fmt, va_list va)
-{
-#ifdef DEBUG
-	if (debug != 1)
-		return;
-	(void) vfprintf(tracefile, fmt, va);
-#endif
-}
-
-
-#ifdef DEBUG
-void
-trputs(const char *s)
-{
-	if (debug != 1)
-		return;
-	fputs(s, tracefile);
-}
-
-
-static void
-trstring(char *s)
-{
-	char *p;
-	char c;
-
-	if (debug != 1)
-		return;
-	putc('"', tracefile);
-	for (p = s ; *p ; p++) {
-		switch (*p) {
-		case '\n':  c = 'n';  goto backslash;
-		case '\t':  c = 't';  goto backslash;
-		case '\r':  c = 'r';  goto backslash;
-		case '"':  c = '"';  goto backslash;
-		case '\\':  c = '\\';  goto backslash;
-		case CTLESC:  c = 'e';  goto backslash;
-		case CTLVAR:  c = 'v';  goto backslash;
-		case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
-		case CTLBACKQ:  c = 'q';  goto backslash;
-		case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
-backslash:	  putc('\\', tracefile);
-			putc(c, tracefile);
-			break;
-		default:
-			if (*p >= ' ' && *p <= '~')
-				putc(*p, tracefile);
-			else {
-				putc('\\', tracefile);
-				putc(*p >> 6 & 03, tracefile);
-				putc(*p >> 3 & 07, tracefile);
-				putc(*p & 07, tracefile);
-			}
-			break;
-		}
-	}
-	putc('"', tracefile);
-}
-#endif
-
-
-void
-trargs(char **ap)
-{
-#ifdef DEBUG
-	if (debug != 1)
-		return;
-	while (*ap) {
-		trstring(*ap++);
-		if (*ap)
-			putc(' ', tracefile);
-		else
-			putc('\n', tracefile);
-	}
-#endif
-}
-
-
-#ifdef DEBUG
-void
-opentrace(void)
-{
-	char s[100];
-#ifdef O_APPEND
-	int flags;
-#endif
-
-	if (debug != 1) {
-		if (tracefile)
-			fflush(tracefile);
-		/* leave open because libedit might be using it */
-		return;
-	}
-#ifdef not_this_way
-	{
-		char *p;
-		if ((p = getenv("HOME")) == NULL) {
-			if (geteuid() == 0)
-				p = "/";
-			else
-				p = "/tmp";
-		}
-		scopy(p, s);
-		strcat(s, "/trace");
-	}
-#else
-	scopy("./trace", s);
-#endif /* not_this_way */
-	if (tracefile) {
-		if (!freopen(s, "a", tracefile)) {
-			fprintf(stderr, "Can't re-open %s\n", s);
-			debug = 0;
-			return;
-		}
-	} else {
-		if ((tracefile = fopen(s, "a")) == NULL) {
-			fprintf(stderr, "Can't open %s\n", s);
-			debug = 0;
-			return;
-		}
-	}
-#ifdef O_APPEND
-	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
-		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
-#endif
-	setlinebuf(tracefile);
-	fputs("\nTracing started.\n", tracefile);
-}
-#endif /* DEBUG */
diff --git a/sh/show.h b/sh/show.h
deleted file mode 100644
index 3152ff2..0000000
--- a/sh/show.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*	$NetBSD: show.h,v 1.7 2003/08/07 09:05:38 agc Exp $	*/
-
-/*-
- * Copyright (c) 1995
- *      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.
- * 3. 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.
- *
- *	@(#)show.h	1.1 (Berkeley) 5/4/95
- */
-
-#include <stdarg.h>
-
-union node;
-void showtree(union node *);
-void trace(const char *, ...);
-void tracev(const char *, va_list);
-void trargs(char **);
-#ifdef DEBUG
-void trputc(int);
-void trputs(const char *);
-void opentrace(void);
-#endif
diff --git a/sh/syntax.c b/sh/syntax.c
deleted file mode 100644
index 094f674..0000000
--- a/sh/syntax.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*	$NetBSD: syntax.c,v 1.1 2004/01/17 17:38:12 dsl Exp $	*/
-
-#include "shell.h"
-#include "syntax.h"
-#include "parser.h"
-#include <limits.h>
-
-#if CWORD != 0
-#error initialisation assumes 'CWORD' is zero
-#endif
-
-#define ndx(ch) (ch + 1 - CHAR_MIN)
-#define set(ch, val) [ndx(ch)] = val,
-#define set_range(s, e, val) [ndx(s) ... ndx(e)] = val,
-
-/* syntax table used when not in quotes */
-const char basesyntax[257] = { CEOF,
-    set_range(CTL_FIRST, CTL_LAST, CCTL)
-    set('\n', CNL)
-    set('\\', CBACK)
-    set('\'', CSQUOTE)
-    set('"', CDQUOTE)
-    set('`', CBQUOTE)
-    set('$', CVAR)
-    set('}', CENDVAR)
-    set('<', CSPCL)
-    set('>', CSPCL)
-    set('(', CSPCL)
-    set(')', CSPCL)
-    set(';', CSPCL)
-    set('&', CSPCL)
-    set('|', CSPCL)
-    set(' ', CSPCL)
-    set('\t', CSPCL)
-};
-
-/* syntax table used when in double quotes */
-const char dqsyntax[257] = { CEOF,
-    set_range(CTL_FIRST, CTL_LAST, CCTL)
-    set('\n', CNL)
-    set('\\', CBACK)
-    set('"', CDQUOTE)
-    set('`', CBQUOTE)
-    set('$', CVAR)
-    set('}', CENDVAR)
-    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
-    set('!', CCTL)
-    set('*', CCTL)
-    set('?', CCTL)
-    set('[', CCTL)
-    set('=', CCTL)
-    set('~', CCTL)
-    set(':', CCTL)
-    set('/', CCTL)
-    set('-', CCTL)
-};
-
-/* syntax table used when in single quotes */
-const char sqsyntax[257] = { CEOF,
-    set_range(CTL_FIRST, CTL_LAST, CCTL)
-    set('\n', CNL)
-    set('\'', CSQUOTE)
-    /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
-    set('!', CCTL)
-    set('*', CCTL)
-    set('?', CCTL)
-    set('[', CCTL)
-    set('=', CCTL)
-    set('~', CCTL)
-    set(':', CCTL)
-    set('/', CCTL)
-    set('-', CCTL)
-};
-
-/* syntax table used when in arithmetic */
-const char arisyntax[257] = { CEOF,
-    set_range(CTL_FIRST, CTL_LAST, CCTL)
-    set('\n', CNL)
-    set('\\', CBACK)
-    set('`', CBQUOTE)
-    set('\'', CSQUOTE)
-    set('"', CDQUOTE)
-    set('$', CVAR)
-    set('}', CENDVAR)
-    set('(', CLP)
-    set(')', CRP)
-};
-
-/* character classification table */
-const char is_type[257] = { 0,
-    set_range('0', '9', ISDIGIT)
-    set_range('a', 'z', ISLOWER)
-    set_range('A', 'Z', ISUPPER)
-    set('_', ISUNDER)
-    set('#', ISSPECL)
-    set('?', ISSPECL)
-    set('$', ISSPECL)
-    set('!', ISSPECL)
-    set('-', ISSPECL)
-    set('*', ISSPECL)
-    set('@', ISSPECL)
-};
diff --git a/sh/syntax.h b/sh/syntax.h
deleted file mode 100644
index 89a32dc..0000000
--- a/sh/syntax.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*	$NetBSD: syntax.h,v 1.2 2004/01/17 17:38:12 dsl Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#include <ctype.h>
-
-/* Syntax classes */
-#define CWORD 0			/* character is nothing special */
-#define CNL 1			/* newline character */
-#define CBACK 2			/* a backslash character */
-#define CSQUOTE 3		/* single quote */
-#define CDQUOTE 4		/* double quote */
-#define CBQUOTE 5		/* backwards single quote */
-#define CVAR 6			/* a dollar sign */
-#define CENDVAR 7		/* a '}' character */
-#define CLP 8			/* a left paren in arithmetic */
-#define CRP 9			/* a right paren in arithmetic */
-#define CEOF 10			/* end of file */
-#define CCTL 11			/* like CWORD, except it must be escaped */
-#define CSPCL 12		/* these terminate a word */
-
-/* Syntax classes for is_ functions */
-#define ISDIGIT 01		/* a digit */
-#define ISUPPER 02		/* an upper case letter */
-#define ISLOWER 04		/* a lower case letter */
-#define ISUNDER 010		/* an underscore */
-#define ISSPECL 020		/* the name of a special parameter */
-
-#define PEOF (CHAR_MIN - 1)
-#define SYNBASE (-PEOF)
-/* XXX UPEOF is CHAR_MAX, so is a valid 'char' value... */
-#define UPEOF ((char)PEOF)
-
-
-#define BASESYNTAX (basesyntax + SYNBASE)
-#define DQSYNTAX (dqsyntax + SYNBASE)
-#define SQSYNTAX (sqsyntax + SYNBASE)
-#define ARISYNTAX (arisyntax + SYNBASE)
-
-/* These defines assume that the digits are contiguous */
-#define is_digit(c)	((unsigned)((c) - '0') <= 9)
-#define is_alpha(c)	(((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && isalpha((unsigned char)(c)))
-#define is_name(c)	(((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalpha((unsigned char)(c))))
-#define is_in_name(c)	(((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalnum((unsigned char)(c))))
-#define is_special(c)	((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
-#define digit_val(c)	((c) - '0')
-
-extern const char basesyntax[];
-extern const char dqsyntax[];
-extern const char sqsyntax[];
-extern const char arisyntax[];
-extern const char is_type[];
diff --git a/sh/token.h b/sh/token.h
deleted file mode 100644
index c961f01..0000000
--- a/sh/token.h
+++ /dev/null
@@ -1,112 +0,0 @@
-#define TEOF 0
-#define TNL 1
-#define TSEMI 2
-#define TBACKGND 3
-#define TAND 4
-#define TOR 5
-#define TPIPE 6
-#define TLP 7
-#define TRP 8
-#define TENDCASE 9
-#define TENDBQUOTE 10
-#define TREDIR 11
-#define TWORD 12
-#define TIF 13
-#define TTHEN 14
-#define TELSE 15
-#define TELIF 16
-#define TFI 17
-#define TWHILE 18
-#define TUNTIL 19
-#define TFOR 20
-#define TDO 21
-#define TDONE 22
-#define TBEGIN 23
-#define TEND 24
-#define TCASE 25
-#define TESAC 26
-#define TNOT 27
-
-/* Array indicating which tokens mark the end of a list */
-const char tokendlist[] = {
-	1,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	1,
-	1,
-	1,
-	0,
-	0,
-	0,
-	1,
-	1,
-	1,
-	1,
-	0,
-	0,
-	0,
-	1,
-	1,
-	0,
-	1,
-	0,
-	1,
-	0,
-};
-
-const char *const tokname[] = {
-	"end of file",
-	"newline",
-	"\";\"",
-	"\"&\"",
-	"\"&&\"",
-	"\"||\"",
-	"\"|\"",
-	"\"(\"",
-	"\")\"",
-	"\";;\"",
-	"\"`\"",
-	"redirection",
-	"word",
-	"\"if\"",
-	"\"then\"",
-	"\"else\"",
-	"\"elif\"",
-	"\"fi\"",
-	"\"while\"",
-	"\"until\"",
-	"\"for\"",
-	"\"do\"",
-	"\"done\"",
-	"\"{\"",
-	"\"}\"",
-	"\"case\"",
-	"\"esac\"",
-	"\"!\"",
-};
-
-#define KWDOFFSET 13
-
-const char *const parsekwd[] = {
-	"if",
-	"then",
-	"else",
-	"elif",
-	"fi",
-	"while",
-	"until",
-	"for",
-	"do",
-	"done",
-	"{",
-	"}",
-	"case",
-	"esac",
-	"!",
-	0
-};
diff --git a/sh/trap.c b/sh/trap.c
deleted file mode 100644
index dcd76ac..0000000
--- a/sh/trap.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*	$NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)trap.c	8.5 (Berkeley) 6/5/95";
-#else
-__RCSID("$NetBSD: trap.c,v 1.31 2005/01/11 19:38:57 christos Exp $");
-#endif
-#endif /* not lint */
-
-#include <signal.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include "shell.h"
-#include "main.h"
-#include "nodes.h"	/* for other headers */
-#include "eval.h"
-#include "jobs.h"
-#include "show.h"
-#include "options.h"
-#include "syntax.h"
-#include "output.h"
-#include "memalloc.h"
-#include "error.h"
-#include "trap.h"
-#include "mystring.h"
-#include "var.h"
-
-/*
- * Sigmode records the current value of the signal handlers for the various
- * modes.  A value of zero means that the current handler is not known.
- * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
- */
-
-#define S_DFL 1			/* default signal handling (SIG_DFL) */
-#define S_CATCH 2		/* signal is caught */
-#define S_IGN 3			/* signal is ignored (SIG_IGN) */
-#define S_HARD_IGN 4		/* signal is ignored permenantly */
-#define S_RESET 5		/* temporary - to reset a hard ignored sig */
-
-
-char *trap[NSIG+1];		/* trap handler commands */
-MKINIT char sigmode[NSIG];	/* current value of signal */
-char gotsig[NSIG];		/* indicates specified signal received */
-int pendingsigs;		/* indicates some signal received */
-
-static int getsigaction(int, sig_t *);
-
-/*
- * return the signal number described by `p' (as a number or a name)
- * or -1 if it isn't one
- */
-
-static int
-signame_to_signum(const char *p)
-{
-	int i;
-
-	if (is_number(p))
-		return number(p);
-
-	if (strcasecmp(p, "exit") == 0 )
-		return 0;
-	
-	if (strncasecmp(p, "sig", 3) == 0)
-		p += 3;
-
-	for (i = 0; i < NSIG; ++i)
-		if (sys_signame[i] && (strcasecmp (p, sys_signame[i]) == 0))
-			return i;
-	return -1;
-}
-
-/*
- * Print a list of valid signal names
- */
-static void
-printsignals(void)
-{
-	int n;
-
-	out1str("EXIT ");
-
-	for (n = 1; n < NSIG; n++) {
-		out1fmt("%s", sys_signame[n]);
-		if ((n == NSIG/2) ||  n == (NSIG - 1))
-			out1str("\n");
-		else
-			out1c(' ');
-	}
-}
-
-/*
- * The trap builtin.
- */
-
-int
-trapcmd(int argc, char **argv)
-{
-	char *action;
-	char **ap;
-	int signo;
-
-	if (argc <= 1) {
-		for (signo = 0 ; signo <= NSIG ; signo++)
-			if (trap[signo] != NULL) {
-				out1fmt("trap -- ");
-				print_quoted(trap[signo]);
-				out1fmt(" %s\n",
-				    (signo) ? sys_signame[signo] : "EXIT");
-			}
-		return 0;
-	}
-	ap = argv + 1;
-
-	action = NULL;
-
-	if (strcmp(*ap, "--") == 0)
-		if (*++ap == NULL)
-			return 0;
-
-	if (signame_to_signum(*ap) == -1) {
-		if ((*ap)[0] == '-') {
-			if ((*ap)[1] == '\0')
-				ap++;
-			else if ((*ap)[1] == 'l' && (*ap)[2] == '\0') {
-				printsignals();
-				return 0;
-			}
-			else
-				error("bad option %s\n", *ap);
-		}
-		else
-			action = *ap++;
-	}
-
-	while (*ap) {
-		if (is_number(*ap))
-			signo = number(*ap);
-		else
-			signo = signame_to_signum(*ap);
-
-		if (signo < 0 || signo > NSIG)
-			error("%s: bad trap", *ap);
-
-		INTOFF;
-		if (action)
-			action = savestr(action);
-
-		if (trap[signo])
-			ckfree(trap[signo]);
-
-		trap[signo] = action;
-
-		if (signo != 0)
-			setsignal(signo, 0);
-		INTON;
-		ap++;
-	}
-	return 0;
-}
-
-
-
-/*
- * Clear traps on a fork or vfork.
- * Takes one arg vfork, to tell it to not be destructive of
- * the parents variables.
- */
-
-void
-clear_traps(int vforked)
-{
-	char **tp;
-
-	for (tp = trap ; tp <= &trap[NSIG] ; tp++) {
-		if (*tp && **tp) {	/* trap not NULL or SIG_IGN */
-			INTOFF;
-			if (!vforked) {
-				ckfree(*tp);
-				*tp = NULL;
-			}
-			if (tp != &trap[0])
-				setsignal(tp - trap, vforked);
-			INTON;
-		}
-	}
-}
-
-
-
-/*
- * Set the signal handler for the specified signal.  The routine figures
- * out what it should be set to.
- */
-
-long
-setsignal(int signo, int vforked)
-{
-	int action;
-	sig_t sigact = SIG_DFL;
-	struct sigaction act, oact;
-	char *t, tsig;
-
-	if ((t = trap[signo]) == NULL)
-		action = S_DFL;
-	else if (*t != '\0')
-		action = S_CATCH;
-	else
-		action = S_IGN;
-	if (rootshell && !vforked && action == S_DFL) {
-		switch (signo) {
-		case SIGINT:
-			if (iflag || minusc || sflag == 0)
-				action = S_CATCH;
-			break;
-		case SIGQUIT:
-#ifdef DEBUG
-			if (debug)
-				break;
-#endif
-			/* FALLTHROUGH */
-		case SIGTERM:
-			if (iflag)
-				action = S_IGN;
-			break;
-#if JOBS
-		case SIGTSTP:
-		case SIGTTOU:
-			if (mflag)
-				action = S_IGN;
-			break;
-#endif
-		}
-	}
-
-	t = &sigmode[signo - 1];
-	tsig = *t;
-	if (tsig == 0) {
-		/*
-		 * current setting unknown
-		 */
-		if (!getsigaction(signo, &sigact)) {
-			/*
-			 * Pretend it worked; maybe we should give a warning
-			 * here, but other shells don't. We don't alter
-			 * sigmode, so that we retry every time.
-			 */
-			return 0;
-		}
-		if (sigact == SIG_IGN) {
-			if (mflag && (signo == SIGTSTP ||
-			     signo == SIGTTIN || signo == SIGTTOU)) {
-				tsig = S_IGN;	/* don't hard ignore these */
-			} else
-				tsig = S_HARD_IGN;
-		} else {
-			tsig = S_RESET;	/* force to be set */
-		}
-	}
-	if (tsig == S_HARD_IGN || tsig == action)
-		return 0;
-	switch (action) {
-		case S_DFL:	sigact = SIG_DFL;	break;
-		case S_CATCH:  	sigact = onsig;		break;
-		case S_IGN:	sigact = SIG_IGN;	break;
-	}
-	if (!vforked)
-		*t = action;
-    act.sa_handler = sigact;
-    sigemptyset(&act.sa_mask);
-    act.sa_flags = 0;
-#ifdef SA_INTERRUPT
-    act.sa_flags |= SA_INTERRUPT;
-#endif
-    if(sigaction(signo, &act, &oact) < 0)
-        return (long) SIG_ERR;
-    return (long) oact.sa_handler;
-}
-
-/*
- * Return the current setting for sig w/o changing it.
- */
-static int
-getsigaction(int signo, sig_t *sigact)
-{
-	struct sigaction sa;
-
-	if (sigaction(signo, (struct sigaction *)0, &sa) == -1)
-		return 0;
-	*sigact = (sig_t) sa.sa_handler;
-	return 1;
-}
-
-/*
- * Ignore a signal.
- */
-
-void
-ignoresig(int signo, int vforked)
-{
-	if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN)
-		bsd_signal(signo, SIG_IGN);
-	if (!vforked)
-		sigmode[signo - 1] = S_HARD_IGN;
-}
-
-
-#ifdef mkinit
-INCLUDE <signal.h>
-INCLUDE "trap.h"
-
-SHELLPROC {
-	char *sm;
-
-	clear_traps(0);
-	for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
-		if (*sm == S_IGN)
-			*sm = S_HARD_IGN;
-	}
-}
-#endif
-
-
-
-/*
- * Signal handler.
- */
-
-void
-onsig(int signo)
-{
-	bsd_signal(signo, onsig);
-	if (signo == SIGINT && trap[SIGINT] == NULL) {
-		onint();
-		return;
-	}
-	gotsig[signo - 1] = 1;
-	pendingsigs++;
-}
-
-
-
-/*
- * Called to execute a trap.  Perhaps we should avoid entering new trap
- * handlers while we are executing a trap handler.
- */
-
-void
-dotrap(void)
-{
-	int i;
-	int savestatus;
-
-	for (;;) {
-		for (i = 1 ; ; i++) {
-			if (gotsig[i - 1])
-				break;
-			if (i >= NSIG)
-				goto done;
-		}
-		gotsig[i - 1] = 0;
-		savestatus=exitstatus;
-		evalstring(trap[i], 0);
-		exitstatus=savestatus;
-	}
-done:
-	pendingsigs = 0;
-}
-
-
-
-/*
- * Controls whether the shell is interactive or not.
- */
-
-
-void
-setinteractive(int on)
-{
-	static int is_interactive;
-
-	if (on == is_interactive)
-		return;
-	setsignal(SIGINT, 0);
-	setsignal(SIGQUIT, 0);
-	setsignal(SIGTERM, 0);
-	is_interactive = on;
-}
-
-
-
-/*
- * Called to exit the shell.
- */
-
-void
-exitshell(int status)
-{
-	struct jmploc loc1, loc2;
-	char *p;
-
-	TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
-	if (setjmp(loc1.loc)) {
-		goto l1;
-	}
-	if (setjmp(loc2.loc)) {
-		goto l2;
-	}
-	handler = &loc1;
-	if ((p = trap[0]) != NULL && *p != '\0') {
-		trap[0] = NULL;
-		evalstring(p, 0);
-	}
-l1:   handler = &loc2;			/* probably unnecessary */
-	flushall();
-#if JOBS
-	setjobctl(0);
-#endif
-l2:   _exit(status);
-	/* NOTREACHED */
-}
diff --git a/sh/trap.h b/sh/trap.h
deleted file mode 100644
index 125ef40..0000000
--- a/sh/trap.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*	$NetBSD: trap.h,v 1.17 2003/08/07 09:05:39 agc Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)trap.h	8.3 (Berkeley) 6/5/95
- */
-
-extern int pendingsigs;
-
-int trapcmd(int, char **);
-void clear_traps(int);
-long setsignal(int, int);
-void ignoresig(int, int);
-void onsig(int);
-void dotrap(void);
-void setinteractive(int);
-void exitshell(int) __attribute__((__noreturn__));
diff --git a/sh/var.c b/sh/var.c
deleted file mode 100644
index a1f1689..0000000
--- a/sh/var.c
+++ /dev/null
@@ -1,825 +0,0 @@
-/*	$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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 <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 5/4/95";
-#else
-__RCSID("$NetBSD: var.c,v 1.36 2004/10/06 10:23:43 enami Exp $");
-#endif
-#endif /* not lint */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <paths.h>
-
-/*
- * Shell variables.
- */
-
-#include "shell.h"
-#include "output.h"
-#include "expand.h"
-#include "nodes.h"	/* for other headers */
-#include "eval.h"	/* defines cmdenviron */
-#include "exec.h"
-#include "syntax.h"
-#include "options.h"
-#include "var.h"
-#include "memalloc.h"
-#include "error.h"
-#include "mystring.h"
-#include "parser.h"
-#include "show.h"
-#ifndef SMALL
-#include "myhistedit.h"
-#endif
-
-#ifdef SMALL
-#define VTABSIZE 39
-#else
-#define VTABSIZE 517
-#endif
-
-
-struct varinit {
-	struct var *var;
-	int flags;
-	const char *text;
-	void (*func)(const char *);
-};
-
-
-#if ATTY
-struct var vatty;
-#endif
-#ifdef WITH_HISTORY
-struct var vhistsize;
-struct var vterm;
-#endif
-struct var vifs;
-struct var vmpath;
-struct var vpath;
-struct var vps1;
-struct var vps2;
-struct var vps4;
-struct var vvers;
-struct var voptind;
-
-const struct varinit varinit[] = {
-#if ATTY
-	{ &vatty,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY=",
-	  NULL },
-#endif
-#ifdef WITH_HISTORY
-	{ &vhistsize,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE=",
-	  sethistsize },
-#endif
-	{ &vifs,	VSTRFIXED|VTEXTFIXED,		"IFS= \t\n",
-	  NULL },
-	{ &vmpath,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH=",
-	  NULL },
-	{ &vpath,	VSTRFIXED|VTEXTFIXED,		"PATH=" _PATH_DEFPATH,
-	  changepath },
-	/*
-	 * vps1 depends on uid
-	 */
-	{ &vps2,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",
-	  NULL },
-	{ &vps4,	VSTRFIXED|VTEXTFIXED,		"PS4=+ ",
-	  NULL },
-#ifdef WITH_HISTORY
-	{ &vterm,	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM=",
-	  setterm },
-#endif
-	{ &voptind,	VSTRFIXED|VTEXTFIXED|VNOFUNC,	"OPTIND=1",
-	  getoptsreset },
-	{ NULL,	0,				NULL,
-	  NULL }
-};
-
-struct var *vartab[VTABSIZE];
-
-STATIC int strequal(const char *, const char *);
-STATIC struct var *find_var(const char *, struct var ***, int *);
-
-/*
- * Initialize the varable symbol tables and import the environment
- */
-
-#ifdef mkinit
-INCLUDE "var.h"
-MKINIT char **environ;
-INIT {
-	char **envp;
-
-	initvar();
-	for (envp = environ ; *envp ; envp++) {
-		if (strchr(*envp, '=')) {
-			setvareq(*envp, VEXPORT|VTEXTFIXED);
-		}
-	}
-}
-#endif
-
-
-/*
- * This routine initializes the builtin variables.  It is called when the
- * shell is initialized and again when a shell procedure is spawned.
- */
-
-void
-initvar(void)
-{
-	const struct varinit *ip;
-	struct var *vp;
-	struct var **vpp;
-
-	for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
-		if (find_var(ip->text, &vpp, &vp->name_len) != NULL)
-			continue;
-		vp->next = *vpp;
-		*vpp = vp;
-		vp->text = strdup(ip->text);
-		vp->flags = ip->flags;
-		vp->func = ip->func;
-	}
-	/*
-	 * PS1 depends on uid
-	 */
-	if (find_var("PS1", &vpp, &vps1.name_len) == NULL) {
-		vps1.next = *vpp;
-		*vpp = &vps1;
-		vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
-		vps1.flags = VSTRFIXED|VTEXTFIXED;
-	}
-}
-
-/*
- * Safe version of setvar, returns 1 on success 0 on failure.
- */
-
-int
-setvarsafe(const char *name, const char *val, int flags)
-{
-	struct jmploc jmploc;
-	struct jmploc *volatile savehandler = handler;
-	int err = 0;
-#ifdef __GNUC__
-	(void) &err;
-#endif
-
-	if (setjmp(jmploc.loc))
-		err = 1;
-	else {
-		handler = &jmploc;
-		setvar(name, val, flags);
-	}
-	handler = savehandler;
-	return err;
-}
-
-/*
- * Set the value of a variable.  The flags argument is ored with the
- * flags of the variable.  If val is NULL, the variable is unset.
- */
-
-void
-setvar(const char *name, const char *val, int flags)
-{
-	const char *p;
-	const char *q;
-	char *d;
-	int len;
-	int namelen;
-	char *nameeq;
-	int isbad;
-
-	isbad = 0;
-	p = name;
-	if (! is_name(*p))
-		isbad = 1;
-	p++;
-	for (;;) {
-		if (! is_in_name(*p)) {
-			if (*p == '\0' || *p == '=')
-				break;
-			isbad = 1;
-		}
-		p++;
-	}
-	namelen = p - name;
-	if (isbad)
-		error("%.*s: bad variable name", namelen, name);
-	len = namelen + 2;		/* 2 is space for '=' and '\0' */
-	if (val == NULL) {
-		flags |= VUNSET;
-	} else {
-		len += strlen(val);
-	}
-	d = nameeq = ckmalloc(len);
-	q = name;
-	while (--namelen >= 0)
-		*d++ = *q++;
-	*d++ = '=';
-	*d = '\0';
-	if (val)
-		scopy(val, d);
-	setvareq(nameeq, flags);
-}
-
-
-
-/*
- * Same as setvar except that the variable and value are passed in
- * the first argument as name=value.  Since the first argument will
- * be actually stored in the table, it should not be a string that
- * will go away.
- */
-
-void
-setvareq(char *s, int flags)
-{
-	struct var *vp, **vpp;
-	int nlen;
-
-	if (aflag)
-		flags |= VEXPORT;
-	vp = find_var(s, &vpp, &nlen);
-	if (vp != NULL) {
-		if (vp->flags & VREADONLY)
-			error("%.*s: is read only", vp->name_len, s);
-		if (flags & VNOSET)
-			return;
-		INTOFF;
-
-		if (vp->func && (flags & VNOFUNC) == 0)
-			(*vp->func)(s + vp->name_len + 1);
-
-		if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
-			ckfree(vp->text);
-
-		vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
-		vp->flags |= flags & ~VNOFUNC;
-		vp->text = s;
-
-		INTON;
-		return;
-	}
-	/* not found */
-	if (flags & VNOSET)
-		return;
-	vp = ckmalloc(sizeof (*vp));
-	vp->flags = flags & ~VNOFUNC;
-	vp->text = s;
-	vp->name_len = nlen;
-	vp->next = *vpp;
-	vp->func = NULL;
-	*vpp = vp;
-}
-
-
-
-/*
- * Process a linked list of variable assignments.
- */
-
-void
-listsetvar(struct strlist *list, int flags)
-{
-	struct strlist *lp;
-
-	INTOFF;
-	for (lp = list ; lp ; lp = lp->next) {
-		setvareq(savestr(lp->text), flags);
-	}
-	INTON;
-}
-
-void
-listmklocal(struct strlist *list, int flags)
-{
-	struct strlist *lp;
-
-	for (lp = list ; lp ; lp = lp->next)
-		mklocal(lp->text, flags);
-}
-
-
-/*
- * Find the value of a variable.  Returns NULL if not set.
- */
-
-char *
-lookupvar(const char *name)
-{
-	struct var *v;
-
-	v = find_var(name, NULL, NULL);
-	if (v == NULL || v->flags & VUNSET)
-		return NULL;
-	return v->text + v->name_len + 1;
-}
-
-
-
-/*
- * Search the environment of a builtin command.  If the second argument
- * is nonzero, return the value of a variable even if it hasn't been
- * exported.
- */
-
-char *
-bltinlookup(const char *name, int doall)
-{
-	struct strlist *sp;
-	struct var *v;
-
-	for (sp = cmdenviron ; sp ; sp = sp->next) {
-		if (strequal(sp->text, name))
-			return strchr(sp->text, '=') + 1;
-	}
-
-	v = find_var(name, NULL, NULL);
-
-	if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT)))
-		return NULL;
-	return v->text + v->name_len + 1;
-}
-
-
-
-/*
- * Generate a list of exported variables.  This routine is used to construct
- * the third argument to execve when executing a program.
- */
-
-char **
-environment(void)
-{
-	int nenv;
-	struct var **vpp;
-	struct var *vp;
-	char **env;
-	char **ep;
-
-	nenv = 0;
-	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
-		for (vp = *vpp ; vp ; vp = vp->next)
-			if (vp->flags & VEXPORT)
-				nenv++;
-	}
-	ep = env = stalloc((nenv + 1) * sizeof *env);
-	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
-		for (vp = *vpp ; vp ; vp = vp->next)
-			if (vp->flags & VEXPORT)
-				*ep++ = vp->text;
-	}
-	*ep = NULL;
-	return env;
-}
-
-
-/*
- * Called when a shell procedure is invoked to clear out nonexported
- * variables.  It is also necessary to reallocate variables of with
- * VSTACK set since these are currently allocated on the stack.
- */
-
-#ifdef mkinit
-void shprocvar(void);
-
-SHELLPROC {
-	shprocvar();
-}
-#endif
-
-void
-shprocvar(void)
-{
-	struct var **vpp;
-	struct var *vp, **prev;
-
-	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
-		for (prev = vpp ; (vp = *prev) != NULL ; ) {
-			if ((vp->flags & VEXPORT) == 0) {
-				*prev = vp->next;
-				if ((vp->flags & VTEXTFIXED) == 0)
-					ckfree(vp->text);
-				if ((vp->flags & VSTRFIXED) == 0)
-					ckfree(vp);
-			} else {
-				if (vp->flags & VSTACK) {
-					vp->text = savestr(vp->text);
-					vp->flags &=~ VSTACK;
-				}
-				prev = &vp->next;
-			}
-		}
-	}
-	initvar();
-}
-
-
-
-/*
- * Command to list all variables which are set.  Currently this command
- * is invoked from the set command when the set command is called without
- * any variables.
- */
-
-void
-print_quoted(const char *p)
-{
-	const char *q;
-
-	if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) {
-		out1fmt("%s", p);
-		return;
-	}
-	while (*p) {
-		if (*p == '\'') {
-			out1fmt("\\'");
-			p++;
-			continue;
-		}
-		q = index(p, '\'');
-		if (!q) {
-			out1fmt("'%s'", p );
-			return;
-		}
-		out1fmt("'%.*s'", (int)(q - p), p );
-		p = q;
-	}
-}
-
-static int
-sort_var(const void *v_v1, const void *v_v2)
-{
-	const struct var * const *v1 = v_v1;
-	const struct var * const *v2 = v_v2;
-
-	/* XXX Will anyone notice we include the '=' of the shorter name? */
-	return strcmp((*v1)->text, (*v2)->text);
-}
-
-/*
- * POSIX requires that 'set' (but not export or readonly) output the
- * variables in lexicographic order - by the locale's collating order (sigh).
- * Maybe we could keep them in an ordered balanced binary tree
- * instead of hashed lists.
- * For now just roll 'em through qsort for printing...
- */
-
-int
-showvars(const char *name, int flag, int show_value)
-{
-	struct var **vpp;
-	struct var *vp;
-	const char *p;
-
-	static struct var **list;	/* static in case we are interrupted */
-	static int list_len;
-	int count = 0;
-
-	if (!list) {
-		list_len = 32;
-		list = ckmalloc(list_len * sizeof *list);
-	}
-
-	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
-		for (vp = *vpp ; vp ; vp = vp->next) {
-			if (flag && !(vp->flags & flag))
-				continue;
-			if (vp->flags & VUNSET && !(show_value & 2))
-				continue;
-			if (count >= list_len) {
-				list = ckrealloc(list,
-					(list_len << 1) * sizeof *list);
-				list_len <<= 1;
-			}
-			list[count++] = vp;
-		}
-	}
-
-	qsort(list, count, sizeof *list, sort_var);
-
-	for (vpp = list; count--; vpp++) {
-		vp = *vpp;
-		if (name)
-			out1fmt("%s ", name);
-		for (p = vp->text ; *p != '=' ; p++)
-			out1c(*p);
-		if (!(vp->flags & VUNSET) && show_value) {
-			out1fmt("=");
-			print_quoted(++p);
-		}
-		out1c('\n');
-	}
-	return 0;
-}
-
-
-
-/*
- * The export and readonly commands.
- */
-
-int
-exportcmd(int argc, char **argv)
-{
-	struct var *vp;
-	char *name;
-	const char *p;
-	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
-	int pflag;
-
-	pflag = nextopt("p") == 'p' ? 3 : 0;
-	if (argc <= 1 || pflag) {
-		showvars( pflag ? argv[0] : 0, flag, pflag );
-		return 0;
-	}
-
-	while ((name = *argptr++) != NULL) {
-		if ((p = strchr(name, '=')) != NULL) {
-			p++;
-		} else {
-			vp = find_var(name, NULL, NULL);
-			if (vp != NULL) {
-				vp->flags |= flag;
-				continue;
-			}
-		}
-		setvar(name, p, flag);
-	}
-	return 0;
-}
-
-
-/*
- * The "local" command.
- */
-
-int
-localcmd(int argc, char **argv)
-{
-	char *name;
-
-	if (! in_function())
-		error("Not in a function");
-	while ((name = *argptr++) != NULL) {
-		mklocal(name, 0);
-	}
-	return 0;
-}
-
-
-/*
- * Make a variable a local variable.  When a variable is made local, it's
- * value and flags are saved in a localvar structure.  The saved values
- * will be restored when the shell function returns.  We handle the name
- * "-" as a special case.
- */
-
-void
-mklocal(const char *name, int flags)
-{
-	struct localvar *lvp;
-	struct var **vpp;
-	struct var *vp;
-
-	INTOFF;
-	lvp = ckmalloc(sizeof (struct localvar));
-	if (name[0] == '-' && name[1] == '\0') {
-		char *p;
-		p = ckmalloc(sizeof_optlist);
-		lvp->text = memcpy(p, optlist, sizeof_optlist);
-		vp = NULL;
-	} else {
-		vp = find_var(name, &vpp, NULL);
-		if (vp == NULL) {
-			if (strchr(name, '='))
-				setvareq(savestr(name), VSTRFIXED|flags);
-			else
-				setvar(name, NULL, VSTRFIXED|flags);
-			vp = *vpp;	/* the new variable */
-			lvp->text = NULL;
-			lvp->flags = VUNSET;
-		} else {
-			lvp->text = vp->text;
-			lvp->flags = vp->flags;
-			vp->flags |= VSTRFIXED|VTEXTFIXED;
-			if (name[vp->name_len] == '=')
-				setvareq(savestr(name), flags);
-		}
-	}
-	lvp->vp = vp;
-	lvp->next = localvars;
-	localvars = lvp;
-	INTON;
-}
-
-
-/*
- * Called after a function returns.
- */
-
-void
-poplocalvars(void)
-{
-	struct localvar *lvp;
-	struct var *vp;
-
-	while ((lvp = localvars) != NULL) {
-		localvars = lvp->next;
-		vp = lvp->vp;
-		TRACE(("poplocalvar %s", vp ? vp->text : "-"));
-		if (vp == NULL) {	/* $- saved */
-			memcpy(optlist, lvp->text, sizeof_optlist);
-			ckfree(lvp->text);
-		} else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
-			(void)unsetvar(vp->text, 0);
-		} else {
-			if (vp->func && (vp->flags & VNOFUNC) == 0)
-				(*vp->func)(lvp->text + vp->name_len + 1);
-			if ((vp->flags & VTEXTFIXED) == 0)
-				ckfree(vp->text);
-			vp->flags = lvp->flags;
-			vp->text = lvp->text;
-		}
-		ckfree(lvp);
-	}
-}
-
-
-int
-setvarcmd(int argc, char **argv)
-{
-	if (argc <= 2)
-		return unsetcmd(argc, argv);
-	else if (argc == 3)
-		setvar(argv[1], argv[2], 0);
-	else
-		error("List assignment not implemented");
-	return 0;
-}
-
-
-/*
- * The unset builtin command.  We unset the function before we unset the
- * variable to allow a function to be unset when there is a readonly variable
- * with the same name.
- */
-
-int
-unsetcmd(int argc, char **argv)
-{
-	char **ap;
-	int i;
-	int flg_func = 0;
-	int flg_var = 0;
-	int ret = 0;
-
-	while ((i = nextopt("evf")) != '\0') {
-		if (i == 'f')
-			flg_func = 1;
-		else
-			flg_var = i;
-	}
-	if (flg_func == 0 && flg_var == 0)
-		flg_var = 1;
-
-	for (ap = argptr; *ap ; ap++) {
-		if (flg_func)
-			ret |= unsetfunc(*ap);
-		if (flg_var)
-			ret |= unsetvar(*ap, flg_var == 'e');
-	}
-	return ret;
-}
-
-
-/*
- * Unset the specified variable.
- */
-
-int
-unsetvar(const char *s, int unexport)
-{
-	struct var **vpp;
-	struct var *vp;
-
-	vp = find_var(s, &vpp, NULL);
-	if (vp == NULL)
-		return 1;
-
-	if (vp->flags & VREADONLY)
-		return (1);
-
-	INTOFF;
-	if (unexport) {
-		vp->flags &= ~VEXPORT;
-	} else {
-		if (vp->text[vp->name_len + 1] != '\0')
-			setvar(s, nullstr, 0);
-		vp->flags &= ~VEXPORT;
-		vp->flags |= VUNSET;
-		if ((vp->flags & VSTRFIXED) == 0) {
-			if ((vp->flags & VTEXTFIXED) == 0)
-				ckfree(vp->text);
-			*vpp = vp->next;
-			ckfree(vp);
-		}
-	}
-	INTON;
-	return 0;
-}
-
-
-/*
- * Returns true if the two strings specify the same varable.  The first
- * variable name is terminated by '='; the second may be terminated by
- * either '=' or '\0'.
- */
-
-STATIC int
-strequal(const char *p, const char *q)
-{
-	while (*p == *q++) {
-		if (*p++ == '=')
-			return 1;
-	}
-	if (*p == '=' && *(q - 1) == '\0')
-		return 1;
-	return 0;
-}
-
-/*
- * Search for a variable.
- * 'name' may be terminated by '=' or a NUL.
- * vppp is set to the pointer to vp, or the list head if vp isn't found
- * lenp is set to the number of charactets in 'name'
- */
-
-STATIC struct var *
-find_var(const char *name, struct var ***vppp, int *lenp)
-{
-	unsigned int hashval;
-	int len;
-	struct var *vp, **vpp;
-	const char *p = name;
-
-	hashval = 0;
-	while (*p && *p != '=')
-		hashval = 2 * hashval + (unsigned char)*p++;
-	len = p - name;
-
-	if (lenp)
-		*lenp = len;
-	vpp = &vartab[hashval % VTABSIZE];
-	if (vppp)
-		*vppp = vpp;
-
-	for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) {
-		if (vp->name_len != len)
-			continue;
-		if (memcmp(vp->text, name, len) != 0)
-			continue;
-		if (vppp)
-			*vppp = vpp;
-		return vp;
-	}
-	return NULL;
-}
diff --git a/sh/var.h b/sh/var.h
deleted file mode 100644
index b7b7db8..0000000
--- a/sh/var.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*	$NetBSD: var.h,v 1.23 2004/10/02 12:16:53 dsl Exp $	*/
-
-/*-
- * Copyright (c) 1991, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Kenneth Almquist.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. 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.
- *
- *	@(#)var.h	8.2 (Berkeley) 5/4/95
- */
-
-/*
- * Shell variables.
- */
-
-/* flags */
-#define VEXPORT		0x01	/* variable is exported */
-#define VREADONLY	0x02	/* variable cannot be modified */
-#define VSTRFIXED	0x04	/* variable struct is statically allocated */
-#define VTEXTFIXED	0x08	/* text is statically allocated */
-#define VSTACK		0x10	/* text is allocated on the stack */
-#define VUNSET		0x20	/* the variable is not set */
-#define VNOFUNC		0x40	/* don't call the callback function */
-#define VNOSET		0x80	/* do not set variable - just readonly test */
-
-
-struct var {
-	struct var *next;		/* next entry in hash list */
-	int flags;			/* flags are defined above */
-	char *text;			/* name=value */
-	int name_len;			/* length of name */
-	void (*func)(const char *);
-					/* function to be called when  */
-					/* the variable gets set/unset */
-};
-
-
-struct localvar {
-	struct localvar *next;		/* next local variable in list */
-	struct var *vp;			/* the variable that was made local */
-	int flags;			/* saved flags */
-	char *text;			/* saved text */
-};
-
-
-struct localvar *localvars;
-
-#if ATTY
-extern struct var vatty;
-#endif
-extern struct var vifs;
-extern struct var vmpath;
-extern struct var vpath;
-extern struct var vps1;
-extern struct var vps2;
-extern struct var vps4;
-#ifdef WITH_HISTORY 
-extern struct var vterm;
-extern struct var vtermcap;
-extern struct var vhistsize;
-#endif
-
-/*
- * The following macros access the values of the above variables.
- * They have to skip over the name.  They return the null string
- * for unset variables.
- */
-
-#define ifsval()	(vifs.text + 4)
-#define ifsset()	((vifs.flags & VUNSET) == 0)
-#define mpathval()	(vmpath.text + 9)
-#define pathval()	(vpath.text + 5)
-#define ps1val()	(vps1.text + 4)
-#define ps2val()	(vps2.text + 4)
-#define ps4val()	(vps4.text + 4)
-#define optindval()	(voptind.text + 7)
-#ifdef WITH_HISTORY
-#define histsizeval()	(vhistsize.text + 9)
-#define termval()	(vterm.text + 5)
-#endif
-
-#if ATTY
-#define attyset()	((vatty.flags & VUNSET) == 0)
-#endif
-#define mpathset()	((vmpath.flags & VUNSET) == 0)
-
-void initvar(void);
-void setvar(const char *, const char *, int);
-void setvareq(char *, int);
-struct strlist;
-void listsetvar(struct strlist *, int);
-char *lookupvar(const char *);
-char *bltinlookup(const char *, int);
-char **environment(void);
-void shprocvar(void);
-int showvars(const char *, int, int);
-int exportcmd(int, char **);
-int localcmd(int, char **);
-void mklocal(const char *, int);
-void listmklocal(struct strlist *, int);
-void poplocalvars(void);
-int setvarcmd(int, char **);
-int unsetcmd(int, char **);
-int unsetvar(const char *, int);
-int setvarsafe(const char *, const char *, int);
-void print_quoted(const char *);
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index c764690..75ce53f 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -16,7 +16,6 @@
 	rm \
 	mkdir \
 	rmdir \
-	reboot \
 	getevent \
 	sendevent \
 	date \
@@ -66,7 +65,11 @@
 	runcon \
 	getsebool \
 	setsebool \
-	load_policy
+	load_policy \
+	swapon \
+	swapoff \
+	mkswap \
+	readlink
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 TOOLS += r
diff --git a/toolbox/log.c b/toolbox/log.c
index f30e6a7..2f020a8 100644
--- a/toolbox/log.c
+++ b/toolbox/log.c
@@ -30,7 +30,7 @@
  */
 
 #include <stdio.h>
-#include <cutils/logd.h>
+#include <log/logd.h>
 #include <ctype.h>
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -130,8 +130,8 @@
     buffer[0] = '\0';
     
     for (i = optind ; i < argc ; i++) {
-        strncat(buffer, argv[i], sizeof(buffer)-1);
-        strncat(buffer, " ", sizeof(buffer)-1);
+        strlcat(buffer, argv[i], sizeof(buffer)-1);
+        strlcat(buffer, " ", sizeof(buffer)-1);
     }
 
     if(buffer[0] == 0) {
diff --git a/toolbox/ls.c b/toolbox/ls.c
index 5324511..8467628 100644
--- a/toolbox/ls.c
+++ b/toolbox/ls.c
@@ -75,23 +75,23 @@
     *out = 0;
 }
 
-static void user2str(unsigned uid, char *out)
+static void user2str(uid_t uid, char *out, size_t out_size)
 {
     struct passwd *pw = getpwuid(uid);
     if(pw) {
-        strcpy(out, pw->pw_name);
+        strlcpy(out, pw->pw_name, out_size);
     } else {
-        sprintf(out, "%d", uid);
+        snprintf(out, out_size, "%d", uid);
     }
 }
 
-static void group2str(unsigned gid, char *out)
+static void group2str(gid_t gid, char *out, size_t out_size)
 {
     struct group *gr = getgrgid(gid);
     if(gr) {
-        strcpy(out, gr->gr_name);
+        strlcpy(out, gr->gr_name, out_size);
     } else {
-        sprintf(out, "%d", gid);
+        snprintf(out, out_size, "%d", gid);
     }
 }
 
@@ -164,8 +164,8 @@
 {
     char date[32];
     char mode[16];
-    char user[16];
-    char group[16];
+    char user[32];
+    char group[32];
     const char *name;
 
     if(!s || !path) {
@@ -182,11 +182,11 @@
 
     mode2str(s->st_mode, mode);
     if (flags & LIST_LONG_NUMERIC) {
-        sprintf(user, "%ld", s->st_uid);
-        sprintf(group, "%ld", s->st_gid);
+        snprintf(user, sizeof(user), "%ld", s->st_uid);
+        snprintf(group, sizeof(group), "%ld", s->st_gid);
     } else {
-        user2str(s->st_uid, user);
-        group2str(s->st_gid, group);
+        user2str(s->st_uid, user, sizeof(user));
+        group2str(s->st_gid, group, sizeof(group));
     }
 
     strftime(date, 32, "%Y-%m-%d %H:%M", localtime((const time_t*)&s->st_mtime));
@@ -209,7 +209,7 @@
         break;
     case S_IFLNK: {
         char linkto[256];
-        int len;
+        ssize_t len;
 
         len = readlink(path, linkto, 256);
         if(len < 0) return -1;
@@ -235,11 +235,11 @@
     return 0;
 }
 
-static int listfile_maclabel(const char *path, struct stat *s, int flags)
+static int listfile_maclabel(const char *path, struct stat *s)
 {
     char mode[16];
-    char user[16];
-    char group[16];
+    char user[32];
+    char group[32];
     char *maclabel = NULL;
     const char *name;
 
@@ -261,8 +261,8 @@
     }
 
     mode2str(s->st_mode, mode);
-    user2str(s->st_uid, user);
-    group2str(s->st_gid, group);
+    user2str(s->st_uid, user, sizeof(user));
+    group2str(s->st_gid, group, sizeof(group));
 
     switch(s->st_mode & S_IFMT) {
     case S_IFLNK: {
@@ -324,7 +324,7 @@
     }
 
     if ((flags & LIST_MACLABEL) != 0) {
-        return listfile_maclabel(pathname, &s, flags);
+        return listfile_maclabel(pathname, &s);
     } else if ((flags & LIST_LONG) != 0) {
         return listfile_long(pathname, &s, flags);
     } else /*((flags & LIST_SIZE) != 0)*/ {
diff --git a/toolbox/lsof.c b/toolbox/lsof.c
index 376a642..113c120 100644
--- a/toolbox/lsof.c
+++ b/toolbox/lsof.c
@@ -54,7 +54,7 @@
     ssize_t parent_length;
 };
 
-void print_header()
+static void print_header()
 {
     printf("%-9s %5s %10s %4s %9s %18s %9s %10s %s\n",
             "COMMAND",
@@ -68,12 +68,12 @@
             "NAME");
 }
 
-void print_type(char *type, struct pid_info_t* info)
+static void print_type(char *type, struct pid_info_t* info)
 {
     static ssize_t link_dest_size;
     static char link_dest[PATH_MAX];
 
-    strncat(info->path, type, sizeof(info->path));
+    strlcat(info->path, type, sizeof(info->path));
     if ((link_dest_size = readlink(info->path, link_dest, sizeof(link_dest)-1)) < 0) {
         if (errno == ENOENT)
             goto out;
@@ -96,7 +96,7 @@
 }
 
 // Prints out all file that have been memory mapped
-void print_maps(struct pid_info_t* info)
+static void print_maps(struct pid_info_t* info)
 {
     FILE *maps;
     char buffer[PATH_MAX + 100];
@@ -107,7 +107,7 @@
     long int inode;
     char file[PATH_MAX];
 
-    strncat(info->path, "maps", sizeof(info->path));
+    strlcat(info->path, "maps", sizeof(info->path));
 
     maps = fopen(info->path, "r");
     if (!maps)
@@ -131,10 +131,10 @@
 }
 
 // Prints out all open file descriptors
-void print_fds(struct pid_info_t* info)
+static void print_fds(struct pid_info_t* info)
 {
     static char* fd_path = "fd/";
-    strncat(info->path, fd_path, sizeof(info->path));
+    strlcat(info->path, fd_path, sizeof(info->path));
 
     int previous_length = info->parent_length;
     info->parent_length += strlen(fd_path);
@@ -163,7 +163,7 @@
     info->path[info->parent_length] = '\0';
 }
 
-void lsof_dumpinfo(pid_t pid)
+static void lsof_dumpinfo(pid_t pid)
 {
     int fd;
     struct pid_info_t info;
@@ -187,7 +187,7 @@
     }
 
     // Read the command line information; each argument is terminated with NULL.
-    strncat(info.path, "cmdline", sizeof(info.path));
+    strlcat(info.path, "cmdline", sizeof(info.path));
     fd = open(info.path, O_RDONLY);
     if (fd < 0) {
         fprintf(stderr, "Couldn't read %s\n", info.path);
diff --git a/toolbox/mkswap.c b/toolbox/mkswap.c
new file mode 100644
index 0000000..1710ef6
--- /dev/null
+++ b/toolbox/mkswap.c
@@ -0,0 +1,94 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <asm/page.h>
+#include <sys/swap.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* XXX This needs to be obtained from kernel headers. See b/9336527 */
+struct linux_swap_header {
+    char            bootbits[1024]; /* Space for disklabel etc. */
+    uint32_t        version;
+    uint32_t        last_page;
+    uint32_t        nr_badpages;
+    unsigned char   sws_uuid[16];
+    unsigned char   sws_volume[16];
+    uint32_t        padding[117];
+    uint32_t        badpages[1];
+};
+
+#define MAGIC_SWAP_HEADER     "SWAPSPACE2"
+#define MAGIC_SWAP_HEADER_LEN 10
+#define MIN_PAGES             10
+
+int mkswap_main(int argc, char **argv)
+{
+    int err = 0;
+    int fd;
+    ssize_t len;
+    off_t swap_size;
+    int pagesize;
+    struct linux_swap_header sw_hdr;
+
+    if (argc != 2) {
+        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
+        return -EINVAL;
+    }
+
+    fd = open(argv[1], O_WRONLY);
+    if (fd < 0) {
+        err = errno;
+        fprintf(stderr, "Cannot open %s\n", argv[1]);
+        return err;
+    }
+
+    pagesize = getpagesize();
+    /* Determine the length of the swap file */
+    swap_size = lseek(fd, 0, SEEK_END);
+    if (swap_size < MIN_PAGES * pagesize) {
+        fprintf(stderr, "Swap file needs to be at least %dkB\n",
+            (MIN_PAGES * pagesize) >> 10);
+        err = -ENOSPC;
+        goto err;
+    }
+    if (lseek(fd, 0, SEEK_SET)) {
+        err = errno;
+        fprintf(stderr, "Can't seek to the beginning of the file\n");
+        goto err;
+    }
+
+    memset(&sw_hdr, 0, sizeof(sw_hdr));
+    sw_hdr.version = 1;
+    sw_hdr.last_page = (swap_size / pagesize) - 1;
+
+    len = write(fd, &sw_hdr, sizeof(sw_hdr));
+    if (len != sizeof(sw_hdr)) {
+        err = errno;
+        fprintf(stderr, "Failed to write swap header into %s\n", argv[1]);
+        goto err;
+    }
+
+    /* Write the magic header */
+    if (lseek(fd, pagesize - MAGIC_SWAP_HEADER_LEN, SEEK_SET) < 0) {
+        err = errno;
+        fprintf(stderr, "Failed to seek into %s\n", argv[1]);
+        goto err;
+    }
+
+    len = write(fd, MAGIC_SWAP_HEADER, MAGIC_SWAP_HEADER_LEN);
+    if (len != MAGIC_SWAP_HEADER_LEN) {
+        err = errno;
+        fprintf(stderr, "Failed to write magic swap header into %s\n", argv[1]);
+        goto err;
+    }
+
+    if (fsync(fd) < 0) {
+        err = errno;
+        fprintf(stderr, "Failed to sync %s\n", argv[1]);
+        goto err;
+    }
+err:
+    close(fd);
+    return err;
+}
diff --git a/toolbox/mount.c b/toolbox/mount.c
index bcda2a2..66ae8b1 100644
--- a/toolbox/mount.c
+++ b/toolbox/mount.c
@@ -138,6 +138,24 @@
 	return rwflag;
 }
 
+/*
+ * Mark the given block device as read-write, using the BLKROSET ioctl.
+ */
+static void fs_set_blk_rw(const char *blockdev)
+{
+    int fd;
+    int OFF = 0;
+
+    fd = open(blockdev, O_RDONLY);
+    if (fd < 0) {
+        // should never happen
+        return;
+    }
+
+    ioctl(fd, BLKROSET, &OFF);
+    close(fd);
+}
+
 static char *progname;
 
 static struct extra_opts extra;
@@ -179,6 +197,10 @@
         dev = loopdev;
     }
 
+    if ((rwflag & MS_RDONLY) == 0) {
+        fs_set_blk_rw(dev);
+    }
+
 	while ((s = strsep(&type, ",")) != NULL) {
 retry:
 		if (mount(dev, dir, s, rwflag, data) == -1) {
diff --git a/toolbox/nandread.c b/toolbox/nandread.c
index b124731..4666f26 100644
--- a/toolbox/nandread.c
+++ b/toolbox/nandread.c
@@ -12,7 +12,7 @@
 static int test_empty(const char *buf, size_t size)
 {
     while(size--) {
-        if (*buf++ != 0xff)
+        if (*buf++ != (char) 0xff)
             return 0;
     }
     return 1;
@@ -44,7 +44,7 @@
     struct mtd_info_user mtdinfo;
     struct mtd_ecc_stats initial_ecc, last_ecc, ecc;
     struct mtd_oob_buf oobbuf;
-    struct nand_ecclayout ecclayout;
+    nand_ecclayout_t ecclayout;
 
     do {
         c = getopt(argc, argv, "d:f:s:S:L:Rhv");
@@ -177,7 +177,11 @@
 
     if (rawmode) {
         rawmode = mtdinfo.oobsize;
+#if !defined(MTD_STUPID_LOCK) /* using uapi kernel headers */
+        ret = ioctl(fd, MTDFILEMODE, MTD_FILE_MODE_RAW);
+#else /* still using old kernel headers */
         ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW);
+#endif
         if (ret) {
             fprintf(stderr, "failed set raw mode for %s, %s\n",
                     devname, strerror(errno));
diff --git a/toolbox/readlink.c b/toolbox/readlink.c
new file mode 100644
index 0000000..d114e20
--- /dev/null
+++ b/toolbox/readlink.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static int skip_newline, quiet_errors, canonicalize;
+
+static void usage(char* name) {
+    fprintf(stderr, "Usage: %s [OPTION]... FILE\n", name);
+}
+
+int readlink_main(int argc, char* argv[]) {
+    int c;
+    while ((c = getopt(argc, argv, "nfqs")) != -1) {
+        switch (c) {
+        case 'n':
+            skip_newline = 1;
+            break;
+        case 'f':
+            canonicalize = 1;
+            break;
+        case 'q':
+        case 's':
+            quiet_errors = 1;
+            break;
+        case '?':
+        default:
+            usage(argv[0]);
+            return EXIT_FAILURE;
+        }
+    }
+    int index = optind;
+    if (argc - index != 1) {
+        usage(argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    char name[PATH_MAX+1];
+    if (canonicalize) {
+        if(!realpath(argv[optind], name)) {
+            if (!quiet_errors) {
+                perror("readlink");
+            }
+            return EXIT_FAILURE;
+        }
+    } else {
+        ssize_t len = readlink(argv[1], name, PATH_MAX);
+
+        if (len < 0) {
+            if (!quiet_errors) {
+                perror("readlink");
+            }
+            return EXIT_FAILURE;
+        }
+        name[len] = '\0';
+    }
+
+    fputs(name, stdout);
+    if (!skip_newline) {
+        fputs("\n", stdout);
+    }
+
+    return EXIT_SUCCESS;
+}
diff --git a/toolbox/reboot.c b/toolbox/reboot.c
deleted file mode 100644
index f8546de..0000000
--- a/toolbox/reboot.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <cutils/android_reboot.h>
-#include <unistd.h>
-
-int reboot_main(int argc, char *argv[])
-{
-    int ret;
-    int nosync = 0;
-    int poweroff = 0;
-    int flags = 0;
-
-    opterr = 0;
-    do {
-        int c;
-
-        c = getopt(argc, argv, "np");
-        
-        if (c == EOF) {
-            break;
-        }
-        
-        switch (c) {
-        case 'n':
-            nosync = 1;
-            break;
-        case 'p':
-            poweroff = 1;
-            break;
-        case '?':
-            fprintf(stderr, "usage: %s [-n] [-p] [rebootcommand]\n", argv[0]);
-            exit(EXIT_FAILURE);
-        }
-    } while (1);
-
-    if(argc > optind + 1) {
-        fprintf(stderr, "%s: too many arguments\n", argv[0]);
-        exit(EXIT_FAILURE);
-    }
-
-    if(nosync)
-        /* also set NO_REMOUNT_RO as remount ro includes an implicit sync */
-        flags = ANDROID_RB_FLAG_NO_SYNC | ANDROID_RB_FLAG_NO_REMOUNT_RO;
-
-    if(poweroff)
-        ret = android_reboot(ANDROID_RB_POWEROFF, flags, 0);
-    else if(argc > optind)
-        ret = android_reboot(ANDROID_RB_RESTART2, flags, argv[optind]);
-    else
-        ret = android_reboot(ANDROID_RB_RESTART, flags, 0);
-    if(ret < 0) {
-        perror("reboot");
-        exit(EXIT_FAILURE);
-    }
-    fprintf(stderr, "reboot returned\n");
-    return 0;
-}
diff --git a/toolbox/rm.c b/toolbox/rm.c
index 3a24bec..957b586 100644
--- a/toolbox/rm.c
+++ b/toolbox/rm.c
@@ -45,8 +45,10 @@
             continue;
         sprintf(dn, "%s/%s", name, de->d_name);
         if (unlink_recursive(dn, flags) < 0) {
-            fail = 1;
-            break;
+            if (!(flags & OPT_FORCE)) {
+                fail = 1;
+                break;
+            }
         }
         errno = 0;
     }
@@ -71,6 +73,7 @@
     int ret;
     int i, c;
     int flags = 0;
+    int something_failed = 0;
 
     if (argc < 2)
         return usage();
@@ -103,17 +106,21 @@
             ret = unlink_recursive(argv[i], flags);
         } else {
             ret = unlink(argv[i]);
-            if (errno == ENOENT && (flags & OPT_FORCE)) {
-                return 0;
+            if (ret < 0 && errno == ENOENT && (flags & OPT_FORCE)) {
+                continue;
             }
         }
 
         if (ret < 0) {
             fprintf(stderr, "rm failed for %s, %s\n", argv[i], strerror(errno));
-            return -1;
+            if (!(flags & OPT_FORCE)) {
+                return -1;
+            } else {
+                something_failed = 1;
+            }
         }
     }
 
-    return 0;
+    return something_failed;
 }
 
diff --git a/toolbox/swapoff.c b/toolbox/swapoff.c
new file mode 100644
index 0000000..8f14158
--- /dev/null
+++ b/toolbox/swapoff.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <asm/page.h>
+#include <sys/swap.h>
+
+int swapoff_main(int argc, char **argv)
+{
+    int err = 0;
+
+    if (argc != 2) {
+        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
+        return -EINVAL;
+    }
+
+    err = swapoff(argv[1]);
+    if (err) {
+        fprintf(stderr, "swapoff failed for %s\n", argv[1]);
+    }
+
+    return err;
+}
diff --git a/toolbox/swapon.c b/toolbox/swapon.c
new file mode 100644
index 0000000..afa6868
--- /dev/null
+++ b/toolbox/swapon.c
@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <asm/page.h>
+#include <sys/swap.h>
+
+/* XXX These need to be obtained from kernel headers. See b/9336527 */
+#define SWAP_FLAG_PREFER        0x8000
+#define SWAP_FLAG_PRIO_MASK     0x7fff
+#define SWAP_FLAG_PRIO_SHIFT    0
+#define SWAP_FLAG_DISCARD       0x10000
+
+void usage(char *name)
+{
+    fprintf(stderr, "Usage: %s [-p prio] <filename>\n"
+        "        prio must be between 0 and %d\n", name, SWAP_FLAG_PRIO_MASK);
+}
+
+int parse_prio(char *prio_str)
+{
+    unsigned long p = strtoul(prio_str, NULL, 10);
+
+    return (p > SWAP_FLAG_PRIO_MASK)? -1 : (int)p;
+}
+
+int swapon_main(int argc, char **argv)
+{
+    int err = 0;
+    int flags = 0;
+    int prio;
+
+    opterr = 0;
+    do {
+        int c = getopt(argc, argv, "hp:");
+        if (c == -1)
+            break;
+
+        switch (c) {
+            case 'p':
+                if (optarg != NULL)
+                    prio = parse_prio(optarg);
+                else
+                    prio = -1;
+
+                if (prio < 0) {
+                    usage(argv[0]);
+                    return -EINVAL;
+                }
+                flags |= SWAP_FLAG_PREFER;
+                flags |= (prio << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK;
+                break;
+            case 'h':
+                usage(argv[0]);
+                return 0;
+            case '?':
+                fprintf(stderr, "unknown option: %c\n", optopt);
+                return -EINVAL;
+        }
+    } while (1);
+
+    if (optind != argc - 1) {
+        usage(argv[0]);
+        return -EINVAL;
+    }
+
+    err = swapon(argv[argc - 1], flags);
+    if (err) {
+        fprintf(stderr, "swapon failed for %s\n", argv[argc - 1]);
+    }
+
+    return err;
+}
diff --git a/toolbox/touch.c b/toolbox/touch.c
index b8ab310..52ddf2a 100644
--- a/toolbox/touch.c
+++ b/toolbox/touch.c
@@ -5,13 +5,40 @@
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <fcntl.h>
+#include <time.h>
 
 static void usage(void)
 {
-        fprintf(stderr, "touch: usage: touch [-alm] [-t time_t] <file>\n");
+        fprintf(stderr, "touch: usage: touch [-alm] [-t YYYYMMDD[.hhmmss]] <file>\n");
         exit(1);
 }
 
+static time_t parse_time(char *s)
+{
+    struct tm tm;
+    int day = atoi(s);
+    int hour = 0;
+
+    while (*s && *s != '.') {
+        s++;
+    }
+
+    if (*s) {
+        s++;
+        hour = atoi(s);
+    }
+
+    tm.tm_year = day / 10000 - 1900;
+    tm.tm_mon = (day % 10000) / 100 - 1;
+    tm.tm_mday = day % 100;
+    tm.tm_hour = hour / 10000;
+    tm.tm_min = (hour % 10000) / 100;
+    tm.tm_sec = hour % 100;
+    tm.tm_isdst = -1;
+
+    return mktime(&tm);
+}
+
 int touch_main(int argc, char *argv[])
 {
         int i, fd, aflag = 0, mflag = 0, debug = 0, flags = 0;
@@ -31,9 +58,9 @@
                     case 't':
                         if ((i+1) >= argc)
                             usage();
-                        specified_time.tv_sec = atol(argv[++i]);
-                        if (specified_time.tv_sec == 0) {
-                            fprintf(stderr, "touch: invalid time_t\n");
+                        specified_time.tv_sec = parse_time(argv[++i]);
+                        if (specified_time.tv_sec == -1) {
+                            fprintf(stderr, "touch: invalid timestamp specified\n");
                             exit(1);
                         }
                         specified_time.tv_nsec = 0;