Filewatcher File Search
FTP Search
  
Directory 
  
Content Search 
   
pkg://procps-2.0.7-11.src.rpm:212926/procps-2.0.7.tar.gz  info  downloads

procps-2.0.7/0040775000076400007640000000000007133676463013333 5ustar  johnsonmjohnsonmprocps-2.0.7/proc/0040775000076400007640000000000007133676463014276 5ustar  johnsonmjohnsonmprocps-2.0.7/proc/.cvsignore0100664000076400007640000000004007133675715016264 0ustar  johnsonmjohnsonm.depend
signames.h
libproc.so.*
procps-2.0.7/proc/COPYING0100664000076400007640000006127306672166704015336 0ustar  johnsonmjohnsonm		  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!
procps-2.0.7/proc/Makefile0100664000076400007640000000601407132402377015722 0ustar  johnsonmjohnsonm# Auto-adaptive C library Makefile adapted for libproc, Chuck Blake.
# Assumptions are basically that all the .c files in the CWD are modules
# for the library and that all .h files are the interface to the library.

# PROJECT SPECIFIC MACROS
NAME       =  proc

# INSTALLATION OPTIONS
TOPDIR     = /usr
HDRDIR     = $(TOPDIR)/include/$(NAME)#	where to put .h files
LIBDIR     = $(TOPDIR)/lib#		where to put library files
SHLIBDIR   = /lib#			where to put shared library files
HDROWN     = $(OWNERGROUP) #		owner of header files
LIBOWN     = $(OWNERGROUP) #		owner of library files
INSTALL    = install

# ----------------------------------------------------------------#
# The rest is the auto-magic section -- highly GNU make dependent #
# You should never need to edit this.                             #
# ----------------------------------------------------------------#

VC_SUF     =  ,v
VC_PFX     =  RCS/
RCSFILES   =  $(patsubst $(VC_PFX)%$(VC_SUF),%,$(wildcard $(VC_PFX)*$(VC_SUF)))

# We take the union of RCS files and other files in CWD so that new files do
# not need to alter this makefile.  'sort' removes duplicates.  This allows the
# convenience of compiling and testing new files before the initial check-in.

SRC        =  $(sort $(wildcard *.c) $(filter %.c,$(RCSFILES)))
HDR        =  $(sort $(wildcard *.h) $(filter %.h,$(RCSFILES)))

OBJ        =  $(SRC:.c=.o)
SONAME     =  lib$(NAME).so.$(LIBVERSION)

ifeq ($(SHARED),1)
CFLAGS += -fpic
all: lib$(NAME).a $(SONAME)
else
all: lib$(NAME).a
endif

lib$(NAME).a: $(OBJ)
	$(AR) rcs $@ $^

$(SONAME): $(OBJ)
	gcc -shared -Wl,-soname,$(SONAME) -o $@ $^ -lc
	ln -sf $(SONAME) lib$(NAME).so

# AUTOMATIC DEPENDENCY GENERATION -- GCC AND GNUMAKE DEPENDENT

.depend:
	$(strip $(CC) $(CFLAGS) -MM -MG $(SRC) > .depend)
-include .depend

# INSTALLATION

install: all
	if ! [ -d $(HDRDIR) ] ; then mkdir $(HDRDIR) ; fi
	$(INSTALL) $(HDROWN) $(HDR) $(TOPDIR)/include/$(NAME)
	$(INSTALL) $(LIBOWN) lib$(NAME).a $(LIBDIR)
ifeq ($(SHARED),1)
	$(INSTALL) $(LIBOWN) $(SONAME) $(SHLIBDIR)
	ln -sf $(SHLIBDIR)/$(SONAME) $(SHLIBDIR)/lib$(NAME).so
	ldconfig
endif

# VARIOUS SHORT CUT TARGETS
.PHONY:	all install dep clean distclean checkout checkclean

dep:	.depend

clean:
	$(RM) lib$(NAME).* *.o signames.h

distclean:	clean
	$(RM) .depend signames.h

checkout:
	$(CO) $(RCSFILES)

checkclean:
	$(RM) $(RCSFILES)

# CUSTOM c -> o rule so that command-line has minimal whitespace

%.o : %.c
	$(strip $(CC) $(CFLAGS) -c $<)

# PROJECT SPECIFIC DEPENDENCIES/BUILD RULES


