diff options
author | Edwin Groothuis <edwin@FreeBSD.org> | 2009-05-21 07:54:21 +0000 |
---|---|---|
committer | Edwin Groothuis <edwin@FreeBSD.org> | 2009-05-21 07:54:21 +0000 |
commit | b16ac5b53f6b943b7017f01d411721173b4f1b96 (patch) | |
tree | 4f4a683a19a5fb250b588f359f30f135a697f2f7 /utils.c | |
parent | c1dc0a1745ca8959fc4ce61ce026e2a83984c13e (diff) | |
download | src-b16ac5b53f6b943b7017f01d411721173b4f1b96.tar.gz src-b16ac5b53f6b943b7017f01d411721173b4f1b96.zip |
Vendor import of top-3.8b1vendor/top/3.8b1vendor/top
Obtained from: http://www.unixtop.org
Notes
Notes:
svn path=/vendor/top/dist/; revision=192526
svn path=/vendor/top/3.8b1/; revision=192527; tag=vendor/top/3.8b1
Diffstat (limited to 'utils.c')
-rw-r--r-- | utils.c | 409 |
1 files changed, 343 insertions, 66 deletions
@@ -1,24 +1,72 @@ /* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* * Top users/processes display for Unix * Version 3 - * - * This program may be freely redistributed, - * but this entire comment MUST remain intact. - * - * Copyright (c) 1984, 1989, William LeFebvre, Rice University - * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University */ /* * This file contains various handy utilities used by top. */ -#include "top.h" #include "os.h" +#include <ctype.h> +#ifdef HAVE_STDARG_H +#include <stdarg.h> +#else +#undef DEBUG +#endif +#include "top.h" +#include "utils.h" + +static int +alldigits(char *s) -int atoiwi(str) +{ + int ch; + + while ((ch = *s++) != '\0') + { + if (!isdigit(ch)) + { + return 0; + } + } + return 1; +} -char *str; +int +atoiwi(char *str) { register int len; @@ -32,13 +80,13 @@ char *str; { return(Infinity); } - else if (str[0] == '-') + else if (alldigits(str)) { - return(Invalid); + return(atoi(str)); } else { - return(atoi(str)); + return(Invalid); } } return(0); @@ -57,9 +105,8 @@ char *str; * digits. */ -char *itoa(val) - -register int val; +char * +itoa(int val) { register char *ptr; @@ -88,18 +135,22 @@ register int val; * a front end to a more general routine for efficiency. */ -char *itoa7(val) - -register int val; +char * +itoa_w(int val, int w) { - register char *ptr; + char *ptr; + char *eptr; static char buffer[16]; /* result is built here */ /* 16 is sufficient since the largest number we will ever convert will be 2^32-1, which is 10 digits. */ - ptr = buffer + sizeof(buffer); + if (w > 15) + { + w = 15; + } + eptr = ptr = buffer + sizeof(buffer); *--ptr = '\0'; if (val == 0) { @@ -110,25 +161,36 @@ register int val; *--ptr = (val % 10) + '0'; val /= 10; } - while (ptr > buffer + sizeof(buffer) - 7) + while (ptr >= eptr - w) { *--ptr = ' '; } return(ptr); } +char * +itoa7(int val) + +{ + return itoa_w(val, 7); +} + /* * digits(val) - return number of decimal digits in val. Only works for - * positive numbers. If val <= 0 then digits(val) == 0. + * positive numbers. If val < 0 then digits(val) == 0, but + * digits(0) == 1. */ -int digits(val) - -int val; +int +digits(int val) { register int cnt = 0; + if (val == 0) + { + return 1; + } while (val > 0) { cnt++; @@ -138,14 +200,38 @@ int val; } /* - * strecpy(to, from) - copy string "from" into "to" and return a pointer - * to the END of the string "to". + * printable(char *str) - make the string pointed to by "str" into one that is + * printable (i.e.: all ascii), by converting all non-printable + * characters into '?'. Replacements are done in place and a pointer + * to the original buffer is returned. */ -char *strecpy(to, from) +char * +printable(char *str) -register char *to; -register char *from; +{ + register char *ptr; + register int ch; + + ptr = str; + while ((ch = *ptr) != '\0') + { + if (!isprint(ch)) + { + *ptr = '?'; + } + ptr++; + } + return(str); +} + +/* + * strcpyend(to, from) - copy string "from" into "to" and return a pointer + * to the END of the string "to". + */ + +char * +strcpyend(char *to, char *from) { while ((*to++ = *from++) != '\0'); @@ -153,13 +239,40 @@ register char *from; } /* - * string_index(string, array) - find string in array and return index + * char * + * homogenize(char *str) + * + * Remove unwanted characters from "str" and make everything lower case. + * Newly allocated string is returned: the original is not altered. */ -int string_index(string, array) +char *homogenize(char *str) + +{ + char *ans; + char *fr; + char *to; + int ch; + + to = fr = ans = strdup(str); + while ((ch = *fr++) != '\0') + { + if (isalnum(ch)) + { + *to++ = tolower(ch); + } + } -char *string; -char **array; + *to = '\0'; + return ans; +} + +/* + * string_index(string, array) - find string in array and return index + */ + +int +string_index(char *string, char **array) { register int i = 0; @@ -177,16 +290,54 @@ char **array; } /* + * char *string_list(char **strings) + * + * Create a comma-separated list of the strings in the NULL-terminated + * "strings". Returned string is malloc-ed and should be freed when the + * caller is done. Note that this is not an efficient function. + */ + +char *string_list(char **strings) + +{ + int cnt = 0; + char **pp; + char *p; + char *result = NULL; + char *resp = NULL; + + pp = strings; + while ((p = *pp++) != NULL) + { + cnt += strlen(p) + 2; + } + + if (cnt > 0) + { + resp = result = (char *)malloc(cnt); + pp = strings; + while ((p = *pp++) != NULL) + { + resp = strcpyend(resp, p); + if (*pp != NULL) + { + resp = strcpyend(resp, ", "); + } + } + } + + return result; +} + +/* * argparse(line, cntp) - parse arguments in string "line", separating them * out into an argv-like array, and setting *cntp to the number of * arguments encountered. This is a simple parser that doesn't understand * squat about quotes. */ -char **argparse(line, cntp) - -char *line; -int *cntp; +char ** +argparse(char *line, int *cntp) { register char *from; @@ -268,13 +419,8 @@ int *cntp; * useful on BSD mchines for calculating cpu state percentages. */ -long percentages(cnt, out, new, old, diffs) - -int cnt; -int *out; -register long *new; -register long *old; -long *diffs; +long +percentages(int cnt, int *out, long *new, long *old, long *diffs) { register int i; @@ -331,17 +477,15 @@ long *diffs; /* externs referenced by errmsg */ #ifndef HAVE_STRERROR -#ifndef SYS_ERRLIST_DECLARED -#define SYS_ERRLIST_DECLARED +#if !HAVE_DECL_SYS_ERRLIST extern char *sys_errlist[]; #endif extern int sys_nerr; #endif -char *errmsg(errnum) - -int errnum; +char * +errmsg(int errnum) { #ifdef HAVE_STRERROR @@ -353,12 +497,43 @@ int errnum; #else if (errnum > 0 && errnum < sys_nerr) { - return(sys_errlist[errnum]); + return((char *)(sys_errlist[errnum])); } #endif return("No error"); } +/* format_percent(v) - format a double as a percentage in a manner that + * does not exceed 5 characters (excluding any trailing + * percent sign). Since it is possible for the value + * to exceed 100%, we format such values with no fractional + * component to fit within the 5 characters. + */ + +char * +format_percent(double v) + +{ + static char result[10]; + + /* enumerate the possibilities */ + if (v < 0 || v >= 100000.) + { + /* we dont want to try extreme values */ + strcpy(result, " ???"); + } + else if (v > 99.99) + { + sprintf(result, "%5.0f", v); + } + else + { + sprintf(result, "%5.2f", v); + } + + return result; +} + /* format_time(seconds) - format number of seconds into a suitable * display that will fit within 6 characters. Note that this * routine builds its string in a static area. If it needs @@ -375,14 +550,10 @@ int errnum; exceed 9999.9, we use "???". */ -char *format_time(seconds) - -long seconds; +char * +format_time(long seconds) { - register int value; - register int digit; - register char *ptr; static char result[10]; /* sanity protection */ @@ -405,7 +576,7 @@ long seconds; { /* standard method produces MMM:SS */ /* we avoid printf as must as possible to make this quick */ - sprintf(result, "%3d:%02d", seconds / 60l, seconds % 60l); + sprintf(result, "%3ld:%02ld", seconds / 60l, seconds % 60l); } return(result); } @@ -435,18 +606,16 @@ long seconds; #define NUM_STRINGS 8 -char *format_k(amt) - -int amt; +char * +format_k(long amt) { static char retarray[NUM_STRINGS][16]; static int index = 0; - register char *p; register char *ret; register char tag = 'K'; - p = ret = retarray[index]; + ret = retarray[index]; index = (index + 1) % NUM_STRINGS; if (amt >= 10000) @@ -460,9 +629,117 @@ int amt; } } - p = strecpy(p, itoa(amt)); - *p++ = tag; - *p = '\0'; + snprintf(ret, sizeof(retarray[index])-1, "%ld%c", amt, tag); return(ret); } + +/* + * Time keeping functions. + */ + +static struct timeval lasttime = { 0, 0 }; +static unsigned int elapsed_msecs = 0; + +void +time_get(struct timeval *tv) + +{ + /* get the current time */ +#ifdef HAVE_GETTIMEOFDAY + gettimeofday(tv, NULL); +#else + tv->tv_sec = (long)time(NULL); + tv->tv_usec = 0; +#endif +} + +void +time_mark(struct timeval *tv) + +{ + struct timeval thistime; + struct timeval timediff; + + /* if the caller didnt provide one then use our own */ + if (tv == NULL) + { + tv = &thistime; + } + + /* get the current time */ +#ifdef HAVE_GETTIMEOFDAY + gettimeofday(tv, NULL); +#else + tv->tv_sec = (long)time(NULL); + tv->tv_usec = 0; +#endif + + /* calculate the difference */ + timediff.tv_sec = tv->tv_sec - lasttime.tv_sec; + timediff.tv_usec = tv->tv_usec - lasttime.tv_usec; + if (timediff.tv_usec < 0) { + timediff.tv_sec--; + timediff.tv_usec += 1000000; + } + + /* convert to milliseconds */ + elapsed_msecs = timediff.tv_sec * 1000 + timediff.tv_usec / 1000; + if (elapsed_msecs == 0) + { + elapsed_msecs = 1; + } + + /* save for next time */ + lasttime = *tv; +} + +unsigned int +time_elapsed() + +{ + return elapsed_msecs; +} + +unsigned int +diff_per_second(unsigned int x, unsigned int y) + +{ + return (y > x ? UINT_MAX - y + x + 1 : x - y) * 1000 / elapsed_msecs; +} + +static int debug_on = 0; + +#ifdef DEBUG +FILE *debugfile; +#endif + +void +debug_set(int i) + +{ + debug_on = i; +#ifdef DEBUG + debugfile = fopen("/tmp/top.debug", "w"); +#endif +} + +#ifdef DEBUG +void +xdprintf(char *fmt, ...) + +{ + va_list argp; + + va_start(argp, fmt); + + if (debug_on) + { + vfprintf(debugfile, fmt, argp); + fflush(debugfile); + } + + va_end(argp); +} +#endif + |