diff options
Diffstat (limited to 'libps/spec.c')
-rw-r--r-- | libps/spec.c | 398 |
1 files changed, 189 insertions, 209 deletions
diff --git a/libps/spec.c b/libps/spec.c index 0a60d116..048a5810 100644 --- a/libps/spec.c +++ b/libps/spec.c @@ -26,6 +26,8 @@ #include <hurd/resource.h> #include <unistd.h> #include <string.h> +#include <timefmt.h> +#include <sys/time.h> #include "ps.h" #include "common.h" @@ -173,26 +175,32 @@ struct ps_getter ps_max_priority_getter = {"max_priority", PSTAT_THREAD_SCHED, (vf) ps_get_max_priority}; static void -ps_get_usr_time(proc_stat_t ps, time_value_t * tv_out) +ps_get_usr_time (proc_stat_t ps, struct timeval *tv) { - *tv_out = proc_stat_thread_basic_info(ps)->user_time; + time_value_t tvt = proc_stat_thread_basic_info (ps)->user_time; + tv->tv_sec = tvt.seconds; + tv->tv_usec = tvt.microseconds; } struct ps_getter ps_usr_time_getter = {"usr_time", PSTAT_THREAD_BASIC, ps_get_usr_time}; static void -ps_get_sys_time(proc_stat_t ps, time_value_t * tv_out) +ps_get_sys_time (proc_stat_t ps, struct timeval *tv) { - *tv_out = proc_stat_thread_basic_info(ps)->system_time; + time_value_t tvt = proc_stat_thread_basic_info (ps)->system_time; + tv->tv_sec = tvt.seconds; + tv->tv_usec = tvt.microseconds; } struct ps_getter ps_sys_time_getter = {"sys_time", PSTAT_THREAD_BASIC, ps_get_sys_time}; static void -ps_get_tot_time(proc_stat_t ps, time_value_t * tv_out) +ps_get_tot_time (proc_stat_t ps, struct timeval *tv) { - *tv_out = proc_stat_thread_basic_info(ps)->user_time; - time_value_add(tv_out, &proc_stat_thread_basic_info(ps)->system_time); + time_value_t tvt = proc_stat_thread_basic_info (ps)->user_time; + time_value_add (&tvt, &proc_stat_thread_basic_info (ps)->system_time); + tv->tv_sec = tvt.seconds; + tv->tv_usec = tvt.microseconds; } struct ps_getter ps_tot_time_getter = {"tot_time", PSTAT_THREAD_BASIC, ps_get_tot_time}; @@ -427,150 +435,45 @@ ps_emit_nice_int (proc_stat_t ps, ps_getter_t getter, int width, sfx++; } - sprintf(buf + sprint_frac_value(buf, value, 1, frac, 3, ABS(width) - 1), + sprintf(buf + sprint_frac_value (buf, value, 1, frac, 3, ABS(width) - 1), "%c", *sfx); return ps_stream_write_field (stream, buf, width); } -#define MINUTE 60 -#define HOUR (60*MINUTE) -#define DAY (24*HOUR) -#define WEEK (7*DAY) - -static int -sprint_long_time(char *buf, int seconds, int width) +error_t +ps_emit_seconds (proc_stat_t ps, ps_getter_t getter, int width, + ps_stream_t stream) { - char *p = buf; - struct tscale - { - int length; - char *sfx; - char *short_sfx; - } - time_scales[] = - { - { WEEK, " week", "wk"} , - { DAY, " day", "dy"} , - { HOUR, " hour", "hr"} , - { MINUTE," min", "m"} , - { 0} - }; - struct tscale *ts = time_scales; - - while (ts->length > 0 && width > 0) - { - if (ts->length < seconds) - { - int len; - int num = seconds / ts->length; - seconds %= ts->length; - sprintf(p, "%d%s", num, ts->sfx); - len = strlen(p); - width -= len; - if (width < 0 && p > buf) - break; - p += len; - } - ts++; - } + char buf[20]; + struct timeval tv; - *p = '\0'; + G(getter, void)(ps, &tv); + + fmt_seconds (&tv, ABS (width), buf, sizeof (buf)); - return p - buf; + return ps_stream_write_field (stream, buf, width); } error_t -ps_emit_nice_seconds (proc_stat_t ps, ps_getter_t getter, int width, - ps_stream_t stream) +ps_emit_minutes (proc_stat_t ps, ps_getter_t getter, + int width, ps_stream_t stream) { char buf[20]; - time_value_t tv; + struct timeval tv; G(getter, int)(ps, &tv); - if (tv.seconds == 0) - { - if (tv.microseconds < 500) - sprintf(buf, "%dus", tv.microseconds); - else - strcpy(buf - + sprint_frac_value(buf, - tv.microseconds / 1000, 1, - tv.microseconds % 1000, 3, - ABS(width) - 2), - "ms"); - } - else if (tv.seconds < MINUTE) - sprint_frac_value(buf, tv.seconds, 1, tv.microseconds, 6, ABS(width)); - else if (tv.seconds < HOUR) - { - /* 0:00.00... */ - int min_len; - sprintf(buf, "%d:", tv.seconds / 60); - min_len = strlen(buf); - sprint_frac_value(buf + min_len, - tv.seconds % 60, 2, - tv.microseconds, 6, - ABS(width) - min_len); - } - else - sprint_long_time(buf, tv.seconds, width); + fmt_minutes (&tv, ABS (width), buf, sizeof (buf)); return ps_stream_write_field (stream, buf, width); } -static int -append_fraction(char *buf, int frac, int digits, int width) -{ - int slen = strlen(buf); - int left = width - strlen(buf); - if (left > 1) - { - buf[slen] = '.'; - left--; - while (digits > left) - frac /= 10, digits--; - sprintf(buf + slen + 1, "%0*d", digits, frac); - return slen + 1 + digits; - } - else - return slen; -} - error_t -ps_emit_seconds (proc_stat_t ps, ps_getter_t getter, int width, - ps_stream_t stream) +ps_emit_past_time (proc_stat_t ps, ps_getter_t getter, + int width, ps_stream_t stream) { - int max = (width == 0 ? 999 : ABS(width)); - char buf[20]; - time_value_t tv; - - G(getter, void)(ps, &tv); - - if (tv.seconds > DAY) - sprint_long_time(buf, tv.seconds, max); - else if (tv.seconds > HOUR) - if (max >= 8) - { - /* 0:00:00.00... */ - sprintf(buf, "%2d:%02d:%02d", - tv.seconds / HOUR, - (tv.seconds % HOUR) / MINUTE, (tv.seconds % MINUTE)); - append_fraction(buf, tv.microseconds, 6, max); - } - else - sprint_long_time(buf, tv.seconds, max); - else if (max >= 5 || tv.seconds > MINUTE) - { - /* 0:00.00... */ - sprintf(buf, "%2d:%02d", tv.seconds / MINUTE, tv.seconds % MINUTE); - append_fraction(buf, tv.microseconds, 6, max); - } - else - sprint_frac_value(buf, tv.seconds, 1, tv.microseconds, 6, max); - - return ps_stream_write_field (stream, buf, width); + } error_t @@ -694,9 +597,12 @@ struct state_shadow state_shadows[] = { /* Only show the longest sleep. */ { PSTAT_STATE_T_IDLE, PSTAT_STATE_T_SLEEP | PSTAT_STATE_T_WAIT }, { PSTAT_STATE_T_SLEEP, PSTAT_STATE_T_WAIT }, - /* Turn off the per-thread stop bits when the process is stopped, as - they're expected. */ - { PSTAT_STATE_P_STOP, PSTAT_STATE_T_HALT | PSTAT_STATE_T_UNCLEAN }, + /* Turn off the thread stop bits if any thread is not stopped. This is + generally reasonable, as threads are often suspended to be frobed; if + they're all suspended, then something's odd (probably in the debugger, + or crashed). */ + { PSTAT_STATE_T_STATES & ~PSTAT_STATE_T_HALT, + PSTAT_STATE_T_HALT | PSTAT_STATE_T_UNCLEAN }, { 0 } }; @@ -784,6 +690,23 @@ ps_cmp_strings(proc_stat_t ps1, proc_stat_t ps2, ps_getter_t getter) return GUARDED_CMP(s1, s2, strncmp(s1, s2, MIN(s1len, s2len))); } +int +ps_cmp_times (proc_stat_t ps1, proc_stat_t ps2, ps_getter_t getter) +{ + void (*g)() = G(getter, void); + struct timeval tv1, tv2; + + g (ps1, &tv1); + g (ps2, &tv2); + + return + tv1.tv_sec > tv2.tv_sec ? 1 + : tv1.tv_sec < tv2.tv_sec ? -1 + : tv1.tv_usec > tv2.tv_usec ? 1 + : tv2.tv_usec < tv2.tv_usec ? -1 + : 0; +} + /* ---------------------------------------------------------------- */ /* `Nominal' functions -- return true for `unexciting' values. */ @@ -835,87 +758,144 @@ ps_nominal_uid (proc_stat_t ps, ps_getter_t getter) /* ---------------------------------------------------------------- */ ps_fmt_spec_t -find_ps_fmt_spec(char *name, ps_fmt_spec_t specs) +ps_fmt_specs_find (ps_fmt_specs_t specs, char *name) { - while (!ps_fmt_spec_is_end(specs)) - if (strcasecmp(ps_fmt_spec_name(specs), name) == 0) - return specs; - else - specs++; - return NULL; + if (specs) /* Allow NULL to make recursion more handy. */ + { + ps_fmt_spec_t s = specs->specs; + + while (! ps_fmt_spec_is_end (s)) + { + char *alias = index (s->name, '='); + if (alias) + { + unsigned name_len = strlen (name); + + if (name_len == alias - s->name + && strncasecmp (name, s->name, name_len) == 0) + /* S is an alias, lookup what it refs to. */ + { + ps_fmt_spec_t src; /* What S is an alias to. */ + + ++alias; /* Point at the alias name. */ + + if (strcasecmp (name, alias) == 0) + /* An alias to the same name (useful to just change some + property) -- start looking up in the parent. */ + src = ps_fmt_specs_find (specs->parent, alias); + else + src = ps_fmt_specs_find (specs, alias); + + if (! src) + return 0; + + /* Copy fields into the alias entry. */ + if (! s->title && src->title) + s->title = src->title; + if (! s->width && src->width) + s->width = src->width; + if (! s->getter && src->getter) + s->getter = src->getter; + if (! s->output_fn && src->output_fn) + s->output_fn = src->output_fn; + if (! s->cmp_fn && src->cmp_fn) + s->cmp_fn = src->cmp_fn; + if (! s->nominal_fn && src->nominal_fn) + s->nominal_fn = src->nominal_fn; + + /* Now make this not an alias. */ + *--alias = '\0'; + + return s; + } + } + else + if (strcasecmp (s->name, name) == 0) + return s; + s++; + } + + /* Try again with our parent. */ + return ps_fmt_specs_find (specs->parent, name); + } + else + return 0; } /* ---------------------------------------------------------------- */ -struct ps_fmt_spec ps_std_fmt_specs[] = -{ - {"PID", - &ps_pid_getter, ps_emit_int, ps_cmp_ints, 0, -5}, - {"TH#", - &ps_thread_index_getter,ps_emit_int, ps_cmp_ints, 0, -2}, - {"PPID", - &ps_ppid_getter, ps_emit_int, ps_cmp_ints, 0, -5}, - {"UID", - &ps_owner_uid_getter, ps_emit_uid, ps_cmp_ints, ps_nominal_uid, -4}, - {"User", - &ps_owner_getter, ps_emit_uname, ps_cmp_unames, ps_nominal_user, 8}, - {"NTh", - &ps_num_threads_getter, ps_emit_int, ps_cmp_ints, ps_nominal_nth, -2}, - {"PGrp", - &ps_pgrp_getter, ps_emit_int, ps_cmp_ints, 0, -5}, - {"Sess", - &ps_session_getter, ps_emit_int, ps_cmp_ints, 0, -5}, - {"LColl", - &ps_login_col_getter, ps_emit_int, ps_cmp_ints, 0, -5}, - {"Args", - &ps_args_getter, ps_emit_string0, ps_cmp_strings,0, 0}, - {"Arg0", - &ps_args_getter, ps_emit_string, ps_cmp_strings,0, 0}, - {"Time", - &ps_tot_time_getter, ps_emit_seconds, ps_cmp_ints, 0, -8}, - {"UTime", - &ps_usr_time_getter, ps_emit_seconds, ps_cmp_ints, 0, -8}, - {"STime", - &ps_sys_time_getter, ps_emit_seconds, ps_cmp_ints, 0, -8}, - {"VSize", - &ps_vsize_getter, ps_emit_nice_int,ps_cmp_ints, 0, -5}, - {"RSize", - &ps_rsize_getter, ps_emit_nice_int,ps_cmp_ints, 0, -5}, - {"Pri", - &ps_cur_priority_getter,ps_emit_priority,ps_cmp_ints, ps_nominal_pri, -3}, - {"BPri", - &ps_base_priority_getter,ps_emit_priority,ps_cmp_ints, ps_nominal_pri, -3}, - {"MPri", - &ps_max_priority_getter,ps_emit_priority,ps_cmp_ints, ps_nominal_pri, -3}, - {"%Mem", - &ps_rmem_frac_getter, ps_emit_percent, ps_cmp_floats, 0, -4}, - {"%CPU", - &ps_cpu_frac_getter, ps_emit_percent, ps_cmp_floats, 0, -4}, - {"State", - &ps_state_getter, ps_emit_state, 0, 0, 4}, - {"RPC", - &ps_rpc_getter, ps_emit_nz_int, ps_cmp_ints, ps_nominal_zint,-6}, - {"Sleep", - &ps_sleep_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint,-2}, - {"Susp", - &ps_susp_count_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint,-2}, - {"PSusp", - &ps_proc_susp_count_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint,-2}, - {"TSusp", - &ps_thread_susp_count_getter, ps_emit_int,ps_cmp_ints, ps_nominal_zint,-2}, - {"TTY", - &ps_tty_getter, ps_emit_tty_name,ps_cmp_strings,0, 2}, - {"PgFlts", - &ps_page_faults_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint,-5}, - {"COWFlts", - &ps_cow_faults_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint,-5}, - {"PgIns", - &ps_pageins_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint,-5}, - {"MsgIn", - &ps_msgs_rcvd_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint,-5}, - {"MsgOut", - &ps_msgs_sent_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint,-5}, - {"ZFills", - &ps_zero_fills_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint,-5}, +static struct ps_fmt_spec +specs[] = +{ + {"PID", 0, -5, + &ps_pid_getter, ps_emit_int, ps_cmp_ints, 0}, + {"TH#", 0, -2, + &ps_thread_index_getter,ps_emit_int, ps_cmp_ints, 0}, + {"PPID", 0, -5, + &ps_ppid_getter, ps_emit_int, ps_cmp_ints, 0}, + {"UID", 0, -4, + &ps_owner_uid_getter, ps_emit_uid, ps_cmp_ints, ps_nominal_uid}, + {"User", 0, 8, + &ps_owner_getter, ps_emit_uname, ps_cmp_unames, ps_nominal_user}, + {"NTh", 0, -2, + &ps_num_threads_getter, ps_emit_int, ps_cmp_ints, ps_nominal_nth}, + {"PGrp", 0, -5, + &ps_pgrp_getter, ps_emit_int, ps_cmp_ints, 0}, + {"Sess", 0, -5, + &ps_session_getter, ps_emit_int, ps_cmp_ints, 0}, + {"LColl", 0, -5, + &ps_login_col_getter, ps_emit_int, ps_cmp_ints, 0}, + {"Args", 0, 0, + &ps_args_getter, ps_emit_string0, ps_cmp_strings,0}, + {"Arg0", 0, 0, + &ps_args_getter, ps_emit_string, ps_cmp_strings,0}, + {"Time", 0, -8, + &ps_tot_time_getter, ps_emit_seconds, ps_cmp_times, 0}, + {"UTime", 0, -8, + &ps_usr_time_getter, ps_emit_seconds, ps_cmp_times, 0}, + {"STime", 0, -8, + &ps_sys_time_getter, ps_emit_seconds, ps_cmp_times, 0}, + {"VSize", 0, -5, + &ps_vsize_getter, ps_emit_nice_int,ps_cmp_ints, 0}, + {"RSize", 0, -5, + &ps_rsize_getter, ps_emit_nice_int,ps_cmp_ints, 0}, + {"Pri", 0, -3, + &ps_cur_priority_getter,ps_emit_priority,ps_cmp_ints, ps_nominal_pri}, + {"BPri", 0, -3, + &ps_base_priority_getter,ps_emit_priority,ps_cmp_ints, ps_nominal_pri}, + {"MPri", 0, -3, + &ps_max_priority_getter,ps_emit_priority,ps_cmp_ints, ps_nominal_pri}, + {"%Mem", 0, -4, + &ps_rmem_frac_getter, ps_emit_percent, ps_cmp_floats, 0}, + {"%CPU", 0, -4, + &ps_cpu_frac_getter, ps_emit_percent, ps_cmp_floats, 0}, + {"State", 0, 4, + &ps_state_getter, ps_emit_state, 0, 0}, + {"RPC", 0, -6, + &ps_rpc_getter, ps_emit_nz_int, ps_cmp_ints, ps_nominal_zint}, + {"Sleep", 0, -2, + &ps_sleep_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, + {"Susp", 0, -2, + &ps_susp_count_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, + {"PSusp", 0, -2, + &ps_proc_susp_count_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, + {"TSusp", 0, -2, + &ps_thread_susp_count_getter, ps_emit_int,ps_cmp_ints, ps_nominal_zint}, + {"TTY", 0, 2, + &ps_tty_getter, ps_emit_tty_name,ps_cmp_strings,0}, + {"PgFlts", 0, -5, + &ps_page_faults_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, + {"COWFlts", 0, -5, + &ps_cow_faults_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, + {"PgIns", 0, -5, + &ps_pageins_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, + {"MsgIn", 0, -5, + &ps_msgs_rcvd_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, + {"MsgOut", 0, -5, + &ps_msgs_sent_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, + {"ZFills", 0, -5, + &ps_zero_fills_getter, ps_emit_int, ps_cmp_ints, ps_nominal_zint}, {0} }; + +struct ps_fmt_specs ps_std_fmt_specs = { specs, 0 }; |