]> granicus.if.org Git - procps-ng/commitdiff
library: eliminated a final potential NULL, <PIDS> api
authorJim Warner <james.warner@comcast.net>
Thu, 19 May 2016 05:00:00 +0000 (00:00 -0500)
committerCraig Small <csmall@dropbear.xyz>
Sun, 22 May 2016 11:59:18 +0000 (21:59 +1000)
In that reference below a specific systemd problem was
fixed in the commit shown. However lurking deep within
the <pids> interface was yet one final case where NULL
could be returned, involving 'strv' and the following:

. a user requested both a single string vector (always
returned as a normal string) & the vectorized version,
as with PROCPS_PIDS_CMDLINE and PROCPS_PIDS_CMDLINE_V.

. a user simply duplicated some vectorized enum items.

The root of that NULL problem is the fact those single
string vectors shared the same proc_t field with their
true vectorized version. So while multiple occurrences
for most strings could be satisfied with strdup versus
the normal ownership usurpation, those true vectorized
fields could not be quite so easily copied/duplicated.

Thus newlib chose to return a NULL result.strv pointer
under either of the above scenarios (which perhaps was
just a user boo-boo in the first place). In any event,
the NULL was a potential for true string vectors only.

Now, since newlib is the sole caller into the readproc
module, separate fields have been created for what are
just normal strings (never vectorized) and those which
remain the true vectorized versions. And, former flags
which only worked if combined, now act as stand alone.

Thus, both PROCPS_PIDS_CMDLINE & PROCPS_PIDS_CMDLINE_V
can be used simultaneously (as they should have been).

Also with this patch, items which a user duplicates in
the stack (beyond the first such item) will return the
the string "[ duplicate ENUM_ID ]". This practice will
apply to both single strings and true vectorized ones.
In addition to informing users of their error, it will
also mean potential NULLs need now never be a concern.

Reference(s);
http://www.freelists.org/post/procps/systemd-binary-vs-library
commit 0580a7b4c67d0297629d37281b4f690894429626

Signed-off-by: Jim Warner <james.warner@comcast.net>
proc/pids.c
proc/readproc.c
proc/readproc.h

index 658f0524844be20ec3e212bb34b3e9896d1e9c27..e921b096894769ad548ae003079cc945cd149819 100644 (file)
 #define FILL_ID_MAX  255               // upper limit for pid/uid fills
 #define MEMORY_INCR  128               // amt by which allocations grow
 
-    // these represent the proc_t fields whose storage cannot be managed
-    // optimally if they are ever referenced more than once in any stack
-enum rel_ref {
-    ref_CGROUP,   ref_CMD,     ref_CMDLINE,   ref_ENVIRON,  ref_SD_MACH,
-    ref_SD_OUID,  ref_SD_SEAT, ref_SD_SESS,   ref_SD_SLICE, ref_SD_UNIT,
-    ref_SD_UUNIT, ref_SUPGIDS, ref_SUPGROUPS,
-    MAXIMUM_ref
-};
 
 struct stacks_extent {
     struct pids_stack **stacks;
@@ -89,7 +81,6 @@ struct procps_pidsinfo {
     PROCTAB *PT;                       // the old library essential interface
     unsigned long hertz;               // for TIME_ALL & TIME_ELAPSED calculations
     unsigned long long boot_seconds;   // for TIME_ELAPSED calculation
-    int ref_counts[MAXIMUM_ref];       // ref counts for special string fields
     PROCTAB *get_PT;                   // old library interface for active 'get'
     struct stacks_extent *get_ext;     // an extent used for active 'get'
     enum pids_fetch_type get_type;     // last known type of 'get' request
@@ -98,37 +89,51 @@ struct procps_pidsinfo {
 
 // ___ Results 'Set' Support ||||||||||||||||||||||||||||||||||||||||||||||||||
 
+static char** vectorize_this (const char* src) {
+ #define pSZ  (sizeof(char*))
+    char *cpy, **vec;
+    int adj, tot;
+
+    tot = strlen(src) + 1;                       // prep for our vectors
+    adj = (pSZ-1) - ((tot + pSZ-1) & (pSZ-1));   // calc alignment bytes
+    cpy = calloc(1, tot + adj + (2 * pSZ));      // get new larger buffer
+    if (!cpy) return NULL;                       // we no longer use xcalloc
+    snprintf(cpy, tot, "%s", src);               // duplicate their string
+    vec = (char**)(cpy + tot + adj);             // prep pointer to pointers
+    *vec = cpy;                                  // point 1st vector to string
+    *(vec+1) = NULL;                             // null ptr 'list' delimit
+    return vec;                                  // ==> free(*vec) to dealloc
+ #undef pSZ
+} // end: vectorize_this
+
+
+#define mkSTR(a) xySTR(a)
+#define xySTR(z) #z
+
 #define setNAME(e) set_results_ ## e
 #define setDECL(e) static void setNAME(e) \
     (struct procps_pidsinfo *I, struct pids_result *R, proc_t *P)
 
-// convert pages to kib
+/* convert pages to kib */
 #define CVT_set(e,t,x) setDECL(e) { \
     R->result. t = (long)(P-> x) << I -> pgs2k_shift; }
-// strdup of a static char array
+/* strdup of a static char array */
 #define DUP_set(e,x) setDECL(e) { \
     (void)I; R->result.str = strdup(P-> x); }
-// regular assignment copy
+/* regular assignment copy */
 #define REG_set(e,t,x) setDECL(e) { \
     (void)I; R->result. t = P-> x; }
-// take ownership of a regular char* string if possible, else duplicate
+/* take ownership of a normal single string if possible, else return
+   some sort of hint that they duplicated this char * item ... */
 #define STR_set(e,x) setDECL(e) { \
