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