On Wed, Nov 28, 2018 at 12:07:37AM +0100, Klemens Nanni wrote:
> On Tue, Nov 27, 2018 at 03:52:52PM -0600, Scott Cheloha wrote:
> > > > static int
> > > > +getorder(char *field)
> > > > +{
> > > > + rev_order = field[0] == '-';
> > > > +
> > > > + return string_index(rev_order ? field + 1 : field,
> > > > statics.order_names);
> > > > +}
> > > > +
> >
> > You need to check that the field has an ordering before potentially
> > modifying rev_order, otherwise a bogus input will have a side effect.
> >
> > For example, with the current code the input "o -notafield" reverses
> > the ordering.
> Good catch.
>
> Updated diff to fix that, rest unchanged.
>
> Note how an empty field is silently treated as the default field
> "state", but that's an independent issue I'd like to address in a
> separate diff for string_index().
>
> OK?
ok cheloha@
> Index: display.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/top/display.c,v
> retrieving revision 1.57
> diff -u -p -r1.57 display.c
> --- display.c 17 Nov 2018 23:10:08 -0000 1.57
> +++ display.c 27 Nov 2018 21:09:56 -0000
> @@ -817,7 +817,8 @@ show_help(void)
> "I | i - toggle the display of idle processes\n"
> "k [-sig] pid - send signal `-sig' to process `pid'\n"
> "n|# count - show `count' processes\n"
> - "o field - specify sort order (size, res, cpu, time, pri, pid,
> command)\n"
> + "o [-]field - specify sort order (size, res, cpu, time, pri, pid,
> command)\n"
> + " (o -field sorts in reverse)\n"
> "P pid - highlight process `pid' (P+ switches highlighting
> off)\n"
> "p pid - display process by `pid' (p+ selects all
> processes)\n"
> "q - quit\n"
> Index: machine.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/top/machine.c,v
> retrieving revision 1.95
> diff -u -p -r1.95 machine.c
> --- machine.c 17 Nov 2018 23:10:08 -0000 1.95
> +++ machine.c 27 Nov 2018 21:09:56 -0000
> @@ -602,6 +602,8 @@ static unsigned char sorted_state[] =
> 1 /* zombie */
> };
>
> +extern int rev_order;
> +
> /*
> * proc_compares - comparison functions for "qsort"
> */
> @@ -631,6 +633,17 @@ static unsigned char sorted_state[] =
> #define ORDERKEY_CMD \
> if ((result = strcmp(p1->p_comm, p2->p_comm)) == 0)
>
> +/* remove one level of indirection and set sort order */
> +#define SETORDER do { \
> + if (rev_order) { \
> + p1 = *(struct kinfo_proc **) pp2; \
> + p2 = *(struct kinfo_proc **) pp1; \
> + } else { \
> + p1 = *(struct kinfo_proc **) pp1; \
> + p2 = *(struct kinfo_proc **) pp2; \
> + } \
> + } while (0)
> +
> /* compare_cpu - the comparison function for sorting by cpu percentage */
> static int
> compare_cpu(const void *v1, const void *v2)
> @@ -640,9 +653,7 @@ compare_cpu(const void *v1, const void *
> struct kinfo_proc *p1, *p2;
> int result;
>
> - /* remove one level of indirection */
> - p1 = *(struct kinfo_proc **) pp1;
> - p2 = *(struct kinfo_proc **) pp2;
> + SETORDER;
>
> ORDERKEY_PCTCPU
> ORDERKEY_CPUTIME
> @@ -663,9 +674,7 @@ compare_size(const void *v1, const void
> struct kinfo_proc *p1, *p2;
> int result;
>
> - /* remove one level of indirection */
> - p1 = *(struct kinfo_proc **) pp1;
> - p2 = *(struct kinfo_proc **) pp2;
> + SETORDER;
>
> ORDERKEY_MEM
> ORDERKEY_RSSIZE
> @@ -686,9 +695,7 @@ compare_res(const void *v1, const void *
> struct kinfo_proc *p1, *p2;
> int result;
>
> - /* remove one level of indirection */
> - p1 = *(struct kinfo_proc **) pp1;
> - p2 = *(struct kinfo_proc **) pp2;
> + SETORDER;
>
> ORDERKEY_RSSIZE
> ORDERKEY_MEM
> @@ -709,9 +716,7 @@ compare_time(const void *v1, const void
> struct kinfo_proc *p1, *p2;
> int result;
>
> - /* remove one level of indirection */
> - p1 = *(struct kinfo_proc **) pp1;
> - p2 = *(struct kinfo_proc **) pp2;
> + SETORDER;
>
> ORDERKEY_CPUTIME
> ORDERKEY_PCTCPU
> @@ -732,9 +737,7 @@ compare_prio(const void *v1, const void
> struct kinfo_proc *p1, *p2;
> int result;
>
> - /* remove one level of indirection */
> - p1 = *(struct kinfo_proc **) pp1;
> - p2 = *(struct kinfo_proc **) pp2;
> + SETORDER;
>
> ORDERKEY_PRIO
> ORDERKEY_PCTCPU
> @@ -754,9 +757,7 @@ compare_pid(const void *v1, const void *
> struct kinfo_proc *p1, *p2;
> int result;
>
> - /* remove one level of indirection */
> - p1 = *(struct kinfo_proc **) pp1;
> - p2 = *(struct kinfo_proc **) pp2;
> + SETORDER;
>
> ORDERKEY_PID
> ORDERKEY_PCTCPU
> @@ -777,9 +778,7 @@ compare_cmd(const void *v1, const void *
> struct kinfo_proc *p1, *p2;
> int result;
>
> - /* remove one level of indirection */
> - p1 = *(struct kinfo_proc **) pp1;
> - p2 = *(struct kinfo_proc **) pp2;
> + SETORDER;
>
> ORDERKEY_CMD
> ORDERKEY_PCTCPU
> Index: top.1
> ===================================================================
> RCS file: /cvs/src/usr.bin/top/top.1,v
> retrieving revision 1.70
> diff -u -p -r1.70 top.1
> --- top.1 2 Nov 2018 12:46:10 -0000 1.70
> +++ top.1 27 Nov 2018 21:09:56 -0000
> @@ -35,7 +35,7 @@
> .Op Fl 1bCHIinqSu
> .Op Fl d Ar count
> .Op Fl g Ar string
> -.Op Fl o Ar field
> +.Op Fl o Oo - Oc Ns Ar field
> .Op Fl p Ar pid
> .Op Fl s Ar time
> .Op Fl U Oo - Oc Ns Ar user
> @@ -137,13 +137,16 @@ mode.
> This is identical to
> .Em batch
> mode.
> -.It Fl o Ar field
> +.It Fl o Oo - Oc Ns Ar field
> Sort the process display area using the specified
> .Ar field
> as the primary key.
> The field name is the name of the column as seen in the output,
> but in lower case.
> The
> +.Sq -
> +prefix reverses the order.
> +The
> .Ox
> version of
> .Nm
> @@ -327,10 +330,13 @@ This acts similarly to the command
> Show
> .Ar count
> processes.
> -.It o Ar field
> +.It o Oo - Oc Ns Ar field
> Sort the process display area using the specified
> .Ar field
> as the primary key.
> +The
> +.Sq -
> +prefix reverses the order.
> Values are the same as for the
> .Fl o
> flag, as detailed above.
> Index: top.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/top/top.c,v
> retrieving revision 1.97
> diff -u -p -r1.97 top.c
> --- top.c 17 Nov 2018 23:10:08 -0000 1.97
> +++ top.c 27 Nov 2018 22:54:42 -0000
> @@ -74,6 +74,7 @@ extern int ncpuonline;
>
> extern int (*proc_compares[])(const void *, const void *);
> int order_index;
> +int rev_order;
>
> int displays = 0; /* indicates unspecified */
> char do_unames = Yes;
> @@ -93,6 +94,9 @@ int combine_cpus = 0;
> char topn_specified = No;
> #endif
>
> +struct system_info system_info;
> +struct statics statics;
> +
> /*
> * these defines enumerate the "strchr"s of the commands in
> * command_chars
> @@ -129,12 +133,24 @@ usage(void)
> extern char *__progname;
>
> fprintf(stderr,
> - "usage: %s [-1bCHIinqSu] [-d count] [-g string] [-o field] "
> + "usage: %s [-1bCHIinqSu] [-d count] [-g string] [-o [-]field] "
> "[-p pid] [-s time]\n\t[-U [-]user] [number]\n",
> __progname);
> }
>
> static int
> +getorder(char *field)
> +{
> + int i, r = field[0] == '-';
> +
> + i = string_index(r ? field + 1 : field, statics.order_names);
> + if (i != -1)
> + rev_order = r;
> +
> + return i;
> +}
> +
> +static int
> filteruser(char buf[])
> {
> const char *errstr;
> @@ -311,9 +327,6 @@ parseargs(int ac, char **av)
> }
> }
>
> -struct system_info system_info;
> -struct statics statics;
> -
> int
> main(int argc, char *argv[])
> {
> @@ -381,20 +394,9 @@ main(int argc, char *argv[])
>
> /* determine sorting order index, if necessary */
> if (order_name != NULL) {
> - if ((order_index = string_index(order_name,
> - statics.order_names)) == -1) {
> - char **pp, msg[512];
> -
> - snprintf(msg, sizeof(msg),
> - "'%s' is not a recognized sorting order",
> - order_name);
> - strlcat(msg, ". Valid are:", sizeof(msg));
> - pp = statics.order_names;
> - while (*pp != NULL) {
> - strlcat(msg, " ", sizeof(msg));
> - strlcat(msg, *pp++, sizeof(msg));
> - }
> - new_message(MT_delayed, msg);
> + if ((order_index = getorder(order_name)) == -1) {
> + new_message(MT_delayed,
> + " %s: unrecognized sorting order", order_name);
> order_index = 0;
> }
> }
> @@ -879,10 +881,10 @@ rundisplay(void)
> new_message(MT_standout,
> "Order to sort: ");
> if (readline(tempbuf, sizeof(tempbuf)) > 0) {
> - if ((i = string_index(tempbuf,
> - statics.order_names)) == -1) {
> + if ((i = getorder(tempbuf)) == -1) {
> new_message(MT_standout,
> " %s: unrecognized sorting order",
> + tempbuf[0] == '-' ? tempbuf + 1 :
> tempbuf);
> no_command = Yes;
> } else
>