GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: main.c,v 1.16 2016/08/14 22:29:01 krw Exp $ */ |
||
2 |
/* |
||
3 |
* Copyright (c) 1994 Christopher G. Demetriou |
||
4 |
* All rights reserved. |
||
5 |
* |
||
6 |
* Redistribution and use in source and binary forms, with or without |
||
7 |
* modification, are permitted provided that the following conditions |
||
8 |
* are met: |
||
9 |
* 1. Redistributions of source code must retain the above copyright |
||
10 |
* notice, this list of conditions and the following disclaimer. |
||
11 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
12 |
* notice, this list of conditions and the following disclaimer in the |
||
13 |
* documentation and/or other materials provided with the distribution. |
||
14 |
* 3. All advertising materials mentioning features or use of this software |
||
15 |
* must display the following acknowledgement: |
||
16 |
* This product includes software developed by Christopher G. Demetriou. |
||
17 |
* 4. The name of the author may not be used to endorse or promote products |
||
18 |
* derived from this software without specific prior written permission |
||
19 |
* |
||
20 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
||
21 |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
||
22 |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
||
23 |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
||
24 |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||
25 |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
26 |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||
27 |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
28 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
||
29 |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
30 |
*/ |
||
31 |
|||
32 |
/* |
||
33 |
* sa: system accounting |
||
34 |
*/ |
||
35 |
|||
36 |
#include <sys/types.h> |
||
37 |
#include <sys/acct.h> |
||
38 |
#include <ctype.h> |
||
39 |
#include <err.h> |
||
40 |
#include <fcntl.h> |
||
41 |
#include <signal.h> |
||
42 |
#include <stdio.h> |
||
43 |
#include <stdlib.h> |
||
44 |
#include <string.h> |
||
45 |
#include <unistd.h> |
||
46 |
#include "extern.h" |
||
47 |
#include "pathnames.h" |
||
48 |
|||
49 |
static int acct_load(char *, int); |
||
50 |
static uint64_t decode_comp_t(comp_t); |
||
51 |
static int cmp_comm(const char *, const char *); |
||
52 |
static int cmp_usrsys(const DBT *, const DBT *); |
||
53 |
static int cmp_avgusrsys(const DBT *, const DBT *); |
||
54 |
static int cmp_dkio(const DBT *, const DBT *); |
||
55 |
static int cmp_avgdkio(const DBT *, const DBT *); |
||
56 |
static int cmp_cpumem(const DBT *, const DBT *); |
||
57 |
static int cmp_avgcpumem(const DBT *, const DBT *); |
||
58 |
static int cmp_calls(const DBT *, const DBT *); |
||
59 |
|||
60 |
int aflag, bflag, cflag, dflag, Dflag, fflag, iflag, jflag, kflag; |
||
61 |
int Kflag, lflag, mflag, qflag, rflag, sflag, tflag, uflag, vflag; |
||
62 |
int cutoff = 1; |
||
63 |
|||
64 |
static char *dfltargv[] = { _PATH_ACCT }; |
||
65 |
static int dfltargc = (sizeof(dfltargv)/sizeof(char *)); |
||
66 |
|||
67 |
/* default to comparing by sum of user + system time */ |
||
68 |
cmpf_t sa_cmp = cmp_usrsys; |
||
69 |
|||
70 |
int |
||
71 |
main(int argc, char **argv) |
||
72 |
{ |
||
73 |
int ch; |
||
74 |
int error = 0; |
||
75 |
10 |
const char *errstr; |
|
76 |
extern char *__progname; |
||
77 |
|||
78 |
✗✓ | 5 |
if (pledge("stdio rpath wpath cpath getpw flock", NULL) == -1) |
79 |
err(1, "pledge"); |
||
80 |
|||
81 |
✓✓ | 30 |
while ((ch = getopt(argc, argv, "abcdDfijkKlmnqrstuv:")) != -1) |
82 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✓ ✗✗✗✗ |
10 |
switch (ch) { |
83 |
case 'a': |
||
84 |
/* print all commands */ |
||
85 |
aflag = 1; |
||
86 |
break; |
||
87 |
case 'b': |
||
88 |
/* sort by per-call user/system time average */ |
||
89 |
bflag = 1; |
||
90 |
sa_cmp = cmp_avgusrsys; |
||
91 |
break; |
||
92 |
case 'c': |
||
93 |
/* print percentage total time */ |
||
94 |
cflag = 1; |
||
95 |
break; |
||
96 |
case 'd': |
||
97 |
/* sort by averge number of disk I/O ops */ |
||
98 |
dflag = 1; |
||
99 |
sa_cmp = cmp_avgdkio; |
||
100 |
break; |
||
101 |
case 'D': |
||
102 |
/* print and sort by total disk I/O ops */ |
||
103 |
Dflag = 1; |
||
104 |
sa_cmp = cmp_dkio; |
||
105 |
break; |
||
106 |
case 'f': |
||
107 |
/* force no interactive threshold comprison */ |
||
108 |
fflag = 1; |
||
109 |
break; |
||
110 |
case 'i': |
||
111 |
/* do not read in summary file */ |
||
112 |
iflag = 1; |
||
113 |
break; |
||
114 |
case 'j': |
||
115 |
/* instead of total minutes, give sec/call */ |
||
116 |
jflag = 1; |
||
117 |
break; |
||
118 |
case 'k': |
||
119 |
/* sort by cpu-time average memory usage */ |
||
120 |
kflag = 1; |
||
121 |
sa_cmp = cmp_avgcpumem; |
||
122 |
break; |
||
123 |
case 'K': |
||
124 |
/* print and sort by cpu-storage integral */ |
||
125 |
sa_cmp = cmp_cpumem; |
||
126 |
Kflag = 1; |
||
127 |
break; |
||
128 |
case 'l': |
||
129 |
/* separate system and user time */ |
||
130 |
lflag = 1; |
||
131 |
break; |
||
132 |
case 'm': |
||
133 |
/* print procs and time per-user */ |
||
134 |
mflag = 1; |
||
135 |
break; |
||
136 |
case 'n': |
||
137 |
/* sort by number of calls */ |
||
138 |
sa_cmp = cmp_calls; |
||
139 |
break; |
||
140 |
case 'q': |
||
141 |
/* quiet; error messages only */ |
||
142 |
5 |
qflag = 1; |
|
143 |
5 |
break; |
|
144 |
case 'r': |
||
145 |
/* reverse order of sort */ |
||
146 |
rflag = 1; |
||
147 |
break; |
||
148 |
case 's': |
||
149 |
/* merge accounting file into summaries */ |
||
150 |
5 |
sflag = 1; |
|
151 |
5 |
break; |
|
152 |
case 't': |
||
153 |
/* report ratio of user and system times */ |
||
154 |
tflag = 1; |
||
155 |
break; |
||
156 |
case 'u': |
||
157 |
/* first, print uid and command name */ |
||
158 |
uflag = 1; |
||
159 |
break; |
||
160 |
case 'v': |
||
161 |
/* cull junk */ |
||
162 |
vflag = 1; |
||
163 |
cutoff = strtonum(optarg, 1, INT_MAX, &errstr); |
||
164 |
if (errstr) |
||
165 |
errx(1, "-v %s: %s", optarg, errstr); |
||
166 |
break; |
||
167 |
case '?': |
||
168 |
default: |
||
169 |
(void)fprintf(stderr, |
||
170 |
"usage: %s [-abcDdfijKklmnqrstu] [-v cutoff]" |
||
171 |
" [file ...]\n", __progname); |
||
172 |
exit(1); |
||
173 |
} |
||
174 |
|||
175 |
5 |
argc -= optind; |
|
176 |
5 |
argv += optind; |
|
177 |
|||
178 |
/* various argument checking */ |
||
179 |
✗✓ | 5 |
if (fflag && !vflag) |
180 |
errx(1, "only one of -f requires -v"); |
||
181 |
✗✓ | 5 |
if (fflag && aflag) |
182 |
errx(1, "only one of -a and -v may be specified"); |
||
183 |
/* XXX need more argument checking */ |
||
184 |
|||
185 |
✓✗ | 5 |
if (!uflag) { |
186 |
/* initialize tables */ |
||
187 |
✗✓✗✗ ✗✓ |
10 |
if ((sflag || (!mflag && !qflag)) && pacct_init() != 0) |
188 |
errx(1, "process accounting initialization failed"); |
||
189 |
✗✓✗✗ ✗✓ |
10 |
if ((sflag || (mflag && !qflag)) && usracct_init() != 0) |
190 |
errx(1, "user accounting initialization failed"); |
||
191 |
} |
||
192 |
|||
193 |
✓✗ | 5 |
if (argc == 0) { |
194 |
5 |
argc = dfltargc; |
|
195 |
argv = dfltargv; |
||
196 |
5 |
} |
|
197 |
|||
198 |
/* for each file specified */ |
||
199 |
✓✓ | 20 |
for (; argc > 0; argc--, argv++) { |
200 |
int fd; |
||
201 |
|||
202 |
/* |
||
203 |
* load the accounting data from the file. |
||
204 |
* if it fails, go on to the next file. |
||
205 |
*/ |
||
206 |
5 |
fd = acct_load(argv[0], sflag); |
|
207 |
✗✓ | 5 |
if (fd < 0) |
208 |
continue; |
||
209 |
|||
210 |
✓✗ | 5 |
if (!uflag && sflag) { |
211 |
#ifndef DEBUG |
||
212 |
5 |
sigset_t nmask, omask; |
|
213 |
int unmask = 1; |
||
214 |
|||
215 |
/* |
||
216 |
* block most signals so we aren't interrupted during |
||
217 |
* the update. |
||
218 |
*/ |
||
219 |
✗✓ | 5 |
if (sigfillset(&nmask) == -1) { |
220 |
warn("sigfillset"); |
||
221 |
unmask = 0; |
||
222 |
error = 1; |
||
223 |
} |
||
224 |
✓✗✗✓ |
10 |
if (unmask && |
225 |
5 |
(sigprocmask(SIG_BLOCK, &nmask, &omask) == -1)) { |
|
226 |
warn("couldn't set signal mask "); |
||
227 |
unmask = 0; |
||
228 |
error = 1; |
||
229 |
} |
||
230 |
#endif /* DEBUG */ |
||
231 |
|||
232 |
/* |
||
233 |
* truncate the accounting data file ASAP, to avoid |
||
234 |
* losing data. don't worry about errors in updating |
||
235 |
* the saved stats; better to underbill than overbill, |
||
236 |
* but we want every accounting record intact. |
||
237 |
*/ |
||
238 |
✗✓ | 5 |
if (ftruncate(fd, 0) == -1) { |
239 |
warn("couldn't truncate %s", *argv); |
||
240 |
error = 1; |
||
241 |
} |
||
242 |
|||
243 |
/* |
||
244 |
* update saved user and process accounting data. |
||
245 |
* note errors for later. |
||
246 |
*/ |
||
247 |
✓✗✗✓ |
10 |
if (pacct_update() != 0 || usracct_update() != 0) |
248 |
error = 1; |
||
249 |
|||
250 |
#ifndef DEBUG |
||
251 |
/* |
||
252 |
* restore signals |
||
253 |
*/ |
||
254 |
✓✗✗✓ |
10 |
if (unmask && |
255 |
5 |
(sigprocmask(SIG_SETMASK, &omask, NULL) == -1)) { |
|
256 |
warn("couldn't restore signal mask"); |
||
257 |
error = 1; |
||
258 |
} |
||
259 |
#endif /* DEBUG */ |
||
260 |
5 |
} |
|
261 |
|||
262 |
/* |
||
263 |
* close the opened accounting file |
||
264 |
*/ |
||
265 |
✗✓ | 5 |
if (close(fd) == -1) { |
266 |
warn("close %s", *argv); |
||
267 |
error = 1; |
||
268 |
} |
||
269 |
5 |
} |
|
270 |
|||
271 |
✗✓ | 5 |
if (!uflag && !qflag) { |
272 |
/* print any results we may have obtained. */ |
||
273 |
if (!mflag) |
||
274 |
pacct_print(); |
||
275 |
else |
||
276 |
usracct_print(); |
||
277 |
} |
||
278 |
|||
279 |
✓✗ | 5 |
if (!uflag) { |
280 |
/* finally, deallocate databases */ |
||
281 |
✗✓✗✗ |
5 |
if (sflag || (!mflag && !qflag)) |
282 |
5 |
pacct_destroy(); |
|
283 |
✗✓✗✗ |
5 |
if (sflag || (mflag && !qflag)) |
284 |
5 |
usracct_destroy(); |
|
285 |
} |
||
286 |
|||
287 |
exit(error); |
||
288 |
} |
||
289 |
|||
290 |
static int |
||
291 |
acct_load(char *pn, int wr) |
||
292 |
{ |
||
293 |
10 |
struct acct ac; |
|
294 |
5 |
struct cmdinfo ci; |
|
295 |
ssize_t rv; |
||
296 |
int fd, i; |
||
297 |
|||
298 |
/* |
||
299 |
* open the file |
||
300 |
*/ |
||
301 |
5 |
fd = open(pn, wr ? O_RDWR : O_RDONLY, 0); |
|
302 |
✗✓ | 5 |
if (fd == -1) { |
303 |
warn("open %s %s", pn, wr ? "for read/write" : "read-only"); |
||
304 |
return (-1); |
||
305 |
} |
||
306 |
|||
307 |
/* |
||
308 |
* read all we can; don't stat and open because more processes |
||
309 |
* could exit, and we'd miss them |
||
310 |
*/ |
||
311 |
298128 |
while (1) { |
|
312 |
/* get one accounting entry and punt if there's an error */ |
||
313 |
298128 |
rv = read(fd, &ac, sizeof(struct acct)); |
|
314 |
✗✓ | 298128 |
if (rv == -1) |
315 |
warn("error reading %s", pn); |
||
316 |
✗✓ | 298128 |
else if (rv > 0 && rv < sizeof(struct acct)) |
317 |
warnx("short read of accounting data in %s", pn); |
||
318 |
✓✓ | 298128 |
if (rv != sizeof(struct acct)) |
319 |
break; |
||
320 |
|||
321 |
/* decode it */ |
||
322 |
298123 |
ci.ci_calls = 1; |
|
323 |
✓✓✓✓ |
3607377 |
for (i = 0; i < sizeof(ac.ac_comm) && ac.ac_comm[i] != '\0'; |
324 |
904719 |
i++) { |
|
325 |
unsigned char c = ac.ac_comm[i]; |
||
326 |
|||
327 |
✓✗✗✓ |
1809438 |
if (!isascii(c) || iscntrl(c)) { |
328 |
ci.ci_comm[i] = '?'; |
||
329 |
ci.ci_flags |= CI_UNPRINTABLE; |
||
330 |
} else |
||
331 |
904719 |
ci.ci_comm[i] = c; |
|
332 |
} |
||
333 |
✓✓ | 298123 |
if (ac.ac_flag & AFORK) |
334 |
32448 |
ci.ci_comm[i++] = '*'; |
|
335 |
298123 |
ci.ci_comm[i++] = '\0'; |
|
336 |
298123 |
ci.ci_etime = decode_comp_t(ac.ac_etime); |
|
337 |
298123 |
ci.ci_utime = decode_comp_t(ac.ac_utime); |
|
338 |
298123 |
ci.ci_stime = decode_comp_t(ac.ac_stime); |
|
339 |
298123 |
ci.ci_uid = ac.ac_uid; |
|
340 |
298123 |
ci.ci_mem = ac.ac_mem; |
|
341 |
298123 |
ci.ci_io = decode_comp_t(ac.ac_io) / AHZ; |
|
342 |
|||
343 |
✓✗ | 298123 |
if (!uflag) { |
344 |
/* and enter it into the usracct and pacct databases */ |
||
345 |
✗✓✗✗ |
298123 |
if (sflag || (!mflag && !qflag)) |
346 |
298123 |
pacct_add(&ci); |
|
347 |
✗✓✗✗ |
298123 |
if (sflag || (mflag && !qflag)) |
348 |
298123 |
usracct_add(&ci); |
|
349 |
} else if (!qflag) |
||
350 |
printf("%6u %12.2f cpu %12lluk mem %12llu io %s\n", |
||
351 |
ci.ci_uid, |
||
352 |
(ci.ci_utime + ci.ci_stime) / (double) AHZ, |
||
353 |
ci.ci_mem, ci.ci_io, ci.ci_comm); |
||
354 |
} |
||
355 |
|||
356 |
/* finally, return the file descriptor for possible truncation */ |
||
357 |
5 |
return (fd); |
|
358 |
5 |
} |
|
359 |
|||
360 |
static uint64_t |
||
361 |
decode_comp_t(comp_t comp) |
||
362 |
{ |
||
363 |
uint64_t rv; |
||
364 |
|||
365 |
/* |
||
366 |
* for more info on the comp_t format, see: |
||
367 |
* /usr/src/sys/kern/kern_acct.c |
||
368 |
* /usr/src/sys/sys/acct.h |
||
369 |
* /usr/src/usr.bin/lastcomm/lastcomm.c |
||
370 |
*/ |
||
371 |
2384984 |
rv = comp & 0x1fff; /* 13 bit fraction */ |
|
372 |
1192492 |
comp >>= 13; /* 3 bit base-8 exponent */ |
|
373 |
✓✓ | 2386510 |
while (comp--) |
374 |
763 |
rv <<= 3; |
|
375 |
|||
376 |
1192492 |
return (rv); |
|
377 |
} |
||
378 |
|||
379 |
/* sort commands, doing the right thing in terms of reversals */ |
||
380 |
static int |
||
381 |
cmp_comm(const char *s1, const char *s2) |
||
382 |
{ |
||
383 |
int rv; |
||
384 |
|||
385 |
rv = strcmp(s1, s2); |
||
386 |
if (rv == 0) |
||
387 |
rv = -1; |
||
388 |
return (rflag ? rv : -rv); |
||
389 |
} |
||
390 |
|||
391 |
/* sort by total user and system time */ |
||
392 |
static int |
||
393 |
cmp_usrsys(const DBT *d1, const DBT *d2) |
||
394 |
{ |
||
395 |
struct cmdinfo c1, c2; |
||
396 |
uint64_t t1, t2; |
||
397 |
|||
398 |
memcpy(&c1, d1->data, sizeof(c1)); |
||
399 |
memcpy(&c2, d2->data, sizeof(c2)); |
||
400 |
|||
401 |
t1 = c1.ci_utime + c1.ci_stime; |
||
402 |
t2 = c2.ci_utime + c2.ci_stime; |
||
403 |
|||
404 |
if (t1 < t2) |
||
405 |
return -1; |
||
406 |
else if (t1 == t2) |
||
407 |
return (cmp_comm(c1.ci_comm, c2.ci_comm)); |
||
408 |
else |
||
409 |
return 1; |
||
410 |
} |
||
411 |
|||
412 |
/* sort by average user and system time */ |
||
413 |
static int |
||
414 |
cmp_avgusrsys(const DBT *d1, const DBT *d2) |
||
415 |
{ |
||
416 |
struct cmdinfo c1, c2; |
||
417 |
double t1, t2; |
||
418 |
|||
419 |
memcpy(&c1, d1->data, sizeof(c1)); |
||
420 |
memcpy(&c2, d2->data, sizeof(c2)); |
||
421 |
|||
422 |
t1 = c1.ci_utime + c1.ci_stime; |
||
423 |
t1 /= (double) (c1.ci_calls ? c1.ci_calls : 1); |
||
424 |
|||
425 |
t2 = c2.ci_utime + c2.ci_stime; |
||
426 |
t2 /= (double) (c2.ci_calls ? c2.ci_calls : 1); |
||
427 |
|||
428 |
if (t1 < t2) |
||
429 |
return -1; |
||
430 |
else if (t1 == t2) |
||
431 |
return (cmp_comm(c1.ci_comm, c2.ci_comm)); |
||
432 |
else |
||
433 |
return 1; |
||
434 |
} |
||
435 |
|||
436 |
/* sort by total number of disk I/O operations */ |
||
437 |
static int |
||
438 |
cmp_dkio(const DBT *d1, const DBT *d2) |
||
439 |
{ |
||
440 |
struct cmdinfo c1, c2; |
||
441 |
|||
442 |
memcpy(&c1, d1->data, sizeof(c1)); |
||
443 |
memcpy(&c2, d2->data, sizeof(c2)); |
||
444 |
|||
445 |
if (c1.ci_io < c2.ci_io) |
||
446 |
return -1; |
||
447 |
else if (c1.ci_io == c2.ci_io) |
||
448 |
return (cmp_comm(c1.ci_comm, c2.ci_comm)); |
||
449 |
else |
||
450 |
return 1; |
||
451 |
} |
||
452 |
|||
453 |
/* sort by average number of disk I/O operations */ |
||
454 |
static int |
||
455 |
cmp_avgdkio(const DBT *d1, const DBT *d2) |
||
456 |
{ |
||
457 |
struct cmdinfo c1, c2; |
||
458 |
double n1, n2; |
||
459 |
|||
460 |
memcpy(&c1, d1->data, sizeof(c1)); |
||
461 |
memcpy(&c2, d2->data, sizeof(c2)); |
||
462 |
|||
463 |
n1 = (double) c1.ci_io / (double) (c1.ci_calls ? c1.ci_calls : 1); |
||
464 |
n2 = (double) c2.ci_io / (double) (c2.ci_calls ? c2.ci_calls : 1); |
||
465 |
|||
466 |
if (n1 < n2) |
||
467 |
return -1; |
||
468 |
else if (n1 == n2) |
||
469 |
return (cmp_comm(c1.ci_comm, c2.ci_comm)); |
||
470 |
else |
||
471 |
return 1; |
||
472 |
} |
||
473 |
|||
474 |
/* sort by the cpu-storage integral */ |
||
475 |
static int |
||
476 |
cmp_cpumem(const DBT *d1, const DBT *d2) |
||
477 |
{ |
||
478 |
struct cmdinfo c1, c2; |
||
479 |
|||
480 |
memcpy(&c1, d1->data, sizeof(c1)); |
||
481 |
memcpy(&c2, d2->data, sizeof(c2)); |
||
482 |
|||
483 |
if (c1.ci_mem < c2.ci_mem) |
||
484 |
return -1; |
||
485 |
else if (c1.ci_mem == c2.ci_mem) |
||
486 |
return (cmp_comm(c1.ci_comm, c2.ci_comm)); |
||
487 |
else |
||
488 |
return 1; |
||
489 |
} |
||
490 |
|||
491 |
/* sort by the cpu-time average memory usage */ |
||
492 |
static int |
||
493 |
cmp_avgcpumem(const DBT *d1, const DBT *d2) |
||
494 |
{ |
||
495 |
struct cmdinfo c1, c2; |
||
496 |
uint64_t t1, t2; |
||
497 |
double n1, n2; |
||
498 |
|||
499 |
memcpy(&c1, d1->data, sizeof(c1)); |
||
500 |
memcpy(&c2, d2->data, sizeof(c2)); |
||
501 |
|||
502 |
t1 = c1.ci_utime + c1.ci_stime; |
||
503 |
t2 = c2.ci_utime + c2.ci_stime; |
||
504 |
|||
505 |
n1 = (double) c1.ci_mem / (double) (t1 ? t1 : 1); |
||
506 |
n2 = (double) c2.ci_mem / (double) (t2 ? t2 : 1); |
||
507 |
|||
508 |
if (n1 < n2) |
||
509 |
return -1; |
||
510 |
else if (n1 == n2) |
||
511 |
return (cmp_comm(c1.ci_comm, c2.ci_comm)); |
||
512 |
else |
||
513 |
return 1; |
||
514 |
} |
||
515 |
|||
516 |
/* sort by the number of invocations */ |
||
517 |
static int |
||
518 |
cmp_calls(const DBT *d1, const DBT *d2) |
||
519 |
{ |
||
520 |
struct cmdinfo c1, c2; |
||
521 |
|||
522 |
memcpy(&c1, d1->data, sizeof(c1)); |
||
523 |
memcpy(&c2, d2->data, sizeof(c2)); |
||
524 |
|||
525 |
if (c1.ci_calls < c2.ci_calls) |
||
526 |
return -1; |
||
527 |
else if (c1.ci_calls == c2.ci_calls) |
||
528 |
return (cmp_comm(c1.ci_comm, c2.ci_comm)); |
||
529 |
else |
||
530 |
return 1; |
||
531 |
} |
Generated by: GCOVR (Version 3.3) |