Date: Mon, 28 Apr 2025 12:23:32 GMT From: Olivier Certner <olce@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 5dad61d9b949 - main - ps(1): Make '-O' more versatile and predictable Message-ID: <202504281223.53SCNWCf025505@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=5dad61d9b949bb859450266c6accebc106f50fcc commit 5dad61d9b949bb859450266c6accebc106f50fcc Author: Olivier Certner <olce@FreeBSD.org> AuthorDate: 2025-03-07 10:50:46 +0000 Commit: Olivier Certner <olce@FreeBSD.org> CommitDate: 2025-04-28 11:58:47 +0000 ps(1): Make '-O' more versatile and predictable The ps(1) display's list of columns is now first built without taking into account the '-O' options. In a second step, all columns passed via '-O' are finally inserted after the built-so-far display's first PID column (if it exists, else at start), in their order of appearance as arguments to the '-O' options. This new two-step procedure suppresses the following undesirable behaviors: - '-O' used to insert the columns of the default display even if the user also passed other options to request specific columns. - Each occurence of '-O' beyond the first would just insert the passed keywords after those requested by the previous options, as if by '-o', inconsistently with the behavior for the first occurence. These behaviors had more annoying consequences: - Where the columns of some '-O' occurence appear in the display used to depend on the actual position of '-O' with respect to other options, despite the natural expectation that they should go near a single PID column considered as an anchor regardless of other options adding columns. - Columns specified with multiple '-O' options would not be grouped together. - It used to be impossible to specify custom headers but for the last column for columns that are next to each other (i.e., specified by a single '-O' occurence). which are now all lifted. With these changes, '-O' can still be used alone to amend the default display, but can now be used also in conjunction with any specific display, and in particular "canned" ones invoked by '-j', '-l', '-u' or '-v'. ****** This part discusses other ps(1) implementations' behaviors and compares them to the one established by this change. NetBSD seems to be the only other BSD having refined the meaning of ps(1)'s '-O' option. While the behavior there is similar to the new one here on the surface, it differs on the following points: 1. If no options requesting a specific display are present before the first '-O' option, the appearance of '-O' triggers the insertion of the default display, regardless of whether such specific display options appear *after* it. 2. If options requesting a specific display appear before the first '-O' and none specify a PID column, columns listed in the first '-O' are appended to them (as '-o' would do), but columns passed by further '-O' options are then inserted next to the columns of the first '-O' options. Behavior of point 1 seems to have only one advantage: To allow to customize the default display by first using '-O' and then other options appending to it, but as the default display finishes with the COMMAND column, it is unlikely that one wants to use '-o' or other specific display options after '-O' (NetBSD's ps(1) does not suppress duplicate columns). A much simpler and easy-to-understand way to reach that effect in FreeBSD, if it really proves useful, would be to introduce a new explicit option that inserts the default display. The column-appending behavior of the first '-O' option in point 2 can be also achieved by using '-o' instead. As '-O' is used to insert columns after the PID one, which is located near the left in the default and all "canned" displays, we found it more consistent and practical to push its columns completely to the left on the absence of a PID column. The effect of multiple '-O' options in NetBSD when no PID column has been requested beforehand is also cumbersome and inconsistent with the documentation (it is likely a bug). Both NetBSD-specific behaviors exposed above also have the disadvantage that the position of '-O' options with respect to other ones is meaningful in ways that are not obvious and that are arguably not desirable as '-O' is meant to append columns after an anchor (the PID column). Linux's procps-ng's ps(1) is very limited in its handling of '-O', and more generally when mixing options tweaking the display. '-O' causes insertion of the default display (like NetBSD does). If '-o' options are specified, '-O' must come before them. '-O' is not usable with canned display options. Additionally, only one '-O' option may appear on the command line, limiting header customization. The only case in which these implementations and ours behave in the same way with respect to '-O' is if only a single '-O' option and no other options changing the display are specified. MFC after: 3 days Relnotes: yes Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D49615 (code) Differential Revision: https://reviews.freebsd.org/D49616 (manual page) --- bin/ps/ps.1 | 31 ++++++++++--------------------- bin/ps/ps.c | 28 ++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 index 801b089820c7..2e25249c2e76 100644 --- a/bin/ps/ps.1 +++ b/bin/ps/ps.1 @@ -125,9 +125,7 @@ First, options .Fl o and .Fl O -add columns with data corresponding to the explicitly passed keywords and, for -.Fl O , -additionally the same columns as in the default display. +add columns with data corresponding to the explicitly passed keywords. Available keywords are documented in the .Sx KEYWORDS section below. @@ -327,15 +325,15 @@ terminal and process ID. Extract the name list from the specified system instead of the default, which is the kernel image the system has booted from. .It Fl O -On first occurence, add all columns of the default display -.Po -as if by -.Fl o -.Pc -and insert just after the process ID column in that default display the columns -associated with the passed space- or comma-separated list of keywords. -On next occurences, just insert the keywords of the passed list, as if by -.Fl o . +Save passed columns in a separate list that in the end is grafted just after the +display's first occurence of the process ID column as specified by other +options, or the default display if there is none. +If the display prepared by other options does not include a process ID column, +the list is inserted at start of the display. +Further occurences of +.Fl O +append to the to-be-grafted list of columns. +This option takes a space- or comma-separated list of keywords. The last keyword in the list may be appended with an equals sign .Pq Ql = as explained for option @@ -1023,15 +1021,6 @@ implementation (for other BSDs, illumos or Linux) behaves like this. For all these reasons, the behavior is expected to be changed soon to using the effective user ID instead. .Pp -Option -.Fl O -has not been designed to be combined with other options as it forces insertion -of the default display on first occurence. -Moreover, these default display's columns are then not considered for duplicate -elimination, contrary to those of canned displays. -Finally, columns requested through multiple occurences are not grouped together, -as one may naturally expect. -.Pp The .Fl a option has no effect if other options affecting the selection of processes are diff --git a/bin/ps/ps.c b/bin/ps/ps.c index 0a4a289a6a63..48839cd00837 100644 --- a/bin/ps/ps.c +++ b/bin/ps/ps.c @@ -96,6 +96,7 @@ struct keyword_info { }; struct velisthead varlist = STAILQ_HEAD_INITIALIZER(varlist); +static struct velisthead Ovarlist = STAILQ_HEAD_INITIALIZER(Ovarlist); static kvm_t *kd; static int needcomm; /* -o "command" */ @@ -151,8 +152,6 @@ static const char dfmt[] = "pid,tt,state,time,command"; static const char jfmt[] = "user,pid,ppid,pgid,sid,jobc,state,tt,time,command"; static const char lfmt[] = "uid,pid,ppid,cpu,pri,nice,vsz,rss,mwchan,state," "tt,time,command"; -static const char o1[] = "pid"; -static const char o2[] = "tt,state,time,command"; static const char ufmt[] = "user,pid,%cpu,%mem,vsz,rss,tt,state,start,time,command"; static const char vfmt[] = "pid,state,time,sl,re,pagein,vsz,rss,lim,tsiz," "%cpu,%mem,command"; @@ -334,10 +333,7 @@ main(int argc, char *argv[]) nlistf = optarg; break; case 'O': - parsefmt(o1, &varlist, 1); - parsefmt(optarg, &varlist, 1); - parsefmt(o2, &varlist, 1); - _fmt = 1; + parsefmt(optarg, &Ovarlist, 1); break; case 'o': parsefmt(optarg, &varlist, 1); @@ -471,6 +467,26 @@ main(int argc, char *argv[]) if (!_fmt) parsefmt(dfmt, &varlist, 0); + if (!STAILQ_EMPTY(&Ovarlist)) { + VARENT *const pid_entry = find_varentry("pid"); + + /* + * We insert the keywords passed by '-O' after the process ID if + * specified, else at start. + */ + if (pid_entry != NULL) { + struct velisthead rest; + + STAILQ_SPLIT_AFTER(&varlist, pid_entry, &rest, next_ve); + STAILQ_CONCAT(&varlist, &Ovarlist); + STAILQ_CONCAT(&varlist, &rest); + } + else { + STAILQ_SWAP(&varlist, &Ovarlist, varent); + STAILQ_CONCAT(&varlist, &Ovarlist); + } + } + keywords_info = calloc(known_keywords_nb, sizeof(struct keyword_info)); if (keywords_info == NULL) xo_errx(1, "malloc failed");
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202504281223.53SCNWCf025505>