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
alldigits(char * s)54 alldigits(char *s)
55
56 {
57 int ch;
58
59 while ((ch = *s++) != '\0')
60 {
61 if (!isdigit(ch))
62 {
63 return 0;
64 }
65 }
66 return 1;
67 }
68
69 int
atoiwi(char * str)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 *
itoa(int val)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 *
itoa_w(int val,int w)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 *
itoa7(int val)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
digits(int val)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 *
printable(char * str)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(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 *
strcpyend(char * to,const char * from)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
homogenize(const char * str)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(ch))
262 {
263 *to++ = tolower(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
string_index(const char * string,const char ** array)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
string_list(const char ** strings)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 **
argparse(char * line,int * cntp)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
percentages(int cnt,int * out,long * new,long * old,long * diffs)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 *
errmsg(int errnum)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 *
format_percent(double v)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 strcpy(result, " ???");
525 }
526 else if (v > 99.99)
527 {
528 sprintf(result, "%5.0f", v);
529 }
530 else
531 {
532 sprintf(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 *
format_time(long seconds)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 sprintf(result, "%5.1fH", (double)seconds / (double)(60l * 60l));
569
570 /* It is possible that the sprintf took more than 6 characters.
571 If so, then the "H" appears as result[6]. If not, then there
572 is a \0 in result[6]. Either way, it is safe to step on.
573 */
574 result[6] = '\0';
575 }
576 else
577 {
578 /* standard method produces MMM:SS */
579 /* we avoid printf as must as possible to make this quick */
580 sprintf(result, "%3ld:%02ld", seconds / 60l, seconds % 60l);
581 }
582 return(result);
583 }
584
585 /*
586 * format_k(amt) - format a kilobyte memory value, returning a string
587 * suitable for display. Returns a pointer to a static
588 * area that changes each call. "amt" is converted to a
589 * string with a trailing "K". If "amt" is 10000 or greater,
590 * then it is formatted as megabytes (rounded) with a
591 * trailing "M".
592 */
593
594 /*
595 * Compromise time. We need to return a string, but we don't want the
596 * caller to have to worry about freeing a dynamically allocated string.
597 * Unfortunately, we can't just return a pointer to a static area as one
598 * of the common uses of this function is in a large call to sprintf where
599 * it might get invoked several times. Our compromise is to maintain an
600 * array of strings and cycle thru them with each invocation. We make the
601 * array large enough to handle the above mentioned case. The constant
602 * NUM_STRINGS defines the number of strings in this array: we can tolerate
603 * up to NUM_STRINGS calls before we start overwriting old information.
604 * Keeping NUM_STRINGS a power of two will allow an intelligent optimizer
605 * to convert the modulo operation into something quicker. What a hack!
606 */
607
608 #define NUM_STRINGS 8
609
610 char *
format_k(long amt)611 format_k(long amt)
612
613 {
614 static char retarray[NUM_STRINGS][24];
615 static int idx = 0;
616 register char *ret;
617 register char tag = 'K';
618
619 ret = retarray[idx];
620 idx = (idx + 1) % NUM_STRINGS;
621
622 if (amt >= 10000)
623 {
624 amt = (amt + 512) / 1024;
625 tag = 'M';
626 if (amt >= 10000)
627 {
628 amt = (amt + 512) / 1024;
629 tag = 'G';
630 }
631 }
632
633 snprintf(ret, sizeof(retarray[idx])-1, "%ld%c", amt, tag);
634
635 return(ret);
636 }
637
638 /*
639 * Time keeping functions.
640 */
641
642 static struct timeval lasttime = { 0, 0 };
643 static unsigned int elapsed_msecs = 0;
644
645 void
time_get(struct timeval * tv)646 time_get(struct timeval *tv)
647
648 {
649 /* get the current time */
650 #ifdef HAVE_GETTIMEOFDAY
651 gettimeofday(tv, NULL);
652 #else
653 tv->tv_sec = (long)time(NULL);
654 tv->tv_usec = 0;
655 #endif
656 }
657
658 void
time_mark(struct timeval * tv)659 time_mark(struct timeval *tv)
660
661 {
662 struct timeval thistime;
663 struct timeval timediff;
664
665 /* if the caller didnt provide one then use our own */
666 if (tv == NULL)
667 {
668 tv = &thistime;
669 }
670
671 /* get the current time */
672 #ifdef HAVE_GETTIMEOFDAY
673 gettimeofday(tv, NULL);
674 #else
675 tv->tv_sec = (long)time(NULL);
676 tv->tv_usec = 0;
677 #endif
678
679 /* calculate the difference */
680 timediff.tv_sec = tv->tv_sec - lasttime.tv_sec;
681 timediff.tv_usec = tv->tv_usec - lasttime.tv_usec;
682 if (timediff.tv_usec < 0) {
683 timediff.tv_sec--;
684 timediff.tv_usec += 1000000;
685 }
686
687 /* convert to milliseconds */
688 elapsed_msecs = timediff.tv_sec * 1000 + timediff.tv_usec / 1000;
689 if (elapsed_msecs == 0)
690 {
691 elapsed_msecs = 1;
692 }
693
694 /* save for next time */
695 lasttime = *tv;
696 }
697
698 unsigned int
time_elapsed()699 time_elapsed()
700
701 {
702 return elapsed_msecs;
703 }
704
705 unsigned int
diff_per_second(unsigned int x,unsigned int y)706 diff_per_second(unsigned int x, unsigned int y)
707
708 {
709 return (y > x ? UINT_MAX - y + x + 1 : x - y) * 1000 / elapsed_msecs;
710 }
711
712 void
double2tv(struct timeval * tv,double d)713 double2tv(struct timeval *tv, double d)
714 {
715 double di;
716
717 di = floor(d);
718 tv->tv_sec = (time_t)di;
719 tv->tv_usec = (int)ceil((d - di) * 1000000.0);
720 }
721
722 static int debug_on = 0;
723
724 #ifdef DEBUG
725 FILE *debugfile;
726 #endif
727
728 void
debug_set(int i)729 debug_set(int i)
730
731 {
732 debug_on = i;
733 #ifdef DEBUG
734 debugfile = fopen("/tmp/top.debug", "w");
735 #endif
736 }
737
738 #ifdef DEBUG
739 void
xdprintf(char * fmt,...)740 xdprintf(char *fmt, ...)
741
742 {
743 va_list argp;
744
745 va_start(argp, fmt);
746
747 if (debug_on)
748 {
749 vfprintf(debugfile, fmt, argp);
750 fflush(debugfile);
751 }
752
753 va_end(argp);
754 }
755 #endif
756
757