version.o:	version.c version.h
ifdef MINORVERSION
	$(strip $(CC) $(CFLAGS) -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" -c version.c)
else
	$(strip $(CC) $(CFLAGS) -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -c version.c)
endif

signals.o : signames.h

signames.h ../proc/signames.h : /usr/include/signal.h
	$(CPP) -dM /usr/include/signal.h |	\
	grep -v SIGSTKSZ | \
	tr -s '\t ' '  ' | sort -n +2 | sed		\
	's:#define SIG\([A-Z]\+[0-9]*\) \([0-9]\+\) *\(\|/\*.*\)$$:{\
\2,"\1" },:p;d'  > signames.h

procps-2.0.7/proc/alloc.c0100664000076400007640000000225406672166704015533 0ustar  johnsonmjohnsonm/***********************************************************************\
*   Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com  *
*									*
*	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>

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);
    } else {
        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);
}
procps-2.0.7/proc/compare.c0100664000076400007640000002471306672166704016073 0ustar  johnsonmjohnsonm/*
 *
 * Copyright 1994 Charles Blake and Michael K. Johnson
 * This file is a part of procps, which is distributable
 * under the conditions of the GNU Library General Public License.
 * See the file COPYING for details.
 *
 */

#include <string.h>		/* for strcmp */
#include <stdio.h>		/* for parse error output */
#include "proc/readproc.h"	/* for proc_t */
#include "proc/tree.h"		/* for struct tree_node */

/*
  This module was written by Charles Blake for procps.

mult_lvl_cmp:
    slick general purpose multi-level compare function I invented.
sort_depth:
    the number of levels of functions *to use*.  This means many more levels
    can be defined than mult_lvl_cmp tres out.  If this is 1 then mult_lvl_cmp
    is just a trivial wrapper around (*sort_function[0]).
sort_direction:
    multiplicative factor for the output of cmp_whatever.
    1 ==> default order, -1 ==> reverse order, 0 ==> forced equality
    The 0 bit is the neat part.  Since a value of zero is the code for equality
    multiplying the output of cmp_foo(a,b) forces a==b to be true.  This is a
    convenient way to turn sorting off in middle levels of a multi-level sort.
    If time is a problem, reforming the whole sort_function array to not include
    these unsorted middle levels will be faster since then cmp_foo won't even
    be called.  It might simplify some code depending upon how you organize it.
sort_function[]:
    array of function pointers that points to our family of comparison functions
    (I have named them cmp_* but mult_lvl_cmp doesn't care what they're named).
    This may be declared and initialized like so:
       int (*sort_function[])(void* a, void* b)={&cmp_foo, &cmp_bar, &cmp_hiho};
    You could also use my command line '-O' parser below.

Note that we only descend levels until the order is determined.  If we descend
all levels, that means that the items are equal at all levels, so we return 0.
Otherwise we return whatever the level's cmp_foo function would have returned.
This allows whatever default behavior you want for cmp_foo.  sort_direction[]
reverses this default behavior, but mult_lvl_cmp doesn't decide that ascending
or descending is the default.  That is the job of your cmp_foo's.
*/

/* the only reason these are global is because qsort(3) likes it that way.
   It's also a little more efficient if mult_lvl_cmp() is called many times.
*/

typedef int (*cmp_t)(void*,void*);	/* for function pointer casts */

int sort_depth = 0;
int sort_direction[10];     /* storage for 10 levels, but 4 would be plenty!*/
int (*sort_function[10])(void* a, void* b);

int mult_lvl_cmp(void* a, void* b) {
    int i, cmp_val;
    for(i = 0; i < sort_depth; i++) {
        cmp_val = sort_direction[i] * (*sort_function[i])(a,b);
        if (cmp_val != 0)
            return cmp_val;
    }
    return 0;
}

int node_mult_lvl_cmp(void* a, void* b) {
    int i, cmp_val;
    for(i = 0; i < sort_depth; i++) {
        cmp_val = sort_direction[i] * (*sort_function[i])(&(((struct tree_node *)a)->proc),&(((struct tree_node *)b)->proc));
        if (cmp_val != 0)
            return cmp_val;
    }
    return 0;
}

/* qsort(3) compliant comparison functions for all members of the ps_proc
   structure (in the same order in which they appear in the proc_t declaration)
   return is {-1,0,1} as {a<b, a==b, a>b}
   default ordering is ascending for all members. (flip 1,-1 to reverse)
*/
/* pre-processor macros to cut down on source size (and typing!)
   Note the use of the string concatenation operator ##
*/
#define CMP_STR(NAME) \
int cmp_ ## NAME(proc_t** P, proc_t** Q) { \
    return strcmp((*P)-> ## NAME, (*Q)-> ## NAME); \
}

#define CMP_INT(NAME) \
int cmp_ ## NAME (proc_t** P, proc_t** Q) { \
    if ((*P)-> ## NAME < (*Q)-> ## NAME) return -1; \
    if ((*P)-> ## NAME > (*Q)-> ## NAME) return  1; \
    return 0; \
}

/* Define the (46!) cmp_ functions with the above macros for every element
   of proc_t.  If the binary gets too big, we could nuke inessentials.
*/

/* CMP_STR(cmdline) */
CMP_STR(ruser)
CMP_STR(euser)
CMP_STR(cmd)
/* CMP_INT(state) */
/* CMP_STR(ttyc) */
CMP_INT(euid)
CMP_INT(pid)
CMP_INT(ppid)
CMP_INT(pgrp)
CMP_INT(session)
CMP_INT(tty)
CMP_INT(tpgid)
CMP_INT(utime)
CMP_INT(stime)
CMP_INT(cutime)
CMP_INT(cstime)
/* CMP_INT(priority) */
CMP_INT(nice)
CMP_INT(start_time)
/* CMP_INT(signal) */
/* CMP_INT(blocked) */
/* CMP_INT(sigignore) */
/* CMP_INT(sigcatch) */
CMP_INT(flags)
CMP_INT(min_flt)
CMP_INT(cmin_flt)
CMP_INT(maj_flt)
CMP_INT(cmaj_flt)
/* CMP_INT(timeout) */
CMP_INT(vsize)
CMP_INT(rss)
/* CMP_INT(rss_rlim) */
/* CMP_INT(start_code) */
/* CMP_INT(end_code) */
/* CMP_INT(start_stack) */
/* CMP_INT(kstk_esp) */
/* CMP_INT(kstk_eip) */
/* CMP_INT(wchan) */
CMP_INT(pcpu)
CMP_INT(size)
CMP_INT(resident)
CMP_INT(share)
/* CMP_INT(trs) */
/* CMP_INT(lrs) */
/* CMP_INT(drs) */
/* CMP_INT(dt) */

/* define user interface to sort keys.  Fairly self-explanatory. */

struct cmp_fun_struct {
    char letter;                           /* single option-letter for key */
    char name[15];                             /* long option name for key */
    int (*fun)(proc_t**, proc_t**);  /* pointer to cmp_key */
} cmp[] = {
/*  { '?', "cmdline",       &cmp_cmdline       }, */
    { 'u', "user",          &cmp_euser         },
/*  { '?', "ruser",         &cmp_ruser         }, */
    { 'c', "cmd",           &cmp_cmd           },
/*  { '?', "state",         &cmp_state         }, */
/*  { '?', "ttyc",          &cmp_ttyc          }, */
    { 'U', "uid",           &cmp_euid          },
    { 'p', "pid",           &cmp_pid           },
    { 'P', "ppid",          &cmp_ppid          },
    { 'g', "pgrp",          &cmp_pgrp          },
    { 'o', "session",       &cmp_session       },
    { 't', "tty",           &cmp_tty           },
    { 'G', "tpgid",         &cmp_tpgid         },
    { 'k', "utime",         &cmp_utime         },
    { 'K', "stime",         &cmp_stime         },
    { 'j', "cutime",        &cmp_cutime        },
    { 'J', "cstime",        &cmp_cstime        },
/*  { '?', "counter",       &cmp_counter       }, */
    { 'y', "priority",      &cmp_nice          },
    { 'T', "start_time",    &cmp_start_time    },
/*  { '?', "signal",        &cmp_signal        }, */
/*  { '?', "blocked",       &cmp_blocked       }, */
/*  { '?', "sigignore",     &cmp_sigignore     }, */
/*  { '?', "sigcatch",      &cmp_sigcatch      }, */
    { 'f', "flags",         &cmp_flags         },
    { 'm', "min_flt",       &cmp_min_flt       },
    { 'n', "cmin_flt",      &cmp_cmin_flt      },
    { 'M', "maj_flt",       &cmp_maj_flt       },
    { 'N', "cmaj_flt",      &cmp_cmaj_flt      },
/*  { 'C', "timeout",       &cmp_timeout       }, */
    { 'v', "vsize",         &cmp_vsize         },
    { 'r', "rss",           &cmp_rss           },
/*  { '?', "rss_rlim",      &cmp_rss_rlim      }, */
/*  { '?', "start_code",    &cmp_start_code    }, */
/*  { '?', "end_code",      &cmp_end_code      }, */
/*  { '?', "start_stack",   &cmp_start_stack   }, */
/*  { '?', "kstk_esp",      &cmp_kstk_esp      }, */
/*  { '?', "kstk_eip",      &cmp_kstk_eip      }, */
/*  { '?', "wchan",         &cmp_wchan         }, */
    { 'C', "pcpu",          &cmp_pcpu          },
    { 's', "size",          &cmp_size          },
    { 'R', "resident",      &cmp_resident      },
    { 'S', "share",         &cmp_share         },
/*  { '?', "trs",           &cmp_trs           }, */
/*  { '?', "lrs",           &cmp_lrs           }, */
/*  { '?', "drs",           &cmp_drs           }, */
/*  { '?', "dt",            &cmp_dt            }, */
    { '\0',"terminator",    NULL               }
};

void dump_keys(void) {
    int i;
    for(i=0; cmp[i].letter; i++)
        fprintf(stderr, "%s-O%c , --sort:%-15.15s%s",
		i%2?"":"           ",
		cmp[i].letter, cmp[i].name,
		i%2?"\n":"");
    if (i%2)
      fprintf(stderr, "\n");
}
 
/* command line option parsing.  Assign sort_{depth,direction[],function[]}
   based upon a string of the form:
        [+-]a[+-]b[+-]c...
   with a,b,c,... being letter flags corresponding to a particular sort
   key and the optional '-' specifying a reverse sort on that key.  + doesn't
   mean anything, but it keeps things looking balanced...
*/
const char *parse_sort_opt(const char* opt) {
    int i, next_dir=1;
    for(; *opt ; ++opt) {
        if (*opt == '-' || *opt == '+') {
            if (*opt == '-')
                next_dir = -1;
	    opt++;
            continue;
        }
        for (i = 0; cmp[i].letter; i++)
            if (*opt == cmp[i].letter)
                break;
        if (!cmp[i].letter) { /* failed, clear and return */
            sort_depth=0;
            for (i=0;i<10;i++){
              sort_direction[i]=0;
              sort_function[i]=(cmp_t)NULL;
            }
            return "Unknown sort key.";
        } else {
#ifdef DEBUG
	    fprintf(stderr,
		    "sort level %d: key %s, direction % d\n",
		    sort_depth, cmp[i].name, next_dir);
#endif
            sort_function[sort_depth] = (cmp_t)cmp[i].fun;
            sort_direction[sort_depth++] = next_dir;
            next_dir = 1;
        }
    }
    return NULL;
}

const char *parse_long_sort(const char* opt) {
    char* comma;
    int i, more_keys, next_dir=1;
    do {
        if (*opt == '-' || *opt == '+') {
            if (*opt == '-')
                next_dir = -1;
            more_keys = 1;
            opt++;
            continue;
        }
        more_keys = ((comma=index(opt,',')) != NULL);
	                      /* keys are ',' delimited */
        if (more_keys)
            *comma='\0';      /* terminate for strcmp() */
        for(i = 0; cmp[i].letter; ++i)
            if (strcmp(opt, cmp[i].name) == 0)
                break;
        if (!cmp[i].letter) { /* failed, clear and return */
            sort_depth=0;
            for (i=0;i<10;i++){
              sort_direction[i]=0;
              sort_function[i]=(cmp_t)NULL;
            }
            return "Unknown sort key.";
        } else {
#ifdef DEBUG
	    fprintf(stderr,
		    "sort level %d: key %s, direction % d\n",
		    sort_depth, cmp[i].name, next_dir);
#endif
            sort_function[sort_depth] = (cmp_t)cmp[i].fun;
            sort_direction[sort_depth++] = next_dir;
            next_dir = 1;
        }
        opt = comma + 1; /* do next loop on next key, if more keys, else done*/
    } while (more_keys);
    return NULL;
}

void reset_sort_options (void)
{
  int i;

  sort_depth=0;
  for (i=0;i<10;i++){
    sort_direction[i]=0;
    sort_function[i]=(cmp_t)NULL;
  }
}

void register_sort_function (int dir, cmp_t func)
{
    sort_function[sort_depth] = func;
    sort_direction[sort_depth++] = dir;
}
procps-2.0.7/proc/devname.c0100664000076400007640000001376207132365673016064 0ustar  johnsonmjohnsonm/*
 * Copyright 1998 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 <sys/sysmacros.h>
#include "devname.h"

#include <asm/page.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE (sizeof(long)*1024)
#endif

/* Who uses what:
 *
 * tty_to_dev   oldps, w (there is a fancy version in ps)
 * dev_to_tty   oldps, top, ps
 */

typedef struct c_syntax_requires_useless_crap {
  struct c_syntax_requires_useless_crap *next;
  unsigned int major_number;
  char name[4];
} 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, 9999);
  if(bytes == -1) goto fail;
  buf[bytes] = '\0';
  p = buf;
  while(( p = strstr(p, " /dev/tty") )){
    tty_map_node *tmn;
    int len;
    p += 9;
    len = strspn(p, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    if(!len) continue;
    if(len>3) continue;
    if((len=1) && (*p=='S')) continue;
    tmn = malloc(sizeof(tty_map_node));
    tmn->next = tty_map;
    tty_map = tmn;
    memset(tmn->name, '\0', 4);
    strncpy(tmn->name, p, len);
    p += len;
    tmn->major_number = atoi(p);
  }
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 * const buf, int maj, int 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) break;
    tmn = tmn->next;
  }
  sprintf(buf, "/dev/tty%s%d", tmn->name, min);  /* like "/dev/ttyZZ255" */
  if(stat(buf, &sbuf) < 0) return 0;
  if(min != minor(sbuf.st_rdev)) return 0;
  if(maj != major(sbuf.st_rdev)) return 0;
  return 1;
}

