diff options
Diffstat (limited to 'libps')
-rw-r--r-- | libps/ChangeLog | 761 | ||||
-rw-r--r-- | libps/Makefile | 9 | ||||
-rw-r--r-- | libps/common.h | 6 | ||||
-rw-r--r-- | libps/context.c | 74 | ||||
-rw-r--r-- | libps/filters.c | 12 | ||||
-rw-r--r-- | libps/fmt.c | 60 | ||||
-rw-r--r-- | libps/host.c | 52 | ||||
-rw-r--r-- | libps/proclist.c | 27 | ||||
-rw-r--r-- | libps/procstat.c | 340 | ||||
-rw-r--r-- | libps/ps.h | 345 | ||||
-rw-r--r-- | libps/spec.c | 225 | ||||
-rw-r--r-- | libps/tty.c | 24 | ||||
-rw-r--r-- | libps/user.c | 5 | ||||
-rw-r--r-- | libps/write.c | 4 |
14 files changed, 669 insertions, 1275 deletions
diff --git a/libps/ChangeLog b/libps/ChangeLog deleted file mode 100644 index ff633deb..00000000 --- a/libps/ChangeLog +++ /dev/null @@ -1,761 +0,0 @@ -Fri Aug 2 15:12:19 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * procstat.c (set_procinfo_flags): Pass HAVE to count_threads. - (count_threads): Take new argument HAVE, and use different thread - counting method depending on whether we have thread detail info. - -Thu Jul 18 18:54:07 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * tty.c (ps_tty_abbrevs): Add an entry for /dev/comX -> cX. - -Thu Jul 18 00:45:25 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * Makefile (LCLHDRS): Remove ps_msg.h and ps_term.h. - -Wed Jul 10 22:49:39 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * procstat.c (set_procinfo_flags): Don't use fake "*" wait value - if there's no msgport. - -Mon Jul 8 21:39:58 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * write.c (_ps_stream_write_field): If a field is truncatable - (MAX_WIDTH >= 0), take some of our spacing deficit out of it. - -Tue Jul 2 14:43:39 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * procstat.c (proc_stat_set_flags): Pass PS->task_events_info to - task_info, not its address. - -Thu Jun 27 18:32:27 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * Makefile (LCLHDRS): Add common.h. - -Thu Jun 27 12:33:41 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * ps.h (struct ps_fmt): Add SRC_LEN field. - (proc_stat_list_clone, ps_fmt_clone): New declarations. - * fmt.c (_fmt_create): Set NEW_FMT->src_len. Use strdup. - (ps_fmt_clone): New function. - * proclist.c (proc_stat_list_clone): New function. - -Mon Jun 3 10:17:43 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * spec.c (ps_emit_wait): Never truncate what we write. - - * user.c (ps_user_passwd): Check return value of install_passwd - correctly (it's an error_t). - - * ps.h (struct proc_stat): Add PROC_INFO_VM_ALLOCED, - THREAD_WAITS_VM_ALLOCED, and ARGS_VM_ALLOCED fields, - * procstat.c (merge_procinfo) Take a struct proc_stat as an arg, - not all the individual fields. Correctly set OLD_PI_HDR. - Correctly calculate REALLY_NEED. - (set_procinfo_flags): Use new calling merge_procinfo calling convention. - (_proc_stat_free): Use explicit VM_ALLOCED flag for MFREEMEM. - (proc_stat_set_flags): Try mallocing a buffer for PS->args. - Move second call to set_procinfo_flags after msgport suppress test. - Add TEST_MSGPORT_FLAGS variable, & use it. - Be more picky about when we call set_procinfo_flags. - -Sat Jun 1 11:18:58 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * procstat.c (set_procinfo_flags): New function. - (proc_stat_set_flags): Use it, to get msgport validity testing right. - (merge_procinfo): Take and return HAVE instead of using a - reference parameter. Clean up malloced storage if we get an error. - - * spec.c (struct ps_fmt_spec_block): New type. - (specs_add_alias): Use a linked list of ps_fmt_spec_blocks instead of - reallocing a vector of specs. - (ps_fmt_specs_find): Change searching accordingly. - * ps.h (struct ps_fmt_specs): The EXPANSIONS field now points to a - struct ps_fmt_spec_block. Delete EXPANSIONS_ALLOCED field. - - * procstat.c (merge_procinfo): Correctly test for malloc failure. - -Fri May 31 18:36:18 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * procstat.c (MFREEMEM): New macro combining MFREEM & MFREEVM. - (MFREEM, MFREEVM): Macros deleted. - (merge_procinfo): Do mem allocation more efficiently and correctly. - (fetch_procinfo): Do conversion for PI_SIZE from/to units of - sizeof (int), so no one else has to deal with it. - (PROCINFO_MALLOC_SIZE, WAITS_MALLOC_SIZE): New macros. - - * procstat.c (proc_stat_set_flags): After fetching number of - threads to guess whether we need wait info, put it in PS->num_threads. - (merge_procinfo): Avoid vm_allocing a procinfo buffer each time if - we can help it. - Correctly reflect newly fetched info. - (PSTAT_PROCINFO_MERGE, PSTAT_PROCINFO_REFETCH): New macros. - -Wed May 29 11:31:31 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * procstat.c (MP_MGET): Only disable msgport on timeout. - (get_thread_wait): Decrement N in loop. - - * ps.h: Renumber PSTAT_ values to remove dup. - - * procstat.c (merge_procinfo): Don't die if WAITS == 0. - (summarize_thread_waits): Correctly advance NEXT_WAIT. - Skip threads marked `itimer'. - (proc_stat_set_flags): Consider processes with less than 4 threads - to be candidates for a meaningful process wait status. - (get_thread_wait): Use strnlen instead of memchr. - (PSTAT_PROCINFO): Typo: PSTAT_THREAD_WAIT --> PSTAT_THREAD_WAITS. - (PSTAT_USES_MSGPORT): Add PSTAT_THREAD_WAIT. - -Tue May 28 16:36:17 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * fmt.c (_fmt_create): Make NAME termination work for posix-mode. - - * fmt.c (ps_fmt_write_proc_stat): Call the output function correctly. - (_fmt_create): Get FIELD's precision, not width, from its spec. - -Fri May 24 13:33:14 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * procstat.c (fetch_procinfo): Always turn on PSTAT_PROC_INFO if - proc_getprocinfo returns successfully. - (merge_procinfo): Update *HAVE with PSTAT_PROC_INFO from - REALLY_HAVE here. - -Wed May 22 19:55:04 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * fmt.c (_fmt_create): Increment SRC when reading modifiers. - Recognize '^' modifier. - -Sun May 12 13:33:16 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * procstat.c (PSTAT_PROCINFO, PSTAT_PROCINFO_THREAD): Add - PSTAT_THREAD_WAITS. - (proc_stat_set_flags): Be more careful about when we fetch - thread_wait information, and synthesize a process-summary thread_wait - value for lots of threads. - (summarize_thread_waits): Only give a real summary if there's but - a single user thread. - (fetch_procinfo): Use PSTAT_THREAD_WAITS instead of PSTAT_THREAD_WAIT. - * ps.h (PSTAT_THREAD_WAITS): New macro. - - * procstat.c (merge_procinfo, fetch_procinfo): Change HAVE to be an - input/output parameter. - (proc_stat_set_flags): Change accordingly. - - * procstat.c (get_thread_wait): Correctly advance WAIT. - - * spec.c (specs): Give runtime specs 2 fraction digits by default. - -Thu May 9 17:03:37 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * procstat.c (fetch_procinfo): Pass a reference to PI_FLAGS in - call to fetch_procinfo. - -Mon May 6 16:28:54 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * proclist.c (proc_stat_list_spec_nominal): Take a spec again. - * ps.h (proc_stat_list_spec_nominal): Change FIELD arg to SPEC. - - * user.c (install_passwd): New function. - (ps_user_passwd): Use it. - (ps_user_uname_create, ps_user_passwd_create): New functions. - * ps.h (ps_user_uname_create, ps_user_passwd_create): New declarations. - (ps_fmt_set_output_width): New declaration. - - * spec.c (ps_emit_user_name): New function. - - * ps.h (struct ps_fmt_spec): Remove keep field, add flags field. - (struct ps_fmt_field): Remove at_mod, colon_mod, & keep fields, - add flags field. - (PS_FMT_FIELD_AT_MOD, PS_FMT_FIELD_COLON_MOD, PS_FMT_FIELD_KEEP, - PS_FMT_FIELD_UPCASE_TITLE): New macros. - * spec.c (specs): Initialize flags field, not keep field. - (specs_add_alias): Pass on flags field. - * fmt.c (_fmt_create): Use flags fields, and implement global - flags, and add upcase flag (^). - (ps_fmt_write_titles): Implement PS_FMT_FIELD_UPCASE_TITLE. - * proclist.c (proc_stat_list_spec_nominal): Use flags field, not - keep field. - - * ps.h (struct proc_stat): Remove exec_flags field. - (PSTAT_EXEC_FLAGS): Macro removed. - * procstat.c (add_preconditions, proc_stat_set_flags): Remove - references to exec_flags. - -Sun May 5 00:22:01 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * proclist.c (proc_stat_list_spec_nominal): Take a field, not a spec. - If the field has the keep flag set, don't nominalize it. - * fmt.c (_fmt_create): Change syntax of fields. Add support for - precision and `@', `:', `?', & `!' modifiers. - Add POSIX argument, and support for posix-style format strings. - When using the field name as the title, use the defn, not the user's. - (ps_fmt_squash): Call FN with the field, not the field's spec. - (ps_fmt_squash_flags): Appropiately modify the function we use. - (ps_fmt_create, ps_fmt_creation_error): Add POSIX argument. - * ps.h (struct ps_fmt_spec): Add precision & keep fields. - Change args to OUTPUT_FN. - (struct ps_fmt_field): Add precision, keep, at_mod, & colon_mod fields. - (proc_stat_list_spec_nominal): Change SPEC arg to FIELD. - (ps_fmt_squash): Call FN on the field, not the spec. - (ps_fmt_create, ps_fmt_creation_error): Add POSIX arg. - * spec.c (specs): Add precision & keep fields. - (FG): New macro. - (ps_emit_*): Take FIELD argument instead of WIDTH. - -Thu May 2 00:12:19 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * ps.h (ps_fmt_creation_error): New declaration. - -Tue Apr 30 18:54:57 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * fmt.c (_fmt_create): New function (was ps_fmt_create). - (ps_fmt_create): Call _fmt_create. - (ps_fmt_creation_error): New function. - - * spec.c (ps_emit_past_time): Implement. - -Mon Apr 29 12:59:08 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * spec.c (ps_emit_seconds): Use new args to fmt_seconds. - (ps_emit_minutes): Use new args to fmt_minutes. - -Tue Apr 23 13:38:06 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * ps.h (PSTAT_STATE_P_ATTRS): Fix names of individual flags. - - * spec.c (state_shadows): If a process has no parent don't show - various process attributes (that are likely to be noise). - -Thu Apr 11 18:05:16 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu> - - * Makefile (MIGCOMUFLAGS): Delete variable. - - * spec.c (ps_emit_past_time): Return zero. - -Wed Mar 27 15:19:40 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * Makefile (msg-MIGUFLAGS, term-MIGUFLAGS): Add a user prefix of `ps_'. - * procstat.c (proc_stat_set_flags): Use new prefix. - Include "ps_msg.h". - * tty.c (ps_tty_name): Use new prefix. - Include "ps_term.h". - -Mon Mar 25 11:35:48 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * ...just about everything...: Get rid of mega typedefs, and just - use structure pointers like other hurd libraries. Other misc cleanups. - - * ps.h (struct ps_fmt_specs): Add EXPANSIONS & EXPANSIONS_ALLOCED. - * spec.c (ps_fmt_specs_find): Use new alias expansion method. - (specv_find, specs_add_alias): New functions. - -Mon Mar 11 16:27:14 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * write.c (noise_write): Keep track of amount printed correctly. - -Sat Mar 9 15:52:55 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * write.c (iscntl): New macro. - (noise_write, noise_len): Correctly handle MAX < 0 case. - (noise_write): Use new arguments for flush. - (flush): Moved to file scope. Remove END argument and use NEW - 1. - (noise_write): Make T of type unsigned char * so that chars with - the high bit set print correctly. - -Thu Mar 7 19:08:00 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * write.c (iscntl): New macro. - (noise_write, noise_len, flush): New functions. - (ps_stream_write, _ps_stream_write_field): Use noise functions. - -Thu Feb 15 00:02:53 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * spec.c (specs): Right-align the TTY column. - -Wed Feb 14 17:49:17 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * write.c (ps_stream_write): Don't screw up on negative spaces. - - * proclist.c (proc_stat_list_add_pids): Add and support new return - parameter PROC_STATS. - (proc_stat_list_add_pid): Add and support new return parameter PS. - (proc_stat_list_add_fn_pids, proc_stat_list_add_id_fn_pids, - proc_stat_list_add_all, proc_stat_list_add_login_coll, - proc_stat_list_add_session, proc_stat_list_add_pgrp): - Add and support new return parameters PROC_STATS & NUM_PROCS. - * ps.h (proc_stat_list_add_pids, proc_stat_list_add_pid, - proc_stat_list_add_all, proc_stat_list_add_login_coll, - proc_stat_list_add_session, proc_stat_list_add_pgrp): - Update declarations. - - * filters.c (ps_alive_filter): New variable. - (ps_alive_p): New function. - * ps.h (ps_alive_filter): New declaration. - -Mon Feb 12 14:34:22 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * spec.c (ps_emit_wait): For rpcs, put the port first. - -Fri Feb 9 15:55:35 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * ps.h (struct proc_stat): Add thread_wait, thread_waits, & - thread_waits_len fields. - (PSTAT_THREAD_WAIT): Renamed from PSTAT_THREAD_RPC. - (proc_stat_thread_wait): New macro. - (ps_stream_write_trunc_field): New declaration. - * procstat.c (fetch_procinfo, merge_procinfo): Return wait strings. - (summarize_thread_waits): Return both wait and rpc info. - (get_thread_wait): New function. - (proc_stat_set_flags): Support finding wait info. - Change occurances of PSTAT_THREAD_RPC to PSTAT_THREAD_WAIT. - * spec.c (specs): Change `Rpc' entry to `Wait'. - (ps_emit_wait): New function. - (ps_emit_string, ps_emit_string0): Use ps_stream_write_trunc_field. - (ps_get_wait): Renamed from ps_get_rpc; calling convention changed. - (ps_wait_getter): Renamed from ps_rpc_getter & contents changed accord. - (get_syscall_name, get_rpc_name): New stub functions. - * write.c (ps_stream_write_field): Call _ps_stream_write_field. - (ps_stream_write_trunc_field): New function. - (_ps_stream_write_field): New function, from ps_stream_write_field. - -Sat Feb 3 22:22:01 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * spec.c (specs, state_shadows, ps_pid_getter, - ps_thread_index_getter, ps_owner_getter, ps_owner_uid_getter, - ps_ppid_getter, ps_pgrp_getter, ps_session_getter, - ps_login_col_getter, ps_num_threads_getter, ps_args_getter, - ps_state_getter, ps_rpc_getter, ps_vsize_getter, ps_rsize_getter, - ps_cur_priority_getter, ps_base_priority_getter, - ps_max_priority_getter, ps_usr_time_getter, ps_sys_time_getter, - ps_tot_time_getter, ps_rmem_frac_getter, ps_cpu_frac_getter, - ps_sleep_getter, ps_susp_count_getter, ps_proc_susp_count_getter, - ps_thread_susp_count_getter, ps_tty_getter, ps_page_faults_getter, - ps_cow_faults_getter, ps_pageins_getter, ps_msgs_sent_getter, - ps_msgs_rcvd_getter, ps_zero_fills_getter): Make const. - * ps.h (ps_getter_t, ps_filter_t, struct ps_filter, - ps_not_leader_filter, ps_ctty_filter, ps_unorphaned_filter, - ps_parent_filter, ps_std_fmt_specs): Make const. - -Mon Jan 15 16:32:31 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * procstat.c (summarize_thread_basic_info): If there are any - running threads, then only average priority from them. - -Sun Jan 14 00:24:55 1996 Miles Bader <miles@gnu.ai.mit.edu> - - * spec.c (state_shadows): Don't reflect a suspended thread in the - process state display if any thread isn't suspended. - -Sun Dec 24 14:24:52 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * Makefile (installhdrsubdir): New macro (put ps.h in <>, not <hurd/>). - -Sat Dec 23 21:50:58 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * fmt.c (ps_fmt_set_output_width): New function. - -Fri Dec 22 12:21:04 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * ps.h (struct ps_user_hooks): New structure. - (PSTAT_HOOK, PSTAT_USER_BASE, PSTAT_USER_MASK): New macros. - (struct ps_context): Add USER_HOOKS field. - * procstat.c (_proc_stat_free): Call user cleanup hook. - (proc_stat_set_flags, add_preconditions): Deal with user bits. - * context.c (ps_context_create): Initialize USER_HOOKS field. - -Thu Dec 21 12:04:24 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * spec.c (ps_get_usr_time, ps_get_sys_time, ps_get_tot_time): - Return a struct timeval instead of mach time_value_t. - (ps_cmp_times): New function. - (ps_emit_seconds, ps_emit_minutes): Use timefmt functions. - (append_fraction, sprint_long_time, ps_emit_nice_seconds): Deleted. - Include <timefmt.h>. - - * ps.h (struct ps_fmt_spec): Add TITLE field. Renamed - DEFAULT_WIDTH field to WIDTH, and move to after TITLE. - (ps_fmt_spec_width): Renamed from ps_fmt_spec_default_width().. - (ps_fmt_spec_title): New macro. - (struct ps_fmt): Add INVAL field. - (ps_fmt_inval): New macro. - * spec.c (specs): Rearrange to use new field layout. - - * fmt.c (ps_fmt_create): Use the new spec fields. - (ps_fmt_write_proc_stat): Support new inval field in FMT. - - * spec.c (ps_fmt_specs_find): Renamed from find_ps_fmt_spec; now - uses a struct ps_fmt_specs instead of an array of specs. - (specs): Renamed from ps_std_fmt_specs; - (ps_std_fmt_specs): Now of type struct ps_fmt_specs, pointing to specs. - * ps.h (ps_fmt_specs_t): New typedef. - (struct ps_fmt_specs): New structure. - (ps_std_fmt_specs): Now of type struct ps_fmt_specs. - (ps_fmt_specs_find): Renamed from find_ps_fmt_spec; now uses a - struct ps_fmt_specs instead of an array of specs. - (ps_fmt_create): Now takes a ps_fmt_specs_t structure instead of - an array of specs. - - * fmt.c (ps_fmt_create): Now takes a ps_fmt_specs_t instead of an - array of specs. Also fixup call to ps_fmt_specs_find(). - - * ps.h (struct proc_stat): Add failed and hook fields. - * procstat.c (proc_stat_set_flags): Support the failed field. - (_proc_stat_create): Initialize the failed and hook fields. - -Wed Dec 20 12:49:24 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * spec.c (ps_emit_nz_int): Write `-' when the value is 0, rather - than mangling the output. - -Sun Dec 17 03:09:31 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * procstat.c (proc_stat_set_flags): If there's no owner, set the - uid to -1 (and the owner to null), instead of failing. - * spec.c (ps_emit_uid): Use an int uid, and emit "-" for none. - (ps_emit_uname, ps_cmp_uids, ps_cmp_unames, ps_nominal_user): - Handle NULL users. - - * filters.c (ps_not_leader_p): Renamed from ps_not_sess_leader_p. - (ps_not_leader_filter): Renamed from ps_not_sess_leader_filter. - (ps_unorphaned_p): Include login leaders as well as session leaders. - * ps.h (ps_not_leader_filter): Renamed from ps_not_sess_leader_filter. - -Sat Dec 16 23:42:27 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * ps.h (proc_stat_owner_uid): New macro. - (PSTAT_OWNER_UID): New macro. - (struct proc_stat): Add owner_uid field. - * procstat.c (proc_stat_set_flags): Add support for PROC_OWNER_UID. - (add_preconditions): Add preconditions for owner_uid (& owner). - * spec.c (ps_owner_uid_getter): New variable. - (ps_get_owner_uid, ps_nominal_uid): New functions. - (ps_std_fmt_specs): Make "UID" use owner_uid rather than owner. - (own_uid): New variable (was function local). - * filters.c (ps_own_filter): Depend on PSTAT_OWNER_UID. - (ps_own_p): Account for there being no uid. - -Thu Nov 16 12:51:34 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * write.c (ps_stream_write_field): Trim spaces from BUF. - -Wed Nov 15 18:55:26 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * ps.h (ps_fmt_write_titles, ps_fmt_write_proc_stat, - proc_stat_list_fmt, ps_emit_int, ps_emit_nz_int, ps_emit_priority, - ps_emit_percent, ps_emit_num_blocks, ps_emit_nice_int, - ps_emit_nice_seconds, ps_emit_seconds, ps_emit_uid, ps_emit_uname, - ps_emit_string0, ps_emit_string, ps_emit_tty_name, ps_emit_state, - ps_stream_write, ps_stream_space, ps_stream_pad, - ps_stream_newline, ps_stream_write_field, ps_stream_write_int_field): - Use new STREAM parameter instead of old one and count. - (ps_stream_write): Renamed from ps_write_string. - (ps_stream_space): Renamed from ps_write_spaces. - (ps_stream_pad): Renamed from ps_write_padding. - (ps_stream_write_field): Renamed from ps_write_field. - (ps_stream_write_int_field): Renamed from ps_write_int_field. - (ps_stream_newline): New declaration. - - * fmt.c (ps_fmt_write_titles, ps_fmt_write_proc_stat): Use new - write function names. Use new STREAM parameter instead of old one - and count. - * proclist.c (proc_stat_list_fmt): Ditto. - * spec.c (ps_emit_int, ps_emit_nz_int, ps_emit_priority, - ps_emit_percent, ps_emit_num_blocks, ps_emit_nice_int, - ps_emit_nice_seconds, ps_emit_seconds, ps_emit_uid, ps_emit_uname, - ps_emit_string0, ps_emit_string, ps_emit_tty_name, ps_emit_state): - Ditto. - (ps_emit_seconds): Remove leading spaces from what we print. - - * write.c (ps_stream_write): Renamed from ps_write_string. - (ps_stream_space): Renamed from ps_write_spaces. - (ps_stream_pad): Renamed from ps_write_padding. - (ps_stream_write_field): Renamed from ps_write_field. - (ps_stream_write_int_field): Renamed from ps_write_int_field. - (ps_stream_write, ps_stream_space, ps_stream_pad, - ps_stream_newline, ps_stream_write_field, ps_stream_write_int_field): - Use new STREAM parameter instead of old one and count. - Use new function names. - (ps_stream_write, ps_stream_space): Support negative spaces. - (ps_stream_newline): New function. - (ps_stream_pad, ps_stream_write_field): Use negative spaces. - -Tue Nov 7 17:43:48 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * spec.c (ps_base_priority_getter, ps_cur_priority_getter, - ps_get_base_priority, ps_get_cur_priority): Get this info using - PSTAT_THREAD_BASIC instead of PSTAT_THREAD_SCHED. - * procstat.c (summarize_thread_basic_info): Summarize available - priority info too. - (summarize_thread_sched_info): Do max_ & depress_priority too. - - * procstat.c (proc_stat_set_flags): Initialize the proc_info and - proc_info_size fields if they've never been set before. - Always update proc_getprocinfo fields, even if we already had them. - (add_preconditions): Correct preconditions for PSTAT_STATE. - (PSTAT_TEST_MSGPORT): Renamed from SHOULD_SUPPRESS_MSGPORT_FLAGS. - (PSTAT_USES_MSGPORT): New macro. - (SUPPRESS_MSGPORT_FLAGS): Use PSTAT_USES_MSGPORT, not PSTAT_MSGPORT. - (proc_stat_set_flags): Use PSTAT_TEST_MSGPORT. - (merge_procinfo): Only copy old task info if we actually had it. - (proc_stat_set_flags): Don't unnecessarily grab procinfo stuff. - -Tue Oct 31 14:03:53 1995 Miles Bader <miles@gnu.ai.mit.edu> - - * spec.c (ps_rpc_getter): New variable. - (ps_get_rpc): New function. - (ps_std_fmt_specs): Add "RPC" entry. - (ps_emit_nz_int): New function. - - * ps.h (PSTAT_STATE_P_LOGINLDR, PSTAT_STATE_P_WAIT, - PSTAT_STATE_P_GETMSG): New flags. - * procstat.c (add_preconditions): Don't require PSTAT_EXEC_FLAGS for - getting the state anymore (but do require PSTAT_{TASK,THREAD}_BASIC). - (proc_stat_state_tags): Update to reflect new flags. - (proc_stat_set_flags): Set new flags. - - * procstat.c (PSTAT_PROCINFO, PSTAT_PROCINFO_THREAD): New macros. - (fetch_procinfo, merge_procinfo): New functions. - (SHOULD_SUPPRESS_MSGPORT_FLAGS): Change to use more accurate flags. - (should_suppress_msgport): Use new fields. - (summarize_thread_basic_info, summarize_thread_sched_info, - summarize_thread_states, summarize_thread_rpcs, count_threads): - New functions. - (proc_stat_set_flags): Support the new division of PSTAT_INFO into - individual flags, and support getting thread information by - using the thread's origin proc_stat. - (_proc_stat_free): Free the thread_basic_info and - thread_sched_info fields if necessary. - (proc_stat_thread_create): Don't require that the source process - have thread information around; it will be fetched later if necessary. - - * spec.c (ps_ppid_getter, ps_pgrp_getter, ps_session_getter, - ps_login_col_getter): Use PSTAT_PROC_INFO, not PSTAT_INFO. - (ps_get_ppid, ps_get_pgrp, ps_get_session, ps_get_login_col): Use - proc_stat_proc_info, not proc_stat_info. - (ps_vsize_getter, ps_rsize_getter, ps_rmem_frac_getter, - ps_proc_susp_count_getter): Use PSTAT_TASK_BASIC, not PSTAT_INFO. - (ps_get_vsize, ps_get_rsize, ps_get_rmem_frac, ps_get_proc_susp_count): - Use proc_stat_task_basic_info, not proc_stat_info. - (ps_cur_priority_getter, ps_base_priority_getter, - ps_max_priority_getter): Use PSTAT_THREAD_SCHED, not PSTAT_THREAD_INFO. - (ps_usr_time_getter, ps_sys_time_getter, ps_tot_time_getter, - ps_cpu_frac_getter, ps_sleep_getter): - Use PSTAT_THREAD_BASIC, not PSTAT_THREAD_INFO. - - * filters.c (ps_own_filter): Use PSTAT_PROC_INFO, not PSTAT_INFO. - (ps_own_p): Use proc_stat_proc_info, not proc_stat_info. - - * ps.h (proc_stat_num_threads): Use the num_threads field. - (proc_stat_thread_sched_info, proc_stat_thread_basic_info): Don't - take the address, now that the fields used are pointers themselves. - (proc_stat_thread_rpc, proc_stat_task_basic_info): New macros. - (proc_stat_proc_info): Renamed from proc_stat_info. - (PSTAT_PROC_INFO): Renamed from PSTAT_INFO. - (PSTAT_TASK_BASIC, PSTAT_THREAD_BASIC, PSTAT_THREAD_SCHED, - PSTAT_THREAD_RPC): New macros. - (struct proc_stat): info & info_len --> proc_info & proc_info_len. - Add the num_threads, task_basic_info, and thread_rpc fields. - thread_basic_info & thread_sched_info are now pointers. - -Mon Oct 9 14:57:48 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> - - * Makefile: Specify shared library dependencies. - -Fri Aug 25 18:55:51 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * ps.h (ps_std_fmt_specs): Declare extern. - -Wed Aug 23 15:04:51 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * Makefile (OBJS): Just put the migs stubs directly in here. - (REMHDRS, MIGSTUBS): Removed. - -Sat Aug 19 11:49:06 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * procstat.c (proc_stat_set_flags): Actually set the P_STOP bit. - -Fri Aug 18 16:43:41 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * ps.h (PSTAT_STATE_*): All proc state flags reorganized and - renamed to PSTAT_STATE_P_* for process-global bits, and - PSTAT_STATE_T_* for per-thread bits. - * procstat.c (proc_stat_state_tags): Reordered to reflect the new - ordering of the state bits. - (thread_state, proc_stat_set_flags): Use the new state bits. - * spec.c (ps_emit_state): Rearrange things to reflect the new - state bits. - (state_shadows): New variable. - (ps_emit_state): Use the state_shadows list to turn off some states. - * filters.c (ps_not_sess_leader_p, ps_unorphaned_p, ps_parent_p): - Use the new state bits. - -Sat Jul 8 13:34:20 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * tty.c (ps_tty_short_name): That assignment around which extra - parents were put was actually supposed to be a test! Make it so... - -Thu Jul 6 22:25:20 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * tty.c (ps_tty_short_name): Put extra parens around assignment - inside if test. - -Thu Jul 6 15:36:04 1995 Miles Bader <miles@geech.gnu.ai.mit.edu> - - * Makefile: Remove include dependencies. - -Thu Jun 29 15:29:05 1995 Miles Bader <miles@geech.gnu.ai.mit.edu> - - * Makefile (REMHDRS): New variable. - ($(OBJS)): depend on ../libihash/ihash.h. - * ps.h: Include hurd/ihash.h instead of ihash.h. - -Wed May 31 13:09:04 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * fmt.c (ps_fmt_create): Don't mutate the format spec name in the - fmt_spec list we're passed just to get correctly capitalized - titles. Instead, do things correctly by making enough room to - store our own version of the title string, which we can do with - what we please. - - * ps.h (ps_own_filter, ps_not_sess_leader_filter, ps_ctty_filter, - ps_unorphaned_filter, ps_parent_filter): Declare these as extern - so that the linker will bring in the initialized version (it's not - doing so otherwise may be a bug). - -Thu May 4 20:01:32 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * procstat.c (proc_stat_set_flags): If a msg port call times out, - disable use of that msg port. - * Makefile (MIGSTUBS, term-MIGUFLAGS, msg-MIGUFLAGS): Compile our - own msg & term user stubs to add msg timeouts. - -Wed May 3 11:32:52 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * proclist.c (proc_stat_list_for_each): New function for iterating - over proc_stat_lists. - (proc_stat_list_spec_nominal): New function for deciding if a - particular spec is always nominal. - * ps.h: Add entries for proc_stat_list_for_each and - proc_stat_list_spec_nominal. - - * fmt.c (ps_fmt_squash, ps_fmt_squash_flags): Recalculate the set - of ps flags needed by the fmt in ps_fmt_squash. - -Tue May 2 12:25:57 1995 Miles Bader <miles@geech.gnu.ai.mit.edu> - - * ps.h (ps_fmt_squash): Rename to ps_fmt_squash_flags. - * fmt.c (ps_fmt_squash, ps_fmt_squash_flags): Rename ps_fmt_squash to - ps_fmt_squash_flags, moving most of the guts into a new more - general ps_fmt_squash, which is usable for other things than flags. - - * ps.h (struct ps_fmt_spec): Add the nominal_fn field, which will - be used to decide whether values are `unexciting'. - * spec.c (ps_std_fmt_specs): Add values for the nominal_fn field. - (ps_nominal_zint, ps_nominal_user, ps_nominal_pri, ps_nominal_nth): - Possible nominal funs. - - * ps.h (struct proc_stat): Add the suspend_count field, along with - PSTAT_SUSPEND_COUNT, and proc_stat_suspend_count(ps). - * procstat.c (proc_stat_set_flags, add_preconditions): Add support for - the suspend_count field. - * spec.c (ps_std_fmt_specs): Add the Susp (task/thread suspend count), - PSusp (task suspend count), and TSusp (thread suspend count) output - specs. - - * procstat.c (add_preconditions): A new function that calculates inter- - flag dependencies; code moved here from from proc_stat_set_flags. - (should_suppress_msgport): A new function that returns true when - there's some condition indicating that we shouldn't use a process's msg - port. - (proc_stat_set_flags): Avoid using a process's msg port when it may be - unusable. - - * ps.h (PSTAT_STATE_FORKED): A new flag to replace PSTAT_STATE_EXECED; - we want to the flags to mark exceptional conditions, and this is rarer. - * procstat.c (proc_stat_set_flags): Set PSTAT_STATE_FORKED instead of - PSTAT_STATE_EXECED. - (proc_stat_state_tags): Change the user state letter to "f" from "e". - -Sun Apr 23 15:38:39 1995 Miles Bader <miles@geech.gnu.ai.mit.edu> - - * Makefile: Set libname. - -Fri Apr 7 11:12:15 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * proclist.c (proc_stat_list_sort1): Always keep threads after their - process when sorting! - - * spec.c (ps_emit_state): If a process is marked as stopped, then - don't mention sleeping or idle threads' status (as that's presumably - the signal thread). - - * ps.h: Add decls for proc_stat_list_add_pgrp & ps_tty_short_name. - - * proclist.c (proc_stat_list_add_all, proc_stat_list_add_login_coll, - proc_stat_list_add_session): Move most of the functionality into - proc_stat_list_add_[id_]fn_pids. - (proc_stat_list_add_pgrp): New function, adds pids for a pgrp. - - * tty.c (ps_tty_short_name): New function; functionality used to be in - spec.c - (ps_tty_create, ps_tty_free): Add short_name fields. - * spec.c (ps_emit_tty_name): Move guts into into ps_tty_short_name. - - * Just about everything: tighten up types used (i.e., don't use int - for everything). - -Wed Apr 5 22:42:24 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * spec.c (ps_std_fmt_specs): Add the `Arg0' spec, which is the - same as `Args', but only prints the first one. Change MsgsIn - and MsgsOut to MsgIn and MsgOut. - -Tue Apr 4 20:13:55 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * ps.h: Add the PSTAT_NO_MSGPORT flag, which when set disables any - use of the process's message port. - * procstat.c (proc_stat_set_flags): If PSTAT_NO_MSGPORT is set, - don't use the msg port. - -Wed Mar 29 15:36:43 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu> - - * procstat.c (proc_stat_set_flags): Don't barf if a process has - zero threads. - -Tue Mar 28 10:33:08 1995 Miles Bader <miles@duality.gnu.ai.mit.edu> - - * ps.h: Add the exec_flags field to the proc_stat structure, and - add PSTAT_STATE_TRACED. - * procstat.c (proc_stat_set_flags): Add support for the exec_flags - field, and make the state bits calculation use that to support the - PSTAT_STATE_TRACED bit. - -Mon Mar 20 20:51:51 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu> - - * user.c (ps_user_passwd) [COUNT, COPY]: Use `if' statement. - * spec.c (ps_emit_num_blocks): Use int format for int arg. - (sprint_frac_value): Likewise. - * write.c (ps_write_int_field): Likewise. - * host.c (ps_host_basic_info): Cast third arg to host_info. - (ps_host_sched_info): Likewise. - (ps_host_load_info): Likewise. - - * filters.c: Include <unistd.h>. - * context.c: Include <hurd/term.h>. - * tty.c: Likewise. - * spec.c: Include <string.h>. - * procstat.c: Likewise. - - * host.c: Don't include "pshost.h". - * spec.c: Likewise. - - * ps.h: Include <errno.h>. - (ps_get_host, ps_host_basic_info, ps_host_sched_info, - ps_host_load_info): Copied here from pshost.h. - (ps_write_string, ps_write_spaces, ps_write_padding, - ps_write_field, ps_write_int_field): Copied here from pswrite.h - * pshost.h, pswrite.h: Delete files. - - * New ChangeLog, moved into canonical directory structure. - Old ChangeLog is in .../hurd/utils/ps.ChangeLog. - diff --git a/libps/Makefile b/libps/Makefile index 8c8a22fc..ec35c852 100644 --- a/libps/Makefile +++ b/libps/Makefile @@ -1,6 +1,6 @@ # Makefile for libps -# -# Copyright (C) 1995, 1996 Free Software Foundation +# +# Copyright (C) 1995,96,99,2002 Free Software Foundation, Inc. # Written by Michael I. Bushnell. # # This file is part of the GNU Hurd. @@ -26,9 +26,10 @@ libname = libps SRCS = context.c filters.c fmt.c host.c proclist.c procstat.c spec.c \ tty.c user.c write.c LCLHDRS=ps.h common.h -installhdrs=$(LCLHDRS) +installhdrs = ps.h installhdrsubdir = . +HURDLIBS=ihash shouldbeinlibc OBJS = $(SRCS:.c=.o) msgUser.o termUser.o msg-MIGUFLAGS = -D'MSG_IMPORTS=waittime 1000;' -DUSERPREFIX=ps_ @@ -38,5 +39,3 @@ ps_%.h: %_U.h sed 's/_$*_user_/_ps_$*_user_/g' $< > $@ include ../Makeconf - -libps.so: ../libihash/libihash.so diff --git a/libps/common.h b/libps/common.h index 67d89bfd..6c44641e 100644 --- a/libps/common.h +++ b/libps/common.h @@ -1,6 +1,6 @@ /* Handy common functions for things in libps. - Copyright (C) 1995 Free Software Foundation, Inc. + Copyright (C) 1995, 1999 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.ai.mit.edu> @@ -18,6 +18,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <sys/mman.h> + #define ABS(x) ((x) < 0 ? -(x) : (x)) #define MAX(x, y) ((x) < (y) ? (y) : (x)) #define MIN(x, y) ((x) < (y) ? (x) : (y)) @@ -32,7 +34,7 @@ ((type *)realloc((void *)(old),(unsigned)(sizeof(type)*(len)))) #define FREE(x) (void)free((void *)x) -#define VMFREE(x, len) vm_deallocate(mach_task_self(), (vm_address_t)x, len) +#define VMFREE(x, len) munmap((caddr_t)x, len) #ifndef FALSE #define FALSE 0 diff --git a/libps/context.c b/libps/context.c index 4c5aeaf0..3082d83b 100644 --- a/libps/context.c +++ b/libps/context.c @@ -1,8 +1,8 @@ /* The ps_context type, for per-procserver and somewhat global state. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995,96,99,2000,02 Free Software Foundation, Inc. - Written by Miles Bader <miles@gnu.ai.mit.edu> + Written by Miles Bader <miles@gnu.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -34,39 +34,23 @@ error_t ps_context_create (process_t server, struct ps_context **pc) { - error_t err_procs, err_ttys, err_ttys_by_cttyid, err_users; - *pc = NEW (struct ps_context); if (*pc == NULL) return ENOMEM; (*pc)->server = server; (*pc)->user_hooks = 0; - err_procs = ihash_create (&(*pc)->procs); - err_ttys = ihash_create (&(*pc)->ttys); - err_ttys_by_cttyid = ihash_create (&(*pc)->ttys_by_cttyid); - err_users = ihash_create (&(*pc)->users); - - if (err_procs || err_ttys || err_ttys_by_cttyid) - /* Some allocation error occurred, backout any successful ones and fail. */ - { - if (!err_procs) ihash_free ((*pc)->procs); - if (!err_users) ihash_free ((*pc)->users); - if (!err_ttys) ihash_free ((*pc)->ttys); - if (!err_ttys_by_cttyid) ihash_free ((*pc)->ttys_by_cttyid); - free (*pc); - return ENOMEM; - } - - ihash_set_cleanup ((*pc)->procs, - (void (*)(void *, void *arg))_proc_stat_free, - NULL); - ihash_set_cleanup ((*pc)->ttys, - (void (*)(void *, void *arg))ps_tty_free, - NULL); - ihash_set_cleanup ((*pc)->users, - (void (*)(void *, void *arg))ps_user_free, - NULL); + hurd_ihash_init (&(*pc)->procs, HURD_IHASH_NO_LOCP); + hurd_ihash_init (&(*pc)->ttys, HURD_IHASH_NO_LOCP); + hurd_ihash_init (&(*pc)->ttys_by_cttyid, HURD_IHASH_NO_LOCP); + hurd_ihash_init (&(*pc)->users, HURD_IHASH_NO_LOCP); + + hurd_ihash_set_cleanup (&(*pc)->procs, + (hurd_ihash_cleanup_t) _proc_stat_free, NULL); + hurd_ihash_set_cleanup (&(*pc)->ttys, + (hurd_ihash_cleanup_t) ps_tty_free, NULL); + hurd_ihash_set_cleanup (&(*pc)->users, + (hurd_ihash_cleanup_t) ps_user_free, NULL); return 0; } @@ -75,10 +59,13 @@ ps_context_create (process_t server, struct ps_context **pc) void ps_context_free (struct ps_context *pc) { - ihash_free (pc->procs); - ihash_free (pc->procs); + hurd_ihash_destroy (&pc->procs); + hurd_ihash_destroy (&pc->ttys); + hurd_ihash_destroy (&pc->ttys_by_cttyid); + hurd_ihash_destroy (&pc->users); free (pc); } + /* ---------------------------------------------------------------- */ @@ -87,15 +74,16 @@ ps_context_free (struct ps_context *pc) (CREATE should return either an error-code or 0 if no error occurs), and cache it in HT. */ static error_t -lookup (int id, ihash_t ht, error_t (*create)(int id, void **), void **value) +lookup (int id, hurd_ihash_t ht, error_t (*create)(int id, void **), + void **value) { - *value = ihash_find (ht, id); + *value = hurd_ihash_find (ht, id); if (*value == NULL) { error_t err = create (id, value); if (err) return err; - ihash_add (ht, id, *value, NULL); + hurd_ihash_add (ht, id, *value); } return 0; } @@ -109,7 +97,7 @@ ps_context_find_proc_stat (struct ps_context *pc, pid_t pid, struct proc_stat ** { return _proc_stat_create (pid, pc, (struct proc_stat **)value); } - return lookup (pid, pc->procs, create, (void **)ps); + return lookup (pid, &pc->procs, create, (void **)ps); } /* Find a ps_tty for the terminal referred to by the port TTY_PORT, and @@ -119,9 +107,9 @@ ps_context_find_tty (struct ps_context *pc, mach_port_t tty_port, struct ps_tty **tty) { return lookup (tty_port, - pc->ttys, - (error_t (*)(int id, void **result))ps_tty_create, - (void **)tty); + &pc->ttys, + (error_t (*)(int id, void **result))ps_tty_create, + (void **)tty); } /* Find a ps_tty for the terminal referred to by the ctty id port @@ -140,7 +128,7 @@ ps_context_find_tty_by_cttyid (struct ps_context *pc, mach_port_t cttyid_port, } else { - int tty_port; + mach_port_t tty_port; error_t err = termctty_open_terminal (cttyid_port, 0, &tty_port); if (err) return err; @@ -149,7 +137,7 @@ ps_context_find_tty_by_cttyid (struct ps_context *pc, mach_port_t cttyid_port, } } - return lookup (cttyid_port, pc->ttys, create, (void **)tty); + return lookup (cttyid_port, &pc->ttys_by_cttyid, create, (void **)tty); } /* Find a ps_user for the user referred to by UID, and return it in U. */ @@ -157,7 +145,7 @@ error_t ps_context_find_user (struct ps_context *pc, uid_t uid, struct ps_user **u) { return lookup (uid, - pc->users, - (error_t (*)(int id, void **result))ps_user_create, - (void **)u); + &pc->users, + (error_t (*)(int id, void **result))ps_user_create, + (void **) u); } diff --git a/libps/filters.c b/libps/filters.c index 4fac0390..6663e61e 100644 --- a/libps/filters.c +++ b/libps/filters.c @@ -38,7 +38,7 @@ ps_own_p (struct proc_stat *ps) own_uid = getuid (); return own_uid >= 0 && own_uid == proc_stat_owner_uid (ps); } -struct ps_filter ps_own_filter = +const struct ps_filter ps_own_filter = {"own", PSTAT_OWNER_UID, ps_own_p}; static int @@ -47,7 +47,7 @@ ps_not_leader_p (struct proc_stat *ps) return !(proc_stat_state (ps) & (PSTAT_STATE_P_SESSLDR | PSTAT_STATE_P_LOGINLDR)); } -struct ps_filter ps_not_leader_filter = +const struct ps_filter ps_not_leader_filter = {"not-sess-leader", PSTAT_STATE, ps_not_leader_p}; static int @@ -58,7 +58,7 @@ ps_unorphaned_p (struct proc_stat *ps) !(state & PSTAT_STATE_P_ORPHAN) || (state & (PSTAT_STATE_P_SESSLDR | PSTAT_STATE_P_LOGINLDR)); } -struct ps_filter ps_unorphaned_filter = +const struct ps_filter ps_unorphaned_filter = {"unorphaned", PSTAT_STATE, ps_unorphaned_p}; static int @@ -66,7 +66,7 @@ ps_ctty_p (struct proc_stat *ps) { return proc_stat_cttyid (ps) != MACH_PORT_NULL; } -struct ps_filter ps_ctty_filter = +const struct ps_filter ps_ctty_filter = {"ctty", PSTAT_CTTYID, ps_ctty_p}; static int @@ -74,7 +74,7 @@ ps_parent_p (struct proc_stat *ps) { return !(proc_stat_state (ps) & PSTAT_STATE_P_NOPARENT); } -struct ps_filter ps_parent_filter = +const struct ps_filter ps_parent_filter = {"parent", PSTAT_STATE, ps_parent_p}; static int @@ -87,5 +87,5 @@ ps_alive_p (struct proc_stat *ps) proc_stat_set_flags (ps, test_flag); return proc_stat_has (ps, test_flag); } -struct ps_filter ps_alive_filter = +const struct ps_filter ps_alive_filter = {"alive", 0, ps_alive_p}; diff --git a/libps/fmt.c b/libps/fmt.c index 8fed27a3..0465555d 100644 --- a/libps/fmt.c +++ b/libps/fmt.c @@ -1,7 +1,7 @@ /* Implements the ps_fmt type, which describes how to output a user-readable version of a proc_stat. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.ai.mit.edu> @@ -194,7 +194,9 @@ _fmt_create (char *src, int posix, struct ps_fmt_specs *fmt_specs, while (*src != '\0' && *src != stop) src++; } - *src++ = '\0'; /* NUL terminhate NAME. */ + + if (*src) + *src++ = '\0'; /* NUL terminate NAME. */ } else /* A gnu-style field spec: `NAME' or `NAME:TITLE'. */ @@ -240,11 +242,13 @@ _fmt_create (char *src, int posix, struct ps_fmt_specs *fmt_specs, } if (! field->title) - /* No explicit title specified in the fmt string. */ - if (field->spec->title) - field->title = field->spec->title; /* But the spec has one. */ - else - field->title = field->spec->name; /* Just use the field name. */ + { + /* No explicit title specified in the fmt string. */ + if (field->spec->title) + field->title = field->spec->title; /* But the spec has one. */ + else + field->title = field->spec->name; /* Just use field name. */ + } /* Add FIELD's required pstat_flags to FMT's set */ needs |= ps_getter_needs (ps_fmt_spec_getter (field->spec)); @@ -255,7 +259,7 @@ _fmt_create (char *src, int posix, struct ps_fmt_specs *fmt_specs, field->precision = field->spec->precision; field->flags = (field->spec->flags & ~clr_flags) ^ inv_flags; - + if (quoted_name && *src == '}') /* Skip optional trailing `}' after the spec name. */ src++; @@ -288,7 +292,8 @@ _fmt_create (char *src, int posix, struct ps_fmt_specs *fmt_specs, new_fmt->fields = fields; new_fmt->num_fields = field - fields; new_fmt->needs = needs; - new_fmt->inval = posix ? "-" : 0; + new_fmt->inapp = posix ? "-" : 0; + new_fmt->error = "?"; *fmt = new_fmt; @@ -323,7 +328,7 @@ ps_fmt_creation_error (char *src, int posix, struct ps_fmt_specs *fmt_specs, } /* Free FMT, and any resources it consumes. */ -void +void ps_fmt_free (struct ps_fmt *fmt) { FREE (fmt->src); @@ -358,14 +363,15 @@ ps_fmt_clone (struct ps_fmt *fmt, struct ps_fmt **copy) new->num_fields = fmt->num_fields; new->src = src; new->src_len = fmt->src_len; - new->inval = fmt->inval; + new->inapp = fmt->inapp; + new->error = fmt->error; *copy = new; return 0; } -/* Write an appropiate header line for FMT, containing the titles of all its - fields appropiately aligned with where the values would be printed, to +/* Write an appropriate header line for FMT, containing the titles of all its + fields appropriately 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. */ @@ -418,7 +424,8 @@ ps_fmt_write_proc_stat (struct ps_fmt *fmt, struct proc_stat *ps, struct ps_stre error_t err = 0; struct ps_fmt_field *field = ps_fmt_fields (fmt); int nfields = ps_fmt_num_fields (fmt); - int have = proc_stat_flags (ps); + ps_flags_t have = ps->flags; + ps_flags_t inapp = ps->inapp; while (nfields-- > 0 && !err) { @@ -431,16 +438,20 @@ ps_fmt_write_proc_stat (struct ps_fmt *fmt, struct proc_stat *ps, struct ps_stre if (spec != NULL && !err) { - int need = ps_getter_needs (ps_fmt_spec_getter (spec)); + ps_flags_t need = ps_getter_needs (ps_fmt_spec_getter (spec)); /* do we have the resources to print this field? */ if ((need & have) == need) /* Yup */ err = (*spec->output_fn) (ps, field, stream); + else if (need & ~have & inapp) + /* This field is inappropriate for PS. */ + err = + ps_stream_write_field (stream, fmt->inapp ?: "", field->width); else - /* Something to display in invalid fields. */ - err = ps_stream_write_field (stream, fmt->inval ?: "", - ps_fmt_field_width (field)); + /* This field is appropriate, but couldn't be fetched. */ + err = + ps_stream_write_field (stream, fmt->error ?: "", field->width); } field++; @@ -450,9 +461,9 @@ ps_fmt_write_proc_stat (struct ps_fmt *fmt, struct proc_stat *ps, struct ps_stre } /* Remove those fields from FMT for which the function FN, when called on the - field, returns true. Appropiate inter-field characters are also removed: + field, returns true. Appropriate 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. */ + *preceding* deleted fields *not* at the beginning. */ void ps_fmt_squash (struct ps_fmt *fmt, int (*fn)(struct ps_fmt_field *field)) { @@ -468,7 +479,7 @@ ps_fmt_squash (struct ps_fmt *fmt, int (*fn)(struct ps_fmt_field *field)) { /* Save the old prefix, in case we're deleting the first field, and need to prepend it to the next field. */ - const char *beg_pfx = field->pfx; + const char *beg_pfx = field->pfx; int beg_pfx_len = field->pfx_len; nfields--; @@ -519,7 +530,8 @@ ps_fmt_squash (struct ps_fmt *fmt, int (*fn)(struct ps_fmt_field *field)) else /* don't squash this field, just move to the next one */ { - need |= ps_getter_needs (ps_fmt_spec_getter (field->spec)); + if (field->spec) + need |= ps_getter_needs (field->spec->getter); field++; } @@ -528,8 +540,8 @@ 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 + Appropriate inter-field characters are also removed: those *following* + deleted fields at the beginning of the fmt, and those *preceding* deleted fields *not* at the beginning. */ void ps_fmt_squash_flags (struct ps_fmt *fmt, ps_flags_t flags) diff --git a/libps/host.c b/libps/host.c index 26be9a31..9a46e008 100644 --- a/libps/host.c +++ b/libps/host.c @@ -1,8 +1,8 @@ /* Routines to get global host info. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995,96,2001,02 Free Software Foundation, Inc. - Written by Miles Bader <miles@gnu.ai.mit.edu> + Written by Miles Bader <miles@gnu.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -29,78 +29,80 @@ /* ---------------------------------------------------------------- */ /* - The Basic & Sched info types are pretty static, so we cache them, but load - info is dynamic so we don't cache that. + The Basic & Sched info types are pretty must static so we cache them. + However, as load info is dynamic, we do not cache it. See <mach/host_info.h> for information on the data types these routines return. */ /* Return the current host port. */ -host_t +mach_port_t ps_get_host () { - static host_t host = MACH_PORT_NULL; + static mach_port_t host = MACH_PORT_NULL; if (host == MACH_PORT_NULL) host = mach_host_self (); return host; } -/* Return a pointer to basic info about the current host in 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. */ +/* Return a pointer to the basic info about the current host in 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 is + returned. */ error_t ps_host_basic_info (host_basic_info_t *info) { - int initialized = FALSE; + static int initialized; static host_basic_info_data_t buf; if (!initialized) { - int size = sizeof (buf); - error_t err = host_info (ps_get_host (), HOST_BASIC_INFO, + size_t size = sizeof (buf); + error_t err = host_info (ps_get_host (), HOST_BASIC_INFO, (host_info_t) &buf, &size); if (err) return err; - initialized = TRUE; + initialized = 1; } *info = &buf; return 0; } -/* Return a pointer to scheduling info about the current host in 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. */ +/* Return a pointer to the scheduling info about the current host in 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 is + returned. */ error_t ps_host_sched_info (host_sched_info_t *info) { - int initialized = FALSE; + static int initialized; static host_sched_info_data_t buf; if (!initialized) { - int size = sizeof (buf); - error_t err = host_info (ps_get_host (), HOST_SCHED_INFO, + size_t size = sizeof (buf); + error_t err = host_info (ps_get_host (), HOST_SCHED_INFO, (host_info_t) &buf, &size); if (err) return err; - initialized = TRUE; + initialized = 1; } *info = &buf; return 0; } -/* Return a pointer to load info about the current host in 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. */ +/* Return a pointer to the load info about the current host in INFO. Since + this is global information, we just use a static buffer (if someone desires + to keep old load info, they should copy the returned buffer). If a system + error occurs, the error code is returned, otherwise 0 is returned. */ error_t ps_host_load_info (host_load_info_t *info) { static host_load_info_data_t buf; - int size = sizeof (buf); + size_t size = sizeof (buf); error_t err = host_info (ps_get_host (), HOST_LOAD_INFO, (host_info_t) &buf, &size); diff --git a/libps/proclist.c b/libps/proclist.c index 2dfcfe7d..9a4d6ed5 100644 --- a/libps/proclist.c +++ b/libps/proclist.c @@ -1,6 +1,6 @@ /* The type proc_stat_list_t, which holds lists of proc_stats. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995,96,2002 Free Software Foundation, Inc. Written by Miles Bader <miles@gnu.ai.mit.edu> @@ -46,7 +46,7 @@ proc_stat_list_create (struct ps_context *context, struct proc_stat_list **pp) } /* Free PP, and any resources it consumes. */ -void +void proc_stat_list_free (struct proc_stat_list *pp) { proc_stat_list_remove_threads (pp); @@ -267,12 +267,12 @@ static error_t proc_stat_list_add_fn_pids (struct proc_stat_list *pp, kern_return_t (*fetch_fn)(process_t proc, pid_t **pids, - unsigned *num_pids), - struct proc_stat ***proc_stats, unsigned *num_procs) + size_t *num_pids), + struct proc_stat ***proc_stats, size_t *num_procs) { error_t err; pid_t pid_array[STATICPIDS], *pids = pid_array; - unsigned num_pids = STATICPIDS; + size_t num_pids = STATICPIDS; err = (*fetch_fn)(ps_context_server (pp->context), &pids, &num_pids); if (err) @@ -298,10 +298,11 @@ proc_stat_list_add_id_fn_pids (struct proc_stat_list *pp, unsigned id, kern_return_t (*fetch_fn)(process_t proc, pid_t id, pid_t **pids, - unsigned *num_pids), - struct proc_stat ***proc_stats, unsigned *num_procs) + size_t *num_pids), + struct proc_stat ***proc_stats, + size_t *num_procs) { - error_t id_fetch_fn (process_t proc, pid_t **pids, unsigned *num_pids) + error_t id_fetch_fn (process_t proc, pid_t **pids, size_t *num_pids) { return (*fetch_fn)(proc, id, pids, num_pids); } @@ -316,7 +317,7 @@ proc_stat_list_add_id_fn_pids (struct proc_stat_list *pp, unsigned id, returned in them. */ error_t proc_stat_list_add_all (struct proc_stat_list *pp, - struct proc_stat ***proc_stats, unsigned *num_procs) + struct proc_stat ***proc_stats, size_t *num_procs) { return proc_stat_list_add_fn_pids (pp, proc_getallpids, proc_stats, num_procs); @@ -328,7 +329,8 @@ proc_stat_list_add_all (struct proc_stat_list *pp, 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) + struct proc_stat ***proc_stats, + size_t *num_procs) { return proc_stat_list_add_id_fn_pids (pp, login_id, proc_getloginpids, @@ -341,7 +343,8 @@ proc_stat_list_add_login_coll (struct proc_stat_list *pp, pid_t login_id, 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) + struct proc_stat ***proc_stats, + size_t *num_procs) { return proc_stat_list_add_id_fn_pids (pp, session_id, proc_getsessionpids, @@ -354,7 +357,7 @@ proc_stat_list_add_session (struct proc_stat_list *pp, pid_t session_id, 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) + struct proc_stat ***proc_stats, size_t *num_procs) { return proc_stat_list_add_id_fn_pids (pp, pgrp, proc_getpgrppids, diff --git a/libps/procstat.c b/libps/procstat.c index 0938073e..ba923780 100644 --- a/libps/procstat.c +++ b/libps/procstat.c @@ -1,8 +1,7 @@ /* The proc_stat type, which holds information about a hurd process. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> + Copyright (C) 1995,96,97,98,99,2002 Free Software Foundation, Inc. + Written by Miles Bader <miles@gnu.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -43,7 +42,7 @@ typedef threadinfo_data_t *threadinfo_t; /* Return the PSTAT_STATE_ bits describing the state of an individual thread, from that thread's thread_basic_info_t struct */ -static int +static int thread_state (thread_basic_info_t bi) { int state = 0; @@ -79,19 +78,26 @@ thread_state (thread_basic_info_t bi) /* ---------------------------------------------------------------- */ -/* The set of PSTAT_ flags that we get using proc_getprocinfo. */ -#define PSTAT_PROCINFO \ - (PSTAT_PROC_INFO | PSTAT_TASK_BASIC | PSTAT_NUM_THREADS \ - | PSTAT_THREAD_BASIC | PSTAT_THREAD_SCHED | PSTAT_THREAD_WAIT \ - | PSTAT_THREAD_WAITS) -/* The set of things we get from procinfo that's thread dependent. */ +/* The set of things we get from procinfo that are per-thread. */ #define PSTAT_PROCINFO_THREAD \ - (PSTAT_NUM_THREADS |PSTAT_THREAD_BASIC |PSTAT_THREAD_SCHED \ - | PSTAT_THREAD_WAIT | PSTAT_THREAD_WAITS) + (PSTAT_THREAD_BASIC | PSTAT_THREAD_SCHED | PSTAT_THREAD_WAIT) + +/* The set of things we get from procinfo that are per-task, and thread dependent. */ +#define PSTAT_PROCINFO_TASK_THREAD_DEP \ + (PSTAT_PROCINFO_THREAD | PSTAT_NUM_THREADS | PSTAT_THREAD_WAITS) + +/* The set of things we get from procinfo that are per-task (note that this + includes thread fields, because tasks use them for thread summaries). */ +#define PSTAT_PROCINFO_TASK \ + (PSTAT_PROCINFO_TASK_THREAD_DEP | PSTAT_PROC_INFO \ + | PSTAT_TASK_BASIC | PSTAT_TASK_EVENTS) + +/* The set of PSTAT_ flags that we get using proc_getprocinfo. */ +#define PSTAT_PROCINFO PSTAT_PROCINFO_TASK /* The set of things in PSTAT_PROCINFO that we will not attempt to refetch on subsequent getprocinfo calls. */ -#define PSTAT_PROCINFO_MERGE PSTAT_TASK_BASIC +#define PSTAT_PROCINFO_MERGE (PSTAT_TASK_BASIC | PSTAT_TASK_EVENTS) #define PSTAT_PROCINFO_REFETCH (PSTAT_PROCINFO - PSTAT_PROCINFO_MERGE) /* Fetches process information from the set in PSTAT_PROCINFO, returning it @@ -103,18 +109,22 @@ fetch_procinfo (process_t server, pid_t pid, struct procinfo **pi, size_t *pi_size, char **waits, size_t *waits_len) { + static const struct { ps_flags_t ps_flag; int pi_flags; } map[] = + { + { PSTAT_TASK_BASIC, PI_FETCH_TASKINFO }, + { PSTAT_TASK_EVENTS, PI_FETCH_TASKEVENTS }, + { PSTAT_NUM_THREADS, PI_FETCH_THREADS }, + { PSTAT_THREAD_BASIC, PI_FETCH_THREAD_BASIC | PI_FETCH_THREADS }, + { PSTAT_THREAD_SCHED, PI_FETCH_THREAD_SCHED | PI_FETCH_THREADS }, + { PSTAT_THREAD_WAITS, PI_FETCH_THREAD_WAITS | PI_FETCH_THREADS }, + { 0, } + }; int pi_flags = 0; + int i; - if ((need & PSTAT_TASK_BASIC) && !(*have & PSTAT_TASK_BASIC)) - pi_flags |= PI_FETCH_TASKINFO; - if ((need & PSTAT_NUM_THREADS) && !(*have & PSTAT_NUM_THREADS)) - pi_flags |= PI_FETCH_THREADS; - if ((need & PSTAT_THREAD_BASIC) && !(*have & PSTAT_THREAD_BASIC)) - pi_flags |= PI_FETCH_THREAD_BASIC | PI_FETCH_THREADS; - if ((need & PSTAT_THREAD_SCHED) && !(*have & PSTAT_THREAD_SCHED)) - pi_flags |= PI_FETCH_THREAD_SCHED | PI_FETCH_THREADS; - if ((need & PSTAT_THREAD_WAITS) && !(*have & PSTAT_THREAD_WAITS)) - pi_flags |= PI_FETCH_THREAD_WAITS | PI_FETCH_THREADS; + for (i = 0; map[i].ps_flag; i++) + if ((need & map[i].ps_flag) && !(*have & map[i].ps_flag)) + pi_flags |= map[i].pi_flags; if (pi_flags || ((need & PSTAT_PROC_INFO) && !(*have & PSTAT_PROC_INFO))) { @@ -129,16 +139,9 @@ fetch_procinfo (process_t server, pid_t pid, /* Update *HAVE to reflect what we've successfully fetched. */ { *have |= PSTAT_PROC_INFO; - if (pi_flags & PI_FETCH_TASKINFO) - *have |= PSTAT_TASK_BASIC; - if (pi_flags & PI_FETCH_THREADS) - *have |= PSTAT_NUM_THREADS; - if (pi_flags & PI_FETCH_THREAD_BASIC) - *have |= PSTAT_THREAD_BASIC; - if (pi_flags & PI_FETCH_THREAD_SCHED) - *have |= PSTAT_THREAD_SCHED; - if (pi_flags & PI_FETCH_THREAD_WAITS) - *have |= PSTAT_THREAD_WAITS; + for (i = 0; map[i].ps_flag; i++) + if ((pi_flags & map[i].pi_flags) == map[i].pi_flags) + *have |= map[i].ps_flag; } return err; } @@ -150,7 +153,7 @@ fetch_procinfo (process_t server, pid_t pid, vm_alloced memory for the procinfo structure returned by getprocinfo. Here we just give enough for four threads. */ #define PROCINFO_MALLOC_SIZE \ - (sizeof (struct procinfo) + 4 * sizeof (threadinfo_data_t)) + (sizeof (struct procinfo) + 4 * sizeof (threadinfo_data_t)) #define WAITS_MALLOC_SIZE 128 @@ -229,8 +232,7 @@ merge_procinfo (struct proc_stat *ps, ps_flags_t need, ps_flags_t have) /* We got new memory vm_alloced by the getprocinfo, discard the old. */ { if (ps->proc_info_vm_alloced) - vm_deallocate (mach_task_self (), - (vm_address_t)ps->proc_info, ps->proc_info_size); + munmap (ps->proc_info, ps->proc_info_size); else free (ps->proc_info); ps->proc_info = new_pi; @@ -248,8 +250,7 @@ merge_procinfo (struct proc_stat *ps, ps_flags_t need, ps_flags_t have) /* We got new memory vm_alloced by the getprocinfo, discard the old. */ { if (ps->thread_waits_vm_alloced) - vm_deallocate (mach_task_self (), - (vm_address_t)ps->thread_waits, ps->thread_waits_len); + munmap (ps->thread_waits, ps->thread_waits_len); else free (ps->thread_waits); ps->thread_waits = new_waits; @@ -266,7 +267,7 @@ merge_procinfo (struct proc_stat *ps, ps_flags_t need, ps_flags_t have) /* Returns FLAGS augmented with any other flags that are necessary preconditions to setting them. */ -static ps_flags_t +static ps_flags_t add_preconditions (ps_flags_t flags, struct ps_context *context) { /* Implement any inter-flag dependencies: if the new flags in FLAGS depend on @@ -287,7 +288,7 @@ add_preconditions (ps_flags_t flags, struct ps_context *context) flags |= PSTAT_PROC_INFO; if (flags & PSTAT_SUSPEND_COUNT) /* We just request the resources require for both the thread and task - versions, as the extraneous info won't be possible to aquire anyway. */ + versions, as the extraneous info won't be possible to acquire anyway. */ flags |= PSTAT_TASK_BASIC | PSTAT_THREAD_BASIC; if (flags & (PSTAT_CTTYID | PSTAT_CWDIR | PSTAT_AUTH | PSTAT_UMASK) && !(flags & PSTAT_NO_MSGPORT)) @@ -295,8 +296,6 @@ add_preconditions (ps_flags_t flags, struct ps_context *context) flags |= PSTAT_MSGPORT; flags |= PSTAT_TASK; /* for authentication */ } - if (flags & PSTAT_TASK_EVENTS) - flags |= PSTAT_TASK; return flags; } @@ -359,7 +358,8 @@ summarize_thread_basic_info (struct procinfo *pi) bzero (tbi, sizeof *tbi); for (i = 0; i < pi->nthreads; i++) - if (! pi->threadinfos[i].died) + if (! pi->threadinfos[i].died + && ! (pi->threadinfos[i].pis_bi.flags & TH_FLAGS_IDLE)) { thread_basic_info_t bi = &pi->threadinfos[i].pis_bi; int thread_run_state = bi->run_state; @@ -446,7 +446,8 @@ summarize_thread_sched_info (struct procinfo *pi) bzero (tsi, sizeof *tsi); for (i = 0; i < pi->nthreads; i++) - if (! pi->threadinfos[i].died) + if (! pi->threadinfos[i].died + && ! (pi->threadinfos[i].pis_bi.flags & TH_FLAGS_IDLE)) { thread_sched_info_t si = &pi->threadinfos[i].pis_si; tsi->base_priority += si->base_priority; @@ -476,7 +477,8 @@ summarize_thread_states (struct procinfo *pi) /* The union of all thread state bits... */ for (i = 0; i < pi->nthreads; i++) - if (! pi->threadinfos[i].died) + if (! pi->threadinfos[i].died + && ! (pi->threadinfos[i].pis_bi.flags & TH_FLAGS_IDLE)) state |= thread_state (&pi->threadinfos[i].pis_bi); return state; @@ -485,7 +487,7 @@ summarize_thread_states (struct procinfo *pi) /* Returns what's blocking the first blocked thread in PI in WAIT and RPC. */ static void summarize_thread_waits (struct procinfo *pi, char *waits, size_t waits_len, - char **wait, int *rpc) + char **wait, mach_msg_id_t *rpc) { int i; char *next_wait = waits; @@ -495,38 +497,42 @@ summarize_thread_waits (struct procinfo *pi, char *waits, size_t waits_len, for (i = 0; i < pi->nthreads; i++) if (! pi->threadinfos[i].died) - if (next_wait > waits + waits_len) - break; - else - { - int left = waits + waits_len - next_wait; - - if (strncmp (next_wait, "msgport", left) == 0 - || strncmp (next_wait, "itimer", left) == 0) - ; /* libc internal threads; ignore. */ - else if (*wait) - /* There are multiple user threads. Punt. */ - { - *wait = "*"; - *rpc = 0; - break; - } - else - { - *wait = next_wait; - *rpc = pi->threadinfos[i].rpc_block; - } - - /* Advance NEXT_WAIT to the next wait string. */ - next_wait += strnlen (next_wait, left) + 1; - } + { + if (next_wait > waits + waits_len) + break; + else + { + int left = waits + waits_len - next_wait; + + if (pi->threadinfos[i].pis_bi.flags & TH_FLAGS_IDLE) + ; /* kernel idle thread; ignore */ + else if (strncmp (next_wait, "msgport", left) == 0 + || strncmp (next_wait, "itimer", left) == 0) + ; /* libc internal threads; ignore. */ + else if (*wait) + /* There are multiple user threads. Punt. */ + { + *wait = "*"; + *rpc = 0; + break; + } + else + { + *wait = next_wait; + *rpc = pi->threadinfos[i].rpc_block; + } + + /* Advance NEXT_WAIT to the next wait string. */ + next_wait += strnlen (next_wait, left) + 1; + } + } } /* Returns the number of threads in PI that aren't marked dead. */ static unsigned count_threads (struct procinfo *pi, ps_flags_t have) { - if (have & (PSTAT_PROCINFO_THREAD & ~PSTAT_NUM_THREADS)) + if (have & (PSTAT_PROCINFO_TASK_THREAD_DEP & ~PSTAT_NUM_THREADS)) /* If we have thread info besides the number of threads, then the threadinfos structures in PI are valid (we use the died bit). */ { @@ -683,20 +689,19 @@ set_procinfo_flags (struct proc_stat *ps, ps_flags_t need, ps_flags_t have) /* Now copy out the information for this particular thread from the ORIGIN's list of thread information. */ - if ((need & PSTAT_THREAD_BASIC) && ! (have & PSTAT_THREAD_BASIC) - && (oflags & PSTAT_THREAD_BASIC) + need &= ~have; + + if ((need & PSTAT_THREAD_BASIC) && (oflags & PSTAT_THREAD_BASIC) && (ps->thread_basic_info = clone (&ti->pis_bi, sizeof (struct thread_basic_info)))) have |= PSTAT_THREAD_BASIC; - if ((need & PSTAT_THREAD_SCHED) && ! (have & PSTAT_THREAD_SCHED) - && (oflags & PSTAT_THREAD_SCHED) + if ((need & PSTAT_THREAD_SCHED) && (oflags & PSTAT_THREAD_SCHED) && (ps->thread_sched_info = clone (&ti->pis_si, sizeof (struct thread_sched_info)))) have |= PSTAT_THREAD_SCHED; - if ((need & PSTAT_THREAD_WAIT) && ! (have & PSTAT_THREAD_WAIT) - && (oflags & PSTAT_THREAD_WAITS)) + if ((need & PSTAT_THREAD_WAIT) && (oflags & PSTAT_THREAD_WAITS)) { ps->thread_wait = get_thread_wait (origin->thread_waits, @@ -709,6 +714,11 @@ set_procinfo_flags (struct proc_stat *ps, ps_flags_t need, ps_flags_t have) } } } + + /* Mark things that don't apply to threads (note that we don't do the + analogous thing for tasks above, as tasks do have thread fields + containing summary information for all their threads). */ + ps->inapp |= need & ~have & PSTAT_PROCINFO & ~PSTAT_PROCINFO_THREAD; } return have; @@ -762,23 +772,45 @@ proc_stat_set_flags (struct proc_stat *ps, ps_flags_t flags) need = flags & ~have & ~ps->failed; + /* Returns true if (1) FLAGS is in NEED, and (2) the appropriate + preconditions PRECOND are available; if only (1) is true, FLAG is added + to the INAPP set if appropriate (to distinguish it from an error), and + returns false. */ +#define NEED(flag, precond) \ + ({ \ + ps_flags_t __flag = (flag), _precond = (precond); \ + int val; \ + if (! (__flag & need)) \ + val = 0; \ + else if ((_precond & have) == _precond) \ + val = 1; \ + else \ + { \ + val = 0; \ + if (_precond & ps->inapp) \ + ps->inapp |= __flag; \ + } \ + val; \ + }) + /* MGET: If we're trying to set FLAG, and the preconditions PRECOND are set in the flags already, then eval CALL and set ERR to the result. If the resulting ERR is 0 add FLAG to the set of valid flags. ERR is returned. */ -#define MGET(_flag, _precond, call) \ - ({ ps_flags_t flag = (_flag), precond = (_precond); \ - error_t err; \ - if (!(need & (flag)) || (have & (precond)) != (precond)) \ - err = 0; \ - else \ - { \ - err = (call); \ - if (!err) \ - have |= flag; \ - } \ - err; \ - }) +#define MGET(flag, precond, call) \ + ({ \ + error_t err; \ + ps_flags_t _flag = (flag); \ + if (NEED (_flag, precond)) \ + { \ + err = (call); \ + if (!err) \ + have |= _flag; \ + } \ + else \ + err = 0; \ + err; \ + }) /* A version of MGET specifically for the msg port, that turns off the msg port if a call to it times out. It also implies a precondition of @@ -795,11 +827,8 @@ proc_stat_set_flags (struct proc_stat *ps, ps_flags_t flags) later. */ have = set_procinfo_flags (ps, need & ~have & test_msgport_flags, have); - if ((need & PSTAT_SUSPEND_COUNT) - && - ((have & PSTAT_PID) - ? (have & PSTAT_TASK_BASIC) - : (have & PSTAT_THREAD_BASIC))) + if (NEED (PSTAT_SUSPEND_COUNT, + ((have & PSTAT_PID) ? PSTAT_TASK_BASIC : PSTAT_THREAD_BASIC))) { if (have & PSTAT_PID) ps->suspend_count = ps->task_basic_info->suspend_count; @@ -823,31 +852,21 @@ proc_stat_set_flags (struct proc_stat *ps, ps_flags_t flags) /* The process's task port. */ MGET(PSTAT_TASK, PSTAT_PID, proc_pid2task (server, ps->pid, &ps->task)); - /* VM statistics for the task. See <mach/task_info.h>. */ - if ((need & PSTAT_TASK_EVENTS) && (have & PSTAT_TASK)) - { - ps->task_events_info = &ps->task_events_info_buf; - ps->task_events_info_size = TASK_EVENTS_INFO_COUNT; - if (task_info (ps->task, TASK_EVENTS_INFO, - (task_info_t)ps->task_events_info, - &ps->task_events_info_size) - == 0) - have |= PSTAT_TASK_EVENTS; - } - /* PSTAT_STATE_ bits for the process and all its threads. */ if ((need & PSTAT_STATE) && (have & (PSTAT_PROC_INFO | PSTAT_THREAD_BASIC))) { ps->state = 0; if (have & PSTAT_THREAD_BASIC) - /* Thread states. */ - if (have & PSTAT_THREAD) - ps->state |= thread_state (ps->thread_basic_info); - else - /* For a process, we use the thread list instead of - PS->thread_basic_info because it contains more information. */ - ps->state |= summarize_thread_states (ps->proc_info); + { + /* Thread states. */ + if (have & PSTAT_THREAD) + ps->state |= thread_state (ps->thread_basic_info); + else + /* For a process, we use the thread list instead of + PS->thread_basic_info because it contains more information. */ + ps->state |= summarize_thread_states (ps->proc_info); + } if (have & PSTAT_PROC_INFO) /* Process state. */ @@ -881,21 +900,43 @@ proc_stat_set_flags (struct proc_stat *ps, ps_flags_t flags) } /* The process's exec arguments */ - if ((need & PSTAT_ARGS) && (have & PSTAT_PID)) + if (NEED (PSTAT_ARGS, PSTAT_PID)) { char *buf = malloc (100); ps->args_len = 100; ps->args = buf; if (ps->args) - if (proc_getprocargs (server, ps->pid, &ps->args, &ps->args_len)) - free (buf); - else - { - have |= PSTAT_ARGS; - ps->args_vm_alloced = (ps->args != buf); - if (ps->args_vm_alloced) - free (buf); - } + { + if (proc_getprocargs (server, ps->pid, &ps->args, &ps->args_len)) + free (buf); + else + { + have |= PSTAT_ARGS; + ps->args_vm_alloced = (ps->args != buf); + if (ps->args_vm_alloced) + free (buf); + } + } + } + + /* The process's exec environment */ + if (NEED (PSTAT_ENV, PSTAT_PID)) + { + char *buf = malloc (100); + ps->env_len = 100; + ps->env = buf; + if (ps->env) + { + if (proc_getprocenv (server, ps->pid, &ps->env, &ps->env_len)) + free (buf); + else + { + have |= PSTAT_ENV; + ps->env_vm_alloced = (ps->env != buf); + if (ps->env_vm_alloced) + free (buf); + } + } } /* The ctty id port; note that this is just a magic cookie; @@ -920,9 +961,9 @@ proc_stat_set_flags (struct proc_stat *ps, ps_flags_t flags) when creating a file. */ MP_MGET (PSTAT_UMASK, PSTAT_TASK, ps_msg_get_init_int (ps->msgport, ps->task, INIT_UMASK, - &ps->umask)); + (int *) &ps->umask)); - if ((need & PSTAT_OWNER_UID) && (have & PSTAT_PROC_INFO)) + if (NEED (PSTAT_OWNER_UID, PSTAT_PROC_INFO)) { if (ps->proc_info->state & PI_NOTOWNED) ps->owner_uid = -1; @@ -932,34 +973,43 @@ proc_stat_set_flags (struct proc_stat *ps, ps_flags_t flags) } /* A ps_user object for the process's owner. */ - if ((need & PSTAT_OWNER) && (have & PSTAT_OWNER_UID)) - if (ps->owner_uid < 0) - { - ps->owner = 0; + if (NEED (PSTAT_OWNER, PSTAT_OWNER_UID)) + { + if (ps->owner_uid < 0) + { + ps->owner = 0; + have |= PSTAT_OWNER; + } + else if (! ps_context_find_user (ps->context, ps->owner_uid, &ps->owner)) have |= PSTAT_OWNER; - } - else if (! ps_context_find_user (ps->context, ps->owner_uid, &ps->owner)) - have |= PSTAT_OWNER; + } /* A ps_tty for the process's controlling terminal, or NULL if it doesn't have one. */ - if ((need & PSTAT_TTY) && (have & PSTAT_CTTYID)) + if (NEED (PSTAT_TTY, PSTAT_CTTYID)) if (ps_context_find_tty_by_cttyid (ps->context, ps->cttyid, &ps->tty) == 0) have |= PSTAT_TTY; + /* The number of Mach ports in the task. */ + MGET (PSTAT_NUM_PORTS, PSTAT_PID, + proc_getnports (server, ps->pid, &ps->num_ports)); + /* Update PS's flag state. We haven't tried user flags yet, so don't mark them as having failed. We do this before checking user bits so that the user fetch hook sees PS in a consistent state. */ ps->failed |= (need & ~PSTAT_USER_MASK) & ~have; ps->flags = have; - need &= PSTAT_USER_MASK; /* Only consider user bits now. */ + need &= ~have; if (need && ps->context->user_hooks && ps->context->user_hooks->fetch) /* There is some user state we need to fetch. */ { have |= (*ps->context->user_hooks->fetch) (ps, need, have); - /* Update the flag state again having tried the user bits. */ - ps->failed |= need & ~have; + /* Update the flag state again having tried the user bits. We allow + the user hook to turn on non-user bits, in which case we remove them + from the failed set; the user hook may know some way of getting the + info that we don't. */ + ps->failed = (ps->failed | need) & ~have; ps->flags = have; } @@ -968,7 +1018,7 @@ proc_stat_set_flags (struct proc_stat *ps, ps_flags_t flags) /* ---------------------------------------------------------------- */ /* Discard PS and any resources it holds. */ -void +void _proc_stat_free (ps) struct proc_stat *ps; { @@ -982,7 +1032,7 @@ _proc_stat_free (ps) ? mach_port_deallocate(mach_task_self (), (ps->port)) : 0) /* If FLAG is set in PS's flags, then if VM_ALLOCED is zero, free the malloced - field MEM in PS; othrewise, vm_deallocate MEM, consisting of SIZE + field MEM in PS; othrewise, vm_deallocate MEM, consisting of SIZE elements of type ELTYPE, *unless* MEM == SBUF, which usually means that MEM points to a static buffer somewhere instead of vm_alloc'd memory. */ @@ -999,13 +1049,16 @@ _proc_stat_free (ps) MFREEPORT (PSTAT_AUTH, auth); /* free any allocated memory pointed to by PS */ - MFREEMEM (PSTAT_PROCINFO, proc_info, ps->proc_info_size, + MFREEMEM (PSTAT_PROC_INFO, proc_info, ps->proc_info_size, ps->proc_info_vm_alloced, 0, char); MFREEMEM (PSTAT_THREAD_BASIC, thread_basic_info, 0, 0, 0, 0); MFREEMEM (PSTAT_THREAD_SCHED, thread_sched_info, 0, 0, 0, 0); MFREEMEM (PSTAT_ARGS, args, ps->args_len, ps->args_vm_alloced, 0, char); + MFREEMEM (PSTAT_ENV, env, ps->env_len, ps->env_vm_alloced, 0, char); MFREEMEM (PSTAT_TASK_EVENTS, task_events_info, ps->task_events_info_size, 0, &ps->task_events_info_buf, char); + MFREEMEM (PSTAT_THREAD_WAITS, thread_waits, ps->thread_waits_len, + ps->thread_waits_vm_alloced, 0, char); FREE (ps); } @@ -1023,6 +1076,7 @@ _proc_stat_create (pid_t pid, struct ps_context *context, struct proc_stat **ps) (*ps)->pid = pid; (*ps)->flags = PSTAT_PID; (*ps)->failed = 0; + (*ps)->inapp = PSTAT_THREAD; (*ps)->context = context; (*ps)->hook = 0; @@ -1036,7 +1090,7 @@ _proc_stat_create (pid_t pid, struct ps_context *context, struct proc_stat **ps) resulting proc_stat isn't fully functional -- most flags can't be set in it. It also contains a pointer to PS, so PS shouldn't be freed without also freeing THREAD_PS. If N was out of range, EINVAL is returned. If a - memory allocation error occured, ENOMEM is returned. Otherwise, 0 is + memory allocation error occurred, ENOMEM is returned. Otherwise, 0 is returned. */ error_t proc_stat_thread_create (struct proc_stat *ps, unsigned index, struct proc_stat **thread_ps) @@ -1057,6 +1111,8 @@ proc_stat_thread_create (struct proc_stat *ps, unsigned index, struct proc_stat /* A value of -1 for the PID indicates that this is a thread. */ tps->pid = -1; tps->flags = PSTAT_THREAD; + tps->failed = 0; + tps->inapp = PSTAT_PID; tps->thread_origin = ps; tps->thread_index = index; @@ -1,8 +1,8 @@ /* Routines to gather and print process information. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995,96,99,2001,02 Free Software Foundation, Inc. - Written by Miles Bader <miles@gnu.ai.mit.edu> + Written by Miles Bader <miles@gnu.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -40,8 +40,8 @@ struct ps_user uid_t uid; /* The status */ - enum ps_user_passwd_state passwd_state; - + 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; @@ -85,7 +85,7 @@ enum ps_tty_name_state 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. */ @@ -125,17 +125,17 @@ struct ps_context process_t server; /* proc_stats for every process we know about, indexed by process id. */ - ihash_t procs; + struct hurd_ihash procs; /* ps_ttys for every tty we know about, indexed by the terminal port. */ - ihash_t ttys; + struct hurd_ihash ttys; /* ps_ttys for every tty we know about, indexed by their ctty id port (from libc). */ - ihash_t ttys_by_cttyid; + struct hurd_ihash ttys_by_cttyid; /* A ps_user for every user we know about, indexed by user-id. */ - ihash_t users; + struct hurd_ihash users; /* Functions that can be set to extend the behavior of proc_stats. */ struct ps_user_hooks *user_hooks; @@ -178,121 +178,134 @@ 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. */ - - /* 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; - - /* 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; - }; +{ + /* 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. */ + size_t 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. */ + /* FIXME: we are actually currently storing it into proc_info, see + fetch_procinfo. */ + task_events_info_t task_events_info; + task_events_info_data_t task_events_info_buf; + size_t 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. */ + size_t env_len; + + unsigned num_ports; +}; /* Proc_stat flag bits; each bit is set in the FLAGS field if that information is currently valid. */ @@ -317,6 +330,7 @@ struct proc_stat #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 */ @@ -328,12 +342,13 @@ struct proc_stat #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 */ +#define PSTAT_NUM_PORTS 0x4000000 /* Number of Mach ports in the task */ /* 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 0x2000000 +#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 @@ -390,7 +405,7 @@ struct proc_stat /* 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; +extern char *proc_stat_state_tags; /* Process info accessor functions. @@ -420,6 +435,8 @@ char *proc_stat_state_tags; #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) @@ -429,6 +446,7 @@ char *proc_stat_state_tags; #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_num_ports(ps) ((ps)->num_ports) #define proc_stat_has(ps, needs) (((ps)->flags & needs) == needs) /* True if PS refers to a thread and not a process. */ @@ -442,7 +460,9 @@ error_t _proc_stat_create (pid_t pid, struct ps_context *context, /* 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. */ + away. Insubordinate users will make sure they free the thread proc_stats + before they free the corresponding process proc_stat since the thread_wait + fields of the former may reference the latter. */ void _proc_stat_free (struct proc_stat *ps); /* Adds FLAGS to PS's flags, fetching information as necessary to validate @@ -455,7 +475,7 @@ error_t proc_stat_set_flags (struct proc_stat *ps, ps_flags_t flags); 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 occurred, ENOMEM is returned. Otherwise, 0 is returned. */ error_t proc_stat_thread_create (struct proc_stat *ps, unsigned n, struct proc_stat **thread_ps); @@ -504,7 +524,7 @@ struct ps_getter ps_flags_t needs; /* A function that will get the value; the protocol between this function - and its caller is type-dependent. */ + and its caller is type-dependent. */ void (*fn) (); }; @@ -608,7 +628,7 @@ 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 + 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 @@ -620,7 +640,7 @@ 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; @@ -673,7 +693,7 @@ struct ps_fmt_specs struct ps_fmt_spec_block *expansions; /* Storage for expanded aliases. */ }; -/* An struct ps_fmt_specs, suitable for use with ps_fmt_specs_find, +/* 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; @@ -730,24 +750,29 @@ struct ps_fmt_field /* 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 have no valid value. */ - char *inval; - }; +{ + /* 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 appropriate, but + couldn't be fetched due to some error. */ + char *error; +}; /* Accessor macros: */ #define ps_fmt_fields(fmt) ((fmt)->fields) @@ -797,7 +822,7 @@ void ps_fmt_free (struct ps_fmt *fmt); 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 +/* Write an appropriate 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. @@ -812,14 +837,14 @@ 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: + field, returns true. Appropriate 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. */ + *preceding* 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 + Appropriate inter-field characters are also removed: those *following* + deleted fields at the beginning of the fmt, and those *preceding* deleted fields *not* at the beginning. */ void ps_fmt_squash_flags (struct ps_fmt *fmt, ps_flags_t flags); @@ -898,7 +923,7 @@ error_t proc_stat_list_merge (struct proc_stat_list *pp, returned in them. */ error_t proc_stat_list_add_all (struct proc_stat_list *pp, struct proc_stat ***proc_stats, - unsigned *num_procs); + size_t *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, @@ -907,7 +932,7 @@ error_t proc_stat_list_add_all (struct proc_stat_list *pp, 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); + size_t *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 @@ -916,7 +941,7 @@ error_t proc_stat_list_add_login_coll (struct proc_stat_list *pp, error_t proc_stat_list_add_session (struct proc_stat_list *pp, pid_t session_id, struct proc_stat ***proc_stats, - unsigned *num_procs); + size_t *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 @@ -924,7 +949,7 @@ error_t proc_stat_list_add_session (struct proc_stat_list *pp, 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); + size_t *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 @@ -1009,7 +1034,7 @@ int proc_stat_list_spec_nominal (struct proc_stat_list *pp, information on the data types these routines return. */ /* Return the current host port. */ -host_t ps_get_host (); +mach_port_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 diff --git a/libps/spec.c b/libps/spec.c index 62b6dfc2..b34a2343 100644 --- a/libps/spec.c +++ b/libps/spec.c @@ -1,8 +1,8 @@ /* Access, formatting, & comparison routines for printing process info. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995,96,97,99,2001,02 Free Software Foundation, Inc. - Written by Miles Bader <miles@gnu.ai.mit.edu> + Written by Miles Bader <miles@gnu.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -41,7 +41,7 @@ static char *get_rpc_name (mach_msg_id_t it) { return 0; } typedef void (*vf)(); -static int +static int ps_get_pid (struct proc_stat *ps) { return proc_stat_pid (ps); @@ -49,7 +49,7 @@ ps_get_pid (struct proc_stat *ps) const struct ps_getter ps_pid_getter = {"pid", PSTAT_PID, (vf) ps_get_pid}; -static int +static int ps_get_thread_index (struct proc_stat *ps) { return proc_stat_thread_index (ps); @@ -73,7 +73,7 @@ ps_get_owner_uid (struct proc_stat *ps) const struct ps_getter ps_owner_uid_getter = {"uid", PSTAT_OWNER_UID, (vf) ps_get_owner_uid}; -static int +static int ps_get_ppid (struct proc_stat *ps) { return proc_stat_proc_info (ps)->ppid; @@ -81,7 +81,7 @@ ps_get_ppid (struct proc_stat *ps) const struct ps_getter ps_ppid_getter = {"ppid", PSTAT_PROC_INFO, (vf) ps_get_ppid}; -static int +static int ps_get_pgrp (struct proc_stat *ps) { return proc_stat_proc_info (ps)->pgrp; @@ -89,7 +89,7 @@ ps_get_pgrp (struct proc_stat *ps) const struct ps_getter ps_pgrp_getter = {"pgrp", PSTAT_PROC_INFO, (vf) ps_get_pgrp}; -static int +static int ps_get_session (struct proc_stat *ps) { return proc_stat_proc_info (ps)->session; @@ -97,7 +97,7 @@ ps_get_session (struct proc_stat *ps) const struct ps_getter ps_session_getter = {"session", PSTAT_PROC_INFO, (vf) ps_get_session}; -static int +static int ps_get_login_col (struct proc_stat *ps) { return proc_stat_proc_info (ps)->logincollection; @@ -105,7 +105,7 @@ ps_get_login_col (struct proc_stat *ps) const struct ps_getter ps_login_col_getter = {"login_col", PSTAT_PROC_INFO, (vf) ps_get_login_col}; -static int +static int ps_get_num_threads (struct proc_stat *ps) { return proc_stat_num_threads (ps); @@ -113,7 +113,7 @@ ps_get_num_threads (struct proc_stat *ps) const struct ps_getter ps_num_threads_getter = {"num_threads", PSTAT_NUM_THREADS, (vf)ps_get_num_threads}; -static void +static void ps_get_args (struct proc_stat *ps, char **args_p, int *args_len_p) { *args_p = proc_stat_args (ps); @@ -122,7 +122,16 @@ ps_get_args (struct proc_stat *ps, char **args_p, int *args_len_p) const struct ps_getter ps_args_getter = {"args", PSTAT_ARGS, ps_get_args}; -static int +static void +ps_get_env (struct proc_stat *ps, char **env_p, int *env_len_p) +{ + *env_p = proc_stat_env (ps); + *env_len_p = proc_stat_env_len (ps); +} +const struct ps_getter ps_env_getter = +{"env", PSTAT_ENV, ps_get_env}; + +static int ps_get_state (struct proc_stat *ps) { return proc_stat_state (ps); @@ -139,7 +148,7 @@ ps_get_wait (struct proc_stat *ps, char **wait, int *rpc) const struct ps_getter ps_wait_getter = {"wait", PSTAT_THREAD_WAIT, ps_get_wait}; -static int +static size_t ps_get_vsize (struct proc_stat *ps) { return proc_stat_task_basic_info (ps)->virtual_size; @@ -147,7 +156,7 @@ ps_get_vsize (struct proc_stat *ps) const struct ps_getter ps_vsize_getter = {"vsize", PSTAT_TASK_BASIC, (vf) ps_get_vsize}; -static int +static size_t ps_get_rsize (struct proc_stat *ps) { return proc_stat_task_basic_info (ps)->resident_size; @@ -155,7 +164,7 @@ ps_get_rsize (struct proc_stat *ps) const struct ps_getter ps_rsize_getter = {"rsize", PSTAT_TASK_BASIC, (vf) ps_get_rsize}; -static int +static int ps_get_cur_priority (struct proc_stat *ps) { return proc_stat_thread_basic_info (ps)->cur_priority; @@ -163,7 +172,7 @@ ps_get_cur_priority (struct proc_stat *ps) const struct ps_getter ps_cur_priority_getter = {"cur_priority", PSTAT_THREAD_BASIC, (vf) ps_get_cur_priority}; -static int +static int ps_get_base_priority (struct proc_stat *ps) { return proc_stat_thread_basic_info (ps)->base_priority; @@ -171,7 +180,7 @@ ps_get_base_priority (struct proc_stat *ps) const struct ps_getter ps_base_priority_getter = {"base_priority", PSTAT_THREAD_BASIC, (vf) ps_get_base_priority}; -static int +static int ps_get_max_priority (struct proc_stat *ps) { return proc_stat_thread_sched_info (ps)->max_priority; @@ -179,7 +188,7 @@ ps_get_max_priority (struct proc_stat *ps) const struct ps_getter ps_max_priority_getter = {"max_priority", PSTAT_THREAD_SCHED, (vf) ps_get_max_priority}; -static void +static void ps_get_usr_time (struct proc_stat *ps, struct timeval *tv) { time_value_t tvt = proc_stat_thread_basic_info (ps)->user_time; @@ -189,7 +198,7 @@ ps_get_usr_time (struct proc_stat *ps, struct timeval *tv) const struct ps_getter ps_usr_time_getter = {"usr_time", PSTAT_THREAD_BASIC, ps_get_usr_time}; -static void +static void ps_get_sys_time (struct proc_stat *ps, struct timeval *tv) { time_value_t tvt = proc_stat_thread_basic_info (ps)->system_time; @@ -199,7 +208,7 @@ ps_get_sys_time (struct proc_stat *ps, struct timeval *tv) const struct ps_getter ps_sys_time_getter = {"sys_time", PSTAT_THREAD_BASIC, ps_get_sys_time}; -static void +static void ps_get_tot_time (struct proc_stat *ps, struct timeval *tv) { time_value_t tvt = proc_stat_thread_basic_info (ps)->user_time; @@ -210,10 +219,20 @@ ps_get_tot_time (struct proc_stat *ps, struct timeval *tv) const struct ps_getter ps_tot_time_getter = {"tot_time", PSTAT_THREAD_BASIC, ps_get_tot_time}; -static float +static void +ps_get_start_time (struct proc_stat *ps, struct timeval *tv) +{ + time_value_t *const tvt = &proc_stat_task_basic_info (ps)->creation_time; + tv->tv_sec = tvt->seconds; + tv->tv_usec = tvt->microseconds; +} +const struct ps_getter ps_start_time_getter = +{"start_time", PSTAT_TASK_BASIC, ps_get_start_time}; + +static float ps_get_rmem_frac (struct proc_stat *ps) { - static int mem_size = 0; + static size_t mem_size = 0; if (mem_size == 0) { @@ -222,7 +241,7 @@ ps_get_rmem_frac (struct proc_stat *ps) if (err == 0) mem_size = info->memory_size; } - + if (mem_size > 0) return (float)proc_stat_task_basic_info (ps)->resident_size @@ -233,7 +252,7 @@ ps_get_rmem_frac (struct proc_stat *ps) const struct ps_getter ps_rmem_frac_getter = {"rmem_frac", PSTAT_TASK_BASIC, (vf) ps_get_rmem_frac}; -static float +static float ps_get_cpu_frac (struct proc_stat *ps) { return (float) proc_stat_thread_basic_info (ps)->cpu_usage @@ -242,7 +261,7 @@ ps_get_cpu_frac (struct proc_stat *ps) const struct ps_getter ps_cpu_frac_getter = {"cpu_frac", PSTAT_THREAD_BASIC, (vf) ps_get_cpu_frac}; -static int +static int ps_get_sleep (struct proc_stat *ps) { return proc_stat_thread_basic_info (ps)->sleep_time; @@ -250,7 +269,7 @@ ps_get_sleep (struct proc_stat *ps) const struct ps_getter ps_sleep_getter = {"sleep", PSTAT_THREAD_BASIC, (vf) ps_get_sleep}; -static int +static int ps_get_susp_count (struct proc_stat *ps) { return proc_stat_suspend_count (ps); @@ -258,7 +277,7 @@ ps_get_susp_count (struct proc_stat *ps) const struct ps_getter ps_susp_count_getter = {"susp_count", PSTAT_SUSPEND_COUNT, (vf) ps_get_susp_count}; -static int +static int ps_get_proc_susp_count (struct proc_stat *ps) { return proc_stat_task_basic_info (ps)->suspend_count; @@ -266,7 +285,7 @@ ps_get_proc_susp_count (struct proc_stat *ps) const struct ps_getter ps_proc_susp_count_getter = {"proc_susp_count", PSTAT_TASK_BASIC, (vf) ps_get_proc_susp_count}; -static int +static int ps_get_thread_susp_count (struct proc_stat *ps) { return proc_stat_thread_basic_info (ps)->suspend_count; @@ -282,7 +301,7 @@ ps_get_tty (struct proc_stat *ps) const struct ps_getter ps_tty_getter = {"tty", PSTAT_TTY, (vf)ps_get_tty}; -static int +static int ps_get_page_faults (struct proc_stat *ps) { return proc_stat_task_events_info (ps)->faults; @@ -290,7 +309,7 @@ ps_get_page_faults (struct proc_stat *ps) const struct ps_getter ps_page_faults_getter = {"page_faults", PSTAT_TASK_EVENTS, (vf) ps_get_page_faults}; -static int +static int ps_get_cow_faults (struct proc_stat *ps) { return proc_stat_task_events_info (ps)->cow_faults; @@ -298,7 +317,7 @@ ps_get_cow_faults (struct proc_stat *ps) const struct ps_getter ps_cow_faults_getter = {"cow_faults", PSTAT_TASK_EVENTS, (vf) ps_get_cow_faults}; -static int +static int ps_get_pageins (struct proc_stat *ps) { return proc_stat_task_events_info (ps)->pageins; @@ -306,7 +325,7 @@ ps_get_pageins (struct proc_stat *ps) const struct ps_getter ps_pageins_getter = {"pageins", PSTAT_TASK_EVENTS, (vf) ps_get_pageins}; -static int +static int ps_get_msgs_sent (struct proc_stat *ps) { return proc_stat_task_events_info (ps)->messages_sent; @@ -314,7 +333,7 @@ ps_get_msgs_sent (struct proc_stat *ps) const struct ps_getter ps_msgs_sent_getter = {"msgs_sent", PSTAT_TASK_EVENTS, (vf) ps_get_msgs_sent}; -static int +static int ps_get_msgs_rcvd (struct proc_stat *ps) { return proc_stat_task_events_info (ps)->messages_received; @@ -322,7 +341,7 @@ ps_get_msgs_rcvd (struct proc_stat *ps) const struct ps_getter ps_msgs_rcvd_getter = {"msgs_rcvd", PSTAT_TASK_EVENTS, (vf) ps_get_msgs_rcvd}; -static int +static int ps_get_zero_fills (struct proc_stat *ps) { return proc_stat_task_events_info (ps)->zero_fills; @@ -330,6 +349,14 @@ ps_get_zero_fills (struct proc_stat *ps) const struct ps_getter ps_zero_fills_getter = {"zero_fills", PSTAT_TASK_EVENTS, (vf) ps_get_zero_fills}; +static int +ps_get_num_ports (struct proc_stat *ps) +{ + return proc_stat_num_ports (ps); +} +const struct ps_getter ps_num_ports_getter = +{"num_ports", PSTAT_NUM_PORTS, (vf) ps_get_num_ports}; + /* ---------------------------------------------------------------- */ /* some printing functions */ @@ -378,16 +405,18 @@ ps_emit_num_blocks (struct proc_stat *ps, struct ps_fmt_field *field, return ps_stream_write_field (stream, buf, field->width); } -int +size_t sprint_frac_value (char *buf, - int value, int min_value_len, - int frac, int frac_scale, + size_t value, int min_value_len, + size_t frac, int frac_scale, int width) { - int value_len; - int frac_len; + int value_len = 0; + int frac_len = 0; - if (value >= 100) /* the integer part */ + if (value >= 1000) /* the integer part */ + value_len = 4; /* values 1000-1023 */ + if (value >= 100) value_len = 3; else if (value >= 10) value_len = 2; @@ -403,9 +432,9 @@ sprint_frac_value (char *buf, frac /= 10; if (frac_len > 0) - sprintf (buf, "%d.%0*d", value, frac_len, frac); + sprintf (buf, "%zd.%0*zd", value, frac_len, frac); else - sprintf (buf, "%d", value); + sprintf (buf, "%zd", value); return strlen (buf); } @@ -430,13 +459,13 @@ ps_emit_percent (struct proc_stat *ps, struct ps_fmt_field *field, /* prints its value nicely */ error_t -ps_emit_nice_int (struct proc_stat *ps, struct ps_fmt_field *field, - struct ps_stream *stream) +ps_emit_nice_size_t (struct proc_stat *ps, struct ps_fmt_field *field, + struct ps_stream *stream) { char buf[20]; - int value = FG (field, int)(ps); + size_t value = FG (field, size_t)(ps); char *sfx = " KMG"; - int frac = 0; + size_t frac = 0; while (value >= 1024) { @@ -462,8 +491,11 @@ ps_emit_seconds (struct proc_stat *ps, struct ps_fmt_field *field, FG (field, void)(ps, &tv); - fmt_seconds (&tv, !(field->flags & PS_FMT_FIELD_AT_MOD), prec, ABS (width), - buf, sizeof (buf)); + if ((field->flags & PS_FMT_FIELD_COLON_MOD) && tv.tv_sec == 0) + strcpy (buf, "-"); + else + fmt_seconds (&tv, !(field->flags & PS_FMT_FIELD_AT_MOD), prec, ABS (width), + buf, sizeof (buf)); return ps_stream_write_field (stream, buf, width); } @@ -476,10 +508,13 @@ ps_emit_minutes (struct proc_stat *ps, struct ps_fmt_field *field, struct timeval tv; int width = field->width; - FG (field, int)(ps, &tv); + FG (field, void)(ps, &tv); - fmt_minutes (&tv, !(field->flags & PS_FMT_FIELD_AT_MOD), ABS (width), - buf, sizeof (buf)); + if ((field->flags & PS_FMT_FIELD_COLON_MOD) && tv.tv_sec < 60) + strcpy (buf, "-"); + else + fmt_minutes (&tv, !(field->flags & PS_FMT_FIELD_AT_MOD), ABS (width), + buf, sizeof (buf)); return ps_stream_write_field (stream, buf, width); } @@ -493,7 +528,7 @@ ps_emit_past_time (struct proc_stat *ps, struct ps_fmt_field *field, struct timeval tv; int width = field->width; - FG (field, int)(ps, &tv); + FG (field, void)(ps, &tv); if (now.tv_sec == 0 && gettimeofday (&now, 0) < 0) return errno; @@ -544,7 +579,7 @@ ps_emit_user_name (struct proc_stat *ps, struct ps_fmt_field *field, if (pw == NULL) { char buf[20]; - sprintf (buf, "(UID %d)", pw->pw_uid); + sprintf (buf, "(UID %d)", u->uid); return ps_stream_write_field (stream, buf, width); } else @@ -568,8 +603,8 @@ ps_emit_args (struct proc_stat *ps, struct ps_fmt_field *field, FG (field, void)(ps, &s0, &s0len); - if (s0 == NULL) - *buf = '\0'; + if (!s0 || s0len == 0 ) + strcpy (buf, "-"); else { if (s0len > sizeof static_buf) @@ -610,8 +645,8 @@ ps_emit_string (struct proc_stat *ps, struct ps_fmt_field *field, FG (field, void)(ps, &str, &len); - if (str == NULL) - str = ""; + if (!str || len == 0) + str = "-"; return ps_stream_write_trunc_field (stream, str, field->width); } @@ -706,7 +741,6 @@ ps_emit_wait (struct proc_stat *ps, struct ps_fmt_field *field, else if (strcmp (wait, "kernel") == 0) /* A syscall. RPC is actually the syscall number. */ { - extern char *get_syscall_name (int num); char *name = get_syscall_name (rpc); if (! name) { @@ -719,29 +753,35 @@ ps_emit_wait (struct proc_stat *ps, struct ps_fmt_field *field, /* An rpc (with msg id RPC); WAIT describes the dest port. */ { char port_name_buf[20]; - extern char *get_rpc_name (mach_msg_id_t num); char *name = get_rpc_name (rpc); /* See if we should give a more useful name for the port. */ if (strcmp (wait, "init#0") == 0) - wait = "cwdir"; /* Current directory */ + wait = "cwd"; /* Current directory */ else if (strcmp (wait, "init#1") == 0) - wait = "crdir"; /* Root directory */ + wait = "root"; /* Root directory */ else if (strcmp (wait, "init#2") == 0) wait = "auth"; /* Auth port */ else if (strcmp (wait, "init#3") == 0) wait = "proc"; /* Proc port */ else if (strcmp (wait, "init#4") == 0) - wait = "bootstrap"; /* Bootstrap port */ + wait = "cttyid"; /* Ctty id port */ + else if (strcmp (wait, "init#5") == 0) + wait = "boot"; /* Bootstrap port */ else - /* See if we can shorten the name to fit better. We happen know that - all currently returned keys are unique in the first character. */ + /* See if we can shorten the name to fit better. */ { - char *sep = index (wait, '#'); - if (sep && sep > wait) + char *abbrev = 0, *num = 0; + if (strncmp (wait, "fd#", 3) == 0) + abbrev = "fd", num = wait + 3; + else if (strncmp (wait, "bgfd#", 5) == 0) + abbrev = "bg", num = wait + 5; + else if (strncmp (wait, "port#", 5) == 0) + abbrev = "", num = wait + 5; + if (abbrev) { snprintf (port_name_buf, sizeof port_name_buf, - "%c%s", wait[0], sep); + "%s%s", abbrev, num); wait = port_name_buf; } } @@ -764,25 +804,34 @@ ps_emit_wait (struct proc_stat *ps, struct ps_fmt_field *field, #define GUARDED_CMP(s1, s2, call) \ ((s1) == NULL ? (((s2) == NULL) ? 0 : -1) : ((s2) == NULL ? 1 : (call))) -int +int ps_cmp_ints (struct proc_stat *ps1, struct proc_stat *ps2, const struct ps_getter *getter) { int (*gf)() = G (getter, int); int v1 = gf(ps1), v2 = gf (ps2); return v1 == v2 ? 0 : v1 < v2 ? -1 : 1; -} +} -int +int ps_cmp_floats (struct proc_stat *ps1, struct proc_stat *ps2, const struct ps_getter *getter) { float (*gf)() = G (getter, float); float v1 = gf(ps1), v2 = gf (ps2); return v1 == v2 ? 0 : v1 < v2 ? -1 : 1; -} +} -int +int +ps_cmp_size_ts (struct proc_stat *ps1, struct proc_stat *ps2, + const struct ps_getter *getter) +{ + size_t (*gf)() = G (getter, size_t); + size_t v1 = gf(ps1), v2 = gf (ps2); + return v1 == v2 ? 0 : v1 < v2 ? -1 : 1; +} + +int ps_cmp_uids (struct proc_stat *ps1, struct proc_stat *ps2, const struct ps_getter *getter) { @@ -791,7 +840,7 @@ ps_cmp_uids (struct proc_stat *ps1, struct proc_stat *ps2, return (u1 ? ps_user_uid (u1) : -1) - (u2 ? ps_user_uid (u2) : -1); } -int +int ps_cmp_unames (struct proc_stat *ps1, struct proc_stat *ps2, const struct ps_getter *getter) { @@ -802,7 +851,7 @@ ps_cmp_unames (struct proc_stat *ps1, struct proc_stat *ps2, return GUARDED_CMP (pw1, pw2, strcmp (pw1->pw_name, pw2->pw_name)); } -int +int ps_cmp_strings (struct proc_stat *ps1, struct proc_stat *ps2, const struct ps_getter *getter) { @@ -845,6 +894,16 @@ ps_nominal_zint (struct proc_stat *ps, const struct ps_getter *getter) return G (getter, int)(ps) == 0; } +/* Neither is an empty string. */ +int +ps_nominal_string (struct proc_stat *ps, const struct ps_getter *getter) +{ + char *str; + size_t len; + G (getter, char *)(ps, &str, &len); + return !str || len == 0 || (len == 1 && *str == '-'); +} + /* Priorities are similar, but have to be converted to the unix nice scale first. */ int @@ -864,7 +923,7 @@ ps_nominal_nth (struct proc_stat *ps, const struct ps_getter *getter) static int own_uid = -2; /* -1 means no uid at all. */ /* A user is nominal if it's the current user. */ -int +int ps_nominal_user (struct proc_stat *ps, const struct ps_getter *getter) { struct ps_user *u = G (getter, struct ps_user *)(ps); @@ -874,7 +933,7 @@ ps_nominal_user (struct proc_stat *ps, const struct ps_getter *getter) } /* A uid is nominal if it's that of the current user. */ -int +int ps_nominal_uid (struct proc_stat *ps, const struct ps_getter *getter) { uid_t uid = G (getter, uid_t)(ps); @@ -916,7 +975,7 @@ specv_find (const struct ps_fmt_spec *specs, const char *name, return 0; } -/* Number of specs allocated in each block of expansions. */ +/* Number of specs allocated in each block of expansions. */ #define EXP_BLOCK_SIZE 20 /* A node in a linked list of spec vectors. */ @@ -1051,9 +1110,13 @@ static const struct ps_fmt_spec specs[] = {"LColl", 0, -5, -1, 0, &ps_login_col_getter, ps_emit_int, ps_cmp_ints, 0}, {"Args", 0, 0, -1, 0, - &ps_args_getter, ps_emit_args, ps_cmp_strings,0}, + &ps_args_getter, ps_emit_args, ps_cmp_strings,ps_nominal_string}, {"Arg0", 0, 0, -1, 0, - &ps_args_getter, ps_emit_string, ps_cmp_strings,0}, + &ps_args_getter, ps_emit_string, ps_cmp_strings,ps_nominal_string}, + {"Env", 0, 0, -1, 0, + &ps_env_getter, ps_emit_args, ps_cmp_strings,ps_nominal_string}, + {"Start", 0, -7, 1, 0, + &ps_start_time_getter, ps_emit_past_time, ps_cmp_times,0}, {"Time", 0, -8, 2, 0, &ps_tot_time_getter, ps_emit_seconds, ps_cmp_times, 0}, {"UTime", 0, -8, 2, 0, @@ -1061,9 +1124,9 @@ static const struct ps_fmt_spec specs[] = {"STime", 0, -8, 2, 0, &ps_sys_time_getter, ps_emit_seconds, ps_cmp_times, 0}, {"VSize", 0, -5, -1, 0, - &ps_vsize_getter, ps_emit_nice_int,ps_cmp_ints, 0}, + &ps_vsize_getter, ps_emit_nice_size_t,ps_cmp_size_ts, 0}, {"RSize", 0, -5, -1, 0, - &ps_rsize_getter, ps_emit_nice_int,ps_cmp_ints, 0}, + &ps_rsize_getter, ps_emit_nice_size_t,ps_cmp_size_ts, 0}, {"Pri", 0, -3, -1, 0, &ps_cur_priority_getter,ps_emit_priority,ps_cmp_ints, ps_nominal_pri}, {"BPri", 0, -3, -1, 0, @@ -1100,6 +1163,8 @@ static const struct ps_fmt_spec specs[] = &ps_msgs_sent_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, {"ZFills", 0, -5, -1, 0, &ps_zero_fills_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, + {"Ports", 0, -5, -1, 0, + &ps_num_ports_getter, ps_emit_int, ps_cmp_ints, 0}, {0} }; diff --git a/libps/tty.c b/libps/tty.c index 9d9ee649..3ab72ee8 100644 --- a/libps/tty.c +++ b/libps/tty.c @@ -1,8 +1,8 @@ /* The ps_tty type, for per-tty info. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995,1996,2000 Free Software Foundation, Inc. - Written by Miles Bader <miles@gnu.ai.mit.edu> + Written by Miles Bader <miles@gnu.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -91,11 +91,11 @@ ps_tty_name (struct ps_tty *tty) struct ps_tty_abbrev { - char *pfx; - char *subst; + const char *pfx; + const char *subst; }; -struct ps_tty_abbrev ps_tty_abbrevs[] = +const struct ps_tty_abbrev ps_tty_abbrevs[] = { { "/tmp/console", "oc" }, /* temp hack */ { "/dev/console", "co" }, @@ -115,14 +115,14 @@ ps_tty_short_name (struct ps_tty *tty) return tty->short_name; else { - struct ps_tty_abbrev *abbrev; + const struct ps_tty_abbrev *abbrev; const char *name = ps_tty_name (tty); if (name) for (abbrev = ps_tty_abbrevs; abbrev->pfx != NULL; abbrev++) { - char *subst = abbrev->subst; - unsigned pfx_len = strlen (abbrev->pfx); + const char *subst = abbrev->subst; + size_t pfx_len = strlen (abbrev->pfx); if (strncmp (name, abbrev->pfx, pfx_len) == 0) { @@ -132,11 +132,13 @@ ps_tty_short_name (struct ps_tty *tty) tty->short_name = name + pfx_len; else { - char *n = malloc (strlen(subst) + strlen (name + pfx_len)); + size_t slen = strlen (subst); + size_t nlen = strlen (name + pfx_len) + 1; + char *n = malloc (slen + nlen); if (n) { - strcpy (n, subst); - strcat (n, name + pfx_len); + memcpy (n, subst, slen); + memcpy (&n[slen], &name[pfx_len], nlen); tty->short_name = n; tty->short_name_alloced = TRUE; } diff --git a/libps/user.c b/libps/user.c index 4af5014f..0b87ace3 100644 --- a/libps/user.c +++ b/libps/user.c @@ -1,8 +1,8 @@ /* The ps_user type, for per-user info. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995,96,2001 Free Software Foundation, Inc. - Written by Miles Bader <miles@gnu.ai.mit.edu> + Written by Miles Bader <miles@gnu.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -21,6 +21,7 @@ #include <hurd.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <assert.h> #include "ps.h" diff --git a/libps/write.c b/libps/write.c index 725ea288..83be42ab 100644 --- a/libps/write.c +++ b/libps/write.c @@ -68,7 +68,7 @@ noise_write (const unsigned char *t, ssize_t max, FILE *s) if (flush (&ok, t, s)) return errno; - len += (is_cntl ? 2 : 3); + len += (is_cntl ? 2 : 4); if (max >= 0 && len > max) break; @@ -96,7 +96,7 @@ noise_len (const char *t, ssize_t max) len++; else { - size_t rep_len = iscntl (ch) ? 2 : 3; + size_t rep_len = iscntl (ch) ? 2 : 4; if (max >= 0 && rep_len + len > max) break; len += rep_len; |