-    if (I->ref_counts[ref_ ## e] > 1) R->result.str = strdup(P-> x); \
-    else { R->result.str = P-> x; P-> x = NULL; } }
-// take ownership of a vectorized single string if possible, else duplicate
-#define STV_set(e,x) setDECL(e) { \
-    if (I->ref_counts[ref_ ## e] > 1) R->result.str = strdup(*P-> x); \
-    else { R->result.str = *P-> x; P-> x = NULL; } }
-/*
-   take ownership of true vectorized strings if possible, else return NULL
-   [ if there's a source field ref_count, then those true string vectors ]
-   [ have already been converted into a single string so we return NULL. ]
-   [ otherwise, the first result struct now gets ownership of those true ]
-   [ string vectors and any duplicate structures will then receive NULL. ]
-*/
-#define VEC_set(e1,e2,x) setDECL(e1) { \
-    if (I->ref_counts[ref_ ## e2]) R->result.strv = NULL; \
-    else { R->result.strv = P-> x; P-> x = NULL; } }
+    (void)I; if (NULL != P-> x) { R->result.str = P-> x; P-> x = NULL; } \
+    else R->result.str = strdup("[ duplicate " mkSTR(e) " ]"); }
+/* take ownership of true vectorized strings if possible, else return
+   some sort of hint that they duplicated this char ** item ... */
+#define VEC_set(e,x) setDECL(e) { \
+    (void)I; if (NULL != P-> x) { R->result.strv = P-> x;  P-> x = NULL; } \
+    else R->result.strv = vectorize_this("[ duplicate " mkSTR(e) " ]"); }
+
 
 setDECL(noop)         { (void)I; (void)R; (void)P; return; }
 setDECL(extra)        { (void)I; (void)R; (void)P; return; }
@@ -138,14 +143,14 @@ REG_set(ADDR_KSTK_ESP,    ul_int,  kstk_esp)
 REG_set(ADDR_START_CODE,  ul_int,  start_code)
 REG_set(ADDR_START_STACK, ul_int,  start_stack)
 REG_set(ALARM,            sl_int,  alarm)
-setDECL(CGNAME)       { char *name = strstr(*P->cgroup, ":name="); if (name && *(name+6)) name += 6; else name = *P->cgroup; R->result.str = strdup(name); }
-STV_set(CGROUP,                    cgroup)
-VEC_set(CGROUP_V,     CGROUP,      cgroup)
+STR_set(CGNAME,                    cgname)
+STR_set(CGROUP,                    cgroup)
+VEC_set(CGROUP_V,                  cgroup_v)
 STR_set(CMD,                       cmd)
-STV_set(CMDLINE,                   cmdline)
-VEC_set(CMDLINE_V,    CMDLINE,     cmdline)
-STV_set(ENVIRON,                   environ)
-VEC_set(ENVIRON_V,    ENVIRON,     environ)
+STR_set(CMDLINE,                   cmdline)
+VEC_set(CMDLINE_V,                 cmdline_v)
+STR_set(ENVIRON,                   environ)
+VEC_set(ENVIRON_V,                 environ_v)
 REG_set(EXIT_SIGNAL,      s_int,   exit_signal)
 REG_set(FLAGS,            ul_int,  flags)
 REG_set(FLT_MAJ,          sl_int,  maj_flt)
@@ -249,12 +254,15 @@ REG_set(VSIZE_PGS,        ul_int,  vsize)
 REG_set(WCHAN_ADDR,       ul_int,  wchan)
 setDECL(WCHAN_NAME)   { (void)I; R->result.str = strdup(lookup_wchan(P->tid)); }
 
+
+#undef mkSTR
+#undef xySTR
+
 #undef setDECL
 #undef CVT_set
 #undef DUP_set
 #undef REG_set
 #undef STR_set
-#undef STV_set
 #undef VEC_set
 
 
@@ -347,14 +355,15 @@ static int srtNAME(noop) (
 #define f_status   PROC_FILLSTATUS
 #define f_systemd  PROC_FILLSYSTEMD
 #define f_usr      PROC_FILLUSR
+   // these next three will yield a single string (never vectorized)
+#define x_cgroup   PROC_EDITCGRPCVT
+#define x_cmdline  PROC_EDITCMDLCVT
+#define x_environ  PROC_EDITENVRCVT
    // these next three will yield true verctorized strings
 #define v_arg      PROC_FILLARG
 #define v_cgroup   PROC_FILLCGROUP
 #define v_env      PROC_FILLENV
-   // remaining are compound flags, yielding a single string (maybe vectorized)
-#define x_cgroup   PROC_EDITCGRPCVT | PROC_FILLCGROUP           // just 1 str
-#define x_cmdline  PROC_EDITCMDLCVT | PROC_FILLARG              // just 1 str
-#define x_environ  PROC_EDITENVRCVT | PROC_FILLENV              // just 1 str
+   // remaining are compound flags
 #define x_ogroup   PROC_FILLSTATUS  | PROC_FILLGRP
 #define x_ouser    PROC_FILLSTATUS  | PROC_FILLUSR
 #define x_supgrp   PROC_FILLSTATUS  | PROC_FILLSUPGRP
@@ -378,130 +387,129 @@ static struct {
     FRE_t    freefunc;            // free function for strings storage
     QSR_t    sortfunc;            // sort cmp func for a specific type
     int      needhist;            // a result requires history support
-    int      refcount;            // the result needs reference counts
 } Item_table[] = {
-/*    setsfunc               oldflags    freefunc   sortfunc      needhist  refcount
-      ---------------------  ----------  ---------  ------------  --------  ------------- */
-    { RS(noop),              0,          NULL,      QS(noop),     0,        -1            }, // user only, never altered
-    { RS(extra),             0,          NULL,      QS(ull_int),  0,        -1            }, // user only, reset to zero
-    { RS(ADDR_END_CODE),     f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(ADDR_KSTK_EIP),     f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(ADDR_KSTK_ESP),     f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(ADDR_START_CODE),   f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(ADDR_START_STACK),  f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(ALARM),             f_stat,     NULL,      QS(sl_int),   0,        -1            },
-    { RS(CGNAME),            x_cgroup,   FF(str),   QS(str),      0,        ref_CGROUP    }, // refcount: diff result, same source
-    { RS(CGROUP),            x_cgroup,   FF(str),   QS(str),      0,        ref_CGROUP    }, // refcount: diff result, same source
-    { RS(CGROUP_V),          v_cgroup,   FF(strv),  QS(strv),     0,        -1            },
-    { RS(CMD),               f_either,   FF(str),   QS(str),      0,        ref_CMD       },
-    { RS(CMDLINE),           x_cmdline,  FF(str),   QS(str),      0,        ref_CMDLINE   },
-    { RS(CMDLINE_V),         v_arg,      FF(strv),  QS(strv),     0,        -1            },
-    { RS(ENVIRON),           x_environ,  FF(str),   QS(str),      0,        ref_ENVIRON   },
-    { RS(ENVIRON_V),         v_env,      FF(strv),  QS(strv),     0,        -1            },
-    { RS(EXIT_SIGNAL),       f_stat,     NULL,      QS(s_int),    0,        -1            },
-    { RS(FLAGS),             f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(FLT_MAJ),           f_stat,     NULL,      QS(sl_int),   0,        -1            },
-    { RS(FLT_MAJ_C),         f_stat,     NULL,      QS(sl_int),   0,        -1            },
-    { RS(FLT_MAJ_DELTA),     f_stat,     NULL,      QS(sl_int),   +1,       -1            },
-    { RS(FLT_MIN),           f_stat,     NULL,      QS(sl_int),   0,        -1            },
-    { RS(FLT_MIN_C),         f_stat,     NULL,      QS(sl_int),   0,        -1            },
-    { RS(FLT_MIN_DELTA),     f_stat,     NULL,      QS(sl_int),   +1,       -1            },
-    { RS(ID_EGID),           0,          NULL,      QS(u_int),    0,        -1            }, // oldflags: free w/ simple_read...
-    { RS(ID_EGROUP),         f_grp,      NULL,      QS(str),      0,        -1            },
-    { RS(ID_EUID),           0,          NULL,      QS(u_int),    0,        -1            }, // oldflags: free w/ simple_read...
-    { RS(ID_EUSER),          f_usr,      NULL,      QS(str),      0,        -1            },
-    { RS(ID_FGID),           f_status,   NULL,      QS(u_int),    0,        -1            },
-    { RS(ID_FGROUP),         x_ogroup,   NULL,      QS(str),      0,        -1            },
-    { RS(ID_FUID),           f_status,   NULL,      QS(u_int),    0,        -1            },
-    { RS(ID_FUSER),          x_ouser,    NULL,      QS(str),      0,        -1            },
-    { RS(ID_PGRP),           f_stat,     NULL,      QS(s_int),    0,        -1            },
-    { RS(ID_PID),            0,          NULL,      QS(s_int),    0,        -1            }, // oldflags: free w/ simple_nextpid
-    { RS(ID_PPID),           f_either,   NULL,      QS(s_int),    0,        -1            },
-    { RS(ID_RGID),           f_status,   NULL,      QS(u_int),    0,        -1            },
-    { RS(ID_RGROUP),         x_ogroup,   NULL,      QS(str),      0,        -1            },
-    { RS(ID_RUID),           f_status,   NULL,      QS(u_int),    0,        -1            },
-    { RS(ID_RUSER),          x_ouser,    NULL,      QS(str),      0,        -1            },
-    { RS(ID_SESSION),        f_stat,     NULL,      QS(s_int),    0,        -1            },
-    { RS(ID_SGID),           f_status,   NULL,      QS(u_int),    0,        -1            },
-    { RS(ID_SGROUP),         x_ogroup,   NULL,      QS(str),      0,        -1            },
-    { RS(ID_SUID),           f_status,   NULL,      QS(u_int),    0,        -1            },
-    { RS(ID_SUSER),          x_ouser,    NULL,      QS(str),      0,        -1            },
-    { RS(ID_TGID),           0,          NULL,      QS(s_int),    0,        -1            }, // oldflags: free w/ simple_nextpid
-    { RS(ID_TPGID),          f_stat,     NULL,      QS(s_int),    0,        -1            },
-    { RS(LXCNAME),           f_lxc,      NULL,      QS(str),      0,        -1            },
-    { RS(MEM_CODE),          f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_CODE_KIB),      f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_DATA),          f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_DATA_KIB),      f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_DT),            f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_LRS),           f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_RES),           f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_RES_KIB),       f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_SHR),           f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_SHR_KIB),       f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_VIRT),          f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(MEM_VIRT_KIB),      f_statm,    NULL,      QS(sl_int),   0,        -1            },
-    { RS(NICE),              f_stat,     NULL,      QS(sl_int),   0,        -1            },
-    { RS(NLWP),              f_either,   NULL,      QS(s_int),    0,        -1            },
-    { RS(NS_IPC),            f_ns,       NULL,      QS(ul_int),   0,        -1            },
-    { RS(NS_MNT),            f_ns,       NULL,      QS(ul_int),   0,        -1            },
-    { RS(NS_NET),            f_ns,       NULL,      QS(ul_int),   0,        -1            },
-    { RS(NS_PID),            f_ns,       NULL,      QS(ul_int),   0,        -1            },
-    { RS(NS_USER),           f_ns,       NULL,      QS(ul_int),   0,        -1            },
-    { RS(NS_UTS),            f_ns,       NULL,      QS(ul_int),   0,        -1            },
-    { RS(OOM_ADJ),           f_oom,      NULL,      QS(s_int),    0,        -1            },
-    { RS(OOM_SCORE),         f_oom,      NULL,      QS(s_int),    0,        -1            },
-    { RS(PRIORITY),          f_stat,     NULL,      QS(s_int),    0,        -1            },
-    { RS(PROCESSOR),         f_stat,     NULL,      QS(u_int),    0,        -1            },
-    { RS(RSS),               f_stat,     NULL,      QS(sl_int),   0,        -1            },
-    { RS(RSS_RLIM),          f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(RTPRIO),            f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(SCHED_CLASS),       f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(SD_MACH),           f_systemd,  FF(str),   QS(str),      0,        ref_SD_MACH   },
-    { RS(SD_OUID),           f_systemd,  FF(str),   QS(str),      0,        ref_SD_OUID   },
-    { RS(SD_SEAT),           f_systemd,  FF(str),   QS(str),      0,        ref_SD_SEAT   },
-    { RS(SD_SESS),           f_systemd,  FF(str),   QS(str),      0,        ref_SD_SESS   },
-    { RS(SD_SLICE),          f_systemd,  FF(str),   QS(str),      0,        ref_SD_SLICE  },
-    { RS(SD_UNIT),           f_systemd,  FF(str),   QS(str),      0,        ref_SD_UNIT   },
-    { RS(SD_UUNIT),          f_systemd,  FF(str),   QS(str),      0,        ref_SD_UUNIT  },
-    { RS(SIGBLOCKED),        f_status,   FF(str),   QS(str),      0,        -1            },
-    { RS(SIGCATCH),          f_status,   FF(str),   QS(str),      0,        -1            },
-    { RS(SIGIGNORE),         f_status,   FF(str),   QS(str),      0,        -1            },
-    { RS(SIGNALS),           f_status,   FF(str),   QS(str),      0,        -1            },
-    { RS(SIGPENDING),        f_status,   FF(str),   QS(str),      0,        -1            },
-    { RS(STATE),             f_either,   NULL,      QS(s_ch),     0,        -1            },
-    { RS(SUPGIDS),           f_status,   FF(str),   QS(str),      0,        ref_SUPGIDS   },
-    { RS(SUPGROUPS),         x_supgrp,   FF(str),   QS(str),      0,        ref_SUPGROUPS },
-    { RS(TICS_ALL),          f_stat,     NULL,      QS(ull_int),  0,        -1            },
-    { RS(TICS_ALL_C),        f_stat,     NULL,      QS(ull_int),  0,        -1            },
-    { RS(TICS_DELTA),        f_stat,     NULL,      QS(sl_int),  +1,        -1            },
-    { RS(TICS_SYSTEM),       f_stat,     NULL,      QS(ull_int),  0,        -1            },
-    { RS(TICS_SYSTEM_C),     f_stat,     NULL,      QS(ull_int),  0,        -1            },
-    { RS(TICS_USER),         f_stat,     NULL,      QS(ull_int),  0,        -1            },
-    { RS(TICS_USER_C),       f_stat,     NULL,      QS(ull_int),  0,        -1            },
-    { RS(TIME_ALL),          f_stat,     NULL,      QS(ull_int),  0,        -1            },
-    { RS(TIME_ELAPSED),      f_stat,     NULL,      QS(ull_int),  0,        -1            },
-    { RS(TIME_START),        f_stat,     NULL,      QS(ull_int),  0,        -1            },
-    { RS(TTY),               f_stat,     NULL,      QS(s_int),    0,        -1            },
-    { RS(TTY_NAME),          f_stat,     FF(str),   QS(strvers),  0,        -1            },
-    { RS(TTY_NUMBER),        f_stat,     FF(str),   QS(strvers),  0,        -1            },
-    { RS(VM_DATA),           f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_EXE),            f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_LIB),            f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_RSS),            f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_RSS_ANON),       f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_RSS_FILE),       f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_RSS_LOCKED),     f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_RSS_SHARED),     f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_SIZE),           f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_STACK),          f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_SWAP),           f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VM_USED),           f_status,   NULL,      QS(sl_int),   0,        -1            },
-    { RS(VSIZE_PGS),         f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(WCHAN_ADDR),        f_stat,     NULL,      QS(ul_int),   0,        -1            },
-    { RS(WCHAN_NAME),        0,          FF(str),   QS(str),      0,        -1            }, // oldflags: tid already free
+/*    setsfunc               oldflags    freefunc   sortfunc       needhist
+      ---------------------  ----------  ---------  -------------  -------- */
+    { RS(noop),              0,          NULL,      QS(noop),      0        }, // user only, never altered
+    { RS(extra),             0,          NULL,      QS(ull_int),   0        }, // user only, reset to zero
+    { RS(ADDR_END_CODE),     f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(ADDR_KSTK_EIP),     f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(ADDR_KSTK_ESP),     f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(ADDR_START_CODE),   f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(ADDR_START_STACK),  f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(ALARM),             f_stat,     NULL,      QS(sl_int),    0        },
+    { RS(CGNAME),            x_cgroup,   FF(str),   QS(str),       0        },
+    { RS(CGROUP),            x_cgroup,   FF(str),   QS(str),       0        },
+    { RS(CGROUP_V),          v_cgroup,   FF(strv),  QS(strv),      0        },
+    { RS(CMD),               f_either,   FF(str),   QS(str),       0        },
+    { RS(CMDLINE),           x_cmdline,  FF(str),   QS(str),       0        },
+    { RS(CMDLINE_V),         v_arg,      FF(strv),  QS(strv),      0        },
+    { RS(ENVIRON),           x_environ,  FF(str),   QS(str),       0        },
+    { RS(ENVIRON_V),         v_env,      FF(strv),  QS(strv),      0        },
+    { RS(EXIT_SIGNAL),       f_stat,     NULL,      QS(s_int),     0        },
+    { RS(FLAGS),             f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(FLT_MAJ),           f_stat,     NULL,      QS(sl_int),    0        },
+    { RS(FLT_MAJ_C),         f_stat,     NULL,      QS(sl_int),    0        },
+    { RS(FLT_MAJ_DELTA),     f_stat,     NULL,      QS(sl_int),    +1       },
+    { RS(FLT_MIN),           f_stat,     NULL,      QS(sl_int),    0        },
+    { RS(FLT_MIN_C),         f_stat,     NULL,      QS(sl_int),    0        },
+    { RS(FLT_MIN_DELTA),     f_stat,     NULL,      QS(sl_int),    +1       },
+    { RS(ID_EGID),           0,          NULL,      QS(u_int),     0        }, // oldflags: free w/ simple_read...
+    { RS(ID_EGROUP),         f_grp,      NULL,      QS(str),       0        },
+    { RS(ID_EUID),           0,          NULL,      QS(u_int),     0        }, // oldflags: free w/ simple_read...
+    { RS(ID_EUSER),          f_usr,      NULL,      QS(str),       0        },
+    { RS(ID_FGID),           f_status,   NULL,      QS(u_int),     0        },
+    { RS(ID_FGROUP),         x_ogroup,   NULL,      QS(str),       0        },
+    { RS(ID_FUID),           f_status,   NULL,      QS(u_int),     0        },
+    { RS(ID_FUSER),          x_ouser,    NULL,      QS(str),       0        },
+    { RS(ID_PGRP),           f_stat,     NULL,      QS(s_int),     0        },
+    { RS(ID_PID),            0,          NULL,      QS(s_int),     0        }, // oldflags: free w/ simple_nextpid
+    { RS(ID_PPID),           f_either,   NULL,      QS(s_int),     0        },
+    { RS(ID_RGID),           f_status,   NULL,      QS(u_int),     0        },
+    { RS(ID_RGROUP),         x_ogroup,   NULL,      QS(str),       0        },
+    { RS(ID_RUID),           f_status,   NULL,      QS(u_int),     0        },
+    { RS(ID_RUSER),          x_ouser,    NULL,      QS(str),       0        },
+    { RS(ID_SESSION),        f_stat,     NULL,      QS(s_int),     0        },
+    { RS(ID_SGID),           f_status,   NULL,      QS(u_int),     0        },
+    { RS(ID_SGROUP),         x_ogroup,   NULL,      QS(str),       0        },
+    { RS(ID_SUID),           f_status,   NULL,      QS(u_int),     0        },
+    { RS(ID_SUSER),          x_ouser,    NULL,      QS(str),       0        },
+    { RS(ID_TGID),           0,          NULL,      QS(s_int),     0        }, // oldflags: free w/ simple_nextpid
+    { RS(ID_TPGID),          f_stat,     NULL,      QS(s_int),     0        },
+    { RS(LXCNAME),           f_lxc,      NULL,      QS(str),       0        },
+    { RS(MEM_CODE),          f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_CODE_KIB),      f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_DATA),          f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_DATA_KIB),      f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_DT),            f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_LRS),           f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_RES),           f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_RES_KIB),       f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_SHR),           f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_SHR_KIB),       f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_VIRT),          f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(MEM_VIRT_KIB),      f_statm,    NULL,      QS(sl_int),    0        },
+    { RS(NICE),              f_stat,     NULL,      QS(sl_int),    0        },
+    { RS(NLWP),              f_either,   NULL,      QS(s_int),     0        },
+    { RS(NS_IPC),            f_ns,       NULL,      QS(ul_int),    0        },
+    { RS(NS_MNT),            f_ns,       NULL,      QS(ul_int),    0        },
+    { RS(NS_NET),            f_ns,       NULL,      QS(ul_int),    0        },
+    { RS(NS_PID),            f_ns,       NULL,      QS(ul_int),    0        },
+    { RS(NS_USER),           f_ns,       NULL,      QS(ul_int),    0        },
+    { RS(NS_UTS),            f_ns,       NULL,      QS(ul_int),    0        },
+    { RS(OOM_ADJ),           f_oom,      NULL,      QS(s_int),     0        },
+    { RS(OOM_SCORE),         f_oom,      NULL,      QS(s_int),     0        },
+    { RS(PRIORITY),          f_stat,     NULL,      QS(s_int),     0        },
+    { RS(PROCESSOR),         f_stat,     NULL,      QS(u_int),     0        },
+    { RS(RSS),               f_stat,     NULL,      QS(sl_int),    0        },
+    { RS(RSS_RLIM),          f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(RTPRIO),            f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(SCHED_CLASS),       f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(SD_MACH),           f_systemd,  FF(str),   QS(str),       0        },
+    { RS(SD_OUID),           f_systemd,  FF(str),   QS(str),       0        },
+    { RS(SD_SEAT),           f_systemd,  FF(str),   QS(str),       0        },
+    { RS(SD_SESS),           f_systemd,  FF(str),   QS(str),       0        },
+    { RS(SD_SLICE),          f_systemd,  FF(str),   QS(str),       0        },
+    { RS(SD_UNIT),           f_systemd,  FF(str),   QS(str),       0        },
+    { RS(SD_UUNIT),          f_systemd,  FF(str),   QS(str),       0        },
+    { RS(SIGBLOCKED),        f_status,   FF(str),   QS(str),       0        },
+    { RS(SIGCATCH),          f_status,   FF(str),   QS(str),       0        },
+    { RS(SIGIGNORE),         f_status,   FF(str),   QS(str),       0        },
+    { RS(SIGNALS),           f_status,   FF(str),   QS(str),       0        },
+    { RS(SIGPENDING),        f_status,   FF(str),   QS(str),       0        },
+    { RS(STATE),             f_either,   NULL,      QS(s_ch),      0        },
+    { RS(SUPGIDS),           f_status,   FF(str),   QS(str),       0        },
+    { RS(SUPGROUPS),         x_supgrp,   FF(str),   QS(str),       0        },
+    { RS(TICS_ALL),          f_stat,     NULL,      QS(ull_int),   0        },
+    { RS(TICS_ALL_C),        f_stat,     NULL,      QS(ull_int),   0        },
+    { RS(TICS_DELTA),        f_stat,     NULL,      QS(sl_int),    +1       },
+    { RS(TICS_SYSTEM),       f_stat,     NULL,      QS(ull_int),   0        },
+    { RS(TICS_SYSTEM_C),     f_stat,     NULL,      QS(ull_int),   0        },
+    { RS(TICS_USER),         f_stat,     NULL,      QS(ull_int),   0        },
+    { RS(TICS_USER_C),       f_stat,     NULL,      QS(ull_int),   0        },
+    { RS(TIME_ALL),          f_stat,     NULL,      QS(ull_int),   0        },
+    { RS(TIME_ELAPSED),      f_stat,     NULL,      QS(ull_int),   0        },
+    { RS(TIME_START),        f_stat,     NULL,      QS(ull_int),   0        },
+    { RS(TTY),               f_stat,     NULL,      QS(s_int),     0        },
+    { RS(TTY_NAME),          f_stat,     FF(str),   QS(strvers),   0        },
+    { RS(TTY_NUMBER),        f_stat,     FF(str),   QS(strvers),   0        },
+    { RS(VM_DATA),           f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_EXE),            f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_LIB),            f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_RSS),            f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_RSS_ANON),       f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_RSS_FILE),       f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_RSS_LOCKED),     f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_RSS_SHARED),     f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_SIZE),           f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_STACK),          f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_SWAP),           f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VM_USED),           f_status,   NULL,      QS(sl_int),    0        },
+    { RS(VSIZE_PGS),         f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(WCHAN_ADDR),        f_stat,     NULL,      QS(ul_int),    0        },
+    { RS(WCHAN_NAME),        0,          FF(str),   QS(str),       0        }, // oldflags: tid already free
    // dummy entry corresponding to PROCPS_PIDS_logical_end ...