/* Try to guess the device name (we only need pre-2.2 devices) */
static int guess_name(char * const buf, int maj, int min){
  struct stat sbuf;
  int t0, t1;
  int tmpmin = min;
  switch(maj){
  case   4:
    if(min<64){
      sprintf(buf, "/dev/tty%d", min);
      break;
    }
    if(min<128){
      sprintf(buf, "/dev/ttyS%d", min-64);
      break;
    }
    tmpmin = min & 0x3f;  /* FALL THROUGH */
  case   3:      /* /dev/[pt]ty[p-za-o][0-9a-z] is 936 */
    t0 = "pqrstuvwxyzabcde"[tmpmin>>4];
    t1 = "0123456789abcdef"[tmpmin&0x0f];
    sprintf(buf, "/dev/tty%c%c", t0, t1);
    break;
  case  17:  sprintf(buf, "/dev/ttyH%d",  min); break;
  case  19:  sprintf(buf, "/dev/ttyC%d",  min); break;
  case  23:  sprintf(buf, "/dev/ttyD%d",  min); break;
  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;
  case 105:  sprintf(buf, "/dev/ttyV%d",  min); break;
  /* 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;
  default: return 0;
  }
  if(stat(buf, &sbuf) < 0) return 0;
  if(min != minor(sbuf.st_rdev)) return 0;
  if(maj != major(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 fd_name(char * const buf, int maj, int min, int pid, int fd){
  struct stat sbuf;
  char path[32];
  int count;
  sprintf(path, "/proc/%d/fd/%d", pid, fd);  /* often permission denied */
  count = readlink(path,buf,PAGE_SIZE);
  if(count == -1) return 0;
  buf[count] = '\0';
  if(stat(buf, &sbuf) < 0) return 0;
  if(min != minor(sbuf.st_rdev)) return 0;
  if(maj != major(sbuf.st_rdev)) return 0;
  return 1;
}

/* number --> name */
int dev_to_tty(char *ret, int chop, int dev, int pid, unsigned int flags) {
  static char buf[PAGE_SIZE];
  char *tmp = buf;
  int i = 0;
  int c;
  if((short)dev == (short)-1) goto fail;
  if(    fd_name(tmp, major(dev), minor(dev), pid, 2  )) goto abbrev;
  if(    fd_name(tmp, major(dev), minor(dev), pid, 255)) goto abbrev;
  if( guess_name(tmp, major(dev), minor(dev)          )) goto abbrev;
  if(driver_name(tmp, major(dev), minor(dev)          )) goto abbrev;
fail:
  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;
  tmp[chop] = '\0';
  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(char *name) {
  struct stat sbuf;
  static char buf[32];
  if(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;
}
procps-2.0.7/proc/devname.h0100664000076400007640000000041006672166704016055 0ustar  johnsonmjohnsonm#define ABBREV_DEV  1     /* remove /dev/         */
#define ABBREV_TTY  2     /* remove tty           */
#define ABBREV_PTS  4     /* remove pts/          */

int dev_to_tty(char *ret, int chop, int dev, int pid, unsigned int flags);

int tty_to_dev(char *name);
procps-2.0.7/proc/ksym.c0100664000076400007640000002445507132365133015420 0ustar  johnsonmjohnsonm/*
 * Copyright (C) 1996 Charles Blake
 * Copyright (C) 1998 Michael K. Johnson
 * kernel address -> symbol with next lower address.  Charles Blake, 1996.
 * Written to obviate the need for psdatabase initialization based upon kernel
 * binary formats, etc.
 *
 * The basic algorithm is an approximate (intervals split vaguely 50-50) binary
 * search taking advantage of the fact the System.map is already sorted in
 * ascending order by the kernel makefile.  It needs to assume an average symbol
 * record length to avoid scanning the entire symbol table, but in practice the
 * search time does not seem to be especially sensitive to this choice.
 *
 * The search could be an exact binary search if the lines of System.map were
 * padded with blanks to the right.  awk '{printf "%8s%2s %-21.21s\n",$1,$2,$3}'
 * would do the trick for this but either makes the file large or truncates
 * symbols.  The approximate method seems to be plenty fast enough, costing
 * only about as much as one extra fstat() or so per process.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/utsname.h>
#include "proc/psdata.h"
#include "proc/procps.h"
#include "proc/version.h"

#define MAX_ADDR_SZ 32
static char *sysmap, *sysmap_last, sysmap_fmt[10];
static int   sysmap_len, sysmap_mean = 32, sysmap_addrsz;

static int three_column = 0;

/*
 * '?' 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"

/*******************************/

/* scan backward in a string no further than address beg looking for c */
static char *strchrrev(char *a, char *beg, char c) {
    if (a)
	while (--a > beg && *a != c) ;
    return a;
}

/* return ptr to the beg of approximately the i-th record */
static char *addr_str(int i) {
    char *guess = sysmap + sysmap_mean * i;
    if (!i) return sysmap;
    if (guess - sysmap > sysmap_len - 2) guess = sysmap + sysmap_len - 2;
    for ( ; *guess != '\n' && guess > sysmap; guess--)
	;
    return guess + 1;

}

/* return ptr to symbol string (\n terminated) given beg of record ptr */
static char *sym_put(char *buf, int len, char *addrptr) {
    char *s;
    while (*addrptr++ != ' ')   ;
    if(three_column) while (*addrptr++ != ' ')   ;
    strncpy(buf, addrptr, len);
    for (s = buf; s < buf + len; s++)
	if (*s == '\n')
	    *s = '\0';
    buf[len - 1] = '\0';
    return buf;
}

/****************************************/

/* Try to open and mmap a single symbol table file and initialize globals */
static int sysmap_mmap(const char *path, void (*message)(const char *, ...)) {
    int fd;
    struct stat sbuf;
    char *p;
    if (sysmap)		/* do nothing if already mapped */
	return 1;
    if ((fd = open(path, O_RDONLY)) < 0
	|| fstat(fd, &sbuf) < 0
	|| (sysmap = mmap(0, sbuf.st_size + 1,
			  PROT_READ, MAP_SHARED,
			  fd, 0)) == (caddr_t) -1)
    {
	close(fd);
	sysmap = NULL;
	return 0;
    }
    close(fd);
    sysmap_len = sbuf.st_size;
    sysmap_last = strchrrev(sysmap + sysmap_len - 2, sysmap, '\n') + 1;

    /* Now sanity check the System.map file */
    for (p = sysmap; *p != ' '
	     && ((*p >= '0' && *p <= '9') ||
		 (*p >= 'a' && *p <= 'f'))
	     && p < sysmap + MAX_ADDR_SZ;
	 p++) /* no-op */ ;
    three_column = (*(p+2) == ' ');
    sysmap_addrsz = p - sysmap;
    snprintf(sysmap_fmt, sizeof sysmap_fmt, "%%0%dlx", sysmap_addrsz);
    if( (*p != ' ') || (strspn(sysmap,LEGAL_SYSMAP_CHARS)!=strlen(sysmap)) ){
	message("Warning: %s not parseable as a System.map\n", path);
	munmap(sysmap, sysmap_len);
	sysmap = NULL;
	return 0;
    }
    /*
     * We should make sure this file matches the kernel. We can't get a build
     * number, but we do have a version code. The map file will contain
     * something like "001b407c D Version_131103\n".
     */
    do {
        char Version[32];
        sprintf(Version, " Version_%d\n", linux_version_code);
        if(strstr(sysmap, Version)) break;
	message("Warning: %s has an incorrect kernel version.\n", path);
	munmap(sysmap, sysmap_len);
	sysmap = NULL;
	return 0;
    } while(0);
    return 1;
}

/*******************************/

/* kernel address -> name resolver.
   returned value is only good until the next call to the function.
 */
static char *sysmap_symbol(unsigned long address) {
    static char rval[128], *pc, addr[MAX_ADDR_SZ];
    int i, p, n = sysmap_len / (double)sysmap_mean;

    sprintf(addr, sysmap_fmt, address);
    p = 0; pc = sysmap;
    while (n) {
	i = p + (n >> 1);
	if (strncmp(addr, pc = addr_str(i), sysmap_addrsz) > 0)
	    p = i + 1;
	n >>= 1;
    }
    if (pc == sysmap_last)		/* scan forward but not past end */
	return sym_put(rval, sizeof rval, pc);
    while (strncmp(addr, pc, sysmap_addrsz) > 0)
	pc = strchr(pc, '\n') + 1;
    if (pc == sysmap)			/* scan backward but not past beg */
	return sym_put(rval, sizeof rval, pc);
    while (strncmp(addr, pc, sysmap_addrsz) < 0)
	pc = strchrrev(pc - 1, sysmap, '\n') + 1;
    return sym_put(rval, sizeof rval, pc);
}

/*********************************/

#if 0
/* extern struct nlist *namelist; */
struct tbl_s vars, fncs;
struct psdb_hdr db_hdr;
int psdb = -1;
#endif

static void default_message(const char *format, ...) {
    va_list arg;

    va_start (arg, format);
    vfprintf (stderr, format, arg);
    va_end (arg);
}

int open_psdb_message(const char *override, void (*message)(const char *, ...)) {
    static char *sysmap_paths[] = {
	"/boot/System.map-%s",
	"/boot/System.map",
	"/lib/modules/%s/System.map",
	"/usr/src/linux/System.map",
	"/System.map",
	NULL
    };
#if 0
    static char *psdb_paths[] = {
	"/etc/psdatabase",
	"/boot/psdatabase-%s",
	"/boot/psdatabase",
	"/lib/modules/%s/psdatabase",
	NULL
    };
#endif
    char **fmt, *env, path[64];
    struct utsname uts;
    if(getuid()!=geteuid()){
      printf("The /proc library is not secure for setuid operation.");
      exit(1);
    }
    if(getgid()!=getegid()){
      printf("The /proc library is not secure for setgid operation.");
      exit(1);
    }
    uname(&uts);
    if(override){           /* ought to search some path */
      if(sysmap_mmap(override, message)) return 0;
      return -1;           /* ought to return "Namelist not found." */
      /* failure is better than ignoring the user & using bad data */
    }
    /* Arrrgh, the old man page and code did not match. */
    if ((env = getenv("PS_SYSMAP"))     && sysmap_mmap(env, message))	return 0;
    if ((env = getenv("PS_SYSTEM_MAP")) && sysmap_mmap(env, message))	return 0;
    for (fmt = sysmap_paths; *fmt; fmt++) {
	snprintf(path, sizeof path, *fmt, uts.release);
	if (sysmap_mmap(path, message)) return 0;
    }
#if 0
    for (fmt = psdb_paths; *fmt; fmt++) {
	snprintf(path, sizeof path, *fmt, uts.release);
	if ((psdb = open(path, O_RDONLY)) != -1 &&
	    read(psdb, (char*)&db_hdr, sizeof db_hdr) == sizeof db_hdr &&
	    strncmp(db_hdr.magic, procps_version, sizeof(db_hdr.magic)) == 0)
	    /* && version_cmp(kernel,psdatabase) */
	    return 0;
	if (psdb != -1)
	    message("psdatabase has magic no. %*s instead of %*s\n",
		    (int) sizeof db_hdr.magic, db_hdr.magic,
		    (int) sizeof db_hdr.magic, procps_version);
	close(psdb);
    }
#endif
    return -1;
}

int open_psdb(const char *override) {
    return open_psdb_message(override, default_message);
}

/***********************************/

void close_psdb(void) {
    if (sysmap)
	munmap(sysmap, sysmap_len);
#if 0
    else
        if (psdb != -1) close(psdb);
    psdb = -1;
#endif
    sysmap = NULL;
}

/*************************************/

#if 0
int read_tbl(struct dbtbl_s *dbtbl, struct tbl_s *tbl) {
    lseek(psdb, dbtbl->off, SEEK_SET);
    tbl->tbl = (struct sym_s *) xmalloc(dbtbl->size);
    if (read(psdb, (char *) tbl->tbl, dbtbl->size) != dbtbl->size) {
	perror(PSDATABASE);
	exit(1);
    }
    tbl->nsym = dbtbl->nsym;
    tbl->strings = (char *) (tbl->tbl + tbl->nsym);
    return 0;
}
#endif

/*************************************/

/* Can't cache this, since modules may be loaded while top runs. */
char* find_module_sym(unsigned long address) {
   FILE *fd;
   static char buf[512];
   unsigned long adr, best_adr = 0;
   char mod[32], nm[32]; char c;
   *mod = 1;
   *buf = '\0'; /* sprintf (buf, "%08x", address); */
   fd = fopen ("/proc/ksyms", "r");
   if (!fd) return ("(no proc)");   /* FIXME return the number as text */
   while (!feof (fd) && !(*mod == '\0')) {
      fscanf (fd, "%lx %s\n", &adr, nm);
      if ((c = fgetc (fd)) != '[') *mod = '\0'; 
      else { fscanf (fd, "%s", mod); };
      if (abs(address - adr) < abs(address - best_adr) /* && address >= adr */
         && abs(address - adr) < 0xa00) {  /* FIXME is 0xa00 a good test? */
        best_adr = adr; *buf = '[';
/* FIXME Why the 0x100 limitation? */
        if (address - adr > 0x100) strcpy (buf+1, mod); /* module name */
        else strcpy(buf, nm); /* name of function/variable */
      };
   };
   fclose (fd);
   return buf;
};

/*************************************/

char * find_func(unsigned long address)	{
#if 0
    int n;
    struct sym_s *p;
    char *s;
#endif
    if (sysmap)
	return sysmap_symbol(address);
#if 0
    if (psdb == -1)
	return "(no psdb)";
    if (fncs.tbl == NULL)
	read_tbl(&db_hdr.fncs, &fncs);
    p = fncs.tbl;
    n = fncs.nsym;
    if (address > p[n-1].addr) return find_module_sym(address);
    while (n) {
	int i = n / 2;
	if (p[i].addr < address) {
	    p = &p[i+1];
	    if (p->addr > address) {
		--p;
		break;
	    }
	    --n;
	}
	n /= 2;
    }
    s = p->name + fncs.strings;
    return *s=='_' ? s+1 : s;
#else
    return "ERROR";
#endif
}

/***************************************/

char * wchan(unsigned long address) {
    static char zero = 0;
    char *p;

    if (address) {
	p = find_func(address);
	if (strncmp(p, "sys_", 4) == 0)
	    p += 4;
	while (*p == '_' && *p)
	    ++p;
    } else /* 0 address means not in kernel space */
	p = &zero;
    return p;
}

#ifdef SYSMAP_TEST
int main(int ac, char** av) {
    if (ac < 3) {printf("%s System.map lines hexaddr ...\n",av[0]); return 1;}
    if (!sysmap_mmap(av[1], default_message)) return 1;
    if ((sysmap_mean = atoi(av[2])) <= 0) return 1;
    for (av += 3; *av; av++)
	printf("%s %s\n", *av, sysmap_symbol(strtoul(*av, NULL, 16)));
    return 0;
}
#endif
procps-2.0.7/proc/output.c0100664000076400007640000000267706672166704016012 0ustar  johnsonmjohnsonm/*
  Some output conversion routines for libproc
  Copyright (C) 1996, Charles Blake.  See COPYING for details.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>

/* output a string, converting unprintables to octal as we go, and stopping after
   processing max chars of output (accounting for expansion due to octal rep).
*/
unsigned print_str(FILE* file, char *s, unsigned max) {
    int i;
    for (i=0; s[i] && i < max; i++)
	if (isprint(s[i]) || s[i] == ' ')
	    fputc(s[i], file);
	else {
	    if (max - i > 3) {
		fprintf(file, "\\%03o", s[i]);
		i += 3; /* 4 printed, but i counts one */
	    } else
		return max - i;
	}
    return max - i;
}

/* output an argv style NULL-terminated string list, converting unprintables
   to octal as we go, separating items of the list by 'sep' and stopping after
   processing max chars of output (accounting for expansion due to octal rep).
*/
unsigned print_strlist(FILE* file, char **strs, char* sep, unsigned max) {
    int i, n, seplen = strlen(sep);
    for (n=0; *strs && n < max; strs++) {
	for (i=0; strs[0][i] && n+i < max; i++)
	    if (isprint(strs[0][i]) || strs[0][i] == ' ')
		fputc(strs[0][i], file);
	    else {
		if (max-(n+i) > 3) {
		    fprintf(file, "\\%03o", strs[0][i]);
		    n += 3; /* 4 printed, but i counts one */
		} else
		    return max - n;
	    }
	n += i;
	if (n + seplen < max) {
	    fputs(sep, file);
	    n += seplen;
	} else
	    return max - n;
    }
    return max - n;
}
procps-2.0.7/proc/procps.h0100664000076400007640000000200407132365133015732 0ustar  johnsonmjohnsonm/* The shadow of the original with only common prototypes now. */
#include <stdio.h>
#include <sys/types.h>

/* get definition of HZ */
/*#include <asm/param.h>*/

/* get page info */
#include <asm/page.h>

char *wchan(unsigned long);
char *find_func(unsigned long address);
void *xcalloc(void *pointer, int size);
void *xmalloc(unsigned int size);
void *xrealloc(void *oldp, unsigned int size);
       
int   mult_lvl_cmp(void* a, void* b);
int   node_mult_lvl_cmp(void* a, void* b);
void  dump_keys(void);
       
char *user_from_uid(uid_t uid);
char *group_from_gid(gid_t gid);

/* int   open_sysmap(void); */
int   open_psdb(const char *override);
int   open_psdb_message(const char *override, void (*message)(const char *, ...));
void  close_psdb(void);
void  make_fnctbl(void);

unsigned print_str    (FILE* file, char *s, unsigned max);
unsigned print_strlist(FILE* file, char **strs, char* sep, unsigned max);

/* This doesn't really exist! */
/* unsigned snprint_strlist(char *buf, int max, char **strs, char *sep); */
procps-2.0.7/proc/ps.h0100664000076400007640000000151406403052072015046 0ustar  johnsonmjohnsonm/* The shadow of the original with only common prototypes now. */
#include <stdio.h>
#include <sys/types.h>

/* get definition of HZ */
#include <asm/param.h>

/* get page info */
#include <asm/page.h>

char *wchan(unsigned long);
char *find_func(unsigned long address);
void *xcalloc(void *pointer, int size);
void *xmalloc(unsigned int size);
void *xrealloc(void *oldp, unsigned int size);
       
int   mult_lvl_cmp(void* a, void* b);
int   node_mult_lvl_cmp(void* a, void* b);
void  dump_keys(void);
       
char *user_from_uid(int uid);

int   open_sysmap(void);
int   open_psdb(void);
void  close_psdb(void);
void  make_fnctbl(void);

unsigned print_str    (FILE* file, char *s, unsigned max);
unsigned print_strlist(FILE* file, char **strs, char* sep, unsigned max);
unsigned snprint_strlist(char *buf, int max, char **strs, char *sep);
procps-2.0.7/proc/psdata.h0100664000076400007640000000515706403041345015710 0ustar  johnsonmjohnsonm/*
 * psdata.h
 *
 * Jeffrey A. Uphoff <juphoff@nrao.edu>, 1995, 1996.
 * Michael K. Johnson.
 * Bruno Lankester.
 * (And others I'm sure...)
 *
 */

/*
 * Capabilities are for reading system images and producing maps for
 * WCHAN output.
 *
 * AOUT_CAPABLE and ELF_CAPABLE may have 32-bit word size limitations
 * and have only been tested by the maintainer on Intel systems.  They
 * are retained in the source tree in case they are useful; they are
 * intended to be generally deprecated.
 *
 * BFD_CAPABLE should work on any system with BFD.
 *
 * Set the capabilities in the top-level Makefile.
 */

#if defined(ELF_CAPABLE)
# define ELF_OBJECT 1
# define ELF_FUNC 2
#endif

#include <sys/types.h>
#include <linux/utsname.h>

#define        PSDATABASE      "/etc/psdatabase"

struct dbtbl_s {
  off_t off;			/* offset in psdatabase */
  int nsym;			/* # symbols */
  int size;			/* size of array + strings */
};

/*
 * header of psdatabase
 */
struct psdb_hdr {
  /* Current procps package version goes here.  kmemps doesn't like this. */
  char magic[32];
  /* 
   * These are not functional--they only reside in the database for
   * informational purposes (i.e. if you want to look at the raw
   * database and see what kernel it's for).
   */
  char uts_release[__NEW_UTS_LEN];
  char uts_version[__NEW_UTS_LEN];
  /* 
   * Again, this is not functional, it's just there for information: it
   * shows the path to the uncompressed kernel image that was used to
   * generate this database.
   */
  char sys_path[128];
  /* List of all functions. */
  struct dbtbl_s fncs;
  /* 
   * This is currently only used to look up system_utsname while
   * psupdate is building the database--it really should be phased out!
   */
  /* List of all bss and data symbols. */
  struct dbtbl_s vars;
  /* 
   * The list of tty names that kmemps likes/uses in no longer present
   * in the procps psdatabase--it was never being built by procps'
   * psupdate anyway, so I removed the entry from the database header.
   */
};

struct sym_s {
  unsigned long addr;		/* core address in kernel */
  int name;			/* offset from strings ptr */
};

struct tbl_s {
  struct sym_s *tbl;
  int nsym;
  char *strings;		/* ptr to start of strings */
};

extern struct psdb_hdr db_hdr;
extern struct tbl_s fncs, vars;

int read_tbl (struct dbtbl_s *, struct tbl_s *);
void *xmalloc (unsigned int);
void *xrealloc (void *, unsigned int);

#define MLSEEK(FD, WHERE, WHENCE, ERROR)\
if (lseek ((FD), (WHERE), (WHENCE)) == -1) {\
  perror ((ERROR));\
  exit (errno);\
}

#define MREAD(FD, WHAT, SIZE, ERROR)\
if (read ((FD), (WHAT), (SIZE)) != (SIZE)) {\
  perror ((ERROR));\
  exit (errno);\
}
procps-2.0.7/proc/pwcache.c0100664000076400007640000000366307132441526016046 0ustar  johnsonmjohnsonm/***********************************************************************\
*   Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com *
*                                                                      *
*      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 <sys/types.h>
#include <stdlib.h>
#include <pwd.h>
#include "proc/procps.h"
#include <grp.h>

#define	HASHSIZE	16			/* power of 2 */
#define	HASH(x)		((x) & (HASHSIZE - 1))

#define NAMESIZE	16
#define NAMELENGTH	"15"

static struct pwbuf {
    uid_t uid;
    char name[NAMESIZE];
    struct pwbuf *next;
} *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;
    if ((pw = getpwuid(uid)) == NULL)
	sprintf((*p)->name, "#%d", uid);
    else
	sprintf((*p)->name, "%-." NAMELENGTH "s", pw->pw_name);
    (*p)->next = NULL;
    return((*p)->name);
}

static struct grpbuf {
    gid_t gid;
    char name[NAMESIZE];
    struct grpbuf *next;
} *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;
    if ((gr = getgrgid(gid)) == NULL)
       sprintf((*g)->name, "#%d", gid);
    else
       sprintf((*g)->name, "%-." NAMELENGTH "s", gr->gr_name);
    (*g)->next = NULL;
    return((*g)->name);
}

void bad_user_access_length() { }
procps-2.0.7/proc/readproc.c0100664000076400007640000005032007132425073016222 0ustar  johnsonmjohnsonm/*
 * New Interface to Process Table -- PROCTAB Stream (a la Directory streams)
 * Copyright (C) 1996 Charles L. Blake.
 * Copyright (C) 1998 Michael K. Johnson
 * May be distributed under the conditions of the
 * GNU Library General Public License; a copy is in COPYING
 */
#include "proc/version.h"
#include "proc/readproc.h"
#include "proc/devname.h"
#include "proc/procps.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/dir.h>
#include <sys/types.h>
#include <sys/stat.h>

#define Do(x) (flags & PROC_ ## x)	/* convenient shorthand */

/* initiate a process table scan
 */
PROCTAB* openproc(int flags, ...) {
    va_list ap;
    PROCTAB* PT = xmalloc(sizeof(PROCTAB));
    
    if (Do(PID))
      PT->procfs = NULL;
    else if (!(PT->procfs = opendir("/proc")))
      return NULL;
    PT->flags = flags;
    va_start(ap, flags);		/*  Init args list */
    if (Do(PID))
    	PT->pids = va_arg(ap, pid_t*);
    else if (Do(TTY))
    	PT->ttys = va_arg(ap, dev_t*);
    else if (Do(UID)) {
    	PT->uids = va_arg(ap, uid_t*);
	PT->nuid = va_arg(ap, int);
    } else if (Do(STAT))
    	PT->stats = va_arg(ap, char*);
    va_end(ap);				/*  Clean up args list */
    if (Do(ANYTTY) && Do(TTY))
	PT->flags = PT->flags & ~PROC_TTY; /* turn off TTY flag */
    return PT;
}

/* terminate a process table scan
 */
void closeproc(PROCTAB* PT) {
    if (PT->procfs) closedir(PT->procfs);
    if (PT)         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 status2proc (char* S, proc_t* P, int fill) {
    char* tmp;
    if (fill == 1) {
        memset(P->cmd, 0, sizeof P->cmd);
        sscanf (S, "Name:\t%15c", P->cmd);
        tmp = strchr(P->cmd,'\n');
        *tmp='\0';
        tmp = strstr (S,"State");
        sscanf (tmp, "State:\t%c", &P->state);
    }

    tmp = strstr (S,"Pid:");
    if(tmp) sscanf (tmp,
        "Pid:\t%d\n"
        "PPid:\t%d\n",
        &P->pid,
        &P->ppid
    );
    else fprintf(stderr, "Internal error!\n");

    tmp = strstr (S,"Uid:");
    if(tmp) sscanf (tmp,
        "Uid:\t%d\t%d\t%d\t%d",
        &P->ruid, &P->euid, &P->suid, &P->fuid
    );
    else fprintf(stderr, "Internal error!\n");

    tmp = strstr (S,"Gid:");
    if(tmp) sscanf (tmp,
        "Gid:\t%d\t%d\t%d\t%d",
        &P->rgid, &P->egid, &P->sgid, &P->fgid
    );
    else fprintf(stderr, "Internal error!\n");

    tmp = strstr (S,"VmSize:");
    if(tmp) sscanf (tmp,
        "VmSize: %lu kB\n"
        "VmLck: %lu kB\n"
        "VmRSS: %lu kB\n"
        "VmData: %lu kB\n"
        "VmStk: %lu kB\n"
        "VmExe: %lu kB\n"
        "VmLib: %lu kB\n",
        &P->vm_size, &P->vm_lock, &P->vm_rss, &P->vm_data,
        &P->vm_stack, &P->vm_exe, &P->vm_lib
    );
    else /* looks like an annoying kernel thread */
    {
        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;
    }

    tmp = strstr (S,"SigPnd:");
    if(tmp) sscanf (tmp,
#ifdef SIGNAL_STRING
        "SigPnd: %s SigBlk: %s SigIgn: %s %*s %s",
        P->signal, P->blocked, P->sigignore, P->sigcatch
#else
        "SigPnd: %Lx SigBlk: %Lx SigIgn: %Lx %*s %Lx",
        &P->signal, &P->blocked, &P->sigignore, &P->sigcatch
#endif
    );
    else fprintf(stderr, "Internal error!\n");
}



/* stat2proc() makes sure it can handle arbitrary executable file basenames
   for `cmd', i.e. those with embedded whitespace or embedded ')'s.  Such names
   confuse %s (see scanf(3)), so the string is split and %39c is used instead.
   (except for embedded ')' "(%[^)]c)" would work.
*/
void stat2proc(char* S, proc_t* P) {
    int num;
    char* tmp = strrchr(S, ')');	/* 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 even though *P xcalloc'd ?! */
    sscanf(S, "%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 "
       "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */
       "%lu %lu %lu %*d %d",
       &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->timeout, &P->it_real_value,
       &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 /* , &P->exit_signal  */, &P->lproc);
/* TODO: add &P->exit_signal support here, perhaps to identify Linux threads */
    
/*    fprintf(stderr, "stat2proc converted %d fields.\n",num); */
    if (P->tty == 0)
	P->tty = -1;  /* the old notty val, update elsewhere bef. moving to 0 */
    if (linux_version_code < LINUX_VERSION(1,3,39)) {
	P->priority = 2*15 - P->priority;	/* map old meanings to new */
	P->nice = 15 - P->nice;
    }
    if (linux_version_code < LINUX_VERSION(1,1,30) && P->tty != -1)
	P->tty = 4*0x100 + P->tty;		/* when tty wasn't full devno */
}

void statm2proc(char* s, proc_t* 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); */
}

void nulls2sep(char* str, int len, char sep) {
    int i;
    for (i = 0; i < len; i++)
    	if (str[i] == 0)
    	    str[i] = sep;
}

int file2str(char *directory, char *what, char *ret, int cap) {
    static char filename[80];
    int fd, num_read;

    sprintf(filename, "%s/%s", directory, what);
    if ( (fd       = open(filename, O_RDONLY, 0)) == -1 ) return -1;
    if ( (num_read = read(fd, ret, cap - 1))      <= 0 ) num_read = -1;
    else ret[num_read] = 0;
    close(fd);
    return num_read;
}

char** file2strvec(char* directory, 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);
    if ( (fd = open(buf, O_RDONLY, 0) ) == -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 < 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;
}


/* 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;			\
	} )

/* 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.
 * Unfortunately, the reverse filtering option in which any PID *except* the
 * ones listed is pursued.
 */
proc_t* readproc(PROCTAB* PT, proc_t* rbuf) {
    static struct direct *ent;		/* dirent handle */
    static struct stat sb;		/* stat buffer */
    static char path[32], sbuf[512];	/* bufs for stat,statm */
    int allocated = 0, matched = 0;	/* flags */
    proc_t *p = NULL;

    /* loop until a proc matching restrictions is found or no more processes */
    /* I know this could be a while loop -- this way is easier to indent ;-) */
next_proc:				/* get next PID for consideration */

/*printf("PT->flags is 0x%08x\n", PT->flags);*/
#define flags (PT->flags)

    if (Do(PID)) {
	if (!*PT->pids)			/* set to next item in pids */
	    return NULL;
	sprintf(path, "/proc/%d", *(PT->pids)++);
	matched = 1;
    } else {					/* get next numeric /proc ent */
	while ((ent = readdir(PT->procfs)) &&
	       (*ent->d_name < '0' || *ent->d_name > '9'))
	    ;
	if (!ent || !ent->d_name)
	    return NULL;
	sprintf(path, "/proc/%s", ent->d_name);
    }
    if (stat(path, &sb) == -1)		/* no such dirent (anymore) */
	goto next_proc;
    if (Do(UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid))
	goto next_proc;			/* not one of the requested uids */

    if (!allocated) {				 /* assign mem for return buf */
	p = rbuf ? rbuf : xcalloc(p, sizeof *p); /* passed buf or alloced mem */
	allocated = 1;				 /* remember space is set up */
    }
    p->euid = sb.st_uid;			/* need a way to get real uid */

    if ((file2str(path, "stat", sbuf, sizeof sbuf)) == -1)
	goto next_proc;			/* error reading /proc/#/stat */
    stat2proc(sbuf, p);				/* parse /proc/#/stat */

    if (!matched && Do(TTY) && !XinL(dev_t, p->tty, PT->ttys))
	goto next_proc;			/* not one of the requested ttys */

    if (!matched && Do(ANYTTY) && p->tty == -1)
	goto next_proc;			/* no controlling terminal */

    if (!matched && Do(STAT) && !strchr(PT->stats,p->state))
	goto next_proc;			/* not one of the requested states */

    if (Do(FILLMEM)) {				/* read, parse /proc/#/statm */
	if ((file2str(path, "statm", sbuf, sizeof sbuf)) != -1 )
	    statm2proc(sbuf, p);		/* ignore statm errors here */
    }						/* statm fields just zero */

    if (Do(FILLSTATUS)) {         /* read, parse /proc/#/status */
       if ((file2str(path, "status", sbuf, sizeof sbuf)) != -1 ){
           status2proc(sbuf, p, 0 /*FIXME*/);
       }
    }

    /* some number->text resolving which is time consuming */
    if (Do(FILLUSR)){
	strncpy(p->euser,   user_from_uid(p->euid), sizeof p->euser);
        strncpy(p->egroup, group_from_gid(p->egid), sizeof p->egroup);
        if(Do(FILLSTATUS)) {
            strncpy(p->ruser,   user_from_uid(p->ruid), sizeof p->ruser);
            strncpy(p->rgroup, group_from_gid(p->rgid), sizeof p->rgroup);
            strncpy(p->suser,   user_from_uid(p->suid), sizeof p->suser);
            strncpy(p->sgroup, group_from_gid(p->sgid), sizeof p->sgroup);
            strncpy(p->fuser,   user_from_uid(p->fuid), sizeof p->fuser);
            strncpy(p->fgroup, group_from_gid(p->fgid), sizeof p->fgroup);
        }
    }

    if (Do(FILLCMD))				/* read+parse /proc/#/cmdline */
	p->cmdline = file2strvec(path, "cmdline");
    if (Do(FILLENV))				/* read+parse /proc/#/environ */
	p->environ = file2strvec(path, "environ");
    
    if (p->state == 'Z')			/* fixup cmd for zombies */
	strncat(p->cmd," <defunct>", sizeof p->cmd);

    return p;
}
#undef flags

/* ps_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.
 * Unfortunately, the reverse filtering option in which any PID *except* the
 * ones listed is pursued.
 */
proc_t* ps_readproc(PROCTAB* PT, proc_t* rbuf) {
    static struct direct *ent;		/* dirent handle */
    static struct stat sb;		/* stat buffer */
    static char path[32], sbuf[512];	/* bufs for stat,statm */
    int allocated = 0 /* , matched = 0 */ ;	/* flags */
    proc_t *p = NULL;

    /* loop until a proc matching restrictions is found or no more processes */
    /* I know this could be a while loop -- this way is easier to indent ;-) */
next_proc:				/* get next PID for consideration */

/*printf("PT->flags is 0x%08x\n", PT->flags);*/
#define flags (PT->flags)

	while ((ent = readdir(PT->procfs)) &&
	       (*ent->d_name < '0' || *ent->d_name > '9'))
	    ;
	if (!ent || !ent->d_name)
	    return NULL;
	sprintf(path, "/proc/%s", ent->d_name);

    if (stat(path, &sb) == -1)		/* no such dirent (anymore) */
	goto next_proc;

    if (!allocated) {				 /* assign mem for return buf */
	p = rbuf ? rbuf : xcalloc(p, sizeof *p); /* passed buf or alloced mem */
	allocated = 1;				 /* remember space is set up */
    }
    p->euid = sb.st_uid;			/* need a way to get real uid */

    if ((file2str(path, "stat", sbuf, sizeof sbuf)) == -1)
	goto next_proc;			/* error reading /proc/#/stat */
    stat2proc(sbuf, p);				/* parse /proc/#/stat */

/*    if (Do(FILLMEM)) {*/				/* read, parse /proc/#/statm */
	if ((file2str(path, "statm", sbuf, sizeof sbuf)) != -1 )
	    statm2proc(sbuf, p);		/* ignore statm errors here */
/*    }			*/			/* statm fields just zero */

  /*  if (Do(FILLSTATUS)) { */        /* read, parse /proc/#/status */
       if ((file2str(path, "status", sbuf, sizeof sbuf)) != -1 ){
           status2proc(sbuf, p, 0 /*FIXME*/);
       }
/*    }*/

    /* some number->text resolving which is time consuming */
 /*   if (Do(FILLUSR)){ */
	strncpy(p->euser,   user_from_uid(p->euid), sizeof p->euser);
        strncpy(p->egroup, group_from_gid(p->egid), sizeof p->egroup);
/*        if(Do(FILLSTATUS)) { */
            strncpy(p->ruser,   user_from_uid(p->ruid), sizeof p->ruser);
            strncpy(p->rgroup, group_from_gid(p->rgid), sizeof p->rgroup);
            strncpy(p->suser,   user_from_uid(p->suid), sizeof p->suser);
            strncpy(p->sgroup, group_from_gid(p->sgid), sizeof p->sgroup);
            strncpy(p->fuser,   user_from_uid(p->fuid), sizeof p->fuser);
            strncpy(p->fgroup, group_from_gid(p->fgid), sizeof p->fgroup);
/*        }*/
/*    }*/

/*    if (Do(FILLCMD))	*/			/* read+parse /proc/#/cmdline */
	p->cmdline = file2strvec(path, "cmdline");
/*    if (Do(FILLENV))	*/			/* read+parse /proc/#/environ */
	p->environ = file2strvec(path, "environ");
    
    if (p->state == 'Z')			/* fixup cmd for zombies */
	strncat(p->cmd," <defunct>", sizeof p->cmd);

    return p;
}
#undef flags


void look_up_our_self(proc_t *p) {
    static char path[32], sbuf[512];	/* bufs for stat,statm */
    sprintf(path, "/proc/%d", getpid());
    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*/);
}


