freebsd-src/bin/ps/extern.h
Olivier Certner cd768a8406
ps(1): Remove not-explicitly-requested columns with duplicate data
Before this change, when stacking up more columns in the display through
command-line options, if user requested to add some "canned" display
(through options '-j', '-l', '-u' or '-v'), columns in it that were
"duplicates" of already requested ones (meaning that they share the same
keyword, regardless of whether their headers have been customized) were
in the end omitted.

However, this mechanism did not work the other way around, i.e.,
requesting some canned display(s) first and then adding some columns
that are duplicates (through '-o' or '-O') would not remove them from
the canned display.  Additionally, it did not take into account keyword
aliases (which also lead to displaying the same information).

This whole mechanism of removing columns from requested canned displays
when there are duplicates is useful in a number of scenarios:
1. When one wants the columns of a canned display, but with some of them
   in a different order and at the edges of the bulk.  This needs the
   change here to move columns after the bulk (previously, only moving
   them before the bulk would work).
2. To combine multiple canned displays to get more information without
   repeating common columns. This part has been working before and
   this behavior is unchanged.
3. In combination with requesting a canned display and additional
   columns after it, ensure that a single COMMAND column appears at the
   end of the display (to benefit from the fact that a last COMMAND
   column can extend further to the right).

Point 2 above implies that, when multiple canned displays are requested,
we should keep the leftmost column with same keyword.  However, columns
requested explicitly by '-o' have priority (as the natural extension of
point 1's behavior before this change), and in this case all matching
columns in canned displays must be suppressed.

To this end, when adding requested options to the display's list, we
stop trying to find an earlier matching column (which is incidentally
a O(n²) algorithm).  Instead, we do a first pass over all requested
options once they have all been added to the display's list (in
scan_vars()).  For each keyword, we note if it was requested at least
once explicitly (through '-o' or '-O'), in addition to setting
'needuser' and 'needcomm' (as before).  Then, a second pass decides
whether to keep each column.  A column is removed if it should not be
kept absolutely (i.e., it wasn't specified via '-o' or '-O') and there
is either a matching column that must be kept (determined during the
first pass), or we have seen one already (earlier canned displays take
precedence).

Matching columns are in fact not only those that have same keywords, but
also those that have keywords determined to be aliases to each other.
Some previous commits ensured that this determination is O(1) and in
practice just a few assembly instructions.

find_varentry() has been kept although its last caller has been removed
as next commit will reintroduce a call to it.

MFC after:      3 days
Relnotes:       yes
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D49612
Differential Revision:  https://reviews.freebsd.org/D49613 (manual page)
2025-04-28 13:57:52 +02:00

95 lines
3.6 KiB
C

/*-
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
struct kinfo;
struct nlist;
struct var;
struct varent;
extern fixpt_t ccpu;
extern int cflag, eval, fscale, nlistread, rawcpu;
extern unsigned long mempages;
extern time_t now;
extern int showthreads, sumrusage, termwidth;
extern struct velisthead varlist;
extern const size_t known_keywords_nb;
__BEGIN_DECLS
char *arguments(KINFO *, VARENT *);
void check_keywords(void);
char *command(KINFO *, VARENT *);
char *cputime(KINFO *, VARENT *);
char *cpunum(KINFO *, VARENT *);
int donlist(void);
char *elapsed(KINFO *, VARENT *);
char *elapseds(KINFO *, VARENT *);
char *emulname(KINFO *, VARENT *);
VARENT *find_varentry(const char *);
const char *fmt_argv(char **, char *, char *, size_t);
double getpcpu(const KINFO *);
char *jailname(KINFO *, VARENT *);
size_t aliased_keyword_index(const VAR *);
char *kvar(KINFO *, VARENT *);
char *label(KINFO *, VARENT *);
char *loginclass(KINFO *, VARENT *);
char *logname(KINFO *, VARENT *);
char *longtname(KINFO *, VARENT *);
char *lstarted(KINFO *, VARENT *);
char *maxrss(KINFO *, VARENT *);
char *lockname(KINFO *, VARENT *);
char *mwchan(KINFO *, VARENT *);
char *nwchan(KINFO *, VARENT *);
char *pagein(KINFO *, VARENT *);
void parsefmt(const char *, struct velisthead *, int);
char *pcpu(KINFO *, VARENT *);
char *pmem(KINFO *, VARENT *);
char *pri(KINFO *, VARENT *);
void printheader(void);
char *priorityr(KINFO *, VARENT *);
char *egroupname(KINFO *, VARENT *);
char *rgroupname(KINFO *, VARENT *);
void resolve_aliases(void);
char *runame(KINFO *, VARENT *);
char *rvar(KINFO *, VARENT *);
void showkey(void);
char *started(KINFO *, VARENT *);
char *state(KINFO *, VARENT *);
char *systime(KINFO *, VARENT *);
char *tdev(KINFO *, VARENT *);
char *tdnam(KINFO *, VARENT *);
char *tname(KINFO *, VARENT *);
char *ucomm(KINFO *, VARENT *);
char *username(KINFO *, VARENT *);
char *upr(KINFO *, VARENT *);
char *usertime(KINFO *, VARENT *);
char *vsize(KINFO *, VARENT *);
char *wchan(KINFO *, VARENT *);
__END_DECLS