Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * Copyright (c) 1984 through 2008, William LeFebvre
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *
     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
     14  * distribution.
     15  *
     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.
     19  *
     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.
     31  */
     32 
     33 /*
     34  *  Top users/processes display for Unix
     35  *  Version 3
     36  */
     37 
     38 /*
     39  *  This file contains various handy utilities used by top.
     40  */
     41 
     42 #include "os.h"
     43 #include <ctype.h>
     44 #include <math.h>
     45 #ifdef HAVE_STDARG_H
     46 #include <stdarg.h>
     47 #else
     48 #undef DEBUG
     49 #endif
     50 #include "top.h"
     51 #include "utils.h"
     52 
     53 static int
     54 alldigits(char *s)
     55 
     56 {
     57     int ch;
     58 
     59     while ((ch = *s++) != '\0')
     60     {
     61 	if (!isdigit((unsigned char)ch))
     62 	{
     63 	    return 0;
     64 	}
     65     }
     66     return 1;
     67 }
     68 
     69 int
     70 atoiwi(char *str)
     71 
     72 {
     73     register int len;
     74 
     75     len = strlen(str);
     76     if (len != 0)
     77     {
     78 	if (strncmp(str, "infinity", len) == 0 ||
     79 	    strncmp(str, "all",      len) == 0 ||
     80 	    strncmp(str, "maximum",  len) == 0)
     81 	{
     82 	    return(Infinity);
     83 	}
     84 	else if (alldigits(str))
     85 	{
     86 	    return(atoi(str));
     87 	}
     88 	else
     89 	{
     90 	    return(Invalid);
     91 	}
     92     }
     93     return(0);
     94 }
     95 
     96 /*
     97  *  itoa - convert integer (decimal) to ascii string for positive numbers
     98  *  	   only (we don't bother with negative numbers since we know we
     99  *	   don't use them).
    100  */
    101 
    102 				/*
    103 				 * How do we know that 16 will suffice?
    104 				 * Because the biggest number that we will
    105 				 * ever convert will be 2^32-1, which is 10
    106 				 * digits.
    107 				 */
    108 
    109 char *
    110 itoa(int val)
    111 
    112 {
    113     register char *ptr;
    114     static char buffer[16];	/* result is built here */
    115     				/* 16 is sufficient since the largest number
    116 				   we will ever convert will be 2^32-1,
    117 				   which is 10 digits. */
    118 
    119     ptr = buffer + sizeof(buffer);
    120     *--ptr = '\0';
    121     if (val == 0)
    122     {
    123 	*--ptr = '0';
    124     }
    125     else while (val != 0)
    126     {
    127 	*--ptr = (val % 10) + '0';
    128 	val /= 10;
    129     }
    130     return(ptr);
    131 }
    132 
    133 /*
    134  *  itoa7(val) - like itoa, except the number is right justified in a 7
    135  *	character field.  This code is a duplication of itoa instead of
    136  *	a front end to a more general routine for efficiency.
    137  */
    138 
    139 char *
    140 itoa_w(int val, int w)
    141 
    142 {
    143     char *ptr;
    144     char *eptr;
    145     static char buffer[16];	/* result is built here */
    146     				/* 16 is sufficient since the largest number
    147 				   we will ever convert will be 2^32-1,
    148 				   which is 10 digits. */
    149 
    150     if (w > 15)
    151     {
    152 	w = 15;
    153     }
    154     eptr = ptr = buffer + sizeof(buffer);
    155     *--ptr = '\0';
    156     if (val == 0)
    157     {
    158 	*--ptr = '0';
    159     }
    160     else while (val != 0)
    161     {
    162 	*--ptr = (val % 10) + '0';
    163 	val /= 10;
    164     }
    165     while (ptr >= eptr - w)
    166     {
    167 	*--ptr = ' ';
    168     }
    169     return(ptr);
    170 }
    171 
    172 char *
    173 itoa7(int val)
    174 
    175 {
    176     return itoa_w(val, 7);
    177 }
    178 
    179 /*
    180  *  digits(val) - return number of decimal digits in val.  Only works for
    181  *	positive numbers.  If val < 0 then digits(val) == 0, but
    182  *      digits(0) == 1.
    183  */
    184 
    185 int
    186 digits(int val)
    187 
    188 {
    189     register int cnt = 0;
    190 
    191     if (val == 0)
    192     {
    193 	return 1;
    194     }
    195     while (val > 0)
    196     {
    197 	cnt++;
    198 	val /= 10;
    199     }
    200     return(cnt);
    201 }
    202 
    203 /*
    204  *  printable(char *str) - make the string pointed to by "str" into one that is
    205  *	printable (i.e.: all ascii), by converting all non-printable
    206  *	characters into '?'.  Replacements are done in place and a pointer
    207  *	to the original buffer is returned.
    208  */
    209 
    210 char *
    211 printable(char *str)
    212 
    213 {
    214     register char *ptr;
    215     register int ch;
    216 
    217     ptr = str;
    218     while ((ch = *ptr) != '\0')
    219     {
    220 	if (!isprint((unsigned char)ch))
    221 	{
    222 	    *ptr = '?';
    223 	}
    224 	ptr++;
    225     }
    226     return(str);
    227 }
    228 
    229 /*
    230  *  strcpyend(to, from) - copy string "from" into "to" and return a pointer
    231  *	to the END of the string "to".
    232  */
    233 
    234 char *
    235 strcpyend(char *to, const char *from)
    236 
    237 {
    238     while ((*to++ = *from++) != '\0');
    239     return(--to);
    240 }
    241 
    242 /*
    243  * char *
    244  * homogenize(const char *str)
    245  *
    246  * Remove unwanted characters from "str" and make everything lower case.
    247  * Newly allocated string is returned: the original is not altered.
    248  */
    249 
    250 char *homogenize(const char *str)
    251 
    252 {
    253     char *ans;
    254     char *fr;
    255     char *to;
    256     int ch;
    257 
    258     to = fr = ans = estrdup(str);
    259     while ((ch = *fr++) != '\0')
    260     {
    261 	if (isalnum((unsigned char)ch))
    262 	{
    263 	    *to++ = tolower((unsigned char)ch);
    264 	}
    265     }
    266 
    267     *to = '\0';
    268     return ans;
    269 }
    270 
    271 /*
    272  * string_index(string, array) - find string in array and return index
    273  */
    274 
    275 int
    276 string_index(const char *string, const char **array)
    277 
    278 {
    279     register int i = 0;
    280 
    281     while (*array != NULL)
    282     {
    283 	if (strcmp(string, *array) == 0)
    284 	{
    285 	    return(i);
    286 	}
    287 	array++;
    288 	i++;
    289     }
    290     return(-1);
    291 }
    292 
    293 /*
    294  * char *string_list(char **strings)
    295  *
    296  * Create a comma-separated list of the strings in the NULL-terminated
    297  * "strings".  Returned string is malloc-ed and should be freed when the
    298  * caller is done.  Note that this is not an efficient function.
    299  */
    300 
    301 char *string_list(const char **strings)
    302 
    303 {
    304     int cnt = 0;
    305     const char **pp;
    306     const char *p;
    307     char *result = NULL;
    308     char *resp = NULL;
    309 
    310     pp = strings;
    311     while ((p = *pp++) != NULL)
    312     {
    313 	cnt += strlen(p) + 2;
    314     }
    315 
    316     if (cnt > 0)
    317     {
    318 	resp = result = emalloc(cnt);
    319 	pp = strings;
    320 	while ((p = *pp++) != NULL)
    321 	{
    322 	    resp = strcpyend(resp, p);
    323 	    if (*pp != NULL)
    324 	    {
    325 		resp = strcpyend(resp, ", ");
    326 	    }
    327 	}
    328     }
    329 
    330     return result;
    331 }
    332 
    333 /*
    334  * argparse(line, cntp) - parse arguments in string "line", separating them
    335  *	out into an argv-like array, and setting *cntp to the number of
    336  *	arguments encountered.  This is a simple parser that doesn't understand
    337  *	squat about quotes.
    338  */
    339 
    340 char **
    341 argparse(char *line, int *cntp)
    342 
    343 {
    344     register char *from;
    345     register char *to;
    346     register int cnt;
    347     register int ch;
    348     int length;
    349     int lastch;
    350     register char **argv;
    351     char **argarray;
    352     char *args;
    353 
    354     /* unfortunately, the only real way to do this is to go thru the
    355        input string twice. */
    356 
    357     /* step thru the string counting the white space sections */
    358     from = line;
    359     lastch = cnt = length = 0;
    360     while ((ch = *from++) != '\0')
    361     {
    362 	length++;
    363 	if (ch == ' ' && lastch != ' ')
    364 	{
    365 	    cnt++;
    366 	}
    367 	lastch = ch;
    368     }
    369 
    370     /* add three to the count:  one for the initial "dummy" argument,
    371        one for the last argument and one for NULL */
    372     cnt += 3;
    373 
    374     /* allocate a char * array to hold the pointers */
    375     argarray = emalloc(cnt * sizeof(char *));
    376 
    377     /* allocate another array to hold the strings themselves */
    378     args = emalloc(length+2);
    379 
    380     /* initialization for main loop */
    381     from = line;
    382     to = args;
    383     argv = argarray;
    384     lastch = '\0';
    385 
    386     /* create a dummy argument to keep getopt happy */
    387     *argv++ = to;
    388     *to++ = '\0';
    389     cnt = 2;
    390 
    391     /* now build argv while copying characters */
    392     *argv++ = to;
    393     while ((ch = *from++) != '\0')
    394     {
    395 	if (ch != ' ')
    396 	{
    397 	    if (lastch == ' ')
    398 	    {
    399 		*to++ = '\0';
    400 		*argv++ = to;
    401 		cnt++;
    402 	    }
    403 	    *to++ = ch;
    404 	}
    405 	lastch = ch;
    406     }
    407     *to++ = '\0';
    408 
    409     /* set cntp and return the allocated array */
    410     *cntp = cnt;
    411     return(argarray);
    412 }
    413 
    414 /*
    415  *  percentages(cnt, out, new, old, diffs) - calculate percentage change
    416  *	between array "old" and "new", putting the percentages i "out".
    417  *	"cnt" is size of each array and "diffs" is used for scratch space.
    418  *	The array "old" is updated on each call.
    419  *	The routine assumes modulo arithmetic.  This function is especially
    420  *	useful on BSD mchines for calculating cpu state percentages.
    421  */
    422 
    423 long
    424 percentages(int cnt, int *out, long *new, long *old, long *diffs)
    425 
    426 {
    427     register int i;
    428     register long change;
    429     register long total_change;
    430     register long *dp;
    431     long half_total;
    432 
    433     /* initialization */
    434     total_change = 0;
    435     dp = diffs;
    436 
    437     /* calculate changes for each state and the overall change */
    438     for (i = 0; i < cnt; i++)
    439     {
    440 	if ((change = *new - *old) < 0)
    441 	{
    442 	    /* this only happens when the counter wraps */
    443 	    change = (int)
    444 		((unsigned long)*new-(unsigned long)*old);
    445 	}
    446 	total_change += (*dp++ = change);
    447 	*old++ = *new++;
    448     }
    449 
    450     /* avoid divide by zero potential */
    451     if (total_change == 0)
    452     {
    453 	total_change = 1;
    454     }
    455 
    456     /* calculate percentages based on overall change, rounding up */
    457     half_total = total_change / 2l;
    458     for (i = 0; i < cnt; i++)
    459     {
    460 	*out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
    461     }
    462 
    463     /* return the total in case the caller wants to use it */
    464     return(total_change);
    465 }
    466 
    467 /*
    468  * errmsg(errnum) - return an error message string appropriate to the
    469  *           error number "errnum".  This is a substitute for the System V
    470  *           function "strerror".  There appears to be no reliable way to
    471  *           determine if "strerror" exists at compile time, so I make do
    472  *           by providing something of similar functionality.  For those
    473  *           systems that have strerror and NOT errlist, define
    474  *           -DHAVE_STRERROR in the module file and this function will
    475  *           use strerror.
    476  */
    477 
    478 /* externs referenced by errmsg */
    479 
    480 #ifndef HAVE_STRERROR
    481 #if !HAVE_DECL_SYS_ERRLIST
    482 extern char *sys_errlist[];
    483 #endif
    484 
    485 extern int sys_nerr;
    486 #endif
    487 
    488 const char *
    489 errmsg(int errnum)
    490 
    491 {
    492 #ifdef HAVE_STRERROR
    493     char *msg = strerror(errnum);
    494     if (msg != NULL)
    495     {
    496 	return msg;
    497     }
    498 #else
    499     if (errnum > 0 && errnum < sys_nerr)
    500     {
    501 	return((char *)(sys_errlist[errnum]));
    502     }
    503 #endif
    504     return("No error");
    505 }
    506 
    507 /* format_percent(v) - format a double as a percentage in a manner that
    508  *		does not exceed 5 characters (excluding any trailing
    509  *		percent sign).  Since it is possible for the value
    510  *		to exceed 100%, we format such values with no fractional
    511  *		component to fit within the 5 characters.
    512  */
    513 
    514 char *
    515 format_percent(double v)
    516 
    517 {
    518     static char result[10];
    519 
    520     /* enumerate the possibilities */
    521     if (v < 0 || v >= 100000.)
    522     {
    523 	/* we dont want to try extreme values */
    524 	strlcpy(result, "  ???", sizeof(result));
    525     }
    526     else if (v > 99.99)
    527     {
    528 	snprintf(result, sizeof(result), "%5.0f", v);
    529     }
    530     else
    531     {
    532 	snprintf(result, sizeof(result), "%5.2f", v);
    533     }
    534 
    535     return result;
    536 }
    537 
    538 /* format_time(seconds) - format number of seconds into a suitable
    539  *		display that will fit within 6 characters.  Note that this
    540  *		routine builds its string in a static area.  If it needs
    541  *		to be called more than once without overwriting previous data,
    542  *		then we will need to adopt a technique similar to the
    543  *		one used for format_k.
    544  */
    545 
    546 /* Explanation:
    547    We want to keep the output within 6 characters.  For low values we use
    548    the format mm:ss.  For values that exceed 999:59, we switch to a format
    549    that displays hours and fractions:  hhh.tH.  For values that exceed
    550    999.9, we use hhhh.t and drop the "H" designator.  For values that
    551    exceed 9999.9, we use "???".
    552  */
    553 
    554 char *
    555 format_time(long seconds)
    556 
    557 {
    558     static char result[10];
    559 
    560     /* sanity protection */
    561     if (seconds < 0 || seconds > (99999l * 360l))
    562     {
    563 	strcpy(result, "   ???");
    564     }
    565     else if (seconds >= (1000l * 60l))
    566     {
    567 	/* alternate (slow) method displaying hours and tenths */
    568 	snprintf(result, sizeof(result),
    569 	    "%5.1fH", (double)seconds / (double)(60l * 60l));
    570 
    571 	/* It is possible that the snprintf took more than 6 characters.
    572 	   If so, then the "H" appears as result[6].  If not, then there
    573 	   is a \0 in result[6].  Either way, it is safe to step on.
    574 	 */
    575 	result[6] = '\0';
    576     }
    577     else
    578     {
    579 	/* standard method produces MMM:SS */
    580 	/* we avoid printf as must as possible to make this quick */
    581 	snprintf(result, sizeof(result), "%3ld:%02ld",
    582 	    seconds / 60l, seconds % 60l);
    583     }
    584     return(result);
    585 }
    586 
    587 /*
    588  * format_k(amt) - format a kilobyte memory value, returning a string
    589  *		suitable for display.  Returns a pointer to a static
    590  *		area that changes each call.  "amt" is converted to a
    591  *		string with a trailing "K".  If "amt" is 10000 or greater,
    592  *		then it is formatted as megabytes (rounded) with a
    593  *		trailing "M".
    594  */
    595 
    596 /*
    597  * Compromise time.  We need to return a string, but we don't want the
    598  * caller to have to worry about freeing a dynamically allocated string.
    599  * Unfortunately, we can't just return a pointer to a static area as one
    600  * of the common uses of this function is in a large call to snprintf where
    601  * it might get invoked several times.  Our compromise is to maintain an
    602  * array of strings and cycle thru them with each invocation.  We make the
    603  * array large enough to handle the above mentioned case.  The constant
    604  * NUM_STRINGS defines the number of strings in this array:  we can tolerate
    605  * up to NUM_STRINGS calls before we start overwriting old information.
    606  * Keeping NUM_STRINGS a power of two will allow an intelligent optimizer
    607  * to convert the modulo operation into something quicker.  What a hack!
    608  */
    609 
    610 #define NUM_STRINGS 8
    611 
    612 char *
    613 format_k(long amt)
    614 
    615 {
    616     static char retarray[NUM_STRINGS][24];
    617     static int idx = 0;
    618     register char *ret;
    619     register char tag = 'K';
    620 
    621     ret = retarray[idx];
    622     idx = (idx + 1) % NUM_STRINGS;
    623 
    624     if (amt >= 10000)
    625     {
    626 	amt = (amt + 512) / 1024;
    627 	tag = 'M';
    628 	if (amt >= 10000)
    629 	{
    630 	    amt = (amt + 512) / 1024;
    631 	    tag = 'G';
    632 	}
    633     }
    634 
    635     snprintf(ret, sizeof(retarray[idx])-1, "%ld%c", amt, tag);
    636 
    637     return(ret);
    638 }
    639 
    640 /*
    641  * Time keeping functions.
    642  */
    643 
    644 static struct timeval lasttime = { 0, 0 };
    645 static unsigned int elapsed_msecs = 0;
    646 
    647 void
    648 time_get(struct timeval *tv)
    649 
    650 {
    651     /* get the current time */
    652 #ifdef HAVE_GETTIMEOFDAY
    653     gettimeofday(tv, NULL);
    654 #else
    655     tv->tv_sec = (long)time(NULL);
    656     tv->tv_usec = 0;
    657 #endif
    658 }
    659 
    660 void
    661 time_mark(struct timeval *tv)
    662 
    663 {
    664     struct timeval thistime;
    665     struct timeval timediff;
    666 
    667     /* if the caller didnt provide one then use our own */
    668     if (tv == NULL)
    669     {
    670 	tv = &thistime;
    671     }
    672 
    673     /* get the current time */
    674 #ifdef HAVE_GETTIMEOFDAY
    675     gettimeofday(tv, NULL);
    676 #else
    677     tv->tv_sec = (long)time(NULL);
    678     tv->tv_usec = 0;
    679 #endif
    680 
    681     /* calculate the difference */
    682     timediff.tv_sec = tv->tv_sec - lasttime.tv_sec;
    683     timediff.tv_usec = tv->tv_usec - lasttime.tv_usec;
    684     if (timediff.tv_usec < 0) {
    685 	timediff.tv_sec--;
    686 	timediff.tv_usec += 1000000;
    687     }
    688 
    689     /* convert to milliseconds */
    690     elapsed_msecs = timediff.tv_sec * 1000 + timediff.tv_usec / 1000;
    691     if (elapsed_msecs == 0)
    692     {
    693 	elapsed_msecs = 1;
    694     }
    695 
    696     /* save for next time */
    697     lasttime = *tv;
    698 }
    699 
    700 unsigned int
    701 time_elapsed()
    702 
    703 {
    704     return elapsed_msecs;
    705 }
    706 
    707 unsigned int
    708 diff_per_second(unsigned int x, unsigned int y)
    709 
    710 {
    711     return (y > x ? UINT_MAX - y + x + 1 : x - y) * 1000 / elapsed_msecs;
    712 }
    713 
    714 void
    715 double2tv(struct timeval *tv, double d)
    716 {
    717     double di;
    718 
    719     di = floor(d);
    720     tv->tv_sec = (time_t)di;
    721     tv->tv_usec = (int)ceil((d - di) * 1000000.0);
    722 }
    723 
    724 static int debug_on = 0;
    725 
    726 #ifdef DEBUG
    727 FILE *debugfile;
    728 #endif
    729 
    730 void
    731 debug_set(int i)
    732 
    733 {
    734     debug_on = i;
    735 #ifdef DEBUG
    736     debugfile = fopen("/tmp/top.debug", "w");
    737 #endif
    738 }
    739 
    740 #ifdef DEBUG
    741 void
    742 xdprintf(char *fmt, ...)
    743 
    744 {
    745     va_list argp;
    746 
    747     va_start(argp, fmt);
    748 
    749     if (debug_on)
    750     {
    751 	vfprintf(debugfile, fmt, argp);
    752 	fflush(debugfile);
    753     }
    754 
    755     va_end(argp);
    756 }
    757 #endif
    758 
    759