/* Convenient wrapper around openproc and readproc to slurp in the whole process
 * tree subset satisfying the constraints of flags and the optional PID list.
 * Free allocated memory with freeproctree().  The tree structure is a classic
 * left-list children + right-list siblings.  The algorithm is a two-pass of the
 * process table.  Since most process trees will have children with strictly
 * increasing PIDs, most of the structure will be picked up in the first pass.
 * The second loop then cleans up any nodes which turn out to have preceeded
 * their parent in /proc order.
 */

/* Traverse tree 't' breadth-first looking for a process with pid p */
proc_t* LookupPID(proc_t* t, pid_t p) {
    proc_t* tmp = NULL;
    if (!t)
	return NULL;
    if (t->pid == p)				/* look here/terminate recursion */
	return t;
    if ((tmp = LookupPID(t->l, p)))		/* recurse over children */
	return tmp;
    for (; t; t=t->r)				/* recurse over siblings */
	if ((tmp = LookupPID(tmp, p)))
	    return tmp;
    return NULL;
}

proc_t* readproctree(int flags, ...) {
    static proc_t tree;
    PROCTAB* PT = NULL;
    proc_t *node, *tmp=NULL, *tmp2=NULL;
    va_list ap;
    
    /* pass through apropriate arguments to openproc */
    va_start(ap, flags);
    if (Do(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 (Do(PID) || Do(TTY) || Do(STAT))
	PT = openproc(flags, va_arg(ap, void*));
    else
	PT = openproc(flags);
    va_end(ap);

    /* first pass: build tree, putting orphans on the first level */
    tree.l = tree.r = NULL;
    while ((node = readproc(PT,0)))
	if ((tmp = LookupPID(&tree, node->ppid))) {
	    node->r = tmp->l->r;	/* node --> left list of parent */
	    tmp->l->r = node;
	} else {
	    node->r = tree.r;		/* node --> right list of 'tree' */
	    tree.r = node;
	}
    /* second pass: scan tree for PPIDs of level-1 nodes moving links as necessary */
    for (node = &tree; node; node = node->r)
	if ((tmp = LookupPID(&tree, node->r->ppid))) {
	    tmp2 = node->r;			/* unlink from right list of 'tree' */
	    node->r = node->r->r;
	    tmp2->r = tmp->l->r;		/* insert as child of found node */
	    tmp->l->r = node;
	}
    closeproc(PT);
    return &tree;
}

/* 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 freeproctab().  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 (Do(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 (Do(PID) || Do(TTY) || Do(STAT))
	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(PT, NULL);		  /* final null to terminate */
    } while (tab[n++]);				  /* stop when NULL reached */
    closeproc(PT);
    return tab;
}

