Page MenuHomeFreeBSD

D49612.id152972.diff
No OneTemporary

D49612.id152972.diff

diff --git a/bin/ps/extern.h b/bin/ps/extern.h
--- a/bin/ps/extern.h
+++ b/bin/ps/extern.h
@@ -40,6 +40,7 @@
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 *);
@@ -54,6 +55,7 @@
const char *fmt_argv(char **, char *, char *, size_t);
double getpcpu(const KINFO *);
char *jailname(KINFO *, VARENT *);
+size_t keyword_index(const VAR *);
char *kvar(KINFO *, VARENT *);
char *label(KINFO *, VARENT *);
char *loginclass(KINFO *, VARENT *);
diff --git a/bin/ps/keyword.c b/bin/ps/keyword.c
--- a/bin/ps/keyword.c
+++ b/bin/ps/keyword.c
@@ -36,10 +36,12 @@
#include <sys/sysctl.h>
#include <sys/user.h>
+#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
#include <libxo/xo.h>
#include "ps.h"
@@ -224,6 +226,17 @@
USHORT, "x"},
};
+const size_t known_keywords_nb = nitems(var);
+
+size_t
+keyword_index(const VAR *const v)
+{
+ const size_t idx = v - var;
+
+ assert(idx < known_keywords_nb);
+ return (idx);
+}
+
void
showkey(void)
{
@@ -280,16 +293,6 @@
}
if (cp == NULL || !(v = findvar(cp, var_list, user, &hp)))
continue;
- if (!user) {
- /*
- * If the user is NOT adding this field manually,
- * get on with our lives if this VAR is already
- * represented in the list.
- */
- vent = find_varentry(v->name);
- if (vent != NULL)
- continue;
- }
if ((vent = malloc(sizeof(struct varent))) == NULL)
xo_errx(1, "malloc failed");
vent->header = v->header;
@@ -300,6 +303,7 @@
}
vent->width = strlen(vent->header);
vent->var = v;
+ vent->flags = user ? VE_KEEP : 0;
STAILQ_INSERT_TAIL(var_list, vent, next_ve);
}
free(tempstr1);
@@ -322,7 +326,7 @@
*hp++ = '\0';
key.name = p;
- v = bsearch(&key, var, nitems(var), sizeof(VAR), vcmp);
+ v = bsearch(&key, var, known_keywords_nb, sizeof(VAR), vcmp);
if (v && v->alias) {
/*
diff --git a/bin/ps/ps.h b/bin/ps/ps.h
--- a/bin/ps/ps.h
+++ b/bin/ps/ps.h
@@ -58,7 +58,9 @@
STAILQ_ENTRY(varent) next_ve;
const char *header;
const struct var *var;
- u_int width;
+ u_int width;
+#define VE_KEEP (1 << 0)
+ uint16_t flags;
} VARENT;
STAILQ_HEAD(velisthead, varent);
diff --git a/bin/ps/ps.c b/bin/ps/ps.c
--- a/bin/ps/ps.c
+++ b/bin/ps/ps.c
@@ -82,6 +82,19 @@
int termwidth; /* Width of the screen (0 == infinity). */
int showthreads; /* will threads be shown? */
+struct keyword_info {
+ /*
+ * Whether there is (at least) one column referencing this keyword that
+ * must be kept.
+ */
+#define KWI_HAS_MUST_KEEP_COLUMN (1 << 0)
+ /*
+ * Whether a column with such a keyword has been seen.
+ */
+#define KWI_SEEN (1 << 1)
+ u_int flags;
+};
+
struct velisthead varlist = STAILQ_HEAD_INITIALIZER(varlist);
static kvm_t *kd;
@@ -129,7 +142,8 @@
static char *kludge_oldps_options(const char *, char *, const char *);
static int pscomp(const void *, const void *);
static void saveuser(KINFO *);
-static void scanvars(void);
+static void scan_vars(struct keyword_info *);
+static void remove_redundant_columns(struct keyword_info *);
static void pidmax_init(void);
static void usage(void);
@@ -166,6 +180,7 @@
char fmtbuf[_POSIX2_LINE_MAX];
enum { NONE = 0, UP = 1, DOWN = 2, BOTH = 1 | 2 } directions = NONE;
struct { int traversed; int initial; } pid_count;
+ struct keyword_info *keywords_info;
(void) setlocale(LC_ALL, "");
time(&now); /* Used by routines in print.c. */
@@ -455,6 +470,22 @@
if (!_fmt)
parsefmt(dfmt, &varlist, 0);
+ keywords_info = calloc(known_keywords_nb, sizeof(struct keyword_info));
+ if (keywords_info == NULL)
+ xo_errx(1, "malloc failed");
+ /*
+ * Scan requested variables, noting which structures are needed and
+ * which keywords are specified.
+ */
+ scan_vars(keywords_info);
+ /*
+ * Remove redundant columns from "canned" displays (see the callee's
+ * herald comment for more details).
+ */
+ remove_redundant_columns(keywords_info);
+ free(keywords_info);
+ keywords_info = NULL;
+
if (!all && nselectors == 0) {
uidlist.l.ptr = malloc(sizeof(uid_t));
if (uidlist.l.ptr == NULL)
@@ -464,12 +495,6 @@
*uidlist.l.uids = getuid();
}
- /*
- * scan requested variables, noting what structures are needed,
- * and adjusting header widths as appropriate.
- */
- scanvars();
-
/*
* Get process list. If the user requested just one selector-
* option, then kvm_getprocs can be asked to return just those
@@ -1189,7 +1214,7 @@
}
static void
-scanvars(void)
+scan_vars(struct keyword_info *const keywords_info)
{
struct varent *vent;
const VAR *v;
@@ -1200,6 +1225,47 @@
needuser = 1;
if (v->flag & COMM)
needcomm = 1;
+ if ((vent->flags & VE_KEEP) != 0)
+ keywords_info[keyword_index(v)].flags |=
+ KWI_HAS_MUST_KEEP_COLUMN;
+ }
+}
+
+/*
+ * For each explicitly requested keyword, remove all the same keywords
+ * from "canned" displays. If the same keyword appears multiple times
+ * only in "canned displays", then keep the first (leftmost) occurence
+ * only (with the reasoning that columns requested first are the most
+ * important as their positions catch the eye more).
+ */
+static void
+remove_redundant_columns(struct keyword_info *const keywords_info)
+{
+ struct varent *prev_vent, *vent, *next_vent;
+
+ prev_vent = NULL;
+ STAILQ_FOREACH_SAFE(vent, &varlist, next_ve, next_vent) {
+ const VAR *const v = vent->var;
+ struct keyword_info *const kwi =
+ &keywords_info[keyword_index(v)];
+
+ /*
+ * If the current column is not marked as to absolutely keep,
+ * and we have either already output one with the same keyword
+ * or know we will output one later, remove it.
+ */
+ if ((vent->flags & VE_KEEP) == 0 &&
+ (kwi->flags & (KWI_HAS_MUST_KEEP_COLUMN | KWI_SEEN)) != 0) {
+ if (prev_vent == NULL)
+ STAILQ_REMOVE_HEAD(&varlist, next_ve);
+ else
+ STAILQ_REMOVE_AFTER(&varlist, prev_vent,
+ next_ve);
+ } else
+ prev_vent = vent;
+
+
+ kwi->flags |= KWI_SEEN;
}
}

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 23, 1:09 PM (38 m, 34 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35403027
Default Alt Text
D49612.id152972.diff (5 KB)

Event Timeline