GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: ps.c,v 1.71 2016/09/23 06:28:08 bentley Exp $ */ |
||
2 |
/* $NetBSD: ps.c,v 1.15 1995/05/18 20:33:25 mycroft Exp $ */ |
||
3 |
|||
4 |
/*- |
||
5 |
* Copyright (c) 1990, 1993, 1994 |
||
6 |
* The Regents of the University of California. All rights reserved. |
||
7 |
* |
||
8 |
* Redistribution and use in source and binary forms, with or without |
||
9 |
* modification, are permitted provided that the following conditions |
||
10 |
* are met: |
||
11 |
* 1. Redistributions of source code must retain the above copyright |
||
12 |
* notice, this list of conditions and the following disclaimer. |
||
13 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
14 |
* notice, this list of conditions and the following disclaimer in the |
||
15 |
* documentation and/or other materials provided with the distribution. |
||
16 |
* 3. Neither the name of the University nor the names of its contributors |
||
17 |
* may be used to endorse or promote products derived from this software |
||
18 |
* without specific prior written permission. |
||
19 |
* |
||
20 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
||
21 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
22 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
23 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
||
24 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
25 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
26 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
27 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
28 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
29 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
30 |
* SUCH DAMAGE. |
||
31 |
*/ |
||
32 |
|||
33 |
#include <sys/param.h> /* MAXCOMLEN NODEV */ |
||
34 |
#include <sys/types.h> |
||
35 |
#include <sys/sysctl.h> |
||
36 |
#include <sys/time.h> |
||
37 |
#include <sys/resource.h> |
||
38 |
#include <sys/proc.h> |
||
39 |
#include <sys/stat.h> |
||
40 |
#include <sys/ioctl.h> |
||
41 |
|||
42 |
#include <ctype.h> |
||
43 |
#include <err.h> |
||
44 |
#include <errno.h> |
||
45 |
#include <fcntl.h> |
||
46 |
#include <kvm.h> |
||
47 |
#include <locale.h> |
||
48 |
#include <nlist.h> |
||
49 |
#include <paths.h> |
||
50 |
#include <pwd.h> |
||
51 |
#include <stdio.h> |
||
52 |
#include <stdlib.h> |
||
53 |
#include <string.h> |
||
54 |
#include <unistd.h> |
||
55 |
#include <limits.h> |
||
56 |
|||
57 |
#include "ps.h" |
||
58 |
|||
59 |
extern char *__progname; |
||
60 |
|||
61 |
struct varent *vhead; |
||
62 |
|||
63 |
int eval; /* exit value */ |
||
64 |
int sumrusage; /* -S */ |
||
65 |
int termwidth; /* width of screen (0 == infinity) */ |
||
66 |
int totwidth; /* calculated width of requested variables */ |
||
67 |
|||
68 |
int needcomm, needenv, neednlist, commandonly; |
||
69 |
|||
70 |
enum sort { DEFAULT, SORTMEM, SORTCPU } sortby = DEFAULT; |
||
71 |
|||
72 |
static char *kludge_oldps_options(char *); |
||
73 |
static int pscomp(const void *, const void *); |
||
74 |
static void scanvars(void); |
||
75 |
static void usage(void); |
||
76 |
|||
77 |
char dfmt[] = "pid tt state time command"; |
||
78 |
char tfmt[] = "pid tid tt state time command"; |
||
79 |
char jfmt[] = "user pid ppid pgid sess jobc state tt time command"; |
||
80 |
char lfmt[] = "uid pid ppid cpu pri nice vsz rss wchan state tt time command"; |
||
81 |
char o1[] = "pid"; |
||
82 |
char o2[] = "tt state time command"; |
||
83 |
char ufmt[] = "user pid %cpu %mem vsz rss tt state start time command"; |
||
84 |
char vfmt[] = "pid state time sl re pagein vsz rss lim tsiz %cpu %mem command"; |
||
85 |
|||
86 |
kvm_t *kd; |
||
87 |
int kvm_sysctl_only; |
||
88 |
|||
89 |
int |
||
90 |
main(int argc, char *argv[]) |
||
91 |
{ |
||
92 |
struct kinfo_proc *kp, **kinfo; |
||
93 |
struct varent *vent; |
||
94 |
1826 |
struct winsize ws; |
|
95 |
struct passwd *pwd; |
||
96 |
dev_t ttydev; |
||
97 |
pid_t pid; |
||
98 |
uid_t uid; |
||
99 |
913 |
int all, ch, flag, i, fmt, lineno, nentries; |
|
100 |
int prtheader, showthreads, wflag, kflag, what, Uflag, xflg; |
||
101 |
913 |
char *nlistf, *memf, *swapf, *cols, errbuf[_POSIX2_LINE_MAX]; |
|
102 |
|||
103 |
913 |
setlocale(LC_CTYPE, ""); |
|
104 |
|||
105 |
913 |
termwidth = 0; |
|
106 |
✓✓ | 913 |
if ((cols = getenv("COLUMNS")) != NULL) |
107 |
85 |
termwidth = strtonum(cols, 1, INT_MAX, NULL); |
|
108 |
✓✓✓✗ |
1649 |
if (termwidth == 0 && |
109 |
✓✗ | 828 |
(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 || |
110 |
✓✓ | 828 |
ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == 0 || |
111 |
✓✓ | 678 |
ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) && |
112 |
736 |
ws.ws_col > 0) |
|
113 |
736 |
termwidth = ws.ws_col - 1; |
|
114 |
✓✓ | 913 |
if (termwidth == 0) |
115 |
92 |
termwidth = 79; |
|
116 |
|||
117 |
✓✗ | 913 |
if (argc > 1) |
118 |
913 |
argv[1] = kludge_oldps_options(argv[1]); |
|
119 |
|||
120 |
all = fmt = prtheader = showthreads = wflag = kflag = Uflag = xflg = 0; |
||
121 |
pid = -1; |
||
122 |
uid = 0; |
||
123 |
ttydev = NODEV; |
||
124 |
memf = nlistf = swapf = NULL; |
||
125 |
✓✓ | 10875 |
while ((ch = getopt(argc, argv, |
126 |
3625 |
"AaCcegHhjkLlM:mN:O:o:p:rSTt:U:uvW:wx")) != -1) |
|
127 |
✗✗✓✓ ✗✗✗✗ ✓✗✗✗ ✗✗✓✓ ✗✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓ |
5442 |
switch (ch) { |
128 |
case 'A': |
||
129 |
all = 1; |
||
130 |
xflg = 1; |
||
131 |
break; |
||
132 |
case 'a': |
||
133 |
all = 1; |
||
134 |
break; |
||
135 |
case 'C': |
||
136 |
break; /* no-op */ |
||
137 |
case 'c': |
||
138 |
120 |
commandonly = 1; |
|
139 |
120 |
break; |
|
140 |
case 'e': /* XXX set ufmt */ |
||
141 |
175 |
needenv = 1; |
|
142 |
175 |
break; |
|
143 |
case 'g': |
||
144 |
break; /* no-op */ |
||
145 |
case 'H': |
||
146 |
showthreads = 1; |
||
147 |
break; |
||
148 |
case 'h': |
||
149 |
prtheader = ws.ws_row > 5 ? ws.ws_row : 22; |
||
150 |
break; |
||
151 |
case 'j': |
||
152 |
parsefmt(jfmt); |
||
153 |
fmt = 1; |
||
154 |
jfmt[0] = '\0'; |
||
155 |
break; |
||
156 |
case 'k': |
||
157 |
kflag = 1; |
||
158 |
break; |
||
159 |
case 'L': |
||
160 |
showkey(); |
||
161 |
exit(0); |
||
162 |
case 'l': |
||
163 |
parsefmt(lfmt); |
||
164 |
fmt = 1; |
||
165 |
lfmt[0] = '\0'; |
||
166 |
break; |
||
167 |
case 'M': |
||
168 |
memf = optarg; |
||
169 |
break; |
||
170 |
case 'm': |
||
171 |
sortby = SORTMEM; |
||
172 |
break; |
||
173 |
case 'N': |
||
174 |
nlistf = optarg; |
||
175 |
break; |
||
176 |
case 'O': |
||
177 |
parsefmt(o1); |
||
178 |
parsefmt(optarg); |
||
179 |
parsefmt(o2); |
||
180 |
o1[0] = o2[0] = '\0'; |
||
181 |
fmt = 1; |
||
182 |
break; |
||
183 |
case 'o': |
||
184 |
904 |
parsefmt(optarg); |
|
185 |
fmt = 1; |
||
186 |
904 |
break; |
|
187 |
case 'p': |
||
188 |
886 |
pid = atol(optarg); |
|
189 |
xflg = 1; |
||
190 |
886 |
break; |
|
191 |
case 'r': |
||
192 |
sortby = SORTCPU; |
||
193 |
break; |
||
194 |
case 'S': |
||
195 |
sumrusage = 1; |
||
196 |
break; |
||
197 |
case 'T': |
||
198 |
if ((optarg = ttyname(STDIN_FILENO)) == NULL) |
||
199 |
errx(1, "stdin: not a terminal"); |
||
200 |
/* FALLTHROUGH */ |
||
201 |
case 't': { |
||
202 |
struct stat sb; |
||
203 |
char *ttypath, pathbuf[PATH_MAX]; |
||
204 |
|||
205 |
if (strcmp(optarg, "co") == 0) |
||
206 |
ttypath = _PATH_CONSOLE; |
||
207 |
else if (*optarg != '/') |
||
208 |
(void)snprintf(ttypath = pathbuf, |
||
209 |
sizeof(pathbuf), "%s%s", _PATH_TTY, optarg); |
||
210 |
else |
||
211 |
ttypath = optarg; |
||
212 |
if (stat(ttypath, &sb) == -1) |
||
213 |
err(1, "%s", ttypath); |
||
214 |
if (!S_ISCHR(sb.st_mode)) |
||
215 |
errx(1, "%s: not a terminal", ttypath); |
||
216 |
ttydev = sb.st_rdev; |
||
217 |
break; |
||
218 |
} |
||
219 |
case 'U': |
||
220 |
92 |
pwd = getpwnam(optarg); |
|
221 |
✗✓ | 92 |
if (pwd == NULL) |
222 |
errx(1, "%s: no such user", optarg); |
||
223 |
92 |
uid = pwd->pw_uid; |
|
224 |
92 |
endpwent(); |
|
225 |
Uflag = xflg = 1; |
||
226 |
92 |
break; |
|
227 |
case 'u': |
||
228 |
parsefmt(ufmt); |
||
229 |
sortby = SORTCPU; |
||
230 |
fmt = 1; |
||
231 |
ufmt[0] = '\0'; |
||
232 |
break; |
||
233 |
case 'v': |
||
234 |
parsefmt(vfmt); |
||
235 |
sortby = SORTMEM; |
||
236 |
fmt = 1; |
||
237 |
vfmt[0] = '\0'; |
||
238 |
break; |
||
239 |
case 'W': |
||
240 |
swapf = optarg; |
||
241 |
break; |
||
242 |
case 'w': |
||
243 |
✓✓ | 544 |
if (wflag) |
244 |
termwidth = UNLIMITED; |
||
245 |
✓✓ | 272 |
else if (termwidth < 131) |
246 |
termwidth = 131; |
||
247 |
364 |
wflag = 1; |
|
248 |
544 |
break; |
|
249 |
case 'x': |
||
250 |
xflg = 1; |
||
251 |
break; |
||
252 |
default: |
||
253 |
usage(); |
||
254 |
} |
||
255 |
895 |
argc -= optind; |
|
256 |
895 |
argv += optind; |
|
257 |
|||
258 |
#define BACKWARD_COMPATIBILITY |
||
259 |
#ifdef BACKWARD_COMPATIBILITY |
||
260 |
✗✓ | 895 |
if (*argv) { |
261 |
nlistf = *argv; |
||
262 |
if (*++argv) { |
||
263 |
memf = *argv; |
||
264 |
if (*++argv) |
||
265 |
swapf = *argv; |
||
266 |
} |
||
267 |
} |
||
268 |
#endif |
||
269 |
|||
270 |
✓✗ | 895 |
if (nlistf == NULL && memf == NULL && swapf == NULL) { |
271 |
895 |
kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); |
|
272 |
895 |
kvm_sysctl_only = 1; |
|
273 |
895 |
} else { |
|
274 |
kd = kvm_openfiles(nlistf, memf, swapf, O_RDONLY, errbuf); |
||
275 |
} |
||
276 |
✗✓ | 895 |
if (kd == NULL) |
277 |
errx(1, "%s", errbuf); |
||
278 |
|||
279 |
✗✓ | 895 |
if (pledge("stdio rpath getpw ps flock cpath wpath", NULL) == -1) |
280 |
err(1, "pledge"); |
||
281 |
|||
282 |
✗✓ | 895 |
if (!fmt) { |
283 |
if (showthreads) |
||
284 |
parsefmt(tfmt); |
||
285 |
else |
||
286 |
parsefmt(dfmt); |
||
287 |
} |
||
288 |
|||
289 |
/* XXX - should be cleaner */ |
||
290 |
✓✓ | 895 |
if (!all && ttydev == NODEV && pid == -1 && !Uflag) { |
291 |
9 |
uid = getuid(); |
|
292 |
Uflag = 1; |
||
293 |
9 |
} |
|
294 |
|||
295 |
/* |
||
296 |
* scan requested variables, noting what structures are needed, |
||
297 |
* and adjusting header widths as appropriate. |
||
298 |
*/ |
||
299 |
895 |
scanvars(); |
|
300 |
|||
301 |
✓✓ | 895 |
if (neednlist && !nlistread) |
302 |
9 |
(void) donlist(); |
|
303 |
|||
304 |
/* |
||
305 |
* get proc list |
||
306 |
*/ |
||
307 |
✓✓ | 895 |
if (Uflag) { |
308 |
what = KERN_PROC_UID; |
||
309 |
flag = uid; |
||
310 |
✗✓ | 895 |
} else if (ttydev != NODEV) { |
311 |
what = KERN_PROC_TTY; |
||
312 |
flag = ttydev; |
||
313 |
✓✗ | 794 |
} else if (pid != -1) { |
314 |
what = KERN_PROC_PID; |
||
315 |
flag = pid; |
||
316 |
✗✗ | 794 |
} else if (kflag) { |
317 |
what = KERN_PROC_KTHREAD; |
||
318 |
flag = 0; |
||
319 |
} else { |
||
320 |
what = KERN_PROC_ALL; |
||
321 |
flag = 0; |
||
322 |
} |
||
323 |
✗✓ | 895 |
if (showthreads) |
324 |
what |= KERN_PROC_SHOW_THREADS; |
||
325 |
|||
326 |
/* |
||
327 |
* select procs |
||
328 |
*/ |
||
329 |
895 |
kp = kvm_getprocs(kd, what, flag, sizeof(*kp), &nentries); |
|
330 |
✗✓ | 895 |
if (kp == NULL) |
331 |
errx(1, "%s", kvm_geterr(kd)); |
||
332 |
|||
333 |
/* |
||
334 |
* print header |
||
335 |
*/ |
||
336 |
895 |
printheader(); |
|
337 |
✗✓ | 895 |
if (nentries == 0) |
338 |
exit(1); |
||
339 |
/* |
||
340 |
* sort proc list, we convert from an array of structs to an array |
||
341 |
* of pointers to make the sort cheaper. |
||
342 |
*/ |
||
343 |
✗✓ | 895 |
if ((kinfo = reallocarray(NULL, nentries, sizeof(*kinfo))) == NULL) |
344 |
err(1, "failed to allocate memory for proc pointers"); |
||
345 |
✓✓ | 4770 |
for (i = 0; i < nentries; i++) |
346 |
1490 |
kinfo[i] = &kp[i]; |
|
347 |
895 |
qsort(kinfo, nentries, sizeof(*kinfo), pscomp); |
|
348 |
/* |
||
349 |
* for each proc, call each variable output function. |
||
350 |
*/ |
||
351 |
✓✓ | 4770 |
for (i = lineno = 0; i < nentries; i++) { |
352 |
✓✗✓✗ |
2980 |
if (showthreads == 0 && (kinfo[i]->p_flag & P_THREAD) != 0) |
353 |
continue; |
||
354 |
✓✓✓✓ ✓✗ |
2077 |
if (xflg == 0 && ((int)kinfo[i]->p_tdev == NODEV || |
355 |
159 |
(kinfo[i]->p_psflags & PS_CONTROLT ) == 0)) |
|
356 |
continue; |
||
357 |
✗✓✗✗ |
1221 |
if (showthreads && kinfo[i]->p_tid == -1) |
358 |
continue; |
||
359 |
✓✓ | 30048 |
for (vent = vhead; vent; vent = vent->next) { |
360 |
13803 |
(vent->var->oproc)(kinfo[i], vent); |
|
361 |
✓✓ | 13803 |
if (vent->next != NULL) |
362 |
✓✗ | 25164 |
(void)putchar(' '); |
363 |
} |
||
364 |
✓✗ | 2442 |
(void)putchar('\n'); |
365 |
✗✓✗✗ |
1221 |
if (prtheader && lineno++ == prtheader - 4) { |
366 |
(void)putchar('\n'); |
||
367 |
printheader(); |
||
368 |
lineno = 0; |
||
369 |
} |
||
370 |
} |
||
371 |
exit(eval); |
||
372 |
} |
||
373 |
|||
374 |
static void |
||
375 |
scanvars(void) |
||
376 |
{ |
||
377 |
struct varent *vent; |
||
378 |
VAR *v; |
||
379 |
int i; |
||
380 |
|||
381 |
✓✓ | 6735 |
for (vent = vhead; vent; vent = vent->next) { |
382 |
2025 |
v = vent->var; |
|
383 |
2025 |
i = strlen(v->header); |
|
384 |
✓✓ | 2025 |
if (v->width < i) |
385 |
117 |
v->width = i; |
|
386 |
2025 |
totwidth += v->width + 1; /* +1 for space */ |
|
387 |
✓✓ | 2025 |
if (v->flag & COMM) |
388 |
399 |
needcomm = 1; |
|
389 |
✓✓ | 2025 |
if (v->flag & NLIST) |
390 |
27 |
neednlist = 1; |
|
391 |
} |
||
392 |
895 |
totwidth--; |
|
393 |
895 |
} |
|
394 |
|||
395 |
static int |
||
396 |
pscomp(const void *v1, const void *v2) |
||
397 |
{ |
||
398 |
4052 |
const struct kinfo_proc *kp1 = *(const struct kinfo_proc **)v1; |
|
399 |
2026 |
const struct kinfo_proc *kp2 = *(const struct kinfo_proc **)v2; |
|
400 |
int i; |
||
401 |
#define VSIZE(k) ((k)->p_vm_dsize + (k)->p_vm_ssize + (k)->p_vm_tsize) |
||
402 |
|||
403 |
✗✓✗✗ |
2026 |
if (sortby == SORTCPU && (i = getpcpu(kp2) - getpcpu(kp1)) != 0) |
404 |
return (i); |
||
405 |
✗✓✗✗ |
2026 |
if (sortby == SORTMEM && (i = VSIZE(kp2) - VSIZE(kp1)) != 0) |
406 |
return (i); |
||
407 |
✓✓✓✓ |
3442 |
if ((i = kp1->p_tdev - kp2->p_tdev) == 0 && |
408 |
1416 |
(i = kp1->p_ustart_sec - kp2->p_ustart_sec) == 0) |
|
409 |
628 |
i = kp1->p_ustart_usec - kp2->p_ustart_usec; |
|
410 |
2026 |
return (i); |
|
411 |
2026 |
} |
|
412 |
|||
413 |
/* |
||
414 |
* ICK (all for getopt), would rather hide the ugliness |
||
415 |
* here than taint the main code. |
||
416 |
* |
||
417 |
* ps foo -> ps -foo |
||
418 |
* ps 34 -> ps -p34 |
||
419 |
* |
||
420 |
* The old convention that 't' with no trailing tty arg means the users |
||
421 |
* tty, is only supported if argv[1] doesn't begin with a '-'. This same |
||
422 |
* feature is available with the option 'T', which takes no argument. |
||
423 |
*/ |
||
424 |
static char * |
||
425 |
kludge_oldps_options(char *s) |
||
426 |
{ |
||
427 |
size_t len; |
||
428 |
char *newopts, *ns, *cp; |
||
429 |
|||
430 |
1826 |
len = strlen(s); |
|
431 |
✗✓ | 913 |
if ((newopts = ns = malloc(2 + len + 1)) == NULL) |
432 |
err(1, NULL); |
||
433 |
/* |
||
434 |
* options begin with '-' |
||
435 |
*/ |
||
436 |
✗✓ | 913 |
if (*s != '-') |
437 |
*ns++ = '-'; /* add option flag */ |
||
438 |
|||
439 |
/* |
||
440 |
* gaze to end of argv[1] |
||
441 |
*/ |
||
442 |
913 |
cp = s + len - 1; |
|
443 |
/* |
||
444 |
* if last letter is a 't' flag with no argument (in the context |
||
445 |
* of the oldps options -- option string NOT starting with a '-' -- |
||
446 |
* then convert to 'T' (meaning *this* terminal, i.e. ttyname(0)). |
||
447 |
*/ |
||
448 |
✗✓✗✗ |
913 |
if (*cp == 't' && *s != '-') |
449 |
*cp = 'T'; |
||
450 |
else { |
||
451 |
/* |
||
452 |
* otherwise check for trailing number, which *may* be a |
||
453 |
* pid. |
||
454 |
*/ |
||
455 |
✓✗✗✓ |
2739 |
while (cp >= s && isdigit((unsigned char)*cp)) |
456 |
--cp; |
||
457 |
} |
||
458 |
913 |
cp++; |
|
459 |
913 |
memmove(ns, s, (size_t)(cp - s)); /* copy up to trailing number */ |
|
460 |
913 |
ns += cp - s; |
|
461 |
/* |
||
462 |
* if there's a trailing number, and not a preceding 'p' (pid) or |
||
463 |
* 't' (tty) flag, then assume it's a pid and insert a 'p' flag. |
||
464 |
*/ |
||
465 |
✗✓✗✗ |
913 |
if (isdigit((unsigned char)*cp) && |
466 |
(cp == s || (cp[-1] != 't' && cp[-1] != 'p' && |
||
467 |
(cp - 1 == s || cp[-2] != 't')))) |
||
468 |
*ns++ = 'p'; |
||
469 |
/* and append the number */ |
||
470 |
913 |
(void)strlcpy(ns, cp, newopts + len + 3 - ns); |
|
471 |
|||
472 |
913 |
return (newopts); |
|
473 |
} |
||
474 |
|||
475 |
static void |
||
476 |
usage(void) |
||
477 |
{ |
||
478 |
(void)fprintf(stderr, |
||
479 |
"usage: %s [-AaceHhjkLlmrSTuvwx] [-M core] [-N system] [-O fmt] [-o fmt] [-p pid]\n", |
||
480 |
__progname); |
||
481 |
(void)fprintf(stderr, |
||
482 |
"%-*s[-t tty] [-U username] [-W swap]\n", (int)strlen(__progname) + 8, ""); |
||
483 |
exit(1); |
||
484 |
} |
Generated by: GCOVR (Version 3.3) |