/* deallocate a table of pointers to proc structures
 */
void freeproctab(proc_t** tab) {
    proc_t** p;
    for(p = tab; *p; p++)
	freeproc(*p);
    free(tab);
}
procps-2.0.7/proc/readproc.h0100664000076400007640000002215307132377621016237 0ustar  johnsonmjohnsonm#ifndef PROCPS_PROC_READPROC_H
#define PROCPS_PROC_READPROC_H
/*
 * New Interface to Process Table -- PROCTAB Stream (a la Directory streams)
 * Copyright (C) 1996 Charles L. Blake.
 * Copyright (C) 1998 Michael K. Johnson
 * May be distributed under the terms of the
 * GNU Library General Public License, a copy of which is provided
 * in the file COPYING
 */


#define SIGNAL_STRING


/*
ld	cutime, cstime, priority, nice, timeout, it_real_value, 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, nswap, cnswap,
*/

/* 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_s {
#ifdef SIGNAL_STRING
    char
	/* Linux 2.1.7x and up have more signals. This handles 88. */
	signal[24],	/* mask of pending signals */
	blocked[24],	/* mask of blocked signals */
	sigignore[24],	/* mask of ignored signals */
	sigcatch[24];	/* mask of caught  signals */
#else
    long long
	/* Linux 2.1.7x and up have more signals. This handles 64. */
	signal,		/* mask of pending signals */
	blocked,	/* mask of blocked signals */
	sigignore,	/* mask of ignored signals */
	sigcatch;	/* mask of caught  signals */
