aboutsummaryrefslogtreecommitdiff
path: root/libps/ps.h
diff options
context:
space:
mode:
Diffstat (limited to 'libps/ps.h')
-rw-r--r--libps/ps.h1047
1 files changed, 1047 insertions, 0 deletions
diff --git a/libps/ps.h b/libps/ps.h
new file mode 100644
index 00000000..417ad374
--- /dev/null
+++ b/libps/ps.h
@@ -0,0 +1,1047 @@
+/* Routines to gather and print process information.
+
+ Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef __PS_H__
+#define __PS_H__
+
+#include <hurd/hurd_types.h>
+#include <hurd/ihash.h>
+#include <mach/mach.h>
+
+#include <pwd.h>
+#include <errno.h>
+
+/* A PS_USER holds info about a particular user. */
+
+/* Possible states a ps_user's passwd can be in: valid, not fet */
+enum ps_user_passwd_state
+ { PS_USER_PASSWD_OK, PS_USER_PASSWD_PENDING, PS_USER_PASSWD_ERROR };
+
+struct ps_user
+{
+ /* Which user this refers to. */
+ uid_t uid;
+
+ /* The status */
+ enum ps_user_passwd_state passwd_state;
+
+ /* The user's password file entry. Only valid if PASSWD_STATE ==
+ PS_USER_PASSWD_OK. */
+ struct passwd passwd;
+
+ /* String storage for strings pointed to by ENTRY. */
+ char *storage;
+};
+
+#define ps_user_uid(u) ((u)->uid)
+
+/* Create a ps_user for the user referred to by UID, returning it in U.
+ If a memory allocation error occurs, ENOMEM is returned, otherwise 0. */
+error_t ps_user_create (uid_t uid, struct ps_user **u);
+
+/* Create a ps_user for the user referred to by UNAME, returning it in U.
+ If a memory allocation error occurs, ENOMEM is returned. If no such user
+ is known, EINVAL is returned. */
+error_t ps_user_uname_create (char *uname, struct ps_user **u);
+
+/* Makes makes a ps_user containing PW (which is copied). */
+error_t ps_user_passwd_create (struct passwd *pw, struct ps_user **u);
+
+/* Free U and any resources it consumes. */
+void ps_user_free (struct ps_user *u);
+
+/* Returns the password file entry (struct passwd, from <pwd.h>) for the user
+ referred to by U, or NULL if it can't be gotten. */
+struct passwd *ps_user_passwd (struct ps_user *u);
+
+/* Returns the user name for the user referred to by U, or NULL if it can't
+ be gotten. */
+char *ps_user_name (struct ps_user *u);
+
+/* A ps_tty holds information about a terminal. */
+
+/* Possible states a ps_tty's name can be in: valid, not fetched yet,
+ couldn't fetch. */
+enum ps_tty_name_state
+ { PS_TTY_NAME_OK, PS_TTY_NAME_PENDING, PS_TTY_NAME_ERROR };
+
+struct ps_tty {
+ /* Which tty this refers to. */
+ file_t port;
+
+ /* The name of the tty, if we could figure it out. */
+ const char *name;
+ /* What state the name is in. */
+ enum ps_tty_name_state name_state;
+
+ /* A more abbreviated name for the tty, or NULL if no name at all. */
+ const char *short_name;
+ int short_name_alloced : 1;
+};
+
+#define ps_tty_port(tty) ((tty)->port)
+
+/* Create a ps_tty for the tty referred to by PORT, returning it in TTY.
+ If a memory allocation error occurs, ENOMEM is returned, otherwise 0. */
+error_t ps_tty_create (file_t port, struct ps_tty **tty);
+
+/* Frees TTY and any resources it consumes. */
+void ps_tty_free (struct ps_tty *tty);
+
+/* Returns the name of the tty, or NULL if it can't be figured out. */
+const char *ps_tty_name (struct ps_tty *tty);
+
+/* Returns the standard abbreviated name of the tty, the whole name if there
+ is no standard abbreviation, or NULL if it can't be figured out. */
+const char *ps_tty_short_name (struct ps_tty *tty);
+
+/* A PS_CONTEXT holds various information resulting from querying a
+ particular process server, in particular a group of proc_stats, ps_users,
+ and ps_ttys. This information sticks around until the context is freed
+ (subsets may be created by making proc_stat_lists). */
+
+struct proc_stat; /* Fwd declared */
+
+struct ps_context
+{
+ /* The process server our process info is from. */
+ process_t server;
+
+ /* proc_stats for every process we know about, indexed by process id. */
+ ihash_t procs;
+
+ /* ps_ttys for every tty we know about, indexed by the terminal port. */
+ ihash_t ttys;
+
+ /* ps_ttys for every tty we know about, indexed by their ctty id port
+ (from libc). */
+ ihash_t ttys_by_cttyid;
+
+ /* A ps_user for every user we know about, indexed by user-id. */
+ ihash_t users;
+
+ /* Functions that can be set to extend the behavior of proc_stats. */
+ struct ps_user_hooks *user_hooks;
+};
+
+#define ps_context_server(pc) ((pc)->server)
+
+/* Returns in PC a new ps_context for the proc server SERVER. If a memory
+ allocation error occurs, ENOMEM is returned, otherwise 0. */
+error_t ps_context_create (process_t server, struct ps_context **pc);
+
+/* Frees PC and any resources it consumes. */
+void ps_context_free (struct ps_context *pc);
+
+/* Find a proc_stat for the process referred to by PID, and return it in
+ PS. If an error occurs, it is returned, otherwise 0. */
+error_t ps_context_find_proc_stat (struct ps_context *pc, pid_t pid,
+ struct proc_stat **ps);
+
+/* Find a ps_tty for the terminal referred to by the port TTY_PORT, and
+ return it in TTY. If an error occurs, it is returned, otherwise 0. */
+error_t ps_context_find_tty (struct ps_context *pc, mach_port_t tty_port,
+ struct ps_tty **tty);
+
+/* Find a ps_tty for the terminal referred to by the ctty id port
+ CTTYID_PORT, and return it in TTY. If an error occurs, it is returned,
+ otherwise 0. */
+error_t ps_context_find_tty_by_cttyid (struct ps_context *pc,
+ mach_port_t cttyid_port,
+ struct ps_tty **tty);
+
+/* Find a ps_user for the user referred to by UID, and return it in U. */
+error_t ps_context_find_user (struct ps_context *pc, uid_t uid,
+ struct ps_user **u);
+
+/* A PROC_STAT holds lots of info about the process PID at SERVER; exactly
+ which info is dependent on its FLAGS field. */
+
+typedef unsigned ps_flags_t;
+typedef unsigned ps_state_t;
+
+struct proc_stat
+{
+ /* Which process server this is from. */
+ struct ps_context *context;
+
+ /* The proc's process id; if <0 then this is a thread, not a process. */
+ pid_t pid;
+
+ /* Flags describing which fields in this structure are valid. */
+ ps_flags_t flags;
+ ps_flags_t failed; /* flags that we tried to set and couldn't. */
+ ps_flags_t inapp; /* flags that don't apply to this procstat;
+ subset of FAILED. */
+
+ /* Thread fields -- these are valid if PID < 0. */
+ struct proc_stat *thread_origin; /* A proc_stat for the task we're in. */
+ unsigned thread_index; /* Which thread in our proc we are. */
+
+ /* A process_t port for the process. */
+ process_t process;
+
+ /* The mach task port for the process. */
+ task_t task;
+
+ /* A libc msgport for the process. This port is responded to by the
+ process itself (usually by the c library); see <hurd/msg.defs> for the
+ standard set of rpcs you can send to this port. Accordingly, you
+ cannot depend on a timely (or any) reply to messages sent here --
+ program carefully! */
+ mach_port_t msgport;
+
+ /* A pointer to the process's procinfo structure (as returned by
+ proc_getinfo; see <hurd/hurd_types.h>). Vm_alloced. */
+ struct procinfo *proc_info;
+ /* The size of the info structure for deallocation purposes. */
+ unsigned proc_info_size;
+
+ /* If present, these are just pointers into the proc_info structure. */
+ unsigned num_threads;
+ task_basic_info_t task_basic_info;
+
+ /* For a thread, the obvious structures; for a process, summaries of the
+ proc's thread_{basic,sched}_info_t structures: sizes and cumulative
+ times are summed, prioritys and delta time are averaged. The
+ run_states are added by having running thread take precedence over
+ waiting ones, and if there are any other incompatible states, simply
+ using a bogus value of -1. Malloced. */
+ thread_basic_info_t thread_basic_info;
+ thread_sched_info_t thread_sched_info;
+
+ /* For a blocked thread, these next fields describe how it's blocked. */
+
+ /* A string (pointing into the thread_waits field of the parent
+ procstat), describing what's being blocked on. If "KERNEL", a system
+ call (not mach_msg), and thread_rpc is the system call number.
+ Otherwise if thread_rpc isn't zero, this string describes the port the
+ rpc is on; if thread_rpc is 0, this string describes a non-rpc event. */
+ char *thread_wait;
+ /* The rpc that it's blocked on. For a process the rpc blocking the
+ first blocked thread (if any). 0 means no block. */
+ mach_msg_id_t thread_rpc;
+
+ /* Storage for child-thread waits. */
+ char *thread_waits;
+ size_t thread_waits_len;
+
+ /* The task or thread suspend count (whatever this proc_stat refers to). */
+ int suspend_count;
+
+ /* A bitmask summarizing the scheduling state of this process and all its
+ threads. See the PSTAT_STATE_ defines below for a list of bits. */
+ ps_state_t state;
+
+ /* A ps_user object for the owner of this process, or NULL if none. */
+ struct ps_user *owner;
+ int owner_uid; /* The corresponding UID, or -1. */
+
+ /* The process's argv, as a string with each element separated by '\0'. */
+ char *args;
+ /* The length of ARGS. */
+ unsigned args_len;
+
+ /* Virtual memory statistics for the process, as returned by task_info;
+ see <mach/task_info.h> for a description of task_events_info_t. */
+ task_events_info_t task_events_info;
+ task_events_info_data_t task_events_info_buf;
+ unsigned task_events_info_size;
+
+ /* Flags showing whether a field is vm_alloced or malloced. */
+ unsigned proc_info_vm_alloced : 1;
+ unsigned thread_waits_vm_alloced : 1;
+ unsigned args_vm_alloced : 1;
+ unsigned env_vm_alloced : 1;
+
+ /* Various libc ports: */
+
+ /* The process's ctty id port, or MACH_PORT_NULL if the process has no
+ controlling terminal. Note that this is just a magic cookie; we use
+ it to fetch a port to the actual terminal -- it's not useful for much
+ else. */
+ mach_port_t cttyid;
+
+ /* A port to the process's current working directory. */
+ mach_port_t cwdir;
+
+ /* The process's auth port, which we can use to determine who the process
+ is authenticated as. */
+ mach_port_t auth;
+
+ /* The process's umask, which controls which protection bits won't be set
+ when creating a file. */
+ unsigned umask;
+
+ /* A ps_tty object for the process's controlling terminal. */
+ struct ps_tty *tty;
+
+ /* A hook for the user to use. */
+ void *hook;
+
+ /* XXX these members added at the end for binary compatibility */
+ /* The process's envp, as a string with each element separated by '\0'. */
+ char *env;
+ /* The length of ENV. */
+ unsigned env_len;
+};
+
+/* Proc_stat flag bits; each bit is set in the FLAGS field if that
+ information is currently valid. */
+#define PSTAT_PID 0x00001 /* Process ID */
+#define PSTAT_THREAD 0x00002 /* thread_index & thread_origin */
+#define PSTAT_PROCESS 0x00004 /* The process_t for the process */
+#define PSTAT_TASK 0x00008 /* The task port for the process */
+#define PSTAT_MSGPORT 0x00010 /* The process's msgport */
+#define PSTAT_PROC_INFO 0x00020 /* Basic process info. */
+#define PSTAT_TASK_BASIC 0x00040 /* The task's struct task_basic_info. */
+#define PSTAT_TASK_EVENTS 0x00080 /* A task_events_info_t for the proc. */
+#define PSTAT_NUM_THREADS 0x00100 /* The number of threads in the task. */
+/* Note that for a process-procstat, the thread information fields generally
+ are a summary of the process's threads, and imply that the corresponding
+ information has been fetched for all its threads. The exception is
+ thread-wait information (PSTAT_THREAD_WAIT), which is expensive to fetch
+ for processes with lots of threads, and not terrible useful. In this
+ case, the thread waits vector containing per-thread information is only
+ guaranteed to be valid if PSTAT_THREAD_WAITS is true as well. */
+#define PSTAT_THREAD_BASIC 0x00200 /* A struct thread_basic_info. */
+#define PSTAT_THREAD_SCHED 0x00400 /* A struct thread_sched_info. */
+#define PSTAT_THREAD_WAIT 0x00800 /* The rpc the thread is waiting on. */
+#define PSTAT_THREAD_WAITS 0x01000 /* Thread waits for this PS's threads */
+#define PSTAT_ARGS 0x02000 /* The process's args */
+#define PSTAT_ENV 0x2000000 /* The process's environment */
+#define PSTAT_STATE 0x04000 /* A bitmask describing the process's
+ state (see below) */
+#define PSTAT_SUSPEND_COUNT 0x08000 /* Task/thread suspend count */
+#define PSTAT_CTTYID 0x10000 /* The process's CTTYID port */
+#define PSTAT_CWDIR 0x20000 /* A file_t for the proc's CWD */
+#define PSTAT_AUTH 0x40000 /* The proc's auth port */
+#define PSTAT_TTY 0x80000 /* A ps_tty for the proc's terminal.*/
+#define PSTAT_OWNER 0x100000 /* A ps_user for the proc's owner */
+#define PSTAT_OWNER_UID 0x200000 /* The uid of the the proc's owner */
+#define PSTAT_UMASK 0x400000 /* The proc's current umask */
+#define PSTAT_HOOK 0x800000 /* Has a non-zero hook */
+
+/* Flag bits that don't correspond precisely to any field. */
+#define PSTAT_NO_MSGPORT 0x1000000 /* Don't use the msgport at all */
+
+/* Bits from PSTAT_USER_BASE on up are available for user-use. */
+#define PSTAT_USER_BASE 0x10000000
+#define PSTAT_USER_MASK ~(PSTAT_USER_BASE - 1)
+
+/* If the PSTAT_STATE flag is set, then the proc_stats state field holds a
+ bitmask of the following bits, describing the process's run state. If you
+ change the value of these, you must change proc_stat_state_tags as well! */
+
+/* Process global state. */
+
+/* Mutually exclusive bits, each of which is a possible process `state'. */
+#define PSTAT_STATE_P_STOP 0x00001 /* T stopped (e.g., by ^Z) */
+#define PSTAT_STATE_P_ZOMBIE 0x00002 /* Z process exited but not reaped */
+
+#define PSTAT_STATE_P_STATES (PSTAT_STATE_P_STOP | PSTAT_STATE_P_ZOMBIE)
+
+/* Independent bits describing additional attributes of the process. */
+#define PSTAT_STATE_P_FG 0x00400 /* + in foreground process group */
+#define PSTAT_STATE_P_SESSLDR 0x00800 /* s session leader */
+#define PSTAT_STATE_P_LOGINLDR 0x01000 /* l login collection leader */
+#define PSTAT_STATE_P_FORKED 0x02000 /* f has forked and not execed */
+#define PSTAT_STATE_P_NOMSG 0x04000 /* m no msg port */
+#define PSTAT_STATE_P_NOPARENT 0x08000 /* p no parent */
+#define PSTAT_STATE_P_ORPHAN 0x10000 /* o orphaned */
+#define PSTAT_STATE_P_TRACE 0x20000 /* x traced */
+#define PSTAT_STATE_P_WAIT 0x40000 /* w process waiting for a child */
+#define PSTAT_STATE_P_GETMSG 0x80000 /* g waiting for a msgport */
+
+#define PSTAT_STATE_P_ATTRS (PSTAT_STATE_P_FG | PSTAT_STATE_P_SESSLDR \
+ | PSTAT_STATE_P_LOGINLDR | PSTAT_STATE_P_FORKED \
+ | PSTAT_STATE_P_NOMSG | PSTAT_STATE_P_NOPARENT \
+ | PSTAT_STATE_P_ORPHAN | PSTAT_STATE_P_TRACE \
+ | PSTAT_STATE_P_WAIT | PSTAT_STATE_P_GETMSG)
+
+/* Per-thread state; in a process, these represent the union of its threads. */
+
+/* Mutually exclusive bits, each of which is a possible thread `state'. */
+#define PSTAT_STATE_T_RUN 0x00004 /* R thread is running */
+#define PSTAT_STATE_T_HALT 0x00008 /* H thread is halted */
+#define PSTAT_STATE_T_WAIT 0x00010 /* D uninterruptable wait */
+#define PSTAT_STATE_T_SLEEP 0x00020 /* S sleeping */
+#define PSTAT_STATE_T_IDLE 0x00040 /* I idle (sleeping > 20 seconds) */
+
+#define PSTAT_STATE_T_STATES (PSTAT_STATE_T_RUN | PSTAT_STATE_T_HALT \
+ | PSTAT_STATE_T_WAIT | PSTAT_STATE_T_SLEEP \
+ | PSTAT_STATE_T_IDLE)
+
+/* Independent bits describing additional attributes of the thread. */
+#define PSTAT_STATE_T_NICE 0x00080 /* N lowered priority */
+#define PSTAT_STATE_T_NASTY 0x00100 /* < raised priority */
+#define PSTAT_STATE_T_UNCLEAN 0x00200 /* u thread is uncleanly halted */
+
+#define PSTAT_STATE_T_ATTRS (PSTAT_STATE_T_UNCLEAN \
+ | PSTAT_STATE_T_NICE | PSTAT_STATE_T_NASTY)
+
+/* This is a constant string holding a single character for each possible bit
+ in a proc_stats STATE field, in order from bit zero. These are intended
+ for printing a user-readable summary of a process's state. */
+char *proc_stat_state_tags;
+
+/* Process info accessor functions.
+
+ You must be sure that the associated flag bit is set before accessing a
+ field in a proc_stat! A field FOO (with accessor macro proc_foo ()), has
+ a flag named PSTAT_FOO. If the flag is'nt set, you may attempt to set it
+ with proc_stat_set_flags (but note that this may not succeed). */
+
+/* FLAGS doesn't have a flag bit; it's always valid */
+#define proc_stat_flags(ps) ((ps)->flags)
+
+/* These both use the flag PSTAT_THREAD. */
+#define proc_stat_thread_origin(ps) ((ps)->thread_origin)
+#define proc_stat_thread_index(ps) ((ps)->thread_index)
+
+#define proc_stat_pid(ps) ((ps)->pid)
+#define proc_stat_process(ps) ((ps)->process)
+#define proc_stat_task(ps) ((ps)->task)
+#define proc_stat_msgport(ps) ((ps)->msgport)
+#define proc_stat_proc_info(ps) ((ps)->proc_info)
+#define proc_stat_num_threads(ps) ((ps)->num_threads)
+#define proc_stat_task_basic_info(ps) ((ps)->task_basic_info)
+#define proc_stat_thread_basic_info(ps) ((ps)->thread_basic_info)
+#define proc_stat_thread_sched_info(ps) ((ps)->thread_sched_info)
+#define proc_stat_thread_rpc(ps) ((ps)->thread_rpc)
+#define proc_stat_thread_wait(ps) ((ps)->thread_rpc)
+#define proc_stat_suspend_count(ps) ((ps)->suspend_count)
+#define proc_stat_args(ps) ((ps)->args)
+#define proc_stat_args_len(ps) ((ps)->args_len)
+#define proc_stat_env(ps) ((ps)->env)
+#define proc_stat_env_len(ps) ((ps)->env_len)
+#define proc_stat_state(ps) ((ps)->state)
+#define proc_stat_cttyid(ps) ((ps)->cttyid)
+#define proc_stat_cwdir(ps) ((ps)->cwdir)
+#define proc_stat_owner(ps) ((ps)->owner)
+#define proc_stat_owner_uid(ps) ((ps)->owner_uid)
+#define proc_stat_auth(ps) ((ps)->auth)
+#define proc_stat_umask(ps) ((ps)->umask)
+#define proc_stat_tty(ps) ((ps)->tty)
+#define proc_stat_task_events_info(ps) ((ps)->task_events_info)
+#define proc_stat_has(ps, needs) (((ps)->flags & needs) == needs)
+
+/* True if PS refers to a thread and not a process. */
+#define proc_stat_is_thread(ps) ((ps)->pid < 0)
+
+/* Returns in PS a new proc_stat for the process PID in the ps context PC.
+ If a memory allocation error occurs, ENOMEM is returned, otherwise 0.
+ Users shouldn't use this routine, use pc_context_find_proc_stat instead. */
+error_t _proc_stat_create (pid_t pid, struct ps_context *context,
+ struct proc_stat **ps);
+
+/* Frees PS and any memory/ports it references. Users shouldn't use this
+ routine; proc_stats are normally freed only when their ps_context goes
+ away. */
+void _proc_stat_free (struct proc_stat *ps);
+
+/* Adds FLAGS to PS's flags, fetching information as necessary to validate
+ the corresponding fields in PS. Afterwards you must still check the flags
+ field before using new fields, as something might have failed. Returns
+ a system error code if a fatal error occurred, and 0 otherwise. */
+error_t proc_stat_set_flags (struct proc_stat *ps, ps_flags_t flags);
+
+/* Returns in THREAD_PS a proc_stat for the Nth thread in the proc_stat
+ PS (N should be between 0 and the number of threads in the process). The
+ resulting proc_stat isn't fully functional -- most flags can't be set in
+ it. If N was out of range, EINVAL is returned. If a memory allocation
+ error occured, ENOMEM is returned. Otherwise, 0 is returned. */
+error_t proc_stat_thread_create (struct proc_stat *ps, unsigned n,
+ struct proc_stat **thread_ps);
+
+/* A struct ps_user_hooks holds functions that allow the user to extend the
+ behavior of libps. */
+
+struct ps_user_hooks
+{
+ /* Given a set of flags in the range defined by PSTAT_USER_MASK, should
+ return any other flags (user or system) which should be set as a
+ precondition to setting them. */
+ ps_flags_t (*dependencies) (ps_flags_t flags);
+
+ /* Try and fetch the information corresponding to NEED (which is in the
+ range defined by PSTAT_USER_MASK), and fill in the necessary fields in
+ PS (probably in a user defined structure pointed to by the hook field).
+ The user flags corresponding to what is successfully fetched should be
+ returned. HAVE are the flags defining whas is currently valid in PS. */
+ ps_flags_t (*fetch) (struct proc_stat *ps, ps_flags_t need, ps_flags_t have);
+
+ /* When a proc_stat goes away, this function is called on it. */
+ void (*cleanup) (struct proc_stat *ps);
+};
+
+/* A PS_GETTER describes how to get a particular value from a PROC_STAT.
+
+ To get a value from a proc_stat PS with a getter, you must make sure all
+ the pstat_flags returned by ps_getter_needs (GETTER) are set in PS, and
+ then call the function returned ps_getter_function (GETTER) with PS as the
+ first argument.
+
+ The way the actual value is returned from this funciton is dependent on
+ the type of the value:
+ For ints and floats, the value is the return value.
+ For strings, you must pass in two extra arguments, a char **, which is
+ filled in with a pointer to the string, or NULL if the string is NULL,
+ and an int *, which is filled in with the length of the string. */
+
+struct ps_getter
+ {
+ /* The getter's name */
+ char *name;
+
+ /* What proc_stat flags need to be set as a precondition to calling this
+ getter's function. */
+ ps_flags_t needs;
+
+ /* A function that will get the value; the protocol between this function
+ and its caller is type-dependent. */
+ void (*fn) ();
+ };
+
+/* Access macros: */
+#define ps_getter_name(g) ((g)->name)
+#define ps_getter_needs(g) ((g)->needs)
+#define ps_getter_function(g) ((g)->fn)
+
+/* A PS_FILTER_T describes how to select some subset of a PROC_STAT_LIST_T */
+
+struct ps_filter
+ {
+ /* Name of this filter. */
+ char *name;
+
+ /* The flags that need to be set in each proc_stat in the list to
+ call the filter's predicate function; if these flags can't be set in a
+ particular proc_stat, the function is not called, and it isn't deleted
+ from the list. */
+ ps_flags_t needs;
+
+ /* A function that returns true if called on a proc_stat that the
+ filter accepts, or false if the filter rejects it. */
+ int (*fn) (struct proc_stat *ps);
+ };
+
+/* Access macros: */
+#define ps_filter_name(f) ((f)->name)
+#define ps_filter_needs(f) ((f)->needs)
+#define ps_filter_predicate(f) ((f)->fn)
+
+/* Some predefined filters. These are structures; you must use the &
+ operator to get a ps_filter from them */
+
+/* A filter that retains only processes owned by getuid () */
+extern const struct ps_filter ps_own_filter;
+/* A filter that retains only processes that aren't session or login leaders */
+extern const struct ps_filter ps_not_leader_filter;
+/* A filter that retains only processes with a controlling terminal */
+extern const struct ps_filter ps_ctty_filter;
+/* A filter that retains only `unorphaned' process. A process is unorphaned
+ if it's a session leader, or the process's process group is not orphaned */
+extern const struct ps_filter ps_unorphaned_filter;
+/* A filter that retains only `parented' process. Typically only hurd
+ processes have parents. */
+extern const struct ps_filter ps_parent_filter;
+/* A filter that retains only processes/threads that aren't totally dead. */
+extern const struct ps_filter ps_alive_filter;
+
+/* A ps_stream describes an output stream for libps to use. */
+
+struct ps_stream
+{
+ FILE *stream; /* The actual destination. */
+ int pos; /* The number of characters output. */
+ int spaces; /* The number of spaces pending. */
+};
+
+/* Create a stream outputing to DEST, and return it in STREAM, or an error. */
+error_t ps_stream_create (FILE *dest, struct ps_stream **stream);
+
+/* Frees STREAM. The destination file is *not* closed. */
+void ps_stream_free (struct ps_stream *stream);
+
+/* Write at most MAX_LEN characters of STRING to STREAM (if MAX_LEN > the
+ length of STRING, then write all of it; if MAX_LEN == -1, then write all
+ of STRING regardless). */
+error_t ps_stream_write (struct ps_stream *stream,
+ const char *string, int max_len);
+
+/* Write NUM spaces to STREAM. NUM may be negative, in which case the same
+ number of adjacent spaces (written by other calls to ps_stream_space) are
+ consumed if possible. If an error occurs, the error code is returned,
+ otherwise 0. */
+error_t ps_stream_space (struct ps_stream *stream, int num);
+
+/* Write as many spaces to STREAM as required to make a field of width SOFAR
+ be at least WIDTH characters wide (the absolute value of WIDTH is used).
+ If an error occurs, the error code is returned, otherwise 0. */
+error_t ps_stream_pad (struct ps_stream *stream, int sofar, int width);
+
+/* Write a newline to STREAM, resetting its position to zero. */
+error_t ps_stream_newline (struct ps_stream *stream);
+
+/* Write the string BUF to STREAM, padded on one side with spaces to be at
+ least the absolute value of WIDTH long: if WIDTH >= 0, then on the left
+ side, otherwise on the right side. If an error occurs, the error code is
+ returned, otherwise 0. */
+error_t ps_stream_write_field (struct ps_stream *stream,
+ const char *buf, int width);
+
+/* Like ps_stream_write_field, but truncates BUF to make it fit into WIDTH. */
+error_t ps_stream_write_trunc_field (struct ps_stream *stream,
+ const char *buf, int width);
+
+/* Write the decimal representation of VALUE to STREAM, padded on one side
+ with spaces to be at least the absolute value of WIDTH long: if WIDTH >=
+ 0, then on the left side, otherwise on the right side. If an error
+ occurs, the error code is returned, otherwise 0. */
+error_t ps_stream_write_int_field (struct ps_stream *stream,
+ int value, int width);
+
+/* A PS_FMT_SPEC describes how to output something from a PROC_STAT; it
+ is a combination of a getter (describing how to get the value), an output
+ function (which outputs the result of the getter), and a compare function
+ (which can be used to sort proc_stats according to how they are
+ output). It also specifies the default width of the field in which the
+ output should be printed. */
+
+struct ps_fmt_field; /* fwd decl */
+
+struct ps_fmt_spec
+ {
+ /* The name of the spec (and it's title, if TITLE is NULL). */
+ const char *name;
+
+ /* The title to be printed in the headers. */
+ const char *title;
+
+ /* The width of the field that this spec will be printed in if not
+ overridden. */
+ int width;
+
+ /* A default value for the fields `precision'. */
+ int precision;
+
+ /* Default values for PS_FMT_FIELD_ flags. */
+ int flags;
+
+ const struct ps_getter *getter;
+
+ /* A function that outputs what FIELD specifies in PS to STREAM. */
+ error_t (*output_fn)(struct proc_stat *ps, struct ps_fmt_field *field,
+ struct ps_stream *stream);
+
+ /* A function that, given two pses and a getter, will compare what
+ the getter gets for each ps, and return an integer ala qsort. This
+ may be NULL, in which case values in this field cannot be compared. */
+ int (*cmp_fn)(struct proc_stat *ps1, struct proc_stat *ps2,
+ const struct ps_getter *getter);
+
+ /* A function that, given a ps and a getter, will return true if what the
+ getter gets from the ps is `nominal' -- a default unexciting value.
+ This may be NULL, in which case values in this field are _always_
+ exciting... */
+ int (*nominal_fn)(struct proc_stat *ps, const struct ps_getter *getter);
+ };
+
+/* Accessor macros: */
+#define ps_fmt_spec_name(spec) ((spec)->name)
+#define ps_fmt_spec_title(spec) ((spec)->title)
+#define ps_fmt_spec_width(spec) ((spec)->width)
+#define ps_fmt_spec_output_fn(spec) ((spec)->output_fn)
+#define ps_fmt_spec_compare_fn(spec) ((spec)->cmp_fn)
+#define ps_fmt_spec_nominal_fn(spec) ((spec)->nominal_fn)
+#define ps_fmt_spec_getter(spec) ((spec)->getter)
+
+/* Returns true if a pointer into an array of struct ps_fmt_specs is at the
+ end. */
+#define ps_fmt_spec_is_end(spec) ((spec)->name == NULL)
+
+struct ps_fmt_specs
+{
+ const struct ps_fmt_spec *specs; /* An array of specs. */
+ struct ps_fmt_specs *parent; /* A link to more specs shadowed by us. */
+ struct ps_fmt_spec_block *expansions; /* Storage for expanded aliases. */
+};
+
+/* An struct ps_fmt_specs, suitable for use with ps_fmt_specs_find,
+ containing specs for most values in a proc_stat. */
+extern struct ps_fmt_specs ps_std_fmt_specs;
+
+/* Searches for a spec called NAME in SPECS and returns it if found,
+ otherwise NULL. */
+const struct ps_fmt_spec *ps_fmt_specs_find (struct ps_fmt_specs *specs,
+ const char *name);
+
+/* A PS_FMT describes how to output user-readable version of a proc_stat.
+ It consists of a series of PS_FMT_FIELD_Ts, each describing how to output
+ one value. */
+
+/* Flags for ps_fmt_fields. */
+#define PS_FMT_FIELD_AT_MOD 0x1 /* `@' modifier */
+#define PS_FMT_FIELD_COLON_MOD 0x2 /* `:' modifier */
+#define PS_FMT_FIELD_KEEP 0x4 /* Never nominalize this field. */
+#define PS_FMT_FIELD_UPCASE_TITLE 0x8 /* Upcase this field's title. */
+
+/* PS_FMT_FIELD */
+struct ps_fmt_field
+ {
+ /* A ps_fmt_spec describing how to output this field's value, or NULL
+ if there is no value (in which case this is the last field, and exists
+ just to output its prefix string). */
+ const struct ps_fmt_spec *spec;
+
+ /* A non-zero-terminated string of characters that should be output
+ between the previous field and this one. */
+ const char *pfx;
+ /* The number of characters from PFX that should be output. */
+ unsigned pfx_len;
+
+ /* The number of characters that the value portion of this field should
+ consume. If this field is negative, then the absolute value is used,
+ and the field should be right-aligned, otherwise, it is left-aligned. */
+ int width;
+
+ /* User-specifiable attributes, interpreted by each output format. */
+ int precision; /* fraction following field width */
+
+ /* Flags, from the set PS_FMT_FIELD_. */
+ int flags;
+
+ /* Returns the title used when printing a header line for this field. */
+ const char *title;
+ };
+
+/* Accessor macros: */
+#define ps_fmt_field_fmt_spec(field) ((field)->spec)
+#define ps_fmt_field_prefix(field) ((field)->pfx)
+#define ps_fmt_field_prefix_length(field) ((field)->pfx_len)
+#define ps_fmt_field_width(field) ((field)->width)
+#define ps_fmt_field_title(field) ((field)->title)
+
+/* PS_FMT */
+struct ps_fmt
+{
+ /* A pointer to an array of struct ps_fmt_fields holding the individual
+ fields to be formatted. */
+ struct ps_fmt_field *fields;
+ /* The (valid) length of the fields array. */
+ unsigned num_fields;
+
+ /* A set of proc_stat flags describing what a proc_stat needs to hold in
+ order to print out every field in the fmt. */
+ ps_flags_t needs;
+
+ /* Storage for various strings pointed to by the fields. */
+ char *src;
+ size_t src_len; /* Size of SRC. */
+
+ /* The string displayed by default for fields that aren't appropriate for
+ this procstat. */
+ char *inapp;
+
+ /* The string displayed by default for fields which are appropiate, but
+ couldn't be fetched due to some error. */
+ char *error;
+};
+
+/* Accessor macros: */
+#define ps_fmt_fields(fmt) ((fmt)->fields)
+#define ps_fmt_num_fields(fmt) ((fmt)->num_fields)
+#define ps_fmt_needs(fmt) ((fmt)->needs)
+#define ps_fmt_inval (fmt) ((fmt)->inval)
+
+/* Make a PS_FMT by parsing the string SRC, searching for any named
+ field specs in FMT_SPECS, and returning the result in FMT. If a memory
+ allocation error occurs, ENOMEM is returned. If SRC contains an unknown
+ field name, EINVAL is returned. Otherwise 0 is returned.
+
+ If POSIX is true, a posix-style format string is parsed, otherwise
+ the syntax of SRC is:
+
+ SRC: FIELD* [ SUFFIX ]
+ FIELD: [ PREFIX ] SPEC
+ SPEC: `%' [ FLAGS ] [ `-' ] [ WIDTH ] [ `.' PRECISION ] NAMESPEC
+ FLAGS: `[!?@:]+'
+ WIDTH, PRECISION: `[0-9]+'
+ NAMESPEC: `{' NAME [ `:' TITLE ] `}' | NAME_AN
+ NAME, TITLE: `[^}]*'
+ NAME_AN: `[A-Za-z0-9_]*'
+
+ PREFIXes and SUFFIXes are printed verbatim, and specs are replaced by the
+ output of the named spec with that name (each spec specifies what
+ proc_stat field to print, and how to print it, as well as a default field
+ width into which put the output). WIDTH is used to override the spec's
+ default width. If a `-' is included, the output is right-aligned within
+ this width, otherwise it is left-aligned. The FLAGS `@' & `:' are
+ spec-specific, `!' means never omit a nominal field, and `?' means omit a
+ field if it's nominal (in case the defualt is to never do so). PRECISION
+ has a spec-specific meaning. */
+error_t ps_fmt_create (char *src, int posix, struct ps_fmt_specs *fmt_specs,
+ struct ps_fmt **fmt);
+
+/* Given the same arguments as a previous call to ps_fmt_create that returned
+ an error, this function returns a malloced string describing the error. */
+void ps_fmt_creation_error (char *src, int posix,
+ struct ps_fmt_specs *fmt_specs,
+ char **error);
+
+/* Free FMT, and any resources it consumes. */
+void ps_fmt_free (struct ps_fmt *fmt);
+
+/* Return a copy of FMT in COPY, or an error. This is useful if, for
+ instance, you would like squash a format without destroying the original. */
+error_t ps_fmt_clone (struct ps_fmt *fmt, struct ps_fmt **copy);
+
+/* Write an appropiate header line for FMT, containing the titles of all its
+ fields appropiately aligned with where the values would be printed, to
+ STREAM (without a trailing newline). If count is non-NULL, the total
+ number number of characters output is added to the integer it points to.
+ If any fatal error occurs, the error code is returned, otherwise 0. */
+error_t ps_fmt_write_titles (struct ps_fmt *fmt, struct ps_stream *stream);
+
+/* Format a description as instructed by FMT, of the process described by PS
+ to STREAM (without a trailing newline). If count is non-NULL, the total
+ number number of characters output is added to the integer it points to.
+ If any fatal error occurs, the error code is returned, otherwise 0. */
+error_t ps_fmt_write_proc_stat (struct ps_fmt *fmt, struct proc_stat *ps,
+ struct ps_stream *stream);
+
+/* Remove those fields from FMT for which the function FN, when called on the
+ field, returns true. Appropiate inter-field characters are also removed:
+ those *following* deleted fields at the beginning of the fmt, and those
+ *preceeding* deleted fields *not* at the beginning. */
+void ps_fmt_squash (struct ps_fmt *fmt, int (*fn)(struct ps_fmt_field *field));
+
+/* Remove those fields from FMT which would need the proc_stat flags FLAGS.
+ Appropiate inter-field characters are also removed: those *following*
+ deleted fields at the beginning of the fmt, and those *preceeding* deleted
+ fields *not* at the beginning. */
+void ps_fmt_squash_flags (struct ps_fmt *fmt, ps_flags_t flags);
+
+/* Try and restrict the number of output columns in FMT to WIDTH. */
+void ps_fmt_set_output_width (struct ps_fmt *fmt, int width);
+
+/* A PROC_STAT_LIST represents a list of proc_stats */
+
+struct proc_stat_list
+ {
+ /* An array of proc_stats for the processes in this list. */
+ struct proc_stat **proc_stats;
+
+ /* The number of processes in the list. */
+ unsigned num_procs;
+
+ /* The actual allocated length of PROC_STATS (in case we want to add more
+ processes). */
+ unsigned alloced;
+
+ /* Returns the proc context that these processes are from. */
+ struct ps_context *context;
+ };
+
+/* Accessor macros: */
+#define proc_stat_list_num_procs(pp) ((pp)->num_procs)
+#define proc_stat_list_context(pp) ((pp)->context)
+
+/* Creates a new proc_stat_list_t for processes from CONTEXT, which is
+ returned in PP, and returns 0, or else returns ENOMEM if there wasn't
+ enough memory. */
+error_t proc_stat_list_create (struct ps_context *context,
+ struct proc_stat_list **pp);
+
+/* Free PP, and any resources it consumes. */
+void proc_stat_list_free (struct proc_stat_list *pp);
+
+/* Returns a copy of PP in COPY, or an error. */
+error_t proc_stat_list_clone (struct proc_stat_list *pp,
+ struct proc_stat_list **copy);
+
+/* Returns the proc_stat in PP with a process-id of PID, if there's one,
+ otherwise, NULL. */
+struct proc_stat *proc_stat_list_pid_proc_stat (struct proc_stat_list *pp,
+ pid_t pid);
+
+/* Add proc_stat entries to PP for each process with a process id in the
+ array PIDS (where NUM_PROCS is the length of PIDS). Entries are only
+ added for processes not already in PP. ENOMEM is returned if a memory
+ allocation error occurs, otherwise 0. PIDs is not referenced by the
+ resulting proc_stat_list_t, and so may be subsequently freed. If
+ PROC_STATS is non-NULL, a malloced array NUM_PROCS entries long of the
+ resulting proc_stats is returned in it. */
+error_t proc_stat_list_add_pids (struct proc_stat_list *pp,
+ pid_t *pids, unsigned num_procs,
+ struct proc_stat ***proc_stats);
+
+/* Add a proc_stat for the process designated by PID at PP's proc context
+ to PP. If PID already has an entry in PP, nothing is done. If a memory
+ allocation error occurs, ENOMEM is returned, otherwise 0. If PS is
+ non-NULL, the resulting entry is returned in it. */
+error_t proc_stat_list_add_pid (struct proc_stat_list *pp, pid_t pid,
+ struct proc_stat **ps);
+
+/* Adds all proc_stats in MERGEE to PP that don't correspond to processes
+ already in PP; the resulting order of proc_stats in PP is undefined.
+ If MERGEE and PP point to different proc contexts, EINVAL is returned. If a
+ memory allocation error occurs, ENOMEM is returned. Otherwise 0 is
+ returned, and MERGEE is freed. */
+error_t proc_stat_list_merge (struct proc_stat_list *pp,
+ struct proc_stat_list *mergee);
+
+/* Add to PP entries for all processes at its context. If an error occurs,
+ the system error code is returned, otherwise 0. If PROC_STATS and
+ NUM_PROCS are non-NULL, a malloced vector of the resulting entries is
+ returned in them. */
+error_t proc_stat_list_add_all (struct proc_stat_list *pp,
+ struct proc_stat ***proc_stats,
+ unsigned *num_procs);
+
+/* Add to PP entries for all processes in the login collection LOGIN_ID at
+ its context. If an error occurs, the system error code is returned,
+ otherwise 0. If PROC_STATS and NUM_PROCS are non-NULL, a malloced vector
+ of the resulting entries is returned in them. */
+error_t proc_stat_list_add_login_coll (struct proc_stat_list *pp,
+ pid_t login_id,
+ struct proc_stat ***proc_stats,
+ unsigned *num_procs);
+
+/* Add to PP entries for all processes in the session SESSION_ID at its
+ context. If an error occurs, the system error code is returned, otherwise
+ 0. If PROC_STATS and NUM_PROCS are non-NULL, a malloced vector of the
+ resulting entries is returned in them. */
+error_t proc_stat_list_add_session (struct proc_stat_list *pp,
+ pid_t session_id,
+ struct proc_stat ***proc_stats,
+ unsigned *num_procs);
+
+/* Add to PP entries for all processes in the process group PGRP at its
+ context. If an error occurs, the system error code is returned, otherwise
+ 0. If PROC_STATS and NUM_PROCS are non-NULL, a malloced vector of the
+ resulting entries is returned in them. */
+error_t proc_stat_list_add_pgrp (struct proc_stat_list *pp, pid_t pgrp,
+ struct proc_stat ***proc_stats,
+ unsigned *num_procs);
+
+/* Try to set FLAGS in each proc_stat in PP (but they may still not be set
+ -- you have to check). If a fatal error occurs, the error code is
+ returned, otherwise 0. */
+error_t proc_stat_list_set_flags (struct proc_stat_list *pp, ps_flags_t flags);
+
+/* Destructively modify PP to only include proc_stats for which the
+ function PREDICATE returns true; if INVERT is true, only proc_stats for
+ which PREDICATE returns false are kept. FLAGS is the set of pstat_flags
+ that PREDICATE requires be set as precondition. Regardless of the value
+ of INVERT, all proc_stats for which the predicate's preconditions can't
+ be satisfied are kept. If a fatal error occurs, the error code is
+ returned, it returns 0. */
+error_t proc_stat_list_filter1 (struct proc_stat_list *pp,
+ int (*predicate)(struct proc_stat *ps),
+ ps_flags_t flags,
+ int invert);
+
+/* Destructively modify PP to only include proc_stats for which the
+ predicate function in FILTER returns true; if INVERT is true, only
+ proc_stats for which the predicate returns false are kept. Regardless
+ of the value of INVERT, all proc_stats for which the predicate's
+ preconditions can't be satisfied are kept. If a fatal error occurs,
+ the error code is returned, it returns 0. */
+error_t proc_stat_list_filter (struct proc_stat_list *pp,
+ const struct ps_filter *filter, int invert);
+
+/* Destructively sort proc_stats in PP by ascending value of the field
+ returned by GETTER, and compared by CMP_FN; If REVERSE is true, use the
+ opposite order. If a fatal error occurs, the error code is returned, it
+ returns 0. */
+error_t proc_stat_list_sort1 (struct proc_stat_list *pp,
+ const struct ps_getter *getter,
+ int (*cmp_fn)(struct proc_stat *ps1,
+ struct proc_stat *ps2,
+ const struct ps_getter *getter),
+ int reverse);
+
+/* Destructively sort proc_stats in PP by ascending value of the field KEY;
+ if REVERSE is true, use the opposite order. If KEY isn't a valid sort
+ key, EINVAL is returned. If a fatal error occurs the error code is
+ returned. Otherwise, 0 is returned. */
+error_t proc_stat_list_sort (struct proc_stat_list *pp,
+ const struct ps_fmt_spec *key, int reverse);
+
+/* Format a description as instructed by FMT, of the processes in PP to
+ STREAM, separated by newlines (and with a terminating newline). If COUNT
+ is non-NULL, it points to an integer which is incremented by the number of
+ characters output. If a fatal error occurs, the error code is returned,
+ otherwise 0. */
+error_t proc_stat_list_fmt (struct proc_stat_list *pp, struct ps_fmt *fmt,
+ struct ps_stream *stream);
+
+/* Modifies FLAGS to be the subset which can't be set in any proc_stat in
+ PP (and as a side-effect, adds as many bits from FLAGS to each proc_stat
+ as possible). If a fatal error occurs, the error code is returned,
+ otherwise 0. */
+error_t proc_stat_list_find_bogus_flags (struct proc_stat_list *pp,
+ ps_flags_t *flags);
+
+/* Add thread entries for for every process in PP, located immediately after
+ the containing process in sequence. Subsequent sorting of PP will leave
+ the thread entries located after the containing process, although the
+ order of the thread entries themselves may change. If a fatal error
+ occurs, the error code is returned, otherwise 0. */
+error_t proc_stat_list_add_threads (struct proc_stat_list *pp);
+
+error_t proc_stat_list_remove_threads (struct proc_stat_list *pp);
+
+/* Calls FN in order for each proc_stat in PP. If FN ever returns a non-zero
+ value, then the iteration is stopped, and the value is returned
+ immediately; otherwise, 0 is returned. */
+int proc_stat_list_for_each (struct proc_stat_list *pp,
+ int (*fn)(struct proc_stat *ps));
+
+/* Returns true if SPEC is `nominal' in every entry in PP. */
+int proc_stat_list_spec_nominal (struct proc_stat_list *pp,
+ const struct ps_fmt_spec *spec);
+
+/* The Basic & Sched info types are pretty static, so we cache them, but load
+ info is dynamic so we don't cache that. See <mach/host_info.h> for
+ information on the data types these routines return. */
+
+/* Return the current host port. */
+host_t ps_get_host ();
+
+/* Return a pointer to basic info about the current host in HOST_INFO. Since
+ this is static global information we just use a static buffer. If a
+ system error occurs, the error code is returned, otherwise 0. */
+error_t ps_host_basic_info (host_basic_info_t *host_info);
+
+/* Return a pointer to scheduling info about the current host in HOST_INFO.
+ Since this is static global information we just use a static buffer. If a
+ system error occurs, the error code is returned, otherwise 0. */
+error_t ps_host_sched_info (host_sched_info_t *host_info);
+
+/* Return a pointer to load info about the current host in HOST_INFO. Since
+ this is global information we just use a static buffer (if someone desires
+ to keep old load info, they should copy the buffer we return a pointer
+ to). If a system error occurs, the error code is returned, otherwise 0. */
+error_t ps_host_load_info (host_load_info_t *host_info);
+
+#endif /* __PS_H__ */