-    { NULL,                  0,          NULL,      NULL,         0,        -1            }
+    { NULL,                  0,          NULL,      NULL,          0        }
 };
 
    // next MUST be kept in sync with highest value enum
@@ -907,17 +915,14 @@ static inline void libflags_set (
         struct procps_pidsinfo *info)
 {
     enum pids_item e;
-    int i, n;
+    int i;
 
-    memset (info->ref_counts, 0, sizeof(info->ref_counts));
     info->oldflags = info->history_yes = 0;
     for (i = 0; i < info->curitems; i++) {
         if (((e = info->items[i])) >= PROCPS_PIDS_logical_end)
             break;
         info->oldflags |= Item_table[e].oldflags;
         info->history_yes |= Item_table[e].needhist;
-        n = Item_table[e].refcount;
-        if (n > -1) ++info->ref_counts[n];
     }
     if (info->oldflags & f_either) {
         if (!(info->oldflags & f_stat))
index b75918929ec341c053a7c7131b8288fad1e8d8b0..d87eeac6821baabc7f9a1199dd5f082cbfdd5363 100644 (file)
@@ -91,19 +91,23 @@ static inline void free_acquired (proc_t *p, int reuse) {
 #ifdef QUICK_THREADS
     if (!IS_THREAD(p)) {
 #endif
-        if (p->environ)  free((void*)*p->environ);
-        if (p->cmdline)  free((void*)*p->cmdline);
-        if (p->cgroup)   free((void*)*p->cgroup);
-        if (p->supgid)   free(p->supgid);
-        if (p->supgrp)   free(p->supgrp);
-        if (p->cmd)      free(p->cmd);
-        if (p->sd_mach)  free(p->sd_mach);
-        if (p->sd_ouid)  free(p->sd_ouid);
-        if (p->sd_seat)  free(p->sd_seat);
-        if (p->sd_sess)  free(p->sd_sess);
-        if (p->sd_slice) free(p->sd_slice);
-        if (p->sd_unit)  free(p->sd_unit);
-        if (p->sd_uunit) free(p->sd_uunit);
+        if (p->environ)   free((void*)p->environ);
+        if (p->cmdline)   free((void*)p->cmdline);
+        if (p->cgname)    free((void*)p->cgname);
+        if (p->cgroup)    free((void*)p->cgroup);
+        if (p->environ_v) free((void*)*p->environ_v);
+        if (p->cmdline_v) free((void*)*p->cmdline_v);
+        if (p->cgroup_v)  free((void*)*p->cgroup_v);
+        if (p->supgid)    free(p->supgid);
+        if (p->supgrp)    free(p->supgrp);
+        if (p->cmd)       free(p->cmd);
+        if (p->sd_mach)   free(p->sd_mach);
+        if (p->sd_ouid)   free(p->sd_ouid);
+        if (p->sd_seat)   free(p->sd_seat);
+        if (p->sd_sess)   free(p->sd_sess);
+        if (p->sd_slice)  free(p->sd_slice);
+        if (p->sd_unit)   free(p->sd_unit);
+        if (p->sd_uunit)  free(p->sd_uunit);
 #ifdef QUICK_THREADS
     }
 #endif
@@ -713,28 +717,11 @@ static int read_unvectored(char *restrict const dst, unsigned sz, const char* wh
     return n;
 }
 
-static char** vectorize_this_str (const char* src) {
- #define pSZ  (sizeof(char*))
-    char *cpy, **vec;
-    int adj, tot;
-
-    tot = strlen(src) + 1;                       // prep for our vectors
-    adj = (pSZ-1) - ((tot + pSZ-1) & (pSZ-1));   // calc alignment bytes
-    cpy = xcalloc(tot + adj + (2 * pSZ));        // get new larger buffer
-    snprintf(cpy, tot, "%s", src);               // duplicate their string
-    vec = (char**)(cpy + tot + adj);             // prep pointer to pointers
-    *vec = cpy;                                  // point 1st vector to string
-    *(vec+1) = NULL;                             // null ptr 'list' delimit
-    return vec;                                  // ==> free(*vec) to dealloc
- #undef pSZ
-}
-
-    // This routine reads a 'cgroup' for the designated proc_t.
-    // It is similar to file2strvec except we filter and concatenate
-    // the data into a single string represented as a single vector.
+    // This routine reads a 'cgroup' for the designated proc_t and
+    // guarantees the caller a valid proc_t.cgroup pointer.
 static void fill_cgroup_cvt (const char* directory, proc_t *restrict p) {
  #define vMAX ( MAX_BUFSZ - (int)(dst - dst_buffer) )
-    char *src, *dst, *grp, *eob;
+    char *src, *dst, *grp, *eob, *name;
     int tot, x, whackable_int = MAX_BUFSZ;
 
     *(dst = dst_buffer) = '\0';                  // empty destination
@@ -750,13 +737,17 @@ static void fill_cgroup_cvt (const char* directory, proc_t *restrict p) {
         dst += snprintf(dst, vMAX, "%s", (dst > dst_buffer) ? "," : "");
         dst += escape_str(dst, grp, vMAX, &whackable_int);
     }
-    p->cgroup = vectorize_this_str(dst_buffer[0] ? dst_buffer : "-");
+    p->cgroup = strdup(dst_buffer[0] ? dst_buffer : "-");
+
+    name = strstr(p->cgroup, ":name=");
+    if (name && *(name+6)) name += 6; else name = p->cgroup;
+    p->cgname = strdup(name);
  #undef vMAX
 }
 
     // This routine reads a 'cmdline' for the designated proc_t, "escapes"
-    // the result into a single string represented as a single vector
-    // and guarantees the caller a valid proc_t.cmdline pointer.
+    // the result into a single string while guaranteeing the caller a
+    // valid proc_t.cmdline pointer.
 static void fill_cmdline_cvt (const char* directory, proc_t *restrict p) {
  #define uFLG ( ESC_BRACKETS | ESC_DEFUNCT )
     int whackable_int = MAX_BUFSZ;
@@ -765,7 +756,7 @@ static void fill_cmdline_cvt (const char* directory, proc_t *restrict p) {
         escape_str(dst_buffer, src_buffer, MAX_BUFSZ, &whackable_int);
     else
         escape_command(dst_buffer, p, MAX_BUFSZ, &whackable_int, uFLG);
-    p->cmdline = vectorize_this_str(dst_buffer);
+    p->cmdline = strdup(dst_buffer[0] ? dst_buffer : "?");
  #undef uFLG
 }
 
@@ -777,7 +768,7 @@ static void fill_environ_cvt (const char* directory, proc_t *restrict p) {
     dst_buffer[0] = '\0';
     if (read_unvectored(src_buffer, MAX_BUFSZ, directory, "environ", ' '))
         escape_str(dst_buffer, src_buffer, MAX_BUFSZ, &whackable_int);
-    p->environ = vectorize_this_str(dst_buffer[0] ? dst_buffer : "-");
+    p->environ = strdup(dst_buffer[0] ? dst_buffer : "-");
 }
 
 
@@ -924,29 +915,20 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict cons
         }
     }
 
-    if (flags & PROC_FILLENV) {                 // read /proc/#/environ
-        if (flags & PROC_EDITENVRCVT)
-            fill_environ_cvt(path, p);
-        else
-            p->environ = file2strvec(path, "environ");
-    } else
-        p->environ = NULL;
+    if (flags & PROC_FILLENV)                   // read /proc/#/environ
+        p->environ_v = file2strvec(path, "environ");
+    if (flags & PROC_EDITENVRCVT)
+        fill_environ_cvt(path, p);
 
-    if (flags & (PROC_FILLCOM|PROC_FILLARG)) {  // read /proc/#/cmdline
-        if (flags & PROC_EDITCMDLCVT)
-            fill_cmdline_cvt(path, p);
-        else
-            p->cmdline = file2strvec(path, "cmdline");
-    } else
-        p->cmdline = NULL;
+    if (flags & PROC_FILLARG)                   // read /proc/#/cmdline
+        p->cmdline_v = file2strvec(path, "cmdline");
+    if (flags & PROC_EDITCMDLCVT)
+        fill_cmdline_cvt(path, p);
 
-    if ((flags & PROC_FILLCGROUP)) {            // read /proc/#/cgroup
-        if (flags & PROC_EDITCGRPCVT)
-            fill_cgroup_cvt(path, p);
-        else
-            p->cgroup = file2strvec(path, "cgroup");
-    } else
-        p->cgroup = NULL;
+    if ((flags & PROC_FILLCGROUP))              // read /proc/#/cgroup
+        p->cgroup_v = file2strvec(path, "cgroup");
+    if (flags & PROC_EDITCGRPCVT)
+        fill_cgroup_cvt(path, p);
 
     if (flags & PROC_FILLOOM) {
         if (file2str(path, "oom_score", &ub) != -1)
@@ -1046,29 +1028,20 @@ static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restric
         if (flags & PROC_FILLSUPGRP)
             supgrps_from_supgids(t);
 #endif
-        if (flags & PROC_FILLENV) {                     // read /proc/#/task/#/environ
-            if (flags & PROC_EDITENVRCVT)
-                fill_environ_cvt(path, t);
-            else
-                t->environ = file2strvec(path, "environ");
-        } else
-            t->environ = NULL;
-
-        if (flags & (PROC_FILLCOM|PROC_FILLARG)) {      // read /proc/#/task/#/cmdline
-            if (flags & PROC_EDITCMDLCVT)
-                fill_cmdline_cvt(path, t);
-            else
-                t->cmdline = file2strvec(path, "cmdline");
-        } else
-            t->cmdline = NULL;
-
-        if ((flags & PROC_FILLCGROUP)) {                // read /proc/#/task/#/cgroup
-            if (flags & PROC_EDITCGRPCVT)
-                fill_cgroup_cvt(path, t);
-            else
-                t->cgroup = file2strvec(path, "cgroup");
-        } else
-            t->cgroup = NULL;
+        if (flags & PROC_FILLENV)                       // read /proc/#/task/#/environ
+            t->environ_v = file2strvec(path, "environ");
+        if (flags & PROC_EDITENVRCVT)
+            fill_environ_cvt(path, t);
+
+        if (flags & PROC_FILLARG)                       // read /proc/#/task/#/cmdline
+            t->cmdline_v = file2strvec(path, "cmdline");
+        if (flags & PROC_EDITCMDLCVT)
+            fill_cmdline_cvt(path, t);
+
+        if ((flags & PROC_FILLCGROUP))                  // read /proc/#/task/#/cgroup
+            t->cgroup_v = file2strvec(path, "cgroup");
+        if (flags & PROC_EDITCGRPCVT)
+            fill_cgroup_cvt(path, t);
 
         if (flags & PROC_FILLSYSTEMD)                   // get sd-login.h stuff
             sd2proc(t);
@@ -1078,26 +1051,30 @@ static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restric
 
 #ifdef QUICK_THREADS
     } else {
-        t->size     = p->size;
-        t->resident = p->resident;
-        t->share    = p->share;
-        t->trs      = p->trs;
-        t->lrs      = p->lrs;
-        t->drs      = p->drs;
-        t->dt       = p->dt;
-        t->cmdline  = p->cmdline;  // better not free these until done with all threads!
-        t->environ  = p->environ;
-        t->cgroup   = p->cgroup;
-        t->supgid   = p->supgid;
-        t->supgrp   = p->supgrp;
-        t->sd_mach  = p->sd_mach;
-        t->sd_ouid  = p->sd_ouid;
-        t->sd_seat  = p->sd_seat;
-        t->sd_sess  = p->sd_sess;
-        t->sd_slice = p->sd_slice;
-        t->sd_unit  = p->sd_unit;
-        t->sd_uunit = p->sd_uunit;
-        t->lxcname = p->lxcname;
+        t->size      = p->size;
+        t->resident  = p->resident;
+        t->share     = p->share;
+        t->trs       = p->trs;
+        t->lrs       = p->lrs;
+        t->drs       = p->drs;
+        t->dt        = p->dt;
+        t->cmdline   = p->cmdline;     // better not free these until done with all threads!
+        t->cmdline_v = p->cmdline_v;
+        t->environ   = p->environ;
+        t->environ_v = p->environ_v;
+        t->cgname    = p->cgname;
+        t->cgroup    = p->cgroup;
+        t->cgroup_v  = p->cgroup_v;
+        t->supgid    = p->supgid;
+        t->supgrp    = p->supgrp;
+        t->sd_mach   = p->sd_mach;
+        t->sd_ouid   = p->sd_ouid;
+        t->sd_seat   = p->sd_seat;
+        t->sd_sess   = p->sd_sess;
+        t->sd_slice  = p->sd_slice;
+        t->sd_unit   = p->sd_unit;
+        t->sd_uunit  = p->sd_uunit;
+        t->lxcname   = p->lxcname;
         MK_THREAD(t);
     }
 #endif
index ec51749efc498a613e608aec3dc38911e6394a26..65e771c627faa1501d72208a23f2e0f94127e681 100644 (file)
@@ -124,11 +124,15 @@ typedef struct proc_t {
        cmin_flt,       // stat            cumulative min_flt of process and child processes
        cmaj_flt;       // stat            cumulative maj_flt of process and child processes
     char
-        **environ,      // (special)       environment string vector (/proc/#/environ)
-        **cmdline,      // (special)       command line string vector (/proc/#/cmdline)
-        **cgroup,       // (special)       cgroup string vector (/proc/#/cgroup)
-         *supgid,       // status          supplementary gids as comma delimited str
-         *supgrp;       // supp grp names as comma delimited str, derived from supgid
+        *environ,       // (special)       environment as string (/proc/#/environ)
+        *cmdline,       // (special)       command line as string (/proc/#/cmdline)
+        *cgroup,        // (special)       cgroup as string (/proc/#/cgroup)
+        *cgname,        // (special)       name portion of above (if possible)
+        *supgid,        // status          supplementary gids as comma delimited str
+        *supgrp,        // supp grp names as comma delimited str, derived from supgid
+       **environ_v,     // (special)       environment string vectors (/proc/#/environ)
+       **cmdline_v,     // (special)       command line string vectors (/proc/#/cmdline)
+       **cgroup_v;      // (special)       cgroup string vectors (/proc/#/cgroup)
     char
         *euser,         // stat(),status   effective user name
         *ruser,         // status          real user name
@@ -213,14 +217,13 @@ typedef struct PROCTAB {
 // id's since uid_t supports no convenient termination sentinel.)
 
 #define PROC_FILLMEM         0x0001 // read statm
-#define PROC_FILLCOM         0x0002 // alloc and fill in `cmdline'
-#define PROC_FILLENV         0x0004 // alloc and fill in `environ'
+#define PROC_FILLARG         0x0002 // alloc and fill in `cmdline' vectors
+#define PROC_FILLENV         0x0004 // alloc and fill in `environ' vectors
 #define PROC_FILLUSR         0x0008 // resolve user id number -> user name
 #define PROC_FILLGRP         0x0010 // resolve group id number -> group name
 #define PROC_FILLSTATUS      0x0020 // read status
 #define PROC_FILLSTAT        0x0040 // read stat
-#define PROC_FILLARG         0x0100 // alloc and fill in `cmdline'
-#define PROC_FILLCGROUP      0x0200 // alloc and fill in `cgroup`
+#define PROC_FILLCGROUP      0x0200 // alloc and fill in `cgroup` vectors
 #define PROC_FILLSUPGRP      0x0400 // resolve supplementary group id -> group name
 #define PROC_FILLOOM         0x0800 // fill in proc_t oom_score and oom_adj
 #define PROC_FILLNS          0x8000 // fill in proc_t namespace information
@@ -233,9 +236,9 @@ typedef struct PROCTAB {
 #define PROC_PID             0x1000  // process id numbers ( 0   terminated)
 #define PROC_UID             0x4000  // user id numbers    ( length needed )
 
-#define PROC_EDITCGRPCVT    0x10000 // edit `cgroup' as single vector
-#define PROC_EDITCMDLCVT    0x20000 // edit `cmdline' as single vector
-#define PROC_EDITENVRCVT    0x40000 // edit `environ' as single vector
+#define PROC_EDITCGRPCVT    0x10000 // edit `cgroup' as regular string
+#define PROC_EDITCMDLCVT    0x20000 // edit `cmdline' as regular string
+#define PROC_EDITENVRCVT    0x40000 // edit `environ' as regular string
 
 // it helps to give app code a few spare bits
 #define PROC_SPARE_1     0x01000000