#endif
    long
	cutime,		/* cumulative utime of process and reaped children */
	cstime,		/* cumulative stime of process and reaped children */
	priority,	/* kernel scheduling priority */
	timeout,	/* ? */
	nice,		/* standard unix nice level of process */
	rss,		/* resident set size from /proc/#/stat */
	it_real_value,	/* ? */
    /* the next 7 members come from /proc/#/statm */
	size,		/* total # of pages of memory */
	resident,	/* number of resident set (non-swapped) pages (4k) */
	share,		/* number of pages of shared (mmap'd) memory */
	trs,		/* text resident set size */
	lrs,		/* shared-lib resident set size */
	drs,		/* data resident set size */
	dt;		/* dirty pages */
    unsigned long
	/* FIXME: are these longs? Maybe when the alpha does PCI bounce buffers */
	vm_size,        /* same as vsize in kb */
	vm_lock,        /* locked pages in kb */
	vm_rss,         /* same as rss in kb */
	vm_data,        /* data size */
	vm_stack,       /* stack size */
	vm_exe,         /* executable size */
	vm_lib,         /* library size (all pages, not just used ones) */
	vsize,		/* number of pages of virtual memory ... */
	rss_rlim,	/* resident set size ... ? */
	flags,		/* kernel flags for the process */
	min_flt,	/* number of minor page faults since process start */
	maj_flt,	/* number of major page faults since process start */
	cmin_flt,	/* cumulative min_flt of process and child processes */
	cmaj_flt,	/* cumulative maj_flt of process and child processes */
	nswap,		/* ? */
	cnswap,		/* cumulative nswap ? */
	utime,		/* user-mode CPU time accumulated by process */
	stime,		/* kernel-mode CPU time accumulated by process */
	start_code,	/* address of beginning of code segment */
	end_code,	/* address of end of code segment */
	start_stack,	/* address of the bottom of stack for the process */
	kstk_esp,	/* kernel stack pointer */
	kstk_eip,	/* kernel stack pointer */
	start_time,	/* start time of process -- seconds since 1-1-70 */
	wchan;		/* address of kernel wait channel proc is sleeping in */
	int lproc;	/* last processor */
    struct proc_s *l,	/* ptrs for building arbitrary linked structs */
                  *r;	/* (i.e. singly/doubly-linked lists and trees */
    char
	**environ,	/* environment string vector (/proc/#/environ) */
	**cmdline;	/* command line string vector (/proc/#/cmdline) */
    char
	/* Be compatible: Digital allows 16 and NT allows 14 ??? */
    	ruser[16],	/* real user name */
    	euser[16],	/* effective user name */
    	suser[16],	/* saved user name */
    	fuser[16],	/* filesystem user name */
    	rgroup[16],	/* real group name */
    	egroup[16],	/* effective group name */
    	sgroup[16],	/* saved group name */
    	fgroup[16],	/* filesystem group name */
    	cmd[16];	/* basename of executable file in call to exec(2) */
    int
        ruid, rgid,     /* real      */
        euid, egid,     /* effective */
        suid, sgid,     /* saved     */
        fuid, fgid,     /* fs (used for file access only) */
    	pid,		/* process id */
    	ppid,		/* pid of parent process */
	pgrp,		/* process group id */
	session,	/* session id */
	tty,		/* full device number of controlling terminal */
	tpgid;		/* terminal process group id */
    unsigned
        pcpu;           /* %CPU usage (is not filled in by readproc!!!) */
    char
    	state;		/* single-char code for process state (S=sleeping) */
} 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>
typedef struct {
    DIR*	procfs;
    int		flags;
    pid_t*	pids;	/* pids of the procs */
    dev_t*	ttys;	/* devnos of the cttys */
    uid_t*	uids;	/* uids of procs */
    int		nuid;	/* cannot really sentinel-terminate unsigned short[] */
    char*	stats;	/* status chars (actually output into /proc//stat) */
} PROCTAB;

/* initialize a PROCTAB structure holding needed call-to-call persistent data
 */
PROCTAB* openproc(int flags, ... /* pid_t*|uid_t*|dev_t*|char* [, int n] */ );

/* 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 freeproctab().  Access via tab[N]->member.  The
 * pointer list is NULL terminated.
 */
proc_t** readproctab(int flags, ... /* same as openproc */ );

/* Convenient wrapper around openproc and readproc to slurp in the whole process
 * tree subset satisfying the constraints of flags and the optional PID list.
 */
proc_t* readproctree(int flags, ... /* same as openproc */ );

/* clean-up open files, etc from the openproc()
 */
void closeproc(PROCTAB* PT);

/* retrieve the next process matching the criteria set by the openproc()
 */
proc_t* readproc(PROCTAB* PT, proc_t* return_buf);
proc_t* ps_readproc(PROCTAB* PT, proc_t* return_buf);

void look_up_our_self(proc_t *p);

/* deallocate space allocated by readproc
 */
void freeproc(proc_t* p);

/* deallocate space allocated by readproctab
 */
