Skip site navigation (1)Skip section navigation (2)
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>