856005af54ebab4a75de0ca7e9349e573b534071
[dragonfly.git] / contrib / top / utils.c
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 #ifdef HAVE_STDARG_H
45 #include <stdarg.h>
46 #else
47 #undef DEBUG
48 #endif
49 #include "top.h"
50 #include "utils.h"
51
52 static int
53 alldigits(char *s)
54
55 {
56     int ch;
57
58     while ((ch = *s++) != '\0')
59     {
60         if (!isdigit(ch))
61         {
62             return 0;
63         }
64     }
65     return 1;
66 }
67
68 int
69 atoiwi(char *str)
70
71 {
72     register int len;
73
74     len = strlen(str);
75     if (len != 0)
76     {
77         if (strncmp(str, "infinity", len) == 0 ||
78             strncmp(str, "all",      len) == 0 ||
79             strncmp(str, "maximum",  len) == 0)
80         {
81             return(Infinity);
82         }
83         else if (alldigits(str))
84         {
85             return(atoi(str));
86         }
87         else
88         {
89             return(Invalid);
90         }
91     }
92     return(0);
93 }
94
95 /*
96  *  itoa - convert integer (decimal) to ascii string for positive numbers
97  *         only (we don't bother with negative numbers since we know we
98  *         don't use them).
99  */
100
101                                 /*
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
105                                  * digits.
106                                  */
107
108 char *
109 itoa(int val)
110
111 {
112     register char *ptr;
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. */
117
118     ptr = buffer + sizeof(buffer);
119     *--ptr = '\0';
120     if (val == 0)
121     {
122         *--ptr = '0';
123     }
124     else while (val != 0)
125     {
126         *--ptr = (val % 10) + '0';
127         val /= 10;
128     }
129     return(ptr);
130 }
131
132 /*
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.
136  */
137
138 char *
139 itoa_w(int val, int w)
140
141 {
142     char *ptr;
143     char *eptr;
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. */
148
149     if (w > 15)
150     {
151         w = 15;
152     }
153     eptr = ptr = buffer + sizeof(buffer);
154     *--ptr = '\0';
155     if (val == 0)
156     {
157         *--ptr = '0';
158     }
159     else while (val != 0)
160     {
161         *--ptr = (val % 10) + '0';
162         val /= 10;
163     }
164     while (ptr >= eptr - w)
165     {
166         *--ptr = ' ';
167     }
168     return(ptr);
169 }
170
171 char *
172 itoa7(int val)
173
174 {
175     return itoa_w(val, 7);
176 }
177
178 /*
179  *  digits(val) - return number of decimal digits in val.  Only works for
180  *      positive numbers.  If val < 0 then digits(val) == 0, but
181  *      digits(0) == 1.
182  */
183
184 int
185 digits(int val)
186
187 {
188     register int cnt = 0;
189
190     if (val == 0)
191     {
192         return 1;
193     }
194     while (val > 0)
195     {
196         cnt++;
197         val /= 10;
198     }
199     return(cnt);
200 }
201
202 /*
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.
207  */
208
209 char *
210 printable(char *str)
211
212 {
213     register char *ptr;
214     register int ch;
215
216     ptr = str;
217     while ((ch = *ptr) != '\0')
218     {
219         if (!isprint(ch))
220         {
221             *ptr = '?';
222         }
223         ptr++;
224     }
225     return(str);
226 }
227
228 /*
229  *  strcpyend(to, from) - copy string "from" into "to" and return a pointer
230  *      to the END of the string "to".
231  */
232
233 char *
234 strcpyend(char *to, char *from)
235
236 {
237     while ((*to++ = *from++) != '\0');
238     return(--to);
239 }
240
241 /*
242  * char *
243  * homogenize(char *str)
244  *
245  * Remove unwanted characters from "str" and make everything lower case.
246  * Newly allocated string is returned: the original is not altered.
247  */
248
249 char *homogenize(char *str)
250
251 {
252     char *ans;
253     char *fr;
254     char *to;
255     int ch;
256
257     to = fr = ans = strdup(str);
258     while ((ch = *fr++) != '\0')
259     {
260         if (isalnum(ch))
261         {
262             *to++ = tolower(ch);
263         }
264     }
265
266     *to = '\0';
267     return ans;
268 }
269
270 /*
271  * string_index(string, array) - find string in array and return index
272  */
273
274 int
275 string_index(char *string, char **array)
276
277 {
278     register int i = 0;
279
280     while (*array != NULL)
281     {
282         if (strcmp(string, *array) == 0)
283         {
284             return(i);
285         }
286         array++;
287         i++;
288     }
289     return(-1);
290 }
291
292 /*
293  * char *string_list(char **strings)
294  *
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.
298  */
299
300 char *string_list(char **strings)
301
302 {
303     int cnt = 0;
304     char **pp;
305     char *p;
306     char *result = NULL;
307     char *resp = NULL;
308
309     pp = strings;
310     while ((p = *pp++) != NULL)
311     {
312         cnt += strlen(p) + 2;
313     }
314
315     if (cnt > 0)
316     {
317         resp = result = (char *)malloc(cnt);
318         pp = strings;
319         while ((p = *pp++) != NULL)
320         {
321             resp = strcpyend(resp, p);
322             if (*pp != NULL)
323             {
324                 resp = strcpyend(resp, ", ");
325             }
326         }
327     }
328
329     return result;
330 }
331
332 /*
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.
337  */
338
339 char **
340 argparse(char *line, int *cntp)
341
342 {
343     register char *from;
344     register char *to;
345     register int cnt;
346     register int ch;
347     int length;
348     int lastch;
349     register char **argv;
350     char **argarray;
351     char *args;
352
353     /* unfortunately, the only real way to do this is to go thru the
354        input string twice. */
355
356     /* step thru the string counting the white space sections */
357     from = line;
358     lastch = cnt = length = 0;
359     while ((ch = *from++) != '\0')
360     {
361         length++;
362         if (ch == ' ' && lastch != ' ')
363         {
364             cnt++;
365         }
366         lastch = ch;
367     }
368
369     /* add three to the count:  one for the initial "dummy" argument,
370        one for the last argument and one for NULL */
371     cnt += 3;
372
373     /* allocate a char * array to hold the pointers */
374     argarray = (char **)malloc(cnt * sizeof(char *));
375
376     /* allocate another array to hold the strings themselves */
377     args = (char *)malloc(length+2);
378
379     /* initialization for main loop */
380     from = line;
381     to = args;
382     argv = argarray;
383     lastch = '\0';
384
385     /* create a dummy argument to keep getopt happy */
386     *argv++ = to;
387     *to++ = '\0';
388     cnt = 2;
389
390     /* now build argv while copying characters */
391     *argv++ = to;
392     while ((ch = *from++) != '\0')
393     {
394         if (ch != ' ')
395         {
396             if (lastch == ' ')
397             {
398                 *to++ = '\0';
399                 *argv++ = to;
400                 cnt++;
401             }
402             *to++ = ch;
403         }
404         lastch = ch;
405     }
406     *to++ = '\0';
407
408     /* set cntp and return the allocated array */
409     *cntp = cnt;
410     return(argarray);
411 }
412
413 /*
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.
420  */
421
422 long
423 percentages(int cnt, int *out, long *new, long *old, long *diffs)
424
425 {
426     register int i;
427     register long change;
428     register long total_change;
429     register long *dp;
430     long half_total;
431
432     /* initialization */
433     total_change = 0;
434     dp = diffs;
435
436     /* calculate changes for each state and the overall change */
437     for (i = 0; i < cnt; i++)
438     {
439         if ((change = *new - *old) < 0)
440         {
441             /* this only happens when the counter wraps */
442             change = (int)
443                 ((unsigned long)*new-(unsigned long)*old);
444         }
445         total_change += (*dp++ = change);
446         *old++ = *new++;
447     }
448
449     /* avoid divide by zero potential */
450     if (total_change == 0)
451     {
452         total_change = 1;
453     }
454
455     /* calculate percentages based on overall change, rounding up */
456     half_total = total_change / 2l;
457     for (i = 0; i < cnt; i++)
458     {
459         *out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
460     }
461
462     /* return the total in case the caller wants to use it */
463     return(total_change);
464 }
465
466 /*
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
474  *           use strerror.
475  */
476
477 /* externs referenced by errmsg */
478
479 #ifndef HAVE_STRERROR
480 #if !HAVE_DECL_SYS_ERRLIST
481 extern char *sys_errlist[];
482 #endif
483
484 extern int sys_nerr;
485 #endif
486
487 char *
488 errmsg(int errnum)
489
490 {
491 #ifdef HAVE_STRERROR
492     char *msg = strerror(errnum);
493     if (msg != NULL)
494     {
495         return msg;
496     }
497 #else
498     if (errnum > 0 && errnum < sys_nerr)
499     {
500         return((char *)(sys_errlist[errnum]));
501     }
502 #endif
503     return("No error");
504 }
505
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.
511  */
512
513 char *
514 format_percent(double v)
515
516 {
517     static char result[10];
518
519     /* enumerate the possibilities */
520     if (v < 0 || v >= 100000.)
521     {
522         /* we dont want to try extreme values */
523         strcpy(result, "  ???");
524     }
525     else if (v > 99.99)
526     {
527         sprintf(result, "%5.0f", v);
528     }
529     else
530     {
531         sprintf(result, "%5.2f", v);
532     }
533
534     return result;
535 }
536
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.
543  */
544
545 /* Explanation:
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 "???".
551  */
552
553 char *
554 format_time(long seconds)
555
556 {
557     static char result[10];
558
559     /* sanity protection */
560     if (seconds < 0 || seconds > (99999l * 360l))
561     {
562         strcpy(result, "   ???");
563     }
564     else if (seconds >= (1000l * 60l))
565     {
566         /* alternate (slow) method displaying hours and tenths */
567         sprintf(result, "%5.1fH", (double)seconds / (double)(60l * 60l));
568
569         /* It is possible that the sprintf took more than 6 characters.
570            If so, then the "H" appears as result[6].  If not, then there
571            is a \0 in result[6].  Either way, it is safe to step on.
572          */
573         result[6] = '\0';
574     }
575     else
576     {
577         /* standard method produces MMM:SS */
578         /* we avoid printf as must as possible to make this quick */
579         sprintf(result, "%3ld:%02ld", seconds / 60l, seconds % 60l);
580     }
581     return(result);
582 }
583
584 /*
585  * format_k(amt) - format a kilobyte memory value, returning a string
586  *              suitable for display.  Returns a pointer to a static
587  *              area that changes each call.  "amt" is converted to a
588  *              string with a trailing "K".  If "amt" is 10000 or greater,
589  *              then it is formatted as megabytes (rounded) with a
590  *              trailing "M".
591  */
592
593 /*
594  * Compromise time.  We need to return a string, but we don't want the
595  * caller to have to worry about freeing a dynamically allocated string.
596  * Unfortunately, we can't just return a pointer to a static area as one
597  * of the common uses of this function is in a large call to sprintf where
598  * it might get invoked several times.  Our compromise is to maintain an
599  * array of strings and cycle thru them with each invocation.  We make the
600  * array large enough to handle the above mentioned case.  The constant
601  * NUM_STRINGS defines the number of strings in this array:  we can tolerate
602  * up to NUM_STRINGS calls before we start overwriting old information.
603  * Keeping NUM_STRINGS a power of two will allow an intelligent optimizer
604  * to convert the modulo operation into something quicker.  What a hack!
605  */
606
607 #define NUM_STRINGS 8
608
609 char *
610 format_k(long amt)
611
612 {
613     static char retarray[NUM_STRINGS][16];
614     static int index = 0;
615     register char *ret;
616     register char tag = 'K';
617
618     ret = retarray[index];
619     index = (index + 1) % NUM_STRINGS;
620
621     if (amt >= 10000)
622     {
623         amt = (amt + 512) / 1024;
624         tag = 'M';
625         if (amt >= 10000)
626         {
627             amt = (amt + 512) / 1024;
628             tag = 'G';
629         }
630     }
631
632     snprintf(ret, sizeof(retarray[index])-1, "%ld%c", amt, tag);
633
634     return(ret);
635 }
636
637 /*
638  * Time keeping functions.  
639  */
640
641 static struct timeval lasttime = { 0, 0 };
642 static unsigned int elapsed_msecs = 0;
643
644 void
645 time_get(struct timeval *tv)
646
647 {
648     /* get the current time */
649 #ifdef HAVE_GETTIMEOFDAY
650     gettimeofday(tv, NULL);
651 #else
652     tv->tv_sec = (long)time(NULL);
653     tv->tv_usec = 0;
654 #endif
655 }
656
657 void
658 time_mark(struct timeval *tv)
659
660 {
661     struct timeval thistime;
662     struct timeval timediff;
663
664     /* if the caller didnt provide one then use our own */
665     if (tv == NULL)
666     {
667         tv = &thistime;
668     }
669
670     /* get the current time */
671 #ifdef HAVE_GETTIMEOFDAY
672     gettimeofday(tv, NULL);
673 #else
674     tv->tv_sec = (long)time(NULL);
675     tv->tv_usec = 0;
676 #endif
677
678     /* calculate the difference */
679     timediff.tv_sec = tv->tv_sec - lasttime.tv_sec;
680     timediff.tv_usec = tv->tv_usec - lasttime.tv_usec;
681     if (timediff.tv_usec < 0) {
682         timediff.tv_sec--;
683         timediff.tv_usec += 1000000;
684     }
685
686     /* convert to milliseconds */
687     elapsed_msecs = timediff.tv_sec * 1000 + timediff.tv_usec / 1000;
688     if (elapsed_msecs == 0)
689     {
690         elapsed_msecs = 1;
691     }
692
693     /* save for next time */
694     lasttime = *tv;
695 }
696
697 unsigned int
698 time_elapsed()
699
700 {
701     return elapsed_msecs;
702 }
703
704 unsigned int
705 diff_per_second(unsigned int x, unsigned int y)
706
707 {
708     return (y > x ? UINT_MAX - y + x + 1 : x - y) * 1000 / elapsed_msecs;
709 }
710
711 static int debug_on = 0;
712
713 #ifdef DEBUG
714 FILE *debugfile;
715 #endif
716
717 void
718 debug_set(int i)
719
720 {
721     debug_on = i;
722 #ifdef DEBUG
723     debugfile = fopen("/tmp/top.debug", "w");
724 #endif
725 }
726
727 #ifdef DEBUG
728 void
729 xdprintf(char *fmt, ...)
730
731 {
732     va_list argp;
733
734     va_start(argp, fmt);
735
736     if (debug_on)
737     {
738         vfprintf(debugfile, fmt, argp);
739         fflush(debugfile);
740     }
741
742     va_end(argp);
743 }
744 #endif
745