Project import
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..da90807
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,134 @@
+#
+#    Copyright (c) 2010-2011 Nest, Inc.
+#    All rights reserved.
+#
+#    This document is the property of Nest. It is considered
+#    confidential and proprietary information.
+#
+#    This document may not be reproduced or transmitted in any form,
+#    in whole or in part, without the express written permission of
+#    Nest.
+#
+#    Description:
+#      This file is for the Linux process utilities, procps. These
+#      utilities provide both command line and full-screen information
+#      about the Linux process table and the processes within it.
+#
+
+BuildConfigSpecialized	:= No
+BuildProductSpecialized	:= No
+
+include pre.mak
+
+PackageName		:= procps
+
+PackageExtension	:= tar.gz
+PackageSeparator	:= -
+
+PackagePatchArgs	:= -p1
+
+PackageArchive		:= $(PackageName).$(PackageExtension)
+PackageSourceDir	:= $(PackageName)$(PackageSeparator)$(PackageVersion)
+
+PackageBuildMakefile	= $(call GenerateBuildPaths,Makefile)
+
+LicenseSourceFiles	:= COPYING COPYING.LIB
+LicenseSourcePaths      := $(addprefix $(PackageSourceDir)/,$(LicenseSourceFiles))
+
+CleanPaths		+= $(PackageLicenseFile)
+
+LinuxDir		:= sw/tps/linux
+LinuxIncDir		:= $(call GenerateResultPaths,$(LinuxDir),include)
+
+NCursesDir		:= sw/tps/ncurses
+NCursesIncDir		:= $(call GenerateResultPaths,$(NCursesDir),usr/include)
+NCursesLibDir		:= $(call GenerateResultPaths,$(NCursesDir),usr/lib)
+
+all: $(PackageDefaultGoal)
+
+# Generate the package license contents.
+
+$(LicenseSourcePaths): source
+
+$(PackageLicenseFile): $(LicenseSourcePaths)
+	$(Verbose)touch $@
+	$(Verbose)for file in $(LicenseSourcePaths); do	\
+		echo "Concatenating \"$${file}\"...";	\
+		cat $${file} >> $@;			\
+	done
+
+# Extract the source from the archive and apply patches, if any.
+
+$(PackageSourceDir): $(PackageArchive) $(PackagePatchPaths)
+	$(expand-and-patch-package)
+
+# Prepare the sources.
+
+.PHONY: source
+source: | $(PackageSourceDir)
+
+# Patch the sources, if necessary.
+
+.PHONY: patch
+patch: source
+
+# Generate the package build makefile.
+
+$(PackageBuildMakefile): | $(PackageSourceDir) $(BuildDirectory)
+	$(call create-links,$(CURDIR)/$(PackageSourceDir),$(BuildDirectory))
+
+# Configure the source for building.
+
+.PHONY: configure
+configure: source $(PackageBuildMakefile)
+
+# Build the source.
+#
+# We have to unset MAKEFLAGS since they confuse the package build otherwise.
+
+.PHONY: build
+build: configure | $(BuildDirectory)
+	$(Verbose)unset MAKEFLAGS && \
+	$(MAKE) $(JOBSFLAG) -C $(BuildDirectory) \
+	CC="$(CC)" CXX="$(CXX)" AR=$(AR) NM=$(NM) RANLIB=$(RANLIB) STRIP=$(STRIP) \
+	CPPFLAGS="$(call ToolGenerateIncludeArgument,$(LinuxIncDir)) \
+	$(call ToolGenerateIncludeArgument,$(NCursesIncDir))" \
+	LDFLAGS="-L$(NCursesLibDir)" \
+	all
+
+# Stage the build to a temporary installation area.
+#
+# We have to unset MAKEFLAGS since they confuse the package build otherwise.
+#
+# Also, override both install and ldconfig. We aren't running install
+# for a native host and we aren't running as super user, so the
+# default actions for those won't otherwise work.
+
+.PHONY: stage stage-default stage-headers
+stage: stage-default stage-headers
+
+stage-default: build | $(ResultDirectory)
+	$(Verbose)unset MAKEFLAGS && \
+	$(MAKE) $(JOBSFLAG) -C $(BuildDirectory) \
+	DESTDIR=$(ResultDirectory) \
+	install="$(shell which install) -D" \
+	ldconfig="$(shell which true)" \
+        m64=-m32 \
+        lib64=lib \
+	install
+
+ResultHeaderDir			= $(ResultDirectory)/usr/include/proc
+SourceHeaderPaths		= $(wildcard $(BuildDirectory)/proc/*.h)
+
+$(ResultHeaderDir):
+	$(create-directory)
+
+stage-headers: build | $(ResultHeaderDir)
+	install --mode=0664 $(SourceHeaderPaths) $(ResultHeaderDir)
+
+clean:
+	$(Verbose)$(RM) $(RMFLAGS) -r $(PackageSourceDir)
+	$(Verbose)$(RM) $(RMFLAGS) -r $(BuildDirectory)
+	$(Verbose)$(RM) $(RMFLAGS) -r $(ResultDirectory)
+
+include post.mak
diff --git a/procps-3.2.8/AUTHORS b/procps-3.2.8/AUTHORS
new file mode 100644
index 0000000..0860b24
--- /dev/null
+++ b/procps-3.2.8/AUTHORS
@@ -0,0 +1,50 @@
+free:
+Brian Edmonds
+
+oldps:
+Branko Lankester <lankeste@fwi.uva.nl>
+Michael K. Johnson <johnsonm@redhat.com>
+Michael Shields <mjshield@nyx.cs.du.edu>
+Charles Blake <cblake@bbn.com>
+David Mossberger-Tang
+
+ps:
+Albert Cahalan <albert@users.sf.net>
+
+skill/kill/snice:
+Albert Cahalan <albert@users.sf.net>
+
+tload:
+Branko Lankester
+David Engel <david@ods.com>
+Michael K. Johnson <johnsonm@redhat.com>
+
+top:
+Jim Warner <warnerjc@worldnet.att.net>
+
+oldtop:
+Branko Lankester <lankeste@fwi.uva.nl>
+Roger Binns
+Robert Nation <nation@rocket.sanders.lockheed.com>
+Michael K. Johnson <johnsonm@redhat.com>
+Michael Shields <mjshield@nyx.cs.du.edu>
+Tim Janik <timj@gtk.org>
+Helmut Geyer <Helmut.Geyer@iwr.uni-heidelberg.de>
+George Bonser <george@captech.com>
+
+uptime:
+Larry Greenfield <greenfie@gauss.rutgers.edu>
+Michael K. Johnson <johnsonm@sunsite.unc.edu>
+
+vmstat:
+Henry Ware <al172@yfn.ysu.edu>. 
+
+w:
+Larry Greenfield <greenfie@gauss.rutgers.edu>
+Michael K. Johnson <johnsonm@redhat.com>
+Charles Blake
+
+watch:
+Tony Rems <rembo@unisoft.com>
+Mike Coleman <mkc@acm.org>
+
diff --git a/procps-3.2.8/BUGS b/procps-3.2.8/BUGS
new file mode 100644
index 0000000..ec45bde
--- /dev/null
+++ b/procps-3.2.8/BUGS
@@ -0,0 +1,74 @@
+BUG REPORTS
+
+Please read this file before sending in a bug report or patch.
+
+Also, PLEASE read the documentation first.  90% of the mail I get
+complaining about procps is due to the sender not having read the
+documentation!
+
+
+Where to send
+=============
+Send comments, bug reports, patches, etc., to albert@users.sf.net
+
+
+What to send
+============
+It is much more useful to me if a program really crashes to recompile it
+with make "CFLAGS=-ggdb -O", run it with "gdb prog" and "run" and send
+me a stack trace ('bt' command).  That said, any bug report is still
+better than none.
+
+strace and ltrace output are very helpful:
+
+        strace -o output-file ps --blah
+        bzip2 output-file
+
+I also like "ps --info" output, even if there isn't a ps problem.
+
+Kernel-Dependent Patches
+========================
+If you send me patches which are specific to *running* with a particular
+kernel version of /proc, please condition them with the runtime determined
+variable 'linux_version_code' from libproc/version.c.  It is the same
+number as the macro LINUX_VERSION_CODE for which the kernel /proc fs
+code was compiled.
+
+A macro is provide in libproc/version.h to construct the code from its
+components, e.g.
+  if (linux_version_code < LINUX_VERSION(2,5,41))
+     /* blah blah blah */
+A startup call to set_linux_version may also be necessary.
+
+Of course, if a bug is due to a change in kernel file formats, it would
+be best to first try to generalize the parsing, since the code is then
+more resilient against future change.
+
+Also unified diffs (diff -u) are my preference, context diffs (diff -c )
+are kind of usable, and standard diffs (diff) are more useless than a
+generic text description of what you did.  Just use
+	diff -Naurd oldfile newfile
+or
+	diff -Naurd old-procps-dir new-procps-dir
+to create your diffs and you will make me happy.  Also make sure to
+include a description of what the diff is for or I'm likely to ignore
+it because of general lack of time...
+
+It might be nice to get rid of miscellaneous compiler warnings, but
+don't bend over backwards to do it.
+
+
+Code Structure
+==============
+
+A goal is to encapsulate *all* parsing dependent on /proc
+file formats into the libproc library.  If the API is general enough
+it can hopefully stabilize and then /proc changes might only require
+updating libproc.so.  Beyond that having the set of utilities be simple
+command lines parsers and output formatters and encapsulating all kernel
+divergence in libproc is the way to go.
+
+Hence if you are submitting a new program or are fixing an old one, keep
+in mind that adding files to libproc which encapsulate such things is
+more desirable than patching the actual driver program.  (well, except
+to move it toward the API of the library).
diff --git a/procps-3.2.8/COPYING b/procps-3.2.8/COPYING
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/procps-3.2.8/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/procps-3.2.8/COPYING.LIB b/procps-3.2.8/COPYING.LIB
new file mode 100644
index 0000000..92b8903
--- /dev/null
+++ b/procps-3.2.8/COPYING.LIB
@@ -0,0 +1,481 @@
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+    		    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/procps-3.2.8/CodingStyle b/procps-3.2.8/CodingStyle
new file mode 100644
index 0000000..962207d
--- /dev/null
+++ b/procps-3.2.8/CodingStyle
@@ -0,0 +1,101 @@
+If you start a new file, you get to choose the style.
+If you change an existing file, follow the existing style.
+
+Hard tabs are OK, as long as you consider the tab stops to
+be every 8 characters. You can also use 2, 3, or 4 spaces.
+Tabs are kind of yucky, since cut-and-paste mangles them
+sometimes and they make "diff -Naurd old new" output less
+readable.
+
+Spaces within a line don't matter much, and won't be
+considered part of the style. Just make it readable:
+
+if(x){            // OK
+if( x ){           // OK
+if (x) {            // OK
+if(x==y && a==b){     // OK
+if(x == y && a == b){ // poor
+if(x==y&&a==b){       // poor
+
+This is evil:
+
+szWinStallman
+FoulCodingStyle (int iInsanity)
+  {
+     if (iInsanity)
+       {
+          GoHackEmacs () ;
+       }
+          else
+       {
+          SeekHelpForYourLisp () ;
+       }
+  }
+
+
+Curly braces belong at the end of a line. If you must, go ahead
+and make function bodies an exception to that rule. (as Linus does)
+
+Big fprintf() calls and similar go like this:
+
+fprintf(fd, "%d %d %d %d %d %d\n",
+  sdfsdf_sdfsdf + sdfs_iii,     // not an example of good names!
+  iijjij,
+  kjfkkj_sdfssss_sfff,
+  sdflkjfdskj + sdf - sfds,
+  jksss,
+  sfssss + wwwwfwfw
+);
+
+Keep these distinct: NULL, '\0', 0, 0.0
+
+Command-line parsers need to be bomb-proof. It is not acceptable
+to crash due to a messed up command-line. For an option "-x" that
+takes an argument, accept both "-x arg" and "-xarg". Remember to
+support "--" and "--version".
+
+Be extremely careful when handling data from other users.
+For example, it is a security hole if /proc/123/cmdline can
+overflow an array. It is often a security hole if you allow
+non-ASCII characters to be printed. Assuming the console is
+not in UTF-8 mode, all of these are bad: "\b\e\f\n\r\t\v\x9b".
+(the "\x9b" is valid in UTF-8 mode, but equivalent to "\e["
+when not in UTF-8 mode -- which gives control of terminal
+settings) It's best if you consider user-supplied data to
+be unsafe, since this makes for less work in case the code
+ends up needing to run setuid. Termcap data is user-supplied.
+Except for the above security issues, don't bother to check
+for something you can't handle... like printf() failing.
+It is expected that /dev exists and so on.
+
+Remember that a read() may return early, with partial data
+or with -1 and errno set to EINTR. You then must try again.
+
+char:      may be signed or unsigned by default
+int:       always 32-bit
+long long: always 64-bit
+pointer:   either 32-bit or 64-bit
+long:      same size as a pointer
+KLONG:     same size as a pointer or long IN THE KERNEL
+
+Functions used in just one file must be marked static.
+Use the "const" and "restrict" keywords wherever you can.
+
+Put main() at the bottom of a file so you don't need all
+those ugly forward declarations.
+
+Avoid the strcat() function. It is slow. For some odd
+reason, snprintf() is faster than sprintf().
+
+Reuse memory allocations when you can. When using realloc(),
+do your increments by more than one. 25% is a nice amount.
+
+Avoid compile-time choices. They make documentation difficult,
+and they are not friendly to binary distribution.
+
+Write programs that can handle a million processes without
+getting hopelessly slow. Allow for /proc/123/cmdline to
+be at least 128 kB.
+
+The LGPL license is strongly preferred. This allows use of
+the code in the library.
diff --git a/procps-3.2.8/Makefile b/procps-3.2.8/Makefile
new file mode 100644
index 0000000..daa4927
--- /dev/null
+++ b/procps-3.2.8/Makefile
@@ -0,0 +1,261 @@
+# procps Makefile
+# Albert Cahalan, 2002-2004
+#
+# Recursive make is considered harmful:
+# http://google.com/search?q=%22recursive+make+considered+harmful%22
+#
+# For now this Makefile uses explicit dependencies. The project
+# hasn't grown big enough to need something complicated, and the
+# dependency tracking files are an ugly annoyance.
+#
+# This file includes */module.mk files which add on to variables:
+# FOO += bar/baz
+#
+#
+# Set (or uncomment) SKIP if you wish to avoid something.
+# For example, you may prefer the /bin/kill from util-linux or bsdutils.
+
+
+VERSION      := 3
+SUBVERSION   := 2
+MINORVERSION := 8
+TARVERSION   := $(VERSION).$(SUBVERSION).$(MINORVERSION)
+
+############ vars
+
+# so you can disable them or choose alternates
+ldconfig := ldconfig
+ln_f     := ln -f
+ln_sf    := ln -sf
+install  := install -D --owner 0 --group 0
+
+# Lame x86-64 /lib64 and /usr/lib64 abomination:
+lib64    := lib$(shell [ -d /lib64 ] && echo 64)
+
+usr/bin                  := $(DESTDIR)/usr/bin/
+bin                      := $(DESTDIR)/bin/
+sbin                     := $(DESTDIR)/sbin/
+usr/proc/bin             := $(DESTDIR)/usr/bin/
+man1                     := $(DESTDIR)/usr/share/man/man1/
+man5                     := $(DESTDIR)/usr/share/man/man5/
+man8                     := $(DESTDIR)/usr/share/man/man8/
+lib                      := $(DESTDIR)/$(lib64)/
+usr/lib                  := $(DESTDIR)/usr/$(lib64)/
+usr/include              := $(DESTDIR)/usr/include/
+
+#SKIP     := $(bin)kill $(man1)kill.1
+
+BINFILES := $(usr/bin)uptime $(usr/bin)tload $(usr/bin)free $(usr/bin)w \
+            $(usr/bin)top $(usr/bin)vmstat $(usr/bin)watch $(usr/bin)skill \
+            $(usr/bin)snice $(bin)kill $(sbin)sysctl $(usr/bin)pmap \
+            $(usr/proc/bin)pgrep $(usr/proc/bin)pkill $(usr/bin)slabtop \
+            $(usr/proc/bin)pwdx
+
+MANFILES := $(man1)uptime.1 $(man1)tload.1 $(man1)free.1 $(man1)w.1 \
+            $(man1)top.1 $(man1)watch.1 $(man1)skill.1 $(man1)kill.1 \
+            $(man1)snice.1 $(man1)pgrep.1 $(man1)pkill.1 $(man1)pmap.1 \
+            $(man5)sysctl.conf.5 $(man8)vmstat.8 $(man8)sysctl.8 \
+            $(man1)slabtop.1 $(man1)pwdx.1
+
+TARFILES := AUTHORS BUGS NEWS README TODO COPYING COPYING.LIB \
+            Makefile procps.lsm procps.spec v t README.top CodingStyle \
+            sysctl.conf minimal.c $(notdir $(MANFILES)) dummy.c \
+            uptime.c tload.c free.c w.c top.c vmstat.c watch.c skill.c \
+            sysctl.c pgrep.c top.h pmap.c slabtop.c pwdx.c
+
+# Stuff (tests, temporary hacks, etc.) left out of the standard tarball
+# plus the top-level Makefile to make it work stand-alone.
+_TARFILES := Makefile
+
+CURSES := -lncurses
+
+# This seems about right for the dynamic library stuff.
+# Something like this is probably needed to make the SE Linux
+# library loading not conflict with embedded systems stuff.
+#
+#ifeq ($(SHARED),1)
+#ldl := -ldl
+#LIBTYPE := -DSHAREDLIB
+#else
+#LIBTYPE := -DSTATICLIB
+#endif
+
+# Preprocessor flags.
+PKG_CPPFLAGS := -D_GNU_SOURCE -I proc
+CPPFLAGS     := -I/usr/include/ncurses
+ALL_CPPFLAGS := $(PKG_CPPFLAGS) $(CPPFLAGS)
+
+# Left out -Wconversion due to noise in glibc headers.
+# Left out -Wunreachable-code and -Wdisabled-optimization
+# because gcc spews many useless warnings with them.
+#
+# Since none of the PKG_CFLAGS things are truly required
+# to compile procps, they might best be moved to CFLAGS.
+# On the other hand, they aren't normal -O -g things either.
+#
+# Note that -O2 includes -fomit-frame-pointer only if the arch
+# doesn't lose some debugging ability.
+#
+PKG_CFLAGS   := -fno-common -ffast-math \
+  -W -Wall -Wshadow -Wcast-align -Wredundant-decls \
+  -Wbad-function-cast -Wcast-qual -Wwrite-strings -Waggregate-return \
+  -Wstrict-prototypes -Wmissing-prototypes
+# Note that some stuff below is conditional on CFLAGS containing
+# an option that starts with "-g". (-g, -g2, -g3, -ggdb, etc.)
+CFLAGS       := -O2 -s
+ALL_CFLAGS   := $(PKG_CFLAGS) $(CFLAGS)
+
+PKG_LDFLAGS  := -Wl,-warn-common
+LDFLAGS      :=
+ALL_LDFLAGS  := $(PKG_LDFLAGS) $(LDFLAGS)
+
+############ Add some extra flags if gcc allows
+
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),tar)  
+ifneq ($(MAKECMDGOALS),extratar)
+ifneq ($(MAKECMDGOALS),beta)
+
+# Unlike the kernel one, this check_gcc goes all the way to
+# producing an executable. There might be a -m64 that works
+# until you go looking for a 64-bit curses library.
+check_gcc = $(shell if $(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) dummy.c $(ALL_LDFLAGS) $(1) -o /dev/null $(CURSES) > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+
+# Be 64-bit if at all possible. In a cross-compiling situation, one may
+# do "make m64=-m32 lib64=lib" to produce 32-bit executables. DO NOT
+# attempt to use a 32-bit executable on a 64-bit kernel. Packagers MUST
+# produce separate executables for ppc and ppc64, s390 and s390x,
+# i386 and x86-64, mips and mips64, sparc and sparc64, and so on.
+# Failure to do so will cause data corruption.
+m64 := $(call check_gcc,-m64,$(call check_gcc,-mabi=64,))
+ALL_CFLAGS += $(m64)
+
+ALL_CFLAGS += $(call check_gcc,-Wdeclaration-after-statement,)
+ALL_CFLAGS += $(call check_gcc,-Wpadded,)
+ALL_CFLAGS += $(call check_gcc,-Wstrict-aliasing,)
+
+# Adding -fno-gcse might be good for those files which
+# use computed goto.
+#ALL_CFLAGS += $(call check_gcc,-fno-gcse,)
+
+# if not debugging, enable things that could confuse gdb
+ifeq (,$(findstring -g,$(filter -g%,$(CFLAGS))))
+ALL_CFLAGS += $(call check_gcc,-fweb,)
+ALL_CFLAGS += $(call check_gcc,-frename-registers,)
+ALL_CFLAGS += $(call check_gcc,-fomit-frame-pointer,)
+endif
+
+# in case -O3 is enabled, avoid bloat
+ALL_CFLAGS += $(call check_gcc,-fno-inline-functions,)
+
+endif
+endif
+endif
+endif
+
+############ misc.
+
+# free.c pmap.c sysctl.c uptime.c vmstat.c watch.c pgrep.c skill.c tload.c top.c w.c
+# utmp.c oldtop.c tmp-junk.c minimal.c
+
+.SUFFIXES:
+.SUFFIXES: .a .o .c .s .h
+
+.PHONY: all clean do_all install tar extratar beta
+
+ALL := $(notdir $(BINFILES))
+
+CLEAN := $(notdir $(BINFILES))
+
+DIRS :=
+
+INSTALL := $(BINFILES) $(MANFILES)
+
+# want this rule first, use := on ALL, and ALL not filled in yet
+all: do_all
+
+-include proc/module.mk ps/module.mk
+
+do_all:    $(ALL)
+
+junk := DEADJOE *~ *.o core gmon.out
+
+# Remove $(junk) from all $(DIRS)
+CLEAN += $(junk) $(foreach dir,$(DIRS),$(addprefix $(dir), $(junk)))
+
+##########
+# not maintained because it isn't really needed:
+#
+#SRC :=
+#OBJ := $(patsubst %.c,%.o, $(filter %.c,$(SRC)))
+#
+#ifneq ($(MAKECMDGOALS),clean)
+#-include $(OBJ:.o=.d)
+#endif
+#
+#%.d: %.c
+#	depend.sh $(ALL_CPPFLAGS) $(ALL_CFLAGS) $< > $@
+############
+
+# don't want to type "make procps-$(TARVERSION).tar.gz"
+tar: $(TARFILES)
+	mkdir procps-$(TARVERSION)
+	(tar cf - $(TARFILES)) | (cd procps-$(TARVERSION) && tar xf -)
+	tar cf procps-$(TARVERSION).tar procps-$(TARVERSION)
+	gzip -9 procps-$(TARVERSION).tar
+
+extratar: $(_TARFILES)
+	mkdir procps-$(TARVERSION)
+	(tar cf - $(_TARFILES)) | (cd procps-$(TARVERSION) && tar xf -)
+	tar cf extra-$(TARVERSION).tar procps-$(TARVERSION)
+	gzip -9 extra-$(TARVERSION).tar
+
+beta: $(TARFILES) $(_TARFILES)
+	mkdir beta-$(TARVERSION)
+	(tar cf - $(TARFILES) $(_TARFILES)) | (cd beta-$(TARVERSION) && tar xf -)
+	tar cf beta-$(TARVERSION).tar beta-$(TARVERSION)
+	gzip -9 beta-$(TARVERSION).tar
+
+clean:
+	rm -f $(CLEAN)
+
+###### install
+
+$(BINFILES) : all
+	$(install) --mode 775 $(notdir $@) $@
+
+$(MANFILES) : all
+	$(install) --mode a=r $(notdir $@) $@
+
+install: $(filter-out $(SKIP) $(addprefix $(DESTDIR),$(SKIP)),$(INSTALL))
+	cd $(usr/bin) && $(ln_f) skill snice
+	cd $(usr/proc/bin) && $(ln_f) pgrep pkill
+
+############ prog.c --> prog.o
+
+top.o : top.h
+
+%.o : %.c
+	$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
+
+w.o:    w.c
+	$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) $(W_SHOWFROM) -c $<
+
+############ prog.o --> prog
+
+pmap w uptime tload free sysctl vmstat utmp pgrep skill pwdx: % : %.o $(LIBPROC)
+	$(CC) $(ALL_CFLAGS) $^ $(ALL_LDFLAGS) -o $@
+
+slabtop top: % : %.o $(LIBPROC)
+	$(CC) $(ALL_CFLAGS) $^ $(ALL_LDFLAGS) -o $@ $(CURSES)
+
+watch: % : %.o
+	$(CC) $(ALL_CFLAGS) $^ $(ALL_LDFLAGS) -o $@ $(CURSES)
+
+############ progX --> progY
+
+snice kill: skill
+	$(ln_f) skill $@
+
+pkill: pgrep
+	$(ln_f) pgrep pkill
diff --git a/procps-3.2.8/NEWS b/procps-3.2.8/NEWS
new file mode 100644
index 0000000..60acc88
--- /dev/null
+++ b/procps-3.2.8/NEWS
@@ -0,0 +1,368 @@
+procps-3.2.7 --> procps-3.2.8
+
+ps: allow "+" in sort specifications, as in man page     rh208217
+ps: recognize SCHED_ISO and SCHED_IDLE
+ps: document SCHED_BATCH and add a "see also" for stime
+ps: man page less ambiguous
+top: normal exit code should be 0          #341272 #354255 rh199174
+top: misc fixes
+pgrep: usage error should exit with 2       #413383
+vmstat: use EXIT_FAILURE -- thanks Yoshio Nakamura   #425492
+sysctl: fix crash -- thanks Steinar Gunderson      #423704
+watch: tolerate umlauts                          #207103
+pmap: range limits with -A low,high
+update /dev/tty* info to May 2009 devices.txt
+don't read off end of string const                rh469495 rh498182
+
+procps-3.2.6 --> procps-3.2.7
+
+top: document H option -- thanks Tony Ernst
+top: terabytes -- thanks Tony Ernst
+top: CPU usage column width fixes -- thanks Tony Ernst
+top: *roff change                                   #326517
+ps: SCHED_BATCH is B
+ps: fix s format (signals) output with thread display
+watch: avoid integer overflow for the time delay
+pwdx: buffer overflow fixed -- thanks Ulf Harnhammar
+procps.spec needed a slash -- thanks Jesse Brandeburg
+w: stale utmp entries snuck in via uninitialized var -- thanks Robert A Basch
+pgrep/pkill: fix some realloc-related crashes       #353894
+pgrep/pkill: g is criteria (PLD Linux, patch found in locked filing cabinet)
+sysctl: use - for stdin (PLD Linux: beware of the leopard)
+top: show CPU time stolen from a virtual machine
+
+procps-3.2.5 --> procps-3.2.6
+
+vmstat: /proc/stat buffer big enough for 1024 CPUs
+dietlibc needs termios.h for struct winsize -- thanks Thomas Ogrisegg
+top: can do per-task display -- thanks John Blackwood     rh114012
+more MIPS crud  -- thanks Jim Gifford and Ryan Oliver
+begin prep for setuid
+top: fix %CPU max on 2..9 CPU SMP -- thanks Ga*tan LEURENT  rh110555
+ps: fix crash related to realloc -- thanks David Houlder
+ps: man page more detailed                         #334682
+spelling fixes                       #300333 #334684 #334685
+top: crash on resize fixed -- thanks Michal Maruska   #320289
+vmstat: -p handles /dev/ and does not overflow  #319523 #330969
+
+procps-3.2.4 --> procps-3.2.5
+
+display problem on 64-bit systems fixed   #287947
+top: variable-width PID and PPID
+top: variable-width %CPU                   rh110555
+sysctl: better error messages
+ps: security labels can contain any printable ASCII
+top: help and version message on stdout, with exit(0)    #283541
+ps: SIGTSTP and SIGTTOU shouldn't print bug email address    #246123
+slabtop: compile with glibc 2.2.17 (and older, likely)
+slabtop: fix overflow on huge NUMA boxes                #264640
+slabtop: accept any slabinfo 2.x format        g77301  #287691 rh145369 rh145906
+ps: alignment after WCHAN fixed                            ub5385
+pmap: when no -x or -d option, show full path        rh142751
+
+procps-3.2.3 --> procps-3.2.4
+
+support 64-bit MIPS with n32 binary
+sparc32 optimized for sparc32 again
+pwdx: new command -- thanks Nicholas Miell
+ps: UTF-8 username + command -- thanks Karel Zak rh134763,rh112518,rh134780
+ps: more room for some columns
+ps: tolerate SubDomain security module CONTEXT/LABEL data    #277401
+watch: passes COLUMNS and LINES in environment
+top: in batch mode, tolerate unknown $TERM -- thanks Daniel Walsh
+pkill: quiet about processes that die before kill()
+
+procps-3.2.2 --> procps-3.2.3
+
+avoid truncating long usernames
+avoid warning about -lncurses when not linking (more)
+new names for shared libraries (packagers: watch out!)
+"make install" no longer rebuilds everything
+wchan now '*' for multi-threaded processes
+ps: new man page -- thanks Nicolas Francois
+ps: STAT shows l for multi-threaded processes
+vmstat: some overflow problems fixed -- thanks Holger Kiehl
+sysctl: man page fix
+
+procps-3.2.1 --> procps-3.2.2
+
+new packager (downstream maintainer) guidelines in README
+move striping from install command to CFLAGS
+new gcc options in use: -fweb, -frename-registers, etc.
+avoid warning about -lncurses when not linking -- thanks FLWM
+tolerate IA-64 headers without PAGE_SIZE
+ps: k option, same as --sort
+ps: personality-specific -x support (HP-UX and SVR4-MP)
+pgrep: man page SEE ALSO updated                    #226817
+sysctl: -q and -N options
+sysctl: better error handling of failed writes
+top: tolerate sparse CPU numbering
+top: try to handle terminals lacking rmam and smam     #235003
+top: xterm dislikes clear-to-eol at eol (char lost)
+vmstat: fixed -d
+watch: allow sub-second intervals -- thanks Thomas Stewart
+
+procps-3.2.0 --> procps-3.2.1
+
+build even w/ curses in an odd location -- thanks to Segher Boessenkool
+ps: STAT flags for fg process group and session leader
+ps: STAT flags for swapped out process dropped (was broken)
+ps: new -M and Z options for security data (SE Linux, etc.)
+slabtop: detect broken /proc/slabinfo -- thanks to Fabian Frederick
+slabtop: ensure that error messages show up on the screen -- FF again
+
+procps-3.1.15 --> procps-3.2.0
+
+build on IA-64 again                            #227933
+pmap: output like Solaris 9, not Solaris 7
+ps: also handle SELinux on the 2.4.xx kernels
+top: during a ^Z, the terminal was messed up     #228822
+future-proof the tty handling   (thanks to Zhou Wei)
+slabtop  (Chris Rivera and Robert Love)          #226778
+pmap: detect the primary stack
+pmap: -d format
+free: report high and low memory
+
+procps-3.1.14 --> procps-3.1.15
+
+install to /lib64 if it exists
+hide kernel PID bug (Linux 2.4.13-pre1 to 2.4.MAX)   #217278 #219730 #217525 #224470
+ps: faster threaded display
+top: auto-margin problem                           #217559
+ps: support NSA SELinux, all builds, Linux 2.6+    #193648
+sysctl: tweak man page for ESR's broken parser
+
+procps-3.1.13 --> procps-3.1.14
+
+top: displays on more genuine serial terminals
+handle 32-bit dev_t of Linux 2.6
+ps: finally, m and -m satisfy the original design
+ps: distinct per-thread and whole-process pending signals
+
+procps-3.1.12 --> procps-3.1.13
+
+ps: can display NPTL threads w/ kernel patch
+no seLinux for now (new kernel interface)
+
+procps-3.1.11 --> procps-3.1.12
+
+ps: explicit width ("ps -o pid,wchan:42,args")
+ps: $PS_FORMAT works properly                    #201575
+top: new Linux 2.6.0-test4 CPU stats shown
+top: multiple -p options work again
+top: fixed 4 GB wrap-around
+ps: has a set of tests to ensure correctness
+man page: /var/run/utmp, not /etc/utmp           #206583
+required flags moved out of CFLAGS               #205429
+RPM generation handles /lib64
+WCHAN skips leading '.'
+vmstat: numerous new features
+
+procps-3.1.10 --> procps-3.1.11
+
+compile with gcc 2.95 again (C99 issue)
+
+procps-3.1.9 --> procps-3.1.10
+
+handle GPLONLY_ symbols                       #143549 #188374
+kill: better man page
+skill: better man page
+ps: PID-like columns change width as needed
+top: COMMAND instead of Command
+vmstat: -m displays slabinfo
+vmstat: -d displays disk stats
+
+procps-3.1.8 --> procps-3.1.9
+
+memory sizes fixed for 64-bit w/ gcc 3.x      #194376 #191933
+ps: detect broken OS install w/o /proc mounted        #172735
+top: fix suspend/resume behavior
+top: ditch warning until a GOOD interface is found    #188271
+kill: more info in the man page                       #182414
+ps: document the -o, o, -O, and O options             #169301
+vmstat: choose units you like: 1000, 1024, 1000000...
+
+procps-3.1.7 --> procps-3.1.8
+
+top: fix keyboard handling (help screen, etc.)
+
+procps-3.1.6 --> procps-3.1.7
+
+Makefile: made SKIP feature easier to use
+watch: --help now explains -t, --no-title    #182246
+ps: warning directs users to the FAQ
+top: batch mode can refresh by fractional seconds
+top: faster start-up
+top: do not refresh like crazy
+ps: better crash message
+
+procps-3.1.5 --> procps-3.1.6
+
+handle the 2.5.61 kernel
+top: memory leak fixed
+ps: new --ppid option selects by PPID
+watch: new --no-title option              #179862
+handle SPARC Linux badness
+rare crash fixed
+compile with gcc 2.91.xx again
+more informative "ps --info"
+README update
+ps: compare more with "ps -C verylongname"     #178127
+
+procps-3.1.4 --> procps-3.1.5
+
+ancient (2.x.xx era) data corruption fixed
+serious hidden-process problem (3.1.3+) fixed
+w: escape sequence vulnerability fixed
+
+procps-3.1.3 --> procps-3.1.4
+
+top: was trashing every "3" in a command name
+top: when killing a process, the PID was cut at a "3"
+top: more reliable %CPU
+update copyright dates (GPL & LGPL require this)
+RPM generation works now
+
+procps-3.1.2 --> procps-3.1.3
+
+uses /proc/*/wchan files when available
+top: user selection
+sysctl: add -e for Red Hat 8.0 boot scripts
+sysctl: the obvious --help, -V, and --version
+sysctl: some command line error checking
+w: stdout, not stderr -- thanks to Sander van Malssen
+
+procps-3.1.1 --> procps-3.1.2
+
+better RPM generation
+use C99 features
+some seLinux fixes
+now count Inact_laundry as needed  #172163
+ps: fewer globals
+ps: hardware-enforced buffer protection
+ps: 1 kB smaller
+top: B command added (for bold on/off)
+top: handle old (and future) config files
+top: man page tweak
+top: old sort keys     #167249
+top: out-of-bounds RT as "RT"
+top: several times faster
+top: t command fixed
+vmstat: -f
+vmstat: -s
+w: much faster
+watch: don't drop empty lines   #171005
+watch: re-indented
+
+procps-3.1.0 --> procps-3.1.1
+
+vmstat faster on 2.5.xx kernels
+vmstat header fixed
+vmstat -a re-fixed
+
+procps-3.0.5 --> procps-3.1.0
+
+vmstat displays IO-wait time instead of bogus "w"
+can build w/o shared library (set SHARED=0)
+when IO-wait hidden, count as idle, not as sys
+pmap command added (like Sun has)
+do not crash GNU make 3.79
+top slightly faster
+
+procps-3.0.4 --> procps-3.0.5
+
+top tolerates super-wide displays
+better (?) RPM generation
+XConsole and top.desktop removed
+old build system removed
+code cleanup
+pgrep and pkill get "-o" (oldest matching process)
+had vmstat "bi" and "bo" output interchanged on 2.5.xx
+fix man page tbl directives
+top man page cleaned up
+
+procps-3.0.3 --> procps-3.0.4
+
+make top go faster
+Linux 2.2.xx ELF note warning removed
+only show IO-wait on recent kernels
+fix top's SMP stats
+fix top for "dumb" and "vt510" terminals
+in top, limit the priority values to -99 ... 99
+
+procps-3.0.2 --> procps-3.0.3
+
+more "make install" fixes
+lib CFLAGS working again
+top.1 codes fixed
+bad (int*) cast in top removed
+top runs faster
+libproc memory corruption fixed
+rant moved out of top.1 man page
+ability to SKIP installing things
+fixed ps --sort crash
+
+procps-3.0.1 --> procps-3.0.2
+
+top defaults to the old layout
+top defaults to sorting by %CPU
+fix top for non-SMP 2.2.xx and 2.0.xx
+new "make install" fixed
+vmstat -a fixed
+vmstat compiles with latest gcc-3.x
+vmstat does 64-bit time
+
+procps-3.0.0 --> procps-3.0.1
+
+sysctl handles net/ipv4/conf/eth1.0123/tag (VLAN interface)
+sysctl handles net.ipv4.conf.eth1/0123.tag (VLAN interface)
+"ps" is now about 2x faster than in procps-2.x.x
+"ps -F" now documented
+w works in KOI8-R locale
+vmstat documentation update
+"skill -n blah blah blah" lets you test options
+simple "make && make install" now
+
+procps-2.x.x --> procps-3.0.0
+
+designed to support Linux 2.0 through 2.5.41 and beyond
+new top, with optional: color, windowing, SMP stats
+runs faster
+more "it crashes" bugs fixed
+top shows IO-wait time
+vmstat can show active/inactive memory stats
+real-time info supported in ps
+correct "ps -o size" and "ps --sort size"
+new maintainers
+reduced memory usage for ps
+allow large PIDs to be specified
+SELINUX support is just a recompile away
+the "F" column shrank, so "ps -l" has more command name room
+64-bit time reduces the overflow problem
+support S/390, IA-64 emulator, and user-mode Linux
+oldps is gone
+configure script -- use "make -f Makefile.noam" as a backup
+"w" program better at determining what a user is doing
+more stable
+code at http://procps.sf.net/ now (SourceForge)
+
+Earlier changes, for those not using Debian already:
+
+more stable
+runs faster
+-F format option
+better error reporting in ps for unknown format specifiers
+BSD's sysctl options -b and -X
+top displays well on large-memory systems
+old BSD-style select-by-PID ("ps l$$")
+15-character user names
+ps 'f' ASCII art forest fixed
+add SIGSYS on i386
+top reports real RSS value
+large-memory systems work
+minimal ps program for embedded systems (minimal.c)
+BSD personality process selection fixed
+support locale (French) with ',' and '.' mixed up
+pgrep program
+includes the "kill" and "nice" programs
+don't chop non-tty ps output at 80 columns
diff --git a/procps-3.2.8/README b/procps-3.2.8/README
new file mode 100644
index 0000000..fd76134
--- /dev/null
+++ b/procps-3.2.8/README
@@ -0,0 +1,72 @@
+COMPATIBILITY
+
+    This code is intended for use with Linux 2.2.xx, 2.4.xx,
+    2.6.xx, and hopefully all future kernels. You should be
+    running a system with libc 6, but libc 5 might work too.
+
+INSTALLATION
+
+    make
+    make install
+
+    Only the second ("make install") is needed if you just
+    want to build and install procps in the normal way.
+
+    If you wish to test before installing, use the scripts
+    named t, v, and p to ensure that the correct libproc
+    (the new one) is used during your testing.
+
+    You may set SKIP to avoid building or installing things.
+    For example:
+
+    make SKIP='/bin/kill /usr/share/man/man1/kill.1' install
+
+    Use SHARED=0 to build procps without shared libraries.
+    This may be useful for installing in your home directory.
+
+    make SHARED=0 DESTDIR=$HOME install
+
+    Suppose you wanted to install stuff in strange places.
+    You might do something like this:
+
+    make usr/bin=/tmp/Q/i/ DESTDIR=/tmp/Q install="install -D" ldconfig=echo install
+
+    If cross-compiling, you might need to set lib64 to
+    either "lib" or "lib64". You might need to set m64 to
+    -m64, -m32, or nothing at all. Some examples:
+
+    make lib64=lib m64=-m32      # for a bi-arch gcc
+    make lib64=lib64 CC=x86_64-gcc
+    make lib64=lib CC=alpha-gcc
+
+PACKAGING
+
+    If you are a downstream maintainer (packager) for a Linux distribution,
+    please avoid causing troubles. This section applies to you.
+
+    Send patches in regularly. Many patches made by vendors have been buggy,
+    some quite severely so. Sending in a patch will at least get it reviewed,
+    if not included. There is a procps test suite that must be passed.
+    Forward all bug reports. If your bug database is public and busy enough
+    to bother with, please make this known. Follow Debian's lead in making
+    the bug database easy to comment on via email w/o need for an account.
+
+    Do not change the user interface. Many of the programs are intended to be
+    compatible with Solaris, FreeBSD, AIX, IRIX, Tru64, and the UNIX standard.
+    Your nice new command options WILL BE BROKEN as needed to ensure that
+    procps remains compatible with the rest of the world. Sysadmins hate to
+    deal with incompatible behavior. If you need a new option, ask for it.
+
+    For normal packages, ensure that you do not add debugging flags
+    to the CFLAGS variable. If debugging flags are present, the Makefile
+    will avoid adding several optimizations that would interfere with gdb.
+
+    There should be no need to modify the Makefile. You can set variables
+    on the "make" command line or use "make -e" to pass variables from
+    the environment.
+
+BUG REPORTS
+
+    Debian users should use the Debian bug tracking system.
+    Email to albert@users.sf.net or csmall@debian.org or
+    procps-feedback@lists.sf.net will also work.
diff --git a/procps-3.2.8/README.top b/procps-3.2.8/README.top
new file mode 100644
index 0000000..3f225d5
--- /dev/null
+++ b/procps-3.2.8/README.top
@@ -0,0 +1,545 @@
+Credit for this belongs to:
+Jim / James C. Warner, <warnerjc@worldnet.att.net>
+
+----------------------------------
+
+Ok, ok, I yield -- most of what follows has been removed from the manual page
+and packaged separately as this README (hey, it was only TEMPORARY insanity).
+
+Of course, that means that now absolutely nobody will ever read it.
+
+This is probably a good thing...
+
+
+## Table of Contents ---------------------------------------------------##
+      # the only darn thing that wasn't in the man page
+   CUSTOMIZING the Sources
+      # the following carry their original topic numbers
+   DIFFERENCES / New Features
+      Interface Etiquette
+      Expanded Configurable Display Support
+      Enhanced Field/Column Management
+      Customization Flexibility
+   NOTES and Rantings
+      The top Binary
+      Comparing Performance
+      Cost of Stuff
+      The top Sources
+   EXAMPLES of Windows
+      The 'A' Mode Command Toggle
+      STACKIN' & WHACKIN' Windows
+      ALL TOGETHER Now, Window(s)
+
+
+## CUSTOMIZING the Sources ---------------------------------------------##
+
+Listed below are the conditionals available should you wish to recompile
+this top.  The author's favorite is:  PRETEND4CPUS.
+
+That's the #define allowing you to simulate an SMP environment, and
+(perhaps) impress your friends.  It's currently set to display four
+separate CPUs, but could easily be changed.
+
+   Caution: do NOT use this provision in an effort to impress someone
+            who truly possesses such a machine!  The fact that all 4
+            CPUs show the same dynamic results will likely have the
+            opposite effect.
+
+
+//#define ATEOJ_REPORT            /* report a bunch of stuff, at end-of-job  */
+//#define CASEUP_HEXES            /* show any hex values in upper case       */
+//#define CASEUP_SCALE            /* show scaled time/num suffix upper case  */
+//#define CASEUP_SUMMK            /* show memory summary kilobytes with 'K'  */
+//#define POSIX_CMDLIN            /* use '[ ]' for kernel threads, not '( )' */
+//#define PRETEND2_5_X            /* pretend we're linux 2.5.x (for IO-wait) */
+//#define PRETEND4CPUS            /* pretend we're smp with 4 ticsers (sic)  */
+//#define PRETENDNOCAP            /* use a terminal without essential caps   */
+//#define SORT_SUPRESS            /* *attempt* to reduce qsort overhead      */
+//#define STDOUT_IOLBF            /* disable our own stdout _IOFBF override  */
+//#define USE_LIB_STA3            /* use lib status (3 ch) vs. proc_t (1 ch) */
+//#define WARN_NOT_SMP            /* restrict '1' & 'I' commands to true smp */
+
+
+## 6. DIFFERENCES / New Features ---------------------------------------##
+       The  following  summarizes  differences  between this top and your
+       former top.  It was originally based  on  procps-2.0.7.   However,
+       except  for  the separate/summary CPU toggle, all of these differ-
+       ences also apply through procps-2.0.10.
+
+   6a. Interface Etiquette
+       -*-  Input and  output  are  far  more  carefully  implemented  in
+            this top.   You won't be subjected to 4 - 5 'Unknown command'
+            messages should you press the wrong key.
+
+       -*-  You need suffer a confirmation message only when the  results
+            of a command are not obvious by their effects on the display.
+
+       -*-  The Help screen will no longer overflow,  even  when  running
+            with a 24 row xterm (vt100).
+
+       -*-  The  fields  selection/ordering  screens  do  not  carelessly
+            destroy important information through unintended line  wraps.
+
+       -*-  Should  you  narrow  a  xterm  window to less than 80 columns
+            while this top is running, you  will  not  be  left  with  an
+            utterly worthless, embarrassing display.
+
+   6b. Expanded Configurable Display Support
+       -*-  In  an SMP environment, you can choose between a summary dis-
+            play or you may show each cpu  separately.   No  longer  must
+            this choice be irrevocably made at startup.
+
+       -*-  There  are  new  fields  and  with  this top,  any  field  is
+            selectable for sorting.  Plus,  your  sorted  column  can  be
+            instantly reversed with just a single keystroke.
+
+       -*-  You  may optionally apply 2 distinct types of highlighting to
+            running tasks and/or sorted columns.  With  this top,  you'll
+            be  able  to instantly spot running tasks and always know the
+            current sort field.
+
+       -*-  While you could  continue  to  use  the  more  familiar  (and
+            boring)  monochrome display, you might want to try this top's
+            new color display.  You can even create your own unique  col-
+            ors  used in summaries, messages, headings and tasks, each of
+            which can be made persistent until you choose to change them.
+
+       -*-  Up  to four separate windows can be displayed simultaneously,
+            giving you four separate ways to sort and view the tasks cur-
+            rently cluttering up your system.  You could have one view by
+            pids, another by cpu usage, yet another showing  memory  con-
+            sumption.  You get the idea...
+
+       -*-  Each window comes with pre-configured (but user configurable)
+            fields and you can size each window individually.
+
+       -*-  Virtually every one of this top's options (summaries, fields,
+            colors,  sorted  column, etc.) is separately configurable for
+            each of those four windows.
+
+            Heck, you can even change a window's name, if you don't  care
+            for  top's  choices.  Your changes will be reflected not only
+            when you're in what top calls alternate-display mode but also
+            on his special new 'Windows' help screen.
+
+       -*-  And,  [ ** Drum-Roll + Ta-Da ** ] with just one keystroke you
+            can quickly switch between full-screen  and  multiple  window
+            modes!   Or, with a different keystroke, toggle a single win-
+            dow Off for now, then On again later!!
+
+   6c. Enhanced Field/Column Management
+       -*-  Many Field/Column names have been changed to make  them  more
+            intuitive,  more  self-descriptive.   And  with  this top you
+            won't be fooled with field choices that are "not  yet  imple-
+            mented".
+
+       -*-  Task memory statistics are more meaningful and more accurate.
+
+       -*-  You'll finally have complete display integrity regardless  of
+            field  selections,  their  order  or  screen width.  And that
+            means the command column no longer need be kept as the right-
+            most  field,  lest  your  screen turn to <bleep> when all the
+            following columns get misaligned.
+
+   6d. Customization Flexibility
+       -*-  You have complete program naming  freedom  with  no  internal
+            ties  to  a  specific  personal configuration file.  Symbolic
+            links could be  used  to  establish  different  configuration
+            files  reflecting  the  different  personalities of your cus-
+            tomized "tops", under whatever aliases you've used.
+
+            Thus, you could have an  alias  for  running  top  in  'Batch
+            mode',  another  for when you work from the Linux console and
+            maybe a third used with X-Windows.  All of  that,  yet  still
+            just a single binary image!
+
+       -*-  All  of your configuration choices can be preserved in a per-
+            sonal configuration file, including any  changes  made  on  a
+            per-window  basis.   Thus,  once  you personalize things they
+            remain personalized until you decide to  change  them  again.
+            This top has been completely cured of:
+                     i-cant-remember-so-please-do-that-all-over-again
+                                         ( and again, and again ... )
+
+            The  bottom  line  is  this:  if  you save your configuration
+            before quitting top, upon restart  the  display  will  appear
+            exactly as you left it.  And that means you no longer have to
+            keep top  running  until-the-end-of-time  (ok,  a  long  time
+            anyway), lest your customizations go bye-bye.
+
+
+## 7. NOTES and Rantings -----------------------------------------------##
+   7a. The top Binary
+       To  whom  it may (should) concern:  this top, even with its vastly
+       expanded capabilities, is only slightly larger than the  old  top.
+       Were it not for extensive help text and additional sort callbacks,
+       it would be smaller.
+                       Throw source carelessly at objectives, it will
+                       produce equally careless machine instructions.
+                       example: (num_pages - an_address)/1024 == duh?
+                       kicker: document result as broken, due to elf!
+                       ----------------------------------------------
+                       I know you're out there, are you getting this?
+
+       Now, as for all those new capabilities like colors and windows and
+       highlighting, you'd expect this top to be the "mother of all pigs"
+       compared to old top  --  right?
+
+       Yea, with this top expect following piglets:
+        . A smaller virtual image and resident footprint
+        . Slightly fewer major page faults
+        . A large reduction in minor page faults for SMP
+        . The same or better response time
+        . The same or even less CPU costs
+
+       Ideally any comparison of the old and new top  should  be  against
+       the  same libproc format (32-bit or 64-bit tics) and run in a true
+       or simulated SMP environment (producing separate CPU stats).  This
+       latter  requirement  will  coax  old  top  into  handling  his own
+       '/proc/stat' access  --  something this top always does, but  with
+       less cost.
+
+   7b. Comparing Performance
+       Even  with equivalent libraries and '/proc/stat' access, it's dif-
+       ficult to  accurately  compare  tops  using  their  own  displays.
+       Results  for  these  cpu-intensive programs (who frequently exceed
+       their time-slice) generally show a wide disparity in  %CPU.   This
+       is due to differing call patterns, kernel preemptions and the tim-
+       ing of process snapshots.  For slightly better results, start each
+       program with the following commands:
+            ./old-top -d 0.5
+            nice -n-10 ./new-top -d 0.4
+
+       While actually putting this top at a performance disadvantage, the
+       higher scheduling priority and staggered timing will  periodically
+       yield  a  somewhat  truer  picture.   You could even reverse those
+       roles and get similar results.
+
+       The most consistent performance results  will  be  obtained  'off-
+       line',  using  your  shell's time pipe or the time program itself.
+       And even in a single processor environment or  without  equivalent
+       libraries,  total cpu costs (user time + system time) are similar.
+
+       However, this top's cpu costs ARE influenced by  the  capabilities
+       you  choose to exploit, even if they don't SEEM to be reflected in
+       such timings.  So let's examine some...
+
+   7c. Cost of Stuff
+       Colors Cost  --  Nada (almost).
+          Once the terminfo strings are built (at  and  during  a  user's
+          behest)  they  are  SAVED  with each window's stuff.  And while
+          there will be extra tty escape sequences transmitted because of
+          colors, it makes no difference which 'char *' is actually used.
+
+       Highlighting Cost  --  Nada (maybe), or blame it on Rio.
+          On second thought, let's blame it on the user.
+
+          For row highlighting, there is only the cost of those extra tty
+          escape  sequences  (same as for colors).  For column highlight-
+          ing, there is a fairly significant cost associated with  column
+          transition  management  combined  with  even  more  tty output.
+          These increased costs are incurred on every task display row.
+
+          Sooo... hey USER  --  do NOT highlight COLUMNS.  You  shouldn't
+          need  a  constant  visual  reminder  of your chosen sort field.
+          However, if you forget which field top is sorting it can  serve
+          as a quick visual reminder.
+
+       Windows Cost  --  Nada (if just 1 window).
+          If more than 1 window, almost certainly NOT Nada so blame it on
+          reality.  Colors are not an issue, but those sort fields are.
+
+          If we could trust the user to always select the same 'c' state,
+          'S' state and sort field (hey, why ya got multiple windows then
+          user, huh?) AND if we can trust someone to recompile top with a
+          #define enabled, then we could achieve 'Nada'.
+
+          Ok,  not likely, so we're gonna' be doing multiple sorts.  BUT,
+          it may not be as bad as it sounds.  Those sorts involve  point-
+          ers only.  And, that's as good as it gets !  (right Mr. N?)
+
+   7d. The top Sources
+       top.h
+          Unlike  his predecessor, this top has a proper header file.  It
+          contains ONLY declarations, NOT  definitions.   And  there  are
+          several  conditionals  present  to help with further customiza-
+          tions and experimentation.  All are Off by default.
+
+       top.c
+          Hopefully proves that source code needn't  be  a  disorganized,
+          misaligned  MESS.   And,  WHO  says  a source listing shouldn't
+          occasionally make you SMILE?  Why, top.c even does a darn  good
+          job  of  following the suggestions in a document hardly anybody
+          seems to observe.
+
+                        the Linus Torvalds CodingStyle guidelines ...
+                        -*- -*- -*- on indentation + etc. -*- -*- -*-
+                        well almost all, except for those stinkin'...
+
+       I suppose even Linus Torvalds is entitled to err  now  and  again.
+       How  so  you say?  Tabs, me' bucko, stinkin' tabs!  That, plus the
+       simplistic position regarding indentation espoused in that  other-
+       wise excellent document.
+
+   -*- Rant On, and on -*-
+       Let's  compare  two approaches to the tab/indentation issue with a
+       small code sample using tabs then spaces.  This snippet happens to
+       be  the key to top's use of dynamic colors on many static screens,
+       while also ensuring screen width isn't exceeded  so  as  to  avoid
+       line  wraps.   We'll  view just the first 40 columns, assuming one
+       wishes to occasionally provide comments to  the  right  of  actual
+       code (you do, don't you?).
+
+       Then YOU decide which approach makes the most SENSE!
+
+                           Stinkin' Tabs versus Spaces: the Linus way
+           Hey, where'd my +----+----1----+----2----+----3----+----4+
+           many code lines |                while (*sub_beg) {      :
+           up-and-gone-to? |                        switch (*sub_end:
+                           |                                case 0: :
+           Gosh, wonder if |   \ Tabs Induced /                     :
+           Linus expects a |                                case 1: :
+           fellow to stick |   + WASTE-Lands! +             case 5: :
+           his comments on |                                        :
+           the left side?! |   + Not a Living +                     :
+                           |                                        :
+           Ever see source |   + line-of-code +                     :
+           with not enough |                                        :
+           whitespace; and |   / To Be Found! \                     :
+           this is better? |                                default::
+                           |                                        :
+           Oh lookie here, \                        }               :
+           there's just a hint of REAL code! ---->  if (0 >= room) b:
+                           /                } /* end: while 'subtrin:
+                           +----------------------------------------+
+
+                           Spaces versus Stinkin' Tabs: the other way
+                           +----+----1----+----2----+----3----+----4+
+          Wow, now this is |      while (*sub_beg) {                :
+          Visible hackin'! |         switch (*sub_end) {            :
+                           |            case 0:                     :
+          Hmmm, wonder how |               *(sub_end + 1) = '\0';   :
+          many programmers |            case 1: case 2: case 3: case:
+          read those lines |            case 5: case 6: case 7: case:
+          from the LEFT to |               cap = Curwin->captab[(int:
+          the RIGHT?  This |               *sub_end = '\0';         :
+          "innovation" may |               PUTP("%s%.*s%s", cap, roo:
+          possibly benefit |               room -= (sub_end - sub_be:
+          those particular |               sub_beg = ++sub_end;     :
+          kinds of people, |               break;                   :
+          you agree?  Duh! |            default:                    :
+                           |               ++sub_end;               :
+          AND, there might |         }                              :
+          even be room for |         if (0 >= room) break;          :
+          unseen comments! |      } /* end: while 'subtrings' */    :
+                           +----------------------------------------+
+
+       Gosh, I just don't KNOW  --  it's such a TOUGH choice...
+
+       Oh  you  Stinkin' Tabs:  correspondence, Who-Cares; documentation,
+       Oh-Alright; even scripts, Well-If-You-Must.  But you have NO place
+       within  the  code-space  of  MY  C-source  listing!   So  be  gone
+       already!!
+
+   In Summation...
+       -  If you want to use tabs to the right of  the  code,  go-for-it.
+          But  PLEASE,  not  ever  in the C-source code-space, thank-you-
+          kindly.  Just use three little ol' spaces (exactly 3,  no-more,
+          no-less) where you WOULD have stuck a stinkin' tab.
+
+          We'll  get  far more READABLE files, much less WAISTED precious
+          horizontal space, more consistent CURSORS and on, and  ON,  AND
+          ON!  Plus, without those awful *the-devil's-own-handiwork*, the
+          aforementioned document need NEVER speak of their EVILS  again.
+
+       -  Lastly,  since  SPACES  (not  stinkin' tabs) are SO beneficial,
+          maybe we should use just a few more of 'em.  Some of  those  C-
+          thingies  are VERY sensitive  --  they don't like being TOUCHED
+          by any other syntax element!  Which ones?  Why these guys:
+
+             braces, reserved words and binary operators
+             ( it's the TRUTH, they told me themselves )
+
+          It's so EASY to keep 'em HAPPY!  And lo-and-behold, the  combi-
+          nation  of  <sp>thingy<sp> turns out to be a darn effective bug
+          repellent, too.  So  much  so,  one  can  actually  code  while
+          TOTALLY NUDE yet still avoid them ol' bug-bytes (sic-sic)!
+                                                                 step
+                                                            down_from
+                                                       me_punctilious
+                                                  soap-box_once_again
+                                                  [1 +5 +5 +5 = huh?]
+
+
+## 4c. EXAMPLES of Windows ---------------------------------------------##
+
+                    -*- The 'A' Mode Command Toggle -*-
+   Here's what you'll see when you  first  invoke  the  alternate-display
+   mode interactive command.
+
+   This  particular  display  was  produce on a VT100 xterm, with only 24
+   rows.  All four task displays are visible, but they could not be sized
+   the  same.  Available lines are parceled out in the fairest way possi-
+   ble so the last two task displays have an extra line each.
+
+   Notice the 'current' window name in the summary area   --   it's  been
+   emphasized  because  the  associated  task  display is visible.  Since
+   1:Def has a task area, the full range of interactive commands would be
+   at  your  disposal.   But  remember, many of those commands will apply
+   only to window 1:Def.
+
+                             +--------------------------------------+
+        1:Def name is bold,  |1:Def - 15:46:37 up 16:25,  9 users,  :
+         thus all commands   |Tasks:  76 total,   1 running,  75 sle:
+         will be available.  |Cpu(s):   0.7% user,   1.3% system,   :
+                             |Mem:    126588k total,   123688k used,:
+                             |Swap:   265032k total,     8232k used,:
+                             |______________________________________:
+        Tough luck windows   |1__PID_USER______PR__NI_%CPU____TIME+_:
+         #1 & 2 - you lost   |  7343 jtwm      16   0  0.9   0:00.59:
+         one line each  --   |  7339 jtwm       9   0  0.0   0:00.02:
+         guess you'll just   |__7337_root_______9___0__0.0___0:01.30:
+         have to learn how   |2__PID__PPID_Command____________TIME+_:
+         to live with it.    |   997   952 kdeinit          17:59.59:
+                             |  1115   952 kdeinit           2:16.47:
+                             |__1803__1116_led_______________1:55.30:
+                             |3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_:
+        The #3 & #4 windows  |  4634 12.3 15620    0  15m  860  14m :
+         better not gloat    |  7337 11.3 14396   92  13m   36  13m :
+         over 1 extra line.  |   923 10.6 30524  16m  13m 1120  12m :
+        That user could yet  |___991__7.2__9492__316_9176___12_9164_:
+         sock 'em with the   |4_UID_USER_____GROUP____TTY________PID:
+         'n' command and     |   43 xfs      xfs      ?          806:
+         take those lines,   |    0 ykde     users    pts/7     5561:
+         plus others, away!  |    0 wgnome   users    pts/7     5560:
+                             |    0 root     root     pts/7     5325:
+                             +--------------------------------------+
+
+   So, what say we start applying some of those "full range  of  interac-
+   tive commands"?
+
+   Onward + Downward...
+
+                    -*- STACKIN' & WHACKIN' Windows -*-
+   Whoa,  hold on mate.  Someone has already whacked these windows.  See,
+   there are no task areas for windows 1:Def and 4:Usr.  Well, we can  at
+   least retrace their steps...
+
+   Here's  what  was  done,  after  issuing  the 'A' command and entering
+   alternate-display mode.
+      1) When #1 was the 'current' window, '-' was pressed,
+         toggling Off the associated task display
+         ( if 'l t m' had been applied to its summary, too )
+         ( then there'll be only a msg line when 'current' )
+      2) Then the 'w' key was struck to cycle backward,
+         making 4:Usr the 'current' window
+         (could have used 'a a a', if one likes to type)
+      3) Then step #1 was repeated, and bye-bye window #4
+      4) Finally, window #2 was made the 'current' window
+         ( Q. how many keystrokes were used? )
+         ( A. minimum of 2:  'a a' or 'w w'. )
+
+                             +--------------------------------------+
+        No 'l','t','m','1'   |2:Top - 15:48:35 up 16:27,  9 users,  :
+         commands have been  |Tasks:  75 total,   1 running,  74 sle:
+         issued here,        |Cpu(s):   2.0% user,   0.7% system,   :
+         but...              |Mem:    126588k total,   123712k used,:
+                             |Swap:   265032k total,     8232k used,:
+                             |______________________________________:
+        #2's been changed;   |2__PID__PPID_Command____________TIME+_:
+         user applied a 'c'  |   997   952 kdeinit: konsol  18:00.70:
+         command (when it    |  1115   952 kdeinit: konsol   2:16.47:
+         was current) - now  |  1803  1116 led tiptop.HELP   1:55.30:
+         shows cmd lines vs. |   923   922 X :0              1:09.60:
+         program names;      |   973     1 klaptopdaemon     0:59.63:
+         still seems to be   |   981   952 /usr/bin/artsd    0:48.63:
+         sorted on TIME+     |   987     1 kdeinit: kdeskt   0:24.34:
+         though              |___991_____1_kdeinit:_kicker___0:04.59:
+                             |3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_:
+        This #3 guy appears  |  4634 12.3 15620    0  15m  860  14m :
+         to still be running |  7337 11.3 14396   92  13m   36  13m :
+         with the supplied   |   923 10.6 30544  16m  13m 1120  12m :
+         defaults, but no    |   991  7.2  9492  316 9176   12 9164 :
+         telling what damage |  7329  7.0  9036  140 8896   36 8860 :
+         might have been     |  1115  6.9  8956  160 8796   36 8760 :
+         done to it's        |   987  6.4  8668  524 8144   20 8124 :
+         summary info stuff  |  1131  6.4  8268  144 8124   36 8088 :
+                             +--------------------------------------+
+
+   And that's what brought us to  this  current  state.   No,  wait.   Oh
+   lordy, will you look at that  --  someone has changed the name of win-
+   dow #2 from 'Job' to 'Top'!
+
+   How'd they do that?  Well, they just issued the 'g'  interactive  com-
+   mand, of course.  That command is available whenever alternate-display
+   mode is active and always impacts just the  'current'  window.   Gosh,
+   you  can  even issue the 'g' command when 'l' has toggled Off the very
+   summary area line containing the window name!
+
+   Almost Done...
+
+                    -*- ALL TOGETHER Now, Window(s) -*-
+   Here, the window 1:Def task  display  has  been  toggled  Off  but  it
+   remains  the 'current' window.  Since there is no task area, many com-
+   mands will be restricted.  However, the commands ('l', 't', 'm',  '1')
+   affecting  the  summary  area,  as  well as some other global commands
+   ('k', 'Z', etc.), would still be active.
+
+   Notice that the Mem and Swap lines are not shown.  This means that the
+   loser  (oops, user) has, in fact, issued the 'm' command!  Now, if you
+   were to cycle the 'current' window with the 'a' or 'w'  commands,  the
+   task  display would remain the same (except possibly growing/shrinking
+   slightly) but the summary area would change periodically.
+
+   The comments to the left of the image provide additional insights into
+   how  things came to be.  Note especially the comments for window 4:Usr
+    --  the one with some empty rows...
+
+        1:Def no highlight,  +--------------------------------------+
+         thus disabled cmds: |1:Def - 15:50:32 up 16:29,  9 users,  :
+         b,i,n,u,x,y, etc.   |Tasks:  75 total,   2 running,  73 sle:
+         & m = lost Mem/Swap |Cpu(s):  10.6% user,   0.0% system,   :
+                             |______________________________________:
+        2:Job was very busy: |2__PID__PPID_Command____________TIME+_:
+         'n' cmd, w/ 7 tasks |    80     1 ( khubd )         0:00.00:
+         'c' cmd, cmd line   |     6     0 ( kreclaimd )     0:00.00:
+         'O' cmd, sort cmd   |     9     1 ( mdrecoveryd )   0:00.00:
+         'R' cmd, sort bkwd  | 11358     1 /bin/bash/ /usr   0:00.00:
+         'x' cmd, hi column  |  1297     1 /sbin/mingetty    0:00.00:
+        (when 2 WAS current) |   683     1 xinetd -stayali   0:00.00:
+                             |___836_____1_login_--_root_____0:00.00:
+        3:Mem has altered    |3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_:
+         some std defaults:  |  4634 12.3 15620    0  15m  860  14m :
+         'y' turned Off      |  7337 11.3 14396   92  13m   36  13m :
+         'x' turned On       |   923 10.6 30544  16m  13m 1120  12m :
+        (when 3 WAS current) |   991  7.2  9492  316 9176   12 9164 :
+                             |__7329__7.0__9036__140_8896___36_8860_:
+        Huh?  4:Usr has some |4_UID_USER_____GROUP____TTY________PID:
+         blank rows! ? ? ? ? |    0 jtwm     root     pts/2     5561:
+        Aha, the 'i' command |    0 root     root     ?         5560:
+         applied (when 4 WAS |                                      :
+         current); could be  |                                      :
+         reversed with '=',  |                                      :
+         when 4 IS current!  +--------------------------------------+
+
+   Ok now, how about that 'current' window 1:Def and  its  unseen  tasks?
+   At any time, you can quickly retrieve lost tasks in a number of ways:
+      1) Press '-', toggling just the 'current' window
+      2) Press '_', toggling all visible/invisible windows
+         ( 1:Def is the only window currently not shown )
+         ( afterward, it'll be the only window showing! )
+    * 3) Press '+', forcing all task displays to become visible
+      4) Press 'A' to return to full-screen mode,
+         with only 1:Def tasks shown and without a window name
+
+   Now that should be enough ways of getting a task area visible again to
+   satisfy almost any user, don't ya think?
+
+       Note: Use #3 above  when  you've  messed  up  your  screen  beyond
+       redemption.   The four task displays will reappear, nice and even.
+       They will also have retained any customizations you had previously
+       applied,  except for the 'i' (idle tasks) and 'n' (max tasks) com-
+       mands.
+
+   That's It !  Piece of Cake !!  Enjoy them there windows !!!
+
diff --git a/procps-3.2.8/TODO b/procps-3.2.8/TODO
new file mode 100644
index 0000000..7831ea0
--- /dev/null
+++ b/procps-3.2.8/TODO
@@ -0,0 +1,151 @@
+-------------------------- general ------------------------
+
+Consider using glibc obstacks for memory allocation.
+
+Implement /usr/proc/bin tools like Solaris has.
+The prstat command is interesting, like top in batch mode.
+SCO has a pstat command.
+
+Don't these really belong in the procps package?
+         killall   pstree   fuser   lsof   who
+(they are maintained elsewhere, which causes version problems)
+
+OpenBSD has a pfind command.
+
+Cache results of dev_to_tty.
+
+---------------------- kernel -------------------------
+
+Add an "adopted child" flag to mark processes that are not
+natural children of init. This can make --forest work better.
+
+Supply better data for top's CPU state display. Currently top has
+to subtract old numbers from new numbers and divide that result by
+the number of processors. The kernel won't even supply the number
+of processors in a portable way.
+
+Supply data for the ADDR and JOBC fields.
+
+Support & supply data for SL and RE.
+
+Add a /proc/*/tty symlink to eliminate guessing when /proc/*/fd is
+not accessable.
+
+Add /proc/*/.bindata files to avoid string parsing. It should be an array
+of 64-bit values on all machines. New entries go on the end and obsolete
+ones get filled in with something logical -- entries must never be deleted!
+
+Add all the stuff Solaris has. This would also replace ptrace.
+
+---------------------- watch --------------------------
+
+Tolerate UTF-8.
+
+Tolerate color, bold, underline, etc. #129334
+
+Tolerate stderr.  #420377 #155227 #225549
+
+Tolerate VT100 line-drawing characters. Maybe translate them.
+
+---------------------- w --------------------------
+
+The LOGIN@ column sometimes has a space in it. This makes correct
+scripting difficult.
+
+Time formats are demented.
+
+---------------------- vmstat --------------------------
+
+Extract /proc/diskstats parsing from vmstat into libproc somewhere.
+
+--------------------- libproc ----------------------
+
+Stop storing fields with duplicate info (often different
+units: kB and pages, seconds and jiffies) in the proc_t struct.
+
+Use own readdir code (assembly language) because glibc sucks ass.
+
+---------------------- top -------------------------
+
+Share more stuff with ps.
+
+don't truncate long usernames
+
+have a --config option
+
+---------------- ps for now, maybe move to libproc ------------------
+
+With forest output and a tty named /dev/this_is_my_tty, the position
+of the command name gets messed up. (we print too many spaces) (fixed?)
+
+Fix missing stuff for these formats: FB_j FB_l FB_v HP_f HP_l HP_fl JFMT OL_m
+(jobc,cpu,sl,re,cpu,prmgrp,m_swap,m_share,vm_lib,m_dt)
+Note that "cpu" has two meanings.
+
+Add Beowulf support. This is ugly, since the current patches use a
+daemon to collect info and add a HOST field after the PID field.
+
+Query optimizer, put cheap/required process selection first.
+
+Avoid reading both /proc/*/status and /proc/*/stat.
+
+Support printing the client hostname (the FROM that w(1) uses) in place
+of a pty.
+
+Disambiguate narrow tty info. (/dev/tty7 == /dev/pts/7 now)
+1------8     1--4
+ttyS2        S2
+ttyI31       I31
+pts/7        7        Short form could be /999.
+pts/9999     9999     Short form could just be trunctuated to /999.
+tty7         7        Short form could be vc-7.
+tty63        63       Short form could be vc63.
+
+Internationalization, as specified by XPG3, Volume 1, Commands and Utilities.
+(and suggested by Unix98) LC_TIME affects date format.
+
+----------------------- ps -----------------------
+
+Add an option to select all processes that a user can kill.
+(related to RUID, EUID, tty, etc. -- but maybe ignore root power)
+
+Add a nice display option for killing things.
+ruser,euser,ppid,pid,pmem,stime,args
+
+For RT stuff:
+pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,comm
+
+For job control:
+stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm
+
+Make the column alignment algorithm support this:
+    FOO BAR
+    8 44444
+    453  45
+    45 2989
+    63666 0
+    34  333
+(useful for the UNIX tty and time values, since the time might look
+like 100-10:40:32 for old processes and the tty might have extra room)
+
+Improve long sort/format specifiers documentation and fill in the missing
+code as much as the kernel can support. Make sure that memory amounts are in
+pages when they should be and in kB when they should be, not backwards.
+
+output encoding: UTF8 --nul --null
+
+Make BSD formats use non-standard BSD time format, at least when it
+doesn't violate the "no whitespace" rule.
+
+Better unmangling of '?' as a tty. The shell destroys '?' when there
+is a filename that matches. If the argument seems like garbage,
+check for a file that might have screwed up the '?'.
+
+If the 'O' option is given something already implied by 'O',
+assume the user wanted a sorting option.
+
+Conflict:
+Digital THREAD is user,pcpu,pri,scnt,wchan,usertime,systime
+AIX     THREAD is uname,pid,ppid,tid,S,C,PRI,scount,WCHAN,F,tty,bnd,comm
+AIX looks like this:
+         USER   PID  PPID  TID S  C PRI SC   WCHAN   FLAG   TTY BND  CMD
diff --git a/procps-3.2.8/dummy.c b/procps-3.2.8/dummy.c
new file mode 100644
index 0000000..95e7824
--- /dev/null
+++ b/procps-3.2.8/dummy.c
@@ -0,0 +1,31 @@
+// This is to test the compiler.
+
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <curses.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Foul POS defines all sorts of stuff...
+#include <term.h>
+#undef tab
+
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+#include <values.h>
+
+int main(int argc, char *argv[]){
+  (void)argc;
+  (void)argv;
+  return 0;
+}
diff --git a/procps-3.2.8/free.1 b/procps-3.2.8/free.1
new file mode 100644
index 0000000..954c8d9
--- /dev/null
+++ b/procps-3.2.8/free.1
@@ -0,0 +1,47 @@
+.\"             -*-Nroff-*-
+.\"  This page Copyright (C) 1993 Matt Welsh, mdw@sunsite.unc.edu.
+.\"  Freely distributable under the terms of the GPL
+.TH FREE 1 "20 Mar 1993 " "Cohesive Systems" "Linux User's Manual"
+.SH NAME
+free \- Display amount of free and used memory in the system
+.SH SYNOPSIS
+.BR "free " [ "\-b" " | " "\-k" " | " "\-m" "] [" "\-o" "] [" "\-s"
+.I delay
+.RB "] [" "\-t" "] [" "\-V" ]
+.SH DESCRIPTION
+\fBfree\fP displays the total amount of free and used physical and swap 
+memory in the system, as well as the buffers used by the kernel.
+The shared memory column should be ignored; it is obsolete.
+.SS Options
+The \fB-b\fP switch displays the amount of memory in bytes; the 
+\fB-k\fP switch (set by default) displays it in kilobytes; the \fB-m\fP
+switch displays it in megabytes.
+.PP
+The \fB-t\fP switch displays a line containing the totals.
+.PP
+The \fB-o\fP switch disables the display of a "buffer adjusted" line.
+If the -o option is not specified, \fBfree\fP subtracts buffer memory
+from the used memory and adds it to the free memory reported.
+.PP
+The \fB-s\fP switch activates continuous polling \fIdelay\fP seconds apart. You
+may actually specify any floating point number for \fIdelay\fP, 
+.BR usleep (3)
+is used for microsecond resolution delay times.
+.PP
+The \fB\-V\fP displays version information.
+.SH FILES
+.ta
+.IR /proc/meminfo "\-\- memory information"
+.fi
+
+.SH "SEE ALSO"
+.BR ps (1),
+.BR slabtop (1),
+.BR vmstat (8),
+.BR top(1)
+
+.SH AUTHORS
+Written by Brian Edmonds. 
+
+Send bug reports to <albert@users.sf.net>
+
diff --git a/procps-3.2.8/free.c b/procps-3.2.8/free.c
new file mode 100644
index 0000000..bd78f02
--- /dev/null
+++ b/procps-3.2.8/free.c
@@ -0,0 +1,122 @@
+// free.c - free(1)
+// procps utility to display free memory information
+//
+// All new, Robert Love <rml@tech9.net>             18 Nov 2002
+// Original by Brian Edmonds and Rafal Maszkowski   14 Dec 1992
+//
+// This program is licensed under the GNU Library General Public License, v2
+//
+// Copyright 2003 Robert Love
+// Copyright 2004 Albert Cahalan
+
+#include "proc/sysinfo.h"
+#include "proc/version.h"
+//#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define S(X) ( ((unsigned long long)(X) << 10) >> shift)
+
+const char help_message[] =
+"usage: free [-b|-k|-m|-g] [-l] [-o] [-t] [-s delay] [-c count] [-V]\n"
+"  -b,-k,-m,-g show output in bytes, KB, MB, or GB\n"
+"  -l show detailed low and high memory statistics\n"
+"  -o use old format (no -/+buffers/cache line)\n"
+"  -t display total for RAM + swap\n"
+"  -s update every [delay] seconds\n"
+"  -c update [count] times\n"
+"  -V display version information and exit\n"
+;
+
+int main(int argc, char *argv[]){
+    int i;
+    int count = 0;
+    int shift = 10;
+    int pause_length = 0;
+    int show_high = 0;
+    int show_total = 0;
+    int old_fmt = 0;
+
+    /* check startup flags */
+    while( (i = getopt(argc, argv, "bkmglotc:s:V") ) != -1 )
+        switch (i) {
+        case 'b': shift = 0;  break;
+        case 'k': shift = 10; break;
+        case 'm': shift = 20; break;
+        case 'g': shift = 30; break;
+        case 'l': show_high = 1; break;
+        case 'o': old_fmt = 1; break;
+        case 't': show_total = 1; break;
+        case 's': pause_length = 1000000 * atof(optarg); break;
+        case 'c': count = strtoul(optarg, NULL, 10); break;
+	case 'V': display_version(); exit(0);
+        default:
+            fwrite(help_message,1,strlen(help_message),stderr);
+	    return 1;
+    }
+
+    do {
+        meminfo();
+        printf("             total       used       free     shared    buffers     cached\n");
+        printf(
+            "%-7s %10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n", "Mem:",
+            S(kb_main_total),
+            S(kb_main_used),
+            S(kb_main_free),
+            S(kb_main_shared),
+            S(kb_main_buffers),
+            S(kb_main_cached)
+        );
+        // Print low vs. high information, if the user requested it.
+        // Note we check if low_total==0: if so, then this kernel does
+        // not export the low and high stats.  Note we still want to
+        // print the high info, even if it is zero.
+        if (show_high) {
+            printf(
+                "%-7s %10Lu %10Lu %10Lu\n", "Low:",
+                S(kb_low_total),
+                S(kb_low_total - kb_low_free),
+                S(kb_low_free)
+            );
+            printf(
+                "%-7s %10Lu %10Lu %10Lu\n", "High:",
+                S(kb_high_total),
+                S(kb_high_total - kb_high_free),
+                S(kb_high_free)
+            );
+        }
+        if(!old_fmt){
+            unsigned KLONG buffers_plus_cached = kb_main_buffers + kb_main_cached;
+            printf(
+                "-/+ buffers/cache: %10Lu %10Lu\n", 
+                S(kb_main_used - buffers_plus_cached),
+                S(kb_main_free + buffers_plus_cached)
+            );
+        }
+        printf(
+            "%-7s %10Lu %10Lu %10Lu\n", "Swap:",
+            S(kb_swap_total),
+            S(kb_swap_used),
+            S(kb_swap_free)
+        );
+        if(show_total){
+            printf(
+                "%-7s %10Lu %10Lu %10Lu\n", "Total:",
+                S(kb_main_total + kb_swap_total),
+                S(kb_main_used  + kb_swap_used),
+                S(kb_main_free  + kb_swap_free)
+            );
+        }
+        if(pause_length){
+	    fputc('\n', stdout);
+	    fflush(stdout);
+	    if (count != 1) usleep(pause_length);
+	}
+    } while(pause_length && --count);
+
+    return 0;
+}
diff --git a/procps-3.2.8/kill.1 b/procps-3.2.8/kill.1
new file mode 100644
index 0000000..aef9dbf
--- /dev/null
+++ b/procps-3.2.8/kill.1
@@ -0,0 +1,118 @@
+'\" t
+.\" (The preceding line is a note to broken versions of man to tell
+.\" them to pre-process this man page with tbl)
+.\" Man page for kill.
+.\" Licensed under version 2 of the GNU General Public License.
+.\" Written by Albert Cahalan; converted to a man page by
+.\" Michael K. Johnson
+.TH KILL 1 "November 21, 1999" "Linux" "Linux User's Manual"
+.SH NAME
+kill \- send a signal to a process
+
+.SH SYNOPSIS
+.TS
+l l.
+kill pid ...	Send SIGTERM to every process listed.
+kill -signal pid ...	Send a signal to every process listed.
+kill -s signal pid ...	Send a signal to every process listed.
+kill -l	List all signal names.
+kill -L	List all signal names in a nice table.
+kill -l signal	Convert a signal number into a name.
+kill -V,--version	Show version of program
+.TE
+
+.SH DESCRIPTION
+The default signal for kill is TERM. Use -l or -L to list available signals.
+Particularly useful signals include HUP, INT, KILL, STOP, CONT, and 0.
+Alternate signals may be specified in three ways: -9 -SIGKILL -KILL.
+Negative PID values may be used to choose whole process groups; see the
+PGID column in ps command output. A PID of -1 is special; it indicates
+all processes except the kill process itself and init.
+
+.SH SIGNALS
+The signals listed below may be available for use with kill.
+When known constant, numbers and default behavior are shown.
+
+.TS
+lB rB lB lB
+lfCW r l l.
+Name	Num	Action	Description
+.TH
+0	0	n/a	exit code indicates if a signal may be sent
+ALRM	14	exit
+HUP	1	exit
+INT	2	exit
+KILL	9	exit	this signal may not be blocked
+PIPE	13	exit
+POLL		exit
+PROF		exit
+TERM	15	exit
+USR1		exit
+USR2		exit
+VTALRM		exit
+STKFLT		exit	may not be implemented
+PWR		ignore	may exit on some systems
+WINCH		ignore
+CHLD		ignore
+URG		ignore
+TSTP		stop	may interact with the shell
+TTIN		stop	may interact with the shell
+TTOU		stop	may interact with the shell
+STOP		stop	this signal may not be blocked
+CONT		restart	continue if stopped, otherwise ignore
+ABRT	6	core
+FPE	8	core
+ILL	4	core
+QUIT	3	core
+SEGV	11	core
+TRAP	5	core
+SYS		core	may not be implemented
+EMT		core	may not be implemented
+BUS		core	core dump may fail
+XCPU		core	core dump may fail
+XFSZ		core	core dump may fail
+.TE
+
+.SH NOTES
+Your shell (command line interpreter) may have a built-in kill command.
+You may need to run the command described here as /bin/kill to solve
+the conflict.
+
+.SH EXAMPLES
+
+.SS
+.B "kill -9 -1"
+.nf
+Kill all processes you can kill.
+.fi
+.PP
+.SS
+.B "kill -l 11"
+.nf
+Translate number 11 into a signal name.
+.fi
+.PP
+.SS
+.B "kill -L"
+.nf
+List the available signal choices in a nice table.
+.fi
+.PP
+.SS
+.B "kill 123 543 2341 3453"
+.nf
+Send the default signal, SIGTERM, to all those processes.
+.fi
+.PP
+.SH "SEE ALSO"
+pkill(1) skill(1) kill(2) renice(1) nice(1) signal(7) killall(1)
+
+.SH STANDARDS
+This command meets appropriate standards. The -L flag is Linux-specific.
+
+.SH AUTHOR
+Albert Cahalan <albert@users.sf.net> wrote kill in 1999 to replace a
+bsdutils one that was not standards compliant. The util-linux one might
+also work correctly.
+
+Please send bug reports to <procps-feedback@lists.sf.net>
diff --git a/procps-3.2.8/minimal.c b/procps-3.2.8/minimal.c
new file mode 100644
index 0000000..a38e4c7
--- /dev/null
+++ b/procps-3.2.8/minimal.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright 1998,2004 by Albert Cahalan; all rights reserved.
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+
+/* This is a minimal /bin/ps, designed to be smaller than the old ps
+ * while still supporting some of the more important features of the
+ * new ps. (for total size, note that this ps does not need libproc)
+ * It is suitable for Linux-on-a-floppy systems only.
+ *
+ * Maintainers: do not compile or install for normal systems.
+ * Anyone needing this will want to tweak their compiler anyway.
+ */
+
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+
+#define DEV_ENCODE(M,m) ( \
+  ( (M&0xfff) << 8)   |   ( (m&0xfff00) << 12)   |   (m&0xff)   \
+)
+
+///////////////////////////////////////////////////////
+#ifdef __sun__
+#include <sys/mkdev.h>
+#define _STRUCTURED_PROC 1
+#include <sys/procfs.h>
+#define NO_TTY_VALUE DEV_ENCODE(-1,-1)
+#define HZ 1    // only bother with seconds
+#endif
+
+///////////////////////////////////////////////////////
+#ifdef __FreeBSD__
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/stat.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#define NO_TTY_VALUE DEV_ENCODE(-1,-1)
+#define HZ 1    // only bother with seconds
+#endif
+
+///////////////////////////////////////////////////////
+#ifdef __linux__
+#include <asm/param.h>  /* HZ */
+#include <asm/page.h>   /* PAGE_SIZE */
+#define NO_TTY_VALUE DEV_ENCODE(0,0)
+#ifndef HZ
+#warning HZ not defined, assuming it is 100
+#define HZ 100
+#endif
+#endif
+
+///////////////////////////////////////////////////////////
+
+#ifndef PAGE_SIZE
+#warning PAGE_SIZE not defined, assuming it is 4096
+#define PAGE_SIZE 4096
+#endif
+
+
+
+static char P_tty_text[16];
+static char P_cmd[16];
+static char P_state;
+static int P_euid;
+static int P_pid;
+static int P_ppid, P_pgrp, P_session, P_tty_num, P_tpgid;
+static unsigned long P_flags, P_min_flt, P_cmin_flt, P_maj_flt, P_cmaj_flt, P_utime, P_stime;
+static long P_cutime, P_cstime, P_priority, P_nice, P_timeout, P_alarm;
+static unsigned long P_start_time, P_vsize;
+static long P_rss;
+static unsigned long P_rss_rlim, P_start_code, P_end_code, P_start_stack, P_kstk_esp, P_kstk_eip;
+static unsigned P_signal, P_blocked, P_sigignore, P_sigcatch;
+static unsigned long P_wchan, P_nswap, P_cnswap;
+
+
+
+#if 0
+static int screen_cols = 80;
+static int w_count;
+#endif
+
+static int want_one_pid;
+static const char *want_one_command;
+static int select_notty;
+static int select_all;
+
+static int ps_format;
+static int old_h_option;
+
+/* we only pretend to support this */
+static int show_args;    /* implicit with -f and all BSD options */
+static int bsd_c_option; /* this option overrides the above */
+
+static int ps_argc;    /* global argc */
+static char **ps_argv; /* global argv */
+static int thisarg;    /* index into ps_argv */
+static char *flagptr;  /* current location in ps_argv[thisarg] */
+
+
+
+
+static void usage(void){
+  fprintf(stderr,
+    "-C   select by command name (minimal ps only accepts one)\n"
+    "-p   select by process ID (minimal ps only accepts one)\n"
+    "-e   all processes (same as ax)\n"
+    "a    all processes w/ tty, including other users\n"
+    "x    processes w/o controlling ttys\n"
+    "-f   full format\n"
+    "-j,j job control format\n"
+    "v    virtual memory format\n"
+    "-l,l long format\n"
+    "u    user-oriented format\n"
+    "-o   user-defined format (limited support, only \"ps -o pid=\")\n"
+    "h    no header\n"
+/*
+    "-A   all processes (same as ax)\n"
+    "c    true command name\n"
+    "-w,w wide output\n"
+*/
+  );
+  exit(1);
+}
+
+/*
+ * Return the next argument, or call the usage function.
+ * This handles both:   -oFOO   -o FOO
+ */
+static const char *get_opt_arg(void){
+  const char *ret;
+  ret = flagptr+1;    /* assume argument is part of ps_argv[thisarg] */
+  if(*ret) return ret;
+  if(++thisarg >= ps_argc) usage();   /* there is nothing left */
+  /* argument is the new ps_argv[thisarg] */
+  ret = ps_argv[thisarg];
+  if(!ret || !*ret) usage();
+  return ret;
+}
+
+
+/* return the PID, or 0 if nothing good */
+static void parse_pid(const char *str){
+  char *endp;
+  int num;
+  if(!str)            goto bad;
+  num = strtol(str, &endp, 0);
+  if(*endp != '\0')   goto bad;
+  if(num<1)           goto bad;
+  if(want_one_pid)    goto bad;
+  want_one_pid = num;
+  return;
+bad:
+  usage();
+}
+
+/***************** parse SysV options, including Unix98  *****************/
+static void parse_sysv_option(void){
+  do{
+    switch(*flagptr){
+    /**** selection ****/
+    case 'C': /* end */
+      if(want_one_command) usage();
+      want_one_command = get_opt_arg();
+      return; /* can't have any more options */
+    case 'p': /* end */
+      parse_pid(get_opt_arg());
+      return; /* can't have any more options */
+    case 'A':
+    case 'e':
+      select_all++;
+      select_notty++;
+case 'w':    /* here for now, since the real one is not used */
+      break;
+    /**** output format ****/
+    case 'f':
+      show_args = 1;
+      /* FALL THROUGH */
+    case 'j':
+    case 'l':
+      if(ps_format) usage();
+      ps_format = *flagptr;
+      break;
+    case 'o': /* end */
+      /* We only support a limited form: "ps -o pid="  (yes, just "pid=") */
+      if(strcmp(get_opt_arg(),"pid=")) usage();
+      if(ps_format) usage();
+      ps_format = 'o';
+      old_h_option++;
+      return; /* can't have any more options */
+    /**** other stuff ****/
+#if 0
+    case 'w':
+      w_count++;
+      break;
+#endif
+    default:
+      usage();
+    } /* switch */
+  }while(*++flagptr);
+}
+
+/************************* parse BSD options **********************/
+static void parse_bsd_option(void){
+  do{
+    switch(*flagptr){
+    /**** selection ****/
+    case 'a':
+      select_all++;
+      break;
+    case 'x':
+      select_notty++;
+      break;
+    case 'p': /* end */
+      parse_pid(get_opt_arg());
+      return; /* can't have any more options */
+    /**** output format ****/
+    case 'j':
+    case 'l':
+    case 'u':
+    case 'v':
+      if(ps_format) usage();
+      ps_format = 0x80 | *flagptr;  /* use 0x80 to tell BSD from SysV */
+      break;
+    /**** other stuff ****/
+    case 'c':
+      bsd_c_option++;
+#if 0
+      break;
+#endif
+    case 'w':
+#if 0
+      w_count++;
+#endif
+      break;
+    case 'h':
+      old_h_option++;
+      break;
+    default:
+      usage();
+    } /* switch */
+  }while(*++flagptr);
+}
+
+#if 0
+#include <termios.h>
+/* not used yet */
+static void choose_dimensions(void){
+  struct winsize ws;
+  char *columns;
+  /* screen_cols is 80 by default */
+  if(ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col>30) screen_cols = ws.ws_col;
+  columns = getenv("COLUMNS");
+  if(columns && *columns){
+    long t;
+    char *endptr;
+    t = strtol(columns, &endptr, 0);
+    if(!*endptr && (t>30) && (t<(long)999999999)) screen_cols = (int)t;
+  }
+  if(w_count && (screen_cols<132)) screen_cols=132;
+  if(w_count>1) screen_cols=999999999;
+}
+#endif
+
+static void arg_parse(int argc, char *argv[]){
+  int sel = 0;  /* to verify option sanity */
+  ps_argc = argc;
+  ps_argv = argv;
+  thisarg = 0;
+  /**** iterate over the args ****/
+  while(++thisarg < ps_argc){
+    flagptr = ps_argv[thisarg];
+    switch(*flagptr){
+    case '0' ... '9':
+      show_args = 1;
+      parse_pid(flagptr);
+      break;
+    case '-':
+      flagptr++;
+      parse_sysv_option();
+      break;
+    default:
+      show_args = 1;
+      parse_bsd_option();
+      break;
+    }
+  }
+  /**** sanity check and clean-up ****/
+  if(want_one_pid) sel++;
+  if(want_one_command) sel++;
+  if(select_notty || select_all) sel++;
+  if(sel>1 || select_notty>1 || select_all>1 || bsd_c_option>1 || old_h_option>1) usage();
+  if(bsd_c_option) show_args = 0;
+}
+
+#ifdef __sun__
+/* return 1 if it works, or 0 for failure */
+static int stat2proc(int pid) {
+    struct psinfo p;  //   /proc/*/psinfo, struct psinfo, psinfo_t
+    char buf[32];
+    int num;
+    int fd;
+    int tty_maj, tty_min;
+    snprintf(buf, sizeof buf, "/proc/%d/psinfo", pid);
+    if ( (fd = open(buf, O_RDONLY, 0) ) == -1 ) return 0;
+    num = read(fd, &p, sizeof p);
+    close(fd);
+    if(num != sizeof p) return 0;
+
+    num = PRFNSZ;
+    if (num >= sizeof P_cmd) num = sizeof P_cmd - 1;
+    memcpy(P_cmd, p.pr_fname, num);  // p.pr_fname or p.pr_lwp.pr_name
+    P_cmd[num] = '\0';
+
+    P_pid     = p.pr_pid;
+    P_ppid    = p.pr_ppid;
+    P_pgrp    = p.pr_pgid;
+    P_session = p.pr_sid;
+    P_euid    = p.pr_euid;
+    P_rss     = p.pr_rssize;
+    P_vsize   = p.pr_size;
+    P_start_time = p.pr_start.tv_sec;
+    P_wchan   = p.pr_lwp.pr_wchan;
+    P_state   = p.pr_lwp.pr_sname;
+    P_nice    = p.pr_lwp.pr_nice;
+    P_priority = p.pr_lwp.pr_pri;  // or pr_oldpri
+//    P_ruid    = p.pr_uid;
+//    P_rgid    = p.pr_gid;
+//    P_egid    = p.pr_egid;
+
+#if 0
+    // don't support these
+    P_tpgid; P_flags,
+    P_min_flt, P_cmin_flt, P_maj_flt, P_cmaj_flt, P_utime, P_stime;
+    P_cutime, P_cstime, P_timeout, P_alarm;
+    P_rss_rlim, P_start_code, P_end_code, P_start_stack, P_kstk_esp, P_kstk_eip;
+    P_signal, P_blocked, P_sigignore, P_sigcatch;
+    P_nswap, P_cnswap;
+#endif
+
+    // we like it Linux-encoded :-)
+    tty_maj = major(p.pr_ttydev);
+    tty_min = minor(p.pr_ttydev);
+    P_tty_num = DEV_ENCODE(tty_maj,tty_min);
+
+    snprintf(P_tty_text, sizeof P_tty_text, "%3d,%-3d", tty_maj, tty_min);
+#if 1
+    if (tty_maj == 24) snprintf(P_tty_text, sizeof P_tty_text, "pts/%-3u", tty_min);
+    if (P_tty_num == NO_TTY_VALUE)    memcpy(P_tty_text, "   ?   ", 8);
+    if (P_tty_num == DEV_ENCODE(0,0)) memcpy(P_tty_text, "console", 8);
+#endif
+
+    if(P_pid != pid) return 0;
+    return 1;
+}
+#endif
+
+#ifdef __FreeBSD__
+/* return 1 if it works, or 0 for failure */
+static int stat2proc(int pid) {
+    char buf[400];
+    int num;
+    int fd;
+    char* tmp;
+    int tty_maj, tty_min;
+    snprintf(buf, 32, "/proc/%d/status", pid);
+    if ( (fd = open(buf, O_RDONLY, 0) ) == -1 ) return 0;
+    num = read(fd, buf, sizeof buf - 1);
+    close(fd);
+    if(num<43) return 0;
+    buf[num] = '\0';
+
+    P_state = '-';
+
+    // FreeBSD /proc/*/status is seriously fucked. Unlike the Linux
+    // files, we can't use strrchr to find the end of a command name.
+    // Spaces in command names do not get escaped. To avoid spoofing,
+    // one may skip 20 characters and then look _forward_ only to
+    // find a pattern of entries that are {with,with,without} a comma.
+    // The entry without a comma is wchan. Then count backwards!
+    //
+    // Don't bother for now. FreeBSD isn't worth the trouble.
+
+    tmp = strchr(buf,' ');
+    num = tmp - buf;
+    if (num >= sizeof P_cmd) num = sizeof P_cmd - 1;
+    memcpy(P_cmd,buf,num);
+    P_cmd[num] = '\0';
+
+    num = sscanf(tmp+1,
+       "%d %d %d %d "
+       "%d,%d "
+       "%*s "
+       "%ld,%*d "
+       "%ld,%*d "
+       "%ld,%*d "
+       "%*s "
+       "%d %d ",
+       &P_pid, &P_ppid, &P_pgrp, &P_session,
+       &tty_maj, &tty_min,
+       /* SKIP funny flags thing */
+       &P_start_time, /* SKIP microseconds */
+       &P_utime, /* SKIP microseconds */
+       &P_stime, /* SKIP microseconds */
+       /* SKIP &P_wchan, for now -- it is a string */
+       &P_euid, &P_euid   // don't know which is which
+    );
+/*    fprintf(stderr, "stat2proc converted %d fields.\n",num); */
+
+    snprintf(P_tty_text, sizeof P_tty_text, "%3d,%-3d", tty_maj, tty_min);
+    P_tty_num = DEV_ENCODE(tty_maj,tty_min);
+// tty decode is 224 to 256 bytes on i386
+#if 1
+    tmp = NULL;
+    if (tty_maj ==  5) tmp = " ttyp%c ";
+    if (tty_maj == 12) tmp = " ttyv%c ";
+    if (tty_maj == 28) tmp = " ttyd%c ";
+    if (P_tty_num == NO_TTY_VALUE) tmp = "   ?   ";
+    if (P_tty_num == DEV_ENCODE(0,0)) tmp = "console";
+    if (P_tty_num == DEV_ENCODE(12,255)) tmp = "consolectl";
+    if (tmp) {
+      snprintf(
+        P_tty_text,
+        sizeof P_tty_text,
+        tmp,
+        "0123456789abcdefghijklmnopqrstuvwxyz"[tty_min&31]
+      );
+    }
+#endif
+
+    if(num < 9) return 0;
+    if(P_pid != pid) return 0;
+    return 1;
+}
+#endif
+
+#ifdef __linux__
+/* return 1 if it works, or 0 for failure */
+static int stat2proc(int pid) {
+    char buf[800]; /* about 40 fields, 64-bit decimal is about 20 chars */
+    int num;
+    int fd;
+    char* tmp;
+    struct stat sb; /* stat() used to get EUID */
+    snprintf(buf, 32, "/proc/%d/stat", pid);
+    if ( (fd = open(buf, O_RDONLY, 0) ) == -1 ) return 0;
+    num = read(fd, buf, sizeof buf - 1);
+    fstat(fd, &sb);
+    P_euid = sb.st_uid;
+    close(fd);
+    if(num<80) return 0;
+    buf[num] = '\0';
+    tmp = strrchr(buf, ')');      /* split into "PID (cmd" and "<rest>" */
+    *tmp = '\0';                  /* replace trailing ')' with NUL */
+    /* parse these two strings separately, skipping the leading "(". */
+    memset(P_cmd, 0, sizeof P_cmd);          /* clear */
+    sscanf(buf, "%d (%15c", &P_pid, P_cmd);  /* comm[16] in kernel */
+    num = sscanf(tmp + 2,                    /* skip space after ')' too */
+       "%c "
+       "%d %d %d %d %d "
+       "%lu %lu %lu %lu %lu %lu %lu "
+       "%ld %ld %ld %ld %ld %ld "
+       "%lu %lu "
+       "%ld "
+       "%lu %lu %lu %lu %lu %lu "
+       "%u %u %u %u " /* no use for RT signals */
+       "%lu %lu %lu",
+       &P_state,
+       &P_ppid, &P_pgrp, &P_session, &P_tty_num, &P_tpgid,
+       &P_flags, &P_min_flt, &P_cmin_flt, &P_maj_flt, &P_cmaj_flt, &P_utime, &P_stime,
+       &P_cutime, &P_cstime, &P_priority, &P_nice, &P_timeout, &P_alarm,
+       &P_start_time, &P_vsize,
+       &P_rss,
+       &P_rss_rlim, &P_start_code, &P_end_code, &P_start_stack, &P_kstk_esp, &P_kstk_eip,
+       &P_signal, &P_blocked, &P_sigignore, &P_sigcatch,
+       &P_wchan, &P_nswap, &P_cnswap
+    );
+/*    fprintf(stderr, "stat2proc converted %d fields.\n",num); */
+    P_vsize /= 1024;
+    P_rss *= (PAGE_SIZE/1024);
+
+    memcpy(P_tty_text, "   ?   ", 8);
+    if (P_tty_num != NO_TTY_VALUE) {
+      int tty_maj = (P_tty_num>>8)&0xfff;
+      int tty_min = (P_tty_num&0xff) | ((P_tty_num>>12)&0xfff00);
+      snprintf(P_tty_text, sizeof P_tty_text, "%3d,%-3d", tty_maj, tty_min);
+    }
+
+    if(num < 30) return 0;
+    if(P_pid != pid) return 0;
+    return 1;
+}
+#endif
+
+static const char *do_time(unsigned long t){
+  int hh,mm,ss;
+  static char buf[32];
+  int cnt = 0;
+  t /= HZ;
+  ss = t%60;
+  t /= 60;
+  mm = t%60;
+  t /= 60;
+  hh = t%24;
+  t /= 24;
+  if(t) cnt = snprintf(buf, sizeof buf, "%d-", (int)t);
+  snprintf(cnt + buf, sizeof(buf)-cnt, "%02d:%02d:%02d", hh, mm, ss);
+  return buf;
+}
+
+static const char *do_user(void){
+  static char buf[32];
+  static struct passwd *p;
+  static int lastuid = -1;
+  if(P_euid != lastuid){
+    p = getpwuid(P_euid);
+    if(p) snprintf(buf, sizeof buf, "%-8.8s", p->pw_name);
+    else  snprintf(buf, sizeof buf, "%5d   ", P_euid);
+  }
+  return buf;
+}
+
+static const char *do_cpu(int longform){
+  static char buf[8];
+  strcpy(buf," -  ");
+  if(!longform) buf[2] = '\0';
+  return buf;
+}
+
+static const char *do_mem(int longform){
+  static char buf[8];
+  strcpy(buf," -  ");
+  if(!longform) buf[2] = '\0';
+  return buf;
+}
+
+static const char *do_stime(void){
+  static char buf[32];
+  strcpy(buf,"  -  ");
+  return buf;
+}
+
+static void print_proc(void){
+  switch(ps_format){
+  case 0:
+    printf("%5d %s %s", P_pid, P_tty_text, do_time(P_utime+P_stime));
+    break;
+  case 'o':
+    printf("%d\n", P_pid);
+    return; /* don't want the command */
+  case 'l':
+    printf(
+      "0 %c %5d %5d %5d %s %3d %3d - "
+      "%5ld %06x %s %s",
+      P_state, P_euid, P_pid, P_ppid, do_cpu(0),
+      (int)P_priority, (int)P_nice, P_vsize/(PAGE_SIZE/1024),
+      (unsigned)(P_wchan&0xffffff), P_tty_text, do_time(P_utime+P_stime)
+    );
+    break;
+  case 'f':
+    printf(
+      "%8s %5d %5d %s %s %s %s",
+      do_user(), P_pid, P_ppid, do_cpu(0), do_stime(), P_tty_text, do_time(P_utime+P_stime)
+    );
+    break;
+  case 'j':
+    printf(
+      "%5d %5d %5d %s %s",
+      P_pid, P_pgrp, P_session, P_tty_text, do_time(P_utime+P_stime)
+    );
+    break;
+  case 'u'|0x80:
+    printf(
+      "%8s %5d %s %s %5ld %4ld %s %c %s %s",
+      do_user(), P_pid, do_cpu(1), do_mem(1), P_vsize, P_rss, P_tty_text, P_state,
+      do_stime(), do_time(P_utime+P_stime)
+    );
+    break;
+  case 'v'|0x80:
+    printf(
+      "%5d %s %c %s %6d   -   - %5d %s",
+      P_pid, P_tty_text, P_state, do_time(P_utime+P_stime), (int)P_maj_flt,
+      (int)P_rss, do_mem(1)
+    );
+    break;
+  case 'j'|0x80:
+    printf(
+      "%5d %5d %5d %5d %s %5d %c %5d %s",
+      P_ppid, P_pid, P_pgrp, P_session, P_tty_text, P_tpgid, P_state, P_euid, do_time(P_utime+P_stime)
+    );
+    break;
+  case 'l'|0x80:
+    printf(
+      "0 %5d %5d %5d %3d %3d "
+      "%5ld %4ld %06x %c %s %s",
+      P_euid, P_pid, P_ppid, (int)P_priority, (int)P_nice,
+      P_vsize, P_rss, (unsigned)(P_wchan&0xffffff), P_state, P_tty_text, do_time(P_utime+P_stime)
+    );
+    break;
+  default:
+    ;
+  }
+  if(show_args) printf(" [%s]\n", P_cmd);
+  else          printf(" %s\n", P_cmd);
+}
+
+
+int main(int argc, char *argv[]){
+  arg_parse(argc, argv);
+#if 0
+  choose_dimensions();
+#endif
+  if(!old_h_option){
+    const char *head;
+    switch(ps_format){
+    default: /* can't happen */
+    case 0:        head = "  PID TTY         TIME CMD"; break;
+    case 'l':      head = "F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN    TTY       TIME CMD"; break;
+    case 'f':      head = "USER       PID  PPID  C STIME   TTY       TIME CMD"; break;
+    case 'j':      head = "  PID  PGID   SID TTY         TIME CMD"; break;
+    case 'u'|0x80: head = "USER       PID %CPU %MEM   VSZ  RSS   TTY   S START     TIME COMMAND"; break;
+    case 'v'|0x80: head = "  PID   TTY   S     TIME  MAJFL TRS DRS   RSS %MEM COMMAND"; break;
+    case 'j'|0x80: head = " PPID   PID  PGID   SID   TTY   TPGID S   UID     TIME COMMAND"; break;
+    case 'l'|0x80: head = "F   UID   PID  PPID PRI  NI   VSZ  RSS WCHAN  S   TTY       TIME COMMAND"; break;
+    }
+    printf("%s\n",head);
+  }
+  if(want_one_pid){
+    if(stat2proc(want_one_pid)) print_proc();
+    else exit(1);
+  }else{
+    struct dirent *ent;          /* dirent handle */
+    DIR *dir;
+    int ouruid;
+    int found_a_proc;
+    found_a_proc = 0;
+    ouruid = getuid();
+    dir = opendir("/proc");
+    while(( ent = readdir(dir) )){
+      if(*ent->d_name<'0' || *ent->d_name>'9') continue;
+      if(!stat2proc(atoi(ent->d_name))) continue;
+      if(want_one_command){
+        if(strcmp(want_one_command,P_cmd)) continue;
+      }else{
+        if(!select_notty && P_tty_num==NO_TTY_VALUE) continue;
+        if(!select_all && P_euid!=ouruid) continue;
+      }
+      found_a_proc++;
+      print_proc();
+    }
+    closedir(dir);
+    exit(!found_a_proc);
+  }
+  return 0;
+}
diff --git a/procps-3.2.8/pgrep.1 b/procps-3.2.8/pgrep.1
new file mode 100644
index 0000000..ae2edc2
--- /dev/null
+++ b/procps-3.2.8/pgrep.1
@@ -0,0 +1,162 @@
+.\" Manual page for pgrep / pkill.
+.\" Licensed under version 2 of the GNU General Public License.
+.\" Copyright 2000 Kjetil Torgrim Homme
+.\"
+.TH PGREP 1 "June 25, 2000" "Linux" "Linux User's Manual"
+.SH NAME
+pgrep, pkill \- look up or signal processes based on name and other attributes
+
+.SH SYNOPSIS
+pgrep [\-flvx] [\-d \fIdelimiter\fP] [\-n|\-o] [\-P \fIppid\fP,...] [\-g \fIpgrp\fP,...]
+.br
+	[\-s \fIsid\fP,...] [\-u \fIeuid\fP,...] [\-U \fIuid\fP,...] [\-G \fIgid\fP,...]
+.br
+	[\-t \fIterm\fP,...] [\fIpattern\fP]
+
+pkill [\-\fIsignal\fP] [\-fvx] [\-n|\-o] [\-P \fIppid\fP,...] [\-g \fIpgrp\fP,...]
+.br
+	[\-s \fIsid\fP,...] [\-u \fIeuid\fP,...] [\-U \fIuid\fP,...] [\-G \fIgid\fP,...]
+.br
+	[\-t \fIterm\fP,...] [\fIpattern\fP]
+
+.SH DESCRIPTION
+\fBpgrep\fP looks through the currently running processes and lists the
+process IDs which matches the selection criteria to stdout.  All
+the criteria have to match.  For example,
+
+pgrep -u root sshd
+
+will only list the processes called \fBsshd\fP AND owned by \fBroot\fP.
+On the other hand,
+
+pgrep -u root,daemon
+
+will list the processes owned by \fBroot\fP OR \fBdaemon\fP.
+
+\fBpkill\fP will send the specified signal (by default \fBSIGTERM\fP)
+to each process instead of listing them on stdout.
+
+.SH OPTIONS
+.TP
+\-d \fIdelimiter\fP
+Sets the string used to delimit each process ID in the output (by
+default a newline).  (\fBpgrep\fP only.)
+.TP
+\-f
+The \fIpattern\fP is normally only matched against the process name.
+When \-f is set, the full command line is used.
+.TP
+\-g \fIpgrp\fP,...
+Only match processes in the process group IDs listed.  Process group 0
+is translated into \fBpgrep\fP's or \fBpkill\fP's own process group.
+.TP
+\-G \fIgid\fP,...
+Only match processes whose real group ID is listed.  Either the
+numerical or symbolical value may be used.
+.TP
+\-l
+List the process name as well as the process ID. (\fBpgrep\fP only.)
+.TP
+\-n
+Select only the newest (most recently started) of the matching
+processes.
+.TP
+\-o
+Select only the oldest (least recently started) of the matching
+processes.
+.TP
+\-P \fIppid\fP,...
+Only match processes whose parent process ID is listed.
+.TP
+\-s \fIsid\fP,...
+Only match processes whose process session ID is listed.  Session ID 0
+is translated into \fBpgrep\fP's or \fBpkill\fP's own session ID.
+.TP
+\-t \fIterm\fP,...
+Only match processes whose controlling terminal is listed.  The
+terminal name should be specified without the "/dev/" prefix.
+.TP
+\-u \fIeuid\fP,...
+Only match processes whose effective user ID is listed.  Either the
+numerical or symbolical value may be used.
+.TP
+\-U \fIuid\fP,...
+Only match processes whose real user ID is listed.  Either the
+numerical or symbolical value may be used.
+.TP
+\-v
+Negates the matching.
+.TP
+\-x
+Only match processes whose name (or command line if \-f is specified)
+\fBexactly\fP match the \fIpattern\fP.
+.TP
+\-\fIsignal\fP
+Defines the signal to send to each matched process.  Either the
+numeric or the symbolic signal name can be used.  (\fBpkill\fP only.)
+
+.SH OPERANDS
+.TP
+\fIpattern\fP
+Specifies an Extended Regular Expression for matching against the
+process names or command lines.
+
+.SH EXAMPLES
+Example 1: Find the process ID of the \fBnamed\fP daemon:
+
+unix$ pgrep \-u root named
+
+Example 2: Make \fBsyslog\fP reread its configuration file:
+
+unix$ pkill \-HUP syslogd
+
+Example 3: Give detailed information on all \fBxterm\fP processes:
+
+unix$ ps \-fp $(pgrep \-d, \-x xterm)
+
+Example 4: Make all \fBnetscape\fP processes run nicer:
+
+unix$ renice +4 `pgrep netscape`
+
+.SH "EXIT STATUS"
+.TP
+.I "0"
+One or more processes matched the criteria.
+.TP
+.I "1"
+No processes matched.
+.TP
+.I "2"
+Syntax error in the command line.
+.TP
+.I "3"
+Fatal error: out of memory etc.
+
+.SH NOTES
+The process name used for matching is limited to the 15 characters
+present in the output of /proc/\fIpid\fP/stat.  Use the \-f option to
+match against the complete command line, /proc/\fIpid\fP/cmdline.
+
+The running \fBpgrep\fP or \fBpkill\fP process will never report
+itself as a match.
+
+.SH BUGS
+The options \-n and \-o and \-v can not be combined.  Let me know if
+you need to do this.
+
+Defunct processes are reported.
+
+.SH "SEE ALSO"
+ps(1) regex(7) signal(7) killall(1) skill(1) kill(1) kill(2)
+
+.SH STANDARDS
+\fBpkill\fP and \fBpgrep\fP were introduced in Sun's Solaris 7.  This
+implementation is fully compatible.
+
+.SH AUTHOR
+Kjetil Torgrim Homme <kjetilho@ifi.uio.no>
+
+Albert Cahalan <albert@users.sf.net> is the current maintainer of
+the procps package.
+
+Please send bug reports to <procps-feedback@lists.sf.net>
diff --git a/procps-3.2.8/pgrep.c b/procps-3.2.8/pgrep.c
new file mode 100644
index 0000000..bbb7cd1
--- /dev/null
+++ b/procps-3.2.8/pgrep.c
@@ -0,0 +1,732 @@
+/* emacs settings:  -*- c-basic-offset: 8 tab-width: 8 -*-
+ *
+ * pgrep/pkill -- utilities to filter the process table
+ *
+ * Copyright 2000 Kjetil Torgrim Homme <kjetilho@ifi.uio.no>
+ *
+ * May be distributed under the conditions of the
+ * GNU General Public License; a copy is in COPYING
+ *
+ * Changes by Albert Cahalan, 2002,2006.
+ * 
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <pwd.h>
+#include <grp.h>
+#include <regex.h>
+#include <errno.h>
+
+#include "proc/readproc.h"
+#include "proc/sig.h"
+#include "proc/devname.h"
+#include "proc/sysinfo.h"
+#include "proc/version.h" /* procps_version */
+
+// EXIT_SUCCESS is 0
+// EXIT_FAILURE is 1
+#define EXIT_USAGE 2
+#define EXIT_FATAL 3
+
+static int i_am_pkill = 0;
+static const char *progname = "pgrep";
+
+union el {
+	long	num;
+	char *	str;
+};
+
+/* User supplied arguments */
+
+static int opt_full = 0;
+static int opt_long = 0;
+static int opt_oldest = 0;
+static int opt_newest = 0;
+static int opt_negate = 0;
+static int opt_exact = 0;
+static int opt_signal = SIGTERM;
+static int opt_lock = 0;
+static int opt_case = 0;
+
+static const char *opt_delim = "\n";
+static union el *opt_pgrp = NULL;
+static union el *opt_rgid = NULL;
+static union el *opt_pid = NULL;
+static union el *opt_ppid = NULL;
+static union el *opt_sid = NULL;
+static union el *opt_term = NULL;
+static union el *opt_euid = NULL;
+static union el *opt_ruid = NULL;
+static char *opt_pattern = NULL;
+static char *opt_pidfile = NULL;
+
+static int usage (int opt) NORETURN;
+static int usage (int opt)
+{
+	int err = (opt=='?'); /* getopt() uses '?' to mark an error */
+	FILE *fp = err ? stderr : stdout;
+
+	if (i_am_pkill)
+		fprintf (fp, "Usage: pkill [-SIGNAL] [-fvx] ");
+	else
+		fprintf (fp, "Usage: pgrep [-flvx] [-d DELIM] ");
+	fprintf (fp, "[-n|-o] [-P PPIDLIST] [-g PGRPLIST] [-s SIDLIST]\n"
+		 "\t[-u EUIDLIST] [-U UIDLIST] [-G GIDLIST] [-t TERMLIST] "
+		 "[PATTERN]\n");
+
+	exit(err ? EXIT_USAGE : EXIT_SUCCESS);
+}
+
+
+static union el *split_list (const char *restrict str, int (*convert)(const char *, union el *))
+{
+	char *copy = strdup (str);
+	char *ptr = copy;
+	char *sep_pos;
+	int i = 0;
+	int size = 0;
+	union el *list = NULL;
+
+	do {
+		if (i == size) {
+			size = size * 5 / 4 + 4;
+			// add 1 because slot zero is a count
+			list = realloc (list, 1 + size * sizeof *list);
+			if (list == NULL)
+				exit (EXIT_FATAL);
+		}
+		sep_pos = strchr (ptr, ',');
+		if (sep_pos)
+			*sep_pos = 0;
+		// Use ++i instead of i++ because slot zero is a count
+		if (!convert (ptr, &list[++i]))
+			exit (EXIT_USAGE);
+		if (sep_pos)
+			ptr = sep_pos + 1;
+	} while (sep_pos);
+
+	free (copy);
+	if (!i) {
+		free (list);
+		list = NULL;
+	} else {
+		list[0].num = i;
+	}
+	return list;
+}
+
+// strict_atol returns a Boolean: TRUE if the input string
+// contains a plain number, FALSE if there are any non-digits.
+static int strict_atol (const char *restrict str, long *restrict value)
+{
+	int res = 0;
+	int sign = 1;
+
+	if (*str == '+')
+		++str;
+	else if (*str == '-') {
+		++str;
+		sign = -1;
+	}
+
+	for ( ; *str; ++str) {
+		if (! isdigit (*str))
+			return (0);
+		res *= 10;
+		res += *str - '0';
+	}
+	*value = sign * res;
+	return 1;
+}
+
+#include <sys/file.h>
+
+// Seen non-BSD code do this:
+//
+//if (fcntl_lock(pid_fd, F_SETLK, F_WRLCK, SEEK_SET, 0, 0) == -1)
+//                return -1;
+int fcntl_lock(int fd, int cmd, int type, int whence, int start, int len)
+{
+        struct flock lock[1];
+
+        lock->l_type = type;
+        lock->l_whence = whence;
+        lock->l_start = start;
+        lock->l_len = len;
+
+        return fcntl(fd, cmd, lock);
+}
+                                                
+
+// We try a read lock. The daemon should have a write lock.
+// Seen using flock: FreeBSD code
+static int has_flock(int fd)
+{
+	return flock(fd, LOCK_SH|LOCK_NB)==-1 && errno==EWOULDBLOCK;
+}
+
+// We try a read lock. The daemon should have a write lock.
+// Seen using fcntl: libslack
+static int has_fcntl(int fd)
+{
+	struct flock f;  // seriously, struct flock is for a fnctl lock!
+	f.l_type = F_RDLCK;
+	f.l_whence = SEEK_SET;
+	f.l_start = 0;
+	f.l_len = 0;
+	return fcntl(fd,F_SETLK,&f)==-1 && (errno==EACCES || errno==EAGAIN);
+}
+
+static union el *read_pidfile(void)
+{
+	char buf[12];
+	int fd;
+	struct stat sbuf;
+	char *endp;
+	int pid;
+	union el *list = NULL;
+
+	fd = open(opt_pidfile, O_RDONLY|O_NOCTTY|O_NONBLOCK);
+	if(fd<0)
+		goto out;
+	if(fstat(fd,&sbuf) || !S_ISREG(sbuf.st_mode) || sbuf.st_size<1)
+		goto out;
+	// type of lock, if any, is not standardized on Linux
+	if(opt_lock && !has_flock(fd) && !has_fcntl(fd))
+			goto out;
+	memset(buf,'\0',sizeof buf);
+	buf[read(fd,buf+1,sizeof buf-2)] = '\0';
+	pid = strtoul(buf+1,&endp,10);
+	if(endp<=buf+1 || pid<1 || pid>0x7fffffff)
+		goto out;
+	if(*endp && !isspace(*endp))
+		goto out;
+	list = malloc(2 * sizeof *list);
+	list[0].num = 1;
+	list[1].num = pid;
+out:
+	close(fd);
+	return list;
+}
+
+static int conv_uid (const char *restrict name, union el *restrict e)
+{
+	struct passwd *pwd;
+
+	if (strict_atol (name, &e->num))
+		return (1);
+
+	pwd = getpwnam (name);
+	if (pwd == NULL) {
+		fprintf (stderr, "%s: invalid user name: %s\n",
+			 progname, name);
+		return 0;
+	}
+	e->num = pwd->pw_uid;
+	return 1;
+}
+
+
+static int conv_gid (const char *restrict name, union el *restrict e)
+{
+	struct group *grp;
+
+	if (strict_atol (name, &e->num))
+		return 1;
+
+	grp = getgrnam (name);
+	if (grp == NULL) {
+		fprintf (stderr, "%s: invalid group name: %s\n",
+			 progname, name);
+		return 0;
+	}
+	e->num = grp->gr_gid;
+	return 1;
+}
+
+
+static int conv_pgrp (const char *restrict name, union el *restrict e)
+{
+	if (! strict_atol (name, &e->num)) {
+		fprintf (stderr, "%s: invalid process group: %s\n",
+			 progname, name);
+		return 0;
+	}
+	if (e->num == 0)
+		e->num = getpgrp ();
+	return 1;
+}
+
+
+static int conv_sid (const char *restrict name, union el *restrict e)
+{
+	if (! strict_atol (name, &e->num)) {
+		fprintf (stderr, "%s: invalid session id: %s\n",
+			 progname, name);
+		return 0;
+	}
+	if (e->num == 0)
+		e->num = getsid (0);
+	return 1;
+}
+
+
+static int conv_num (const char *restrict name, union el *restrict e)
+{
+	if (! strict_atol (name, &e->num)) {
+		fprintf (stderr, "%s: not a number: %s\n",
+			 progname, name);
+		return 0;
+	}
+	return 1;
+}
+
+
+static int conv_str (const char *restrict name, union el *restrict e)
+{
+	e->str = strdup (name);
+	return 1;
+}
+
+
+static int match_numlist (long value, const union el *restrict list)
+{
+	int found = 0;
+	if (list == NULL)
+		found = 0;
+	else {
+		int i;
+		for (i = list[0].num; i > 0; i--) {
+			if (list[i].num == value)
+				found = 1;
+		}
+	}
+	return found;
+}
+
+static int match_strlist (const char *restrict value, const union el *restrict list)
+{
+	int found = 0;
+	if (list == NULL)
+		found = 0;
+	else {
+		int i;
+		for (i = list[0].num; i > 0; i--) {
+			if (! strcmp (list[i].str, value))
+				found = 1;
+		}
+	}
+	return found;
+}
+
+static void output_numlist (const union el *restrict list, int num)
+{
+	int i;
+	const char *delim = opt_delim;
+	for (i = 0; i < num; i++) {
+		if(i+1==num)
+			delim = "\n";
+		printf ("%ld%s", list[i].num, delim);
+	}
+}
+
+static void output_strlist (const union el *restrict list, int num)
+{
+// FIXME: escape codes
+	int i;
+	const char *delim = opt_delim;
+	for (i = 0; i < num; i++) {
+		if(i+1==num)
+			delim = "\n";
+		printf ("%s%s", list[i].str, delim);
+	}
+}
+
+static PROCTAB *do_openproc (void)
+{
+	PROCTAB *ptp;
+	int flags = 0;
+
+	if (opt_pattern || opt_full)
+		flags |= PROC_FILLCOM;
+	if (opt_ruid || opt_rgid)
+		flags |= PROC_FILLSTATUS;
+	if (opt_oldest || opt_newest || opt_pgrp || opt_sid || opt_term)
+		flags |= PROC_FILLSTAT;
+	if (!(flags & PROC_FILLSTAT))
+		flags |= PROC_FILLSTATUS;  // FIXME: need one, and PROC_FILLANY broken
+	if (opt_euid && !opt_negate) {
+		int num = opt_euid[0].num;
+		int i = num;
+		uid_t *uids = malloc (num * sizeof (uid_t));
+		if (uids == NULL)
+			exit (EXIT_FATAL);
+		while (i-- > 0) {
+			uids[i] = opt_euid[i+1].num;
+		}
+		flags |= PROC_UID;
+		ptp = openproc (flags, uids, num);
+	} else {
+		ptp = openproc (flags);
+	}
+	return ptp;
+}
+
+static regex_t * do_regcomp (void)
+{
+	regex_t *preg = NULL;
+
+	if (opt_pattern) {
+		char *re;
+		char errbuf[256];
+		int re_err;
+
+		preg = malloc (sizeof (regex_t));
+		if (preg == NULL)
+			exit (EXIT_FATAL);
+		if (opt_exact) {
+			re = malloc (strlen (opt_pattern) + 5);
+			if (re == NULL)
+				exit (EXIT_FATAL);
+			sprintf (re, "^(%s)$", opt_pattern);
+		} else {
+		 	re = opt_pattern;
+		}
+
+		re_err = regcomp (preg, re, REG_EXTENDED | REG_NOSUB | opt_case);
+		if (re_err) {
+			regerror (re_err, preg, errbuf, sizeof(errbuf));
+			fputs(errbuf,stderr);
+			exit (EXIT_USAGE);
+		}
+	}
+	return preg;
+}
+
+static union el * select_procs (int *num)
+{
+	PROCTAB *ptp;
+	proc_t task;
+	unsigned long long saved_start_time;      // for new/old support
+	pid_t saved_pid = 0;                      // for new/old support
+	int matches = 0;
+	int size = 0;
+	regex_t *preg;
+	pid_t myself = getpid();
+	union el *list = NULL;
+	char cmd[4096];
+
+	ptp = do_openproc();
+	preg = do_regcomp();
+
+	if (opt_newest) saved_start_time =  0ULL;
+	if (opt_oldest) saved_start_time = ~0ULL;
+	if (opt_newest) saved_pid = 0;
+	if (opt_oldest) saved_pid = INT_MAX;
+	
+	memset(&task, 0, sizeof (task));
+	while(readproc(ptp, &task)) {
+		int match = 1;
+
+		if (task.XXXID == myself)
+			continue;
+		else if (opt_newest && task.start_time < saved_start_time)
+			match = 0;
+		else if (opt_oldest && task.start_time > saved_start_time)
+			match = 0;
+		else if (opt_ppid && ! match_numlist (task.ppid, opt_ppid))
+			match = 0;
+		else if (opt_pid && ! match_numlist (task.tgid, opt_pid))
+			match = 0;
+		else if (opt_pgrp && ! match_numlist (task.pgrp, opt_pgrp))
+			match = 0;
+		else if (opt_euid && ! match_numlist (task.euid, opt_euid))
+			match = 0;
+		else if (opt_ruid && ! match_numlist (task.ruid, opt_ruid))
+			match = 0;
+		else if (opt_rgid && ! match_numlist (task.rgid, opt_rgid))
+			match = 0;
+		else if (opt_sid && ! match_numlist (task.session, opt_sid))
+			match = 0;
+		else if (opt_term) {
+			if (task.tty == 0) {
+				match = 0;
+			} else {
+				char tty[256];
+				dev_to_tty (tty, sizeof(tty) - 1,
+					    task.tty, task.XXXID, ABBREV_DEV);
+				match = match_strlist (tty, opt_term);
+			}
+		}
+		if (opt_long || (match && opt_pattern)) {
+			if (opt_full && task.cmdline) {
+				int i = 0;
+				int bytes = sizeof (cmd) - 1;
+
+				/* make sure it is always NUL-terminated */
+				cmd[bytes] = 0;
+				/* make room for SPC in loop below */
+				--bytes;
+
+				strncpy (cmd, task.cmdline[i], bytes);
+				bytes -= strlen (task.cmdline[i++]);
+				while (task.cmdline[i] && bytes > 0) {
+					strncat (cmd, " ", bytes);
+					strncat (cmd, task.cmdline[i], bytes);
+					bytes -= strlen (task.cmdline[i++]) + 1;
+				}
+			} else {
+				strcpy (cmd, task.cmd);
+			}
+		}
+
+		if (match && opt_pattern) {
+			if (regexec (preg, cmd, 0, NULL, 0) != 0)
+				match = 0;
+		}
+
+		if (match ^ opt_negate) {	/* Exclusive OR is neat */
+			if (opt_newest) {
+				if (saved_start_time == task.start_time &&
+				    saved_pid > task.XXXID)
+					continue;
+				saved_start_time = task.start_time;
+				saved_pid = task.XXXID;
+				matches = 0;
+			}
+			if (opt_oldest) {
+				if (saved_start_time == task.start_time &&
+				    saved_pid < task.XXXID)
+					continue;
+				saved_start_time = task.start_time;
+				saved_pid = task.XXXID;
+				matches = 0;
+			}
+			if (matches == size) {
+				size = size * 5 / 4 + 4;
+				list = realloc(list, size * sizeof *list);
+				if (list == NULL)
+					exit (EXIT_FATAL);
+			}
+			if (opt_long) {
+				char buff[5096];  // FIXME
+				sprintf (buff, "%d %s", task.XXXID, cmd);
+				list[matches++].str = strdup (buff);
+			} else {
+				list[matches++].num = task.XXXID;
+			}
+		}
+		
+		memset (&task, 0, sizeof (task));
+	}
+	closeproc (ptp);
+
+	*num = matches;
+	return list;
+}
+
+
+static void parse_opts (int argc, char **argv)
+{
+	char opts[32] = "";
+	int opt;
+	int criteria_count = 0;
+
+	if (strstr (argv[0], "pkill")) {
+		i_am_pkill = 1;
+		progname = "pkill";
+		/* Look for a signal name or number as first argument */
+		if (argc > 1 && argv[1][0] == '-') {
+			int sig;
+			sig = signal_name_to_number (argv[1] + 1);
+			if (sig == -1 && isdigit (argv[1][1]))
+				sig = atoi (argv[1] + 1);
+			if (sig != -1) {
+				int i;
+				for (i = 2; i < argc; i++)
+					argv[i-1] = argv[i];
+				--argc;
+				opt_signal = sig;
+			}
+		}
+	} else {
+		/* These options are for pgrep only */
+		strcat (opts, "ld:");
+	}
+			
+	strcat (opts, "LF:fnovxP:g:s:u:U:G:t:?V");
+	
+	while ((opt = getopt (argc, argv, opts)) != -1) {
+		switch (opt) {
+//		case 'D':   // FreeBSD: print info about non-matches for debugging
+//			break;
+		case 'F':   // FreeBSD: the arg is a file containing a PID to match
+			opt_pidfile = strdup (optarg);
+			++criteria_count;
+			break;
+		case 'G':   // Solaris: match rgid/rgroup
+	  		opt_rgid = split_list (optarg, conv_gid);
+			if (opt_rgid == NULL)
+				usage (opt);
+			++criteria_count;
+			break;
+//		case 'I':   // FreeBSD: require confirmation before killing
+//			break;
+//		case 'J':   // Solaris: match by project ID (name or number)
+//			break;
+		case 'L':   // FreeBSD: fail if pidfile (see -F) not locked
+			opt_lock++;
+			break;
+//		case 'M':   // FreeBSD: specify core (OS crash dump) file
+//			break;
+//		case 'N':   // FreeBSD: specify alternate namelist file (for us, System.map -- but we don't need it)
+//			break;
+		case 'P':   // Solaris: match by PPID
+	  		opt_ppid = split_list (optarg, conv_num);
+			if (opt_ppid == NULL)
+				usage (opt);
+			++criteria_count;
+			break;
+//		case 'S':   // FreeBSD: don't ignore the built-in kernel tasks
+//			break;
+//		case 'T':   // Solaris: match by "task ID" (probably not a Linux task)
+//			break;
+		case 'U':   // Solaris: match by ruid/rgroup
+	  		opt_ruid = split_list (optarg, conv_uid);
+			if (opt_ruid == NULL)
+				usage (opt);
+			++criteria_count;
+			break;
+		case 'V':
+			fprintf(stdout, "%s (%s)\n", progname, procps_version);
+			exit(EXIT_SUCCESS);
+//		case 'c':   // Solaris: match by contract ID
+//			break;
+		case 'd':   // Solaris: change the delimiter
+			opt_delim = strdup (optarg);
+			break;
+		case 'f':   // Solaris: match full process name (as in "ps -f")
+			opt_full = 1;
+			break;
+		case 'g':   // Solaris: match pgrp
+	  		opt_pgrp = split_list (optarg, conv_pgrp);
+			if (opt_pgrp == NULL)
+				usage (opt);
+			++criteria_count;
+			break;
+//		case 'i':   // FreeBSD: ignore case. OpenBSD: withdrawn. See -I. This sucks.
+//			if (opt_case)
+//				usage (opt);
+//			opt_case = REG_ICASE;
+//			break;
+//		case 'j':   // FreeBSD: restricted to the given jail ID
+//			break;
+		case 'l':   // Solaris: long output format (pgrep only) Should require -f for beyond argv[0] maybe?
+			opt_long = 1;
+			break;
+		case 'n':   // Solaris: match only the newest
+			if (opt_oldest|opt_negate|opt_newest)
+				usage (opt);
+			opt_newest = 1;
+			++criteria_count;
+			break;
+		case 'o':   // Solaris: match only the oldest
+			if (opt_oldest|opt_negate|opt_newest)
+				usage (opt);
+			opt_oldest = 1;
+			++criteria_count;
+			break;
+		case 's':   // Solaris: match by session ID -- zero means self
+	  		opt_sid = split_list (optarg, conv_sid);
+			if (opt_sid == NULL)
+				usage (opt);
+			++criteria_count;
+			break;
+		case 't':   // Solaris: match by tty
+	  		opt_term = split_list (optarg, conv_str);
+			if (opt_term == NULL)
+				usage (opt);
+			++criteria_count;
+			break;
+		case 'u':   // Solaris: match by euid/egroup
+	  		opt_euid = split_list (optarg, conv_uid);
+			if (opt_euid == NULL)
+				usage (opt);
+			++criteria_count;
+			break;
+		case 'v':   // Solaris: as in grep, invert the matching (uh... applied after selection I think)
+			if (opt_oldest|opt_negate|opt_newest)
+				usage (opt);
+	  		opt_negate = 1;
+			break;
+		// OpenBSD -x, being broken, does a plain string
+		case 'x':   // Solaris: use ^(regexp)$ in place of regexp (FreeBSD too)
+			opt_exact = 1;
+			break;
+//		case 'z':   // Solaris: match by zone ID
+//			break;
+		case '?':
+			usage (opt);
+			break;
+		}
+	}
+
+	if(opt_lock && !opt_pidfile){
+		fprintf(stderr, "%s: -L without -F makes no sense\n",progname);
+		usage(0);
+	}
+
+	if(opt_pidfile){
+		opt_pid = read_pidfile();
+		if(!opt_pid){
+			fprintf(stderr, "%s: pidfile not valid\n",progname);
+			usage(0);
+		}
+	}
+
+        if (argc - optind == 1)
+		opt_pattern = argv[optind];
+	else if (argc - optind > 1)
+		usage (0);
+	else if (criteria_count == 0) {
+		fprintf (stderr, "%s: No matching criteria specified\n",
+			 progname);
+		usage (0);
+	}
+}
+
+
+int main (int argc, char *argv[])
+{
+	union el *procs;
+	int num;
+
+	parse_opts (argc, argv);
+
+	procs = select_procs (&num);
+	if (i_am_pkill) {
+		int i;
+		for (i = 0; i < num; i++) {
+			if (kill (procs[i].num, opt_signal) != -1) continue;
+			if (errno==ESRCH) continue; // gone now, which is OK
+			fprintf (stderr, "pkill: %ld - %s\n",
+				 procs[i].num, strerror (errno));
+		}
+	} else {
+		if (opt_long)
+			output_strlist(procs,num);
+		else
+			output_numlist(procs,num);
+	}
+	return !num; // exit(EXIT_SUCCESS) if match, otherwise exit(EXIT_FAILURE)
+}
diff --git a/procps-3.2.8/pkill.1 b/procps-3.2.8/pkill.1
new file mode 100644
index 0000000..0e94b52
--- /dev/null
+++ b/procps-3.2.8/pkill.1
@@ -0,0 +1 @@
+.so man1/pgrep.1
diff --git a/procps-3.2.8/pmap.1 b/procps-3.2.8/pmap.1
new file mode 100644
index 0000000..a91d0e8
--- /dev/null
+++ b/procps-3.2.8/pmap.1
@@ -0,0 +1,39 @@
+'\" t
+.\" (The preceding line is a note to broken versions of man to tell
+.\" them to pre-process this man page with tbl)
+.\" Man page for pmap.
+.\" Licensed under version 2 of the GNU General Public License.
+.\" Written by Albert Cahalan.
+.\"
+.TH PMAP 1 "October 26, 2002" "Linux" "Linux User's Manual"
+.SH NAME
+pmap \- report memory map of a process
+
+.SH SYNOPSIS
+.nf
+pmap [ -x | -d ] [ -q ] pids...
+pmap -V
+.fi
+
+.SH DESCRIPTION
+The pmap command reports the memory map of a process or processes.
+
+.SH "GENERAL OPTIONS"
+.TS
+l l l.
+-x	extended	Show the extended format.
+-d	device	Show the device format.
+-q	quiet	Do not display some header/footer lines.
+-V	show version	Displays version of program.
+.TE
+
+.SH "SEE ALSO"
+ps(1) pgrep(1)
+
+.SH STANDARDS
+No standards apply, but pmap looks an awful lot like a SunOS command.
+
+.SH AUTHOR
+Albert Cahalan <albert@users.sf.net> wrote pmap in 2002, and is the current
+maintainer of the procps collection. Please send bug reports
+to <procps-feedback@lists.sf.net>.
diff --git a/procps-3.2.8/pmap.c b/procps-3.2.8/pmap.c
new file mode 100644
index 0000000..6b865fc
--- /dev/null
+++ b/procps-3.2.8/pmap.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2002 by Albert Cahalan; all rights reserved.
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include "proc/readproc.h"
+#include "proc/version.h"
+#include "proc/escape.h"
+
+static void usage(void) NORETURN;
+static void usage(void){
+  fprintf(stderr,
+    "Usage: pmap [-x | -d] [-q] [-A low,high] pid...\n"
+    "-x  show details\n"
+    "-d  show offset and device number\n"
+    "-q  quiet; less header/footer info\n"
+    "-V  show the version number\n"
+    "-A  limit results to the given range\n"
+  );
+  exit(1);
+}
+
+
+static unsigned KLONG range_low;
+static unsigned KLONG range_high = ~0ull;
+
+static int V_option;
+static int r_option;  // ignored -- for SunOS compatibility
+static int x_option;
+static int d_option;
+static int q_option;
+
+static unsigned shm_minor = ~0u;
+
+static void discover_shm_minor(void){
+  void *addr;
+  int shmid;
+  char mapbuf[256];
+
+  if(!freopen("/proc/self/maps", "r", stdin)) return;
+
+  // create
+  shmid = shmget(IPC_PRIVATE, 42, IPC_CREAT | 0666);
+  if(shmid==-1) return; // failed; oh well
+  // attach
+  addr = shmat(shmid, NULL, SHM_RDONLY);
+  if(addr==(void*)-1) goto out_destroy;
+
+  while(fgets(mapbuf, sizeof mapbuf, stdin)){
+    char flags[32];
+    char *tmp; // to clean up unprintables
+    unsigned KLONG start, end;
+    unsigned long long file_offset, inode;
+    unsigned dev_major, dev_minor;
+    sscanf(mapbuf,"%"KLF"x-%"KLF"x %31s %Lx %x:%x %Lu", &start, &end, flags, &file_offset, &dev_major, &dev_minor, &inode);
+    tmp = strchr(mapbuf,'\n');
+    if(tmp) *tmp='\0';
+    tmp = mapbuf;
+    while(*tmp){
+      if(!isprint(*tmp)) *tmp='?';
+      tmp++;
+    }
+    if(start > (unsigned long)addr) continue;
+    if(dev_major) continue;
+    if(flags[3] != 's') continue;
+    if(strstr(mapbuf,"/SYSV")){
+      shm_minor = dev_minor;
+      break;
+    }
+  }
+
+  if(shmdt(addr)) perror("shmdt");
+
+out_destroy:
+  if(shmctl(shmid, IPC_RMID, NULL)) perror("IPC_RMID");
+
+  return;
+}
+
+
+static const char *mapping_name(proc_t *p, unsigned KLONG addr, unsigned KLONG len, const char *mapbuf, unsigned showpath, unsigned dev_major, unsigned dev_minor, unsigned long long inode){
+  const char *cp;
+
+  if(!dev_major && dev_minor==shm_minor && strstr(mapbuf,"/SYSV")){
+    static char shmbuf[64];
+    snprintf(shmbuf, sizeof shmbuf, "  [ shmid=0x%Lx ]", inode);
+    return shmbuf;
+  }
+
+  cp = strrchr(mapbuf,'/');
+  if(cp){
+    if(showpath) return strchr(mapbuf,'/');
+    return cp[1] ? cp+1 : cp;
+  }
+
+  cp = strchr(mapbuf,'/');
+  if(cp){
+    if(showpath) return cp;
+    return strrchr(cp,'/') + 1;  // it WILL succeed
+  }
+
+  cp = "  [ anon ]";
+  if( (p->start_stack >= addr) && (p->start_stack <= addr+len) )  cp = "  [ stack ]";
+  return cp;
+}
+
+static int one_proc(proc_t *p){
+  char buf[32];
+  char mapbuf[9600];
+  char cmdbuf[512];
+  unsigned long total_shared = 0ul;
+  unsigned long total_private_readonly = 0ul;
+  unsigned long total_private_writeable = 0ul;
+
+  // Overkill, but who knows what is proper? The "w" prog
+  // uses the tty width to determine this.
+  int maxcmd = 0xfffff;
+
+  sprintf(buf,"/proc/%u/maps",p->tgid);
+  if(!freopen(buf, "r", stdin)) return 1;
+
+  escape_command(cmdbuf, p, sizeof cmdbuf, &maxcmd, ESC_ARGS|ESC_BRACKETS);
+  printf("%u:   %s\n", p->tgid, cmdbuf);
+
+  if(!q_option && (x_option|d_option)){
+    if(x_option){
+      if(sizeof(KLONG)==4) printf("Address   Kbytes     RSS    Anon  Locked Mode   Mapping\n");
+      else         printf("Address           Kbytes     RSS    Anon  Locked Mode   Mapping\n");
+    }
+    if(d_option){
+      if(sizeof(KLONG)==4) printf("Address   Kbytes Mode  Offset           Device    Mapping\n");
+      else         printf("Address           Kbytes Mode  Offset           Device    Mapping\n");
+    }
+  }
+
+  while(fgets(mapbuf,sizeof mapbuf,stdin)){
+    char flags[32];
+    char *tmp; // to clean up unprintables
+    unsigned KLONG start, end, diff;
+    unsigned long long file_offset, inode;
+    unsigned dev_major, dev_minor;
+    sscanf(mapbuf,"%"KLF"x-%"KLF"x %31s %Lx %x:%x %Lu", &start, &end, flags, &file_offset, &dev_major, &dev_minor, &inode);
+
+    if(start > range_high)
+      break;
+    if(end < range_low)
+      continue;
+
+    tmp = strchr(mapbuf,'\n');
+    if(tmp) *tmp='\0';
+    tmp = mapbuf;
+    while(*tmp){
+      if(!isprint(*tmp)) *tmp='?';
+      tmp++;
+    }
+    
+    diff = end-start;
+    if(flags[3]=='s') total_shared  += diff;
+    if(flags[3]=='p'){
+      flags[3] = '-';
+      if(flags[1]=='w') total_private_writeable += diff;
+      else              total_private_readonly  += diff;
+    }
+
+    // format used by Solaris 9 and procps-3.2.0+
+    // an 'R' if swap not reserved (MAP_NORESERVE, SysV ISM shared mem, etc.)
+    flags[4] = '-';
+    flags[5] = '\0';
+
+    if(x_option){
+      const char *cp = mapping_name(p, start, diff, mapbuf, 0, dev_major, dev_minor, inode);
+      printf(
+        (sizeof(KLONG)==8)
+          ? "%016"KLF"x %7lu       -       -       - %s  %s\n"
+          :      "%08lx %7lu       -       -       - %s  %s\n",
+        start,
+        (unsigned long)(diff>>10),
+        flags,
+        cp
+      );
+    }
+    if(d_option){
+      const char *cp = mapping_name(p, start, diff, mapbuf, 0, dev_major, dev_minor, inode);
+      printf(
+        (sizeof(KLONG)==8)
+          ? "%016"KLF"x %7lu %s %016Lx %03x:%05x %s\n"
+          :      "%08lx %7lu %s %016Lx %03x:%05x %s\n",
+        start,
+        (unsigned long)(diff>>10),
+        flags,
+        file_offset,
+        dev_major, dev_minor,
+        cp
+      );
+    }
+    if(!x_option && !d_option){
+      const char *cp = mapping_name(p, start, diff, mapbuf, 1, dev_major, dev_minor, inode);
+      printf(
+        (sizeof(KLONG)==8)
+          ? "%016"KLF"x %6luK %s  %s\n"
+          :      "%08lx %6luK %s  %s\n",
+        start,
+        (unsigned long)(diff>>10),
+        flags,
+        cp
+      );
+    }
+    
+  }
+
+
+
+
+  if(!q_option){
+    if(x_option){
+      if(sizeof(KLONG)==8){
+        printf("----------------  ------  ------  ------  ------\n");
+        printf(
+          "total kB %15ld       -       -       -\n",
+          (total_shared + total_private_writeable + total_private_readonly) >> 10
+        );
+      }else{
+        printf("-------- ------- ------- ------- -------\n");
+        printf(
+          "total kB %7ld       -       -       -\n",
+          (total_shared + total_private_writeable + total_private_readonly) >> 10
+        );
+      }
+    }
+    if(d_option){
+        printf(
+          "mapped: %ldK    writeable/private: %ldK    shared: %ldK\n",
+          (total_shared + total_private_writeable + total_private_readonly) >> 10,
+          total_private_writeable >> 10,
+          total_shared >> 10
+        );
+    }
+    if(!x_option && !d_option){
+      if(sizeof(KLONG)==8) printf(" total %16ldK\n", (total_shared + total_private_writeable + total_private_readonly) >> 10);
+      else                 printf(" total %8ldK\n",  (total_shared + total_private_writeable + total_private_readonly) >> 10);
+    }
+  }
+
+  return 0;
+}
+
+
+int main(int argc, char *argv[]){
+  unsigned *pidlist;
+  unsigned count = 0;
+  PROCTAB* PT;
+  proc_t p;
+  int ret = 0;
+
+  if(argc<2) usage();
+  pidlist = malloc(sizeof(unsigned)*argc);  // a bit more than needed perhaps
+
+  while(*++argv){
+    if(!strcmp("--version",*argv)){
+      V_option++;
+      continue;
+    }
+    if(**argv=='-'){
+      char *walk = *argv;
+      if(!walk[1]) usage();
+      while(*++walk){
+        switch(*walk){
+        case 'V':
+          V_option++;
+          break;
+        case 'x':
+          x_option++;
+          break;
+        case 'r':
+          r_option++;
+          break;
+        case 'd':
+          d_option++;
+          break;
+        case 'q':
+          q_option++;
+          break;
+        case 'A':{
+            char *arg1;
+            if(walk[1]){
+              arg1 = walk+1;
+              walk += strlen(walk)-1;
+            }else{
+              arg1 = *++argv;
+              if(!arg1)
+                usage();
+            }
+            char *arg2 = strchr(arg1,',');
+            if(arg2)
+              *arg2 = '\0';
+            arg2 = arg2 ? arg2++ : arg1;
+            
+            if(*arg1)
+              range_low = STRTOUKL(arg1,&arg1,16);
+            if(*arg2)
+              range_high = STRTOUKL(arg2,&arg2,16);
+            if(*arg1 || *arg2)
+            	usage();
+          }
+          break;
+        case 'a': // Sun prints anon/swap reservations
+        case 'F': // Sun forces hostile ptrace-like grab
+        case 'l': // Sun shows unresolved dynamic names
+        case 'L': // Sun shows lgroup info
+        case 's': // Sun shows page sizes
+        case 'S': // Sun shows swap reservations
+        default:
+          usage();
+        }
+      }
+    }else{
+      char *walk = *argv;
+      char *endp;
+      unsigned long pid;
+      if(!strncmp("/proc/",walk,6)){
+        walk += 6;
+        // user allowed to do: pmap /proc/*
+        if(*walk<'0' || *walk>'9') continue;
+      }
+      if(*walk<'0' || *walk>'9') usage();
+      pid = strtoul(walk, &endp, 0);
+      if(pid<1ul || pid>0x7ffffffful || *endp) usage();
+      pidlist[count++] = pid;
+    }
+  }
+
+  if( (x_option|V_option|r_option|d_option|q_option) >> 1 ) usage(); // dupes
+  if(V_option){
+    if(count|x_option|r_option|d_option|q_option) usage();
+    fprintf(stdout, "pmap (%s)\n", procps_version);
+    return 0;
+  }
+  if(count<1) usage();   // no processes
+  if(d_option && x_option) usage();
+
+  discover_shm_minor();
+
+  pidlist[count] = 0;  // old libproc interface is zero-terminated
+  PT = openproc(PROC_FILLSTAT|PROC_FILLARG|PROC_PID, pidlist);
+  while(readproc(PT, &p)){
+    ret |= one_proc(&p);
+    if(p.cmdline) free((void*)*p.cmdline);
+    count--;
+  }
+  closeproc(PT);
+
+  if(count) ret |= 42;  // didn't find all processes asked for
+  return ret;
+}
diff --git a/procps-3.2.8/proc/COPYING b/procps-3.2.8/proc/COPYING
new file mode 100644
index 0000000..92b8903
--- /dev/null
+++ b/procps-3.2.8/proc/COPYING
@@ -0,0 +1,481 @@
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+    		    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/procps-3.2.8/proc/alloc.c b/procps-3.2.8/proc/alloc.c
new file mode 100644
index 0000000..4a0aca7
--- /dev/null
+++ b/procps-3.2.8/proc/alloc.c
@@ -0,0 +1,49 @@
+// Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com
+// Copyright 2002 Albert Cahalan
+//
+// This file is placed under the conditions of the GNU Library
+// General Public License, version 2, or any later version.
+// See file COPYING for information on distribution conditions.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "alloc.h"
+
+void *xcalloc(void *pointer, int size) {
+    void * ret;
+    if (pointer)
+        free(pointer);
+    if (!(ret = calloc(1, size))) {
+        fprintf(stderr, "xcalloc: allocation error, size = %d\n", size);
+        exit(1);
+    }
+    return ret;
+}
+
+void *xmalloc(unsigned int size) {
+    void *p;
+
+    if (size == 0)
+        ++size;
+    p = malloc(size);
+    if (!p) {
+	fprintf(stderr, "xmalloc: malloc(%d) failed", size);
+	perror(NULL);
+	exit(1);
+    }
+    return(p);
+}
+
+void *xrealloc(void *oldp, unsigned int size) {
+    void *p;
+
+    if (size == 0)
+        ++size;
+    p = realloc(oldp, size);
+    if (!p) {
+	fprintf(stderr, "xrealloc: realloc(%d) failed", size);
+	perror(NULL);
+	exit(1);
+    }
+    return(p);
+}
diff --git a/procps-3.2.8/proc/alloc.h b/procps-3.2.8/proc/alloc.h
new file mode 100644
index 0000000..8c5016d
--- /dev/null
+++ b/procps-3.2.8/proc/alloc.h
@@ -0,0 +1,14 @@
+#ifndef PROCPS_PROC_ALLOC_H
+#define PROCPS_PROC_ALLOC_H
+
+#include "procps.h"
+
+EXTERN_C_BEGIN
+
+extern void *xrealloc(void *oldp, unsigned int size) MALLOC;
+extern void *xmalloc(unsigned int size) MALLOC;
+extern void *xcalloc(void *pointer, int size) MALLOC;
+
+EXTERN_C_END
+
+#endif
diff --git a/procps-3.2.8/proc/devname.c b/procps-3.2.8/proc/devname.c
new file mode 100644
index 0000000..32ad954
--- /dev/null
+++ b/procps-3.2.8/proc/devname.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright 1998-2002 by Albert Cahalan; all rights resered.         
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version  
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */                                 
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "version.h"
+#include "devname.h"
+
+// This is the buffer size for a tty name. Any path is legal,
+// which makes PAGE_SIZE appropriate (see kernel source), but
+// that is only 99% portable and utmp only holds 32 anyway.
+// We need at least 20 for guess_name().
+#define TTY_NAME_SIZE 128
+
+/* Who uses what:
+ *
+ * tty_to_dev   w (there is a fancy version in ps)
+ * dev_to_tty   top, ps
+ */
+
+#if 0
+#include <sys/sysmacros.h>
+#define MAJOR_OF(d) ((unsigned)major(d))
+#define MINOR_OF(d) ((unsigned)minor(d))
+#else
+#define MAJOR_OF(d) ( ((unsigned)(d)>>8u) & 0xfffu )
+#define MINOR_OF(d) ( ((unsigned)(d)&0xffu) | (((unsigned)(d)&0xfff00000u)>>12u) )
+#undef major
+#undef minor
+#define major <-- do not use -->
+#define minor <-- do not use -->
+#endif
+
+typedef struct tty_map_node {
+  struct tty_map_node *next;
+  unsigned short devfs_type;  // bool
+  unsigned short major_number;
+  unsigned minor_first;
+  unsigned minor_last;
+  char name[16];
+} tty_map_node;
+
+static tty_map_node *tty_map = NULL;
+
+/* Load /proc/tty/drivers for device name mapping use. */
+static void load_drivers(void){
+  char buf[10000];
+  char *p;
+  int fd;
+  int bytes;
+  fd = open("/proc/tty/drivers",O_RDONLY);
+  if(fd == -1) goto fail;
+  bytes = read(fd, buf, sizeof(buf) - 1);
+  if(bytes == -1) goto fail;
+  buf[bytes] = '\0';
+  p = buf;
+  while(( p = strstr(p, " /dev/") )){  // " /dev/" is the second column
+    tty_map_node *tmn;
+    int len;
+    char *end;
+    p += 6;
+    end = strchr(p, ' ');
+    if(!end) continue;
+    len = end - p;
+    tmn = calloc(1, sizeof(tty_map_node));
+    tmn->next = tty_map;
+    tty_map = tmn;
+    /* if we have a devfs type name such as /dev/tts/%d then strip the %d but
+       keep a flag. */
+    if(len >= 3 && !strncmp(end - 2, "%d", 2)){
+      len -= 2;
+      tmn->devfs_type = 1;
+    }
+    if(len >= sizeof tmn->name)
+      len = sizeof tmn->name - 1; // mangle it to avoid overflow
+    memcpy(tmn->name, p, len);
+    p = end; /* set p to point past the %d as well if there is one */
+    while(*p == ' ') p++;
+    tmn->major_number = atoi(p);
+    p += strspn(p, "0123456789");
+    while(*p == ' ') p++;
+    switch(sscanf(p, "%u-%u", &tmn->minor_first, &tmn->minor_last)){
+    default:
+      /* Can't finish parsing this line so we remove it from the list */
+      tty_map = tty_map->next;
+      free(tmn);
+      break;
+    case 1:
+      tmn->minor_last = tmn->minor_first;
+      break;
+    case 2:
+      break;
+    }
+  }
+fail:
+  if(fd != -1) close(fd);
+  if(!tty_map) tty_map = (tty_map_node *)-1;
+}
+
+/* Try to guess the device name from /proc/tty/drivers info. */
+static int driver_name(char *restrict const buf, unsigned maj, unsigned min){
+  struct stat sbuf;
+  tty_map_node *tmn;
+  if(!tty_map) load_drivers();
+  if(tty_map == (tty_map_node *)-1) return 0;
+  tmn = tty_map;
+  for(;;){
+    if(!tmn) return 0;
+    if(tmn->major_number == maj && tmn->minor_first <= min && tmn->minor_last >= min) break;
+    tmn = tmn->next;
+  }
+  sprintf(buf, "/dev/%s%d", tmn->name, min);  /* like "/dev/ttyZZ255" */
+  if(stat(buf, &sbuf) < 0){
+    if(tmn->devfs_type) return 0;
+    sprintf(buf, "/dev/%s", tmn->name);  /* like "/dev/ttyZZ255" */
+    if(stat(buf, &sbuf) < 0) return 0;
+  }
+  if(min != MINOR_OF(sbuf.st_rdev)) return 0;
+  if(maj != MAJOR_OF(sbuf.st_rdev)) return 0;
+  return 1;
+}
+
+// major 204 is a mess -- "Low-density serial ports"
+static const char low_density_names[][6] = {
+"LU0",  "LU1",  "LU2",  "LU3",
+"FB0",
+"SA0",  "SA1",  "SA2",
+"SC0",  "SC1",  "SC2",  "SC3",
+"FW0",  "FW1",  "FW2",  "FW3",
+"AM0",  "AM1",  "AM2",  "AM3",  "AM4",  "AM5",  "AM6",  "AM7",
+"AM8",  "AM9",  "AM10", "AM11", "AM12", "AM13", "AM14", "AM15",
+"DB0",  "DB1",  "DB2",  "DB3",  "DB4",  "DB5",  "DB6",  "DB7",
+"SG0",
+"SMX0",  "SMX1",  "SMX2",
+"MM0",  "MM1",
+"CPM0", "CPM1", "CPM2", "CPM3", /* "CPM4", "CPM5", */  // bad allocation?
+"IOC0",  "IOC1",  "IOC2",  "IOC3",  "IOC4",  "IOC5",  "IOC6",  "IOC7",
+"IOC8",  "IOC9",  "IOC10", "IOC11", "IOC12", "IOC13", "IOC14", "IOC15",
+"IOC16", "IOC17", "IOC18", "IOC19", "IOC20", "IOC21", "IOC22", "IOC23",
+"IOC24", "IOC25", "IOC26", "IOC27", "IOC28", "IOC29", "IOC30", "IOC31",
+"VR0", "VR1",
+"IOC84",  "IOC85",  "IOC86",  "IOC87",  "IOC88",  "IOC89",  "IOC90",  "IOC91",
+"IOC92",  "IOC93",  "IOC94", "IOC95", "IOC96", "IOC97", "IOC98", "IOC99",
+"IOC100", "IOC101", "IOC102", "IOC103", "IOC104", "IOC105", "IOC106", "IOC107",
+"IOC108", "IOC109", "IOC110", "IOC111", "IOC112", "IOC113", "IOC114", "IOC115",
+"SIOC0",  "SIOC1",  "SIOC2",  "SIOC3",  "SIOC4",  "SIOC5",  "SIOC6",  "SIOC7",
+"SIOC8",  "SIOC9",  "SIOC10", "SIOC11", "SIOC12", "SIOC13", "SIOC14", "SIOC15",
+"SIOC16", "SIOC17", "SIOC18", "SIOC19", "SIOC20", "SIOC21", "SIOC22", "SIOC23",
+"SIOC24", "SIOC25", "SIOC26", "SIOC27", "SIOC28", "SIOC29", "SIOC30", "SIOC31",
+"PSC0", "PSC1", "PSC2", "PSC3", "PSC4", "PSC5",
+"AT0",  "AT1",  "AT2",  "AT3",  "AT4",  "AT5",  "AT6",  "AT7",
+"AT8",  "AT9",  "AT10", "AT11", "AT12", "AT13", "AT14", "AT15",
+"NX0",  "NX1",  "NX2",  "NX3",  "NX4",  "NX5",  "NX6",  "NX7",
+"NX8",  "NX9",  "NX10", "NX11", "NX12", "NX13", "NX14", "NX15",
+"J0",   // minor is 186
+"UL0","UL1","UL2","UL3",
+"xvc0", // FAIL -- "/dev/xvc0" lacks "tty" prefix
+"PZ0","PZ1","PZ2","PZ3",
+"TX0","TX1","TX2","TX3","TX4","TX5","TX6","TX7",
+"SC0","SC1","SC2","SC3",
+"MAX0","MAX1","MAX2","MAX3",
+};
+
+#if 0
+// test code
+#include <stdio.h>
+#define AS(x) (sizeof(x)/sizeof((x)[0]))
+int main(int argc, char *argv[]){
+  int i = 0;
+  while(i<AS(low_density_names)){
+    printf("%3d = /dev/tty%.*s\n",i,sizeof low_density_names[i],low_density_names[i]);
+    i++;
+  }
+  return 0;
+}
+#endif
+
+/* Try to guess the device name (useful until /proc/PID/tty is added) */
+static int guess_name(char *restrict const buf, unsigned maj, unsigned min){
+  struct stat sbuf;
+  int t0, t1;
+  unsigned tmpmin = min;
+
+  switch(maj){
+  case   3:      /* /dev/[pt]ty[p-za-o][0-9a-z] is 936 */
+    if(tmpmin > 255) return 0;   // should never happen; array index protection
+    t0 = "pqrstuvwxyzabcde"[tmpmin>>4];
+    t1 = "0123456789abcdef"[tmpmin&0x0f];
+    sprintf(buf, "/dev/tty%c%c", t0, t1);
+    break;
+  case   4:
+    if(min<64){
+      sprintf(buf, "/dev/tty%d", min);
+      break;
+    }
+    sprintf(buf, "/dev/ttyS%d", min-64);
+    break;
+  case  11:  sprintf(buf, "/dev/ttyB%d",  min); break;
+  case  17:  sprintf(buf, "/dev/ttyH%d",  min); break;
+  case  19:  sprintf(buf, "/dev/ttyC%d",  min); break;
+  case  22:  sprintf(buf, "/dev/ttyD%d",  min); break; /* devices.txt */
+  case  23:  sprintf(buf, "/dev/ttyD%d",  min); break; /* driver code */
+  case  24:  sprintf(buf, "/dev/ttyE%d",  min); break;
+  case  32:  sprintf(buf, "/dev/ttyX%d",  min); break;
+  case  43:  sprintf(buf, "/dev/ttyI%d",  min); break;
+  case  46:  sprintf(buf, "/dev/ttyR%d",  min); break;
+  case  48:  sprintf(buf, "/dev/ttyL%d",  min); break;
+  case  57:  sprintf(buf, "/dev/ttyP%d",  min); break;
+  case  71:  sprintf(buf, "/dev/ttyF%d",  min); break;
+  case  75:  sprintf(buf, "/dev/ttyW%d",  min); break;
+  case  78:  sprintf(buf, "/dev/ttyM%d",  min); break; /* conflict */
+  case 105:  sprintf(buf, "/dev/ttyV%d",  min); break;
+  case 112:  sprintf(buf, "/dev/ttyM%d",  min); break; /* conflict */
+  /* 136 ... 143 are /dev/pts/0, /dev/pts/1, /dev/pts/2 ... */
+  case 136 ... 143:  sprintf(buf, "/dev/pts/%d",  min+(maj-136)*256); break;
+  case 148:  sprintf(buf, "/dev/ttyT%d",  min); break;
+  case 154:  sprintf(buf, "/dev/ttySR%d", min); break;
+  case 156:  sprintf(buf, "/dev/ttySR%d", min+256); break;
+  case 164:  sprintf(buf, "/dev/ttyCH%d",  min); break;
+  case 166:  sprintf(buf, "/dev/ttyACM%d", min); break; /* bummer, 9-char */
+  case 172:  sprintf(buf, "/dev/ttyMX%d",  min); break;
+  case 174:  sprintf(buf, "/dev/ttySI%d",  min); break;
+  case 188:  sprintf(buf, "/dev/ttyUSB%d", min); break; /* bummer, 9-char */
+  case 204:
+    if(min >= sizeof low_density_names / sizeof low_density_names[0]) return 0;
+    memcpy(buf,"/dev/tty",8);
+    memcpy(buf+8, low_density_names[min], sizeof low_density_names[0]);
+    buf[8 + sizeof low_density_names[0]] = '\0';
+//    snprintf(buf, 9 + sizeof low_density_names[0], "/dev/tty%.*s", sizeof low_density_names[0], low_density_names[min]);
+    break;
+  case 208:  sprintf(buf, "/dev/ttyU%d",  min); break;
+  case 216:  sprintf(buf, "/dev/ttyUB%d",  min); break; // "/dev/rfcomm%d" now?
+  case 224:  sprintf(buf, "/dev/ttyY%d",  min); break;
+  case 227:  sprintf(buf, "/dev/3270/tty%d", min); break; /* bummer, HUGE */
+  case 229:  sprintf(buf, "/dev/iseries/vtty%d",  min); break; /* bummer, HUGE */
+  case 256:  sprintf(buf, "/dev/ttyEQ%d",  min); break;
+  default: return 0;
+  }
+  if(stat(buf, &sbuf) < 0) return 0;
+  if(min != MINOR_OF(sbuf.st_rdev)) return 0;
+  if(maj != MAJOR_OF(sbuf.st_rdev)) return 0;
+  return 1;
+}
+
+/* Linux 2.2 can give us filenames that might be correct.
+ * Useful names could be in /proc/PID/fd/2 (stderr, seldom redirected)
+ * and in /proc/PID/fd/255 (used by bash to remember the tty).
+ */
+static int link_name(char *restrict const buf, unsigned maj, unsigned min, int pid, const char *restrict name){
+  struct stat sbuf;
+  char path[32];
+  int count;
+  sprintf(path, "/proc/%d/%s", pid, name);  /* often permission denied */
+  count = readlink(path,buf,TTY_NAME_SIZE-1);
+  if(count == -1) return 0;
+  buf[count] = '\0';
+  if(stat(buf, &sbuf) < 0) return 0;
+  if(min != MINOR_OF(sbuf.st_rdev)) return 0;
+  if(maj != MAJOR_OF(sbuf.st_rdev)) return 0;
+  return 1;
+}
+
+/* number --> name */
+unsigned dev_to_tty(char *restrict ret, unsigned chop, dev_t dev_t_dev, int pid, unsigned int flags) {
+  static char buf[TTY_NAME_SIZE];
+  char *restrict tmp = buf;
+  unsigned dev = dev_t_dev;
+  unsigned i = 0;
+  int c;
+  if(dev == 0u) goto no_tty;
+  if(linux_version_code > LINUX_VERSION(2, 7, 0)){  // not likely to make 2.6.xx
+    if(link_name(tmp, MAJOR_OF(dev), MINOR_OF(dev), pid, "tty"   )) goto abbrev;
+  }
+  if(driver_name(tmp, MAJOR_OF(dev), MINOR_OF(dev)               )) goto abbrev;
+  if(  link_name(tmp, MAJOR_OF(dev), MINOR_OF(dev), pid, "fd/2"  )) goto abbrev;
+  if( guess_name(tmp, MAJOR_OF(dev), MINOR_OF(dev)               )) goto abbrev;
+  if(  link_name(tmp, MAJOR_OF(dev), MINOR_OF(dev), pid, "fd/255")) goto abbrev;
+  // fall through if unable to find a device file
+no_tty:
+  strcpy(ret, "?");
+  return 1;
+abbrev:
+  if((flags&ABBREV_DEV) && !strncmp(tmp,"/dev/",5) && tmp[5]) tmp += 5;
+  if((flags&ABBREV_TTY) && !strncmp(tmp,"tty",  3) && tmp[3]) tmp += 3;
+  if((flags&ABBREV_PTS) && !strncmp(tmp,"pts/", 4) && tmp[4]) tmp += 4;
+  /* gotta check before we chop or we may chop someone else's memory */
+  if(chop + (unsigned long)(tmp-buf) <= sizeof buf)
+    tmp[chop] = '\0';
+  /* replace non-ASCII characters with '?' and return the number of chars */
+  for(;;){
+    c = *tmp;
+    tmp++;
+    if(!c) break;
+    i++;
+    if(c<=' ') c = '?';
+    if(c>126)  c = '?';
+    *ret = c;
+    ret++;
+  }
+  *ret = '\0';
+  return i;
+}
+
+/* name --> number */
+int tty_to_dev(const char *restrict const name) {
+  struct stat sbuf;
+  static char buf[32];
+  if(name[0]=='/' && stat(name, &sbuf) >= 0) return sbuf.st_rdev;
+  snprintf(buf,32,"/dev/%s",name);
+  if(stat(buf, &sbuf) >= 0) return sbuf.st_rdev;
+  snprintf(buf,32,"/dev/tty%s",name);
+  if(stat(buf, &sbuf) >= 0) return sbuf.st_rdev;
+  snprintf(buf,32,"/dev/pts/%s",name);
+  if(stat(buf, &sbuf) >= 0) return sbuf.st_rdev;
+  return -1;
+}
diff --git a/procps-3.2.8/proc/devname.h b/procps-3.2.8/proc/devname.h
new file mode 100644
index 0000000..10c2cb6
--- /dev/null
+++ b/procps-3.2.8/proc/devname.h
@@ -0,0 +1,17 @@
+#ifndef PROC_DEVNAME_H
+#define PROC_DEVNAME_H
+
+#include "procps.h"
+
+EXTERN_C_BEGIN
+
+#define ABBREV_DEV  1     /* remove /dev/         */
+#define ABBREV_TTY  2     /* remove tty           */
+#define ABBREV_PTS  4     /* remove pts/          */
+
+extern unsigned dev_to_tty(char *restrict ret, unsigned chop, dev_t dev_t_dev, int pid, unsigned int flags);
+
+extern int tty_to_dev(const char *restrict const name);
+
+EXTERN_C_END
+#endif
diff --git a/procps-3.2.8/proc/escape.c b/procps-3.2.8/proc/escape.c
new file mode 100644
index 0000000..0eb1418
--- /dev/null
+++ b/procps-3.2.8/proc/escape.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright 1998-2002 by Albert Cahalan; all rights resered.         
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version  
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */                                 
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include "procps.h"
+#include "escape.h"
+#include "readproc.h"
+
+#if (__GNU_LIBRARY__ >= 6)
+# include <wchar.h>
+# include <wctype.h>
+# include <stdlib.h>  /* MB_CUR_MAX */
+# include <ctype.h>
+# include <langinfo.h>
+#endif
+
+#if (__GNU_LIBRARY__ >= 6)
+static int escape_str_utf8(char *restrict dst, const char *restrict src, int bufsize, int *maxcells){
+  int my_cells = 0;
+  int my_bytes = 0;
+  mbstate_t s;
+  
+  memset(&s, 0, sizeof (s));
+  
+  for(;;) {
+    wchar_t wc;
+    int len = 0;
+	  
+    if(my_cells >= *maxcells || my_bytes+1 >= bufsize) 
+      break;
+    
+    if (!(len = mbrtowc (&wc, src, MB_CUR_MAX, &s)))
+      /* 'str' contains \0 */
+      break;
+    
+    if (len < 0) {
+      /* invalid multibyte sequence -- zeroize state */
+      memset (&s, 0, sizeof (s));
+      *(dst++) = '?';
+      src++;
+      my_cells++; 
+      my_bytes++;
+
+    } else if (len==1) {
+      /* non-multibyte */
+      *(dst++) = isprint(*src) ? *src : '?';
+      src++;
+      my_cells++;
+      my_bytes++;
+      
+    } else if (!iswprint(wc)) {
+      /* multibyte - no printable */
+      *(dst++) = '?';
+      src+=len;
+      my_cells++;
+      my_bytes++; 
+    
+    } else {
+      /* multibyte - printable */	
+      int wlen = wcwidth(wc);
+
+      if (wlen==0) {
+	// invisible multibyte -- we don't ignore it, because some terminal 
+	// interpret it wrong and more safe is replace it with '?'
+	*(dst++) = '?';
+	src+=len;
+	my_cells++;
+	my_bytes++;
+      } else {
+        // multibyte - printable
+        // Got space?
+        if (my_cells+wlen > *maxcells || my_bytes+1+len >= bufsize) break;
+        // 0x9b is control byte for some terminals
+        if (memchr(src, 0x9B, len)) {
+	  // unsafe multibyte
+	  *(dst++) = '?';
+	  src+=len;
+	  my_cells++;
+	  my_bytes++;
+        } else {
+	  // safe multibyte
+       	  memcpy(dst, src, len);
+	  my_cells += wlen;
+	  dst += len;
+	  my_bytes += len;
+          src += len;
+        }
+      }
+    }
+    //fprintf(stdout, "cells: %d\n", my_cells);
+  }
+  *(dst++) = '\0';
+
+  // fprintf(stderr, "maxcells: %d, my_cells; %d\n", *maxcells, my_cells);
+  
+  *maxcells -= my_cells;
+  return my_bytes;        // bytes of text, excluding the NUL
+}
+
+#endif /* __GNU_LIBRARY__  */
+
+/* sanitize a string via one-way mangle */
+int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *maxcells){
+  unsigned char c;
+  int my_cells = 0;
+  int my_bytes = 0;
+  const char codes[] =
+  "Z-------------------------------"
+  "********************************"
+  "********************************"
+  "*******************************-"
+  "--------------------------------"
+  "********************************"
+  "********************************"
+  "********************************";
+  
+#if (__GNU_LIBRARY__ >= 6)
+  static int utf_init=0;
+  
+  if(utf_init==0){
+     /* first call -- check if UTF stuff is usable */
+     char *enc = nl_langinfo(CODESET);
+     utf_init = enc && strcasecmp(enc, "UTF-8")==0 ? 1 : -1;
+  }
+  if (utf_init==1)
+     /* UTF8 locales */
+     return escape_str_utf8(dst, src, bufsize, maxcells);
+#endif
+		  
+  if(bufsize > *maxcells+1) bufsize=*maxcells+1; // FIXME: assumes 8-bit locale
+
+  for(;;){
+    if(my_cells >= *maxcells || my_bytes+1 >= bufsize) 
+      break;
+    c = (unsigned char) *(src++);
+    if(!c) break;
+    if(codes[c]=='-') c='?';
+    my_cells++;
+    my_bytes++;
+    *(dst++) = c;
+  }
+  *(dst++) = '\0';
+  
+  *maxcells -= my_cells;
+  return my_bytes;        // bytes of text, excluding the NUL
+}
+
+/////////////////////////////////////////////////
+
+// escape an argv or environment string array
+//
+// bytes arg means sizeof(buf)
+int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t bytes, int *cells){
+  size_t i = 0;
+
+  for(;;){
+    i += escape_str(dst+i, *src, bytes-i, cells);
+    if(bytes-i < 3) break;  // need room for space, a character, and the NUL
+    src++;
+    if(!*src) break;  // need something to print
+    if (*cells<=1) break;  // need room for printed size of text
+    dst[i++] = ' ';
+    --*cells;
+  }
+  return i;    // bytes, excluding the NUL
+}
+
+///////////////////////////////////////////////////
+
+int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags){
+  int overhead = 0;
+  int end = 0;
+
+  if(flags & ESC_ARGS){
+    const char **lc = (const char**)pp->cmdline;
+    if(lc && *lc) return escape_strlist(outbuf, lc, bytes, cells);
+  }
+  if(flags & ESC_BRACKETS){
+    overhead += 2;
+  }
+  if(flags & ESC_DEFUNCT){
+    if(pp->state=='Z') overhead += 10;    // chars in " <defunct>"
+    else flags &= ~ESC_DEFUNCT;
+  }
+  if(overhead + 1 >= *cells){  // if no room for even one byte of the command name
+    // you'd damn well better have _some_ space
+//    outbuf[0] = '-';  // Oct23
+    outbuf[1] = '\0';
+    return 1;
+  }
+  if(flags & ESC_BRACKETS){
+    outbuf[end++] = '[';
+  }
+  *cells -= overhead;
+  end += escape_str(outbuf+end, pp->cmd, bytes-overhead, cells);
+
+  // Hmmm, do we want "[foo] <defunct>" or "[foo <defunct>]"?
+  if(flags & ESC_BRACKETS){
+    outbuf[end++] = ']';
+  }
+  if(flags & ESC_DEFUNCT){
+    memcpy(outbuf+end, " <defunct>", 10);
+    end += 10;
+  }
+  outbuf[end] = '\0';
+  return end;  // bytes, not including the NUL
+}
diff --git a/procps-3.2.8/proc/escape.h b/procps-3.2.8/proc/escape.h
new file mode 100644
index 0000000..172960f
--- /dev/null
+++ b/procps-3.2.8/proc/escape.h
@@ -0,0 +1,22 @@
+#ifndef PROCPS_PROC_ESCAPE_H
+#define PROCPS_PROC_ESCAPE_H
+
+//#include <stdio.h>
+#include <sys/types.h>
+#include "procps.h"
+#include "readproc.h"
+
+EXTERN_C_BEGIN
+
+#define ESC_STRETCH 1  // since we mangle to '?' this is 1 (would be 4 for octal escapes)
+
+#define ESC_ARGS     0x1  // try to use cmdline instead of cmd
+#define ESC_BRACKETS 0x2  // if using cmd, put '[' and ']' around it
+#define ESC_DEFUNCT  0x4  // mark zombies with " <defunct>"
+
+extern int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t n, int *cells);
+extern int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *maxcells);
+extern int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags);
+
+EXTERN_C_END
+#endif
diff --git a/procps-3.2.8/proc/ksym.c b/procps-3.2.8/proc/ksym.c
new file mode 100644
index 0000000..2e5379f
--- /dev/null
+++ b/procps-3.2.8/proc/ksym.c
@@ -0,0 +1,631 @@
+/*
+ * Copyright 1998-2003 by Albert Cahalan; all rights reserved.
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/utsname.h>
+#include "procps.h"
+#include "version.h"
+#include "sysinfo.h" /* smp_num_cpus */
+#include "wchan.h"  // to verify prototypes
+
+#define KSYMS_FILENAME "/proc/ksyms"
+
+#if 0
+#undef KSYMS_FILENAME
+#define KSYMS_FILENAME  "/would/be/nice/to/have/this/file"
+#define SYSMAP_FILENAME "/home/albert/ps/45621/System.map-hacked"
+#define linux_version_code 131598 /* ? */
+#define smp_num_cpus 2
+#endif
+
+#if 0
+#undef KSYMS_FILENAME
+#define KSYMS_FILENAME  "/home/albert/ps/45621/ksyms-2.3.12"
+#define SYSMAP_FILENAME "/home/albert/ps/45621/System.map-2.3.12"
+#define linux_version_code 131852 /* 2.3.12 */
+#define smp_num_cpus 2
+#endif
+
+#if 0
+#undef KSYMS_FILENAME
+#define KSYMS_FILENAME  "/home/albert/ps/45621/ksyms-2.3.18ac8-MODVERS"
+#define SYSMAP_FILENAME "/home/albert/ps/45621/System.map-2.3.18ac8-MODVERS"
+#define linux_version_code 131858 /* 2.3.18ac8 */
+#define smp_num_cpus 2
+#endif
+
+#if 0
+#undef KSYMS_FILENAME
+#define KSYMS_FILENAME  "/home/albert/ps/45621/ksyms-2.3.18ac8-NOMODVERS"
+#define SYSMAP_FILENAME "/home/albert/ps/45621/System.map-2.3.18ac8-NOMODVERS"
+#define linux_version_code 131858 /* 2.3.18ac8 */
+#define smp_num_cpus 2
+#endif
+
+/* These are the symbol types, with relative popularity:
+ *     ? w  machine type junk for Alpha -- odd syntax
+ *     ? S  not for i386
+ *     4 W  not for i386
+ *    60 R
+ *   100 A
+ *   125 r
+ *   363 s  not for i386
+ *   858 B
+ *   905 g  generated by modutils?
+ *   929 G  generated by modutils?
+ *  1301 b
+ *  2750 D
+ *  4481 d
+ * 11417 ?
+ * 13666 t
+ * 15442 T
+ *
+ * For i386, that is: "RArBbDd?tT"
+ */
+
+#define SYMBOL_TYPE_CHARS "Tt?dDbBrARGgsWS"
+
+/*
+ * '?' is a symbol type
+ * '.' is part of a name (versioning?)
+ * "\t[]" are for the module name in /proc/ksyms
+ */
+#define LEGAL_SYSMAP_CHARS "0123456789_ ?.\n\t[]" \
+                     "abcdefghijklmnopqrstuvwxyz" \
+                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+/* System.map lines look like:
+ * hex num, space, one of SYMBOL_TYPE_CHARS, space, LEGAL_SYSMAP_CHARS, \n
+ *
+ * Alpha systems can start with a few lines that have the address replaced
+ * by space padding and a 'w' for the type. For those lines, the last space
+ * is followed by something like: mikasa_primo_mv p2k_mv sable_gamma_mv
+ * (just one of those, always with a "_mv", then the newline)
+ *
+ * The /proc/ksyms lines are like System.map lines w/o the symbol type char.
+ * When odd features are used, the name part contains:
+ * "(.*)_R(smp_|smp2gig_|2gig_)?[0-9a-fA-F]{8,}"
+ * It is likely that more crap will be added...
+ */
+
+typedef struct symb {
+  unsigned KLONG addr;
+  const char *name;
+} symb;
+
+/* These mostly rely on POSIX to make them zero. */
+
+static symb hashtable[256];
+
+static char       *sysmap_data;
+static unsigned    sysmap_room;
+static symb       *sysmap_index;
+static unsigned    sysmap_count;
+
+static char       *ksyms_data;
+static unsigned    ksyms_room     = 4096;
+static symb       *ksyms_index;
+static unsigned    ksyms_count;
+static unsigned    idx_room;
+
+/*********************************/
+
+/* Kill this:  _R(smp_?|smp2gig_?|2gig_?)?[0-9a-f]{8,}$
+ * We kill:    (_R[^A-Z]*[0-9a-f]{8,})+$
+ *
+ * The loop should almost never be taken, but it has to be there.
+ * It gets rid of anything that _looks_ like a version code, even
+ * if a real version code has already been found. This is because
+ * the inability to perfectly recognize a version code may lead to
+ * symbol mangling, which in turn leads to mismatches between the
+ * /proc/ksyms and System.map data files.
+ */
+#if 0
+static char *chop_version(char *arg){
+  char *cp;
+  cp = strchr(arg,'\t');
+  if(cp) *cp = '\0';  /* kill trailing module name first */
+  for(;;){
+    char *p;
+    int len = 0;
+    cp = strrchr(arg, 'R');
+    if(!cp || cp<=arg+1 || cp[-1]!='_') break;
+    for(p=cp; *++p; ){
+      switch(*p){
+      default:
+        goto out;
+      case '0' ... '9':
+      case 'a' ... 'f':
+        len++;
+        continue;
+      case 'g' ... 'z':
+      case '_':
+        len=0;
+        continue;
+      }
+    }
+    if(len<8) break;
+    cp[-1] = '\0';
+  }
+out:
+  if(*arg=='G'){
+    int len = strlen(arg);
+    while( len>8 && !memcmp(arg,"GPLONLY_",8) ){
+      arg += 8;
+      len -= 8;
+    }
+  }
+  return arg;
+}
+#endif
+static char *chop_version(char *arg){
+  char *cp;
+  cp = strchr(arg,'\t');
+  if(cp) *cp = '\0';  /* kill trailing module name first */
+  for(;;){
+    int len;
+    cp = strrchr(arg, 'R');
+    if(!cp || cp<=arg+1 || cp[-1]!='_') break;
+    len=strlen(cp);
+    if(len<9) break;
+    if(strpbrk(cp+1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ")) break;
+    if(strspn(cp+len-8,"0123456789abcdef")!=8) break;
+    cp[-1] = '\0';
+  }
+  if(*arg=='G'){
+    int len = strlen(arg);
+    while( len>8 && !memcmp(arg,"GPLONLY_",8) ){
+      arg += 8;
+      len -= 8;
+    }
+  }
+  return arg;
+}
+
+/***********************************/
+
+static const symb *search(unsigned KLONG address, symb *idx, unsigned count){
+  unsigned left;
+  unsigned mid;
+  unsigned right;
+  if(!idx) return NULL;   /* maybe not allocated */
+  if(address < idx[0].addr) return NULL;
+  if(address >= idx[count-1].addr) return idx+count-1;
+  left  = 0;
+  right = count-1;
+  for(;;){
+    mid = (left + right) / 2;
+    if(address >= idx[mid].addr) left  = mid;
+    if(address <= idx[mid].addr) right = mid;
+    if(right-left <= 1) break;
+  }
+  if(address == idx[right].addr) return idx+right;
+  return idx+left;
+}
+
+/*********************************/
+
+/* allocate if needed, read, and return buffer size */
+static void read_file(const char *restrict filename, char **bufp, unsigned *restrict roomp) {
+  int fd = 0;
+  ssize_t done;
+  char *buf = *bufp;
+  ssize_t total = 0;
+  unsigned room = *roomp;
+
+  if(!room) goto hell;     /* failed before */
+  if(!buf) buf = malloc(room);
+  if(!buf) goto hell;
+open_again:
+  fd = open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK);
+  if(fd<0){
+    switch(errno){
+    case EINTR:  goto open_again;
+    default:     _exit(101);
+    case EACCES:   /* somebody screwing around? */
+      /* FIXME: set a flag to disable symbol lookup? */
+    case ENOENT:;  /* no module support */
+    }
+    goto hell;
+  }
+  for(;;){
+    done = read(fd, buf+total, room-total-1);
+    if(done==0) break;  /* nothing left */
+    if(done==-1){
+      if(errno==EINTR) continue;  /* try again */
+      perror("");
+      goto hell;
+    }
+    if(done==(ssize_t)room-total-1){
+      char *tmp;
+      total += done;
+      /* more to go, but no room in buffer */
+      room *= 2;
+      tmp = realloc(buf, room);
+      if(!tmp) goto hell;
+      buf = tmp;
+      continue;
+    }
+    if(done>0 && done<(ssize_t)room-total-1){
+      total += done; 
+      continue;   /* OK, we read some. Go do more. */
+    }
+    fprintf(stderr,"%ld can't happen\n", (long)done);
+    /* FIXME: memory leak */
+    _exit(42);
+  }
+  buf[total] = '\0';   // parse_ksyms() expects NUL-terminated file
+  *bufp = buf;
+  *roomp = room;
+  close(fd);
+  return;
+hell:
+  if(buf) free(buf);
+  *bufp = NULL;
+  *roomp = 0;   /* this function will never work again */
+  total = 0;
+  if(fd>0) close(fd);
+  return;
+}
+
+/*********************************/
+
+static int parse_ksyms(void) {
+  char *endp;
+  if(!ksyms_room || !ksyms_data) goto quiet_goodbye;
+  endp = ksyms_data;
+  ksyms_count = 0;
+  if(idx_room) goto bypass;  /* some space already allocated */
+  idx_room = 512;
+  for(;;){
+    void *vp;
+    idx_room *= 2;
+    vp = realloc(ksyms_index, sizeof(symb)*idx_room);
+    if(!vp) goto bad_alloc;
+    ksyms_index = vp;
+bypass:
+    for(;;){
+      char *saved;
+      if(!*endp) return 1;
+      saved = endp;
+      ksyms_index[ksyms_count].addr = STRTOUKL(endp, &endp, 16);
+      if(endp==saved || *endp != ' ') goto bad_parse;
+      endp++;
+      saved = endp;
+      endp = strchr(endp,'\n');
+      if(!endp) goto bad_parse;   /* no newline */
+      *endp = '\0';
+      ksyms_index[ksyms_count].name = chop_version(saved);
+      ++endp;
+      if(++ksyms_count >= idx_room) break;  /* need more space */
+    }
+  }
+
+  if(0){
+bad_alloc:
+    fprintf(stderr, "Warning: not enough memory available\n");
+  }
+  if(0){
+bad_parse:
+    fprintf(stderr, "Warning: "KSYMS_FILENAME" not normal\n");
+  }
+quiet_goodbye:
+  idx_room = 0;
+  if(ksyms_data) free(ksyms_data) , ksyms_data = NULL;
+  ksyms_room = 0;
+  if(ksyms_index) free(ksyms_index) , ksyms_index = NULL;
+  ksyms_count = 0;
+  return 0;
+}
+
+/*********************************/
+
+#define VCNT 16
+
+static int sysmap_mmap(const char *restrict const filename, message_fn message) {
+  struct stat sbuf;
+  char *endp;
+  int fd;
+  char Version[32];
+  fd = open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK);
+  if(fd<0) return 0;
+  if(fstat(fd, &sbuf) < 0) goto bad_open;
+  if(!S_ISREG(sbuf.st_mode)) goto bad_open;
+  if(sbuf.st_size < 5000) goto bad_open;  /* if way too small */
+  /* Would be shared read-only, but we want '\0' after each name. */
+  endp = mmap(0, sbuf.st_size + 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+  sysmap_data = endp;
+  while(*endp==' '){  /* damn Alpha machine types */
+    if(strncmp(endp,"                 w ", 19)) goto bad_parse;
+    endp += 19;
+    endp = strchr(endp,'\n');
+    if(!endp) goto bad_parse;   /* no newline */
+    if(strncmp(endp-3, "_mv\n", 4)) goto bad_parse;
+    endp++;
+  }
+  if(sysmap_data == (caddr_t) -1) goto bad_open;
+  close(fd);
+  fd = -1;
+  sprintf(Version, "Version_%d", linux_version_code);
+  sysmap_room = 512;
+  for(;;){
+    void *vp;
+    sysmap_room *= 2;
+    vp = realloc(sysmap_index, sizeof(symb)*sysmap_room);
+    if(!vp) goto bad_alloc;
+    sysmap_index = vp;
+    for(;;){
+      char *vstart;
+      if(endp - sysmap_data >= sbuf.st_size){   /* if we reached the end */
+        int i = VCNT;            /* check VCNT times to verify this file */
+        if(*Version) goto bad_version;
+        if(!ksyms_index) return 1; /* if can not verify, assume success */
+        while(i--){
+#if 1
+          const symb *findme;
+          const symb *map_symb;
+          /* Choose VCNT entries from /proc/ksyms to test */
+          findme = ksyms_index + (ksyms_count*i/VCNT);
+          /* Search for them in the System.map */
+          map_symb = search(findme->addr, sysmap_index, sysmap_count);
+          if(map_symb){
+            if(map_symb->addr != findme->addr) continue;
+            /* backup to first matching address */
+            while (map_symb != sysmap_index){
+              if (map_symb->addr != (map_symb-1)->addr) break;
+              map_symb--;
+            }
+            /* search for name in symbols with same address */
+            while (map_symb != (sysmap_index+sysmap_count)){
+              if (map_symb->addr != findme->addr) break;
+              if (!strcmp(map_symb->name,findme->name)) goto good_match;
+              map_symb++;
+            }
+            map_symb--; /* backup to last symbol with matching address */
+            message("{%s} {%s}\n",map_symb->name,findme->name);
+            goto bad_match;
+          }
+good_match:;
+#endif
+        }
+        return 1; /* success */
+      }
+      sysmap_index[sysmap_count].addr = STRTOUKL(endp, &endp, 16);
+      if(*endp != ' ') goto bad_parse;
+      endp++;
+      if(!strchr(SYMBOL_TYPE_CHARS, *endp)) goto bad_parse;
+      endp++;
+      if(*endp != ' ') goto bad_parse;
+      endp++;
+      vstart = endp;
+      endp = strchr(endp,'\n');
+      if(!endp) goto bad_parse;   /* no newline */
+      *endp = '\0';
+      ++endp;
+      vstart = chop_version(vstart);
+      sysmap_index[sysmap_count].name = vstart;
+      if(*vstart=='V' && *Version && !strcmp(Version,vstart)) *Version='\0';
+      if(++sysmap_count >= sysmap_room) break;  /* need more space */
+    }
+  }
+
+  if(0){
+bad_match:
+    message("Warning: %s does not match kernel data.\n", filename);
+  }
+  if(0){
+bad_version:
+    message("Warning: %s has an incorrect kernel version.\n", filename);
+  }
+  if(0){
+bad_alloc:
+    message("Warning: not enough memory available\n");
+  }
+  if(0){
+bad_parse:
+    message("Warning: %s not parseable as a System.map\n", filename);
+  }
+  if(0){
+bad_open:
+    message("Warning: %s could not be opened as a System.map\n", filename);
+  }
+
+  sysmap_room=0;
+  sysmap_count=0;
+  if(sysmap_index) free(sysmap_index);
+  sysmap_index = NULL;
+  if(fd>=0) close(fd);
+  if(sysmap_data) munmap(sysmap_data, sbuf.st_size + 1);
+  sysmap_data = NULL;
+  return 0;
+}
+
+/*********************************/
+
+static void read_and_parse(void){
+  static time_t stamp;    /* after data gets old, load /proc/ksyms again */
+  if(time(NULL) != stamp){
+    read_file(KSYMS_FILENAME, &ksyms_data, &ksyms_room);
+    parse_ksyms();
+    memset((void*)hashtable,0,sizeof(hashtable)); /* invalidate cache */
+    stamp = time(NULL);
+  }
+}
+
+/*********************************/
+
+static void default_message(const char *restrict format, ...) __attribute__((format(printf,1,2)));
+static void default_message(const char *restrict format, ...) {
+    va_list arg;
+
+    va_start (arg, format);
+    vfprintf (stderr, format, arg);
+    va_end (arg);
+}
+
+/*********************************/
+
+static int use_wchan_file;
+
+int open_psdb_message(const char *restrict override, message_fn message) {
+  static const char *sysmap_paths[] = {
+    "/boot/System.map-%s",
+    "/boot/System.map",
+    "/lib/modules/%s/System.map",
+    "/usr/src/linux/System.map",
+    "/System.map",
+    NULL
+  };
+  struct stat sbuf;
+  struct utsname uts;
+  char path[128];
+  const char **fmt = sysmap_paths;
+  const char *sm;
+
+#ifdef SYSMAP_FILENAME    /* debug feature */
+  override = SYSMAP_FILENAME;
+#endif
+
+  // first allow for a user-selected System.map file
+  if(
+    (sm=override)
+    ||
+    (sm=getenv("PS_SYSMAP"))
+    ||
+    (sm=getenv("PS_SYSTEM_MAP"))
+  ){
+    if(!have_privs){
+      read_and_parse();
+      if(sysmap_mmap(sm, message)) return 0;
+    }
+    /* failure is better than ignoring the user & using bad data */
+    return -1;           /* ought to return "Namelist not found." */
+  }
+
+  // next try the Linux 2.5.xx method
+  if(!stat("/proc/self/wchan", &sbuf)){
+    use_wchan_file = 1; // hack
+    return 0;
+  }
+
+  // finally, search for the System.map file
+  uname(&uts);
+  path[sizeof path - 1] = '\0';
+  do{
+    int did_ksyms = 0;
+    snprintf(path, sizeof path - 1, *fmt, uts.release);
+    if(!stat(path, &sbuf)){
+      if (did_ksyms++) read_and_parse();
+      if (sysmap_mmap(path, message)) return 0;
+    }
+  }while(*++fmt);
+  /* TODO: Without System.map, no need to keep ksyms loaded. */
+  return -1;
+}
+
+/***************************************/
+
+int open_psdb(const char *restrict override) {
+    return open_psdb_message(override, default_message);
+}
+
+/***************************************/
+
+static const char * read_wchan_file(unsigned pid){
+  static char buf[64];
+  const char *ret = buf;
+  ssize_t num;
+  int fd;
+
+  snprintf(buf, sizeof buf, "/proc/%d/wchan", pid);
+  fd = open(buf, O_RDONLY);
+  if(fd==-1) return "?";
+  num = read(fd, buf, sizeof buf - 1);
+  close(fd);
+  if(num<1) return "?"; // allow for "0"
+  buf[num] = '\0';
+
+  if(buf[0]=='0' && buf[1]=='\0') return "-";
+
+  // would skip over numbers if they existed -- but no
+
+  // lame ppc64 has a '.' in front of every name
+  if(*ret=='.') ret++;
+  switch(*ret){
+    case 's': if(!strncmp(ret, "sys_", 4)) ret += 4;   break;
+    case 'd': if(!strncmp(ret, "do_",  3)) ret += 3;   break;
+    case '_': while(*ret=='_') ret++;                  break;
+  }
+  return ret;
+}
+
+/***************************************/
+
+static const symb fail = { .name = "?" };
+static const char dash[] = "-";
+static const char star[] = "*";
+
+#define MAX_OFFSET (0x1000*sizeof(long))  /* past this is generally junk */
+
+/* return pointer to temporary static buffer with function name */
+const char * lookup_wchan(unsigned KLONG address, unsigned pid) {
+  const symb *mod_symb;
+  const symb *map_symb;
+  const symb *good_symb;
+  const char *ret;
+  unsigned hash;
+
+  // can't cache it due to a race condition :-(
+  if(use_wchan_file) return read_wchan_file(pid);
+
+  if(!address)  return dash;
+  if(!~address) return star;
+
+  read_and_parse();
+  hash = (address >> 4) & 0xff;  /* got 56/63 hits & 7/63 misses */
+  if(hashtable[hash].addr == address) return hashtable[hash].name;
+  mod_symb = search(address, ksyms_index,  ksyms_count);
+  if(!mod_symb) mod_symb = &fail;
+  map_symb = search(address, sysmap_index, sysmap_count);
+  if(!map_symb) map_symb = &fail;
+
+  /* which result is closest? */
+  good_symb = (mod_symb->addr > map_symb->addr)
+            ? mod_symb
+            : map_symb
+  ;
+  if(address > good_symb->addr + MAX_OFFSET) good_symb = &fail;
+
+  /* good_symb->name has the data, but needs to be trimmed */
+  ret = good_symb->name;
+  // lame ppc64 has a '.' in front of every name
+  if(*ret=='.') ret++;
+  switch(*ret){
+    case 's': if(!strncmp(ret, "sys_", 4)) ret += 4;   break;
+    case 'd': if(!strncmp(ret, "do_",  3)) ret += 3;   break;
+    case '_': while(*ret=='_') ret++;                  break;
+  }
+  /* if(!*ret) ret = fail.name; */  /* not likely (name was "sys_", etc.) */
+
+  /* cache name after abbreviation */
+  hashtable[hash].addr = address;
+  hashtable[hash].name = ret;
+
+  return ret;
+}
diff --git a/procps-3.2.8/proc/library.map b/procps-3.2.8/proc/library.map
new file mode 100644
index 0000000..a38627b
--- /dev/null
+++ b/procps-3.2.8/proc/library.map
@@ -0,0 +1,24 @@
+# for --version-script
+# WTF is the syntax for this file?
+# Give me a BNF, man!
+_3_2_5 {
+global:
+  __cyg_profile_func_enter; __cyg_profile_func_exit; main;
+
+  readproc; readtask; readproctab; readproctab2; look_up_our_self; escape_command;
+  escape_str; escape_strlist;
+  openproc; closeproc;
+  tty_to_dev; dev_to_tty; open_psdb_message; open_psdb; lookup_wchan;
+  display_version; procps_version; linux_version_code;
+  Hertz; smp_num_cpus; have_privs;
+  sprint_uptime; uptime; user_from_uid; print_uptime; loadavg;
+  pretty_print_signals; print_given_signals; unix_print_signals; signal_name_to_number; signal_number_to_name;
+  meminfo; vminfo; getstat; getdiskstat; getpartitions_num; getslabinfo; get_pid_digits;
+  kb_active; kb_inactive; kb_main_buffers; kb_main_cached;
+  kb_main_free; kb_main_total; kb_main_used; kb_swap_free;
+  kb_swap_total; kb_swap_used; kb_main_shared;
+  kb_low_total; kb_low_free; kb_high_total; kb_high_free;
+  vm_pgpgin; vm_pgpgout; vm_pswpin; vm_pswpout;
+  free_slabinfo; put_slabinfo; get_slabinfo; get_proc_stats;
+local: *;
+};
diff --git a/procps-3.2.8/proc/module.mk b/procps-3.2.8/proc/module.mk
new file mode 100644
index 0000000..f5b5258
--- /dev/null
+++ b/procps-3.2.8/proc/module.mk
@@ -0,0 +1,130 @@
+# This file gets included into the main Makefile, in the top directory.
+
+# Ideally, we want something like this:
+#
+# /lib/libproc.so.w        ELF soname ('w' is a digit, starting from 1)
+# /lib/procps-x.y.z.so     file itself (x.y.z is the procps version)
+# /lib/libproc.so          for linking, UNSUPPORTED
+# /usr/lib/libproc.a       for linking, UNSUPPORTED
+# proc/libproc.so.w        as above, if testing with LD_LIBRARY_PATH
+# proc/whatever            if testing with LD_PRELOAD
+# proc/libproc.a           for static build
+#
+# Without a stable ABI, there's no point in having any of that.
+# Without a stable API, there's no point in having the *.a file.
+#
+# A new ELF soname is required for every big ABI change. To conserve
+# numbers for future use, the ELF soname can be set equal to the
+# file name until some future date when a stable ABI is declared.
+
+SHARED     := 1
+
+# for lib$(NAME).so and /usr/include/($NAME) and such
+NAME       :=  proc
+
+LIBVERSION := $(VERSION).$(SUBVERSION).$(MINORVERSION)
+ABIVERSION := 0
+
+SOFILE     := lib$(NAME)-$(LIBVERSION).so
+ifneq ($(ABIVERSION),0)
+SOLINK     := lib$(NAME).so
+SONAME     := lib$(NAME).so.$(ABIVERSION)
+else
+SONAME     := $(SOFILE)
+SOLINK     := $(SOFILE)
+endif
+
+ANAME      := lib$(NAME).a
+
+############
+
+FPIC       := -fpic
+
+ifeq ($(SHARED),1)
+ALL        += proc/$(SONAME)
+INSTALL    += ldconfig
+LIBFLAGS   := -DSHARED=1 $(FPIC)
+# This is in gcc 3.5, but exported functions must be marked.
+#LIBFLAGS += $(call check_gcc,-fvisibility=hidden,)
+LIBPROC    := proc/$(SONAME)
+else
+ALL        += proc/$(ANAME)
+#INSTALL    += $(usr/lib)$(ANAME)
+LIBFLAGS   := -DSHARED=0
+LIBPROC    := proc/$(ANAME)
+endif
+
+LIBSRC :=  $(wildcard proc/*.c)
+LIBHDR :=  $(wildcard proc/*.h)
+LIBOBJ :=  $(LIBSRC:.c=.o)
+
+# Separate rule for this directory, to use -fpic or -fPIC
+$(filter-out proc/version.o,$(LIBOBJ)): proc/%.o: proc/%.c
+	$(CC) -c $(ALL_CPPFLAGS) $(ALL_CFLAGS) $(LIBFLAGS) $< -o $@
+
+LIB_X := COPYING module.mk library.map
+TARFILES += $(LIBSRC) $(LIBHDR) $(addprefix proc/,$(LIB_X))
+
+
+# Clean away all output files, .depend, and symlinks.
+# Use wildcards in case the version has changed.
+CLEAN += proc/.depend proc/lib*.so* proc/lib*.a $(LIBOBJ)
+DIRS  += proc/
+
+proc/$(ANAME): $(LIBOBJ)
+	$(AR) rcs $@ $^
+
+#proc/$(SONAME): proc/library.map
+proc/$(SONAME): $(LIBOBJ)
+	$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -shared -Wl,-soname,$(SONAME) -Wl,--version-script=proc/library.map -o $@ $^ -lc
+
+
+# AUTOMATIC DEPENDENCY GENERATION -- GCC AND GNUMAKE DEPENDENT
+proc/.depend: $(LIBSRC) $(LIBHDR)
+	$(strip $(CC) $(ALL_CPPFLAGS) $(LIB_CFLAGS) -MM -MG $(LIBSRC) > $@)
+
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(MAKECMDGOALS),tar)
+ifneq ($(MAKECMDGOALS),extratar)
+ifneq ($(MAKECMDGOALS),beta)
+-include proc/.depend
+endif
+endif
+endif
+endif
+
+#################### install rules ###########################
+
+$(lib)$(SOFILE) : proc/$(SONAME)
+	$(install) --mode 775 $< $@
+
+ifneq ($(SOLINK),$(SOFILE))
+.PHONY: $(lib)$(SOLINK)
+$(lib)$(SOLINK) : $(lib)$(SOFILE)
+	cd $(lib) && $(ln_sf) $(SOFILE) $(SOLINK)
+endif
+
+ifneq ($(SONAME),$(SOFILE))
+.PHONY: $(lib)$(SONAME)
+$(lib)$(SONAME) : $(lib)$(SOFILE)
+	cd $(lib) && $(ln_sf) $(SOFILE) $(SONAME)
+endif
+
+.PHONY: ldconfig
+ldconfig : $(lib)$(SONAME) $(lib)$(SOLINK)
+	$(ldconfig)
+
+$(usr/lib)$(ANAME) : proc/$(ANAME)
+	$(install) --mode a=r $< $@
+
+# Junk anyway... supposed to go in /usr/include/$(NAME)
+#INSTALL += $(addprefix $(include),$(HDRFILES))
+#
+#$(addprefix $(include),$(HDRFILES)): $(include)% : proc/%
+#$(include)% : proc/%
+#	$(install) --mode a=r $< $@
+
+##################################################################
+
+proc/version.o:	proc/version.c proc/version.h
+	$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) $(LIBFLAGS) -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" -c -o $@ $<
diff --git a/procps-3.2.8/proc/procps.h b/procps-3.2.8/proc/procps.h
new file mode 100644
index 0000000..a70e925
--- /dev/null
+++ b/procps-3.2.8/proc/procps.h
@@ -0,0 +1,112 @@
+#ifndef PROCPS_PROC_PROCPS_H
+#define PROCPS_PROC_PROCPS_H
+
+#ifdef  __cplusplus
+#define EXTERN_C_BEGIN extern "C" {
+#define EXTERN_C_END }
+#else
+#define EXTERN_C_BEGIN
+#define EXTERN_C_END
+#endif
+
+// Some ports make the mistake of running a 32-bit userspace
+// on a 64-bit kernel. Shame on them. It's not at all OK to
+// make everything "long long", since that causes unneeded
+// slowness on 32-bit hardware.
+//
+// SPARC: The 32-bit kernel was looking like an ex-penguin,
+// but it lives! ("I'm not dead yet.") So, 64-bit users will
+// just have to compile for 64-bit. Aw, the suffering.
+//
+// MIPS: Used 32-bit for embedded systems and obsolete hardware.
+// The 64-bit systems use an n32 format executable, defining
+// _ABIN32 to indicate this. Since n32 doesn't currently run on
+// any 32-bit system, nobody get hurt if it's bloated. Not that
+// this is sane of course, but it won't hurt the 32-bit users.
+// __mips_eabi means eabi, which comes in both sizes, but isn't used.
+//
+// PowerPC: Big ugly problem! 32-bit Macs are still popular. :-/
+//
+// x86-64: So far, nobody has been dumb enough to go 32-bit.
+//
+// Unknown: PA-RISC and zSeries
+//
+#if defined(k64test) || (defined(_ABIN32) && _MIPS_SIM == _ABIN32)
+#define KLONG long long    // not typedef; want "unsigned KLONG" to work
+#define KLF "L"
+#define STRTOUKL strtoull
+#else
+#define KLONG long
+#define KLF "l"
+#define STRTOUKL strtoul
+#endif
+
+// since gcc-2.5
+#define NORETURN __attribute__((__noreturn__))
+#define FUNCTION __attribute__((__const__))  // no access to global mem, even via ptr, and no side effect
+
+#if !defined(restrict) && __STDC_VERSION__ < 199901
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 92
+#define restrict __restrict__
+#else
+#warning No restrict keyword?
+#define restrict
+#endif
+#endif
+
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 96
+// won't alias anything, and aligned enough for anything
+#define MALLOC __attribute__ ((__malloc__))
+// no side effect, may read globals
+#define PURE __attribute__ ((__pure__))
+// tell gcc what to expect:   if(unlikely(err)) die(err);
+#define likely(x)       __builtin_expect(!!(x),1)
+#define unlikely(x)     __builtin_expect(!!(x),0)
+#define expected(x,y)   __builtin_expect((x),(y))
+#else
+#define MALLOC
+#define PURE
+#define likely(x)       (x)
+#define unlikely(x)     (x)
+#define expected(x,y)   (x)
+#endif
+
+#if SHARED==1 && (__GNUC__ > 2 || __GNUC_MINOR__ >= 96)
+#define LABEL_OFFSET
+#endif
+
+#define STRINGIFY_ARG(a)	#a
+#define STRINGIFY(a)		STRINGIFY_ARG(a)
+
+// marks old junk, to warn non-procps library users
+#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3
+#define OBSOLETE __attribute__((deprecated))
+#else
+#define OBSOLETE
+#endif
+
+#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 1 ) || __GNUC__ > 3
+// Tells gcc that function is library-internal;
+// so no need to do dynamic linking at run-time.
+// This might work with slightly older compilers too.
+#define HIDDEN __attribute__((visibility("hidden")))
+// The opposite, in case -fvisibility=hidden used
+#define EXPORT __attribute__((visibility("default")))
+// Tell g++ that a function won't throw exceptions.
+#define NOTHROW __attribute__((__nothrow__))
+#else
+#define HIDDEN
+#define EXPORT
+#define NOTHROW
+#endif
+
+// Like HIDDEN, but for an alias that gets created.
+// In gcc-3.2 there is an alias+hidden conflict.
+// Many will have patched this bug, but oh well.
+#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 2 ) || __GNUC__ > 3
+#define HIDDEN_ALIAS(x) extern __typeof(x) x##_direct __attribute__((alias(#x),visibility("hidden")))
+#else
+#define HIDDEN_ALIAS(x) extern __typeof(x) x##_direct __attribute__((alias(#x)))
+#endif
+
+#endif
diff --git a/procps-3.2.8/proc/pwcache.c b/procps-3.2.8/proc/pwcache.c
new file mode 100644
index 0000000..ab7e528
--- /dev/null
+++ b/procps-3.2.8/proc/pwcache.c
@@ -0,0 +1,77 @@
+// Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com
+// Note: most likely none of his code remains
+//
+// Copyright 2002, Albert Cahalan
+//
+// This file is placed under the conditions of the GNU Library
+// General Public License, version 2, or any later version.
+// See file COPYING for information on distribution conditions.
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include "alloc.h"
+#include "pwcache.h"
+#include <grp.h>
+
+// might as well fill cache lines... else we waste memory anyway
+
+#define	HASHSIZE	64		/* power of 2 */
+#define	HASH(x)		((x) & (HASHSIZE - 1))
+
+static struct pwbuf {
+    struct pwbuf *next;
+    uid_t uid;
+    char name[P_G_SZ];
+} *pwhash[HASHSIZE];
+
+char *user_from_uid(uid_t uid) {
+    struct pwbuf **p;
+    struct passwd *pw;
+
+    p = &pwhash[HASH(uid)];
+    while (*p) {
+	if ((*p)->uid == uid)
+	    return((*p)->name);
+	p = &(*p)->next;
+    }
+    *p = (struct pwbuf *) xmalloc(sizeof(struct pwbuf));
+    (*p)->uid = uid;
+    pw = getpwuid(uid);
+    if(!pw || strlen(pw->pw_name) >= P_G_SZ)
+	sprintf((*p)->name, "%u", uid);
+    else
+        strcpy((*p)->name, pw->pw_name);
+
+    (*p)->next = NULL;
+    return((*p)->name);
+}
+
+static struct grpbuf {
+    struct grpbuf *next;
+    gid_t gid;
+    char name[P_G_SZ];
+} *grphash[HASHSIZE];
+
+char *group_from_gid(gid_t gid) {
+    struct grpbuf **g;
+    struct group *gr;
+
+    g = &grphash[HASH(gid)];
+    while (*g) {
+        if ((*g)->gid == gid)
+            return((*g)->name);
+        g = &(*g)->next;
+    }
+    *g = (struct grpbuf *) malloc(sizeof(struct grpbuf));
+    (*g)->gid = gid;
+    gr = getgrgid(gid);
+    if (!gr || strlen(gr->gr_name) >= P_G_SZ)
+        sprintf((*g)->name, "%u", gid);
+    else
+        strcpy((*g)->name, gr->gr_name);
+    (*g)->next = NULL;
+    return((*g)->name);
+}
diff --git a/procps-3.2.8/proc/pwcache.h b/procps-3.2.8/proc/pwcache.h
new file mode 100644
index 0000000..678554d
--- /dev/null
+++ b/procps-3.2.8/proc/pwcache.h
@@ -0,0 +1,17 @@
+#ifndef PROCPS_PROC_PWCACHE_H
+#define PROCPS_PROC_PWCACHE_H
+
+#include <sys/types.h>
+#include "procps.h"
+
+EXTERN_C_BEGIN
+
+// used in pwcache and in readproc to set size of username or groupname
+#define P_G_SZ 20
+
+extern char *user_from_uid(uid_t uid);
+extern char *group_from_gid(gid_t gid);
+
+EXTERN_C_END
+
+#endif
diff --git a/procps-3.2.8/proc/readproc.c b/procps-3.2.8/proc/readproc.c
new file mode 100644
index 0000000..4fad11d
--- /dev/null
+++ b/procps-3.2.8/proc/readproc.c
@@ -0,0 +1,1054 @@
+/*
+ * New Interface to Process Table -- PROCTAB Stream (a la Directory streams)
+ * Copyright (C) 1996 Charles L. Blake.
+ * Copyright (C) 1998 Michael K. Johnson
+ * Copyright 1998-2003 Albert Cahalan
+ * May be distributed under the conditions of the
+ * GNU Library General Public License; a copy is in COPYING
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "version.h"
+#include "readproc.h"
+#include "alloc.h"
+#include "pwcache.h"
+#include "devname.h"
+#include "procps.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/dir.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+// sometimes it's easier to do this manually, w/o gcc helping
+#ifdef PROF
+extern void __cyg_profile_func_enter(void*,void*);
+#define ENTER(x) __cyg_profile_func_enter((void*)x,(void*)x)
+#define LEAVE(x) __cyg_profile_func_exit((void*)x,(void*)x)
+#else
+#define ENTER(x)
+#define LEAVE(x)
+#endif
+
+// convert hex string to unsigned long long
+static unsigned long long unhex(const char *restrict cp){
+    unsigned long long ull = 0;
+    for(;;){
+        char c = *cp++;
+        if(unlikely(c<0x30)) break;
+        ull = (ull<<4) | (c - (c>0x57) ? 0x57 : 0x30) ;
+    }
+    return ull;
+}
+
+static int task_dir_missing;
+
+///////////////////////////////////////////////////////////////////////////
+
+typedef struct status_table_struct {
+    unsigned char name[7];        // /proc/*/status field name
+    unsigned char len;            // name length
+#ifdef LABEL_OFFSET
+    long offset;                  // jump address offset
+#else
+    void *addr;
+#endif
+} status_table_struct;
+
+#ifdef LABEL_OFFSET
+#define F(x) {#x, sizeof(#x)-1, (long)(&&case_##x-&&base)},
+#else
+#define F(x) {#x, sizeof(#x)-1, &&case_##x},
+#endif
+#define NUL  {"", 0, 0},
+
+// Derived from:
+// gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c sml.gperf
+//
+// Suggested method:
+// Grep this file for "case_", then strip those down to the name.
+// (leave the colon and newline) So "Pid:\n" and "Threads:\n"
+// would be lines in the file. (no quote, no escape, etc.)
+//
+// Watch out for name size in the status_table_struct (grrr, expanding)
+// and the number of entries (we mask with 63 for now). The table
+// must be padded out to 64 entries, maybe 128 in the future.
+
+static void status2proc(char *S, proc_t *restrict P, int is_proc){
+    long Threads = 0;
+    long Tgid = 0;
+    long Pid = 0;
+
+  static const unsigned char asso[] =
+    {
+      61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+      61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+      61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+      61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+      61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+      61, 61, 61, 61, 61, 61, 61, 61, 15, 61,
+      61, 61, 61, 61, 61, 61, 30,  3,  5,  5,
+      61,  5, 61,  8, 61, 61,  3, 61, 10, 61,
+       6, 61, 13,  0, 30, 25,  0, 61, 61, 61,
+      61, 61, 61, 61, 61, 61, 61,  3, 61, 13,
+       0,  0, 61, 30, 61, 25, 61, 61, 61,  0,
+      61, 61, 61, 61,  5, 61,  0, 61, 61, 61,
+       0, 61, 61, 61, 61, 61, 61, 61
+    };
+
+    static const status_table_struct table[] = {
+      F(VmStk)
+      NUL NUL
+      F(State)
+      NUL
+      F(VmExe)
+      F(ShdPnd)
+      NUL
+      F(VmData)
+      NUL
+      F(Name)
+      NUL NUL
+      F(VmRSS)
+      NUL NUL
+      F(VmLck)
+      NUL NUL NUL
+      F(Gid)
+      F(Pid)
+      NUL NUL NUL
+      F(VmSize)
+      NUL NUL
+      F(VmLib)
+      NUL NUL
+      F(PPid)
+      NUL
+      F(SigCgt)
+      NUL
+      F(Threads)
+      F(SigPnd)
+      NUL
+      F(SigIgn)
+      NUL
+      F(Uid)
+      NUL NUL NUL NUL NUL NUL NUL NUL NUL
+      NUL NUL NUL NUL NUL
+      F(Tgid)
+      NUL NUL NUL NUL
+      F(SigBlk)
+      NUL NUL NUL
+    };
+
+#undef F
+#undef NUL
+
+ENTER(0x220);
+
+    P->vm_size = 0;
+    P->vm_lock = 0;
+    P->vm_rss  = 0;
+    P->vm_data = 0;
+    P->vm_stack= 0;
+    P->vm_exe  = 0;
+    P->vm_lib  = 0;
+    P->nlwp    = 0;
+    P->signal[0] = '\0';  // so we can detect it as missing for very old kernels
+
+    goto base;
+
+    for(;;){
+        char *colon;
+        status_table_struct entry;
+
+        // advance to next line
+        S = strchr(S, '\n');
+        if(unlikely(!S)) break;  // if no newline
+        S++;
+
+        // examine a field name (hash and compare)
+    base:
+        if(unlikely(!*S)) break;
+        entry = table[63 & (asso[S[3]] + asso[S[2]] + asso[S[0]])];
+        colon = strchr(S, ':');
+        if(unlikely(!colon)) break;
+        if(unlikely(colon[1]!='\t')) break;
+        if(unlikely(colon-S != entry.len)) continue;
+        if(unlikely(memcmp(entry.name,S,colon-S))) continue;
+
+        S = colon+2; // past the '\t'
+
+#ifdef LABEL_OFFSET
+        goto *(&&base + entry.offset);
+#else
+        goto *entry.addr;
+#endif
+
+    case_Name:{
+        unsigned u = 0;
+        while(u < sizeof P->cmd - 1u){
+            int c = *S++;
+            if(unlikely(c=='\n')) break;
+            if(unlikely(c=='\0')) break; // should never happen
+            if(unlikely(c=='\\')){
+                c = *S++;
+                if(c=='\n') break; // should never happen
+                if(!c)      break; // should never happen
+                if(c=='n') c='\n'; // else we assume it is '\\'
+            }
+            P->cmd[u++] = c;
+        }
+        P->cmd[u] = '\0';
+        S--;   // put back the '\n' or '\0'
+        continue;
+    }
+#ifdef SIGNAL_STRING
+    case_ShdPnd:
+        memcpy(P->signal, S, 16);
+        P->signal[16] = '\0';
+        continue;
+    case_SigBlk:
+        memcpy(P->blocked, S, 16);
+        P->blocked[16] = '\0';
+        continue;
+    case_SigCgt:
+        memcpy(P->sigcatch, S, 16);
+        P->sigcatch[16] = '\0';
+        continue;
+    case_SigIgn:
+        memcpy(P->sigignore, S, 16);
+        P->sigignore[16] = '\0';
+        continue;
+    case_SigPnd:
+        memcpy(P->_sigpnd, S, 16);
+        P->_sigpnd[16] = '\0';
+        continue;
+#else
+    case_ShdPnd:
+        P->signal = unhex(S);
+        continue;
+    case_SigBlk:
+        P->blocked = unhex(S);
+        continue;
+    case_SigCgt:
+        P->sigcatch = unhex(S);
+        continue;
+    case_SigIgn:
+        P->sigignore = unhex(S);
+        continue;
+    case_SigPnd:
+        P->_sigpnd = unhex(S);
+        continue;
+#endif
+    case_State:
+        P->state = *S;
+        continue;
+    case_Tgid:
+        Tgid = strtol(S,&S,10);
+        continue;
+    case_Pid:
+        Pid = strtol(S,&S,10);
+        continue;
+    case_PPid:
+        P->ppid = strtol(S,&S,10);
+        continue;
+    case_Threads:
+        Threads = strtol(S,&S,10);
+        continue;
+    case_Uid:
+        P->ruid = strtol(S,&S,10);
+        P->euid = strtol(S,&S,10);
+        P->suid = strtol(S,&S,10);
+        P->fuid = strtol(S,&S,10);
+        continue;
+    case_Gid:
+        P->rgid = strtol(S,&S,10);
+        P->egid = strtol(S,&S,10);
+        P->sgid = strtol(S,&S,10);
+        P->fgid = strtol(S,&S,10);
+        continue;
+    case_VmData:
+        P->vm_data = strtol(S,&S,10);
+        continue;
+    case_VmExe:
+        P->vm_exe = strtol(S,&S,10);
+        continue;
+    case_VmLck:
+        P->vm_lock = strtol(S,&S,10);
+        continue;
+    case_VmLib:
+        P->vm_lib = strtol(S,&S,10);
+        continue;
+    case_VmRSS:
+        P->vm_rss = strtol(S,&S,10);
+        continue;
+    case_VmSize:
+        P->vm_size = strtol(S,&S,10);
+        continue;
+    case_VmStk:
+        P->vm_stack = strtol(S,&S,10);
+        continue;
+    }
+
+#if 0
+    // recent kernels supply per-tgid pending signals
+    if(is_proc && *ShdPnd){
+	memcpy(P->signal, ShdPnd, 16);
+	P->signal[16] = '\0';
+    }
+#endif
+
+    // recent kernels supply per-tgid pending signals
+#ifdef SIGNAL_STRING
+    if(!is_proc || !P->signal[0]){
+	memcpy(P->signal, P->_sigpnd, 16);
+	P->signal[16] = '\0';
+    }
+#else
+    if(!is_proc || !have_process_pending){
+	P->signal = P->_sigpnd;
+    }
+#endif
+
+    // Linux 2.4.13-pre1 to max 2.4.xx have a useless "Tgid"
+    // that is not initialized for built-in kernel tasks.
+    // Only 2.6.0 and above have "Threads" (nlwp) info.
+
+    if(Threads){
+       P->nlwp = Threads;
+       P->tgid = Tgid;     // the POSIX PID value
+       P->tid  = Pid;      // the thread ID
+    }else{
+       P->nlwp = 1;
+       P->tgid = Pid;
+       P->tid  = Pid;
+    }
+
+LEAVE(0x220);
+}
+
+///////////////////////////////////////////////////////////////////////
+
+// Reads /proc/*/stat files, being careful not to trip over processes with
+// names like ":-) 1 2 3 4 5 6".
+static void stat2proc(const char* S, proc_t *restrict P) {
+    unsigned num;
+    char* tmp;
+
+ENTER(0x160);
+
+    /* fill in default values for older kernels */
+    P->processor = 0;
+    P->rtprio = -1;
+    P->sched = -1;
+    P->nlwp = 0;
+
+    S = strchr(S, '(') + 1;
+    tmp = strrchr(S, ')');
+    num = tmp - S;
+    if(unlikely(num >= sizeof P->cmd)) num = sizeof P->cmd - 1;
+    memcpy(P->cmd, S, num);
+    P->cmd[num] = '\0';
+    S = tmp + 2;                 // skip ") "
+
+    num = sscanf(S,
+       "%c "
+       "%d %d %d %d %d "
+       "%lu %lu %lu %lu %lu "
+       "%Lu %Lu %Lu %Lu "  /* utime stime cutime cstime */
+       "%ld %ld "
+       "%d "
+       "%ld "
+       "%Lu "  /* start_time */
+       "%lu "
+       "%ld "
+       "%lu %"KLF"u %"KLF"u %"KLF"u %"KLF"u %"KLF"u "
+       "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */
+       "%"KLF"u %*lu %*lu "
+       "%d %d "
+       "%lu %lu",
+       &P->state,
+       &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid,
+       &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt,
+       &P->utime, &P->stime, &P->cutime, &P->cstime,
+       &P->priority, &P->nice,
+       &P->nlwp,
+       &P->alarm,
+       &P->start_time,
+       &P->vsize,
+       &P->rss,
+       &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip,
+/*     P->signal, P->blocked, P->sigignore, P->sigcatch,   */ /* can't use */
+       &P->wchan, /* &P->nswap, &P->cnswap, */  /* nswap and cnswap dead for 2.4.xx and up */
+/* -- Linux 2.0.35 ends here -- */
+       &P->exit_signal, &P->processor,  /* 2.2.1 ends with "exit_signal" */
+/* -- Linux 2.2.8 to 2.5.17 end here -- */
+       &P->rtprio, &P->sched  /* both added to 2.5.18 */
+    );
+
+    if(!P->nlwp){
+      P->nlwp = 1;
+    }
+
+LEAVE(0x160);
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+static void statm2proc(const char* s, proc_t *restrict P) {
+    int num;
+    num = sscanf(s, "%ld %ld %ld %ld %ld %ld %ld",
+	   &P->size, &P->resident, &P->share,
+	   &P->trs, &P->lrs, &P->drs, &P->dt);
+/*    fprintf(stderr, "statm2proc converted %d fields.\n",num); */
+}
+
+static int file2str(const char *directory, const char *what, char *ret, int cap) {
+    static char filename[80];
+    int fd, num_read;
+
+    sprintf(filename, "%s/%s", directory, what);
+    fd = open(filename, O_RDONLY, 0);
+    if(unlikely(fd==-1)) return -1;
+    num_read = read(fd, ret, cap - 1);
+    close(fd);
+    if(unlikely(num_read<=0)) return -1;
+    ret[num_read] = '\0';
+    return num_read;
+}
+
+static char** file2strvec(const char* directory, const char* what) {
+    char buf[2048];	/* read buf bytes at a time */
+    char *p, *rbuf = 0, *endbuf, **q, **ret;
+    int fd, tot = 0, n, c, end_of_file = 0;
+    int align;
+
+    sprintf(buf, "%s/%s", directory, what);
+    fd = open(buf, O_RDONLY, 0);
+    if(fd==-1) return NULL;
+
+    /* read whole file into a memory buffer, allocating as we go */
+    while ((n = read(fd, buf, sizeof buf - 1)) > 0) {
+	if (n < (int)(sizeof buf - 1))
+	    end_of_file = 1;
+	if (n == 0 && rbuf == 0)
+	    return NULL;	/* process died between our open and read */
+	if (n < 0) {
+	    if (rbuf)
+		free(rbuf);
+	    return NULL;	/* read error */
+	}
+	if (end_of_file && buf[n-1])		/* last read char not null */
+	    buf[n++] = '\0';			/* so append null-terminator */
+	rbuf = xrealloc(rbuf, tot + n);		/* allocate more memory */
+	memcpy(rbuf + tot, buf, n);		/* copy buffer into it */
+	tot += n;				/* increment total byte ctr */
+	if (end_of_file)
+	    break;
+    }
+    close(fd);
+    if (n <= 0 && !end_of_file) {
+	if (rbuf) free(rbuf);
+	return NULL;		/* read error */
+    }
+    endbuf = rbuf + tot;			/* count space for pointers */
+    align = (sizeof(char*)-1) - ((tot + sizeof(char*)-1) & (sizeof(char*)-1));
+    for (c = 0, p = rbuf; p < endbuf; p++)
+    	if (!*p)
+	    c += sizeof(char*);
+    c += sizeof(char*);				/* one extra for NULL term */
+
+    rbuf = xrealloc(rbuf, tot + c + align);	/* make room for ptrs AT END */
+    endbuf = rbuf + tot;			/* addr just past data buf */
+    q = ret = (char**) (endbuf+align);		/* ==> free(*ret) to dealloc */
+    *q++ = p = rbuf;				/* point ptrs to the strings */
+    endbuf--;					/* do not traverse final NUL */
+    while (++p < endbuf) 
+    	if (!*p)				/* NUL char implies that */
+	    *q++ = p+1;				/* next string -> next char */
+
+    *q = 0;					/* null ptr list terminator */
+    return ret;
+}
+
+// warning: interface may change
+int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
+    char name[32];
+    int fd;
+    unsigned n = 0;
+    dst[0] = '\0';
+    snprintf(name, sizeof name, "/proc/%u/cmdline", pid);
+    fd = open(name, O_RDONLY);
+    if(fd==-1) return 0;
+    for(;;){
+        ssize_t r = read(fd,dst+n,sz-n);
+        if(r==-1){
+            if(errno==EINTR) continue;
+            break;
+        }
+        n += r;
+        if(n==sz) break; // filled the buffer
+        if(r==0) break;  // EOF
+    }
+    close(fd);
+    if(n){
+        int i;
+        if(n==sz) n--;
+        dst[n] = '\0';
+        i=n;
+        while(i--){
+            int c = dst[i];
+            if(c<' ' || c>'~') dst[i]=' ';
+        }
+    }
+    return n;
+}
+
+/* These are some nice GNU C expression subscope "inline" functions.
+ * The can be used with arbitrary types and evaluate their arguments
+ * exactly once.
+ */
+
+/* Test if item X of type T is present in the 0 terminated list L */
+#   define XinL(T, X, L) ( {			\
+	    T  x = (X), *l = (L);		\
+	    while (*l && *l != x) l++;		\
+	    *l == x;				\
+	} )
+
+/* Test if item X of type T is present in the list L of length N */
+#   define XinLN(T, X, L, N) ( {		\
+	    T x = (X), *l = (L);		\
+	    int i = 0, n = (N);			\
+	    while (i < n && l[i] != x) i++;	\
+	    i < n && l[i] == x;			\
+	} )
+
+//////////////////////////////////////////////////////////////////////////////////
+// This reads process info from /proc in the traditional way, for one process.
+// The pid (tgid? tid?) is already in p, and a path to it in path, with some
+// room to spare.
+static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict const p) {
+    static struct stat sb;		// stat() buffer
+    static char sbuf[1024];	// buffer for stat,statm
+    char *restrict const path = PT->path;
+    unsigned flags = PT->flags;
+
+    if (unlikely(stat(path, &sb) == -1))	/* no such dirent (anymore) */
+	goto next_proc;
+
+    if ((flags & PROC_UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid))
+	goto next_proc;			/* not one of the requested uids */
+
+    p->euid = sb.st_uid;			/* need a way to get real uid */
+    p->egid = sb.st_gid;			/* need a way to get real gid */
+
+    if (flags & PROC_FILLSTAT) {         /* read, parse /proc/#/stat */
+	if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 ))
+	    goto next_proc;			/* error reading /proc/#/stat */
+	stat2proc(sbuf, p);				/* parse /proc/#/stat */
+    }
+
+    if (unlikely(flags & PROC_FILLMEM)) {	/* read, parse /proc/#/statm */
+	if (likely( file2str(path, "statm", sbuf, sizeof sbuf) != -1 ))
+	    statm2proc(sbuf, p);		/* ignore statm errors here */
+    }						/* statm fields just zero */
+
+    if (flags & PROC_FILLSTATUS) {         /* read, parse /proc/#/status */
+       if (likely( file2str(path, "status", sbuf, sizeof sbuf) != -1 )){
+           status2proc(sbuf, p, 1);
+       }
+    }
+
+    // if multithreaded, some values are crap
+    if(p->nlwp > 1){
+      p->wchan = (KLONG)~0ull;
+    }
+
+    /* some number->text resolving which is time consuming and kind of insane */
+    if (flags & PROC_FILLUSR){
+	memcpy(p->euser,   user_from_uid(p->euid), sizeof p->euser);
+        if(flags & PROC_FILLSTATUS) {
+            memcpy(p->ruser,   user_from_uid(p->ruid), sizeof p->ruser);
+            memcpy(p->suser,   user_from_uid(p->suid), sizeof p->suser);
+            memcpy(p->fuser,   user_from_uid(p->fuid), sizeof p->fuser);
+        }
+    }
+
+    /* some number->text resolving which is time consuming and kind of insane */
+    if (flags & PROC_FILLGRP){
+        memcpy(p->egroup, group_from_gid(p->egid), sizeof p->egroup);
+        if(flags & PROC_FILLSTATUS) {
+            memcpy(p->rgroup, group_from_gid(p->rgid), sizeof p->rgroup);
+            memcpy(p->sgroup, group_from_gid(p->sgid), sizeof p->sgroup);
+            memcpy(p->fgroup, group_from_gid(p->fgid), sizeof p->fgroup);
+        }
+    }
+
+    if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG))	/* read+parse /proc/#/cmdline */
+	p->cmdline = file2strvec(path, "cmdline");
+    else
+        p->cmdline = NULL;
+
+    if (unlikely(flags & PROC_FILLENV))			/* read+parse /proc/#/environ */
+	p->environ = file2strvec(path, "environ");
+    else
+        p->environ = NULL;
+    
+    return p;
+next_proc:
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// This reads /proc/*/task/* data, for one task.
+// p is the POSIX process (task group summary) (not needed by THIS implementation)
+// t is the POSIX thread (task group member, generally not the leader)
+// path is a path to the task, with some room to spare.
+static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict const t, char *restrict const path) {
+    static struct stat sb;		// stat() buffer
+    static char sbuf[1024];	// buffer for stat,statm
+    unsigned flags = PT->flags;
+
+//printf("hhh\n");
+    if (unlikely(stat(path, &sb) == -1))	/* no such dirent (anymore) */
+	goto next_task;
+
+//    if ((flags & PROC_UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid))
+//	goto next_task;			/* not one of the requested uids */
+
+    t->euid = sb.st_uid;			/* need a way to get real uid */
+    t->egid = sb.st_gid;			/* need a way to get real gid */
+
+//printf("iii\n");
+    if (flags & PROC_FILLSTAT) {         /* read, parse /proc/#/stat */
+	if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 ))
+	    goto next_task;			/* error reading /proc/#/stat */
+	stat2proc(sbuf, t);				/* parse /proc/#/stat */
+    }
+
+    if (unlikely(flags & PROC_FILLMEM)) {	/* read, parse /proc/#/statm */
+#if 0
+	if (likely( file2str(path, "statm", sbuf, sizeof sbuf) != -1 ))
+	    statm2proc(sbuf, t);		/* ignore statm errors here */
+#else
+	t->size     = p->size;
+	t->resident = p->resident;
+	t->share    = p->share;
+	t->trs      = p->trs;
+	t->lrs      = p->lrs;
+	t->drs      = p->drs;
+	t->dt       = p->dt;
+#endif
+    }						/* statm fields just zero */
+
+    if (flags & PROC_FILLSTATUS) {         /* read, parse /proc/#/status */
+       if (likely( file2str(path, "status", sbuf, sizeof sbuf) != -1 )){
+           status2proc(sbuf, t, 0);
+       }
+    }
+
+    /* some number->text resolving which is time consuming */
+    if (flags & PROC_FILLUSR){
+	memcpy(t->euser,   user_from_uid(t->euid), sizeof t->euser);
+        if(flags & PROC_FILLSTATUS) {
+            memcpy(t->ruser,   user_from_uid(t->ruid), sizeof t->ruser);
+            memcpy(t->suser,   user_from_uid(t->suid), sizeof t->suser);
+            memcpy(t->fuser,   user_from_uid(t->fuid), sizeof t->fuser);
+        }
+    }
+
+    /* some number->text resolving which is time consuming */
+    if (flags & PROC_FILLGRP){
+        memcpy(t->egroup, group_from_gid(t->egid), sizeof t->egroup);
+        if(flags & PROC_FILLSTATUS) {
+            memcpy(t->rgroup, group_from_gid(t->rgid), sizeof t->rgroup);
+            memcpy(t->sgroup, group_from_gid(t->sgid), sizeof t->sgroup);
+            memcpy(t->fgroup, group_from_gid(t->fgid), sizeof t->fgroup);
+        }
+    }
+
+#if 0
+    if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG))	/* read+parse /proc/#/cmdline */
+	t->cmdline = file2strvec(path, "cmdline");
+    else
+        t->cmdline = NULL;
+
+    if (unlikely(flags & PROC_FILLENV))			/* read+parse /proc/#/environ */
+	t->environ = file2strvec(path, "environ");
+    else
+        t->environ = NULL;
+#else
+    t->cmdline = p->cmdline;  // better not free these until done with all threads!
+    t->environ = p->environ;
+#endif
+
+    t->ppid = p->ppid;  // ought to put the per-task ppid somewhere
+
+    return t;
+next_task:
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// This finds processes in /proc in the traditional way.
+// Return non-zero on success.
+static int simple_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p) {
+  static struct direct *ent;		/* dirent handle */
+  char *restrict const path = PT->path;
+  for (;;) {
+    ent = readdir(PT->procfs);
+    if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return 0;
+    if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
+  }
+  p->tgid = strtoul(ent->d_name, NULL, 10);
+  p->tid = p->tgid;
+  memcpy(path, "/proc/", 6);
+  strcpy(path+6, ent->d_name);  // trust /proc to not contain evil top-level entries
+  return 1;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// This finds tasks in /proc/*/task/ in the traditional way.
+// Return non-zero on success.
+static int simple_nexttid(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict const t, char *restrict const path) {
+  static struct direct *ent;		/* dirent handle */
+  if(PT->taskdir_user != p->tgid){
+    if(PT->taskdir){
+      closedir(PT->taskdir);
+    }
+    // use "path" as some tmp space
+    snprintf(path, PROCPATHLEN, "/proc/%d/task", p->tgid);
+    PT->taskdir = opendir(path);
+    if(!PT->taskdir) return 0;
+    PT->taskdir_user = p->tgid;
+  }
+  for (;;) {
+    ent = readdir(PT->taskdir);
+    if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))) return 0;
+    if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') )) break;
+  }
+  t->tid = strtoul(ent->d_name, NULL, 10);
+  t->tgid = p->tgid;
+  t->ppid = p->ppid;  // cover for kernel behavior? we want both actually...?
+  snprintf(path, PROCPATHLEN, "/proc/%d/task/%s", p->tgid, ent->d_name);
+  return 1;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// This "finds" processes in a list that was given to openproc().
+// Return non-zero on success. (tgid was handy)
+static int listed_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p) {
+  char *restrict const path = PT->path;
+  pid_t tgid = *(PT->pids)++;
+  if(likely( tgid )){
+    snprintf(path, PROCPATHLEN, "/proc/%d", tgid);
+    p->tgid = tgid;
+    p->tid = tgid;  // they match for leaders
+  }
+  return tgid;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+/* readproc: return a pointer to a proc_t filled with requested info about the
+ * next process available matching the restriction set.  If no more such
+ * processes are available, return a null pointer (boolean false).  Use the
+ * passed buffer instead of allocating space if it is non-NULL.  */
+
+/* This is optimized so that if a PID list is given, only those files are
+ * searched for in /proc.  If other lists are given in addition to the PID list,
+ * the same logic can follow through as for the no-PID list case.  This is
+ * fairly complex, but it does try to not to do any unnecessary work.
+ */
+proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict p) {
+  proc_t *ret;
+  proc_t *saved_p;
+
+  PT->did_fake=0;
+//  if (PT->taskdir) {
+//    closedir(PT->taskdir);
+//    PT->taskdir = NULL;
+//    PT->taskdir_user = -1;
+//  }
+
+  saved_p = p;
+  if(!p) p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
+
+  for(;;){
+    // fills in the path, plus p->tid and p->tgid
+    if (unlikely(! PT->finder(PT,p) )) goto out;
+
+    // go read the process data
+    ret = PT->reader(PT,p);
+    if(ret) return ret;
+  }
+
+out:
+  if(!saved_p) free(p);
+  // FIXME: maybe set tid to -1 here, for "-" in display?
+  return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// readtask: return a pointer to a proc_t filled with requested info about the
+// next task available.  If no more such tasks are available, return a null
+// pointer (boolean false).  Use the passed buffer instead of allocating
+// space if it is non-NULL.
+proc_t* readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict t) {
+  static char path[PROCPATHLEN];       // must hold /proc/2000222000/task/2000222000/cmdline
+  proc_t *ret;
+  proc_t *saved_t;
+
+  saved_t = t;
+  if(!t) t = xcalloc(t, sizeof *t); /* passed buf or alloced mem */
+
+  // 1. got to fake a thread for old kernels
+  // 2. for single-threaded processes, this is faster (but must patch up stuff that differs!)
+  if(task_dir_missing || p->nlwp < 2){
+    if(PT->did_fake) goto out;
+    PT->did_fake=1;
+    memcpy(t,p,sizeof(proc_t));
+    // use the per-task pending, not per-tgid pending
+#ifdef SIGNAL_STRING
+	memcpy(&t->signal, &t->_sigpnd, sizeof t->signal);
+#else
+	t->signal = t->_sigpnd;
+#endif
+    return t;
+  }
+
+  for(;;){
+    // fills in the path, plus t->tid and t->tgid
+    if (unlikely(! PT->taskfinder(PT,p,t,path) )) goto out;  // simple_nexttid
+
+    // go read the task data
+    ret = PT->taskreader(PT,p,t,path);          // simple_readtask
+    if(ret) return ret;
+  }
+
+out:
+  if(!saved_t) free(t);
+  return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+// initiate a process table scan
+PROCTAB* openproc(int flags, ...) {
+    va_list ap;
+    struct stat sbuf;
+    static int did_stat;
+    PROCTAB* PT = xmalloc(sizeof(PROCTAB));
+
+    if(!did_stat){
+      task_dir_missing = stat("/proc/self/task", &sbuf);
+      did_stat = 1;
+    }
+    PT->taskdir = NULL;
+    PT->taskdir_user = -1;
+    PT->taskfinder = simple_nexttid;
+    PT->taskreader = simple_readtask;
+
+    PT->reader = simple_readproc;
+    if (flags & PROC_PID){
+      PT->procfs = NULL;
+      PT->finder = listed_nextpid;
+    }else{
+      PT->procfs = opendir("/proc");
+      if(!PT->procfs) return NULL;
+      PT->finder = simple_nextpid;
+    }
+    PT->flags = flags;
+
+    va_start(ap, flags);		/*  Init args list */
+    if (flags & PROC_PID)
+    	PT->pids = va_arg(ap, pid_t*);
+    else if (flags & PROC_UID) {
+    	PT->uids = va_arg(ap, uid_t*);
+	PT->nuid = va_arg(ap, int);
+    }
+    va_end(ap);				/*  Clean up args list */
+
+    return PT;
+}
+
+// terminate a process table scan
+void closeproc(PROCTAB* PT) {
+    if (PT){
+        if (PT->procfs) closedir(PT->procfs);
+        if (PT->taskdir) closedir(PT->taskdir);
+        memset(PT,'#',sizeof(PROCTAB));
+        free(PT);
+    }
+}
+
+// deallocate the space allocated by readproc if the passed rbuf was NULL
+void freeproc(proc_t* p) {
+    if (!p)	/* in case p is NULL */
+	return;
+    /* ptrs are after strings to avoid copying memory when building them. */
+    /* so free is called on the address of the address of strvec[0]. */
+    if (p->cmdline)
+	free((void*)*p->cmdline);
+    if (p->environ)
+	free((void*)*p->environ);
+    free(p);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////
+void look_up_our_self(proc_t *p) {
+    char sbuf[1024];
+
+    if(file2str("/proc/self", "stat", sbuf, sizeof sbuf) == -1){
+        fprintf(stderr, "Error, do this: mount -t proc none /proc\n");
+        _exit(47);
+    }
+    stat2proc(sbuf, p);    // parse /proc/self/stat
+}
+
+HIDDEN_ALIAS(readproc);
+HIDDEN_ALIAS(readtask);
+
+/* Convenient wrapper around openproc and readproc to slurp in the whole process
+ * table subset satisfying the constraints of flags and the optional PID list.
+ * Free allocated memory with exit().  Access via tab[N]->member.  The pointer
+ * list is NULL terminated.
+ */
+proc_t** readproctab(int flags, ...) {
+    PROCTAB* PT = NULL;
+    proc_t** tab = NULL;
+    int n = 0;
+    va_list ap;
+
+    va_start(ap, flags);		/* pass through args to openproc */
+    if (flags & PROC_UID) {
+	/* temporary variables to ensure that va_arg() instances
+	 * are called in the right order
+	 */
+	uid_t* u;
+	int i;
+
+	u = va_arg(ap, uid_t*);
+	i = va_arg(ap, int);
+	PT = openproc(flags, u, i);
+    }
+    else if (flags & PROC_PID)
+	PT = openproc(flags, va_arg(ap, void*)); /* assume ptr sizes same */
+    else
+	PT = openproc(flags);
+    va_end(ap);
+    do {					/* read table: */
+	tab = xrealloc(tab, (n+1)*sizeof(proc_t*));/* realloc as we go, using */
+	tab[n] = readproc_direct(PT, NULL);     /* final null to terminate */
+    } while (tab[n++]);				  /* stop when NULL reached */
+    closeproc(PT);
+    return tab;
+}
+
+// Try again, this time with threads and selection.
+proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t *buf), PROCTAB *restrict const PT) {
+    proc_t** ptab = NULL;
+    unsigned n_proc_alloc = 0;
+    unsigned n_proc = 0;
+
+    proc_t** ttab = NULL;
+    unsigned n_task_alloc = 0;
+    unsigned n_task = 0;
+
+    proc_t*  data = NULL;
+    unsigned n_alloc = 0;
+    unsigned long n_used = 0;
+
+    proc_data_t *pd;
+
+    for(;;){
+        proc_t *tmp;
+        if(n_alloc == n_used){
+          //proc_t *old = data;
+          n_alloc = n_alloc*5/4+30;  // grow by over 25%
+          data = realloc(data,sizeof(proc_t)*n_alloc);
+          //if(!data) return NULL;
+        }
+        if(n_proc_alloc == n_proc){
+          //proc_t **old = ptab;
+          n_proc_alloc = n_proc_alloc*5/4+30;  // grow by over 25%
+          ptab = realloc(ptab,sizeof(proc_t*)*n_proc_alloc);
+          //if(!ptab) return NULL;
+        }
+        tmp = readproc_direct(PT, data+n_used);
+        if(!tmp) break;
+        if(!want_proc(tmp)) continue;
+        ptab[n_proc++] = (proc_t*)(n_used++);
+        if(!(  PT->flags & PROC_LOOSE_TASKS  )) continue;
+        for(;;){
+          proc_t *t;
+          if(n_alloc == n_used){
+            proc_t *old = data;
+            n_alloc = n_alloc*5/4+30;  // grow by over 25%
+            data = realloc(data,sizeof(proc_t)*n_alloc);
+	    // have to move tmp too
+	    tmp = data+(tmp-old);
+            //if(!data) return NULL;
+          }
+          if(n_task_alloc == n_task){
+            //proc_t **old = ttab;
+            n_task_alloc = n_task_alloc*5/4+1;  // grow by over 25%
+            ttab = realloc(ttab,sizeof(proc_t*)*n_task_alloc);
+            //if(!ttab) return NULL;
+          }
+          t = readtask_direct(PT, tmp, data+n_used);
+          if(!t) break;
+          if(!want_task(t)) continue;
+          ttab[n_task++] = (proc_t*)(n_used++);
+        }
+    }
+
+    pd = malloc(sizeof(proc_data_t));
+    pd->proc = ptab;
+    pd->task = ttab;
+    pd->nproc = n_proc;
+    pd->ntask = n_task;
+    if(PT->flags & PROC_LOOSE_TASKS){
+      pd->tab = ttab;
+      pd->n   = n_task;
+    }else{
+      pd->tab = ptab;
+      pd->n   = n_proc;
+    }
+    // change array indexes to pointers
+    while(n_proc--) ptab[n_proc] = data+(long)(ptab[n_proc]);
+    while(n_task--) ttab[n_task] = data+(long)(ttab[n_task]);
+
+    return pd;
+}
+
+/*
+ * get_proc_stats - lookup a single tasks information and fill out a proc_t
+ *
+ * On failure, returns NULL.  On success, returns 'p' and 'p' is a valid
+ * and filled out proc_t structure.
+ */
+proc_t * get_proc_stats(pid_t pid, proc_t *p) {
+	static char path[PATH_MAX], sbuf[1024];
+	struct stat statbuf;
+
+	sprintf(path, "/proc/%d", pid);
+	if (stat(path, &statbuf)) {
+		perror("stat");
+		return NULL;
+	}
+
+	if (file2str(path, "stat", sbuf, sizeof sbuf) >= 0)
+		stat2proc(sbuf, p);	/* parse /proc/#/stat */
+	if (file2str(path, "statm", sbuf, sizeof sbuf) >= 0)
+		statm2proc(sbuf, p);	/* ignore statm errors here */
+	if (file2str(path, "status", sbuf, sizeof sbuf) >= 0)
+		status2proc(sbuf, p, 0 /*FIXME*/);
+
+	return p;
+}
diff --git a/procps-3.2.8/proc/readproc.h b/procps-3.2.8/proc/readproc.h
new file mode 100644
index 0000000..a953b29
--- /dev/null
+++ b/procps-3.2.8/proc/readproc.h
@@ -0,0 +1,253 @@
+#ifndef PROCPS_PROC_READPROC_H
+#define PROCPS_PROC_READPROC_H
+
+// New Interface to Process Table -- PROCTAB Stream (a la Directory streams)
+// Copyright 1996 Charles L. Blake.
+// Copyright 1998 Michael K. Johnson
+// Copyright 1998-2003 Albert Cahalan
+// May be distributed under the terms of the
+// GNU Library General Public License, a copy of which is provided
+// in the file COPYING
+
+
+#include "procps.h"
+#include "pwcache.h"
+
+#define SIGNAL_STRING
+
+EXTERN_C_BEGIN
+
+// ld	cutime, cstime, priority, nice, timeout, alarm, rss,
+// c	state,
+// d	ppid, pgrp, session, tty, tpgid,
+// s	signal, blocked, sigignore, sigcatch,
+// lu	flags, min_flt, cmin_flt, maj_flt, cmaj_flt, utime, stime,
+// lu	rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip,
+// lu	start_time, vsize, wchan,
+
+// This is to help document a transition from pid to tgid/tid caused
+// by the introduction of thread support. It is used in cases where
+// neither tgid nor tid seemed correct. (in other words, FIXME)
+#define XXXID tid
+
+// Basic data structure which holds all information we can get about a process.
+// (unless otherwise specified, fields are read from /proc/#/stat)
+//
+// Most of it comes from task_struct in linux/sched.h
+//
+typedef struct proc_t {
+// 1st 16 bytes
+    int
+        tid,		// (special)       task id, the POSIX thread ID (see also: tgid)
+    	ppid;		// stat,status     pid of parent process
+    unsigned
+        pcpu;           // stat (special)  %CPU usage (is not filled in by readproc!!!)
+    char
+    	state,		// stat,status     single-char code for process state (S=sleeping)
+    	pad_1,		// n/a             padding
+    	pad_2,		// n/a             padding
+    	pad_3;		// n/a             padding
+// 2nd 16 bytes
+    unsigned long long
+	utime,		// stat            user-mode CPU time accumulated by process
+	stime,		// stat            kernel-mode CPU time accumulated by process
+// and so on...
+	cutime,		// stat            cumulative utime of process and reaped children
+	cstime,		// stat            cumulative stime of process and reaped children
+	start_time;	// stat            start time of process -- seconds since 1-1-70
+#ifdef SIGNAL_STRING
+    char
+	// Linux 2.1.7x and up have 64 signals. Allow 64, plus '\0' and padding.
+	signal[18],	// status          mask of pending signals, per-task for readtask() but per-proc for readproc()
+	blocked[18],	// status          mask of blocked signals
+	sigignore[18],	// status          mask of ignored signals
+	sigcatch[18],	// status          mask of caught  signals
+	_sigpnd[18];	// status          mask of PER TASK pending signals
+#else
+    long long
+	// Linux 2.1.7x and up have 64 signals.
+	signal,		// status          mask of pending signals, per-task for readtask() but per-proc for readproc()
+	blocked,	// status          mask of blocked signals
+	sigignore,	// status          mask of ignored signals
+	sigcatch,	// status          mask of caught  signals
+	_sigpnd;	// status          mask of PER TASK pending signals
+#endif
+    unsigned KLONG
+	start_code,	// stat            address of beginning of code segment
+	end_code,	// stat            address of end of code segment
+	start_stack,	// stat            address of the bottom of stack for the process
+	kstk_esp,	// stat            kernel stack pointer
+	kstk_eip,	// stat            kernel instruction pointer
+	wchan;		// stat (special)  address of kernel wait channel proc is sleeping in
+    long
+	priority,	// stat            kernel scheduling priority
+	nice,		// stat            standard unix nice level of process
+	rss,		// stat            resident set size from /proc/#/stat (pages)
+	alarm,		// stat            ?
+    // the next 7 members come from /proc/#/statm
+	size,		// statm           total # of pages of memory
+	resident,	// statm           number of resident set (non-swapped) pages (4k)
+	share,		// statm           number of pages of shared (mmap'd) memory
+	trs,		// statm           text resident set size
+	lrs,		// statm           shared-lib resident set size
+	drs,		// statm           data resident set size
+	dt;		// statm           dirty pages
+    unsigned long
+	vm_size,        // status          same as vsize in kb
+	vm_lock,        // status          locked pages in kb
+	vm_rss,         // status          same as rss in kb
+	vm_data,        // status          data size
+	vm_stack,       // status          stack size
+	vm_exe,         // status          executable size
+	vm_lib,         // status          library size (all pages, not just used ones)
+	rtprio,		// stat            real-time priority
+	sched,		// stat            scheduling class
+	vsize,		// stat            number of pages of virtual memory ...
+	rss_rlim,	// stat            resident set size limit?
+	flags,		// stat            kernel flags for the process
+	min_flt,	// stat            number of minor page faults since process start
+	maj_flt,	// stat            number of major page faults since process start
+	cmin_flt,	// stat            cumulative min_flt of process and child processes
+	cmaj_flt;	// stat            cumulative maj_flt of process and child processes
+    char
+	**environ,	// (special)       environment string vector (/proc/#/environ)
+	**cmdline;	// (special)       command line string vector (/proc/#/cmdline)
+    char
+	// Be compatible: Digital allows 16 and NT allows 14 ???
+    	euser[P_G_SZ],	// stat(),status   effective user name
+    	ruser[P_G_SZ],	// status          real user name
+    	suser[P_G_SZ],	// status          saved user name
+    	fuser[P_G_SZ],	// status          filesystem user name
+    	rgroup[P_G_SZ],	// status          real group name
+    	egroup[P_G_SZ],	// status          effective group name
+    	sgroup[P_G_SZ],	// status          saved group name
+    	fgroup[P_G_SZ],	// status          filesystem group name
+    	cmd[16];	// stat,status     basename of executable file in call to exec(2)
+    struct proc_t
+	*ring,		// n/a             thread group ring
+	*next;		// n/a             various library uses
+    int
+	pgrp,		// stat            process group id
+	session,	// stat            session id
+	nlwp,		// stat,status     number of threads, or 0 if no clue
+	tgid,		// (special)       task group ID, the POSIX PID (see also: tid)
+	tty,		// stat            full device number of controlling terminal
+        euid, egid,     // stat(),status   effective
+        ruid, rgid,     // status          real
+        suid, sgid,     // status          saved
+        fuid, fgid,     // status          fs (used for file access only)
+	tpgid,		// stat            terminal process group id
+	exit_signal,	// stat            might not be SIGCHLD
+	processor;      // stat            current (or most recent?) CPU
+} proc_t;
+
+// PROCTAB: data structure holding the persistent information readproc needs
+// from openproc().  The setup is intentionally similar to the dirent interface
+// and other system table interfaces (utmp+wtmp come to mind).
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#define PROCPATHLEN 64  // must hold /proc/2000222000/task/2000222000/cmdline
+
+typedef struct PROCTAB {
+    DIR*	procfs;
+//    char deBug0[64];
+    DIR*	taskdir;  // for threads
+//    char deBug1[64];
+    pid_t	taskdir_user;  // for threads
+    int         did_fake; // used when taskdir is missing
+    int(*finder)(struct PROCTAB *restrict const, proc_t *restrict const);
+    proc_t*(*reader)(struct PROCTAB *restrict const, proc_t *restrict const);
+    int(*taskfinder)(struct PROCTAB *restrict const, const proc_t *restrict const, proc_t *restrict const, char *restrict const);
+    proc_t*(*taskreader)(struct PROCTAB *restrict const, const proc_t *restrict const, proc_t *restrict const, char *restrict const);
+    pid_t*	pids;	// pids of the procs
+    uid_t*	uids;	// uids of procs
+    int		nuid;	// cannot really sentinel-terminate unsigned short[]
+    int         i;  // generic
+    unsigned	flags;
+    unsigned    u;  // generic
+    void *      vp; // generic
+    char        path[PROCPATHLEN];  // must hold /proc/2000222000/task/2000222000/cmdline
+    unsigned pathlen;        // length of string in the above (w/o '\0')
+} PROCTAB;
+
+// initialize a PROCTAB structure holding needed call-to-call persistent data
+extern PROCTAB* openproc(int flags, ... /* pid_t*|uid_t*|dev_t*|char* [, int n] */ );
+
+typedef struct proc_data_t {
+    proc_t **tab;
+    proc_t **proc;
+    proc_t **task;
+    int n;
+    int nproc;
+    int ntask;
+} proc_data_t;
+
+extern proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t *buf), PROCTAB *restrict const PT);
+
+// Convenient wrapper around openproc and readproc to slurp in the whole process
+// table subset satisfying the constraints of flags and the optional PID list.
+// Free allocated memory with exit().  Access via tab[N]->member.  The pointer
+// list is NULL terminated.
+
+extern proc_t** readproctab(int flags, ... /* same as openproc */ );
+
+// clean-up open files, etc from the openproc()
+extern void closeproc(PROCTAB* PT);
+
+// retrieve the next process matching the criteria set by the openproc()
+extern proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict p);
+extern proc_t* readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict t);
+
+// warning: interface may change
+extern int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid);
+
+extern void look_up_our_self(proc_t *p);
+
+// deallocate space allocated by readproc
+
+extern void freeproc(proc_t* p);
+
+//fill out a proc_t for a single task
+extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
+
+// openproc/readproctab:
+//
+// Return PROCTAB* / *proc_t[] or NULL on error ((probably) "/proc" cannot be
+// opened.)  By default readproc will consider all processes as valid to parse
+// and return, but not actually fill in the cmdline, environ, and /proc/#/statm
+// derived memory fields.
+//
+// `flags' (a bitwise-or of PROC_* below) modifies the default behavior.  The
+// "fill" options will cause more of the proc_t to be filled in.  The "filter"
+// options all use the second argument as the pointer to a list of objects:
+// process status', process id's, user id's.  The third
+// argument is the length of the list (currently only used for lists of user
+// id's since uid_t supports no convenient termination sentinel.)
+
+#define PROC_FILLMEM         0x0001 // read statm
+#define PROC_FILLCOM         0x0002 // alloc and fill in `cmdline'
+#define PROC_FILLENV         0x0004 // alloc and fill in `environ'
+#define PROC_FILLUSR         0x0008 // resolve user id number -> user name
+#define PROC_FILLGRP         0x0010 // resolve group id number -> group name
+#define PROC_FILLSTATUS      0x0020 // read status -- currently unconditional
+#define PROC_FILLSTAT        0x0040 // read stat -- currently unconditional
+#define PROC_FILLWCHAN       0x0080 // look up WCHAN name
+#define PROC_FILLARG         0x0100 // alloc and fill in `cmdline'
+
+#define PROC_LOOSE_TASKS     0x0200 // threat threads as if they were processes
+
+// Obsolete, consider only processes with one of the passed:
+#define PROC_PID             0x1000  // process id numbers ( 0   terminated)
+#define PROC_UID             0x4000  // user id numbers    ( length needed )
+
+// it helps to give app code a few spare bits
+#define PROC_SPARE_1     0x01000000
+#define PROC_SPARE_2     0x02000000
+#define PROC_SPARE_3     0x04000000
+#define PROC_SPARE_4     0x08000000
+
+EXTERN_C_END
+#endif
diff --git a/procps-3.2.8/proc/sig.c b/procps-3.2.8/proc/sig.c
new file mode 100644
index 0000000..ea63397
--- /dev/null
+++ b/procps-3.2.8/proc/sig.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright 1998-2003 by Albert Cahalan; all rights resered.
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "sig.h"
+
+/* Linux signals:
+ *
+ * SIGSYS is required by Unix98.
+ * SIGEMT is part of SysV, BSD, and ancient UNIX tradition.
+ *
+ * They are provided by these Linux ports: alpha, mips, sparc, and sparc64.
+ * You get SIGSTKFLT and SIGUNUSED instead on i386, m68k, ppc, and arm.
+ * (this is a Linux & libc bug -- both must be fixed)
+ *
+ * Total garbage: SIGIO SIGINFO SIGIOT SIGLOST SIGCLD
+ *                 (popular ones are handled as aliases)
+ * Nearly garbage: SIGSTKFLT SIGUNUSED (nothing else to fill slots)
+ */
+
+/* Linux 2.3.29 replaces SIGUNUSED with the standard SIGSYS signal */
+#ifndef SIGSYS
+#  warning Standards require that <signal.h> define SIGSYS
+#  define SIGSYS SIGUNUSED
+#endif
+
+/* If we see both, it is likely SIGSTKFLT (junk) was replaced. */
+#ifdef SIGEMT
+#  undef SIGSTKFLT
+#endif
+
+#ifndef SIGRTMIN
+#  warning Standards require that <signal.h> define SIGRTMIN; assuming 32
+#  define SIGRTMIN 32
+#endif
+
+/* It seems the SPARC libc does not know the kernel supports SIGPWR. */
+#ifndef SIGPWR
+#  warning Your header files lack SIGPWR. (assuming it is number 29)
+#  define SIGPWR 29
+#endif
+
+typedef struct mapstruct {
+  const char *name;
+  int num;
+} mapstruct;
+
+
+static const mapstruct sigtable[] = {
+  {"ABRT",   SIGABRT},  /* IOT */
+  {"ALRM",   SIGALRM},
+  {"BUS",    SIGBUS},
+  {"CHLD",   SIGCHLD},  /* CLD */
+  {"CONT",   SIGCONT},
+#ifdef SIGEMT
+  {"EMT",    SIGEMT},
+#endif
+  {"FPE",    SIGFPE},
+  {"HUP",    SIGHUP},
+  {"ILL",    SIGILL},
+  {"INT",    SIGINT},
+  {"KILL",   SIGKILL},
+  {"PIPE",   SIGPIPE},
+  {"POLL",   SIGPOLL},  /* IO */
+  {"PROF",   SIGPROF},
+  {"PWR",    SIGPWR},
+  {"QUIT",   SIGQUIT},
+  {"SEGV",   SIGSEGV},
+#ifdef SIGSTKFLT
+  {"STKFLT", SIGSTKFLT},
+#endif
+  {"STOP",   SIGSTOP},
+  {"SYS",    SIGSYS},   /* UNUSED */
+  {"TERM",   SIGTERM},
+  {"TRAP",   SIGTRAP},
+  {"TSTP",   SIGTSTP},
+  {"TTIN",   SIGTTIN},
+  {"TTOU",   SIGTTOU},
+  {"URG",    SIGURG},
+  {"USR1",   SIGUSR1},
+  {"USR2",   SIGUSR2},
+  {"VTALRM", SIGVTALRM},
+  {"WINCH",  SIGWINCH},
+  {"XCPU",   SIGXCPU},
+  {"XFSZ",   SIGXFSZ}
+};
+
+static const int number_of_signals = sizeof(sigtable)/sizeof(mapstruct);
+
+static int compare_signal_names(const void *a, const void *b){
+  return strcasecmp( ((const mapstruct*)a)->name, ((const mapstruct*)b)->name );
+}
+
+/* return -1 on failure */
+int signal_name_to_number(const char *restrict name){
+  long val;
+  int offset;
+
+  /* clean up name */
+  if(!strncasecmp(name,"SIG",3)) name += 3;
+
+  if(!strcasecmp(name,"CLD")) return SIGCHLD;
+  if(!strcasecmp(name,"IO"))  return SIGPOLL;
+  if(!strcasecmp(name,"IOT")) return SIGABRT;
+
+  /* search the table */
+  {
+    const mapstruct ms = {name,0};
+    const mapstruct *restrict const ptr = bsearch(
+      &ms,
+      sigtable,
+      number_of_signals,
+      sizeof(mapstruct),
+      compare_signal_names
+    );
+    if(ptr) return ptr->num;
+  }
+
+  if(!strcasecmp(name,"RTMIN")) return SIGRTMIN;
+  if(!strcasecmp(name,"EXIT"))  return 0;
+  if(!strcasecmp(name,"NULL"))  return 0;
+
+  offset = 0;
+  if(!strncasecmp(name,"RTMIN+",6)){
+    name += 6;
+    offset = SIGRTMIN;
+  }
+
+  /* not found, so try as a number */
+  {
+    char *endp;
+    val = strtol(name,&endp,10);
+    if(*endp || endp==name) return -1; /* not valid */
+  }
+  if(val+SIGRTMIN>127) return -1; /* not valid */
+  return val+offset;
+}
+
+const char *signal_number_to_name(int signo){
+  static char buf[32];
+  int n = number_of_signals;
+  signo &= 0x7f; /* need to process exit values too */
+  while(n--){
+    if(sigtable[n].num==signo) return sigtable[n].name;
+  }
+  if(signo == SIGRTMIN) return "RTMIN";
+  if(signo) sprintf(buf, "RTMIN+%d", signo-SIGRTMIN);
+  else      strcpy(buf,"0");  /* AIX has NULL; Solaris has EXIT */
+  return buf;
+}
+
+int print_given_signals(int argc, const char *restrict const *restrict argv, int max_line){
+  char buf[1280]; /* 128 signals, "RTMIN+xx" is largest */
+  int ret = 0;  /* to be used as exit code by caller */
+  int place = 0; /* position on this line */
+  int amt;
+  if(argc > 128) return 1;
+  while(argc--){
+    char tmpbuf[16];
+    const char *restrict const txt = *argv;
+    if(*txt >= '0' && *txt <= '9'){
+      long val;
+      char *endp;
+      val = strtol(txt,&endp,10);
+      if(*endp){
+        fprintf(stderr, "Signal \"%s\" not known.\n", txt);
+        ret = 1;
+        goto end;
+      }
+      amt = sprintf(tmpbuf, "%s", signal_number_to_name(val));
+    }else{
+      int sno;
+      sno = signal_name_to_number(txt);
+      if(sno == -1){
+        fprintf(stderr, "Signal \"%s\" not known.\n", txt);
+        ret = 1;
+        goto end;
+      }
+      amt = sprintf(tmpbuf, "%d", sno);
+    }
+
+    if(!place){
+      strcpy(buf,tmpbuf);
+      place = amt;
+      goto end;
+    }
+    if(amt+place+1 > max_line){
+      printf("%s\n", buf);
+      strcpy(buf,tmpbuf);
+      place = amt;
+      goto end;
+    }
+    sprintf(buf+place, " %s", tmpbuf);
+    place += amt+1;
+end:
+    argv++;
+  }
+  if(place) printf("%s\n", buf);
+  return ret;
+}
+
+void pretty_print_signals(void){
+  int i = 0;
+  while(++i <= number_of_signals){
+    int n;
+    n = printf("%2d %s", i, signal_number_to_name(i));
+    if(i%7) printf("           \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + n);
+    else printf("\n");
+  }
+  if((i-1)%7) printf("\n");
+}
+
+void unix_print_signals(void){
+  int pos = 0;
+  int i = 0;
+  while(++i <= number_of_signals){
+    if(i-1) printf("%c", (pos>73)?(pos=0,'\n'):(pos++,' ') );
+    pos += printf("%s", signal_number_to_name(i));
+  }
+  printf("\n");
+}
+
+/* sanity check */
+static int init_signal_list(void) __attribute__((constructor));
+static int init_signal_list(void){
+  if(number_of_signals != 31){
+    fprintf(stderr, "WARNING: %d signals -- adjust and recompile.\n", number_of_signals);
+  }
+  return 0;
+}
diff --git a/procps-3.2.8/proc/sig.h b/procps-3.2.8/proc/sig.h
new file mode 100644
index 0000000..ee850a2
--- /dev/null
+++ b/procps-3.2.8/proc/sig.h
@@ -0,0 +1,30 @@
+#ifndef PROC_SIG_H
+#define PROC_SIG_H
+/*
+ * Copyright 1998-2003 by Albert Cahalan; all rights resered.
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+
+#include "procps.h"
+
+EXTERN_C_BEGIN
+
+/* return -1 on failure */
+extern int signal_name_to_number(const char *restrict name);
+
+extern const char *signal_number_to_name(int signo);
+
+extern int print_given_signals(int argc, const char *restrict const *restrict argv, int max_line);
+
+extern void pretty_print_signals(void);
+
+extern void unix_print_signals(void);
+
+EXTERN_C_END
+#endif
diff --git a/procps-3.2.8/proc/slab.c b/procps-3.2.8/proc/slab.c
new file mode 100644
index 0000000..60c5696
--- /dev/null
+++ b/procps-3.2.8/proc/slab.c
@@ -0,0 +1,337 @@
+/* 
+ * slab.c - slab related functions for libproc
+ *
+ * Chris Rivera <cmrivera@ufl.edu>
+ * Robert Love <rml@tech9.net>
+ *
+ * This program is licensed under the GNU Library General Public License, v2
+ *
+ * Copyright (C) 2003 Chris Rivera
+ * Copyright 2004, Albert Cahalan
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <ctype.h>
+
+#include "slab.h"
+#include "procps.h"
+
+#define SLABINFO_LINE_LEN	2048
+#define SLABINFO_VER_LEN	100
+#define SLABINFO_FILE		"/proc/slabinfo"
+
+static struct slab_info *free_index;
+
+/*
+ * get_slabnode - allocate slab_info structures using a free list
+ *
+ * In the fast path, we simply return a node off the free list.  In the slow
+ * list, we malloc() a new node.  The free list is never automatically reaped,
+ * both for simplicity and because the number of slab caches is fairly
+ * constant.
+ */
+static struct slab_info *get_slabnode(void)
+{
+	struct slab_info *node;
+
+	if (free_index) {
+		node = free_index;
+		free_index = free_index->next;
+	} else {
+		node = malloc(sizeof(struct slab_info));
+		if (!node)
+			perror("malloc");
+	}
+
+	return node;
+}
+
+/*
+ * slab_badname_detect - return true if current slab was declared with
+ *                       whitespaces for instance 
+ *			 FIXME :Other cases ?
+ */
+
+static int slab_badname_detect(const char *restrict buffer)
+{
+	int numberarea=0;
+	while (*buffer){
+		if((*buffer)==' ')
+			numberarea=1;
+		if(isalpha(*buffer)&&numberarea)	
+			return 1;
+		buffer++;	
+	}
+	return 0;
+}
+
+/*
+ * put_slabinfo - return all allocated nodes to the free list
+ */
+void put_slabinfo(struct slab_info *head)
+{
+	free_index = head;
+}
+
+/*
+ * free_slabinfo - deallocate the memory associated with each node in the
+ * slab_info linked list
+ */
+void free_slabinfo(struct slab_info *list)
+{
+	while (list) {
+		struct slab_info *temp = list->next;
+		free(list);
+		list = temp;
+	}
+}
+
+// parse_slabinfo20 - actual parse routine for slabinfo 2.x (2.6 kernels)
+// Note: difference between 2.0 and 2.1 is in the ": globalstat" part where version 2.1 
+// has extra column <nodeallocs>. We don't use ": globalstat" part in both versions.
+//
+// Formats (we don't use "statistics" extensions)
+//
+//  slabinfo - version: 2.1
+//  # name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> \
+//  : tunables <batchcount> <limit> <sharedfactor> \
+//  : slabdata <active_slabs> <num_slabs> <sharedavail>
+//
+//  slabinfo - version: 2.1 (statistics)
+//  # name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> \
+//  : tunables <batchcount> <limit> <sharedfactor> \
+//  : slabdata <active_slabs> <num_slabs> <sharedavail> \
+//  : globalstat <listallocs> <maxobjs> <grown> <reaped> <error> <maxfreeable> <freelimit> <nodeallocs> \
+//  : cpustat <allochit> <allocmiss> <freehit> <freemiss>
+//             
+//  slabinfo - version: 2.0
+//  # name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> \
+//  : tunables <batchcount> <limit> <sharedfactor> \
+//  : slabdata <active_slabs> <num_slabs> <sharedavail>
+//
+//  slabinfo - version: 2.0 (statistics)
+//  # name            <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> \
+//  : tunables <batchcount> <limit> <sharedfactor> \
+//  : slabdata <active_slabs> <num_slabs> <sharedavail> \
+//  : globalstat <listallocs> <maxobjs> <grown> <reaped> <error> <maxfreeable> <freelimit> \
+//  : cpustat <allochit> <allocmiss> <freehit> <freemiss>
+static int parse_slabinfo20(struct slab_info **list, struct slab_stat *stats,
+				FILE *f)
+{
+	struct slab_info *curr = NULL, *prev = NULL;
+	char buffer[SLABINFO_LINE_LEN];
+	int entries = 0;
+	int page_size = getpagesize();
+
+	stats->min_obj_size = INT_MAX;
+	stats->max_obj_size = 0;
+
+	while (fgets(buffer, SLABINFO_LINE_LEN, f)) {
+		int assigned;
+
+		if (buffer[0] == '#')
+			continue;
+	
+		curr = get_slabnode();
+		if (!curr)
+			break;
+
+		if (entries++ == 0)
+			*list = curr;
+		else
+			prev->next = curr;
+
+		assigned = sscanf(buffer, "%" STRINGIFY(SLAB_INFO_NAME_LEN)
+				"s %d %d %d %d %d : tunables %*d %*d %*d : \
+				slabdata %d %d %*d", curr->name, 
+				&curr->nr_active_objs, &curr->nr_objs, 
+				&curr->obj_size, &curr->objs_per_slab,
+				&curr->pages_per_slab, &curr->nr_active_slabs,
+				&curr->nr_slabs);
+
+		if (assigned < 8) {
+			fprintf(stderr, "unrecognizable data in slabinfo!\n");
+			curr = NULL;
+			break;
+		}
+
+		if (curr->obj_size < stats->min_obj_size)
+			stats->min_obj_size = curr->obj_size;
+		if (curr->obj_size > stats->max_obj_size)
+			stats->max_obj_size = curr->obj_size;
+
+		curr->cache_size = (unsigned long)curr->nr_slabs * curr->pages_per_slab * page_size;
+
+		if (curr->nr_objs) {
+			curr->use = 100 * curr->nr_active_objs / curr->nr_objs;
+			stats->nr_active_caches++;
+		} else
+			curr->use = 0;
+
+		stats->nr_objs += curr->nr_objs;
+		stats->nr_active_objs += curr->nr_active_objs;
+		stats->total_size += (unsigned long)curr->nr_objs * curr->obj_size;
+		stats->active_size += (unsigned long)curr->nr_active_objs * curr->obj_size;
+		stats->nr_pages += curr->nr_slabs * curr->pages_per_slab;
+		stats->nr_slabs += curr->nr_slabs;
+		stats->nr_active_slabs += curr->nr_active_slabs;
+
+		prev = curr;
+	}
+
+	if (!curr) {
+		fprintf(stderr, "\rerror reading slabinfo!\n");
+		return 1;
+	}
+
+	curr->next = NULL;
+	stats->nr_caches = entries;
+	if (stats->nr_objs)
+		stats->avg_obj_size = stats->total_size / stats->nr_objs;
+
+	return 0;
+}
+
+/*
+ * parse_slabinfo11 - actual parsing routine for slabinfo 1.1 (2.4 kernels)
+ */
+static int parse_slabinfo11(struct slab_info **list, struct slab_stat *stats,
+				FILE *f)
+{
+	struct slab_info *curr = NULL, *prev = NULL;
+	char buffer[SLABINFO_LINE_LEN];
+	int entries = 0;
+	int page_size = getpagesize();
+
+	stats->min_obj_size = INT_MAX;
+	stats->max_obj_size = 0;
+
+	while (fgets(buffer, SLABINFO_LINE_LEN, f)) {
+		int assigned;
+
+		curr = get_slabnode();
+		if (!curr)
+			break;
+
+		if (entries++ == 0)
+			*list = curr;
+		else
+			prev->next = curr;
+
+		assigned = sscanf(buffer, "%" STRINGIFY(SLAB_INFO_NAME_LEN)
+				"s %d %d %d %d %d %d",
+				curr->name, &curr->nr_active_objs,
+				&curr->nr_objs, &curr->obj_size,
+				&curr->nr_active_slabs, &curr->nr_slabs,
+				&curr->pages_per_slab);
+
+		if (assigned < 6) {
+			fprintf(stderr, "unrecognizable data in  your slabinfo version 1.1\n\r");
+			if(slab_badname_detect(buffer))
+				fprintf(stderr, "Found an error in cache name at line %s\n", buffer); 
+			curr = NULL;
+			break;
+		}
+
+		if (curr->obj_size < stats->min_obj_size)
+			stats->min_obj_size = curr->obj_size;
+		if (curr->obj_size > stats->max_obj_size)
+			stats->max_obj_size = curr->obj_size;
+
+		curr->cache_size = (unsigned long)curr->nr_slabs * curr->pages_per_slab * page_size;
+
+		if (curr->nr_objs) {
+			curr->use = 100 * curr->nr_active_objs / curr->nr_objs;
+			stats->nr_active_caches++;
+		} else
+			curr->use = 0;
+
+		if (curr->obj_size)
+			curr->objs_per_slab = curr->pages_per_slab *
+					page_size / curr->obj_size;		
+
+		stats->nr_objs += curr->nr_objs;
+		stats->nr_active_objs += curr->nr_active_objs;
+		stats->total_size += (unsigned long)curr->nr_objs * curr->obj_size;
+		stats->active_size += (unsigned long)curr->nr_active_objs * curr->obj_size;
+		stats->nr_pages += curr->nr_slabs * curr->pages_per_slab;
+		stats->nr_slabs += curr->nr_slabs;
+		stats->nr_active_slabs += curr->nr_active_slabs;
+
+		prev = curr;
+	}
+
+	if (!curr) {
+		fprintf(stderr, "\rerror reading slabinfo!\n");
+		return 1;
+	}
+
+	curr->next = NULL;
+	stats->nr_caches = entries;
+	if (stats->nr_objs)
+		stats->avg_obj_size = stats->total_size / stats->nr_objs;
+
+	return 0;
+}
+
+/*
+ * parse_slabinfo10 - actual parsing routine for slabinfo 1.0 (2.2 kernels)
+ *
+ * Not yet implemented.  Please feel free.
+ */
+static int parse_slabinfo10(struct slab_info **list, struct slab_stat *stats,
+				FILE *f)
+{
+	(void) list, (void) stats, (void) f;
+	fprintf(stderr, "slabinfo version 1.0 not yet supported\n");
+	return 1;
+}
+
+/*
+ * slabinfo - parse the system's slabinfo and fill out both a linked list of
+ * slab_info structures and the slab_stat structure
+ *
+ * The function returns zero on success, in which case 'list' and 'stats' are
+ * valid.  Nonzero is returned on failure and the state of 'list' and 'stats'
+ * are undefined.
+ */
+int get_slabinfo(struct slab_info **list, struct slab_stat *stats)
+{
+	FILE *slabfile;
+	char buffer[SLABINFO_VER_LEN];
+	int major, minor, ret = 0;
+
+	slabfile = fopen(SLABINFO_FILE, "r");
+	if (!slabfile) {
+		perror("fopen " SLABINFO_FILE);
+		return 1;
+	}
+
+	if (!fgets(buffer, SLABINFO_VER_LEN, slabfile)) {
+		fprintf(stderr, "cannot read from slabinfo\n");
+		return 1;
+	}
+
+	if (sscanf(buffer, "slabinfo - version: %d.%d", &major, &minor) != 2) {
+		fprintf(stderr, "not the good old slabinfo we know\n");
+		return 1;
+	}
+
+	if (major == 2)
+		ret = parse_slabinfo20(list, stats, slabfile);
+	else if (major == 1 && minor == 1)
+		ret = parse_slabinfo11(list, stats, slabfile);
+	else if (major == 1 && minor == 0)
+		ret = parse_slabinfo10(list, stats, slabfile);
+	else {
+		fprintf(stderr, "unrecognizable slabinfo version\n");
+		return 1;
+	}
+
+	fclose(slabfile);
+
+	return ret;
+}
diff --git a/procps-3.2.8/proc/slab.h b/procps-3.2.8/proc/slab.h
new file mode 100644
index 0000000..ea17ddc
--- /dev/null
+++ b/procps-3.2.8/proc/slab.h
@@ -0,0 +1,39 @@
+#ifndef _PROC_SLAB_H
+#define _PROC_SLAB_H
+
+#define SLAB_INFO_NAME_LEN      64
+
+struct slab_info {
+	char name[SLAB_INFO_NAME_LEN];  /* name of this cache */
+	struct slab_info *next;
+	unsigned long cache_size;       /* size of entire cache */
+	unsigned nr_objs;               /* number of objects in this cache */
+	unsigned nr_active_objs;        /* number of active objects */
+	unsigned obj_size;              /* size of each object */
+	unsigned objs_per_slab;         /* number of objects per slab */
+	unsigned pages_per_slab;        /* number of pages per slab */
+	unsigned nr_slabs;              /* number of slabs in this cache */
+	unsigned nr_active_slabs;       /* number of active slabs */
+	unsigned use;                   /* percent full: total / active */
+};
+
+struct slab_stat {
+	unsigned long total_size;       /* size of all objects */
+	unsigned long active_size;      /* size of all active objects */
+	unsigned nr_objs;               /* number of objects, among all caches */
+	unsigned nr_active_objs;        /* number of active objects, among all caches */
+	unsigned nr_pages;              /* number of pages consumed by all objects */
+	unsigned nr_slabs;              /* number of slabs, among all caches */
+	unsigned nr_active_slabs;       /* number of active slabs, among all caches */
+	unsigned nr_caches;             /* number of caches */
+	unsigned nr_active_caches;      /* number of active caches */
+	unsigned avg_obj_size;          /* average object size */
+	unsigned min_obj_size;          /* size of smallest object */
+	unsigned max_obj_size;          /* size of largest object */
+};
+
+extern void put_slabinfo(struct slab_info *);
+extern void free_slabinfo(struct slab_info *);
+extern int get_slabinfo(struct slab_info **, struct slab_stat *);
+
+#endif /* _PROC_SLAB_H */
diff --git a/procps-3.2.8/proc/smaps.c b/procps-3.2.8/proc/smaps.c
new file mode 100644
index 0000000..17789a1
--- /dev/null
+++ b/procps-3.2.8/proc/smaps.c
@@ -0,0 +1,171 @@
+#if 0
+#include "procps.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "procps.h"
+
+struct smap_entry {
+	unsigned KLONG start;
+	unsigned KLONG beyond;
+	long long offset;
+	char flags[8];
+	unsigned dev_major;
+	unsigned dev_minor;
+	unsigned long long inode;
+
+	unsigned long rss;
+	unsigned long pss;
+	unsigned long sclean;
+	unsigned long sdirty;
+	unsigned long pclean;
+	unsigned long pdirty;
+	unsigned long ref;
+	unsigned long swap;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// This code will surely make normal programmers cry. I need speed though,
+// and /proc/*/smaps should make anybody cry. (WTF kind of brain damage...?)
+
+struct smap_summary {
+	unsigned long size;
+	unsigned long rss;
+	unsigned long pss;
+	unsigned long sclean;
+	unsigned long sdirty;
+	unsigned long pclean;
+	unsigned long pdirty;
+	unsigned long ref;
+	unsigned long swap;
+};
+
+struct ssjt {
+	char str[16];
+	int len;
+	int offset;
+};
+
+#define JTE(o,x) {#x,sizeof(#x)-1,o}
+
+void get_smap_sums(struct smap_summary *restrict ss, const char *restrict const filename){
+	static struct ssjt table[] = {
+		JTE(-1,default),
+		JTE( 1,Rss),
+		JTE(-1,default),
+		JTE( 2,Pss),
+		JTE( 8,Swap),
+		JTE( 5,Private_Clean),
+		JTE( 6,Private_Dirty),
+		JTE(-1,default),
+		JTE( 7,Referenced),
+		JTE(-1,default),
+		JTE( 0,Size),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default), // KernelPageSize would go here
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE( 4,Shared_Dirty),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE( 3,Shared_Clean),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default),
+		JTE(-1,default),
+	};
+	char buf[20480];
+	int p1 = 0;
+	int p2 = 0;
+	memset(ss,0,sizeof *ss);
+	int fd = open(filename,O_RDONLY);
+	if(fd==-1)
+		return;
+	for(;;){
+		char *nlp = memchr(buf+p1,'\n',p2-p1);
+		if(!nlp){
+			if(p1){
+				// the memmove should never do anything, because the
+				// kernel seems to give us the greatest number of
+				// complete lines of text that fit in a single page
+				// (and thus p2-p1 is zero)
+				memmove(buf,buf+p1,p2-p1);
+				p2 -= p1;
+				p1 = 0;
+			}
+			ssize_t rb = read(fd,buf+p1,sizeof buf - p1);
+			if(rb < 1)
+				break;
+			p2 += rb;
+			nlp = memchr(buf+p1,'\n',p2-p1);
+			if(!nlp)
+				break;
+		}
+		char *s = buf+p1;
+		int len = nlp-s;
+		p1 += len+1;
+		if(len<27)
+			continue;
+//printf("j      <%13.13s>\n",s);
+		if(s[0]<'A' || s[0]>'Z')
+			continue;
+		unsigned hash = ( (s[8]&15) + (s[1]&15) ) ^ (s[0]&3);
+		hash &= 31;
+//printf("x   %2d <%13.13s>\n",hash,s);
+		if(s[table[hash].len] != ':')
+			continue;
+//printf("y   %2d <%13.13s>\n",hash,s);
+		if(memcmp(table[hash].str,s,table[hash].len))
+			continue;
+//printf("z   %2d <%13.13s>\n",hash,s);
+		s += table[hash].len;
+		while(*++s==' ')
+			;
+		unsigned long ul = 0;
+		for(;;){
+			char c = *s++;
+			if(c != ' '){
+				ul *= 10;
+				ul += c-'0';
+				continue;
+			}
+			break;
+		}
+//		if(table[hash].offset == 2)
+//			printf("Pss:%20lu kB\n",ul);
+		unsigned long *ulp = &ss->size + table[hash].offset;
+		*ulp += ul;
+//		memcpy(ss+table[hash].offset*sizeof(unsigned long), &ul, sizeof(unsigned long));
+	}
+	close(fd);
+}
+
+int main(int argc, char *argv[]){
+	struct smap_summary ss;
+	get_smap_sums(&ss, argv[1]);
+	printf("%9lu\n",ss.size);
+	printf("%9lu\n",ss.rss);
+	printf("%9lu\n",ss.pss);
+	printf("%9lu\n",ss.sclean);
+	printf("%9lu\n",ss.sdirty);
+	printf("%9lu\n",ss.pclean);
+	printf("%9lu\n",ss.pdirty);
+	printf("%9lu\n",ss.ref);
+	printf("%9lu\n",ss.swap);
+	return 0;
+}
+#endif
diff --git a/procps-3.2.8/proc/sysinfo.c b/procps-3.2.8/proc/sysinfo.c
new file mode 100644
index 0000000..b56df04
--- /dev/null
+++ b/procps-3.2.8/proc/sysinfo.c
@@ -0,0 +1,914 @@
+// Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com
+// Copyright 1998-2003 Albert Cahalan
+//
+// This file is placed under the conditions of the GNU Library
+// General Public License, version 2, or any later version.
+// See file COPYING for information on distribution conditions.
+//
+// File for parsing top-level /proc entities. */
+//
+// June 2003, Fabian Frederick, disk and slab info
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <locale.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include "version.h"
+#include "sysinfo.h" /* include self to verify prototypes */
+
+#ifndef HZ
+#include <netinet/in.h>  /* htons */
+#endif
+
+long smp_num_cpus;     /* number of CPUs */
+
+#define BAD_OPEN_MESSAGE					\
+"Error: /proc must be mounted\n"				\
+"  To mount /proc at boot you need an /etc/fstab line like:\n"	\
+"      /proc   /proc   proc    defaults\n"			\
+"  In the meantime, run \"mount /proc /proc -t proc\"\n"
+
+#define STAT_FILE    "/proc/stat"
+static int stat_fd = -1;
+#define UPTIME_FILE  "/proc/uptime"
+static int uptime_fd = -1;
+#define LOADAVG_FILE "/proc/loadavg"
+static int loadavg_fd = -1;
+#define MEMINFO_FILE "/proc/meminfo"
+static int meminfo_fd = -1;
+#define VMINFO_FILE "/proc/vmstat"
+static int vminfo_fd = -1;
+
+// As of 2.6.24 /proc/meminfo seems to need 888 on 64-bit,
+// and would need 1258 if the obsolete fields were there.
+static char buf[2048];
+
+/* This macro opens filename only if necessary and seeks to 0 so
+ * that successive calls to the functions are more efficient.
+ * It also reads the current contents of the file into the global buf.
+ */
+#define FILE_TO_BUF(filename, fd) do{				\
+    static int local_n;						\
+    if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) {	\
+	fputs(BAD_OPEN_MESSAGE, stderr);			\
+	fflush(NULL);						\
+	_exit(102);						\
+    }								\
+    lseek(fd, 0L, SEEK_SET);					\
+    if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) {	\
+	perror(filename);					\
+	fflush(NULL);						\
+	_exit(103);						\
+    }								\
+    buf[local_n] = '\0';					\
+}while(0)
+
+/* evals 'x' twice */
+#define SET_IF_DESIRED(x,y) do{  if(x) *(x) = (y); }while(0)
+
+
+/***********************************************************************/
+int uptime(double *restrict uptime_secs, double *restrict idle_secs) {
+    double up=0, idle=0;
+    char *restrict savelocale;
+
+    FILE_TO_BUF(UPTIME_FILE,uptime_fd);
+    savelocale = setlocale(LC_NUMERIC, NULL);
+    setlocale(LC_NUMERIC,"C");
+    if (sscanf(buf, "%lf %lf", &up, &idle) < 2) {
+        setlocale(LC_NUMERIC,savelocale);
+        fputs("bad data in " UPTIME_FILE "\n", stderr);
+	    return 0;
+    }
+    setlocale(LC_NUMERIC,savelocale);
+    SET_IF_DESIRED(uptime_secs, up);
+    SET_IF_DESIRED(idle_secs, idle);
+    return up;	/* assume never be zero seconds in practice */
+}
+
+/***********************************************************************
+ * Some values in /proc are expressed in units of 1/HZ seconds, where HZ
+ * is the kernel clock tick rate. One of these units is called a jiffy.
+ * The HZ value used in the kernel may vary according to hacker desire.
+ * According to Linus Torvalds, this is not true. He considers the values
+ * in /proc as being in architecture-dependant units that have no relation
+ * to the kernel clock tick rate. Examination of the kernel source code
+ * reveals that opinion as wishful thinking.
+ *
+ * In any case, we need the HZ constant as used in /proc. (the real HZ value
+ * may differ, but we don't care) There are several ways we could get HZ:
+ *
+ * 1. Include the kernel header file. If it changes, recompile this library.
+ * 2. Use the sysconf() function. When HZ changes, recompile the C library!
+ * 3. Ask the kernel. This is obviously correct...
+ *
+ * Linus Torvalds won't let us ask the kernel, because he thinks we should
+ * not know the HZ value. Oh well, we don't have to listen to him.
+ * Someone smuggled out the HZ value. :-)
+ *
+ * This code should work fine, even if Linus fixes the kernel to match his
+ * stated behavior. The code only fails in case of a partial conversion.
+ *
+ * Recent update: on some architectures, the 2.4 kernel provides an
+ * ELF note to indicate HZ. This may be for ARM or user-mode Linux
+ * support. This ought to be investigated. Note that sysconf() is still
+ * unreliable, because it doesn't return an error code when it is
+ * used with a kernel that doesn't support the ELF note. On some other
+ * architectures there may be a system call or sysctl() that will work.
+ */
+
+unsigned long long Hertz;
+
+static void old_Hertz_hack(void){
+  unsigned long long user_j, nice_j, sys_j, other_j;  /* jiffies (clock ticks) */
+  double up_1, up_2, seconds;
+  unsigned long long jiffies;
+  unsigned h;
+  char *restrict savelocale;
+
+  savelocale = setlocale(LC_NUMERIC, NULL);
+  setlocale(LC_NUMERIC, "C");
+  do{
+    FILE_TO_BUF(UPTIME_FILE,uptime_fd);  sscanf(buf, "%lf", &up_1);
+    /* uptime(&up_1, NULL); */
+    FILE_TO_BUF(STAT_FILE,stat_fd);
+    sscanf(buf, "cpu %Lu %Lu %Lu %Lu", &user_j, &nice_j, &sys_j, &other_j);
+    FILE_TO_BUF(UPTIME_FILE,uptime_fd);  sscanf(buf, "%lf", &up_2);
+    /* uptime(&up_2, NULL); */
+  } while((long long)( (up_2-up_1)*1000.0/up_1 )); /* want under 0.1% error */
+  setlocale(LC_NUMERIC, savelocale);
+  jiffies = user_j + nice_j + sys_j + other_j;
+  seconds = (up_1 + up_2) / 2;
+  h = (unsigned)( (double)jiffies/seconds/smp_num_cpus );
+  /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
+  switch(h){
+  case    9 ...   11 :  Hertz =   10; break; /* S/390 (sometimes) */
+  case   18 ...   22 :  Hertz =   20; break; /* user-mode Linux */
+  case   30 ...   34 :  Hertz =   32; break; /* ia64 emulator */
+  case   48 ...   52 :  Hertz =   50; break;
+  case   58 ...   61 :  Hertz =   60; break;
+  case   62 ...   65 :  Hertz =   64; break; /* StrongARM /Shark */
+  case   95 ...  105 :  Hertz =  100; break; /* normal Linux */
+  case  124 ...  132 :  Hertz =  128; break; /* MIPS, ARM */
+  case  195 ...  204 :  Hertz =  200; break; /* normal << 1 */
+  case  247 ...  252 :  Hertz =  250; break;
+  case  253 ...  260 :  Hertz =  256; break;
+  case  393 ...  408 :  Hertz =  400; break; /* normal << 2 */
+  case  790 ...  808 :  Hertz =  800; break; /* normal << 3 */
+  case  990 ... 1010 :  Hertz = 1000; break; /* ARM */
+  case 1015 ... 1035 :  Hertz = 1024; break; /* Alpha, ia64 */
+  case 1180 ... 1220 :  Hertz = 1200; break; /* Alpha */
+  default:
+#ifdef HZ
+    Hertz = (unsigned long long)HZ;    /* <asm/param.h> */
+#else
+    /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 100. */
+    Hertz = (sizeof(long)==sizeof(int) || htons(999)==999) ? 100UL : 1024UL;
+#endif
+    // There's a bug that causes this warning. We just comment it out
+    // for F1 build.
+    //fprintf(stderr, "Unknown HZ value! (%d) Assume %Ld.\n", h, Hertz);
+  }
+}
+
+// same as:   euid != uid || egid != gid
+#ifndef AT_SECURE
+#define AT_SECURE      23     // secure mode boolean (true if setuid, etc.)
+#endif
+
+#ifndef AT_CLKTCK
+#define AT_CLKTCK       17    // frequency of times()
+#endif
+
+#define NOTE_NOT_FOUND 42
+
+//extern char** environ;
+
+/* for ELF executables, notes are pushed before environment and args */
+static unsigned long find_elf_note(unsigned long findme){
+  unsigned long *ep = (unsigned long *)environ;
+  while(*ep++);
+  while(*ep){
+    if(ep[0]==findme) return ep[1];
+    ep+=2;
+  }
+  return NOTE_NOT_FOUND;
+}
+
+int have_privs;
+
+static int check_for_privs(void){
+  unsigned long rc = find_elf_note(AT_SECURE);
+  if(rc==NOTE_NOT_FOUND){
+    // not valid to run this code after UID or GID change!
+    // (if needed, may use AT_UID and friends instead)
+    rc = geteuid() != getuid() || getegid() != getgid();
+  }
+  return !!rc;
+}
+
+static void init_libproc(void) __attribute__((constructor));
+static void init_libproc(void){
+  have_privs = check_for_privs();
+  // ought to count CPUs in /proc/stat instead of relying
+  // on glibc, which foolishly tries to parse /proc/cpuinfo
+  //
+  // SourceForge has an old Alpha running Linux 2.2.20 that
+  // appears to have a non-SMP kernel on a 2-way SMP box.
+  // _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512
+  // _SC_NPROCESSORS_ONLN returns 1, which should work OK
+  smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+  if(smp_num_cpus<1) smp_num_cpus=1; /* SPARC glibc is buggy */
+
+  if(linux_version_code > LINUX_VERSION(2, 4, 0)){ 
+    Hertz = find_elf_note(AT_CLKTCK);
+    if(Hertz!=NOTE_NOT_FOUND) return;
+    fputs("2.4+ kernel w/o ELF notes? -- report this\n", stderr);
+  }
+  old_Hertz_hack();
+}
+
+#if 0
+/***********************************************************************
+ * The /proc filesystem calculates idle=jiffies-(user+nice+sys) and we
+ * recover jiffies by adding up the 4 or 5 numbers we are given. SMP kernels
+ * (as of pre-2.4 era) can report idle time going backwards, perhaps due
+ * to non-atomic reads and updates. There is no locking for these values.
+ */
+#ifndef NAN
+#define NAN (-0.0)
+#endif
+#define JT unsigned long long
+void eight_cpu_numbers(double *restrict uret, double *restrict nret, double *restrict sret, double *restrict iret, double *restrict wret, double *restrict xret, double *restrict yret, double *restrict zret){
+    double tmp_u, tmp_n, tmp_s, tmp_i, tmp_w, tmp_x, tmp_y, tmp_z;
+    double scale;  /* scale values to % */
+    static JT old_u, old_n, old_s, old_i, old_w, old_x, old_y, old_z;
+    JT new_u, new_n, new_s, new_i, new_w, new_x, new_y, new_z;
+    JT ticks_past; /* avoid div-by-0 by not calling too often :-( */
+
+    tmp_w = 0.0;
+    new_w = 0;
+    tmp_x = 0.0;
+    new_x = 0;
+    tmp_y = 0.0;
+    new_y = 0;
+    tmp_z = 0.0;
+    new_z = 0;
+ 
+    FILE_TO_BUF(STAT_FILE,stat_fd);
+    sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &new_u, &new_n, &new_s, &new_i, &new_w, &new_x, &new_y, &new_z);
+    ticks_past = (new_u+new_n+new_s+new_i+new_w+new_x+new_y+new_z)-(old_u+old_n+old_s+old_i+old_w+old_x+old_y+old_z);
+    if(ticks_past){
+      scale = 100.0 / (double)ticks_past;
+      tmp_u = ( (double)new_u - (double)old_u ) * scale;
+      tmp_n = ( (double)new_n - (double)old_n ) * scale;
+      tmp_s = ( (double)new_s - (double)old_s ) * scale;
+      tmp_i = ( (double)new_i - (double)old_i ) * scale;
+      tmp_w = ( (double)new_w - (double)old_w ) * scale;
+      tmp_x = ( (double)new_x - (double)old_x ) * scale;
+      tmp_y = ( (double)new_y - (double)old_y ) * scale;
+      tmp_z = ( (double)new_z - (double)old_z ) * scale;
+    }else{
+      tmp_u = NAN;
+      tmp_n = NAN;
+      tmp_s = NAN;
+      tmp_i = NAN;
+      tmp_w = NAN;
+      tmp_x = NAN;
+      tmp_y = NAN;
+      tmp_z = NAN;
+    }
+    SET_IF_DESIRED(uret, tmp_u);
+    SET_IF_DESIRED(nret, tmp_n);
+    SET_IF_DESIRED(sret, tmp_s);
+    SET_IF_DESIRED(iret, tmp_i);
+    SET_IF_DESIRED(wret, tmp_w);
+    SET_IF_DESIRED(xret, tmp_x);
+    SET_IF_DESIRED(yret, tmp_y);
+    SET_IF_DESIRED(zret, tmp_z);
+    old_u=new_u;
+    old_n=new_n;
+    old_s=new_s;
+    old_i=new_i;
+    old_w=new_w;
+    old_x=new_x;
+    old_y=new_y;
+    old_z=new_z;
+}
+#undef JT
+#endif
+
+/***********************************************************************/
+void loadavg(double *restrict av1, double *restrict av5, double *restrict av15) {
+    double avg_1=0, avg_5=0, avg_15=0;
+    char *restrict savelocale;
+    
+    FILE_TO_BUF(LOADAVG_FILE,loadavg_fd);
+    savelocale = setlocale(LC_NUMERIC, NULL);
+    setlocale(LC_NUMERIC, "C");
+    if (sscanf(buf, "%lf %lf %lf", &avg_1, &avg_5, &avg_15) < 3) {
+	fputs("bad data in " LOADAVG_FILE "\n", stderr);
+	exit(1);
+    }
+    setlocale(LC_NUMERIC, savelocale);
+    SET_IF_DESIRED(av1,  avg_1);
+    SET_IF_DESIRED(av5,  avg_5);
+    SET_IF_DESIRED(av15, avg_15);
+}
+
+  static char buff[BUFFSIZE]; /* used in the procedures */
+/***********************************************************************/
+
+static void crash(const char *filename) {
+    perror(filename);
+    exit(EXIT_FAILURE);
+}
+
+/***********************************************************************/
+
+static void getrunners(unsigned int *restrict running, unsigned int *restrict blocked) {
+  struct direct *ent;
+  DIR *proc;
+
+  *running=0;
+  *blocked=0;
+
+  if((proc=opendir("/proc"))==NULL) crash("/proc");
+
+  while(( ent=readdir(proc) )) {
+    char tbuf[32];
+    char *cp;
+    int fd;
+    char c;
+
+    if (!isdigit(ent->d_name[0])) continue;
+    sprintf(tbuf, "/proc/%s/stat", ent->d_name);
+
+    fd = open(tbuf, O_RDONLY, 0);
+    if (fd == -1) continue;
+    memset(tbuf, '\0', sizeof tbuf); // didn't feel like checking read()
+    read(fd, tbuf, sizeof tbuf - 1); // need 32 byte buffer at most
+    close(fd);
+
+    cp = strrchr(tbuf, ')');
+    if(!cp) continue;
+    c = cp[2];
+
+    if (c=='R') {
+      (*running)++;
+      continue;
+    }
+    if (c=='D') {
+      (*blocked)++;
+      continue;
+    }
+  }
+  closedir(proc);
+}
+
+/***********************************************************************/
+
+void getstat(jiff *restrict cuse, jiff *restrict cice, jiff *restrict csys, jiff *restrict cide, jiff *restrict ciow, jiff *restrict cxxx, jiff *restrict cyyy, jiff *restrict czzz,
+	     unsigned long *restrict pin, unsigned long *restrict pout, unsigned long *restrict s_in, unsigned long *restrict sout,
+	     unsigned *restrict intr, unsigned *restrict ctxt,
+	     unsigned int *restrict running, unsigned int *restrict blocked,
+	     unsigned int *restrict btime, unsigned int *restrict processes) {
+  static int fd;
+  unsigned long long llbuf = 0;
+  int need_vmstat_file = 0;
+  int need_proc_scan = 0;
+  const char* b;
+  buff[BUFFSIZE-1] = 0;  /* ensure null termination in buffer */
+
+  if(fd){
+    lseek(fd, 0L, SEEK_SET);
+  }else{
+    fd = open("/proc/stat", O_RDONLY, 0);
+    if(fd == -1) crash("/proc/stat");
+  }
+  read(fd,buff,BUFFSIZE-1);
+  *intr = 0; 
+  *ciow = 0;  /* not separated out until the 2.5.41 kernel */
+  *cxxx = 0;  /* not separated out until the 2.6.0-test4 kernel */
+  *cyyy = 0;  /* not separated out until the 2.6.0-test4 kernel */
+  *czzz = 0;  /* not separated out until the 2.6.11 kernel */
+
+  b = strstr(buff, "cpu ");
+  if(b) sscanf(b,  "cpu  %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", cuse, cice, csys, cide, ciow, cxxx, cyyy, czzz);
+
+  b = strstr(buff, "page ");
+  if(b) sscanf(b,  "page %lu %lu", pin, pout);
+  else need_vmstat_file = 1;
+
+  b = strstr(buff, "swap ");
+  if(b) sscanf(b,  "swap %lu %lu", s_in, sout);
+  else need_vmstat_file = 1;
+
+  b = strstr(buff, "intr ");
+  if(b) sscanf(b,  "intr %Lu", &llbuf);
+  *intr = llbuf;
+
+  b = strstr(buff, "ctxt ");
+  if(b) sscanf(b,  "ctxt %Lu", &llbuf);
+  *ctxt = llbuf;
+
+  b = strstr(buff, "btime ");
+  if(b) sscanf(b,  "btime %u", btime);
+
+  b = strstr(buff, "processes ");
+  if(b) sscanf(b,  "processes %u", processes);
+
+  b = strstr(buff, "procs_running ");
+  if(b) sscanf(b,  "procs_running %u", running);
+  else need_proc_scan = 1;
+
+  b = strstr(buff, "procs_blocked ");
+  if(b) sscanf(b,  "procs_blocked %u", blocked);
+  else need_proc_scan = 1;
+
+  if(need_proc_scan){   /* Linux 2.5.46 (approximately) and below */
+    getrunners(running, blocked);
+  }
+
+  (*running)--;   // exclude vmstat itself
+
+  if(need_vmstat_file){  /* Linux 2.5.40-bk4 and above */
+    vminfo();
+    *pin  = vm_pgpgin;
+    *pout = vm_pgpgout;
+    *s_in = vm_pswpin;
+    *sout = vm_pswpout;
+  }
+}
+
+/***********************************************************************/
+/*
+ * Copyright 1999 by Albert Cahalan; all rights reserved.
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+
+typedef struct mem_table_struct {
+  const char *name;     /* memory type name */
+  unsigned long *slot; /* slot in return struct */
+} mem_table_struct;
+
+static int compare_mem_table_structs(const void *a, const void *b){
+  return strcmp(((const mem_table_struct*)a)->name,((const mem_table_struct*)b)->name);
+}
+
+/* example data, following junk, with comments added:
+ *
+ * MemTotal:        61768 kB    old
+ * MemFree:          1436 kB    old
+ * MemShared:           0 kB    old (now always zero; not calculated)
+ * Buffers:          1312 kB    old
+ * Cached:          20932 kB    old
+ * Active:          12464 kB    new
+ * Inact_dirty:      7772 kB    new
+ * Inact_clean:      2008 kB    new
+ * Inact_target:        0 kB    new
+ * Inact_laundry:       0 kB    new, and might be missing too
+ * HighTotal:           0 kB
+ * HighFree:            0 kB
+ * LowTotal:        61768 kB
+ * LowFree:          1436 kB
+ * SwapTotal:      122580 kB    old
+ * SwapFree:        60352 kB    old
+ * Inactive:        20420 kB    2.5.41+
+ * Dirty:               0 kB    2.5.41+
+ * Writeback:           0 kB    2.5.41+
+ * Mapped:           9792 kB    2.5.41+
+ * Slab:             4564 kB    2.5.41+
+ * Committed_AS:     8440 kB    2.5.41+
+ * PageTables:        304 kB    2.5.41+
+ * ReverseMaps:      5738       2.5.41+
+ * SwapCached:          0 kB    2.5.??+
+ * HugePages_Total:   220       2.5.??+
+ * HugePages_Free:    138       2.5.??+
+ * Hugepagesize:     4096 kB    2.5.??+
+ */
+
+/* obsolete */
+unsigned long kb_main_shared;
+/* old but still kicking -- the important stuff */
+unsigned long kb_main_buffers;
+unsigned long kb_main_cached;
+unsigned long kb_main_free;
+unsigned long kb_main_total;
+unsigned long kb_swap_free;
+unsigned long kb_swap_total;
+/* recently introduced */
+unsigned long kb_high_free;
+unsigned long kb_high_total;
+unsigned long kb_low_free;
+unsigned long kb_low_total;
+/* 2.4.xx era */
+unsigned long kb_active;
+unsigned long kb_inact_laundry;
+unsigned long kb_inact_dirty;
+unsigned long kb_inact_clean;
+unsigned long kb_inact_target;
+unsigned long kb_swap_cached;  /* late 2.4 and 2.6+ only */
+/* derived values */
+unsigned long kb_swap_used;
+unsigned long kb_main_used;
+/* 2.5.41+ */
+unsigned long kb_writeback;
+unsigned long kb_slab;
+unsigned long nr_reversemaps;
+unsigned long kb_committed_as;
+unsigned long kb_dirty;
+unsigned long kb_inactive;
+unsigned long kb_mapped;
+unsigned long kb_pagetables;
+// seen on a 2.6.x kernel:
+static unsigned long kb_vmalloc_chunk;
+static unsigned long kb_vmalloc_total;
+static unsigned long kb_vmalloc_used;
+// seen on 2.6.24-rc6-git12
+static unsigned long kb_anon_pages;
+static unsigned long kb_bounce;
+static unsigned long kb_commit_limit;
+static unsigned long kb_nfs_unstable;
+static unsigned long kb_swap_reclaimable;
+static unsigned long kb_swap_unreclaimable;
+
+void meminfo(void){
+  char namebuf[16]; /* big enough to hold any row name */
+  mem_table_struct findme = { namebuf, NULL};
+  mem_table_struct *found;
+  char *head;
+  char *tail;
+  static const mem_table_struct mem_table[] = {
+  {"Active",       &kb_active},       // important
+  {"AnonPages",    &kb_anon_pages},
+  {"Bounce",       &kb_bounce},
+  {"Buffers",      &kb_main_buffers}, // important
+  {"Cached",       &kb_main_cached},  // important
+  {"CommitLimit",  &kb_commit_limit},
+  {"Committed_AS", &kb_committed_as},
+  {"Dirty",        &kb_dirty},        // kB version of vmstat nr_dirty
+  {"HighFree",     &kb_high_free},
+  {"HighTotal",    &kb_high_total},
+  {"Inact_clean",  &kb_inact_clean},
+  {"Inact_dirty",  &kb_inact_dirty},
+  {"Inact_laundry",&kb_inact_laundry},
+  {"Inact_target", &kb_inact_target},
+  {"Inactive",     &kb_inactive},     // important
+  {"LowFree",      &kb_low_free},
+  {"LowTotal",     &kb_low_total},
+  {"Mapped",       &kb_mapped},       // kB version of vmstat nr_mapped
+  {"MemFree",      &kb_main_free},    // important
+  {"MemShared",    &kb_main_shared},  // important, but now gone!
+  {"MemTotal",     &kb_main_total},   // important
+  {"NFS_Unstable", &kb_nfs_unstable},
+  {"PageTables",   &kb_pagetables},   // kB version of vmstat nr_page_table_pages
+  {"ReverseMaps",  &nr_reversemaps},  // same as vmstat nr_page_table_pages
+  {"SReclaimable", &kb_swap_reclaimable}, // "swap reclaimable" (dentry and inode structures)
+  {"SUnreclaim",   &kb_swap_unreclaimable},
+  {"Slab",         &kb_slab},         // kB version of vmstat nr_slab
+  {"SwapCached",   &kb_swap_cached},
+  {"SwapFree",     &kb_swap_free},    // important
+  {"SwapTotal",    &kb_swap_total},   // important
+  {"VmallocChunk", &kb_vmalloc_chunk},
+  {"VmallocTotal", &kb_vmalloc_total},
+  {"VmallocUsed",  &kb_vmalloc_used},
+  {"Writeback",    &kb_writeback},    // kB version of vmstat nr_writeback
+  };
+  const int mem_table_count = sizeof(mem_table)/sizeof(mem_table_struct);
+
+  FILE_TO_BUF(MEMINFO_FILE,meminfo_fd);
+
+  kb_inactive = ~0UL;
+
+  head = buf;
+  for(;;){
+    tail = strchr(head, ':');
+    if(!tail) break;
+    *tail = '\0';
+    if(strlen(head) >= sizeof(namebuf)){
+      head = tail+1;
+      goto nextline;
+    }
+    strcpy(namebuf,head);
+    found = bsearch(&findme, mem_table, mem_table_count,
+        sizeof(mem_table_struct), compare_mem_table_structs
+    );
+    head = tail+1;
+    if(!found) goto nextline;
+    *(found->slot) = strtoul(head,&tail,10);
+nextline:
+    tail = strchr(head, '\n');
+    if(!tail) break;
+    head = tail+1;
+  }
+  if(!kb_low_total){  /* low==main except with large-memory support */
+    kb_low_total = kb_main_total;
+    kb_low_free  = kb_main_free;
+  }
+  if(kb_inactive==~0UL){
+    kb_inactive = kb_inact_dirty + kb_inact_clean + kb_inact_laundry;
+  }
+  kb_swap_used = kb_swap_total - kb_swap_free;
+  kb_main_used = kb_main_total - kb_main_free;
+}
+
+/*****************************************************************/
+
+/* read /proc/vminfo only for 2.5.41 and above */
+
+typedef struct vm_table_struct {
+  const char *name;     /* VM statistic name */
+  unsigned long *slot;       /* slot in return struct */
+} vm_table_struct;
+
+static int compare_vm_table_structs(const void *a, const void *b){
+  return strcmp(((const vm_table_struct*)a)->name,((const vm_table_struct*)b)->name);
+}
+
+// see include/linux/page-flags.h and mm/page_alloc.c
+unsigned long vm_nr_dirty;           // dirty writable pages
+unsigned long vm_nr_writeback;       // pages under writeback
+unsigned long vm_nr_pagecache;       // pages in pagecache -- gone in 2.5.66+ kernels
+unsigned long vm_nr_page_table_pages;// pages used for pagetables
+unsigned long vm_nr_reverse_maps;    // includes PageDirect
+unsigned long vm_nr_mapped;          // mapped into pagetables
+unsigned long vm_nr_slab;            // in slab
+unsigned long vm_pgpgin;             // kB disk reads  (same as 1st num on /proc/stat page line)
+unsigned long vm_pgpgout;            // kB disk writes (same as 2nd num on /proc/stat page line)
+unsigned long vm_pswpin;             // swap reads     (same as 1st num on /proc/stat swap line)
+unsigned long vm_pswpout;            // swap writes    (same as 2nd num on /proc/stat swap line)
+unsigned long vm_pgalloc;            // page allocations
+unsigned long vm_pgfree;             // page freeings
+unsigned long vm_pgactivate;         // pages moved inactive -> active
+unsigned long vm_pgdeactivate;       // pages moved active -> inactive
+unsigned long vm_pgfault;           // total faults (major+minor)
+unsigned long vm_pgmajfault;       // major faults
+unsigned long vm_pgscan;          // pages scanned by page reclaim
+unsigned long vm_pgrefill;       // inspected by refill_inactive_zone
+unsigned long vm_pgsteal;       // total pages reclaimed
+unsigned long vm_kswapd_steal; // pages reclaimed by kswapd
+// next 3 as defined by the 2.5.52 kernel
+unsigned long vm_pageoutrun;  // times kswapd ran page reclaim
+unsigned long vm_allocstall; // times a page allocator ran direct reclaim
+unsigned long vm_pgrotated; // pages rotated to the tail of the LRU for immediate reclaim
+// seen on a 2.6.8-rc1 kernel, apparently replacing old fields
+static unsigned long vm_pgalloc_dma;          // 
+static unsigned long vm_pgalloc_high;         // 
+static unsigned long vm_pgalloc_normal;       // 
+static unsigned long vm_pgrefill_dma;         // 
+static unsigned long vm_pgrefill_high;        // 
+static unsigned long vm_pgrefill_normal;      // 
+static unsigned long vm_pgscan_direct_dma;    // 
+static unsigned long vm_pgscan_direct_high;   // 
+static unsigned long vm_pgscan_direct_normal; // 
+static unsigned long vm_pgscan_kswapd_dma;    // 
+static unsigned long vm_pgscan_kswapd_high;   // 
+static unsigned long vm_pgscan_kswapd_normal; // 
+static unsigned long vm_pgsteal_dma;          // 
+static unsigned long vm_pgsteal_high;         // 
+static unsigned long vm_pgsteal_normal;       // 
+// seen on a 2.6.8-rc1 kernel
+static unsigned long vm_kswapd_inodesteal;    //
+static unsigned long vm_nr_unstable;          //
+static unsigned long vm_pginodesteal;         //
+static unsigned long vm_slabs_scanned;        //
+
+void vminfo(void){
+  char namebuf[16]; /* big enough to hold any row name */
+  vm_table_struct findme = { namebuf, NULL};
+  vm_table_struct *found;
+  char *head;
+  char *tail;
+  static const vm_table_struct vm_table[] = {
+  {"allocstall",          &vm_allocstall},
+  {"kswapd_inodesteal",   &vm_kswapd_inodesteal},
+  {"kswapd_steal",        &vm_kswapd_steal},
+  {"nr_dirty",            &vm_nr_dirty},           // page version of meminfo Dirty
+  {"nr_mapped",           &vm_nr_mapped},          // page version of meminfo Mapped
+  {"nr_page_table_pages", &vm_nr_page_table_pages},// same as meminfo PageTables
+  {"nr_pagecache",        &vm_nr_pagecache},       // gone in 2.5.66+ kernels
+  {"nr_reverse_maps",     &vm_nr_reverse_maps},    // page version of meminfo ReverseMaps GONE
+  {"nr_slab",             &vm_nr_slab},            // page version of meminfo Slab
+  {"nr_unstable",         &vm_nr_unstable},
+  {"nr_writeback",        &vm_nr_writeback},       // page version of meminfo Writeback
+  {"pageoutrun",          &vm_pageoutrun},
+  {"pgactivate",          &vm_pgactivate},
+  {"pgalloc",             &vm_pgalloc},  // GONE (now separate dma,high,normal)
+  {"pgalloc_dma",         &vm_pgalloc_dma},
+  {"pgalloc_high",        &vm_pgalloc_high},
+  {"pgalloc_normal",      &vm_pgalloc_normal},
+  {"pgdeactivate",        &vm_pgdeactivate},
+  {"pgfault",             &vm_pgfault},
+  {"pgfree",              &vm_pgfree},
+  {"pginodesteal",        &vm_pginodesteal},
+  {"pgmajfault",          &vm_pgmajfault},
+  {"pgpgin",              &vm_pgpgin},     // important
+  {"pgpgout",             &vm_pgpgout},     // important
+  {"pgrefill",            &vm_pgrefill},  // GONE (now separate dma,high,normal)
+  {"pgrefill_dma",        &vm_pgrefill_dma},
+  {"pgrefill_high",       &vm_pgrefill_high},
+  {"pgrefill_normal",     &vm_pgrefill_normal},
+  {"pgrotated",           &vm_pgrotated},
+  {"pgscan",              &vm_pgscan},  // GONE (now separate direct,kswapd and dma,high,normal)
+  {"pgscan_direct_dma",   &vm_pgscan_direct_dma},
+  {"pgscan_direct_high",  &vm_pgscan_direct_high},
+  {"pgscan_direct_normal",&vm_pgscan_direct_normal},
+  {"pgscan_kswapd_dma",   &vm_pgscan_kswapd_dma},
+  {"pgscan_kswapd_high",  &vm_pgscan_kswapd_high},
+  {"pgscan_kswapd_normal",&vm_pgscan_kswapd_normal},
+  {"pgsteal",             &vm_pgsteal},  // GONE (now separate dma,high,normal)
+  {"pgsteal_dma",         &vm_pgsteal_dma},
+  {"pgsteal_high",        &vm_pgsteal_high},
+  {"pgsteal_normal",      &vm_pgsteal_normal},
+  {"pswpin",              &vm_pswpin},     // important
+  {"pswpout",             &vm_pswpout},     // important
+  {"slabs_scanned",       &vm_slabs_scanned},
+  };
+  const int vm_table_count = sizeof(vm_table)/sizeof(vm_table_struct);
+
+  vm_pgalloc = 0;
+  vm_pgrefill = 0;
+  vm_pgscan = 0;
+  vm_pgsteal = 0;
+
+  FILE_TO_BUF(VMINFO_FILE,vminfo_fd);
+
+  head = buf;
+  for(;;){
+    tail = strchr(head, ' ');
+    if(!tail) break;
+    *tail = '\0';
+    if(strlen(head) >= sizeof(namebuf)){
+      head = tail+1;
+      goto nextline;
+    }
+    strcpy(namebuf,head);
+    found = bsearch(&findme, vm_table, vm_table_count,
+        sizeof(vm_table_struct), compare_vm_table_structs
+    );
+    head = tail+1;
+    if(!found) goto nextline;
+    *(found->slot) = strtoul(head,&tail,10);
+nextline:
+
+//if(found) fprintf(stderr,"%s=%d\n",found->name,*(found->slot));
+//else      fprintf(stderr,"%s not found\n",findme.name);
+
+    tail = strchr(head, '\n');
+    if(!tail) break;
+    head = tail+1;
+  }
+  if(!vm_pgalloc)
+    vm_pgalloc  = vm_pgalloc_dma + vm_pgalloc_high + vm_pgalloc_normal;
+  if(!vm_pgrefill)
+    vm_pgrefill = vm_pgrefill_dma + vm_pgrefill_high + vm_pgrefill_normal;
+  if(!vm_pgscan)
+    vm_pgscan   = vm_pgscan_direct_dma + vm_pgscan_direct_high + vm_pgscan_direct_normal
+                + vm_pgscan_kswapd_dma + vm_pgscan_kswapd_high + vm_pgscan_kswapd_normal;
+  if(!vm_pgsteal)
+    vm_pgsteal  = vm_pgsteal_dma + vm_pgsteal_high + vm_pgsteal_normal;
+}
+
+///////////////////////////////////////////////////////////////////////
+// based on Fabian Frederick's /proc/diskstats parser
+
+
+unsigned int getpartitions_num(struct disk_stat *disks, int ndisks){
+  int i=0;
+  int partitions=0;
+
+  for (i=0;i<ndisks;i++){
+	partitions+=disks[i].partitions;
+  }
+  return partitions;
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+unsigned int getdiskstat(struct disk_stat **disks, struct partition_stat **partitions){
+  FILE* fd;
+  int cDisk = 0;
+  int cPartition = 0;
+  int fields;
+  unsigned dummy;
+
+  *disks = NULL;
+  *partitions = NULL;
+  buff[BUFFSIZE-1] = 0; 
+  fd = fopen("/proc/diskstats", "rb");
+  if(!fd) crash("/proc/diskstats");
+
+  for (;;) {
+    if (!fgets(buff,BUFFSIZE-1,fd)){
+      fclose(fd);
+      break;
+    }
+    fields = sscanf(buff, " %*d %*d %*s %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %u", &dummy);
+    if (fields == 1){
+      (*disks) = realloc(*disks, (cDisk+1)*sizeof(struct disk_stat));
+      sscanf(buff,  "   %*d    %*d %15s %u %u %llu %u %u %u %llu %u %u %u %u",
+        //&disk_major,
+        //&disk_minor,
+        (*disks)[cDisk].disk_name,
+        &(*disks)[cDisk].reads,
+        &(*disks)[cDisk].merged_reads,
+        &(*disks)[cDisk].reads_sectors,
+        &(*disks)[cDisk].milli_reading,
+        &(*disks)[cDisk].writes,
+        &(*disks)[cDisk].merged_writes,
+        &(*disks)[cDisk].written_sectors,
+        &(*disks)[cDisk].milli_writing,
+        &(*disks)[cDisk].inprogress_IO,
+        &(*disks)[cDisk].milli_spent_IO,
+        &(*disks)[cDisk].weighted_milli_spent_IO
+      );
+        (*disks)[cDisk].partitions=0;
+      cDisk++;
+    }else{
+      (*partitions) = realloc(*partitions, (cPartition+1)*sizeof(struct partition_stat));
+      fflush(stdout);
+      sscanf(buff,  "   %*d    %*d %15s %u %llu %u %u",
+        //&part_major,
+        //&part_minor,
+        (*partitions)[cPartition].partition_name,
+        &(*partitions)[cPartition].reads,
+        &(*partitions)[cPartition].reads_sectors,
+        &(*partitions)[cPartition].writes,
+        &(*partitions)[cPartition].requested_writes
+      );
+      (*partitions)[cPartition++].parent_disk = cDisk-1;
+      (*disks)[cDisk-1].partitions++;	
+    }
+  }
+
+  return cDisk;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// based on Fabian Frederick's /proc/slabinfo parser
+
+unsigned int getslabinfo (struct slab_cache **slab){
+  FILE* fd;
+  int cSlab = 0;
+  buff[BUFFSIZE-1] = 0; 
+  *slab = NULL;
+  fd = fopen("/proc/slabinfo", "rb");
+  if(!fd) crash("/proc/slabinfo");
+  while (fgets(buff,BUFFSIZE-1,fd)){
+    if(!memcmp("slabinfo - version:",buff,19)) continue; // skip header
+    if(*buff == '#')                           continue; // skip comments
+    (*slab) = realloc(*slab, (cSlab+1)*sizeof(struct slab_cache));
+    sscanf(buff,  "%47s %u %u %u %u",  // allow 47; max seen is 24
+      (*slab)[cSlab].name,
+      &(*slab)[cSlab].active_objs,
+      &(*slab)[cSlab].num_objs,
+      &(*slab)[cSlab].objsize,
+      &(*slab)[cSlab].objperslab
+    ) ;
+    cSlab++;
+  }
+  fclose(fd);
+  return cSlab;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+unsigned get_pid_digits(void){
+  char pidbuf[24];
+  char *endp;
+  long rc;
+  int fd;
+  static unsigned ret;
+
+  if(ret) goto out;
+  ret = 5;
+  fd = open("/proc/sys/kernel/pid_max", O_RDONLY);
+  if(fd==-1) goto out;
+  rc = read(fd, pidbuf, sizeof pidbuf);
+  close(fd);
+  if(rc<3) goto out;
+  pidbuf[rc] = '\0';
+  rc = strtol(pidbuf,&endp,10);
+  if(rc<42) goto out;
+  if(*endp && *endp!='\n') goto out;
+  rc--;  // the pid_max value is really the max PID plus 1
+  ret = 0;
+  while(rc){
+    rc /= 10;
+    ret++;
+  }
+out:
+  return ret;
+}
diff --git a/procps-3.2.8/proc/sysinfo.h b/procps-3.2.8/proc/sysinfo.h
new file mode 100644
index 0000000..e30a38b
--- /dev/null
+++ b/procps-3.2.8/proc/sysinfo.h
@@ -0,0 +1,135 @@
+#ifndef PROC_SYSINFO_H
+#define PROC_SYSINFO_H
+#include <sys/types.h>
+#include <sys/dir.h>
+#include "procps.h"
+
+EXTERN_C_BEGIN
+
+extern unsigned long long Hertz;   /* clock tick frequency */
+extern long smp_num_cpus;     /* number of CPUs */
+extern int have_privs;     /* boolean, true if setuid or similar */
+
+#if 0
+#define JT double
+extern void eight_cpu_numbers(JT *uret, JT *nret, JT *sret, JT *iret, JT *wret, JT *xret, JT *yret, JT *zret);
+#undef JT
+#endif
+
+extern int        uptime (double *uptime_secs, double *idle_secs);
+extern void       loadavg(double *av1, double *av5, double *av15);
+
+
+/* obsolete */
+extern unsigned long kb_main_shared;
+/* old but still kicking -- the important stuff */
+extern unsigned long kb_main_buffers;
+extern unsigned long kb_main_cached;
+extern unsigned long kb_main_free;
+extern unsigned long kb_main_total;
+extern unsigned long kb_swap_free;
+extern unsigned long kb_swap_total;
+/* recently introduced */
+extern unsigned long kb_high_free;
+extern unsigned long kb_high_total;
+extern unsigned long kb_low_free;
+extern unsigned long kb_low_total;
+/* 2.4.xx era */
+extern unsigned long kb_active;
+extern unsigned long kb_inact_laundry;  // grrr...
+extern unsigned long kb_inact_dirty;
+extern unsigned long kb_inact_clean;
+extern unsigned long kb_inact_target;
+extern unsigned long kb_swap_cached;  /* late 2.4+ */
+/* derived values */
+extern unsigned long kb_swap_used;
+extern unsigned long kb_main_used;
+/* 2.5.41+ */
+extern unsigned long kb_writeback;
+extern unsigned long kb_slab;
+extern unsigned long nr_reversemaps;
+extern unsigned long kb_committed_as;
+extern unsigned long kb_dirty;
+extern unsigned long kb_inactive;
+extern unsigned long kb_mapped;
+extern unsigned long kb_pagetables;
+
+#define BUFFSIZE (64*1024)
+typedef unsigned long long jiff;
+extern void getstat(jiff *restrict cuse, jiff *restrict cice, jiff *restrict csys, jiff *restrict cide, jiff *restrict ciow, jiff *restrict cxxx, jiff *restrict cyyy, jiff *restrict czzz,
+	     unsigned long *restrict pin, unsigned long *restrict pout, unsigned long *restrict s_in, unsigned long *restrict sout,
+	     unsigned *restrict intr, unsigned *restrict ctxt,
+	     unsigned int *restrict running, unsigned int *restrict blocked,
+	     unsigned int *restrict btime, unsigned int *restrict processes);
+
+extern void meminfo(void);
+
+
+extern unsigned long vm_nr_dirty;
+extern unsigned long vm_nr_writeback;
+extern unsigned long vm_nr_pagecache;
+extern unsigned long vm_nr_page_table_pages;
+extern unsigned long vm_nr_reverse_maps;
+extern unsigned long vm_nr_mapped;
+extern unsigned long vm_nr_slab;
+extern unsigned long vm_pgpgin;
+extern unsigned long vm_pgpgout;
+extern unsigned long vm_pswpin;
+extern unsigned long vm_pswpout;
+extern unsigned long vm_pgalloc;
+extern unsigned long vm_pgfree;
+extern unsigned long vm_pgactivate;
+extern unsigned long vm_pgdeactivate;
+extern unsigned long vm_pgfault;
+extern unsigned long vm_pgmajfault;
+extern unsigned long vm_pgscan;
+extern unsigned long vm_pgrefill;
+extern unsigned long vm_pgsteal;
+extern unsigned long vm_kswapd_steal;
+extern unsigned long vm_pageoutrun;
+extern unsigned long vm_allocstall;
+
+extern void vminfo(void);
+
+typedef struct disk_stat{
+	unsigned long long reads_sectors;
+	unsigned long long written_sectors;
+	char               disk_name [16];
+	unsigned           inprogress_IO;
+	unsigned           merged_reads;
+	unsigned           merged_writes;
+	unsigned           milli_reading;
+	unsigned           milli_spent_IO;
+	unsigned           milli_writing;
+	unsigned           partitions;
+	unsigned           reads;
+	unsigned           weighted_milli_spent_IO;
+	unsigned           writes;
+}disk_stat;
+
+typedef struct partition_stat{
+	char partition_name [16];
+	unsigned long long reads_sectors;
+	unsigned           parent_disk;  // index into a struct disk_stat array
+	unsigned           reads;
+	unsigned           writes;
+	unsigned           requested_writes;
+}partition_stat;
+
+extern unsigned int getpartitions_num(struct disk_stat *disks, int ndisks);
+extern unsigned int getdiskstat (struct disk_stat**,struct partition_stat**);
+
+typedef struct slab_cache{
+	char name[48];
+	unsigned active_objs;
+	unsigned num_objs;
+	unsigned objsize;
+	unsigned objperslab;
+}slab_cache;
+
+extern unsigned int getslabinfo (struct slab_cache**);
+
+extern unsigned get_pid_digits(void) FUNCTION;
+
+EXTERN_C_END
+#endif /* SYSINFO_H */
diff --git a/procps-3.2.8/proc/version.c b/procps-3.2.8/proc/version.c
new file mode 100644
index 0000000..69bae4f
--- /dev/null
+++ b/procps-3.2.8/proc/version.c
@@ -0,0 +1,49 @@
+/* Suite version information for procps utilities
+ * Copyright (c) 1995 Martin Schulze <joey@infodrom.north.de>
+ * Ammended by cblake to only export the function symbol.
+ *
+ * Modified by Albert Cahalan, ????-2003
+ *
+ * Redistributable under the terms of the
+ * GNU Library General Public License; see COPYING
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include "version.h"
+
+#ifdef MINORVERSION
+const char procps_version[] = "procps version " VERSION "." SUBVERSION "." MINORVERSION;
+#else
+const char procps_version[] = "procps version " VERSION "." SUBVERSION;
+#endif
+
+void display_version(void) {
+    fprintf(stdout, "%s\n", procps_version);
+}
+
+/* Linux kernel version information for procps utilities
+ * Copyright (c) 1996 Charles Blake <cblake@bbn.com>
+ */
+#include <sys/utsname.h>
+
+#define LINUX_VERSION(x,y,z)   (0x10000*(x) + 0x100*(y) + z)
+
+int linux_version_code;
+
+static void init_Linux_version(void) __attribute__((constructor));
+static void init_Linux_version(void) {
+    static struct utsname uts;
+    int x = 0, y = 0, z = 0;	/* cleared in case sscanf() < 3 */
+    
+    if (uname(&uts) == -1)	/* failure implies impending death */
+	exit(1);
+    if (sscanf(uts.release, "%d.%d.%d", &x, &y, &z) < 3)
+	fprintf(stderr,		/* *very* unlikely to happen by accident */
+		"Non-standard uts for running kernel:\n"
+		"release %s=%d.%d.%d gives version code %d\n",
+		uts.release, x, y, z, LINUX_VERSION(x,y,z));
+    linux_version_code = LINUX_VERSION(x, y, z);
+}
diff --git a/procps-3.2.8/proc/version.h b/procps-3.2.8/proc/version.h
new file mode 100644
index 0000000..3769b84
--- /dev/null
+++ b/procps-3.2.8/proc/version.h
@@ -0,0 +1,31 @@
+#ifndef PROC_VERSION_H
+#define PROC_VERSION_H
+
+#include "procps.h"
+
+/* Suite version information for procps utilities
+ * Copyright (c) 1995 Martin Schulze <joey@infodrom.north.de>
+ * Linux kernel version information for procps utilities
+ * Copyright (c) 1996 Charles Blake <cblake@bbn.com>
+ * Distributable under the terms of the GNU Library General Public License
+ *
+ * Copyright 2002 Albert Cahalan
+ */
+
+EXTERN_C_BEGIN
+
+extern void display_version(void);	/* display suite version */
+extern const char procps_version[];		/* global buf for suite version */
+
+extern int linux_version_code;		/* runtime version of LINUX_VERSION_CODE
+					   in /usr/include/linux/version.h */
+
+/* Convenience macros for composing/decomposing version codes */
+#define LINUX_VERSION(x,y,z)   (0x10000*(x) + 0x100*(y) + z)
+#define LINUX_VERSION_MAJOR(x) (((x)>>16) & 0xFF)
+#define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF)
+#define LINUX_VERSION_PATCH(x) ( (x)      & 0xFF)
+
+EXTERN_C_END
+
+#endif	/* PROC_VERSION_H */
diff --git a/procps-3.2.8/proc/wchan.h b/procps-3.2.8/proc/wchan.h
new file mode 100644
index 0000000..93d4e70
--- /dev/null
+++ b/procps-3.2.8/proc/wchan.h
@@ -0,0 +1,16 @@
+#ifndef PROCPS_PROC_WCHAN_H
+#define PROCPS_PROC_WCHAN_H
+
+#include "procps.h"
+
+EXTERN_C_BEGIN
+
+typedef void (*message_fn)(const char *restrict, ...) __attribute__((format(printf,1,2)));
+
+extern const char * lookup_wchan(unsigned KLONG address, unsigned pid);
+extern int   open_psdb(const char *restrict override);
+extern int   open_psdb_message(const char *restrict override, message_fn message);
+
+EXTERN_C_END
+
+#endif
diff --git a/procps-3.2.8/proc/whattime.c b/procps-3.2.8/proc/whattime.c
new file mode 100644
index 0000000..d2785a8
--- /dev/null
+++ b/procps-3.2.8/proc/whattime.c
@@ -0,0 +1,87 @@
+/* This is a trivial uptime program.  I hereby release this program
+ * into the public domain.  I disclaim any responsibility for this
+ * program --- use it at your own risk.  (as if there were any.. ;-)
+ * -michaelkjohnson (johnsonm@sunsite.unc.edu)
+ *
+ * Modified by Larry Greenfield to give a more traditional output,
+ * count users, etc.  (greenfie@gauss.rutgers.edu)
+ *
+ * Modified by mkj again to fix a few tiny buglies.
+ *
+ * Modified by J. Cowley to add printing the uptime message to a
+ * string (for top) and to optimize file handling.  19 Mar 1993.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <utmp.h>
+#include <sys/ioctl.h>
+#include "whattime.h"
+#include "sysinfo.h"
+
+static char buf[128];
+static double av[3];
+
+char *sprint_uptime(void) {
+  struct utmp *utmpstruct;
+  int upminutes, uphours, updays;
+  int pos;
+  struct tm *realtime;
+  time_t realseconds;
+  int numuser;
+  double uptime_secs, idle_secs;
+
+/* first get the current time */
+
+  time(&realseconds);
+  realtime = localtime(&realseconds);
+  pos = sprintf(buf, " %02d:%02d:%02d ",
+    realtime->tm_hour, realtime->tm_min, realtime->tm_sec);
+
+/* read and calculate the amount of uptime */
+
+  uptime(&uptime_secs, &idle_secs);
+
+  updays = (int) uptime_secs / (60*60*24);
+  strcat (buf, "up ");
+  pos += 3;
+  if (updays)
+    pos += sprintf(buf + pos, "%d day%s, ", updays, (updays != 1) ? "s" : "");
+  upminutes = (int) uptime_secs / 60;
+  uphours = upminutes / 60;
+  uphours = uphours % 24;
+  upminutes = upminutes % 60;
+  if(uphours)
+    pos += sprintf(buf + pos, "%2d:%02d, ", uphours, upminutes);
+  else
+    pos += sprintf(buf + pos, "%d min, ", upminutes);
+
+/* count the number of users */
+
+  numuser = 0;
+  setutent();
+  while ((utmpstruct = getutent())) {
+    if ((utmpstruct->ut_type == USER_PROCESS) &&
+       (utmpstruct->ut_name[0] != '\0'))
+      numuser++;
+  }
+  endutent();
+
+  pos += sprintf(buf + pos, "%2d user%s, ", numuser, numuser == 1 ? "" : "s");
+
+  loadavg(&av[0], &av[1], &av[2]);
+
+  pos += sprintf(buf + pos, " load average: %.2f, %.2f, %.2f",
+		 av[0], av[1], av[2]);
+
+  return buf;
+}
+
+void print_uptime(void) {
+  printf("%s\n", sprint_uptime());
+}
diff --git a/procps-3.2.8/proc/whattime.h b/procps-3.2.8/proc/whattime.h
new file mode 100644
index 0000000..891ccd3
--- /dev/null
+++ b/procps-3.2.8/proc/whattime.h
@@ -0,0 +1,13 @@
+#ifndef PROC_WHATTIME_H
+#define PROC_WHATTIME_H
+
+#include "procps.h"
+
+EXTERN_C_BEGIN
+
+extern void print_uptime(void);
+extern char *sprint_uptime(void);
+
+EXTERN_C_END
+
+#endif
diff --git a/procps-3.2.8/procps.lsm b/procps-3.2.8/procps.lsm
new file mode 100644
index 0000000..f2b8064
--- /dev/null
+++ b/procps-3.2.8/procps.lsm
@@ -0,0 +1,15 @@
+Begin4
+Title: procps
+Version: 3.2.7
+Entered-date: 2006-06-25
+Description: Linux system utilities
+Keywords: procps /proc libproc sysctl pmap ps uptime tload slabtop
+	free w top vmstat watch skill snice kill pgrep pkill
+Author: Albert Cahalan, Michael K. Johnson, Jim Warner, etc.
+Maintained-by: various <procps-feedback@lists.sf.net>
+Primary-site: http://procps.sf.net/
+	281kB procps-3.2.7.tar.gz
+Alternate-site: http://www.debian.org/Packages/unstable/base/procps.html
+	281kB procps-3.2.7.tar.gz
+Copying-policy: mixed
+End
diff --git a/procps-3.2.8/procps.spec b/procps-3.2.8/procps.spec
new file mode 100644
index 0000000..5ac1be9
--- /dev/null
+++ b/procps-3.2.8/procps.spec
@@ -0,0 +1,52 @@
+URL: http://procps.sf.net/
+Summary: System and process monitoring utilities
+Name: procps
+%define major_version 3
+%define minor_version 2
+%define revision 8
+%define version %{major_version}.%{minor_version}.%{revision}
+Version: %{version}
+Release: 1
+License: LGPL, GPL, BSD-like
+Group: Applications/System
+Source: http://procps.sf.net/procps-%{version}.tar.gz
+BuildRoot: %{_tmppath}/procps-root
+Packager: <procps-feedback@lists.sf.net>
+
+%description
+The procps package contains a set of system utilities which provide
+system information.  Procps includes ps, free, sysctl, skill, snice,
+tload, top, uptime, vmstat, w, and watch. You need some of these.
+
+%prep
+%setup
+
+%build
+make SKIP="/bin/kill /usr/share/man/man1/kill.1" CFLAGS="$RPM_OPT_FLAGS"
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make SKIP="/bin/kill /usr/share/man/man1/kill.1" DESTDIR=$RPM_BUILD_ROOT ldconfig=echo install="install -D" lib="$RPM_BUILD_ROOT/%{_lib}/" install
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+# add libproc to the cache
+/sbin/ldconfig
+
+%files
+%defattr(0644,root,root,755)
+%doc NEWS BUGS TODO COPYING COPYING.LIB README.top README AUTHORS sysctl.conf
+%attr(555,root,root) /lib*/libproc*.so*
+%attr(555,root,root) /bin/*
+%attr(555,root,root) /sbin/*
+%attr(555,root,root) /usr/bin/*
+
+%attr(0644,root,root) /usr/share/man/man1/*
+%attr(0644,root,root) /usr/share/man/man5/*
+%attr(0644,root,root) /usr/share/man/man8/*
+
+%changelog
+* Fri Apr 14 09:23:45 PDT 2006  Jesse Brandeburg <jesse.brandeburg@in...>
+- fix missing trailing slash in %install to fix builds on x86_64
diff --git a/procps-3.2.8/ps/COPYING b/procps-3.2.8/ps/COPYING
new file mode 100644
index 0000000..92b8903
--- /dev/null
+++ b/procps-3.2.8/ps/COPYING
@@ -0,0 +1,481 @@
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+    		    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it.  You can use it for
+your libraries, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library.  If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software.  To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+  Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs.  This
+license, the GNU Library General Public License, applies to certain
+designated libraries.  This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+  The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it.  Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program.  However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+  Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries.  We
+concluded that weaker conditions might promote sharing better.
+
+  However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves.  This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them.  (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.)  The hope is that this
+will lead to faster development of free libraries.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+  Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+		  GNU LIBRARY GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License").  Each licensee is
+addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    c) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    d) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/procps-3.2.8/ps/HACKING b/procps-3.2.8/ps/HACKING
new file mode 100644
index 0000000..ffae92c
--- /dev/null
+++ b/procps-3.2.8/ps/HACKING
@@ -0,0 +1,53 @@
+Warning:
+
+This code must corrctly handle lots of picky little details to meet
+the Unix98 standard while simultaneously being as compatible as
+possible with the original Linux ps. Don't "fix" something without
+considering the impact on all the special-case code. For example,
+the "tty" format _must_ use "TT" as the header, even though the SysV
+output formats _must_ use "TTY".
+
+File overview:
+
+display.c     main(), debug code, iterates over processes
+escape.c      Does stuff like \202 and &lt; to command and environment.
+global.c      Data + code to init it.
+help.c        Help message.
+output.c      Giant tables and lots of output functions.
+parser.c      Initial command parsing.
+select.c      want_this_proc() checks a process against flags & lists
+sortformat.c  Parses sort & format specifier lists. Picks output format.
+stacktrace.c  Debug code, not normally used.
+../proc/*     Library used to gather data.
+regression    Regression tests that ought to be run.
+common.h      Lots of interesting stuff.
+Makefile      Makefile
+p             Script used to test ps when the library is not installed.
+utf           Empty file used to test "ps ut?" unmangling behavior.
+ps.1          Man page.
+
+Compiling:
+
+Whatever you do, don't trust the Makefiles. They are severely broken.
+You can touch top.h and top won't be recompiled, or you can change
+library files and discover that the library and programs won't be
+recompiled.
+
+Operation:
+
+Unless the personality forces BSD parsing, parser.c tries to parse the
+command line as a mixed BSD+SysV+Gnu mess. On failure, BSD parsing is
+attempted. If BSD parsing fails _after_ SysV parsing has been attempted,
+the error message comes from the original SysV parse.
+
+Control goes to sortformat.c, which must pick apart ambiguous options
+like "O". Failure can reset the whole program and set PER_FORCE_BSD,
+which means a second trip through parser.c and sortformat.c.
+
+The choice of output format happens in sortformat.c. There is a switch()
+with all the valid format_flags combinations. The SysV and default
+options are NULL (unless overridden by personality), which causes a
+trip through SysV output format generation hackery. Note that the
+default format always goes through there, even if it is for BSD.
+Formats that came from the switch() (generally BSD, plus overrides)
+get mangled a bit to support various SysV output modifiers.
diff --git a/procps-3.2.8/ps/TRANSLATION b/procps-3.2.8/ps/TRANSLATION
new file mode 100644
index 0000000..ff8df84
--- /dev/null
+++ b/procps-3.2.8/ps/TRANSLATION
@@ -0,0 +1,39 @@
+Initially I only want to translate the --help output and man page.
+Common error messages would be next on the list. I want to avoid
+run-time overhead and bloat.
+
+Translations of the --help output should not be longer than 22 lines long.
+Feel free to leave out the less useful options to save space. (not even
+the English help text has all the options)
+
+I think these are the most important options:
+
+*** selection ***
+-C  by command name list
+-G  by real group ID list (supports names)
+-U  by real user ID list (supports names)
+-u  by effective user ID list (supports names)
+-e  all processes
+-p  by process ID list
+
+*** output ***
+--no-heading  No header line.
+-o,o          user-defined output
+-j,j          job control format
+-l,l          long format
+-f            full format
+s             signal format
+u             user-oriented format
+--forest      ASCII art forest (process hierarchy)
+c             show true command name
+
+List of man page translators:
+
+de  Wed Jan 10 19:09:15 2001 by Martin Schulze <joey@infodrom.ffis.de>
+es  19 Jan 1999 by Diego Sevilla Ruiz (dsevilla@ditec.um.es)
+fr  09/06/1997 par Christophe Blaess (ccb@club-internet.fr)
+hu  Horv#th Andr#s (the '#' is 'a' w/ '/') <horvatha@rs1.szif.hu>
+it  Traduzione in italiano di Giovanni Bortolozzo <borto@dei.unipd.it>
+it  Revisione parziale di Daniele Giacomini <daniele@evo.it> 30/03/1999
+ja  Tue Nov 14 2000 by NAKANO Takeo <nakano@apm.seikei.ac.jp>
+nl  <manpages-nl@nl.linux.org>
diff --git a/procps-3.2.8/ps/common.h b/procps-3.2.8/ps/common.h
new file mode 100644
index 0000000..0b47d90
--- /dev/null
+++ b/procps-3.2.8/ps/common.h
@@ -0,0 +1,337 @@
+/*
+ * Copyright 1998-2002 by Albert Cahalan; all rights resered.         
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version  
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+
+#ifndef PROCPS_PS_H
+#define PROCPS_PS_H
+
+#include "../proc/procps.h"
+#include "../proc/escape.h"
+#include "../proc/readproc.h"
+
+#if 0
+#define trace(args...) printf(## args)
+#else
+#define trace(args...)
+#endif
+
+
+/***************** GENERAL DEFINE ********************/
+
+
+/* selection list */
+#define SEL_RUID 1
+#define SEL_EUID 2
+#define SEL_SUID 3
+#define SEL_FUID 4
+#define SEL_RGID 5
+#define SEL_EGID 6
+#define SEL_SGID 7
+#define SEL_FGID 8
+#define SEL_PGRP 9
+#define SEL_PID  10
+#define SEL_TTY  11
+#define SEL_SESS 12
+#define SEL_COMM 13
+#define SEL_PPID 14
+
+/* Since an enum could be smashed by a #define, it would be bad. */
+#define U98  0 /* Unix98 standard */    /* This must be 0 */
+#define XXX  1 /* Common extension */
+#define DEC  2 /* Digital Unix */
+#define AIX  3 /* AIX */
+#define SCO  4 /* SCO */
+#define LNX  5 /* Linux original :-) */
+#define BSD  6 /* FreeBSD and OpenBSD */
+#define SUN  7 /* SunOS 5 (Solaris) */
+#define HPU  8 /* HP-UX */
+#define SGI  9 /* Irix */
+#define SOE 10 /* IBM's S/390 OpenEdition */
+#define TST 11 /* test code */
+
+/*
+ * Try not to overflow the output buffer:
+ *    32 pages for env+cmd
+ *    64 kB pages on IA-64
+ *    4 chars for "\377", or 1 when mangling to '?'  (ESC_STRETCH)
+ *    plus some slack for other stuff
+ * That is about 8.5 MB on IA-64, or 0.6 MB on i386
+ *
+ * Sadly, current kernels only supply one page of env/command data.
+ * The buffer is now protected with a guard page, and via other means
+ * to avoid hitting the guard page.
+ */
+
+/* output buffer size */
+#define OUTBUF_SIZE (2 * 64*1024 * ESC_STRETCH)
+
+/******************* PS DEFINE *******************/
+
+// Column flags
+// Justification control for flags field comes first.
+#define CF_JUST_MASK                0x0f
+//      CF_AIXHACK                     0
+#define CF_USER                        1 // left if text, right if numeric
+#define CF_LEFT                        2
+#define CF_RIGHT                       3
+#define CF_UNLIMITED                   4
+#define CF_WCHAN                       5 // left if text, right if numeric
+#define CF_SIGNAL                      6 // right in 9, or 16 if screen_cols>107
+// Then the other flags
+#define CF_PIDMAX             0x00000010 // react to pid_max
+// Only one allowed; use separate bits to catch errors.
+#define CF_PRINT_THREAD_ONLY  0x10000000
+#define CF_PRINT_PROCESS_ONLY 0x20000000
+#define CF_PRINT_EVERY_TIME   0x40000000
+#define CF_PRINT_AS_NEEDED    0x80000000 // means we have no clue, so assume EVERY TIME
+#define CF_PRINT_MASK         0xf0000000
+
+#define needs_for_select (PROC_FILLSTAT | PROC_FILLSTATUS)
+
+/* thread_flags */
+#define TF_B_H         0x0001
+#define TF_B_m         0x0002
+#define TF_U_m         0x0004
+#define TF_U_T         0x0008
+#define TF_U_L         0x0010
+#define TF_show_proc   0x0100  // show the summary line
+#define TF_show_task   0x0200  // show the per-thread lines
+#define TF_show_both   0x0400  // distinct proc/task format lists
+#define TF_loose_tasks 0x0800  // let sorting break up task groups (BSDish)
+#define TF_no_sort     0x1000  // don't know if thread-grouping should survive a sort
+#define TF_no_forest   0x2000  // don't see how to do threads w/ forest option
+#define TF_must_use    0x4000  // options only make sense if LWP/SPID column added
+
+/* personality control flags */
+#define PER_BROKEN_o      0x0001
+#define PER_BSD_h         0x0002
+#define PER_BSD_m         0x0004
+#define PER_IRIX_l        0x0008
+#define PER_FORCE_BSD     0x0010
+#define PER_GOOD_o        0x0020
+#define PER_OLD_m         0x0040
+#define PER_NO_DEFAULT_g  0x0080
+#define PER_ZAP_ADDR      0x0100
+#define PER_SANE_USER     0x0200
+#define PER_HPUX_x        0x0400
+#define PER_SVR4_x        0x0800
+#define PER_BSD_COLS      0x1000
+#define PER_UNIX_COLS     0x2000
+
+/* Simple selections by bit mask */
+#define SS_B_x 0x01
+#define SS_B_g 0x02
+#define SS_U_d 0x04
+#define SS_U_a 0x08
+#define SS_B_a 0x10
+
+/* predefined format flags such as:  -l -f l u s -j */
+#define FF_Uf 0x0001 /* -f */
+#define FF_Uj 0x0002 /* -j */
+#define FF_Ul 0x0004 /* -l */
+#define FF_Bj 0x0008 /* j */
+#define FF_Bl 0x0010 /* l */
+#define FF_Bs 0x0020 /* s */
+#define FF_Bu 0x0040 /* u */
+#define FF_Bv 0x0080 /* v */
+#define FF_LX 0x0100 /* X */
+#define FF_Lm 0x0200 /* m */  /* overloaded: threads, sort, format */
+#define FF_Fc 0x0400 /* --context */  /* Flask security context format */
+
+/* predefined format modifier flags such as:  -l -f l u s -j */
+#define FM_c 0x0001 /* -c */
+#define FM_j 0x0002 /* -j */  /* only set when !sysv_j_format */
+#define FM_y 0x0004 /* -y */
+//#define FM_L 0x0008 /* -L */
+#define FM_P 0x0010 /* -P */
+#define FM_M 0x0020 /* -M */
+//#define FM_T 0x0040 /* -T */
+#define FM_F 0x0080 /* -F */  /* -F also sets the regular -f flags */
+
+/* sorting & formatting */
+/* U,B,G is Unix,BSD,Gnu and then there is the option itself */
+#define SF_U_O      1
+#define SF_U_o      2
+#define SF_B_O      3
+#define SF_B_o      4
+#define SF_B_m      5       /* overloaded: threads, sort, format */
+#define SF_G_sort   6
+#define SF_G_format 7
+
+/* headers */
+#define HEAD_SINGLE 0  /* default, must be 0 */
+#define HEAD_NONE   1
+#define HEAD_MULTI  2
+
+
+/********************** GENERAL TYPEDEF *******************/
+
+/* Other fields that might be useful:
+ *
+ * char *name;     user-defined column name (format specification)
+ * int reverse;    sorting in reverse (sort specification)
+ *
+ * name in place of u
+ * reverse in place of n
+ */
+
+typedef union sel_union {
+  pid_t pid;
+  pid_t ppid;
+  uid_t uid;
+  gid_t gid;
+  dev_t tty;
+  char  cmd[16];  /* this is _not_ \0 terminated */
+} sel_union;
+
+typedef struct selection_node {
+  struct selection_node *next;
+  sel_union *u;  /* used if selection type has a list of values */
+  int n;         /* used if selection type has a list of values */
+  int typecode;
+} selection_node;
+
+typedef struct sort_node {
+  struct sort_node *next;
+  int (*sr)(const proc_t* P, const proc_t* Q); /* sort function */
+  int reverse;   /* can sort backwards */
+  int typecode;
+  int need;
+} sort_node;
+
+typedef struct format_node {
+  struct format_node *next;
+  char *name;                             /* user can override default name */
+  int (*pr)(char *restrict const outbuf, const proc_t *restrict const pp); // print function
+/*  int (* const sr)(const proc_t* P, const proc_t* Q); */ /* sort function */
+  int width;
+  int need;
+  int vendor;                             /* Vendor that invented this */
+  int flags;
+  int typecode;
+} format_node;
+
+typedef struct format_struct {
+  const char *spec; /* format specifier */
+  const char *head; /* default header in the POSIX locale */
+  int (* const pr)(char *restrict const outbuf, const proc_t *restrict const pp); // print function
+  int (* const sr)(const proc_t* P, const proc_t* Q); /* sort function */
+  const int width;
+  const int need;       /* data we will need (files to read, etc.) */
+  const int vendor; /* Where does this come from? */
+  const int flags;
+} format_struct;
+
+/* though ps-specific, needed by general file */
+typedef struct macro_struct {
+  const char *spec; /* format specifier */
+  const char *head; /* default header in the POSIX locale */
+} macro_struct;
+
+/**************** PS TYPEDEF ***********************/
+
+typedef struct aix_struct {
+  const int   desc; /* 1-character format code */
+  const char *spec; /* format specifier */
+  const char *head; /* default header in the POSIX locale */
+} aix_struct;
+
+typedef struct shortsort_struct {
+  const int   desc; /* 1-character format code */
+  const char *spec; /* format specifier */
+} shortsort_struct;
+
+/* Save these options for later: -o o -O O --format --sort */
+typedef struct sf_node {
+  struct sf_node *next;  /* next arg */
+  format_node *f_cooked;  /* convert each arg alone, then merge */
+  sort_node   *s_cooked;  /* convert each arg alone, then merge */
+  char *sf;
+  int sf_code;
+} sf_node;
+
+/********************* UNDECIDED GLOBALS **************/
+
+/* output.c */
+extern void show_one_proc(const proc_t *restrict const p, const format_node *restrict fmt);
+extern void print_format_specifiers(void);
+extern const aix_struct *search_aix_array(const int findme);
+extern const shortsort_struct *search_shortsort_array(const int findme);
+extern const format_struct *search_format_array(const char *findme);
+extern const macro_struct *search_macro_array(const char *findme);
+extern void init_output(void);
+extern int pr_nop(char *restrict const outbuf, const proc_t *restrict const pp);
+
+/* global.c */
+extern void reset_global(void);
+
+/* global.c */
+extern int             all_processes;
+extern const char     *bsd_j_format;
+extern const char     *bsd_l_format;
+extern const char     *bsd_s_format;
+extern const char     *bsd_u_format;
+extern const char     *bsd_v_format;
+extern int             bsd_c_option;
+extern int             bsd_e_option;
+extern uid_t           cached_euid;
+extern dev_t           cached_tty;
+extern char            forest_prefix[4 * 32*1024 + 100];
+extern int             forest_type;
+extern unsigned        format_flags;     /* -l -f l u s -j... */
+extern format_node    *format_list; /* digested formatting options */
+extern unsigned        format_modifiers; /* -c -j -y -P -L... */
+extern int             header_gap;
+extern int             header_type; /* none, single, multi... */
+extern int             include_dead_children;
+extern int             lines_to_next_header;
+extern int             max_line_width;
+extern const char     *namelist_file;
+extern int             negate_selection;
+extern int             page_size;  // "int" for math reasons?
+extern unsigned        personality;
+extern int             prefer_bsd_defaults;
+extern int             running_only;
+extern int             screen_cols;
+extern int             screen_rows;
+extern unsigned long   seconds_since_boot;
+extern selection_node *selection_list;
+extern unsigned        simple_select;
+extern sort_node      *sort_list;
+extern const char     *sysv_f_format;
+extern const char     *sysv_fl_format;
+extern const char     *sysv_j_format;
+extern const char     *sysv_l_format;
+extern unsigned        thread_flags;
+extern int             unix_f_option;
+extern int             user_is_number;
+extern int             wchan_is_number;
+
+/************************* PS GLOBALS *********************/
+
+/* sortformat.c */
+extern int defer_sf_option(const char *arg, int source);
+extern const char *process_sf_options(int localbroken);
+extern void reset_sortformat(void);
+
+/* select.c */
+extern int want_this_proc(proc_t *buf);
+extern const char *select_bits_setup(void);
+
+/* help.c */
+extern const char *help_message;
+
+/* global.c */
+extern void self_info(void);
+
+/* parser.c */
+extern int arg_parse(int argc, char *argv[]);
+
+#endif
diff --git a/procps-3.2.8/ps/display.c b/procps-3.2.8/ps/display.c
new file mode 100644
index 0000000..4574b9c
--- /dev/null
+++ b/procps-3.2.8/ps/display.c
@@ -0,0 +1,594 @@
+/*
+ * Copyright 1998-2003 by Albert Cahalan; all rights resered.
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */                                                                     
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#if (__GNU_LIBRARY__ >= 6)
+# include <locale.h>
+#endif
+
+/* username lookups */
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+
+/* major/minor number */
+#include <sys/sysmacros.h>
+
+#include <signal.h>   /* catch signals */
+
+#include "common.h"
+#include "../proc/wchan.h"
+#include "../proc/version.h"
+#include "../proc/readproc.h"
+#include "../proc/sysinfo.h"
+#include "../proc/sig.h"
+
+#ifndef SIGCHLD
+#define SIGCHLD SIGCLD
+#endif
+
+/* just reports a crash */
+static void signal_handler(int signo){
+  if(signo==SIGPIPE) _exit(0);  /* "ps | head" will cause this */
+  /* fprintf() is not reentrant, but we _exit() anyway */
+  fprintf(stderr,
+    "\n\n"
+    "Signal %d (%s) caught by ps (%s).\n"
+    "Please send bug reports to <feedback@lists.sf.net> or <albert@users.sf.net>\n",
+    signo,
+    signal_number_to_name(signo),
+    procps_version
+  );
+  _exit(signo+128);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+#undef DEBUG
+#ifdef DEBUG
+void init_stack_trace(char *prog_name);
+
+#include <ctype.h>
+
+void hex_dump(void *vp){
+  char *charlist;
+  int i = 0;
+  int line = 45;
+  char *cp = (char *)vp;
+
+  while(line--){
+      printf("%8lx  ", (unsigned long)cp);
+      charlist = cp;
+      cp += 16;
+      for(i=0; i<16; i++){
+        if((charlist[i]>31) && (charlist[i]<127)){
+          printf("%c", charlist[i]);
+        }else{
+          printf(".");
+        }
+      }
+      printf(" ");
+      for(i=0; i<16; i++) printf(" %2x",(unsigned int)((unsigned char)(charlist[i])));
+      printf("\n");
+      i=0;
+  }
+}
+
+static void show_tgid(char *s, int n, sel_union *data){
+  printf("%s  ", s);
+  while(--n){
+    printf("%d,", data[n].tgid);
+  }
+  printf("%d\n", data[0].tgid);
+}
+
+static void show_uid(char *s, int n, sel_union *data){
+  struct passwd *pw_data;
+  printf("%s  ", s);
+  while(--n){
+    pw_data = getpwuid(data[n].uid);
+    if(pw_data) printf("%s,", pw_data->pw_name);
+    else        printf("%d,", data[n].uid);
+  }
+  pw_data = getpwuid(data[n].uid);
+  if(pw_data) printf("%s\n", pw_data->pw_name);
+  else        printf("%d\n", data[n].uid);
+}
+
+static void show_gid(char *s, int n, sel_union *data){
+  struct group *gr_data;
+  printf("%s  ", s);
+  while(--n){
+    gr_data = getgrgid(data[n].gid);
+    if(gr_data) printf("%s,", gr_data->gr_name);
+    else        printf("%d,", data[n].gid);
+  }
+  gr_data = getgrgid(data[n].gid);
+  if(gr_data) printf("%s\n", gr_data->gr_name);
+  else        printf("%d\n", data[n].gid);
+}
+
+static void show_tty(char *s, int n, sel_union *data){
+  printf("%s  ", s);
+  while(--n){
+    printf("%d:%d,", (int)major(data[n].tty), (int)minor(data[n].tty));
+  }
+  printf("%d:%d\n", (int)major(data[n].tty), (int)minor(data[n].tty));
+}
+
+static void show_cmd(char *s, int n, sel_union *data){
+  printf("%s  ", s);
+  while(--n){
+    printf("%.8s,", data[n].cmd);
+  }
+  printf("%.8s\n", data[0].cmd);
+}
+
+static void arg_show(void){
+  selection_node *walk = selection_list;
+  while(walk){
+    switch(walk->typecode){
+    case SEL_RUID: show_uid("RUID", walk->n, walk->u); break;
+    case SEL_EUID: show_uid("EUID", walk->n, walk->u); break;
+    case SEL_SUID: show_uid("SUID", walk->n, walk->u); break;
+    case SEL_FUID: show_uid("FUID", walk->n, walk->u); break;
+    case SEL_RGID: show_gid("RGID", walk->n, walk->u); break;
+    case SEL_EGID: show_gid("EGID", walk->n, walk->u); break;
+    case SEL_SGID: show_gid("SGID", walk->n, walk->u); break;
+    case SEL_FGID: show_gid("FGID", walk->n, walk->u); break;
+    case SEL_PGRP: show_pid("PGRP", walk->n, walk->u); break;
+    case SEL_PID : show_pid("PID ", walk->n, walk->u); break;
+    case SEL_PPID: show_pid("PPID", walk->n, walk->u); break;
+    case SEL_TTY : show_tty("TTY ", walk->n, walk->u); break;
+    case SEL_SESS: show_pid("SESS", walk->n, walk->u); break;
+    case SEL_COMM: show_cmd("COMM", walk->n, walk->u); break;
+    default: printf("Garbage typecode value!\n");
+    }
+    walk = walk->next;
+  }
+}
+
+#endif
+//////////////////////////////////////////////////////////////////////////
+
+
+/***** check the header */
+/* Unix98: must not print empty header */
+static void check_headers(void){
+  format_node *walk = format_list;
+  int head_normal = 0;
+  if(header_type==HEAD_MULTI){
+    header_gap = screen_rows-1;  /* true BSD */
+    return;
+  }
+  if(header_type==HEAD_NONE){
+    lines_to_next_header = -1;  /* old Linux */
+    return;
+  }
+  while(walk){
+    if(!*(walk->name)){
+      walk = walk->next;
+      continue;
+    }
+    if(walk->pr){
+      head_normal++;
+      walk = walk->next;
+      continue;
+    }
+    walk = walk->next;
+  }
+  if(!head_normal) lines_to_next_header = -1; /* how UNIX does --noheader */
+}
+
+/***** check sort needs */
+/* see what files need to be read, etc. */
+static unsigned check_sort_needs(sort_node *walk){
+  unsigned needs = 0;
+  while(walk){
+    needs |= walk->need;
+    walk = walk->next;
+  }
+  return needs;
+}
+
+/***** check needs */
+/* see what files need to be read, etc. */
+static unsigned collect_format_needs(format_node *walk){
+  unsigned needs = 0;
+  while(walk){
+    needs |= walk->need;
+    walk = walk->next;
+  }
+  return needs;
+}
+
+static format_node *proc_format_list;
+static format_node *task_format_list;
+
+static unsigned needs_for_threads;
+static unsigned needs_for_sort;
+static unsigned proc_format_needs;
+static unsigned task_format_needs;
+
+#define needs_for_format (proc_format_needs|task_format_needs)
+
+#define PROC_ONLY_FLAGS (PROC_FILLENV|PROC_FILLARG|PROC_FILLCOM|PROC_FILLMEM)
+
+/***** munge lists and determine openproc() flags */
+static void lists_and_needs(void){
+  check_headers();
+
+  // only care about the difference when showing both
+  if(thread_flags & TF_show_both){
+    format_node pfn, tfn; // junk, to handle special case at begin of list
+    format_node *walk = format_list;
+    format_node *p_end = &pfn;
+    format_node *t_end = &tfn;
+    while(walk){
+      format_node *new = malloc(sizeof(format_node));
+      memcpy(new,walk,sizeof(format_node));
+      p_end->next = walk;
+      t_end->next = new;
+      p_end       = walk;
+      t_end       = new;
+      switch(walk->flags & CF_PRINT_MASK){
+      case CF_PRINT_THREAD_ONLY:
+        p_end->pr   = pr_nop;
+        p_end->need = 0;
+        break;
+      case CF_PRINT_PROCESS_ONLY:
+        t_end->pr   = pr_nop;
+        t_end->need = 0;
+        break;
+      default:
+        fprintf(stderr, "please report this bug\n");
+        // FALL THROUGH
+      case CF_PRINT_AS_NEEDED:
+      case CF_PRINT_EVERY_TIME:
+        break;
+      }
+      walk = walk->next;
+    }
+    t_end->next = NULL;
+    p_end->next = NULL;
+    proc_format_list = pfn.next;
+    task_format_list = tfn.next;
+  }else{
+    proc_format_list = format_list;
+    task_format_list = format_list;
+  }
+
+  proc_format_needs = collect_format_needs(proc_format_list);
+  task_format_needs = collect_format_needs(task_format_list);
+
+  needs_for_sort = check_sort_needs(sort_list);
+
+  // move process-only flags to the process
+  proc_format_needs |= (task_format_needs &~ PROC_ONLY_FLAGS);
+  task_format_needs &= ~PROC_ONLY_FLAGS;
+
+  if(bsd_c_option){
+    proc_format_needs &= ~PROC_FILLARG;
+    needs_for_sort    &= ~PROC_FILLARG;
+  }
+  if(!unix_f_option){
+    proc_format_needs &= ~PROC_FILLCOM;
+    needs_for_sort    &= ~PROC_FILLCOM;
+  }
+  // convert ARG to COM as a standard
+  if(proc_format_needs & PROC_FILLARG){
+    proc_format_needs |= PROC_FILLCOM;
+    proc_format_needs &= ~PROC_FILLARG;
+  }
+  if(bsd_e_option){
+    if(proc_format_needs&PROC_FILLCOM) proc_format_needs |= PROC_FILLENV;
+  }
+  
+  /* FIXME  broken filthy hack -- got to unify some stuff here */
+  if( ( (proc_format_needs|task_format_needs|needs_for_sort) & PROC_FILLWCHAN) && !wchan_is_number)
+    if (open_psdb(namelist_file)) wchan_is_number = 1;
+
+  if(thread_flags&TF_loose_tasks) needs_for_threads |= PROC_LOOSE_TASKS;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+/***** fill in %CPU; not in libproc because of include_dead_children */
+/* Note: for sorting, not display, so 0..0x7fffffff would be OK */
+static int want_this_proc_pcpu(proc_t *buf){
+  unsigned long long used_jiffies;
+  unsigned long pcpu = 0;
+  unsigned long long avail_jiffies;
+
+  if(!want_this_proc(buf)) return 0;
+
+  used_jiffies = buf->utime + buf->stime;
+  if(include_dead_children) used_jiffies += (buf->cutime + buf->cstime);
+
+  avail_jiffies = seconds_since_boot * Hertz - buf->start_time;
+  if(avail_jiffies) pcpu = (used_jiffies << 24) / avail_jiffies;
+
+  buf->pcpu = pcpu;  // fits in an int, summing children on 128 CPUs
+
+  return 1;
+}
+
+/***** just display */
+static void simple_spew(void){
+  proc_t buf;
+  PROCTAB* ptp;
+  ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads);
+  if(!ptp) {
+    fprintf(stderr, "Error: can not access /proc.\n");
+    exit(1);
+  }
+  memset(&buf, '#', sizeof(proc_t));
+  switch(thread_flags & (TF_show_proc|TF_loose_tasks|TF_show_task)){
+  case TF_show_proc:                   // normal non-thread output
+    while(readproc(ptp,&buf)){
+      if(want_this_proc(&buf)){
+        show_one_proc(&buf, proc_format_list);
+      }
+      if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
+      if(buf.environ) free((void*)*buf.environ); // ought to reuse
+    }
+    break;
+  case TF_show_proc|TF_loose_tasks:    // H option
+    while(readproc(ptp,&buf)){
+      proc_t buf2;
+      // must still have the process allocated
+      while(readtask(ptp,&buf,&buf2)){
+        if(!want_this_proc(&buf)) continue;
+        show_one_proc(&buf2, task_format_list);
+      }
+      if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
+      if(buf.environ) free((void*)*buf.environ); // ought to reuse
+    }
+    break;
+  case TF_show_proc|TF_show_task:      // m and -m options
+    while(readproc(ptp,&buf)){
+      if(want_this_proc(&buf)){
+        proc_t buf2;
+        show_one_proc(&buf, proc_format_list);
+        // must still have the process allocated
+        while(readtask(ptp,&buf,&buf2)) show_one_proc(&buf2, task_format_list);
+      }
+      if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
+      if(buf.environ) free((void*)*buf.environ); // ought to reuse
+    }
+    break;
+  case TF_show_task:                   // -L and -T options
+    while(readproc(ptp,&buf)){
+      if(want_this_proc(&buf)){
+        proc_t buf2;
+        // must still have the process allocated
+        while(readtask(ptp,&buf,&buf2)) show_one_proc(&buf2, task_format_list);
+      }
+      if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
+      if(buf.environ) free((void*)*buf.environ); // ought to reuse
+    }
+    break;
+  }
+  closeproc(ptp);
+}
+
+/***** forest output requires sorting by ppid; add start_time by default */
+static void prep_forest_sort(void){
+  sort_node *tmp_list = sort_list;
+  const format_struct *incoming;
+
+  if(!sort_list) {     /* assume start time order */
+    incoming = search_format_array("start_time");
+    if(!incoming) fprintf(stderr, "Could not find start_time!\n");
+    tmp_list = malloc(sizeof(sort_node));
+    tmp_list->reverse = 0;
+    tmp_list->typecode = '?'; /* what was this for? */
+    tmp_list->sr = incoming->sr;
+    tmp_list->need = incoming->need;
+    tmp_list->next = sort_list;
+    sort_list = tmp_list;
+  }
+  /* this is required for the forest option */
+  incoming = search_format_array("ppid");
+  if(!incoming) fprintf(stderr, "Could not find ppid!\n");
+  tmp_list = malloc(sizeof(sort_node));
+  tmp_list->reverse = 0;
+  tmp_list->typecode = '?'; /* what was this for? */
+  tmp_list->sr = incoming->sr;
+  tmp_list->need = incoming->need;
+  tmp_list->next = sort_list;
+  sort_list = tmp_list;
+}
+
+/* we rely on the POSIX requirement for zeroed memory */
+//static proc_t *processes[98*1024];  // FIXME
+static proc_t **processes;
+
+/***** compare function for qsort */
+static int compare_two_procs(const void *a, const void *b){
+  sort_node *tmp_list = sort_list;
+  while(tmp_list){
+    int result;
+    result = (*tmp_list->sr)(*(const proc_t *const*)a, *(const proc_t *const*)b);
+    if(result) return (tmp_list->reverse) ? -result : result;
+    tmp_list = tmp_list->next;
+  }
+  return 0; /* no conclusion */
+}
+
+/***** show pre-sorted array of process pointers */
+static void show_proc_array(PROCTAB *restrict ptp, int n){
+  proc_t **p = processes;
+  while(n--){
+    if(thread_flags & TF_show_proc) show_one_proc(*p, proc_format_list);
+    if(thread_flags & TF_show_task){
+      proc_t buf2;
+      // must still have the process allocated
+      while(readtask(ptp,*p,&buf2)) show_one_proc(&buf2, task_format_list);
+      // must not attempt to free cmdline and environ
+    }
+    /* no point freeing any of this -- won't need more mem */
+//    if((*p)->cmdline) free((void*)*(*p)->cmdline);
+//    if((*p)->environ) free((void*)*(*p)->environ);
+//    memset(*p, '%', sizeof(proc_t)); /* debug */
+//    free(*p);
+    p++;
+  }
+}
+
+/***** show tree */
+/* this needs some optimization work */
+#define ADOPTED(x) 1
+static void show_tree(const int self, const int n, const int level, const int have_sibling){
+  int i = 0;
+  if(level){
+    /* add prefix of "+" or "L" */
+    if(have_sibling) forest_prefix[level-1] = '+';
+    else             forest_prefix[level-1] = 'L';
+    forest_prefix[level] = '\0';
+  }
+  show_one_proc(processes[self],format_list);  /* first show self */
+  /* no point freeing any of this -- won't need more mem */
+//  if(processes[self]->cmdline) free((void*)*processes[self]->cmdline);
+//  if(processes[self]->environ) free((void*)*processes[self]->environ);
+  for(;;){  /* look for children */
+    if(i >= n) return; /* no children */
+    if(processes[i]->ppid == processes[self]->XXXID) break;
+    i++;
+  }
+  if(level){
+    /* change our prefix to "|" or " " for the children */
+    if(have_sibling) forest_prefix[level-1] = '|';
+    else             forest_prefix[level-1] = ' ';
+    forest_prefix[level] = '\0';
+  }
+  for(;;){
+    int self_pid;
+    int more_children = 1;
+    if(i >= n) break; /* over the edge */
+    self_pid=processes[self]->XXXID;
+    if(i+1 >= n)
+      more_children = 0;
+    else
+      if(processes[i+1]->ppid != self_pid) more_children = 0;
+    if(self_pid==1 && ADOPTED(processes[i]) && forest_type!='u')
+      show_tree(i++, n, level,   more_children);
+    else
+      show_tree(i++, n, level+1, more_children);
+    if(!more_children) break;
+  }
+  /* chop prefix that children added -- do we need this? */
+  forest_prefix[level] = '\0';
+//  memset(processes[self], '$', sizeof(proc_t));  /* debug */
+}
+
+/***** show forest */
+static void show_forest(const int n){
+  int i = n;
+  int j;
+  while(i--){   /* cover whole array looking for trees */
+    j = n;
+    while(j--){   /* search for parent: if none, i is a tree! */
+      if(processes[j]->XXXID == processes[i]->ppid) goto not_root;
+    }
+    show_tree(i,n,0,0);
+not_root:
+    ;
+  }
+  /* don't free the array because it takes time and ps will exit anyway */
+}
+
+static int want_this_proc_nop(proc_t *dummy){
+  (void)dummy;
+  return 1;
+}
+
+/***** sorted or forest */
+static void fancy_spew(void){
+  proc_data_t *pd = NULL;
+  PROCTAB *restrict ptp;
+  int n = 0;  /* number of processes & index into array */
+
+  ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads);
+  if(!ptp) {
+    fprintf(stderr, "Error: can not access /proc.\n");
+    exit(1);
+  }
+
+  if(thread_flags & TF_loose_tasks){
+    pd = readproctab2(want_this_proc_nop, want_this_proc_pcpu, ptp);
+  }else{
+    pd = readproctab2(want_this_proc_pcpu, (void*)0xdeadbeaful, ptp);
+  }
+  n = pd->n;
+  processes = pd->tab;
+
+  if(!n) return;  /* no processes */
+  if(forest_type) prep_forest_sort();
+  qsort(processes, n, sizeof(proc_t*), compare_two_procs);
+  if(forest_type) show_forest(n);
+  else show_proc_array(ptp,n);
+  closeproc(ptp);
+}
+
+
+/***** no comment */
+int main(int argc, char *argv[]){
+#if (__GNU_LIBRARY__ >= 6)
+  setlocale (LC_CTYPE, "");
+#endif
+
+#ifdef DEBUG
+  init_stack_trace(argv[0]);
+#else
+  do {
+    struct sigaction sa;
+    int i = 32;
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = signal_handler;
+    sigfillset(&sa.sa_mask);
+    while(i--) switch(i){
+    default:
+      sigaction(i,&sa,NULL);
+    case 0:
+    case SIGINT:   /* ^C */
+    case SIGTSTP:  /* ^Z */
+    case SIGTTOU:  /* see stty(1) man page */
+    case SIGQUIT:  /* ^\ */
+    case SIGPROF:  /* profiling */
+    case SIGKILL:  /* can not catch */
+    case SIGSTOP:  /* can not catch */
+    case SIGWINCH: /* don't care if window size changes */
+      ;
+    }
+  } while (0);
+#endif
+
+  reset_global();  /* must be before parser */
+  arg_parse(argc,argv);
+
+/*  arg_show(); */
+  trace("screen is %ux%u\n",screen_cols,screen_rows);
+/*  printf("sizeof(proc_t) is %d.\n", sizeof(proc_t)); */
+  trace("======= ps output follows =======\n");
+
+  init_output(); /* must be between parser and output */
+
+  lists_and_needs();
+
+  if(forest_type || sort_list) fancy_spew(); /* sort or forest */
+  else simple_spew(); /* no sort, no forest */
+  show_one_proc((proc_t *)-1,format_list); /* no output yet? */
+  return 0;
+}
diff --git a/procps-3.2.8/ps/global.c b/procps-3.2.8/ps/global.c
new file mode 100644
index 0000000..0b3bc5b
--- /dev/null
+++ b/procps-3.2.8/ps/global.c
@@ -0,0 +1,498 @@
+/*
+ * Copyright 1998-2002 by Albert Cahalan; all rights resered.         
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version  
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */                                 
+#include <stdlib.h>
+#include <termios.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+                     
+
+#include "common.h"
+
+#include <sys/sysmacros.h>
+#include "../proc/wchan.h"
+#include "../proc/version.h"
+#include "../proc/sysinfo.h"
+
+
+#ifndef __GNU_LIBRARY__
+#define __GNU_LIBRARY__ -1
+#endif
+#ifndef __GLIBC__
+#define __GLIBC__ -1
+#endif
+#ifndef __GLIBC_MINOR__
+#define __GLIBC_MINOR__ -1
+#endif
+
+
+static const char * saved_personality_text = "You found a bug!";
+
+int             all_processes = -1;
+const char     *bsd_j_format = (const char *)0xdeadbeef;
+const char     *bsd_l_format = (const char *)0xdeadbeef;
+const char     *bsd_s_format = (const char *)0xdeadbeef;
+const char     *bsd_u_format = (const char *)0xdeadbeef;
+const char     *bsd_v_format = (const char *)0xdeadbeef;
+int             bsd_c_option = -1;
+int             bsd_e_option = -1;
+uid_t           cached_euid = -1;
+dev_t           cached_tty = -1;
+char            forest_prefix[4 * 32*1024 + 100];     // FIXME
+int             forest_type = -1;
+unsigned        format_flags = 0xffffffff;   /* -l -f l u s -j... */
+format_node    *format_list = (format_node *)0xdeadbeef; /* digested formatting options */
+unsigned        format_modifiers = 0xffffffff;   /* -c -j -y -P -L... */
+int             header_gap = -1;
+int             header_type = -1;
+int             include_dead_children = -1;
+int             lines_to_next_header = -1;
+const char     *namelist_file = (const char *)0xdeadbeef;
+int             negate_selection = -1;
+int             running_only = -1;
+int             page_size = -1;  // "int" for math reasons?
+unsigned        personality = 0xffffffff;
+int             prefer_bsd_defaults = -1;
+int             screen_cols = -1;
+int             screen_rows = -1;
+unsigned long   seconds_since_boot = -1;
+selection_node *selection_list = (selection_node *)0xdeadbeef;
+unsigned        simple_select = 0xffffffff;
+sort_node      *sort_list = (sort_node *)0xdeadbeef; /* ready-to-use sort list */
+const char     *sysv_f_format = (const char *)0xdeadbeef;
+const char     *sysv_fl_format = (const char *)0xdeadbeef;
+const char     *sysv_j_format = (const char *)0xdeadbeef;
+const char     *sysv_l_format = (const char *)0xdeadbeef;
+unsigned        thread_flags = 0xffffffff;
+int             unix_f_option = -1;
+int             user_is_number = -1;
+int             wchan_is_number = -1;
+
+
+static void reset_selection_list(void){
+  selection_node *old;
+  selection_node *walk = selection_list;
+  if(selection_list == (selection_node *)0xdeadbeef){
+    selection_list = NULL;
+    return;
+  }
+  while(walk){
+    old = walk;
+    walk = old->next;
+    free(old->u);
+    free(old);
+  }
+  selection_list = NULL;
+}
+
+// The rules:
+// 1. Defaults are implementation-specific. (ioctl,termcap,guess)
+// 2. COLUMNS and LINES override the defaults. (standards compliance)
+// 3. Command line options override everything else.
+// 4. Actual output may be more if the above is too narrow.
+//
+// SysV tends to spew semi-wide output in all cases. The args
+// will be limited to 64 or 80 characters, without regard to
+// screen size. So lines of 120 to 160 chars are normal.
+// Tough luck if you want more or less than that! HP-UX has a
+// new "-x" option for 1024-char args in place of comm that
+// we'll implement at some point.
+//
+// BSD tends to make a good effort, then fall back to 80 cols.
+// Use "ww" to get infinity. This is nicer for "ps | less"
+// and "watch ps". It can run faster too.
+static void set_screen_size(void){
+  struct winsize ws;
+  char *columns; /* Unix98 environment variable */
+  char *lines;   /* Unix98 environment variable */
+
+  do{
+    int fd;
+    if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0) break;
+    if(ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0) break;
+    if(ioctl(STDIN_FILENO,  TIOCGWINSZ, &ws) != -1 && ws.ws_col>0 && ws.ws_row>0) break;
+    fd = open("/dev/tty", O_NOCTTY|O_NONBLOCK|O_RDONLY);
+    if(fd != -1){
+      int ret = ioctl(fd, TIOCGWINSZ, &ws);
+      close(fd);
+      if(ret != -1 && ws.ws_col>0 && ws.ws_row>0) break;
+    }
+    // TODO: ought to do tgetnum("co") and tgetnum("li") here
+    ws.ws_col = 80;
+    ws.ws_row = 24;
+  }while(0);
+  screen_cols = ws.ws_col;  // hmmm, NetBSD subtracts 1
+  screen_rows = ws.ws_row;
+
+  // TODO: delete this line
+  if(!isatty(STDOUT_FILENO)) screen_cols = OUTBUF_SIZE;
+
+  columns = getenv("COLUMNS");
+  if(columns && *columns){
+    long t;
+    char *endptr;
+    t = strtol(columns, &endptr, 0);
+    if(!*endptr && (t>0) && (t<(long)OUTBUF_SIZE)) screen_cols = (int)t;
+  }
+
+  lines   = getenv("LINES");
+  if(lines && *lines){
+    long t;
+    char *endptr;
+    t = strtol(lines, &endptr, 0);
+    if(!*endptr && (t>0) && (t<(long)OUTBUF_SIZE)) screen_rows = (int)t;
+  }
+
+  if((screen_cols<9) || (screen_rows<2))
+    fprintf(stderr,"Your %dx%d screen size is bogus. Expect trouble.\n",
+      screen_cols, screen_rows
+    );
+}
+
+/**************** personality control **************/
+
+typedef struct personality_table_struct {
+  const char *name; /* personality name */
+  const void *jump; /* See gcc extension info.   :-)   */
+} personality_table_struct;
+
+static int compare_personality_table_structs(const void *a, const void *b){
+  return strcasecmp(((const personality_table_struct*)a)->name,((const personality_table_struct*)b)->name);
+}
+
+static const char *set_personality(void){
+  const char *s;
+  size_t sl;
+  char buf[16];
+  personality_table_struct findme = { buf, NULL};
+  personality_table_struct *found;
+  static const personality_table_struct personality_table[] = {
+  {"390",      &&case_390},
+  {"aix",      &&case_aix},
+  {"bsd",      &&case_bsd},
+  {"compaq",   &&case_compaq},
+  {"debian",   &&case_debian},
+  {"default",  &&case_default},
+  {"digital",  &&case_digital},
+  {"gnu",      &&case_gnu},
+  {"hp",       &&case_hp},
+  {"hpux",     &&case_hpux},
+  {"irix",     &&case_irix},
+  {"linux",    &&case_linux},
+  {"old",      &&case_old},
+  {"os390",    &&case_os390},
+  {"posix",    &&case_posix},
+  {"s390",     &&case_s390},
+  {"sco",      &&case_sco},
+  {"sgi",      &&case_sgi},
+  {"solaris2", &&case_solaris2},
+  {"sunos4",   &&case_sunos4},
+  {"svr4",     &&case_svr4},
+  {"sysv",     &&case_sysv},
+  {"tru64",    &&case_tru64},
+  {"unix",     &&case_unix},
+  {"unix95",   &&case_unix95},
+  {"unix98",   &&case_unix98},
+  {"unknown",  &&case_unknown}
+  };
+  const int personality_table_count = sizeof(personality_table)/sizeof(personality_table_struct);
+
+  personality = 0;
+  prefer_bsd_defaults = 0;
+
+  bsd_j_format = "OL_j";
+  bsd_l_format = "OL_l";
+  bsd_s_format = "OL_s";
+  bsd_u_format = "OL_u";
+  bsd_v_format = "OL_v";
+
+  /* When these are NULL, the code does SysV output modifier logic */
+  sysv_f_format  = NULL;
+  sysv_fl_format = NULL;
+  sysv_j_format  = NULL;
+  sysv_l_format  = NULL;
+
+  s = getenv("PS_PERSONALITY");
+  if(!s || !*s) s = getenv("CMD_ENV");
+  if(!s || !*s) s="unknown";   /* "Do The Right Thing[tm]" */
+  if(getenv("I_WANT_A_BROKEN_PS")) s="old";
+  sl = strlen(s);
+  if(sl > 15) return "Environment specified an unknown personality.";
+  strncpy(buf, s, sl);
+  buf[sl] = '\0';
+  saved_personality_text = strdup(buf);
+
+  found = bsearch(&findme, personality_table, personality_table_count,
+      sizeof(personality_table_struct), compare_personality_table_structs
+  );
+
+  if(!found) return "Environment specified an unknown personality.";
+
+  goto *(found->jump);    /* See gcc extension info.  :-)   */
+
+  case_bsd:
+    personality = PER_FORCE_BSD | PER_BSD_h | PER_BSD_m;
+    prefer_bsd_defaults = 1;
+    bsd_j_format = "FB_j";
+    bsd_l_format = "FB_l";
+    /* bsd_s_format not used */
+    bsd_u_format = "FB_u";
+    bsd_v_format = "FB_v";
+    return NULL;
+
+  case_old:
+    personality = PER_FORCE_BSD | PER_OLD_m;
+    prefer_bsd_defaults = 1;
+    return NULL;
+
+  case_debian:  /* Toss this? They don't seem to care much. */
+  case_gnu:
+    personality = PER_GOOD_o | PER_OLD_m;
+    prefer_bsd_defaults = 1;
+    sysv_f_format  = "RD_f";
+    /* sysv_fl_format = "RD_fl"; */   /* old Debian ps can't do this! */
+    sysv_j_format  = "RD_j";
+    sysv_l_format  = "RD_l";
+    return NULL;
+
+  case_linux:
+    personality = PER_GOOD_o | PER_ZAP_ADDR | PER_SANE_USER;
+    return NULL;
+
+  case_default: /* use defaults for ps, ignoring other environment variables */
+    return NULL;
+
+  case_unknown: /* defaults, but also check inferior environment variables */
+    if(
+      getenv("UNIX95")     /* Irix */
+      || getenv("POSIXLY_CORRECT")  /* most gnu stuff */
+      || (getenv("POSIX2") && !strcmp(getenv("POSIX2"), "on")) /* Unixware 7 */
+    ) personality = PER_BROKEN_o;
+    return NULL;
+
+  case_aix:
+    bsd_j_format = "FB_j";
+    bsd_l_format = "FB_l";
+    /* bsd_s_format not used */
+    bsd_u_format = "FB_u";
+    bsd_v_format = "FB_v";
+    return NULL;
+
+  case_tru64:
+  case_compaq:
+  case_digital:
+    // no PER_NO_DEFAULT_g even though man page claims it
+    // Reality: the g is a NOP
+    personality = PER_GOOD_o | PER_BSD_h;
+    prefer_bsd_defaults = 1;
+    sysv_f_format  = "F5FMT";
+    sysv_fl_format = "FL5FMT";
+    sysv_j_format  = "JFMT";
+    sysv_l_format  = "L5FMT";
+    bsd_j_format = "JFMT";
+    bsd_l_format = "LFMT";
+    bsd_s_format = "SFMT";
+    bsd_u_format = "UFMT";
+    bsd_v_format = "VFMT";
+    return NULL;
+
+  case_sunos4:
+    personality = PER_NO_DEFAULT_g;
+    prefer_bsd_defaults = 1;
+    bsd_j_format = "FB_j";
+    bsd_l_format = "FB_l";
+    /* bsd_s_format not used */
+    bsd_u_format = "FB_u";
+    bsd_v_format = "FB_v";
+    return NULL;
+
+  case_irix:
+  case_sgi:
+    s = getenv("_XPG");
+    if(s && s[0]>'0' && s[0]<='9') personality = PER_BROKEN_o;
+    else personality = PER_IRIX_l;
+    return NULL;
+
+  case_os390:  /* IBM's OS/390 OpenEdition on the S/390 mainframe */
+  case_s390:
+  case_390:
+    sysv_j_format  = "J390";  /* don't know what -jl and -jf do */
+    return NULL;
+
+  case_hp:
+  case_hpux:
+    personality = PER_BROKEN_o | PER_HPUX_x;
+    return NULL;
+
+  case_svr4:
+  case_sysv:
+  case_sco:
+    personality = PER_BROKEN_o | PER_SVR4_x;
+    return NULL;
+
+  case_posix:
+  case_solaris2:
+  case_unix95:
+  case_unix98:
+  case_unix:
+    personality = PER_BROKEN_o;
+    return NULL;
+}
+
+
+/************ Call this to reinitialize everything ***************/
+void reset_global(void){
+  static proc_t p;
+  reset_selection_list();
+  look_up_our_self(&p);
+  set_screen_size();
+  set_personality();
+  
+  all_processes         = 0;
+  bsd_c_option          = 0;
+  bsd_e_option          = 0;
+  cached_euid           = geteuid();
+  cached_tty            = p.tty;
+/* forest_prefix must be all zero because of POSIX */
+  forest_type           = 0;
+  format_flags          = 0;   /* -l -f l u s -j... */
+  format_list           = NULL; /* digested formatting options */
+  format_modifiers      = 0;   /* -c -j -y -P -L... */
+  header_gap            = -1;  /* send lines_to_next_header to -infinity */
+  header_type           = HEAD_SINGLE;
+  include_dead_children = 0;
+  lines_to_next_header  = 1;
+  namelist_file         = NULL;
+  negate_selection      = 0;
+  page_size             = getpagesize();
+  running_only          = 0;
+  seconds_since_boot    = uptime(0,0);
+  selection_list        = NULL;
+  simple_select         = 0;
+  sort_list             = NULL;
+  thread_flags          = 0;
+  unix_f_option         = 0;
+  user_is_number        = 0;
+  wchan_is_number       = 0;
+}
+
+static const char archdefs[] =
+#ifdef __alpha__
+" alpha"
+#endif
+#ifdef __arm__
+" arm"
+#endif
+#ifdef __hppa__
+" hppa"
+#endif
+#ifdef __i386__
+" i386"
+#endif
+#ifdef __ia64__
+" ia64"
+#endif
+#ifdef __mc68000__
+" mc68000"
+#endif
+#ifdef __mips64__
+" mips64"
+#endif
+#ifdef __mips__
+" mips"
+#endif
+#ifdef __powerpc__
+" powerpc"
+#endif
+#ifdef __sh3__
+" sh3"
+#endif
+#ifdef __sh__
+" sh"
+#endif
+#ifdef __sparc__
+" sparc"
+#endif
+#ifdef __sparc_v9__
+" sparc_v9"
+#endif
+#ifdef __x86_64__
+" x86_64"
+#endif
+"";
+
+/*********** spew variables ***********/
+void self_info(void){
+  fprintf(stderr,
+    "BSD j    %s\n"
+    "BSD l    %s\n"
+    "BSD s    %s\n"
+    "BSD u    %s\n"
+    "BSD v    %s\n"
+    "SysV -f  %s\n"
+    "SysV -fl %s\n"
+    "SysV -j  %s\n"
+    "SysV -l  %s\n"
+    "\n",
+    bsd_j_format   ? bsd_j_format   : "(none)",
+    bsd_l_format   ? bsd_l_format   : "(none)",
+    bsd_s_format   ? bsd_s_format   : "(none)",
+    bsd_u_format   ? bsd_u_format   : "(none)",
+    bsd_v_format   ? bsd_v_format   : "(none)",
+    sysv_f_format  ? sysv_f_format  : "(none)",
+    sysv_fl_format ? sysv_fl_format : "(none)",
+    sysv_j_format  ? sysv_j_format  : "(none)",
+    sysv_l_format  ? sysv_l_format  : "(none)"
+  );
+
+  display_version();
+  fprintf(stderr, "Linux version %d.%d.%d\n",
+    LINUX_VERSION_MAJOR(linux_version_code),
+    LINUX_VERSION_MINOR(linux_version_code),
+    LINUX_VERSION_PATCH(linux_version_code)
+  );
+  /* __libc_print_version(); */  /* how can we get the run-time version? */
+  fprintf(stderr, "Compiled with: glibc %d.%d, gcc %d.%d\n\n",
+    __GLIBC__, __GLIBC_MINOR__, __GNUC__, __GNUC_MINOR__
+  );
+
+  fprintf(stderr,
+    "header_gap=%d lines_to_next_header=%d\n"
+    "screen_cols=%d screen_rows=%d\n"
+    "\n",
+    header_gap, lines_to_next_header,
+    screen_cols, screen_rows
+  );
+
+  fprintf(stderr,
+    "personality=0x%08x (from \"%s\")\n"
+    "EUID=%d TTY=%d,%d Hertz=%Ld page_size=%d\n",
+    personality, saved_personality_text,
+    cached_euid, (int)major(cached_tty), (int)minor(cached_tty), Hertz,
+    (int)(page_size)
+  );
+
+  fprintf(stderr,
+    "sizeof(proc_t)=%d sizeof(long)=%d sizeof(KLONG)=%d\n",
+    (int)sizeof(proc_t), (int)sizeof(long), (int)sizeof(KLONG)
+  );
+
+  fprintf(stderr, "archdefs:%s\n", archdefs);
+
+  open_psdb(namelist_file);
+  fprintf(stderr,"namelist_file=\"%s\"\n",namelist_file?namelist_file:"<no System.map file>");
+}
diff --git a/procps-3.2.8/ps/help.c b/procps-3.2.8/ps/help.c
new file mode 100644
index 0000000..2f39a9d
--- /dev/null
+++ b/procps-3.2.8/ps/help.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1998-2004 by Albert Cahalan; all rights reserved.
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+
+/*
+ * The help message must not become longer, because it must fit
+ * on an 80x24 screen _with_ the error message and command prompt.
+ */
+
+const char *help_message =
+"********* simple selection *********  ********* selection by list *********\n"
+"-A all processes                      -C by command name\n"
+"-N negate selection                   -G by real group ID (supports names)\n"
+"-a all w/ tty except session leaders  -U by real user ID (supports names)\n"
+"-d all except session leaders         -g by session OR by effective group name\n"
+"-e all processes                      -p by process ID\n"
+"T  all processes on this terminal     -s processes in the sessions given\n"
+"a  all w/ tty, including other users  -t by tty\n"
+"g  OBSOLETE -- DO NOT USE             -u by effective user ID (supports names)\n"
+"r  only running processes             U  processes for specified users\n"
+"x  processes w/o controlling ttys     t  by tty\n"
+"*********** output format **********  *********** long options ***********\n"
+"-o,o user-defined  -f full            --Group --User --pid --cols --ppid\n"
+"-j,j job control   s  signal          --group --user --sid --rows --info\n"
+"-O,O preloaded -o  v  virtual memory  --cumulative --format --deselect\n"
+"-l,l long          u  user-oriented   --sort --tty --forest --version\n"
+"-F   extra full    X  registers       --heading --no-heading --context\n"
+"                    ********* misc options *********\n"
+"-V,V  show version      L  list format codes  f  ASCII art forest\n"
+"-m,m,-L,-T,H  threads   S  children in sum    -y change -l format\n"
+"-M,Z  security data     c  true command name  -c scheduling class\n"
+"-w,w  wide output       n  numeric WCHAN,UID  -H process hierarchy\n"
+;
+
+
+
+/* Missing:
+ *
+ * -P e k
+ *
+ */
diff --git a/procps-3.2.8/ps/it b/procps-3.2.8/ps/it
new file mode 100644
index 0000000..07fd6dc
--- /dev/null
+++ b/procps-3.2.8/ps/it
@@ -0,0 +1,35 @@
+From ddainese@dsi.unive.it Sun Apr 18 14:12:27 1999
+
+here is a first translation of the text:
+---------------------------------------------------------------------
+const char *help_message =
+"****** seleziona i processi *******   * seleziona una lista specificando: *\n"
+"-A tutti                              -C il nome del comando\n"
+"-N nega la selezione                  -G il real group ID (supporta i nomi)\n"
+"-a con tty, tranne i session leader   -U il real user ID (supporta i nomi)\n"
+"-d tutti, tranne i session leader     -g il session leader OPPURE il gruppo\n"
+"-e tutti                              -p l'ID del processo\n"
+"T  su questo terminale                -s la sessione\n"
+"a  con tty, di tutti gli utenti       -t il tty\n"
+"g  tutti, anche i leader di gruppo    -u l'effective user ID (supporta i nomi)\n"
+"r  in stato running                   U  una lista di utenti\n"
+"x  senza tty                          t  il tty\n"
+"******** formato dell'output ******   ********** opzioni lunghe **********\n"
+"-o,o definito dall'utente                --Group --User --pid --cols\n"
+"-j,j job              s segnali          --group --user --sid --rows\n"
+"-O,O -o preimpostato  v memoria virtuale --cumulative --format --deselect\n"
+"-l,l lungo            u utenti           --sort --tty --forest --version\n"
+"-f   completo         X registri         --heading --no-heading\n"
+"                    ******** opzioni varie *********\n"
+"-V,V versione           L  codici di formato       f  foresta di ASCII\n"
+"-m,m vista ad albero    S  figli in sum           -y  cambia il formato -l\n"
+"-n,N namelist file      c  nome reale del comando  n  WCHAN,UID numerici\n"
+"-w,w output ampio       e  mostra l'environment   -H  gerarchia dei processi\n"
+;
+---------------------------------------------------------------------
+
+Unfortunately it isn't really understandable for a newbie, because
+there is too little space for a good translation; to make it more
+meaningful, I would need about an entire line for every option, thus
+if you really want the help text stays under 22 lines, it must
+contains only 22 options. What do you think about it?
diff --git a/procps-3.2.8/ps/module.mk b/procps-3.2.8/ps/module.mk
new file mode 100755
index 0000000..fbe5ed5
--- /dev/null
+++ b/procps-3.2.8/ps/module.mk
@@ -0,0 +1,40 @@
+# This file gets included into the main Makefile, in the top directory.
+
+INSTALL += $(bin)ps $(man1)ps.1
+
+# files to remove
+CLEAN += ps/ps ps/debug
+
+# a directory for cleaning
+DIRS += ps/
+
+# a file to create
+ALL += ps/ps
+
+PS_C    := display global help output parser select sortformat
+PSNAMES := $(addprefix ps/,$(PS_C))
+PSOBJ   := $(addsuffix .o,$(PSNAMES))
+PSSRC   := $(addsuffix .c,$(PSNAMES))
+
+PS_X := COPYING HACKING TRANSLATION common.h module.mk it p ps.1 regression
+TARFILES += $(PSSRC) $(addprefix ps/,$(PS_X))
+
+ps/ps: $(PSOBJ) $(LIBPROC)
+	$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $^ $(ldl)
+
+# This just adds the stacktrace code
+ps/debug: $(PSOBJ) stacktrace.o $(LIBPROC)
+	$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $^ -lefence $(ldl)
+
+$(PSOBJ): %.o: %.c ps/common.h $(LIBPROC)
+	$(CC) -c $(ALL_CPPFLAGS) $(ALL_CFLAGS) $< -o $@
+
+ps/stacktrace.o: ps/stacktrace.c
+
+
+$(bin)ps: ps/ps
+	$(install) --mode 775 $< $@
+
+$(man1)ps.1 : ps/ps.1
+	$(install) --mode a=r $< $@
+	-rm -f $(DESTDIR)/var/catman/cat1/ps.1.gz $(DESTDIR)/var/man/cat1/ps.1.gz
diff --git a/procps-3.2.8/ps/output.c b/procps-3.2.8/ps/output.c
new file mode 100644
index 0000000..87bf9de
--- /dev/null
+++ b/procps-3.2.8/ps/output.c
@@ -0,0 +1,1969 @@
+/*
+ * Copyright 1999-2004 by Albert Cahalan; all rights reserved.
+ *
+ * This file may be used subject to the terms and conditions of the
+ * GNU Library General Public License Version 2, or any later version
+ * at your option, as published by the Free Software Foundation.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ */
+
+/*
+ * This file is really gross, and I know it. I looked into several
+ * alternate ways to deal with the mess, and they were all ugly.
+ *
+ * FreeBSD has a fancy hack using offsets into a struct -- that
+ * saves code but it is _really_ gross. See the PO macro below.
+ *
+ * We could have a second column width for wide output format.
+ * For example, Digital prints the real-time signals.
+ */
+
+
+/*
+ * Data table idea:
+ *
+ * table 1 maps aix to specifier
+ * table 2 maps shortsort to specifier
+ * table 3 maps macro to specifiers
+ * table 4 maps specifier to title,datatype,offset,vendor,helptext
+ * table 5 maps datatype to justification,width,widewidth,sorting,printing
+ *
+ * Here, "datatype" could be user,uid,u16,pages,deltaT,signals,tty,longtty...
+ * It must be enough to determine printing and sorting.
+ *
+ * After the tables, increase width as needed to fit the header.
+ *
+ * Table 5 could go in a file with the output functions.
+ */
+ 
+#include <ctype.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <unistd.h>
+#include <dlfcn.h>
+
+#include "../proc/readproc.h"
+#include "../proc/sysinfo.h"
+#include "../proc/wchan.h"
+#include "../proc/procps.h"
+#include "../proc/devname.h"
+#include "../proc/escape.h"
+#include "common.h"
+
+/* TODO:
+ * Stop assuming system time is local time.
+ */
+
+#define COLWID 240 /* satisfy snprintf, which is faster than sprintf */
+
+static unsigned max_rightward = 0x12345678; /* space for RIGHT stuff */
+static unsigned max_leftward = 0x12345678; /* space for LEFT stuff */
+
+
+
+static int wide_signals;  /* true if we have room */
+
+static unsigned long seconds_since_1970;
+static unsigned long time_of_boot;
+static unsigned long page_shift;
+
+
+/*************************************************************************/
+/************ Lots of sort functions, starting with the NOP **************/
+
+static int sr_nop(const proc_t* a, const proc_t* b){
+  (void)a;(void)b; /* shut up gcc */
+  return 0;
+}
+
+#define CMP_STR(NAME) \
+static int sr_ ## NAME(const proc_t* P, const proc_t* Q) { \
+    return strcmp(P->NAME, Q->NAME); \
+}
+
+#define CMP_INT(NAME) \
+static int sr_ ## NAME (const proc_t* P, const proc_t* Q) { \
+    if (P->NAME < Q->NAME) return -1; \
+    if (P->NAME > Q->NAME) return  1; \
+    return 0; \
+}
+
+/* fast version, for values which either:
+ * a. differ by no more than 0x7fffffff
+ * b. only need to be grouped same w/ same
+ */
+#define CMP_SMALL(NAME) \
+static int sr_ ## NAME (const proc_t* P, const proc_t* Q) { \
+    return (int)(P->NAME) - (int)(Q->NAME); \
+}
+
+CMP_INT(rtprio)
+CMP_SMALL(sched)
+CMP_INT(cutime)
+CMP_INT(cstime)
+CMP_SMALL(priority)                                             /* nice */
+CMP_SMALL(nlwp)
+CMP_SMALL(nice)                                                 /* priority */
+CMP_INT(rss)      /* resident set size from stat file */ /* vm_rss, resident */
+CMP_INT(alarm)
+CMP_INT(size)      /* total pages */                     /* vm_size, vsize */
+CMP_INT(resident)  /* resident pages */                     /* vm_rss, rss */
+CMP_INT(share)     /* shared pages */
+CMP_INT(trs)       /* executable pages */
+CMP_INT(lrs)       /* obsolete "library" pages above 0x60000000 */
+CMP_INT(drs)       /* other pages (assumed data?) */
+CMP_INT(dt)        /* dirty pages */
+
+CMP_INT(vm_size)    /* kB VM */                             /* size, vsize */
+CMP_INT(vm_lock)    /* kB locked */
+CMP_INT(vm_rss)     /* kB rss */                          /* rss, resident */
+CMP_INT(vm_data)    /* kB "data" == data-stack */
+CMP_INT(vm_stack)   /* kB stack */
+CMP_INT(vm_exe)     /* kB "exec" == exec-lib */
+CMP_INT(vm_lib)     /* kB "libraries" */
+CMP_INT(vsize)      /* pages VM */                        /* size, vm_size */
+CMP_INT(rss_rlim)
+CMP_SMALL(flags)
+CMP_INT(min_flt)
+CMP_INT(maj_flt)
+CMP_INT(cmin_flt)
+CMP_INT(cmaj_flt)
+CMP_INT(utime)
+CMP_INT(stime)    /* Old: sort by systime. New: show start time. Uh oh. */
+CMP_INT(start_code)
+CMP_INT(end_code)
+CMP_INT(start_stack)
+CMP_INT(kstk_esp)
+CMP_INT(kstk_eip)
+CMP_INT(start_time)
+CMP_INT(wchan)
+
+/* CMP_STR(*environ) */
+/* CMP_STR(*cmdline) */
+
+CMP_STR(ruser)
+CMP_STR(euser)
+CMP_STR(suser)
+CMP_STR(fuser)
+CMP_STR(rgroup)
+CMP_STR(egroup)
+CMP_STR(sgroup)
+CMP_STR(fgroup)
+CMP_STR(cmd)
+/* CMP_STR(ttyc) */    /* FIXME -- use strncmp with 8 max */
+
+CMP_INT(ruid)
+CMP_INT(rgid)
+CMP_INT(euid)
+CMP_INT(egid)
+CMP_INT(suid)
+CMP_INT(sgid)
+CMP_INT(fuid)
+CMP_INT(fgid)
+CMP_SMALL(tid)
+CMP_SMALL(tgid)
+CMP_SMALL(ppid)
+CMP_SMALL(pgrp)
+CMP_SMALL(session)
+CMP_INT(tty)
+CMP_SMALL(tpgid)
+
+CMP_SMALL(pcpu)
+
+CMP_SMALL(state)
+
+/* approximation to: kB of address space that could end up in swap */
+static int sr_swapable(const proc_t* P, const proc_t* Q) {
+  unsigned long p_swapable = P->vm_data + P->vm_stack;
+  unsigned long q_swapable = Q->vm_data + Q->vm_stack;
+  if (p_swapable < q_swapable) return -1;
+  if (p_swapable > q_swapable) return  1;
+  return 0;
+}
+
+
+/***************************************************************************/
+/************ Lots of format functions, starting with the NOP **************/
+
+// so popular it can't be "static"
+int pr_nop(char *restrict const outbuf, const proc_t *restrict const pp){
+  (void)pp;
+  return snprintf(outbuf, COLWID, "%c", '-');
+}
+
+
+/********* Unix 98 ************/
+
+/***
+
+Only comm and args are allowed to contain blank characters; all others are
+not. Any implementation-dependent variables will be specified in the system
+documentation along with the default header and indicating if the field
+may contain blank characters.
+
+Some headers do not have a standardized specifier!
+
+%CPU	pcpu	The % of cpu time used recently, with unspecified "recently".
+ADDR		The address of the process.
+C		Processor utilisation for scheduling.
+CMD		The command name, or everything with -f.
+COMMAND	args	Command + args. May chop as desired. May use either version.
+COMMAND	comm	argv[0]
+ELAPSED	etime	Elapsed time since the process was started. [[dd-]hh:]mm:ss
+F		Flags (octal and additive)
+GROUP	group	Effective group ID, prefer text over decimal.
+NI	nice	Decimal system scheduling priority, see nice(1).
+PGID	pgid	The decimal value of the process group ID.
+PID	pid	Decimal PID.
+PPID	ppid	Decimal PID.
+PRI		Priority. Higher numbers mean lower priority.
+RGROUP	rgroup	Real group ID, prefer text over decimal.
+RUSER	ruser	Real user ID, prefer text over decimal.
+S		The state of the process.
+STIME		Starting time of the process.
+SZ		The size in blocks of the core image of the process.
+TIME	time	Cumulative CPU time. [dd-]hh:mm:ss
+TT	tty	Name of tty in format used by who(1).
+TTY		The controlling terminal for the process.
+UID		UID, or name when -f
+USER	user	Effective user ID, prefer text over decimal.
+VSZ	vsz	Virtual memory size in decimal kB.
+WCHAN		Where waiting/sleeping or blank if running.
+
+The nice value is used to compute the priority.
+
+For some undefined ones, Digital does:
+
+F       flag    Process flags -- but in hex!
+PRI     pri     Process priority
+S       state   Symbolic process status
+TTY     tt,tty,tname,longtname  -- all do "ttyp1", "console", "??"
+UID     uid     Process user ID (effective UID)
+WCHAN   wchan   Address of event on which a
+
+For some undefined ones, Sun does:
+
+ADDR	addr	memory address of the process
+C	c	Processor utilization  for  scheduling  (obsolete).
+CMD
+F	f
+S	s	state: OSRZT
+STIME		start time, printed w/o blanks. If 24h old, months & days
+SZ		size (in pages) of the swappable process's image in main memory
+TTY
+UID	uid
+WCHAN	wchan
+
+For some undefined ones, SCO does:
+ADDR	addr	Virtual address of the process' entry in the process table.
+SZ		swappable size in kB of the virtual data and stack
+STIME	stime	hms or md time format
+***/
+
+/* Source & destination are known. Return bytes or screen characters? */
+static int forest_helper(char *restrict const outbuf){
+  char *p = forest_prefix;
+  char *q = outbuf;
+  int rightward=max_rightward;
+  if(!*p) return 0;
+  /* Arrrgh! somebody defined unix as 1 */
+  if(forest_type == 'u') goto unixy;
+  while(*p){
+    switch(*p){
+    case ' ': strcpy(q, "    ");  break;
+    case 'L': strcpy(q, " \\_ "); break;
+    case '+': strcpy(q, " \\_ "); break;
+    case '|': strcpy(q, " |  ");  break;
+    case '\0': return q-outbuf;    /* redundant & not used */
+    }
+    if (rightward-4 < 0) {
+      *(q+rightward)='\0';
+      return max_rightward;
+    }
+    q += 4;
+    rightward -= 4;
+    p++;
+  }
+  return q-outbuf;   /* gcc likes this here */
+unixy:
+  while(*p){
+    switch(*p){
+    case ' ': strcpy(q, "  "); break;
+    case 'L': strcpy(q, "  "); break;
+    case '+': strcpy(q, "  "); break;
+    case '|': strcpy(q, "  "); break;
+    case '\0': return q-outbuf;    /* redundant & not used */
+    }
+    if (rightward-2 < 0) {
+      *(q+rightward)='\0';
+      return max_rightward;
+    }
+    q += 2;
+    rightward -= 2;
+    p++;
+  }
+  return q-outbuf;   /* gcc likes this here */
+}
+
+
+/* XPG4-UNIX, according to Digital:
+The "args" and "command" specifiers show what was passed to the command.
+Modifications to the arguments are not shown.
+*/
+
+/*
+ * pp->cmd       short accounting name (comm & ucomm)
+ * pp->cmdline   long name with args (args & command)
+ * pp->environ   environment
+ */
+
+// FIXME: some of these may hit the guard page in forest mode
+
+/* "command" is the same thing: long unless c */
+static int pr_args(char *restrict const outbuf, const proc_t *restrict const pp){
+  char *endp = outbuf;
+  unsigned flags;
+  int rightward=max_rightward;
+
+  if(forest_prefix){
+    int fh = forest_helper(outbuf);
+    endp += fh;
+    rightward -= fh;
+  }
+  if(bsd_c_option) flags = ESC_DEFUNCT;
+  else             flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS;
+  endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, flags);
+
+  if(bsd_e_option && rightward>1){
+    const char **env = (const char**)pp->environ;
+    if(env && *env){
+      *endp++ = ' ';
+      rightward--;
+      endp += escape_strlist(endp, env, OUTBUF_SIZE, &rightward);
+    }
+  }
+  //return endp - outbuf;
+  return max_rightward-rightward;
+}
+
+/* "ucomm" is the same thing: short unless -f */
+static int pr_comm(char *restrict const outbuf, const proc_t *restrict const pp){
+  char *endp = outbuf;
+  unsigned flags;
+  int rightward=max_rightward;
+  
+  if(forest_prefix){
+    int fh = forest_helper(outbuf);
+    endp += fh;
+    rightward -= fh;
+  }
+  if(unix_f_option) flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS;
+  else              flags = ESC_DEFUNCT;
+  endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, flags);
+
+  if(bsd_e_option && rightward>1){
+    const char **env = (const char**)pp->environ;
+    if(env && *env){
+      *endp++ = ' ';
+      rightward--;
+      endp += escape_strlist(endp, env, OUTBUF_SIZE, &rightward);
+    }
+  }
+  //return endp - outbuf;
+  return max_rightward-rightward;
+}
+/* Non-standard, from SunOS 5 */
+static int pr_fname(char *restrict const outbuf, const proc_t *restrict const pp){
+  char *endp = outbuf;
+  int rightward = max_rightward;
+  
+  if(forest_prefix){
+    int fh = forest_helper(outbuf);
+    endp += fh;
+    rightward -= fh;
+  }
+  if (rightward>8)  /* 8=default, but forest maybe feeds more */
+    rightward = 8;
+  
+  endp += escape_str(endp, pp->cmd, OUTBUF_SIZE, &rightward);
+  //return endp - outbuf;
+  return max_rightward-rightward;
+}
+
+/* elapsed wall clock time, [[dd-]hh:]mm:ss format (not same as "time") */
+static int pr_etime(char *restrict const outbuf, const proc_t *restrict const pp){
+  unsigned long t;
+  unsigned dd,hh,mm,ss;
+  char *cp = outbuf;
+  t = seconds_since_boot - (unsigned long)(pp->start_time / Hertz);
+  ss = t%60;
+  t /= 60;
+  mm = t%60;
+  t /= 60;
+  hh = t%24;
+  t /= 24;
+  dd = t;
+  cp +=(     dd      ?  snprintf(cp, COLWID, "%u-", dd)           :  0 );
+  cp +=( (dd || hh)  ?  snprintf(cp, COLWID, "%02u:", hh)         :  0 );
+  cp +=                 snprintf(cp, COLWID, "%02u:%02u", mm, ss)       ;
+  return (int)(cp-outbuf);
+}
+
+/* "Processor utilisation for scheduling."  --- we use %cpu w/o fraction */
+static int pr_c(char *restrict const outbuf, const proc_t *restrict const pp){
+  unsigned long long total_time;   /* jiffies used by this process */
+  unsigned pcpu = 0;               /* scaled %cpu, 99 means 99% */
+  unsigned long long seconds;      /* seconds of process life */
+  total_time = pp->utime + pp->stime;
+  if(include_dead_children) total_time += (pp->cutime + pp->cstime);
+  seconds = seconds_since_boot - pp->start_time / Hertz;
+  if(seconds) pcpu = (total_time * 100ULL / Hertz) / seconds;
+  if (pcpu > 99U) pcpu = 99U;
+  return snprintf(outbuf, COLWID, "%2u", pcpu);
+}
+/* normal %CPU in ##.# format. */
+static int pr_pcpu(char *restrict const outbuf, const proc_t *restrict const pp){
+  unsigned long long total_time;   /* jiffies used by this process */
+  unsigned pcpu = 0;               /* scaled %cpu, 999 means 99.9% */
+  unsigned long long seconds;      /* seconds of process life */
+  total_time = pp->utime + pp->stime;
+  if(include_dead_children) total_time += (pp->cutime + pp->cstime);
+  seconds = seconds_since_boot - pp->start_time / Hertz;
+  if(seconds) pcpu = (total_time * 1000ULL / Hertz) / seconds;
+  if (pcpu > 999U)
+    return snprintf(outbuf, COLWID, "%u", pcpu/10U);
+  return snprintf(outbuf, COLWID, "%u.%u", pcpu/10U, pcpu%10U);
+}
+/* this is a "per-mill" format, like %cpu with no decimal point */
+static int pr_cp(char *restrict const outbuf, const proc_t *restrict const pp){
+  unsigned long long total_time;   /* jiffies used by this process */
+  unsigned pcpu = 0;               /* scaled %cpu, 999 means 99.9% */
+  unsigned long long seconds;      /* seconds of process life */
+  total_time = pp->utime + pp->stime;
+  if(include_dead_children) total_time += (pp->cutime + pp->cstime);
+  seconds = seconds_since_boot - pp->start_time / Hertz ;
+  if(seconds) pcpu = (total_time * 1000ULL / Hertz) / seconds;
+  if (pcpu > 999U) pcpu = 999U;
+  return snprintf(outbuf, COLWID, "%3u", pcpu);
+}
+
+static int pr_pgid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%u", pp->pgrp);
+}
+static int pr_pid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%u", pp->tgid);
+}
+static int pr_ppid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%u", pp->ppid);
+}
+
+
+/* cumulative CPU time, [dd-]hh:mm:ss format (not same as "etime") */
+static int pr_time(char *restrict const outbuf, const proc_t *restrict const pp){
+  unsigned long t;
+  unsigned dd,hh,mm,ss;
+  int c;
+  t = (pp->utime + pp->stime) / Hertz;
+  ss = t%60;
+  t /= 60;
+  mm = t%60;
+  t /= 60;
+  hh = t%24;
+  t /= 24;
+  dd = t;
+  c  =( dd ? snprintf(outbuf, COLWID, "%u-", dd) : 0              );
+  c +=( snprintf(outbuf+c, COLWID, "%02u:%02u:%02u", hh, mm, ss)    );
+  return c;
+}
+
+/* HP-UX puts this (I forget, vsz or vsize?) in kB and uses "sz" for pages.
+ * Unix98 requires "vsz" to be kB.
+ * Tru64 does both vsize and vsz like "1.23M"
+ *
+ * Our pp->vm_size is kB and our pp->vsize is pages.
+ *
+ * TODO: add flag for "1.23M" behavior, on this and other columns.
+ */
+static int pr_vsz(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%lu", pp->vm_size);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+// "PRI" is created by "opri", or by "pri" when -c is used.
+//
+// Unix98 only specifies that a high "PRI" is low priority.
+// Sun and SCO add the -c behavior. Sun defines "pri" and "opri".
+// Linux may use "priority" for historical purposes.
+//
+// According to the kernel's fs/proc/array.c and kernel/sched.c source,
+// the kernel reports it in /proc via this:
+//        p->prio - MAX_RT_PRIO
+// such that "RT tasks are offset by -200. Normal tasks are centered
+// around 0, value goes from -16 to +15" but who knows if that is
+// before or after the conversion...
+//
+// <linux/sched.h> says:
+// MAX_RT_PRIO is currently 100.       (so we see 0 in /proc)
+// RT tasks have a p->prio of 0 to 99. (so we see -100 to -1)
+// non-RT tasks are from 100 to 139.   (so we see 0 to 39)
+// Lower values have higher priority, as in the UNIX standard.
+//
+// In any case, pp->priority+100 should get us back to what the kernel
+// has for p->prio.
+//
+// Test results with the "yes" program on a 2.6.x kernel:
+//
+// # ps -C19,_20 -o pri,opri,intpri,priority,ni,pcpu,pid,comm
+// PRI PRI PRI PRI  NI %CPU  PID COMMAND
+//   0  99  99  39  19 10.6 8686 19
+//  34  65  65   5 -20 94.7 8687 _20
+//
+// Grrr. So the UNIX standard "PRI" must NOT be from "pri".
+// Either of the others will do. We use "opri" for this.
+// (and use "pri" when the "-c" option is used)
+// Probably we should have Linux-specific "pri_for_l" and "pri_for_lc"
+//
+// sched_get_priority_min.2 says the Linux static priority is
+// 1..99 for RT and 0 for other... maybe 100 is kernel-only?
+//
+// A nice range would be -99..0 for RT and 1..40 for normal,
+// which is pp->priority+1. (3-digit max, positive is normal,
+// negative or 0 is RT, and meets the standard for PRI)
+//
+
+// legal as UNIX "PRI"
+// "priority"         (was -20..20, now -100..39)
+static int pr_priority(char *restrict const outbuf, const proc_t *restrict const pp){    /* -20..20 */
+    return snprintf(outbuf, COLWID, "%ld", pp->priority);
+}
+
+// legal as UNIX "PRI"
+// "intpri" and "opri" (was 39..79, now  -40..99)
+static int pr_opri(char *restrict const outbuf, const proc_t *restrict const pp){        /* 39..79 */
+    return snprintf(outbuf, COLWID, "%ld", 60 + pp->priority);
+}
+
+// legal as UNIX "PRI"
+// "pri_foo"   --  match up w/ nice values of sleeping processes (-120..19)
+static int pr_pri_foo(char *restrict const outbuf, const proc_t *restrict const pp){
+    return snprintf(outbuf, COLWID, "%ld", pp->priority - 20);
+}
+
+// legal as UNIX "PRI"
+// "pri_bar"   --  makes RT pri show as negative       (-99..40)
+static int pr_pri_bar(char *restrict const outbuf, const proc_t *restrict const pp){
+    return snprintf(outbuf, COLWID, "%ld", pp->priority + 1);
+}
+
+// legal as UNIX "PRI"
+// "pri_baz"   --  the kernel's ->prio value, as of Linux 2.6.8     (1..140)
+static int pr_pri_baz(char *restrict const outbuf, const proc_t *restrict const pp){
+    return snprintf(outbuf, COLWID, "%ld", pp->priority + 100);
+}
+
+
+// not legal as UNIX "PRI"
+// "pri"               (was 20..60, now    0..139)
+static int pr_pri(char *restrict const outbuf, const proc_t *restrict const pp){         /* 20..60 */
+    return snprintf(outbuf, COLWID, "%ld", 39 - pp->priority);
+}
+
+// not legal as UNIX "PRI"
+// "pri_api"   --  match up w/ RT API    (-40..99)
+static int pr_pri_api(char *restrict const outbuf, const proc_t *restrict const pp){
+    return snprintf(outbuf, COLWID, "%ld", -1 - pp->priority);
+}
+
+static int pr_nice(char *restrict const outbuf, const proc_t *restrict const pp){
+  if(pp->sched!=0 && pp->sched!=-1) return snprintf(outbuf, COLWID, "-");
+  return snprintf(outbuf, COLWID, "%ld", pp->nice);
+}
+
+// HP-UX   "cls": RT RR RR2 ???? HPUX FIFO KERN
+// Solaris "class": SYS TS FX IA RT FSS (FIFO is RR w/ Inf quant)
+//                  FIFO+RR share RT; FIFO has Inf quant
+//                  IA=interactive; FX=fixed; TS=timeshare; SYS=system
+//                  FSS=fairshare; INTS=interrupts
+// Tru64   "policy": FF RR TS
+// IRIX    "class": RT TS B BC WL GN
+//                  RT=real-time; TS=time-share; B=batch; BC=batch-critical
+//                  WL=weightless; GN=gang-scheduled
+//                  see miser(1) for this; PRI has some letter codes too
+static int pr_class(char *restrict const outbuf, const proc_t *restrict const pp){
+  switch(pp->sched){
+  case -1: return snprintf(outbuf, COLWID, "-");   // not reported
+  case  0: return snprintf(outbuf, COLWID, "TS");  // SCHED_OTHER SCHED_NORMAL
+  case  1: return snprintf(outbuf, COLWID, "FF");  // SCHED_FIFO
+  case  2: return snprintf(outbuf, COLWID, "RR");  // SCHED_RR
+  case  3: return snprintf(outbuf, COLWID, "B");   // SCHED_BATCH
+  case  4: return snprintf(outbuf, COLWID, "ISO"); // reserved for SCHED_ISO (Con Kolivas)
+  case  5: return snprintf(outbuf, COLWID, "IDL"); // SCHED_IDLE
+  case  6: return snprintf(outbuf, COLWID, "#6");  //
+  case  7: return snprintf(outbuf, COLWID, "#7");  //
+  case  8: return snprintf(outbuf, COLWID, "#8");  //
+  case  9: return snprintf(outbuf, COLWID, "#9");  //
+  default: return snprintf(outbuf, COLWID, "?");   // unknown value
+  }
+}
+// Based on "type", FreeBSD would do:
+//    REALTIME  "real:%u", prio
+//    NORMAL    "normal"
+//    IDLE      "idle:%u", prio
+//    default   "%u:%u", type, prio
+// We just print the priority, and have other keywords for type.
+static int pr_rtprio(char *restrict const outbuf, const proc_t *restrict const pp){
+  if(pp->sched==0 || pp->sched==-1) return snprintf(outbuf, COLWID, "-");
+  return snprintf(outbuf, COLWID, "%ld", pp->rtprio);
+}
+static int pr_sched(char *restrict const outbuf, const proc_t *restrict const pp){
+  if(pp->sched==-1) return snprintf(outbuf, COLWID, "-");
+  return snprintf(outbuf, COLWID, "%ld", pp->sched);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+static int pr_wchan(char *restrict const outbuf, const proc_t *restrict const pp){
+/*
+ * Unix98 says "blank if running" and also "no blanks"! :-(
+ * Unix98 also says to use '-' if something is meaningless.
+ * Digital uses both '*' and '-', with undocumented differences.
+ * (the '*' for -1 (rare) and the '-' for 0)
+ * Sun claims to use a blank AND use '-', in the same man page.
+ * Perhaps "blank" should mean '-'.
+ *
+ * AIX uses '-' for running processes, the location when there is
+ * only one thread waiting in the kernel, and '*' when there is
+ * more than one thread waiting in the kernel.
+ *
+ * The output should be truncated to maximal columns width -- overflow
+ * is not supported for the "wchan".
+ */
+  const char *w;
+  size_t len;
+  if(!(pp->wchan & 0xffffff)) return memcpy(outbuf,"-",2),1;
+  if(wchan_is_number) return snprintf(outbuf, COLWID, "%x", (unsigned)(pp->wchan) & 0xffffffu);
+  w = lookup_wchan(pp->wchan, pp->XXXID);
+  len = strlen(w);
+  if(len>max_rightward) len=max_rightward;
+  memcpy(outbuf, w, len);
+  outbuf[len] = '\0';
+  return len;
+}
+
+static int pr_wname(char *restrict const outbuf, const proc_t *restrict const pp){
+/* SGI's IRIX always uses a number for "wchan", so "wname" is provided too.
+ *
+ * We use '-' for running processes, the location when there is
+ * only one thread waiting in the kernel, and '*' when there is
+ * more than one thread waiting in the kernel.
+ *
+ * The output should be truncated to maximal columns width -- overflow
+ * is not supported for the "wchan".
+ */
+  const char *w;
+  size_t len;
+  if(!(pp->wchan & 0xffffff)) return memcpy(outbuf,"-",2),1;
+  w = lookup_wchan(pp->wchan, pp->XXXID);
+  len = strlen(w);
+  if(len>max_rightward) len=max_rightward;
+  memcpy(outbuf, w, len);
+  outbuf[len] = '\0';
+  return len;
+}
+
+static int pr_nwchan(char *restrict const outbuf, const proc_t *restrict const pp){
+  if(!(pp->wchan & 0xffffff)) return memcpy(outbuf,"-",2),1;
+  return snprintf(outbuf, COLWID, "%x", (unsigned)(pp->wchan) & 0xffffffu);
+}
+
+/* Terrible trunctuation, like BSD crap uses: I999 J999 K999 */
+/* FIXME: disambiguate /dev/tty69 and /dev/pts/69. */
+static int pr_tty4(char *restrict const outbuf, const proc_t *restrict const pp){
+/* snprintf(outbuf, COLWID, "%02x:%02x", pp->tty>>8, pp->tty&0xff); */
+  return dev_to_tty(outbuf, 4, pp->tty, pp->XXXID, ABBREV_DEV|ABBREV_TTY|ABBREV_PTS);
+}
+
+/* Unix98: format is unspecified, but must match that used by who(1). */
+static int pr_tty8(char *restrict const outbuf, const proc_t *restrict const pp){
+/* snprintf(outbuf, COLWID, "%02x:%02x", pp->tty>>8, pp->tty&0xff); */
+  return dev_to_tty(outbuf, COLWID, pp->tty, pp->XXXID, ABBREV_DEV);
+}
+
+#if 0
+/* This BSD state display may contain spaces, which is illegal. */
+static int pr_oldstate(char *restrict const outbuf, const proc_t *restrict const pp){
+    return snprintf(outbuf, COLWID, "%s", status(pp));
+}
+#endif
+
+// This state display is Unix98 compliant and has lots of info like BSD.
+static int pr_stat(char *restrict const outbuf, const proc_t *restrict const pp){
+    int end = 0;
+    outbuf[end++] = pp->state;
+//  if(pp->rss==0 && pp->state!='Z')  outbuf[end++] = 'W'; // useless "swapped out"
+    if(pp->nice < 0)                  outbuf[end++] = '<';
+    if(pp->nice > 0)                  outbuf[end++] = 'N';
+// In this order, NetBSD would add:
+//     traced   'X'
+//     systrace 'x'
+//     exiting  'E' (not printed for zombies)
+//     vforked  'V'
+//     system   'K' (and do not print 'L' too)
+    if(pp->vm_lock)                   outbuf[end++] = 'L';
+    if(pp->session == pp->tgid)       outbuf[end++] = 's'; // session leader
+    if(pp->nlwp > 1)                  outbuf[end++] = 'l'; // multi-threaded
+    if(pp->pgrp == pp->tpgid)         outbuf[end++] = '+'; // in foreground process group
+    outbuf[end] = '\0';
+    return end;
+}
+
+/* This minimal state display is Unix98 compliant, like SCO and SunOS 5 */
+static int pr_s(char *restrict const outbuf, const proc_t *restrict const pp){
+    outbuf[0] = pp->state;
+    outbuf[1] = '\0';
+    return 1;
+}
+
+static int pr_flag(char *restrict const outbuf, const proc_t *restrict const pp){
+    /* Unix98 requires octal flags */
+    /* this user-hostile and volatile junk gets 1 character */
+    return snprintf(outbuf, COLWID, "%o", (unsigned)(pp->flags>>6U)&0x7U);
+}
+
+// plus these: euid,ruid,egroup,rgroup (elsewhere in this file)
+
+/*********** non-standard ***********/
+
+/*** BSD
+sess	session pointer
+(SCO has:Process session leader ID as a decimal value. (SESSION))
+jobc	job control count
+cpu	short-term cpu usage factor (for scheduling)
+sl	sleep time (in seconds; 127 = infinity)
+re	core residency time (in seconds; 127 = infinity)
+pagein	pageins (same as majflt)
+lim	soft memory limit
+tsiz	text size (in Kbytes)
+***/
+
+static int pr_stackp(char *restrict const outbuf, const proc_t *restrict const pp){
+    return snprintf(outbuf, COLWID, "%08x", (unsigned)(pp->start_stack));
+}
+
+static int pr_esp(char *restrict const outbuf, const proc_t *restrict const pp){
+    return snprintf(outbuf, COLWID, "%08x", (unsigned)(pp->kstk_esp));
+}
+
+static int pr_eip(char *restrict const outbuf, const proc_t *restrict const pp){
+    return snprintf(outbuf, COLWID, "%08x", (unsigned)(pp->kstk_eip));
+}
+
+/* This function helps print old-style time formats */
+static int old_time_helper(char *dst, unsigned long long t, unsigned long long rel) {
+  if(!t)            return snprintf(dst, COLWID, "    -");
+  if(t == ~0ULL)    return snprintf(dst, COLWID, "   xx");
+  if((long long)(t-=rel) < 0)  t=0ULL;
+  if(t>9999ULL)     return snprintf(dst, COLWID, "%5Lu", t/100ULL);
+  else              return snprintf(dst, COLWID, "%2u.%02u", (unsigned)t/100U, (unsigned)t%100U);
+}
+
+static int pr_bsdtime(char *restrict const outbuf, const proc_t *restrict const pp){
+    unsigned long long t;
+    unsigned u;
+    t = pp->utime + pp->stime;
+    if(include_dead_children) t += (pp->cutime + pp->cstime);
+    u = t / Hertz;
+    return snprintf(outbuf, COLWID, "%3u:%02u", u/60U, u%60U);
+}
+
+static int pr_bsdstart(char *restrict const outbuf, const proc_t *restrict const pp){
+  time_t start;
+  time_t seconds_ago;
+  start = time_of_boot + pp->start_time / Hertz;
+  seconds_ago = seconds_since_1970 - start;
+  if(seconds_ago < 0) seconds_ago=0;
+  if(seconds_ago > 3600*24)  strcpy(outbuf, ctime(&start)+4);
+  else                       strcpy(outbuf, ctime(&start)+10);
+  outbuf[6] = '\0';
+  return 6;
+}
+
+static int pr_alarm(char *restrict const outbuf, const proc_t *restrict const pp){
+    return old_time_helper(outbuf, pp->alarm, 0ULL);
+}
+
+/* HP-UX puts this in pages and uses "vsz" for kB */
+static int pr_sz(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%lu", (pp->vm_size)/(page_size/1024));
+}
+
+
+/*
+ * FIXME: trs,drs,tsiz,dsiz,m_trs,m_drs,vm_exe,vm_data,trss
+ * I suspect some/all of those are broken. They seem to have been
+ * inherited by Linux and AIX from early BSD systems. FreeBSD only
+ * retains tsiz. The prefixed versions come from Debian.
+ * Sun and Digital have none of this crap. The code here comes
+ * from an old Linux ps, and might not be correct for ELF executables.
+ *
+ * AIX            TRS    size of resident-set (real memory) of text
+ * AIX            TSIZ   size of text (shared-program) image
+ * FreeBSD        tsiz   text size (in Kbytes)
+ * 4.3BSD NET/2   trss   text resident set size (in Kbytes)
+ * 4.3BSD NET/2   tsiz   text size (in Kbytes)
+ */
+
+/* kB data size. See drs, tsiz & trs. */
+static int pr_dsiz(char *restrict const outbuf, const proc_t *restrict const pp){
+    long dsiz = 0;
+    if(pp->vsize) dsiz += (pp->vsize - pp->end_code + pp->start_code) >> 10;
+    return snprintf(outbuf, COLWID, "%ld", dsiz);
+}
+
+/* kB text (code) size. See trs, dsiz & drs. */
+static int pr_tsiz(char *restrict const outbuf, const proc_t *restrict const pp){
+    long tsiz = 0;
+    if(pp->vsize) tsiz += (pp->end_code - pp->start_code) >> 10;
+    return snprintf(outbuf, COLWID, "%ld", tsiz);
+}
+
+/* kB _resident_ data size. See dsiz, tsiz & trs. */
+static int pr_drs(char *restrict const outbuf, const proc_t *restrict const pp){
+    long drs = 0;
+    if(pp->vsize) drs += (pp->vsize - pp->end_code + pp->start_code) >> 10;
+    return snprintf(outbuf, COLWID, "%ld", drs);
+}
+
+/* kB text _resident_ (code) size. See tsiz, dsiz & drs. */
+static int pr_trs(char *restrict const outbuf, const proc_t *restrict const pp){
+    long trs = 0;
+    if(pp->vsize) trs += (pp->end_code - pp->start_code) >> 10;
+    return snprintf(outbuf, COLWID, "%ld", trs);
+}
+
+/* approximation to: kB of address space that could end up in swap */
+static int pr_swapable(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%ld", pp->vm_data + pp->vm_stack);
+}
+
+/* nasty old Debian thing */
+static int pr_size(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%ld", pp->size);
+}
+
+
+static int pr_minflt(char *restrict const outbuf, const proc_t *restrict const pp){
+    long flt = pp->min_flt;
+    if(include_dead_children) flt += pp->cmin_flt;
+    return snprintf(outbuf, COLWID, "%ld", flt);
+}
+
+static int pr_majflt(char *restrict const outbuf, const proc_t *restrict const pp){
+    long flt = pp->maj_flt;
+    if(include_dead_children) flt += pp->cmaj_flt;
+    return snprintf(outbuf, COLWID, "%ld", flt);
+}
+
+static int pr_lim(char *restrict const outbuf, const proc_t *restrict const pp){
+    if(pp->rss_rlim == RLIM_INFINITY){
+      outbuf[0] = 'x';
+      outbuf[1] = 'x';
+      outbuf[2] = '\0';
+      return 2;
+    }
+    return snprintf(outbuf, COLWID, "%5ld", pp->rss_rlim >> 10);
+}
+
+/* should print leading tilde ('~') if process is bound to the CPU */
+static int pr_psr(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%d", pp->processor);
+}
+
+static int pr_rss(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%lu", pp->vm_rss);
+}
+
+/* pp->vm_rss * 1000 would overflow on 32-bit systems with 64 GB memory */
+static int pr_pmem(char *restrict const outbuf, const proc_t *restrict const pp){
+  unsigned long pmem = 0;
+  pmem = pp->vm_rss * 1000ULL / kb_main_total;
+  if (pmem > 999) pmem = 999;
+  return snprintf(outbuf, COLWID, "%2u.%u", (unsigned)(pmem/10), (unsigned)(pmem%10));
+}
+
+static int pr_lstart(char *restrict const outbuf, const proc_t *restrict const pp){
+  time_t t;
+  t = time_of_boot + pp->start_time / Hertz;
+  return snprintf(outbuf, COLWID, "%24.24s", ctime(&t));
+}
+
+/* Unix98 specifies a STIME header for a column that shows the start
+ * time of the process, but does not specify a format or format specifier.
+ * From the general Unix98 rules, we know there must not be any spaces.
+ * Most systems violate that rule, though the Solaris documentation
+ * claims to print the column without spaces. (NOT!)
+ *
+ * So this isn't broken, but could be renamed to u98_std_stime,
+ * as long as it still shows as STIME when using the -f option.
+ */
+static int pr_stime(char *restrict const outbuf, const proc_t *restrict const pp){
+  struct tm *proc_time;
+  struct tm *our_time;
+  time_t t;
+  const char *fmt;
+  int tm_year;
+  int tm_yday;
+  our_time = localtime(&seconds_since_1970);   /* not reentrant */
+  tm_year = our_time->tm_year;
+  tm_yday = our_time->tm_yday;
+  t = time_of_boot + pp->start_time / Hertz;
+  proc_time = localtime(&t); /* not reentrant, this corrupts our_time */
+  fmt = "%H:%M";                                   /* 03:02 23:59 */
+  if(tm_yday != proc_time->tm_yday) fmt = "%b%d";  /* Jun06 Aug27 */
+  if(tm_year != proc_time->tm_year) fmt = "%Y";    /* 1991 2001 */
+  return strftime(outbuf, 42, fmt, proc_time);
+}
+
+static int pr_start(char *restrict const outbuf, const proc_t *restrict const pp){
+  time_t t;
+  char *str;
+  t = time_of_boot + pp->start_time / Hertz;
+  str = ctime(&t);
+  if(str[8]==' ')  str[8]='0';
+  if(str[11]==' ') str[11]='0';
+  if((unsigned long)t+60*60*24 > seconds_since_1970)
+    return snprintf(outbuf, COLWID, "%8.8s", str+11);
+  return snprintf(outbuf, COLWID, "  %6.6s", str+4);
+}
+
+
+#ifdef SIGNAL_STRING
+static int help_pr_sig(char *restrict const outbuf, const char *restrict const sig){
+  long len = 0;
+  len = strlen(sig);
+  if(wide_signals){
+    if(len>8) return snprintf(outbuf, COLWID, "%s", sig);
+    return snprintf(outbuf, COLWID, "00000000%s", sig);
+  }
+  if(len-strspn(sig,"0") > 8)
+    return snprintf(outbuf, COLWID, "<%s", sig+len-8);
+  return snprintf(outbuf, COLWID,  "%s", sig+len-8);
+}
+#else
+static int help_pr_sig(unsigned long long sig){
+  if(wide_signals) return snprintf(outbuf, COLWID, "%016Lx", sig);
+  if(sig>>32)      return snprintf(outbuf, COLWID, "<%08Lx", sig&0xffffffffLL);
+  return                  snprintf(outbuf, COLWID,  "%08Lx", sig&0xffffffffLL);
+}
+#endif
+
+// This one is always thread-specific pending. (from Dragonfly BSD)
+static int pr_tsig(char *restrict const outbuf, const proc_t *restrict const pp){
+  return help_pr_sig(outbuf, pp->_sigpnd);
+}
+// This one is (wrongly?) thread-specific when printing thread lines,
+// but process-pending otherwise.
+static int pr_sig(char *restrict const outbuf, const proc_t *restrict const pp){
+  return help_pr_sig(outbuf, pp->signal);
+}
+static int pr_sigmask(char *restrict const outbuf, const proc_t *restrict const pp){
+  return help_pr_sig(outbuf, pp->blocked);
+}
+static int pr_sigignore(char *restrict const outbuf, const proc_t *restrict const pp){
+  return help_pr_sig(outbuf, pp->sigignore);
+}
+static int pr_sigcatch(char *restrict const outbuf, const proc_t *restrict const pp){
+  return help_pr_sig(outbuf, pp->sigcatch);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * internal terms:  ruid  euid  suid  fuid
+ * kernel vars:      uid  euid  suid fsuid
+ * command args:    ruid   uid svuid   n/a
+ */
+
+static int pr_egid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%d", pp->egid);
+}
+static int pr_rgid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%d", pp->rgid);
+}
+static int pr_sgid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%d", pp->sgid);
+}
+static int pr_fgid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%d", pp->fgid);
+}
+
+static int pr_euid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%d", pp->euid);
+}
+static int pr_ruid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%d", pp->ruid);
+}
+static int pr_suid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%d", pp->suid);
+}
+static int pr_fuid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%d", pp->fuid);
+}
+
+// The Open Group Base Specifications Issue 6 (IEEE Std 1003.1, 2004 Edition)
+// requires that user and group names print as decimal numbers if there is
+// not enough room in the column, so tough luck if you don't like it.
+//
+// The UNIX and POSIX way to change column width is to rename it:
+//      ps -o pid,user=CumbersomeUserNames -o comm
+// The easy way is to directly specify the desired width:
+//      ps -o pid,user:19,comm
+//
+static int do_pr_name(char *restrict const outbuf, const char *restrict const name, unsigned u){
+  if(!user_is_number){
+    int rightward = OUTBUF_SIZE;	/* max cells */
+    int len;				/* real cells */
+    
+    escape_str(outbuf, name, OUTBUF_SIZE, &rightward);
+    len = OUTBUF_SIZE-rightward;
+    
+    if(len <= (int)max_rightward)
+      return len;  /* returns number of cells */
+  }
+  return snprintf(outbuf, COLWID, "%u", u);
+}
+
+static int pr_ruser(char *restrict const outbuf, const proc_t *restrict const pp){
+  return do_pr_name(outbuf, pp->ruser, pp->ruid);
+}
+static int pr_euser(char *restrict const outbuf, const proc_t *restrict const pp){
+  return do_pr_name(outbuf, pp->euser, pp->euid);
+}
+static int pr_fuser(char *restrict const outbuf, const proc_t *restrict const pp){
+  return do_pr_name(outbuf, pp->fuser, pp->fuid);
+}
+static int pr_suser(char *restrict const outbuf, const proc_t *restrict const pp){
+  return do_pr_name(outbuf, pp->suser, pp->suid);
+}
+
+static int pr_egroup(char *restrict const outbuf, const proc_t *restrict const pp){
+  return do_pr_name(outbuf, pp->egroup, pp->egid);
+}
+static int pr_rgroup(char *restrict const outbuf, const proc_t *restrict const pp){
+  return do_pr_name(outbuf, pp->rgroup, pp->rgid);
+}
+static int pr_fgroup(char *restrict const outbuf, const proc_t *restrict const pp){
+  return do_pr_name(outbuf, pp->fgroup, pp->fgid);
+}
+static int pr_sgroup(char *restrict const outbuf, const proc_t *restrict const pp){
+  return do_pr_name(outbuf, pp->sgroup, pp->sgid);
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+// TID tid LWP lwp SPID spid
+static int pr_thread(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%u", pp->tid);
+}
+// thcount THCNT
+static int pr_nlwp(char *restrict const outbuf, const proc_t *restrict const pp){
+    return snprintf(outbuf, COLWID, "%d", pp->nlwp);
+}
+
+static int pr_sess(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%u", pp->session);
+}
+static int pr_tpgid(char *restrict const outbuf, const proc_t *restrict const pp){
+  return snprintf(outbuf, COLWID, "%d", pp->tpgid);
+}
+
+
+/* SGI uses "cpu" to print the processor ID with header "P" */
+static int pr_sgi_p(char *restrict const outbuf, const proc_t *restrict const pp){          /* FIXME */
+  if(pp->state == 'R') return snprintf(outbuf, COLWID, "%d", pp->processor);
+  return snprintf(outbuf, COLWID, "*");
+}
+
+
+/****************** FLASK & seLinux security stuff **********************/
+// move the bulk of this to libproc sometime
+
+static int pr_context(char *restrict const outbuf, const proc_t *restrict const pp){
+  char filename[48];
+  size_t len;
+  ssize_t num_read;
+  int fd;
+
+// wchan file is suitable for testing
+//snprintf(filename, sizeof filename, "/proc/%d/wchan", pp->tgid);
+snprintf(filename, sizeof filename, "/proc/%d/attr/current", pp->tgid);
+
+  fd = open(filename, O_RDONLY, 0);
+  if(likely(fd==-1)) goto fail;
+  num_read = read(fd, outbuf, 666);
+  close(fd);
+  if(unlikely(num_read<=0)) goto fail;
+  outbuf[num_read] = '\0';
+
+  len = 0;
+  while(outbuf[len]>' ' && outbuf[len]<='~') len++;
+  outbuf[len] = '\0';
+  if(len) return len;
+
+fail:
+  outbuf[0] = '-';
+  outbuf[1] = '\0';
+  return 1;
+}
+
+#if 0
+// This needs more study, considering:
+// 1. the static linking option (maybe disable this in that case)
+// 2. the -z and -Z option issue
+// 3. width of output
+static int pr_context(char *restrict const outbuf, const proc_t *restrict const pp){
+  static int (*ps_getpidcon)(pid_t pid, char **context) = 0;
+  static int tried_load = 0;
+  size_t len;
+  char *context;
+
+  if(!ps_getpidcon && !tried_load){
+    void *handle = dlopen("libselinux.so.1", RTLD_NOW);
+    if(handle){
+      dlerror();
+      ps_getpidcon = dlsym(handle, "getpidcon");
+      if(dlerror())
+        ps_getpidcon = 0;
+    }
+    tried_load++;
+  }
+  if(ps_getpidcon && !ps_getpidcon(pp->tgid, &context)){
+    size_t max_len = OUTBUF_SIZE-1;
+    len = strlen(context);
+    if(len > max_len) len = max_len;
+    memcpy(outbuf, context, len);
+    outbuf[len] = '\0';
+    free(context);
+  }else{
+    outbuf[0] = '-';
+    outbuf[1] = '\0';
+    len = 1;
+  }
+  return len;
+}
+#endif
+
+
+////////////////////////////// Test code /////////////////////////////////
+
+// like "args"
+static int pr_t_unlimited(char *restrict const outbuf, const proc_t *restrict const pp){
+  static const char *const vals[] = {"[123456789-12345] <defunct>","ps","123456789-123456"};
+  (void)pp;
+  snprintf(outbuf, max_rightward+1, "%s", vals[lines_to_next_header%3u]);
+  return strlen(outbuf);
+}
+static int pr_t_unlimited2(char *restrict const outbuf, const proc_t *restrict const pp){
+  static const char *const vals[] = {"unlimited", "[123456789-12345] <defunct>","ps","123456789-123456"};
+  (void)pp;
+  snprintf(outbuf, max_rightward+1, "%s", vals[lines_to_next_header%4u]);
+  return strlen(outbuf);
+}
+
+// like "etime"
+static int pr_t_right(char *restrict const outbuf, const proc_t *restrict const pp){
+  static const char *const vals[] = {"999-23:59:59","99-23:59:59","9-23:59:59","59:59"};
+  (void)pp;
+  return snprintf(outbuf, COLWID, "%s", vals[lines_to_next_header%4u]);
+}
+static int pr_t_right2(char *restrict const outbuf, const proc_t *restrict const pp){
+  static const char *const vals[] = {"999-23:59:59","99-23:59:59","9-23:59:59"};
+  (void)pp;
+  return snprintf(outbuf, COLWID, "%s", vals[lines_to_next_header%3u]);
+}
+
+// like "tty"
+static int pr_t_left(char *restrict const outbuf, const proc_t *restrict const pp){
+  static const char *const vals[] = {"tty7","pts/9999","iseries/vtty42","ttySMX0","3270/tty4"};
+  (void)pp;
+  return snprintf(outbuf, COLWID, "%s", vals[lines_to_next_header%5u]);
+}
+static int pr_t_left2(char *restrict const outbuf, const proc_t *restrict const pp){
+  static const char *const vals[] = {"tty7","pts/9999","ttySMX0","3270/tty4"};
+  (void)pp;
+  return snprintf(outbuf, COLWID, "%s", vals[lines_to_next_header%4u]);
+}
+
+/***************************************************************************/
+/*************************** other stuff ***********************************/
+
+/*
+ * Old header specifications.
+ *
+ * short   Up  "  PID TTY STAT  TIME COMMAND"
+ * long  l Pp  " FLAGS   UID   PID  PPID PRI  NI   SIZE   RSS WCHAN       STA TTY TIME COMMAND
+ * user  u up  "USER       PID %CPU %MEM  SIZE   RSS TTY STAT START   TIME COMMAND
+ * jobs  j gPp " PPID   PID  PGID   SID TTY TPGID  STAT   UID   TIME COMMAND
+ * sig   s p   "  UID   PID SIGNAL   BLOCKED  IGNORED  CATCHED  STAT TTY   TIME COMMAND
+ * vm    v r   "  PID TTY STAT  TIME  PAGEIN TSIZ DSIZ  RSS   LIM %MEM COMMAND
+ * m     m r   "  PID TTY MAJFLT MINFLT   TRS   DRS  SIZE  SWAP   RSS  SHRD   LIB  DT COMMAND
+ * regs  X p   "NR   PID    STACK      ESP      EIP TMOUT ALARM STAT TTY   TIME COMMAND
+ */
+
+/*
+ * Unix98 requires that the heading for tty is TT, though XPG4, Digital,
+ * and BSD use TTY. The Unix98 headers are:
+ *              args,comm,etime,group,nice,pcpu,pgid
+ *              pid,ppid,rgroup,ruser,time,tty,user,vsz
+ *
+ * BSD c:   "command" becomes accounting name ("comm" or "ucomm")
+ * BSD n:   "user" becomes "uid" and "wchan" becomes "nwchan" (number)
+ */
+
+/* Justification control for flags field. */
+#define USER      CF_USER   // left if text, right if numeric
+#define LEFT      CF_LEFT
+#define RIGHT     CF_RIGHT
+#define UNLIMITED CF_UNLIMITED
+#define WCHAN     CF_WCHAN  // left if text, right if numeric
+#define SIGNAL    CF_SIGNAL // right in 9, or 16 if room
+#define PIDMAX    CF_PIDMAX
+#define TO        CF_PRINT_THREAD_ONLY
+#define PO        CF_PRINT_PROCESS_ONLY
+#define ET        CF_PRINT_EVERY_TIME
+#define AN        CF_PRINT_AS_NEEDED // no idea
+
+/* short names to save space */
+#define MEM PROC_FILLMEM     /* read statm  */
+#define ARG PROC_FILLARG     /* read cmdline (cleared if c option) */
+#define COM PROC_FILLCOM     /* read cmdline (cleared if not -f option) */
+#define ENV PROC_FILLENV     /* read environ */
+#define USR PROC_FILLUSR     /* uid_t -> user names */
+#define GRP PROC_FILLGRP     /* gid_t -> group names */
+#define WCH PROC_FILLWCHAN   /* do WCHAN lookup */
+
+
+/* TODO
+ *      pull out annoying BSD aliases into another table (to macro table?)
+ *      add sorting functions here (to unify names)
+ */
+
+/* temporary hack -- mark new stuff grabbed from Debian ps */
+#define LNx LNX
+
+/* there are about 211 listed */
+
+/* Many of these are placeholders for unsupported options. */
+static const format_struct format_array[] = {
+/* code       header     print()      sort()    width need vendor flags  */
+{"%cpu",      "%CPU",    pr_pcpu,     sr_pcpu,    4,   0,    BSD, ET|RIGHT}, /*pcpu*/
+{"%mem",      "%MEM",    pr_pmem,     sr_nop,     4,   0,    BSD, PO|RIGHT}, /*pmem*/
+{"_left",     "LLLLLLLL", pr_t_left,  sr_nop,     8,   0,    TST, ET|LEFT},
+{"_left2",    "L2L2L2L2", pr_t_left2, sr_nop,     8,   0,    TST, ET|LEFT},
+{"_right",    "RRRRRRRRRRR", pr_t_right, sr_nop, 11,   0,    TST, ET|RIGHT},
+{"_right2",   "R2R2R2R2R2R", pr_t_right2, sr_nop, 11,  0,    TST, ET|RIGHT},
+{"_unlimited","U",   pr_t_unlimited,  sr_nop,    16,   0,    TST, ET|UNLIMITED},
+{"_unlimited2","U2", pr_t_unlimited2, sr_nop,    16,   0,    TST, ET|UNLIMITED},
+{"acflag",    "ACFLG",   pr_nop,      sr_nop,     5,   0,    XXX, AN|RIGHT}, /*acflg*/
+{"acflg",     "ACFLG",   pr_nop,      sr_nop,     5,   0,    BSD, AN|RIGHT}, /*acflag*/
+{"addr",      "ADDR",    pr_nop,      sr_nop,     4,   0,    XXX, AN|RIGHT},
+{"addr_1",    "ADDR",    pr_nop,      sr_nop,     1,   0,    LNX, AN|LEFT},
+{"alarm",     "ALARM",   pr_alarm,    sr_alarm,   5,   0,    LNX, AN|RIGHT},
+{"argc",      "ARGC",    pr_nop,      sr_nop,     4,   0,    LNX, PO|RIGHT},
+{"args",      "COMMAND", pr_args,     sr_cmd,    27, ARG,    U98, PO|UNLIMITED}, /*command*/
+{"atime",     "TIME",    pr_time,     sr_nop,     8,   0,    SOE, ET|RIGHT}, /*cputime*/ /* was 6 wide */
+{"blocked",   "BLOCKED", pr_sigmask,  sr_nop,     9,   0,    BSD, TO|SIGNAL}, /*sigmask*/
+{"bnd",       "BND",     pr_nop,      sr_nop,     1,   0,    AIX, TO|RIGHT},
+{"bsdstart",  "START",   pr_bsdstart, sr_nop,     6,   0,    LNX, ET|RIGHT},
+{"bsdtime",   "TIME",    pr_bsdtime,  sr_nop,     6,   0,    LNX, ET|RIGHT},
+{"c",         "C",       pr_c,        sr_pcpu,    2,   0,    SUN, ET|RIGHT},
+{"caught",    "CAUGHT",  pr_sigcatch, sr_nop,     9,   0,    BSD, TO|SIGNAL}, /*sigcatch*/
+{"class",     "CLS",     pr_class,    sr_sched,   3,   0,    XXX, TO|LEFT},
+{"cls",       "CLS",     pr_class,    sr_sched,   3,   0,    HPU, TO|RIGHT}, /*says HPUX or RT*/
+{"cmaj_flt",  "-",       pr_nop,      sr_cmaj_flt, 1,  0,    LNX, AN|RIGHT},
+{"cmd",       "CMD",     pr_args,     sr_cmd,    27, ARG,    DEC, PO|UNLIMITED}, /*ucomm*/
+{"cmin_flt",  "-",       pr_nop,      sr_cmin_flt, 1,  0,    LNX, AN|RIGHT},
+{"cnswap",    "-",       pr_nop,      sr_nop,     1,   0,    LNX, AN|RIGHT},
+{"comm",      "COMMAND", pr_comm,     sr_cmd,    15, COM,    U98, PO|UNLIMITED}, /*ucomm*/
+{"command",   "COMMAND", pr_args,     sr_cmd,    27, ARG,    XXX, PO|UNLIMITED}, /*args*/
+{"context",   "CONTEXT", pr_context,  sr_nop,    31,   0,    LNX, ET|LEFT},
+{"cp",        "CP",      pr_cp,       sr_pcpu,    3,   0,    DEC, ET|RIGHT}, /*cpu*/
+{"cpu",       "CPU",     pr_nop,      sr_nop,     3,   0,    BSD, AN|RIGHT}, /* FIXME ... HP-UX wants this as the CPU number for SMP? */
+{"cpuid",     "CPUID",   pr_psr,      sr_nop,     5,   0,    BSD, TO|RIGHT}, // OpenBSD: 8 wide!
+{"cputime",   "TIME",    pr_time,     sr_nop,     8,   0,    DEC, ET|RIGHT}, /*time*/
+{"cstime",    "-",       pr_nop,      sr_cstime,  1,   0,    LNX, AN|RIGHT},
+{"ctid",      "CTID",    pr_nop,      sr_nop,     5,   0,    SUN, ET|RIGHT}, // resource contracts?
+{"cursig",    "CURSIG",  pr_nop,      sr_nop,     6,   0,    DEC, AN|RIGHT},
+{"cutime",    "-",       pr_nop,      sr_cutime,  1,   0,    LNX, AN|RIGHT},
+{"cwd",       "CWD",     pr_nop,      sr_nop,     3,   0,    LNX, AN|LEFT},
+{"drs",       "DRS",     pr_drs,      sr_drs,     5, MEM,    LNX, PO|RIGHT},
+{"dsiz",      "DSIZ",    pr_dsiz,     sr_nop,     4,   0,    LNX, PO|RIGHT},
+{"egid",      "EGID",    pr_egid,     sr_egid,    5,   0,    LNX, ET|RIGHT},
+{"egroup",    "EGROUP",  pr_egroup,   sr_egroup,  8, GRP,    LNX, ET|USER},
+{"eip",       "EIP",     pr_eip,      sr_kstk_eip, 8,  0,    LNX, TO|RIGHT},
+{"emul",      "EMUL",    pr_nop,      sr_nop,    13,   0,    BSD, PO|LEFT}, /* "FreeBSD ELF32" and such */
+{"end_code",  "E_CODE",  pr_nop,      sr_end_code, 8,  0,    LNx, PO|RIGHT},
+{"environ","ENVIRONMENT",pr_nop,      sr_nop,    11, ENV,    LNx, PO|UNLIMITED},
+{"esp",       "ESP",     pr_esp,      sr_kstk_esp, 8,  0,    LNX, TO|RIGHT},
+{"etime",     "ELAPSED", pr_etime,    sr_nop,    11,   0,    U98, ET|RIGHT}, /* was 7 wide */
+{"euid",      "EUID",    pr_euid,     sr_euid,    5,   0,    LNX, ET|RIGHT},
+{"euser",     "EUSER",   pr_euser,    sr_euser,   8, USR,    LNX, ET|USER},
+{"f",         "F",       pr_flag,     sr_flags,   1,   0,    XXX, ET|RIGHT}, /*flags*/
+{"fgid",      "FGID",    pr_fgid,     sr_fgid,    5,   0,    LNX, ET|RIGHT},
+{"fgroup",    "FGROUP",  pr_fgroup,   sr_fgroup,  8, GRP,    LNX, ET|USER},
+{"flag",      "F",       pr_flag,     sr_flags,   1,   0,    DEC, ET|RIGHT},
+{"flags",     "F",       pr_flag,     sr_flags,   1,   0,    BSD, ET|RIGHT}, /*f*/ /* was FLAGS, 8 wide */
+{"fname",     "COMMAND", pr_fname,    sr_nop,     8,   0,    SUN, PO|LEFT},
+{"fsgid",     "FSGID",   pr_fgid,     sr_fgid,    5,   0,    LNX, ET|RIGHT},
+{"fsgroup",   "FSGROUP", pr_fgroup,   sr_fgroup,  8, GRP,    LNX, ET|USER},
+{"fsuid",     "FSUID",   pr_fuid,     sr_fuid,    5,   0,    LNX, ET|RIGHT},
+{"fsuser",    "FSUSER",  pr_fuser,    sr_fuser,   8, USR,    LNX, ET|USER},
+{"fuid",      "FUID",    pr_fuid,     sr_fuid,    5,   0,    LNX, ET|RIGHT},
+{"fuser",     "FUSER",   pr_fuser,    sr_fuser,   8, USR,    LNX, ET|USER},
+{"gid",       "GID",     pr_egid,     sr_egid,    5,   0,    SUN, ET|RIGHT},
+{"group",     "GROUP",   pr_egroup,   sr_egroup,  8, GRP,    U98, ET|USER},
+{"ignored",   "IGNORED", pr_sigignore,sr_nop,     9,   0,    BSD, TO|SIGNAL}, /*sigignore*/
+{"inblk",     "INBLK",   pr_nop,      sr_nop,     5,   0,    BSD, AN|RIGHT}, /*inblock*/
+{"inblock",   "INBLK",   pr_nop,      sr_nop,     5,   0,    DEC, AN|RIGHT}, /*inblk*/
+{"intpri",    "PRI",     pr_opri,     sr_priority, 3,  0,    HPU, TO|RIGHT},
+{"jid",       "JID",     pr_nop,      sr_nop,     1,   0,    SGI, PO|RIGHT},
+{"jobc",      "JOBC",    pr_nop,      sr_nop,     4,   0,    XXX, AN|RIGHT},
+{"ktrace",    "KTRACE",  pr_nop,      sr_nop,     8,   0,    BSD, AN|RIGHT},
+{"ktracep",   "KTRACEP", pr_nop,      sr_nop,     8,   0,    BSD, AN|RIGHT},
+{"label",     "LABEL",   pr_context,  sr_nop,    31,  0,     SGI, ET|LEFT},
+{"lastcpu",   "C",       pr_psr,      sr_nop,     3,   0,    BSD, TO|RIGHT}, // DragonFly
+{"lim",       "LIM",     pr_lim,      sr_rss_rlim, 5,  0,    BSD, AN|RIGHT},
+{"login",     "LOGNAME", pr_nop,      sr_nop,     8,   0,    BSD, AN|LEFT}, /*logname*/   /* double check */
+{"logname",   "LOGNAME", pr_nop,      sr_nop,     8,   0,    XXX, AN|LEFT}, /*login*/
+{"longtname", "TTY",     pr_tty8,     sr_tty,     8,   0,    DEC, PO|LEFT},
+{"lstart",    "STARTED", pr_lstart,   sr_nop,    24,   0,    XXX, ET|RIGHT},
+{"luid",      "LUID",    pr_nop,      sr_nop,     5,   0,    LNX, ET|RIGHT}, /* login ID */
+{"luser",     "LUSER",   pr_nop,      sr_nop,     8, USR,    LNX, ET|USER}, /* login USER */
+{"lwp",       "LWP",     pr_thread,   sr_tid,     5,   0,    SUN, TO|PIDMAX|RIGHT},
+{"m_drs",     "DRS",     pr_drs,      sr_drs,     5, MEM,    LNx, PO|RIGHT},
+{"m_dt",      "DT",      pr_nop,      sr_dt,      4, MEM,    LNx, PO|RIGHT},
+{"m_lrs",     "LRS",     pr_nop,      sr_lrs,     5, MEM,    LNx, PO|RIGHT},
+{"m_resident", "RES",    pr_nop,      sr_resident, 5,MEM,    LNx, PO|RIGHT},
+{"m_share",   "SHRD",    pr_nop,      sr_share,   5, MEM,    LNx, PO|RIGHT},
+{"m_size",    "SIZE",    pr_size,     sr_size,    5, MEM,    LNX, PO|RIGHT},
+{"m_swap",    "SWAP",    pr_nop,      sr_nop,     5,   0,    LNx, PO|RIGHT},
+{"m_trs",     "TRS",     pr_trs,      sr_trs,     5, MEM,    LNx, PO|RIGHT},
+{"maj_flt",   "MAJFL",   pr_majflt,   sr_maj_flt, 6,   0,    LNX, AN|RIGHT},
+{"majflt",    "MAJFLT",  pr_majflt,   sr_maj_flt, 6,   0,    XXX, AN|RIGHT},
+{"min_flt",   "MINFL",   pr_minflt,   sr_min_flt, 6,   0,    LNX, AN|RIGHT},
+{"minflt",    "MINFLT",  pr_minflt,   sr_min_flt, 6,   0,    XXX, AN|RIGHT},
+{"msgrcv",    "MSGRCV",  pr_nop,      sr_nop,     6,   0,    XXX, AN|RIGHT},
+{"msgsnd",    "MSGSND",  pr_nop,      sr_nop,     6,   0,    XXX, AN|RIGHT},
+{"mwchan",    "MWCHAN",  pr_nop,      sr_nop,     6, WCH,    BSD, TO|WCHAN}, /* mutex (FreeBSD) */
+{"ni",        "NI",      pr_nice,     sr_nice,    3,   0,    BSD, TO|RIGHT}, /*nice*/
+{"nice",      "NI",      pr_nice,     sr_nice,    3,   0,    U98, TO|RIGHT}, /*ni*/
+{"nivcsw",    "IVCSW",   pr_nop,      sr_nop,     5,   0,    XXX, AN|RIGHT},
+{"nlwp",      "NLWP",    pr_nlwp,     sr_nlwp,    4,   0,    SUN, PO|RIGHT},
+{"nsignals",  "NSIGS",   pr_nop,      sr_nop,     5,   0,    DEC, AN|RIGHT}, /*nsigs*/
+{"nsigs",     "NSIGS",   pr_nop,      sr_nop,     5,   0,    BSD, AN|RIGHT}, /*nsignals*/
+{"nswap",     "NSWAP",   pr_nop,      sr_nop,     5,   0,    XXX, AN|RIGHT},
+{"nvcsw",     "VCSW",    pr_nop,      sr_nop,     5,   0,    XXX, AN|RIGHT},
+{"nwchan",    "WCHAN",   pr_nwchan,   sr_nop,     6,   0,    XXX, TO|RIGHT},
+{"opri",      "PRI",     pr_opri,     sr_priority, 3,  0,    SUN, TO|RIGHT},
+{"osz",       "SZ",      pr_nop,      sr_nop,     2,   0,    SUN, PO|RIGHT},
+{"oublk",     "OUBLK",   pr_nop,      sr_nop,     5,   0,    BSD, AN|RIGHT}, /*oublock*/
+{"oublock",   "OUBLK",   pr_nop,      sr_nop,     5,   0,    DEC, AN|RIGHT}, /*oublk*/
+{"p_ru",      "P_RU",    pr_nop,      sr_nop,     6,   0,    BSD, AN|RIGHT},
+{"paddr",     "PADDR",   pr_nop,      sr_nop,     6,   0,    BSD, AN|RIGHT},
+{"pagein",    "PAGEIN",  pr_majflt,   sr_maj_flt, 6,   0,    XXX, AN|RIGHT},
+{"pcpu",      "%CPU",    pr_pcpu,     sr_pcpu,    4,   0,    U98, ET|RIGHT}, /*%cpu*/
+{"pending",   "PENDING", pr_sig,      sr_nop,     9,   0,    BSD, ET|SIGNAL}, /*sig*/
+{"pgid",      "PGID",    pr_pgid,     sr_pgrp,    5,   0,    U98, PO|PIDMAX|RIGHT},
+{"pgrp",      "PGRP",    pr_pgid,     sr_pgrp,    5,   0,    LNX, PO|PIDMAX|RIGHT},
+{"pid",       "PID",     pr_pid,      sr_tgid,    5,   0,    U98, PO|PIDMAX|RIGHT},
+{"pmem",      "%MEM",    pr_pmem,     sr_nop,     4,   0,    XXX, PO|RIGHT}, /*%mem*/
+{"poip",      "-",       pr_nop,      sr_nop,     1,   0,    BSD, AN|RIGHT},
+{"policy",    "POL",     pr_class,    sr_sched,   3,   0,    DEC, TO|LEFT},
+{"ppid",      "PPID",    pr_ppid,     sr_ppid,    5,   0,    U98, PO|PIDMAX|RIGHT},
+{"pri",       "PRI",     pr_pri,      sr_nop,     3,   0,    XXX, TO|RIGHT},
+{"pri_api",   "API",     pr_pri_api,  sr_nop,     3,   0,    LNX, TO|RIGHT},
+{"pri_bar",   "BAR",     pr_pri_bar,  sr_nop,     3,   0,    LNX, TO|RIGHT},
+{"pri_baz",   "BAZ",     pr_pri_baz,  sr_nop,     3,   0,    LNX, TO|RIGHT},
+{"pri_foo",   "FOO",     pr_pri_foo,  sr_nop,     3,   0,    LNX, TO|RIGHT},
+{"priority",  "PRI",     pr_priority, sr_priority, 3,  0,    LNX, TO|RIGHT},
+{"prmgrp",    "PRMGRP",  pr_nop,      sr_nop,    12,   0,    HPU, PO|RIGHT},
+{"prmid",     "PRMID",   pr_nop,      sr_nop,    12,   0,    HPU, PO|RIGHT},
+{"project",   "PROJECT", pr_nop,      sr_nop,    12,   0,    SUN, PO|LEFT}, // see prm* andctid
+{"projid",    "PROJID",  pr_nop,      sr_nop,     5,   0,    SUN, PO|RIGHT},
+{"pset",      "PSET",    pr_nop,      sr_nop,     4,   0,    DEC, TO|RIGHT},
+{"psr",       "PSR",     pr_psr,      sr_nop,     3,   0,    DEC, TO|RIGHT},
+{"psxpri",    "PPR",     pr_nop,      sr_nop,     3,   0,    DEC, TO|RIGHT},
+{"re",        "RE",      pr_nop,      sr_nop,     3,   0,    BSD, AN|RIGHT},
+{"resident",  "RES",     pr_nop,      sr_resident, 5,MEM,    LNX, PO|RIGHT},
+{"rgid",      "RGID",    pr_rgid,     sr_rgid,    5,   0,    XXX, ET|RIGHT},
+{"rgroup",    "RGROUP",  pr_rgroup,   sr_rgroup,  8, GRP,    U98, ET|USER}, /* was 8 wide */
+{"rlink",     "RLINK",   pr_nop,      sr_nop,     8,   0,    BSD, AN|RIGHT},
+{"rss",       "RSS",     pr_rss,      sr_rss,     5,   0,    XXX, PO|RIGHT}, /* was 5 wide */
+{"rssize",    "RSS",     pr_rss,      sr_vm_rss,  5,   0,    DEC, PO|RIGHT}, /*rsz*/
+{"rsz",       "RSZ",     pr_rss,      sr_vm_rss,  5,   0,    BSD, PO|RIGHT}, /*rssize*/
+{"rtprio",    "RTPRIO",  pr_rtprio,   sr_rtprio,  6,   0,    BSD, TO|RIGHT},
+{"ruid",      "RUID",    pr_ruid,     sr_ruid,    5,   0,    XXX, ET|RIGHT},
+{"ruser",     "RUSER",   pr_ruser,    sr_ruser,   8, USR,    U98, ET|USER},
+{"s",         "S",       pr_s,        sr_state,   1,   0,    SUN, TO|LEFT}, /*stat,state*/
+{"sched",     "SCH",     pr_sched,    sr_sched,   3,   0,    AIX, TO|RIGHT},
+{"scnt",      "SCNT",    pr_nop,      sr_nop,     4,   0,    DEC, AN|RIGHT},  /* man page misspelling of scount? */
+{"scount",    "SC",      pr_nop,      sr_nop,     4,   0,    AIX, AN|RIGHT},  /* scnt==scount, DEC claims both */
+{"sess",      "SESS",    pr_sess,     sr_session, 5,   0,    XXX, PO|PIDMAX|RIGHT},
+{"session",   "SESS",    pr_sess,     sr_session, 5,   0,    LNX, PO|PIDMAX|RIGHT},
+{"sgi_p",     "P",       pr_sgi_p,    sr_nop,     1,   0,    LNX, TO|RIGHT}, /* "cpu" number */
+{"sgi_rss",   "RSS",     pr_rss,      sr_nop,     4,   0,    LNX, PO|LEFT}, /* SZ:RSS */
+{"sgid",      "SGID",    pr_sgid,     sr_sgid,    5,   0,    LNX, ET|RIGHT},
+{"sgroup",    "SGROUP",  pr_sgroup,   sr_sgroup,  8, GRP,    LNX, ET|USER},
+{"share",     "-",       pr_nop,      sr_share,   1, MEM,    LNX, PO|RIGHT},
+{"sid",       "SID",     pr_sess,     sr_session, 5,   0,    XXX, PO|PIDMAX|RIGHT}, /* Sun & HP */
+{"sig",       "PENDING", pr_sig,      sr_nop,     9,   0,    XXX, ET|SIGNAL}, /*pending -- Dragonfly uses this for whole-proc and "tsig" for thread */
+{"sig_block", "BLOCKED",  pr_sigmask, sr_nop,     9,   0,    LNX, TO|SIGNAL},
+{"sig_catch", "CATCHED", pr_sigcatch, sr_nop,     9,   0,    LNX, TO|SIGNAL},
+{"sig_ignore", "IGNORED",pr_sigignore, sr_nop,    9,   0,    LNX, TO|SIGNAL},
+{"sig_pend",  "SIGNAL",   pr_sig,     sr_nop,     9,   0,    LNX, ET|SIGNAL},
+{"sigcatch",  "CAUGHT",  pr_sigcatch, sr_nop,     9,   0,    XXX, TO|SIGNAL}, /*caught*/
+{"sigignore", "IGNORED", pr_sigignore,sr_nop,     9,   0,    XXX, TO|SIGNAL}, /*ignored*/
+{"sigmask",   "BLOCKED", pr_sigmask,  sr_nop,     9,   0,    XXX, TO|SIGNAL}, /*blocked*/
+{"size",      "SZ",      pr_swapable, sr_swapable, 5,  0,    SCO, PO|RIGHT},
+{"sl",        "SL",      pr_nop,      sr_nop,     3,   0,    XXX, AN|RIGHT},
+{"spid",      "SPID",    pr_thread,   sr_tid,     5,   0,    SGI, TO|PIDMAX|RIGHT},
+{"stackp",    "STACKP",  pr_stackp,   sr_start_stack, 8, 0,  LNX, PO|RIGHT}, /*start_stack*/
+{"start",     "STARTED", pr_start,    sr_nop,     8,   0,    XXX, ET|RIGHT},
+{"start_code", "S_CODE",  pr_nop,     sr_start_code, 8, 0,   LNx, PO|RIGHT},
+{"start_stack", "STACKP", pr_stackp,  sr_start_stack, 8, 0,  LNX, PO|RIGHT}, /*stackp*/
+{"start_time", "START",  pr_stime,    sr_start_time, 5, 0,   LNx, ET|RIGHT},
+{"stat",      "STAT",    pr_stat,     sr_state,   4,   0,    BSD, TO|LEFT}, /*state,s*/
+{"state",     "S",       pr_s,        sr_state,   1,   0,    XXX, TO|LEFT}, /*stat,s*/ /* was STAT */
+{"status",    "STATUS",  pr_nop,      sr_nop,     6,   0,    DEC, AN|RIGHT},
+{"stime",     "STIME",   pr_stime,    sr_stime,   5,   0,    XXX, ET|RIGHT}, /* was 6 wide */
+{"suid",      "SUID",    pr_suid,     sr_suid,    5,   0,    LNx, ET|RIGHT},
+{"suser",     "SUSER",   pr_suser,    sr_suser,   8, USR,    LNx, ET|USER},
+{"svgid",     "SVGID",   pr_sgid,     sr_sgid,    5,   0,    XXX, ET|RIGHT},
+{"svgroup",   "SVGROUP", pr_sgroup,   sr_sgroup,  8, GRP,    LNX, ET|USER},
+{"svuid",     "SVUID",   pr_suid,     sr_suid,    5,   0,    XXX, ET|RIGHT},
+{"svuser",    "SVUSER",  pr_suser,    sr_suser,   8, USR,    LNX, ET|USER},
+{"systime",   "SYSTEM",  pr_nop,      sr_nop,     6,   0,    DEC, ET|RIGHT},
+{"sz",        "SZ",      pr_sz,       sr_nop,     5,   0,    HPU, PO|RIGHT},
+{"taskid",    "TASKID",  pr_nop,      sr_nop,     5,   0,    SUN, TO|PIDMAX|RIGHT}, // is this a thread ID?
+{"tdev",      "TDEV",    pr_nop,      sr_nop,     4,   0,    XXX, AN|RIGHT},
+{"thcount",   "THCNT",   pr_nlwp,     sr_nlwp,    5,   0,    AIX, PO|RIGHT},
+{"tid",       "TID",     pr_thread,   sr_tid,     5,   0,    AIX, TO|PIDMAX|RIGHT},
+{"time",      "TIME",    pr_time,     sr_nop,     8,   0,    U98, ET|RIGHT}, /*cputime*/ /* was 6 wide */
+{"timeout",   "TMOUT",   pr_nop,      sr_nop,     5,   0,    LNX, AN|RIGHT}, // 2.0.xx era
+{"tmout",     "TMOUT",   pr_nop,      sr_nop,     5,   0,    LNX, AN|RIGHT}, // 2.0.xx era
+{"tname",     "TTY",     pr_tty8,     sr_tty,     8,   0,    DEC, PO|LEFT},
+{"tpgid",     "TPGID",   pr_tpgid,    sr_tpgid,   5,   0,    XXX, PO|PIDMAX|RIGHT},
+{"trs",       "TRS",     pr_trs,      sr_trs,     4, MEM,    AIX, PO|RIGHT},
+{"trss",      "TRSS",    pr_trs,      sr_trs,     4, MEM,    BSD, PO|RIGHT}, /* 4.3BSD NET/2 */
+{"tsess",     "TSESS",   pr_nop,      sr_nop,     5,   0,    BSD, PO|PIDMAX|RIGHT},
+{"tsession",  "TSESS",   pr_nop,      sr_nop,     5,   0,    DEC, PO|PIDMAX|RIGHT},
+{"tsid",      "TSID",    pr_nop,      sr_nop,     5,   0,    BSD, PO|PIDMAX|RIGHT},
+{"tsig",      "PENDING", pr_tsig,     sr_nop,     9,   0,    BSD, ET|SIGNAL}, /* Dragonfly used this for thread-specific, and "sig" for whole-proc */
+{"tsiz",      "TSIZ",    pr_tsiz,     sr_nop,     4,   0,    BSD, PO|RIGHT},
+{"tt",        "TT",      pr_tty8,     sr_tty,     8,   0,    BSD, PO|LEFT},
+{"tty",       "TT",      pr_tty8,     sr_tty,     8,   0,    U98, PO|LEFT}, /* Unix98 requires "TT" but has "TTY" too. :-( */  /* was 3 wide */
+{"tty4",      "TTY",     pr_tty4,     sr_tty,     4,   0,    LNX, PO|LEFT},
+{"tty8",      "TTY",     pr_tty8,     sr_tty,     8,   0,    LNX, PO|LEFT},
+{"u_procp",   "UPROCP",  pr_nop,      sr_nop,     6,   0,    DEC, AN|RIGHT},
+{"ucmd",      "CMD",     pr_comm,     sr_cmd,    15, COM,    DEC, PO|UNLIMITED}, /*ucomm*/
+{"ucomm",     "COMMAND", pr_comm,     sr_cmd,    15, COM,    XXX, PO|UNLIMITED}, /*comm*/
+{"uid",       "UID",     pr_euid,     sr_euid,    5,   0,    XXX, ET|RIGHT},
+{"uid_hack",  "UID",     pr_euser,    sr_euser,   8, USR,    XXX, ET|USER},
+{"umask",     "UMASK",   pr_nop,      sr_nop,     5,   0,    DEC, AN|RIGHT},
+{"uname",     "USER",    pr_euser,    sr_euser,   8, USR,    DEC, ET|USER}, /* man page misspelling of user? */
+{"upr",       "UPR",     pr_nop,      sr_nop,     3,   0,    BSD, TO|RIGHT}, /*usrpri*/
+{"uprocp",    "UPROCP",  pr_nop,      sr_nop,     8,   0,    BSD, AN|RIGHT},
+{"user",      "USER",    pr_euser,    sr_euser,   8, USR,    U98, ET|USER}, /* BSD n forces this to UID */
+{"usertime",  "USER",    pr_nop,      sr_nop,     4,   0,    DEC, ET|RIGHT},
+{"usrpri",    "UPR",     pr_nop,      sr_nop,     3,   0,    DEC, TO|RIGHT}, /*upr*/
+{"util",      "C",       pr_c,        sr_pcpu,    2,   0,    SGI, ET|RIGHT}, // not sure about "C"
+{"utime",     "UTIME",   pr_nop,      sr_utime,   6,   0,    LNx, ET|RIGHT},
+{"vm_data",   "DATA",    pr_nop,      sr_vm_data, 5,   0,    LNx, PO|RIGHT},
+{"vm_exe",    "EXE",     pr_nop,      sr_vm_exe,  5,   0,    LNx, PO|RIGHT},
+{"vm_lib",    "LIB",     pr_nop,      sr_vm_lib,  5,   0,    LNx, PO|RIGHT},
+{"vm_lock",   "LCK",     pr_nop,      sr_vm_lock, 3,   0,    LNx, PO|RIGHT},
+{"vm_stack",  "STACK",   pr_nop,      sr_vm_stack, 5,  0,    LNx, PO|RIGHT},
+{"vsize",     "VSZ",     pr_vsz,      sr_vsize,   6,   0,    DEC, PO|RIGHT}, /*vsz*/
+{"vsz",       "VSZ",     pr_vsz,      sr_vm_size, 6,   0,    U98, PO|RIGHT}, /*vsize*/
+{"wchan",     "WCHAN",   pr_wchan,    sr_wchan,   6, WCH,    XXX, TO|WCHAN}, /* BSD n forces this to nwchan */ /* was 10 wide */
+{"wname",     "WCHAN",   pr_wname,    sr_nop,     6, WCH,    SGI, TO|WCHAN}, /* opposite of nwchan */
+{"xstat",     "XSTAT",   pr_nop,      sr_nop,     5,   0,    BSD, AN|RIGHT},
+{"zone",      "ZONE",    pr_context,  sr_nop,    31,   0,    SUN, ET|LEFT}, // Solaris zone == Linux context?
+{"zoneid",    "ZONEID",  pr_nop,      sr_nop,    31,   0,    SUN, ET|RIGHT},// Linux only offers context names
+{"~",         "-",       pr_nop,      sr_nop,     1,   0,    LNX, AN|RIGHT}  /* NULL would ruin alphabetical order */
+};
+
+#undef USER
+#undef LEFT
+#undef RIGHT
+#undef UNLIMITED
+#undef WCHAN
+#undef SIGNAL
+#undef PIDMAX
+#undef PO
+#undef TO
+#undef AN
+#undef ET
+
+static const int format_array_count = sizeof(format_array)/sizeof(format_struct);
+
+
+/****************************** Macro formats *******************************/
+/* First X field may be NR, which is p->start_code>>26 printed with %2ld */
+/* That seems useless though, and Debian already killed it. */
+/* The ones marked "Digital" have the name defined, not just the data. */
+static const macro_struct macro_array[] = {
+{"DFMT",     "pid,tname,state,cputime,cmd"},         /* Digital's default */
+{"DefBSD",   "pid,tname,stat,bsdtime,args"},               /* Our BSD default */
+{"DefSysV",  "pid,tname,time,cmd"},                     /* Our SysV default */
+{"END_BSD",  "state,tname,cputime,comm"},                 /* trailer for O */
+{"END_SYS5", "state,tname,time,command"},                 /* trailer for -O */
+{"F5FMT",    "uname,pid,ppid,c,start,tname,time,cmd"},       /* Digital -f */
+
+{"FB_",      "pid,tt,stat,time,command"},                          /* FreeBSD default */
+{"FB_j",     "user,pid,ppid,pgid,sess,jobc,stat,tt,time,command"},     /* FreeBSD j */
+{"FB_l",     "uid,pid,ppid,cpu,pri,nice,vsz,rss,wchan,stat,tt,time,command"},   /* FreeBSD l */
+{"FB_u",     "user,pid,pcpu,pmem,vsz,rss,tt,stat,start,time,command"},     /* FreeBSD u */
+{"FB_v",     "pid,stat,time,sl,re,pagein,vsz,rss,lim,tsiz,pcpu,pmem,command"},   /* FreeBSD v */
+
+{"FD_",      "pid,tty,time,comm"},                                 /* Fictional Debian SysV default */
+{"FD_f",     "user,pid,ppid,start_time,tty,time,comm"},                /* Fictional Debian -f */
+{"FD_fj",    "user,pid,ppid,start_time,tty,time,pgid,sid,comm"},        /* Fictional Debian -jf */
+{"FD_j",     "pid,tty,time,pgid,sid,comm"},                                  /* Fictional Debian -j */
+{"FD_l",     "flags,state,uid,pid,ppid,priority,nice,vsz,wchan,tty,time,comm"},    /* Fictional Debian -l */
+{"FD_lj",    "flags,state,uid,pid,ppid,priority,nice,vsz,wchan,tty,time,pgid,sid,comm"}, /* Fictional Debian -jl */
+
+{"FL5FMT",   "f,state,uid,pid,ppid,pcpu,pri,nice,rss,wchan,start,time,command"},  /* Digital -fl */
+
+{"FLASK_context",   "pid,context,command"},  /* Flask Linux context, --context */
+
+{"HP_",      "pid,tty,time,comm"},  /* HP default */
+{"HP_f",     "user,pid,ppid,cpu,stime,tty,time,args"},  /* HP -f */
+{"HP_fl",    "flags,state,user,pid,ppid,cpu,intpri,nice,addr,sz,wchan,stime,tty,time,args"},  /* HP -fl */
+{"HP_l",     "flags,state,uid,pid,ppid,cpu,intpri,nice,addr,sz,wchan,tty,time,comm"},  /* HP -l */
+
+{"J390",     "pid,sid,pgrp,tname,atime,args"},   /* OS/390 -j */
+{"JFMT",     "user,pid,ppid,pgid,sess,jobc,state,tname,cputime,command"},   /* Digital j and -j */
+{"L5FMT",    "f,state,uid,pid,ppid,c,pri,nice,addr,sz,wchan,tt,time,ucmd"},   /* Digital -l */
+{"LFMT",     "uid,pid,ppid,cp,pri,nice,vsz,rss,wchan,state,tname,cputime,command"},   /* Digital l */
+
+{"OL_X",     "pid,start_stack,esp,eip,timeout,alarm,stat,tname,bsdtime,args"},      /* Old i386 Linux X */
+{"OL_j",     "ppid,pid,pgid,sid,tname,tpgid,stat,uid,bsdtime,args"},                   /* Old Linux j */
+{"OL_l",     "flags,uid,pid,ppid,priority,nice,vsz,rss,wchan,stat,tname,bsdtime,args"},     /* Old Linux l */
+{"OL_m",     "pid,tname,majflt,minflt,m_trs,m_drs,m_size,m_swap,rss,m_share,vm_lib,m_dt,args"}, /* Old Linux m */
+{"OL_s",     "uid,pid,pending,sig_block,sig_ignore,caught,stat,tname,bsdtime,args"},  /* Old Linux s */
+{"OL_u",     "user,pid,pcpu,pmem,vsz,rss,tname,stat,start_time,bsdtime,args"},       /* Old Linux u */
+{"OL_v",     "pid,tname,stat,bsdtime,maj_flt,m_trs,m_drs,rss,pmem,args"},            /* Old Linux v */
+
+{"RD_",      "pid,tname,state,bsdtime,comm"},                                       /* Real Debian default */
+{"RD_f",     "uid,pid,ppid,start_time,tname,bsdtime,args"},                         /* Real Debian -f */
+{"RD_fj",    "uid,pid,ppid,start_time,tname,bsdtime,pgid,sid,args"},                /* Real Debian -jf */
+{"RD_j",     "pid,tname,state,bsdtime,pgid,sid,comm"},                               /* Real Debian -j */
+{"RD_l",     "flags,state,uid,pid,ppid,priority,nice,wchan,tname,bsdtime,comm"},           /* Real Debian -l */
+{"RD_lj",    "flags,state,uid,pid,ppid,priority,nice,wchan,tname,bsdtime,pgid,sid,comm"},  /* Real Debian -jl */
+
+{"RUSAGE",   "minflt,majflt,nswap,inblock,oublock,msgsnd,msgrcv,nsigs,nvcsw,nivcsw"}, /* Digital -o "RUSAGE" */
+{"SCHED",    "user,pcpu,pri,usrpri,nice,psxpri,psr,policy,pset"},                /* Digital -o "SCHED" */
+{"SFMT",     "uid,pid,cursig,sig,sigmask,sigignore,sigcatch,stat,tname,command"},  /* Digital s */
+
+{"Std_f",    "uid_hack,pid,ppid,c,stime,tname,time,cmd"},                     /* new -f */
+{"Std_fl",   "f,s,uid_hack,pid,ppid,c,opri,ni,addr,sz,wchan,stime,tname,time,cmd"}, /* -fl */
+{"Std_l",    "f,s,uid,pid,ppid,c,opri,ni,addr,sz,wchan,tname,time,ucmd"},  /* new -l */
+
+{"THREAD",   "user,pcpu,pri,scnt,wchan,usertime,systime"},                /* Digital -o "THREAD" */
+{"UFMT",     "uname,pid,pcpu,pmem,vsz,rss,tt,state,start,time,command"},   /* Digital u */
+{"VFMT",     "pid,tt,state,time,sl,pagein,vsz,rss,pcpu,pmem,command"},   /* Digital v */
+{"~", "~"} /* NULL would ruin alphabetical order */
+};
+
+static const int macro_array_count = sizeof(macro_array)/sizeof(macro_struct);
+
+
+/*************************** AIX formats ********************/
+/* Convert AIX format codes to normal format specifiers. */
+static const aix_struct aix_array[] = {
+{'C', "pcpu",   "%CPU"},
+{'G', "group",  "GROUP"},
+{'P', "ppid",   "PPID"},
+{'U', "user",   "USER"},
+{'a', "args",   "COMMAND"},
+{'c', "comm",   "COMMAND"},
+{'g', "rgroup", "RGROUP"},
+{'n', "nice",   "NI"},
+{'p', "pid",    "PID"},
+{'r', "pgid",   "PGID"},
+{'t', "etime",  "ELAPSED"},
+{'u', "ruser",  "RUSER"},
+{'x', "time",   "TIME"},
+{'y', "tty",    "TTY"},
+{'z', "vsz",    "VSZ"},
+{'~', "~",      "~"} /* NULL would ruin alphabetical order */
+};
+static const int aix_array_count = sizeof(aix_array)/sizeof(aix_struct);
+
+
+/********************* sorting ***************************/
+/* Convert short sorting codes to normal format specifiers. */
+static const shortsort_struct sho