2 * Copyright (c) 1984 through 2008, William LeFebvre
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
16 * * Neither the name of William LeFebvre nor the names of other
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Top users/processes display for Unix
39 * This file contains various handy utilities used by top.
58 while ((ch
= *s
++) != '\0')
77 if (strncmp(str
, "infinity", len
) == 0 ||
78 strncmp(str
, "all", len
) == 0 ||
79 strncmp(str
, "maximum", len
) == 0)
83 else if (alldigits(str
))
96 * itoa - convert integer (decimal) to ascii string for positive numbers
97 * only (we don't bother with negative numbers since we know we
102 * How do we know that 16 will suffice?
103 * Because the biggest number that we will
104 * ever convert will be 2^32-1, which is 10
113 static char buffer
[16]; /* result is built here */
114 /* 16 is sufficient since the largest number
115 we will ever convert will be 2^32-1,
116 which is 10 digits. */
118 ptr
= buffer
+ sizeof(buffer
);
124 else while (val
!= 0)
126 *--ptr
= (val
% 10) + '0';
133 * itoa7(val) - like itoa, except the number is right justified in a 7
134 * character field. This code is a duplication of itoa instead of
135 * a front end to a more general routine for efficiency.
139 itoa_w(int val
, int w
)
144 static char buffer
[16]; /* result is built here */
145 /* 16 is sufficient since the largest number
146 we will ever convert will be 2^32-1,
147 which is 10 digits. */
153 eptr
= ptr
= buffer
+ sizeof(buffer
);
159 else while (val
!= 0)
161 *--ptr
= (val
% 10) + '0';
164 while (ptr
>= eptr
- w
)
175 return itoa_w(val
, 7);
179 * digits(val) - return number of decimal digits in val. Only works for
180 * positive numbers. If val < 0 then digits(val) == 0, but
188 register int cnt
= 0;
203 * printable(char *str) - make the string pointed to by "str" into one that is
204 * printable (i.e.: all ascii), by converting all non-printable
205 * characters into '?'. Replacements are done in place and a pointer
206 * to the original buffer is returned.
217 while ((ch
= *ptr
) != '\0')
229 * strcpyend(to, from) - copy string "from" into "to" and return a pointer
230 * to the END of the string "to".
234 strcpyend(char *to
, char *from
)
237 while ((*to
++ = *from
++) != '\0');
243 * homogenize(char *str)
245 * Remove unwanted characters from "str" and make everything lower case.
246 * Newly allocated string is returned: the original is not altered.
249 char *homogenize(char *str
)
257 to
= fr
= ans
= strdup(str
);
258 while ((ch
= *fr
++) != '\0')
271 * string_index(string, array) - find string in array and return index
275 string_index(char *string
, char **array
)
280 while (*array
!= NULL
)
282 if (strcmp(string
, *array
) == 0)
293 * char *string_list(char **strings)
295 * Create a comma-separated list of the strings in the NULL-terminated
296 * "strings". Returned string is malloc-ed and should be freed when the
297 * caller is done. Note that this is not an efficient function.
300 char *string_list(char **strings
)
310 while ((p
= *pp
++) != NULL
)
312 cnt
+= strlen(p
) + 2;
317 resp
= result
= (char *)malloc(cnt
);
319 while ((p
= *pp
++) != NULL
)
321 resp
= strcpyend(resp
, p
);
324 resp
= strcpyend(resp
, ", ");
333 * argparse(line, cntp) - parse arguments in string "line", separating them
334 * out into an argv-like array, and setting *cntp to the number of
335 * arguments encountered. This is a simple parser that doesn't understand
336 * squat about quotes.
340 argparse(char *line
, int *cntp
)
349 register char **argv
;
353 /* unfortunately, the only real way to do this is to go thru the
354 input string twice. */
356 /* step thru the string counting the white space sections */
358 lastch
= cnt
= length
= 0;
359 while ((ch
= *from
++) != '\0')
362 if (ch
== ' ' && lastch
!= ' ')
369 /* add three to the count: one for the initial "dummy" argument,
370 one for the last argument and one for NULL */
373 /* allocate a char * array to hold the pointers */
374 argarray
= (char **)malloc(cnt
* sizeof(char *));
376 /* allocate another array to hold the strings themselves */
377 args
= (char *)malloc(length
+2);
379 /* initialization for main loop */
385 /* create a dummy argument to keep getopt happy */
390 /* now build argv while copying characters */
392 while ((ch
= *from
++) != '\0')
408 /* set cntp and return the allocated array */
414 * percentages(cnt, out, new, old, diffs) - calculate percentage change
415 * between array "old" and "new", putting the percentages i "out".
416 * "cnt" is size of each array and "diffs" is used for scratch space.
417 * The array "old" is updated on each call.
418 * The routine assumes modulo arithmetic. This function is especially
419 * useful on BSD mchines for calculating cpu state percentages.
423 percentages(int cnt
, int *out
, long *new, long *old
, long *diffs
)
427 register long change
;
428 register long total_change
;
436 /* calculate changes for each state and the overall change */
437 for (i
= 0; i
< cnt
; i
++)
439 if ((change
= *new - *old
) < 0)
441 /* this only happens when the counter wraps */
443 ((unsigned long)*new-(unsigned long)*old
);
445 total_change
+= (*dp
++ = change
);
449 /* avoid divide by zero potential */
450 if (total_change
== 0)
455 /* calculate percentages based on overall change, rounding up */
456 half_total
= total_change
/ 2l;
457 for (i
= 0; i
< cnt
; i
++)
459 *out
++ = (int)((*diffs
++ * 1000 + half_total
) / total_change
);
462 /* return the total in case the caller wants to use it */
463 return(total_change
);
467 * errmsg(errnum) - return an error message string appropriate to the
468 * error number "errnum". This is a substitute for the System V
469 * function "strerror". There appears to be no reliable way to
470 * determine if "strerror" exists at compile time, so I make do
471 * by providing something of similar functionality. For those
472 * systems that have strerror and NOT errlist, define
473 * -DHAVE_STRERROR in the module file and this function will
477 /* externs referenced by errmsg */
479 #ifndef HAVE_STRERROR
480 #if !HAVE_DECL_SYS_ERRLIST
481 extern char *sys_errlist
[];
492 char *msg
= strerror(errnum
);
498 if (errnum
> 0 && errnum
< sys_nerr
)
500 return((char *)(sys_errlist
[errnum
]));
506 /* format_percent(v) - format a double as a percentage in a manner that
507 * does not exceed 5 characters (excluding any trailing
508 * percent sign). Since it is possible for the value
509 * to exceed 100%, we format such values with no fractional
510 * component to fit within the 5 characters.
514 format_percent(double v
)
517 static char result
[10];
519 /* enumerate the possibilities */
520 if (v
< 0 || v
>= 100000.)
522 /* we dont want to try extreme values */
523 strcpy(result
, " ???");
527 sprintf(result
, "%5.0f", v
);
531 sprintf(result
, "%5.2f", v
);
537 /* format_time(seconds) - format number of seconds into a suitable
538 * display that will fit within 6 characters. Note that this
539 * routine builds its string in a static area. If it needs
540 * to be called more than once without overwriting previous data,
541 * then we will need to adopt a technique similar to the
542 * one used for format_k.
546 We want to keep the output within 6 characters. For low values we use
547 the format mm:ss. For values that exceed 999:59, we switch to a format
548 that displays hours and fractions: hhh.tH. For values that exceed
549 999.9, we use hhhh.t and drop the "H" designator. For values that
550 exceed 9999.9, we use "???".
554 format_time(long seconds
, char *result
, int len
)
557 /* sanity protection */
558 if (seconds
< 0 || seconds
> (99999l * 360l))
560 strcpy(result
, " ???");
562 else if (seconds
>= (1000l * 60l))
564 /* alternate (slow) method displaying hours and tenths */
565 snprintf(result
, len
- 1, "%5.1fH", (double)seconds
/ (double)(60l * 60l));
567 /* It is possible that the sprintf took more than 6 characters.
568 If so, then the "H" appears as result[6]. If not, then there
569 is a \0 in result[6]. Either way, it is safe to step on.
571 if (len
/ sizeof(result
[0]) > 6)
576 /* standard method produces MMM:SS */
577 /* we avoid printf as must as possible to make this quick */
578 snprintf(result
, len
- 1, "%3ld:%02ld", seconds
/ 60l, seconds
% 60l);
584 * format_k(amt) - format a kilobyte memory value, returning a string
585 * suitable for display. Returns a pointer to a static
586 * area that changes each call. "amt" is converted to a
587 * string with a trailing "K". If "amt" is 10000 or greater,
588 * then it is formatted as megabytes (rounded) with a
593 * Compromise time. We need to return a string, but we don't want the
594 * caller to have to worry about freeing a dynamically allocated string.
595 * Unfortunately, we can't just return a pointer to a static area as one
596 * of the common uses of this function is in a large call to sprintf where
597 * it might get invoked several times. Our compromise is to maintain an
598 * array of strings and cycle thru them with each invocation. We make the
599 * array large enough to handle the above mentioned case. The constant
600 * NUM_STRINGS defines the number of strings in this array: we can tolerate
601 * up to NUM_STRINGS calls before we start overwriting old information.
602 * Keeping NUM_STRINGS a power of two will allow an intelligent optimizer
603 * to convert the modulo operation into something quicker. What a hack!
606 #define NUM_STRINGS 8
612 static char retarray
[NUM_STRINGS
][16];
613 static int index
= 0;
615 register char tag
= 'K';
617 ret
= retarray
[index
];
618 index
= (index
+ 1) % NUM_STRINGS
;
622 amt
= (amt
+ 512) / 1024;
626 amt
= (amt
+ 512) / 1024;
631 snprintf(ret
, sizeof(retarray
[index
])-1, "%ld%c", amt
, tag
);
637 * Time keeping functions.
640 static struct timeval lasttime
= { 0, 0 };
641 static unsigned int elapsed_msecs
= 0;
644 time_get(struct timeval
*tv
)
647 /* get the current time */
648 #ifdef HAVE_GETTIMEOFDAY
649 gettimeofday(tv
, NULL
);
651 tv
->tv_sec
= (long)time(NULL
);
657 time_mark(struct timeval
*tv
)
660 struct timeval thistime
;
661 struct timeval timediff
;
663 /* if the caller didnt provide one then use our own */
669 /* get the current time */
670 #ifdef HAVE_GETTIMEOFDAY
671 gettimeofday(tv
, NULL
);
673 tv
->tv_sec
= (long)time(NULL
);
677 /* calculate the difference */
678 timediff
.tv_sec
= tv
->tv_sec
- lasttime
.tv_sec
;
679 timediff
.tv_usec
= tv
->tv_usec
- lasttime
.tv_usec
;
680 if (timediff
.tv_usec
< 0) {
682 timediff
.tv_usec
+= 1000000;
685 /* convert to milliseconds */
686 elapsed_msecs
= timediff
.tv_sec
* 1000 + timediff
.tv_usec
/ 1000;
687 if (elapsed_msecs
== 0)
692 /* save for next time */
700 return elapsed_msecs
;
704 diff_per_second(unsigned int x
, unsigned int y
)
707 return (y
> x
? UINT_MAX
- y
+ x
+ 1 : x
- y
) * 1000 / elapsed_msecs
;
710 static int debug_on
= 0;
722 debugfile
= fopen("/tmp/top.debug", "w");
728 xdprintf(char *fmt
, ...)
737 vfprintf(debugfile
, fmt
, argp
);