diff options
author | Craig Small <csmall@dropbear.xyz> | 2023-01-18 17:46:06 +1100 |
---|---|---|
committer | Craig Small <csmall@dropbear.xyz> | 2023-01-18 17:46:06 +1100 |
commit | 2532b5d2ddf9158fdec488a25234155be6153aa5 (patch) | |
tree | d311f1d17ac875b196dab6b5b2fb3b58eb67cb32 /src | |
parent | bfe65a2cce8f2536e673b7ebbef84f4397b40f8a (diff) | |
download | procps-ng-2532b5d2ddf9158fdec488a25234155be6153aa5.tar.gz |
ps: Add configurable date format for lstart field
The lstart field has been converted to use the strftime()
function so that it uses the locale. A new option -D
allows the user to define the format that would want this
field to show.
This may mean the field will be longer than it should be,
especially for French locales and the user defined field,
but the field length can be specified too.
---
This commit started off making all the relevant fields use the
locale correctly so it could solve #226 as well. The issue
is there an implied restriction (or not) around
strftime("%b") and probably strftime("%a") for abbrievated month
and day names respectively.
English, and some/most other languages put an additional
restriction that all abbreviations are 3 characters long.
The problem is, not all languages do this.
French is a good example:
janv. févr. mars avril mai juin juil. août sept. oct. nov. déc.
Maybe strip the . at the end?
That helps for some months, not all
Maybe take the first three characters?
Several wide languages will have big issues
Maybe convert wide, get wcslen then use that.
Even after that June "juin" and July "juil" are both "jui".
So, anything that uses the month (bsdstart,start) use ctime which
doesn't use locale. That solves the length issue.
stime does, which means it has this issue but its been like that
for years. You get stuff like this:
janv.13 482261
00:00 1151918
2022 1458628
06:12 1957584
The only way to fix that would be to
a)Make the field two characters longer
b)Convert it back to ctime() which means everyone else
loses.
This could have be oh-so easy if everyone made %b and %a three
(wide) characters everywhere.
References:
procps-ng/procps#228
procps-ng/procps#226
Signed-off-by: Craig Small <csmall@dropbear.xyz>
Diffstat (limited to 'src')
-rw-r--r-- | src/ps/common.h | 1 | ||||
-rw-r--r-- | src/ps/global.c | 1 | ||||
-rw-r--r-- | src/ps/help.c | 1 | ||||
-rw-r--r-- | src/ps/output.c | 16 | ||||
-rw-r--r-- | src/ps/parser.c | 14 |
5 files changed, 30 insertions, 3 deletions
diff --git a/src/ps/common.h b/src/ps/common.h index 26bd38c..6e416a3 100644 --- a/src/ps/common.h +++ b/src/ps/common.h @@ -451,6 +451,7 @@ extern int header_gap; extern int header_type; /* none, single, multi... */ extern int include_dead_children; extern int lines_to_next_header; +extern char *lstart_format; extern int max_line_width; extern int negate_selection; extern int page_size; // "int" for math reasons? diff --git a/src/ps/global.c b/src/ps/global.c index db67a78..826ca92 100644 --- a/src/ps/global.c +++ b/src/ps/global.c @@ -183,6 +183,7 @@ int header_gap = -1; int header_type = -1; int include_dead_children = -1; int lines_to_next_header = -1; +char *lstart_format = NULL; int negate_selection = -1; int running_only = -1; int page_size = -1; // "int" for math reasons? diff --git a/src/ps/help.c b/src/ps/help.c index b64833d..dfd602d 100644 --- a/src/ps/help.c +++ b/src/ps/help.c @@ -126,6 +126,7 @@ void do_help (const char *opt, int rc) { } if (section == HELP_OUT || section == HELP_ALL) { fputs(_("\nOutput formats:\n"), out); + fputs(_(" -D <format> date format for lstart\n"), out); fputs(_(" -F extra full\n"), out); fputs(_(" -f full-format, including command lines\n"), out); fputs(_(" f, --forest ascii art process tree\n"), out); diff --git a/src/ps/output.c b/src/ps/output.c index 26001a6..3074549 100644 --- a/src/ps/output.c +++ b/src/ps/output.c @@ -1044,11 +1044,21 @@ setREL1(VM_RSS) return snprintf(outbuf, COLWID, "%2u.%u", (unsigned)(pmem/10), (unsigned)(pmem%10)); } +// Format cannot be %c as the length changes depending on locale +#define DEFAULT_LSTART_FORMAT "%a %b %e %H:%M:%S %Y" static int pr_lstart(char *restrict const outbuf, const proc_t *restrict const pp){ - time_t t; + time_t t; + struct tm start_time; + size_t len; setREL1(TICS_BEGAN) - t = boot_time() + rSv(TICS_BEGAN, ull_int, pp) / Hertz; - return snprintf(outbuf, COLWID, "%24.24s", ctime(&t)); + t = boot_time() + rSv(TICS_BEGAN, ull_int, pp) / Hertz; + if (localtime_r(&t, &start_time) == NULL) + return 0; + len = strftime(outbuf, COLWID, + (lstart_format?lstart_format:DEFAULT_LSTART_FORMAT), &start_time); + if (len <= 0 || len >= COLWID) + outbuf[len = 0] = '\0'; + return len; } /* Unix98 specifies a STIME header for a column that shows the start diff --git a/src/ps/parser.c b/src/ps/parser.c index b836241..544f736 100644 --- a/src/ps/parser.c +++ b/src/ps/parser.c @@ -244,6 +244,13 @@ static const char *parse_sysv_option(void){ if(err) return err; selection_list->typecode = SEL_COMM; return NULL; /* can't have any more options */ + case 'D': + trace("-D sets lstart date format\n"); + arg = get_opt_arg(); + if (!arg) return _("date format must follow -D"); + if (lstart_format) free(lstart_format); + lstart_format = strdup(arg); + break; case 'F': /* DYNIX/ptx -f plus sz,rss,psr=ENG between c and stime */ trace("-F does fuller listing\n"); format_modifiers |= FM_F; @@ -794,6 +801,7 @@ static const char *parse_gnu_option(void){ {"columns", &&case_columns}, {"context", &&case_context}, {"cumulative", &&case_cumulative}, + {"date-format", &&case_dateformat}, {"deselect", &&case_deselect}, /* -N */ {"forest", &&case_forest}, /* f -H */ {"format", &&case_format}, @@ -881,6 +889,12 @@ static const char *parse_gnu_option(void){ if(s[sl]) return _("option --cumulative does not take an argument"); include_dead_children = 1; return NULL; + case_dateformat: + arg=grab_gnu_arg(); + if (!arg) return _("date format must follow --date-format"); + if (lstart_format) free(lstart_format); + lstart_format = strdup(arg); + return NULL; case_deselect: trace("--deselect\n"); if(s[sl]) return _("option --deselect does not take an argument"); |