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