void freeproctab(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, and tty device numbers.  The third
 * argument is the length of the list (currently only used for lists of user
 * id's since unsigned short[] supports no convenient termination sentinel.)
 */
#define PROC_FILLANY 0     /* either stat or status will do */
#define PROC_FILLMEM 0x1   /* read statm into the appropriate proc_t entries */
#define PROC_FILLCMD 0x2   /* alloc and fill in `cmdline' part of proc_t */
#define PROC_FILLENV 0x4   /* alloc and fill in `environ' part of proc_t */
#define PROC_FILLUSR 0x8  /* resolve user id number -> user name via passwd */
#define PROC_FILLSTATUS 0x10
#define PROC_FILLSTAT 0x20
#define PROC_FILLBUG 0x3f    /* No idea what we need */


/* Obsolete, consider only processes with one of the passed: */
#define PROC_PID     0x100  /* process id numbers ( 0   terminated) */
#define PROC_TTY     0x200  /* ctty device nos.   ( 0   terminated) */
#define PROC_UID     0x400  /* user id numbers    ( length needed ) */
#define PROC_STAT    0x800  /* status fields      ('\0' terminated) */
#define PROC_ANYTTY  0x1000 /* proc must have a controlling terminal */

/* utility functions which may be of general interest: */

/* slurp /proc/DIR/FILE into a single large string into the passed
   buffer.  return the number of bytes actually used.  used for stat,statm
 */
int file2str(char *dir, char *file, char *buf, int buf_size);

/* convert a file of null terminated strings into an argv-style string vector
 * which may be de-allocated with a single free() on a dereference of the return
 * value, e.g. free(*ret).  used for cmdline, environ.
 */
char** file2strvec(char* directory, char* what);

/* parse /proc/#/stat  entries in string s into a proc_t
 */
void stat2proc(char* S, proc_t*);

/* parse /proc/#/statm entries in string s into a proc_t
 */
void statm2proc(char* s, proc_t*);

/* parse /proc/#/status entries in string s into a proc_t
 */
void status2proc(char* s, proc_t*, int);

/* convert a memory buffer with nulls into a single string,
   replacing the nulls with sep.  No longer used.
 */
void nulls2sep(char* str, int len, char sep);


#endif
procps-2.0.7/proc/signals.c0100664000076400007640000000334306672166704016101 0ustar  johnsonmjohnsonm/* signals.c - signal name handling */
/***********************************************************************\
*   Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com *
*                                                                      *
*      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 <string.h>
#include <ctype.h>
#include "proc/signals.h"


typedef struct {
    int number;
    char *name;
} SIGNAME;


static SIGNAME signals[] = {
#include "signames.h" /* should be in same dir as this file */
  { 0,NULL }};


void list_signals(void)
{
    SIGNAME *walk;
    int col;

    col = 0;
    for (walk = signals; walk->name; walk++) {
	if (col+strlen(walk->name)+1 > 80) {
	    putchar('\n');
	    col = 0;
	}
	printf("%s%s",col ? " " : "",walk->name);
	col += strlen(walk->name)+1;
    }
    putchar('\n');
}


int get_signal(char *name,char *cmd)
{
    SIGNAME *walk;

    if (isdigit(*name))
	return atoi(name);
    for (walk = signals; walk->name; walk++)
	if (!strcmp(walk->name,name)) break;
    if (walk->name) return walk->number;
    fprintf(stderr,"%s: unknown signal; %s -l lists signals.\n",name,cmd);
    exit(1);
}

/* get_signal2 is by Michael Shields. 1994/04/25. */
int get_signal2(char *name)
{
    SIGNAME *walk;

    if (!name)
        return(-1);
    if (isdigit(*name))
	return atoi(name);
    for (walk = signals; walk->name; walk++)
        if (!strcmp(walk->name,name))
            return(walk->number);
    return(-1);
}
procps-2.0.7/proc/signals.h0100664000076400007640000000066706672166704016114 0ustar  johnsonmjohnsonm#ifndef __PROC_SIGNALS_H
#define __PROC_SIGNALS_H
/* signals.h - signal name handling */

extern void list_signals(void);

/* Lists all known signal names on standard output. */

extern int get_signal(char *name,char *cmd);
extern int get_signal2(char *name);

/* Returns the signal number of NAME. If no such signal exists, an error
   message is displayed and the program is terminated. CMD is the name of the
   application. */
#endif

procps-2.0.7/proc/status.c0100664000076400007640000000156306672166704015766 0ustar  johnsonmjohnsonm/***********************************************************************\
*   Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com *
*                                                                      *
*      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 "proc/procps.h"
#include "proc/readproc.h"

char * status(proc_t* task) {
    static char buf[4] = "   ";

    buf[0] = task->state;
    if (task->rss == 0 && task->state != 'Z')
        buf[1] = 'W';
    else
        buf[1] = ' ';
    if (task->nice < 0)
	buf[2] = '<';
    else if (task->nice > 0)
	buf[2] = 'N';
    else
	buf[2] = ' ';

    return(buf);
}
procps-2.0.7/proc/status.h0100664000076400007640000000013206672166704015762 0ustar  johnsonmjohnsonm#ifndef __PROC_STATUS_H
#define __PROC_STATUS_H
extern char *status(proc_t* task);
#endif
procps-2.0.7/proc/sysinfo.c0100664000076400007640000002522207132422655016123 0ustar  johnsonmjohnsonm/***********************************************************************\
*   Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com *
*                                                                      *
*      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. */
#include "proc/sysinfo.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include <unistd.h>
#include <fcntl.h>
#include "proc/version.h"

#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, 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;

static char buf[1024];

/* 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 n;						\
    if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) {	\
	fprintf(stderr, BAD_OPEN_MESSAGE);			\
	close(fd);						\
	_exit(1);						\
    }								\
    lseek(fd, 0L, SEEK_SET);					\
    if ((n = read(fd, buf, sizeof buf - 1)) < 0) {		\
	perror(filename);					\
	close(fd);						\
	fd = -1;						\
	return 0;						\
    }								\
    buf[n] = '\0';						\
}while(0)

#define SET_IF_DESIRED(x,y)  if(x) *(x) = (y)	/* evals 'x' twice */


/***********************************************************************/
int uptime(double *uptime_secs, double *idle_secs) {
    double up=0, idle=0;

    FILE_TO_BUF(UPTIME_FILE,uptime_fd);
    if (sscanf(buf, "%lf %lf", &up, &idle) < 2) {
	fprintf(stderr, "bad data in " UPTIME_FILE "\n");
	return 0;
    }
    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.
 *
 * (Albert Cahalan, I think, wrote the rant above.)
 *
 * Unfortunately, this code does not always succeed.  Anyone who can do
 * better is welcome to do so...
 */
unsigned long Hertz;
static int init_Hertz_value(void) __attribute__((constructor));
static int init_Hertz_value(void){
  unsigned long user_j, nice_j, sys_j, other_j;  /* jiffies (clock ticks) */
  double up_1, up_2, seconds;
  unsigned long jiffies, h;
  int i = 0;
  do{
    FILE_TO_BUF(UPTIME_FILE,uptime_fd);  sscanf(buf, "%lf", &up_1);
    /* uptime(&up_1, NULL); */
    FILE_TO_BUF(STAT_FILE,stat_fd);
    /* If we are SMP, then the first line is the sum of jiffies by all CPUs */
    /* In that case, skip it and use the jiffies of the first CPU instead. */
    /* On a single-CPU machine, the 2nd sscanf should harmlessly fail. */
    sscanf(buf, "cpu %lu %lu %lu %lu\n%n",
	   &user_j, &nice_j, &sys_j, &other_j, &i);
    sscanf(buf+i, "cpu0 %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)( (up_2-up_1)*1000.0/up_1 )); /* want under 0.1% error */
  jiffies = user_j + nice_j + sys_j + other_j;
  seconds = (up_1 + up_2) / 2;
  h = (unsigned long)( (double)jiffies/seconds );
  switch(h){
  case   48 ...   52 :  Hertz =   50; break;
  case   58 ...   62 :  Hertz =   60; break;
  case   95 ...  105 :  Hertz =  100; break; /* normal Linux */
  case  124 ...  132 :  Hertz =  128; break;
  case  195 ...  204 :  Hertz =  200; break; /* normal << 1 */
  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;
  case 1015 ... 1035 :  Hertz = 1024; break; /* Alpha */
  default:
#ifdef HZ
    Hertz = (unsigned long)HZ;    /* <asm/param.h> */
#else
    Hertz = (sizeof(long)==sizeof(int)) ? 100UL : 1024UL;
#endif
#if 0 /* This ends up causing more harm than good.  :-( */
    fprintf(stderr, "Unknown HZ value! (%ld) Assume %ld.\n", h, Hertz);
#endif
  }
  return 0; /* useless, but FILE_TO_BUF has a return in it */
}

/***********************************************************************/
#define JT unsigned long
int four_cpu_numbers(JT *uret, JT *nret, JT *sret, JT *iret) {
    static JT u, n, s, i;
    JT user_j, nice_j, sys_j, idle_j;

    FILE_TO_BUF(STAT_FILE,stat_fd);
    sscanf(buf, "cpu %lu %lu %lu %lu", &user_j, &nice_j, &sys_j, &idle_j);
    SET_IF_DESIRED(uret, user_j-u);
    SET_IF_DESIRED(nret, nice_j-n);
    SET_IF_DESIRED(sret,  sys_j-s);
    SET_IF_DESIRED(iret, idle_j-i);
    u=user_j;
    n=nice_j;
    s=sys_j;
    i=idle_j;
    return 0;
}
#undef JT

/***********************************************************************/
int loadavg(double *av1, double *av5, double *av15) {
    double avg_1=0, avg_5=0, avg_15=0;
    
    FILE_TO_BUF(LOADAVG_FILE,loadavg_fd);
    if (sscanf(buf, "%lf %lf %lf", &avg_1, &avg_5, &avg_15) < 3) {
	fprintf(stderr, "bad data in " LOADAVG_FILE "\n");
	exit(1);
    }
    SET_IF_DESIRED(av1,  avg_1);
    SET_IF_DESIRED(av5,  avg_5);
    SET_IF_DESIRED(av15, avg_15);
    return 1;
}

/************************************************************************
 * The following /proc/meminfo parsing routine assumes the following format:
 * [ <label> ... ]				# header lines
 * [ <label> ] <num> [ <num> ... ]		# table rows
 * [ repeats of above line ]
 * 
 * Any lines with fewer <num>s than <label>s get trailing <num>s set to zero.
 * The return value is a NULL terminated unsigned** which is the table of
 * numbers without labels.  Convenient enumeration constants for the major and
 * minor dimensions are available in the header file.  Note that this version
 * requires that labels do not contain digits.  It is readily extensible to
 * labels which do not *begin* with digits, though.
 */
#define MAX_ROW 3	/* these are a little liberal for flexibility */
#define MAX_COL 7
unsigned long long **meminfo(void){
    static unsigned long long *row[MAX_ROW + 1];		/* row pointers */
    static unsigned long long num[MAX_ROW * MAX_COL];	/* number storage */
    char *p;
    char fieldbuf[12];		/* bigger than any field name or size in kb */
    int i, j, k, l;
    
    FILE_TO_BUF(MEMINFO_FILE,meminfo_fd);
    if (!row[0])				/* init ptrs 1st time through */
	for (i=0; i < MAX_ROW; i++)		/* std column major order: */
	    row[i] = num + MAX_COL*i;		/* A[i][j] = A + COLS*i + j */
    p = buf;
    for (i=0; i < MAX_ROW; i++)			/* zero unassigned fields */
	for (j=0; j < MAX_COL; j++)
	    row[i][j] = 0;
    if (linux_version_code < LINUX_VERSION(2,0,0)) {
    	for (i=0; i < MAX_ROW && *p; i++) {                /* loop over rows */
		while(*p && !isdigit(*p)) p++;          /* skip chars until a digit */
		for (j=0; j < MAX_COL && *p; j++) {     /* scanf column-by-column */
		    l = sscanf(p, "%u%n", row[i] + j, &k);
		    p += k;                             /* step over used buffer */
		    if (*p == '\n' || l < 1)            /* end of line/buffer */
			break;
		}
	}
    }
    else {
	    while(*p) {
	    	sscanf(p,"%11s%n",fieldbuf,&k);
	    	if(!strcmp(fieldbuf,"MemTotal:")) {
	    		p+=k;
	    		sscanf(p," %Ld",&(row[meminfo_main][meminfo_total]));
	    		row[meminfo_main][meminfo_total]<<=10;
	    		while(*p++ != '\n');
	    	}
	    	else if(!strcmp(fieldbuf,"MemFree:")) {
	    		p+=k;
	    		sscanf(p," %Ld",&(row[meminfo_main][meminfo_free]));
	    		row[meminfo_main][meminfo_free]<<=10;
	    		while(*p++ != '\n');
	    	}
	    	else if(!strcmp(fieldbuf,"MemShared:")) {
	    		p+=k;
	    		sscanf(p," %Ld",&(row[meminfo_main][meminfo_shared]));
	    		row[meminfo_main][meminfo_shared]<<=10;
	    		while(*p++ != '\n');
	    	}
	    	else if(!strcmp(fieldbuf,"Buffers:")) {
	    		p+=k;
	    		sscanf(p," %Ld",&(row[meminfo_main][meminfo_buffers]));
	    		row[meminfo_main][meminfo_buffers]<<=10;
	    		while(*p++ != '\n');
	    	}
	    	else if(!strcmp(fieldbuf,"Cached:")) {
	    		p+=k;
    			sscanf(p," %Ld",&(row[meminfo_main][meminfo_cached]));
    			row[meminfo_main][meminfo_cached]<<=10;
    			while(*p++ != '\n');
    		}
    		else if(!strcmp(fieldbuf,"SwapTotal:")) {
    			p+=k;
    			sscanf(p," %Ld",&(row[meminfo_swap][meminfo_total]));
    			row[meminfo_swap][meminfo_total]<<=10;
    			while(*p++ != '\n');
    		}
    		else if(!strcmp(fieldbuf,"SwapFree:")) {
    			p+=k;
    			sscanf(p," %Ld",&(row[meminfo_swap][meminfo_free]));
    			row[meminfo_swap][meminfo_free]<<=10;
    			while(*p++ != '\n');
    		}
    		else
    			while(*p++ != '\n'); /* ignore lines we don't understand */
    	}		
    	row[meminfo_swap][meminfo_used]=row[meminfo_swap][meminfo_total]-row[meminfo_swap][meminfo_free];
    	row[meminfo_main][meminfo_used]=row[meminfo_main][meminfo_total]-row[meminfo_main][meminfo_free];
    }
    return row;					/* NULL return ==> error */
}

/**************************************************************************
 * shorthand for read_table("/proc/meminfo")[meminfo_main][meminfo_total] */
unsigned read_total_main(void) {
    unsigned long long** mem;
    return (mem = meminfo()) ? mem[meminfo_main][meminfo_total] : -1;
}
procps-2.0.7/proc/sysinfo.h0100664000076400007640000000116007007603372016121 0ustar  johnsonmjohnsonm#ifndef SYSINFO_H
#define SYSINFO_H

extern unsigned long Hertz;   /* clock tick frequency */

#define JT unsigned long
extern int four_cpu_numbers(JT *uret, JT *nret, JT *sret, JT *iret);
#undef JT

extern int        loadavg(double *av1, double *av5, double *av15);
extern int        uptime (double *uptime_secs, double *idle_secs);
extern unsigned long long ** meminfo(void);

enum meminfo_row { meminfo_main = 0,
		   meminfo_swap };

enum meminfo_col { meminfo_total = 0, meminfo_used, meminfo_free,
		   meminfo_shared, meminfo_buffers, meminfo_cached
};

extern unsigned read_total_main(void);

#endif /* SYSINFO_H */
procps-2.0.7/proc/tree.h0100664000076400007640000000033306403034250015357 0ustar  johnsonmjohnsonmstruct tree_node {
    proc_t *proc;
    pid_t pid;
    pid_t ppid;
    char *line;
    char *cmd;
    char **cmdline;
    char **environ;
    int children;
    int maxchildren;
    int *child;
    int have_parent;
};

procps-2.0.7/proc/version.c0100664000076400007640000000257406672166704016133 0ustar  johnsonmjohnsonm/* Suite version information for procps utilities
 * Copyright (c) 1995 Martin Schulze <joey@infodrom.north.de>
 * Ammended by cblake to only export the function symbol.
 * Redistributable under the terms of the
 * GNU Library General Public License; see COPYING
 */
#include <stdio.h>

#ifdef MINORVERSION
char procps_version[] = "procps version " VERSION "." SUBVERSION "." MINORVERSION;
#else
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 = 0;

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 (linux_version_code) return;
    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);
}
procps-2.0.7/proc/version.h0100664000076400007640000000160506672166704016132 0ustar  johnsonmjohnsonm#ifndef PROC_VERSION_H
#define PROC_VERSION_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
 */

extern void display_version(void);	/* display suite version */
extern 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)

#endif	/* PROC_VERSION_H */
procps-2.0.7/proc/whattime.c0100664000076400007640000000435306516711704016256 0ustar  johnsonmjohnsonm/* 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 "proc/whattime.h"
#include "proc/sysinfo.h"

static char buf[128];
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, " %2d:%02d%s  ",
		realtime->tm_hour%12 ? realtime->tm_hour%12 : 12,
		realtime->tm_min, realtime->tm_hour > 11 ? "pm" : "am");

/* 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());
}
procps-2.0.7/proc/whattime.h0100664000076400007640000000025206672166704016264 0ustar  johnsonmjohnsonm/* whattime.h --- see whattime.c for explanation */

#ifndef __WHATTIME_H
#define __WHATTIME_H

extern void print_uptime(void);
extern char *sprint_uptime(void);

#endif
procps-2.0.7/ps/0040775000076400007640000000000007133676464013756 5ustar  johnsonmjohnsonmprocps-2.0.7/ps/.cvsignore0100664000076400007640000000000307133675715015742 0ustar  johnsonmjohnsonmps
procps-2.0.7/ps/COPYING0100664000076400007640000006127306672265451015014 0ustar  johnsonmjohnsonm		  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!
procps-2.0.7/ps/HACKING0100664000076400007640000000451006672166704014740 0ustar  johnsonmjohnsonmWarning:

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.
procps-2.0.7/ps/Makefile0100775000076400007640000000174407132402377015411 0ustar  johnsonmjohnsonmall: ps

ps: escape.o global.o help.o select.o sortformat.o output.o parser.o display.o
	$(CC) -o ps   escape.o global.o help.o select.o sortformat.o output.o parser.o display.o -L../proc -lproc

# This just adds the stacktrace code
debug: escape.o global.o help.o select.o sortformat.o output.o parser.o display.o stacktrace.o
	$(CC) -o ps   escape.o global.o help.o select.o sortformat.o output.o parser.o display.o stacktrace.o -L../proc -lproc -lefence

sortformat.o: sortformat.c common.h

global.o: global.c common.h

escape.o: escape.c

help.o: help.c

select.o: select.c common.h

output.o: output.c common.h

parser.o: parser.c common.h

display.o: display.c common.h

stacktrace.o: stacktrace.c


install: ps
	install $(OWNERGROUP) --mode a=rx --strip ps $(BINDIR)/ps
	install $(OWNERGROUP) --mode a=r ps.1 $(MAN1DIR)/ps.1
	# The following does no harm and on older systems might help
	rm -f /var/catman/cat1/ps.1.gz /var/man/cat1/ps.1.gz

clean:
	rm -f *.o DEADJOE *~ core ps gmon.out
procps-2.0.7/ps/common.h0100664000076400007640000002374107132365133015406 0ustar  johnsonmjohnsonm/*
 * Copyright 1998 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/readproc.h"
#include <asm/page.h>  /* looks safe for glibc, we need PAGE_SIZE */

#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

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

/*
 * Must not overflow the output buffer:
 *    32 pages for env+cmd
 *    8 kB pages on the Alpha
 *    5 chars for "\001 "
 *    plus some slack for other stuff
 * That is about 1.3 MB on the Alpha
 *
 * This isn't good enough for setuid. If anyone cares, mmap() over the
 * last page with something unwriteable.
 */

/* maximum escape expansion is 6, for &quot; */
#define ESC_STRETCH 6
/* output buffer size */
#define OUTBUF_SIZE (32*PAGE_SIZE*ESC_STRETCH + 8*PAGE_SIZE)
/* spaces used to right-justify things */
#define SPACE_AMOUNT (int)(PAGE_SIZE)

/******************* PS DEFINE *******************/

/* personality control flags */
#define PER_BROKEN_o      0x0001
#define PER_BSD_h         0x0002
#define PER_BSD_m         0x0004
#define PER_CUMUL_MARKED  0x0008
#define PER_FORCE_BSD     0x0010
#define PER_GOOD_o        0x0020
#define PER_OLD_m         0x0040
#define PER_SUN_MUTATE_a  0x0080
#define PER_ZAP_ADDR      0x0100
#define PER_SANE_USER     0x0200
#define PER_IRIX_l        0x0400

/* Simple selections by bit mask
 * Warning: these bit positions are hard-coded into the table in
 * table_accept(), so do not change them.
 */
#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 */

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

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

/* Justification control for flags field. */
#define JUST_MASK 0x0f
     /* AIXHACK   0 */
#define USER      1  /* left if text, right if numeric */
#define LEFT      2
#define RIGHT     3
#define UNLIMITED 4
#define WCHAN     5  /* left if text, right if numeric */
#define SIGNAL    6  /* right in 9, or 16 if screen_cols>107 */

#define CUMUL     16  /* mark cumulative (Summed) headers with 'C' */


/********************** 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;
  uid_t uid;
  gid_t gid;
  dev_t tty;
  char  cmd[8];  /* 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;
} sort_node;

typedef struct format_node {
  struct format_node *next;
  char *name;                             /* user can override default name */
  int (*pr)(void);                         /* print function */
/*  int (* const sr)(const proc_t* P, const proc_t* Q); */ /* sort function */
  int width;
  int pad;
  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)(void); /* print function */
  int (* const sr)(const proc_t* P, const proc_t* Q); /* sort function */
  const int width;
  const int pad;    /* could be second width */
  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;


/*********************** GENERAL GLOBALS *************************/

/* escape.c */
extern int escape_strlist(char *dst, const char **src, size_t n);
extern int escape_str(char *dst, const char *src, size_t n);
extern int octal_escape_str(char *dst, const char *src, size_t n);
extern int simple_escape_str(char *dst, const char *src, size_t n);
extern int html_escape_str(char *dst, const char *src, size_t n);

/********************* UNDECIDED GLOBALS **************/

/* compare.c */
extern void reset_sort_options(void);
extern int mult_lvl_cmp(void* a, void* b);
extern int node_mult_lvl_cmp(void* a, void* b);
extern void dump_keys(void);
extern const char *parse_sort_opt(const char* opt);
extern const char *parse_long_sort(const char* opt);

/* output.c */
extern void show_one_proc(proc_t* p);
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);

/* global.c */
extern void reset_global(void);

/* global.c */
extern int             all_processes;
extern char           *bsd_j_format;
extern char           *bsd_l_format;
extern char           *bsd_s_format;
extern char           *bsd_u_format;
extern char           *bsd_v_format;
extern int             bsd_c_option;
extern int             bsd_e_option;
extern 
Results 1 - 1
Help - FTP Sites List - Software Dir.
Searching half a billion files worldwide
© 1997-2009 MARUHN Internet Solutions